aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/consts.rs2
-rw-r--r--src/interface/peer_server.rs34
-rw-r--r--src/peer.rs65
-rw-r--r--src/time.rs3
4 files changed, 61 insertions, 43 deletions
diff --git a/src/consts.rs b/src/consts.rs
index e2a0f71..fb9b4e4 100644
--- a/src/consts.rs
+++ b/src/consts.rs
@@ -11,7 +11,7 @@ lazy_static! {
pub static ref REKEY_TIMEOUT: Duration = Duration::new(5, 0);
pub static ref KEEPALIVE_TIMEOUT: Duration = Duration::new(10, 0);
pub static ref RECEIVE_REKEY_TIMEOUT: Duration = *REKEY_AFTER_TIME - *KEEPALIVE_TIMEOUT - *REKEY_TIMEOUT;
- pub static ref TIMER_TICK_DURATION: Duration = Duration::from_millis(100);
+ pub static ref TIMER_RESOLUTION: Duration = Duration::from_millis(100);
pub static ref COOKIE_REFRESH_TIME: Duration = Duration::new(120, 0);
}
diff --git a/src/interface/peer_server.rs b/src/interface/peer_server.rs
index b849475..7103379 100644
--- a/src/interface/peer_server.rs
+++ b/src/interface/peer_server.rs
@@ -1,5 +1,5 @@
use consts::{REKEY_TIMEOUT, REKEY_AFTER_TIME, REJECT_AFTER_TIME, REKEY_ATTEMPT_TIME,
- KEEPALIVE_TIMEOUT, MAX_CONTENT_SIZE, TIMER_TICK_DURATION};
+ KEEPALIVE_TIMEOUT, MAX_CONTENT_SIZE, TIMER_RESOLUTION};
use cookie;
use interface::{SharedPeer, SharedState, UtunPacket, config};
use peer::{Peer, SessionType};
@@ -291,7 +291,7 @@ impl PeerServer {
self.send_to_peer((endpoint, init_packet))?;
peer.last_sent_init = Timestamp::now();
- let when = *REKEY_TIMEOUT + *TIMER_TICK_DURATION * 2;
+ let when = *REKEY_TIMEOUT + *TIMER_RESOLUTION * 2;
self.timer.spawn_delayed(&self.handle,
when,
TimerMessage::Rekey(peer_ref.clone(), new_index));
@@ -307,7 +307,7 @@ impl PeerServer {
match peer.find_session(our_index) {
Some((_, SessionType::Next)) => {
if peer.last_sent_init.elapsed() < *REKEY_TIMEOUT {
- let wait = *REKEY_TIMEOUT - peer.last_sent_init.elapsed() + *TIMER_TICK_DURATION * 2;
+ let wait = *REKEY_TIMEOUT - peer.last_sent_init.elapsed() + *TIMER_RESOLUTION * 2;
self.timer.spawn_delayed(&self.handle,
wait,
TimerMessage::Rekey(peer_ref.clone(), our_index));
@@ -321,7 +321,7 @@ impl PeerServer {
Some((_, SessionType::Current)) => {
let elapsed = peer.last_handshake.elapsed();
if elapsed <= *REKEY_AFTER_TIME {
- let wait = *REKEY_AFTER_TIME - elapsed + *TIMER_TICK_DURATION * 2;
+ let wait = *REKEY_AFTER_TIME - elapsed + *TIMER_RESOLUTION * 2;
self.timer.spawn_delayed(&self.handle,
wait,
TimerMessage::Rekey(peer_ref.clone(), our_index));
@@ -355,21 +355,31 @@ impl PeerServer {
let (session, session_type) = peer.find_session(our_index).ok_or_else(|| err_msg("missing session for timer"))?;
ensure!(session_type == SessionType::Current, "expired session for passive keepalive timer");
- if session.last_sent.elapsed() < *KEEPALIVE_TIMEOUT {
- self.timer.spawn_delayed(&self.handle,
- *KEEPALIVE_TIMEOUT - session.last_sent.elapsed() + *TIMER_TICK_DURATION,
+ let since_last_recv = session.last_received.elapsed();
+ let since_last_send = session.last_sent.elapsed();
+ if since_last_recv < *KEEPALIVE_TIMEOUT {
+ let wait = *KEEPALIVE_TIMEOUT - since_last_recv + *TIMER_RESOLUTION;
+ self.timer.spawn_delayed(&self.handle, wait,
TimerMessage::PassiveKeepAlive(peer_ref.clone(), our_index));
- bail!("passive keepalive tick (waiting ~{}s)", (*KEEPALIVE_TIMEOUT - session.last_sent.elapsed()).as_secs());
- } else { // if we're going to send a keepalive reset last_sent
- session.last_sent = Timestamp::unset();
+ bail!("passive keepalive tick (waiting ~{}s due to last recv time)", wait.as_secs());
+ } else if since_last_send < *KEEPALIVE_TIMEOUT {
+ let wait = *KEEPALIVE_TIMEOUT - since_last_send + *TIMER_RESOLUTION;
+ self.timer.spawn_delayed(&self.handle, wait,
+ TimerMessage::PassiveKeepAlive(peer_ref.clone(), our_index));
+ bail!("passive keepalive tick (waiting ~{}s due to last send time)", wait.as_secs());
+ } else if session.keepalive_sent {
+ self.timer.spawn_delayed(&self.handle, *KEEPALIVE_TIMEOUT,
+ TimerMessage::PassiveKeepAlive(peer_ref.clone(), our_index));
+ bail!("passive keepalive already sent (waiting ~{}s to see if session survives)", KEEPALIVE_TIMEOUT.as_secs());
+ } else {
+ session.keepalive_sent = true;
}
}
self.send_to_peer(peer.handle_outgoing_transport(&[])?)?;
debug!("sent passive keepalive packet ({})", our_index);
- self.timer.spawn_delayed(&self.handle,
- *KEEPALIVE_TIMEOUT,
+ self.timer.spawn_delayed(&self.handle, *KEEPALIVE_TIMEOUT,
TimerMessage::PassiveKeepAlive(peer_ref.clone(), our_index));
},
TimerMessage::PersistentKeepAlive(peer_ref, our_index) => {
diff --git a/src/peer.rs b/src/peer.rs
index 95daea5..f364e3c 100644
--- a/src/peer.rs
+++ b/src/peer.rs
@@ -42,35 +42,38 @@ pub enum SessionType {
}
pub struct Session {
- pub noise : snow::Session,
- pub our_index : u32,
- pub their_index : u32,
- pub anti_replay : AntiReplay,
- pub last_sent : Timestamp,
- pub last_received : Timestamp,
+ pub noise : snow::Session,
+ pub our_index : u32,
+ pub their_index : u32,
+ pub anti_replay : AntiReplay,
+ pub last_sent : Timestamp,
+ pub last_received : Timestamp,
+ pub keepalive_sent : bool,
}
impl Session {
#[allow(dead_code)]
pub fn with_their_index(session: snow::Session, their_index: u32) -> Session {
Session {
- noise : session,
- our_index : rand::thread_rng().gen::<u32>(),
- their_index : their_index,
- anti_replay : AntiReplay::default(),
- last_sent : Timestamp::default(),
- last_received : Timestamp::default(),
+ noise : session,
+ our_index : rand::thread_rng().gen::<u32>(),
+ their_index : their_index,
+ anti_replay : AntiReplay::default(),
+ last_sent : Timestamp::default(),
+ last_received : Timestamp::default(),
+ keepalive_sent : false,
}
}
pub fn into_transport_mode(self) -> Session {
Session {
- noise : self.noise.into_transport_mode().unwrap(),
- our_index : self.our_index,
- their_index : self.their_index,
- anti_replay : self.anti_replay,
- last_sent : self.last_sent,
- last_received : self.last_received,
+ noise : self.noise.into_transport_mode().unwrap(),
+ our_index : self.our_index,
+ their_index : self.their_index,
+ anti_replay : self.anti_replay,
+ last_sent : self.last_sent,
+ last_received : self.last_received,
+ keepalive_sent : self.keepalive_sent,
}
}
}
@@ -78,12 +81,13 @@ impl Session {
impl From<snow::Session> for Session {
fn from(session: snow::Session) -> Self {
Session {
- noise : session,
- our_index : rand::thread_rng().gen::<u32>(),
- their_index : 0,
- anti_replay : AntiReplay::default(),
- last_sent : Timestamp::default(),
- last_received : Timestamp::default(),
+ noise : session,
+ our_index : rand::thread_rng().gen::<u32>(),
+ their_index : 0,
+ anti_replay : AntiReplay::default(),
+ last_sent : Timestamp::default(),
+ last_received : Timestamp::default(),
+ keepalive_sent : false,
}
}
}
@@ -283,12 +287,17 @@ impl Peer {
session.anti_replay.update(nonce)?;
session.noise.set_receiving_nonce(nonce)?;
let len = session.noise.read_message(&packet[16..], &mut raw_packet)?;
- let len = IpPacket::new(&raw_packet[..len])
- .ok_or_else(||format_err!("invalid IP packet (len {})", len))?
- .length();
- raw_packet.truncate(len as usize);
+ if len > 0 {
+ let len = IpPacket::new(&raw_packet[..len])
+ .ok_or_else(||format_err!("invalid IP packet (len {})", len))?
+ .length();
+ raw_packet.truncate(len as usize);
+ } else {
+ raw_packet.truncate(0);
+ }
session.last_received = Timestamp::now();
+ session.keepalive_sent = false; // reset passive keepalive token since received a valid ingress transport
session_type
};
diff --git a/src/time.rs b/src/time.rs
index 6261573..9653965 100644
--- a/src/time.rs
+++ b/src/time.rs
@@ -1,7 +1,6 @@
use byteorder::{ByteOrder, BigEndian};
use std::ops::Deref;
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
-use std::u64;
const TAI64N_BASE: i64 = 4611686018427387914;
@@ -36,7 +35,7 @@ impl From<[u8; 12]> for Tai64n {
}
lazy_static! {
- pub static ref FOREVER: Duration = Duration::from_secs(u64::MAX);
+ pub static ref FOREVER: Duration = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
pub static ref FOREVER_AGO: Instant = Instant::now() - *FOREVER;
}