/*
* 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
#ifdef _WIN32
#define usleep(x) Sleep(x / 1000)
#else
#include
#endif
#include "srt.h"
struct
{
const char* name;
int gtype;
} group_types [] = {
{
"broadcast", SRT_GTYPE_BROADCAST
}
// Others will follow
};
#define SIZE(array) (sizeof array/sizeof(array[0]))
int main(int argc, char** argv)
{
int ss, st;
struct sockaddr_in sa;
//int yes = 1; // for options, none needed so far
const char message [] = "This message should be sent to the other side";
if (argc < 3)
{
fprintf(stderr, "Usage: %s { }... \n", argv[0]);
return 1;
}
int gtype = SRT_GTYPE_BROADCAST;
size_t i;
for (i = 0; i < SIZE(group_types); ++i)
if (0 == strcmp(group_types[i].name, argv[1]))
{
gtype = group_types[i].gtype;
break;
}
printf("srt startup\n");
srt_startup();
size_t nmemb = argc - 2;
if (nmemb % 2)
{
fprintf(stderr, "Usage error: after , pairs are expected.\n");
return 1;
}
nmemb /= 2;
SRT_SOCKGROUPCONFIG* grpconfig = calloc(nmemb, sizeof (SRT_SOCKGROUPCONFIG));
printf("srt group\n");
ss = srt_create_group(gtype);
if (ss == SRT_ERROR)
{
fprintf(stderr, "srt_create_group: %s\n", srt_getlasterror_str());
return 1;
}
const int B = 2;
for (i = 0; i < nmemb; ++i)
{
printf("srt remote address #%zi\n", i);
sa.sin_family = AF_INET;
sa.sin_port = htons(atoi(argv[B + 2*i + 1]));
if (inet_pton(AF_INET, argv[B + 2*i], &sa.sin_addr) != 1)
{
return 1;
}
grpconfig[i] = srt_prepare_endpoint(NULL, (struct sockaddr*)&sa, sizeof sa);
}
printf("srt connect (group)\n");
// Note: this function unblocks at the moment when at least one connection
// from the array is established (no matter which one); the others will
// continue in background.
st = srt_connect_group(ss, grpconfig, nmemb);
if (st == SRT_ERROR)
{
fprintf(stderr, "srt_connect: %s\n", srt_getlasterror_str());
return 1;
}
// Important: Normally you need that at least one link is ready for
// the group link to be ready. All but first are done actually in
// background, so this sleep only makes it more probable. If you'd like
// to make sure that ALL links are established - by some reason - then
// you'd have to subscribe for epoll event SRT_EPOLL_UPDATE and after the
// connect function exits do checks by srt_group_data to see if all links
// are established, and if not, repeat it after srt_epoll_wait for the
// SRT_EPOLL_UPDATE signal.
printf("sleeping 1s to make it probable all links are established\n");
sleep(1);
SRT_SOCKGROUPDATA* grpdata = calloc(nmemb, sizeof (SRT_SOCKGROUPDATA));
for (i = 0; i < 100; i++)
{
printf("srt sendmsg2 #%zd >> %s\n",i,message);
SRT_MSGCTRL mc = srt_msgctrl_default;
mc.grpdata = grpdata;
mc.grpdata_size = nmemb; // Set maximum known
st = srt_sendmsg2(ss, message, sizeof message, &mc);
if (st == SRT_ERROR)
{
fprintf(stderr, "srt_sendmsg: %s\n", srt_getlasterror_str());
return 1;
}
// Perform the group check. This can be used to recognize broken connections
// and probably reestablish them by calling `srt_connect` for them. Here they
// are only shown.
printf(" ++ Group status [%zi]:", mc.grpdata_size);
if (!mc.grpdata)
{
printf(" (ERROR: array too small!)\n");
}
else
{
for (i = 0; i < mc.grpdata_size; ++i)
{
printf( "[%zd] result=%d state=%s ", i, mc.grpdata[i].result,
mc.grpdata[i].sockstate <= SRTS_CONNECTING ? "pending" :
mc.grpdata[i].sockstate == SRTS_CONNECTED ? "connected" : "broken");
}
printf("\n");
}
usleep(1000); // 1 ms
}
printf("srt close\n");
st = srt_close(ss);
if (st == SRT_ERROR)
{
fprintf(stderr, "srt_close: %s\n", srt_getlasterror_str());
return 1;
}
free(grpdata);
free(grpconfig);
printf("srt cleanup\n");
srt_cleanup();
return 0;
}