From 82159e4c06c95db5f58954a624d1ac52a9cd661f Mon Sep 17 00:00:00 2001 From: Maxim Sharabayko Date: Fri, 19 Feb 2021 10:56:00 +0100 Subject: [PATCH] [core] Added SRTO_MININPUTBW socket option --- srtcore/core.cpp | 26 ++++++++--- srtcore/core.h | 2 +- srtcore/group.cpp | 3 +- srtcore/socketconfig.cpp | 97 ++++++++++++++++++++-------------------- srtcore/socketconfig.h | 29 +++++++++--- srtcore/srt.h | 1 + 6 files changed, 97 insertions(+), 61 deletions(-) diff --git a/srtcore/core.cpp b/srtcore/core.cpp index fa21a3dcb..a2198e9d8 100644 --- a/srtcore/core.cpp +++ b/srtcore/core.cpp @@ -225,6 +225,7 @@ extern const SRT_SOCKOPT srt_post_opt_list [SRT_SOCKOPT_NPOST] = { SRTO_RCVTIMEO, SRTO_MAXBW, SRTO_INPUTBW, + SRTO_MININPUTBW, SRTO_OHEADBW, SRTO_SNDDROPDELAY, SRTO_CONNTIMEO, @@ -263,6 +264,7 @@ struct SrtOptionAction flags[SRTO_TSBPDMODE] = SRTO_R_PRE; flags[SRTO_LATENCY] = SRTO_R_PRE; flags[SRTO_INPUTBW] = 0 | SRTO_POST_SPEC; + flags[SRTO_MININPUTBW] = 0 | SRTO_POST_SPEC; flags[SRTO_OHEADBW] = 0 | SRTO_POST_SPEC; flags[SRTO_PASSPHRASE] = SRTO_R_PRE; flags[SRTO_PBKEYLEN] = SRTO_R_PRE; @@ -305,7 +307,7 @@ void CUDT::setOpt(SRT_SOCKOPT optName, const void* optval, int optlen) throw CUDTException(MJ_NOTSUP, MN_INVAL, 0); // Restriction check - int oflags = srt_options_action.flags[optName]; + const int oflags = srt_options_action.flags[optName]; ScopedLock cg (m_ConnectionLock); ScopedLock sendguard (m_SendLock); @@ -321,7 +323,7 @@ void CUDT::setOpt(SRT_SOCKOPT optName, const void* optval, int optlen) throw CUDTException(MJ_NOTSUP, MN_ISCONNECTED, 0); // Option execution. If this returns -1, there's no such option. - int status = m_config.set(optName, optval, optlen); + const int status = m_config.set(optName, optval, optlen); if (status == -1) { LOGC(aclog.Error, log << CONID() << "OPTION: #" << optName << " UNKNOWN"); @@ -338,6 +340,7 @@ void CUDT::setOpt(SRT_SOCKOPT optName, const void* optval, int optlen) break; case SRTO_INPUTBW: + case SRTO_MININPUTBW: updateCC(TEV_INIT, EventVariant(TEV_INIT_INPUTBW)); break; @@ -433,15 +436,26 @@ void CUDT::getOpt(SRT_SOCKOPT optName, void *optval, int &optlen) break; case SRTO_MAXBW: + if (optlen < sizeof(m_config.m_llMaxBW)) + throw CUDTException(MJ_NOTSUP, MN_INVAL, 0); *(int64_t *)optval = m_config.m_llMaxBW; optlen = sizeof(int64_t); break; case SRTO_INPUTBW: + if (optlen < sizeof(m_config.m_llInputBW)) + throw CUDTException(MJ_NOTSUP, MN_INVAL, 0); *(int64_t*)optval = m_config.m_llInputBW; - optlen = sizeof(int64_t); + optlen = sizeof(int64_t); break; + case SRTO_MININPUTBW: + if (optlen < sizeof (m_config.m_llMinInputBW)) + throw CUDTException(MJ_NOTSUP, MN_INVAL, 0); + *(int64_t*)optval = m_config.m_llMinInputBW; + optlen = sizeof(int64_t); + break; + case SRTO_OHEADBW: *(int32_t *)optval = m_config.m_iOverheadBW; optlen = sizeof(int32_t); @@ -7085,7 +7099,7 @@ bool CUDT::updateCC(ETransmissionEvent evt, const EventVariant arg) } else { - // No need to calculate input reate if the bandwidth is set + // No need to calculate input rate if the bandwidth is set const bool disable_in_rate_calc = (bw != 0); m_pSndBuffer->resetInputRateSmpPeriod(disable_in_rate_calc); } @@ -7116,8 +7130,8 @@ bool CUDT::updateCC(ETransmissionEvent evt, const EventVariant arg) * and sendrate skyrockets for retransmission. * Keep previously set maximum in that case (inputbw == 0). */ - if (inputbw != 0) - m_CongCtl->updateBandwidth(0, withOverhead(inputbw)); // Bytes/sec + if (inputbw >= 0) + m_CongCtl->updateBandwidth(0, withOverhead(std::max(m_config.m_llMinInputBW, inputbw))); // Bytes/sec } } diff --git a/srtcore/core.h b/srtcore/core.h index 6ed5d02e0..ac489eac0 100644 --- a/srtcore/core.h +++ b/srtcore/core.h @@ -116,7 +116,7 @@ enum AckDataItem }; const size_t ACKD_FIELD_SIZE = sizeof(int32_t); -static const size_t SRT_SOCKOPT_NPOST = 12; +static const size_t SRT_SOCKOPT_NPOST = 13; extern const SRT_SOCKOPT srt_post_opt_list []; enum GroupDataItem diff --git a/srtcore/group.cpp b/srtcore/group.cpp index 9faee8126..a967b146b 100644 --- a/srtcore/group.cpp +++ b/srtcore/group.cpp @@ -465,7 +465,7 @@ void CUDTGroup::setOpt(SRT_SOCKOPT optName, const void* optval, int optlen) { // There's at least one socket in the group, so only // post-options are allowed. - if (!std::binary_search(srt_post_opt_list, srt_post_opt_list + SRT_SOCKOPT_NPOST, optName)) + if (!binary_search(srt_post_opt_list, srt_post_opt_list + SRT_SOCKOPT_NPOST, optName)) { LOGC(gmlog.Error, log << "setsockopt(group): Group is connected, this option can't be altered"); throw CUDTException(MJ_NOTSUP, MN_ISCONNECTED, 0); @@ -567,6 +567,7 @@ void CUDTGroup::deriveSettings(CUDT* u) // Reuseaddr: true by default and should only be true. IM(SRTO_MAXBW, m_llMaxBW); IM(SRTO_INPUTBW, m_llInputBW); + IM(SRTO_MININPUTBW, m_llMinInputBW); IM(SRTO_OHEADBW, m_iOverheadBW); IM(SRTO_IPTOS, m_iIpToS); IM(SRTO_IPTTL, m_iIpTTL); diff --git a/srtcore/socketconfig.cpp b/srtcore/socketconfig.cpp index ace07c1e2..e50bb08f5 100644 --- a/srtcore/socketconfig.cpp +++ b/srtcore/socketconfig.cpp @@ -64,58 +64,59 @@ static struct SrtConfigSetter #define DISPATCH(optname) fn[optname] = &CSrtConfigSetter::set; - DISPATCH(SRTO_MSS); - DISPATCH(SRTO_FC); - DISPATCH(SRTO_SNDBUF); - DISPATCH(SRTO_RCVBUF); - DISPATCH(SRTO_LINGER); - DISPATCH(SRTO_UDP_SNDBUF); - DISPATCH(SRTO_UDP_RCVBUF); - DISPATCH(SRTO_RENDEZVOUS); - DISPATCH(SRTO_SNDTIMEO); - DISPATCH(SRTO_RCVTIMEO); - DISPATCH(SRTO_SNDSYN); - DISPATCH(SRTO_RCVSYN); - DISPATCH(SRTO_REUSEADDR); - DISPATCH(SRTO_MAXBW); - DISPATCH(SRTO_IPTTL); - DISPATCH(SRTO_IPTOS); - DISPATCH(SRTO_BINDTODEVICE); - DISPATCH(SRTO_INPUTBW); - DISPATCH(SRTO_OHEADBW); - DISPATCH(SRTO_SENDER); - DISPATCH(SRTO_TSBPDMODE); - DISPATCH(SRTO_LATENCY); - DISPATCH(SRTO_RCVLATENCY); - DISPATCH(SRTO_PEERLATENCY); - DISPATCH(SRTO_TLPKTDROP); - DISPATCH(SRTO_SNDDROPDELAY); - DISPATCH(SRTO_PASSPHRASE); - DISPATCH(SRTO_PBKEYLEN); - DISPATCH(SRTO_NAKREPORT); - DISPATCH(SRTO_CONNTIMEO); - DISPATCH(SRTO_DRIFTTRACER); - DISPATCH(SRTO_LOSSMAXTTL); - DISPATCH(SRTO_VERSION); - DISPATCH(SRTO_MINVERSION); - DISPATCH(SRTO_STREAMID); - DISPATCH(SRTO_CONGESTION); - DISPATCH(SRTO_MESSAGEAPI); - DISPATCH(SRTO_PAYLOADSIZE); - DISPATCH(SRTO_TRANSTYPE); + DISPATCH(SRTO_MSS); + DISPATCH(SRTO_FC); + DISPATCH(SRTO_SNDBUF); + DISPATCH(SRTO_RCVBUF); + DISPATCH(SRTO_LINGER); + DISPATCH(SRTO_UDP_SNDBUF); + DISPATCH(SRTO_UDP_RCVBUF); + DISPATCH(SRTO_RENDEZVOUS); + DISPATCH(SRTO_SNDTIMEO); + DISPATCH(SRTO_RCVTIMEO); + DISPATCH(SRTO_SNDSYN); + DISPATCH(SRTO_RCVSYN); + DISPATCH(SRTO_REUSEADDR); + DISPATCH(SRTO_MAXBW); + DISPATCH(SRTO_IPTTL); + DISPATCH(SRTO_IPTOS); + DISPATCH(SRTO_BINDTODEVICE); + DISPATCH(SRTO_INPUTBW); + DISPATCH(SRTO_MININPUTBW); + DISPATCH(SRTO_OHEADBW); + DISPATCH(SRTO_SENDER); + DISPATCH(SRTO_TSBPDMODE); + DISPATCH(SRTO_LATENCY); + DISPATCH(SRTO_RCVLATENCY); + DISPATCH(SRTO_PEERLATENCY); + DISPATCH(SRTO_TLPKTDROP); + DISPATCH(SRTO_SNDDROPDELAY); + DISPATCH(SRTO_PASSPHRASE); + DISPATCH(SRTO_PBKEYLEN); + DISPATCH(SRTO_NAKREPORT); + DISPATCH(SRTO_CONNTIMEO); + DISPATCH(SRTO_DRIFTTRACER); + DISPATCH(SRTO_LOSSMAXTTL); + DISPATCH(SRTO_VERSION); + DISPATCH(SRTO_MINVERSION); + DISPATCH(SRTO_STREAMID); + DISPATCH(SRTO_CONGESTION); + DISPATCH(SRTO_MESSAGEAPI); + DISPATCH(SRTO_PAYLOADSIZE); + DISPATCH(SRTO_TRANSTYPE); #if ENABLE_EXPERIMENTAL_BONDING - DISPATCH(SRTO_GROUPCONNECT); + DISPATCH(SRTO_GROUPCONNECT); #endif - DISPATCH(SRTO_KMREFRESHRATE); - DISPATCH(SRTO_KMPREANNOUNCE); - DISPATCH(SRTO_ENFORCEDENCRYPTION); - DISPATCH(SRTO_PEERIDLETIMEO); - DISPATCH(SRTO_IPV6ONLY); - DISPATCH(SRTO_PACKETFILTER); + DISPATCH(SRTO_KMREFRESHRATE); + DISPATCH(SRTO_KMPREANNOUNCE); + DISPATCH(SRTO_ENFORCEDENCRYPTION); + DISPATCH(SRTO_PEERIDLETIMEO); + DISPATCH(SRTO_IPV6ONLY); + DISPATCH(SRTO_PACKETFILTER); #if ENABLE_EXPERIMENTAL_BONDING - DISPATCH(SRTO_GROUPSTABTIMEO); + DISPATCH(SRTO_GROUPSTABTIMEO); #endif - DISPATCH(SRTO_RETRANSMITALGO); + DISPATCH(SRTO_RETRANSMITALGO); #undef DISPATCH } diff --git a/srtcore/socketconfig.h b/srtcore/socketconfig.h index eaff48dec..c415d6ae2 100644 --- a/srtcore/socketconfig.h +++ b/srtcore/socketconfig.h @@ -247,8 +247,8 @@ struct CSrtConfig: CSrtMuxerConfig uint32_t m_uStabilityTimeout; int m_iRetransmitAlgo; - int64_t m_llInputBW; // Input stream rate (bytes/sec) - // 0: use internally estimated input bandwidth + int64_t m_llInputBW; // Input stream rate (bytes/sec). 0: use internally estimated input bandwidth + int64_t m_llMinInputBW; // Minimum input stream rate estimate (bytes/sec) int m_iOverheadBW; // Percent above input stream rate (applies if m_llMaxBW == 0) bool m_bRcvNakReport; // Enable Receiver Periodic NAK Reports int m_iMaxReorderTolerance; //< Maximum allowed value for dynamic reorder tolerance @@ -298,6 +298,7 @@ struct CSrtConfig: CSrtMuxerConfig , m_uStabilityTimeout(COMM_DEF_STABILITY_TIMEOUT_US) , m_iRetransmitAlgo(0) , m_llInputBW(0) + , m_llMinInputBW(0) , m_iOverheadBW(25) , m_bRcvNakReport(true) , m_iMaxReorderTolerance(0) // Sensible optimal value is 10, 0 preserves old behavior @@ -559,7 +560,11 @@ struct CSrtConfigSetter { static void set(CSrtConfig& co, const void* optval, int optlen) { - co.m_llMaxBW = cast_optval(optval, optlen); + const int64_t val = cast_optval(optval, optlen); + if (val < -1) + throw CUDTException(MJ_NOTSUP, MN_INVAL, 0); + + co.m_llMaxBW = val; } }; @@ -620,7 +625,21 @@ struct CSrtConfigSetter { static void set(CSrtConfig& co, const void* optval, int optlen) { - co.m_llInputBW = cast_optval(optval, optlen); + const int64_t val = cast_optval(optval, optlen); + if (val < 0) + throw CUDTException(MJ_NOTSUP, MN_INVAL, 0); + co.m_llInputBW = val; + } +}; +template<> +struct CSrtConfigSetter +{ + static void set(CSrtConfig& co, const void* optval, int optlen) + { + const int64_t val = cast_optval(optval, optlen); + if (val < 0) + throw CUDTException(MJ_NOTSUP, MN_INVAL, 0); + co.m_llMinInputBW = val; } }; template<> @@ -628,7 +647,7 @@ struct CSrtConfigSetter { static void set(CSrtConfig& co, const void* optval, int optlen) { - int32_t val = cast_optval(optval, optlen); + const int32_t val = cast_optval(optval, optlen); if (val < 5 || val > 100) throw CUDTException(MJ_NOTSUP, MN_INVAL, 0); co.m_iOverheadBW = val; diff --git a/srtcore/srt.h b/srtcore/srt.h index db392470a..f9fa24655 100644 --- a/srtcore/srt.h +++ b/srtcore/srt.h @@ -222,6 +222,7 @@ typedef enum SRT_SOCKOPT { SRTO_PEERVERSION, // Peer SRT Version (from SRT Handshake) SRTO_CONNTIMEO = 36, // Connect timeout in msec. Caller default: 3000, rendezvous (x 10) SRTO_DRIFTTRACER = 37, // Enable or disable drift tracer + SRTO_MININPUTBW = 38, // Minimum estimate of input stream rate. // (some space left) SRTO_SNDKMSTATE = 40, // (GET) the current state of the encryption at the peer side SRTO_RCVKMSTATE, // (GET) the current state of the encryption at the agent side