diff options
author | HimbeerserverDE <himbeerserverde@gmail.com> | 2023-05-11 18:03:41 +0200 |
---|---|---|
committer | HimbeerserverDE <himbeerserverde@gmail.com> | 2023-05-11 18:03:41 +0200 |
commit | 8c39c7f86fbf8f35b20239bd9dbd6701ab1c2664 (patch) | |
tree | 321350664847e7c6ead1997f6cfa4de94d7123b5 | |
parent | c08c7e1eeb24592aa2fcd026ec47515fdd6ab699 (diff) |
implement handshake timeouts0.1.5
should fix #2
-rw-r--r-- | Cargo.lock | 2 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | src/client.rs | 82 | ||||
-rw-r--r-- | src/error.rs | 2 |
4 files changed, 79 insertions, 9 deletions
@@ -869,7 +869,7 @@ dependencies = [ [[package]] name = "rsdsl_pppoe" -version = "0.1.4" +version = "0.1.5" dependencies = [ "byteorder", "md5", @@ -1,6 +1,6 @@ [package] name = "rsdsl_pppoe" -version = "0.1.4" +version = "0.1.5" authors = ["HimbeerserverDE <himbeerserverde@gmail.com>"] license = "MIT" edition = "2021" diff --git a/src/client.rs b/src/client.rs index b28773a..1bf205e 100644 --- a/src/client.rs +++ b/src/client.rs @@ -6,7 +6,7 @@ use std::num::NonZeroU16; use std::sync::mpsc; use std::sync::{Arc, Mutex, RwLock}; use std::thread; -use std::time::Duration; +use std::time::{Duration, Instant}; use byteorder::{ByteOrder, NetworkEndian as NE}; @@ -44,6 +44,20 @@ impl Default for State { } } +#[derive(Clone, Copy, Debug, PartialEq)] +enum SessionState { + Link, + Auth, + Network, + Open, +} + +impl Default for SessionState { + fn default() -> Self { + Self::Link + } +} + #[derive(Clone, Debug)] pub struct Client { inner: Arc<RwLock<ClientRef>>, @@ -60,6 +74,7 @@ impl Client { started: false, host_uniq: rand::random(), state: State::default(), + session_state: SessionState::default(), peer: BROADCAST, magic_number: rand::random(), error: String::new(), @@ -158,10 +173,18 @@ impl Client { self.inner.read().unwrap().state } + fn session_state(&self) -> SessionState { + self.inner.read().unwrap().session_state + } + fn set_state(&self, state: State) { self.inner.write().unwrap().state = state; } + fn set_session_state(&self, state: SessionState) { + self.inner.write().unwrap().session_state = state; + } + fn session_id(&self) -> Result<NonZeroU16> { match self.state() { State::Session(session_id) => Ok(session_id), @@ -319,6 +342,31 @@ impl Client { }); } + fn send_timeout(&self, buf: &[u8], state: SessionState, msg: impl Into<String>) { + const MAX: u8 = 10; + + let this = self.clone(); + let buf = buf.to_vec(); + let msg = msg.into(); + + thread::spawn(move || { + let mut i = 1; + while this.session_state() == state && i <= MAX { + match this.send(&buf) { + Ok(_) => println!("[pppoe] (re)transmit {}/{}: {}", i, MAX, &msg), + Err(e) => println!("[pppoe] (re)transmit {}/{} error: {}", i, MAX, e), + } + + thread::sleep(Duration::from_secs(3)); + i += 1 + } + + if i > MAX { + this.terminate(Err(Error::TooManyRetransmissions(msg))); + } + }); + } + fn recv<'a>(&'a self, buf: &'a mut [u8; BUFSIZE]) -> Result<Packet> { let mut n; @@ -397,9 +445,8 @@ impl Client { lcp::HeaderBuilder::create_configure_request(&mut request[22..26 + limit])?; self.new_lcp_packet(request)?; - self.send(request)?; + self.send_timeout(request, SessionState::Link, "lcp configure-req"); - println!("[pppoe] send lcp configure-req"); Ok(()) } @@ -426,9 +473,8 @@ impl Client { pap::HeaderBuilder::create_auth_request(&mut auth_req[22..])?; self.new_pap_packet(auth_req)?; - self.send(auth_req)?; + self.send_timeout(auth_req, SessionState::Auth, "pap authentication request"); - println!("[pppoe] send pap authentication request"); Ok(()) } @@ -457,9 +503,8 @@ impl Client { ipcp::HeaderBuilder::create_configure_request(&mut request[22..26 + limit])?; self.new_ipcp_packet(request)?; - self.send(request)?; + self.send_timeout(request, SessionState::Network, "ipcp configure-req"); - println!("[pppoe] send ipcp configure-req"); Ok(()) } @@ -499,6 +544,22 @@ impl Client { println!("[pppoe] recv lcp configure-req, opts: {:?}", opts); if auth_is_supported { + self.set_session_state(SessionState::Auth); + + let this = self.clone(); + thread::spawn(move || { + let start = Instant::now(); + while this.session_state() == SessionState::Auth + && start.duration_since(Instant::now()).as_secs() < 10 + { + thread::sleep(Duration::from_secs(1)); + } + + if this.session_state() == SessionState::Auth { + this.terminate(Err(Error::AuthTimeout)); + } + }); + let limit = lcp.payload().len(); let mut ack = Vec::new(); @@ -656,6 +717,8 @@ impl Client { pap::AUTH_ACK => { println!("[pppoe] auth success"); + self.set_session_state(SessionState::Network); + self.configure_ip()?; Ok(()) } @@ -707,6 +770,8 @@ impl Client { chap::SUCCESS => { println!("[pppoe] auth success"); + self.set_session_state(SessionState::Network); + self.configure_ip()?; Ok(()) } @@ -804,6 +869,8 @@ impl Client { }) .ok_or(Error::MissingSecondaryDns)?; + self.set_session_state(SessionState::Open); + self.set_ip_config(ip_config); tx.send(ip_config)?; @@ -990,6 +1057,7 @@ struct ClientRef { started: bool, host_uniq: [u8; 16], state: State, + session_state: SessionState, peer: [u8; 6], magic_number: u32, error: String, diff --git a/src/error.rs b/src/error.rs index 1411f3a..33dba2c 100644 --- a/src/error.rs +++ b/src/error.rs @@ -15,6 +15,8 @@ pub enum Error { PartialTransmission, #[error("too many retransmissions: {0}")] TooManyRetransmissions(String), + #[error("authentication timeout")] + AuthTimeout, #[error("invalid pkt code {0}")] InvalidCode(u8), #[error("unexpected pads")] |