aboutsummaryrefslogtreecommitdiffstats
path: root/src/wireguard/peer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/wireguard/peer.rs')
-rw-r--r--src/wireguard/peer.rs111
1 files changed, 111 insertions, 0 deletions
diff --git a/src/wireguard/peer.rs b/src/wireguard/peer.rs
new file mode 100644
index 0000000..9f24dea
--- /dev/null
+++ b/src/wireguard/peer.rs
@@ -0,0 +1,111 @@
+use super::constants::*;
+use super::router;
+use super::timers::{Events, Timers};
+use super::HandshakeJob;
+
+use super::bind::Bind;
+use super::bind::Reader as BindReader;
+use super::tun::{Reader, Tun};
+
+use std::fmt;
+use std::ops::Deref;
+use std::sync::atomic::{AtomicBool, AtomicU64, AtomicUsize, Ordering};
+use std::sync::Arc;
+use std::time::{Instant, SystemTime};
+
+use spin::{Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard};
+
+use crossbeam_channel::Sender;
+use x25519_dalek::PublicKey;
+
+pub struct Peer<T: Tun, B: Bind> {
+ pub router: Arc<router::Peer<B::Endpoint, Events<T, B>, T::Writer, B::Writer>>,
+ pub state: Arc<PeerInner<B>>,
+}
+
+pub struct PeerInner<B: Bind> {
+ // internal id (for logging)
+ pub id: u64,
+
+ // handshake state
+ pub walltime_last_handshake: Mutex<SystemTime>,
+ pub last_handshake_sent: Mutex<Instant>, // instant for last handshake
+ pub handshake_queued: AtomicBool, // is a handshake job currently queued for the peer?
+ pub queue: Mutex<Sender<HandshakeJob<B::Endpoint>>>, // handshake queue
+
+ // stats and configuration
+ pub pk: PublicKey, // public key, DISCUSS: avoid this. TODO: remove
+ pub keepalive_interval: AtomicU64, // keepalive interval
+ pub rx_bytes: AtomicU64, // received bytes
+ pub tx_bytes: AtomicU64, // transmitted bytes
+
+ // timer model
+ pub timers: RwLock<Timers>,
+}
+
+impl<T: Tun, B: Bind> Clone for Peer<T, B> {
+ fn clone(&self) -> Peer<T, B> {
+ Peer {
+ router: self.router.clone(),
+ state: self.state.clone(),
+ }
+ }
+}
+
+impl<B: Bind> PeerInner<B> {
+ #[inline(always)]
+ pub fn timers(&self) -> RwLockReadGuard<Timers> {
+ self.timers.read()
+ }
+
+ #[inline(always)]
+ pub fn timers_mut(&self) -> RwLockWriteGuard<Timers> {
+ self.timers.write()
+ }
+}
+
+impl<T: Tun, B: Bind> fmt::Display for Peer<T, B> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "peer(id = {})", self.id)
+ }
+}
+
+impl<T: Tun, B: Bind> Deref for Peer<T, B> {
+ type Target = PeerInner<B>;
+ fn deref(&self) -> &Self::Target {
+ &self.state
+ }
+}
+
+impl<T: Tun, B: Bind> Peer<T, B> {
+ pub fn down(&self) {
+ self.stop_timers();
+ }
+
+ pub fn up(&self) {}
+}
+
+impl<B: Bind> PeerInner<B> {
+ /* Queue a handshake request for the parallel workers
+ * (if one does not already exist)
+ *
+ * The function is ratelimited.
+ */
+ pub fn packet_send_handshake_initiation(&self) {
+ // the function is rate limited
+
+ {
+ let mut lhs = self.last_handshake_sent.lock();
+ if lhs.elapsed() < REKEY_TIMEOUT {
+ return;
+ }
+ *lhs = Instant::now();
+ }
+
+ // create a new handshake job for the peer
+
+ if !self.handshake_queued.swap(true, Ordering::SeqCst) {
+ self.queue.lock().send(HandshakeJob::New(self.pk)).unwrap();
+ }
+ }
+}