diff --git a/README.md b/README.md index 3cd39d9..2dac285 100644 --- a/README.md +++ b/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 message) { - if (holds_alternative(message)) { - cout << "Received: " << get(message) << endl; +dc->onMessage([](std::variant message) { + if (std::holds_alternative(message)) { + std::cout << "Received: " << get(message) << std::endl; } }); ``` @@ -127,8 +128,8 @@ dc->onMessage([](variant message) { ### Receive a DataChannel ```cpp -shared_ptr dc; -pc.onDataChannel([&dc](shared_ptr incoming) { +std::shared_ptr dc; +pc.onDataChannel([&dc](std::shared_ptr incoming) { dc = incoming; dc->send("Hello world!"); }); @@ -140,12 +141,12 @@ pc.onDataChannel([&dc](shared_ptr incoming) { rtc::WebSocket ws; ws.onOpen([]() { - cout << "WebSocket open" << endl; + std::cout << "WebSocket open" << std::endl; }); -ws.onMessage([](variant message) { - if (holds_alternative(message)) { - cout << "WebSocket received: " << get(message) << endl; +ws.onMessage([](std::variant message) { + if (std::holds_alternative(message)) { + std::cout << "WebSocket received: " << std::get(message) << endl; } }); diff --git a/examples/streamer/fileparser.cpp b/examples/streamer/fileparser.cpp index 0c83995..d81a070 100644 --- a/examples/streamer/fileparser.cpp +++ b/examples/streamer/fileparser.cpp @@ -28,7 +28,7 @@ FileParser::FileParser(string directory, string extension, uint32_t samplesPerSe } void FileParser::start() { - sampleTime_us = -sampleDuration_us; + sampleTime_us = std::numeric_limits::max() - sampleDuration_us + 1; loadNextSample(); } diff --git a/src/description.cpp b/src/description.cpp index 35cdb0f..a7f0df3 100644 --- a/src/description.cpp +++ b/src/description.cpp @@ -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(); diff --git a/src/impl/datachannel.cpp b/src/impl/datachannel.cpp index 51558b6..44bf5fa 100644 --- a/src/impl/datachannel.cpp +++ b/src/impl/datachannel.cpp @@ -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, diff --git a/src/impl/peerconnection.cpp b/src/impl/peerconnection.cpp index b45d160..a0d94c3 100644 --- a/src/impl/peerconnection.cpp +++ b/src/impl/peerconnection.cpp @@ -541,9 +541,11 @@ shared_ptr 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) diff --git a/src/impl/sctptransport.cpp b/src/impl/sctptransport.cpp index 0310b7c..466cdb1 100644 --- a/src/impl/sctptransport.cpp +++ b/src/impl/sctptransport.cpp @@ -27,10 +27,9 @@ #include #include -// 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 lower, uint16_t port, - optional mtu, message_callback recvCallback, - amount_callback bufferedAmountCallback, +SctpTransport::SctpTransport(shared_ptr lower, uint16_t port, optional 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 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 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 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(&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(&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));