22#define MS_RTC_SCTP_SOCKET_HPP
33
44#include " common.hpp"
5- #include " RTC/Consts.hpp"
5+ #include " RTC/SCTP/association/NegotiatedCapabilities.hpp"
6+ #include " RTC/SCTP/association/SocketMetrics.hpp"
7+ #include " RTC/SCTP/association/SocketOptions.hpp"
68#include " RTC/SCTP/association/TransmissionControlBlock.hpp"
7- #include " RTC/SCTP/packet/parameters/ZeroChecksumAcceptableParameter.hpp"
9+ #include " RTC/SCTP/packet/Chunk.hpp"
10+ #include " RTC/SCTP/packet/Packet.hpp"
11+ #include " RTC/SCTP/packet/chunks/AbortAssociationChunk.hpp"
12+ #include " RTC/SCTP/packet/chunks/DataChunk.hpp"
13+ #include " RTC/SCTP/packet/chunks/HeartbeatRequestChunk.hpp"
14+ #include " RTC/SCTP/packet/chunks/InitAckChunk.hpp"
15+ #include " RTC/SCTP/packet/chunks/InitChunk.hpp"
16+ #include " RTC/SCTP/packet/chunks/OperationErrorChunk.hpp"
17+ #include " RTC/SCTP/packet/chunks/SackChunk.hpp"
18+ #include " RTC/SCTP/packet/chunks/ShutdownAckChunk.hpp"
19+ #include " RTC/SCTP/packet/chunks/ShutdownCompleteChunk.hpp"
20+ #include " RTC/SCTP/packet/chunks/UnknownChunk.hpp"
21+ #include " handles/BackoffTimerHandle.hpp"
22+ #include < string>
23+ #include < string_view>
824
925namespace RTC
1026{
@@ -16,82 +32,168 @@ namespace RTC
1632 *
1733 * It manages all Packet and Chunk dispatching and the connection flow.
1834 */
19- class Socket
35+ class Socket : public BackoffTimerHandle ::Listener
2036 {
2137 public:
22- struct SocketOptions
38+ class Listener
2339 {
24- /* *
25- * Signaled local port.
26- */
27- uint16_t localPort{ 0 };
28- /* *
29- * Signaled destination port.
30- */
31- uint16_t destinationPort{ 0 };
32- /* *
33- * Announced maximum number of outbound streams (OS).
34- * NOTE: We use maximum value by default.
35- */
36- uint16_t maxOutboundStreams{ 65535 };
37- /* *
38- * Announced maximum number of inbound streams (MIS).
39- * NOTE: We use maximum value by default.
40- */
41- uint16_t maxInboundStreams{ 65535 };
42- /* *
43- * Maximum received window buffer size. It must be larger than the
44- * largest sized message we want to be able to receive.
45- *
46- * @remarks
47- * Default value copied from dcSCTP library.
48- */
49- uint32_t myAdvertisedReceiverWindowCredit{ 5 * 1024 * 1024 };
50- /* *
51- * Use Partial Reliability Extension.
52- * @see RFC 3758.
53- */
54- bool partialReliability{ false };
55- /* *
56- * Use Stream Schedulers and User Message Interleaving (I-DATA Chunks).
57- * @see RFC 8260.
58- */
59- bool messageInterleaving{ false };
60- /* *
61- * Alternate error detection method for Zero Checksum.
62- *
63- * @remarks
64- * This feature is only enabled if both peers signal their wish to use
65- * the same (non-zero) Zero Checksum Alternate Error Detection Method.
66- *
67- * @see RFC 9653.
68- */
69- ZeroChecksumAcceptableParameter::AlternateErrorDetectionMethod zeroCheksumAlternateErrorDetectionMethod{
70- ZeroChecksumAcceptableParameter::AlternateErrorDetectionMethod::NONE
71- };
72- /* *
73- * Maximum size of a SCTP packet. It doesn't include any overhead of
74- * DTLS, TURN, UDP or IP headers.
75- */
76- size_t mtu{ RTC::Consts::MaxSafeMtuSizeForSctp };
40+ public:
41+ virtual ~Listener () = default ;
42+
43+ public:
44+ virtual void OnSocketSendSctpPacket (const Socket* socket, Packet* packet) const = 0;
45+ };
46+
47+ public:
48+ /* *
49+ * SCTP association state.
50+ */
51+ enum class State
52+ {
53+ CLOSED,
54+ COOKIE_WAIT,
55+ // NOTE: TCB is valid in these states:
56+ COOKIE_ECHOED,
57+ ESTABLISHED,
58+ SHUTDOWN_PENDING,
59+ SHUTDOWN_SENT,
60+ SHUTDOWN_RECEIVED,
61+ SHUTDOWN_ACK_SENT,
7762 };
7863
64+ /* *
65+ * Struct holding local verification tag and initial TSN between having
66+ * sent the INIT Chunk until the connection is established (there is no
67+ * TCB in between).
68+ *
69+ * @remarks
70+ * This is how dcSCTP does, despite RFC 9260 states that the TCB should
71+ * also be created when an INIT Chunk is sent.
72+ */
73+ struct PreTransmissionControlBlock
74+ {
75+ uint32_t localVerificationTag{ 0 };
76+ uint32_t localInitialTsn{ 0 };
77+ };
78+
79+ public:
80+ static constexpr std::string_view State2String (State state);
81+
7982 public:
80- explicit Socket (SocketOptions options);
83+ explicit Socket (SocketOptions options, Listener* listener );
8184
8285 ~Socket ();
8386
8487 void Dump (int indentation = 0 ) const ;
8588
89+ /* *
90+ * Initiate the SCTP association with the remote peer. It sends an INIT
91+ * Chunk.
92+ *
93+ * @remarks
94+ * The Socket must be in Closed state.
95+ */
96+ void Associate ();
97+
98+ /* *
99+ * Receive a Packet received from the peer.
100+ */
101+ void ReceivePacket (const Packet* receivedPacket);
102+
86103 private:
104+ void SetState (State state, const std::string& reason);
105+
106+ void AddCapabilitiesParametersToInitOrInitAckChunk (Chunk* chunk) const ;
107+
108+ void CreateTransmissionControlBlock (
109+ uint32_t localVerificationTag,
110+ uint32_t remoteVerificationTag,
111+ uint32_t localInitialTsn,
112+ uint32_t remoteInitialTsn,
113+ uint32_t localAdvertisedReceiverWindowCredit,
114+ uint64_t tieTag,
115+ const NegotiatedCapabilities& negotiatedCapabilities);
116+
117+ Packet* CreatePacket () const ;
118+
119+ Packet* CreatePacketWithVerificationTag (uint32_t verificationTag) const ;
120+
121+ /* *
122+ * Notify the parent about a Packet to be sent to the peer.
123+ *
124+ * This method also writes the Packet checksum field depending on the value
125+ * of `writeChecksum`. If it's explicitly set then it's honored. Otherwise
126+ * the checksum field is written based on whether Zero Checksum has been
127+ * negotiated or not.
128+ *
129+ * @remarks
130+ * This method does not delete the given `packet`. The caller must do it
131+ * after invoking this method.
132+ */
133+ void SendPacket (Packet* packet, std::optional<bool > writeChecksum = std::nullopt );
134+
87135 void SendInitChunk ();
88136
137+ void SendShutdownAckChunk ();
138+
139+ bool ValidateReceivedPacket (const Packet* receivedPacket);
140+
141+ bool ProcessReceivedChunk (const Packet* receivedPacket, const Chunk* receivedChunk);
142+
143+ void ProcessReceivedDataChunk (const Packet* receivedPacket, const DataChunk* receivedDataChunk);
144+
145+ void ProcessReceivedInitChunk (const Packet* receivedPacket, const InitChunk* receivedInitChunk);
146+
147+ void ProcessReceivedInitAckChunk (
148+ const Packet* receivedPacket, const InitAckChunk* receivedInitAckChunk);
149+
150+ void ProcessReceivedSackChunk (const Packet* receivedPacket, const SackChunk* receivedSackChunk);
151+
152+ void ProcessReceivedHeartbeatRequestChunk (
153+ const Packet* receivedPacket, const HeartbeatRequestChunk* receivedHeartbeatRequestChunk);
154+
155+ bool ProcessReceivedUnknownChunk (
156+ const Packet* receivedPacket, const UnknownChunk* receivedUnknownChunk);
157+
158+ void OnT1InitTimer (uint64_t & baseTimeout, bool & stop);
159+
160+ void OnT1CookieTimer (uint64_t & baseTimeout, bool & stop);
161+
162+ void OnT2ShutdownTimer (uint64_t & baseTimeout, bool & stop);
163+
164+ template <typename ... States>
165+ void AssertState (States... expectedStates) const ;
166+
167+ template <typename ... States>
168+ void AssertNotState (States... unexpectedStates) const ;
169+
170+ void AssertHasTcb () const ;
171+
172+ /* Pure virtual methods inherited from BackoffTimerHandle::Listener. */
173+ public:
174+ void OnTimer (BackoffTimerHandle* backoffTimer, uint64_t & baseTimeout, bool & stop) override ;
175+
89176 private:
90177 // Socket options given in th econstructor.
91- Socket::SocketOptions options;
178+ const SocketOptions options;
179+ // Listener.
180+ const Listener* listener{ nullptr };
181+ // SCTP association state.
182+ State state{ State::CLOSED };
183+ // Metrics.
184+ SocketMetrics metrics{};
185+ // To keep settings between sending of INIT Chunk and establishment of
186+ // the connection.
187+ PreTransmissionControlBlock preTcb;
92188 // Once the SCTP association is established a Transmission Control Block
93- // is created (and also when we are the initiator of the association) .
189+ // is created.
94190 std::unique_ptr<TransmissionControlBlock> tcb;
191+ // T1-init timer.
192+ const std::unique_ptr<BackoffTimerHandle> t1InitTimer;
193+ // T1-cookie timer.
194+ const std::unique_ptr<BackoffTimerHandle> t1CookieTimer;
195+ // T2-shutdown timer.
196+ const std::unique_ptr<BackoffTimerHandle> t2ShutdownTimer;
95197 };
96198 } // namespace SCTP
97199} // namespace RTC
0 commit comments