mirror of
				https://github.com/ossrs/srs.git
				synced 2025-03-09 15:49:59 +00:00 
			
		
		
		
	fix https://github.com/ossrs/srs/issues/3155 Build srt-1-fit fails with `standard attributes in middle of decl-specifiers` on GCC 12,Arch Linux. See https://github.com/Haivision/srt/releases/tag/v1.5.3
		
			
				
	
	
		
			1095 lines
		
	
	
	
		
			34 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1095 lines
		
	
	
	
		
			34 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
 * SRT - Secure, Reliable, Transport
 | 
						|
 * Copyright (c) 2018 Haivision Systems Inc.
 | 
						|
 *
 | 
						|
 * This Source Code Form is subject to the terms of the Mozilla Public
 | 
						|
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
						|
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
/*****************************************************************************
 | 
						|
Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois.
 | 
						|
All rights reserved.
 | 
						|
 | 
						|
Redistribution and use in source and binary forms, with or without
 | 
						|
modification, are permitted provided that the following conditions are
 | 
						|
met:
 | 
						|
 | 
						|
* Redistributions of source code must retain the above
 | 
						|
  copyright notice, this list of conditions and the
 | 
						|
  following disclaimer.
 | 
						|
 | 
						|
* Redistributions in binary form must reproduce the
 | 
						|
  above copyright notice, this list of conditions
 | 
						|
  and the following disclaimer in the documentation
 | 
						|
  and/or other materials provided with the distribution.
 | 
						|
 | 
						|
* Neither the name of the University of Illinois
 | 
						|
  nor the names of its contributors may be used to
 | 
						|
  endorse or promote products derived from this
 | 
						|
  software without specific prior written permission.
 | 
						|
 | 
						|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 | 
						|
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 | 
						|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 | 
						|
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 | 
						|
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 | 
						|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 | 
						|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 | 
						|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 | 
						|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 | 
						|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 | 
						|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
						|
*****************************************************************************/
 | 
						|
 | 
						|
/*****************************************************************************
 | 
						|
written by
 | 
						|
   Haivision Systems Inc.
 | 
						|
*****************************************************************************/
 | 
						|
#include <utility>
 | 
						|
 | 
						|
#include "srt.h"
 | 
						|
#include "socketconfig.h"
 | 
						|
 | 
						|
using namespace srt;
 | 
						|
extern const int32_t SRT_DEF_VERSION = SrtParseVersion(SRT_VERSION);
 | 
						|
 | 
						|
namespace {
 | 
						|
typedef void setter_function(CSrtConfig& co, const void* optval, int optlen);
 | 
						|
 | 
						|
template<SRT_SOCKOPT name>
 | 
						|
struct CSrtConfigSetter
 | 
						|
{
 | 
						|
    static setter_function set;
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_MSS>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        const int ival = cast_optval<int>(optval, optlen);
 | 
						|
        if (ival < int(CPacket::UDP_HDR_SIZE + CHandShake::m_iContentSize))
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
 | 
						|
        co.iMSS = ival;
 | 
						|
 | 
						|
        // Packet size cannot be greater than UDP buffer size
 | 
						|
        if (co.iMSS > co.iUDPSndBufSize)
 | 
						|
            co.iMSS = co.iUDPSndBufSize;
 | 
						|
        if (co.iMSS > co.iUDPRcvBufSize)
 | 
						|
            co.iMSS = co.iUDPRcvBufSize;
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_FC>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        using namespace srt_logging;
 | 
						|
        const int fc = cast_optval<int>(optval, optlen);
 | 
						|
        if (fc < co.DEF_MIN_FLIGHT_PKT)
 | 
						|
        {
 | 
						|
            LOGC(kmlog.Error, log << "SRTO_FC: minimum allowed value is 32 (provided: " << fc << ")");
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL);
 | 
						|
        }
 | 
						|
 | 
						|
        co.iFlightFlagSize = fc;
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_SNDBUF>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        int bs = cast_optval<int>(optval, optlen);
 | 
						|
        if (bs <= 0)
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
 | 
						|
        co.iSndBufSize = bs / (co.iMSS - CPacket::UDP_HDR_SIZE);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_RCVBUF>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        const int val = cast_optval<int>(optval, optlen);
 | 
						|
        if (val <= 0)
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
 | 
						|
        // Mimimum recv buffer size is 32 packets
 | 
						|
        const int mssin_size = co.iMSS - CPacket::UDP_HDR_SIZE;
 | 
						|
 | 
						|
        if (val > mssin_size * co.DEF_MIN_FLIGHT_PKT)
 | 
						|
            co.iRcvBufSize = val / mssin_size;
 | 
						|
        else
 | 
						|
            co.iRcvBufSize = co.DEF_MIN_FLIGHT_PKT;
 | 
						|
 | 
						|
        // recv buffer MUST not be greater than FC size
 | 
						|
        if (co.iRcvBufSize > co.iFlightFlagSize)
 | 
						|
            co.iRcvBufSize = co.iFlightFlagSize;
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_LINGER>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        co.Linger = cast_optval<linger>(optval, optlen);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_UDP_SNDBUF>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        co.iUDPSndBufSize = std::max(co.iMSS, cast_optval<int>(optval, optlen));
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_UDP_RCVBUF>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        co.iUDPRcvBufSize = std::max(co.iMSS, cast_optval<int>(optval, optlen));
 | 
						|
    }
 | 
						|
};
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_RENDEZVOUS>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        co.bRendezvous = cast_optval<bool>(optval, optlen);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_SNDTIMEO>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        const int val = cast_optval<int>(optval, optlen);
 | 
						|
        if (val < -1)
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
 | 
						|
        co.iSndTimeOut = val;
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_RCVTIMEO>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        const int val = cast_optval<int>(optval, optlen);
 | 
						|
        if (val < -1)
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
 | 
						|
        co.iRcvTimeOut = val;
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_SNDSYN>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        co.bSynSending = cast_optval<bool>(optval, optlen);
 | 
						|
    }
 | 
						|
};
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_RCVSYN>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        co.bSynRecving = cast_optval<bool>(optval, optlen);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_REUSEADDR>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        co.bReuseAddr = cast_optval<bool>(optval, optlen);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_MAXBW>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        const int64_t val = cast_optval<int64_t>(optval, optlen);
 | 
						|
        if (val < -1)
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
 | 
						|
        co.llMaxBW = val;
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
#ifdef ENABLE_MAXREXMITBW
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_MAXREXMITBW>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        const int64_t val = cast_optval<int64_t>(optval, optlen);
 | 
						|
        if (val < -1)
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
 | 
						|
        co.llMaxRexmitBW = val;
 | 
						|
    }
 | 
						|
};
 | 
						|
