Browse Source

Implement most of the NAT traversal protocol, still no listening port.

wip
Titouan Rigoudy 9 years ago
parent
commit
332a654a87
4 changed files with 126 additions and 8 deletions
  1. +72
    -5
      src/client.rs
  2. +1
    -0
      src/proto/server/constants.rs
  3. +50
    -0
      src/proto/server/request.rs
  4. +3
    -3
      src/proto/server/response.rs

+ 72
- 5
src/client.rs View File

@ -48,13 +48,19 @@ enum LoginStatus {
#[derive(Debug)] #[derive(Debug)]
enum PeerState { enum PeerState {
/// We are trying to establish a direct connection.
Opening, Opening,
/// We are trying to establish a reverse connection.
OpeningFirewalled, OpeningFirewalled,
/// We are waiting for a reverse connection to be established to us.
WaitingFirewalled,
/// The connection is open.
Open Open
} }
#[derive(Debug)] #[derive(Debug)]
struct Peer { struct Peer {
user_name: String,
ip: net::Ipv4Addr, ip: net::Ipv4Addr,
port: u16, port: u16,
connection_type: String, connection_type: String,
@ -327,12 +333,64 @@ impl Client {
} }
fn handle_peer_connection_closed(&mut self, peer_id: usize) { fn handle_peer_connection_closed(&mut self, peer_id: usize) {
info!("Connection to peer {} has closed", peer_id);
match self.peers.remove(peer_id) {
None => error!("Unknown peer {}", peer_id),
let mut occupied_entry = match self.peers.entry(peer_id) {
None | Some(slab::Entry::Vacant(_)) => {
error!("Unknown peer connection {} has closed", peer_id);
return
},
Some(slab::Entry::Occupied(occupied_entry)) => occupied_entry
};
match occupied_entry.get_mut().state {
PeerState::Open => {
info!("Peer connection {} has closed", peer_id);
occupied_entry.remove();
},
PeerState::WaitingFirewalled => {
error!(
"Peer connection {} has closed, was waiting: inconsistent",
peer_id
);
occupied_entry.remove();
},
PeerState::Opening => {
info!(
"Peer connection {} has been refused, trying reverse",
peer_id
);
Some(peer) => {
// TODO if the peer was not connected, talk to the server
let peer = occupied_entry.get_mut();
peer.state = PeerState::WaitingFirewalled;
self.proto_tx.send(proto::Request::ServerRequest(
server::ServerRequest::ConnectToPeerRequest(
server::ConnectToPeerRequest {
token: peer.token,
user_name: peer.user_name.clone(),
connection_type: peer.connection_type.clone(),
}
)
)).unwrap();
},
PeerState::OpeningFirewalled => {
info!(
"Peer connection {} has been refused, cannot connect",
peer_id
);
let (peer, _) = occupied_entry.remove();
self.proto_tx.send(proto::Request::ServerRequest(
server::ServerRequest::CannotConnectRequest(
server::CannotConnectRequest {
token: peer.token,
user_name: peer.user_name
}
)
)).unwrap();
} }
} }
} }
@ -353,6 +411,14 @@ impl Client {
return return
}, },
Some(peer @ &mut Peer{state: PeerState::WaitingFirewalled, ..}) => {
error!(
"Peer connection {} was waiting: {:?}",
peer_id, peer
);
return
},
Some(peer @ &mut Peer { state: PeerState::Opening, .. }) => { Some(peer @ &mut Peer { state: PeerState::Opening, .. }) => {
info!("Peer connection {} is now open: {:?}", peer_id, peer); info!("Peer connection {} is now open: {:?}", peer_id, peer);
// Mark it as open. // Mark it as open.
@ -430,6 +496,7 @@ impl Client {
&mut self, response: server::ConnectToPeerResponse) &mut self, response: server::ConnectToPeerResponse)
{ {
let peer = Peer { let peer = Peer {
user_name: response.user_name,
ip: response.ip, ip: response.ip,
port: response.port, port: response.port,
connection_type: response.connection_type, connection_type: response.connection_type,


+ 1
- 0
src/proto/server/constants.rs View File

@ -15,3 +15,4 @@ pub const CODE_PARENT_MIN_SPEED: u32 = 83;
pub const CODE_PARENT_SPEED_RATIO: u32 = 84; pub const CODE_PARENT_SPEED_RATIO: u32 = 84;
pub const CODE_WISHLIST_INTERVAL: u32 = 104; pub const CODE_WISHLIST_INTERVAL: u32 = 104;
pub const CODE_ROOM_TICKERS: u32 = 113; pub const CODE_ROOM_TICKERS: u32 = 113;
pub const CODE_CANNOT_CONNECT: u32 = 1001;

+ 50
- 0
src/proto/server/request.rs View File

@ -12,6 +12,8 @@ use super::super::packet::{MutPacket, WriteToPacket};
#[derive(Debug)] #[derive(Debug)]
pub enum ServerRequest { pub enum ServerRequest {
CannotConnectRequest(CannotConnectRequest),
ConnectToPeerRequest(ConnectToPeerRequest),
LoginRequest(LoginRequest), LoginRequest(LoginRequest),
PeerAddressRequest(PeerAddressRequest), PeerAddressRequest(PeerAddressRequest),
RoomJoinRequest(RoomJoinRequest), RoomJoinRequest(RoomJoinRequest),
@ -25,6 +27,16 @@ pub enum ServerRequest {
impl WriteToPacket for ServerRequest { impl WriteToPacket for ServerRequest {
fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> { fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> {
match *self { match *self {
ServerRequest::CannotConnectRequest(ref request) => {
try!(packet.write_value(&CODE_CANNOT_CONNECT));
try!(packet.write_value(request));
},
ServerRequest::ConnectToPeerRequest(ref request) => {
try!(packet.write_value(&CODE_CONNECT_TO_PEER));
try!(packet.write_value(request));
},
ServerRequest::LoginRequest(ref request) => { ServerRequest::LoginRequest(ref request) => {
try!(packet.write_value(&CODE_LOGIN)); try!(packet.write_value(&CODE_LOGIN));
try!(packet.write_value(request)); try!(packet.write_value(request));
@ -74,6 +86,44 @@ fn md5_str(string: &str) -> String {
hasher.result_str() hasher.result_str()
} }
/*================*
* CANNOT CONNECT *
*================*/
#[derive(Debug)]
pub struct CannotConnectRequest {
pub token: u32,
pub user_name: String,
}
impl WriteToPacket for CannotConnectRequest {
fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> {
try!(packet.write_value(&self.token));
try!(packet.write_value(&self.user_name));
Ok(())
}
}
/*=================*
* CONNECT TO PEER *
*=================*/
#[derive(Debug)]
pub struct ConnectToPeerRequest {
pub token: u32,
pub user_name: String,
pub connection_type: String,
}
impl WriteToPacket for ConnectToPeerRequest {
fn write_to_packet(&self, packet: &mut MutPacket) -> io::Result<()> {
try!(packet.write_value(&self.token));
try!(packet.write_value(&self.user_name));
try!(packet.write_value(&self.connection_type));
Ok(())
}
}
/*=======* /*=======*
* LOGIN * * LOGIN *
*=======*/ *=======*/


+ 3
- 3
src/proto/server/response.rs View File

@ -134,7 +134,7 @@ impl ReadFromPacket for ServerResponse {
#[derive(Debug)] #[derive(Debug)]
pub struct ConnectToPeerResponse { pub struct ConnectToPeerResponse {
pub username: String,
pub user_name: String,
pub connection_type: String, pub connection_type: String,
pub ip: net::Ipv4Addr, pub ip: net::Ipv4Addr,
pub port: u16, pub port: u16,
@ -144,7 +144,7 @@ pub struct ConnectToPeerResponse {
impl ReadFromPacket for ConnectToPeerResponse { impl ReadFromPacket for ConnectToPeerResponse {
fn read_from_packet(packet: &mut Packet) -> Result<Self, PacketReadError> { fn read_from_packet(packet: &mut Packet) -> Result<Self, PacketReadError> {
let username = try!(packet.read_value());
let user_name = try!(packet.read_value());
let connection_type = try!(packet.read_value()); let connection_type = try!(packet.read_value());
let ip = try!(packet.read_value()); let ip = try!(packet.read_value());
let port = try!(packet.read_value()); let port = try!(packet.read_value());
@ -152,7 +152,7 @@ impl ReadFromPacket for ConnectToPeerResponse {
let is_privileged = try!(packet.read_value()); let is_privileged = try!(packet.read_value());
Ok(ConnectToPeerResponse { Ok(ConnectToPeerResponse {
username: username,
user_name: user_name,
connection_type: connection_type, connection_type: connection_type,
ip: ip, ip: ip,
port: port, port: port,


Loading…
Cancel
Save