Merge pull request #400 from paullouisageneau/sctp-settings

Add SCTP settings API
This commit is contained in:
Paul-Louis Ageneau
2021-04-13 21:51:06 +02:00
committed by GitHub
26 changed files with 271 additions and 92 deletions

View File

@ -43,7 +43,7 @@ set(LIBDATACHANNEL_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/configuration.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/datachannel.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/description.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/init.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/global.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/log.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/message.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/peerconnection.cpp
@ -75,7 +75,7 @@ set(LIBDATACHANNEL_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/include/rtc/mediahandler.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/rtc/rtcpreceivingsession.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/rtc/common.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/rtc/init.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/rtc/global.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/rtc/log.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/rtc/message.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/rtc/peerconnection.hpp
@ -107,6 +107,7 @@ set(LIBDATACHANNEL_IMPL_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/src/impl/dtlssrtptransport.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/impl/dtlstransport.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/impl/icetransport.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/impl/init.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/impl/peerconnection.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/impl/logcounter.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/impl/sctptransport.cpp
@ -129,6 +130,8 @@ set(LIBDATACHANNEL_IMPL_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/src/impl/dtlssrtptransport.hpp
${CMAKE_CURRENT_SOURCE_DIR}/src/impl/dtlstransport.hpp
${CMAKE_CURRENT_SOURCE_DIR}/src/impl/icetransport.hpp
${CMAKE_CURRENT_SOURCE_DIR}/src/impl/init.hpp
${CMAKE_CURRENT_SOURCE_DIR}/src/impl/internals.hpp
${CMAKE_CURRENT_SOURCE_DIR}/src/impl/peerconnection.hpp
${CMAKE_CURRENT_SOURCE_DIR}/src/impl/queue.hpp
${CMAKE_CURRENT_SOURCE_DIR}/src/impl/logcounter.hpp

View File

@ -70,6 +70,7 @@ using binary = std::vector<byte>;
using binary_ptr = std::shared_ptr<binary>;
using std::size_t;
using std::ptrdiff_t;
using std::uint16_t;
using std::uint32_t;
using std::uint64_t;

44
include/rtc/global.hpp Normal file
View File

@ -0,0 +1,44 @@
/**
* Copyright (c) 2020-2021 Paul-Louis Ageneau
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef RTC_GLOBAL_H
#define RTC_GLOBAL_H
#include "common.hpp"
#include <chrono>
namespace rtc {
RTC_EXPORT void Preload();
RTC_EXPORT void Cleanup();
struct SctpSettings {
optional<size_t> recvBufferSize;
optional<size_t> sendBufferSize;
optional<size_t> maxChunksOnQueue;
optional<size_t> initialCongestionWindow;
optional<unsigned int> congestionControlModule;
optional<std::chrono::milliseconds> delayedSackTime;
};
RTC_EXPORT void SetSctpSettings(SctpSettings s);
} // namespace rtc
#endif

View File

@ -24,7 +24,6 @@
#include "datachannel.hpp"
#include "description.hpp"
#include "common.hpp"
#include "init.hpp"
#include "message.hpp"
#include "reliability.hpp"
#include "track.hpp"

View File

@ -46,7 +46,8 @@ extern "C" {
#define RTC_DEFAULT_MTU 1280 // IPv6 minimum guaranteed MTU
#if RTC_ENABLE_MEDIA
#define RTC_DEFAULT_MAXIMUM_FRAGMENT_SIZE ((uint16_t)(RTC_DEFAULT_MTU - 12 - 8 - 40)) // SRTP/UDP/IPv6
#define RTC_DEFAULT_MAXIMUM_FRAGMENT_SIZE \
((uint16_t)(RTC_DEFAULT_MTU - 12 - 8 - 40)) // SRTP/UDP/IPv6
#define RTC_DEFAULT_MAXIMUM_PACKET_COUNT_FOR_NACK_CACHE ((unsigned)512)
#endif
@ -97,21 +98,21 @@ typedef enum {
#if RTC_ENABLE_MEDIA
typedef enum {
// video
RTC_CODEC_H264 = 0,
RTC_CODEC_VP8 = 1,
RTC_CODEC_VP9 = 2,
// video
RTC_CODEC_H264 = 0,
RTC_CODEC_VP8 = 1,
RTC_CODEC_VP9 = 2,
// audio
RTC_CODEC_OPUS = 128
// audio
RTC_CODEC_OPUS = 128
} rtcCodec;
typedef enum {
RTC_DIRECTION_UNKNOWN = 0,
RTC_DIRECTION_SENDONLY = 1,
RTC_DIRECTION_RECVONLY = 2,
RTC_DIRECTION_SENDRECV = 3,
RTC_DIRECTION_INACTIVE = 4
RTC_DIRECTION_UNKNOWN = 0,
RTC_DIRECTION_SENDONLY = 1,
RTC_DIRECTION_RECVONLY = 2,
RTC_DIRECTION_SENDRECV = 3,
RTC_DIRECTION_INACTIVE = 4
} rtcDirection;
#endif // RTC_ENABLE_MEDIA
@ -130,7 +131,7 @@ typedef struct {
bool disableAutoNegotiation;
uint16_t portRangeBegin;
uint16_t portRangeEnd;
int mtu; // <= 0 means automatic
int mtu; // <= 0 means automatic
int maxMessageSize; // <= 0 means default
} rtcConfiguration;
@ -172,7 +173,7 @@ RTC_EXPORT void rtcInitLogger(rtcLogLevel level, rtcLogCallbackFunc cb);
// User pointer
RTC_EXPORT void rtcSetUserPointer(int id, void *ptr);
RTC_EXPORT void * rtcGetUserPointer(int i);
RTC_EXPORT void *rtcGetUserPointer(int i);
// PeerConnection
RTC_EXPORT int rtcCreatePeerConnection(const rtcConfiguration *config); // returns pc id
@ -219,6 +220,19 @@ RTC_EXPORT int rtcDeleteTrack(int tr);
RTC_EXPORT int rtcGetTrackDescription(int tr, char *buffer, int size);
// SCTP settings
typedef struct {
int recvBufferSize; // <= 0 means optimized default
int sendBufferSize; // <= 0 means optimized default
int maxChunksOnQueue; // <= 0 means optimized default
int initialCongestionWindow; // <= 0 means optimized default
int congestionControlModule; // <= 0 means default (0: RFC2581, 1: HSTCP, 2: H-TCP, 3: RTCC)
int delayedSackTimeMs; // <= 0 means optimized default
} rtcSctpSettings;
// Note: SCTP settings apply to newly-created PeerConnections only
RTC_EXPORT int rtcSetSctpSettings(const rtcSctpSettings *settings);
// Media
#if RTC_ENABLE_MEDIA
@ -233,7 +247,9 @@ RTC_EXPORT int rtcGetTrackDescription(int tr, char *buffer, int size);
/// @param _msid MSID (optional)
/// @param _trackID Track ID used in MSID (optional)
/// @returns Track id
RTC_EXPORT int rtcAddTrackEx(int pc, rtcCodec codec, int payloadType, uint32_t ssrc, const char *_mid, rtcDirection direction, const char *_name, const char *_msid, const char *_trackID);
RTC_EXPORT int rtcAddTrackEx(int pc, rtcCodec codec, int payloadType, uint32_t ssrc,
const char *_mid, rtcDirection direction, const char *_name,
const char *_msid, const char *_trackID);
/// Set H264PacketizationHandler for track
/// @param tr Track id
@ -244,7 +260,10 @@ RTC_EXPORT int rtcAddTrackEx(int pc, rtcCodec codec, int payloadType, uint32_t s
/// @param maxFragmentSize Maximum NALU fragment size
/// @param sequenceNumber Sequence number
/// @param timestamp Timestamp
RTC_EXPORT int rtcSetH264PacketizationHandler(int tr, uint32_t ssrc, const char * cname, uint8_t payloadType, uint32_t clockRate, uint16_t maxFragmentSize, uint16_t sequenceNumber, uint32_t timestamp);
RTC_EXPORT int rtcSetH264PacketizationHandler(int tr, uint32_t ssrc, const char *cname,
uint8_t payloadType, uint32_t clockRate,
uint16_t maxFragmentSize, uint16_t sequenceNumber,
uint32_t timestamp);
/// Set OpusPacketizationHandler for track
/// @param tr Track id
@ -254,7 +273,9 @@ RTC_EXPORT int rtcSetH264PacketizationHandler(int tr, uint32_t ssrc, const char
/// @param clockRate Clock rate
/// @param _sequenceNumber Sequence number
/// @param _timestamp Timestamp
RTC_EXPORT int rtcSetOpusPacketizationHandler(int tr, uint32_t ssrc, const char * cname, uint8_t payloadType, uint32_t clockRate, uint16_t _sequenceNumber, uint32_t _timestamp);
RTC_EXPORT int rtcSetOpusPacketizationHandler(int tr, uint32_t ssrc, const char *cname,
uint8_t payloadType, uint32_t clockRate,
uint16_t _sequenceNumber, uint32_t _timestamp);
/// Chain RtcpSrReporter to handler chain for given track
/// @param tr Track id
@ -267,9 +288,11 @@ int rtcChainRtcpNackResponder(int tr, unsigned maxStoredPacketsCount);
/// Set start time for RTP stream
/// @param startTime_s Start time in seconds
/// @param timeIntervalSince1970 Set true if `startTime_s` is time interval since 1970, false if `startTime_s` is time interval since 1900
/// @param timeIntervalSince1970 Set true if `startTime_s` is time interval since 1970, false if
/// `startTime_s` is time interval since 1900
/// @param _timestamp Start timestamp
int rtcSetRtpConfigurationStartTime(int id, double startTime_s, bool timeIntervalSince1970, uint32_t _timestamp);
int rtcSetRtpConfigurationStartTime(int id, double startTime_s, bool timeIntervalSince1970,
uint32_t _timestamp);
/// Start stats recording for RTCP Sender Reporter
/// @param id Track identifier
@ -279,23 +302,23 @@ int rtcStartRtcpSenderReporterRecording(int id);
/// @param id Track id
/// @param seconds Seconds
/// @param timestamp Pointer to result
int rtcTransformSecondsToTimestamp(int id, double seconds, uint32_t * timestamp);
int rtcTransformSecondsToTimestamp(int id, double seconds, uint32_t *timestamp);
/// Transform timestamp to seconds using track's clock rate
/// @param id Track id
/// @param timestamp Timestamp
/// @param seconds Pointer for result
int rtcTransformTimestampToSeconds(int id, uint32_t timestamp, double * seconds);
int rtcTransformTimestampToSeconds(int id, uint32_t timestamp, double *seconds);
/// Get current timestamp
/// @param id Track id
/// @param timestamp Pointer for result
int rtcGetCurrentTrackTimestamp(int id, uint32_t * timestamp);
int rtcGetCurrentTrackTimestamp(int id, uint32_t *timestamp);
/// Get start timestamp for track identified by given id
/// @param id Track id
/// @param timestamp Pointer for result
int rtcGetTrackStartTimestamp(int id, uint32_t * timestamp);
int rtcGetTrackStartTimestamp(int id, uint32_t *timestamp);
/// Set RTP timestamp for track identified by given id
/// @param id Track id
@ -305,7 +328,7 @@ int rtcSetTrackRTPTimestamp(int id, uint32_t timestamp);
/// Get timestamp of previous RTCP SR
/// @param id Track id
/// @param timestamp Pointer for result
int rtcGetPreviousTrackSenderReportTimestamp(int id, uint32_t * timestamp);
int rtcGetPreviousTrackSenderReportTimestamp(int id, uint32_t *timestamp);
/// Set `NeedsToReport` flag in RtcpSrReporter handler identified by given track id
/// @param id Track id

View File

@ -21,12 +21,12 @@
// C++ API
#include "common.hpp"
#include "init.hpp" // for rtc::Cleanup()
#include "global.hpp"
#include "log.hpp"
//
#include "datachannel.hpp"
#include "track.hpp"
#include "peerconnection.hpp"
#include "track.hpp"
#if RTC_ENABLE_WEBSOCKET
@ -38,14 +38,13 @@
#if RTC_ENABLE_MEDIA
// Media handling
#include "rtcpreceivingsession.hpp"
#include "mediachainablehandler.hpp"
#include "rtcpsrreporter.hpp"
#include "rtcpnackresponder.hpp"
#include "rtcpreceivingsession.hpp"
#include "rtcpsrreporter.hpp"
// Opus/h264 streaming
#include "h264packetizationhandler.hpp"
#include "opuspacketizationhandler.hpp"
#endif // RTC_ENABLE_MEDIA

View File

@ -17,7 +17,8 @@
*/
#include "candidate.hpp"
#include "globals.hpp"
#include "impl/internals.hpp"
#include <algorithm>
#include <array>

View File

@ -715,6 +715,33 @@ int rtcGetTrackDescription(int tr, char *buffer, int size) {
});
}
int rtcSetSctpSettings(const rtcSctpSettings *settings) {
return wrap([&] {
SctpSettings s = {};
if (settings->recvBufferSize > 0)
s.recvBufferSize = size_t(settings->recvBufferSize);
if (settings->sendBufferSize > 0)
s.sendBufferSize = size_t(settings->sendBufferSize);
if (settings->maxChunksOnQueue > 0)
s.maxChunksOnQueue = size_t(settings->maxChunksOnQueue);
if (settings->initialCongestionWindow > 0)
s.initialCongestionWindow = size_t(settings->initialCongestionWindow);
if (settings->congestionControlModule >= 0)
s.congestionControlModule = unsigned(settings->congestionControlModule);
if (settings->delayedSackTimeMs > 0)
s.delayedSackTime = std::chrono::milliseconds(settings->delayedSackTimeMs);
SetSctpSettings(std::move(s));
return RTC_ERR_SUCCESS;
});
}
#if RTC_ENABLE_WEBSOCKET
int rtcCreateWebSocket(const char *url) {
return wrap([&] {

View File

@ -17,8 +17,8 @@
*/
#include "channel.hpp"
#include "globals.hpp"
#include "impl/internals.hpp"
#include "impl/channel.hpp"
namespace rtc {

View File

@ -17,11 +17,11 @@
*/
#include "datachannel.hpp"
#include "globals.hpp"
#include "common.hpp"
#include "peerconnection.hpp"
#include "impl/datachannel.hpp"
#include "impl/internals.hpp"
#include "impl/peerconnection.hpp"
#ifdef _WIN32

31
src/global.cpp Normal file
View File

@ -0,0 +1,31 @@
/**
* Copyright (c) 2020-2021 Paul-Louis Ageneau
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "global.hpp"
#include "impl/init.hpp"
namespace rtc {
void Preload() { Init::Preload(); }
void Cleanup() { Init::Cleanup(); }
void SetSctpSettings(SctpSettings s) { Init::SetSctpSettings(std::move(s)); }
} // namespace rtc

View File

@ -18,7 +18,7 @@
#include "datachannel.hpp"
#include "common.hpp"
#include "globals.hpp"
#include "internals.hpp"
#include "logcounter.hpp"
#include "peerconnection.hpp"
#include "sctptransport.hpp"

View File

@ -17,7 +17,7 @@
*/
#include "dtlstransport.hpp"
#include "globals.hpp"
#include "internals.hpp"
#include "icetransport.hpp"
#include <chrono>

View File

@ -18,7 +18,7 @@
#include "icetransport.hpp"
#include "configuration.hpp"
#include "globals.hpp"
#include "internals.hpp"
#include "transport.hpp"
#include <iostream>

View File

@ -17,7 +17,7 @@
*/
#include "init.hpp"
#include "globals.hpp"
#include "internals.hpp"
#include "impl/certificate.hpp"
#include "impl/dtlstransport.hpp"
@ -42,7 +42,6 @@ namespace rtc {
namespace {
void doInit() {
PLOG_DEBUG << "Global initialization";
#ifdef _WIN32
WSADATA wsaData;
@ -69,8 +68,6 @@ void doInit() {
}
void doCleanup() {
PLOG_DEBUG << "Global cleanup";
impl::ThreadPool::Instance().join();
impl::SctpTransport::Cleanup();
@ -92,6 +89,7 @@ void doCleanup() {
weak_ptr<void> Init::Weak;
shared_ptr<void> *Init::Global = nullptr;
bool Init::Initialized = false;
SctpSettings Init::CurrentSctpSettings = {};
std::recursive_mutex Init::Mutex;
init_token Init::Token() {
@ -118,10 +116,20 @@ void Init::Cleanup() {
Global = nullptr;
}
void Init::SetSctpSettings(SctpSettings s) {
auto token = Token();
std::unique_lock lock(Mutex);
impl::SctpTransport::SetSettings(s);
CurrentSctpSettings = std::move(s); // store for next init
}
Init::Init() {
// Mutex is locked by Token() here
if (!std::exchange(Initialized, true))
if (!std::exchange(Initialized, true)) {
PLOG_DEBUG << "Global initialization";
doInit();
impl::SctpTransport::SetSettings(CurrentSctpSettings);
}
}
Init::~Init() {
@ -130,8 +138,11 @@ Init::~Init() {
std::unique_lock lock(Mutex);
if (Global)
return;
if (std::exchange(Initialized, false))
if (std::exchange(Initialized, false)) {
PLOG_DEBUG << "Global cleanup";
doCleanup();
}
});
t.detach();
}

View File

@ -16,22 +16,25 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef RTC_INIT_H
#define RTC_INIT_H
#ifndef RTC_IMPL_INIT_H
#define RTC_IMPL_INIT_H
#include "common.hpp"
#include "global.hpp" // for SctpSettings
#include <chrono>
#include <mutex>
namespace rtc {
using init_token = shared_ptr<void>;
class RTC_CPP_EXPORT Init {
class Init {
public:
static init_token Token();
static void Preload();
static void Cleanup();
static void SetSctpSettings(SctpSettings s);
~Init();
@ -41,12 +44,10 @@ private:
static weak_ptr<void> Weak;
static shared_ptr<void> *Global;
static bool Initialized;
static SctpSettings CurrentSctpSettings;
static std::recursive_mutex Mutex;
};
inline void Preload() { Init::Preload(); }
inline void Cleanup() { Init::Cleanup(); }
} // namespace rtc
#endif

View File

@ -16,8 +16,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef RTC_GLOBALS_H
#define RTC_GLOBALS_H
#ifndef RTC_IMPL_INTERNALS_H
#define RTC_IMPL_INTERNALS_H
#include "common.hpp"
@ -26,7 +26,7 @@ namespace rtc {
const size_t MAX_NUMERICNODE_LEN = 48; // Max IPv6 string representation length
const size_t MAX_NUMERICSERV_LEN = 6; // Max port string representation length
const uint16_t DEFAULT_SCTP_PORT = 5000; // SCTP port to use by default
const uint16_t DEFAULT_SCTP_PORT = 5000; // SCTP port to use by default
const size_t DEFAULT_LOCAL_MAX_MESSAGE_SIZE = 256 * 1024; // Default local max message size
const size_t DEFAULT_MAX_MESSAGE_SIZE = 65536; // Remote max message size if not specified in SDP

View File

@ -21,7 +21,7 @@
#include "certificate.hpp"
#include "common.hpp"
#include "dtlstransport.hpp"
#include "globals.hpp"
#include "internals.hpp"
#include "icetransport.hpp"
#include "logcounter.hpp"
#include "peerconnection.hpp"

View File

@ -18,12 +18,13 @@
#include "sctptransport.hpp"
#include "dtlstransport.hpp"
#include "globals.hpp"
#include "internals.hpp"
#include "logcounter.hpp"
#include <chrono>
#include <exception>
#include <iostream>
#include <limits>
#include <thread>
#include <vector>
@ -54,6 +55,26 @@
using namespace std::chrono_literals;
using namespace std::chrono;
namespace {
template <typename T> uint16_t to_uint16(T i) {
if (i >= 0 && static_cast<typename std::make_unsigned<T>::type>(i) <=
std::numeric_limits<uint16_t>::max())
return static_cast<uint16_t>(i);
else
throw std::invalid_argument("Integer out of range");
}
template <typename T> uint32_t to_uint32(T i) {
if (i >= 0 && static_cast<typename std::make_unsigned<T>::type>(i) <=
std::numeric_limits<uint32_t>::max())
return static_cast<uint32_t>(i);
else
throw std::invalid_argument("Integer out of range");
}
} // namespace
namespace rtc::impl {
static LogCounter COUNTER_UNKNOWN_PPID(plog::warning,
@ -69,7 +90,8 @@ std::shared_mutex SctpTransport::InstancesMutex;
void SctpTransport::Init() {
usrsctp_init(0, &SctpTransport::WriteCallback, nullptr);
usrsctp_sysctl_set_sctp_ecn_enable(0);
usrsctp_sysctl_set_sctp_pr_enable(1); // Enable Partial Reliability Extension (RFC 3758)
usrsctp_sysctl_set_sctp_ecn_enable(0); // Disable Explicit Congestion Notification
usrsctp_sysctl_set_sctp_init_rtx_max_default(5);
usrsctp_sysctl_set_sctp_path_rtx_max_default(5);
usrsctp_sysctl_set_sctp_assoc_rtx_max_default(5); // single path
@ -78,21 +100,28 @@ void SctpTransport::Init() {
usrsctp_sysctl_set_sctp_rto_initial_default(1 * 1000); // ms
usrsctp_sysctl_set_sctp_init_rto_max_default(10 * 1000); // ms
usrsctp_sysctl_set_sctp_heartbeat_interval_default(10 * 1000); // ms
}
usrsctp_sysctl_set_sctp_max_chunks_on_queue(10 * 1024);
void SctpTransport::SetSettings(const SctpSettings &s) {
// The send and receive window size of usrsctp is 256KiB, which is too small for realistic RTTs,
// therefore we increase it to 1MiB by default for better performance.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1051685
usrsctp_sysctl_set_sctp_recvspace(to_uint32(s.recvBufferSize.value_or(1024 * 1024)));
usrsctp_sysctl_set_sctp_sendspace(to_uint32(s.sendBufferSize.value_or(1024 * 1024)));
// Use default congestion control (RFC 4960)
// Increase maximum chunks number on queue to 10K by default
usrsctp_sysctl_set_sctp_max_chunks_on_queue(to_uint32(s.maxChunksOnQueue.value_or(10 * 1024)));
// Increase initial congestion window size to 10 MTUs (RFC 6928) by default
usrsctp_sysctl_set_sctp_initial_cwnd(to_uint32(s.initialCongestionWindow.value_or(10)));
// Use standard SCTP congestion control (RFC 4960) by default
// See https://github.com/paullouisageneau/libdatachannel/issues/354
usrsctp_sysctl_set_sctp_default_cc_module(0);
usrsctp_sysctl_set_sctp_default_cc_module(to_uint32(s.congestionControlModule.value_or(0)));
// Enable Partial Reliability Extension (RFC 3758)
usrsctp_sysctl_set_sctp_pr_enable(1);
// Increase the initial window size to 10 MTUs (RFC 6928)
usrsctp_sysctl_set_sctp_initial_cwnd(10);
// Reduce SACK delay from the default 200ms to 20ms
usrsctp_sysctl_set_sctp_delayed_sack_time_default(20); // ms
// Reduce SACK delay to 20ms by default
usrsctp_sysctl_set_sctp_delayed_sack_time_default(
to_uint32(s.delayedSackTime.value_or(20ms).count()));
}
void SctpTransport::Cleanup() {
@ -195,7 +224,7 @@ SctpTransport::SctpTransport(shared_ptr<Transport> lower, const Configuration &c
// The MTU value provided specifies the space available for chunks in the
// packet, so we also subtract the SCTP header size.
size_t pmtu = config.mtu.value_or(DEFAULT_MTU) - 12 - 37 - 8 - 40; // SCTP/DTLS/UDP/IPv6
spp.spp_pathmtu = uint32_t(pmtu);
spp.spp_pathmtu = to_uint32(pmtu);
PLOG_VERBOSE << "Path MTU discovery disabled, SCTP MTU set to " << pmtu;
}
@ -222,18 +251,28 @@ SctpTransport::SctpTransport(shared_ptr<Transport> lower, const Configuration &c
throw std::runtime_error("Could not disable SCTP fragmented interleave, errno=" +
std::to_string(errno));
// The default send and receive window size of usrsctp is 256KiB, which is too small for
// realistic RTTs, therefore we increase it to at least 1MiB for better performance.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1051685
const size_t minBufferSize = 1024 * 1024;
int rcvBuf = 0;
socklen_t rcvBufLen = sizeof(rcvBuf);
if (usrsctp_getsockopt(mSock, SOL_SOCKET, SO_RCVBUF, &rcvBuf, &rcvBufLen))
throw std::runtime_error("Could not get SCTP recv buffer size, errno=" +
std::to_string(errno));
int sndBuf = 0;
socklen_t sndBufLen = sizeof(sndBuf);
if (usrsctp_getsockopt(mSock, SOL_SOCKET, SO_SNDBUF, &sndBuf, &sndBufLen))
throw std::runtime_error("Could not get SCTP send buffer size, errno=" +
std::to_string(errno));
// Ensure the buffer is also large enough to accomodate the largest messages
const size_t maxMessageSize = config.maxMessageSize.value_or(DEFAULT_LOCAL_MAX_MESSAGE_SIZE);
const int bufferSize = int(std::max(minBufferSize, maxMessageSize * 2)); // usrsctp reads as int
if (usrsctp_setsockopt(mSock, SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize)))
const int minBuf = int(std::min(maxMessageSize, size_t(std::numeric_limits<int>::max())));
rcvBuf = std::max(rcvBuf, minBuf);
sndBuf = std::max(sndBuf, minBuf);
if (usrsctp_setsockopt(mSock, SOL_SOCKET, SO_RCVBUF, &rcvBuf, sizeof(rcvBuf)))
throw std::runtime_error("Could not set SCTP recv buffer size, errno=" +
std::to_string(errno));
if (usrsctp_setsockopt(mSock, SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize)))
if (usrsctp_setsockopt(mSock, SOL_SOCKET, SO_SNDBUF, &sndBuf, sizeof(sndBuf)))
throw std::runtime_error("Could not set SCTP send buffer size, errno=" +
std::to_string(errno));
}
@ -336,7 +375,7 @@ bool SctpTransport::send(message_ptr message) {
return true;
mSendQueue.push(message);
updateBufferedAmount(uint16_t(message->stream), long(message_size_func(message)));
updateBufferedAmount(to_uint16(message->stream), ptrdiff_t(message_size_func(message)));
return false;
}
@ -353,7 +392,7 @@ bool SctpTransport::flush() {
}
void SctpTransport::closeStream(unsigned int stream) {
send(make_message(0, Message::Reset, uint16_t(stream)));
send(make_message(0, Message::Reset, to_uint16(stream)));
}
void SctpTransport::incoming(message_ptr message) {
@ -458,7 +497,7 @@ bool SctpTransport::trySendQueue() {
if (!trySendMessage(message))
return false;
mSendQueue.pop();
updateBufferedAmount(uint16_t(message->stream), -long(message_size_func(message)));
updateBufferedAmount(to_uint16(message->stream), -ptrdiff_t(message_size_func(message)));
}
return true;
}
@ -511,12 +550,12 @@ bool SctpTransport::trySendMessage(message_ptr message) {
case Reliability::Type::Rexmit:
spa.sendv_flags |= SCTP_SEND_PRINFO_VALID;
spa.sendv_prinfo.pr_policy = SCTP_PR_SCTP_RTX;
spa.sendv_prinfo.pr_value = uint32_t(std::get<int>(reliability.rexmit));
spa.sendv_prinfo.pr_value = to_uint32(std::get<int>(reliability.rexmit));
break;
case Reliability::Type::Timed:
spa.sendv_flags |= SCTP_SEND_PRINFO_VALID;
spa.sendv_prinfo.pr_policy = SCTP_PR_SCTP_TTL;
spa.sendv_prinfo.pr_value = uint32_t(std::get<milliseconds>(reliability.rexmit).count());
spa.sendv_prinfo.pr_value = to_uint32(std::get<milliseconds>(reliability.rexmit).count());
break;
default:
spa.sendv_prinfo.pr_policy = SCTP_PR_SCTP_NONE;
@ -548,10 +587,10 @@ bool SctpTransport::trySendMessage(message_ptr message) {
return true;
}
void SctpTransport::updateBufferedAmount(uint16_t streamId, long delta) {
void SctpTransport::updateBufferedAmount(uint16_t streamId, ptrdiff_t delta) {
// Requires mSendMutex to be locked
auto it = mBufferedAmount.insert(std::make_pair(streamId, 0)).first;
size_t amount = size_t(std::max(long(it->second) + delta, long(0)));
size_t amount = size_t(std::max(ptrdiff_t(it->second) + delta, ptrdiff_t(0)));
if (amount == 0)
mBufferedAmount.erase(it);
else

View File

@ -39,6 +39,7 @@ namespace rtc::impl {
class SctpTransport final : public Transport {
public:
static void Init();
static void SetSettings(const SctpSettings &s);
static void Cleanup();
using amount_callback = std::function<void(uint16_t streamId, size_t amount)>;
@ -83,7 +84,7 @@ private:
void doFlush();
bool trySendQueue();
bool trySendMessage(message_ptr message);
void updateBufferedAmount(uint16_t streamId, long delta);
void updateBufferedAmount(uint16_t streamId, ptrdiff_t delta);
void triggerBufferedAmount(uint16_t streamId, size_t amount);
void sendReset(uint16_t streamId);

View File

@ -17,7 +17,7 @@
*/
#include "tcptransport.hpp"
#include "globals.hpp"
#include "internals.hpp"
#if RTC_ENABLE_WEBSOCKET

View File

@ -17,7 +17,7 @@
*/
#include "track.hpp"
#include "globals.hpp"
#include "internals.hpp"
#include "logcounter.hpp"
#include "peerconnection.hpp"

View File

@ -19,7 +19,7 @@
#if RTC_ENABLE_WEBSOCKET
#include "websocket.hpp"
#include "globals.hpp"
#include "internals.hpp"
#include "common.hpp"
#include "threadpool.hpp"

View File

@ -19,7 +19,8 @@
#if RTC_ENABLE_MEDIA
#include "nalunit.hpp"
#include "globals.hpp"
#include "impl/internals.hpp"
#include <cmath>

View File

@ -17,8 +17,8 @@
*/
#include "track.hpp"
#include "globals.hpp"
#include "impl/internals.hpp"
#include "impl/track.hpp"
namespace rtc {
@ -46,9 +46,7 @@ bool Track::isOpen(void) const { return impl()->isOpen(); }
bool Track::isClosed(void) const { return impl()->isClosed(); }
size_t Track::maxMessageSize() const {
return impl()->maxMessageSize();
}
size_t Track::maxMessageSize() const { return impl()->maxMessageSize(); }
void Track::setMediaHandler(shared_ptr<MediaHandler> handler) {
impl()->setMediaHandler(std::move(handler));

View File

@ -19,10 +19,10 @@
#if RTC_ENABLE_WEBSOCKET
#include "websocket.hpp"
#include "globals.hpp"
#include "common.hpp"
#include "impl/websocket.hpp"
#include "impl/internals.hpp"
#include <regex>