#endif
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_IPTTL>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        int val = cast_optval<int>(optval, optlen);
 | 
						|
        if (!(val == -1) && !((val >= 1) && (val <= 255)))
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
        co.iIpTTL = cast_optval<int>(optval);
 | 
						|
    }
 | 
						|
};
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_IPTOS>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        co.iIpToS = cast_optval<int>(optval, optlen);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_BINDTODEVICE>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        using namespace srt_logging;
 | 
						|
#ifdef SRT_ENABLE_BINDTODEVICE
 | 
						|
        using namespace std;
 | 
						|
 | 
						|
        string val;
 | 
						|
        if (optlen == -1)
 | 
						|
            val = (const char *)optval;
 | 
						|
        else
 | 
						|
            val.assign((const char *)optval, optlen);
 | 
						|
        if (val.size() >= IFNAMSIZ)
 | 
						|
        {
 | 
						|
            LOGC(kmlog.Error, log << "SRTO_BINDTODEVICE: device name too long (max: IFNAMSIZ=" << IFNAMSIZ << ")");
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
        }
 | 
						|
 | 
						|
        co.sBindToDevice = val;
 | 
						|
#else
 | 
						|
        (void)co; // prevent warning
 | 
						|
        (void)optval;
 | 
						|
        (void)optlen;
 | 
						|
        LOGC(kmlog.Error, log << "SRTO_BINDTODEVICE is not supported on that platform");
 | 
						|
        throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
#endif
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_INPUTBW>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        const int64_t val = cast_optval<int64_t>(optval, optlen);
 | 
						|
        if (val < 0)
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
        co.llInputBW = val;
 | 
						|
    }
 | 
						|
};
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_MININPUTBW>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        const int64_t val = cast_optval<int64_t>(optval, optlen);
 | 
						|
        if (val < 0)
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
        co.llMinInputBW = val;
 | 
						|
    }
 | 
						|
};
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_OHEADBW>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        const int32_t val = cast_optval<int32_t>(optval, optlen);
 | 
						|
        if (val < 5 || val > 100)
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
        co.iOverheadBW = val;
 | 
						|
    }
 | 
						|
};
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_SENDER>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        co.bDataSender = cast_optval<bool>(optval, optlen);
 | 
						|
    }
 | 
						|
};
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_TSBPDMODE>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        const bool val = cast_optval<bool>(optval, optlen);
 | 
						|
