1/* 2 * RTP network protocol 3 * Copyright (c) 2002 Fabrice Bellard 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * FFmpeg is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22/** 23 * @file 24 * RTP protocol 25 */ 26 27#include "libavutil/parseutils.h" 28#include "libavutil/avstring.h" 29#include "avformat.h" 30#include "avio_internal.h" 31#include "rtp.h" 32#include "rtpproto.h" 33#include "url.h" 34 35#include <stdarg.h> 36#include "internal.h" 37#include "network.h" 38#include "os_support.h" 39#include <fcntl.h> 40#if HAVE_POLL_H 41#include <sys/poll.h> 42#endif 43 44typedef struct RTPContext { 45 URLContext *rtp_hd, *rtcp_hd; 46 int rtp_fd, rtcp_fd, nb_ssm_include_addrs, nb_ssm_exclude_addrs; 47 struct sockaddr_storage **ssm_include_addrs, **ssm_exclude_addrs; 48 int write_to_source; 49 struct sockaddr_storage last_rtp_source, last_rtcp_source; 50 socklen_t last_rtp_source_len, last_rtcp_source_len; 51} RTPContext; 52 53/** 54 * If no filename is given to av_open_input_file because you want to 55 * get the local port first, then you must call this function to set 56 * the remote server address. 57 * 58 * @param h media file context 59 * @param uri of the remote server 60 * @return zero if no error. 61 */ 62 63int ff_rtp_set_remote_url(URLContext *h, const char *uri) 64{ 65 RTPContext *s = h->priv_data; 66 char hostname[256]; 67 int port, rtcp_port; 68 const char *p; 69 70 char buf[1024]; 71 char path[1024]; 72 73 av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, 74 path, sizeof(path), uri); 75 rtcp_port = port + 1; 76 77 p = strchr(uri, '?'); 78 if (p) { 79 if (av_find_info_tag(buf, sizeof(buf), "rtcpport", p)) { 80 rtcp_port = strtol(buf, NULL, 10); 81 } 82 } 83 84 ff_url_join(buf, sizeof(buf), "udp", NULL, hostname, port, "%s", path); 85 ff_udp_set_remote_url(s->rtp_hd, buf); 86 87 ff_url_join(buf, sizeof(buf), "udp", NULL, hostname, rtcp_port, "%s", path); 88 ff_udp_set_remote_url(s->rtcp_hd, buf); 89 return 0; 90} 91 92static struct addrinfo* rtp_resolve_host(const char *hostname, int port, 93 int type, int family, int flags) 94{ 95 struct addrinfo hints = { 0 }, *res = 0; 96 int error; 97 char service[16]; 98 99 snprintf(service, sizeof(service), "%d", port); 100 hints.ai_socktype = type; 101 hints.ai_family = family; 102 hints.ai_flags = flags; 103 if ((error = getaddrinfo(hostname, service, &hints, &res))) { 104 res = NULL; 105 av_log(NULL, AV_LOG_ERROR, "rtp_resolve_host: %s\n", gai_strerror(error)); 106 } 107 108 return res; 109} 110 111static int compare_addr(const struct sockaddr_storage *a, 112 const struct sockaddr_storage *b) 113{ 114 if (a->ss_family != b->ss_family) 115 return 1; 116 if (a->ss_family == AF_INET) { 117 return (((const struct sockaddr_in *)a)->sin_addr.s_addr != 118 ((const struct sockaddr_in *)b)->sin_addr.s_addr); 119 } 120 121#if HAVE_STRUCT_SOCKADDR_IN6 122 if (a->ss_family == AF_INET6) { 123 const uint8_t *s6_addr_a = ((const struct sockaddr_in6 *)a)->sin6_addr.s6_addr; 124 const uint8_t *s6_addr_b = ((const struct sockaddr_in6 *)b)->sin6_addr.s6_addr; 125 return memcmp(s6_addr_a, s6_addr_b, 16); 126 } 127#endif 128 return 1; 129} 130 131static int get_port(const struct sockaddr_storage *ss) 132{ 133 if (ss->ss_family == AF_INET) 134 return ntohs(((const struct sockaddr_in *)ss)->sin_port); 135#if HAVE_STRUCT_SOCKADDR_IN6 136 if (ss->ss_family == AF_INET6) 137 return ntohs(((const struct sockaddr_in6 *)ss)->sin6_port); 138#endif 139 return 0; 140} 141 142static void set_port(struct sockaddr_storage *ss, int port) 143{ 144 if (ss->ss_family == AF_INET) 145 ((struct sockaddr_in *)ss)->sin_port = htons(port); 146#if HAVE_STRUCT_SOCKADDR_IN6 147 else if (ss->ss_family == AF_INET6) 148 ((struct sockaddr_in6 *)ss)->sin6_port = htons(port); 149#endif 150} 151 152static int rtp_check_source_lists(RTPContext *s, struct sockaddr_storage *source_addr_ptr) 153{ 154 int i; 155 if (s->nb_ssm_exclude_addrs) { 156 for (i = 0; i < s->nb_ssm_exclude_addrs; i++) { 157 if (!compare_addr(source_addr_ptr, s->ssm_exclude_addrs[i])) 158 return 1; 159 } 160 } 161 if (s->nb_ssm_include_addrs) { 162 for (i = 0; i < s->nb_ssm_include_addrs; i++) { 163 if (!compare_addr(source_addr_ptr, s->ssm_include_addrs[i])) 164 return 0; 165 } 166 return 1; 167 } 168 return 0; 169} 170 171/** 172 * add option to url of the form: 173 * "http://host:port/path?option1=val1&option2=val2... 174 */ 175 176static av_printf_format(3, 4) void url_add_option(char *buf, int buf_size, const char *fmt, ...) 177{ 178 char buf1[1024]; 179 va_list ap; 180 181 va_start(ap, fmt); 182 if (strchr(buf, '?')) 183 av_strlcat(buf, "&", buf_size); 184 else 185 av_strlcat(buf, "?", buf_size); 186 vsnprintf(buf1, sizeof(buf1), fmt, ap); 187 av_strlcat(buf, buf1, buf_size); 188 va_end(ap); 189} 190 191static void build_udp_url(char *buf, int buf_size, 192 const char *hostname, int port, 193 int local_port, int ttl, 194 int max_packet_size, int connect, 195 const char *include_sources, 196 const char *exclude_sources) 197{ 198 ff_url_join(buf, buf_size, "udp", NULL, hostname, port, NULL); 199 if (local_port >= 0) 200 url_add_option(buf, buf_size, "localport=%d", local_port); 201 if (ttl >= 0) 202 url_add_option(buf, buf_size, "ttl=%d", ttl); 203 if (max_packet_size >=0) 204 url_add_option(buf, buf_size, "pkt_size=%d", max_packet_size); 205 if (connect) 206 url_add_option(buf, buf_size, "connect=1"); 207 url_add_option(buf, buf_size, "fifo_size=0"); 208 if (include_sources && include_sources[0]) 209 url_add_option(buf, buf_size, "sources=%s", include_sources); 210 if (exclude_sources && exclude_sources[0]) 211 url_add_option(buf, buf_size, "block=%s", exclude_sources); 212} 213 214static void rtp_parse_addr_list(URLContext *h, char *buf, 215 struct sockaddr_storage ***address_list_ptr, 216 int *address_list_size_ptr) 217{ 218 struct addrinfo *ai = NULL; 219 struct sockaddr_storage *source_addr; 220 char tmp = '\0', *p = buf, *next; 221 222 /* Resolve all of the IPs */ 223 224 while (p && p[0]) { 225 next = strchr(p, ','); 226 227 if (next) { 228 tmp = *next; 229 *next = '\0'; 230 } 231 232 ai = rtp_resolve_host(p, 0, SOCK_DGRAM, AF_UNSPEC, 0); 233 if (ai) { 234 source_addr = av_mallocz(sizeof(struct sockaddr_storage)); 235 if (!source_addr) 236 break; 237 238 memcpy(source_addr, ai->ai_addr, ai->ai_addrlen); 239 freeaddrinfo(ai); 240 dynarray_add(address_list_ptr, address_list_size_ptr, source_addr); 241 } else { 242 av_log(h, AV_LOG_WARNING, "Unable to resolve %s\n", p); 243 } 244 245 if (next) { 246 *next = tmp; 247 p = next + 1; 248 } else { 249 p = NULL; 250 } 251 } 252} 253 254/** 255 * url syntax: rtp://host:port[?option=val...] 256 * option: 'ttl=n' : set the ttl value (for multicast only) 257 * 'rtcpport=n' : set the remote rtcp port to n 258 * 'localrtpport=n' : set the local rtp port to n 259 * 'localrtcpport=n' : set the local rtcp port to n 260 * 'pkt_size=n' : set max packet size 261 * 'connect=0/1' : do a connect() on the UDP socket 262 * 'sources=ip[,ip]' : list allowed source IP addresses 263 * 'block=ip[,ip]' : list disallowed source IP addresses 264 * 'write_to_source=0/1' : send packets to the source address of the latest received packet 265 * deprecated option: 266 * 'localport=n' : set the local port to n 267 * 268 * if rtcpport isn't set the rtcp port will be the rtp port + 1 269 * if local rtp port isn't set any available port will be used for the local 270 * rtp and rtcp ports 271 * if the local rtcp port is not set it will be the local rtp port + 1 272 */ 273 274static int rtp_open(URLContext *h, const char *uri, int flags) 275{ 276 RTPContext *s = h->priv_data; 277 int rtp_port, rtcp_port, 278 ttl, connect, 279 local_rtp_port, local_rtcp_port, max_packet_size; 280 char hostname[256], include_sources[1024] = "", exclude_sources[1024] = ""; 281 char buf[1024]; 282 char path[1024]; 283 const char *p; 284 int i, max_retry_count = 3; 285 286 av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &rtp_port, 287 path, sizeof(path), uri); 288 /* extract parameters */ 289 ttl = -1; 290 rtcp_port = rtp_port+1; 291 local_rtp_port = -1; 292 local_rtcp_port = -1; 293 max_packet_size = -1; 294 connect = 0; 295 296 p = strchr(uri, '?'); 297 if (p) { 298 if (av_find_info_tag(buf, sizeof(buf), "ttl", p)) { 299 ttl = strtol(buf, NULL, 10); 300 } 301 if (av_find_info_tag(buf, sizeof(buf), "rtcpport", p)) { 302 rtcp_port = strtol(buf, NULL, 10); 303 } 304 if (av_find_info_tag(buf, sizeof(buf), "localport", p)) { 305 local_rtp_port = strtol(buf, NULL, 10); 306 } 307 if (av_find_info_tag(buf, sizeof(buf), "localrtpport", p)) { 308 local_rtp_port = strtol(buf, NULL, 10); 309 } 310 if (av_find_info_tag(buf, sizeof(buf), "localrtcpport", p)) { 311 local_rtcp_port = strtol(buf, NULL, 10); 312 } 313 if (av_find_info_tag(buf, sizeof(buf), "pkt_size", p)) { 314 max_packet_size = strtol(buf, NULL, 10); 315 } 316 if (av_find_info_tag(buf, sizeof(buf), "connect", p)) { 317 connect = strtol(buf, NULL, 10); 318 } 319 if (av_find_info_tag(buf, sizeof(buf), "write_to_source", p)) { 320 s->write_to_source = strtol(buf, NULL, 10); 321 } 322 if (av_find_info_tag(buf, sizeof(buf), "sources", p)) { 323 av_strlcpy(include_sources, buf, sizeof(include_sources)); 324 rtp_parse_addr_list(h, buf, &s->ssm_include_addrs, &s->nb_ssm_include_addrs); 325 } 326 if (av_find_info_tag(buf, sizeof(buf), "block", p)) { 327 av_strlcpy(exclude_sources, buf, sizeof(exclude_sources)); 328 rtp_parse_addr_list(h, buf, &s->ssm_exclude_addrs, &s->nb_ssm_exclude_addrs); 329 } 330 } 331 332 for (i = 0;i < max_retry_count;i++) { 333 build_udp_url(buf, sizeof(buf), 334 hostname, rtp_port, local_rtp_port, ttl, max_packet_size, 335 connect, include_sources, exclude_sources); 336 if (ffurl_open(&s->rtp_hd, buf, flags, &h->interrupt_callback, NULL) < 0) 337 goto fail; 338 local_rtp_port = ff_udp_get_local_port(s->rtp_hd); 339 if(local_rtp_port == 65535) { 340 local_rtp_port = -1; 341 continue; 342 } 343 if (local_rtcp_port<0) { 344 local_rtcp_port = local_rtp_port + 1; 345 build_udp_url(buf, sizeof(buf), 346 hostname, rtcp_port, local_rtcp_port, ttl, max_packet_size, 347 connect, include_sources, exclude_sources); 348 if (ffurl_open(&s->rtcp_hd, buf, flags, &h->interrupt_callback, NULL) < 0) { 349 local_rtp_port = local_rtcp_port = -1; 350 continue; 351 } 352 break; 353 } 354 build_udp_url(buf, sizeof(buf), 355 hostname, rtcp_port, local_rtcp_port, ttl, max_packet_size, 356 connect, include_sources, exclude_sources); 357 if (ffurl_open(&s->rtcp_hd, buf, flags, &h->interrupt_callback, NULL) < 0) 358 goto fail; 359 break; 360 } 361 362 /* just to ease handle access. XXX: need to suppress direct handle 363 access */ 364 s->rtp_fd = ffurl_get_file_handle(s->rtp_hd); 365 s->rtcp_fd = ffurl_get_file_handle(s->rtcp_hd); 366 367 h->max_packet_size = s->rtp_hd->max_packet_size; 368 h->is_streamed = 1; 369 return 0; 370 371 fail: 372 if (s->rtp_hd) 373 ffurl_close(s->rtp_hd); 374 if (s->rtcp_hd) 375 ffurl_close(s->rtcp_hd); 376 return AVERROR(EIO); 377} 378 379static int rtp_read(URLContext *h, uint8_t *buf, int size) 380{ 381 RTPContext *s = h->priv_data; 382 int len, n, i; 383 struct pollfd p[2] = {{s->rtp_fd, POLLIN, 0}, {s->rtcp_fd, POLLIN, 0}}; 384 int poll_delay = h->flags & AVIO_FLAG_NONBLOCK ? 0 : 100; 385 struct sockaddr_storage *addrs[2] = { &s->last_rtp_source, &s->last_rtcp_source }; 386 socklen_t *addr_lens[2] = { &s->last_rtp_source_len, &s->last_rtcp_source_len }; 387 388 for(;;) { 389 if (ff_check_interrupt(&h->interrupt_callback)) 390 return AVERROR_EXIT; 391 n = poll(p, 2, poll_delay); 392 if (n > 0) { 393 /* first try RTCP, then RTP */ 394 for (i = 1; i >= 0; i--) { 395 if (!(p[i].revents & POLLIN)) 396 continue; 397 *addr_lens[i] = sizeof(*addrs[i]); 398 len = recvfrom(p[i].fd, buf, size, 0, 399 (struct sockaddr *)addrs[i], addr_lens[i]); 400 if (len < 0) { 401 if (ff_neterrno() == AVERROR(EAGAIN) || 402 ff_neterrno() == AVERROR(EINTR)) 403 continue; 404 return AVERROR(EIO); 405 } 406 if (rtp_check_source_lists(s, addrs[i])) 407 continue; 408 return len; 409 } 410 } else if (n < 0) { 411 if (ff_neterrno() == AVERROR(EINTR)) 412 continue; 413 return AVERROR(EIO); 414 } 415 if (h->flags & AVIO_FLAG_NONBLOCK) 416 return AVERROR(EAGAIN); 417 } 418 return len; 419} 420 421static int rtp_write(URLContext *h, const uint8_t *buf, int size) 422{ 423 RTPContext *s = h->priv_data; 424 int ret; 425 URLContext *hd; 426 427 if (size < 2) 428 return AVERROR(EINVAL); 429 430 if (s->write_to_source) { 431 int fd; 432 struct sockaddr_storage *source, temp_source; 433 socklen_t *source_len, temp_len; 434 if (!s->last_rtp_source.ss_family && !s->last_rtcp_source.ss_family) { 435 av_log(h, AV_LOG_ERROR, 436 "Unable to send packet to source, no packets received yet\n"); 437 // Intentionally not returning an error here 438 return size; 439 } 440 441 if (RTP_PT_IS_RTCP(buf[1])) { 442 fd = s->rtcp_fd; 443 source = &s->last_rtcp_source; 444 source_len = &s->last_rtcp_source_len; 445 } else { 446 fd = s->rtp_fd; 447 source = &s->last_rtp_source; 448 source_len = &s->last_rtp_source_len; 449 } 450 if (!source->ss_family) { 451 source = &temp_source; 452 source_len = &temp_len; 453 if (RTP_PT_IS_RTCP(buf[1])) { 454 temp_source = s->last_rtp_source; 455 temp_len = s->last_rtp_source_len; 456 set_port(source, get_port(source) + 1); 457 av_log(h, AV_LOG_INFO, 458 "Not received any RTCP packets yet, inferring peer port " 459 "from the RTP port\n"); 460 } else { 461 temp_source = s->last_rtcp_source; 462 temp_len = s->last_rtcp_source_len; 463 set_port(source, get_port(source) - 1); 464 av_log(h, AV_LOG_INFO, 465 "Not received any RTP packets yet, inferring peer port " 466 "from the RTCP port\n"); 467 } 468 } 469 470 if (!(h->flags & AVIO_FLAG_NONBLOCK)) { 471 ret = ff_network_wait_fd(fd, 1); 472 if (ret < 0) 473 return ret; 474 } 475 ret = sendto(fd, buf, size, 0, (struct sockaddr *) source, 476 *source_len); 477 478 return ret < 0 ? ff_neterrno() : ret; 479 } 480 481 if (RTP_PT_IS_RTCP(buf[1])) { 482 /* RTCP payload type */ 483 hd = s->rtcp_hd; 484 } else { 485 /* RTP payload type */ 486 hd = s->rtp_hd; 487 } 488 489 ret = ffurl_write(hd, buf, size); 490 return ret; 491} 492 493static int rtp_close(URLContext *h) 494{ 495 RTPContext *s = h->priv_data; 496 int i; 497 498 for (i = 0; i < s->nb_ssm_include_addrs; i++) 499 av_free(s->ssm_include_addrs[i]); 500 av_freep(&s->ssm_include_addrs); 501 for (i = 0; i < s->nb_ssm_exclude_addrs; i++) 502 av_free(s->ssm_exclude_addrs[i]); 503 av_freep(&s->ssm_exclude_addrs); 504 505 ffurl_close(s->rtp_hd); 506 ffurl_close(s->rtcp_hd); 507 return 0; 508} 509 510/** 511 * Return the local rtp port used by the RTP connection 512 * @param h media file context 513 * @return the local port number 514 */ 515 516int ff_rtp_get_local_rtp_port(URLContext *h) 517{ 518 RTPContext *s = h->priv_data; 519 return ff_udp_get_local_port(s->rtp_hd); 520} 521 522/** 523 * Return the local rtcp port used by the RTP connection 524 * @param h media file context 525 * @return the local port number 526 */ 527 528int ff_rtp_get_local_rtcp_port(URLContext *h) 529{ 530 RTPContext *s = h->priv_data; 531 return ff_udp_get_local_port(s->rtcp_hd); 532} 533 534static int rtp_get_file_handle(URLContext *h) 535{ 536 RTPContext *s = h->priv_data; 537 return s->rtp_fd; 538} 539 540static int rtp_get_multi_file_handle(URLContext *h, int **handles, 541 int *numhandles) 542{ 543 RTPContext *s = h->priv_data; 544 int *hs = *handles = av_malloc(sizeof(**handles) * 2); 545 if (!hs) 546 return AVERROR(ENOMEM); 547 hs[0] = s->rtp_fd; 548 hs[1] = s->rtcp_fd; 549 *numhandles = 2; 550 return 0; 551} 552 553URLProtocol ff_rtp_protocol = { 554 .name = "rtp", 555 .url_open = rtp_open, 556 .url_read = rtp_read, 557 .url_write = rtp_write, 558 .url_close = rtp_close, 559 .url_get_file_handle = rtp_get_file_handle, 560 .url_get_multi_file_handle = rtp_get_multi_file_handle, 561 .priv_data_size = sizeof(RTPContext), 562 .flags = URL_PROTOCOL_FLAG_NETWORK, 563}; 564