#ifndef INC_SRT_HANDSHAKE_H
#define INC_SRT_HANDSHAKE_H
#include <vector>
#include "crypto.h"
#include "utilities.h"
typedef Bits<31, 16> HS_CMDSPEC_CMD;
typedef Bits<15, 0> HS_CMDSPEC_SIZE;
enum SrtOptions
{
SRT_OPT_TSBPDSND = BIT(0),
SRT_OPT_TSBPDRCV = BIT(1),
SRT_OPT_HAICRYPT = BIT(2),
SRT_OPT_TLPKTDROP = BIT(3),
SRT_OPT_NAKREPORT = BIT(4),
SRT_OPT_REXMITFLG = BIT(5), SRT_OPT_STREAM = BIT(6), SRT_OPT_FILTERCAP = BIT(7), };
inline int SrtVersionCapabilities()
{
return SRT_OPT_HAICRYPT | SRT_OPT_FILTERCAP;
}
std::string SrtFlagString(int32_t flags);
const int SRT_CMD_REJECT = 0, SRT_CMD_HSREQ = 1,
SRT_CMD_HSRSP = 2,
SRT_CMD_KMREQ = 3,
SRT_CMD_KMRSP = 4,
SRT_CMD_SID = 5,
SRT_CMD_CONGESTION = 6,
SRT_CMD_FILTER = 7,
SRT_CMD_GROUP = 8,
SRT_CMD_NONE = -1;
enum SrtDataStruct
{
SRT_HS_VERSION = 0,
SRT_HS_FLAGS,
SRT_HS_LATENCY,
SRT_HS_E_SIZE
};
typedef Bits<31, 16> SRT_HS_LATENCY_RCV;
typedef Bits<15, 0> SRT_HS_LATENCY_SND;
typedef Bits<15, 0> SRT_HS_LATENCY_LEG;
struct SrtHandshakeExtension
{
int16_t type;
std::vector<uint32_t> contents;
SrtHandshakeExtension(int16_t cmd): type(cmd) {}
};
void SrtExtractHandshakeExtensions(const char* bufbegin, size_t size,
std::vector<SrtHandshakeExtension>& w_output);
struct SrtHSRequest: public SrtHandshakeExtension
{
typedef Bits<31, 16> SRT_HSTYPE_ENCFLAGS;
typedef Bits<15, 0> SRT_HSTYPE_HSFLAGS;
typedef Bits<5, 3> SRT_PBKEYLEN_BITS;
static const int32_t SRT_MAGIC_CODE = 0x4A17;
static int32_t wrapFlags(bool withmagic, int crypto_keylen)
{
int32_t base = withmagic ? SRT_MAGIC_CODE : 0;
return base | SRT_HSTYPE_ENCFLAGS::wrap( SRT_PBKEYLEN_BITS::unwrap(crypto_keylen) );
}
typedef Bits<31, 24> HS_GROUP_TYPE;
typedef Bits<23, 16> HS_GROUP_FLAGS;
typedef Bits<15, 0> HS_GROUP_WEIGHT;
private:
friend class CHandShake;
static const size_t SRT_HS_SIZE = 4*sizeof(uint32_t); static const size_t SRT_EXT_HS_SIZE = 2*sizeof(uint32_t) + SRT_HS_SIZE;
typedef Bits<15, 0> SRT_TSBPD_DELAY;
uint32_t m_iSrtVersion;
uint32_t m_iSrtFlags;
uint32_t m_iSrtTsbpd;
uint32_t m_iSrtReserved;
public:
SrtHSRequest(): SrtHandshakeExtension(SRT_CMD_HSREQ), m_iSrtVersion(), m_iSrtFlags(), m_iSrtTsbpd(), m_iSrtReserved() {}
void setVersion(uint32_t v) { m_iSrtVersion = v; }
uint32_t version() const { return m_iSrtVersion; }
void setFlag(SrtOptions opt) { m_iSrtFlags |= uint32_t(opt); }
void clearFlag(SrtOptions opt) { m_iSrtFlags &= ~opt; }
uint32_t flags() const { return m_iSrtFlags; }
void setTsbPdDelay(uint16_t delay) { m_iSrtTsbpd |= SRT_TSBPD_DELAY::wrap(delay); }
uint16_t tsbPdDelay() const
{
return SRT_TSBPD_DELAY::unwrap(m_iSrtTsbpd);
}
size_t size() const { return SRT_EXT_HS_SIZE; }
bool serialize(char* p, size_t size) const;
bool deserialize(const char* mem, size_t size);
};
struct SrtKMRequest: public SrtHandshakeExtension
{
uint32_t m_iKmState;
char m_aKey[1]; };
enum UDTRequestType
{
URQ_INDUCTION_TYPES = 0,
URQ_INDUCTION = 1, URQ_WAVEAHAND = 0,
URQ_CONCLUSION = -1, URQ_AGREEMENT = -2, URQ_DONE = -3,
URQ_FAILURE_TYPES = 1000,
URQ_SERVER_FAILURE_TYPES = URQ_FAILURE_TYPES + SRT_REJC_PREDEFINED,
URQ_USER_FAILURE_TYPES = URQ_FAILURE_TYPES + SRT_REJC_USERDEFINED
};
inline UDTRequestType URQFailure(int reason)
{
return UDTRequestType(URQ_FAILURE_TYPES + int(reason));
}
inline int RejectReasonForURQ(UDTRequestType req)
{
if (req < URQ_FAILURE_TYPES)
return SRT_REJ_UNKNOWN;
int reason = req - URQ_FAILURE_TYPES;
if (reason < SRT_REJC_PREDEFINED && reason >= SRT_REJ_E_SIZE)
return SRT_REJ_UNKNOWN;
return reason;
}
const UDTRequestType URQ_ERROR_REJECT SRT_ATR_DEPRECATED = (UDTRequestType)1002; const UDTRequestType URQ_ERROR_INVALID SRT_ATR_DEPRECATED = (UDTRequestType)1004;
#if ENABLE_LOGGING
std::string RequestTypeStr(UDTRequestType);
#else
inline std::string RequestTypeStr(UDTRequestType) { return ""; }
#endif
class CHandShake
{
public:
CHandShake();
int store_to(char* buf, size_t& size);
int load_from(const char* buf, size_t size);
public:
static const size_t m_iContentSize = 48;
static const int32_t HS_EXT_HSREQ = BIT(0);
static const int32_t HS_EXT_KMREQ = BIT(1);
static const int32_t HS_EXT_CONFIG = BIT(2);
static std::string ExtensionFlagStr(int32_t fl);
int32_t flags() { return m_iType; }
public:
int32_t m_iVersion; int32_t m_iType; int32_t m_iISN; int32_t m_iMSS; int32_t m_iFlightFlagSize; UDTRequestType m_iReqType; int32_t m_iID; int32_t m_iCookie; uint32_t m_piPeerIP[4];
bool m_extension;
std::string show();
enum RendezvousState
{
RDV_INVALID, RDV_WAVING, RDV_ATTENTION, RDV_FINE, RDV_INITIATED, RDV_CONNECTED };
#if ENABLE_LOGGING
static std::string RdvStateStr(RendezvousState s);
#else
static std::string RdvStateStr(RendezvousState) { return ""; }
#endif
};
#endif