From c1803bba86c4af288931aa35b2a6233ac5eab657 Mon Sep 17 00:00:00 2001 From: Jean-Michel Gonet Date: Mon, 21 Oct 2024 07:43:26 +0000 Subject: [PATCH 01/14] [docs] Added 'brew install pkgconfig' to the macOS build guide (#3054). --- docs/build/build-macOS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/build/build-macOS.md b/docs/build/build-macOS.md index b14a56197..07a5a95cd 100644 --- a/docs/build/build-macOS.md +++ b/docs/build/build-macOS.md @@ -19,6 +19,7 @@ Install [CMake](https://cmake.org/) and OpenSSL with development files from `bre ```shell brew install cmake brew install openssl +brew install pkgconfig ``` SRT can be now built with `cmake` or `make` on Mac. From d2811cc215b174e8c3a03b12ba11cdc72c7a3bc3 Mon Sep 17 00:00:00 2001 From: Maxim Sharabayko Date: Tue, 29 Oct 2024 10:25:53 +0100 Subject: [PATCH 02/14] [build] Apply -stdc=99 on SRT library. --- CMakeLists.txt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a2fc63d2..7ed11ef8e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1046,8 +1046,23 @@ macro(srt_set_stdcxx targetname spec) endif() endmacro() +macro(srt_set_stdc targetname spec) + set (stdcspec ${spec}) + if (NOT "${stdcspec}" STREQUAL "") + if (CMAKE_VERSION VERSION_LESS "3.1") + target_compile_options(${targetname} PRIVATE -std=c${stdcspec}) + message(STATUS "C STD: ${targetname}: forced C${stdcspec} standard - GNU option: -std=c${stdcspec}") + else() + set_target_properties(${targetname} PROPERTIES C_STANDARD ${stdcspec}) + message(STATUS "C STD: ${targetname}: forced C${stdcspec} standard - portable way") + endif() + else() + message(STATUS "APP: ${targetname}: using default C standard") + endif() +endmacro() srt_set_stdcxx(srt_virtual "${USE_CXX_STD_LIB}") +srt_set_stdc(srt_virtual "99") set (VIRTUAL_srt $) From 7df2805a5d993395a4d92d56a4bf1a79711aea1b Mon Sep 17 00:00:00 2001 From: Maxim Sharabayko Date: Mon, 21 Oct 2024 11:07:00 +0200 Subject: [PATCH 03/14] [apps] Use sync.h instead of atomic.h in the verbose module. --- apps/verbose.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/verbose.hpp b/apps/verbose.hpp index e3d20732a..56945bf2c 100644 --- a/apps/verbose.hpp +++ b/apps/verbose.hpp @@ -12,7 +12,7 @@ #define INC_SRT_VERBOSE_HPP #include -#include "atomic.h" +#include "sync.h" namespace Verbose { From 47bc92bf42e3b686ca6b5ab249c089e33c2790be Mon Sep 17 00:00:00 2001 From: Maxim Sharabayko Date: Mon, 4 Nov 2024 12:05:21 +0100 Subject: [PATCH 04/14] [docs] Set callbacks before listening or connecting. --- docs/API/API-functions.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/API/API-functions.md b/docs/API/API-functions.md index 74fbc506f..2fdb8a661 100644 --- a/docs/API/API-functions.md +++ b/docs/API/API-functions.md @@ -751,6 +751,9 @@ automatically created to handle the incoming connection on the listening socket (and is about to be returned by [`srt_accept`](#srt_accept)), but before the connection has been accepted. +Note the callback must be set before starting listening, +i.e. before `srt_listen` is called. + **Arguments**: * `lsn`: Listening socket where you want to install the callback hook @@ -1020,6 +1023,9 @@ mode ([`SRTO_RCVSYN`](API-socket-options.md#SRTO_RCVSYN) option set to true). It is guaranteed to be called when a socket is in non-blocking mode, or when you use a group. +Note the callback must be set before starting the connection procedure, +i.e. before `srt_connect`, `srt_connect_bind`, etc. is called. + This function is mainly intended to be used with group connections. Note that even if you use a group connection in blocking mode, after the group is considered connected the member connections still continue in background. Also, when some From 1ce7dbaf679b68d5f7652a568168fe61451f1547 Mon Sep 17 00:00:00 2001 From: Maxim Sharabayko Date: Wed, 6 Nov 2024 11:17:26 +0100 Subject: [PATCH 05/14] [core] Resolved GCC13 build warning regarding std::copy of a bool. --- srtcore/group.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/srtcore/group.cpp b/srtcore/group.cpp index 5601cdeee..e7f40d884 100644 --- a/srtcore/group.cpp +++ b/srtcore/group.cpp @@ -447,11 +447,13 @@ static bool operator!=(const struct linger& l1, const struct linger& l2) template static void importOption(vector& storage, SRT_SOCKOPT optname, const ValueType& field) { - ValueType default_opt = ValueType(); - int default_opt_size = sizeof(ValueType); - ValueType opt = field; - if (!getOptDefault(optname, (&default_opt), (default_opt_size)) || default_opt != opt) + ValueType default_opt = ValueType(); + static const int default_opt_size = sizeof(ValueType); + ValueType opt = field; + int opt_size = default_opt_size; + if (!getOptDefault(optname, (&default_opt), (opt_size)) || default_opt != opt) { + SRT_ASSERT(opt_size == default_opt_size); // Store the option when: // - no default for this option is found // - the option value retrieved from the field is different than default From 5b0d844488871de4c0e4fbde8f1f88b563edcbb1 Mon Sep 17 00:00:00 2001 From: Maxim Sharabayko Date: Wed, 6 Nov 2024 11:18:27 +0100 Subject: [PATCH 06/14] [docs] Fix np.nan in the release notes script. --- scripts/release-notes/generate_release_notes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/release-notes/generate_release_notes.py b/scripts/release-notes/generate_release_notes.py index 2392b4348..c92ef3cca 100644 --- a/scripts/release-notes/generate_release_notes.py +++ b/scripts/release-notes/generate_release_notes.py @@ -21,7 +21,7 @@ def define_area(msg): if msg.startswith(f'[{area}] '): return area - return np.NaN + return np.nan def delete_prefix(msg): From a8c6b65520f814c5bd8f801be48c33ceece7c4a6 Mon Sep 17 00:00:00 2001 From: Maxim Sharabayko Date: Thu, 7 Nov 2024 09:26:05 +0100 Subject: [PATCH 07/14] [core] Fixed group import option. SRTO_CONNTIMEO, SRTO_PAYLOADSIZE, SRTO_PBKEYLEN had size autodetection bugs. --- srtcore/group.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/srtcore/group.cpp b/srtcore/group.cpp index e7f40d884..6b0b16484 100644 --- a/srtcore/group.cpp +++ b/srtcore/group.cpp @@ -517,7 +517,11 @@ void CUDTGroup::deriveSettings(CUDT* u) IM(SRTO_UDP_RCVBUF, iUDPRcvBufSize); // SRTO_RENDEZVOUS: impossible to have it set on a listener socket. // SRTO_SNDTIMEO/RCVTIMEO: groupwise setting - IM(SRTO_CONNTIMEO, tdConnTimeOut); + + // SRTO_CONNTIMEO requires a special handling, because API stores the value in integer milliseconds, + // but the type of the variable is srt::sync::duration. + importOption(m_config, SRTO_CONNTIMEO, (int) count_milliseconds(u->m_config.tdConnTimeOut)); + IM(SRTO_DRIFTTRACER, bDriftTracer); // Reuseaddr: true by default and should only be true. IM(SRTO_MAXBW, llMaxBW); @@ -530,7 +534,9 @@ void CUDTGroup::deriveSettings(CUDT* u) IM(SRTO_RCVLATENCY, iRcvLatency); IM(SRTO_PEERLATENCY, iPeerLatency); IM(SRTO_SNDDROPDELAY, iSndDropDelay); - IM(SRTO_PAYLOADSIZE, zExpPayloadSize); + // Special handling of SRTO_PAYLOADSIZE becuase API stores the value as int32_t, + // while the config structure stores it as size_t. + importOption(m_config, SRTO_PAYLOADSIZE, (int)u->m_config.zExpPayloadSize); IMF(SRTO_TLPKTDROP, m_bTLPktDrop); importOption(m_config, SRTO_STREAMID, u->m_config.sStreamName.str()); @@ -544,7 +550,7 @@ void CUDTGroup::deriveSettings(CUDT* u) importOption(m_config, SRTO_PACKETFILTER, u->m_config.sPacketFilterConfig.str()); - importOption(m_config, SRTO_PBKEYLEN, u->m_pCryptoControl->KeyLen()); + importOption(m_config, SRTO_PBKEYLEN, (int) u->m_pCryptoControl->KeyLen()); // Passphrase is empty by default. Decipher the passphrase and // store as passphrase option @@ -824,7 +830,7 @@ void CUDTGroup::getOpt(SRT_SOCKOPT optname, void* pw_optval, int& w_optlen) if (w_optlen < int(i->value.size())) throw CUDTException(MJ_NOTSUP, MN_XSIZE, 0); - w_optlen = i->value.size(); + w_optlen = (int) i->value.size(); memcpy((pw_optval), &i->value[0], i->value.size()); } From eb5b73f531588cf229d44aacda5f0cd7433148e6 Mon Sep 17 00:00:00 2001 From: Maxim Sharabayko Date: Thu, 14 Nov 2024 11:35:55 +0100 Subject: [PATCH 08/14] [core] Fix CUDTGroup::getOpt(..): check value length in group config storage. The storage could have empty strings, and dereferencing the first element must not happen. --- srtcore/group.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/srtcore/group.cpp b/srtcore/group.cpp index 6b0b16484..dbd809435 100644 --- a/srtcore/group.cpp +++ b/srtcore/group.cpp @@ -806,11 +806,9 @@ void CUDTGroup::getOpt(SRT_SOCKOPT optname, void* pw_optval, int& w_optlen) // Check if the option is in the storage, which means that // it was modified on the group. + vector::const_iterator i = find_if(m_config.begin(), m_config.end(), FOptionValue(optname)); - vector::const_iterator i = find_if(m_config.begin(), m_config.end(), - FOptionValue(optname)); - - if (i == m_config.end()) + if (i == m_config.end() || i->value.empty()) { // Already written to the target variable. if (is_set_on_socket) @@ -822,15 +820,14 @@ void CUDTGroup::getOpt(SRT_SOCKOPT optname, void* pw_optval, int& w_optlen) return; } - // NOTE: even if is_set_on_socket, if it was also found in the group - // settings, overwrite with the value from the group. - // Found, return the value from the storage. + // Found a value set on or derived by a group. Prefer returing it over the one taken from a member socket. // Check the size first. if (w_optlen < int(i->value.size())) throw CUDTException(MJ_NOTSUP, MN_XSIZE, 0); - w_optlen = (int) i->value.size(); + SRT_ASSERT(!i->value.empty()); + w_optlen = (int)i->value.size(); memcpy((pw_optval), &i->value[0], i->value.size()); } From 833880b4fb2111fe7d17ee4c8377cbb0cb7c330e Mon Sep 17 00:00:00 2001 From: Maxim Sharabayko Date: Thu, 14 Nov 2024 11:39:29 +0100 Subject: [PATCH 09/14] [core] Fixed deriving string options by a group. SRTO_STREAMID, SRTO_PACKETFILTER are directly affected. SRTO_PASSPHRASE was derived correctly. --- srtcore/group.cpp | 69 ++++++++++++++++++++++++++++-------------- srtcore/socketconfig.h | 6 ++++ 2 files changed, 52 insertions(+), 23 deletions(-) diff --git a/srtcore/group.cpp b/srtcore/group.cpp index dbd809435..3a9fc3f1d 100644 --- a/srtcore/group.cpp +++ b/srtcore/group.cpp @@ -444,23 +444,45 @@ static bool operator!=(const struct linger& l1, const struct linger& l2) return l1.l_onoff != l2.l_onoff || l1.l_linger != l2.l_linger; } +/// A function template to import socket option of a trivial type. +/// This includes linger, bool, int8_t, int32_t, int64_t, double, etc. +/// Potentially can be extended to trivially_copyable if needed. template -static void importOption(vector& storage, SRT_SOCKOPT optname, const ValueType& field) +static void importTrivialOption(vector& storage, SRT_SOCKOPT optname, const ValueType& optval, const int optsize = sizeof(ValueType)) { - ValueType default_opt = ValueType(); - static const int default_opt_size = sizeof(ValueType); - ValueType opt = field; - int opt_size = default_opt_size; - if (!getOptDefault(optname, (&default_opt), (opt_size)) || default_opt != opt) + SRT_STATIC_ASSERT(std::is_trivial::value, "ValueType must be a trivial type."); + ValueType optval_dflt = ValueType(); + int optsize_dflt = sizeof(ValueType); + if (!getOptDefault(optname, (&optval_dflt), (optsize_dflt)) || optval_dflt != optval) { - SRT_ASSERT(opt_size == default_opt_size); + SRT_ASSERT(optsize == sizeof(ValueType)); // Store the option when: // - no default for this option is found - // - the option value retrieved from the field is different than default - storage.push_back(CUDTGroup::ConfigItem(optname, &opt, default_opt_size)); + // - the option value retrieved from the field is different from the default one +#if HAVE_FULL_CXX11 + storage.emplace_back(optname, &optval, optsize); +#else + storage.push_back(CUDTGroup::ConfigItem(optname, &optval, optsize)); +#endif } } +/// A function template to import a StringStorage option. +template +static void importStringOption(vector& storage, SRT_SOCKOPT optname, const StringStorage& optval) +{ + if (optval.empty()) + return; + + // Store the option when: + // - option has a value (default is empty). +#if HAVE_FULL_CXX11 + storage.emplace_back(optname, optval.c_str(),(int) optval.size()); +#else + storage.push_back(CUDTGroup::ConfigItem(optname, optval.c_str(), (int) optval.size())); +#endif +} + // This function is called by the same premises as the CUDT::CUDT(const CUDT&) (copy constructor). // The intention is to rewrite the part that comprises settings from the socket // into the group. Note that some of the settings concern group, some others concern @@ -502,17 +524,18 @@ void CUDTGroup::deriveSettings(CUDT* u) // to be potentially replicated on the socket. So both pre // and post options apply. -#define IM(option, field) importOption(m_config, option, u->m_config.field) -#define IMF(option, field) importOption(m_config, option, u->field) +#define IM(option, field) importTrivialOption(m_config, option, u->m_config.field) +#define IMF(option, field) importTrivialOption(m_config, option, u->field) IM(SRTO_MSS, iMSS); IM(SRTO_FC, iFlightFlagSize); // Nonstandard - importOption(m_config, SRTO_SNDBUF, u->m_config.iSndBufSize * (u->m_config.iMSS - CPacket::UDP_HDR_SIZE)); - importOption(m_config, SRTO_RCVBUF, u->m_config.iRcvBufSize * (u->m_config.iMSS - CPacket::UDP_HDR_SIZE)); + importTrivialOption(m_config, SRTO_SNDBUF, u->m_config.iSndBufSize * (u->m_config.iMSS - CPacket::UDP_HDR_SIZE)); + importTrivialOption(m_config, SRTO_RCVBUF, u->m_config.iRcvBufSize * (u->m_config.iMSS - CPacket::UDP_HDR_SIZE)); IM(SRTO_LINGER, Linger); + IM(SRTO_UDP_SNDBUF, iUDPSndBufSize); IM(SRTO_UDP_RCVBUF, iUDPRcvBufSize); // SRTO_RENDEZVOUS: impossible to have it set on a listener socket. @@ -520,7 +543,7 @@ void CUDTGroup::deriveSettings(CUDT* u) // SRTO_CONNTIMEO requires a special handling, because API stores the value in integer milliseconds, // but the type of the variable is srt::sync::duration. - importOption(m_config, SRTO_CONNTIMEO, (int) count_milliseconds(u->m_config.tdConnTimeOut)); + importTrivialOption(m_config, SRTO_CONNTIMEO, (int) count_milliseconds(u->m_config.tdConnTimeOut)); IM(SRTO_DRIFTTRACER, bDriftTracer); // Reuseaddr: true by default and should only be true. @@ -536,10 +559,10 @@ void CUDTGroup::deriveSettings(CUDT* u) IM(SRTO_SNDDROPDELAY, iSndDropDelay); // Special handling of SRTO_PAYLOADSIZE becuase API stores the value as int32_t, // while the config structure stores it as size_t. - importOption(m_config, SRTO_PAYLOADSIZE, (int)u->m_config.zExpPayloadSize); + importTrivialOption(m_config, SRTO_PAYLOADSIZE, (int)u->m_config.zExpPayloadSize); IMF(SRTO_TLPKTDROP, m_bTLPktDrop); - importOption(m_config, SRTO_STREAMID, u->m_config.sStreamName.str()); + importStringOption(m_config, SRTO_STREAMID, u->m_config.sStreamName); IM(SRTO_MESSAGEAPI, bMessageAPI); IM(SRTO_NAKREPORT, bRcvNakReport); @@ -548,22 +571,22 @@ void CUDTGroup::deriveSettings(CUDT* u) IM(SRTO_IPV6ONLY, iIpV6Only); IM(SRTO_PEERIDLETIMEO, iPeerIdleTimeout_ms); - importOption(m_config, SRTO_PACKETFILTER, u->m_config.sPacketFilterConfig.str()); + importStringOption(m_config, SRTO_PACKETFILTER, u->m_config.sPacketFilterConfig); - importOption(m_config, SRTO_PBKEYLEN, (int) u->m_pCryptoControl->KeyLen()); + importTrivialOption(m_config, SRTO_PBKEYLEN, (int) u->m_pCryptoControl->KeyLen()); // Passphrase is empty by default. Decipher the passphrase and // store as passphrase option if (u->m_config.CryptoSecret.len) { - string password((const char*)u->m_config.CryptoSecret.str, u->m_config.CryptoSecret.len); - m_config.push_back(ConfigItem(SRTO_PASSPHRASE, password.c_str(), (int)password.size())); + const StringStorage password((const char*)u->m_config.CryptoSecret.str, u->m_config.CryptoSecret.len); + importStringOption(m_config, SRTO_PASSPHRASE, password); } IM(SRTO_KMREFRESHRATE, uKmRefreshRatePkt); IM(SRTO_KMPREANNOUNCE, uKmPreAnnouncePkt); - string cc = u->m_CongCtl.selected_name(); + const string cc = u->m_CongCtl.selected_name(); if (cc != "live") { m_config.push_back(ConfigItem(SRTO_CONGESTION, cc.c_str(), (int)cc.size())); @@ -592,7 +615,7 @@ bool CUDTGroup::applyFlags(uint32_t flags, HandshakeSide) template struct Value { - static int fill(void* optval, int, Type value) + static int fill(void* optval, int, const Type& value) { // XXX assert size >= sizeof(Type) ? *(Type*)optval = value; @@ -601,7 +624,7 @@ struct Value }; template <> -inline int Value::fill(void* optval, int len, std::string value) +inline int Value::fill(void* optval, int len, const std::string& value) { if (size_t(len) < value.size()) return 0; diff --git a/srtcore/socketconfig.h b/srtcore/socketconfig.h index 8a78ea21e..a6dd06caa 100644 --- a/srtcore/socketconfig.h +++ b/srtcore/socketconfig.h @@ -142,6 +142,12 @@ class StringStorage memset(stor, 0, sizeof stor); } + StringStorage(const char* s, size_t length) + : len(0) + { + set(s, length); + } + bool set(const char* s, size_t length) { if (length > SIZE) From 6ab86d8acb85849859ac9aa020f95b2da44674d8 Mon Sep 17 00:00:00 2001 From: Maxim Sharabayko Date: Thu, 14 Nov 2024 12:23:23 +0100 Subject: [PATCH 10/14] [tests] Extended Bonding.Options test with Stream ID and linger set/get check. --- test/test_bonding.cpp | 55 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/test/test_bonding.cpp b/test/test_bonding.cpp index 0e48c8a04..54199b1d6 100644 --- a/test/test_bonding.cpp +++ b/test/test_bonding.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -9,6 +10,7 @@ #include "srt.h" #include "netinet_any.h" +#include "socketconfig.h" TEST(Bonding, SRTConnectGroup) { @@ -330,6 +332,18 @@ TEST(Bonding, CloseGroupAndSocket) listen_promise.wait(); } +// (void* opaq, SRTSOCKET ns, int hsversion, const struct sockaddr* peeraddr, const char* streamid); +int ListenCallbackFn(void* expected_sid, SRTSOCKET, int /*hsversion*/, const sockaddr* /*peer*/, const char* streamid) +{ + const auto* p = (std::pair*) expected_sid; + // Note: It is not safe to access the streamid pointer by the expected size, + // but there is no way to know the real size apart from finding the first null terminator. + // See FR #3073. + EXPECT_EQ(std::memcmp(streamid, p->first, p->second), 0); + + return 0; +} + TEST(Bonding, Options) { using namespace std; @@ -346,12 +360,12 @@ TEST(Bonding, Options) //EXPECT_EQ(srt_setsockflag(grp, SRTO_RENDEZVOUS, &yes, sizeof yes), SRT_ERROR); #ifdef SRT_ENABLE_ENCRYPTION - string pass = "longenoughpassword"; + const string pass = "longenoughpassword"; // passphrase should be ok. - EXPECT_NE(srt_setsockflag(grp, SRTO_PASSPHRASE, pass.c_str(), pass.size()), SRT_ERROR); + EXPECT_NE(srt_setsockflag(grp, SRTO_PASSPHRASE, pass.c_str(), (int) pass.size()), SRT_ERROR); uint32_t val = 16; - EXPECT_NE(srt_setsockflag(grp, SRTO_PBKEYLEN, &val, sizeof val), SRT_ERROR); + EXPECT_NE(srt_setsockflag(grp, SRTO_PBKEYLEN, &val, (int) sizeof val), SRT_ERROR); #ifdef ENABLE_AEAD_API_PREVIEW val = 1; @@ -359,6 +373,35 @@ TEST(Bonding, Options) #endif #endif + // ================ + // Linger is an option of a trivial type, but differes from other integer-typed options. + // Therefore checking it specifically. + const linger l = {1, 10}; + srt_setsockflag(grp, SRTO_LINGER, &l, sizeof l); + + { + linger l2; + int optsize = sizeof l2; + EXPECT_NE(srt_getsockflag(grp, SRTO_LINGER, &l2, &optsize), SRT_ERROR); + EXPECT_EQ(optsize, (int)sizeof l2); + EXPECT_EQ(l2.l_onoff, l.l_onoff); + EXPECT_EQ(l2.l_linger, l.l_linger); + } + // ================ + + const std::array streamid = { 's', 't', 'r', 'e', 0, 'm', 'i', 'd', '%', '&'}; + EXPECT_NE(srt_setsockflag(grp, SRTO_STREAMID, &streamid, streamid.size()), SRT_ERROR); + + auto check_streamid = [&streamid](SRTSOCKET sock) { + std::array tmpbuf; + auto opt_len = (int)tmpbuf.size(); + EXPECT_EQ(srt_getsockflag(sock, SRTO_STREAMID, tmpbuf.data(), &opt_len), SRT_SUCCESS); + EXPECT_EQ(size_t(opt_len), streamid.size()); + EXPECT_EQ(std::memcmp(tmpbuf.data(), streamid.data(), opt_len), 0); + }; + + check_streamid(grp); + int lat = 500; EXPECT_NE(srt_setsockflag(grp, SRTO_RCVLATENCY, &lat, sizeof lat), SRT_ERROR); @@ -371,6 +414,10 @@ TEST(Bonding, Options) unique_lock ux(mx); SRTSOCKET lsn = srt_create_socket(); + + auto expected_sid = std::make_pair(streamid.data(), streamid.size()); + srt_listen_callback(lsn, &ListenCallbackFn, (void*) &expected_sid); + #ifdef SRT_ENABLE_ENCRYPTION EXPECT_NE(srt_setsockflag(lsn, SRTO_PASSPHRASE, pass.c_str(), pass.size()), SRT_ERROR); #endif @@ -388,6 +435,8 @@ TEST(Bonding, Options) SRTSOCKET gs = srt_accept(lsn, revsa.get(), &revsa.len); ASSERT_NE(gs, SRT_ERROR); + check_streamid(gs); + // Connected, wait to close latch.wait(ux); From 3931af64fbe87543d8fc65a9ff067a7e07c9eed7 Mon Sep 17 00:00:00 2001 From: Maxim Sharabayko Date: Tue, 19 Nov 2024 16:12:16 +0100 Subject: [PATCH 11/14] [tests] Minor clean up of socket options tests (#3076). Using std::array where possible. --- test/test_socket_options.cpp | 218 +++++++++++++++-------------------- 1 file changed, 95 insertions(+), 123 deletions(-) diff --git a/test/test_socket_options.cpp b/test/test_socket_options.cpp index 84a93030b..58e60e761 100644 --- a/test/test_socket_options.cpp +++ b/test/test_socket_options.cpp @@ -30,34 +30,28 @@ class TestSocketOptions : public ::srt::Test { protected: - TestSocketOptions() - { - // initialization code here - } + TestSocketOptions() = default; - ~TestSocketOptions() - { - // cleanup any pending stuff, but no exceptions allowed - } + ~TestSocketOptions() override = default; public: - void BindListener() + void BindListener() const { // Specify address of the listener - sockaddr* psa = (sockaddr*)&m_sa; + const auto* psa = (const sockaddr*)&m_sa; ASSERT_NE(srt_bind(m_listen_sock, psa, sizeof m_sa), SRT_ERROR); } - void StartListener() + void StartListener() const { BindListener(); srt_listen(m_listen_sock, 1); } - int Connect() + int Connect() const { - sockaddr* psa = (sockaddr*)&m_sa; + const auto* psa = (const sockaddr*)&m_sa; return srt_connect(m_caller_sock, psa, sizeof m_sa); } @@ -85,7 +79,7 @@ class TestSocketOptions protected: // setup() is run immediately before a test starts. - void setup() + void setup() override { const int yes = 1; @@ -105,7 +99,7 @@ class TestSocketOptions ASSERT_EQ(srt_setsockopt(m_listen_sock, 0, SRTO_SNDSYN, &yes, sizeof yes), SRT_SUCCESS); // for async connect } - void teardown() + void teardown() override { // Code here will be called just after the test completes. // OK to throw exceptions from here if needed. @@ -113,7 +107,6 @@ class TestSocketOptions EXPECT_NE(srt_close(m_listen_sock), SRT_ERROR); } -protected: sockaddr_in m_sa; SRTSOCKET m_caller_sock = SRT_INVALID_SOCK; SRTSOCKET m_listen_sock = SRT_INVALID_SOCK; @@ -121,7 +114,6 @@ class TestSocketOptions int m_pollid = 0; }; - enum class RestrictionType { PREBIND = 0, @@ -131,21 +123,13 @@ enum class RestrictionType const char* RestrictionTypeStr(RestrictionType val) { - switch (val) - { - case RestrictionType::PREBIND: - return "PREBIND"; - break; - case RestrictionType::PRE: - return "PRE"; - break; - case RestrictionType::POST: - return "POST"; - break; - default: - break; - } - return "INVALID"; + const std::map type_to_str = { + { RestrictionType::PREBIND, "PREBIND" }, + { RestrictionType::PRE, "PRE" }, + { RestrictionType::POST, "POST" } + }; + + return type_to_str.find(val) != type_to_str.end() ? type_to_str.at(val) : "INVALID"; } struct OptionTestEntry @@ -249,16 +233,16 @@ void CheckGetSockOpt(const OptionTestEntry& entry, SRTSOCKET sock, const ValueTy EXPECT_EQ(opt_len, (int) entry.opt_len) << desc << "Wrong " << entry.optname << " value length"; } -typedef char const* strptr; +using strptr = const char *; template<> void CheckGetSockOpt(const OptionTestEntry& entry, SRTSOCKET sock, const strptr& value, const char* desc) { - char opt_val[16]; + std::array opt_val; int opt_len = 0; - EXPECT_EQ(srt_getsockopt(sock, 0, entry.optid, &opt_val, &opt_len), SRT_SUCCESS) + EXPECT_EQ(srt_getsockopt(sock, 0, entry.optid, opt_val.data(), &opt_len), SRT_SUCCESS) << "Getting " << entry.optname << " returned error: " << srt_getlasterror_str(); - EXPECT_EQ(strncmp(opt_val, value, min(opt_len, (int)entry.opt_len)), 0) << desc << ": Wrong " << entry.optname << " value " << opt_val; + EXPECT_EQ(strncmp(opt_val.data(), value, min(opt_len, (int)entry.opt_len)), 0) << desc << ": Wrong " << entry.optname << " value " << opt_val.data(); EXPECT_EQ(opt_len, (int) entry.opt_len) << desc << "Wrong " << entry.optname << " value length"; } @@ -484,25 +468,22 @@ TEST_F(TestSocketOptions, InvalidVals) } } +const char* StateToStr(SRT_SOCKSTATUS st) +{ + std::map st_to_str = { + { SRTS_INIT, "SRTS_INIT" }, + { SRTS_OPENED, "SRTS_OPENED" }, + { SRTS_LISTENING, "SRTS_LISTENING" }, + { SRTS_CONNECTING, "SRTS_CONNECTING" }, + { SRTS_CONNECTED, "SRTS_CONNECTED" }, + { SRTS_BROKEN, "SRTS_BROKEN" }, + { SRTS_CLOSING, "SRTS_CLOSING" }, + { SRTS_CLOSED, "SRTS_CLOSED" }, + { SRTS_NONEXIST, "SRTS_NONEXIST" } + }; - -// TODO: taken from test_enforced_encryption -static const char* const socket_state_array[] = { - "IGNORE_SRTS", - "SRTS_INVALID", - "SRTS_INIT", - "SRTS_OPENED", - "SRTS_LISTENING", - "SRTS_CONNECTING", - "SRTS_CONNECTED", - "SRTS_BROKEN", - "SRTS_CLOSING", - "SRTS_CLOSED", - "SRTS_NONEXIST" -}; - -// A trick that allows the array to be indexed by -1 -const char* const* g_socket_state = socket_state_array + 1; + return st_to_str.find(st) != st_to_str.end() ? st_to_str.at(st) : "INVALID"; +} #if 0 // No socket option can be set in blocking mode because m_ConnectionLock is required by both srt_setsockopt and srt_connect @@ -551,17 +532,17 @@ TEST_F(TestSocketOptions, RestrictionBind) if (entry.dflt_val.type() == typeid(bool)) { EXPECT_TRUE(CheckSetNonDefaultValue(entry, m_listen_sock, expected_res, test_desc)) - << "Sock state : " << g_socket_state[srt_getsockstate(m_listen_sock)]; + << "Sock state : " << StateToStr(srt_getsockstate(m_listen_sock)); } else if (entry.dflt_val.type() == typeid(int)) { EXPECT_TRUE(CheckSetNonDefaultValue(entry, m_listen_sock, expected_res, test_desc)) - << "Sock state : " << g_socket_state[srt_getsockstate(m_listen_sock)]; + << "Sock state : " << StateToStr(srt_getsockstate(m_listen_sock)); } else if (entry.dflt_val.type() == typeid(int64_t)) { EXPECT_TRUE(CheckSetNonDefaultValue(entry, m_listen_sock, expected_res, test_desc)) - << "Sock state : " << g_socket_state[srt_getsockstate(m_listen_sock)]; + << "Sock state : " << StateToStr(srt_getsockstate(m_listen_sock)); } else { @@ -585,17 +566,17 @@ TEST_F(TestSocketOptions, RestrictionListening) if (entry.dflt_val.type() == typeid(bool)) { EXPECT_TRUE(CheckSetNonDefaultValue(entry, m_listen_sock, expected_res, test_desc)) - << test_desc << entry.optname << " Sock state: " << g_socket_state[srt_getsockstate(m_listen_sock)]; + << test_desc << entry.optname << " Sock state: " << StateToStr(srt_getsockstate(m_listen_sock)); } else if (entry.dflt_val.type() == typeid(int)) { EXPECT_TRUE(CheckSetNonDefaultValue(entry, m_listen_sock, expected_res, test_desc)) - << test_desc << entry.optname << " Sock state: " << g_socket_state[srt_getsockstate(m_listen_sock)]; + << test_desc << entry.optname << " Sock state: " << StateToStr(srt_getsockstate(m_listen_sock)); } else if (entry.dflt_val.type() == typeid(int64_t)) { EXPECT_TRUE(CheckSetNonDefaultValue(entry, m_listen_sock, expected_res, test_desc)) - << test_desc << entry.optname << " Sock state: " << g_socket_state[srt_getsockstate(m_listen_sock)]; + << test_desc << entry.optname << " Sock state: " << StateToStr(srt_getsockstate(m_listen_sock)); } else { @@ -622,17 +603,17 @@ TEST_F(TestSocketOptions, RestrictionConnected) if (entry.dflt_val.type() == typeid(bool)) { EXPECT_TRUE(CheckSetNonDefaultValue(entry, sock, expected_res, test_desc)) - << test_desc << entry.optname << " Sock state: " << g_socket_state[srt_getsockstate(sock)]; + << test_desc << entry.optname << " Sock state: " << StateToStr(srt_getsockstate(sock)); } else if (entry.dflt_val.type() == typeid(int)) { EXPECT_TRUE(CheckSetNonDefaultValue(entry, sock, expected_res, test_desc)) - << test_desc << entry.optname << " Sock state: " << g_socket_state[srt_getsockstate(sock)]; + << test_desc << entry.optname << " Sock state: " << StateToStr(srt_getsockstate(sock)); } else if (entry.dflt_val.type() == typeid(int64_t)) { EXPECT_TRUE(CheckSetNonDefaultValue(entry, sock, expected_res, test_desc)) - << test_desc << entry.optname << " Sock state: " << g_socket_state[srt_getsockstate(sock)]; + << test_desc << entry.optname << " Sock state: " << StateToStr(srt_getsockstate(sock)); } else { @@ -783,7 +764,7 @@ TEST_F(TestSocketOptions, MinInputBWSet) { const int64_t mininputbw_dflt = 0; const int64_t mininputbw = 50000000; - int optlen = (int)(sizeof mininputbw); + auto optlen = (int)(sizeof mininputbw); int64_t bw = -100; EXPECT_EQ(srt_setsockopt(m_listen_sock, 0, SRTO_MININPUTBW, &bw, sizeof bw), SRT_ERROR) << "Has to be a non-negative number"; @@ -849,15 +830,15 @@ TEST_F(TestSocketOptions, MinInputBWRuntime) TEST_F(TestSocketOptions, StreamIDWrongLen) { - char buffer[CSrtConfig::MAX_SID_LENGTH + 135]; - for (size_t i = 0; i < sizeof buffer; ++i) + std::array buffer; + for (size_t i = 0; i < buffer.size(); ++i) buffer[i] = 'a' + i % 25; - EXPECT_EQ(srt_setsockopt(m_caller_sock, 0, SRTO_STREAMID, buffer, CSrtConfig::MAX_SID_LENGTH+1), SRT_ERROR); - EXPECT_EQ(srt_getlasterror(NULL), SRT_EINVPARAM); + EXPECT_EQ(srt_setsockopt(m_caller_sock, 0, SRTO_STREAMID, buffer.data(), CSrtConfig::MAX_SID_LENGTH + 1), SRT_ERROR); + EXPECT_EQ(srt_getlasterror(nullptr), SRT_EINVPARAM); } -//Check if setting -1 as optlen returns an error +// Check if setting -1 as optlen returns an error TEST_F(TestSocketOptions, StringOptLenInvalid) { const string test_string = "test1234567"; @@ -865,19 +846,19 @@ TEST_F(TestSocketOptions, StringOptLenInvalid) const string fec_config = "fec,cols:10,rows:10"; EXPECT_EQ(srt_setsockopt(m_caller_sock, 0, SRTO_STREAMID, test_string.c_str(), -1), SRT_ERROR); - EXPECT_EQ(srt_getlasterror(NULL), SRT_EINVPARAM); + EXPECT_EQ(srt_getlasterror(nullptr), SRT_EINVPARAM); EXPECT_EQ(srt_setsockopt(m_caller_sock, 0, SRTO_BINDTODEVICE, test_string.c_str(), -1), SRT_ERROR); - EXPECT_EQ(srt_getlasterror(NULL), SRT_EINVPARAM); + EXPECT_EQ(srt_getlasterror(nullptr), SRT_EINVPARAM); EXPECT_EQ(srt_setsockopt(m_caller_sock, 0, SRTO_CONGESTION, srto_congestion_string.c_str(), -1), SRT_ERROR); - EXPECT_EQ(srt_getlasterror(NULL), SRT_EINVPARAM); + EXPECT_EQ(srt_getlasterror(nullptr), SRT_EINVPARAM); EXPECT_EQ(srt_setsockopt(m_caller_sock, 0, SRTO_PACKETFILTER, fec_config.c_str(), -1), SRT_ERROR); - EXPECT_EQ(srt_getlasterror(NULL), SRT_EINVPARAM); + EXPECT_EQ(srt_getlasterror(nullptr), SRT_EINVPARAM); EXPECT_EQ(srt_setsockopt(m_caller_sock, 0, SRTO_PASSPHRASE, test_string.c_str(), -1), SRT_ERROR); - EXPECT_EQ(srt_getlasterror(NULL), SRT_EINVPARAM); + EXPECT_EQ(srt_getlasterror(nullptr), SRT_EINVPARAM); } // Try to set/get a 13-character string in SRTO_STREAMID. @@ -890,23 +871,22 @@ TEST_F(TestSocketOptions, StreamIDOdd) EXPECT_EQ(srt_setsockopt(m_caller_sock, 0, SRTO_STREAMID, sid_odd.c_str(), (int)sid_odd.size()), SRT_SUCCESS); - char buffer[CSrtConfig::MAX_SID_LENGTH + 135]; - int buffer_len = sizeof buffer; - EXPECT_EQ(srt_getsockopt(m_caller_sock, 0, SRTO_STREAMID, &buffer, &buffer_len), SRT_SUCCESS); - EXPECT_EQ(std::string(buffer), sid_odd); + array buffer; + auto buffer_len = (int) buffer.size(); + EXPECT_EQ(srt_getsockopt(m_caller_sock, 0, SRTO_STREAMID, buffer.data(), &buffer_len), SRT_SUCCESS); + EXPECT_EQ(std::string(buffer.data()), sid_odd); EXPECT_EQ(size_t(buffer_len), sid_odd.size()); - EXPECT_EQ(strlen(buffer), sid_odd.size()); + EXPECT_EQ(strlen(buffer.data()), sid_odd.size()); StartListener(); const SRTSOCKET accepted_sock = EstablishConnection(); // Check accepted socket inherits values - for (size_t i = 0; i < sizeof buffer; ++i) - buffer[i] = 'a'; - buffer_len = (int)(sizeof buffer); + fill(buffer.begin(), buffer.end(), 'a'); + buffer_len = (int) buffer.size(); EXPECT_EQ(srt_getsockopt(accepted_sock, 0, SRTO_STREAMID, &buffer, &buffer_len), SRT_SUCCESS); EXPECT_EQ(size_t(buffer_len), sid_odd.size()); - EXPECT_EQ(strlen(buffer), sid_odd.size()); + EXPECT_EQ(strlen(buffer.data()), sid_odd.size()); ASSERT_NE(srt_close(accepted_sock), SRT_ERROR); } @@ -919,23 +899,22 @@ TEST_F(TestSocketOptions, StreamIDEven) EXPECT_EQ(srt_setsockopt(m_caller_sock, 0, SRTO_STREAMID, sid_even.c_str(), (int)sid_even.size()), SRT_SUCCESS); - char buffer[CSrtConfig::MAX_SID_LENGTH + 135]; - int buffer_len = sizeof buffer; - EXPECT_EQ(srt_getsockopt(m_caller_sock, 0, SRTO_STREAMID, &buffer, &buffer_len), SRT_SUCCESS); - EXPECT_EQ(std::string(buffer), sid_even); + array buffer; + auto buffer_len = (int) buffer.size(); + EXPECT_EQ(srt_getsockopt(m_caller_sock, 0, SRTO_STREAMID, buffer.data(), &buffer_len), SRT_SUCCESS); + EXPECT_EQ(std::string(buffer.data()), sid_even); EXPECT_EQ(size_t(buffer_len), sid_even.size()); - EXPECT_EQ(strlen(buffer), sid_even.size()); + EXPECT_EQ(strlen(buffer.data()), sid_even.size()); StartListener(); const SRTSOCKET accepted_sock = EstablishConnection(); // Check accepted socket inherits values - for (size_t i = 0; i < sizeof buffer; ++i) - buffer[i] = 'a'; - buffer_len = (int)(sizeof buffer); + fill(buffer.begin(), buffer.end(), 'a'); + buffer_len = (int) buffer.size(); EXPECT_EQ(srt_getsockopt(accepted_sock, 0, SRTO_STREAMID, &buffer, &buffer_len), SRT_SUCCESS); EXPECT_EQ(size_t(buffer_len), sid_even.size()); - EXPECT_EQ(strlen(buffer), sid_even.size()); + EXPECT_EQ(strlen(buffer.data()), sid_even.size()); ASSERT_NE(srt_close(accepted_sock), SRT_ERROR); } @@ -945,20 +924,18 @@ TEST_F(TestSocketOptions, StreamIDEven) TEST_F(TestSocketOptions, StreamIDAlmostFull) { // 12 characters = 4*3, that is, aligned to 4 - std::array sid_almost_full; + array sid_almost_full; const size_t size = sid_almost_full.size(); - for (size_t i = 0; i < size; ++i) - sid_almost_full[i] += 'x'; - // Just to manipulate the last ones. + sid_almost_full.fill('x'); sid_almost_full[size-2] = '\0'; sid_almost_full[size-1] = 'z'; EXPECT_EQ(srt_setsockopt(m_caller_sock, 0, SRTO_STREAMID, sid_almost_full.data(), (int)size), SRT_SUCCESS); std::array buffer; - int buffer_len = (int) buffer.size(); - EXPECT_EQ(srt_getsockopt(m_caller_sock, 0, SRTO_STREAMID, &buffer, &buffer_len), SRT_SUCCESS); + auto buffer_len = (int) buffer.size(); + EXPECT_EQ(srt_getsockopt(m_caller_sock, 0, SRTO_STREAMID, buffer.data(), &buffer_len), SRT_SUCCESS); EXPECT_EQ(size_t(buffer_len), sid_almost_full.size()); EXPECT_EQ(std::memcmp(buffer.data(), sid_almost_full.data(), buffer_len), 0); @@ -967,8 +944,7 @@ TEST_F(TestSocketOptions, StreamIDAlmostFull) // Check accepted socket inherits values buffer_len = (int) buffer.size(); - for (int i = 0; i < buffer_len; ++i) - buffer[i] = 'a'; + fill(buffer.begin(), buffer.end(), 'a'); EXPECT_EQ(srt_getsockopt(accepted_sock, 0, SRTO_STREAMID, &buffer, &buffer_len), SRT_SUCCESS); EXPECT_EQ(size_t(buffer_len), sid_almost_full.size()); EXPECT_EQ(std::memcmp(buffer.data(), sid_almost_full.data(), buffer_len), 0); @@ -981,35 +957,31 @@ TEST_F(TestSocketOptions, StreamIDAlmostFull) TEST_F(TestSocketOptions, StreamIDFull) { // 12 characters = 4*3, that is, aligned to 4 - string sid_full; - for (size_t i = 0; i < CSrtConfig::MAX_SID_LENGTH; ++i) - sid_full += 'x'; + array sid_full; + sid_full.fill('x'); // Just to manipulate the last ones. size_t size = sid_full.size(); - sid_full[size-2] = 'y'; + sid_full[size-2] = '\0'; sid_full[size-1] = 'z'; - EXPECT_EQ(srt_setsockopt(m_caller_sock, 0, SRTO_STREAMID, sid_full.c_str(), (int)sid_full.size()), SRT_SUCCESS); + EXPECT_EQ(srt_setsockopt(m_caller_sock, 0, SRTO_STREAMID, sid_full.data(), (int)sid_full.size()), SRT_SUCCESS); - char buffer[CSrtConfig::MAX_SID_LENGTH + 135]; - int buffer_len = sizeof buffer; - EXPECT_EQ(srt_getsockopt(m_caller_sock, 0, SRTO_STREAMID, &buffer, &buffer_len), SRT_SUCCESS); - EXPECT_EQ(std::string(buffer), sid_full); + array buffer; + auto buffer_len = (int) buffer.size(); + EXPECT_EQ(srt_getsockopt(m_caller_sock, 0, SRTO_STREAMID, buffer.data(), &buffer_len), SRT_SUCCESS); + EXPECT_EQ(memcmp(buffer.data(), sid_full.data(), sid_full.size()), 0); EXPECT_EQ(size_t(buffer_len), sid_full.size()); - EXPECT_EQ(strlen(buffer), sid_full.size()); StartListener(); const SRTSOCKET accepted_sock = EstablishConnection(); // Check accepted socket inherits values - for (size_t i = 0; i < sizeof buffer; ++i) - buffer[i] = 'a'; - buffer_len = (int)(sizeof buffer); - EXPECT_EQ(srt_getsockopt(accepted_sock, 0, SRTO_STREAMID, &buffer, &buffer_len), SRT_SUCCESS); + fill(buffer.begin(), buffer.end(), 'a'); + buffer_len = (int) buffer.size(); + EXPECT_EQ(srt_getsockopt(accepted_sock, 0, SRTO_STREAMID, buffer.data(), &buffer_len), SRT_SUCCESS); EXPECT_EQ(size_t(buffer_len), sid_full.size()); - EXPECT_EQ(strlen(buffer), sid_full.size()); - EXPECT_EQ(buffer[sid_full.size()-1], 'z'); + EXPECT_EQ(std::memcmp(buffer.data(), sid_full.data(), buffer_len), 0); ASSERT_NE(srt_close(accepted_sock), SRT_ERROR); } @@ -1022,10 +994,10 @@ TEST_F(TestSocketOptions, StreamIDLenListener) EXPECT_EQ(srt_setsockopt(m_listen_sock, 0, SRTO_STREAMID, stream_id_13.c_str(), (int)stream_id_13.size()), SRT_SUCCESS); - char buffer[648]; - int buffer_len = sizeof buffer; - EXPECT_EQ(srt_getsockopt(m_listen_sock, 0, SRTO_STREAMID, &buffer, &buffer_len), SRT_SUCCESS); - EXPECT_EQ(string(buffer), stream_id_13); + array buffer; + auto buffer_len = (int) buffer.size(); + EXPECT_EQ(srt_getsockopt(m_listen_sock, 0, SRTO_STREAMID, buffer.data(), &buffer_len), SRT_SUCCESS); + EXPECT_EQ(string(buffer.data()), stream_id_13); EXPECT_EQ(size_t(buffer_len), stream_id_13.size()); StartListener(); @@ -1034,9 +1006,9 @@ TEST_F(TestSocketOptions, StreamIDLenListener) // Check accepted and caller sockets do not inherit StreamID. for (SRTSOCKET sock : { m_caller_sock, accepted_sock }) { - buffer_len = (int)(sizeof buffer); - fill_n(buffer, buffer_len, 'a'); - EXPECT_EQ(srt_getsockopt(sock, 0, SRTO_STREAMID, &buffer, &buffer_len), SRT_SUCCESS); + buffer_len = (int) buffer.size(); + fill_n(buffer.data(), buffer_len, 'a'); + EXPECT_EQ(srt_getsockopt(sock, 0, SRTO_STREAMID, buffer.data(), &buffer_len), SRT_SUCCESS); EXPECT_EQ(buffer_len, 0) << (sock == accepted_sock ? "ACCEPTED" : "CALLER"); } From 5f16494f584e52b08a5dcdc55fe891d01d02f3a4 Mon Sep 17 00:00:00 2001 From: Maxim Sharabayko Date: Tue, 19 Nov 2024 16:25:53 +0100 Subject: [PATCH 12/14] [core] Fixed getting SRTO_RCVBUF and SRTO_SNDBUF on a group. The documented length is 4 bytes, the code was setting 8 bytes without checking `optlen`. --- srtcore/group.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/srtcore/group.cpp b/srtcore/group.cpp index 3a9fc3f1d..c0df17ac8 100644 --- a/srtcore/group.cpp +++ b/srtcore/group.cpp @@ -472,7 +472,7 @@ template static void importStringOption(vector& storage, SRT_SOCKOPT optname, const StringStorage& optval) { if (optval.empty()) - return; + return; // Store the option when: // - option has a value (default is empty). @@ -615,9 +615,11 @@ bool CUDTGroup::applyFlags(uint32_t flags, HandshakeSide) template struct Value { - static int fill(void* optval, int, const Type& value) + static int fill(void* optval, int len, const Type& value) { - // XXX assert size >= sizeof(Type) ? + if (size_t(len) < sizeof(Type)) + return 0; + *(Type*)optval = value; return sizeof(Type); } @@ -671,7 +673,7 @@ static bool getOptDefault(SRT_SOCKOPT optname, void* pw_optval, int& w_optlen) case SRTO_SNDBUF: case SRTO_RCVBUF: - w_optlen = fillValue((pw_optval), w_optlen, CSrtConfig::DEF_BUFFER_SIZE * (CSrtConfig::DEF_MSS - CPacket::UDP_HDR_SIZE)); + w_optlen = fillValue((pw_optval), w_optlen, CSrtConfig::DEF_BUFFER_SIZE * (CSrtConfig::DEF_MSS - CPacket::UDP_HDR_SIZE)); break; case SRTO_LINGER: From 87850b7926860889e2525853f8411b711dee4e6f Mon Sep 17 00:00:00 2001 From: Maxim Sharabayko Date: Mon, 25 Nov 2024 11:17:44 +0100 Subject: [PATCH 13/14] [docs] Fixed link to rejection codes document. --- docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index 8c07ee515..83baf258b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -7,7 +7,7 @@ | [SRT API](API/API.md) | [API](API/) | [API.md](API/API.md) | Detailed description of the SRT C API. | | [SRT API Functions](API/API-functions.md) | [API](API/) | [API-functions.md](API/API-functions.md) | Reference document for SRT API functions. | | [SRT API Socket Options](API/API-socket-options.md) | [API](API/) | [API-socket-options.md](API/API-socket-options.md) | Instructions and list of socket options for SRT API. | -| [SRT Rejection Codes](API/rejections-codes.md) | [API](API/) | [rejection-codes.md](API/rejection-codes.md) | The list of SRT rejections codes. | +| [SRT Rejection Codes](API/rejection-codes.md) | [API](API/) | [rejection-codes.md](API/rejection-codes.md) | The list of SRT rejections codes. | | [SRT Statistics](API/statistics.md) | [API](API/) | [statistics.md](API/statistics.md) | How to use SRT socket and socket group statistics. | | [Configuration Guidelines](API/configuration-guidelines.md) | [API](API/) | [configuration-guidelines.md](API/configuration-guidelines.md) | How to configure SRT buffers. | | | | | | From cdbe5f515281e7d1050c6046bf372743e0bbcd5b Mon Sep 17 00:00:00 2001 From: Maxim Sharabayko Date: Wed, 27 Nov 2024 12:52:54 +0100 Subject: [PATCH 14/14] [docs] Updated conan badge links. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0bf810144..b6465a347 100644 --- a/README.md +++ b/README.md @@ -223,8 +223,8 @@ By contributing code to the SRT project, you agree to license your contribution [Vcpkg-package]: https://repology.org/project/srt/versions [Vcpkg-badge]: https://repology.org/badge/version-for-repo/vcpkg/srt.svg -[ConanCenter-package]: https://repology.org/project/srt/versions -[ConanCenter-badge]: https://repology.org/badge/version-for-repo/conancenter/srt.svg +[ConanCenter-package]: https://conan.io/center/recipes/srt +[ConanCenter-badge]: https://img.shields.io/conan/v/srt [sonarcloud-project]: https://sonarcloud.io/project/overview?id=srt [sonarcloud-badge]: https://sonarcloud.io/api/project_badges/measure?project=srt&metric=alert_status