Skip to content

Commit

Permalink
Example live receiver (#496)
Browse files Browse the repository at this point in the history
  • Loading branch information
ian-spoonradio authored and rndi committed Oct 29, 2019
1 parent ad149df commit 4f72a51
Show file tree
Hide file tree
Showing 2 changed files with 202 additions and 0 deletions.
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -919,6 +919,9 @@ if (ENABLE_EXAMPLES)
srt_add_example(recvfile.cpp apps/logsupport.cpp)
srt_make_application(recvfile)

srt_add_example(recvlive.cpp apps/logsupport.cpp)
srt_make_application(recvlive)

srt_add_example(test-c-client.c)
srt_make_application(test-c-client)

Expand Down
199 changes: 199 additions & 0 deletions examples/recvlive.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
#ifndef WIN32
#include <cstdlib>
#include <netdb.h>
#else
#include <winsock2.h>
#include <ws2tcpip.h>
#endif
#include <fstream>
#include <iostream>
#include <string>
#include <cstring>
#include <srt.h>
#include <assert.h> // assert

using namespace std;

int main(int argc, char* argv[])
{
// usage: recvlive [server_port]
if ((2 < argc) || ((2 == argc) && (0 == atoi(argv[1]))))
{
cout << "usage: recvlive [server_port]" << endl;
return 0;
}

// use this function to initialize the UDT library
srt_startup();

srt_setloglevel(logging::LogLevel::debug);

addrinfo hints;
addrinfo* res;

memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_flags = AI_PASSIVE;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;

string service("9000");
if (2 == argc)
service = argv[1];

if (0 != getaddrinfo(NULL, service.c_str(), &hints, &res))
{
cout << "illegal port number or port is busy.\n" << endl;
return 0;
}

SRTSOCKET sfd = srt_socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (SRT_INVALID_SOCK == sfd)
{
cout << "srt_socket: " << srt_getlasterror_str() << endl;
return 0;
}

// SRT requires that third argument is always SOCK_DGRAM. The Stream API is set by an option,
// although there's also lots of other options to be set, for which there's a convenience option,
// SRTO_TRANSTYPE.
// SRT_TRANSTYPE tt = SRTT_LIVE;
// if (SRT_ERROR == srt_setsockopt(sfd, 0, SRTO_TRANSTYPE, &tt, sizeof tt))
// {
// cout << "srt_setsockopt: " << srt_getlasterror_str() << endl;
// return 0;
// }

bool no = false;
if (SRT_ERROR == srt_setsockopt(sfd, 0, SRTO_RCVSYN, &no, sizeof no))
{
cout << "srt_setsockopt: " << srt_getlasterror_str() << endl;
return 0;
}

// Windows UDP issue
// For better performance, modify HKLM\System\CurrentControlSet\Services\Afd\Parameters\FastSendDatagramThreshold
#ifdef WIN32
int mss = 1052;
srt_setsockopt(sfd, 0, SRTO_MSS, &mss, sizeof(int));
#endif

// int64_t maxbw = 5000000;
// srt_setsockopt(sfd, 0, SRTO_MAXBW, &maxbw, sizeof maxbw);

if (SRT_ERROR == srt_bind(sfd, res->ai_addr, res->ai_addrlen))
{
cout << "srt_bind: " << srt_getlasterror_str() << endl;
return 0;
}

freeaddrinfo(res);

cout << "server is ready at port: " << service << endl;

if (SRT_ERROR == srt_listen(sfd, 10))
{
cout << "srt_listen: " << srt_getlasterror_str() << endl;
return 0;
}

int epid = srt_epoll_create();
if (epid < 0)
{
cout << "srt_epoll_create: " << srt_getlasterror_str() << endl;
return 0;
}

int events = SRT_EPOLL_IN | SRT_EPOLL_ERR;
if (SRT_ERROR == srt_epoll_add_usock(epid, sfd, &events))
{
cout << "srt_epoll_add_usock: " << srt_getlasterror_str() << endl;
return 0;
}

constexpr int srtrfdslenmax = 100;
SRTSOCKET srtrfds[srtrfdslenmax];
char data[1500];

// the event loop
while (true)
{
int srtrfdslen = srtrfdslenmax;
int n = srt_epoll_wait(epid, &srtrfds[0], &srtrfdslen, 0, 0, 100, 0, 0, 0, 0);
assert(n <= srtrfdslen);
for (int i = 0; i < n; i++)
{
SRTSOCKET s = srtrfds[i];
SRT_SOCKSTATUS status = srt_getsockstate(s);
if ((status == SRTS_BROKEN) ||
(status == SRTS_NONEXIST) ||
(status == SRTS_CLOSED))
{
cout << "source disconnected. status=" << status << endl;
srt_close(s);
continue;
}
else if (s == sfd)
{
assert(status == SRTS_LISTENING);

SRTSOCKET fhandle;
sockaddr_storage clientaddr;
int addrlen = sizeof(clientaddr);

fhandle = srt_accept(sfd, (sockaddr*)&clientaddr, &addrlen);
if (SRT_INVALID_SOCK == fhandle)
{
cout << "srt_accept: " << srt_getlasterror_str() << endl;
return 0;
}

char clienthost[NI_MAXHOST];
char clientservice[NI_MAXSERV];
getnameinfo((sockaddr *)&clientaddr, addrlen,
clienthost, sizeof(clienthost),
clientservice, sizeof(clientservice), NI_NUMERICHOST|NI_NUMERICSERV);
cout << "new connection: " << clienthost << ":" << clientservice << endl;

int events = SRT_EPOLL_IN | SRT_EPOLL_ERR;
if (SRT_ERROR == srt_epoll_add_usock(epid, fhandle, &events))
{
cout << "srt_epoll_add_usock: " << srt_getlasterror_str() << endl;
return 0;
}
}
else
{
while (true)
{
int ret = srt_recvmsg(s, data, sizeof(data));
if (SRT_ERROR == ret)
{
// EAGAIN for SRT READING
if (SRT_EASYNCRCV != srt_getlasterror(NULL))
{
cout << "srt_recvmsg: " << srt_getlasterror_str() << endl;
return 0;
}
break;
}
// cout << ret << " bytes received" << endl;
}
}
}
}

srt_close(sfd);

srt_epoll_release(epid);

// use this function to release the UDT library
srt_cleanup();

return 0;
}

// Local Variables:
// c-file-style: "ellemtel"
// c-basic-offset: 3
// compile-command: "g++ -Wall -O2 -std=c++11 -I.. -I../srtcore -o recvlive recvlive.cpp -L.. -lsrt -lpthread -L/usr/local/opt/openssl/lib -lssl -lcrypto"
// End:

0 comments on commit 4f72a51

Please sign in to comment.