diff --git a/misc/webrtc-utils/CHANGELOG.md b/misc/webrtc-utils/CHANGELOG.md index 600101a55e7..12c3f847219 100644 --- a/misc/webrtc-utils/CHANGELOG.md +++ b/misc/webrtc-utils/CHANGELOG.md @@ -1,5 +1,9 @@ ## 0.5.0 +- Add `sdp::offer`, mirroring the existing `sdp::answer`. The offer template moved here + from `libp2p-webrtc`, where it was private. + See [PR 6572](https://github.com/libp2p/rust-libp2p/pull/6572). + - Revert migration to `quick-protobuf`, migrate back to `prost`. See [PR 6363](https://github.com/libp2p/rust-libp2p/pull/6363). diff --git a/misc/webrtc-utils/src/sdp.rs b/misc/webrtc-utils/src/sdp.rs index 2be0ed76f29..9461090a633 100644 --- a/misc/webrtc-utils/src/sdp.rs +++ b/misc/webrtc-utils/src/sdp.rs @@ -26,6 +26,24 @@ use tinytemplate::TinyTemplate; use crate::fingerprint::Fingerprint; +/// Renders the SDP offer, describing the client (the dialer). +/// +/// The server does not verify the client's certificate -- the client's identity is established by +/// the Noise handshake that runs afterwards -- so a server rendering this offer on the client's +/// behalf passes [`Fingerprint::FF`] here. +pub fn offer(addr: SocketAddr, client_fingerprint: Fingerprint, client_ufrag: &str) -> String { + let offer = render_description( + CLIENT_SESSION_DESCRIPTION, + addr, + client_fingerprint, + client_ufrag, + ); + + tracing::trace!(%offer, "Created SDP offer"); + + offer +} + pub fn answer(addr: SocketAddr, server_fingerprint: Fingerprint, client_ufrag: &str) -> String { let answer = render_description( SERVER_SESSION_DESCRIPTION, @@ -39,6 +57,95 @@ pub fn answer(addr: SocketAddr, server_fingerprint: Fingerprint, client_ufrag: & answer } +// An SDP message that constitutes the offer. +// +// Main RFC: +// `sctp-port` and `max-message-size` attrs RFC: +// `group` and `mid` attrs RFC: +// `ice-ufrag`, `ice-pwd` and `ice-options` attrs RFC: +// `setup` attr RFC: +// +// Short description: +// +// v= -> always 0 +// o= +// +// identifies the creator of the SDP document. We are allowed to use dummy values +// (`-` and `0.0.0.0` as ) to remain anonymous, which we do. Note that "IN" means +// "Internet". +// +// s= +// +// We are allowed to pass a dummy `-`. +// +// c= +// +// Indicates the IP address of the remote. +// Note that "IN" means "Internet". +// +// t= +// +// Start and end of the validity of the session. `0 0` means that the session never expires. +// +// m= ... +// +// A `m=` line describes a request to establish a certain protocol. The protocol in this line +// (i.e. `TCP/DTLS/SCTP` or `UDP/DTLS/SCTP`) must always be the same as the one in the offer. +// We know that this is true because we tweak the offer to match the protocol. The `` +// component must always be `webrtc-datachannel` for WebRTC. +// RFCs: 8839, 8866, 8841 +// +// a=mid: +// +// Media ID - uniquely identifies this media stream (RFC9143). +// +// a=ice-options:ice2 +// +// Indicates that we are complying with RFC8839 (as opposed to the legacy RFC5245). +// +// a=ice-ufrag: +// a=ice-pwd: +// +// ICE username and password, which are used for establishing and +// maintaining the ICE connection. (RFC8839) +// MUST match ones used by the answerer (server). +// +// a=fingerprint:sha-256 +// +// Fingerprint of the certificate that the remote will use during the TLS +// handshake. (RFC8122) +// +// a=setup:actpass +// +// The endpoint that is the offerer MUST use the setup attribute value of setup:actpass and be +// prepared to receive a client_hello before it receives the answer. +// +// a=sctp-port: +// +// The SCTP port (RFC8841) +// Note it's different from the "m=" line port value, which indicates the port of the +// underlying transport-layer protocol (UDP or TCP). +// +// a=max-message-size: +// +// The maximum SCTP user message size (in bytes). (RFC8841) +const CLIENT_SESSION_DESCRIPTION: &str = "v=0 +o=- 0 0 IN {ip_version} {target_ip} +s=- +c=IN {ip_version} {target_ip} +t=0 0 + +m=application {target_port} UDP/DTLS/SCTP webrtc-datachannel +a=mid:0 +a=ice-options:ice2 +a=ice-ufrag:{ufrag} +a=ice-pwd:{pwd} +a=fingerprint:{fingerprint_algorithm} {fingerprint_value} +a=setup:actpass +a=sctp-port:5000 +a=max-message-size:16384 +"; + // See [`CLIENT_SESSION_DESCRIPTION`]. // // a=ice-lite diff --git a/transports/webrtc/CHANGELOG.md b/transports/webrtc/CHANGELOG.md index b090ebd3efe..42de4c704e1 100644 --- a/transports/webrtc/CHANGELOG.md +++ b/transports/webrtc/CHANGELOG.md @@ -1,5 +1,9 @@ ## 0.10.0-alpha +- Move the offer SDP template into `libp2p-webrtc-utils` and render it through the new + `sdp::offer` there. No behaviour change. + See [PR 6572](https://github.com/libp2p/rust-libp2p/pull/6572). + - Update webrtc-rs to `v0.17` and fix libp2p noise data channel negotiation. See [PR 6429](https://github.com/libp2p/rust-libp2p/pull/6429) diff --git a/transports/webrtc/src/tokio/sdp.rs b/transports/webrtc/src/tokio/sdp.rs index f28c5c33105..1a917ea283d 100644 --- a/transports/webrtc/src/tokio/sdp.rs +++ b/transports/webrtc/src/tokio/sdp.rs @@ -20,8 +20,8 @@ use std::net::SocketAddr; +use libp2p_webrtc_utils::Fingerprint; pub(crate) use libp2p_webrtc_utils::sdp::random_ufrag; -use libp2p_webrtc_utils::{Fingerprint, sdp::render_description}; use webrtc::peer_connection::sdp::session_description::RTCSessionDescription; /// Creates the SDP answer used by the client. @@ -42,103 +42,10 @@ pub(crate) fn answer( /// /// Certificate verification is disabled which is why we hardcode a dummy fingerprint here. pub(crate) fn offer(addr: SocketAddr, client_ufrag: &str) -> RTCSessionDescription { - let offer = render_description( - CLIENT_SESSION_DESCRIPTION, + RTCSessionDescription::offer(libp2p_webrtc_utils::sdp::offer( addr, Fingerprint::FF, client_ufrag, - ); - - tracing::trace!(offer=%offer, "Created SDP offer"); - - RTCSessionDescription::offer(offer).unwrap() + )) + .unwrap() } - -// An SDP message that constitutes the offer. -// -// Main RFC: -// `sctp-port` and `max-message-size` attrs RFC: -// `group` and `mid` attrs RFC: -// `ice-ufrag`, `ice-pwd` and `ice-options` attrs RFC: -// `setup` attr RFC: -// -// Short description: -// -// v= -> always 0 -// o= -// -// identifies the creator of the SDP document. We are allowed to use dummy values -// (`-` and `0.0.0.0` as ) to remain anonymous, which we do. Note that "IN" means -// "Internet". -// -// s= -// -// We are allowed to pass a dummy `-`. -// -// c= -// -// Indicates the IP address of the remote. -// Note that "IN" means "Internet". -// -// t= -// -// Start and end of the validity of the session. `0 0` means that the session never expires. -// -// m= ... -// -// A `m=` line describes a request to establish a certain protocol. The protocol in this line -// (i.e. `TCP/DTLS/SCTP` or `UDP/DTLS/SCTP`) must always be the same as the one in the offer. -// We know that this is true because we tweak the offer to match the protocol. The `` -// component must always be `webrtc-datachannel` for WebRTC. -// RFCs: 8839, 8866, 8841 -// -// a=mid: -// -// Media ID - uniquely identifies this media stream (RFC9143). -// -// a=ice-options:ice2 -// -// Indicates that we are complying with RFC8839 (as opposed to the legacy RFC5245). -// -// a=ice-ufrag: -// a=ice-pwd: -// -// ICE username and password, which are used for establishing and -// maintaining the ICE connection. (RFC8839) -// MUST match ones used by the answerer (server). -// -// a=fingerprint:sha-256 -// -// Fingerprint of the certificate that the remote will use during the TLS -// handshake. (RFC8122) -// -// a=setup:actpass -// -// The endpoint that is the offerer MUST use the setup attribute value of setup:actpass and be -// prepared to receive a client_hello before it receives the answer. -// -// a=sctp-port: -// -// The SCTP port (RFC8841) -// Note it's different from the "m=" line port value, which indicates the port of the -// underlying transport-layer protocol (UDP or TCP). -// -// a=max-message-size: -// -// The maximum SCTP user message size (in bytes). (RFC8841) -const CLIENT_SESSION_DESCRIPTION: &str = "v=0 -o=- 0 0 IN {ip_version} {target_ip} -s=- -c=IN {ip_version} {target_ip} -t=0 0 - -m=application {target_port} UDP/DTLS/SCTP webrtc-datachannel -a=mid:0 -a=ice-options:ice2 -a=ice-ufrag:{ufrag} -a=ice-pwd:{pwd} -a=fingerprint:{fingerprint_algorithm} {fingerprint_value} -a=setup:actpass -a=sctp-port:5000 -a=max-message-size:16384 -";