Commit graph

23 commits

Author SHA1 Message Date
Victor Boivie
6791c9d17e dcsctp: Relax thread sequence checker
The DcSctpSocket is thread compatible. As long as you serialize accesses
to it - either by calling it from the same thread, or using some kind of
concurrency primitive (e.g. mutex) to avoid calling the API methods from
different threads concurrently, it's fine.

Using the sequence checker, we can verify that the socket is called from
the thread it was created on, or from the same task queue. This provided
a more strict verification, as it didn't allow e.g. creating a socket on
one thread, and then handing it to a different thread where it was used.
Nor did it allow having multiple threads use it, protecting any calls to
it using an external mutex.

One can avoid these checks using webrtc::CurrentTaskQueueSetter to allow
the sequence checker to believe it's running where it's not running, but
this is a hack.

This CL removes the sequence checker in the socket, to simplify using it
in environments that don't use task queues for synchronization. Since it
is still kept in dcsctp::TaskQueueTimeoutFactory, it's still used in all
environments where the task queue is used (e.g. Chrome).

This makes it easier to use dcSCTP without WebRTC.

Bug: None
Change-Id: I2674d7cd902bad45ed3d0816c908ecf3ee971727
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/333801
Reviewed-by: Florent Castelli <orphis@webrtc.org>
Commit-Queue: Victor Boivie <boivie@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#41482}
2024-01-09 11:50:44 +00:00
Daniel Collins
c9d44b3fb9 Add SendMany method to dcsctp socket
Bug: webrtc:15724
Change-Id: Ib1689cd46395e2315803714ef50c009580fd71bb
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/331021
Reviewed-by: Victor Boivie <boivie@webrtc.org>
Commit-Queue: Victor Boivie <boivie@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#41397}
2023-12-15 21:35:14 +00:00
Victor Boivie
63e273ad4b dcsctp: Persist all state in state cookie
In the example below, the association is being established between peer
A and Z, and A is the initiating party.

