1use super::arq::{ArqConfig, ReceiveWindow, SendWindow};
14use super::header::{ConstrainedHeader, ConstrainedPacket};
15use super::state::{ConnectionState, StateEvent, StateMachine};
16use super::types::{ConnectionId, ConstrainedError, SequenceNumber};
17use std::collections::VecDeque;
18use std::net::SocketAddr;
19use std::time::{Duration, Instant};
20
21pub const DEFAULT_MSS: usize = 235;
24
25pub const DEFAULT_MTU: usize = 247;
27
28#[derive(Debug, Clone)]
30pub struct ConnectionConfig {
31 pub arq: ArqConfig,
33 pub mss: usize,
35 pub mtu: usize,
37 pub keepalive_interval: Duration,
39 pub idle_timeout: Duration,
41}
42
43impl Default for ConnectionConfig {
44 fn default() -> Self {
45 Self {
46 arq: ArqConfig::default(),
47 mss: DEFAULT_MSS,
48 mtu: DEFAULT_MTU,
49 keepalive_interval: Duration::from_secs(30),
50 idle_timeout: Duration::from_secs(300),
51 }
52 }
53}
54
55impl ConnectionConfig {
56 pub fn for_ble() -> Self {
58 Self {
59 arq: ArqConfig::for_ble(),
60 mss: 235,
61 mtu: 247,
62 keepalive_interval: Duration::from_secs(15),
63 idle_timeout: Duration::from_secs(120),
64 }
65 }
66
67 pub fn for_lora() -> Self {
69 Self {
70 arq: ArqConfig::for_lora(),
71 mss: 50, mtu: 55,
73 keepalive_interval: Duration::from_secs(60),
74 idle_timeout: Duration::from_secs(600),
75 }
76 }
77}
78
79#[derive(Debug, Clone)]
81pub enum ConnectionEvent {
82 Connected,
84 DataReceived(Vec<u8>),
86 Closed,
88 Reset,
90 Error(String),
92 Transmit(Vec<u8>),
94}
95
96#[derive(Debug)]
104pub struct ConstrainedConnection {
105 connection_id: ConnectionId,
107 remote_addr: SocketAddr,
109 state: StateMachine,
111 send_window: SendWindow,
113 receive_window: ReceiveWindow,
115 config: ConnectionConfig,
117 outbound: VecDeque<ConstrainedPacket>,
119 inbound: VecDeque<Vec<u8>>,
121 last_activity: Instant,
123 last_keepalive: Option<Instant>,
125 events: VecDeque<ConnectionEvent>,
127 local_seq: SequenceNumber,
129 is_initiator: bool,
131}
132
133impl ConstrainedConnection {
134 pub fn new_outbound(connection_id: ConnectionId, remote_addr: SocketAddr) -> Self {
136 Self::new(
137 connection_id,
138 remote_addr,
139 ConnectionConfig::default(),
140 true,
141 )
142 }
143
144 pub fn new_outbound_with_config(
146 connection_id: ConnectionId,
147 remote_addr: SocketAddr,
148 config: ConnectionConfig,
149 ) -> Self {
150 Self::new(connection_id, remote_addr, config, true)
151 }
152
153 pub fn new_inbound(connection_id: ConnectionId, remote_addr: SocketAddr) -> Self {
155 Self::new(
156 connection_id,
157 remote_addr,
158 ConnectionConfig::default(),
159 false,
160 )
161 }
162
163 pub fn new_inbound_with_config(
165 connection_id: ConnectionId,
166 remote_addr: SocketAddr,
167 config: ConnectionConfig,
168 ) -> Self {
169 Self::new(connection_id, remote_addr, config, false)
170 }
171
172 fn new(
174 connection_id: ConnectionId,
175 remote_addr: SocketAddr,
176 config: ConnectionConfig,
177 is_initiator: bool,
178 ) -> Self {
179 Self {
180 connection_id,
181 remote_addr,
182 state: StateMachine::new(),
183 send_window: SendWindow::new(config.arq.clone()),
184 receive_window: ReceiveWindow::new(config.arq.window_size),
185 config,
186 outbound: VecDeque::new(),
187 inbound: VecDeque::new(),
188 last_activity: Instant::now(),
189 last_keepalive: None,
190 events: VecDeque::new(),
191 local_seq: SequenceNumber::new(0),
192 is_initiator,
193 }
194 }
195
196 pub fn connection_id(&self) -> ConnectionId {
198 self.connection_id
199 }
200
201 pub fn remote_addr(&self) -> SocketAddr {
203 self.remote_addr
204 }
205
206 pub fn state(&self) -> ConnectionState {
208 self.state.state()
209 }
210
211 pub fn is_established(&self) -> bool {
213 self.state.state().is_established()
214 }
215
216 pub fn is_closed(&self) -> bool {
218 self.state.state().is_closed()
219 }
220
221 pub fn can_send(&self) -> bool {
223 self.state.can_send_data() && !self.send_window.is_full()
224 }
225
226 pub fn initiate(&mut self) -> Result<ConstrainedPacket, ConstrainedError> {
230 if !self.is_initiator {
231 return Err(ConstrainedError::InvalidStateTransition {
232 from: "inbound".to_string(),
233 to: "initiating".to_string(),
234 });
235 }
236
237 self.state.transition(StateEvent::Open)?;
238
239 let syn = ConstrainedPacket::control(ConstrainedHeader::syn(self.connection_id));
240
241 self.last_activity = Instant::now();
242 Ok(syn)
243 }
244
245 pub fn accept(
249 &mut self,
250 syn_seq: SequenceNumber,
251 ) -> Result<ConstrainedPacket, ConstrainedError> {
252 if self.is_initiator {
253 return Err(ConstrainedError::InvalidStateTransition {
254 from: "outbound".to_string(),
255 to: "accepting".to_string(),
256 });
257 }
258
259 self.state.transition(StateEvent::RecvSyn)?;
260
261 let syn_ack = ConstrainedPacket::control(ConstrainedHeader::syn_ack(
262 self.connection_id,
263 syn_seq.next(),
264 ));
265
266 self.last_activity = Instant::now();
267 Ok(syn_ack)
268 }
269
270 pub fn send(&mut self, data: &[u8]) -> Result<(), ConstrainedError> {
274 if !self.state.can_send_data() {
275 return Err(ConstrainedError::ConnectionClosed);
276 }
277
278 for chunk in data.chunks(self.config.mss) {
280 if self.send_window.is_full() {
281 return Err(ConstrainedError::SendBufferFull);
282 }
283
284 let seq = self.local_seq;
285 self.local_seq = self.local_seq.next();
286
287 self.send_window.add(seq, chunk.to_vec())?;
288
289 let packet = ConstrainedPacket::data(
290 self.connection_id,
291 seq,
292 self.receive_window.cumulative_ack(),
293 chunk.to_vec(),
294 );
295
296 self.outbound.push_back(packet);
297 }
298
299 self.last_activity = Instant::now();
300 Ok(())
301 }
302
303 pub fn recv(&mut self) -> Option<Vec<u8>> {
305 self.inbound.pop_front()
306 }
307
308 pub fn close(&mut self) -> Result<ConstrainedPacket, ConstrainedError> {
310 self.state.transition(StateEvent::Close)?;
311
312 let fin = ConstrainedPacket::control(ConstrainedHeader::fin(
313 self.connection_id,
314 self.local_seq,
315 self.receive_window.cumulative_ack(),
316 ));
317
318 self.last_activity = Instant::now();
319 Ok(fin)
320 }
321
322 pub fn reset(&mut self) -> ConstrainedPacket {
324 let _ = self.state.transition(StateEvent::RecvRst);
326
327 ConstrainedPacket::control(ConstrainedHeader::reset(self.connection_id))
328 }
329
330 pub fn process_packet(&mut self, packet: &ConstrainedPacket) -> Result<(), ConstrainedError> {
332 self.last_activity = Instant::now();
333 let header = &packet.header;
334
335 if header.is_rst() {
337 let _ = self.state.transition(StateEvent::RecvRst);
338 self.events.push_back(ConnectionEvent::Reset);
339 return Ok(());
340 }
341
342 match self.state.state() {
344 ConnectionState::Closed => {
345 if header.is_syn() && !header.is_ack() {
346 }
349 }
350
351 ConnectionState::SynSent => {
352 if header.is_syn_ack() {
353 self.state.transition(StateEvent::RecvSynAck)?;
354 self.receive_window.reset_with_seq(header.seq.next());
355
356 let ack = ConstrainedPacket::control(ConstrainedHeader::ack(
358 self.connection_id,
359 self.local_seq,
360 header.seq.next(),
361 ));
362 self.outbound.push_back(ack);
363
364 self.events.push_back(ConnectionEvent::Connected);
365 }
366 }
367
368 ConnectionState::SynReceived => {
369 if header.is_ack() {
370 self.state.transition(StateEvent::RecvAck)?;
371 self.events.push_back(ConnectionEvent::Connected);
372 }
373 }
374
375 ConnectionState::Established => {
376 if header.is_ack() {
378 let acked = self.send_window.acknowledge(header.ack);
379 tracing::trace!(acked, ack = header.ack.value(), "Processed ACK");
380 }
381
382 if header.is_data() && !packet.payload.is_empty() {
384 if let Some(deliverable) = self
385 .receive_window
386 .receive(header.seq, packet.payload.clone())
387 {
388 for (_, data) in deliverable {
389 self.inbound.push_back(data);
390 self.events.push_back(ConnectionEvent::DataReceived(vec![]));
391 }
392
393 let ack = ConstrainedPacket::control(ConstrainedHeader::ack(
395 self.connection_id,
396 self.local_seq,
397 self.receive_window.cumulative_ack(),
398 ));
399 self.outbound.push_back(ack);
400 }
401 }
402
403 if header.is_fin() {
405 self.state.transition(StateEvent::RecvFin)?;
406 let ack = ConstrainedPacket::control(ConstrainedHeader::ack(
407 self.connection_id,
408 self.local_seq,
409 header.seq.next(),
410 ));
411 self.outbound.push_back(ack);
412 self.events.push_back(ConnectionEvent::Closed);
413 }
414
415 if header.is_ping() {
417 let pong = ConstrainedPacket::control(ConstrainedHeader::pong(
418 self.connection_id,
419 header.seq,
420 ));
421 self.outbound.push_back(pong);
422 }
423 }
424
425 ConnectionState::FinWait => {
426 if header.is_ack() {
427 self.state.transition(StateEvent::RecvAck)?;
428 }
429 if header.is_fin() {
430 self.state.transition(StateEvent::RecvFin)?;
431 self.events.push_back(ConnectionEvent::Closed);
432 }
433 }
434
435 ConnectionState::Closing => {
436 if header.is_ack() || header.is_fin() {
437 self.state.transition(StateEvent::RecvAck)?;
438 }
439 }
440
441 ConnectionState::TimeWait => {
442 }
444 }
445
446 Ok(())
447 }
448
449 pub fn poll(&mut self) -> Vec<ConstrainedPacket> {
453 let mut packets = Vec::new();
454
455 if self.state.is_timed_out() {
457 let _ = self.state.transition(StateEvent::Timeout);
458 self.events
459 .push_back(ConnectionEvent::Error("Connection timed out".to_string()));
460 return packets;
461 }
462
463 if self.last_activity.elapsed() > self.config.idle_timeout {
465 let _ = self.state.transition(StateEvent::Timeout);
466 self.events
467 .push_back(ConnectionEvent::Error("Idle timeout".to_string()));
468 return packets;
469 }
470
471 match self.send_window.get_retransmissions() {
473 Some(retransmit_data) => {
474 for (seq, data) in retransmit_data {
475 let packet = ConstrainedPacket::data(
476 self.connection_id,
477 seq,
478 self.receive_window.cumulative_ack(),
479 data,
480 );
481 packets.push(packet);
482 }
483 }
484 None => {
485 let _ = self.state.transition(StateEvent::Timeout);
487 self.events.push_back(ConnectionEvent::Error(
488 "Maximum retransmissions exceeded".to_string(),
489 ));
490 return packets;
491 }
492 }
493
494 if self.state.state().is_established() && self.config.keepalive_interval > Duration::ZERO {
496 let should_ping = match self.last_keepalive {
497 Some(last) => last.elapsed() > self.config.keepalive_interval,
498 None => self.last_activity.elapsed() > self.config.keepalive_interval,
499 };
500
501 if should_ping {
502 let ping = ConstrainedPacket::control(ConstrainedHeader::ping(
503 self.connection_id,
504 self.local_seq,
505 ));
506 packets.push(ping);
507 self.last_keepalive = Some(Instant::now());
508 }
509 }
510
511 packets.extend(self.outbound.drain(..));
513
514 packets
515 }
516
517 pub fn next_event(&mut self) -> Option<ConnectionEvent> {
519 self.events.pop_front()
520 }
521
522 pub fn stats(&self) -> ConnectionStats {
524 ConnectionStats {
525 connection_id: self.connection_id,
526 state: self.state.state(),
527 remote_addr: self.remote_addr,
528 is_initiator: self.is_initiator,
529 send_window_used: self.send_window.len(),
530 receive_buffer_len: self.inbound.len(),
531 time_in_state: self.state.time_in_state(),
532 last_activity: self.last_activity.elapsed(),
533 }
534 }
535}
536
537#[derive(Debug, Clone)]
539pub struct ConnectionStats {
540 pub connection_id: ConnectionId,
542 pub state: ConnectionState,
544 pub remote_addr: SocketAddr,
546 pub is_initiator: bool,
548 pub send_window_used: usize,
550 pub receive_buffer_len: usize,
552 pub time_in_state: Duration,
554 pub last_activity: Duration,
556}
557
558#[cfg(test)]
559mod tests {
560 use super::*;
561 use std::net::{IpAddr, Ipv4Addr};
562
563 fn test_addr() -> SocketAddr {
564 SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080)
565 }
566
567 #[test]
568 fn test_connection_new_outbound() {
569 let conn = ConstrainedConnection::new_outbound(ConnectionId::new(0x1234), test_addr());
570 assert_eq!(conn.connection_id(), ConnectionId::new(0x1234));
571 assert_eq!(conn.state(), ConnectionState::Closed);
572 assert!(!conn.is_established());
573 }
574
575 #[test]
576 fn test_connection_initiate() {
577 let mut conn = ConstrainedConnection::new_outbound(ConnectionId::new(0x1234), test_addr());
578
579 let syn = conn.initiate().expect("Should be able to initiate");
580 assert!(syn.header.is_syn());
581 assert!(!syn.header.is_ack());
582 assert_eq!(conn.state(), ConnectionState::SynSent);
583 }
584
585 #[test]
586 fn test_connection_accept() {
587 let mut conn = ConstrainedConnection::new_inbound(ConnectionId::new(0x1234), test_addr());
588
589 let syn_ack = conn.accept(SequenceNumber::new(0)).expect("Should accept");
590 assert!(syn_ack.header.is_syn_ack());
591 assert_eq!(conn.state(), ConnectionState::SynReceived);
592 }
593
594 #[test]
595 fn test_connection_handshake() {
596 let mut initiator =
598 ConstrainedConnection::new_outbound(ConnectionId::new(0x1234), test_addr());
599 let syn = initiator.initiate().expect("initiate");
600
601 let mut responder =
603 ConstrainedConnection::new_inbound(ConnectionId::new(0x1234), test_addr());
604 let syn_ack = responder.accept(syn.header.seq).expect("accept");
605
606 initiator.process_packet(&syn_ack).expect("process syn-ack");
608 assert!(initiator.is_established());
609
610 let packets = initiator.poll();
612 assert!(!packets.is_empty());
613 let ack = &packets[0];
614 assert!(ack.header.is_ack());
615
616 responder.process_packet(ack).expect("process ack");
618 assert!(responder.is_established());
619 }
620
621 #[test]
622 fn test_connection_data_transfer() {
623 let mut sender =
625 ConstrainedConnection::new_outbound(ConnectionId::new(0x1234), test_addr());
626 sender.initiate().expect("initiate");
627
628 let mut receiver =
629 ConstrainedConnection::new_inbound(ConnectionId::new(0x1234), test_addr());
630 let syn_ack = receiver.accept(SequenceNumber::new(0)).expect("accept");
631
632 sender.process_packet(&syn_ack).expect("syn-ack");
633 let packets = sender.poll();
634 receiver.process_packet(&packets[0]).expect("ack");
635
636 sender.send(b"Hello, World!").expect("send");
638 let data_packets = sender.poll();
639 assert!(!data_packets.is_empty());
640
641 let data_pkt = &data_packets[0];
642 assert!(data_pkt.header.is_data());
643 assert_eq!(data_pkt.payload, b"Hello, World!");
644
645 receiver.process_packet(data_pkt).expect("process data");
647 let received = receiver.recv().expect("should have data");
648 assert_eq!(received, b"Hello, World!");
649 }
650
651 #[test]
652 fn test_connection_fragmentation() {
653 let config = ConnectionConfig {
654 mss: 10, ..Default::default()
656 };
657
658 let mut conn = ConstrainedConnection::new_outbound_with_config(
659 ConnectionId::new(0x1234),
660 test_addr(),
661 config,
662 );
663 conn.initiate().expect("initiate");
664
665 conn.state
667 .transition(StateEvent::RecvSynAck)
668 .expect("established");
669
670 let data = b"Hello, this is a longer message!";
672 conn.send(data).expect("send");
673
674 let packets = conn.poll();
675 assert!(packets.len() >= 3);
677 }
678
679 #[test]
680 fn test_connection_close() {
681 let mut conn = ConstrainedConnection::new_outbound(ConnectionId::new(0x1234), test_addr());
682 conn.initiate().expect("initiate");
683 conn.state
684 .transition(StateEvent::RecvSynAck)
685 .expect("established");
686
687 let fin = conn.close().expect("close");
688 assert!(fin.header.is_fin());
689 assert_eq!(conn.state(), ConnectionState::FinWait);
690 }
691
692 #[test]
693 fn test_connection_reset() {
694 let mut conn = ConstrainedConnection::new_outbound(ConnectionId::new(0x1234), test_addr());
695 conn.initiate().expect("initiate");
696
697 let rst = conn.reset();
698 assert!(rst.header.is_rst());
699 assert!(conn.is_closed());
700 }
701
702 #[test]
703 fn test_connection_stats() {
704 let conn = ConstrainedConnection::new_outbound(ConnectionId::new(0xABCD), test_addr());
705 let stats = conn.stats();
706
707 assert_eq!(stats.connection_id, ConnectionId::new(0xABCD));
708 assert_eq!(stats.state, ConnectionState::Closed);
709 assert!(stats.is_initiator);
710 assert_eq!(stats.send_window_used, 0);
711 }
712
713 #[test]
714 fn test_config_for_ble() {
715 let config = ConnectionConfig::for_ble();
716 assert_eq!(config.mss, 235);
717 assert_eq!(config.mtu, 247);
718 assert_eq!(config.arq.window_size, 4);
719 }
720
721 #[test]
722 fn test_config_for_lora() {
723 let config = ConnectionConfig::for_lora();
724 assert_eq!(config.mss, 50);
725 assert_eq!(config.mtu, 55);
726 assert!(config.keepalive_interval >= Duration::from_secs(60));
727 }
728
729 #[test]
730 fn test_process_ping_pong() {
731 let mut conn = ConstrainedConnection::new_outbound(ConnectionId::new(0x1234), test_addr());
732 conn.initiate().expect("initiate");
733 conn.state
734 .transition(StateEvent::RecvSynAck)
735 .expect("established");
736
737 let ping = ConstrainedPacket::control(ConstrainedHeader::ping(
738 ConnectionId::new(0x1234),
739 SequenceNumber::new(5),
740 ));
741
742 conn.process_packet(&ping).expect("process ping");
743
744 let packets = conn.poll();
745 let pong = packets.iter().find(|p| p.header.is_pong());
746 assert!(pong.is_some());
747 }
748
749 #[test]
750 fn test_process_rst() {
751 let mut conn = ConstrainedConnection::new_outbound(ConnectionId::new(0x1234), test_addr());
752 conn.initiate().expect("initiate");
753
754 let rst = ConstrainedPacket::control(ConstrainedHeader::reset(ConnectionId::new(0x1234)));
755
756 conn.process_packet(&rst).expect("process rst");
757 assert!(conn.is_closed());
758
759 let event = conn.next_event();
760 assert!(matches!(event, Some(ConnectionEvent::Reset)));
761 }
762}