#ifdef SRT_ENABLE_ENCRYPTION
 | 
						|
        if (val == false && co.iCryptoMode == CSrtConfig::CIPHER_MODE_AES_GCM)
 | 
						|
        {
 | 
						|
            using namespace srt_logging;
 | 
						|
            LOGC(aclog.Error, log << "Can't disable TSBPD as long as AES GCM is enabled.");
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
        }
 | 
						|
#endif
 | 
						|
 | 
						|
        co.bTSBPD = val;
 | 
						|
    }
 | 
						|
};
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_LATENCY>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        const int val = cast_optval<int>(optval, optlen);
 | 
						|
        if (val < 0)
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
 | 
						|
        co.iRcvLatency  = val;
 | 
						|
        co.iPeerLatency = val;
 | 
						|
    }
 | 
						|
};
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_RCVLATENCY>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        const int val = cast_optval<int>(optval, optlen);
 | 
						|
        if (val < 0)
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
 | 
						|
        co.iRcvLatency = val;
 | 
						|
    }
 | 
						|
};
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_PEERLATENCY>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        const int val = cast_optval<int>(optval, optlen);
 | 
						|
        if (val < 0)
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
 | 
						|
        co.iPeerLatency = val;
 | 
						|
    }
 | 
						|
};
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_TLPKTDROP>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        co.bTLPktDrop = cast_optval<bool>(optval, optlen);
 | 
						|
    }
 | 
						|
};
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_SNDDROPDELAY>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        const int val = cast_optval<int>(optval, optlen);
 | 
						|
        if (val < -1)
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
 | 
						|
        co.iSndDropDelay = val;
 | 
						|
    }
 | 
						|
};
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_PASSPHRASE>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        using namespace srt_logging;
 | 
						|
#ifdef SRT_ENABLE_ENCRYPTION
 | 
						|
        // Password must be 10-80 characters.
 | 
						|
        // Or it can be empty to clear the password.
 | 
						|
        if ((optlen != 0) && (optlen < 10 || optlen > HAICRYPT_SECRET_MAX_SZ))
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
 | 
						|
        memset(&co.CryptoSecret, 0, sizeof(co.CryptoSecret));
 | 
						|
        co.CryptoSecret.typ = HAICRYPT_SECTYP_PASSPHRASE;
 | 
						|
        co.CryptoSecret.len = (optlen <= (int)sizeof(co.CryptoSecret.str) ? optlen : (int)sizeof(co.CryptoSecret.str));
 | 
						|
        memcpy((co.CryptoSecret.str), optval, co.CryptoSecret.len);
 | 
						|
#else
 | 
						|
        (void)co; // prevent warning
 | 
						|
        (void)optval;
 | 
						|
        if (optlen == 0)
 | 
						|
            return; // Allow to set empty passphrase if no encryption supported.
 | 
						|
 | 
						|
        LOGC(aclog.Error, log << "SRTO_PASSPHRASE: encryption not enabled at compile time");
 | 
						|
        throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
#endif
 | 
						|
    }
 | 
						|
};
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_PBKEYLEN>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        using namespace srt_logging;
 | 
						|
#ifdef SRT_ENABLE_ENCRYPTION
 | 
						|
        const int v    = cast_optval<int>(optval, optlen);
 | 
						|
        int const allowed[4] = {
 | 
						|
            0,  // Default value, if this results for initiator, defaults to 16. See below.
 | 
						|
            16, // AES-128
 | 
						|
            24, // AES-192
 | 
						|
            32  // AES-256
 | 
						|
        };
 | 
						|
        const int *const allowed_end = allowed + 4;
 | 
						|
        if (std::find(allowed, allowed_end, v) == allowed_end)
 | 
						|
        {
 | 
						|
            LOGC(aclog.Error,
 | 
						|
                    log << "Invalid value for option SRTO_PBKEYLEN: " << v << "; allowed are: 0, 16, 24, 32");
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
        }
 | 
						|
 | 
						|
        // Note: This works a little different in HSv4 and HSv5.
 | 
						|
 | 
						|
        // HSv4:
 | 
						|
        // The party that is set SRTO_SENDER will send KMREQ, and it will
 | 
						|
        // use default value 16, if SRTO_PBKEYLEN is the default value 0.
 | 
						|
        // The responder that receives KMRSP has nothing to say about
 | 
						|
        // PBKEYLEN anyway and it will take the length of the key from
 | 
						|
        // the initiator (sender) as a good deal.
 | 
						|
        //
 | 
						|
        // HSv5:
 | 
						|
        // The initiator (independently on the sender) will send KMREQ,
 | 
						|
        // and as it should be the sender to decide about the PBKEYLEN.
 | 
						|
        // Your application should do the following then:
 | 
						|
        // 1. The sender should set PBKEYLEN to the required value.
 | 
						|
        // 2. If the sender is initiator, it will create the key using
 | 
						|
        //    its preset PBKEYLEN (or default 16, if not set) and the
 | 
						|
        //    receiver-responder will take it as a good deal.
 | 
						|
        // 3. Leave the PBKEYLEN value on the receiver as default 0.
 | 
						|
        // 4. If sender is responder, it should then advertise the PBKEYLEN
 | 
						|
        //    value in the initial handshake messages (URQ_INDUCTION if
 | 
						|
        //    listener, and both URQ_WAVEAHAND and URQ_CONCLUSION in case
 | 
						|
        //    of rendezvous, as it is the matter of luck who of them will
 | 
						|
        //    eventually become the initiator). This way the receiver
 | 
						|
        //    being an initiator will set iSndCryptoKeyLen before setting
 | 
						|
        //    up KMREQ for sending to the sender-responder.
 | 
						|
        //
 | 
						|
        // Note that in HSv5 if both sides set PBKEYLEN, the responder
 | 
						|
        // wins, unless the initiator is a sender (the effective PBKEYLEN
 | 
						|
        // will be the one advertised by the responder). If none sets,
 | 
						|
        // PBKEYLEN will default to 16.
 | 
						|
 | 
						|
        co.iSndCryptoKeyLen = v;
 | 
						|
