Skip to content

webrtc/: Add message framing to support half-close and reset of stream#1

Merged
mxinden merged 12 commits into
webrtcfrom
webrtc-msg-framing
Sep 13, 2022
Merged

webrtc/: Add message framing to support half-close and reset of stream#1
mxinden merged 12 commits into
webrtcfrom
webrtc-msg-framing

Conversation

@mxinden

@mxinden mxinden commented Aug 18, 2022

Copy link
Copy Markdown
Owner

Note this pull request targets libp2p#412 and not the master branch.

The WebRTC browser APIs do not support half-closing nor resets of streams. This
commit defines a message framing schema to support this functionality on top of
the browser APIs.

This is a first proposal. This has not yet been implemented and will thus most likely change.

Input very much appreciated.

See libp2p#412 (comment) and libp2p#412 (comment) for past discussions on this topic.

The WebRTC browser APIs do not support half-closing nor resets of streams. This
commit defines a message framing schema to support this functionality on top of
the browser APIs.
@mxinden

mxinden commented Aug 19, 2022

Copy link
Copy Markdown
Owner Author

For those that want to play around with this, framing size test is here mxinden/rust-libp2p@59617de.

@mxinden

mxinden commented Aug 22, 2022

Copy link
Copy Markdown
Owner Author

I implemented this proposal on top of libp2p/rust-libp2p#2622. See https://github.com/mxinden/rust-libp2p/tree/webrtc-message-framing. (Happy path only.)

@mxinden

mxinden commented Aug 28, 2022

Copy link
Copy Markdown
Owner Author

JS implementation of this proposal libp2p/js-libp2p-webrtc#20 from @John-LittleBearLabs.

Comment thread webrtc/README.md Outdated
Comment thread webrtc/README.md Outdated
Comment thread webrtc/README.md Outdated
// The sender will no longer read messages.
CLOSE_READ = 1;
// The local endpoint abruptly terminates the stream. The remote endpoint
// may discard any in-flight data.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not mix this up with the read side of the stream. RESET only resets write side, NOT the read side.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works for me. Updated. See 865f4f2.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@John-LittleBearLabs note the above change in semantics. Please comment in case you have questions / concerns.

Comment thread webrtc/README.md Outdated
additional multiplexing.
Following [Connection Security](#connection-security).

The WebRTC browser APIs do not support half-closing nor resets of streams.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just so we're on the same page. when you're talking about reseting a stream, you're not talking about https://datatracker.ietf.org/doc/html/draft-ietf-rtcweb-data-channel-13#section-6.7 (webrtc signalling mechanism to tell remote that data channel was closed), right?

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The above description is misleading. Thanks for the note. I pushed a60234c updating the section.

WebRTC's reset as well as the corresponding RTCDataChannel.close() reset both sending and receiving. We would like to support the former without the latter.

All that said, in the end I don't see this mechanism as particularly useful. I expect readers to read messages from the stream in order, and not do any buffering to the application above. Thus a receiver would receive the RESET after having passed all previous messages to the application already. Thus acting just as if it received a FIN flag, i.e. closing its read side, but not discarding any messages.

I don't have a strong opinion on adding RESET. I guess it doesn't hurt and might enable future optimizations.

The above is not to be generalized to the entire proposal. While I don't see much value in the RESET flag, there is value in being able to half-close a stream via the FIN and STOP_SENDING flag.

Does the above make sense @melekes? These are rather subtle semantics. Please comment in case my explanations and reasoning in the proposal don't make sense to you.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the clarification 👍 The proposed framing looks good to me. Regarding RESET - depending on the implementation there could be some internal buffering. This buffer could be erased once RESET is received. Not sure how useful it would be in practice though.

Instead of resetting both ends of a stream, RESET only resets the sending side
of a stream. This is in line with the QUIC stream reset mechanism.
@mxinden

mxinden commented Sep 5, 2022

Copy link
Copy Markdown
Owner Author

@marten-seemann thanks for the review. I addressed your comments. Do you want to take another look?

@melekes melekes left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@mxinden mxinden marked this pull request as ready for review September 8, 2022 04:06
@mxinden

mxinden commented Sep 8, 2022

Copy link
Copy Markdown
Owner Author

Unless there are any objections, I will merge here end of the week.

@thomaseizinger thomaseizinger left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. Found two typos :)

