From 24609bce15859eb826b7f0b1a90534433aa69558 Mon Sep 17 00:00:00 2001 From: Maxim Sharabayko Date: Thu, 14 Nov 2024 11:39:29 +0100 Subject: [PATCH] [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)