#else
 | 
						|
        (void)co; // prevent warning
 | 
						|
        (void)optval;
 | 
						|
        (void)optlen;
 | 
						|
        LOGC(aclog.Error, log << "SRTO_PBKEYLEN: encryption not enabled at compile time");
 | 
						|
        throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
#endif
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_NAKREPORT>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        co.bRcvNakReport = cast_optval<bool>(optval, optlen);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_CONNTIMEO>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        const int val = cast_optval<int>(optval, optlen);
 | 
						|
        if (val < 0)
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
 | 
						|
        using namespace srt::sync;
 | 
						|
        co.tdConnTimeOut = milliseconds_from(val);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_DRIFTTRACER>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        co.bDriftTracer = cast_optval<bool>(optval, optlen);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_LOSSMAXTTL>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        co.iMaxReorderTolerance = cast_optval<int>(optval, optlen);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_VERSION>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        co.uSrtVersion = cast_optval<uint32_t>(optval, optlen);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_MINVERSION>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        co.uMinimumPeerSrtVersion = cast_optval<uint32_t>(optval, optlen);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_STREAMID>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        if (size_t(optlen) > CSrtConfig::MAX_SID_LENGTH)
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
 | 
						|
        co.sStreamName.set((const char*)optval, optlen);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_CONGESTION>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        std::string val;
 | 
						|
        if (optlen == -1)
 | 
						|
            val = (const char*)optval;
 | 
						|
        else
 | 
						|
            val.assign((const char*)optval, optlen);
 | 
						|
 | 
						|
        // Translate alias
 | 
						|
        if (val == "vod")
 | 
						|
            val = "file";
 | 
						|
 | 
						|
        bool res = SrtCongestion::exists(val);
 | 
						|
        if (!res)
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
 | 
						|
        co.sCongestion.set(val);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_MESSAGEAPI>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        co.bMessageAPI = cast_optval<bool>(optval, optlen);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_PAYLOADSIZE>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        using namespace srt_logging;
 | 
						|
        const int val = cast_optval<int>(optval, optlen);
 | 
						|
        if (val < 0)
 | 
						|
        {
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
        }
 | 
						|
 | 
						|
        if (val > SRT_LIVE_MAX_PLSIZE)
 | 
						|
        {
 | 
						|
            LOGC(aclog.Error, log << "SRTO_PAYLOADSIZE: value exceeds " << SRT_LIVE_MAX_PLSIZE << ", maximum payload per MTU.");
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
        }
 | 
						|
 | 
						|
        if (!co.sPacketFilterConfig.empty())
 | 
						|
        {
 | 
						|
            // This means that the filter might have been installed before,
 | 
						|
            // and the fix to the maximum payload size was already applied.
 | 
						|
            // This needs to be checked now.
 | 
						|
            SrtFilterConfig fc;
 | 
						|
            if (!ParseFilterConfig(co.sPacketFilterConfig.str(), fc))
 | 
						|
            {
 | 
						|
                // Break silently. This should not happen
 | 
						|
                LOGC(aclog.Error, log << "SRTO_PAYLOADSIZE: IPE: failing filter configuration installed");
 | 
						|
                throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
            }
 | 
						|
 | 
						|
            const size_t efc_max_payload_size = SRT_LIVE_MAX_PLSIZE - fc.extra_size;
 | 
						|
            if (size_t(val) > efc_max_payload_size)
 | 
						|
            {
 | 
						|
                LOGC(aclog.Error,
 | 
						|
                     log << "SRTO_PAYLOADSIZE: value exceeds " << SRT_LIVE_MAX_PLSIZE << " bytes decreased by " << fc.extra_size
 | 
						|
                         << " required for packet filter header");
 | 
						|
                throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        // Not checking AUTO to allow defaul 1456 bytes.
 | 
						|
        if ((co.iCryptoMode == CSrtConfig::CIPHER_MODE_AES_GCM)
 | 
						|
            && (val > (SRT_LIVE_MAX_PLSIZE - HAICRYPT_AUTHTAG_MAX)))
 | 
						|
        {
 | 
						|
            LOGC(aclog.Error,
 | 
						|
                log << "SRTO_PAYLOADSIZE: value exceeds " << SRT_LIVE_MAX_PLSIZE << " bytes decreased by " << HAICRYPT_AUTHTAG_MAX
 | 
						|
                << " required for AES-GCM.");
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
        }
 | 
						|
 | 
						|
        co.zExpPayloadSize = val;
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_TRANSTYPE>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        // XXX Note that here the configuration for SRTT_LIVE
 | 
						|
        // is the same as DEFAULT VALUES for these fields set
 | 
						|
        // in CUDT::CUDT.
 | 
						|
        switch (cast_optval<SRT_TRANSTYPE>(optval, optlen))
 | 
						|
        {
 | 
						|
        case SRTT_LIVE:
 | 
						|
            // Default live options:
 | 
						|
            // - tsbpd: on
 | 
						|
            // - latency: 120ms
 | 
						|
            // - linger: off
 | 
						|
            // - congctl: live
 | 
						|
            // - extraction method: message (reading call extracts one message)
 | 
						|
            co.bTSBPD          = true;
 | 
						|
            co.iRcvLatency     = SRT_LIVE_DEF_LATENCY_MS;
 | 
						|
            co.iPeerLatency    = 0;
 | 
						|
            co.bTLPktDrop      = true;
 | 
						|
            co.iSndDropDelay   = 0;
 | 
						|
            co.bMessageAPI     = true;
 | 
						|
            co.bRcvNakReport   = true;
 | 
						|
            co.iRetransmitAlgo = 1;
 | 
						|
            co.zExpPayloadSize = SRT_LIVE_DEF_PLSIZE;
 | 
						|
            co.Linger.l_onoff  = 0;
 | 
						|
            co.Linger.l_linger = 0;
 | 
						|
            co.sCongestion.set("live", 4);
 | 
						|
            break;
 | 
						|
 | 
						|
        case SRTT_FILE:
 | 
						|
            // File transfer mode:
 | 
						|
            // - tsbpd: off
 | 
						|
            // - latency: 0
 | 
						|
            // - linger: on
 | 
						|
            // - congctl: file (original UDT congestion control)
 | 
						|
            // - extraction method: stream (reading call extracts as many bytes as available and fits in buffer)
 | 
						|
            co.bTSBPD          = false;
 | 
						|
            co.iRcvLatency     = 0;
 | 
						|
            co.iPeerLatency    = 0;
 | 
						|
            co.bTLPktDrop      = false;
 | 
						|
            co.iSndDropDelay   = -1;
 | 
						|
            co.bMessageAPI     = false;
 | 
						|
            co.bRcvNakReport   = false;
 | 
						|
            co.iRetransmitAlgo = 0;
 | 
						|
            co.zExpPayloadSize = 0; // use maximum
 | 
						|
            co.Linger.l_onoff  = 1;
 | 
						|
            co.Linger.l_linger = CSrtConfig::DEF_LINGER_S;
 | 
						|
            co.sCongestion.set("file", 4);
 | 
						|
            break;
 | 
						|
 | 
						|
        default:
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
        }
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
#if ENABLE_BONDING
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_GROUPCONNECT>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        co.iGroupConnect = cast_optval<int>(optval, optlen);
 | 
						|
    }
 | 
						|
};
 | 
						|
