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
1224                    if let Some(last_tsn) = self.payload_queue.get_last_tsn_received() {
1225                        if sna32lt(d.tsn, *last_tsn) {
1226                            debug!(
1227                                "[{}] receive buffer full, but accepted as this is a missing chunk with tsn={} ssn={}",
1228                                self.side, d.tsn, d.stream_sequence_number
1229                            );
1230                            self.payload_queue.push(d.clone(), self.peer_last_tsn);
1231                            stream_handle_data = true; //s.handle_data(d.clone());
1232                        }
1233                    } else {
1234                        debug!(
1235                            "[{}] receive buffer full. dropping DATA with tsn={} ssn={}",
1236                            self.side, d.tsn, d.stream_sequence_number
1237                        );
1238                    }
1239                }
1240            } else {
1241                // silently discard the data. (sender will retry on T3-rtx timeout)
1242                debug!("[{}] discard {}", self.side, d.stream_sequence_number);
1243                return Ok(vec![]);
1244            }
1245        }
1246
1247        let immediate_sack = d.immediate_sack;
1248
1249        if stream_handle_data && let Some(s) = self.streams.get_mut(&d.stream_identifier) {
1250            self.events.push_back(Event::DatagramReceived);
1251            if s.handle_data(d) && s.reassembly_queue.is_readable() {
1252                self.events.push_back(Event::Stream(StreamEvent::Readable {
1253                    id: s.stream_identifier,
1254                }));
1255            }
1256        }
1257
1258        self.handle_peer_last_tsn_and_acknowledgement(immediate_sack)
1259    }
1260
1261    fn handle_sack(&mut self, d: &ChunkSelectiveAck, now: Instant) -> Result<Vec<Packet>> {
1262        trace!(
1263            "[{}] {}, SACK: cumTSN={} a_rwnd={}",
1264            self.side,
1265            self.cumulative_tsn_ack_point,
1266            d.cumulative_tsn_ack,
1267            d.advertised_receiver_window_credit
1268        );
1269        let state = self.state();
1270        if state != AssociationState::Established
1271            && state != AssociationState::ShutdownPending
1272            && state != AssociationState::ShutdownReceived
1273        {
1274            return Ok(vec![]);
1275        }
1276
1277        self.stats.inc_sacks();
1278
1279        if sna32gt(self.cumulative_tsn_ack_point, d.cumulative_tsn_ack) {
1280            // RFC 4960 sec 6.2.1.  Processing a Received SACK
1281            // D)
1282            //   i) If Cumulative TSN Ack is less than the Cumulative TSN Ack
1283            //      Point, then drop the SACK.  Since Cumulative TSN Ack is
1284            //      monotonically increasing, a SACK whose Cumulative TSN Ack is
1285            //      less than the Cumulative TSN Ack Point indicates an out-of-
1286            //      order SACK.
1287
1288            debug!(
1289                "[{}] SACK Cumulative ACK {} is older than ACK point {}",
1290                self.side, d.cumulative_tsn_ack, self.cumulative_tsn_ack_point
1291            );
1292
1293            return Ok(vec![]);
1294        }
1295
1296        // Process selective ack
1297        let (bytes_acked_per_stream, htna) = self.process_selective_ack(d, now)?;
1298
1299        let mut total_bytes_acked = 0;
1300        for n_bytes_acked in bytes_acked_per_stream.values() {
1301            total_bytes_acked += *n_bytes_acked;
1302        }
1303
1304        let mut cum_tsn_ack_point_advanced = false;
1305        if sna32lt(self.cumulative_tsn_ack_point, d.cumulative_tsn_ack) {
1306            trace!(
1307                "[{}] SACK: cumTSN advanced: {} -> {}",
1308                self.side, self.cumulative_tsn_ack_point, d.cumulative_tsn_ack
1309            );
1310
1311            self.cumulative_tsn_ack_point = d.cumulative_tsn_ack;
1312            cum_tsn_ack_point_advanced = true;
1313            self.on_cumulative_tsn_ack_point_advanced(total_bytes_acked, now);
1314        }
1315
1316        for (si, n_bytes_acked) in &bytes_acked_per_stream {
1317            if *n_bytes_acked > 0 {
1318                // Report the exact bytes released for this stream (acknowledged OR
1319                // abandoned — both funnel through bytes_acked_per_stream) so upper
1320                // layers can decrement their own send-buffer accounting. Unlike the
1321                // edge-triggered BufferedAmountLow advisory below, this fires on
1322                // every release with the byte delta.
1323                self.events
1324                    .push_back(Event::Stream(StreamEvent::BufferedAmountReleased {
1325                        id: *si,
1326                        n_bytes: *n_bytes_acked as usize,
1327                    }));
1328            }
1329            if let Some(s) = self.streams.get_mut(si)
1330                && s.on_buffer_released(*n_bytes_acked)
1331            {
1332                trace!("StreamEvent::BufferedAmountLow");
1333                self.events
1334                    .push_back(Event::Stream(StreamEvent::BufferedAmountLow { id: *si }))
1335            }
1336        }
1337
1338        // New rwnd value
1339        // RFC 4960 sec 6.2.1.  Processing a Received SACK
1340        // D)
1341        //   ii) Set rwnd equal to the newly received a_rwnd minus the number
1342        //       of bytes still outstanding after processing the Cumulative
1343        //       TSN Ack and the Gap Ack Blocks.
1344
1345        // bytes acked were already subtracted by markAsAcked() method
1346        let bytes_outstanding = self.inflight_queue.get_num_bytes() as u32;
1347        if bytes_outstanding >= d.advertised_receiver_window_credit {
1348            self.rwnd = 0;
1349        } else {
1350            self.rwnd = d.advertised_receiver_window_credit - bytes_outstanding;
1351        }
1352
1353        self.process_fast_retransmission(d.cumulative_tsn_ack, htna, cum_tsn_ack_point_advanced)?;
1354
1355        if self.use_forward_tsn {
1356            // RFC 3758 Sec 3.5 C1
1357            if sna32lt(
1358                self.advanced_peer_tsn_ack_point,
1359                self.cumulative_tsn_ack_point,
1360            ) {
1361                self.advanced_peer_tsn_ack_point = self.cumulative_tsn_ack_point;
1362                // Window reset: everything previously tracked is now at/below
1363                // the cumulative ack point, so start the stream map fresh.
1364                self.fwd_tsn_stream_map.clear();
1365            }
1366
1367            // RFC 3758 Sec 3.5 C2 — advance over newly-abandoned chunks,
1368            // folding each ordered one into the forward-TSN stream map so
1369            // create_forward_tsn needn't rescan the window.
1370            let mut i = self.advanced_peer_tsn_ack_point + 1;
1371            while let Some((abandoned, unordered, si, ssn)) = self.inflight_queue.get(i).map(|c| {
1372                (
1373                    c.abandoned(),
1374                    c.unordered,
1375                    c.stream_identifier,
1376                    c.stream_sequence_number,
1377                )
1378            }) {
1379                if !abandoned {
1380                    break;
1381                }
1382                self.advanced_peer_tsn_ack_point = i;
1383                self.note_abandoned_for_forward_tsn(unordered, si, ssn);
1384                i += 1;
1385            }
1386
1387            // RFC 3758 Sec 3.5 C3
1388            if sna32gt(
1389                self.advanced_peer_tsn_ack_point,
1390                self.cumulative_tsn_ack_point,
1391            ) {
1392                self.will_send_forward_tsn = true;
1393                debug!(
1394                    "[{}] handleSack {}: sna32GT({}, {})",
1395                    self.side,
1396                    self.will_send_forward_tsn,
1397                    self.advanced_peer_tsn_ack_point,
1398                    self.cumulative_tsn_ack_point
1399                );
1400            } else {
1401                // No forward-TSN window open (receiver has caught up): drop any
1402                // stale per-stream SSNs so they aren't reported later.
1403                self.fwd_tsn_stream_map.clear();
1404            }
1405            self.awake_write_loop();
1406        }
1407
1408        self.postprocess_sack(state, cum_tsn_ack_point_advanced, now);
1409
1410        Ok(vec![])
1411    }
1412
1413    fn handle_reconfig(&mut self, c: &ChunkReconfig) -> Result<Vec<Packet>> {
1414        trace!("[{}] handle_reconfig", self.side);
1415
1416        let mut pp = vec![];
1417
1418        if let Some(param_a) = &c.param_a {
1419            self.handle_reconfig_param(param_a, &mut pp)?;
1420        }
1421
1422        if let Some(param_b) = &c.param_b {
1423            self.handle_reconfig_param(param_b, &mut pp)?;
1424        }
1425
1426        Ok(pp)
1427    }
1428
1429    fn handle_forward_tsn(&mut self, c: &ChunkForwardTsn) -> Result<Vec<Packet>> {
1430        trace!("[{}] FwdTSN: {}", self.side, c);
1431
1432        if !self.use_forward_tsn {
1433            warn!("[{}] received FwdTSN but not enabled", self.side);
1434            // Return an error chunk
1435            let cerr = ChunkError {
1436                error_causes: vec![ErrorCauseUnrecognizedChunkType::default()],
1437            };
1438
1439            let outbound = Packet {
1440                common_header: CommonHeader {
1441                    verification_tag: self.peer_verification_tag,
1442                    source_port: self.source_port,
1443                    destination_port: self.destination_port,
1444                },
1445                chunks: vec![Box::new(cerr)],
1446            };
1447            return Ok(vec![outbound]);
1448        }
1449
1450        // From RFC 3758 Sec 3.6:
1451        //   Note, if the "New Cumulative TSN" value carried in the arrived
1452        //   FORWARD TSN chunk is found to be behind or at the current cumulative
1453        //   TSN point, the data receiver MUST treat this FORWARD TSN as out-of-
1454        //   date and MUST NOT update its Cumulative TSN.  The receiver SHOULD
1455        //   send a SACK to its peer (the sender of the FORWARD TSN) since such a
1456        //   duplicate may indicate the previous SACK was lost in the network.
1457
1458        trace!(
1459            "[{}] should send ack? newCumTSN={} peer_last_tsn={}",
1460            self.side, c.new_cumulative_tsn, self.peer_last_tsn
1461        );
1462        if sna32lte(c.new_cumulative_tsn, self.peer_last_tsn) {
1463            trace!("[{}] sending ack on Forward TSN", self.side);
1464            self.ack_state = AckState::Immediate;
1465            self.timers.stop(Timer::Ack);
1466            self.awake_write_loop();
1467            return Ok(vec![]);
1468        }
1469
1470        // From RFC 3758 Sec 3.6:
1471        //   the receiver MUST perform the same TSN handling, including duplicate
1472        //   detection, gap detection, SACK generation, cumulative TSN
1473        //   advancement, etc. as defined in RFC 2960 [2]---with the following
1474        //   exceptions and additions.
1475
1476        //   When a FORWARD TSN chunk arrives, the data receiver MUST first update
1477        //   its cumulative TSN point to the value carried in the FORWARD TSN
1478        //   chunk,
1479
1480        // Advance peer_last_tsn
1481        while sna32lt(self.peer_last_tsn, c.new_cumulative_tsn) {
1482            self.payload_queue.pop(self.peer_last_tsn + 1); // may not exist
1483            self.peer_last_tsn += 1;
1484        }
1485
1486        // Report new peer_last_tsn value and abandoned largest SSN value to
1487        // corresponding streams so that the abandoned chunks can be removed
1488        // from the reassemblyQueue.
1489        for forwarded in &c.streams {
1490            if let Some(s) = self.streams.get_mut(&forwarded.identifier) {
1491                s.handle_forward_tsn_for_ordered(forwarded.sequence);
1492                if s.reassembly_queue.is_readable() {
1493                    self.events.push_back(Event::Stream(StreamEvent::Readable {
1494                        id: s.stream_identifier,
1495                    }));
1496                }
1497            }
1498        }
1499
1500        // TSN may be forwarded for unordered chunks. ForwardTSN chunk does not
1501        // report which stream identifier it skipped for unordered chunks.
1502        // Therefore, we need to broadcast this event to all existing streams for
1503        // unordered chunks.
1504        for s in self.streams.values_mut() {
1505            s.handle_forward_tsn_for_unordered(c.new_cumulative_tsn);
1506            if s.reassembly_queue.is_readable() {
1507                self.events.push_back(Event::Stream(StreamEvent::Readable {
1508                    id: s.stream_identifier,
1509                }));
1510            }
1511        }
1512
1513        self.handle_peer_last_tsn_and_acknowledgement(false)
1514    }
1515
1516    fn handle_shutdown(&mut self, _: &ChunkShutdown) -> Result<Vec<Packet>> {
1517        let state = self.state();
1518
1519        if state == AssociationState::Established {
1520            if !self.inflight_queue.is_empty() {
1521                self.set_state(AssociationState::ShutdownReceived);
1522            } else {
1523                // No more outstanding, send shutdown ack.
1524                self.will_send_shutdown_ack = true;
1525                self.set_state(AssociationState::ShutdownAckSent);
1526
1527                self.awake_write_loop();
1528            }
1529        } else if state == AssociationState::ShutdownSent {
1530            // self.cumulative_tsn_ack_point = c.cumulative_tsn_ack
1531
1532            self.will_send_shutdown_ack = true;
1533            self.set_state(AssociationState::ShutdownAckSent);
1534
1535            self.awake_write_loop();
1536        }
1537
1538        Ok(vec![])
1539    }
1540
1541    fn handle_shutdown_ack(&mut self, _: &ChunkShutdownAck) -> Result<Vec<Packet>> {
1542        let state = self.state();
1543        if state == AssociationState::ShutdownSent || state == AssociationState::ShutdownAckSent {
1544            self.timers.stop(Timer::T2Shutdown);
1545            self.will_send_shutdown_complete = true;
1546
1547            self.awake_write_loop();
1548        }
1549
1550        Ok(vec![])
1551    }
1552
1553    fn handle_shutdown_complete(&mut self, _: &ChunkShutdownComplete) -> Result<Vec<Packet>> {
1554        let state = self.state();
1555        if state == AssociationState::ShutdownAckSent {
1556            self.timers.stop(Timer::T2Shutdown);
1557            self.close(AssociationError::AssociationClosed)?;
1558        }
1559
1560        Ok(vec![])
1561    }
1562
1563    /// A common routine for handle_data and handle_forward_tsn routines
1564    fn handle_peer_last_tsn_and_acknowledgement(
1565        &mut self,
1566        sack_immediately: bool,
1567    ) -> Result<Vec<Packet>> {
1568        let mut reply = vec![];
1569
1570        // Try to advance peer_last_tsn
1571
1572        // From RFC 3758 Sec 3.6:
1573        //   .. and then MUST further advance its cumulative TSN point locally
1574        //   if possible
1575        // Meaning, if peer_last_tsn+1 points to a chunk that is received,
1576        // advance peer_last_tsn until peer_last_tsn+1 points to unreceived chunk.
1577        //debug!("[{}] peer_last_tsn = {}", self.side, self.peer_last_tsn);
1578        while self.payload_queue.pop(self.peer_last_tsn + 1).is_some() {
1579            self.peer_last_tsn += 1;
1580            //debug!("[{}] peer_last_tsn = {}", self.side, self.peer_last_tsn);
1581
1582            let rst_reqs: Vec<ParamOutgoingResetRequest> =
1583                self.reconfig_requests.values().cloned().collect();
1584            for rst_req in rst_reqs {
1585                self.reset_streams_if_any(&rst_req, false, &mut reply)?;
1586            }
1587        }
1588
1589        let has_packet_loss = !self.payload_queue.is_empty();
1590        if has_packet_loss {
1591            trace!(
1592                "[{}] packetloss: {}",
1593                self.side,
1594                self.payload_queue
1595                    .get_gap_ack_blocks_string(self.peer_last_tsn)
1596            );
1597        }
1598
1599        if (self.ack_state != AckState::Immediate
1600            && !sack_immediately
1601            && !has_packet_loss
1602            && self.ack_mode == AckMode::Normal)
1603            || self.ack_mode == AckMode::AlwaysDelay
1604        {
1605            if self.ack_state == AckState::Idle {
1606                self.delayed_ack_triggered = true;
1607            } else {
1608                self.immediate_ack_triggered = true;
1609            }
1610        } else {
1611            self.immediate_ack_triggered = true;
1612        }
1613
1614        Ok(reply)
1615    }
1616
1617    #[allow(clippy::borrowed_box)]
1618    fn handle_reconfig_param(
1619        &mut self,
1620        raw: &Box<dyn Param>,
1621        reply: &mut Vec<Packet>,
1622    ) -> Result<()> {
1623        if let Some(p) = raw.as_any().downcast_ref::<ParamOutgoingResetRequest>() {
1624            self.reconfig_requests
1625                .insert(p.reconfig_request_sequence_number, p.clone());
1626            self.reset_streams_if_any(p, true, reply)?;
1627            Ok(())
1628        } else if let Some(p) = raw.as_any().downcast_ref::<ParamReconfigResponse>() {
1629            self.reconfigs.remove(&p.reconfig_response_sequence_number);
1630            if self.reconfigs.is_empty() {
1631                self.timers.stop(Timer::Reconfig);
1632            }
1633            Ok(())
1634        } else {
1635            Err(Error::ErrParameterType)
1636        }
1637    }
1638
1639    fn process_selective_ack(
1640        &mut self,
1641        d: &ChunkSelectiveAck,
1642        now: Instant,
1643    ) -> Result<(FxHashMap<u16, i64>, u32)> {
1644        let mut bytes_acked_per_stream = FxHashMap::default();
1645
1646        // New ack point, so pop all ACKed packets from inflight_queue
1647        // We add 1 because the "currentAckPoint" has already been popped from the inflight queue
1648        // For the first SACK we take care of this by setting the ackpoint to cumAck - 1
1649        let mut i = self.cumulative_tsn_ack_point + 1;
1650        //log::debug!("[{}] i={} d={}", self.name, i, d.cumulative_tsn_ack);
1651        while sna32lte(i, d.cumulative_tsn_ack) {
1652            if let Some(c) = self.inflight_queue.pop(i) {
1653                if !c.acked {
1654                    // RFC 4096 sec 6.3.2.  Retransmission Timer Rules
1655                    //   R3)  Whenever a SACK is received that acknowledges the DATA chunk
1656                    //        with the earliest outstanding TSN for that address, restart the
1657                    //        T3-rtx timer for that address with its current RTO (if there is
1658                    //        still outstanding data on that address).
1659                    if i == self.cumulative_tsn_ack_point + 1 {
1660                        // T3 timer needs to be reset. Stop it for now.
1661                        self.timers.stop(Timer::T3RTX);
1662                    }
1663
1664                    let n_bytes_acked = c.user_data.len() as i64;
1665
1666                    // Sum the number of bytes acknowledged per stream
1667                    if let Some(amount) = bytes_acked_per_stream.get_mut(&c.stream_identifier) {
1668                        *amount += n_bytes_acked;
1669                    } else {
1670                        bytes_acked_per_stream.insert(c.stream_identifier, n_bytes_acked);
1671                    }
1672
1673                    // RFC 4960 sec 6.3.1.  RTO Calculation
1674                    //   C4)  When data is in flight and when allowed by rule C5 below, a new
1675                    //        RTT measurement MUST be made each round trip.  Furthermore, new
1676                    //        RTT measurements SHOULD be made no more than once per round trip
1677                    //        for a given destination transport address.
1678                    //   C5)  Karn's algorithm: RTT measurements MUST NOT be made using
1679                    //        packets that were retransmitted (and thus for which it is
1680                    //        ambiguous whether the reply was for the first instance of the
1681                    //        chunk or for a later instance)
1682                    if c.nsent == 1 && sna32gte(c.tsn, self.min_tsn2measure_rtt) {
1683                        self.min_tsn2measure_rtt = self.my_next_tsn;
1684                        if let Some(since) = &c.since {
1685                            let rtt = now.duration_since(*since);
1686                            let srtt = self.rto_mgr.set_new_rtt(rtt.as_millis() as u64);
1687                            trace!(
1688                                "[{}] SACK: measured-rtt={} srtt={} new-rto={}",
1689                                self.side,
1690                                rtt.as_millis(),
1691                                srtt,
1692                                self.rto_mgr.get_rto()
1693                            );
1694                        } else {
1695                            error!("[{}] invalid c.since", self.side);
1696                        }
1697                    }
1698                }
1699
1700                if self.in_fast_recovery && c.tsn == self.fast_recover_exit_point {
1701                    debug!("[{}] exit fast-recovery", self.side);
1702                    self.in_fast_recovery = false;
1703                }
1704            } else {
1705                return Err(Error::ErrInflightQueueTsnPop);
1706            }
1707
1708            i += 1;
1709        }
1710
1711        let mut htna = d.cumulative_tsn_ack;
1712
1713        // Mark selectively acknowledged chunks as "acked"
1714        for g in &d.gap_ack_blocks {
1715            for i in g.start..=g.end {
1716                let tsn = d.cumulative_tsn_ack + i as u32;
1717
1718                let (is_existed, is_acked) = if let Some(c) = self.inflight_queue.get(tsn) {
1719                    (true, c.acked)
1720                } else {
1721                    (false, false)
1722                };
1723                let n_bytes_acked = if is_existed && !is_acked {
1724                    self.inflight_queue.mark_as_acked(tsn) as i64
1725                } else {
1726                    0
1727                };
1728
1729                if let Some(c) = self.inflight_queue.get(tsn) {
1730                    if !is_acked {
1731                        // Sum the number of bytes acknowledged per stream
1732                        if let Some(amount) = bytes_acked_per_stream.get_mut(&c.stream_identifier) {
1733                            *amount += n_bytes_acked;
1734                        } else {
1735                            bytes_acked_per_stream.insert(c.stream_identifier, n_bytes_acked);
1736                        }
1737
1738                        trace!("[{}] tsn={} has been sacked", self.side, c.tsn);
1739
1740                        if c.nsent == 1 {
1741                            self.min_tsn2measure_rtt = self.my_next_tsn;
1742                            if let Some(since) = &c.since {
1743                                let rtt = now.duration_since(*since);
1744                                let srtt = self.rto_mgr.set_new_rtt(rtt.as_millis() as u64);
1745                                trace!(
1746                                    "[{}] SACK: measured-rtt={} srtt={} new-rto={}",
1747                                    self.side,
1748                                    rtt.as_millis(),
1749                                    srtt,
1750                                    self.rto_mgr.get_rto()
1751                                );
1752                            } else {
1753                                error!("[{}] invalid c.since", self.side);
1754                            }
1755                        }
1756
1757                        if sna32lt(htna, tsn) {
1758                            htna = tsn;
1759                        }
1760                    }
1761                } else {
1762                    return Err(Error::ErrTsnRequestNotExist);
1763                }
1764            }
1765        }
1766
1767        Ok((bytes_acked_per_stream, htna))
1768    }
1769
1770    fn on_cumulative_tsn_ack_point_advanced(&mut self, total_bytes_acked: i64, now: Instant) {
1771        // RFC 4096, sec 6.3.2.  Retransmission Timer Rules
1772        //   R2)  Whenever all outstanding data sent to an address have been
1773        //        acknowledged, turn off the T3-rtx timer of that address.
1774        if self.inflight_queue.is_empty() {
1775            trace!(
1776                "[{}] SACK: no more packet in-flight (pending={})",
1777                self.side,
1778                self.pending_queue.len()
1779            );
1780            self.timers.stop(Timer::T3RTX);
1781        } else {
1782            trace!("[{}] T3-rtx timer start (pt2)", self.side);
1783            self.timers
1784                .restart_if_stale(Timer::T3RTX, now, self.rto_mgr.get_rto());
1785        }
1786
1787        // Update congestion control parameters
1788        if self.cwnd <= self.ssthresh {
1789            // RFC 4096, sec 7.2.1.  Slow-Start
1790            //   o  When cwnd is less than or equal to ssthresh, an SCTP endpoint MUST
1791            //		use the slow-start algorithm to increase cwnd only if the current
1792            //      congestion window is being fully utilized, an incoming SACK
1793            //      advances the Cumulative TSN Ack Point, and the data sender is not
1794            //      in Fast Recovery.  Only when these three conditions are met can
1795            //      the cwnd be increased; otherwise, the cwnd MUST not be increased.
1796            //		If these conditions are met, then cwnd MUST be increased by, at
1797            //      most, the lesser of 1) the total size of the previously
1798            //      outstanding DATA chunk(s) acknowledged, and 2) the destination's
1799            //      path MTU.
1800            if !self.in_fast_recovery && !self.pending_queue.is_empty() {
1801                self.cwnd += std::cmp::min(total_bytes_acked as u32, self.cwnd); // TCP way
1802                // self.cwnd += min32(uint32(total_bytes_acked), self.mtu) // SCTP way (slow)
1803                trace!(
1804                    "[{}] updated cwnd={} ssthresh={} acked={} (SS)",
1805                    self.side, self.cwnd, self.ssthresh, total_bytes_acked
1806                );
1807            } else {
1808                trace!(
1809                    "[{}] cwnd did not grow: cwnd={} ssthresh={} acked={} FR={} pending={}",
1810                    self.side,
1811                    self.cwnd,
1812                    self.ssthresh,
1813                    total_bytes_acked,
1814                    self.in_fast_recovery,
1815                    self.pending_queue.len()
1816                );
1817            }
1818        } else {
1819            // RFC 4096, sec 7.2.2.  Congestion Avoidance
1820            //   o  Whenever cwnd is greater than ssthresh, upon each SACK arrival
1821            //      that advances the Cumulative TSN Ack Point, increase
1822            //      partial_bytes_acked by the total number of bytes of all new chunks
1823            //      acknowledged in that SACK including chunks acknowledged by the new
1824            //      Cumulative TSN Ack and by Gap Ack Blocks.
1825            self.partial_bytes_acked += total_bytes_acked as u32;
1826
1827            //   o  When partial_bytes_acked is equal to or greater than cwnd and
1828            //      before the arrival of the SACK the sender had cwnd or more bytes
1829            //      of data outstanding (i.e., before arrival of the SACK, flight size
1830            //      was greater than or equal to cwnd), increase cwnd by MTU, and
1831            //      reset partial_bytes_acked to (partial_bytes_acked - cwnd).
1832            if self.partial_bytes_acked >= self.cwnd && !self.pending_queue.is_empty() {
1833                self.partial_bytes_acked -= self.cwnd;
1834                self.cwnd += self.mtu;
1835                trace!(
1836                    "[{}] updated cwnd={} ssthresh={} acked={} (CA)",
1837                    self.side, self.cwnd, self.ssthresh, total_bytes_acked
1838                );
1839            }
1840        }
1841    }
1842
1843    fn process_fast_retransmission(
1844        &mut self,
1845        cum_tsn_ack_point: u32,
1846        htna: u32,
1847        cum_tsn_ack_point_advanced: bool,
1848    ) -> Result<()> {
1849        // HTNA algorithm - RFC 4960 Sec 7.2.4
1850        // Increment missIndicator of each chunks that the SACK reported missing
1851        // when either of the following is met:
1852        // a)  Not in fast-recovery
1853        //     miss indications are incremented only for missing TSNs prior to the
1854        //     highest TSN newly acknowledged in the SACK.
1855        // b)  In fast-recovery AND the Cumulative TSN Ack Point advanced
1856        //     the miss indications are incremented for all TSNs reported missing
1857        //     in the SACK.
1858        if !self.in_fast_recovery || cum_tsn_ack_point_advanced {
1859            let max_tsn = if !self.in_fast_recovery {
1860                // a) increment only for missing TSNs prior to the HTNA
1861                htna
1862            } else {
1863                // b) increment for all TSNs reported missing
1864                cum_tsn_ack_point + (self.inflight_queue.len() as u32) + 1
1865            };
1866
1867            let mut tsn = cum_tsn_ack_point + 1;
1868            while sna32lt(tsn, max_tsn) {
1869                if let Some(c) = self.inflight_queue.get_mut(tsn) {
1870                    if !c.acked && !c.abandoned() && c.miss_indicator < 3 {
1871                        c.miss_indicator += 1;
1872                        if c.miss_indicator == 3 && !self.in_fast_recovery {
1873                            // 2)  If not in Fast Recovery, adjust the ssthresh and cwnd of the
1874                            //     destination address(es) to which the missing DATA chunks were
1875                            //     last sent, according to the formula described in Section 7.2.3.
1876                            self.in_fast_recovery = true;
1877                            self.fast_recover_exit_point = htna;
1878                            self.ssthresh = std::cmp::max(self.cwnd / 2, 4 * self.mtu);
1879                            self.cwnd = self.ssthresh;
1880                            self.partial_bytes_acked = 0;
1881                            self.will_retransmit_fast = true;
1882
1883                            trace!(
1884                                "[{}] updated cwnd={} ssthresh={} inflight={} (FR)",
1885                                self.side,
1886                                self.cwnd,
1887                                self.ssthresh,
1888                                self.inflight_queue.get_num_bytes()
1889                            );
1890                        }
1891                    }
1892                } else {
1893                    return Err(Error::ErrTsnRequestNotExist);
1894                }
1895
1896                tsn += 1;
1897            }
1898        }
1899
1900        if self.in_fast_recovery && cum_tsn_ack_point_advanced {
1901            self.will_retransmit_fast = true;
1902        }
1903
1904        Ok(())
1905    }
1906
1907    /// The caller must hold the lock. This method was only added because the
1908    /// linter was complaining about the "cognitive complexity" of handle_sack.
1909    fn postprocess_sack(
1910        &mut self,
1911        state: AssociationState,
1912        mut should_awake_write_loop: bool,
1913        now: Instant,
1914    ) {
1915        if !self.inflight_queue.is_empty() {
1916            // Start timer. (noop if already started)
1917            trace!("[{}] T3-rtx timer start (pt3)", self.side);
1918            self.timers
1919                .restart_if_stale(Timer::T3RTX, now, self.rto_mgr.get_rto());
1920        } else if state == AssociationState::ShutdownPending {
1921            // No more outstanding, send shutdown.
1922            should_awake_write_loop = true;
1923            self.will_send_shutdown = true;
1924            self.set_state(AssociationState::ShutdownSent);
1925        } else if state == AssociationState::ShutdownReceived {
1926            // No more outstanding, send shutdown ack.
1927            should_awake_write_loop = true;
1928            self.will_send_shutdown_ack = true;
1929            self.set_state(AssociationState::ShutdownAckSent);
1930        }
1931
1932        if should_awake_write_loop {
1933            self.awake_write_loop();
1934        }
1935    }
1936
1937    fn reset_streams_if_any(
1938        &mut self,
1939        p: &ParamOutgoingResetRequest,
1940        respond: bool,
1941        reply: &mut Vec<Packet>,
1942    ) -> Result<()> {
1943        let mut result = ReconfigResult::SuccessPerformed;
1944        let mut sis_to_reset = vec![];
1945
1946        if sna32lte(p.sender_last_tsn, self.peer_last_tsn) {
1947            debug!(
1948                "[{}] resetStream(): senderLastTSN={} <= peer_last_tsn={}",
1949                self.side, p.sender_last_tsn, self.peer_last_tsn
1950            );
1951            for id in &p.stream_identifiers {
1952                if self.streams.contains_key(id) {
1953                    if respond {
1954                        sis_to_reset.push(*id);
1955                    }
1956                    self.unregister_stream(*id, AssociationError::Reset);
1957                }
1958            }
1959            self.reconfig_requests
1960                .remove(&p.reconfig_request_sequence_number);
1961        } else {
1962            debug!(
1963                "[{}] resetStream(): senderLastTSN={} > peer_last_tsn={}",
1964                self.side, p.sender_last_tsn, self.peer_last_tsn
1965            );
1966            result = ReconfigResult::InProgress;
1967        }
1968
1969        // Answer incoming reset requests with the same reset request, but with
1970        // reconfig_response_sequence_number.
1971        if !sis_to_reset.is_empty() {
1972            let rsn = self.generate_next_rsn();
1973            let tsn = self.my_next_tsn - 1;
1974
1975            let c = ChunkReconfig {
1976                param_a: Some(Box::new(ParamOutgoingResetRequest {
1977                    reconfig_request_sequence_number: rsn,
1978                    reconfig_response_sequence_number: p.reconfig_request_sequence_number,
1979                    sender_last_tsn: tsn,
1980                    stream_identifiers: sis_to_reset,
1981                })),
1982                ..Default::default()
1983            };
1984
1985            self.reconfigs.insert(rsn, c.clone()); // store in the map for retransmission
1986
1987            let p = self.create_packet(vec![Box::new(c)]);
1988            reply.push(p);
1989        }
1990
1991        let packet = self.create_packet(vec![Box::new(ChunkReconfig {
1992            param_a: Some(Box::new(ParamReconfigResponse {
1993                reconfig_response_sequence_number: p.reconfig_request_sequence_number,
1994                result,
1995            })),
1996            param_b: None,
1997        })]);
1998
1999        debug!("[{}] RESET RESPONSE: {}", self.side, packet);
2000
2001        reply.push(packet);
2002
2003        Ok(())
2004    }
2005
2006    /// create_packet wraps chunks in a packet.
2007    /// The caller should hold the read lock.
2008    pub(crate) fn create_packet(&self, chunks: Vec<Box<dyn Chunk>>) -> Packet {
2009        Packet {
2010            common_header: CommonHeader {
2011                verification_tag: self.peer_verification_tag,
2012                source_port: self.source_port,
2013                destination_port: self.destination_port,
2014            },
2015            chunks,
2016        }
2017    }
2018
2019    /// Marshal a single control chunk into one SCTP packet, bypassing the
2020    /// `Vec<Box<dyn Chunk>>` + `Packet` allocations of `create_packet(..).marshal()`.
2021    /// Feeds the borrowed chunk straight to the shared framing path
2022    /// ([`Packet::write_framed`]). Used on the hot SACK / FORWARD-TSN send path
2023    /// (a SACK is emitted roughly every 1-2 inbound DATA chunks). The caller holds
2024    /// the lock.
2025    fn marshal_control_chunk(&self, chunk: &dyn Chunk) -> Result<Bytes> {
2026        let common_header = CommonHeader {
2027            verification_tag: self.peer_verification_tag,
2028            source_port: self.source_port,
2029            destination_port: self.destination_port,
2030        };
2031        // common header + chunk header + value + up to 3 bytes of trailing padding.
2032        let mut buf = BytesMut::with_capacity(
2033            COMMON_HEADER_SIZE as usize + CHUNK_HEADER_SIZE + chunk.value_length() + 3,
2034        );
2035        Packet::write_framed(&common_header, std::iter::once(chunk), &mut buf)?;
2036        Ok(buf.freeze())
2037    }
2038
2039    /// create_stream creates a stream. The caller should hold the lock and check no stream exists for this id.
2040    fn create_stream(
2041        &mut self,
2042        stream_identifier: StreamId,
2043        accept: bool,
2044        default_payload_type: PayloadProtocolIdentifier,
2045    ) -> Option<Stream<'_>> {
2046        let s = StreamState::new(
2047            self.side,
2048            stream_identifier,
2049            self.max_payload_size,
2050            default_payload_type,
2051        );
2052
2053        if accept {
2054            self.stream_queue.push_back(stream_identifier);
2055            self.events.push_back(Event::Stream(StreamEvent::Opened {
2056                id: stream_identifier,
2057            }));
2058        }
2059
2060        self.streams.insert(stream_identifier, s);
2061
2062        Some(Stream {
2063            stream_identifier,
2064            association: self,
2065        })
2066    }
2067
2068    /// get_or_create_stream gets or creates a stream. The caller should hold the lock.
2069    fn get_or_create_stream(&mut self, stream_identifier: StreamId) -> Option<Stream<'_>> {
2070        if self.streams.contains_key(&stream_identifier) {
2071            Some(Stream {
2072                stream_identifier,
2073                association: self,
2074            })
2075        } else {
2076            self.create_stream(
2077                stream_identifier,
2078                true,
2079                PayloadProtocolIdentifier::default(),
2080            )
2081        }
2082    }
2083
2084    pub(crate) fn get_my_receiver_window_credit(&self) -> u32 {
2085        let mut bytes_queued = 0;
2086        for s in self.streams.values() {
2087            bytes_queued += s.get_num_bytes_in_reassembly_queue() as u32;
2088        }
2089
2090        self.max_receive_buffer_size.saturating_sub(bytes_queued)
2091    }
2092
2093    /// gather_outbound gathers outgoing packets. The returned bool value set to
2094    /// false means the association should be closed down after the final send.
2095    fn gather_outbound(&mut self, now: Instant) -> (Vec<Bytes>, bool) {
2096        let mut raw_packets = vec![];
2097
2098        if !self.control_queue.is_empty() {
2099            for p in self.control_queue.drain(..) {
2100                if let Ok(raw) = p.marshal() {
2101                    raw_packets.push(raw);
2102                } else {
2103                    warn!("[{}] failed to serialize a control packet", self.side);
2104                    continue;
2105                }
2106            }
2107        }
2108
2109        let state = self.state();
2110        match state {
2111            AssociationState::Established => {
2112                raw_packets = self.gather_data_packets_to_retransmit(raw_packets, now);
2113                raw_packets = self.gather_outbound_data_and_reconfig_packets(raw_packets, now);
2114                raw_packets = self.gather_outbound_fast_retransmission_packets(raw_packets, now);
2115                raw_packets = self.gather_outbound_sack_packets(raw_packets);
2116                raw_packets = self.gather_outbound_forward_tsn_packets(raw_packets);
2117                (raw_packets, true)
2118            }
2119            AssociationState::ShutdownPending
2120            | AssociationState::ShutdownSent
2121            | AssociationState::ShutdownReceived => {
2122                raw_packets = self.gather_data_packets_to_retransmit(raw_packets, now);
2123                raw_packets = self.gather_outbound_fast_retransmission_packets(raw_packets, now);
2124                raw_packets = self.gather_outbound_sack_packets(raw_packets);
2125                self.gather_outbound_shutdown_packets(raw_packets, now)
2126            }
2127            AssociationState::ShutdownAckSent => {
2128                self.gather_outbound_shutdown_packets(raw_packets, now)
2129            }
2130            _ => (raw_packets, true),
2131        }
2132    }
2133
2134    fn gather_data_packets_to_retransmit(
2135        &mut self,
2136        mut raw_packets: Vec<Bytes>,
2137        now: Instant,
2138    ) -> Vec<Bytes> {
2139        // Nothing is ever flagged for T3-rtx in the steady state, so skip the
2140        // full in-flight scan unless the T3-rtx timer has actually marked chunks.
2141        if self.t3_retransmit_pending {
2142            self.get_data_packets_to_retransmit(now, &mut raw_packets);
2143        }
2144        raw_packets
2145    }
2146
2147    fn gather_outbound_data_and_reconfig_packets(
2148        &mut self,
2149        mut raw_packets: Vec<Bytes>,
2150        now: Instant,
2151    ) -> Vec<Bytes> {
2152        // Pop unsent data chunks from the pending queue to send as much as
2153        // cwnd and rwnd allow.
2154        let (chunks, sis_to_reset) = self.pop_pending_data_chunks_to_send(now);
2155        if !chunks.is_empty() {
2156            // Start timer. (noop if already started)
2157            trace!("[{}] T3-rtx timer start (pt1)", self.side);
2158            self.timers
2159                .restart_if_stale(Timer::T3RTX, now, self.rto_mgr.get_rto());
2160
2161            self.bundle_data_chunks_into_packets(chunks, &mut raw_packets);
2162        }
2163
2164        if !sis_to_reset.is_empty() || self.will_retransmit_reconfig {
2165            if self.will_retransmit_reconfig {
2166                self.will_retransmit_reconfig = false;
2167                debug!(
2168                    "[{}] retransmit {} RECONFIG chunk(s)",
2169                    self.side,
2170                    self.reconfigs.len()
2171                );
2172                for c in self.reconfigs.values() {
2173                    let p = self.create_packet(vec![Box::new(c.clone())]);
2174                    if let Ok(raw) = p.marshal() {
2175                        raw_packets.push(raw);
2176                    } else {
2177                        warn!(
2178                            "[{}] failed to serialize a RECONFIG packet to be retransmitted",
2179                            self.side,
2180                        );
2181                    }
2182                }
2183            }
2184
2185            if !sis_to_reset.is_empty() {
2186                let rsn = self.generate_next_rsn();
2187                let tsn = self.my_next_tsn - 1;
2188                debug!(
2189                    "[{}] sending RECONFIG: rsn={} tsn={} streams={:?}",
2190                    self.side,
2191                    rsn,
2192                    self.my_next_tsn - 1,
2193                    sis_to_reset
2194                );
2195
2196                let c = ChunkReconfig {
2197                    param_a: Some(Box::new(ParamOutgoingResetRequest {
2198                        reconfig_request_sequence_number: rsn,
2199                        sender_last_tsn: tsn,
2200                        stream_identifiers: sis_to_reset,
2201                        ..Default::default()
2202                    })),
2203                    ..Default::default()
2204                };
2205                self.reconfigs.insert(rsn, c.clone()); // store in the map for retransmission
2206
2207                let p = self.create_packet(vec![Box::new(c)]);
2208                if let Ok(raw) = p.marshal() {
2209                    raw_packets.push(raw);
2210                } else {
2211                    warn!(
2212                        "[{}] failed to serialize a RECONFIG packet to be transmitted",
2213                        self.side
2214                    );
2215                }
2216            }
2217
2218            if !self.reconfigs.is_empty() {
2219                self.timers
2220                    .start(Timer::Reconfig, now, self.rto_mgr.get_rto());
2221            }
2222        }
2223
2224        raw_packets
2225    }
2226
2227    fn gather_outbound_fast_retransmission_packets(
2228        &mut self,
2229        mut raw_packets: Vec<Bytes>,
2230        now: Instant,
2231    ) -> Vec<Bytes> {
2232        if self.will_retransmit_fast {
2233            self.will_retransmit_fast = false;
2234
2235            let mut to_fast_retrans: Vec<Box<dyn Chunk>> = vec![];
2236            let mut fast_retrans_size = COMMON_HEADER_SIZE;
2237
2238            let mut i = 0;
2239            loop {
2240                let tsn = self.cumulative_tsn_ack_point + i + 1;
2241                if let Some(c) = self.inflight_queue.get_mut(tsn) {
2242                    if c.acked || c.abandoned() || c.nsent > 1 || c.miss_indicator < 3 {
2243                        i += 1;
2244                        continue;
2245                    }
2246
2247                    // RFC 4960 Sec 7.2.4 Fast Retransmit on Gap Reports
2248                    //  3)  Determine how many of the earliest (i.e., lowest TSN) DATA chunks
2249                    //      marked for retransmission will fit into a single packet, subject
2250                    //      to constraint of the path MTU of the destination transport
2251                    //      address to which the packet is being sent.  Call this value K.
2252                    //      Retransmit those K DATA chunks in a single packet.  When a Fast
2253                    //      Retransmit is being performed, the sender SHOULD ignore the value
2254                    //      of cwnd and SHOULD NOT delay retransmission for this single
2255                    //		packet.
2256
2257                    let data_chunk_size = DATA_CHUNK_HEADER_SIZE + c.user_data.len() as u32;
2258                    if self.mtu < fast_retrans_size + data_chunk_size {
2259                        break;
2260                    }
2261
2262                    fast_retrans_size += data_chunk_size;
2263                    self.stats.inc_fast_retrans();
2264                    c.nsent += 1;
2265                } else {
2266                    break; // end of pending data
2267                }
2268
2269                if let Some(c) = self.inflight_queue.get_mut(tsn) {
2270                    Association::check_partial_reliability_status(
2271                        c,
2272                        now,
2273                        self.use_forward_tsn,
2274                        self.side,
2275                        &self.streams,
2276                    );
2277                    to_fast_retrans.push(Box::new(c.clone()));
2278                    trace!(
2279                        "[{}] fast-retransmit: tsn={} sent={} htna={}",
2280                        self.side, c.tsn, c.nsent, self.fast_recover_exit_point
2281                    );
2282                }
2283                i += 1;
2284            }
2285
2286            if !to_fast_retrans.is_empty() {
2287                if let Ok(raw) = self.create_packet(to_fast_retrans).marshal() {
2288                    raw_packets.push(raw);
2289                } else {
2290                    warn!(
2291                        "[{}] failed to serialize a DATA packet to be fast-retransmitted",
2292                        self.side
2293                    );
2294                }
2295            }
2296        }
2297
2298        raw_packets
2299    }
2300
2301    fn gather_outbound_sack_packets(&mut self, mut raw_packets: Vec<Bytes>) -> Vec<Bytes> {
2302        if self.ack_state == AckState::Immediate {
2303            self.ack_state = AckState::Idle;
2304            let sack = self.create_selective_ack_chunk();
2305            debug!("[{}] sending SACK: {}", self.side, sack);
2306            if let Ok(raw) = self.marshal_control_chunk(&sack) {
2307                raw_packets.push(raw);
2308            } else {
2309                warn!("[{}] failed to serialize a SACK packet", self.side);
2310            }
2311        }
2312
2313        raw_packets
2314    }
2315
2316    fn gather_outbound_forward_tsn_packets(&mut self, mut raw_packets: Vec<Bytes>) -> Vec<Bytes> {
2317        /*log::debug!(
2318            "[{}] gatherOutboundForwardTSNPackets {}",
2319            self.name,
2320            self.will_send_forward_tsn
2321        );*/
2322        if self.will_send_forward_tsn {
2323            self.will_send_forward_tsn = false;
2324            if sna32gt(
2325                self.advanced_peer_tsn_ack_point,
2326                self.cumulative_tsn_ack_point,
2327            ) {
2328                let fwd_tsn = self.create_forward_tsn();
2329                if let Ok(raw) = self.marshal_control_chunk(&fwd_tsn) {
2330                    raw_packets.push(raw);
2331                } else {
2332                    warn!("[{}] failed to serialize a Forward TSN packet", self.side);
2333                }
2334            }
2335        }
2336
2337        raw_packets
2338    }
2339
2340    fn gather_outbound_shutdown_packets(
2341        &mut self,
2342        mut raw_packets: Vec<Bytes>,
2343        now: Instant,
2344    ) -> (Vec<Bytes>, bool) {
2345        let mut ok = true;
2346
2347        if self.will_send_shutdown {
2348            self.will_send_shutdown = false;
2349
2350            let shutdown = ChunkShutdown {
2351                cumulative_tsn_ack: self.cumulative_tsn_ack_point,
2352            };
2353
2354            if let Ok(raw) = self.create_packet(vec![Box::new(shutdown)]).marshal() {
2355                self.timers
2356                    .start(Timer::T2Shutdown, now, self.rto_mgr.get_rto());
2357                raw_packets.push(raw);
2358            } else {
2359                warn!("[{}] failed to serialize a Shutdown packet", self.side);
2360            }
2361        } else if self.will_send_shutdown_ack {
2362            self.will_send_shutdown_ack = false;
2363
2364            let shutdown_ack = ChunkShutdownAck {};
2365
2366            if let Ok(raw) = self.create_packet(vec![Box::new(shutdown_ack)]).marshal() {
2367                self.timers
2368                    .start(Timer::T2Shutdown, now, self.rto_mgr.get_rto());
2369                raw_packets.push(raw);
2370            } else {
2371                warn!("[{}] failed to serialize a ShutdownAck packet", self.side);
2372            }
2373        } else if self.will_send_shutdown_complete {
2374            self.will_send_shutdown_complete = false;
2375
2376            let shutdown_complete = ChunkShutdownComplete {};
2377
2378            if let Ok(raw) = self
2379                .create_packet(vec![Box::new(shutdown_complete)])
2380                .marshal()
2381            {
2382                raw_packets.push(raw);
2383                ok = false;
2384            } else {
2385                warn!(
2386                    "[{}] failed to serialize a ShutdownComplete packet",
2387                    self.side
2388                );
2389            }
2390        }
2391
2392        (raw_packets, ok)
2393    }
2394
2395    /// get_data_packets_to_retransmit is called when T3-rtx is timed out and retransmit outstanding data chunks
2396    /// that are not acked or abandoned yet.
2397    fn get_data_packets_to_retransmit(&mut self, now: Instant, raw_packets: &mut Vec<Bytes>) {
2398        let awnd = std::cmp::min(self.cwnd, self.rwnd);
2399        let mut chunks = vec![];
2400        let mut bytes_to_send = 0;
2401        let mut done = false;
2402        let mut i = 0;
2403        // Assume we will re-send every flagged chunk; flip back on if we stop
2404        // early (a marked chunk that doesn't fit awnd, or a zero-window probe)
2405        // so the next gather_outbound still scans.
2406        let mut chunks_remaining = false;
2407        while !done {
2408            let tsn = self.cumulative_tsn_ack_point + i + 1;
2409            if let Some(c) = self.inflight_queue.get_mut(tsn) {
2410                if !c.retransmit {
2411                    i += 1;
2412                    continue;
2413                }
2414
2415                if i == 0 && self.rwnd < c.user_data.len() as u32 {
2416                    // Send it as a zero window probe
2417                    done = true;
2418                    chunks_remaining = true;
2419                } else if bytes_to_send + c.user_data.len() > awnd as usize {
2420                    chunks_remaining = true;
2421                    break;
2422                }
2423
2424                // reset the retransmit flag not to retransmit again before the next
2425                // t3-rtx timer fires
2426                c.retransmit = false;
2427                bytes_to_send += c.user_data.len();
2428
2429                c.nsent += 1;
2430            } else {
2431                break; // end of pending data
2432            }
2433
2434            if let Some(c) = self.inflight_queue.get_mut(tsn) {
2435                Association::check_partial_reliability_status(
2436                    c,
2437                    now,
2438                    self.use_forward_tsn,
2439                    self.side,
2440                    &self.streams,
2441                );
2442
2443                trace!(
2444                    "[{}] retransmitting tsn={} ssn={} sent={}",
2445                    self.side, c.tsn, c.stream_sequence_number, c.nsent
2446                );
2447
2448                chunks.push(c.clone());
2449            }
2450            i += 1;
2451        }
2452
2453        // Cleared once the whole in-flight window has been rescanned with nothing
2454        // left flagged; kept set while awnd/zero-window left chunks behind.
2455        self.t3_retransmit_pending = chunks_remaining;
2456
2457        self.bundle_data_chunks_into_packets(chunks, raw_packets);
2458    }
2459
2460    /// pop_pending_data_chunks_to_send pops chunks from the pending queues as many as
2461    /// the cwnd and rwnd allows to send.
2462    fn pop_pending_data_chunks_to_send(
2463        &mut self,
2464        now: Instant,
2465    ) -> (Vec<ChunkPayloadData>, Vec<u16>) {
2466        let mut chunks = vec![];
2467        let mut sis_to_reset = vec![]; // stream identifiers to reset
2468        if !self.pending_queue.is_empty() {
2469            // RFC 4960 sec 6.1.  Transmission of DATA Chunks
2470            //   A) At any given time, the data sender MUST NOT transmit new data to
2471            //      any destination transport address if its peer's rwnd indicates
2472            //      that the peer has no buffer space (i.e., rwnd is 0; see Section
2473            //      6.2.1).  However, regardless of the value of rwnd (including if it
2474            //      is 0), the data sender can always have one DATA chunk in flight to
2475            //      the receiver if allowed by cwnd (see rule B, below).
2476
2477            while let Some(c) = self.pending_queue.peek() {
2478                let (beginning_fragment, unordered, data_len, stream_identifier) = (
2479                    c.beginning_fragment,
2480                    c.unordered,
2481                    c.user_data.len(),
2482                    c.stream_identifier,
2483                );
2484
2485                if data_len == 0 {
2486                    sis_to_reset.push(stream_identifier);
2487                    if self
2488                        .pending_queue
2489                        .pop(beginning_fragment, unordered)
2490                        .is_none()
2491                    {
2492                        error!("[{}] failed to pop from pending queue", self.side);
2493                    }
2494                    continue;
2495                }
2496
2497                if self.inflight_queue.get_num_bytes() + data_len > self.cwnd as usize {
2498                    break; // would exceeds cwnd
2499                }
2500
2501                if data_len > self.rwnd as usize {
2502                    break; // no more rwnd
2503                }
2504
2505                self.rwnd -= data_len as u32;
2506
2507                if let Some(chunk) = self.move_pending_data_chunk_to_inflight_queue(
2508                    beginning_fragment,
2509                    unordered,
2510                    now,
2511                ) {
2512                    chunks.push(chunk);
2513                }
2514            }
2515
2516            // the data sender can always have one DATA chunk in flight to the receiver
2517            if chunks.is_empty() && self.inflight_queue.is_empty() {
2518                // Send zero window probe
2519                if let Some(c) = self.pending_queue.peek() {
2520                    let (beginning_fragment, unordered) = (c.beginning_fragment, c.unordered);
2521
2522                    if let Some(chunk) = self.move_pending_data_chunk_to_inflight_queue(
2523                        beginning_fragment,
2524                        unordered,
2525                        now,
2526                    ) {
2527                        chunks.push(chunk);
2528                    }
2529                }
2530            }
2531        }
2532
2533        (chunks, sis_to_reset)
2534    }
2535
2536    /// bundle_data_chunks_into_packets packs DATA chunks into packets. It tries to bundle
2537    /// DATA chunks into a packet so long as the resulting packet size does not exceed
2538    /// the path MTU.
2539    fn bundle_data_chunks_into_packets(
2540        &self,
2541        chunks: Vec<ChunkPayloadData>,
2542        raw_packets: &mut Vec<Bytes>,
2543    ) {
2544        // RFC 4960 sec 6.1.  Transmission of DATA Chunks
2545        //   Multiple DATA chunks committed for transmission MAY be bundled in a
2546        //   single packet.  Furthermore, DATA chunks being retransmitted MAY be
2547        //   bundled with new DATA chunks, as long as the resulting packet size
2548        //   does not exceed the path MTU.
2549        //
2550        // Marshal each bundle straight into `raw_packets` from the borrowed
2551        // chunks: no intermediate `Vec<Packet>`, no `Box<dyn Chunk>` per chunk.
2552        // The chunks are already retained in the in-flight queue, so this send
2553        // copy is throwaway.
2554        if chunks.is_empty() {
2555            return;
2556        }
2557        let common_header = CommonHeader {
2558            verification_tag: self.peer_verification_tag,
2559            source_port: self.source_port,
2560            destination_port: self.destination_port,
2561        };
2562
2563        // First pass: split the chunks into MTU-bounded datagrams and total up
2564        // their marshalled (4-byte-padded) length. The whole burst is then
2565        // written into ONE buffer and `split_to` hands out each datagram as a
2566        // zero-copy `Bytes` view sharing that single allocation — one malloc per
2567        // burst instead of one per packet on the hot send path. The bundle
2568        // boundaries are computed once here and reused below, so the MTU-split
2569        // rule lives in exactly one place.
2570        let hdr = COMMON_HEADER_SIZE as usize;
2571        let mut bundles: Vec<(usize, usize)> = Vec::new();
2572        let mut total_len = 0usize;
2573        let mut bundle_start = 0;
2574        let mut bytes_in_packet = COMMON_HEADER_SIZE;
2575        let mut bundle_len = hdr;
2576        for (i, chunk) in chunks.iter().enumerate() {
2577            let data_len = chunk.user_data.len() as u32;
2578            // Close the current bundle before a chunk that would exceed the MTU.
2579            if bytes_in_packet + data_len > self.mtu && i > bundle_start {
2580                bundles.push((bundle_start, i));
2581                total_len += bundle_len;
2582                bundle_start = i;
2583                bytes_in_packet = COMMON_HEADER_SIZE;
2584                bundle_len = hdr;
2585            }
2586            bytes_in_packet += DATA_CHUNK_HEADER_SIZE + data_len;
2587            // Marshalled chunk size, padded up to the SCTP 4-byte boundary.
2588            let wire = (DATA_CHUNK_HEADER_SIZE + data_len) as usize;
2589            bundle_len += (wire + 3) & !3;
2590        }
2591        bundles.push((bundle_start, chunks.len()));
2592        total_len += bundle_len;
2593
2594        // Second pass: marshal each datagram into the shared buffer.
2595        let mut buf = BytesMut::with_capacity(total_len);
2596        for (start, end) in bundles {
2597            match Packet::write_framed(
2598                &common_header,
2599                chunks[start..end].iter().map(|c| c as &dyn Chunk),
2600                &mut buf,
2601            ) {
2602                Ok(_) => {
2603                    let plen = buf.len();
2604                    raw_packets.push(buf.split_to(plen).freeze());
2605                }
2606                Err(_) => {
2607                    warn!("[{}] failed to serialize a DATA packet", self.side);
2608                    buf.clear();
2609                }
2610            }
2611        }
2612    }
2613
2614    /// generate_next_tsn returns the my_next_tsn and increases it. The caller should hold the lock.
2615    fn generate_next_tsn(&mut self) -> u32 {
2616        let tsn = self.my_next_tsn;
2617        self.my_next_tsn += 1;
2618        tsn
2619    }
2620
2621    /// generate_next_rsn returns the my_next_rsn and increases it. The caller should hold the lock.
2622    fn generate_next_rsn(&mut self) -> u32 {
2623        let rsn = self.my_next_rsn;
2624        self.my_next_rsn += 1;
2625        rsn
2626    }
2627
2628    fn check_partial_reliability_status(
2629        c: &mut ChunkPayloadData,
2630        now: Instant,
2631        use_forward_tsn: bool,
2632        side: Side,
2633        streams: &FxHashMap<u16, StreamState>,
2634    ) {
2635        if !use_forward_tsn {
2636            return;
2637        }
2638
2639        // draft-ietf-rtcweb-data-protocol-09.txt section 6
2640        //	6.  Procedures
2641        //		All Data Channel Establishment TransportProtocol messages MUST be sent using
2642        //		ordered delivery and reliable transmission.
2643        //
2644        if c.payload_type == PayloadProtocolIdentifier::Dcep {
2645            return;
2646        }
2647
2648        // PR-SCTP
2649        if let Some(s) = streams.get(&c.stream_identifier) {
2650            let reliability_type: ReliabilityType = s.reliability_type;
2651            let reliability_value = s.reliability_value;
2652
2653            if reliability_type == ReliabilityType::Rexmit {
2654                if c.nsent >= reliability_value {
2655                    c.set_abandoned(true);
2656                    trace!(
2657                        "[{}] marked as abandoned: tsn={} ppi={} (remix: {})",
2658                        side, c.tsn, c.payload_type, c.nsent
2659                    );
2660                }
2661            } else if reliability_type == ReliabilityType::Timed {
2662                if let Some(since) = &c.since {
2663                    let elapsed = now.duration_since(*since);
2664                    if elapsed.as_millis() as u32 >= reliability_value {
2665                        c.set_abandoned(true);
2666                        trace!(
2667                            "[{}] marked as abandoned: tsn={} ppi={} (timed: {:?})",
2668                            side, c.tsn, c.payload_type, elapsed
2669                        );
2670                    }
2671                } else {
2672                    error!("[{}] invalid c.since", side);
2673                }
2674            }
2675        } else {
2676            error!("[{}] stream {} not found)", side, c.stream_identifier);
2677        }
2678    }
2679
2680    fn create_selective_ack_chunk(&mut self) -> ChunkSelectiveAck {
2681        ChunkSelectiveAck {
2682            cumulative_tsn_ack: self.peer_last_tsn,
2683            advertised_receiver_window_credit: self.get_my_receiver_window_credit(),
2684            gap_ack_blocks: self.payload_queue.get_gap_ack_blocks(self.peer_last_tsn),
2685            duplicate_tsn: self.payload_queue.pop_duplicates(),
2686        }
2687    }
2688
2689    /// Record an abandoned chunk into the forward-TSN stream map (RFC 3758 C4),
2690    /// called from the two C2 loops as `advanced_peer_tsn_ack_point` advances
2691    /// over each newly-abandoned in-flight chunk. Only *ordered* streams are
2692    /// tracked: the receiver ignores the per-stream SSN list for unordered
2693    /// chunks (it advances purely by `new_cumulative_tsn`). Keeps the greatest
2694    /// SSN seen per stream, which is the value RFC 3758 C4 requires to report.
2695    ///
2696    /// A stream's entry may briefly outlive the chunk that set it (until the
2697    /// window closes and the map is cleared), so a stale SSN can be re-reported;
2698    /// that is safe because the receiver only advances a stream forward and the
2699    /// SSN always corresponds to a really-abandoned chunk. The `u16` SSN compare
2700    /// (`sna16lt`) is sound because the window span is bounded by rwnd — a
2701    /// stream cannot lap the full 65536-sequence space before the window closes.
2702    fn note_abandoned_for_forward_tsn(&mut self, unordered: bool, si: u16, ssn: u16) {
2703        if unordered {
2704            return;
2705        }
2706        self.fwd_tsn_stream_map
2707            .entry(si)
2708            .and_modify(|cur| {
2709                if sna16lt(*cur, ssn) {
2710                    *cur = ssn;
2711                }
2712            })
2713            .or_insert(ssn);
2714    }
2715
2716    /// Test-only observer for the incremental forward-TSN stream map, so the
2717    /// endpoint tests can assert it is cleared once the forward-TSN window
2718    /// closes (the C1/C3 clear paths, which the unit tests can't reach).
2719    #[cfg(test)]
2720    pub(crate) fn fwd_tsn_stream_map_is_empty(&self) -> bool {
2721        self.fwd_tsn_stream_map.is_empty()
2722    }
2723
2724    /// create_forward_tsn generates ForwardTSN chunk.
2725    /// This method will be be called if use_forward_tsn is set to false.
2726    fn create_forward_tsn(&self) -> ChunkForwardTsn {
2727        // RFC 3758 Sec 3.5 C4: report, once per ordered stream, the greatest
2728        // stream-sequence-number among abandoned chunks in the forward-TSN
2729        // window. This is maintained incrementally in `fwd_tsn_stream_map` (see
2730        // its declaration and the two C2 loops that feed it), so we no longer
2731        // rescan `(cumulative_tsn_ack_point, advanced_peer_tsn_ack_point]` with
2732        // a per-TSN hashmap probe on every FORWARD-TSN — that scan was O(rwnd)
2733        // (~1000 probes/call for a 1 MB window) and dominated the send profile.
2734        let mut fwd_tsn = ChunkForwardTsn {
2735            new_cumulative_tsn: self.advanced_peer_tsn_ack_point,
2736            streams: Vec::with_capacity(self.fwd_tsn_stream_map.len()),
2737        };
2738        for (si, ssn) in &self.fwd_tsn_stream_map {
2739            fwd_tsn.streams.push(ChunkForwardTsnStream {
2740                identifier: *si,
2741                sequence: *ssn,
2742            });
2743        }
2744        // `trace!` evaluates its arguments lazily, so the stream list is only
2745        // formatted when trace logging is enabled -- no per-FORWARD-TSN string
2746        // allocation on the hot send path (this fires often for PR-SCTP data
2747        // channels, which is exactly where it was showing up in profiles).
2748        trace!(
2749            "[{}] building fwd_tsn: newCumulativeTSN={} cumTSN={} streams={:?}",
2750            self.side, fwd_tsn.new_cumulative_tsn, self.cumulative_tsn_ack_point, fwd_tsn.streams
2751        );
2752
2753        fwd_tsn
2754    }
2755
2756    /// Move the chunk peeked with self.pending_queue.peek() to the inflight_queue.
2757    fn move_pending_data_chunk_to_inflight_queue(
2758        &mut self,
2759        beginning_fragment: bool,
2760        unordered: bool,
2761        now: Instant,
2762    ) -> Option<ChunkPayloadData> {
2763        if let Some(mut c) = self.pending_queue.pop(beginning_fragment, unordered) {
2764            // Mark all fragements are in-flight now
2765            if c.ending_fragment {
2766                c.set_all_inflight();
2767            }
2768
2769            // Assign TSN
2770            c.tsn = self.generate_next_tsn();
2771
2772            c.since = Some(now); // use to calculate RTT and also for maxPacketLifeTime
2773            c.nsent = 1; // being sent for the first time
2774
2775            Association::check_partial_reliability_status(
2776                &mut c,
2777                now,
2778                self.use_forward_tsn,
2779                self.side,
2780                &self.streams,
2781            );
2782
2783            trace!(
2784                "[{}] sending ppi={} tsn={} ssn={} sent={} len={} ({},{})",
2785                self.side,
2786                c.payload_type as u32,
2787                c.tsn,
2788                c.stream_sequence_number,
2789                c.nsent,
2790                c.user_data.len(),
2791                c.beginning_fragment,
2792                c.ending_fragment
2793            );
2794
2795            self.inflight_queue.push_no_check(c.clone());
2796
2797            Some(c)
2798        } else {
2799            error!("[{}] failed to pop from pending queue", self.side);
2800            None
2801        }
2802    }
2803
2804    pub(crate) fn send_reset_request(&mut self, stream_identifier: StreamId) -> Result<()> {
2805        let state = self.state();
2806        if state != AssociationState::Established {
2807            return Err(Error::ErrResetPacketInStateNotExist);
2808        }
2809
2810        // Create DATA chunk which only contains valid stream identifier with
2811        // nil userData and use it as a EOS from the stream.
2812        let c = ChunkPayloadData {
2813            stream_identifier,
2814            beginning_fragment: true,
2815            ending_fragment: true,
2816            user_data: Bytes::new(),
2817            ..Default::default()
2818        };
2819
2820        self.pending_queue.push(c);
2821        self.awake_write_loop();
2822
2823        Ok(())
2824    }
2825
2826    /// send_payload_data sends the data chunks.
2827    pub(crate) fn send_payload_data(&mut self, chunks: Vec<ChunkPayloadData>) -> Result<()> {
2828        let state = self.state();
2829        if state != AssociationState::Established {
2830            return Err(Error::ErrPayloadDataStateNotExist);
2831        }
2832
2833        // Push the chunks into the pending queue first.
2834        for c in chunks {
2835            self.pending_queue.push(c);
2836        }
2837
2838        self.awake_write_loop();
2839        Ok(())
2840    }
2841
2842    /// buffered_amount returns total amount (in bytes) of currently buffered user data.
2843    /// This is used only by testing.
2844    pub(crate) fn buffered_amount(&self) -> usize {
2845        self.pending_queue.get_num_bytes() + self.inflight_queue.get_num_bytes()
2846    }
2847
2848    fn awake_write_loop(&self) {
2849        // No Op on Purpose
2850    }
2851
2852    fn close_all_timers(&mut self) {
2853        // Close all retransmission & ack timers
2854        for timer in Timer::VALUES {
2855            self.timers.stop(timer);
2856        }
2857    }
2858
2859    fn on_ack_timeout(&mut self) {
2860        trace!(
2861            "[{}] ack timed out (ack_state: {})",
2862            self.side, self.ack_state
2863        );
2864        self.stats.inc_ack_timeouts();
2865        self.ack_state = AckState::Immediate;
2866        self.awake_write_loop();
2867    }
2868
2869    fn on_retransmission_timeout(&mut self, timer_id: Timer, n_rtos: usize) {
2870        match timer_id {
2871            Timer::T1Init => {
2872                if let Err(err) = self.send_init() {
2873                    debug!(
2874                        "[{}] failed to retransmit init (n_rtos={}): {:?}",
2875                        self.side, n_rtos, err
2876                    );
2877                }
2878            }
2879
2880            Timer::T1Cookie => {
2881                if let Err(err) = self.send_cookie_echo() {
2882                    debug!(
2883                        "[{}] failed to retransmit cookie-echo (n_rtos={}): {:?}",
2884                        self.side, n_rtos, err
2885                    );
2886                }
2887            }
2888
2889            Timer::T2Shutdown => {
2890                debug!(
2891                    "[{}] retransmission of shutdown timeout (n_rtos={})",
2892                    self.side, n_rtos
2893                );
2894                let state = self.state();
2895                match state {
2896                    AssociationState::ShutdownSent => {
2897                        self.will_send_shutdown = true;
2898                        self.awake_write_loop();
2899                    }
2900                    AssociationState::ShutdownAckSent => {
2901                        self.will_send_shutdown_ack = true;
2902                        self.awake_write_loop();
2903                    }
2904                    _ => {}
2905                }
2906            }
2907
2908            Timer::T3RTX => {
2909                self.stats.inc_t3timeouts();
2910
2911                // RFC 4960 sec 6.3.3
2912                //  E1)  For the destination address for which the timer expires, adjust
2913                //       its ssthresh with rules defined in Section 7.2.3 and set the
2914                //       cwnd <- MTU.
2915                // RFC 4960 sec 7.2.3
2916                //   When the T3-rtx timer expires on an address, SCTP should perform slow
2917                //   start by:
2918                //      ssthresh = max(cwnd/2, 4*MTU)
2919                //      cwnd = 1*MTU
2920
2921                self.ssthresh = std::cmp::max(self.cwnd / 2, 4 * self.mtu);
2922                self.cwnd = self.mtu;
2923                trace!(
2924                    "[{}] updated cwnd={} ssthresh={} inflight={} (RTO)",
2925                    self.side,
2926                    self.cwnd,
2927                    self.ssthresh,
2928                    self.inflight_queue.get_num_bytes()
2929                );
2930
2931                // RFC 3758 sec 3.5
2932                //  A5) Any time the T3-rtx timer expires, on any destination, the sender
2933                //  SHOULD try to advance the "Advanced.Peer.Ack.Point" by following
2934                //  the procedures outlined in C2 - C5.
2935                if self.use_forward_tsn {
2936                    // RFC 3758 Sec 3.5 C2
2937                    let mut i = self.advanced_peer_tsn_ack_point + 1;
2938                    while let Some((abandoned, unordered, si, ssn)) =
2939                        self.inflight_queue.get(i).map(|c| {
2940                            (
2941                                c.abandoned(),
2942                                c.unordered,
2943                                c.stream_identifier,
2944                                c.stream_sequence_number,
2945                            )
2946                        })
2947                    {
2948                        if !abandoned {
2949                            break;
2950                        }
2951                        self.advanced_peer_tsn_ack_point = i;
2952                        self.note_abandoned_for_forward_tsn(unordered, si, ssn);
2953                        i += 1;
2954                    }
2955
2956                    // RFC 3758 Sec 3.5 C3
2957                    if sna32gt(
2958                        self.advanced_peer_tsn_ack_point,
2959                        self.cumulative_tsn_ack_point,
2960                    ) {
2961                        self.will_send_forward_tsn = true;
2962                        debug!(
2963                            "[{}] on_retransmission_timeout {}: sna32GT({}, {})",
2964                            self.side,
2965                            self.will_send_forward_tsn,
2966                            self.advanced_peer_tsn_ack_point,
2967                            self.cumulative_tsn_ack_point
2968                        );
2969                    }
2970                }
2971
2972                debug!(
2973                    "[{}] T3-rtx timed out: n_rtos={} cwnd={} ssthresh={}",
2974                    self.side, n_rtos, self.cwnd, self.ssthresh
2975                );
2976
2977                self.inflight_queue.mark_all_to_retrasmit();
2978                self.t3_retransmit_pending = true;
2979                self.awake_write_loop();
2980            }
2981
2982            Timer::Reconfig => {
2983                self.will_retransmit_reconfig = true;
2984                self.awake_write_loop();
2985            }
2986
2987            _ => {}
2988        }
2989    }
2990
2991    fn on_retransmission_failure(&mut self, id: Timer) {
2992        match id {
2993            Timer::T1Init => {
2994                error!("[{}] retransmission failure: T1-init", self.side);
2995                self.error = Some(AssociationError::HandshakeFailed(
2996                    Error::ErrHandshakeInitAck.to_string(),
2997                ));
2998            }
2999
3000            Timer::T1Cookie => {
3001                error!("[{}] retransmission failure: T1-cookie", self.side);
3002                self.error = Some(AssociationError::HandshakeFailed(
3003                    Error::ErrHandshakeCookieEcho.to_string(),
3004                ));
3005            }
3006
3007            Timer::T2Shutdown => {
3008                error!("[{}] retransmission failure: T2-shutdown", self.side);
3009            }
3010
3011            Timer::T3RTX => {
3012                // T3-rtx timer will not fail by design
3013                // Justifications:
3014                //  * ICE would fail if the connectivity is lost
3015                //  * WebRTC spec is not clear how this incident should be reported to ULP
3016                error!("[{}] retransmission failure: T3-rtx (DATA)", self.side);
3017            }
3018
3019            _ => {}
3020        }
3021    }
3022
3023    /// Whether no timers are running
3024    #[cfg(test)]
3025    pub(crate) fn is_idle(&self) -> bool {
3026        Timer::VALUES
3027            .iter()
3028            //.filter(|&&t| t != Timer::KeepAlive && t != Timer::PushNewCid)
3029            .filter_map(|&t| Some((t, self.timers.get(t)?)))
3030            .min_by_key(|&(_, time)| time)
3031            //.map_or(true, |(timer, _)| timer == Timer::Idle)
3032            .is_none()
3033    }
3034}