diff options
author | Jake McGinty <me@jake.su> | 2018-05-08 23:23:28 -0700 |
---|---|---|
committer | Jake McGinty <me@jake.su> | 2018-05-08 23:23:28 -0700 |
commit | 1a22671046a79685f72a1e47b082abbf2aa2811a (patch) | |
tree | 2996b36f6d092ea45a407fd238451c0c2a274501 | |
parent | tests: simulate stale session recovery (dropped keepalive packet) (diff) | |
download | wireguard-rs-1a22671046a79685f72a1e47b082abbf2aa2811a.tar.xz wireguard-rs-1a22671046a79685f72a1e47b082abbf2aa2811a.zip |
timers: hold weak references to peer in timer messages
-rw-r--r-- | src/interface/mod.rs | 3 | ||||
-rw-r--r-- | src/interface/peer_server.rs | 28 | ||||
-rw-r--r-- | src/timer.rs | 10 |
3 files changed, 24 insertions, 17 deletions
diff --git a/src/interface/mod.rs b/src/interface/mod.rs index 8d939f6..21984ce 100644 --- a/src/interface/mod.rs +++ b/src/interface/mod.rs @@ -9,7 +9,7 @@ use router::Router; use failure::{Error, err_msg}; use peer::Peer; use std::io; -use std::rc::Rc; +use std::rc::{Rc, Weak}; use std::cell::RefCell; use std::collections::HashMap; use types::{InterfaceInfo}; @@ -27,6 +27,7 @@ pub fn trace_packet(header: &str, packet: &[u8]) { } pub type SharedPeer = Rc<RefCell<Peer>>; +pub type WeakSharedPeer = Weak<RefCell<Peer>>; pub type SharedState = Rc<RefCell<State>>; #[derive(Default)] diff --git a/src/interface/peer_server.rs b/src/interface/peer_server.rs index ce3aaa6..0e02080 100644 --- a/src/interface/peer_server.rs +++ b/src/interface/peer_server.rs @@ -15,6 +15,7 @@ use udp::{Endpoint, UdpSocket, PeerServerMessage, UdpChannel}; use tokio_core::reactor::Handle; use std::convert::TryInto; +use std::rc::Rc; pub enum ChannelMessage { ClearPrivateKey, @@ -200,7 +201,7 @@ impl PeerServer { } info!("handshake response received, current session now {}", our_index); - self.timer.send_after(*WIPE_AFTER_TIME, TimerMessage::Wipe(peer_ref.clone())); + self.timer.send_after(*WIPE_AFTER_TIME, TimerMessage::Wipe(Rc::downgrade(&peer_ref))); Ok(()) } @@ -235,7 +236,7 @@ impl PeerServer { } } - self.timer.send_after(*WIPE_AFTER_TIME, TimerMessage::Wipe(peer_ref.clone())); + self.timer.send_after(*WIPE_AFTER_TIME, TimerMessage::Wipe(Rc::downgrade(&peer_ref))); } (raw_packet, peer.needs_new_handshake(false)) }; @@ -302,7 +303,7 @@ impl PeerServer { self.send_to_peer((endpoint, init_packet))?; peer.timers.handshake_initialized = Timestamp::now(); - self.timer.send_after(*REKEY_TIMEOUT, TimerMessage::Rekey(peer_ref.clone(), new_index)); + self.timer.send_after(*REKEY_TIMEOUT, TimerMessage::Rekey(Rc::downgrade(&peer_ref), new_index)); Ok(new_index) } @@ -310,9 +311,11 @@ impl PeerServer { use self::TimerMessage::*; match message { Rekey(peer_ref, our_index) => { + let mut upgraded_peer_ref = peer_ref.upgrade() + .ok_or_else(|| err_msg("peer no longer there"))?; { // TODO: clear sticky source endpoint if retrying, in case that is the problem - let mut peer = peer_ref.borrow_mut(); + let mut peer = upgraded_peer_ref.borrow_mut(); match peer.find_session(our_index) { Some((_, SessionType::Next)) => { @@ -343,10 +346,11 @@ impl PeerServer { } } - self.send_handshake_init(&peer_ref)?; + self.send_handshake_init(&upgraded_peer_ref)?; }, PassiveKeepAlive(peer_ref) => { - let mut peer = peer_ref.borrow_mut(); + let mut upgraded_peer_ref = peer_ref.upgrade().ok_or_else(|| err_msg("peer no longer there"))?; + let mut peer = upgraded_peer_ref.borrow_mut(); { if peer.sessions.current.is_none() { self.timer.send_after(*KEEPALIVE_TIMEOUT, PassiveKeepAlive(peer_ref.clone())); @@ -379,7 +383,8 @@ impl PeerServer { self.timer.send_after(*KEEPALIVE_TIMEOUT, PassiveKeepAlive(peer_ref.clone())); }, PersistentKeepAlive(peer_ref) => { - let mut peer = peer_ref.borrow_mut(); + let mut upgraded_peer_ref = peer_ref.upgrade().ok_or_else(|| err_msg("peer no longer there"))?; + let mut peer = upgraded_peer_ref.borrow_mut(); if let Some(persistent_keepalive) = peer.info.persistent_keepalive() { let since_last_auth_any = peer.timers.authenticated_traversed.elapsed(); @@ -399,7 +404,8 @@ impl PeerServer { } }, Wipe(peer_ref) => { - let mut peer = peer_ref.borrow_mut(); + let mut upgraded_peer_ref = peer_ref.upgrade().ok_or_else(|| err_msg("peer no longer there"))?; + let mut peer = upgraded_peer_ref.borrow_mut(); let mut state = self.shared_state.borrow_mut(); if peer.timers.handshake_completed.elapsed() >= *WIPE_AFTER_TIME { info!("wiping all old sessions due to staleness timeout for peer {}", peer.info); @@ -431,9 +437,9 @@ impl PeerServer { }, NewPeer(peer_ref) => { let mut peer = peer_ref.borrow_mut(); - self.timer.send_after(*KEEPALIVE_TIMEOUT, TimerMessage::PassiveKeepAlive(peer_ref.clone())); + self.timer.send_after(*KEEPALIVE_TIMEOUT, TimerMessage::PassiveKeepAlive(Rc::downgrade(&peer_ref))); if let Some(keepalive) = peer.info.persistent_keepalive() { - let handle = self.timer.send_after(keepalive, TimerMessage::PersistentKeepAlive(peer_ref.clone())); + let handle = self.timer.send_after(keepalive, TimerMessage::PersistentKeepAlive(Rc::downgrade(&peer_ref))); peer.timers.persistent_timer = Some(handle); } }, @@ -445,7 +451,7 @@ impl PeerServer { } if let Some(keepalive) = peer.info.persistent_keepalive() { - let handle = self.timer.send_after(keepalive, TimerMessage::PersistentKeepAlive(peer_ref.clone())); + let handle = self.timer.send_after(keepalive, TimerMessage::PersistentKeepAlive(Rc::downgrade(&peer_ref))); peer.timers.persistent_timer = Some(handle); self.send_to_peer(peer.handle_outgoing_transport(&[])?)?; debug!("set new keepalive timer and immediately sent new keepalive packet."); diff --git a/src/timer.rs b/src/timer.rs index 5afbdc0..dc6188a 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -4,14 +4,14 @@ use std::{cell::RefCell, rc::Rc}; use std::time::{Instant, Duration}; use tokio::timer::Delay; use tokio_core::reactor::Handle; -use interface::SharedPeer; +use interface::WeakSharedPeer; #[derive(Debug)] pub enum TimerMessage { - PersistentKeepAlive(SharedPeer), - PassiveKeepAlive(SharedPeer), - Rekey(SharedPeer, u32), - Wipe(SharedPeer), + PersistentKeepAlive(WeakSharedPeer), + PassiveKeepAlive(WeakSharedPeer), + Rekey(WeakSharedPeer, u32), + Wipe(WeakSharedPeer), } pub struct TimerHandle { |