Skip to main content

rtc_sctp/association/
mod.rs

1use crate::association::{
2    state::{AckMode, AckState, AssociationState},
3    stats::AssociationStats,
4};
5use crate::chunk::chunk_header::CHUNK_HEADER_SIZE;
6use crate::chunk::{
7    Chunk, ErrorCauseUnrecognizedChunkType, USER_INITIATED_ABORT, chunk_abort::ChunkAbort,
8    chunk_cookie_ack::ChunkCookieAck, chunk_cookie_echo::ChunkCookieEcho, chunk_error::ChunkError,
9    chunk_forward_tsn::ChunkForwardTsn, chunk_forward_tsn::ChunkForwardTsnStream,
10    chunk_heartbeat::ChunkHeartbeat, chunk_heartbeat_ack::ChunkHeartbeatAck, chunk_init::ChunkInit,
11    chunk_init::ChunkInitAck, chunk_payload_data::ChunkPayloadData,
12    chunk_payload_data::PayloadProtocolIdentifier, chunk_reconfig::ChunkReconfig,
13    chunk_selective_ack::ChunkSelectiveAck, chunk_shutdown::ChunkShutdown,
14    chunk_shutdown_ack::ChunkShutdownAck, chunk_shutdown_complete::ChunkShutdownComplete,
15    chunk_type::CT_FORWARD_TSN,
16};
17use crate::config::{COMMON_HEADER_SIZE, DATA_CHUNK_HEADER_SIZE, ServerConfig, TransportConfig};
18use crate::packet::{CommonHeader, Packet};
19use crate::param::{
20    Param,
21    param_heartbeat_info::ParamHeartbeatInfo,
22    param_outgoing_reset_request::ParamOutgoingResetRequest,
23    param_reconfig_response::{ParamReconfigResponse, ReconfigResult},
24    param_state_cookie::ParamStateCookie,
25    param_supported_extensions::ParamSupportedExtensions,
26};
27use crate::queue::{payload_queue::PayloadQueue, pending_queue::PendingQueue};
28use crate::shared::{AssociationEventInner, AssociationId, EndpointEvent, EndpointEventInner};
29use crate::util::{sna16lt, sna32gt, sna32gte, sna32lt, sna32lte};
30use crate::{AssociationEvent, Payload, Side};
31use shared::error::{Error, Result};
32use shared::{TransportContext, TransportMessage, TransportProtocol};
33use stream::{ReliabilityType, Stream, StreamEvent, StreamId, StreamState};
34use timer::{ACK_INTERVAL, RtoManager, Timer, TimerTable};
35
36use crate::association::stream::RecvSendState;
37use bytes::{Bytes, BytesMut};
38use log::{debug, error, trace, warn};
39use rand::random;
40use rustc_hash::FxHashMap;
41use std::collections::{HashMap, VecDeque};
42use std::net::SocketAddr;
43use std::str::FromStr;
44use std::sync::Arc;
45use std::time::{Duration, Instant};
46use thiserror::Error;
47
48pub(crate) mod state;
49pub(crate) mod stats;
50pub(crate) mod stream;
51pub(crate) mod timer;
52
53#[cfg(test)]
54mod association_test;
55
56/// Reasons why an association might be lost
57#[derive(Debug, Error, Clone, PartialEq)]
58pub enum AssociationError {
59    /// Handshake failed
60    #[error("handshake failed due to {0}")]
61    HandshakeFailed(String),
62    /// The peer violated the QUIC specification as understood by this implementation
63    #[error("transport error")]
64    TransportError,
65    /// The peer's QUIC stack aborted the association automatically
66    #[error("aborted by peer")]
67    AssociationClosed,
68    /// The peer closed the association
69    #[error("closed by peer")]
70    ApplicationClosed,
71    /// The peer is unable to continue processing this association, usually due to having restarted
72    #[error("reset by peer")]
73    Reset,
74    /// Communication with the peer has lapsed for longer than the negotiated idle timeout
75    ///
76    /// If neither side is sending keep-alives, an association will time out after a long enough idle
77    /// period even if the peer is still reachable
78    #[error("timed out")]
79    TimedOut,
80    /// The local application closed the association
81    #[error("closed")]
82    LocallyClosed,
83}
84
85/// Events of interest to the application
86#[derive(Debug)]
87#[non_exhaustive]
88pub enum Event {
89    /// Handshake was failed
90    HandshakeFailed {
91        /// Reason that the association was closed
92        reason: AssociationError,
93    },
94
95    /// The association was successfully established
96    Connected,
97    /// The association was lost
98    ///
99    /// Emitted if the peer closes the association or an error is encountered.
100    AssociationLost {
101        /// Reason that the association was closed
102        reason: AssociationError,
103        /// The stream the loss was reported against.
104        id: StreamId,
105    },
106    /// Stream events
107    Stream(StreamEvent),
108    /// One or more application datagrams have been received
109    DatagramReceived,
110}
111
112///Association represents an SCTP association
113//13.2.  Parameters Necessary per Association (i.e., the TCB)
114//Peer : Tag value to be sent in every packet and is received
115//Verification: in the INIT or INIT ACK chunk.
116//Tag :
117//
118//My : Tag expected in every inbound packet and sent in the
119//Verification: INIT or INIT ACK chunk.
120//
121//Tag :
122//State : A state variable indicating what state the association
123// : is in, i.e., COOKIE-WAIT, COOKIE-ECHOED, ESTABLISHED,
124// : SHUTDOWN-PENDING, SHUTDOWN-SENT, SHUTDOWN-RECEIVED,
125// : SHUTDOWN-ACK-SENT.
126//
127// No Closed state is illustrated since if a
128// association is Closed its TCB SHOULD be removed.
129pub struct Association {
130    side: Side,
131    state: AssociationState,
132    handshake_completed: bool,
133    max_message_size: u32,
134    inflight_queue_length: usize,
135    will_send_shutdown: bool,
136    bytes_received: usize,
137    bytes_sent: usize,
138
139    peer_verification_tag: u32,
140    my_verification_tag: u32,
141    my_next_tsn: u32,
142    peer_last_tsn: u32,
143    // for RTT measurement
144    min_tsn2measure_rtt: u32,
145    will_send_forward_tsn: bool,
146    will_retransmit_fast: bool,
147    will_retransmit_reconfig: bool,
148    /// True only while the in-flight queue may still hold chunks flagged for
149    /// T3-rtx retransmission (set when the timer marks them, cleared once the
150    /// scan has re-sent them all). Lets `gather_outbound` skip the O(in-flight)
151    /// retransmit scan entirely in the steady state, where nothing is ever
152    /// marked — that scan was the single hottest function in the send profile.
153    t3_retransmit_pending: bool,
154
155    will_send_shutdown_ack: bool,
156    will_send_shutdown_complete: bool,
157
158    // Reconfig
159    my_next_rsn: u32,
160    reconfigs: HashMap<u32, ChunkReconfig>,
161    reconfig_requests: HashMap<u32, ParamOutgoingResetRequest>,
162
163    // Non-RFC internal data
164    remote_addr: SocketAddr,
165    local_addr: SocketAddr,
166    transport_protocol: TransportProtocol,
167
168    source_port: u16,
169    destination_port: u16,
170    my_max_num_inbound_streams: u16,
171    my_max_num_outbound_streams: u16,
172    my_cookie: Option<ParamStateCookie>,
173
174    payload_queue: PayloadQueue,
175    inflight_queue: PayloadQueue,
176    pending_queue: PendingQueue,
177    control_queue: VecDeque<Packet>,
178    stream_queue: VecDeque<u16>,
179
180    pub(crate) mtu: u32,
181    // max DATA chunk payload size
182    max_payload_size: u32,
183    cumulative_tsn_ack_point: u32,
184    advanced_peer_tsn_ack_point: u32,
185    use_forward_tsn: bool,
186    /// Max stream-sequence-number per *ordered* stream among abandoned chunks
187    /// currently in the forward-TSN window `(cumulative_tsn_ack_point,
188    /// advanced_peer_tsn_ack_point]`. Maintained incrementally as chunks are
189    /// abandoned (the two RFC 3758 C2 loops) so that `create_forward_tsn` is
190    /// O(streams) instead of rescanning the whole in-flight window — which, for
191    /// PR-SCTP data channels, ran ~1000 hashmap probes per FORWARD-TSN and was
192    /// ~9% of send CPU in profiles. Unordered chunks are omitted: the receiver
193    /// ignores the per-stream list for them (it advances by `new_cumulative_tsn`
194    /// alone), so reporting them was pure waste.
195    fwd_tsn_stream_map: FxHashMap<u16, u16>,
196
197    pub(crate) rto_mgr: RtoManager,
198    timers: TimerTable,
199
200    // Congestion control parameters
201    max_receive_buffer_size: u32,
202    // my congestion window size
203    pub(crate) cwnd: u32,
204    // calculated peer's receiver windows size
205    rwnd: u32,
206    // slow start threshold
207    pub(crate) ssthresh: u32,
208    partial_bytes_acked: u32,
209    pub(crate) in_fast_recovery: bool,
210    fast_recover_exit_point: u32,
211
212    // Chunks stored for retransmission
213    stored_init: Option<ChunkInit>,
214    stored_cookie_echo: Option<ChunkCookieEcho>,
215    /// Per-chunk lookups on the receive path; SIDs are bounded by the
216    /// negotiated stream count, so the faster non-SipHash hasher is safe.
217    pub(crate) streams: FxHashMap<StreamId, StreamState>,
218
219    events: VecDeque<Event>,
220    endpoint_events: VecDeque<EndpointEventInner>,
221    error: Option<AssociationError>,
222
223    // per inbound packet context
224    delayed_ack_triggered: bool,
225    immediate_ack_triggered: bool,
226
227    pub(crate) stats: AssociationStats,
228    ack_state: AckState,
229
230    // for testing
231    pub(crate) ack_mode: AckMode,
232}
233
234impl Default for Association {
235    fn default() -> Self {
236        Association {
237            side: Side::default(),
238            state: AssociationState::default(),
239            handshake_completed: false,
240            max_message_size: 0,
241            inflight_queue_length: 0,
242            will_send_shutdown: false,
243            bytes_received: 0,
244            bytes_sent: 0,
245
246            peer_verification_tag: 0,
247            my_verification_tag: 0,
248            my_next_tsn: 0,
249            peer_last_tsn: 0,
250            // for RTT measurement
251            min_tsn2measure_rtt: 0,
252            will_send_forward_tsn: false,
253            will_retransmit_fast: false,
254            will_retransmit_reconfig: false,
255            t3_retransmit_pending: false,
256
257            will_send_shutdown_ack: false,
258            will_send_shutdown_complete: false,
259
260            // Reconfig
261            my_next_rsn: 0,
262            reconfigs: HashMap::default(),
263            reconfig_requests: HashMap::default(),
264
265            // Non-RFC internal data
266            remote_addr: SocketAddr::from_str("0.0.0.0:0").unwrap(),
267            local_addr: SocketAddr::from_str("0.0.0.0:0").unwrap(),
268            transport_protocol: TransportProtocol::UDP,
269
270            source_port: 0,
271            destination_port: 0,
272            my_max_num_inbound_streams: 0,
273            my_max_num_outbound_streams: 0,
274            my_cookie: None,
275
276            payload_queue: PayloadQueue::default(),
277            inflight_queue: PayloadQueue::default(),
278            pending_queue: PendingQueue::default(),
279            control_queue: VecDeque::default(),
280            stream_queue: VecDeque::default(),
281
282            mtu: 0,
283            // max DATA chunk payload size
284            max_payload_size: 0,
285            cumulative_tsn_ack_point: 0,
286            advanced_peer_tsn_ack_point: 0,
287            use_forward_tsn: false,
288            fwd_tsn_stream_map: FxHashMap::default(),
289
290            rto_mgr: RtoManager::default(),
291            timers: TimerTable::default(),
292
293            // Congestion control parameters
294            max_receive_buffer_size: 0,
295            // my congestion window size
296            cwnd: 0,
297            // calculated peer's receiver windows size
298            rwnd: 0,
299            // slow start threshold
300            ssthresh: 0,
301            partial_bytes_acked: 0,
302            in_fast_recovery: false,
303            fast_recover_exit_point: 0,
304
305            // Chunks stored for retransmission
306            stored_init: None,
307            stored_cookie_echo: None,
308            streams: FxHashMap::default(),
309
310            events: VecDeque::default(),
311            endpoint_events: VecDeque::default(),
312            error: None,
313
314            // per inbound packet context
315            delayed_ack_triggered: false,
316            immediate_ack_triggered: false,
317
318            stats: AssociationStats::default(),
319            ack_state: AckState::default(),
320
321            // for testing
322            ack_mode: AckMode::default(),
323        }
324    }
325}
326
327impl Association {
328    #[allow(clippy::too_many_arguments)]
329    pub(crate) fn new(
330        server_config: Option<Arc<ServerConfig>>,
331        config: Arc<TransportConfig>,
332        max_payload_size: u32,
333        local_aid: AssociationId,
334        remote_addr: SocketAddr,
335        local_addr: SocketAddr,
336        protocol: TransportProtocol,
337        now: Instant,
338    ) -> Self {
339        let side = if server_config.is_some() {
340            Side::Server
341        } else {
342            Side::Client
343        };
344
345        // It's a bit strange, but we're going backwards from the calculation in
346        // config.rs to get max_payload_size from INITIAL_MTU.
347        let mtu = max_payload_size + COMMON_HEADER_SIZE + DATA_CHUNK_HEADER_SIZE;
348
349        // RFC 4690 Sec 7.2.1
350        // The initial cwnd before DATA transmission or after a sufficiently
351        // long idle period MUST be set to min(4*MTU, max (2*MTU, 4380bytes)).
352        let cwnd = (2 * mtu).clamp(4380, 4 * mtu);
353        let mut tsn = random::<u32>();
354        if tsn == 0 {
355            tsn += 1;
356        }
357
358        let mut this = Association {
359            side,
360            handshake_completed: false,
361            max_receive_buffer_size: config.max_receive_buffer_size(),
362            max_message_size: config.max_message_size(),
363            my_max_num_outbound_streams: config.max_num_outbound_streams(),
364            my_max_num_inbound_streams: config.max_num_inbound_streams(),
365            max_payload_size,
366
367            rto_mgr: RtoManager::new(),
368            timers: TimerTable::new(config.timer_config()),
369
370            mtu,
371            cwnd,
372            remote_addr,
373            local_addr,
374            transport_protocol: protocol,
375
376            my_verification_tag: local_aid,
377            my_next_tsn: tsn,
378            my_next_rsn: tsn,
379            min_tsn2measure_rtt: tsn,
380            cumulative_tsn_ack_point: tsn - 1,
381            advanced_peer_tsn_ack_point: tsn - 1,
382            error: None,
383
384            ..Default::default()
385        };
386
387        if side.is_client() {
388            let mut init = ChunkInit {
389                initial_tsn: this.my_next_tsn,
390                num_outbound_streams: this.my_max_num_outbound_streams,
391                num_inbound_streams: this.my_max_num_inbound_streams,
392                initiate_tag: this.my_verification_tag,
393                advertised_receiver_window_credit: this.max_receive_buffer_size,
394                ..Default::default()
395            };
396            init.set_supported_extensions();
397
398            this.set_state(AssociationState::CookieWait);
399            this.stored_init = Some(init);
400            let _ = this.send_init();
401            this.timers
402                .start(Timer::T1Init, now, this.rto_mgr.get_rto());
403        }
404
405        this
406    }
407
408    /// Returns application-facing event
409    ///
410    /// Associations should be polled for events after:
411    /// - a call was made to `handle_event`
412    /// - a call was made to `handle_timeout`
413    #[must_use]
414    pub fn poll(&mut self) -> Option<Event> {
415        if let Some(x) = self.events.pop_front() {
416            return Some(x);
417        }
418
419        /*TODO: if let Some(event) = self.streams.poll() {
420            return Some(Event::Stream(event));
421        }*/
422
423        if let Some(err) = self.error.take() {
424            return Some(Event::HandshakeFailed { reason: err });
425        }
426
427        None
428    }
429
430    /// Return endpoint-facing event
431    #[must_use]
432    pub fn poll_endpoint_event(&mut self) -> Option<EndpointEvent> {
433        self.endpoint_events.pop_front().map(EndpointEvent)
434    }
435
436    /// Returns the next time at which `handle_timeout` should be called
437    ///
438    /// The value returned may change after:
439    /// - the application performed some I/O on the association
440    /// - a call was made to `handle_transmit`
441    /// - a call to `poll_transmit` returned `Some`
442    /// - a call was made to `handle_timeout`
443    #[must_use]
444    pub fn poll_timeout(&self) -> Option<Instant> {
445        self.timers.next_timeout()
446    }
447
448    /// Returns packets to transmit
449    ///
450    /// Associations should be polled for transmit after:
451    /// - the application performed some I/O on the Association
452    /// - a call was made to `handle_event`
453    /// - a call was made to `handle_timeout`
454    #[must_use]
455    pub fn poll_transmit(&mut self, now: Instant) -> Option<TransportMessage<Payload>> {
456        let (contents, _) = self.gather_outbound(now);
457        if contents.is_empty() {
458            None
459        } else {
460            trace!(
461                "[{}] sending {} bytes (total {} datagrams)",
462                self.side,
463                contents.iter().fold(0, |l, c| l + c.len()),
464                contents.len()
465            );
466            Some(TransportMessage {
467                now,
468                transport: TransportContext {
469                    local_addr: self.local_addr,
470                    peer_addr: self.remote_addr,
471                    ecn: None,
472                    transport_protocol: Default::default(),
473                },
474                message: Payload::RawEncode(contents),
475            })
476        }
477    }
478
479    /// Process timer expirations
480    ///
481    /// Executes protocol logic, potentially preparing signals (including application `Event`s,
482    /// `EndpointEvent`s and outgoing datagrams) that should be extracted through the relevant
483    /// methods.
484    ///
485    /// It is most efficient to call this immediately after the system clock reaches the latest
486    /// `Instant` that was output by `poll_timeout`; however spurious extra calls will simply
487    /// no-op and therefore are safe.
488    pub fn handle_timeout(&mut self, now: Instant) {
489        for &timer in &Timer::VALUES {
490            let (expired, failure, n_rtos) = self.timers.is_expired(timer, now);
491            if !expired {
492                continue;
493            }
494            self.timers.set(timer, None);
495            //trace!("{:?} timeout", timer);
496
497            if timer == Timer::Ack {
498                self.on_ack_timeout();
499            } else if failure {
500                self.on_retransmission_failure(timer);
501            } else {
502                self.on_retransmission_timeout(timer, n_rtos);
503                self.timers.start(timer, now, self.rto_mgr.get_rto());
504            }
505        }
506    }
507
508    /// Process `AssociationEvent`s generated by the associated `Endpoint`
509    ///
510    /// Will execute protocol logic upon receipt of an association event, in turn preparing signals
511    /// (including application `Event`s, `EndpointEvent`s and outgoing datagrams) that should be
512    /// extracted through the relevant methods.
513    pub fn handle_event(&mut self, event: AssociationEvent) {
514        match event.0 {
515            AssociationEventInner::Datagram(transmit) => {
516                // If this packet could initiate a migration and we're a client or a server that
517                // forbids migration, drop the datagram. This could be relaxed to heuristically
518                // permit NAT-rebinding-like migration.
519                /*TODO:if remote != self.remote && self.server_config.as_ref().map_or(true, |x| !x.migration)
520                {
521                    trace!("discarding packet from unrecognized peer {}", remote);
522                    return;
523                }*/
524
525                if let Payload::PartialDecode(partial_decode) = transmit.message {
526                    debug!(
527                        "[{}] recving {} bytes",
528                        self.side,
529                        COMMON_HEADER_SIZE as usize + partial_decode.remaining.len()
530                    );
531
532                    let pkt = match partial_decode.finish() {
533                        Ok(p) => p,
534                        Err(err) => {
535                            warn!("[{}] unable to parse SCTP packet {}", self.side, err);
536                            return;
537                        }
538                    };
539
540                    if let Err(err) = self.handle_inbound(pkt, transmit.now) {
541                        error!("handle_inbound got err: {}", err);
542                        let _ = self.close(AssociationError::TransportError);
543                    }
544                } else {
545                    trace!("discarding invalid partial_decode");
546                }
547            } //TODO:
548        }
549    }
550
551    /// Returns Association statistics
552    pub fn stats(&self) -> AssociationStats {
553        self.stats
554    }
555
556    /// Whether the Association is in the process of being established
557    ///
558    /// If this returns `false`, the Association may be either established or closed, signaled by the
559    /// emission of a `Connected` or `AssociationLost` message respectively.
560    pub fn is_handshaking(&self) -> bool {
561        !self.handshake_completed
562    }
563
564    /// Whether the Association is closed
565    ///
566    /// Closed Associations cannot transport any further data. An association becomes closed when
567    /// either peer application intentionally closes it, or when either transport layer detects an
568    /// error such as a time-out or certificate validation failure.
569    ///
570    /// A `AssociationLost` event is emitted with details when the association becomes closed.
571    pub fn is_closed(&self) -> bool {
572        self.state == AssociationState::Closed
573    }
574
575    /// Whether there is no longer any need to keep the association around
576    ///
577    /// Closed associations become drained after a brief timeout to absorb any remaining in-flight
578    /// packets from the peer. All drained associations have been closed.
579    pub fn is_drained(&self) -> bool {
580        self.state.is_drained()
581    }
582
583    /// Look up whether we're the client or server of this Association
584    pub fn side(&self) -> Side {
585        self.side
586    }
587
588    /// The latest socket address for this Association's peer
589    pub fn remote_addr(&self) -> SocketAddr {
590        self.remote_addr
591    }
592
593    /// Current best estimate of this Association's latency (round-trip-time)
594    pub fn rtt(&self) -> Duration {
595        Duration::from_millis(self.rto_mgr.get_rto())
596    }
597
598    /// The local IP address which was used when the peer established
599    /// the association
600    ///
601    /// This can be different from the address the endpoint is bound to, in case
602    /// the endpoint is bound to a wildcard address like `0.0.0.0` or `::`.
603    ///
604    /// This will return `None` for clients.
605    ///
606    /// Retrieving the local IP address is currently supported on the following
607    /// platforms:
608    /// - Linux
609    ///
610    /// On all non-supported platforms the local IP address will not be available,
611    /// and the method will return `None`.
612    pub fn local_addr(&self) -> SocketAddr {
613        self.local_addr
614    }
615
616    /// Shutdown initiates the shutdown sequence. The method blocks until the
617    /// shutdown sequence is completed and the association is closed, or until the
618    /// passed context is done, in which case the context's error is returned.
619    pub fn shutdown(&mut self) -> Result<()> {
620        debug!("[{}] closing association..", self.side);
621
622        let state = self.state();
623        if state != AssociationState::Established {
624            return Err(Error::ErrShutdownNonEstablished);
625        }
626
627        // Attempt a graceful shutdown.
628        self.set_state(AssociationState::ShutdownPending);
629
630        if self.inflight_queue_length == 0 {
631            // No more outstanding, send shutdown.
632            self.will_send_shutdown = true;
633            self.awake_write_loop();
634            self.set_state(AssociationState::ShutdownSent);
635        }
636
637        self.endpoint_events.push_back(EndpointEventInner::Drained);
638
639        Ok(())
640    }
641
642    /// Close ends the SCTP Association and cleans up any state
643    pub fn close(&mut self, reason: AssociationError) -> Result<()> {
644        if self.state() != AssociationState::Closed {
645            self.set_state(AssociationState::Closed);
646
647            debug!("[{}] closing association..", self.side);
648
649            self.close_all_timers();
650
651            for si in self.streams.keys().cloned().collect::<Vec<u16>>() {
652                self.unregister_stream(si, reason.clone());
653            }
654
655            debug!("[{}] association closed", self.side);
656            debug!(
657                "[{}] stats nDATAs (in) : {}",
658                self.side,
659                self.stats.get_num_datas()
660            );
661            debug!(
662                "[{}] stats nSACKs (in) : {}",
663                self.side,
664                self.stats.get_num_sacks()
665            );
666            debug!(
667                "[{}] stats nT3Timeouts : {}",
668                self.side,
669                self.stats.get_num_t3timeouts()
670            );
671            debug!(
672                "[{}] stats nAckTimeouts: {}",
673                self.side,
674                self.stats.get_num_ack_timeouts()
675            );
676            debug!(
677                "[{}] stats nFastRetrans: {}",
678                self.side,
679                self.stats.get_num_fast_retrans()
680            );
681        }
682
683        Ok(())
684    }
685
686    /// open_stream opens a stream
687    pub fn open_stream(
688        &mut self,
689        stream_identifier: StreamId,
690        default_payload_type: PayloadProtocolIdentifier,
691    ) -> Result<Stream<'_>> {
692        if self.streams.contains_key(&stream_identifier) {
693            return Err(Error::ErrStreamAlreadyExist);
694        }
695
696        if let Some(s) = self.create_stream(stream_identifier, false, default_payload_type) {
697            Ok(s)
698        } else {
699            Err(Error::ErrStreamCreateFailed)
700        }
701    }
702
703    /// accept_stream accepts a stream
704    pub fn accept_stream(&mut self) -> Option<Stream<'_>> {
705        self.stream_queue
706            .pop_front()
707            .map(move |stream_identifier| Stream {
708                stream_identifier,
709                association: self,
710            })
711    }
712
713    /// stream returns a stream
714    pub fn stream(&mut self, stream_identifier: StreamId) -> Result<Stream<'_>> {
715        if !self.streams.contains_key(&stream_identifier) {
716            Err(Error::ErrStreamNotExisted)
717        } else {
718            Ok(Stream {
719                stream_identifier,
720                association: self,
721            })
722        }
723    }
724
725    /// The identifiers of every stream currently open on this association.
726    pub fn stream_ids(&self) -> Vec<StreamId> {
727        self.streams.keys().cloned().collect()
728    }
729
730    /// bytes_sent returns the number of bytes sent
731    pub(crate) fn bytes_sent(&self) -> usize {
732        self.bytes_sent
733    }
734
735    /// bytes_received returns the number of bytes received
736    pub(crate) fn bytes_received(&self) -> usize {
737        self.bytes_received
738    }
739
740    /// max_message_size returns the maximum message size you can send.
741    pub(crate) fn max_message_size(&self) -> u32 {
742        self.max_message_size
743    }
744
745    /// set_max_message_size sets the maximum message size you can send.
746    pub(crate) fn set_max_message_size(&mut self, max_message_size: u32) {
747        self.max_message_size = max_message_size;
748    }
749
750    /// unregister_stream un-registers a stream from the association
751    /// The caller should hold the association write lock.
752    fn unregister_stream(&mut self, stream_identifier: StreamId, reason: AssociationError) {
753        if let Some(mut s) = self.streams.remove(&stream_identifier) {
754            debug!("[{}] unregister_stream {}", self.side, stream_identifier);
755            self.events.push_back(Event::AssociationLost {
756                reason,
757                id: stream_identifier,
758            });
759            s.state = RecvSendState::Closed;
760        }
761    }
762
763    /// set_state atomically sets the state of the Association.
764    fn set_state(&mut self, new_state: AssociationState) {
765        if new_state != self.state {
766            debug!(
767                "[{}] state change: '{}' => '{}'",
768                self.side, self.state, new_state,
769            );
770        }
771        self.state = new_state;
772    }
773
774    /// state atomically returns the state of the Association.
775    pub(crate) fn state(&self) -> AssociationState {
776        self.state
777    }
778
779    /// caller must hold self.lock
780    fn send_init(&mut self) -> Result<()> {
781        if let Some(stored_init) = &self.stored_init {
782            debug!("[{}] sending INIT", self.side);
783
784            self.source_port = 5000; // Spec??
785            self.destination_port = 5000; // Spec??
786
787            let outbound = Packet {
788                common_header: CommonHeader {
789                    source_port: self.source_port,
790                    destination_port: self.destination_port,
791                    verification_tag: self.peer_verification_tag,
792                },
793                chunks: vec![Box::new(stored_init.clone())],
794            };
795
796            self.control_queue.push_back(outbound);
797            self.awake_write_loop();
798
799            Ok(())
800        } else {
801            Err(Error::ErrInitNotStoredToSend)
802        }
803    }
804
805    /// caller must hold self.lock
806    fn send_cookie_echo(&mut self) -> Result<()> {
807        if let Some(stored_cookie_echo) = &self.stored_cookie_echo {
808            debug!("[{}] sending COOKIE-ECHO", self.side);
809
810            let outbound = Packet {
811                common_header: CommonHeader {
812                    source_port: self.source_port,
813                    destination_port: self.destination_port,
814                    verification_tag: self.peer_verification_tag,
815                },
816                chunks: vec![Box::new(stored_cookie_echo.clone())],
817            };
818
819            self.control_queue.push_back(outbound);
820            self.awake_write_loop();
821
822            Ok(())
823        } else {
824            Err(Error::ErrCookieEchoNotStoredToSend)
825        }
826    }
827
828    /// handle_inbound parses incoming raw packets
829    fn handle_inbound(&mut self, p: Packet, now: Instant) -> Result<()> {
830        if let Err(err) = p.check_packet() {
831            warn!("[{}] failed validating packet {}", self.side, err);
832            return Ok(());
833        }
834
835        self.handle_chunk_start();
836
837        for c in &p.chunks {
838            self.handle_chunk(&p, c, now)?;
839        }
840
841        self.handle_chunk_end(now);
842
843        Ok(())
844    }
845
846    fn handle_chunk_start(&mut self) {
847        self.delayed_ack_triggered = false;
848        self.immediate_ack_triggered = false;
849    }
850
851    fn handle_chunk_end(&mut self, now: Instant) {
852        if self.immediate_ack_triggered {
853            self.ack_state = AckState::Immediate;
854            self.timers.stop(Timer::Ack);
855            self.awake_write_loop();
856        } else if self.delayed_ack_triggered {
857            // Will send delayed ack in the next ack timeout
858            self.ack_state = AckState::Delay;
859            self.timers.start(Timer::Ack, now, ACK_INTERVAL);
860        }
861    }
862
863    #[allow(clippy::borrowed_box)]
864    fn handle_chunk(&mut self, p: &Packet, chunk: &Box<dyn Chunk>, now: Instant) -> Result<()> {
865        chunk.check()?;
866        let chunk_any = chunk.as_any();
867        let packets = if let Some(c) = chunk_any.downcast_ref::<ChunkInit>() {
868            if c.is_ack {
869                self.handle_init_ack(p, c, now)?
870            } else {
871                self.handle_init(p, c)?
872            }
873        } else if let Some(c) = chunk_any.downcast_ref::<ChunkAbort>() {
874            let mut err_str = String::new();
875            for e in &c.error_causes {
876                if matches!(e.code, USER_INITIATED_ABORT) {
877                    debug!("User initiated abort received");
878                    let _ = self.close(AssociationError::Reset);
879                    return Ok(());
880                }
881                err_str += &format!("({})", e);
882            }
883            return Err(Error::ErrAbortChunk(err_str));
884        } else if let Some(c) = chunk_any.downcast_ref::<ChunkError>() {
885            let mut err_str = String::new();
886            for e in &c.error_causes {
887                err_str += &format!("({})", e);
888            }
889            return Err(Error::ErrAbortChunk(err_str));
890        } else if let Some(c) = chunk_any.downcast_ref::<ChunkHeartbeat>() {
891            self.handle_heartbeat(c)?
892        } else if let Some(c) = chunk_any.downcast_ref::<ChunkCookieEcho>() {
893            self.handle_cookie_echo(c)?
894        } else if chunk_any.downcast_ref::<ChunkCookieAck>().is_some() {
895            self.handle_cookie_ack()?
896        } else if let Some(c) = chunk_any.downcast_ref::<ChunkPayloadData>() {
897            self.handle_data(c)?
898        } else if let Some(c) = chunk_any.downcast_ref::<ChunkSelectiveAck>() {
899            self.handle_sack(c, now)?
900        } else if let Some(c) = chunk_any.downcast_ref::<ChunkReconfig>() {
901            self.handle_reconfig(c)?
902        } else if let Some(c) = chunk_any.downcast_ref::<ChunkForwardTsn>() {
903            self.handle_forward_tsn(c)?
904        } else if let Some(c) = chunk_any.downcast_ref::<ChunkShutdown>() {
905            self.handle_shutdown(c)?
906        } else if let Some(c) = chunk_any.downcast_ref::<ChunkShutdownAck>() {
907            self.handle_shutdown_ack(c)?
908        } else if let Some(c) = chunk_any.downcast_ref::<ChunkShutdownComplete>() {
909            self.handle_shutdown_complete(c)?
910        } else {
911            return Err(Error::ErrChunkTypeUnhandled);
912        };
913
914        if !packets.is_empty() {
915            let mut buf: VecDeque<_> = packets.into_iter().collect();
916            self.control_queue.append(&mut buf);
917            self.awake_write_loop();
918        }
919
920        Ok(())
921    }
922
923    fn handle_init(&mut self, p: &Packet, i: &ChunkInit) -> Result<Vec<Packet>> {
924        let state = self.state();
925        debug!("[{}] chunkInit received in state '{}'", self.side, state);
926
927        // https://tools.ietf.org/html/rfc4960#section-5.2.1
928        // Upon receipt of an INIT in the COOKIE-WAIT state, an endpoint MUST
929        // respond with an INIT ACK using the same parameters it sent in its
930        // original INIT chunk (including its Initiate Tag, unchanged).  When
931        // responding, the endpoint MUST send the INIT ACK back to the same
932        // address that the original INIT (sent by this endpoint) was sent.
933
934        if state != AssociationState::Closed
935            && state != AssociationState::CookieWait
936            && state != AssociationState::CookieEchoed
937        {
938            // 5.2.2.  Unexpected INIT in States Other than CLOSED, COOKIE-ECHOED,
939            //        COOKIE-WAIT, and SHUTDOWN-ACK-SENT
940            return Err(Error::ErrHandleInitState);
941        }
942
943        // Should we be setting any of these permanently until we've ACKed further?
944        self.my_max_num_inbound_streams =
945            std::cmp::min(i.num_inbound_streams, self.my_max_num_inbound_streams);
946        self.my_max_num_outbound_streams =
947            std::cmp::min(i.num_outbound_streams, self.my_max_num_outbound_streams);
948        self.peer_verification_tag = i.initiate_tag;
949        self.source_port = p.common_header.destination_port;
950        self.destination_port = p.common_header.source_port;
951
952        // 13.2 This is the last TSN received in sequence.  This value
953        // is set initially by taking the peer's initial TSN,
954        // received in the INIT or INIT ACK chunk, and
955        // subtracting one from it.
956        self.peer_last_tsn = if i.initial_tsn == 0 {
957            u32::MAX
958        } else {
959            i.initial_tsn - 1
960        };
961
962        // Adopt the peer's advertised receive window and seed ssthresh from it,
963        // mirroring handle_init_ack (and Pion's shared init path). RFC 4960
964        // §7.2.1 (Slow-Start) permits initialising ssthresh to the advertised
965        // receiver window; without this the answerer keeps ssthresh at its
966        // initial 0, so cwnd never starts below it, slow-start never runs, and
967        // cwnd only grows linearly under congestion avoidance (§7.2.2).
968        self.rwnd = i.advertised_receiver_window_credit;
969        debug!("[{}] initial rwnd={}", self.side, self.rwnd);
970        self.ssthresh = self.rwnd;
971
972        for param in &i.params {
973            if let Some(v) = param.as_any().downcast_ref::<ParamSupportedExtensions>() {
974                for t in &v.chunk_types {
975                    if *t == CT_FORWARD_TSN {
976                        debug!("[{}] use ForwardTSN (on init)", self.side);
977                        self.use_forward_tsn = true;
978                    }
979                }
980            }
981        }
982        if !self.use_forward_tsn {
983            warn!("[{}] not using ForwardTSN (on init)", self.side);
984        }
985
986        let mut outbound = Packet {
987            common_header: CommonHeader {
988                verification_tag: self.peer_verification_tag,
989                source_port: self.source_port,
990                destination_port: self.destination_port,
991            },
992            chunks: vec![],
993        };
994
995        let mut init_ack = ChunkInit {
996            is_ack: true,
997            initial_tsn: self.my_next_tsn,
998            num_outbound_streams: self.my_max_num_outbound_streams,
999            num_inbound_streams: self.my_max_num_inbound_streams,
1000            initiate_tag: self.my_verification_tag,
1001            advertised_receiver_window_credit: self.max_receive_buffer_size,
1002            ..Default::default()
1003        };
1004
1005        if self.my_cookie.is_none() {
1006            self.my_cookie = Some(ParamStateCookie::new());
1007        }
1008
1009        if let Some(my_cookie) = &self.my_cookie {
1010            init_ack.params = vec![Box::new(my_cookie.clone())];
1011        }
1012
1013        init_ack.set_supported_extensions();
1014
1015        outbound.chunks = vec![Box::new(init_ack)];
1016
1017        Ok(vec![outbound])
1018    }
1019
1020    fn handle_init_ack(
1021        &mut self,
1022        p: &Packet,
1023        i: &ChunkInitAck,
1024        now: Instant,
1025    ) -> Result<Vec<Packet>> {
1026        let state = self.state();
1027        debug!("[{}] chunkInitAck received in state '{}'", self.side, state);
1028        if state != AssociationState::CookieWait {
1029            // RFC 4960
1030            // 5.2.3.  Unexpected INIT ACK
1031            //   If an INIT ACK is received by an endpoint in any state other than the
1032            //   COOKIE-WAIT state, the endpoint should discard the INIT ACK chunk.
1033            //   An unexpected INIT ACK usually indicates the processing of an old or
1034            //   duplicated INIT chunk.
1035            return Ok(vec![]);
1036        }
1037
1038        self.my_max_num_inbound_streams =
1039            std::cmp::min(i.num_inbound_streams, self.my_max_num_inbound_streams);
1040        self.my_max_num_outbound_streams =
1041            std::cmp::min(i.num_outbound_streams, self.my_max_num_outbound_streams);
1042        self.peer_verification_tag = i.initiate_tag;
1043        self.peer_last_tsn = if i.initial_tsn == 0 {
1044            u32::MAX
1045        } else {
1046            i.initial_tsn - 1
1047        };
1048        if self.source_port != p.common_header.destination_port
1049            || self.destination_port != p.common_header.source_port
1050        {
1051            warn!("[{}] handle_init_ack: port mismatch", self.side);
1052            return Ok(vec![]);
1053        }
1054
1055        self.rwnd = i.advertised_receiver_window_credit;
1056        debug!("[{}] initial rwnd={}", self.side, self.rwnd);
1057
1058        // RFC 4690 Sec 7.2.1
1059        //  o  The initial value of ssthresh MAY be arbitrarily high (for
1060        //     example, implementations MAY use the size of the receiver
1061        //     advertised window).
1062        self.ssthresh = self.rwnd;
1063        trace!(
1064            "[{}] updated cwnd={} ssthresh={} inflight={} (INI)",
1065            self.side,
1066            self.cwnd,
1067            self.ssthresh,
1068            self.inflight_queue.get_num_bytes()
1069        );
1070
1071        self.timers.stop(Timer::T1Init);
1072        self.stored_init = None;
1073
1074        let mut cookie_param = None;
1075        for param in &i.params {
1076            if let Some(v) = param.as_any().downcast_ref::<ParamStateCookie>() {
1077                cookie_param = Some(v);
1078            } else if let Some(v) = param.as_any().downcast_ref::<ParamSupportedExtensions>() {
1079                for t in &v.chunk_types {
1080                    if *t == CT_FORWARD_TSN {
1081                        debug!("[{}] use ForwardTSN (on initAck)", self.side);
1082                        self.use_forward_tsn = true;
1083                    }
1084                }
1085            }
1086        }
1087        if !self.use_forward_tsn {
1088            warn!("[{}] not using ForwardTSN (on initAck)", self.side);
1089        }
1090
1091        if let Some(v) = cookie_param {
1092            self.stored_cookie_echo = Some(ChunkCookieEcho {
1093                cookie: v.cookie.clone(),
1094            });
1095
1096            self.send_cookie_echo()?;
1097
1098            self.timers
1099                .start(Timer::T1Cookie, now, self.rto_mgr.get_rto());
1100
1101            self.set_state(AssociationState::CookieEchoed);
1102
1103            Ok(vec![])
1104        } else {
1105            Err(Error::ErrInitAckNoCookie)
1106        }
1107    }
1108
1109    fn handle_heartbeat(&self, c: &ChunkHeartbeat) -> Result<Vec<Packet>> {
1110        trace!("[{}] chunkHeartbeat", self.side);
1111        if let Some(p) = c.params.first() {
1112            if let Some(hbi) = p.as_any().downcast_ref::<ParamHeartbeatInfo>() {
1113                return Ok(vec![Packet {
1114                    common_header: CommonHeader {
1115                        verification_tag: self.peer_verification_tag,
1116                        source_port: self.source_port,
1117                        destination_port: self.destination_port,
1118                    },
1119                    chunks: vec![Box::new(ChunkHeartbeatAck {
1120                        params: vec![Box::new(ParamHeartbeatInfo {
1121                            heartbeat_information: hbi.heartbeat_information.clone(),
1122                        })],
1123                    })],
1124                }]);
1125            } else {
1126                warn!(
1127                    "[{}] failed to handle Heartbeat, no ParamHeartbeatInfo",
1128                    self.side,
1129                );
1130            }
1131        }
1132
1133        Ok(vec![])
1134    }
1135
1136    fn handle_cookie_echo(&mut self, c: &ChunkCookieEcho) -> Result<Vec<Packet>> {
1137        let state = self.state();
1138        debug!("[{}] COOKIE-ECHO received in state '{}'", self.side, state);
1139
1140        if let Some(my_cookie) = &self.my_cookie {
1141            match state {
1142                AssociationState::Established => {
1143                    if my_cookie.cookie != c.cookie {
1144                        return Ok(vec![]);
1145                    }
1146                }
1147                AssociationState::Closed
1148                | AssociationState::CookieWait
1149                | AssociationState::CookieEchoed => {
1150                    if my_cookie.cookie != c.cookie {
1151                        return Ok(vec![]);
1152                    }
1153
1154                    self.timers.stop(Timer::T1Init);
1155                    self.stored_init = None;
1156
1157                    self.timers.stop(Timer::T1Cookie);
1158                    self.stored_cookie_echo = None;
1159
1160                    self.events.push_back(Event::Connected);
1161                    self.set_state(AssociationState::Established);
1162                    self.handshake_completed = true;
1163                }
1164                _ => return Ok(vec![]),
1165            };
1166        } else {
1167            debug!("[{}] COOKIE-ECHO received before initialization", self.side);
1168            return Ok(vec![]);
1169        }
1170
1171        Ok(vec![Packet {
1172            common_header: CommonHeader {
1173                verification_tag: self.peer_verification_tag,
1174                source_port: self.source_port,
1175                destination_port: self.destination_port,
1176            },
1177            chunks: vec![Box::new(ChunkCookieAck {})],
1178        }])
1179    }
1180
1181    fn handle_cookie_ack(&mut self) -> Result<Vec<Packet>> {
1182        let state = self.state();
1183        debug!("[{}] COOKIE-ACK received in state '{}'", self.side, state);
1184        if state != AssociationState::CookieEchoed {
1185            // RFC 4960
1186            // 5.2.5.  Handle Duplicate COOKIE-ACK.
1187            //   At any state other than COOKIE-ECHOED, an endpoint should silently
1188            //   discard a received COOKIE ACK chunk.
1189            return Ok(vec![]);
1190        }
1191
1192        self.timers.stop(Timer::T1Cookie);
1193        self.stored_cookie_echo = None;
1194
1195        self.events.push_back(Event::Connected);
1196        self.set_state(AssociationState::Established);
1197        self.handshake_completed = true;
1198
1199        Ok(vec![])
1200    }
1201
1202    fn handle_data(&mut self, d: &ChunkPayloadData) -> Result<Vec<Packet>> {
1203        debug!(
1204            "[{}] DATA: tsn={} peer_last_tsn={} immediateSack={} len={}, unordered={}",
1205            self.side,
1206            d.tsn,
1207            self.peer_last_tsn,
1208            d.immediate_sack,
1209            d.user_data.len(),
1210            d.unordered,
1211        );
1212        self.stats.inc_datas();
1213
1214        let can_push = self.payload_queue.can_push(d, self.peer_last_tsn);
1215        let mut stream_handle_data = false;
1216        if can_push {
1217            if self.get_or_create_stream(d.stream_identifier).is_some() {
1218                if self.get_my_receiver_window_credit() > 0 {
1219                    // Pass the new chunk to stream level as soon as it arrives
1220                    self.payload_queue.push(d.clone(), self.peer_last_tsn);
1221                    stream_handle_data = true;
1222                } else {
1223                    // Receive buffer is full. Two kinds of chunk are still worth taking,
1224                    // because refusing them is not something the application can relieve by
1225                    // draining.
1226                    //
1227                    // The first fills a gap below the highest TSN already queued.
1228                    let fills_gap = self
1229                        .payload_queue
1230                        .get_last_tsn_received()
1231                        .is_some_and(|last_tsn| sna32lt(d.tsn, *last_tsn));
1232
1233                    // The second is the next in-sequence chunk when nothing is readable at
1234                    // all, and it is what keeps a full buffer from becoming permanent. Bytes
1235                    // are released only when the application reads; `is_readable()` is
1236                    // head-of-line blocked by an incomplete chunk set; and the chunk that
1237                    // would complete that set is exactly `peer_last_tsn + 1`. Dropping it
1238                    // leaves the window at zero with no way to reopen — every retransmission
1239                    // is refused for the same reason, forever.
1240                    // See <https://github.com/webrtc-rs/webrtc/issues/822>.
1241                    //
1242                    // Guarded on nothing being readable so this stays an escape from deadlock
1243                    // rather than a licence to overrun the bound. A merely slow receiver has
1244                    // data to take and must be made to take it. Without the guard, the chunk
1245                    // accepted here is `peer_last_tsn + 1` — precisely the one that advances
1246                    // the cumulative ack — so every chunk would qualify and
1247                    // `max_receive_buffer_size` would stop bounding anything.
1248                    let unblocks_reassembly =
1249                        d.tsn == self.peer_last_tsn.wrapping_add(1) && !self.has_readable_data();
1250
1251                    if fills_gap || unblocks_reassembly {
1252                        debug!(
1253                            "[{}] receive buffer full, but accepted {} with tsn={} ssn={}",
1254                            self.side,
1255                            if fills_gap {
1256                                "as this is a missing chunk"
1257                            } else {
1258                                "as the in-sequence chunk that unblocks reassembly"
1259                            },
1260                            d.tsn,
1261                            d.stream_sequence_number
1262                        );
1263                        self.payload_queue.push(d.clone(), self.peer_last_tsn);
1264                        stream_handle_data = true;
1265                    } else {
1266                        debug!(
1267                            "[{}] receive buffer full. dropping DATA with tsn={} ssn={}",
1268                            self.side, d.tsn, d.stream_sequence_number
1269                        );
1270                    }
1271                }
1272            } else {
1273                // silently discard the data. (sender will retry on T3-rtx timeout)
1274                debug!("[{}] discard {}", self.side, d.stream_sequence_number);
1275                return Ok(vec![]);
1276            }
1277        }
1278
1279        let immediate_sack = d.immediate_sack;
1280
1281        if stream_handle_data && let Some(s) = self.streams.get_mut(&d.stream_identifier) {
1282            self.events.push_back(Event::DatagramReceived);
1283            if s.handle_data(d) && s.reassembly_queue.is_readable() {
1284                self.events.push_back(Event::Stream(StreamEvent::Readable {
1285                    id: s.stream_identifier,
1286                }));
1287            }
1288        }
1289
1290        self.handle_peer_last_tsn_and_acknowledgement(immediate_sack)
1291    }
1292
1293    fn handle_sack(&mut self, d: &ChunkSelectiveAck, now: Instant) -> Result<Vec<Packet>> {
1294        trace!(
1295            "[{}] {}, SACK: cumTSN={} a_rwnd={}",
1296            self.side,
1297            self.cumulative_tsn_ack_point,
1298            d.cumulative_tsn_ack,
1299            d.advertised_receiver_window_credit
1300        );
1301        let state = self.state();
1302        if state != AssociationState::Established
1303            && state != AssociationState::ShutdownPending
1304            && state != AssociationState::ShutdownReceived
1305        {
1306            return Ok(vec![]);
1307        }
1308
1309        self.stats.inc_sacks();
1310
1311        if sna32gt(self.cumulative_tsn_ack_point, d.cumulative_tsn_ack) {
1312            // RFC 4960 sec 6.2.1.  Processing a Received SACK
1313            // D)
1314            //   i) If Cumulative TSN Ack is less than the Cumulative TSN Ack
1315            //      Point, then drop the SACK.  Since Cumulative TSN Ack is
1316            //      monotonically increasing, a SACK whose Cumulative TSN Ack is
1317            //      less than the Cumulative TSN Ack Point indicates an out-of-
1318            //      order SACK.
1319
1320            debug!(
1321                "[{}] SACK Cumulative ACK {} is older than ACK point {}",
1322                self.side, d.cumulative_tsn_ack, self.cumulative_tsn_ack_point
1323            );
1324
1325            return Ok(vec![]);
1326        }
1327
1328        // Process selective ack
1329        let (bytes_acked_per_stream, htna) = self.process_selective_ack(d, now)?;
1330
1331        let mut total_bytes_acked = 0;
1332        for n_bytes_acked in bytes_acked_per_stream.values() {
1333            total_bytes_acked += *n_bytes_acked;
1334        }
1335
1336        let mut cum_tsn_ack_point_advanced = false;
1337        if sna32lt(self.cumulative_tsn_ack_point, d.cumulative_tsn_ack) {
1338            trace!(
1339                "[{}] SACK: cumTSN advanced: {} -> {}",
1340                self.side, self.cumulative_tsn_ack_point, d.cumulative_tsn_ack
1341            );
1342
1343            self.cumulative_tsn_ack_point = d.cumulative_tsn_ack;
1344            cum_tsn_ack_point_advanced = true;
1345            self.on_cumulative_tsn_ack_point_advanced(total_bytes_acked, now);
1346        }
1347
1348        for (si, n_bytes_acked) in &bytes_acked_per_stream {
1349            if *n_bytes_acked > 0 {
1350                // Report the exact bytes released for this stream (acknowledged OR
1351                // abandoned — both funnel through bytes_acked_per_stream) so upper
1352                // layers can decrement their own send-buffer accounting. Unlike the
1353                // edge-triggered BufferedAmountLow advisory below, this fires on
1354                // every release with the byte delta.
1355                self.events
1356                    .push_back(Event::Stream(StreamEvent::BufferedAmountReleased {
1357                        id: *si,
1358                        n_bytes: *n_bytes_acked as usize,
1359                    }));
1360            }
1361            if let Some(s) = self.streams.get_mut(si)
1362                && s.on_buffer_released(*n_bytes_acked)
1363            {
1364                trace!("StreamEvent::BufferedAmountLow");
1365                self.events
1366                    .push_back(Event::Stream(StreamEvent::BufferedAmountLow { id: *si }))
1367            }
1368        }
1369
1370        // New rwnd value
1371        // RFC 4960 sec 6.2.1.  Processing a Received SACK
1372        // D)
1373        //   ii) Set rwnd equal to the newly received a_rwnd minus the number
1374        //       of bytes still outstanding after processing the Cumulative
1375        //       TSN Ack and the Gap Ack Blocks.
1376
1377        // bytes acked were already subtracted by markAsAcked() method
1378        let bytes_outstanding = self.inflight_queue.get_num_bytes() as u32;
1379        if bytes_outstanding >= d.advertised_receiver_window_credit {
1380            self.rwnd = 0;
1381        } else {
1382            self.rwnd = d.advertised_receiver_window_credit - bytes_outstanding;
1383        }
1384
1385        self.process_fast_retransmission(d.cumulative_tsn_ack, htna, cum_tsn_ack_point_advanced)?;
1386
1387        if self.use_forward_tsn {
1388            // RFC 3758 Sec 3.5 C1
1389            if sna32lt(
1390                self.advanced_peer_tsn_ack_point,
1391                self.cumulative_tsn_ack_point,
1392            ) {
1393                self.advanced_peer_tsn_ack_point = self.cumulative_tsn_ack_point;
1394                // Window reset: everything previously tracked is now at/below
1395                // the cumulative ack point, so start the stream map fresh.
1396                self.fwd_tsn_stream_map.clear();
1397            }
1398
1399            // RFC 3758 Sec 3.5 C2 — advance over newly-abandoned chunks,
1400            // folding each ordered one into the forward-TSN stream map so
1401            // create_forward_tsn needn't rescan the window.
1402            let mut i = self.advanced_peer_tsn_ack_point + 1;
1403            while let Some((abandoned, unordered, si, ssn)) = self.inflight_queue.get(i).map(|c| {
1404                (
1405                    c.abandoned(),
1406                    c.unordered,
1407                    c.stream_identifier,
1408                    c.stream_sequence_number,
1409                )
1410            }) {
1411                if !abandoned {
1412                    break;
1413                }
1414                self.advanced_peer_tsn_ack_point = i;
1415                self.note_abandoned_for_forward_tsn(unordered, si, ssn);
1416                i += 1;
1417            }
1418
1419            // RFC 3758 Sec 3.5 C3
1420            if sna32gt(
1421                self.advanced_peer_tsn_ack_point,
1422                self.cumulative_tsn_ack_point,
1423            ) {
1424                self.will_send_forward_tsn = true;
1425                debug!(
1426                    "[{}] handleSack {}: sna32GT({}, {})",
1427                    self.side,
1428                    self.will_send_forward_tsn,
1429                    self.advanced_peer_tsn_ack_point,
1430                    self.cumulative_tsn_ack_point
1431                );
1432            } else {
1433                // No forward-TSN window open (receiver has caught up): drop any
1434                // stale per-stream SSNs so they aren't reported later.
1435                self.fwd_tsn_stream_map.clear();
1436            }
1437            self.awake_write_loop();
1438        }
1439
1440        self.postprocess_sack(state, cum_tsn_ack_point_advanced, now);
1441
1442        Ok(vec![])
1443    }
1444
1445    fn handle_reconfig(&mut self, c: &ChunkReconfig) -> Result<Vec<Packet>> {
1446        trace!("[{}] handle_reconfig", self.side);
1447
1448        let mut pp = vec![];
1449
1450        if let Some(param_a) = &c.param_a {
1451            self.handle_reconfig_param(param_a, &mut pp)?;
1452        }
1453
1454        if let Some(param_b) = &c.param_b {
1455            self.handle_reconfig_param(param_b, &mut pp)?;
1456        }
1457
1458        Ok(pp)
1459    }
1460
1461    fn handle_forward_tsn(&mut self, c: &ChunkForwardTsn) -> Result<Vec<Packet>> {
1462        trace!("[{}] FwdTSN: {}", self.side, c);
1463
1464        if !self.use_forward_tsn {
1465            warn!("[{}] received FwdTSN but not enabled", self.side);
1466            // Return an error chunk
1467            let cerr = ChunkError {
1468                error_causes: vec![ErrorCauseUnrecognizedChunkType::default()],
1469            };
1470
1471            let outbound = Packet {
1472                common_header: CommonHeader {
1473                    verification_tag: self.peer_verification_tag,
1474                    source_port: self.source_port,
1475                    destination_port: self.destination_port,
1476                },
1477                chunks: vec![Box::new(cerr)],
1478            };
1479            return Ok(vec![outbound]);
1480        }
1481
1482        // From RFC 3758 Sec 3.6:
1483        //   Note, if the "New Cumulative TSN" value carried in the arrived
1484        //   FORWARD TSN chunk is found to be behind or at the current cumulative
1485        //   TSN point, the data receiver MUST treat this FORWARD TSN as out-of-
1486        //   date and MUST NOT update its Cumulative TSN.  The receiver SHOULD
1487        //   send a SACK to its peer (the sender of the FORWARD TSN) since such a
1488        //   duplicate may indicate the previous SACK was lost in the network.
1489
1490        trace!(
1491            "[{}] should send ack? newCumTSN={} peer_last_tsn={}",
1492            self.side, c.new_cumulative_tsn, self.peer_last_tsn
1493        );
1494        if sna32lte(c.new_cumulative_tsn, self.peer_last_tsn) {
1495            trace!("[{}] sending ack on Forward TSN", self.side);
1496            self.ack_state = AckState::Immediate;
1497            self.timers.stop(Timer::Ack);
1498            self.awake_write_loop();
1499            return Ok(vec![]);
1500        }
1501
1502        // From RFC 3758 Sec 3.6:
1503        //   the receiver MUST perform the same TSN handling, including duplicate
1504        //   detection, gap detection, SACK generation, cumulative TSN
1505        //   advancement, etc. as defined in RFC 2960 [2]---with the following
1506        //   exceptions and additions.
1507
1508        //   When a FORWARD TSN chunk arrives, the data receiver MUST first update
1509        //   its cumulative TSN point to the value carried in the FORWARD TSN
1510        //   chunk,
1511
1512        // Advance peer_last_tsn
1513        while sna32lt(self.peer_last_tsn, c.new_cumulative_tsn) {
1514            self.payload_queue.pop(self.peer_last_tsn + 1); // may not exist
1515            self.peer_last_tsn += 1;
1516        }
1517
1518        // Report new peer_last_tsn value and abandoned largest SSN value to
1519        // corresponding streams so that the abandoned chunks can be removed
1520        // from the reassemblyQueue.
1521        for forwarded in &c.streams {
1522            if let Some(s) = self.streams.get_mut(&forwarded.identifier) {
1523                s.handle_forward_tsn_for_ordered(forwarded.sequence);
1524                if s.reassembly_queue.is_readable() {
1525                    self.events.push_back(Event::Stream(StreamEvent::Readable {
1526                        id: s.stream_identifier,
1527                    }));
1528                }
1529            }
1530        }
1531
1532        // TSN may be forwarded for unordered chunks. ForwardTSN chunk does not
1533        // report which stream identifier it skipped for unordered chunks.
1534        // Therefore, we need to broadcast this event to all existing streams for
1535        // unordered chunks.
1536        for s in self.streams.values_mut() {
1537            s.handle_forward_tsn_for_unordered(c.new_cumulative_tsn);
1538            if s.reassembly_queue.is_readable() {
1539                self.events.push_back(Event::Stream(StreamEvent::Readable {
1540                    id: s.stream_identifier,
1541                }));
1542            }
1543        }
1544
1545        self.handle_peer_last_tsn_and_acknowledgement(false)
1546    }
1547
1548    fn handle_shutdown(&mut self, _: &ChunkShutdown) -> Result<Vec<Packet>> {
1549        let state = self.state();
1550
1551        if state == AssociationState::Established {
1552            if !self.inflight_queue.is_empty() {
1553                self.set_state(AssociationState::ShutdownReceived);
1554            } else {
1555                // No more outstanding, send shutdown ack.
1556                self.will_send_shutdown_ack = true;
1557                self.set_state(AssociationState::ShutdownAckSent);
1558
1559                self.awake_write_loop();
1560            }
1561        } else if state == AssociationState::ShutdownSent {
1562            // self.cumulative_tsn_ack_point = c.cumulative_tsn_ack
1563
1564            self.will_send_shutdown_ack = true;
1565            self.set_state(AssociationState::ShutdownAckSent);
1566
1567            self.awake_write_loop();
1568        }
1569
1570        Ok(vec![])
1571    }
1572
1573    fn handle_shutdown_ack(&mut self, _: &ChunkShutdownAck) -> Result<Vec<Packet>> {
1574        let state = self.state();
1575        if state == AssociationState::ShutdownSent || state == AssociationState::ShutdownAckSent {
1576            self.timers.stop(Timer::T2Shutdown);
1577            self.will_send_shutdown_complete = true;
1578
1579            self.awake_write_loop();
1580        }
1581
1582        Ok(vec![])
1583    }
1584
1585    fn handle_shutdown_complete(&mut self, _: &ChunkShutdownComplete) -> Result<Vec<Packet>> {
1586        let state = self.state();
1587        if state == AssociationState::ShutdownAckSent {
1588            self.timers.stop(Timer::T2Shutdown);
1589            self.close(AssociationError::AssociationClosed)?;
1590        }
1591
1592        Ok(vec![])
1593    }
1594
1595    /// A common routine for handle_data and handle_forward_tsn routines
1596    fn handle_peer_last_tsn_and_acknowledgement(
1597        &mut self,
1598        sack_immediately: bool,
1599    ) -> Result<Vec<Packet>> {
1600        let mut reply = vec![];
1601
1602        // Try to advance peer_last_tsn
1603
1604        // From RFC 3758 Sec 3.6:
1605        //   .. and then MUST further advance its cumulative TSN point locally
1606        //   if possible
1607        // Meaning, if peer_last_tsn+1 points to a chunk that is received,
1608        // advance peer_last_tsn until peer_last_tsn+1 points to unreceived chunk.
1609        //debug!("[{}] peer_last_tsn = {}", self.side, self.peer_last_tsn);
1610        while self.payload_queue.pop(self.peer_last_tsn + 1).is_some() {
1611            self.peer_last_tsn += 1;
1612            //debug!("[{}] peer_last_tsn = {}", self.side, self.peer_last_tsn);
1613
1614            let rst_reqs: Vec<ParamOutgoingResetRequest> =
1615                self.reconfig_requests.values().cloned().collect();
1616            for rst_req in rst_reqs {
1617                self.reset_streams_if_any(&rst_req, false, &mut reply)?;
1618            }
1619        }
1620
1621        let has_packet_loss = !self.payload_queue.is_empty();
1622        if has_packet_loss {
1623            trace!(
1624                "[{}] packetloss: {}",
1625                self.side,
1626                self.payload_queue
1627                    .get_gap_ack_blocks_string(self.peer_last_tsn)
1628            );
1629        }
1630
1631        if (self.ack_state != AckState::Immediate
1632            && !sack_immediately
1633            && !has_packet_loss
1634            && self.ack_mode == AckMode::Normal)
1635            || self.ack_mode == AckMode::AlwaysDelay
1636        {
1637            if self.ack_state == AckState::Idle {
1638                self.delayed_ack_triggered = true;
1639            } else {
1640                self.immediate_ack_triggered = true;
1641            }
1642        } else {
1643            self.immediate_ack_triggered = true;
1644        }
1645
1646        Ok(reply)
1647    }
1648
1649    #[allow(clippy::borrowed_box)]
1650    fn handle_reconfig_param(
1651        &mut self,
1652        raw: &Box<dyn Param>,
1653        reply: &mut Vec<Packet>,
1654    ) -> Result<()> {
1655        if let Some(p) = raw.as_any().downcast_ref::<ParamOutgoingResetRequest>() {
1656            self.reconfig_requests
1657                .insert(p.reconfig_request_sequence_number, p.clone());
1658            self.reset_streams_if_any(p, true, reply)?;
1659            Ok(())
1660        } else if let Some(p) = raw.as_any().downcast_ref::<ParamReconfigResponse>() {
1661            self.reconfigs.remove(&p.reconfig_response_sequence_number);
1662            if self.reconfigs.is_empty() {
1663                self.timers.stop(Timer::Reconfig);
1664            }
1665            Ok(())
1666        } else {
1667            Err(Error::ErrParameterType)
1668        }
1669    }
1670
1671    fn process_selective_ack(
1672        &mut self,
1673        d: &ChunkSelectiveAck,
1674        now: Instant,
1675    ) -> Result<(FxHashMap<u16, i64>, u32)> {
1676        let mut bytes_acked_per_stream = FxHashMap::default();
1677
1678        // New ack point, so pop all ACKed packets from inflight_queue
1679        // We add 1 because the "currentAckPoint" has already been popped from the inflight queue
1680        // For the first SACK we take care of this by setting the ackpoint to cumAck - 1
1681        let mut i = self.cumulative_tsn_ack_point + 1;
1682        //log::debug!("[{}] i={} d={}", self.name, i, d.cumulative_tsn_ack);
1683        while sna32lte(i, d.cumulative_tsn_ack) {
1684            if let Some(c) = self.inflight_queue.pop(i) {
1685                if !c.acked {
1686                    // RFC 4096 sec 6.3.2.  Retransmission Timer Rules
1687                    //   R3)  Whenever a SACK is received that acknowledges the DATA chunk
1688                    //        with the earliest outstanding TSN for that address, restart the
1689                    //        T3-rtx timer for that address with its current RTO (if there is
1690                    //        still outstanding data on that address).
1691                    if i == self.cumulative_tsn_ack_point + 1 {
1692                        // T3 timer needs to be reset. Stop it for now.
1693                        self.timers.stop(Timer::T3RTX);
1694                    }
1695
1696                    let n_bytes_acked = c.user_data.len() as i64;
1697
1698                    // Sum the number of bytes acknowledged per stream
1699                    if let Some(amount) = bytes_acked_per_stream.get_mut(&c.stream_identifier) {
1700                        *amount += n_bytes_acked;
1701                    } else {
1702                        bytes_acked_per_stream.insert(c.stream_identifier, n_bytes_acked);
1703                    }
1704
1705                    // RFC 4960 sec 6.3.1.  RTO Calculation
1706                    //   C4)  When data is in flight and when allowed by rule C5 below, a new
1707                    //        RTT measurement MUST be made each round trip.  Furthermore, new
1708                    //        RTT measurements SHOULD be made no more than once per round trip
1709                    //        for a given destination transport address.
1710                    //   C5)  Karn's algorithm: RTT measurements MUST NOT be made using
1711                    //        packets that were retransmitted (and thus for which it is
1712                    //        ambiguous whether the reply was for the first instance of the
1713                    //        chunk or for a later instance)
1714                    if c.nsent == 1 && sna32gte(c.tsn, self.min_tsn2measure_rtt) {
1715                        self.min_tsn2measure_rtt = self.my_next_tsn;
1716                        if let Some(since) = &c.since {
1717                            let rtt = now.duration_since(*since);
1718                            let srtt = self.rto_mgr.set_new_rtt(rtt.as_millis() as u64);
1719                            trace!(
1720                                "[{}] SACK: measured-rtt={} srtt={} new-rto={}",
1721                                self.side,
1722                                rtt.as_millis(),
1723                                srtt,
1724                                self.rto_mgr.get_rto()
1725                            );
1726                        } else {
1727                            error!("[{}] invalid c.since", self.side);
1728                        }
1729                    }
1730                }
1731
1732                if self.in_fast_recovery && c.tsn == self.fast_recover_exit_point {
1733                    debug!("[{}] exit fast-recovery", self.side);
1734                    self.in_fast_recovery = false;
1735                }
1736            } else {
1737                return Err(Error::ErrInflightQueueTsnPop);
1738            }
1739
1740            i += 1;
1741        }
1742
1743        let mut htna = d.cumulative_tsn_ack;
1744
1745        // Mark selectively acknowledged chunks as "acked"
1746        for g in &d.gap_ack_blocks {
1747            for i in g.start..=g.end {
1748                let tsn = d.cumulative_tsn_ack + i as u32;
1749
1750                let (is_existed, is_acked) = if let Some(c) = self.inflight_queue.get(tsn) {
1751                    (true, c.acked)
1752                } else {
1753                    (false, false)
1754                };
1755                let n_bytes_acked = if is_existed && !is_acked {
1756                    self.inflight_queue.mark_as_acked(tsn) as i64
1757                } else {
1758                    0
1759                };
1760
1761                if let Some(c) = self.inflight_queue.get(tsn) {
1762                    if !is_acked {
1763                        // Sum the number of bytes acknowledged per stream
1764                        if let Some(amount) = bytes_acked_per_stream.get_mut(&c.stream_identifier) {
1765                            *amount += n_bytes_acked;
1766                        } else {
1767                            bytes_acked_per_stream.insert(c.stream_identifier, n_bytes_acked);
1768                        }
1769
1770                        trace!("[{}] tsn={} has been sacked", self.side, c.tsn);
1771
1772                        if c.nsent == 1 {
1773                            self.min_tsn2measure_rtt = self.my_next_tsn;
1774                            if let Some(since) = &c.since {
1775                                let rtt = now.duration_since(*since);
1776                                let srtt = self.rto_mgr.set_new_rtt(rtt.as_millis() as u64);
1777                                trace!(
1778                                    "[{}] SACK: measured-rtt={} srtt={} new-rto={}",
1779                                    self.side,
1780                                    rtt.as_millis(),
1781                                    srtt,
1782                                    self.rto_mgr.get_rto()
1783                                );
1784                            } else {
1785                                error!("[{}] invalid c.since", self.side);
1786                            }
1787                        }
1788
1789                        if sna32lt(htna, tsn) {
1790                            htna = tsn;
1791                        }
1792                    }
1793                } else {
1794                    return Err(Error::ErrTsnRequestNotExist);
1795                }
1796            }
1797        }
1798
1799        Ok((bytes_acked_per_stream, htna))
1800    }
1801
1802    fn on_cumulative_tsn_ack_point_advanced(&mut self, total_bytes_acked: i64, now: Instant) {
1803        // RFC 4096, sec 6.3.2.  Retransmission Timer Rules
1804        //   R2)  Whenever all outstanding data sent to an address have been
1805        //        acknowledged, turn off the T3-rtx timer of that address.
1806        if self.inflight_queue.is_empty() {
1807            trace!(
1808                "[{}] SACK: no more packet in-flight (pending={})",
1809                self.side,
1810                self.pending_queue.len()
1811            );
1812            self.timers.stop(Timer::T3RTX);
1813        } else {
1814            trace!("[{}] T3-rtx timer start (pt2)", self.side);
1815            self.timers
1816                .restart_if_stale(Timer::T3RTX, now, self.rto_mgr.get_rto());
1817        }
1818
1819        // Update congestion control parameters
1820        if self.cwnd <= self.ssthresh {
1821            // RFC 4096, sec 7.2.1.  Slow-Start
1822            //   o  When cwnd is less than or equal to ssthresh, an SCTP endpoint MUST
1823            //		use the slow-start algorithm to increase cwnd only if the current
1824            //      congestion window is being fully utilized, an incoming SACK
1825            //      advances the Cumulative TSN Ack Point, and the data sender is not
1826            //      in Fast Recovery.  Only when these three conditions are met can
1827            //      the cwnd be increased; otherwise, the cwnd MUST not be increased.
1828            //		If these conditions are met, then cwnd MUST be increased by, at
1829            //      most, the lesser of 1) the total size of the previously
1830            //      outstanding DATA chunk(s) acknowledged, and 2) the destination's
1831            //      path MTU.
1832            if !self.in_fast_recovery && !self.pending_queue.is_empty() {
1833                self.cwnd += std::cmp::min(total_bytes_acked as u32, self.cwnd); // TCP way
1834                // self.cwnd += min32(uint32(total_bytes_acked), self.mtu) // SCTP way (slow)
1835                trace!(
1836                    "[{}] updated cwnd={} ssthresh={} acked={} (SS)",
1837                    self.side, self.cwnd, self.ssthresh, total_bytes_acked
1838                );
1839            } else {
1840                trace!(
1841                    "[{}] cwnd did not grow: cwnd={} ssthresh={} acked={} FR={} pending={}",
1842                    self.side,
1843                    self.cwnd,
1844                    self.ssthresh,
1845                    total_bytes_acked,
1846                    self.in_fast_recovery,
1847                    self.pending_queue.len()
1848                );
1849            }
1850        } else {
1851            // RFC 4096, sec 7.2.2.  Congestion Avoidance
1852            //   o  Whenever cwnd is greater than ssthresh, upon each SACK arrival
1853            //      that advances the Cumulative TSN Ack Point, increase
1854            //      partial_bytes_acked by the total number of bytes of all new chunks
1855            //      acknowledged in that SACK including chunks acknowledged by the new
1856            //      Cumulative TSN Ack and by Gap Ack Blocks.
1857            self.partial_bytes_acked += total_bytes_acked as u32;
1858
1859            //   o  When partial_bytes_acked is equal to or greater than cwnd and
1860            //      before the arrival of the SACK the sender had cwnd or more bytes
1861            //      of data outstanding (i.e., before arrival of the SACK, flight size
1862            //      was greater than or equal to cwnd), increase cwnd by MTU, and
1863            //      reset partial_bytes_acked to (partial_bytes_acked - cwnd).
1864            if self.partial_bytes_acked >= self.cwnd && !self.pending_queue.is_empty() {
1865                self.partial_bytes_acked -= self.cwnd;
1866                self.cwnd += self.mtu;
1867                trace!(
1868                    "[{}] updated cwnd={} ssthresh={} acked={} (CA)",
1869                    self.side, self.cwnd, self.ssthresh, total_bytes_acked
1870                );
1871            }
1872        }
1873    }
1874
1875    fn process_fast_retransmission(
1876        &mut self,
1877        cum_tsn_ack_point: u32,
1878        htna: u32,
1879        cum_tsn_ack_point_advanced: bool,
1880    ) -> Result<()> {
1881        // HTNA algorithm - RFC 4960 Sec 7.2.4
1882        // Increment missIndicator of each chunks that the SACK reported missing
1883        // when either of the following is met:
1884        // a)  Not in fast-recovery
1885        //     miss indications are incremented only for missing TSNs prior to the
1886        //     highest TSN newly acknowledged in the SACK.
1887        // b)  In fast-recovery AND the Cumulative TSN Ack Point advanced
1888        //     the miss indications are incremented for all TSNs reported missing
1889        //     in the SACK.
1890        if !self.in_fast_recovery || cum_tsn_ack_point_advanced {
1891            let max_tsn = if !self.in_fast_recovery {
1892                // a) increment only for missing TSNs prior to the HTNA
1893                htna
1894            } else {
1895                // b) increment for all TSNs reported missing
1896                cum_tsn_ack_point + (self.inflight_queue.len() as u32) + 1
1897            };
1898
1899            let mut tsn = cum_tsn_ack_point + 1;
1900            while sna32lt(tsn, max_tsn) {
1901                if let Some(c) = self.inflight_queue.get_mut(tsn) {
1902                    if !c.acked && !c.abandoned() && c.miss_indicator < 3 {
1903                        c.miss_indicator += 1;
1904                        if c.miss_indicator == 3 && !self.in_fast_recovery {
1905                            // 2)  If not in Fast Recovery, adjust the ssthresh and cwnd of the
1906                            //     destination address(es) to which the missing DATA chunks were
1907                            //     last sent, according to the formula described in Section 7.2.3.
1908                            self.in_fast_recovery = true;
1909                            self.fast_recover_exit_point = htna;
1910                            self.ssthresh = std::cmp::max(self.cwnd / 2, 4 * self.mtu);
1911                            self.cwnd = self.ssthresh;
1912                            self.partial_bytes_acked = 0;
1913                            self.will_retransmit_fast = true;
1914
1915                            trace!(
1916                                "[{}] updated cwnd={} ssthresh={} inflight={} (FR)",
1917                                self.side,
1918                                self.cwnd,
1919                                self.ssthresh,
1920                                self.inflight_queue.get_num_bytes()
1921                            );
1922                        }
1923                    }
1924                } else {
1925                    return Err(Error::ErrTsnRequestNotExist);
1926                }
1927
1928                tsn += 1;
1929            }
1930        }
1931
1932        if self.in_fast_recovery && cum_tsn_ack_point_advanced {
1933            self.will_retransmit_fast = true;
1934        }
1935
1936        Ok(())
1937    }
1938
1939    /// The caller must hold the lock. This method was only added because the
1940    /// linter was complaining about the "cognitive complexity" of handle_sack.
1941    fn postprocess_sack(
1942        &mut self,
1943        state: AssociationState,
1944        mut should_awake_write_loop: bool,
1945        now: Instant,
1946    ) {
1947        if !self.inflight_queue.is_empty() {
1948            // Start timer. (noop if already started)
1949            trace!("[{}] T3-rtx timer start (pt3)", self.side);
1950            self.timers
1951                .restart_if_stale(Timer::T3RTX, now, self.rto_mgr.get_rto());
1952        } else if state == AssociationState::ShutdownPending {
1953            // No more outstanding, send shutdown.
1954            should_awake_write_loop = true;
1955            self.will_send_shutdown = true;
1956            self.set_state(AssociationState::ShutdownSent);
1957        } else if state == AssociationState::ShutdownReceived {
1958            // No more outstanding, send shutdown ack.
1959            should_awake_write_loop = true;
1960            self.will_send_shutdown_ack = true;
1961            self.set_state(AssociationState::ShutdownAckSent);
1962        }
1963
1964        if should_awake_write_loop {
1965            self.awake_write_loop();
1966        }
1967    }
1968
1969    fn reset_streams_if_any(
1970        &mut self,
1971        p: &ParamOutgoingResetRequest,
1972        respond: bool,
1973        reply: &mut Vec<Packet>,
1974    ) -> Result<()> {
1975        let mut result = ReconfigResult::SuccessPerformed;
1976        let mut sis_to_reset = vec![];
1977
1978        if sna32lte(p.sender_last_tsn, self.peer_last_tsn) {
1979            debug!(
1980                "[{}] resetStream(): senderLastTSN={} <= peer_last_tsn={}",
1981                self.side, p.sender_last_tsn, self.peer_last_tsn
1982            );
1983            for id in &p.stream_identifiers {
1984                if self.streams.contains_key(id) {
1985                    if respond {
1986                        sis_to_reset.push(*id);
1987                    }
1988                    self.unregister_stream(*id, AssociationError::Reset);
1989                }
1990            }
1991            self.reconfig_requests
1992                .remove(&p.reconfig_request_sequence_number);
1993        } else {
1994            debug!(
1995                "[{}] resetStream(): senderLastTSN={} > peer_last_tsn={}",
1996                self.side, p.sender_last_tsn, self.peer_last_tsn
1997            );
1998            result = ReconfigResult::InProgress;
1999        }
2000
2001        // Answer incoming reset requests with the same reset request, but with
2002        // reconfig_response_sequence_number.
2003        if !sis_to_reset.is_empty() {
2004            let rsn = self.generate_next_rsn();
2005            let tsn = self.my_next_tsn - 1;
2006
2007            let c = ChunkReconfig {
2008                param_a: Some(Box::new(ParamOutgoingResetRequest {
2009                    reconfig_request_sequence_number: rsn,
2010                    reconfig_response_sequence_number: p.reconfig_request_sequence_number,
2011                    sender_last_tsn: tsn,
2012                    stream_identifiers: sis_to_reset,
2013                })),
2014                ..Default::default()
2015            };
2016
2017            self.reconfigs.insert(rsn, c.clone()); // store in the map for retransmission
2018
2019            let p = self.create_packet(vec![Box::new(c)]);
2020            reply.push(p);
2021        }
2022
2023        let packet = self.create_packet(vec![Box::new(ChunkReconfig {
2024            param_a: Some(Box::new(ParamReconfigResponse {
2025                reconfig_response_sequence_number: p.reconfig_request_sequence_number,
2026                result,
2027            })),
2028            param_b: None,
2029        })]);
2030
2031        debug!("[{}] RESET RESPONSE: {}", self.side, packet);
2032
2033        reply.push(packet);
2034
2035        Ok(())
2036    }
2037
2038    /// create_packet wraps chunks in a packet.
2039    /// The caller should hold the read lock.
2040    pub(crate) fn create_packet(&self, chunks: Vec<Box<dyn Chunk>>) -> Packet {
2041        Packet {
2042            common_header: CommonHeader {
2043                verification_tag: self.peer_verification_tag,
2044                source_port: self.source_port,
2045                destination_port: self.destination_port,
2046            },
2047            chunks,
2048        }
2049    }
2050
2051    /// Marshal a single control chunk into one SCTP packet, bypassing the
2052    /// `Vec<Box<dyn Chunk>>` + `Packet` allocations of `create_packet(..).marshal()`.
2053    /// Feeds the borrowed chunk straight to the shared framing path
2054    /// ([`Packet::write_framed`]). Used on the hot SACK / FORWARD-TSN send path
2055    /// (a SACK is emitted roughly every 1-2 inbound DATA chunks). The caller holds
2056    /// the lock.
2057    fn marshal_control_chunk(&self, chunk: &dyn Chunk) -> Result<Bytes> {
2058        let common_header = CommonHeader {
2059            verification_tag: self.peer_verification_tag,
2060            source_port: self.source_port,
2061            destination_port: self.destination_port,
2062        };
2063        // common header + chunk header + value + up to 3 bytes of trailing padding.
2064        let mut buf = BytesMut::with_capacity(
2065            COMMON_HEADER_SIZE as usize + CHUNK_HEADER_SIZE + chunk.value_length() + 3,
2066        );
2067        Packet::write_framed(&common_header, std::iter::once(chunk), &mut buf)?;
2068        Ok(buf.freeze())
2069    }
2070
2071    /// create_stream creates a stream. The caller should hold the lock and check no stream exists for this id.
2072    fn create_stream(
2073        &mut self,
2074        stream_identifier: StreamId,
2075        accept: bool,
2076        default_payload_type: PayloadProtocolIdentifier,
2077    ) -> Option<Stream<'_>> {
2078        let s = StreamState::new(
2079            self.side,
2080            stream_identifier,
2081            self.max_payload_size,
2082            default_payload_type,
2083        );
2084
2085        if accept {
2086            self.stream_queue.push_back(stream_identifier);
2087            self.events.push_back(Event::Stream(StreamEvent::Opened {
2088                id: stream_identifier,
2089            }));
2090        }
2091
2092        self.streams.insert(stream_identifier, s);
2093
2094        Some(Stream {
2095            stream_identifier,
2096            association: self,
2097        })
2098    }
2099
2100    /// get_or_create_stream gets or creates a stream. The caller should hold the lock.
2101    fn get_or_create_stream(&mut self, stream_identifier: StreamId) -> Option<Stream<'_>> {
2102        if self.streams.contains_key(&stream_identifier) {
2103            Some(Stream {
2104                stream_identifier,
2105                association: self,
2106            })
2107        } else {
2108            self.create_stream(
2109                stream_identifier,
2110                true,
2111                PayloadProtocolIdentifier::default(),
2112            )
2113        }
2114    }
2115
2116    /// Whether any stream currently holds a complete message the application could read.
2117    ///
2118    /// Distinguishes a receiver that is merely slow — it has data to take, and back-pressure
2119    /// should make it take it — from one wedged behind an incomplete chunk set, which cannot
2120    /// drain anything however attentive it is. Only the second justifies accepting a chunk
2121    /// into a full receive buffer.
2122    fn has_readable_data(&self) -> bool {
2123        self.streams
2124            .values()
2125            .any(|s| s.reassembly_queue.is_readable())
2126    }
2127
2128    pub(crate) fn get_my_receiver_window_credit(&self) -> u32 {
2129        let mut bytes_queued = 0;
2130        for s in self.streams.values() {
2131            bytes_queued += s.get_num_bytes_in_reassembly_queue() as u32;
2132        }
2133
2134        self.max_receive_buffer_size.saturating_sub(bytes_queued)
2135    }
2136
2137    /// gather_outbound gathers outgoing packets. The returned bool value set to
2138    /// false means the association should be closed down after the final send.
2139    fn gather_outbound(&mut self, now: Instant) -> (Vec<Bytes>, bool) {
2140        let mut raw_packets = vec![];
2141
2142        if !self.control_queue.is_empty() {
2143            for p in self.control_queue.drain(..) {
2144                if let Ok(raw) = p.marshal() {
2145                    raw_packets.push(raw);
2146                } else {
2147                    warn!("[{}] failed to serialize a control packet", self.side);
2148                    continue;
2149                }
2150            }
2151        }
2152
2153        let state = self.state();
2154        match state {
2155            AssociationState::Established => {
2156                raw_packets = self.gather_data_packets_to_retransmit(raw_packets, now);
2157                raw_packets = self.gather_outbound_data_and_reconfig_packets(raw_packets, now);
2158                raw_packets = self.gather_outbound_fast_retransmission_packets(raw_packets, now);
2159                raw_packets = self.gather_outbound_sack_packets(raw_packets);
2160                raw_packets = self.gather_outbound_forward_tsn_packets(raw_packets);
2161                (raw_packets, true)
2162            }
2163            AssociationState::ShutdownPending
2164            | AssociationState::ShutdownSent
2165            | AssociationState::ShutdownReceived => {
2166                raw_packets = self.gather_data_packets_to_retransmit(raw_packets, now);
2167                raw_packets = self.gather_outbound_fast_retransmission_packets(raw_packets, now);
2168                raw_packets = self.gather_outbound_sack_packets(raw_packets);
2169                self.gather_outbound_shutdown_packets(raw_packets, now)
2170            }
2171            AssociationState::ShutdownAckSent => {
2172                self.gather_outbound_shutdown_packets(raw_packets, now)
2173            }
2174            _ => (raw_packets, true),
2175        }
2176    }
2177
2178    fn gather_data_packets_to_retransmit(
2179        &mut self,
2180        mut raw_packets: Vec<Bytes>,
2181        now: Instant,
2182    ) -> Vec<Bytes> {
2183        // Nothing is ever flagged for T3-rtx in the steady state, so skip the
2184        // full in-flight scan unless the T3-rtx timer has actually marked chunks.
2185        if self.t3_retransmit_pending {
2186            self.get_data_packets_to_retransmit(now, &mut raw_packets);
2187        }
2188        raw_packets
2189    }
2190
2191    fn gather_outbound_data_and_reconfig_packets(
2192        &mut self,
2193        mut raw_packets: Vec<Bytes>,
2194        now: Instant,
2195    ) -> Vec<Bytes> {
2196        // Pop unsent data chunks from the pending queue to send as much as
2197        // cwnd and rwnd allow.
2198        let (chunks, sis_to_reset) = self.pop_pending_data_chunks_to_send(now);
2199        if !chunks.is_empty() {
2200            // Start timer. (noop if already started)
2201            trace!("[{}] T3-rtx timer start (pt1)", self.side);
2202            self.timers
2203                .restart_if_stale(Timer::T3RTX, now, self.rto_mgr.get_rto());
2204
2205            self.bundle_data_chunks_into_packets(chunks, &mut raw_packets);
2206        }
2207
2208        if !sis_to_reset.is_empty() || self.will_retransmit_reconfig {
2209            if self.will_retransmit_reconfig {
2210                self.will_retransmit_reconfig = false;
2211                debug!(
2212                    "[{}] retransmit {} RECONFIG chunk(s)",
2213                    self.side,
2214                    self.reconfigs.len()
2215                );
2216                for c in self.reconfigs.values() {
2217                    let p = self.create_packet(vec![Box::new(c.clone())]);
2218                    if let Ok(raw) = p.marshal() {
2219                        raw_packets.push(raw);
2220                    } else {
2221                        warn!(
2222                            "[{}] failed to serialize a RECONFIG packet to be retransmitted",
2223                            self.side,
2224                        );
2225                    }
2226                }
2227            }
2228
2229            if !sis_to_reset.is_empty() {
2230                let rsn = self.generate_next_rsn();
2231                let tsn = self.my_next_tsn - 1;
2232                debug!(
2233                    "[{}] sending RECONFIG: rsn={} tsn={} streams={:?}",
2234                    self.side,
2235                    rsn,
2236                    self.my_next_tsn - 1,
2237                    sis_to_reset
2238                );
2239
2240                let c = ChunkReconfig {
2241                    param_a: Some(Box::new(ParamOutgoingResetRequest {
2242                        reconfig_request_sequence_number: rsn,
2243                        sender_last_tsn: tsn,
2244                        stream_identifiers: sis_to_reset,
2245                        ..Default::default()
2246                    })),
2247                    ..Default::default()
2248                };
2249                self.reconfigs.insert(rsn, c.clone()); // store in the map for retransmission
2250
2251                let p = self.create_packet(vec![Box::new(c)]);
2252                if let Ok(raw) = p.marshal() {
2253                    raw_packets.push(raw);
2254                } else {
2255                    warn!(
2256                        "[{}] failed to serialize a RECONFIG packet to be transmitted",
2257                        self.side
2258                    );
2259                }
2260            }
2261
2262            if !self.reconfigs.is_empty() {
2263                self.timers
2264                    .start(Timer::Reconfig, now, self.rto_mgr.get_rto());
2265            }
2266        }
2267
2268        raw_packets
2269    }
2270
2271    fn gather_outbound_fast_retransmission_packets(
2272        &mut self,
2273        mut raw_packets: Vec<Bytes>,
2274        now: Instant,
2275    ) -> Vec<Bytes> {
2276        if self.will_retransmit_fast {
2277            self.will_retransmit_fast = false;
2278
2279            let mut to_fast_retrans: Vec<Box<dyn Chunk>> = vec![];
2280            let mut fast_retrans_size = COMMON_HEADER_SIZE;
2281
2282            let mut i = 0;
2283            loop {
2284                let tsn = self.cumulative_tsn_ack_point + i + 1;
2285                if let Some(c) = self.inflight_queue.get_mut(tsn) {
2286                    if c.acked || c.abandoned() || c.nsent > 1 || c.miss_indicator < 3 {
2287                        i += 1;
2288                        continue;
2289                    }
2290
2291                    // RFC 4960 Sec 7.2.4 Fast Retransmit on Gap Reports
2292                    //  3)  Determine how many of the earliest (i.e., lowest TSN) DATA chunks
2293                    //      marked for retransmission will fit into a single packet, subject
2294                    //      to constraint of the path MTU of the destination transport
2295                    //      address to which the packet is being sent.  Call this value K.
2296                    //      Retransmit those K DATA chunks in a single packet.  When a Fast
2297                    //      Retransmit is being performed, the sender SHOULD ignore the value
2298                    //      of cwnd and SHOULD NOT delay retransmission for this single
2299                    //		packet.
2300
2301                    let data_chunk_size = DATA_CHUNK_HEADER_SIZE + c.user_data.len() as u32;
2302                    if self.mtu < fast_retrans_size + data_chunk_size {
2303                        break;
2304                    }
2305
2306                    fast_retrans_size += data_chunk_size;
2307                    self.stats.inc_fast_retrans();
2308                    c.nsent += 1;
2309                } else {
2310                    break; // end of pending data
2311                }
2312
2313                if let Some(c) = self.inflight_queue.get_mut(tsn) {
2314                    Association::check_partial_reliability_status(
2315                        c,
2316                        now,
2317                        self.use_forward_tsn,
2318                        self.side,
2319                        &self.streams,
2320                    );
2321                    to_fast_retrans.push(Box::new(c.clone()));
2322                    trace!(
2323                        "[{}] fast-retransmit: tsn={} sent={} htna={}",
2324                        self.side, c.tsn, c.nsent, self.fast_recover_exit_point
2325                    );
2326                }
2327                i += 1;
2328            }
2329
2330            if !to_fast_retrans.is_empty() {
2331                if let Ok(raw) = self.create_packet(to_fast_retrans).marshal() {
2332                    raw_packets.push(raw);
2333                } else {
2334                    warn!(
2335                        "[{}] failed to serialize a DATA packet to be fast-retransmitted",
2336                        self.side
2337                    );
2338                }
2339            }
2340        }
2341
2342        raw_packets
2343    }
2344
2345    fn gather_outbound_sack_packets(&mut self, mut raw_packets: Vec<Bytes>) -> Vec<Bytes> {
2346        if self.ack_state == AckState::Immediate {
2347            self.ack_state = AckState::Idle;
2348            let sack = self.create_selective_ack_chunk();
2349            debug!("[{}] sending SACK: {}", self.side, sack);
2350            if let Ok(raw) = self.marshal_control_chunk(&sack) {
2351                raw_packets.push(raw);
2352            } else {
2353                warn!("[{}] failed to serialize a SACK packet", self.side);
2354            }
2355        }
2356
2357        raw_packets
2358    }
2359
2360    fn gather_outbound_forward_tsn_packets(&mut self, mut raw_packets: Vec<Bytes>) -> Vec<Bytes> {
2361        /*log::debug!(
2362            "[{}] gatherOutboundForwardTSNPackets {}",
2363            self.name,
2364            self.will_send_forward_tsn
2365        );*/
2366        if self.will_send_forward_tsn {
2367            self.will_send_forward_tsn = false;
2368            if sna32gt(
2369                self.advanced_peer_tsn_ack_point,
2370                self.cumulative_tsn_ack_point,
2371            ) {
2372                let fwd_tsn = self.create_forward_tsn();
2373                if let Ok(raw) = self.marshal_control_chunk(&fwd_tsn) {
2374                    raw_packets.push(raw);
2375                } else {
2376                    warn!("[{}] failed to serialize a Forward TSN packet", self.side);
2377                }
2378            }
2379        }
2380
2381        raw_packets
2382    }
2383
2384    fn gather_outbound_shutdown_packets(
2385        &mut self,
2386        mut raw_packets: Vec<Bytes>,
2387        now: Instant,
2388    ) -> (Vec<Bytes>, bool) {
2389        let mut ok = true;
2390
2391        if self.will_send_shutdown {
2392            self.will_send_shutdown = false;
2393
2394            let shutdown = ChunkShutdown {
2395                cumulative_tsn_ack: self.cumulative_tsn_ack_point,
2396            };
2397
2398            if let Ok(raw) = self.create_packet(vec![Box::new(shutdown)]).marshal() {
2399                self.timers
2400                    .start(Timer::T2Shutdown, now, self.rto_mgr.get_rto());
2401                raw_packets.push(raw);
2402            } else {
2403                warn!("[{}] failed to serialize a Shutdown packet", self.side);
2404            }
2405        } else if self.will_send_shutdown_ack {
2406            self.will_send_shutdown_ack = false;
2407
2408            let shutdown_ack = ChunkShutdownAck {};
2409
2410            if let Ok(raw) = self.create_packet(vec![Box::new(shutdown_ack)]).marshal() {
2411                self.timers
2412                    .start(Timer::T2Shutdown, now, self.rto_mgr.get_rto());
2413                raw_packets.push(raw);
2414            } else {
2415                warn!("[{}] failed to serialize a ShutdownAck packet", self.side);
2416            }
2417        } else if self.will_send_shutdown_complete {
2418            self.will_send_shutdown_complete = false;
2419
2420            let shutdown_complete = ChunkShutdownComplete {};
2421
2422            if let Ok(raw) = self
2423                .create_packet(vec![Box::new(shutdown_complete)])
2424                .marshal()
2425            {
2426                raw_packets.push(raw);
2427                ok = false;
2428            } else {
2429                warn!(
2430                    "[{}] failed to serialize a ShutdownComplete packet",
2431                    self.side
2432                );
2433            }
2434        }
2435
2436        (raw_packets, ok)
2437    }
2438
2439    /// get_data_packets_to_retransmit is called when T3-rtx is timed out and retransmit outstanding data chunks
2440    /// that are not acked or abandoned yet.
2441    fn get_data_packets_to_retransmit(&mut self, now: Instant, raw_packets: &mut Vec<Bytes>) {
2442        let awnd = std::cmp::min(self.cwnd, self.rwnd);
2443        let mut chunks = vec![];
2444        let mut bytes_to_send = 0;
2445        let mut done = false;
2446        let mut i = 0;
2447        // Assume we will re-send every flagged chunk; flip back on if we stop
2448        // early (a marked chunk that doesn't fit awnd, or a zero-window probe)
2449        // so the next gather_outbound still scans.
2450        let mut chunks_remaining = false;
2451        while !done {
2452            let tsn = self.cumulative_tsn_ack_point + i + 1;
2453            if let Some(c) = self.inflight_queue.get_mut(tsn) {
2454                if !c.retransmit {
2455                    i += 1;
2456                    continue;
2457                }
2458
2459                if i == 0 && self.rwnd < c.user_data.len() as u32 {
2460                    // Send it as a zero window probe
2461                    done = true;
2462                    chunks_remaining = true;
2463                } else if bytes_to_send + c.user_data.len() > awnd as usize {
2464                    chunks_remaining = true;
2465                    break;
2466                }
2467
2468                // reset the retransmit flag not to retransmit again before the next
2469                // t3-rtx timer fires
2470                c.retransmit = false;
2471                bytes_to_send += c.user_data.len();
2472
2473                c.nsent += 1;
2474            } else {
2475                break; // end of pending data
2476            }
2477
2478            if let Some(c) = self.inflight_queue.get_mut(tsn) {
2479                Association::check_partial_reliability_status(
2480                    c,
2481                    now,
2482                    self.use_forward_tsn,
2483                    self.side,
2484                    &self.streams,
2485                );
2486
2487                trace!(
2488                    "[{}] retransmitting tsn={} ssn={} sent={}",
2489                    self.side, c.tsn, c.stream_sequence_number, c.nsent
2490                );
2491
2492                chunks.push(c.clone());
2493            }
2494            i += 1;
2495        }
2496
2497        // Cleared once the whole in-flight window has been rescanned with nothing
2498        // left flagged; kept set while awnd/zero-window left chunks behind.
2499        self.t3_retransmit_pending = chunks_remaining;
2500
2501        self.bundle_data_chunks_into_packets(chunks, raw_packets);
2502    }
2503
2504    /// pop_pending_data_chunks_to_send pops chunks from the pending queues as many as
2505    /// the cwnd and rwnd allows to send.
2506    fn pop_pending_data_chunks_to_send(
2507        &mut self,
2508        now: Instant,
2509    ) -> (Vec<ChunkPayloadData>, Vec<u16>) {
2510        let mut chunks = vec![];
2511        let mut sis_to_reset = vec![]; // stream identifiers to reset
2512        if !self.pending_queue.is_empty() {
2513            // RFC 4960 sec 6.1.  Transmission of DATA Chunks
2514            //   A) At any given time, the data sender MUST NOT transmit new data to
2515            //      any destination transport address if its peer's rwnd indicates
2516            //      that the peer has no buffer space (i.e., rwnd is 0; see Section
2517            //      6.2.1).  However, regardless of the value of rwnd (including if it
2518            //      is 0), the data sender can always have one DATA chunk in flight to
2519            //      the receiver if allowed by cwnd (see rule B, below).
2520
2521            while let Some(c) = self.pending_queue.peek() {
2522                let (beginning_fragment, unordered, data_len, stream_identifier) = (
2523                    c.beginning_fragment,
2524                    c.unordered,
2525                    c.user_data.len(),
2526                    c.stream_identifier,
2527                );
2528
2529                if data_len == 0 {
2530                    sis_to_reset.push(stream_identifier);
2531                    if self
2532                        .pending_queue
2533                        .pop(beginning_fragment, unordered)
2534                        .is_none()
2535                    {
2536                        error!("[{}] failed to pop from pending queue", self.side);
2537                    }
2538                    continue;
2539                }
2540
2541                if self.inflight_queue.get_num_bytes() + data_len > self.cwnd as usize {
2542                    break; // would exceeds cwnd
2543                }
2544
2545                if data_len > self.rwnd as usize {
2546                    break; // no more rwnd
2547                }
2548
2549                self.rwnd -= data_len as u32;
2550
2551                if let Some(chunk) = self.move_pending_data_chunk_to_inflight_queue(
2552                    beginning_fragment,
2553                    unordered,
2554                    now,
2555                ) {
2556                    chunks.push(chunk);
2557                }
2558            }
2559
2560            // the data sender can always have one DATA chunk in flight to the receiver
2561            if chunks.is_empty() && self.inflight_queue.is_empty() {
2562                // Send zero window probe
2563                if let Some(c) = self.pending_queue.peek() {
2564                    let (beginning_fragment, unordered) = (c.beginning_fragment, c.unordered);
2565
2566                    if let Some(chunk) = self.move_pending_data_chunk_to_inflight_queue(
2567                        beginning_fragment,
2568                        unordered,
2569                        now,
2570                    ) {
2571                        chunks.push(chunk);
2572                    }
2573                }
2574            }
2575        }
2576
2577        (chunks, sis_to_reset)
2578    }
2579
2580    /// bundle_data_chunks_into_packets packs DATA chunks into packets. It tries to bundle
2581    /// DATA chunks into a packet so long as the resulting packet size does not exceed
2582    /// the path MTU.
2583    fn bundle_data_chunks_into_packets(
2584        &self,
2585        chunks: Vec<ChunkPayloadData>,
2586        raw_packets: &mut Vec<Bytes>,
2587    ) {
2588        // RFC 4960 sec 6.1.  Transmission of DATA Chunks
2589        //   Multiple DATA chunks committed for transmission MAY be bundled in a
2590        //   single packet.  Furthermore, DATA chunks being retransmitted MAY be
2591        //   bundled with new DATA chunks, as long as the resulting packet size
2592        //   does not exceed the path MTU.
2593        //
2594        // Marshal each bundle straight into `raw_packets` from the borrowed
2595        // chunks: no intermediate `Vec<Packet>`, no `Box<dyn Chunk>` per chunk.
2596        // The chunks are already retained in the in-flight queue, so this send
2597        // copy is throwaway.
2598        if chunks.is_empty() {
2599            return;
2600        }
2601        let common_header = CommonHeader {
2602            verification_tag: self.peer_verification_tag,
2603            source_port: self.source_port,
2604            destination_port: self.destination_port,
2605        };
2606
2607        // First pass: split the chunks into MTU-bounded datagrams and total up
2608        // their marshalled (4-byte-padded) length. The whole burst is then
2609        // written into ONE buffer and `split_to` hands out each datagram as a
2610        // zero-copy `Bytes` view sharing that single allocation — one malloc per
2611        // burst instead of one per packet on the hot send path. The bundle
2612        // boundaries are computed once here and reused below, so the MTU-split
2613        // rule lives in exactly one place.
2614        let hdr = COMMON_HEADER_SIZE as usize;
2615        let mut bundles: Vec<(usize, usize)> = Vec::new();
2616        let mut total_len = 0usize;
2617        let mut bundle_start = 0;
2618        let mut bytes_in_packet = COMMON_HEADER_SIZE;
2619        let mut bundle_len = hdr;
2620        for (i, chunk) in chunks.iter().enumerate() {
2621            let data_len = chunk.user_data.len() as u32;
2622            // Close the current bundle before a chunk that would exceed the MTU.
2623            if bytes_in_packet + data_len > self.mtu && i > bundle_start {
2624                bundles.push((bundle_start, i));
2625                total_len += bundle_len;
2626                bundle_start = i;
2627                bytes_in_packet = COMMON_HEADER_SIZE;
2628                bundle_len = hdr;
2629            }
2630            bytes_in_packet += DATA_CHUNK_HEADER_SIZE + data_len;
2631            // Marshalled chunk size, padded up to the SCTP 4-byte boundary.
2632            let wire = (DATA_CHUNK_HEADER_SIZE + data_len) as usize;
2633            bundle_len += (wire + 3) & !3;
2634        }
2635        bundles.push((bundle_start, chunks.len()));
2636        total_len += bundle_len;
2637
2638        // Second pass: marshal each datagram into the shared buffer.
2639        let mut buf = BytesMut::with_capacity(total_len);
2640        for (start, end) in bundles {
2641            match Packet::write_framed(
2642                &common_header,
2643                chunks[start..end].iter().map(|c| c as &dyn Chunk),
2644                &mut buf,
2645            ) {
2646                Ok(_) => {
2647                    let plen = buf.len();
2648                    raw_packets.push(buf.split_to(plen).freeze());
2649                }
2650                Err(_) => {
2651                    warn!("[{}] failed to serialize a DATA packet", self.side);
2652                    buf.clear();
2653                }
2654            }
2655        }
2656    }
2657
2658    /// generate_next_tsn returns the my_next_tsn and increases it. The caller should hold the lock.
2659    fn generate_next_tsn(&mut self) -> u32 {
2660        let tsn = self.my_next_tsn;
2661        self.my_next_tsn += 1;
2662        tsn
2663    }
2664
2665    /// generate_next_rsn returns the my_next_rsn and increases it. The caller should hold the lock.
2666    fn generate_next_rsn(&mut self) -> u32 {
2667        let rsn = self.my_next_rsn;
2668        self.my_next_rsn += 1;
2669        rsn
2670    }
2671
2672    fn check_partial_reliability_status(
2673        c: &mut ChunkPayloadData,
2674        now: Instant,
2675        use_forward_tsn: bool,
2676        side: Side,
2677        streams: &FxHashMap<u16, StreamState>,
2678    ) {
2679        if !use_forward_tsn {
2680            return;
2681        }
2682
2683        // draft-ietf-rtcweb-data-protocol-09.txt section 6
2684        //	6.  Procedures
2685        //		All Data Channel Establishment TransportProtocol messages MUST be sent using
2686        //		ordered delivery and reliable transmission.
2687        //
2688        if c.payload_type == PayloadProtocolIdentifier::Dcep {
2689            return;
2690        }
2691
2692        // PR-SCTP
2693        if let Some(s) = streams.get(&c.stream_identifier) {
2694            let reliability_type: ReliabilityType = s.reliability_type;
2695            let reliability_value = s.reliability_value;
2696
2697            if reliability_type == ReliabilityType::Rexmit {
2698                if c.nsent >= reliability_value {
2699                    c.set_abandoned(true);
2700                    trace!(
2701                        "[{}] marked as abandoned: tsn={} ppi={} (remix: {})",
2702                        side, c.tsn, c.payload_type, c.nsent
2703                    );
2704                }
2705            } else if reliability_type == ReliabilityType::Timed {
2706                if let Some(since) = &c.since {
2707                    let elapsed = now.duration_since(*since);
2708                    if elapsed.as_millis() as u32 >= reliability_value {
2709                        c.set_abandoned(true);
2710                        trace!(
2711                            "[{}] marked as abandoned: tsn={} ppi={} (timed: {:?})",
2712                            side, c.tsn, c.payload_type, elapsed
2713                        );
2714                    }
2715                } else {
2716                    error!("[{}] invalid c.since", side);
2717                }
2718            }
2719        } else {
2720            error!("[{}] stream {} not found)", side, c.stream_identifier);
2721        }
2722    }
2723
2724    fn create_selective_ack_chunk(&mut self) -> ChunkSelectiveAck {
2725        ChunkSelectiveAck {
2726            cumulative_tsn_ack: self.peer_last_tsn,
2727            advertised_receiver_window_credit: self.get_my_receiver_window_credit(),
2728            gap_ack_blocks: self.payload_queue.get_gap_ack_blocks(self.peer_last_tsn),
2729            duplicate_tsn: self.payload_queue.pop_duplicates(),
2730        }
2731    }
2732
2733    /// Record an abandoned chunk into the forward-TSN stream map (RFC 3758 C4),
2734    /// called from the two C2 loops as `advanced_peer_tsn_ack_point` advances
2735    /// over each newly-abandoned in-flight chunk. Only *ordered* streams are
2736    /// tracked: the receiver ignores the per-stream SSN list for unordered
2737    /// chunks (it advances purely by `new_cumulative_tsn`). Keeps the greatest
2738    /// SSN seen per stream, which is the value RFC 3758 C4 requires to report.
2739    ///
2740    /// A stream's entry may briefly outlive the chunk that set it (until the
2741    /// window closes and the map is cleared), so a stale SSN can be re-reported;
2742    /// that is safe because the receiver only advances a stream forward and the
2743    /// SSN always corresponds to a really-abandoned chunk. The `u16` SSN compare
2744    /// (`sna16lt`) is sound because the window span is bounded by rwnd — a
2745    /// stream cannot lap the full 65536-sequence space before the window closes.
2746    fn note_abandoned_for_forward_tsn(&mut self, unordered: bool, si: u16, ssn: u16) {
2747        if unordered {
2748            return;
2749        }
2750        self.fwd_tsn_stream_map
2751            .entry(si)
2752            .and_modify(|cur| {
2753                if sna16lt(*cur, ssn) {
2754                    *cur = ssn;
2755                }
2756            })
2757            .or_insert(ssn);
2758    }
2759
2760    /// Test-only observer for the incremental forward-TSN stream map, so the
2761    /// endpoint tests can assert it is cleared once the forward-TSN window
2762    /// closes (the C1/C3 clear paths, which the unit tests can't reach).
2763    #[cfg(test)]
2764    pub(crate) fn fwd_tsn_stream_map_is_empty(&self) -> bool {
2765        self.fwd_tsn_stream_map.is_empty()
2766    }
2767
2768    /// create_forward_tsn generates ForwardTSN chunk.
2769    /// This method will be be called if use_forward_tsn is set to false.
2770    fn create_forward_tsn(&self) -> ChunkForwardTsn {
2771        // RFC 3758 Sec 3.5 C4: report, once per ordered stream, the greatest
2772        // stream-sequence-number among abandoned chunks in the forward-TSN
2773        // window. This is maintained incrementally in `fwd_tsn_stream_map` (see
2774        // its declaration and the two C2 loops that feed it), so we no longer
2775        // rescan `(cumulative_tsn_ack_point, advanced_peer_tsn_ack_point]` with
2776        // a per-TSN hashmap probe on every FORWARD-TSN — that scan was O(rwnd)
2777        // (~1000 probes/call for a 1 MB window) and dominated the send profile.
2778        let mut fwd_tsn = ChunkForwardTsn {
2779            new_cumulative_tsn: self.advanced_peer_tsn_ack_point,
2780            streams: Vec::with_capacity(self.fwd_tsn_stream_map.len()),
2781        };
2782        for (si, ssn) in &self.fwd_tsn_stream_map {
2783            fwd_tsn.streams.push(ChunkForwardTsnStream {
2784                identifier: *si,
2785                sequence: *ssn,
2786            });
2787        }
2788        // `trace!` evaluates its arguments lazily, so the stream list is only
2789        // formatted when trace logging is enabled -- no per-FORWARD-TSN string
2790        // allocation on the hot send path (this fires often for PR-SCTP data
2791        // channels, which is exactly where it was showing up in profiles).
2792        trace!(
2793            "[{}] building fwd_tsn: newCumulativeTSN={} cumTSN={} streams={:?}",
2794            self.side, fwd_tsn.new_cumulative_tsn, self.cumulative_tsn_ack_point, fwd_tsn.streams
2795        );
2796
2797        fwd_tsn
2798    }
2799
2800    /// Move the chunk peeked with self.pending_queue.peek() to the inflight_queue.
2801    fn move_pending_data_chunk_to_inflight_queue(
2802        &mut self,
2803        beginning_fragment: bool,
2804        unordered: bool,
2805        now: Instant,
2806    ) -> Option<ChunkPayloadData> {
2807        if let Some(mut c) = self.pending_queue.pop(beginning_fragment, unordered) {
2808            // Mark all fragements are in-flight now
2809            if c.ending_fragment {
2810                c.set_all_inflight();
2811            }
2812
2813            // Assign TSN
2814            c.tsn = self.generate_next_tsn();
2815
2816            c.since = Some(now); // use to calculate RTT and also for maxPacketLifeTime
2817            c.nsent = 1; // being sent for the first time
2818
2819            Association::check_partial_reliability_status(
2820                &mut c,
2821                now,
2822                self.use_forward_tsn,
2823                self.side,
2824                &self.streams,
2825            );
2826
2827            trace!(
2828                "[{}] sending ppi={} tsn={} ssn={} sent={} len={} ({},{})",
2829                self.side,
2830                c.payload_type as u32,
2831                c.tsn,
2832                c.stream_sequence_number,
2833                c.nsent,
2834                c.user_data.len(),
2835                c.beginning_fragment,
2836                c.ending_fragment
2837            );
2838
2839            self.inflight_queue.push_no_check(c.clone());
2840
2841            Some(c)
2842        } else {
2843            error!("[{}] failed to pop from pending queue", self.side);
2844            None
2845        }
2846    }
2847
2848    pub(crate) fn send_reset_request(&mut self, stream_identifier: StreamId) -> Result<()> {
2849        let state = self.state();
2850        if state != AssociationState::Established {
2851            return Err(Error::ErrResetPacketInStateNotExist);
2852        }
2853
2854        // Create DATA chunk which only contains valid stream identifier with
2855        // nil userData and use it as a EOS from the stream.
2856        let c = ChunkPayloadData {
2857            stream_identifier,
2858            beginning_fragment: true,
2859            ending_fragment: true,
2860            user_data: Bytes::new(),
2861            ..Default::default()
2862        };
2863
2864        self.pending_queue.push(c);
2865        self.awake_write_loop();
2866
2867        Ok(())
2868    }
2869
2870    /// send_payload_data sends the data chunks.
2871    pub(crate) fn send_payload_data(&mut self, chunks: Vec<ChunkPayloadData>) -> Result<()> {
2872        let state = self.state();
2873        if state != AssociationState::Established {
2874            return Err(Error::ErrPayloadDataStateNotExist);
2875        }
2876
2877        // Push the chunks into the pending queue first.
2878        for c in chunks {
2879            self.pending_queue.push(c);
2880        }
2881
2882        self.awake_write_loop();
2883        Ok(())
2884    }
2885
2886    /// buffered_amount returns total amount (in bytes) of currently buffered user data.
2887    /// This is used only by testing.
2888    pub(crate) fn buffered_amount(&self) -> usize {
2889        self.pending_queue.get_num_bytes() + self.inflight_queue.get_num_bytes()
2890    }
2891
2892    fn awake_write_loop(&self) {
2893        // No Op on Purpose
2894    }
2895
2896    fn close_all_timers(&mut self) {
2897        // Close all retransmission & ack timers
2898        for timer in Timer::VALUES {
2899            self.timers.stop(timer);
2900        }
2901    }
2902
2903    fn on_ack_timeout(&mut self) {
2904        trace!(
2905            "[{}] ack timed out (ack_state: {})",
2906            self.side, self.ack_state
2907        );
2908        self.stats.inc_ack_timeouts();
2909        self.ack_state = AckState::Immediate;
2910        self.awake_write_loop();
2911    }
2912
2913    fn on_retransmission_timeout(&mut self, timer_id: Timer, n_rtos: usize) {
2914        match timer_id {
2915            Timer::T1Init => {
2916                if let Err(err) = self.send_init() {
2917                    debug!(
2918                        "[{}] failed to retransmit init (n_rtos={}): {:?}",
2919                        self.side, n_rtos, err
2920                    );
2921                }
2922            }
2923
2924            Timer::T1Cookie => {
2925                if let Err(err) = self.send_cookie_echo() {
2926                    debug!(
2927                        "[{}] failed to retransmit cookie-echo (n_rtos={}): {:?}",
2928                        self.side, n_rtos, err
2929                    );
2930                }
2931            }
2932
2933            Timer::T2Shutdown => {
2934                debug!(
2935                    "[{}] retransmission of shutdown timeout (n_rtos={})",
2936                    self.side, n_rtos
2937                );
2938                let state = self.state();
2939                match state {
2940                    AssociationState::ShutdownSent => {
2941                        self.will_send_shutdown = true;
2942                        self.awake_write_loop();
2943                    }
2944                    AssociationState::ShutdownAckSent => {
2945                        self.will_send_shutdown_ack = true;
2946                        self.awake_write_loop();
2947                    }
2948                    _ => {}
2949                }
2950            }
2951
2952            Timer::T3RTX => {
2953                self.stats.inc_t3timeouts();
2954
2955                // RFC 4960 sec 6.3.3
2956                //  E1)  For the destination address for which the timer expires, adjust
2957                //       its ssthresh with rules defined in Section 7.2.3 and set the
2958                //       cwnd <- MTU.
2959                // RFC 4960 sec 7.2.3
2960                //   When the T3-rtx timer expires on an address, SCTP should perform slow
2961                //   start by:
2962                //      ssthresh = max(cwnd/2, 4*MTU)
2963                //      cwnd = 1*MTU
2964
2965                self.ssthresh = std::cmp::max(self.cwnd / 2, 4 * self.mtu);
2966                self.cwnd = self.mtu;
2967                trace!(
2968                    "[{}] updated cwnd={} ssthresh={} inflight={} (RTO)",
2969                    self.side,
2970                    self.cwnd,
2971                    self.ssthresh,
2972                    self.inflight_queue.get_num_bytes()
2973                );
2974
2975                // RFC 3758 sec 3.5
2976                //  A5) Any time the T3-rtx timer expires, on any destination, the sender
2977                //  SHOULD try to advance the "Advanced.Peer.Ack.Point" by following
2978                //  the procedures outlined in C2 - C5.
2979                if self.use_forward_tsn {
2980                    // RFC 3758 Sec 3.5 C2
2981                    let mut i = self.advanced_peer_tsn_ack_point + 1;
2982                    while let Some((abandoned, unordered, si, ssn)) =
2983                        self.inflight_queue.get(i).map(|c| {
2984                            (
2985                                c.abandoned(),
2986                                c.unordered,
2987                                c.stream_identifier,
2988                                c.stream_sequence_number,
2989                            )
2990                        })
2991                    {
2992                        if !abandoned {
2993                            break;
2994                        }
2995                        self.advanced_peer_tsn_ack_point = i;
2996                        self.note_abandoned_for_forward_tsn(unordered, si, ssn);
2997                        i += 1;
2998                    }
2999
3000                    // RFC 3758 Sec 3.5 C3
3001                    if sna32gt(
3002                        self.advanced_peer_tsn_ack_point,
3003                        self.cumulative_tsn_ack_point,
3004                    ) {
3005                        self.will_send_forward_tsn = true;
3006                        debug!(
3007                            "[{}] on_retransmission_timeout {}: sna32GT({}, {})",
3008                            self.side,
3009                            self.will_send_forward_tsn,
3010                            self.advanced_peer_tsn_ack_point,
3011                            self.cumulative_tsn_ack_point
3012                        );
3013                    }
3014                }
3015
3016                debug!(
3017                    "[{}] T3-rtx timed out: n_rtos={} cwnd={} ssthresh={}",
3018                    self.side, n_rtos, self.cwnd, self.ssthresh
3019                );
3020
3021                self.inflight_queue.mark_all_to_retrasmit();
3022                self.t3_retransmit_pending = true;
3023                self.awake_write_loop();
3024            }
3025
3026            Timer::Reconfig => {
3027                self.will_retransmit_reconfig = true;
3028                self.awake_write_loop();
3029            }
3030
3031            _ => {}
3032        }
3033    }
3034
3035    fn on_retransmission_failure(&mut self, id: Timer) {
3036        match id {
3037            Timer::T1Init => {
3038                error!("[{}] retransmission failure: T1-init", self.side);
3039                self.error = Some(AssociationError::HandshakeFailed(
3040                    Error::ErrHandshakeInitAck.to_string(),
3041                ));
3042            }
3043
3044            Timer::T1Cookie => {
3045                error!("[{}] retransmission failure: T1-cookie", self.side);
3046                self.error = Some(AssociationError::HandshakeFailed(
3047                    Error::ErrHandshakeCookieEcho.to_string(),
3048                ));
3049            }
3050
3051            Timer::T2Shutdown => {
3052                error!("[{}] retransmission failure: T2-shutdown", self.side);
3053            }
3054
3055            Timer::T3RTX => {
3056                // T3-rtx timer will not fail by design
3057                // Justifications:
3058                //  * ICE would fail if the connectivity is lost
3059                //  * WebRTC spec is not clear how this incident should be reported to ULP
3060                error!("[{}] retransmission failure: T3-rtx (DATA)", self.side);
3061            }
3062
3063            _ => {}
3064        }
3065    }
3066
3067    /// Whether no timers are running
3068    #[cfg(test)]
3069    pub(crate) fn is_idle(&self) -> bool {
3070        Timer::VALUES
3071            .iter()
3072            //.filter(|&&t| t != Timer::KeepAlive && t != Timer::PushNewCid)
3073            .filter_map(|&t| Some((t, self.timers.get(t)?)))
3074            .min_by_key(|&(_, time)| time)
3075            //.map_or(true, |(timer, _)| timer == Timer::Idle)
3076            .is_none()
3077    }
3078}