TSSRT Support
This commit is contained in:
parent
974380ab30
commit
19199cbff8
17 changed files with 1471 additions and 15 deletions
548
lib/socket_srt.cpp
Normal file
548
lib/socket_srt.cpp
Normal file
|
|
@ -0,0 +1,548 @@
|
|||
#include "defines.h"
|
||||
#include "lib/http_parser.h"
|
||||
#include "socket_srt.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <sstream>
|
||||
|
||||
#define INVALID_SRT_SOCKET -1
|
||||
|
||||
namespace Socket{
|
||||
namespace SRT{
|
||||
bool isInited = false;
|
||||
|
||||
// Both Init and Cleanup functions are called implicitly if not done ourselves.
|
||||
// SRT documentation states explicitly that this is unreliable behaviour
|
||||
bool libraryInit(){
|
||||
if (!isInited){
|
||||
int res = srt_startup();
|
||||
if (res == -1){ERROR_MSG("Unable to initialize SRT Library!");}
|
||||
isInited = (res != -1);
|
||||
}
|
||||
return isInited;
|
||||
}
|
||||
|
||||
bool libraryCleanup(){
|
||||
if (isInited){
|
||||
srt_cleanup();
|
||||
isInited = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}// namespace SRT
|
||||
|
||||
template <typename T> std::string asString(const T &val){
|
||||
std::stringstream x;
|
||||
x << val;
|
||||
return x.str();
|
||||
}
|
||||
|
||||
sockaddr_in createInetAddr(const std::string &_host, int _port){
|
||||
sockaddr_in res;
|
||||
memset(&res, 9, sizeof res);
|
||||
res.sin_family = AF_INET;
|
||||
res.sin_port = htons(_port);
|
||||
|
||||
if (_host != ""){
|
||||
if (inet_pton(AF_INET, _host.c_str(), &res.sin_addr) == 1){return res;}
|
||||
hostent *he = gethostbyname(_host.c_str());
|
||||
if (!he || he->h_addrtype != AF_INET){ERROR_MSG("Host not found %s", _host.c_str());}
|
||||
res.sin_addr = *(in_addr *)he->h_addr_list[0];
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string interpretSRTMode(const std::string &_mode, const std::string &_host, const std::string &_adapter){
|
||||
if (_mode == "client" || _mode == "caller"){return "caller";}
|
||||
if (_mode == "server" || _mode == "listener"){return "listener";}
|
||||
if (_mode == "rendezvouz"){return "rendezvous";}
|
||||
if (_mode != "default"){return "";}
|
||||
if (_host == ""){return "listener";}
|
||||
if (_adapter != ""){return "rendezvous";}
|
||||
return "caller";
|
||||
}
|
||||
|
||||
std::string interpretSRTMode(const HTTP::URL &u){
|
||||
paramList params;
|
||||
HTTP::parseVars(u.args, params);
|
||||
return interpretSRTMode(params.count("mode") ? params.at("mode") : "default", u.host, "");
|
||||
}
|
||||
|
||||
SRTConnection::SRTConnection(){initializeEmpty();}
|
||||
|
||||
SRTConnection::SRTConnection(const std::string &_host, int _port, const std::string &_direction,
|
||||
const std::map<std::string, std::string> &_params){
|
||||
connect(_host, _port, _direction, _params);
|
||||
}
|
||||
|
||||
std::string SRTConnection::getStreamName(){
|
||||
int sNameLen = 512;
|
||||
char sName[sNameLen];
|
||||
int optRes = srt_getsockflag(sock, SRTO_STREAMID, (void *)sName, &sNameLen);
|
||||
if (optRes != -1 && sNameLen){return sName;}
|
||||
return "";
|
||||
}
|
||||
|
||||
/// Updates the downbuffer internal variable.
|
||||
/// Returns true if new data was received, false otherwise.
|
||||
std::string SRTConnection::RecvNow(){
|
||||
char recvbuf[5000];
|
||||
|
||||
bool blockState = blocking;
|
||||
setBlocking(true);
|
||||
|
||||
SRT_MSGCTRL mc = srt_msgctrl_default;
|
||||
int32_t receivedBytes = srt_recvmsg2(sock, recvbuf, 5000, &mc);
|
||||
|
||||
if (prev_pktseq != 0 && (mc.pktseq - prev_pktseq > 1)){WARN_MSG("Packet lost");}
|
||||
prev_pktseq = mc.pktseq;
|
||||
|
||||
setBlocking(blockState);
|
||||
if (receivedBytes == -1){
|
||||
ERROR_MSG("Unable to receive data over socket: %s", srt_getlasterror_str());
|
||||
if (srt_getsockstate(sock) != SRTS_CONNECTED){close();}
|
||||
return "";
|
||||
}
|
||||
|
||||
srt_bstats(sock, &performanceMonitor, false);
|
||||
return std::string(recvbuf, receivedBytes);
|
||||
}
|
||||
|
||||
void SRTConnection::connect(const std::string &_host, int _port, const std::string &_direction,
|
||||
const std::map<std::string, std::string> &_params){
|
||||
initializeEmpty();
|
||||
|
||||
direction = _direction;
|
||||
|
||||
handleConnectionParameters(_host, _params);
|
||||
|
||||
HIGH_MSG("Opening SRT connection %s in %s mode on %s:%d", modeName.c_str(), direction.c_str(),
|
||||
_host.c_str(), _port);
|
||||
|
||||
sock = srt_create_socket();
|
||||
if (sock == SRT_ERROR){
|
||||
ERROR_MSG("Error creating an SRT socket");
|
||||
return;
|
||||
}
|
||||
if (modeName == "rendezvous"){
|
||||
bool v = true;
|
||||
srt_setsockopt(sock, 0, SRTO_RENDEZVOUS, &v, sizeof v);
|
||||
}
|
||||
if (preConfigureSocket() == SRT_ERROR){
|
||||
ERROR_MSG("Error configuring SRT socket");
|
||||
return;
|
||||
}
|
||||
|
||||
if (modeName == "caller"){
|
||||
if (outgoing_port){setupAdapter("", outgoing_port);}
|
||||
|
||||
sockaddr_in sa = createInetAddr(_host, _port);
|
||||
sockaddr *psa = (sockaddr *)&sa;
|
||||
|
||||
HIGH_MSG("Going to connect sock %d", sock);
|
||||
if (srt_connect(sock, psa, sizeof sa) == SRT_ERROR){
|
||||
srt_close(sock);
|
||||
ERROR_MSG("Can't connect SRT Socket");
|
||||
return;
|
||||
}
|
||||
HIGH_MSG("Connected sock %d", sock);
|
||||
|
||||
if (postConfigureSocket() == SRT_ERROR){
|
||||
ERROR_MSG("Error during postconfigure socket");
|
||||
return;
|
||||
}
|
||||
INFO_MSG("Caller SRT socket %" PRId32 " success targetting %s:%u", sock, _host.c_str(), _port);
|
||||
return;
|
||||
}
|
||||
if (modeName == "listener"){
|
||||
HIGH_MSG("Going to bind a server on %s:%u", _host.c_str(), _port);
|
||||
|
||||
sockaddr_in sa = createInetAddr(_host, _port);
|
||||
sockaddr *psa = (sockaddr *)&sa;
|
||||
|
||||
if (srt_bind(sock, psa, sizeof sa) == SRT_ERROR){
|
||||
srt_close(sock);
|
||||
ERROR_MSG("Can't connect SRT Socket");
|
||||
return;
|
||||
}
|
||||
if (srt_listen(sock, 1) == SRT_ERROR){
|
||||
srt_close(sock);
|
||||
ERROR_MSG("Can not listen on Socket");
|
||||
}
|
||||
INFO_MSG("Listener SRT socket sucess @ %s:%u", _host.c_str(), _port);
|
||||
return;
|
||||
}
|
||||
if (modeName == "rendezvous"){
|
||||
int outport = (outgoing_port ? outgoing_port : _port);
|
||||
HIGH_MSG("Going to bind a server on %s:%u", _host.c_str(), _port);
|
||||
|
||||
sockaddr_in sa = createInetAddr(_host, outport);
|
||||
sockaddr *psa = (sockaddr *)&sa;
|
||||
|
||||
if (srt_bind(sock, psa, sizeof sa) == SRT_ERROR){
|
||||
srt_close(sock);
|
||||
ERROR_MSG("Can't connect SRT Socket");
|
||||
return;
|
||||
}
|
||||
|
||||
sockaddr_in sb = createInetAddr(_host, outport);
|
||||
sockaddr *psb = (sockaddr *)&sb;
|
||||
|
||||
if (srt_connect(sock, psb, sizeof sb) == SRT_ERROR){
|
||||
srt_close(sock);
|
||||
ERROR_MSG("Can't connect SRT Socket");
|
||||
return;
|
||||
}
|
||||
|
||||
if (postConfigureSocket() == SRT_ERROR){
|
||||
ERROR_MSG("Error during postconfigure socket");
|
||||
return;
|
||||
}
|
||||
INFO_MSG("Rendezvous SRT socket sucess @ %s:%u", _host.c_str(), _port);
|
||||
return;
|
||||
}
|
||||
ERROR_MSG("Invalid mode parameter. Use 'client' or 'server'");
|
||||
}
|
||||
|
||||
void SRTConnection::setupAdapter(const std::string &_host, int _port){
|
||||
sockaddr_in localsa = createInetAddr(_host, _port);
|
||||
sockaddr *psa = (sockaddr *)&localsa;
|
||||
if (srt_bind(sock, psa, sizeof localsa) == SRT_ERROR){
|
||||
ERROR_MSG("Unable to bind socket to %s:%u", _host.c_str(), _port);
|
||||
}
|
||||
}
|
||||
|
||||
void SRTConnection::SendNow(const std::string &data){SendNow(data.data(), data.size());}
|
||||
|
||||
void SRTConnection::SendNow(const char *data, size_t len){
|
||||
srt_clearlasterror();
|
||||
int res = srt_sendmsg2(sock, data, len, NULL);
|
||||
|
||||
if (res == SRT_ERROR){
|
||||
ERROR_MSG("Unable to send data over socket %" PRId32 ": %s", sock, srt_getlasterror_str());
|
||||
if (srt_getsockstate(sock) != SRTS_CONNECTED){close();}
|
||||
}
|
||||
srt_bstats(sock, &performanceMonitor, false);
|
||||
}
|
||||
|
||||
unsigned int SRTConnection::connTime(){
|
||||
srt_bstats(sock, &performanceMonitor, false);
|
||||
return performanceMonitor.msTimeStamp / 1000;
|
||||
}
|
||||
|
||||
uint64_t SRTConnection::dataUp(){return performanceMonitor.byteSentTotal;}
|
||||
|
||||
uint64_t SRTConnection::dataDown(){return performanceMonitor.byteRecvTotal;}
|
||||
|
||||
uint64_t SRTConnection::packetCount(){
|
||||
return (direction == "input" ? performanceMonitor.pktRecvTotal : performanceMonitor.pktSentTotal);
|
||||
}
|
||||
|
||||
uint64_t SRTConnection::packetLostCount(){
|
||||
return (direction == "input" ? performanceMonitor.pktRcvLossTotal : performanceMonitor.pktSndLossTotal);
|
||||
}
|
||||
|
||||
uint64_t SRTConnection::packetRetransmitCount(){
|
||||
//\todo This should be updated with pktRcvRetransTotal on the retrieving end once srt has implemented this.
|
||||
return (direction == "input" ? 0 : performanceMonitor.pktRetransTotal);
|
||||
}
|
||||
|
||||
void SRTConnection::initializeEmpty(){
|
||||
prev_pktseq = 0;
|
||||
sock = SRT_INVALID_SOCK;
|
||||
outgoing_port = 0;
|
||||
chunkTransmitSize = 1316;
|
||||
blocking = false;
|
||||
}
|
||||
|
||||
void SRTConnection::setBlocking(bool _blocking){
|
||||
if (_blocking == blocking){return;}
|
||||
// If we have an error setting the new blocking state, the state is unchanged so we return early.
|
||||
if (srt_setsockopt(sock, 0, (direction == "output" ? SRTO_SNDSYN : SRTO_RCVSYN), &_blocking,
|
||||
sizeof _blocking) == -1){
|
||||
return;
|
||||
}
|
||||
blocking = _blocking;
|
||||
}
|
||||
|
||||
bool SRTConnection::isBlocking(){return blocking;}
|
||||
|
||||
void SRTConnection::handleConnectionParameters(const std::string &_host,
|
||||
const std::map<std::string, std::string> &_params){
|
||||
params = _params;
|
||||
DONTEVEN_MSG("SRT Received parameters: ");
|
||||
for (std::map<std::string, std::string>::const_iterator it = params.begin(); it != params.end(); it++){
|
||||
DONTEVEN_MSG(" %s: %s", it->first.c_str(), it->second.c_str());
|
||||
}
|
||||
|
||||
adapter = (params.count("adapter") ? params.at("adapter") : "");
|
||||
|
||||
modeName = interpretSRTMode((params.count("mode") ? params.at("mode") : "default"), _host, adapter);
|
||||
if (modeName == ""){
|
||||
ERROR_MSG("Invalid SRT mode encountered");
|
||||
return;
|
||||
}
|
||||
|
||||
// Using strtol because the original code uses base 0 -> automatic detection of octal and hexadecimal systems.
|
||||
timeout = (params.count("timeout") ? strtol(params.at("timeout").c_str(), 0, 0) : 0);
|
||||
|
||||
if (adapter == "" && modeName == "listener"){adapter = _host;}
|
||||
|
||||
tsbpdMode = ((params.count("tsbpd") && isFalseString(params.at("tsbpd"))) ? false : true);
|
||||
|
||||
outgoing_port = (params.count("port") ? strtol(params.at("port").c_str(), 0, 0) : 0);
|
||||
|
||||
if ((!params.count("transtype") || params.at("transtype") != "file") && chunkTransmitSize > SRT_LIVE_DEF_PLSIZE){
|
||||
if (chunkTransmitSize > SRT_LIVE_MAX_PLSIZE){
|
||||
ERROR_MSG("Chunk size in live mode exceeds 1456 bytes!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
params["payloadsize"] = asString(chunkTransmitSize);
|
||||
}
|
||||
|
||||
int SRTConnection::preConfigureSocket(){
|
||||
bool no = false;
|
||||
if (!tsbpdMode){
|
||||
if (srt_setsockopt(sock, 0, SRTO_TSBPDMODE, &no, sizeof no) == -1){return -1;}
|
||||
}
|
||||
if (srt_setsockopt(sock, 0, SRTO_RCVSYN, &no, sizeof no) == -1){return -1;}
|
||||
|
||||
if (params.count("linger")){
|
||||
linger lin;
|
||||
lin.l_linger = atoi(params.at("linger").c_str());
|
||||
lin.l_onoff = lin.l_linger > 0 ? 1 : 0;
|
||||
srt_setsockopt(sock, 0, SRTO_LINGER, &lin, sizeof(linger));
|
||||
}
|
||||
|
||||
std::string errMsg = configureSocketLoop(SRT::SockOpt::PRE);
|
||||
if (errMsg.size()){
|
||||
WARN_MSG("Failed to set the following options: %s", errMsg.c_str());
|
||||
return SRT_ERROR;
|
||||
}
|
||||
|
||||
if (direction == "output"){
|
||||
int v = 1;
|
||||
if (srt_setsockopt(sock, 0, SRTO_SENDER, &v, sizeof v) == SRT_ERROR){return SRT_ERROR;}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SRTConnection::postConfigureSocket(){
|
||||
bool no = false;
|
||||
if (srt_setsockopt(sock, 0, (direction == "output" ? SRTO_SNDSYN : SRTO_RCVSYN), &no, sizeof no) == -1){
|
||||
return -1;
|
||||
}
|
||||
if (timeout){
|
||||
if (srt_setsockopt(sock, 0, (direction == "output" ? SRTO_SNDTIMEO : SRTO_RCVTIMEO), &timeout,
|
||||
sizeof timeout) == -1){
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
std::string errMsg = configureSocketLoop(SRT::SockOpt::POST);
|
||||
if (errMsg.size()){
|
||||
WARN_MSG("Failed to set the following options: %s", errMsg.c_str());
|
||||
return SRT_ERROR;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string SRTConnection::configureSocketLoop(SRT::SockOpt::Binding _binding){
|
||||
std::string errMsg;
|
||||
|
||||
std::vector<SocketOption> allSrtOptions = srtOptions();
|
||||
for (std::vector<SocketOption>::iterator it = allSrtOptions.begin(); it != allSrtOptions.end(); it++){
|
||||
if (it->binding == _binding && params.count(it->name)){
|
||||
std::string value = params.at(it->name);
|
||||
if (!it->apply(sock, value)){errMsg += it->name + " ";}
|
||||
}
|
||||
}
|
||||
return errMsg;
|
||||
}
|
||||
|
||||
void SRTConnection::close(){
|
||||
if (sock != -1){
|
||||
srt_close(sock);
|
||||
sock = -1;
|
||||
}
|
||||
}
|
||||
|
||||
SRTServer::SRTServer(){}
|
||||
|
||||
SRTServer::SRTServer(int fromSock){conn = SRTConnection(fromSock);}
|
||||
|
||||
SRTServer::SRTServer(int port, std::string hostname, bool nonblock, const std::string &_direction){
|
||||
// We always create a server as listening
|
||||
std::map<std::string, std::string> listenMode;
|
||||
listenMode["mode"] = "listener";
|
||||
if (hostname == ""){hostname = "0.0.0.0";}
|
||||
conn.connect(hostname, port, _direction, listenMode);
|
||||
conn.setBlocking(true);
|
||||
if (!conn){
|
||||
ERROR_MSG("Unable to create socket");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SRTConnection SRTServer::accept(bool nonblock, const std::string &direction){
|
||||
if (!conn){return SRTConnection();}
|
||||
struct sockaddr_in6 tmpaddr;
|
||||
int len = sizeof(tmpaddr);
|
||||
|
||||
SRTConnection r(srt_accept(conn.getSocket(), (sockaddr *)&tmpaddr, &len));
|
||||
if (!r){
|
||||
if (conn.getSocket() != -1 && srt_getlasterror(0) != SRT_EASYNCRCV){
|
||||
FAIL_MSG("Error during accept: %s. Closing server socket %d.", srt_getlasterror_str(), conn.getSocket());
|
||||
close();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
r.direction = direction;
|
||||
r.postConfigureSocket();
|
||||
r.setBlocking(!nonblock);
|
||||
static char addrconv[INET6_ADDRSTRLEN];
|
||||
|
||||
r.remoteaddr = tmpaddr;
|
||||
if (tmpaddr.sin6_family == AF_INET6){
|
||||
r.remotehost = inet_ntop(AF_INET6, &(tmpaddr.sin6_addr), addrconv, INET6_ADDRSTRLEN);
|
||||
HIGH_MSG("IPv6 addr [%s]", r.remotehost.c_str());
|
||||
}
|
||||
if (tmpaddr.sin6_family == AF_INET){
|
||||
r.remotehost = inet_ntop(AF_INET, &(((sockaddr_in *)&tmpaddr)->sin_addr), addrconv, INET6_ADDRSTRLEN);
|
||||
HIGH_MSG("IPv4 addr [%s]", r.remotehost.c_str());
|
||||
}
|
||||
INFO_MSG("Accepted a socket coming from %s", r.remotehost.c_str());
|
||||
return r;
|
||||
}
|
||||
|
||||
void SRTServer::setBlocking(bool blocking){conn.setBlocking(blocking);}
|
||||
|
||||
bool SRTServer::isBlocking(){return (conn ? conn.isBlocking() : false);}
|
||||
|
||||
void SRTServer::close(){conn.close();}
|
||||
|
||||
bool SRTServer::connected() const{return conn.connected();}
|
||||
|
||||
int SRTServer::getSocket(){return conn.getSocket();}
|
||||
|
||||
inline int SocketOption::setSo(int socket, int proto, int sym, const void *data, size_t size, bool isSrtOpt){
|
||||
if (isSrtOpt){return srt_setsockopt(socket, 0, SRT_SOCKOPT(sym), data, (int)size);}
|
||||
return ::setsockopt(socket, proto, sym, (const char *)data, (int)size);
|
||||
}
|
||||
|
||||
bool SocketOption::extract(const std::string &v, OptionValue &val, SRT::SockOpt::Type asType){
|
||||
switch (asType){
|
||||
case SRT::SockOpt::STRING:
|
||||
val.s = v;
|
||||
val.value = val.s.data();
|
||||
val.size = val.s.size();
|
||||
break;
|
||||
case SRT::SockOpt::INT:
|
||||
case SRT::SockOpt::INT64:{
|
||||
int64_t tmp = strtol(v.c_str(), 0, 0);
|
||||
if (tmp == 0 && (!v.size() || v[0] != '0')){return false;}
|
||||
if (asType == SRT::SockOpt::INT){
|
||||
val.i = tmp;
|
||||
val.value = &val.i;
|
||||
val.size = sizeof(val.i);
|
||||
}else{
|
||||
val.l = tmp;
|
||||
val.value = &val.l;
|
||||
val.size = sizeof(val.l);
|
||||
}
|
||||
}break;
|
||||
case SRT::SockOpt::BOOL:{
|
||||
bool tmp;
|
||||
if (isFalseString(v)){
|
||||
tmp = true;
|
||||
}else if (isTrueString(v)){
|
||||
tmp = true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
val.b = tmp;
|
||||
val.value = &val.b;
|
||||
val.size = sizeof val.b;
|
||||
}break;
|
||||
case SRT::SockOpt::ENUM:{
|
||||
// Search value in the map. If found, set to o.
|
||||
SockOptVals::const_iterator p = valmap.find(v);
|
||||
if (p != valmap.end()){
|
||||
val.i = p->second;
|
||||
val.value = &val.i;
|
||||
val.size = sizeof val.i;
|
||||
return true;
|
||||
}
|
||||
// Fallback: try interpreting it as integer.
|
||||
return extract(v, val, SRT::SockOpt::INT);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SocketOption::apply(int socket, const std::string &value, bool isSrtOpt){
|
||||
OptionValue o;
|
||||
int result = -1;
|
||||
if (extract(value, o, type)){
|
||||
result = setSo(socket, protocol, symbol, o.value, o.size, isSrtOpt);
|
||||
}
|
||||
return result != -1;
|
||||
}
|
||||
|
||||
const std::map<std::string, int> enummap_transtype;
|
||||
|
||||
std::vector<SocketOption> srtOptions(){
|
||||
|
||||
static std::map<std::string, int> enummap_transtype;
|
||||
if (!enummap_transtype.size()){
|
||||
enummap_transtype["live"] = SRTT_LIVE;
|
||||
enummap_transtype["file"] = SRTT_FILE;
|
||||
}
|
||||
|
||||
static std::vector<SocketOption> res;
|
||||
if (res.size()){return res;}
|
||||
res.push_back(SocketOption("transtype", 0, SRTO_TRANSTYPE, SRT::SockOpt::PRE,
|
||||
SRT::SockOpt::ENUM, enummap_transtype));
|
||||
res.push_back(SocketOption("maxbw", 0, SRTO_MAXBW, SRT::SockOpt::PRE, SRT::SockOpt::INT64));
|
||||
res.push_back(SocketOption("pbkeylen", 0, SRTO_PBKEYLEN, SRT::SockOpt::PRE, SRT::SockOpt::INT));
|
||||
res.push_back(SocketOption("passphrase", 0, SRTO_PASSPHRASE, SRT::SockOpt::PRE, SRT::SockOpt::STRING));
|
||||
|
||||
res.push_back(SocketOption("mss", 0, SRTO_MSS, SRT::SockOpt::PRE, SRT::SockOpt::INT));
|
||||
res.push_back(SocketOption("fc", 0, SRTO_FC, SRT::SockOpt::PRE, SRT::SockOpt::INT));
|
||||
res.push_back(SocketOption("sndbuf", 0, SRTO_SNDBUF, SRT::SockOpt::PRE, SRT::SockOpt::INT));
|
||||
res.push_back(SocketOption("rcvbuf", 0, SRTO_RCVBUF, SRT::SockOpt::PRE, SRT::SockOpt::INT));
|
||||
// linger option is handled outside of the common loop, therefore commented out.
|
||||
// res.push_back(SocketOption( "linger", 0, SRTO_LINGER, SRT::SockOpt::PRE, SRT::SockOpt::INT));
|
||||
res.push_back(SocketOption("ipttl", 0, SRTO_IPTTL, SRT::SockOpt::PRE, SRT::SockOpt::INT));
|
||||
res.push_back(SocketOption("iptos", 0, SRTO_IPTOS, SRT::SockOpt::PRE, SRT::SockOpt::INT));
|
||||
res.push_back(SocketOption("inputbw", 0, SRTO_INPUTBW, SRT::SockOpt::POST, SRT::SockOpt::INT64));
|
||||
res.push_back(SocketOption("oheadbw", 0, SRTO_OHEADBW, SRT::SockOpt::POST, SRT::SockOpt::INT));
|
||||
res.push_back(SocketOption("latency", 0, SRTO_LATENCY, SRT::SockOpt::PRE, SRT::SockOpt::INT));
|
||||
res.push_back(SocketOption("tsbpdmode", 0, SRTO_TSBPDMODE, SRT::SockOpt::PRE, SRT::SockOpt::BOOL));
|
||||
res.push_back(SocketOption("tlpktdrop", 0, SRTO_TLPKTDROP, SRT::SockOpt::PRE, SRT::SockOpt::BOOL));
|
||||
res.push_back(SocketOption("snddropdelay", 0, SRTO_SNDDROPDELAY, SRT::SockOpt::POST, SRT::SockOpt::INT));
|
||||
res.push_back(SocketOption("nakreport", 0, SRTO_NAKREPORT, SRT::SockOpt::PRE, SRT::SockOpt::BOOL));
|
||||
res.push_back(SocketOption("conntimeo", 0, SRTO_CONNTIMEO, SRT::SockOpt::PRE, SRT::SockOpt::INT));
|
||||
res.push_back(SocketOption("lossmaxttl", 0, SRTO_LOSSMAXTTL, SRT::SockOpt::PRE, SRT::SockOpt::INT));
|
||||
res.push_back(SocketOption("rcvlatency", 0, SRTO_RCVLATENCY, SRT::SockOpt::PRE, SRT::SockOpt::INT));
|
||||
res.push_back(SocketOption("peerlatency", 0, SRTO_PEERLATENCY, SRT::SockOpt::PRE, SRT::SockOpt::INT));
|
||||
res.push_back(SocketOption("minversion", 0, SRTO_MINVERSION, SRT::SockOpt::PRE, SRT::SockOpt::INT));
|
||||
res.push_back(SocketOption("streamid", 0, SRTO_STREAMID, SRT::SockOpt::PRE, SRT::SockOpt::STRING));
|
||||
res.push_back(SocketOption("congestion", 0, SRTO_CONGESTION, SRT::SockOpt::PRE, SRT::SockOpt::STRING));
|
||||
res.push_back(SocketOption("messageapi", 0, SRTO_MESSAGEAPI, SRT::SockOpt::PRE, SRT::SockOpt::BOOL));
|
||||
// res.push_back(SocketOption("payloadsize", 0, SRTO_PAYLOADSIZE, SRT::SockOpt::PRE, SRT::SockOpt::INT));
|
||||
res.push_back(SocketOption("kmrefreshrate", 0, SRTO_KMREFRESHRATE, SRT::SockOpt::PRE, SRT::SockOpt::INT));
|
||||
res.push_back(SocketOption("kmpreannounce", 0, SRTO_KMPREANNOUNCE, SRT::SockOpt::PRE, SRT::SockOpt::INT));
|
||||
res.push_back(SocketOption("enforcedencryption", 0, SRTO_ENFORCEDENCRYPTION, SRT::SockOpt::PRE,
|
||||
SRT::SockOpt::BOOL));
|
||||
res.push_back(SocketOption("peeridletimeo", 0, SRTO_PEERIDLETIMEO, SRT::SockOpt::PRE, SRT::SockOpt::INT));
|
||||
res.push_back(SocketOption("packetfilter", 0, SRTO_PACKETFILTER, SRT::SockOpt::PRE, SRT::SockOpt::STRING));
|
||||
// res.push_back(SocketOption( "groupconnect", 0, SRTO_GROUPCONNECT, SRT::SockOpt::PRE, SRT::SockOpt::INT));
|
||||
// res.push_back(SocketOption( "groupstabtimeo", 0, SRTO_GROUPSTABTIMEO, SRT::SockOpt::PRE, SRT::SockOpt::INT));
|
||||
return res;
|
||||
}
|
||||
}// namespace Socket
|
||||
Loading…
Add table
Add a link
Reference in a new issue