Skip to content

Commit

Permalink
[core] Fixed deriving string options by a group.
Browse files Browse the repository at this point in the history
SRTO_STREAMID, SRTO_PACKETFILTER are directly affected.
SRTO_PASSPHRASE was derived correctly.
  • Loading branch information
maxsharabayko committed Nov 14, 2024
1 parent eb5b73f commit 833880b
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 23 deletions.
69 changes: 46 additions & 23 deletions srtcore/group.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <class ValueType>
static void importOption(vector<CUDTGroup::ConfigItem>& storage, SRT_SOCKOPT optname, const ValueType& field)
static void importTrivialOption(vector<CUDTGroup::ConfigItem>& 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<ValueType>::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 <size_t N>
static void importStringOption(vector<CUDTGroup::ConfigItem>& storage, SRT_SOCKOPT optname, const StringStorage<N>& 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
Expand Down Expand Up @@ -502,25 +524,26 @@ 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.
// SRTO_SNDTIMEO/RCVTIMEO: groupwise setting

// 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.
Expand All @@ -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);
Expand All @@ -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<HAICRYPT_SECRET_MAX_SZ> 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()));
Expand Down Expand Up @@ -592,7 +615,7 @@ bool CUDTGroup::applyFlags(uint32_t flags, HandshakeSide)
template <class Type>
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;
Expand All @@ -601,7 +624,7 @@ struct Value
};

template <>
inline int Value<std::string>::fill(void* optval, int len, std::string value)
inline int Value<std::string>::fill(void* optval, int len, const std::string& value)
{
if (size_t(len) < value.size())
return 0;
Expand Down
6 changes: 6 additions & 0 deletions srtcore/socketconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 833880b

Please sign in to comment.