/*
* SRT - Secure, Reliable, Transport
* Copyright (c) 2017 Haivision Systems Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; If not, see
*/
#include
#include
#include "srt.h"
int main(int argc, char** argv)
{
int globstatus = 0;
int ss, st;
struct sockaddr_in sa;
int yes = 1;
struct sockaddr_storage their_addr;
SRT_SOCKGROUPDATA* grpdata = NULL;
if (argc != 3) {
fprintf(stderr, "Usage: %s \n", argv[0]);
return 1;
}
printf("srt startup\n");
srt_startup();
// Since now, srt_cleanup() must be done before exiting.
printf("srt socket\n");
ss = srt_create_socket();
if (ss == SRT_ERROR)
{
fprintf(stderr, "srt_socket: %s\n", srt_getlasterror_str());
globstatus = 1;
goto cleanup;
}
// Now that the socket is created, jump to 'end' on error.
printf("srt bind address\n");
if (0 == strcmp(argv[1], "0"))
{
memset(&sa, 0, sizeof sa);
}
else if (inet_pton(AF_INET, argv[1], &sa.sin_addr) != 1)
{
fprintf(stderr, "srt_bind: Can't resolve address: %s\n", argv[1]);
globstatus = 1;
goto end;
}
sa.sin_family = AF_INET;
sa.sin_port = htons(atoi(argv[2]));
printf("srt setsockflag: groupconnect\n");
srt_setsockflag(ss, SRTO_GROUPCONNECT, &yes, sizeof yes);
printf("srt bind\n");
st = srt_bind(ss, (struct sockaddr*)&sa, sizeof sa);
if (st == SRT_ERROR)
{
fprintf(stderr, "srt_bind: %s\n", srt_getlasterror_str());
globstatus = 1;
goto end;
}
printf("srt listen\n");
// We set here 10, just for a case. Every unit in this number
// defines a maximum number of connections that can be pending
// simultaneously - it doesn't matter here if particular connection
// will belong to a bonding group or will be a single-socket connection.
st = srt_listen(ss, 10);
if (st == SRT_ERROR)
{
fprintf(stderr, "srt_listen: %s\n", srt_getlasterror_str());
globstatus = 1;
goto end;
}
// In this example, there will be prepared an array of 10 items.
// The listener, however, doesn't know how many member connections
// one bonded connection will contain, so a real application should be
// prepared for dynamically adjusting the array size.
const size_t N = 10;
grpdata = calloc(N, sizeof (SRT_SOCKGROUPDATA));
printf("srt accept\n");
int addr_size = sizeof their_addr;
SRTSOCKET their_fd = srt_accept(ss, (struct sockaddr *)&their_addr, &addr_size);
// You never know if `srt_accept` is going to give you a socket or a group.
// You have to check it on your own. The SRTO_GROUPCONNECT flag doesn't disallow
// single socket connections.
int isgroup = their_fd & SRTGROUP_MASK;
// Still, use the same procedure for receiving, no matter if
// this is a bonded or single connection.
int i;
for (i = 0; i < 100; i++)
{
printf("srt recvmsg #%d... ",i);
char msg[2048];
SRT_MSGCTRL mc = srt_msgctrl_default;
mc.grpdata = grpdata;
mc.grpdata_size = N;
st = srt_recvmsg2(their_fd, msg, sizeof msg, &mc);
if (st == SRT_ERROR)
{
fprintf(stderr, "srt_recvmsg: %s\n", srt_getlasterror_str());
goto end;
}
printf("Got msg of len %d << %s (%s)\n", st, msg, isgroup ? "group" : "single");
if (!isgroup)
continue;
if (!mc.grpdata)
printf("Group status: [%zi] members > %zi, can't handle.\n", mc.grpdata_size, N);
else
{
printf(" ++ Group status [%zi]: ", mc.grpdata_size);
size_t z;
for (z = 0; z < mc.grpdata_size; ++z)
{
printf( "[%zd] result=%d state=%s ", z, mc.grpdata[z].result,
mc.grpdata[z].sockstate <= SRTS_CONNECTING ? "pending" :
mc.grpdata[z].sockstate == SRTS_CONNECTED ? "connected" : "broken");
}
printf("\n");
}
}
end:
free(grpdata);
printf("srt close\n");
st = srt_close(ss);
if (st == SRT_ERROR)
{
fprintf(stderr, "srt_close: %s\n", srt_getlasterror_str());
// But not matter, we're finishing here.
}
cleanup:
printf("srt cleanup\n");
srt_cleanup();
return globstatus;
}