Before this CL, when an association was about to be established, Z would
after having received the INIT chunk, persist state in the socket about
which verification tag and initial TSN that was picked. These would be
re-generated on every incoming INIT (that's fine), but when A had
extracted the cookie from INIT_ACK and sent a reply (COOKIE_ECHO) with
the state cookie, that could fail validation when it's received by Z, if
the sent cookie was not the most recent one or if the COOKIE_ECHO had a
verification tag coming not from the most recent INIT_ACK, because Z had
replaced the state in the socket with the one generated when the second
INIT_ACK chunk was generated - state it used for validation of future
received data.

In other words:
A -> INIT 1
<timeout>
A -> INIT 2 (retransmission of INIT 1)
INIT 1 -> Z - sends INIT_ACK 1 with verification_tag=1, initial_tsn=1,
              cookie 1 (and records these to socket state)
INIT 2 -> Z - sends INIT_ACK 2 with verification_tag=2, initial_tsn=2,
              cookie 2 (replaces socket state with the new data)
INIT_ACK 1 -> A -> sends COOKIE_ECHO with verification_tag=1, cookie 1
COOKIE_ECHO (cookie 1) -> Z <FAILS, as the state isn't as expected>.

The solution is really to do what RFC4960 says, to not maintain any
state as the receiving peer until COOKIE_ECHO has been received. This
was initially not done because the underlying reason why this is
important in SCTP is to avoid denial of service, and this is why SCTP
has the four-way handshake. But for Data Channels - SCTP over DTLS -
this attack vector isn't available. So the implementation was
"simplified" by keeping socket state instead of encoding it in the
state cookie, but that obviously had downsides.

So with this CL, the non-initiating peer in connection establishment
doesn't keep any socket state, and puts all that state in the state
cookie instead. This allows any COOKIE_ECHO to be received by Z.

Bug: webrtc:15712
Change-Id: I596c7330ce27292612d3c9f86b21c712f6f4e408
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/330440
Commit-Queue: Victor Boivie <boivie@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#41340}
2023-12-08 10:54:42 +00:00
Victor Boivie
4397482d71 dcsctp: Convert timers to rtc::TimeDelta
With this, the code base should be mostly converted from using
DurationMs to rtc::TimeDelta, and the work can continue to replace
TimeMs with rtc::Timestamp.

Bug: webrtc:15593
Change-Id: I083fee6eccb173efc0232bb8d46e2554a5fbee5b
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/326161
Reviewed-by: Florent Castelli <orphis@webrtc.org>
Commit-Queue: Victor Boivie <boivie@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#41101}
2023-11-07 21:42:15 +00:00
Victor Boivie
51b93a5417 dcsctp: Simplify interface for unchanged timeout
When a timer expires, it can optionally return a new expiration value.
Clearly, that value can't be zero, as that would make it expire
immediately again.

To simplify the interface, and make it easier to migrate to
rtc::TimeDelta, change it from an optional value to an always-present
value that - if zero - means that the expiration time should be
unchanged.

This is just an internal refactoring, and not part of any external
interface.

Bug: webrtc:15593
Change-Id: I6e7010d2dbe774ccb260e14fd6b9861c319e2411
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/325281
Commit-Queue: Victor Boivie <boivie@webrtc.org>
Reviewed-by: Florent Castelli <orphis@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#41045}
2023-10-31 09:44:39 +00:00
Victor Boivie
b847a43488 dcsctp: Reset synchronously with incoming request
When a sender has requested a stream to be reset, and the last sender
assigned TSN hasn't been received yet, the receiver will enter deferred
reset mode, where it will store any data chunks received after that
given TSN, and replay those later, when the stream has been reset.

Before this CL, leaving deferred mode was done as soon as the sender's
last assigned TSN was received. That's actually not how the RFC
describes the process[1], but was done that way to properly handle some
sequences of RE-CONFIG and FORWARD-TSN. But after having read the RFCs
again, and realizing that whenever RFC6525 mention "any data arriving",
this also applies to any FORWARD-TSN[2] - it's better to reset streams
synchronously with the incoming requests, and defer not just DATA past
the sender last assigned TSN, but also any FORWARD-TSN after that TSN.

This mostly simplifies the code and is mostly a refactoring, but most
importantly aligns it with how the resetting procedure is explained in
the RFC. It also fixes two bugs:

 * It defers FORWARD-TSN *as well as* DATA chunks with a TSN later
   than the sender's last assigned TSN - see test case. The old
   implementation tried to handle that by exiting the deferred reset
   processing as soon as it reached the sender's last assigned TSN, but
   it didn't manage to do that in all cases.
 * It only defers DATA chunks for streams that are to be reset, not
   all DATA chunks with a TSN > sender's last assigned TSN. This was
   missed in the old implementation, but as it's now implemented
   strictly according to the RFC, this was now done.

[1] https://datatracker.ietf.org/doc/html/rfc6525#section-5.2.2
[2] RFC6525 cover stream resetting, and RFC3758 cover FORWARD-TSN, and
    the combination of these is not covered in the RFCs.

Bug: webrtc:14600
Change-Id: Ief878b755291b9c923aa6fb4317b0f5c00231df4
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/322623
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Victor Boivie <boivie@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#40889}
2023-10-09 09:47:57 +00:00
Victor Boivie
06fbe63cbf dcsctp: Exit deferred stream reset on FORWARD-TSN
https://datatracker.ietf.org/doc/html/rfc6525#section-5.2.2:

E2:  If the Sender's Last Assigned TSN is greater than the cumulative
        acknowledgment point, then the endpoint MUST enter "deferred
        reset processing". ...  until the cumulative
        acknowledgment point reaches the Sender's Last Assigned TSN.

The cumulative acknowledgement point can not only be reached by
receiving DATA chunks, but also by receiving a FORWARD-TSN that
instructs the receiver to skip them. This was only done for DATA and not
for FORWARD-TSN, which is now corrected.

Additionally, an unnecessary implicit sending of SACK after having
received FORWARD-TSN was removed as this is done anyway every time a
packet has been received. This unifies the processing of DATA and
FORWARD-TSN more.

Bug: webrtc:14600
Change-Id: If797d3c46e741074fe05e322d0aebec765a87968
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/321400
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Victor Boivie <boivie@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#40811}
2023-09-26 07:30:24 +00:00
Victor Boivie
2cffde72b8 dcsctp: Restore from handover as separate methods
Before this CL, some components, e.g. the SendQueue, was first created
and then later restored from handover state, while some were created from
the handover state, as an optional parameter to their constructors.

This CL will make it consistent, by always creating the components in a
pristine state, and then modifying it when restoring them from handover
state. The name "RestoreFromState" was used to be consistent with SendQueue
and the socket.

This is just refactoring.

Bug: None
Change-Id: Ifad2d2e84a74a12a93abbfb0fe1027ebb9580e73
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/267006
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Victor Boivie <boivie@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#37384}
2022-06-30 22:09:04 +00:00
Victor Boivie
7e897aeb92 dcsctp: Add public API for setting priorities
This is a reland of commit 17a02a31d7.

This is the first part of supporting stream priorities, and adds the API
and very basic support for setting and retrieving the stream priority.

This commit doesn't in any way change the actual packet sending - the
specified priority values are stored, but not acted on.

This is all that is client visible, so clients can start using the API
as written, and they would never notice that things are missing.

Bug: webrtc:5696
Change-Id: I04d64a63cbaec67568496ad99667e14eba85f2e0
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/264424
Commit-Queue: Victor Boivie <boivie@webrtc.org>
Reviewed-by: Florent Castelli <orphis@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#37081}
2022-06-01 20:46:25 +00:00
Björn Terelius
51e5bacb8b Revert "dcsctp: Add public API for setting priorities"
This reverts commit 17a02a31d7.

Reason for revert: Breaks downstream test

Original change's description:
> dcsctp: Add public API for setting priorities
>
> This is the first part of supporting stream priorities, and adds the API
> and very basic support for setting and retrieving the stream priority.
>
> This commit doesn't in any way change the actual packet sending - the
> specified priority values are stored, but not acted on.
>
> This is all that is client visible, so clients can start using the API
> as written, and they would never notice that things are missing.
>
> Bug: webrtc:5696
> Change-Id: I24fce8cbb6f3cba187df99d1d3f45e73621c93c6
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/261943
> Reviewed-by: Harald Alvestrand <hta@webrtc.org>
> Commit-Queue: Victor Boivie <boivie@webrtc.org>
> Cr-Commit-Position: refs/heads/main@{#37034}

Bug: webrtc:5696
Change-Id: If172d9c9dbce7aae72152abbbae1ccc77340bbc1
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/264444
Owners-Override: Björn Terelius <terelius@webrtc.org>
Bot-Commit: rubber-stamper@appspot.gserviceaccount.com <rubber-stamper@appspot.gserviceaccount.com>
Commit-Queue: Björn Terelius <terelius@webrtc.org>
Auto-Submit: Björn Terelius <terelius@webrtc.org>
Reviewed-by: Victor Boivie <boivie@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#37039}
2022-05-30 14:12:34 +00:00
Victor Boivie
17a02a31d7 dcsctp: Add public API for setting priorities
This is the first part of supporting stream priorities, and adds the API
and very basic support for setting and retrieving the stream priority.

This commit doesn't in any way change the actual packet sending - the
specified priority values are stored, but not acted on.

This is all that is client visible, so clients can start using the API
as written, and they would never notice that things are missing.

Bug: webrtc:5696
Change-Id: I24fce8cbb6f3cba187df99d1d3f45e73621c93c6
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/261943
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Victor Boivie <boivie@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#37034}
2022-05-30 10:05:03 +00:00
Victor Boivie
f7fc71da44 dcsctp: Cleanup Metrics
This CL first restricts Metrics to be retrievable when the socket is
created. This avoids having most fields as optional and makes it
easier to add more metrics.

Secondly, the peer implementation is moved into Metrics.

Bug: webrtc:13052
Change-Id: I6cb53eeef3f84ac34f3efc883853338f903cc758
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/262256
Reviewed-by: Florent Castelli <orphis@webrtc.org>
Commit-Queue: Victor Boivie <boivie@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#36888}
2022-05-13 15:11:34 +00:00
Victor Boivie
f9e116f46e dcsctp: Continue reset pending streams
When resetting several streams in sequence, only the first stream will
be included in the first RE_CONFIG chunk as it's created eagerly
whenever someone calls ResetStreams. The remaining ones are queued as
pending. When the first request finishes, the remaining ones should
continue to be processed, but this wasn't done prior to this commit.

This would only happen if two streams would be reset with shorter time
between them than a RTT, so that there would be an outstanding request
forcing the second reset to be enqueued.

Bug: chromium:1312009
Change-Id: Id74b375d1d1720406a3bca4ec60df5780ca7edba
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/257306
Reviewed-by: Florent Castelli <orphis@webrtc.org>
Commit-Queue: Victor Boivie <boivie@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#36404}
2022-04-01 06:35:46 +00:00
Victor Boivie
5755f3edaf dcsctp: Add sequence checker to socket
The DcSctpSocket is not thread safe and must be called from a single
thread or from a task queue that serializes access to it. This is now
validated at run-time in debug builds.

Bug: None
Change-Id: I3ed816924c20f6ed7e84a3273bee5a3f8f74112b
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/233420
Reviewed-by: Florent Castelli <orphis@webrtc.org>
Commit-Queue: Victor Boivie <boivie@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#35127}
2021-09-30 11:25:18 +00:00
Victor Boivie
f4fa166cc5 dcsctp: Detect the peer SCTP implementation
It's to be used for clients to record metrics and to e.g. attribute
metrics to which SCTP implementation the peer was using.

This is not explicitly signaled, so heuristics are used. These are not
guaranteed to come to the correct conclusion, and the data is not always
available.

Note: The behavior of dcSCTP will not change depending on the assumed
implementation - only by explicitly signaled capabilities.

Bug: webrtc:13216
Change-Id: I2f58054d17d53d947ed5845df7a08f974d42f918
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/233100
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Victor Boivie <boivie@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#35103}
2021-09-28 05:10:45 +00:00
Sergey Sukhanov
4397281f38 dcsctp: implement socket handover in the DcSctpSocket class and expose the functionality in the API
Bug: webrtc:13154
Change-Id: Idf4f4028c8e65943cb6b41fab0baef1b3584205d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/232126
Reviewed-by: Victor Boivie <boivie@webrtc.org>
Commit-Queue: Sergey Sukhanov <sergeysu@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#35029}
2021-09-17 15:19:01 +00:00
Victor Boivie
abf6188cba dcsctp: Add PacketSender
This is mainly a refactoring commit, to break out packet sending to a
dedicated component.

Bug: webrtc:12943
Change-Id: I78f18933776518caf49737d3952bda97f19ef335
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/228565
Reviewed-by: Florent Castelli <orphis@webrtc.org>
Commit-Queue: Victor Boivie <boivie@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#34772}
2021-08-16 20:19:53 +00:00
Victor Boivie
d4716eaf60 dcsctp: Add metrics support
To support implementing RTCSctpTransportStats, a few metrics are needed.

Some more were added that are useful for metric collection in SFUs.

Bug: webrtc:13052
Change-Id: Idafd49e1084922d01d3e6c5860715f63aea08b7d
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/228243
Commit-Queue: Victor Boivie <boivie@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Florent Castelli <orphis@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#34708}
2021-08-10 20:01:46 +00:00
Victor Boivie
c20f1563b6 dcsctp: Don't sent more packets before COOKIE ACK
While in the COOKIE ECHO state, there is a TCB and there might be data
in the send buffer, and RFC4960 allows the COOKIE ECHO chunk to bundle
additional DATA chunks in the same packet, but there mustn't be more
than one such packet sent, and that packet must have a COOKIE ECHO chunk
as the first chunk in it.

When the COOKIE ACK chunk has been received, the socket is allowed to
send multiple packets.

Previously, this was state managed by the socket and not the TCB, as
the socket is responsible for moving between the different states. And
when the COOKIE ECHO chunk was sent, the TCB was instructed to only send
a single packet by the socket.

However, if there were retransmissions or anything else that could
result in calling TransmissionControlBlock::SendBufferedChunks, it would
do as instructed and send those, even if the socket was in a state where
that wasn't allowed.

When the peer was dcSCTP, this didn't cause any issues as dcSCTP tries
to be tolerant in what it receives (but strict in what it sends, except
for when there are bugs). When the peer was usrsctp, it would send an
ABORT for each received packet that didn't have a COOKIE ECHO as the
first chunk, and then restart the handshake (sending an INIT). So this
resulted in a longer handshake, but the connection would eventually be
correctly established and any DATA chunks that resulted in the ABORTs
would've been retransmitted.

By making the TCB aware of that particular state, and to make it
responsible for creating the SCTP packet with the COOKIE ECHO chunk
first, and also to only send a single packet when it is in that state,
there will not be any way to bypass this limitation.

Also, while not explicitly mentioned in the RFC, the retransmission
timer will not affect resending any outstanding DATA chunks that were
bundled together with the COOKIE ECHO chunk, as then there would be two
timers that both would drive resending COOKIE ECHO and DATA chunks.

Bug: webrtc:12880
Change-Id: I76f215a03cceab5bafe9f16eb4775f3dc68a6f05
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/222645
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Victor Boivie <boivie@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#34329}
2021-06-18 08:50:59 +00:00
Victor Boivie
236ac50628 dcsctp: Add public API for BufferedAmountLow
This adds native support for the RTCDataChannel properties:
https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel/bufferedAmount
https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel/bufferedAmountLowThreshold

And the RTCDataChannel event:
https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel/onbufferedamountlow

The old callback, NotifyOutgoingMessageBufferEmpty, is deprecated as it
didn't work very well. It will not be triggered and will be removed
as soon as all users of it are gone. There is a new callback,
OnTotalBufferedAmountLow, that serves the same purpose but also allows
setting an arbitrary limit when it should be triggered (See
DcSctpOptions::total_buffered_amount_low_threshold).

Bug: webrtc:12794
Change-Id: Ic1c92f174eff8a1acda0b5fd3dcc45bd1cfa2704
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/219691
Commit-Queue: Victor Boivie <boivie@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#34144}
2021-05-27 15:27:27 +00:00
Victor Boivie
2440d34075 dcsctp: Rename FCFSSendQueue to RRSendQueue
The current send queue implements SCTP_SS_FCFS as defined in
https://datatracker.ietf.org/doc/html/rfc8260#section-3.1, but that has
always been known to be a temporary solution. The end goal is to
implement a Weighted Fair Queueing Scheduler (SCTP_SS_WFQ), but that's
likely to take some time.

Meanwhile, a round robin scheduler (SCTP_SS_RR) will be used to avoid
some issues with the current scheduler, such as a single data channel
completely blocking all others if it sends a lot of messages.

In this first commit, the code has simply been renamed and is still
implementing first-come-first-served. That will be fixed in follow-up
CLS.

Bug: webrtc:12793
Change-Id: Idc03b1594551bfe1ddbe1710872814b9fdf60cc9
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/219684
Commit-Queue: Victor Boivie <boivie@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#34090}
2021-05-22 20:56:13 +00:00
Florent Castelli
0810b05104 dcsctp: Add SetMaxMessageSize() to socket
An SCTP transport for Data Channels allows changing the maximum
message size through SDP.
See https://w3c.github.io/webrtc-pc/#sctp-transport-update-mms

Bug: webrtc:12614
Change-Id: I8cff33c5f9c1d60934a726c546bc9cbdcd9e22d9
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/217387
Reviewed-by: Victor Boivie <boivie@webrtc.org>
Commit-Queue: Florent Castelli <orphis@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#33920}
2021-05-04 21:43:24 +00:00
Victor Boivie
b6580ccb29 dcsctp: Add Socket
This completes the basic implementation of the dcSCTP library. There
are a few remaining commits to e.g. add compatibility tests and
benchmarks, as well as more support for e.g. RFC8260, but those are not
strictly vital for evaluation of the library.

The Socket contains the connection establishment and teardown sequences
as well as the general chunk dispatcher.

Bug: webrtc:12614
Change-Id: I313b6c8f4accc144e3bb88ddba22269ebb8eb3cd
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/214342
Commit-Queue: Victor Boivie <boivie@webrtc.org>
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Reviewed-by: Tommi <tommi@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#33890}
2021-05-01 07:16:21 +00:00