#endif
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_KMREFRESHRATE>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        using namespace srt_logging;
 | 
						|
 | 
						|
        const int val = cast_optval<int>(optval, optlen);
 | 
						|
        if (val < 0)
 | 
						|
        {
 | 
						|
            LOGC(aclog.Error,
 | 
						|
                 log << "SRTO_KMREFRESHRATE=" << val << " can't be negative");
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
        }
 | 
						|
 | 
						|
        // Changing the KMREFRESHRATE sets KMPREANNOUNCE to the maximum allowed value
 | 
						|
        co.uKmRefreshRatePkt = (unsigned) val;
 | 
						|
 | 
						|
        if (co.uKmPreAnnouncePkt == 0 && co.uKmRefreshRatePkt == 0)
 | 
						|
            return; // Both values are default
 | 
						|
 | 
						|
        const unsigned km_preanno = co.uKmPreAnnouncePkt == 0 ? HAICRYPT_DEF_KM_PRE_ANNOUNCE : co.uKmPreAnnouncePkt;
 | 
						|
        const unsigned km_refresh = co.uKmRefreshRatePkt == 0 ? HAICRYPT_DEF_KM_REFRESH_RATE : co.uKmRefreshRatePkt;
 | 
						|
 | 
						|
        if (co.uKmPreAnnouncePkt == 0 || km_preanno > (km_refresh - 1) / 2)
 | 
						|
        {
 | 
						|
            co.uKmPreAnnouncePkt = (km_refresh - 1) / 2;
 | 
						|
            LOGC(aclog.Warn,
 | 
						|
                 log << "SRTO_KMREFRESHRATE=0x" << std::hex << km_refresh << ": setting SRTO_KMPREANNOUNCE=0x"
 | 
						|
                     << std::hex << co.uKmPreAnnouncePkt);
 | 
						|
        }
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_KMPREANNOUNCE>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        using namespace srt_logging;
 | 
						|
 | 
						|
        const int val = cast_optval<int>(optval, optlen);
 | 
						|
        if (val < 0)
 | 
						|
        {
 | 
						|
            LOGC(aclog.Error,
 | 
						|
                 log << "SRTO_KMPREANNOUNCE=" << val << " can't be negative");
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
        }
 | 
						|
 | 
						|
        const unsigned km_preanno = val == 0 ? HAICRYPT_DEF_KM_PRE_ANNOUNCE : val;
 | 
						|
        const unsigned kmref = co.uKmRefreshRatePkt == 0 ? HAICRYPT_DEF_KM_REFRESH_RATE : co.uKmRefreshRatePkt;
 | 
						|
        if (km_preanno > (kmref - 1) / 2)
 | 
						|
        {
 | 
						|
            LOGC(aclog.Error,
 | 
						|
                 log << "SRTO_KMPREANNOUNCE=0x" << std::hex << km_preanno << " exceeds KmRefresh/2, 0x" << ((kmref - 1) / 2)
 | 
						|
                     << " - OPTION REJECTED.");
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
        }
 | 
						|
 | 
						|
        co.uKmPreAnnouncePkt = val;
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_ENFORCEDENCRYPTION>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        co.bEnforcedEnc = cast_optval<bool>(optval, optlen);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_PEERIDLETIMEO>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        const int val = cast_optval<int>(optval, optlen);
 | 
						|
        if (val < 0)
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
 | 
						|
        co.iPeerIdleTimeout_ms = val;
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_IPV6ONLY>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        co.iIpV6Only = cast_optval<int>(optval, optlen);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_PACKETFILTER>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        using namespace srt_logging;
 | 
						|
        std::string arg((const char*)optval, optlen);
 | 
						|
        // Parse the configuration string prematurely
 | 
						|
        SrtFilterConfig fc;
 | 
						|
        PacketFilter::Factory* fax = 0;
 | 
						|
        if (!ParseFilterConfig(arg, (fc), (&fax)))
 | 
						|
        {
 | 
						|
            LOGC(aclog.Error,
 | 
						|
                 log << "SRTO_PACKETFILTER: Incorrect syntax. Use: FILTERTYPE[,KEY:VALUE...]. "
 | 
						|
                        "FILTERTYPE ("
 | 
						|
                     << fc.type << ") must be installed (or builtin)");
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
        }
 | 
						|
        std::string error;
 | 
						|
        if (!fax->verifyConfig(fc, (error)))
 | 
						|
        {
 | 
						|
            LOGC(aclog.Error, log << "SRTO_PACKETFILTER: Incorrect config: " << error);
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
        }
 | 
						|
 | 
						|
        size_t efc_max_payload_size = SRT_LIVE_MAX_PLSIZE - fc.extra_size;
 | 
						|
        if (co.zExpPayloadSize > efc_max_payload_size)
 | 
						|
        {
 | 
						|
            LOGC(aclog.Warn,
 | 
						|
                 log << "Due to filter-required extra " << fc.extra_size << " bytes, SRTO_PAYLOADSIZE fixed to "
 | 
						|
                     << efc_max_payload_size << " bytes");
 | 
						|
            co.zExpPayloadSize = efc_max_payload_size;
 | 
						|
        }
 | 
						|
 | 
						|
        co.sPacketFilterConfig.set(arg);
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
#if ENABLE_BONDING
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_GROUPMINSTABLETIMEO>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        using namespace srt_logging;
 | 
						|
        // This option is meaningless for the socket itself.
 | 
						|
        // It's set here just for the sake of setting it on a listener
 | 
						|
        // socket so that it is then applied on the group when a
 | 
						|
        // group connection is configured.
 | 
						|
        const int val_ms = cast_optval<int>(optval, optlen);
 | 
						|
        const int min_timeo_ms = (int) CSrtConfig::COMM_DEF_MIN_STABILITY_TIMEOUT_MS;
 | 
						|
 | 
						|
        if (val_ms < min_timeo_ms)
 | 
						|
        {
 | 
						|
            LOGC(qmlog.Error,
 | 
						|
                log << "group option: SRTO_GROUPMINSTABLETIMEO min allowed value is "
 | 
						|
                    << min_timeo_ms << " ms.");
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
        }
 | 
						|
 | 
						|
        const int idletmo_ms = co.iPeerIdleTimeout_ms;
 | 
						|
 | 
						|
        if (val_ms > idletmo_ms)
 | 
						|
        {
 | 
						|
            LOGC(aclog.Error, log << "group option: SRTO_GROUPMINSTABLETIMEO(" << val_ms
 | 
						|
                                  << ") exceeds SRTO_PEERIDLETIMEO(" << idletmo_ms << ")");
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
        }
 | 
						|
 | 
						|
        co.uMinStabilityTimeout_ms = val_ms;
 | 
						|
        LOGC(smlog.Error, log << "SRTO_GROUPMINSTABLETIMEO set " << val_ms);
 | 
						|
    }
 | 
						|
};
 | 
						|
