mirror of
https://github.com/mii443/libdatachannel.git
synced 2025-08-22 15:15:28 +00:00
Updated RFC references
This commit is contained in:
43
README.md
43
README.md
@ -16,21 +16,22 @@ The library implements the following communication protocols:
|
||||
The WebRTC stack has been tested to be compatible with Firefox and Chromium.
|
||||
|
||||
Protocol stack:
|
||||
- SCTP-based Data Channels ([draft-ietf-rtcweb-data-channel-13](https://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-13))
|
||||
- SRTP-based Media Transport ([draft-ietf-rtcweb-rtp-usage-26](https://tools.ietf.org/html/draft-ietf-rtcweb-rtp-usage-26))
|
||||
- SCTP-based Data Channels ([RFC8831](https://tools.ietf.org/html/rfc8831))
|
||||
- SRTP-based Media Transport ([RFC8834](https://tools.ietf.org/html/rfc8834))
|
||||
- DTLS/UDP ([RFC7350](https://tools.ietf.org/html/rfc7350) and [RFC8261](https://tools.ietf.org/html/rfc8261))
|
||||
- ICE ([RFC8445](https://tools.ietf.org/html/rfc8445)) with STUN ([RFC8489](https://tools.ietf.org/html/rfc8489)) and its extension TURN ([RFC8656](https://tools.ietf.org/html/rfc8656))
|
||||
|
||||
Features:
|
||||
- Full IPv6 support
|
||||
- Trickle ICE ([draft-ietf-ice-trickle-21](https://tools.ietf.org/html/draft-ietf-ice-trickle-21))
|
||||
- JSEP compatible ([draft-ietf-rtcweb-jsep-26](https://tools.ietf.org/html/draft-ietf-rtcweb-jsep-26))
|
||||
- Multicast DNS candidates ([draft-ietf-rtcweb-mdns-ice-candidates-04](https://tools.ietf.org/html/draft-ietf-rtcweb-mdns-ice-candidates-04))
|
||||
- Full IPv6 support (as mandated by [RFC8835](https://tools.ietf.org/html/rfc8835))
|
||||
- Trickle ICE ([RFC8838](https://tools.ietf.org/html/rfc8838))
|
||||
- JSEP-compatible session establishment with SDP ([RFC8829](https://tools.ietf.org/html/rfc8829))
|
||||
- SCTP over DTLS with SDP offer/answer ([RFC8841](https://tools.ietf.org/html/rfc8841))
|
||||
- DTLS with ECDSA or RSA keys ([RFC8824](https://tools.ietf.org/html/rfc8827))
|
||||
- SRTP and SRTCP key derivation from DTLS ([RFC5764](https://tools.ietf.org/html/rfc5764))
|
||||
- Multicast DNS candidates ([draft-ietf-rtcweb-mdns-ice-candidates-04](https://tools.ietf.org/html/draft-ietf-rtcweb-mdns-ice-candidates-04))
|
||||
- Differentiated Services QoS ([draft-ietf-tsvwg-rtcweb-qos-18](https://tools.ietf.org/html/draft-ietf-tsvwg-rtcweb-qos-18))
|
||||
|
||||
Note only SDP BUNDLE mode is supported for media multiplexing ([draft-ietf-mmusic-sdp-bundle-negotiation-54](https://tools.ietf.org/html/draft-ietf-mmusic-sdp-bundle-negotiation-54)). The behavior is equivalent to the JSEP bundle-only policy: the library always negociates one unique network component, where SRTP media streams are multiplexed with SRTCP control packets ([RFC5761](https://tools.ietf.org/html/rfc5761)) and SCTP/DTLS data traffic ([RFC5764](https://tools.ietf.org/html/rfc5764)).
|
||||
Note only SDP BUNDLE mode is supported for media multiplexing ([RFC8843](https://tools.ietf.org/html/rfc8843)). The behavior is equivalent to the JSEP bundle-only policy: the library always negociates one unique network component, where SRTP media streams are multiplexed with SRTCP control packets ([RFC5761](https://tools.ietf.org/html/rfc5761)) and SCTP/DTLS data traffic ([RFC5764](https://tools.ietf.org/html/rfc5764)).
|
||||
|
||||
### WebSocket
|
||||
|
||||
@ -99,12 +100,12 @@ MY_ON_RECV_CANDIDATE_FROM_REMOTE([&pc](string candidate, string mid) {
|
||||
### Observe the PeerConnection state
|
||||
|
||||
```cpp
|
||||
pc.onStateChange([](PeerConnection::State state) {
|
||||
cout << "State: " << state << endl;
|
||||
pc.onStateChange([](rtc::PeerConnection::State state) {
|
||||
std::cout << "State: " << state << std::endl;
|
||||
});
|
||||
|
||||
pc.onGatheringStateChange([](PeerConnection::GatheringState state) {
|
||||
cout << "Gathering state: " << state << endl;
|
||||
pc.onGatheringStateChange([](rtc::PeerConnection::GatheringState state) {
|
||||
std::cout << "Gathering state: " << state << std::endl;
|
||||
});
|
||||
```
|
||||
|
||||
@ -114,12 +115,12 @@ pc.onGatheringStateChange([](PeerConnection::GatheringState state) {
|
||||
auto dc = pc.createDataChannel("test");
|
||||
|
||||
dc->onOpen([]() {
|
||||
cout << "Open" << endl;
|
||||
std::cout << "Open" << std::endl;
|
||||
});
|
||||
|
||||
dc->onMessage([](variant<binary, string> message) {
|
||||
if (holds_alternative<string>(message)) {
|
||||
cout << "Received: " << get<string>(message) << endl;
|
||||
dc->onMessage([](std::variant<binary, string> message) {
|
||||
if (std::holds_alternative<string>(message)) {
|
||||
std::cout << "Received: " << get<string>(message) << std::endl;
|
||||
}
|
||||
});
|
||||
```
|
||||
@ -127,8 +128,8 @@ dc->onMessage([](variant<binary, string> message) {
|
||||
### Receive a DataChannel
|
||||
|
||||
```cpp
|
||||
shared_ptr<rtc::DataChannel> dc;
|
||||
pc.onDataChannel([&dc](shared_ptr<rtc::DataChannel> incoming) {
|
||||
std::shared_ptr<rtc::DataChannel> dc;
|
||||
pc.onDataChannel([&dc](std::shared_ptr<rtc::DataChannel> incoming) {
|
||||
dc = incoming;
|
||||
dc->send("Hello world!");
|
||||
});
|
||||
@ -140,12 +141,12 @@ pc.onDataChannel([&dc](shared_ptr<rtc::DataChannel> incoming) {
|
||||
rtc::WebSocket ws;
|
||||
|
||||
ws.onOpen([]() {
|
||||
cout << "WebSocket open" << endl;
|
||||
std::cout << "WebSocket open" << std::endl;
|
||||
});
|
||||
|
||||
ws.onMessage([](variant<binary, string> message) {
|
||||
if (holds_alternative<string>(message)) {
|
||||
cout << "WebSocket received: " << get<string>(message) << endl;
|
||||
ws.onMessage([](std::variant<binary, string> message) {
|
||||
if (std::holds_alternative<string>(message)) {
|
||||
std::cout << "WebSocket received: " << std::get<string>(message) << endl;
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -243,9 +243,8 @@ string Description::generateSdp(string_view eol) const {
|
||||
sdp << "s=-" << eol;
|
||||
sdp << "t=0 0" << eol;
|
||||
|
||||
// Bundle
|
||||
// see Negotiating Media Multiplexing Using the Session Description Protocol
|
||||
// https://tools.ietf.org/html/draft-ietf-mmusic-sdp-bundle-negotiation-54
|
||||
// Bundle (RFC8843 Negotiating Media Multiplexing Using the Session Description Protocol)
|
||||
// https://tools.ietf.org/html/rfc8843
|
||||
sdp << "a=group:BUNDLE";
|
||||
for (const auto &entry : mEntries)
|
||||
sdp << ' ' << entry->mid();
|
||||
|
@ -36,8 +36,8 @@ using std::chrono::milliseconds;
|
||||
|
||||
namespace rtc::impl {
|
||||
|
||||
// Messages for the DataChannel establishment protocol
|
||||
// See https://tools.ietf.org/html/draft-ietf-rtcweb-data-protocol-09
|
||||
// Messages for the DataChannel establishment protocol (RFC 8832)
|
||||
// See https://tools.ietf.org/html/rfc8832
|
||||
|
||||
enum MessageType : uint8_t {
|
||||
MESSAGE_OPEN_REQUEST = 0x00,
|
||||
|
@ -541,9 +541,11 @@ shared_ptr<DataChannel> PeerConnection::emplaceDataChannel(Description::Role rol
|
||||
if (stream == 65535)
|
||||
throw std::invalid_argument("Invalid DataChannel id");
|
||||
} else {
|
||||
// The active side must use streams with even identifiers, whereas the passive side must use
|
||||
// streams with odd identifiers.
|
||||
// See https://tools.ietf.org/html/draft-ietf-rtcweb-data-protocol-09#section-6
|
||||
// RFC 8832: The peer that initiates opening a data channel selects a stream identifier for
|
||||
// which the corresponding incoming and outgoing streams are unused. If the side is acting
|
||||
// as the DTLS client, it MUST choose an even stream identifier; if the side is acting as
|
||||
// the DTLS server, it MUST choose an odd one.
|
||||
// See https://tools.ietf.org/html/rfc8832#section-6
|
||||
stream = (role == Description::Role::Active) ? 0 : 1;
|
||||
while (mDataChannels.find(stream) != mDataChannels.end()) {
|
||||
if (stream >= 65535 - 2)
|
||||
|
@ -27,10 +27,9 @@
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
// The IETF draft says:
|
||||
// SCTP MUST support performing Path MTU discovery without relying on ICMP or ICMPv6 as specified in
|
||||
// [RFC4821] using probing messages specified in [RFC4820].
|
||||
// See https://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-13#section-5
|
||||
// RFC 8831: SCTP MUST support performing Path MTU discovery without relying on ICMP or ICMPv6 as
|
||||
// specified in [RFC4821] by using probing messages specified in [RFC4820].
|
||||
// See https://tools.ietf.org/html/rfc8831#section-5
|
||||
//
|
||||
// However, usrsctp does not implement Path MTU discovery, so we need to disable it for now.
|
||||
// See https://github.com/sctplab/usrsctp/issues/205
|
||||
@ -101,9 +100,8 @@ void SctpTransport::Cleanup() {
|
||||
std::this_thread::sleep_for(100ms);
|
||||
}
|
||||
|
||||
SctpTransport::SctpTransport(shared_ptr<Transport> lower, uint16_t port,
|
||||
optional<size_t> mtu, message_callback recvCallback,
|
||||
amount_callback bufferedAmountCallback,
|
||||
SctpTransport::SctpTransport(shared_ptr<Transport> lower, uint16_t port, optional<size_t> mtu,
|
||||
message_callback recvCallback, amount_callback bufferedAmountCallback,
|
||||
state_callback stateChangeCallback)
|
||||
: Transport(lower, std::move(stateChangeCallback)), mPort(port),
|
||||
mSendQueue(0, message_size_func), mBufferedAmountCallback(std::move(bufferedAmountCallback)) {
|
||||
@ -161,8 +159,9 @@ SctpTransport::SctpTransport(shared_ptr<Transport> lower, uint16_t port,
|
||||
throw std::runtime_error("Could not subscribe to event SCTP_STREAM_RESET_EVENT, errno=" +
|
||||
std::to_string(errno));
|
||||
|
||||
// The sender SHOULD disable the Nagle algorithm (see RFC1122) to minimize the latency.
|
||||
// See https://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-13#section-6.6
|
||||
// RFC 8831 6.6. Transferring User Data on a Data Channel
|
||||
// The sender SHOULD disable the Nagle algorithm (see [RFC1122) to minimize the latency
|
||||
// See https://tools.ietf.org/html/rfc8831#section-6.6
|
||||
int nodelay = 1;
|
||||
if (usrsctp_setsockopt(mSock, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, sizeof(nodelay)))
|
||||
throw std::runtime_error("Could not set socket option SCTP_NODELAY, errno=" +
|
||||
@ -203,9 +202,10 @@ SctpTransport::SctpTransport(shared_ptr<Transport> lower, uint16_t port,
|
||||
throw std::runtime_error("Could not set socket option SCTP_PEER_ADDR_PARAMS, errno=" +
|
||||
std::to_string(errno));
|
||||
|
||||
// The IETF draft recommends the number of streams negotiated during SCTP association to be
|
||||
// 65535.
|
||||
// See https://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-13#section-6.2
|
||||
// RFC 8831 6.2. SCTP Association Management
|
||||
// The number of streams negotiated during SCTP association setup SHOULD be 65535, which is the
|
||||
// maximum number of streams that can be negotiated during the association setup.
|
||||
// See https://tools.ietf.org/html/rfc8831#section-6.2
|
||||
struct sctp_initmsg sinit = {};
|
||||
sinit.sinit_num_ostreams = 65535;
|
||||
sinit.sinit_max_instreams = 65535;
|
||||
@ -213,7 +213,7 @@ SctpTransport::SctpTransport(shared_ptr<Transport> lower, uint16_t port,
|
||||
throw std::runtime_error("Could not set socket option SCTP_INITMSG, errno=" +
|
||||
std::to_string(errno));
|
||||
|
||||
// Prevent fragmented interleave of messages (i.e. level 0), see RFC 6458 8.1.20.
|
||||
// Prevent fragmented interleave of messages (i.e. level 0), see RFC 6458 section 8.1.20.
|
||||
// Unless the user has set the fragmentation interleave level to 0, notifications
|
||||
// may also be interleaved with partially delivered messages.
|
||||
int level = 0;
|
||||
@ -293,9 +293,9 @@ void SctpTransport::connect() {
|
||||
if (usrsctp_bind(mSock, reinterpret_cast<struct sockaddr *>(&sconn), sizeof(sconn)))
|
||||
throw std::runtime_error("Could not bind usrsctp socket, errno=" + std::to_string(errno));
|
||||
|
||||
// According to the IETF draft, both endpoints must initiate the SCTP association, in a
|
||||
// According to RFC 8841, both endpoints must initiate the SCTP association, in a
|
||||
// simultaneous-open manner, irrelevent to the SDP setup role.
|
||||
// See https://tools.ietf.org/html/draft-ietf-mmusic-sctp-sdp-26#section-9.3
|
||||
// See https://tools.ietf.org/html/rfc8841#section-9.3
|
||||
int ret = usrsctp_connect(mSock, reinterpret_cast<struct sockaddr *>(&sconn), sizeof(sconn));
|
||||
if (ret && errno != EINPROGRESS)
|
||||
throw std::runtime_error("Connection attempt failed, errno=" + std::to_string(errno));
|
||||
@ -632,9 +632,11 @@ int SctpTransport::handleWrite(byte *data, size_t len, uint8_t /*tos*/, uint8_t
|
||||
void SctpTransport::processData(binary &&data, uint16_t sid, PayloadId ppid) {
|
||||
PLOG_VERBOSE << "Process data, size=" << data.size();
|
||||
|
||||
// The usage of the PPIDs "WebRTC String Partial" and "WebRTC Binary Partial" is deprecated.
|
||||
// See https://tools.ietf.org/html/draft-ietf-rtcweb-data-channel-13#section-6.6
|
||||
// We handle them at reception for compatibility reasons but should never send them.
|
||||
// RFC 8831: The usage of the PPIDs "WebRTC String Partial" and "WebRTC Binary Partial" is
|
||||
// deprecated. They were used for a PPID-based fragmentation and reassembly of user messages
|
||||
// belonging to reliable and ordered data channels.
|
||||
// See https://tools.ietf.org/html/rfc8831#section-6.6
|
||||
// We handle those PPIDs at reception for compatibility reasons but shall never send them.
|
||||
switch (ppid) {
|
||||
case PPID_CONTROL:
|
||||
recv(make_message(std::move(data), Message::Control, sid));
|
||||
|
Reference in New Issue
Block a user