mirror of
https://github.com/vacp2p/specs.git
synced 2026-01-09 15:28:03 -05:00
webrtc: add FIN_ACK to close datachannels without data loss (#582)
Specify closing datachannels in a way that ensures all data has been received by the remote before closing. Fixes: #575 --------- Co-authored-by: Max Inden <mail@max-inden.de> Co-authored-by: Thomas Eizinger <thomas@eizinger.io>
This commit is contained in:
@@ -67,6 +67,10 @@ message Message {
|
|||||||
// The sender abruptly terminates the sending part of the stream. The
|
// The sender abruptly terminates the sending part of the stream. The
|
||||||
// receiver MAY discard any data that it already received on that stream.
|
// receiver MAY discard any data that it already received on that stream.
|
||||||
RESET_STREAM = 2;
|
RESET_STREAM = 2;
|
||||||
|
// Sending the FIN_ACK flag acknowledges the previous receipt of a message
|
||||||
|
// with the FIN flag set. Receiving a FIN_ACK flag gives the recipient
|
||||||
|
// confidence that the remote has received all sent messages.
|
||||||
|
FIN_ACK = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional Flag flag=1;
|
optional Flag flag=1;
|
||||||
@@ -132,8 +136,8 @@ real-world experiments.
|
|||||||
|
|
||||||
`RTCDataChannel`s are negotiated in-band by the WebRTC user agent (e.g. Firefox,
|
`RTCDataChannel`s are negotiated in-band by the WebRTC user agent (e.g. Firefox,
|
||||||
Pion, ...). In other words libp2p WebRTC implementations MUST NOT change the
|
Pion, ...). In other words libp2p WebRTC implementations MUST NOT change the
|
||||||
default value `negotiated: false` when creating a standard libp2p stream
|
default value `negotiated: false` when creating a standard libp2p stream
|
||||||
of type `RTCDataChannel` via `RTCPeerConnection.createDataChannel`.
|
of type `RTCDataChannel` via `RTCPeerConnection.createDataChannel`.
|
||||||
Setting `negotiated: true` is reserved only for creating Noise handshake channels
|
Setting `negotiated: true` is reserved only for creating Noise handshake channels
|
||||||
under certain protocol conditions.
|
under certain protocol conditions.
|
||||||
|
|
||||||
@@ -161,6 +165,54 @@ MUST pass an empty string. When receiving an `RTCDataChannel` via
|
|||||||
an empty string. This allows future versions of this specification to make use
|
an empty string. This allows future versions of this specification to make use
|
||||||
of the `RTCDataChannel` `label` property.
|
of the `RTCDataChannel` `label` property.
|
||||||
|
|
||||||
|
## Closing an `RTCDataChannel`
|
||||||
|
|
||||||
|
Some WebRTC implementations do not guarantee that any queued messages will be
|
||||||
|
sent after a datachannel is closed. Other implementations maintain separate
|
||||||
|
outgoing message and transport queues, the status of which may not be visible
|
||||||
|
to the user. Consequently we must add an additional layer of signaling to
|
||||||
|
ensure reliable data delivery.
|
||||||
|
|
||||||
|
When a node wishes to close a stream for writing, it MUST send a message with
|
||||||
|
the `FIN` flag set.
|
||||||
|
|
||||||
|
If a `FIN` flag is received the node SHOULD respond with a `FIN_ACK`.
|
||||||
|
|
||||||
|
A node SHOULD only consider its write-half closed once it has received a
|
||||||
|
`FIN_ACK`.
|
||||||
|
|
||||||
|
When a `FIN_ACK` and a `FIN` have been received, the node may close the
|
||||||
|
datachannel.
|
||||||
|
|
||||||
|
The node MAY close the datachannel without receiving a `FIN_ACK`, for example in
|
||||||
|
the case of a timeout, but there will be no guarantee that all previously sent
|
||||||
|
messages have been received by the remote.
|
||||||
|
|
||||||
|
If a node has previously sent a `STOP_SENDING` flag to the remote node, it MUST
|
||||||
|
continue to act on any flags present in received messages in order to
|
||||||
|
successfully process an incoming `FIN_ACK`.
|
||||||
|
|
||||||
|
### Example of closing an `RTCDataChannel`
|
||||||
|
|
||||||
|
NodeA closes for writing, NodeB delays allowing the channel to close until it
|
||||||
|
also finishes writing.
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
sequenceDiagram
|
||||||
|
A->>B: DATA
|
||||||
|
A->>B: FIN
|
||||||
|
B->>A: FIN_ACK
|
||||||
|
B->>A: DATA
|
||||||
|
B->>A: FIN
|
||||||
|
A->>B: FIN_ACK
|
||||||
|
```
|
||||||
|
|
||||||
|
After _A_ has received the `FIN` it is free to close the datachannel since it
|
||||||
|
has previously received a `FIN_ACK`. If _B_ receives the `FIN_ACK` before this
|
||||||
|
it may close the channel since it previously received a `FIN`.
|
||||||
|
|
||||||
|
This way the channel can be closed from either end without data loss.
|
||||||
|
|
||||||
## Previous, ongoing and related work
|
## Previous, ongoing and related work
|
||||||
|
|
||||||
- Completed implementations of this specification:
|
- Completed implementations of this specification:
|
||||||
|
|||||||
Reference in New Issue
Block a user