#endif
 | 
						|
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_RETRANSMITALGO>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        const int val = cast_optval<int>(optval, optlen);
 | 
						|
        if (val < 0 || val > 1)
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
 | 
						|
        co.iRetransmitAlgo = val;
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
#ifdef ENABLE_AEAD_API_PREVIEW
 | 
						|
template<>
 | 
						|
struct CSrtConfigSetter<SRTO_CRYPTOMODE>
 | 
						|
{
 | 
						|
    static void set(CSrtConfig& co, const void* optval, int optlen)
 | 
						|
    {
 | 
						|
        using namespace srt_logging;
 | 
						|
        const int val = cast_optval<int>(optval, optlen);
 | 
						|
#ifdef SRT_ENABLE_ENCRYPTION
 | 
						|
        if (val < CSrtConfig::CIPHER_MODE_AUTO || val > CSrtConfig::CIPHER_MODE_AES_GCM)
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
 | 
						|
        if (val == CSrtConfig::CIPHER_MODE_AES_GCM && !HaiCrypt_IsAESGCM_Supported())
 | 
						|
        {
 | 
						|
            LOGC(aclog.Error, log << "AES GCM is not supported by the crypto provider.");
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
        }
 | 
						|
 | 
						|
        if (val == CSrtConfig::CIPHER_MODE_AES_GCM && !co.bTSBPD)
 | 
						|
        {
 | 
						|
            LOGC(aclog.Error, log << "Enable TSBPD to use AES GCM.");
 | 
						|
            throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
        }
 | 
						|
 | 
						|
        co.iCryptoMode = val;
 | 
						|
#else
 | 
						|
        LOGC(aclog.Error, log << "SRT was built without crypto module.");
 | 
						|
        throw CUDTException(MJ_NOTSUP, MN_INVAL, 0);
 | 
						|
#endif
 | 
						|
 | 
						|
    }
 | 
						|
};
 | 
						|
