1 /*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 /**
20 * @file
21 * Haivision Open SRT (Secure Reliable Transport) protocol
22 */
23
24 #include <srt/srt.h>
25
29
35
36 /* This is for MPEG-TS and it's a default SRTO_PAYLOADSIZE for SRTT_LIVE (8 TS packets) */
37 #ifndef SRT_LIVE_DEFAULT_PAYLOAD_SIZE
38 #define SRT_LIVE_DEFAULT_PAYLOAD_SIZE 1316
39 #endif
40
41 /* This is the maximum payload size for Live mode, should you have a different payload type than MPEG-TS */
42 #ifndef SRT_LIVE_MAX_PAYLOAD_SIZE
43 #define SRT_LIVE_MAX_PAYLOAD_SIZE 1456
44 #endif
45
50 };
51
60
64 #if SRT_VERSION_VALUE >= 0x010302
65 int enforced_encryption;
66 int kmrefreshrate;
67 int kmpreannounce;
68 int64_t snddropdelay;
69 #endif
95
96 #define D AV_OPT_FLAG_DECODING_PARAM
97 #define E AV_OPT_FLAG_ENCODING_PARAM
98 #define OFFSET(x) offsetof(SRTContext, x)
100 {
"timeout",
"Timeout of socket I/O operations (in microseconds)",
OFFSET(rw_timeout),
AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags =
D|
E },
101 {
"listen_timeout",
"Connection awaiting timeout (in microseconds)" ,
OFFSET(listen_timeout),
AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags =
D|
E },
102 {
"send_buffer_size",
"Socket send buffer size (in bytes)",
OFFSET(send_buffer_size),
AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags =
D|
E },
103 {
"recv_buffer_size",
"Socket receive buffer size (in bytes)",
OFFSET(recv_buffer_size),
AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags =
D|
E },
108 {
"maxbw",
"Maximum bandwidth (bytes per second) that the connection can use",
OFFSET(maxbw),
AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags =
D|
E },
109 {
"pbkeylen",
"Crypto key len in bytes {16,24,32} Default: 16 (128-bit)",
OFFSET(pbkeylen),
AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 32, .flags =
D|
E },
110 {
"passphrase",
"Crypto PBKDF2 Passphrase size[0,10..64] 0:disable crypto",
OFFSET(passphrase),
AV_OPT_TYPE_STRING, { .str =
NULL }, .flags =
D|
E },
111 #if SRT_VERSION_VALUE >= 0x010302
112 {
"enforced_encryption",
"Enforces that both connection parties have the same passphrase set",
OFFSET(enforced_encryption),
AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, .flags =
D|
E },
113 {
"kmrefreshrate",
"The number of packets to be transmitted after which the encryption key is switched to a new key",
OFFSET(kmrefreshrate),
AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags =
D|
E },
114 {
"kmpreannounce",
"The interval between when a new encryption key is sent and when switchover occurs",
OFFSET(kmpreannounce),
AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags =
D|
E },
115 {
"snddropdelay",
"The sender's extra delay(in microseconds) before dropping packets",
OFFSET(snddropdelay),
AV_OPT_TYPE_INT64, { .i64 = -2 }, -2, INT64_MAX, .flags =
D|
E },
116 #endif
118 {
"ffs",
"Flight flag size (window size) (in bytes)",
OFFSET(ffs),
AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags =
D|
E },
121 {
"inputbw",
"Estimated input stream rate",
OFFSET(inputbw),
AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags =
D|
E },
122 {
"oheadbw",
"MaxBW ceiling based on % over input stream rate",
OFFSET(oheadbw),
AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 100, .flags =
D|
E },
123 {
"latency",
"receiver delay (in microseconds) to absorb bursts of missed packet retransmissions",
OFFSET(latency),
AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags =
D|
E },
124 {
"tsbpddelay",
"deprecated, same effect as latency option",
OFFSET(latency),
AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags =
D|
E },
125 {
"rcvlatency",
"receive latency (in microseconds)",
OFFSET(rcvlatency),
AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags =
D|
E },
126 {
"peerlatency",
"peer latency (in microseconds)",
OFFSET(peerlatency),
AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags =
D|
E },
127 {
"tlpktdrop",
"Enable too-late pkt drop",
OFFSET(tlpktdrop),
AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, .flags =
D|
E },
128 {
"nakreport",
"Enable receiver to send periodic NAK reports",
OFFSET(nakreport),
AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, .flags =
D|
E },
129 {
"connect_timeout",
"Connect timeout(in milliseconds). Caller default: 3000, rendezvous (x 10)",
OFFSET(connect_timeout),
AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags =
D|
E },
130 {
"mode",
"Connection mode (caller, listener, rendezvous)",
OFFSET(
mode),
AV_OPT_TYPE_INT, { .i64 =
SRT_MODE_CALLER },
SRT_MODE_CALLER,
SRT_MODE_RENDEZVOUS, .flags =
D|
E,
"mode" },
134 {
"sndbuf",
"Send buffer size (in bytes)",
OFFSET(sndbuf),
AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags =
D|
E },
135 {
"rcvbuf",
"Receive buffer size (in bytes)",
OFFSET(rcvbuf),
AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags =
D|
E },
136 {
"lossmaxttl",
"Maximum possible packet reorder tolerance",
OFFSET(lossmaxttl),
AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags =
D|
E },
137 {
"minversion",
"The minimum SRT version that is required from the peer",
OFFSET(minversion),
AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags =
D|
E },
138 {
"streamid",
"A string of up to 512 characters that an Initiator can pass to a Responder",
OFFSET(streamid),
AV_OPT_TYPE_STRING, { .str =
NULL }, .flags =
D|
E },
139 {
"srt_streamid",
"A string of up to 512 characters that an Initiator can pass to a Responder",
OFFSET(streamid),
AV_OPT_TYPE_STRING, { .str =
NULL }, .flags =
D|
E },
140 {
"smoother",
"The type of Smoother used for the transmission for that socket",
OFFSET(smoother),
AV_OPT_TYPE_STRING, { .str =
NULL }, .flags =
D|
E },
142 {
"transtype",
"The transmission type for the socket",
OFFSET(transtype),
AV_OPT_TYPE_INT, { .i64 = SRTT_INVALID }, SRTT_LIVE, SRTT_INVALID, .flags =
D|
E,
"transtype" },
145 {
"linger",
"Number of seconds that the socket waits for unsent data when closing",
OFFSET(linger),
AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags =
D|
E },
146 {
"tsbpd",
"Timestamp-based packet delivery",
OFFSET(tsbpd),
AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, .flags =
D|
E },
148 };
149
151 {
152 int os_errno;
153 int err = srt_getlasterror(&os_errno);
154 if (err == SRT_EASYNCRCV || err == SRT_EASYNCSND)
158 }
159
161 {
162 if (srt_getsockopt(fd, 0, optname, optval, optlen) < 0) {
163 av_log(
h,
AV_LOG_ERROR,
"failed to get option %s on socket: %s\n", optnamestr, srt_getlasterror_str());
165 }
166 return 0;
167 }
168
170 {
171 int ret, blocking = enable ? 0 : 1;
172 /* Setting SRTO_{SND,RCV}SYN options to 1 enable blocking mode, setting them to 0 enable non-blocking mode. */
173 ret = srt_setsockopt(socket, 0, SRTO_SNDSYN, &blocking,
sizeof(blocking));
176 return srt_setsockopt(socket, 0, SRTO_RCVSYN, &blocking, sizeof(blocking));
177 }
178
180 {
181 int modes = SRT_EPOLL_ERR | (write ? SRT_EPOLL_OUT : SRT_EPOLL_IN);
182 int eid = srt_epoll_create();
183 if (eid < 0)
185 if (srt_epoll_add_usock(eid, fd, &
modes) < 0) {
186 srt_epoll_release(eid);
188 }
189 return eid;
190 }
191
193 {
194 int ret,
len = 1, errlen = 1;
197
198 if (write) {
200 } else {
202 }
204 if (srt_getlasterror(
NULL) == SRT_ETIMEOUT)
206 else
208 } else {
210 }
212 }
213
214 /* TODO de-duplicate code from ff_network_wait_fd_timeout() */
215
217 {
219 int64_t wait_start = 0;
220
221 while (1) {
227 if (timeout > 0) {
228 if (!wait_start)
232 }
233 }
234 }
235
237 {
239 int reuse = 1;
240 /* Max streamid length plus an extra space for the terminating null character */
241 char streamid[513];
242 int streamid_len = sizeof(streamid);
243 if (srt_setsockopt(fd, SOL_SOCKET, SRTO_REUSEADDR, &reuse, sizeof(reuse))) {
245 }
246 if (srt_bind(fd, addr, addrlen))
248
249 if (srt_listen(fd, 1))
251
255
262 /* Note: returned streamid_len doesn't count the terminating null character */
264
266 }
267
269 {
271
272 if (srt_connect(fd, addr, addrlen) < 0)
274
277 if (will_try_next) {
279 "Connection to %s failed (%s), trying next address\n",
281 } else {
284 }
285 }
287 }
288
290 {
291 if (srt_setsockopt(fd, 0, optname, optval, optlen) < 0) {
292 av_log(
h,
AV_LOG_ERROR,
"failed to set option %s on socket: %s\n", optnamestr, srt_getlasterror_str());
294 }
295 return 0;
296 }
297
298 /* - The "POST" options can be altered any time on a connected socket.
299 They MAY have also some meaning when set prior to connecting; such
300 option is SRTO_RCVSYN, which makes connect/accept call asynchronous.
301 Because of that this option is treated special way in this app. */
303 {
305
306 if ((
s->inputbw >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_INPUTBW,
"SRTO_INPUTBW", &
s->inputbw,
sizeof(
s->inputbw)) < 0) ||
307 (
s->oheadbw >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_OHEADBW,
"SRTO_OHEADBW", &
s->oheadbw,
sizeof(
s->oheadbw)) < 0)) {
309 }
310 return 0;
311 }
312
313 /* - The "PRE" options must be set prior to connecting and can't be altered
314 on a connected socket, however if set on a listening socket, they are
315 derived by accept-ed socket. */
317 {
319 int yes = 1;
320 int latency =
s->latency / 1000;
321 int rcvlatency =
s->rcvlatency / 1000;
322 int peerlatency =
s->peerlatency / 1000;
323 #if SRT_VERSION_VALUE >= 0x010302
324 int snddropdelay =
s->snddropdelay > 0 ?
s->snddropdelay / 1000 :
s->snddropdelay;
325 #endif
326 int connect_timeout =
s->connect_timeout;
327
329 (
s->transtype != SRTT_INVALID &&
libsrt_setsockopt(
h, fd, SRTO_TRANSTYPE,
"SRTO_TRANSTYPE", &
s->transtype,
sizeof(
s->transtype)) < 0) ||
330 (
s->maxbw >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_MAXBW,
"SRTO_MAXBW", &
s->maxbw,
sizeof(
s->maxbw)) < 0) ||
331 (
s->pbkeylen >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_PBKEYLEN,
"SRTO_PBKEYLEN", &
s->pbkeylen,
sizeof(
s->pbkeylen)) < 0) ||
332 (
s->passphrase &&
libsrt_setsockopt(
h, fd, SRTO_PASSPHRASE,
"SRTO_PASSPHRASE",
s->passphrase, strlen(
s->passphrase)) < 0) ||
333 #if SRT_VERSION_VALUE >= 0x010302
334 #if SRT_VERSION_VALUE >= 0x010401
335 (
s->enforced_encryption >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_ENFORCEDENCRYPTION,
"SRTO_ENFORCEDENCRYPTION", &
s->enforced_encryption,
sizeof(
s->enforced_encryption)) < 0) ||
336 #else
337 /* SRTO_STRICTENC == SRTO_ENFORCEDENCRYPTION (53), but for compatibility, we used SRTO_STRICTENC */
338 (
s->enforced_encryption >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_STRICTENC,
"SRTO_STRICTENC", &
s->enforced_encryption,
sizeof(
s->enforced_encryption)) < 0) ||
339 #endif
340 (
s->kmrefreshrate >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_KMREFRESHRATE,
"SRTO_KMREFRESHRATE", &
s->kmrefreshrate,
sizeof(
s->kmrefreshrate)) < 0) ||
341 (
s->kmpreannounce >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_KMPREANNOUNCE,
"SRTO_KMPREANNOUNCE", &
s->kmpreannounce,
sizeof(
s->kmpreannounce)) < 0) ||
342 (
s->snddropdelay >=-1 &&
libsrt_setsockopt(
h, fd, SRTO_SNDDROPDELAY,
"SRTO_SNDDROPDELAY", &snddropdelay,
sizeof(snddropdelay)) < 0) ||
343 #endif
346 (
s->ipttl >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_IPTTL,
"SRTO_IPTTL", &
s->ipttl,
sizeof(
s->ipttl)) < 0) ||
347 (
s->iptos >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_IPTOS,
"SRTO_IPTOS", &
s->iptos,
sizeof(
s->iptos)) < 0) ||
348 (
s->latency >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_LATENCY,
"SRTO_LATENCY", &latency,
sizeof(latency)) < 0) ||
349 (
s->rcvlatency >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_RCVLATENCY,
"SRTO_RCVLATENCY", &rcvlatency,
sizeof(rcvlatency)) < 0) ||
350 (
s->peerlatency >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_PEERLATENCY,
"SRTO_PEERLATENCY", &peerlatency,
sizeof(peerlatency)) < 0) ||
351 (
s->tlpktdrop >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_TLPKTDROP,
"SRTO_TLPKTDROP", &
s->tlpktdrop,
sizeof(
s->tlpktdrop)) < 0) ||
352 (
s->nakreport >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_NAKREPORT,
"SRTO_NAKREPORT", &
s->nakreport,
sizeof(
s->nakreport)) < 0) ||
353 (connect_timeout >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_CONNTIMEO,
"SRTO_CONNTIMEO", &connect_timeout,
sizeof(connect_timeout)) <0 ) ||
354 (
s->sndbuf >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_SNDBUF,
"SRTO_SNDBUF", &
s->sndbuf,
sizeof(
s->sndbuf)) < 0) ||
355 (
s->rcvbuf >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_RCVBUF,
"SRTO_RCVBUF", &
s->rcvbuf,
sizeof(
s->rcvbuf)) < 0) ||
356 (
s->lossmaxttl >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_LOSSMAXTTL,
"SRTO_LOSSMAXTTL", &
s->lossmaxttl,
sizeof(
s->lossmaxttl)) < 0) ||
357 (
s->minversion >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_MINVERSION,
"SRTO_MINVERSION", &
s->minversion,
sizeof(
s->minversion)) < 0) ||
358 (
s->streamid &&
libsrt_setsockopt(
h, fd, SRTO_STREAMID,
"SRTO_STREAMID",
s->streamid, strlen(
s->streamid)) < 0) ||
359 #if SRT_VERSION_VALUE >= 0x010401
360 (
s->smoother &&
libsrt_setsockopt(
h, fd, SRTO_CONGESTION,
"SRTO_CONGESTION",
s->smoother, strlen(
s->smoother)) < 0) ||
362 (
s->smoother &&
libsrt_setsockopt(
h, fd, SRTO_SMOOTHER,
"SRTO_SMOOTHER",
s->smoother, strlen(
s->smoother)) < 0) ||
363 #endif
364 (
s->messageapi >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_MESSAGEAPI,
"SRTO_MESSAGEAPI", &
s->messageapi,
sizeof(
s->messageapi)) < 0) ||
365 (
s->payload_size >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_PAYLOADSIZE,
"SRTO_PAYLOADSIZE", &
s->payload_size,
sizeof(
s->payload_size)) < 0) ||
367 (
s->tsbpd >= 0 &&
libsrt_setsockopt(
h, fd, SRTO_TSBPDMODE,
"SRTO_TSBPDMODE", &
s->tsbpd,
sizeof(
s->tsbpd)) < 0)) {
369 }
370
371 if (
s->linger >= 0) {
372 struct linger lin;
373 lin.l_linger =
s->linger;
374 lin.l_onoff = lin.l_linger > 0 ? 1 : 0;
377 }
378 return 0;
379 }
380
381
383 {
384 struct addrinfo hints = { 0 }, *ai, *cur_ai;
385 int port, fd;
387 const char *p;
388 char buf[256];
390 char hostname[1024],proto[1024],path[1024];
391 char portstr[10];
392 int64_t open_timeout = 0;
393 int eid, write_eid;
394
396 &port, path, sizeof(path), uri);
397 if (strcmp(proto, "srt"))
399 if (port <= 0 || port >= 65536) {
402 }
403 p = strchr(uri, '?');
404 if (p) {
406 s->rw_timeout = strtoll(buf,
NULL, 10);
407 }
409 s->listen_timeout = strtoll(buf,
NULL, 10);
410 }
411 }
412 if (
s->rw_timeout >= 0) {
413 open_timeout =
h->rw_timeout =
s->rw_timeout;
414 }
417 snprintf(portstr,
sizeof(portstr),
"%d", port);
423 "Failed to resolve hostname %s: %s\n",
426 }
427
428 cur_ai = ai;
429
430 restart:
431
432 #if SRT_VERSION_VALUE >= 0x010401
433 fd = srt_create_socket();
434 #else
435 fd = srt_socket(cur_ai->ai_family, cur_ai->ai_socktype, 0);
436 #endif
437 if (fd < 0) {
440 }
441
444 }
445
446 /* Set the socket's send or receive buffer sizes, if specified.
447 If unspecified or setting fails, system default is used. */
448 if (
s->recv_buffer_size > 0) {
449 srt_setsockopt(fd, SOL_SOCKET, SRTO_UDP_RCVBUF, &
s->recv_buffer_size, sizeof (
s->recv_buffer_size));
450 }
451 if (
s->send_buffer_size > 0) {
452 srt_setsockopt(fd, SOL_SOCKET, SRTO_UDP_SNDBUF, &
s->send_buffer_size, sizeof (
s->send_buffer_size));
453 }
456
459 goto fail1;
461 // multi-client
462 ret =
libsrt_listen(write_eid, fd, cur_ai->ai_addr, cur_ai->ai_addrlen,
h,
s->listen_timeout);
463 srt_epoll_release(write_eid);
465 goto fail1;
466 srt_close(fd);
468 } else {
470 if (srt_bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen)) {
472 srt_epoll_release(write_eid);
473 goto fail1;
474 }
475 }
476
478 open_timeout,
h, !!cur_ai->ai_next);
479 srt_epoll_release(write_eid);
482 goto fail1;
483 else
485 }
486 }
489 }
490
492 int packet_size = 0;
493 int optlen = sizeof(packet_size);
496 goto fail1;
497 if (packet_size > 0)
498 h->max_packet_size = packet_size;
499 }
500
502 if (eid < 0)
503 goto fail1;
504
508
510 return 0;
511
513 if (cur_ai->ai_next) {
514 /* Retry with the next sockaddr */
515 cur_ai = cur_ai->ai_next;
516 if (fd >= 0)
517 srt_close(fd);
519 goto restart;
520 }
521 fail1:
522 if (fd >= 0)
523 srt_close(fd);
526 }
527
529 {
531 const char * p;
532 char buf[1024];
534
535 if (srt_startup() < 0) {
537 }
538
539 /* SRT options (srt/srt.h) */
540 p = strchr(uri, '?');
541 if (p) {
543 s->maxbw = strtoll(buf,
NULL, 10);
544 }
546 s->pbkeylen = strtol(buf,
NULL, 10);
547 }
551 }
552 #if SRT_VERSION_VALUE >= 0x010302
554 s->enforced_encryption = strtol(buf,
NULL, 10);
555 }
557 s->kmrefreshrate = strtol(buf,
NULL, 10);
558 }
560 s->kmpreannounce = strtol(buf,
NULL, 10);
561 }
563 s->snddropdelay = strtoll(buf,
NULL, 10);
564 }
565 #endif
567 s->mss = strtol(buf,
NULL, 10);
568 }
570 s->ffs = strtol(buf,
NULL, 10);
571 }
573 s->ipttl = strtol(buf,
NULL, 10);
574 }
576 s->iptos = strtol(buf,
NULL, 10);
577 }
579 s->inputbw = strtoll(buf,
NULL, 10);
580 }
582 s->oheadbw = strtol(buf,
NULL, 10);
583 }
585 s->latency = strtoll(buf,
NULL, 10);
586 }
588 s->latency = strtoll(buf,
NULL, 10);
589 }
591 s->rcvlatency = strtoll(buf,
NULL, 10);
592 }
594 s->peerlatency = strtoll(buf,
NULL, 10);
595 }
597 s->tlpktdrop = strtol(buf,
NULL, 10);
598 }
600 s->nakreport = strtol(buf,
NULL, 10);
601 }
603 s->connect_timeout = strtoll(buf,
NULL, 10);
604 }
607 s->payload_size = strtol(buf,
NULL, 10);
608 }
610 if (!strcmp(buf, "caller")) {
612 } else if (!strcmp(buf, "listener")) {
614 } else if (!strcmp(buf, "rendezvous")) {
616 } else {
618 goto err;
619 }
620 }
622 s->sndbuf = strtol(buf,
NULL, 10);
623 }
625 s->rcvbuf = strtol(buf,
NULL, 10);
626 }
628 s->lossmaxttl = strtol(buf,
NULL, 10);
629 }
631 s->minversion = strtol(buf,
NULL, 0);
632 }
638 goto err;
639 }
640 }
646 goto err;
647 }
648 }
650 s->messageapi = strtol(buf,
NULL, 10);
651 }
653 if (!strcmp(buf, "live")) {
654 s->transtype = SRTT_LIVE;
655 } else if (!strcmp(buf, "file")) {
656 s->transtype = SRTT_FILE;
657 } else {
659 goto err;
660 }
661 }
663 s->linger = strtol(buf,
NULL, 10);
664 }
665 }
668 goto err;
669 return 0;
670
671 err:
674 srt_cleanup();
676 }
677
679 {
682
687 }
688
689 ret = srt_recvmsg(
s->fd, buf,
size);
692 }
693
695 }
696
698 {
701
706 }
707
708 ret = srt_sendmsg(
s->fd, buf,
size, -1, 1);
711 }
712
714 }
715
717 {
719
720 srt_epoll_release(
s->eid);
722
723 srt_cleanup();
724
725 return 0;
726 }
727
733 };
734
744 };