Comment thread webrtc/README.md Outdated
Comment thread webrtc/README.md Outdated

@marten-seemann marten-seemann left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to specify what happens when receiving a STOP_SENDING? If we want to go in parallel with RFC 9000 we'd need to say that you send a RESET.

mxinden and others added 2 commits September 10, 2022 11:13
@mxinden

mxinden commented Sep 10, 2022

Copy link
Copy Markdown
Owner Author

I was not aware of this convention @marten-seemann. Thanks for pointing it out. I think it makes sense to be consistent with RFC 9000. 31ac65d includes the convention for our adaptation of the QUIC multiplexer.

For the sake of consistency with the QUIC RFC, rename RESET to RESET_STREAM.
Instead of executing the additional Noise handshake on a plain `RTCDataChannel`,
frame the Noise messages with the proposed message framing mechanism already.

Benefits:

- The additional Noise handshake can already make use of the proper closing
mechanism. Note that `RTCDataChannel.close` may drop any in-flight data. See
https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel/close.

- Simplifies implementations as there is only one way to write on an `RTCDataChannel`.

- Allows us to role out new versions of the Noise handshake in the future by
adding a version to the message framing Protobuf.
@mxinden

mxinden commented Sep 11, 2022

Copy link
Copy Markdown
Owner Author

Bringing 7a8ebc0 to everyone's attention here:

webrtc/: Use message framing for Noise handshake already

Instead of executing the additional Noise handshake on a plain RTCDataChannel,
frame the Noise messages with the proposed message framing mechanism already.

Benefits:

  • The additional Noise handshake can already make use of the proper closing
    mechanism. Note that RTCDataChannel.close may drop any in-flight data. See
    https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel/close.

  • Simplifies implementations as there is only one way to write on an RTCDataChannel.

  • Allows us to role out new versions of the Noise handshake in the future by
    adding a version to the message framing Protobuf.

Let me know in case you see any issues with this.

@thomaseizinger thomaseizinger left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Comment thread webrtc/README.md Outdated
Co-authored-by: Thomas Eizinger <thomas@eizinger.io>
@mxinden

mxinden commented Sep 13, 2022

Copy link
Copy Markdown
Owner Author

I am going to merge here. In case you have any follow-ups please raise them on libp2p#412.

@mxinden

mxinden commented Sep 22, 2022

Copy link
Copy Markdown
Owner Author

Moving a question from @melekes on melekes/rust-libp2p#8 (comment) here.

Send RESET_STREAM when receiving STOP_SENDING

again, not sure why it's needed. The remote has already indicated it won't accept any more data, so why send RESET_STREAM?

My rational for introducing it in this pull request was for the sake of consistency with the QUIC specification. I am assuming this can be useful for applications leveraging the acknowledgement of the closing of the read side. I can not find any past discussions on the matter

@marten-seemann do you know more?

@marten-seemann

Copy link
Copy Markdown

My rational for introducing it in this pull request was for the sake of consistency with the QUIC specification. I am assuming this can be useful for applications leveraging the acknowledgement of the closing of the read side. I can not find any past discussions on the matter

@marten-seemann do you know more?

In QUIC it's needed to have an accurate accounting of the number of bytes sent for connection-level flow control purposes (RESET_STREAM contains the final offset of that stream). How does flow control work in WebRTC? Is it purely based on streams? Then we probably don't need to send a RESET_STREAM.

@melekes

melekes commented Sep 22, 2022

Copy link
Copy Markdown

How does flow control work in WebRTC? Is it purely based on streams? Then we probably don't need to send a RESET_STREAM.

Each data channel is a SCTP stream (http://www.myreadingroom.co.in/notes-and-studymaterial/68-dcn/858-flow-control-in-sctp.html).

@mxinden

mxinden commented Sep 22, 2022

Copy link
Copy Markdown
Owner Author

Thanks @marten-seemann and @melekes. Removed requirement with libp2p@65a894a.

//CC @ckousik and @John-LittleBearLabs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants