Skip to main content

bitfold_peer/peer/
command_processor.rs

1use std::{collections::VecDeque, time::Instant};
2
3use bitfold_core::error::{ErrorKind, Result};
4use bitfold_protocol::{
5    command::ProtocolCommand,
6    command_codec::CommandDecoder,
7    packet::{DeliveryGuarantee, IncomingPackets, OrderingGuarantee, Packet, PacketType},
8};
9
10use super::Peer;
11use crate::{
12    channel_state::ChannelState, fragment_buffer::CommandFragmentBuffer, peer_state::PeerState,
13    pmtu_discovery::PmtuDiscovery,
14};
15
16impl Peer {
17    /// Decodes and processes an incoming command packet.
18    /// This is the command-based alternative to `process_incoming`.
19    /// Returns all user packets that resulted from processing the commands.
20    /// Validates CRC32 checksum if enabled, then decompresses if needed.
21    pub fn process_command_packet(
22        &mut self,
23        data: &[u8],
24        time: Instant,
25    ) -> Result<IncomingPackets> {
26        // Track bytes received
27        self.record_data_received(data.len());
28
29        // Validate and strip checksum if enabled (before decompression)
30        let payload = if self.config.use_checksums {
31            CommandDecoder::validate_and_strip_checksum(data)
32                .map_err(|e| ErrorKind::CouldNotReadHeader(e.to_string()))?
33        } else {
34            data
35        };
36
37        // Decompress if needed
38        let decompressed = CommandDecoder::decompress(payload)
39            .map_err(|e| ErrorKind::CouldNotReadHeader(e.to_string()))?;
40
41        let command_packet = CommandDecoder::decode_packet(&decompressed)
42            .map_err(|e| ErrorKind::CouldNotReadHeader(e.to_string()))?;
43
44        // Record packet being received
45        self.record_packet_received();
46
47        let mut all_packets = std::collections::VecDeque::new();
48
49        for command in &command_packet.commands {
50            let packets = self.process_command(command, time)?;
51            for packet in packets.into_iter() {
52                all_packets.push_back(packet);
53            }
54        }
55
56        Ok(IncomingPackets::many(all_packets))
57    }
58
59    /// Processes an incoming protocol command and returns resulting actions.
60    /// This is the command-based alternative to `process_incoming`.
61    /// Automatically enqueues response commands (ACK, Pong) when appropriate.
62    pub fn process_command(
63        &mut self,
64        command: &ProtocolCommand,
65        time: Instant,
66    ) -> Result<IncomingPackets> {
67        self.last_heard = time;
68
69        match command {
70            ProtocolCommand::Acknowledge { sequence, received_mask, .. } => {
71                self.acknowledge_handler.process_incoming(
72                    *sequence,
73                    *sequence,
74                    *received_mask,
75                    time,
76                );
77                Ok(IncomingPackets::zero())
78            }
79            ProtocolCommand::Ping { timestamp } => {
80                // Automatically respond with Pong
81                self.enqueue_pong_command(*timestamp);
82                Ok(IncomingPackets::zero())
83            }
84            ProtocolCommand::Pong { .. } => {
85                // Pong received, RTT calculated in acknowledgment handler
86                Ok(IncomingPackets::zero())
87            }
88            ProtocolCommand::SendReliable { channel_id, sequence, ordered, data } => {
89                // Process reliable data command
90                self.acknowledge_handler.process_incoming(*sequence, *sequence, 0, time);
91
92                // Automatically enqueue ACK for reliable data
93                self.enqueue_ack_command(None);
94                if *ordered {
95                    // Ordered delivery via per-channel buffering
96                    let channel_state =
97                        self.channel_states.entry(*channel_id).or_insert_with(ChannelState::new);
98
99                    let ordered_packets = channel_state.process_ordered(
100                        *sequence,
101                        bitfold_core::shared::SharedBytes::from_arc(
102                            data.clone().into_full_arc().unwrap_or_else(|| {
103                                std::sync::Arc::<[u8]>::from(
104                                    data.as_slice().to_vec().into_boxed_slice(),
105                                )
106                            }),
107                        ),
108                    );
109
110                    // Convert all ready packets to IncomingPackets
111                    let mut packets = VecDeque::new();
112                    for packet_data in ordered_packets {
113                        packets.push_back((
114                            Packet::new(
115                                self.remote_address,
116                                {
117                                    if let Some(full) = packet_data.clone().into_full_arc() {
118                                        full
119                                    } else {
120                                        std::sync::Arc::<[u8]>::from(
121                                            packet_data.as_slice().to_vec().into_boxed_slice(),
122                                        )
123                                    }
124                                },
125                                DeliveryGuarantee::Reliable,
126                                OrderingGuarantee::Ordered(None),
127                                *channel_id,
128                            ),
129                            PacketType::Packet,
130                        ));
131                    }
132
133                    Ok(IncomingPackets::many(packets))
134                } else {
135                    // Unordered reliable: deliver immediately
136                    Ok(IncomingPackets::one(
137                        Packet::new(
138                            self.remote_address,
139                            data.clone().into_full_arc().unwrap_or_else(|| {
140                                std::sync::Arc::<[u8]>::from(
141                                    data.as_slice().to_vec().into_boxed_slice(),
142                                )
143                            }),
144                            DeliveryGuarantee::Reliable,
145                            OrderingGuarantee::None,
146                            *channel_id,
147                        ),
148                        PacketType::Packet,
149                    ))
150                }
151            }
152            ProtocolCommand::SendUnreliable { channel_id, data } => {
153                // Process unreliable data command (no ACK needed)
154                Ok(IncomingPackets::one(
155                    Packet::new(
156                        self.remote_address,
157                        data.clone().into_full_arc().unwrap_or_else(|| {
158                            std::sync::Arc::<[u8]>::from(
159                                data.as_slice().to_vec().into_boxed_slice(),
160                            )
161                        }),
162                        DeliveryGuarantee::Unreliable,
163                        OrderingGuarantee::None,
164                        *channel_id,
165                    ),
166                    PacketType::Packet,
167                ))
168            }
169            ProtocolCommand::SendUnreliableSequenced { channel_id, sequence, data } => {
170                // Get or create channel state for sequencing
171                let channel_state =
172                    self.channel_states.entry(*channel_id).or_insert_with(ChannelState::new);
173
174                // Apply per-channel sequencing (drops old packets)
175                if let Some(packet_data) = channel_state.process_sequenced(
176                    *sequence,
177                    bitfold_core::shared::SharedBytes::from_arc(
178                        data.clone().into_full_arc().unwrap_or_else(|| {
179                            std::sync::Arc::<[u8]>::from(
180                                data.as_slice().to_vec().into_boxed_slice(),
181                            )
182                        }),
183                    ),
184                ) {
185                    Ok(IncomingPackets::one(
186                        Packet::new(
187                            self.remote_address,
188                            {
189                                if let Some(full) = packet_data.clone().into_full_arc() {
190                                    full
191                                } else {
192                                    std::sync::Arc::<[u8]>::from(
193                                        packet_data.as_slice().to_vec().into_boxed_slice(),
194                                    )
195                                }
196                            },
197                            DeliveryGuarantee::Unreliable,
198                            OrderingGuarantee::Sequenced(None),
199                            *channel_id,
200                        ),
201                        PacketType::Packet,
202                    ))
203                } else {
204                    // Old packet, drop it
205                    Ok(IncomingPackets::zero())
206                }
207            }
208            ProtocolCommand::SendUnsequenced { channel_id, unsequenced_group, data } => {
209                // Check if this is a duplicate using the sliding window
210                if self.is_unsequenced_duplicate(*unsequenced_group) {
211                    // Duplicate packet, drop it
212                    Ok(IncomingPackets::zero())
213                } else {
214                    // Mark as received in the window
215                    self.mark_unsequenced_received(*unsequenced_group);
216
217                    // Deliver the packet
218                    Ok(IncomingPackets::one(
219                        Packet::new(
220                            self.remote_address,
221                            data.clone().into_full_arc().unwrap_or_else(|| {
222                                std::sync::Arc::<[u8]>::from(
223                                    data.as_slice().to_vec().into_boxed_slice(),
224                                )
225                            }),
226                            DeliveryGuarantee::Unreliable,
227                            OrderingGuarantee::Unsequenced,
228                            *channel_id,
229                        ),
230                        PacketType::Packet,
231                    ))
232                }
233            }
234            ProtocolCommand::SendFragment {
235                channel_id,
236                sequence,
237                ordered,
238                fragment_id,
239                fragment_count,
240                data,
241            } => {
242                // Process fragment and reassemble if complete
243                self.acknowledge_handler.process_incoming(*sequence, *sequence, 0, time);
244
245                // Get or create fragment buffer for this sequence
246                let buffer = self.command_fragments.entry(*sequence).or_insert_with(|| {
247                    CommandFragmentBuffer::new(*channel_id, *fragment_count, *ordered, time)
248                });
249
250                // Add this fragment
251                buffer.add_fragment(
252                    *fragment_id,
253                    data.clone().into_full_arc().unwrap_or_else(|| {
254                        std::sync::Arc::<[u8]>::from(data.as_slice().to_vec().into_boxed_slice())
255                    }),
256                );
257
258                // Check if reassembly is complete
259                if buffer.is_complete() {
260                    // Remove buffer and reassemble
261                    if let Some(buffer) = self.command_fragments.remove(sequence) {
262                        let channel_id = buffer.channel_id();
263                        let is_ordered = buffer.is_ordered();
264                        if let Some(reassembled) = buffer.reassemble() {
265                            // Automatically enqueue ACK for the complete fragmented packet
266                            self.enqueue_ack_command(None);
267
268                            if is_ordered {
269                                // For ordered: push through channel ordering using the sequence
270                                let channel_state = self
271                                    .channel_states
272                                    .entry(channel_id)
273                                    .or_insert_with(ChannelState::new);
274
275                                let ready_packets = channel_state.process_ordered(
276                                    *sequence,
277                                    bitfold_core::shared::SharedBytes::from_vec(reassembled),
278                                );
279                                if ready_packets.is_empty() {
280                                    return Ok(IncomingPackets::zero());
281                                } else if ready_packets.len() == 1 {
282                                    return Ok(IncomingPackets::one(
283                                        Packet::new(
284                                            self.remote_address,
285                                            ready_packets[0]
286                                                .clone()
287                                                .into_full_arc()
288                                                .unwrap_or_else(|| {
289                                                    std::sync::Arc::<[u8]>::from(
290                                                        ready_packets[0]
291                                                            .as_slice()
292                                                            .to_vec()
293                                                            .into_boxed_slice(),
294                                                    )
295                                                }),
296                                            DeliveryGuarantee::Reliable,
297                                            OrderingGuarantee::None,
298                                            channel_id,
299                                        ),
300                                        PacketType::Packet,
301                                    ));
302                                } else {
303                                    let mut vec = std::collections::VecDeque::new();
304                                    for payload in ready_packets {
305                                        vec.push_back((
306                                            Packet::new(
307                                                self.remote_address,
308                                                {
309                                                    if let Some(full) =
310                                                        payload.clone().into_full_arc()
311                                                    {
312                                                        full
313                                                    } else {
314                                                        std::sync::Arc::<[u8]>::from(
315                                                            payload
316                                                                .as_slice()
317                                                                .to_vec()
318                                                                .into_boxed_slice(),
319                                                        )
320                                                    }
321                                                },
322                                                DeliveryGuarantee::Reliable,
323                                                OrderingGuarantee::None,
324                                                channel_id,
325                                            ),
326                                            PacketType::Packet,
327                                        ));
328                                    }
329                                    return Ok(IncomingPackets::many(vec));
330                                }
331                            } else {
332                                // Unordered reliable: deliver immediately
333                                return Ok(IncomingPackets::one(
334                                    Packet::new(
335                                        self.remote_address,
336                                        std::sync::Arc::<[u8]>::from(
337                                            reassembled.into_boxed_slice(),
338                                        ),
339                                        DeliveryGuarantee::Reliable,
340                                        OrderingGuarantee::None,
341                                        channel_id,
342                                    ),
343                                    PacketType::Packet,
344                                ));
345                            }
346                        }
347                    }
348                }
349
350                // Not complete yet, or reassembly failed
351                Ok(IncomingPackets::zero())
352            }
353            ProtocolCommand::SendUnreliableFragment {
354                channel_id,
355                sequence,
356                fragment_id,
357                fragment_count,
358                data,
359            } => {
360                // Process unreliable fragment and reassemble if complete (no ACK needed)
361                // Get or create fragment buffer for this sequence
362                let buffer = self.command_fragments.entry(*sequence).or_insert_with(|| {
363                    CommandFragmentBuffer::new(*channel_id, *fragment_count, false, time)
364                });
365
366                // Add this fragment
367                buffer.add_fragment(
368                    *fragment_id,
369                    data.clone().into_full_arc().unwrap_or_else(|| {
370                        std::sync::Arc::<[u8]>::from(data.as_slice().to_vec().into_boxed_slice())
371                    }),
372                );
373
374                // Check if reassembly is complete
375                if buffer.is_complete() {
376                    // Remove buffer and reassemble
377                    if let Some(buffer) = self.command_fragments.remove(sequence) {
378                        let channel_id = buffer.channel_id();
379                        if let Some(reassembled) = buffer.reassemble() {
380                            // Return unreliable packet (no ACK)
381                            return Ok(IncomingPackets::one(
382                                Packet::new(
383                                    self.remote_address,
384                                    std::sync::Arc::<[u8]>::from(reassembled.into_boxed_slice()),
385                                    DeliveryGuarantee::Unreliable,
386                                    OrderingGuarantee::None,
387                                    channel_id,
388                                ),
389                                PacketType::Packet,
390                            ));
391                        }
392                    }
393                }
394
395                // Not complete yet, or reassembly failed
396                Ok(IncomingPackets::zero())
397            }
398            ProtocolCommand::Disconnect { reason: _ } => {
399                // Mark peer as zombie - session manager will emit disconnect event and clean up
400                self.state = PeerState::Zombie;
401                Ok(IncomingPackets::zero())
402            }
403            ProtocolCommand::Connect {
404                channels,
405                mtu: _,
406                protocol_version: _,
407                outgoing_session_id,
408                connect_id,
409            } => {
410                // Server-side: Received CONNECT from client (step 1 of 3-way handshake)
411                // Validate connect_id for replay protection
412                if self.state == PeerState::Idle {
413                    use rand::Rng;
414                    let mut rng = rand::rng();
415
416                    // Store client's session ID as our incoming
417                    self.incoming_session_id = *outgoing_session_id;
418                    // Assign a peer ID (in real impl, this would be managed by host)
419                    self.peer_id = rng.random();
420                    // Store connect ID for validation
421                    self.connect_id = *connect_id;
422
423                    // Transition to AcknowledgingConnect
424                    self.state = PeerState::AcknowledgingConnect;
425
426                    // Send VERIFY_CONNECT (step 2 of 3-way handshake)
427                    let verify_command = ProtocolCommand::VerifyConnect {
428                        peer_id: self.peer_id,
429                        channels: *channels.min(&self.config.channel_count), // Negotiate
430                        mtu: 1400,                                           // Negotiate MTU
431                        incoming_session_id: self.outgoing_session_id, // Server's outgoing (from client's perspective = incoming)
432                        outgoing_session_id: self.incoming_session_id, // Client's outgoing (echo it back for verification)
433                        window_size: self.window_size(),               // Send our window size
434                    };
435                    self.command_queue.enqueue(verify_command);
436                }
437                Ok(IncomingPackets::zero())
438            }
439            ProtocolCommand::VerifyConnect {
440                peer_id,
441                channels: _,
442                mtu: _,
443                incoming_session_id,
444                outgoing_session_id,
445                window_size,
446            } => {
447                // Client-side: Received VERIFY_CONNECT from server (step 2 of 3-way handshake)
448                if self.state == PeerState::Connecting {
449                    // Store server's session IDs
450                    self.peer_id = *peer_id;
451                    self.incoming_session_id = *incoming_session_id;
452
453                    // Negotiate window size (take minimum of ours and server's)
454                    if self.config.use_window_flow_control {
455                        self.set_window_size((*window_size).min(self.window_size()));
456                    }
457                    // Verify outgoing session ID matches
458                    if *outgoing_session_id != self.outgoing_session_id {
459                        // Session ID mismatch - potential attack
460                        return Err(ErrorKind::CouldNotReadHeader(
461                            "Session ID mismatch".to_string(),
462                        ));
463                    }
464
465                    // Transition to ConnectionSucceeded
466                    self.state = PeerState::ConnectionSucceeded;
467
468                    // Send ACK (any data packet serves as implicit ACK - step 3)
469                    // The next data packet sent will complete the handshake
470                }
471                Ok(IncomingPackets::zero())
472            }
473            ProtocolCommand::BandwidthLimit { incoming, outgoing } => {
474                // Dynamically adjust bandwidth limits at runtime
475                self.config.incoming_bandwidth_limit = *incoming;
476                self.config.outgoing_bandwidth_limit = *outgoing;
477                self.bandwidth_throttle.set_incoming_bandwidth_limit(*incoming);
478                self.bandwidth_throttle.set_outgoing_bandwidth_limit(*outgoing);
479                tracing::debug!(
480                    "Applied BandwidthLimit: incoming={}B/s outgoing={}B/s",
481                    incoming,
482                    outgoing
483                );
484                Ok(IncomingPackets::zero())
485            }
486            ProtocolCommand::ThrottleConfigure { interval, acceleration, deceleration } => {
487                // Update throttle configuration dynamically
488                self.acknowledge_handler.congestion_mut().configure_throttle(
489                    *interval,
490                    *acceleration,
491                    *deceleration,
492                );
493                tracing::debug!(
494                    "Throttle configured: interval={}ms, accel={}, decel={}",
495                    interval,
496                    acceleration,
497                    deceleration
498                );
499                Ok(IncomingPackets::zero())
500            }
501            ProtocolCommand::PMTUProbe { size, token, .. } => {
502                // Respond to PMTU probe with a reply (small control)
503                let reply = PmtuDiscovery::create_reply(*size, *token);
504                self.enqueue_command(reply);
505                Ok(IncomingPackets::zero())
506            }
507            ProtocolCommand::PMTUReply { size, token } => {
508                // Process the reply through the PMTU discovery module
509                self.pmtu.process_reply(*size, *token, time);
510                Ok(IncomingPackets::zero())
511            }
512        }
513    }
514}
515
516#[cfg(test)]
517mod tests {
518    use bitfold_core::config::Config;
519    use bitfold_protocol::command::ProtocolCommand;
520
521    use super::*;
522
523    fn create_virtual_connection() -> Peer {
524        Peer::new(get_fake_addr(), &Config::default(), Instant::now())
525    }
526
527    fn get_fake_addr() -> std::net::SocketAddr {
528        "127.0.0.1:0".parse().unwrap()
529    }
530
531    #[test]
532    fn test_command_queue_integration() {
533        let mut peer = create_virtual_connection();
534
535        // Test enqueuing commands
536        assert!(!peer.has_queued_commands());
537        assert_eq!(peer.queued_commands_count(), 0);
538
539        peer.enqueue_command(ProtocolCommand::Ping { timestamp: 1000 });
540        assert!(peer.has_queued_commands());
541        assert_eq!(peer.queued_commands_count(), 1);
542
543        peer.enqueue_command(ProtocolCommand::SendReliable {
544            channel_id: 0,
545            sequence: 0,
546            ordered: true,
547            data: vec![1, 2, 3].into(),
548        });
549        assert_eq!(peer.queued_commands_count(), 2);
550
551        // Test draining commands
552        let commands: Vec<_> = peer.drain_commands().collect();
553        assert_eq!(commands.len(), 2);
554        assert!(!peer.has_queued_commands());
555    }
556
557    #[test]
558    fn test_process_command_reliable_data() {
559        let mut peer = create_virtual_connection();
560        let time = Instant::now();
561
562        let command = ProtocolCommand::SendReliable {
563            channel_id: 0,
564            sequence: 0,
565            ordered: true,
566            data: vec![1, 2, 3, 4].into(),
567        };
568
569        let result = peer.process_command(&command, time).unwrap();
570        let packets: Vec<_> = result.into_iter().collect();
571
572        assert_eq!(packets.len(), 1);
573        let (packet, _) = &packets[0];
574        assert_eq!(packet.payload(), &[1, 2, 3, 4]);
575    }
576
577    #[test]
578    fn test_process_command_unreliable_data() {
579        let mut peer = create_virtual_connection();
580        let time = Instant::now();
581
582        let command = ProtocolCommand::SendUnreliable { channel_id: 0, data: vec![5, 6, 7].into() };
583
584        let result = peer.process_command(&command, time).unwrap();
585        let packets: Vec<_> = result.into_iter().collect();
586
587        assert_eq!(packets.len(), 1);
588        let (packet, _) = &packets[0];
589        assert_eq!(packet.payload(), &[5, 6, 7]);
590    }
591
592    #[test]
593    fn test_automatic_pong_response() {
594        let mut peer = create_virtual_connection();
595        let time = Instant::now();
596
597        // Initially no queued commands
598        assert!(!peer.has_queued_commands());
599
600        // Process Ping command
601        let ping = ProtocolCommand::Ping { timestamp: 12345 };
602        peer.process_command(&ping, time).unwrap();
603
604        // Should have automatically enqueued a Pong response
605        assert!(peer.has_queued_commands());
606        assert_eq!(peer.queued_commands_count(), 1);
607
608        let commands: Vec<_> = peer.drain_commands().collect();
609        assert_eq!(commands.len(), 1);
610        match &commands[0] {
611            ProtocolCommand::Pong { timestamp } => {
612                assert_eq!(*timestamp, 12345);
613            }
614            _ => panic!("Expected Pong command"),
615        }
616    }
617
618    #[test]
619    fn test_automatic_ack_response() {
620        let mut peer = create_virtual_connection();
621        let time = Instant::now();
622
623        // Initially no queued commands
624        assert!(!peer.has_queued_commands());
625
626        // Process SendReliable command (sequence starts at 0)
627        let reliable = ProtocolCommand::SendReliable {
628            channel_id: 0,
629            sequence: 0,
630            ordered: true,
631            data: vec![1, 2, 3, 4].into(),
632        };
633        let result = peer.process_command(&reliable, time).unwrap();
634
635        // Should have data packet
636        assert_eq!(result.into_iter().count(), 1);
637
638        // Should have automatically enqueued an ACK
639        assert!(peer.has_queued_commands());
640        let commands: Vec<_> = peer.drain_commands().collect();
641        assert_eq!(commands.len(), 1);
642        match &commands[0] {
643            ProtocolCommand::Acknowledge { .. } => {
644                // ACK command was enqueued
645            }
646            _ => panic!("Expected Acknowledge command"),
647        }
648    }
649
650    #[test]
651    fn test_round_trip_ping_pong() {
652        let mut peer1 = create_virtual_connection();
653        let mut peer2 = create_virtual_connection();
654        let time = Instant::now();
655
656        // peer1 sends Ping
657        peer1.enqueue_ping_command(1000);
658        let bytes = peer1.encode_queued_commands().unwrap();
659
660        // peer2 receives Ping and auto-responds with Pong
661        peer2.process_command_packet(&bytes, time).unwrap();
662        assert!(peer2.has_queued_commands());
663
664        let pong_bytes = peer2.encode_queued_commands().unwrap();
665
666        // peer1 receives Pong
667        peer1.process_command_packet(&pong_bytes, time).unwrap();
668        assert!(!peer1.has_queued_commands()); // No response to Pong
669    }
670
671    #[test]
672    fn test_round_trip_reliable_with_ack() {
673        let mut peer1 = create_virtual_connection();
674        let mut peer2 = create_virtual_connection();
675        let time = Instant::now();
676
677        // peer1 sends reliable data
678        peer1.enqueue_command(ProtocolCommand::SendReliable {
679            channel_id: 0,
680            sequence: 0,
681            ordered: true,
682            data: vec![1, 2, 3, 4, 5].into(),
683        });
684        let bytes = peer1.encode_queued_commands().unwrap();
685
686        // peer2 receives data and auto-responds with ACK
687        let result = peer2.process_command_packet(&bytes, time).unwrap();
688        let packets: Vec<_> = result.into_iter().collect();
689        assert_eq!(packets.len(), 1);
690        assert_eq!(packets[0].0.payload(), &[1, 2, 3, 4, 5]);
691
692        // peer2 should have ACK queued
693        assert!(peer2.has_queued_commands());
694        let ack_bytes = peer2.encode_queued_commands().unwrap();
695
696        // peer1 receives ACK (no packets produced, but internal state updated)
697        let result = peer1.process_command_packet(&ack_bytes, time).unwrap();
698        assert_eq!(result.into_iter().count(), 0);
699    }
700
701    #[test]
702    fn test_bandwidth_limit_command_updates_config() {
703        let start = Instant::now();
704        let cfg = Config::default();
705        let mut peer = Peer::new(get_fake_addr(), &cfg, start);
706
707        // Initially set to default (2 MB/s for security)
708        assert_eq!(peer.config().incoming_bandwidth_limit, 2_097_152);
709        assert_eq!(peer.config().outgoing_bandwidth_limit, 2_097_152);
710
711        // Apply BandwidthLimit command
712        let _ = peer
713            .process_command(
714                &ProtocolCommand::BandwidthLimit { incoming: 1234, outgoing: 5678 },
715                start,
716            )
717            .unwrap();
718
719        assert_eq!(peer.config().incoming_bandwidth_limit, 1234);
720        assert_eq!(peer.config().outgoing_bandwidth_limit, 5678);
721    }
722
723    #[test]
724    fn test_multi_channel_packets() {
725        let mut peer = create_virtual_connection();
726        let time = Instant::now();
727
728        // Send data on different channels (each channel has independent sequences starting at 0)
729        let cmd_ch0 = ProtocolCommand::SendReliable {
730            channel_id: 0,
731            sequence: 0,
732            ordered: true,
733            data: vec![0, 1, 2].into(),
734        };
735        let cmd_ch1 = ProtocolCommand::SendReliable {
736            channel_id: 1,
737            sequence: 0,
738            ordered: true,
739            data: vec![10, 11, 12].into(),
740        };
741        let cmd_ch5 =
742            ProtocolCommand::SendUnreliable { channel_id: 5, data: vec![50, 51, 52].into() };
743
744        // Process commands
745        let result0 = peer.process_command(&cmd_ch0, time).unwrap();
746        let result1 = peer.process_command(&cmd_ch1, time).unwrap();
747        let result5 = peer.process_command(&cmd_ch5, time).unwrap();
748
749        // Verify packets have correct channel IDs
750        let packets0: Vec<_> = result0.into_iter().collect();
751        assert_eq!(packets0.len(), 1);
752        assert_eq!(packets0[0].0.channel_id(), 0);
753        assert_eq!(packets0[0].0.payload(), &[0, 1, 2]);
754
755        let packets1: Vec<_> = result1.into_iter().collect();
756        assert_eq!(packets1.len(), 1);
757        assert_eq!(packets1[0].0.channel_id(), 1);
758        assert_eq!(packets1[0].0.payload(), &[10, 11, 12]);
759
760        let packets5: Vec<_> = result5.into_iter().collect();
761        assert_eq!(packets5.len(), 1);
762        assert_eq!(packets5[0].0.channel_id(), 5);
763        assert_eq!(packets5[0].0.payload(), &[50, 51, 52]);
764    }
765
766    #[test]
767    fn test_per_channel_ordering() {
768        let mut peer = create_virtual_connection();
769        let time = Instant::now();
770
771        // Send packets out of order on channel 0
772        let cmd2 = ProtocolCommand::SendReliable {
773            channel_id: 0,
774            sequence: 2,
775            ordered: true,
776            data: vec![20, 21, 22].into(),
777        };
778        let cmd0 = ProtocolCommand::SendReliable {
779            channel_id: 0,
780            sequence: 0,
781            ordered: true,
782            data: vec![0, 1, 2].into(),
783        };
784        let cmd1 = ProtocolCommand::SendReliable {
785            channel_id: 0,
786            sequence: 1,
787            ordered: true,
788            data: vec![10, 11, 12].into(),
789        };
790
791        // Process out of order: 2, then 0, then 1
792        let result2 = peer.process_command(&cmd2, time).unwrap();
793        assert_eq!(result2.into_iter().count(), 0); // Buffered, waiting for 0 and 1
794
795        let result0 = peer.process_command(&cmd0, time).unwrap();
796        assert_eq!(result0.into_iter().count(), 1); // Delivers 0
797
798        let result1 = peer.process_command(&cmd1, time).unwrap();
799        let packets: Vec<_> = result1.into_iter().collect();
800        assert_eq!(packets.len(), 2); // Delivers 1 and 2 (buffered)
801
802        // Verify order
803        assert_eq!(packets[0].0.payload(), &[10, 11, 12]); // sequence 1
804        assert_eq!(packets[1].0.payload(), &[20, 21, 22]); // sequence 2
805    }
806
807    #[test]
808    fn test_reliable_unordered_delivery() {
809        let mut peer = create_virtual_connection();
810        let time = Instant::now();
811
812        // Send reliable packets out of order but mark as unordered
813        let cmd2 = ProtocolCommand::SendReliable {
814            channel_id: 0,
815            sequence: 2,
816            ordered: false,
817            data: vec![20, 21, 22].into(),
818        };
819        let cmd0 = ProtocolCommand::SendReliable {
820            channel_id: 0,
821            sequence: 0,
822            ordered: false,
823            data: vec![0, 1, 2].into(),
824        };
825        let cmd1 = ProtocolCommand::SendReliable {
826            channel_id: 0,
827            sequence: 1,
828            ordered: false,
829            data: vec![10, 11, 12].into(),
830        };
831
832        // Process in order: 2, then 0, then 1 — each should be delivered immediately
833        let r2 = peer.process_command(&cmd2, time).unwrap();
834        let v2: Vec<_> = r2.into_iter().collect();
835        assert_eq!(v2.len(), 1);
836        assert_eq!(v2[0].0.payload(), &[20, 21, 22]);
837
838        let r0 = peer.process_command(&cmd0, time).unwrap();
839        let v0: Vec<_> = r0.into_iter().collect();
840        assert_eq!(v0.len(), 1);
841        assert_eq!(v0[0].0.payload(), &[0, 1, 2]);
842
843        let r1 = peer.process_command(&cmd1, time).unwrap();
844        let v1: Vec<_> = r1.into_iter().collect();
845        assert_eq!(v1.len(), 1);
846        assert_eq!(v1[0].0.payload(), &[10, 11, 12]);
847    }
848
849    #[test]
850    fn test_per_channel_sequencing() {
851        let mut peer = create_virtual_connection();
852        let time = Instant::now();
853
854        // Send unreliable sequenced packets
855        let cmd0 = ProtocolCommand::SendUnreliableSequenced {
856            channel_id: 0,
857            sequence: 0,
858            data: vec![0, 1, 2].into(),
859        };
860        let cmd2 = ProtocolCommand::SendUnreliableSequenced {
861            channel_id: 0,
862            sequence: 2,
863            data: vec![20, 21, 22].into(),
864        };
865        let cmd1 = ProtocolCommand::SendUnreliableSequenced {
866            channel_id: 0,
867            sequence: 1,
868            data: vec![10, 11, 12].into(),
869        };
870
871        // Process in order: 0, 2, 1
872        let result0 = peer.process_command(&cmd0, time).unwrap();
873        assert_eq!(result0.into_iter().count(), 1); // Accepted
874
875        let result2 = peer.process_command(&cmd2, time).unwrap();
876        assert_eq!(result2.into_iter().count(), 1); // Accepted (newer)
877
878        let result1 = peer.process_command(&cmd1, time).unwrap();
879        assert_eq!(result1.into_iter().count(), 0); // Dropped (older than 2)
880    }
881
882    #[test]
883    fn test_independent_channel_ordering() {
884        let mut peer = create_virtual_connection();
885        let time = Instant::now();
886
887        // Send packets on different channels, out of order
888        let ch0_cmd1 = ProtocolCommand::SendReliable {
889            channel_id: 0,
890            sequence: 1,
891            ordered: true,
892            data: vec![0, 1].into(),
893        };
894        let ch1_cmd1 = ProtocolCommand::SendReliable {
895            channel_id: 1,
896            sequence: 1,
897            ordered: true,
898            data: vec![1, 1].into(),
899        };
900        let ch0_cmd0 = ProtocolCommand::SendReliable {
901            channel_id: 0,
902            sequence: 0,
903            ordered: true,
904            data: vec![0, 0].into(),
905        };
906        let ch1_cmd0 = ProtocolCommand::SendReliable {
907            channel_id: 1,
908            sequence: 0,
909            ordered: true,
910            data: vec![1, 0].into(),
911        };
912
913        // Channel 0: send 1 first (buffered)
914        let result = peer.process_command(&ch0_cmd1, time).unwrap();
915        assert_eq!(result.into_iter().count(), 0);
916
917        // Channel 1: send 1 first (buffered)
918        let result = peer.process_command(&ch1_cmd1, time).unwrap();
919        assert_eq!(result.into_iter().count(), 0);
920
921        // Channel 0: send 0 (delivers 0 and 1)
922        let result = peer.process_command(&ch0_cmd0, time).unwrap();
923        let packets: Vec<_> = result.into_iter().collect();
924        assert_eq!(packets.len(), 2);
925        assert_eq!(packets[0].0.channel_id(), 0);
926
927        // Channel 1: send 0 (delivers 0 and 1)
928        let result = peer.process_command(&ch1_cmd0, time).unwrap();
929        let packets: Vec<_> = result.into_iter().collect();
930        assert_eq!(packets.len(), 2);
931        assert_eq!(packets[0].0.channel_id(), 1);
932    }
933
934    #[test]
935    fn test_unsequenced_packets_basic() {
936        let mut peer = create_virtual_connection();
937        let time = Instant::now();
938
939        // Send unsequenced packets in order
940        let cmd1 = ProtocolCommand::SendUnsequenced {
941            channel_id: 0,
942            unsequenced_group: 0,
943            data: vec![1, 2, 3].into(),
944        };
945        let cmd2 = ProtocolCommand::SendUnsequenced {
946            channel_id: 0,
947            unsequenced_group: 1,
948            data: vec![4, 5, 6].into(),
949        };
950
951        // Process both packets
952        let result1 = peer.process_command(&cmd1, time).unwrap();
953        let result2 = peer.process_command(&cmd2, time).unwrap();
954
955        // Both should be delivered
956        assert_eq!(result1.into_iter().count(), 1);
957        assert_eq!(result2.into_iter().count(), 1);
958    }
959
960    #[test]
961    fn test_unsequenced_packets_prevent_duplicates() {
962        let mut peer = create_virtual_connection();
963        let time = Instant::now();
964
965        // Send the same unsequenced packet twice
966        let cmd = ProtocolCommand::SendUnsequenced {
967            channel_id: 0,
968            unsequenced_group: 5,
969            data: vec![1, 2, 3].into(),
970        };
971
972        // First delivery should succeed
973        let result1 = peer.process_command(&cmd, time).unwrap();
974        assert_eq!(result1.into_iter().count(), 1);
975
976        // Second delivery (duplicate) should be dropped
977        let result2 = peer.process_command(&cmd, time).unwrap();
978        assert_eq!(result2.into_iter().count(), 0); // Dropped as duplicate
979    }
980
981    #[test]
982    fn test_unsequenced_packets_allow_out_of_order() {
983        let mut peer = create_virtual_connection();
984        let time = Instant::now();
985
986        // Send packets out of order (10, 5, 15)
987        let cmd10 = ProtocolCommand::SendUnsequenced {
988            channel_id: 0,
989            unsequenced_group: 10,
990            data: vec![10].into(),
991        };
992        let cmd5 = ProtocolCommand::SendUnsequenced {
993            channel_id: 0,
994            unsequenced_group: 5,
995            data: vec![5].into(),
996        };
997        let cmd15 = ProtocolCommand::SendUnsequenced {
998            channel_id: 0,
999            unsequenced_group: 15,
1000            data: vec![15].into(),
1001        };
1002
1003        // All should be delivered (out of order is allowed)
1004        let result10 = peer.process_command(&cmd10, time).unwrap();
1005        let result5 = peer.process_command(&cmd5, time).unwrap();
1006        let result15 = peer.process_command(&cmd15, time).unwrap();
1007
1008        assert_eq!(result10.into_iter().count(), 1);
1009        assert_eq!(result5.into_iter().count(), 1);
1010        assert_eq!(result15.into_iter().count(), 1);
1011    }
1012
1013    #[test]
1014    fn test_unsequenced_window_sliding() {
1015        let mut peer = create_virtual_connection();
1016        let time = Instant::now();
1017
1018        // Send a packet at group 0
1019        let cmd0 = ProtocolCommand::SendUnsequenced {
1020            channel_id: 0,
1021            unsequenced_group: 0,
1022            data: vec![0].into(),
1023        };
1024        let result0 = peer.process_command(&cmd0, time).unwrap();
1025        assert_eq!(result0.into_iter().count(), 1);
1026
1027        // Send a packet far ahead (group 1500, outside window of 1024)
1028        let cmd1500 = ProtocolCommand::SendUnsequenced {
1029            channel_id: 0,
1030            unsequenced_group: 1500,
1031            data: vec![1].into(),
1032        };
1033        let result1500 = peer.process_command(&cmd1500, time).unwrap();
1034        assert_eq!(result1500.into_iter().count(), 1); // Should be delivered, window slides
1035
1036        // Now send group 0 again - should be treated as very old and dropped
1037        let result0_again = peer.process_command(&cmd0, time).unwrap();
1038        assert_eq!(result0_again.into_iter().count(), 0); // Dropped as old/duplicate
1039    }
1040}