diff --git a/Cargo.toml b/Cargo.toml index 81ed4683..ebeb7810 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,6 @@ rand = "~0.3.14" rustc-serialize = "~0.3.18" socket_addr = "~0.1.0" sodiumoxide = "~0.0.9" -time = "~0.1.34" void = "1.0.1" w_result = "~0.1.1" byteorder = "~0.5.0" diff --git a/examples/simple-tcp-server.rs b/examples/simple-tcp-server.rs index a43e8605..5956b718 100644 --- a/examples/simple-tcp-server.rs +++ b/examples/simple-tcp-server.rs @@ -38,6 +38,8 @@ extern crate nat_traversal; extern crate w_result; +use std::time::{Instant, Duration}; + use nat_traversal::{MappingContext, SimpleTcpHolePunchServer}; use w_result::{WOk, WErr}; @@ -60,7 +62,8 @@ fn main() { }; // Now we create the server. - let simple_server = match SimpleTcpHolePunchServer::new(Box::new(mapping_context)) { + let deadline = Instant::now() + Duration::from_secs(3); + let simple_server = match SimpleTcpHolePunchServer::new(Box::new(mapping_context), deadline) { WOk(simple_server, warnings) => { for warning in warnings { println!("Warning when creating simple server: {}", warning); diff --git a/examples/simple-udp-server.rs b/examples/simple-udp-server.rs index 98b2e649..9fcfa318 100644 --- a/examples/simple-udp-server.rs +++ b/examples/simple-udp-server.rs @@ -38,6 +38,8 @@ extern crate nat_traversal; extern crate w_result; +use std::time::{Instant, Duration}; + use nat_traversal::{MappingContext, SimpleUdpHolePunchServer}; use w_result::{WOk, WErr}; @@ -60,7 +62,8 @@ fn main() { }; // Now we create the server. - let simple_server = match SimpleUdpHolePunchServer::new(Box::new(mapping_context)) { + let deadline = Instant::now() + Duration::from_secs(3); + let simple_server = match SimpleUdpHolePunchServer::new(Box::new(mapping_context), deadline) { WOk(simple_server, warnings) => { for warning in warnings { println!("Warning when creating simple server: {}", warning); diff --git a/examples/tcp-hole-punch.rs b/examples/tcp-hole-punch.rs index 9002db07..acd57ca8 100644 --- a/examples/tcp-hole-punch.rs +++ b/examples/tcp-hole-punch.rs @@ -45,6 +45,7 @@ extern crate socket_addr; use std::net::ToSocketAddrs; use std::io::{Read, Write}; +use std::time::{Instant, Duration}; use socket_addr::SocketAddr; use nat_traversal::{MappingContext, gen_rendezvous_info, MappedTcpSocket, tcp_punch_hole}; @@ -109,7 +110,8 @@ fn main() { } // Now we use our context to create a mapped tcp socket. - let mapped_socket = match MappedTcpSocket::new(&mapping_context) { + let deadline = Instant::now() + Duration::from_secs(5); + let mapped_socket = match MappedTcpSocket::new(&mapping_context, deadline) { WOk(mapped_socket, warnings) => { for warning in warnings { println!("Warning when mapping socket: {}", warning); @@ -171,7 +173,10 @@ fn main() { // Now we use the socket, our private rendezvous info and their public rendezvous info to // complete the connection. - let mut stream = match tcp_punch_hole(socket, our_priv_info, their_pub_info) { + let mut stream = match tcp_punch_hole( + socket, our_priv_info, their_pub_info, + Instant::now() + Duration::from_secs(5) + ) { WOk(punched_socket, warnings) => { for warning in warnings { println!("Warning when punching hole: {}", warning); diff --git a/examples/udp-hole-punch.rs b/examples/udp-hole-punch.rs index 241b180f..dfeb22d0 100644 --- a/examples/udp-hole-punch.rs +++ b/examples/udp-hole-punch.rs @@ -44,6 +44,7 @@ extern crate rustc_serialize; extern crate socket_addr; use std::net::ToSocketAddrs; +use std::time::{Instant, Duration}; use socket_addr::SocketAddr; use nat_traversal::{MappingContext, gen_rendezvous_info, MappedUdpSocket, PunchedUdpSocket}; @@ -108,7 +109,10 @@ fn main() { } // Now we use our context to create a mapped udp socket. - let mapped_socket = match MappedUdpSocket::new(&mapping_context) { + let mapped_socket = match MappedUdpSocket::new( + &mapping_context, + Instant::now() + Duration::from_secs(5) + ) { WOk(mapped_socket, warnings) => { for warning in warnings { println!("Warning when mapping socket: {}", warning); @@ -170,7 +174,10 @@ fn main() { // Now we use the socket, our private rendezvous info and their public rendezvous info to // complete the connection. - let punched_socket = match PunchedUdpSocket::punch_hole(socket, our_priv_info, their_pub_info) { + let deadline = Instant::now() + Duration::from_secs(5); + let punched_socket = match PunchedUdpSocket::punch_hole(socket, our_priv_info, + their_pub_info, deadline) + { WOk(punched_socket, warnings) => { for warning in warnings { println!("Warning when punching hole: {}", warning); diff --git a/src/lib.rs b/src/lib.rs index 934ac5f2..d6fc9172 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -49,7 +49,6 @@ extern crate byteorder; extern crate net2; extern crate rand; extern crate rustc_serialize; -extern crate time; extern crate void; #[macro_use] extern crate maidsafe_utilities; diff --git a/src/mapped_tcp_socket.rs b/src/mapped_tcp_socket.rs index 717e8f48..05a2cfa7 100644 --- a/src/mapped_tcp_socket.rs +++ b/src/mapped_tcp_socket.rs @@ -19,10 +19,10 @@ //! NAT traversal utilities. use std::net; -use std::net::{IpAddr, TcpStream}; +use std::net::{IpAddr, Ipv4Addr, TcpStream}; use std::io; use std::io::{Read, Write}; -use std::time::Duration; +use std::time::{Instant, Duration}; use std::thread; use std::str; use std::sync::mpsc; @@ -35,8 +35,6 @@ use net2; use socket_addr::SocketAddr; use w_result::{WResult, WErr, WOk}; use maidsafe_utilities::serialisation::{deserialise, SerialisationError}; -use time::SteadyTime; -use time; use rand::random; use byteorder::{ReadBytesExt, WriteBytesExt, BigEndian}; @@ -47,7 +45,6 @@ use rendezvous_info; use socket_utils; use mapping_context; use listener_message; -use utils; use utils::DisplaySlice; /// A tcp socket for which we know our external endpoints. @@ -163,28 +160,10 @@ quick_error! { /// Errors returned by MappedTcpSocket::new #[derive(Debug)] pub enum MappedTcpSocketNewError { - /// Error creating TCP socket. - CreateSocket { err: io::Error } { - description("Error creating TCP socket") - display("Error creating TCP socket: {}", err) - cause(err) - } - /// Error enabling SO_REUSEADDR on new socket. - EnableReuseAddr { err: io::Error } { - description("Error enabling SO_REUSEADDR on new socket") - display("Error enabling SO_REUSEADDR on new socket: {}", err) - cause(err) - } - /// Error enabling SO_REUSEPORT (or equivalent) on new socket. - EnableReusePort { err: io::Error } { - description("Error enabling SO_REUSEPORT (or equivalent) on new socket") - display("Error enabling SO_REUSEPORT (or equivalent) on new socket: {}", err) - cause(err) - } - /// Error binding new socket. - Bind { err: io::Error } { - description("Error binding new socket") - display("Error binding new socket: {}", err) + /// Error creating a reusably bound tcp socket. + NewReusablyBoundTcpSocket { err: NewReusablyBoundTcpSocketError } { + description("Error creating a reusably bound tcp socket.") + display("Error creating a reusably bound tcp socket: {}", err) cause(err) } /// Error mapping new socket. @@ -200,10 +179,10 @@ impl From for io::Error { fn from(e: MappedTcpSocketNewError) -> io::Error { let err_str = format!("{}", e); let kind = match e { - MappedTcpSocketNewError::CreateSocket { err } => err.kind(), - MappedTcpSocketNewError::EnableReuseAddr { err } => err.kind(), - MappedTcpSocketNewError::EnableReusePort { err } => err.kind(), - MappedTcpSocketNewError::Bind { err } => err.kind(), + MappedTcpSocketNewError::NewReusablyBoundTcpSocket { err } => { + let err: io::Error = From::from(err); + err.kind() + }, MappedTcpSocketNewError::Map { err } => { let err: io::Error = From::from(err); err.kind() @@ -291,7 +270,7 @@ pub fn new_reusably_bound_tcp_socket(local_addr: &net::SocketAddr) -> Result WResult { let mut endpoints = Vec::new(); @@ -465,30 +444,36 @@ impl MappedTcpSocket { }; Ok(external_addr) }; - let _ = results_tx.send(map()); + let _ = results_tx.send(Some(map())); })); } - drop(results_tx); + let timeout_thread = thread!("MappedTcpSocket::map timeout", move || { + let now = Instant::now(); + if deadline > now { + let timeout = deadline - now; + thread::park_timeout(timeout); + } + let _ = results_tx.send(None); + }); - let mut num_results = 0; for result in results_rx { match result { - Ok(external_addr) => { + Some(Ok(external_addr)) => { endpoints.push(MappedSocketAddr { addr: external_addr, nat_restricted: true, }); - num_results += 1; - if num_results >= 2 { - break; - } }, - Err(e) => { + Some(Err(e)) => { warnings.push(e); }, + None => { + break; + }, } } + timeout_thread.thread().unpark(); WOk(MappedTcpSocket { socket: socket, endpoints: endpoints, @@ -496,27 +481,16 @@ impl MappedTcpSocket { } /// Create a new `MappedTcpSocket` - pub fn new(mc: &MappingContext) -> WResult { - let socket = match net2::TcpBuilder::new_v4() { + pub fn new(mc: &MappingContext, deadline: Instant) + -> WResult + { + let unspec_addr = net::SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0); + let socket = match new_reusably_bound_tcp_socket(&unspec_addr) { Ok(socket) => socket, - Err(e) => return WErr(MappedTcpSocketNewError::CreateSocket { err: e }), - }; - match socket.reuse_address(true) { - Ok(_) => (), - Err(e) => return WErr(MappedTcpSocketNewError::EnableReuseAddr { err: e }), - }; - match socket_utils::enable_so_reuseport(&socket) { - Ok(()) => (), - Err(e) => return WErr(MappedTcpSocketNewError::EnableReusePort { err: e }), - }; - // need to connect to a bunch of guys in parallel and get our addresses. - // need a bunch of sockets that are bound to the same local port. - match socket.bind("0.0.0.0:0") { - Ok(_) => (), - Err(e) => return WErr(MappedTcpSocketNewError::Bind { err: e }), + Err(e) => return WErr(MappedTcpSocketNewError::NewReusablyBoundTcpSocket { err: e }), }; - MappedTcpSocket::map(socket, mc).map_err(|e| MappedTcpSocketNewError::Map { err: e }) + MappedTcpSocket::map(socket, mc, deadline).map_err(|e| MappedTcpSocketNewError::Map { err: e }) } } @@ -624,7 +598,8 @@ impl From for io::Error { /// `MappedTcpSocket`. pub fn tcp_punch_hole(socket: net2::TcpBuilder, our_priv_rendezvous_info: PrivRendezvousInfo, - their_pub_rendezvous_info: PubRendezvousInfo) + their_pub_rendezvous_info: PubRendezvousInfo, + deadline: Instant) -> WResult { // In order to do tcp hole punching we connect to all of their endpoints in parallel while // simultaneously listening. All the sockets we use must be bound to the same local address. As @@ -636,10 +611,6 @@ pub fn tcp_punch_hole(socket: net2::TcpBuilder, // we're stuck with spawning (and then detaching) loads of threads. Setting the read/write // timeouts should prevent the detached threads from leaking indefinitely. - // The total timeout for the entire function. - let start_time = SteadyTime::now(); - let deadline = start_time + time::Duration::seconds(10); - let mut warnings = Vec::new(); let shutdown = Arc::new(AtomicBool::new(false)); @@ -715,13 +686,12 @@ pub fn tcp_punch_hole(socket: net2::TcpBuilder, Ok(stream) }; loop { - let now = SteadyTime::now(); + let now = Instant::now(); if now >= deadline || shutdown_clone.load(Ordering::SeqCst) { break; } else { let timeout = deadline - now; - let timeout = utils::time_duration_to_std_duration(timeout); match f(timeout) { Ok(stream) => { let _ = results_tx_clone.send(Some(Ok((stream, addr)))); @@ -769,13 +739,12 @@ pub fn tcp_punch_hole(socket: net2::TcpBuilder, // Spawn a new thread here to prevent someone from connecting then not sending any data // and preventing us from accepting any more connections. let results_tx_clone = results_tx_clone.clone(); - let now = SteadyTime::now(); + let now = Instant::now(); if now >= deadline { break; }; let _ = thread!("tcp_punch_hole listen handshake", move || { let timeout = deadline - now; - let timeout = utils::time_duration_to_std_duration(timeout); match stream.set_write_timeout(Some(timeout)) { Ok(()) => (), Err(e) => { @@ -841,10 +810,11 @@ pub fn tcp_punch_hole(socket: net2::TcpBuilder, // TODO(canndrew): We won't need to do this one this is fixed: https://github.com/rust-lang/rfcs/issues/962 let results_tx_clone = results_tx.clone(); let timeout_thread = thread!("tcp_punch_hole timeout", move || { - let now = SteadyTime::now(); - let timeout = deadline - now; - let timeout = utils::time_duration_to_std_duration(timeout); - thread::park_timeout(timeout); + let now = Instant::now(); + if deadline > now { + let timeout = deadline - now; + thread::park_timeout(timeout); + } let _ = results_tx_clone.send(None); }); let timeout_thread_handle = timeout_thread.thread(); @@ -982,26 +952,29 @@ mod test { use super::*; use std::io::{Read, Write}; + use std::time::{Instant, Duration}; use mapping_context::MappingContext; use rendezvous_info::gen_rendezvous_info; #[test] fn two_peers_tcp_hole_punch_over_loopback() { + let deadline = Instant::now() + Duration::from_secs(5); let mapping_context = unwrap_result!(MappingContext::new().result_log()); - let mapped_socket_0 = unwrap_result!(MappedTcpSocket::new(&mapping_context).result_log()); + let mapped_socket_0 = unwrap_result!(MappedTcpSocket::new(&mapping_context, deadline).result_log()); let socket_0 = mapped_socket_0.socket; let endpoints_0 = mapped_socket_0.endpoints; let (priv_info_0, pub_info_0) = gen_rendezvous_info(endpoints_0); - let mapped_socket_1 = unwrap_result!(MappedTcpSocket::new(&mapping_context).result_log()); + let mapped_socket_1 = unwrap_result!(MappedTcpSocket::new(&mapping_context, deadline).result_log()); let socket_1 = mapped_socket_1.socket; let endpoints_1 = mapped_socket_1.endpoints; let (priv_info_1, pub_info_1) = gen_rendezvous_info(endpoints_1); + let deadline = Instant::now() + Duration::from_secs(5); let thread_0 = thread!("two_peers_tcp_hole_punch_over_loopback_0", move || { - let mut stream = unwrap_result!(tcp_punch_hole(socket_0, priv_info_0, pub_info_1).result_log()); + let mut stream = unwrap_result!(tcp_punch_hole(socket_0, priv_info_0, pub_info_1, deadline).result_log()); let mut data = [0u8; 4]; let n = unwrap_result!(stream.write(&data)); assert_eq!(n, 4); @@ -1011,7 +984,7 @@ mod test { }); let thread_1 = thread!("two_peers_tcp_hole_punch_over_loopback_1", move || { - let mut stream = unwrap_result!(tcp_punch_hole(socket_1, priv_info_1, pub_info_0).result_log()); + let mut stream = unwrap_result!(tcp_punch_hole(socket_1, priv_info_1, pub_info_0, deadline).result_log()); let mut data = [1u8; 4]; let n = unwrap_result!(stream.write(&data)); assert_eq!(n, 4); diff --git a/src/mapped_udp_socket.rs b/src/mapped_udp_socket.rs index b66e6218..c27e69f5 100644 --- a/src/mapped_udp_socket.rs +++ b/src/mapped_udp_socket.rs @@ -22,11 +22,10 @@ use std::io; use std::net::UdpSocket; use std::net; use std::net::IpAddr; -use std::time::Duration; +use std::time::{Instant, Duration}; use std::collections::HashSet; use igd; -use time; use maidsafe_utilities::serialisation::deserialise; use socket_addr::SocketAddr; use w_result::{WResult, WOk, WErr}; @@ -164,7 +163,7 @@ impl From for io::Error { impl MappedUdpSocket { /// Map an existing `UdpSocket`. - pub fn map(socket: UdpSocket, mc: &MappingContext) + pub fn map(socket: UdpSocket, mc: &MappingContext, deadline: Instant) -> WResult { let mut endpoints = Vec::new(); @@ -291,11 +290,11 @@ impl MappedUdpSocket { .into_iter().collect(); // Ping all the simple servers and waiting for a response. - let start_time = time::SteadyTime::now(); - let mut deadline = start_time; - let mut final_deadline = start_time + time::Duration::seconds(2); - while deadline < final_deadline && simple_servers.len() > 0 { - deadline = deadline + time::Duration::milliseconds(250); + let start_time = Instant::now(); + let mut recv_deadline = start_time; + let mut deadline = deadline; + while recv_deadline < deadline && simple_servers.len() > 0 { + recv_deadline = recv_deadline + Duration::from_millis(250); // TODO(canndrew): We should limit the number of servers that we send to. If the user // has added two thousand servers we really don't want to be pinging all of them. We @@ -310,7 +309,7 @@ impl MappedUdpSocket { }; let mut recv_data = [0u8; MAX_DATAGRAM_SIZE]; loop { - let (read_size, recv_addr) = match socket.recv_until(&mut recv_data[..], deadline) { + let (read_size, recv_addr) = match socket.recv_until(&mut recv_data[..], recv_deadline) { Ok(Some(res)) => res, Ok(None) => break, Err(e) => return WErr(MappedUdpSocketMapError::RecvError { err: e }), @@ -331,7 +330,10 @@ impl MappedUdpSocket { // let is_global = recv_addr.is_global(); let is_global = false; if is_global { - final_deadline = start_time + time::Duration::seconds(1); + let now = Instant::now(); + if deadline > now { + deadline = now + (now - deadline) / 2; + } }; // Add this endpoint if we don't already know about it. We may have found it @@ -356,7 +358,7 @@ impl MappedUdpSocket { } /// Create a new `MappedUdpSocket` - pub fn new(mc: &MappingContext) + pub fn new(mc: &MappingContext, deadline: Instant) -> WResult { // Sometimes we might bind a socket to a random port then find that we have an IGD gateway @@ -369,7 +371,7 @@ impl MappedUdpSocket { Ok(socket) => socket, Err(e) => return WErr(MappedUdpSocketNewError::CreateSocket { err: e }), }; - let (socket, warnings) = match Self::map(socket, mc) { + let (socket, warnings) = match Self::map(socket, mc, deadline) { WOk(s, ws) => (s, ws), WErr(e) => return WErr(MappedUdpSocketNewError::MapSocket { err: e }), }; diff --git a/src/punched_udp_socket.rs b/src/punched_udp_socket.rs index 5e313fbf..9865d22e 100644 --- a/src/punched_udp_socket.rs +++ b/src/punched_udp_socket.rs @@ -21,10 +21,9 @@ use maidsafe_utilities::serialisation::{deserialise, SerialisationError, serialise}; use std::io; use std::net::UdpSocket; -use std; +use std::time::{Instant, Duration}; use std::thread; -use time; use socket_addr::SocketAddr; use w_result::{WResult, WOk, WErr}; @@ -131,7 +130,8 @@ impl PunchedUdpSocket { /// Punch a udp socket using a mapped socket and the peer's rendezvous info. pub fn punch_hole(socket: UdpSocket, our_priv_rendezvous_info: PrivRendezvousInfo, - their_pub_rendezvous_info: PubRendezvousInfo) + their_pub_rendezvous_info: PubRendezvousInfo, + deadline: Instant) -> WResult { let mut warnings = Vec::new(); @@ -205,14 +205,11 @@ impl PunchedUdpSocket { // Spend TOTAL_TIMEOUT_MS trying to get their actual address that we can // communicate with. - const DELAY_BETWEEN_RESENDS_MS: i64 = 600; - const TOTAL_TIMEOUT_MS: i64 = 10000; + const DELAY_BETWEEN_RESENDS_MS: u64 = 600; - let start_time = time::SteadyTime::now(); - let mut deadline = start_time; - let total_deadline = start_time + time::Duration::milliseconds(TOTAL_TIMEOUT_MS); - while deadline < total_deadline { - deadline = deadline + time::Duration::milliseconds(DELAY_BETWEEN_RESENDS_MS); + let mut recv_deadline = Instant::now(); + while recv_deadline < deadline { + recv_deadline = recv_deadline + Duration::from_millis(DELAY_BETWEEN_RESENDS_MS); let mut i = 0; while i < endpoints.len() { // TODO(canndrew): How should we handle partial write? @@ -230,7 +227,7 @@ impl PunchedUdpSocket { } // Keep reading until it's time to send to all endpoints again. loop { - let (read_size, addr) = match socket.recv_until(&mut recv_data[..], deadline) { + let (read_size, addr) = match socket.recv_until(&mut recv_data[..], recv_deadline) { Ok(Some(x)) => x, Ok(None) => break, Err(e) => return WErr(UdpPunchHoleError::Io { err: e }), @@ -261,7 +258,7 @@ impl PunchedUdpSocket { let mut attempts = 0; let mut successful_attempts = 0; let mut error = None; - while attempts < 2 || time::SteadyTime::now() < total_deadline { + while attempts < 2 || Instant::now() < deadline { attempts += 1; match socket.send_to(&send_data[..], &*addr) { Ok(n) => { @@ -278,7 +275,7 @@ impl PunchedUdpSocket { } } }; - thread::sleep(std::time::Duration::from_millis(100)); + thread::sleep(Duration::from_millis(100)); } if successful_attempts == 0 { let ret = match error { @@ -335,7 +332,7 @@ pub fn filter_udp_hole_punch_packet(data: &[u8]) -> Option<&[u8]> { mod tests { use std::sync::mpsc; use std::thread; - use std::time::Duration; + use std::time::{Instant, Duration}; use rand; use mapping_context::MappingContext; @@ -345,9 +342,10 @@ mod tests { #[test] fn two_peers_udp_hole_punch_over_loopback() { + let deadline = Instant::now() + Duration::from_secs(3); let mapping_context = unwrap_result!(MappingContext::new().result_discard()); - let mapped_socket_0 = unwrap_result!(MappedUdpSocket::new(&mapping_context).result_discard()); - let mapped_socket_1 = unwrap_result!(MappedUdpSocket::new(&mapping_context).result_discard()); + let mapped_socket_0 = unwrap_result!(MappedUdpSocket::new(&mapping_context, deadline).result_discard()); + let mapped_socket_1 = unwrap_result!(MappedUdpSocket::new(&mapping_context, deadline).result_discard()); let socket_0 = mapped_socket_0.socket; let socket_1 = mapped_socket_1.socket; @@ -357,16 +355,19 @@ mod tests { let (tx_0, rx_0) = mpsc::channel(); let (tx_1, rx_1) = mpsc::channel(); + let deadline = Instant::now() + Duration::from_secs(3); let jh_0 = thread!("two_peers_hole_punch_over_loopback punch socket 0", move || { let res = PunchedUdpSocket::punch_hole(socket_0, priv_info_0, - pub_info_1); + pub_info_1, + deadline); unwrap_result!(tx_0.send(res)); }); let jh_1 = thread!("two_peers_hole_punch_over_loopback punch socket 1", move || { let res = PunchedUdpSocket::punch_hole(socket_1, priv_info_1, - pub_info_0); + pub_info_0, + deadline); unwrap_result!(tx_1.send(res)); }); diff --git a/src/simple_tcp_hole_punch_server.rs b/src/simple_tcp_hole_punch_server.rs index c675ba11..c07c17f0 100644 --- a/src/simple_tcp_hole_punch_server.rs +++ b/src/simple_tcp_hole_punch_server.rs @@ -21,7 +21,7 @@ use std::io; use std::io::{Read, Write}; use std::net::{TcpStream, TcpListener}; -use std::time::Duration; +use std::time::{Instant, Duration}; use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; use std::net; @@ -90,12 +90,12 @@ impl From for io::Error { impl> SimpleTcpHolePunchServer { /// Create a new server. This will spawn a background thread which will serve requests until /// the server is dropped. - pub fn new(mapping_context: T) + pub fn new(mapping_context: T, deadline: Instant) -> WResult, MappedTcpSocketMapWarning, SimpleTcpHolePunchServerNewError> { - let (mapped_socket, warnings) = match MappedTcpSocket::new(mapping_context.as_ref()) { + let (mapped_socket, warnings) = match MappedTcpSocket::new(mapping_context.as_ref(), deadline) { WOk(mapped_socket, warnings) => (mapped_socket, warnings), WErr(e) => { return WErr(SimpleTcpHolePunchServerNewError::CreateMappedSocket { err: e }); diff --git a/src/simple_udp_hole_punch_server.rs b/src/simple_udp_hole_punch_server.rs index 8fedca29..70812377 100644 --- a/src/simple_udp_hole_punch_server.rs +++ b/src/simple_udp_hole_punch_server.rs @@ -20,7 +20,7 @@ use std::io; use std::net::UdpSocket; -use std::time::Duration; +use std::time::{Instant, Duration}; use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; @@ -84,12 +84,12 @@ impl From for io::Error { impl> SimpleUdpHolePunchServer { /// Create a new server. This will spawn a background thread which will serve requests until /// the server is dropped. - pub fn new(mapping_context: T) + pub fn new(mapping_context: T, deadline: Instant) -> WResult, MappedUdpSocketMapWarning, SimpleUdpHolePunchServerNewError> { - let (mapped_socket, warnings) = match MappedUdpSocket::new(mapping_context.as_ref()) { + let (mapped_socket, warnings) = match MappedUdpSocket::new(mapping_context.as_ref(), deadline) { WOk(mapped_socket, warnings) => (mapped_socket, warnings), WErr(e) => { return WErr(SimpleUdpHolePunchServerNewError::CreateMappedSocket { err: e }); diff --git a/src/socket_utils.rs b/src/socket_utils.rs index a31c38b3..66fed09a 100644 --- a/src/socket_utils.rs +++ b/src/socket_utils.rs @@ -18,42 +18,36 @@ use std::io; use std::net::{TcpStream, UdpSocket, IpAddr, Ipv4Addr, Ipv6Addr}; use std::net; -use std::time::Duration as StdDuration; +use std::time::Instant; #[cfg(target_family = "windows")] use std::mem; use socket_addr::SocketAddr; use std::io::ErrorKind; use net2; -use utils; - /// A self interruptable receive trait that allows a timed-out period to be defined pub trait RecvUntil { /// After specified timed-out period, the blocking receive method shall return with an error fn recv_until(&self, buf: &mut [u8], - deadline: ::time::SteadyTime) + deadline: Instant) -> io::Result>; } impl RecvUntil for UdpSocket { fn recv_until(&self, buf: &mut [u8], - deadline: ::time::SteadyTime) + deadline: Instant) -> io::Result> { let old_timeout = try!(self.read_timeout()); loop { - let current_time = ::time::SteadyTime::now(); + let current_time = Instant::now(); if current_time >= deadline { try!(self.set_read_timeout(old_timeout)); return Ok(None); } { let timeout = deadline - current_time; - let mut timeout = utils::time_duration_to_std_duration(timeout); - if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 { - timeout = StdDuration::new(0, 1); - } try!(self.set_read_timeout(Some(timeout))); } diff --git a/src/utils.rs b/src/utils.rs index bdcfe427..c0360623 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,25 +1,4 @@ -use std; use std::fmt; -use time; - -// TODO(canndrew): Deprecate this function as soon as #[feature(time2)] is stable. -pub fn time_duration_to_std_duration(dur: time::Duration) -> std::time::Duration { - let secs = dur.num_seconds(); - let secs = if secs < 0 { 0 } else { secs as u64 }; - let nanos = match dur.num_nanoseconds() { - Some(v) => { - if v < 0 { - 0 - } else { - let secs_and_nanos_part = v as u64; - let secs_par = secs * 1_000_000_000; - (secs_and_nanos_part - secs_par) as u32 - } - } - None => 0, - }; - std::time::Duration::new(secs, nanos) -} pub struct DisplaySlice<'a, T: 'a>(pub &'static str, pub &'a [T]);