PageRenderTime 59ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/AMVmuxer/ffmpeg/libavformat/udp.c

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