#endif
 | 
						|
 | 
						|
int dispatchSet(SRT_SOCKOPT optName, CSrtConfig& co, const void* optval, int optlen)
 | 
						|
{
 | 
						|
    switch (optName)
 | 
						|
    {
 | 
						|
#define DISPATCH(optname) case optname: CSrtConfigSetter<optname>::set(co, optval, optlen); return 0;
 | 
						|
 | 
						|
        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_BONDING
 | 
						|
        DISPATCH(SRTO_GROUPCONNECT);
 | 
						|
        DISPATCH(SRTO_GROUPMINSTABLETIMEO);
 | 
						|
#endif
 | 
						|
        DISPATCH(SRTO_KMREFRESHRATE);
 | 
						|
        DISPATCH(SRTO_KMPREANNOUNCE);
 | 
						|
        DISPATCH(SRTO_ENFORCEDENCRYPTION);
 | 
						|
        DISPATCH(SRTO_PEERIDLETIMEO);
 | 
						|
        DISPATCH(SRTO_IPV6ONLY);
 | 
						|
        DISPATCH(SRTO_PACKETFILTER);
 | 
						|
        DISPATCH(SRTO_RETRANSMITALGO);
 | 
						|
#ifdef ENABLE_AEAD_API_PREVIEW
 | 
						|
        DISPATCH(SRTO_CRYPTOMODE);
 | 
						|
#endif
 | 
						|
#ifdef ENABLE_MAXREXMITBW
 | 
						|
        DISPATCH(SRTO_MAXREXMITBW);
 | 
						|
#endif
 | 
						|
 | 
						|
#undef DISPATCH
 | 
						|
    default:
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
} // anonymous namespace
 | 
						|
 | 
						|
int CSrtConfig::set(SRT_SOCKOPT optName, const void* optval, int optlen)
 | 
						|
{
 | 
						|
    return dispatchSet(optName, *this, optval, optlen);
 | 
						|
}
 | 
						|
 | 
						|
#if ENABLE_BONDING
 | 
						|
bool SRT_SocketOptionObject::add(SRT_SOCKOPT optname, const void* optval, size_t optlen)
 | 
						|
{
 | 
						|
    // Check first if this option is allowed to be set
 | 
						|
    // as on a member socket.
 | 
						|
 | 
						|
    switch (optname)
 | 
						|
    {
 | 
						|
    case SRTO_BINDTODEVICE:
 | 
						|
    case SRTO_CONNTIMEO:
 | 
						|
    case SRTO_DRIFTTRACER:
 | 
						|
        //SRTO_FC - not allowed to be different among group members
 | 
						|
    case SRTO_GROUPMINSTABLETIMEO:
 | 
						|
        //SRTO_INPUTBW - per transmission setting
 | 
						|
    case SRTO_IPTOS:
 | 
						|
    case SRTO_IPTTL:
 | 
						|
    case SRTO_KMREFRESHRATE:
 | 
						|
    case SRTO_KMPREANNOUNCE:
 | 
						|
        //SRTO_LATENCY - per transmission setting
 | 
						|
        //SRTO_LINGER - not for managed sockets
 | 
						|
    case SRTO_LOSSMAXTTL:
 | 
						|
        //SRTO_MAXBW - per transmission setting
 | 
						|
        //SRTO_MESSAGEAPI - groups are live mode only
 | 
						|
        //SRTO_MINVERSION - per group connection setting
 | 
						|
    case SRTO_NAKREPORT:
 | 
						|
        //SRTO_OHEADBW - per transmission setting
 | 
						|
        //SRTO_PACKETFILTER - per transmission setting
 | 
						|
        //SRTO_PASSPHRASE - per group connection setting
 | 
						|
        //SRTO_PASSPHRASE - per transmission setting
 | 
						|
        //SRTO_PBKEYLEN - per group connection setting
 | 
						|
    case SRTO_PEERIDLETIMEO:
 | 
						|
    case SRTO_RCVBUF:
 | 
						|
        //SRTO_RCVSYN - must be always false in groups
 | 
						|
        //SRTO_RCVTIMEO - must be always -1 in groups
 | 
						|
    case SRTO_SNDBUF:
 | 
						|
    case SRTO_SNDDROPDELAY:
 | 
						|
        //SRTO_TLPKTDROP - per transmission setting
 | 
						|
        //SRTO_TSBPDMODE - per transmission setting
 | 
						|
    case SRTO_UDP_RCVBUF:
 | 
						|
    case SRTO_UDP_SNDBUF:
 | 
						|
        break;
 | 
						|
 | 
						|
    default:
 | 
						|
        // Other options are not allowed
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    // Header size will get the size likely aligned, but it won't
 | 
						|
    // hurt if the memory size will be up to 4 bytes more than
 | 
						|
    // needed - and it's better to not risk that alighment rules
 | 
						|
    // will make these calculations result in less space than needed.
 | 
						|
    const size_t headersize = sizeof(SingleOption);
 | 
						|
    const size_t payload = std::min(sizeof(uint32_t), optlen);
 | 
						|
    unsigned char* mem = new unsigned char[headersize + payload];
 | 
						|
    SingleOption* option = reinterpret_cast<SingleOption*>(mem);
 | 
						|
    option->option = optname;
 | 
						|
    option->length = (uint16_t) optlen;
 | 
						|
    memcpy(option->storage, optval, optlen);
 | 
						|
 | 
						|
    options.push_back(option);
 | 
						|
 | 
						|
    return true;
 | 
						|
}
 | 
						|
#endif
 |