#ifndef INC_SRT_COMMON_TRANSMITMEDIA_HPP
#define INC_SRT_COMMON_TRANSMITMEDIA_HPP
#include <string>
#include <map>
#include <stdexcept>
#include "transmitbase.hpp"
#include <udt.h>
using namespace std;
struct TransmissionError: public std::runtime_error
{
TransmissionError(const std::string& arg):
std::runtime_error(arg)
{
}
};
class SrtCommon
{
protected:
bool m_output_direction = false; int m_timeout = 0; bool m_tsbpdmode = true;
int m_outgoing_port = 0;
string m_mode;
string m_adapter;
map<string, string> m_options; SRTSOCKET m_sock = SRT_INVALID_SOCK;
SRTSOCKET m_bindsock = SRT_INVALID_SOCK;
bool IsUsable() { SRT_SOCKSTATUS st = srt_getsockstate(m_sock); return st > SRTS_INIT && st < SRTS_BROKEN; }
bool IsBroken() { return srt_getsockstate(m_sock) > SRTS_CONNECTED; }
public:
void InitParameters(string host, map<string,string> par);
void PrepareListener(string host, int port, int backlog);
void StealFrom(SrtCommon& src);
bool AcceptNewClient();
SRTSOCKET Socket() const { return m_sock; }
SRTSOCKET Listener() const { return m_bindsock; }
virtual void Close();
protected:
void Error(string src);
void Init(string host, int port, map<string,string> par, bool dir_output);
virtual int ConfigurePost(SRTSOCKET sock);
virtual int ConfigurePre(SRTSOCKET sock);
void OpenClient(string host, int port);
void PrepareClient();
void SetupAdapter(const std::string& host, int port);
void ConnectClient(string host, int port);
void OpenServer(string host, int port)
{
PrepareListener(host, port, 1);
}
void OpenRendezvous(string adapter, string host, int port);
virtual ~SrtCommon();
};
class SrtSource: public Source, public SrtCommon
{
std::string hostport_copy;
public:
SrtSource(std::string host, int port, const std::map<std::string,std::string>& par);
SrtSource()
{
}
int Read(size_t chunk, MediaPacket& pkt, ostream& out_stats = cout) override;
bool IsOpen() override { return IsUsable(); }
bool End() override { return IsBroken(); }
void Close() override { return SrtCommon::Close(); }
SRTSOCKET GetSRTSocket() const override
{
SRTSOCKET socket = SrtCommon::Socket();
if (socket == SRT_INVALID_SOCK)
socket = SrtCommon::Listener();
return socket;
}
bool AcceptNewClient() override { return SrtCommon::AcceptNewClient(); }
};
class SrtTarget: public Target, public SrtCommon
{
public:
SrtTarget(std::string host, int port, const std::map<std::string,std::string>& par)
{
Init(host, port, par, true);
}
SrtTarget() {}
int ConfigurePre(SRTSOCKET sock) override;
int Write(const char* data, size_t size, int64_t src_time, ostream &out_stats = cout) override;
bool IsOpen() override { return IsUsable(); }
bool Broken() override { return IsBroken(); }
void Close() override { return SrtCommon::Close(); }
size_t Still() override
{
size_t bytes;
int st = srt_getsndbuffer(m_sock, nullptr, &bytes);
if (st == -1)
return 0;
return bytes;
}
SRTSOCKET GetSRTSocket() const override
{
SRTSOCKET socket = SrtCommon::Socket();
if (socket == SRT_INVALID_SOCK)
socket = SrtCommon::Listener();
return socket;
}
bool AcceptNewClient() override { return SrtCommon::AcceptNewClient(); }
};
class SrtModel: public SrtCommon
{
public:
bool is_caller = false;
string m_host;
int m_port = 0;
SrtModel(string host, int port, map<string,string> par);
void Establish(std::string& name);
void Close()
{
if (m_sock != SRT_INVALID_SOCK)
{
srt_close(m_sock);
m_sock = SRT_INVALID_SOCK;
}
}
};
#endif