libp2p_webrtc/tokio/
sdp.rs

1// Copyright 2022 Parity Technologies (UK) Ltd.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and associated documentation files (the "Software"),
5// to deal in the Software without restriction, including without limitation
6// the rights to use, copy, modify, merge, publish, distribute, sublicense,
7// and/or sell copies of the Software, and to permit persons to whom the
8// Software is furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
14// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19// DEALINGS IN THE SOFTWARE.
20
21use std::net::SocketAddr;
22
23pub(crate) use libp2p_webrtc_utils::sdp::random_ufrag;
24use libp2p_webrtc_utils::{sdp::render_description, Fingerprint};
25use webrtc::peer_connection::sdp::session_description::RTCSessionDescription;
26
27/// Creates the SDP answer used by the client.
28pub(crate) fn answer(
29    addr: SocketAddr,
30    server_fingerprint: Fingerprint,
31    client_ufrag: &str,
32) -> RTCSessionDescription {
33    RTCSessionDescription::answer(libp2p_webrtc_utils::sdp::answer(
34        addr,
35        server_fingerprint,
36        client_ufrag,
37    ))
38    .unwrap()
39}
40
41/// Creates the SDP offer used by the server.
42///
43/// Certificate verification is disabled which is why we hardcode a dummy fingerprint here.
44pub(crate) fn offer(addr: SocketAddr, client_ufrag: &str) -> RTCSessionDescription {
45    let offer = render_description(
46        CLIENT_SESSION_DESCRIPTION,
47        addr,
48        Fingerprint::FF,
49        client_ufrag,
50    );
51
52    tracing::trace!(offer=%offer, "Created SDP offer");
53
54    RTCSessionDescription::offer(offer).unwrap()
55}
56
57// An SDP message that constitutes the offer.
58//
59// Main RFC: <https://datatracker.ietf.org/doc/html/rfc8866>
60// `sctp-port` and `max-message-size` attrs RFC: <https://datatracker.ietf.org/doc/html/rfc8841>
61// `group` and `mid` attrs RFC: <https://datatracker.ietf.org/doc/html/rfc9143>
62// `ice-ufrag`, `ice-pwd` and `ice-options` attrs RFC: <https://datatracker.ietf.org/doc/html/rfc8839>
63// `setup` attr RFC: <https://datatracker.ietf.org/doc/html/rfc8122>
64//
65// Short description:
66//
67// v=<protocol-version> -> always 0
68// o=<username> <sess-id> <sess-version> <nettype> <addrtype> <unicast-address>
69//
70//     <username> identifies the creator of the SDP document. We are allowed to use dummy values
71//     (`-` and `0.0.0.0` as <addrtype>) to remain anonymous, which we do. Note that "IN" means
72//     "Internet".
73//
74// s=<session name>
75//
76//     We are allowed to pass a dummy `-`.
77//
78// c=<nettype> <addrtype> <connection-address>
79//
80//     Indicates the IP address of the remote.
81//     Note that "IN" means "Internet".
82//
83// t=<start-time> <stop-time>
84//
85//     Start and end of the validity of the session. `0 0` means that the session never expires.
86//
87// m=<media> <port> <proto> <fmt> ...
88//
89//     A `m=` line describes a request to establish a certain protocol. The protocol in this line
90//     (i.e. `TCP/DTLS/SCTP` or `UDP/DTLS/SCTP`) must always be the same as the one in the offer.
91//     We know that this is true because we tweak the offer to match the protocol. The `<fmt>`
92//     component must always be `webrtc-datachannel` for WebRTC.
93//     RFCs: 8839, 8866, 8841
94//
95// a=mid:<MID>
96//
97//     Media ID - uniquely identifies this media stream (RFC9143).
98//
99// a=ice-options:ice2
100//
101//     Indicates that we are complying with RFC8839 (as opposed to the legacy RFC5245).
102//
103// a=ice-ufrag:<ICE user>
104// a=ice-pwd:<ICE password>
105//
106//     ICE username and password, which are used for establishing and
107//     maintaining the ICE connection. (RFC8839)
108//     MUST match ones used by the answerer (server).
109//
110// a=fingerprint:sha-256 <fingerprint>
111//
112//     Fingerprint of the certificate that the remote will use during the TLS
113//     handshake. (RFC8122)
114//
115// a=setup:actpass
116//
117//     The endpoint that is the offerer MUST use the setup attribute value of setup:actpass and be
118//     prepared to receive a client_hello before it receives the answer.
119//
120// a=sctp-port:<value>
121//
122//     The SCTP port (RFC8841)
123//     Note it's different from the "m=" line port value, which indicates the port of the
124//     underlying transport-layer protocol (UDP or TCP).
125//
126// a=max-message-size:<value>
127//
128//     The maximum SCTP user message size (in bytes). (RFC8841)
129const CLIENT_SESSION_DESCRIPTION: &str = "v=0
130o=- 0 0 IN {ip_version} {target_ip}
131s=-
132c=IN {ip_version} {target_ip}
133t=0 0
134
135m=application {target_port} UDP/DTLS/SCTP webrtc-datachannel
136a=mid:0
137a=ice-options:ice2
138a=ice-ufrag:{ufrag}
139a=ice-pwd:{pwd}
140a=fingerprint:{fingerprint_algorithm} {fingerprint_value}
141a=setup:actpass
142a=sctp-port:5000
143a=max-message-size:16384
144";