You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

505 lines
14KB

  1. /*
  2. * UDP prototype streaming system
  3. * Copyright (c) 2000, 2001, 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. #include "avformat.h"
  22. #include <unistd.h>
  23. #include <sys/types.h>
  24. #include <sys/socket.h>
  25. #include <netinet/in.h>
  26. #ifndef __BEOS__
  27. # include <arpa/inet.h>
  28. #else
  29. # include "barpainet.h"
  30. #endif
  31. #include <netdb.h>
  32. #ifndef IPV6_ADD_MEMBERSHIP
  33. #define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
  34. #define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP
  35. #endif
  36. typedef struct {
  37. int udp_fd;
  38. int ttl;
  39. int is_multicast;
  40. int local_port;
  41. #ifndef CONFIG_IPV6
  42. struct ip_mreq mreq;
  43. struct sockaddr_in dest_addr;
  44. #else
  45. struct sockaddr_storage dest_addr;
  46. size_t dest_addr_len;
  47. #endif
  48. } UDPContext;
  49. #define UDP_TX_BUF_SIZE 32768
  50. #ifdef CONFIG_IPV6
  51. static int udp_ipv6_is_multicast_address(const struct sockaddr *addr) {
  52. if (addr->sa_family == AF_INET)
  53. return IN_MULTICAST(ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr));
  54. if (addr->sa_family == AF_INET6)
  55. return IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)addr)->sin6_addr);
  56. return -1;
  57. }
  58. static int udp_ipv6_set_multicast_ttl(int sockfd, int mcastTTL, struct sockaddr *addr) {
  59. if (addr->sa_family == AF_INET) {
  60. if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &mcastTTL, sizeof(mcastTTL)) < 0) {
  61. perror("setsockopt(IP_MULTICAST_TTL)");
  62. return -1;
  63. }
  64. }
  65. if (addr->sa_family == AF_INET6) {
  66. if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &mcastTTL, sizeof(mcastTTL)) < 0) {
  67. perror("setsockopt(IPV6_MULTICAST_HOPS)");
  68. return -1;
  69. }
  70. }
  71. return 0;
  72. }
  73. static int udp_ipv6_join_multicast_group(int sockfd, struct sockaddr *addr) {
  74. struct ip_mreq mreq;
  75. struct ipv6_mreq mreq6;
  76. if (addr->sa_family == AF_INET) {
  77. mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
  78. mreq.imr_interface.s_addr= INADDR_ANY;
  79. if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const void *)&mreq, sizeof(mreq)) < 0) {
  80. perror("setsockopt(IP_ADD_MEMBERSHIP)");
  81. return -1;
  82. }
  83. }
  84. if (addr->sa_family == AF_INET6) {
  85. memcpy(&mreq6.ipv6mr_multiaddr, &(((struct sockaddr_in6 *)addr)->sin6_addr), sizeof(struct in6_addr));
  86. mreq6.ipv6mr_interface= 0;
  87. if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq6, sizeof(mreq6)) < 0) {
  88. perror("setsockopt(IPV6_ADD_MEMBERSHIP)");
  89. return -1;
  90. }
  91. }
  92. return 0;
  93. }
  94. static int udp_ipv6_leave_multicast_group(int sockfd, struct sockaddr *addr) {
  95. struct ip_mreq mreq;
  96. struct ipv6_mreq mreq6;
  97. if (addr->sa_family == AF_INET) {
  98. mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
  99. mreq.imr_interface.s_addr= INADDR_ANY;
  100. if (setsockopt(sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP, (const void *)&mreq, sizeof(mreq)) < 0) {
  101. perror("setsockopt(IP_DROP_MEMBERSHIP)");
  102. return -1;
  103. }
  104. }
  105. if (addr->sa_family == AF_INET6) {
  106. memcpy(&mreq6.ipv6mr_multiaddr, &(((struct sockaddr_in6 *)addr)->sin6_addr), sizeof(struct in6_addr));
  107. mreq6.ipv6mr_interface= 0;
  108. if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mreq6, sizeof(mreq6)) < 0) {
  109. perror("setsockopt(IPV6_DROP_MEMBERSHIP)");
  110. return -1;
  111. }
  112. }
  113. return 0;
  114. }
  115. static struct addrinfo* udp_ipv6_resolve_host(const char *hostname, int port, int type, int family, int flags) {
  116. struct addrinfo hints, *res = 0;
  117. int error;
  118. char sport[16];
  119. const char *node = 0, *service = 0;
  120. if (port > 0) {
  121. snprintf(sport, sizeof(sport), "%d", port);
  122. service = sport;
  123. }
  124. if ((hostname) && (hostname[0] != '\0') && (hostname[0] != '?')) {
  125. node = hostname;
  126. }
  127. if ((node) || (service)) {
  128. memset(&hints, 0, sizeof(hints));
  129. hints.ai_socktype = type;
  130. hints.ai_family = family;
  131. hints.ai_flags = flags;
  132. if ((error = getaddrinfo(node, service, &hints, &res))) {
  133. av_log(NULL, AV_LOG_ERROR, "udp_ipv6_resolve_host: %s\n", gai_strerror(error));
  134. }
  135. }
  136. return res;
  137. }
  138. static int udp_ipv6_set_remote_url(URLContext *h, const char *uri) {
  139. UDPContext *s = h->priv_data;
  140. char hostname[256];
  141. int port;
  142. struct addrinfo *res0;
  143. url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri);
  144. res0 = udp_ipv6_resolve_host(hostname, port, SOCK_DGRAM, AF_UNSPEC, 0);
  145. if (res0 == 0) return AVERROR_IO;
  146. memcpy(&s->dest_addr, res0->ai_addr, res0->ai_addrlen);
  147. s->dest_addr_len = res0->ai_addrlen;
  148. freeaddrinfo(res0);
  149. return 0;
  150. }
  151. static int udp_ipv6_set_local(URLContext *h) {
  152. UDPContext *s = h->priv_data;
  153. int udp_fd = -1;
  154. struct sockaddr_storage clientaddr;
  155. socklen_t addrlen;
  156. char sbuf[NI_MAXSERV];
  157. char hbuf[NI_MAXHOST];
  158. struct addrinfo *res0 = NULL, *res = NULL;
  159. if (s->local_port != 0) {
  160. res0 = udp_ipv6_resolve_host(0, s->local_port, SOCK_DGRAM, AF_UNSPEC, AI_PASSIVE);
  161. if (res0 == 0)
  162. goto fail;
  163. for (res = res0; res; res=res->ai_next) {
  164. udp_fd = socket(res->ai_family, SOCK_DGRAM, 0);
  165. if (udp_fd > 0) break;
  166. perror("socket");
  167. }
  168. } else {
  169. udp_fd = socket(s->dest_addr.ss_family, SOCK_DGRAM, 0);
  170. if (udp_fd < 0)
  171. perror("socket");
  172. }
  173. if (udp_fd < 0)
  174. goto fail;
  175. if (s->local_port != 0) {
  176. if (bind(udp_fd, res0->ai_addr, res0->ai_addrlen) < 0) {
  177. perror("bind");
  178. goto fail;
  179. }
  180. freeaddrinfo(res0);
  181. res0 = NULL;
  182. }
  183. addrlen = sizeof(clientaddr);
  184. if (getsockname(udp_fd, (struct sockaddr *)&clientaddr, &addrlen) < 0) {
  185. perror("getsockname");
  186. goto fail;
  187. }
  188. if (getnameinfo((struct sockaddr *)&clientaddr, addrlen, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
  189. perror("getnameinfo");
  190. goto fail;
  191. }
  192. s->local_port = strtol(sbuf, NULL, 10);
  193. return udp_fd;
  194. fail:
  195. if (udp_fd >= 0)
  196. #ifdef CONFIG_BEOS_NETSERVER
  197. closesocket(udp_fd);
  198. #else
  199. close(udp_fd);
  200. #endif
  201. if(res0)
  202. freeaddrinfo(res0);
  203. return -1;
  204. }
  205. #endif
  206. /**
  207. * If no filename is given to av_open_input_file because you want to
  208. * get the local port first, then you must call this function to set
  209. * the remote server address.
  210. *
  211. * url syntax: udp://host:port[?option=val...]
  212. * option: 'multicast=1' : enable multicast
  213. * 'ttl=n' : set the ttl value (for multicast only)
  214. * 'localport=n' : set the local port
  215. * 'pkt_size=n' : set max packet size
  216. *
  217. * @param s1 media file context
  218. * @param uri of the remote server
  219. * @return zero if no error.
  220. */
  221. int udp_set_remote_url(URLContext *h, const char *uri)
  222. {
  223. #ifdef CONFIG_IPV6
  224. return udp_ipv6_set_remote_url(h, uri);
  225. #else
  226. UDPContext *s = h->priv_data;
  227. char hostname[256];
  228. int port;
  229. url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri);
  230. /* set the destination address */
  231. if (resolve_host(&s->dest_addr.sin_addr, hostname) < 0)
  232. return AVERROR_IO;
  233. s->dest_addr.sin_family = AF_INET;
  234. s->dest_addr.sin_port = htons(port);
  235. return 0;
  236. #endif
  237. }
  238. /**
  239. * Return the local port used by the UDP connexion
  240. * @param s1 media file context
  241. * @return the local port number
  242. */
  243. int udp_get_local_port(URLContext *h)
  244. {
  245. UDPContext *s = h->priv_data;
  246. return s->local_port;
  247. }
  248. /**
  249. * Return the udp file handle for select() usage to wait for several RTP
  250. * streams at the same time.
  251. * @param h media file context
  252. */
  253. int udp_get_file_handle(URLContext *h)
  254. {
  255. UDPContext *s = h->priv_data;
  256. return s->udp_fd;
  257. }
  258. /* put it in UDP context */
  259. /* return non zero if error */
  260. static int udp_open(URLContext *h, const char *uri, int flags)
  261. {
  262. char hostname[1024];
  263. int port, udp_fd = -1, tmp;
  264. UDPContext *s = NULL;
  265. int is_output;
  266. const char *p;
  267. char buf[256];
  268. #ifndef CONFIG_IPV6
  269. struct sockaddr_in my_addr, my_addr1;
  270. int len;
  271. #endif
  272. h->is_streamed = 1;
  273. h->max_packet_size = 1472;
  274. is_output = (flags & URL_WRONLY);
  275. s = av_malloc(sizeof(UDPContext));
  276. if (!s)
  277. return -ENOMEM;
  278. h->priv_data = s;
  279. s->ttl = 16;
  280. s->is_multicast = 0;
  281. s->local_port = 0;
  282. p = strchr(uri, '?');
  283. if (p) {
  284. s->is_multicast = find_info_tag(buf, sizeof(buf), "multicast", p);
  285. if (find_info_tag(buf, sizeof(buf), "ttl", p)) {
  286. s->ttl = strtol(buf, NULL, 10);
  287. }
  288. if (find_info_tag(buf, sizeof(buf), "localport", p)) {
  289. s->local_port = strtol(buf, NULL, 10);
  290. }
  291. if (find_info_tag(buf, sizeof(buf), "pkt_size", p)) {
  292. h->max_packet_size = strtol(buf, NULL, 10);
  293. }
  294. }
  295. /* fill the dest addr */
  296. url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri);
  297. /* XXX: fix url_split */
  298. if (hostname[0] == '\0' || hostname[0] == '?') {
  299. /* only accepts null hostname if input */
  300. if (s->is_multicast || (flags & URL_WRONLY))
  301. goto fail;
  302. } else {
  303. udp_set_remote_url(h, uri);
  304. }
  305. #ifndef CONFIG_IPV6
  306. udp_fd = socket(PF_INET, SOCK_DGRAM, 0);
  307. if (udp_fd < 0)
  308. goto fail;
  309. my_addr.sin_family = AF_INET;
  310. my_addr.sin_addr.s_addr = htonl (INADDR_ANY);
  311. if (s->is_multicast && !(h->flags & URL_WRONLY)) {
  312. /* special case: the bind must be done on the multicast address port */
  313. my_addr.sin_port = s->dest_addr.sin_port;
  314. } else {
  315. my_addr.sin_port = htons(s->local_port);
  316. }
  317. /* the bind is needed to give a port to the socket now */
  318. if (bind(udp_fd,(struct sockaddr *)&my_addr, sizeof(my_addr)) < 0)
  319. goto fail;
  320. len = sizeof(my_addr1);
  321. getsockname(udp_fd, (struct sockaddr *)&my_addr1, &len);
  322. s->local_port = ntohs(my_addr1.sin_port);
  323. #ifndef CONFIG_BEOS_NETSERVER
  324. if (s->is_multicast) {
  325. if (h->flags & URL_WRONLY) {
  326. /* output */
  327. if (setsockopt(udp_fd, IPPROTO_IP, IP_MULTICAST_TTL,
  328. &s->ttl, sizeof(s->ttl)) < 0) {
  329. perror("IP_MULTICAST_TTL");
  330. goto fail;
  331. }
  332. } else {
  333. /* input */
  334. memset(&s->mreq, 0, sizeof(s->mreq));
  335. s->mreq.imr_multiaddr = s->dest_addr.sin_addr;
  336. s->mreq.imr_interface.s_addr = htonl (INADDR_ANY);
  337. if (setsockopt(udp_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
  338. &s->mreq, sizeof(s->mreq)) < 0) {
  339. perror("rtp: IP_ADD_MEMBERSHIP");
  340. goto fail;
  341. }
  342. }
  343. }
  344. #endif
  345. #else
  346. if (s->is_multicast && !(h->flags & URL_WRONLY))
  347. s->local_port = port;
  348. udp_fd = udp_ipv6_set_local(h);
  349. if (udp_fd < 0)
  350. goto fail;
  351. #ifndef CONFIG_BEOS_NETSERVER
  352. if (s->is_multicast) {
  353. if (h->flags & URL_WRONLY) {
  354. if (udp_ipv6_set_multicast_ttl(udp_fd, s->ttl, (struct sockaddr *)&s->dest_addr) < 0)
  355. goto fail;
  356. } else {
  357. if (udp_ipv6_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr) < 0)
  358. goto fail;
  359. }
  360. }
  361. #endif
  362. #endif
  363. if (is_output) {
  364. /* limit the tx buf size to limit latency */
  365. tmp = UDP_TX_BUF_SIZE;
  366. if (setsockopt(udp_fd, SOL_SOCKET, SO_SNDBUF, &tmp, sizeof(tmp)) < 0) {
  367. perror("setsockopt sndbuf");
  368. goto fail;
  369. }
  370. }
  371. s->udp_fd = udp_fd;
  372. return 0;
  373. fail:
  374. if (udp_fd >= 0)
  375. #ifdef CONFIG_BEOS_NETSERVER
  376. closesocket(udp_fd);
  377. #else
  378. close(udp_fd);
  379. #endif
  380. av_free(s);
  381. return AVERROR_IO;
  382. }
  383. static int udp_read(URLContext *h, uint8_t *buf, int size)
  384. {
  385. UDPContext *s = h->priv_data;
  386. #ifndef CONFIG_IPV6
  387. struct sockaddr_in from;
  388. #else
  389. struct sockaddr_storage from;
  390. #endif
  391. socklen_t from_len;
  392. int len;
  393. for(;;) {
  394. from_len = sizeof(from);
  395. len = recvfrom (s->udp_fd, buf, size, 0,
  396. (struct sockaddr *)&from, &from_len);
  397. if (len < 0) {
  398. if (errno != EAGAIN && errno != EINTR)
  399. return AVERROR_IO;
  400. } else {
  401. break;
  402. }
  403. }
  404. return len;
  405. }
  406. static int udp_write(URLContext *h, uint8_t *buf, int size)
  407. {
  408. UDPContext *s = h->priv_data;
  409. int ret;
  410. for(;;) {
  411. ret = sendto (s->udp_fd, buf, size, 0,
  412. (struct sockaddr *) &s->dest_addr,
  413. #ifndef CONFIG_IPV6
  414. sizeof (s->dest_addr));
  415. #else
  416. s->dest_addr_len);
  417. #endif
  418. if (ret < 0) {
  419. if (errno != EINTR && errno != EAGAIN)
  420. return AVERROR_IO;
  421. } else {
  422. break;
  423. }
  424. }
  425. return size;
  426. }
  427. static int udp_close(URLContext *h)
  428. {
  429. UDPContext *s = h->priv_data;
  430. #ifndef CONFIG_BEOS_NETSERVER
  431. #ifndef CONFIG_IPV6
  432. if (s->is_multicast && !(h->flags & URL_WRONLY)) {
  433. if (setsockopt(s->udp_fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
  434. &s->mreq, sizeof(s->mreq)) < 0) {
  435. perror("IP_DROP_MEMBERSHIP");
  436. }
  437. }
  438. #else
  439. if (s->is_multicast && !(h->flags & URL_WRONLY))
  440. udp_ipv6_leave_multicast_group(s->udp_fd, (struct sockaddr *)&s->dest_addr);
  441. #endif
  442. close(s->udp_fd);
  443. #else
  444. closesocket(s->udp_fd);
  445. #endif
  446. av_free(s);
  447. return 0;
  448. }
  449. URLProtocol udp_protocol = {
  450. "udp",
  451. udp_open,
  452. udp_read,
  453. udp_write,
  454. NULL, /* seek */
  455. udp_close,
  456. };