2016-10-25 07:35:10 +03:00
|
|
|
// Copyright 2016 The Grin Developers
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2016-10-28 00:28:02 +03:00
|
|
|
use std::fmt;
|
2016-10-26 21:21:45 +03:00
|
|
|
use std::io::{self, Read, Write};
|
2016-10-28 00:28:02 +03:00
|
|
|
use std::net::SocketAddr;
|
2016-10-25 07:35:10 +03:00
|
|
|
|
2016-10-26 21:21:45 +03:00
|
|
|
use mioco::tcp::{TcpStream, Shutdown};
|
2016-10-25 07:35:10 +03:00
|
|
|
|
2016-10-26 08:06:13 +03:00
|
|
|
use handshake::Handshake;
|
2016-10-26 21:21:45 +03:00
|
|
|
use core::ser::Error;
|
2016-10-26 08:06:13 +03:00
|
|
|
use msg::*;
|
|
|
|
use types::*;
|
2016-10-25 07:35:10 +03:00
|
|
|
|
|
|
|
/// The local representation of a remotely connected peer. Handles most
|
|
|
|
/// low-level network communication and tracks peer information.
|
2016-10-26 08:06:13 +03:00
|
|
|
pub struct PeerConn {
|
2016-10-25 07:35:10 +03:00
|
|
|
conn: TcpStream,
|
2016-10-26 08:06:13 +03:00
|
|
|
pub capabilities: Capabilities,
|
|
|
|
pub user_agent: String,
|
2016-10-25 07:35:10 +03:00
|
|
|
}
|
|
|
|
|
2016-10-28 00:28:02 +03:00
|
|
|
impl fmt::Display for PeerConn {
|
|
|
|
// This trait requires `fmt` with this exact signature.
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
write!(f, "{} {}", self.peer_addr(), self.user_agent)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-25 07:35:10 +03:00
|
|
|
/// Make the Peer a Reader for convenient access to the underlying connection.
|
|
|
|
/// Allows the peer to track how much is received.
|
2016-10-26 08:06:13 +03:00
|
|
|
impl Read for PeerConn {
|
|
|
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
2016-10-26 21:21:45 +03:00
|
|
|
self.conn.read(buf)
|
2016-10-25 07:35:10 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Make the Peer a Writer for convenient access to the underlying connection.
|
|
|
|
/// Allows the peer to track how much is sent.
|
2016-10-26 08:06:13 +03:00
|
|
|
impl Write for PeerConn {
|
|
|
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
|
|
|
self.conn.write(buf)
|
2016-10-25 07:35:10 +03:00
|
|
|
}
|
2016-10-28 00:28:02 +03:00
|
|
|
fn flush(&mut self) -> io::Result<()> {
|
|
|
|
self.conn.flush()
|
|
|
|
}
|
2016-10-25 07:35:10 +03:00
|
|
|
}
|
|
|
|
|
2016-10-26 08:06:13 +03:00
|
|
|
impl Close for PeerConn {
|
|
|
|
fn close(&self) {
|
2016-10-25 07:35:10 +03:00
|
|
|
self.conn.shutdown(Shutdown::Both);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-26 08:06:13 +03:00
|
|
|
impl PeerConn {
|
2016-10-25 07:35:10 +03:00
|
|
|
/// Create a new local peer instance connected to a remote peer with the
|
|
|
|
/// provided TcpStream.
|
2016-10-26 08:06:13 +03:00
|
|
|
pub fn new(conn: TcpStream) -> PeerConn {
|
2016-10-25 07:35:10 +03:00
|
|
|
// don't wait on read for more than 2 seconds by default
|
2016-10-26 08:06:13 +03:00
|
|
|
conn.set_keepalive(Some(2));
|
2016-10-25 07:35:10 +03:00
|
|
|
|
2016-10-26 08:06:13 +03:00
|
|
|
PeerConn {
|
2016-10-25 07:35:10 +03:00
|
|
|
conn: conn,
|
|
|
|
capabilities: UNKNOWN,
|
2016-10-26 08:06:13 +03:00
|
|
|
user_agent: "".to_string(),
|
2016-10-25 07:35:10 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-26 08:06:13 +03:00
|
|
|
pub fn connect(&mut self, hs: &Handshake, na: &NetAdapter) -> Option<Error> {
|
|
|
|
let mut proto = try_to_o!(hs.connect(self));
|
|
|
|
proto.handle(na)
|
2016-10-25 07:35:10 +03:00
|
|
|
}
|
|
|
|
|
2016-10-26 08:06:13 +03:00
|
|
|
pub fn handshake(&mut self, hs: &Handshake, na: &NetAdapter) -> Option<Error> {
|
|
|
|
let mut proto = try_to_o!(hs.handshake(self));
|
|
|
|
proto.handle(na)
|
2016-10-25 07:35:10 +03:00
|
|
|
}
|
2016-10-26 08:06:13 +03:00
|
|
|
}
|
2016-10-25 07:35:10 +03:00
|
|
|
|
2016-10-26 08:06:13 +03:00
|
|
|
impl PeerInfo for PeerConn {
|
2016-10-25 07:35:10 +03:00
|
|
|
fn peer_addr(&self) -> SocketAddr {
|
2016-10-26 08:06:13 +03:00
|
|
|
self.conn.peer_addr().unwrap()
|
|
|
|
}
|
|
|
|
fn local_addr(&self) -> SocketAddr {
|
2016-10-28 00:28:02 +03:00
|
|
|
// TODO likely not exactly what we want (private vs public IP)
|
2016-10-26 08:06:13 +03:00
|
|
|
self.conn.local_addr().unwrap()
|
2016-10-25 07:35:10 +03:00
|
|
|
}
|
|
|
|
}
|