comparison udp.c @ 2739:091af9f47edf libavformat

Avoid to duplicate the multicast code between the IPv4-only and protocol-independent versions
author lucabe
date Wed, 14 Nov 2007 07:42:46 +0000
parents 1f5c5c223764
children e23eaab1a894
comparison
equal deleted inserted replaced
2738:1f5c5c223764 2739:091af9f47edf
43 } UDPContext; 43 } UDPContext;
44 44
45 #define UDP_TX_BUF_SIZE 32768 45 #define UDP_TX_BUF_SIZE 32768
46 #define UDP_MAX_PKT_SIZE 65536 46 #define UDP_MAX_PKT_SIZE 65536
47 47
48 #ifdef CONFIG_IPV6
49
50 static int udp_ipv6_set_multicast_ttl(int sockfd, int mcastTTL, struct sockaddr *addr) { 48 static int udp_ipv6_set_multicast_ttl(int sockfd, int mcastTTL, struct sockaddr *addr) {
49 #ifdef IP_MULTICAST_TTL
51 if (addr->sa_family == AF_INET) { 50 if (addr->sa_family == AF_INET) {
52 if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &mcastTTL, sizeof(mcastTTL)) < 0) { 51 if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &mcastTTL, sizeof(mcastTTL)) < 0) {
53 perror("setsockopt(IP_MULTICAST_TTL)"); 52 perror("setsockopt(IP_MULTICAST_TTL)");
54 return -1; 53 return -1;
55 } 54 }
56 } 55 }
56 #endif
57 #ifdef CONFIG_IPV6
57 if (addr->sa_family == AF_INET6) { 58 if (addr->sa_family == AF_INET6) {
58 if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &mcastTTL, sizeof(mcastTTL)) < 0) { 59 if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &mcastTTL, sizeof(mcastTTL)) < 0) {
59 perror("setsockopt(IPV6_MULTICAST_HOPS)"); 60 perror("setsockopt(IPV6_MULTICAST_HOPS)");
60 return -1; 61 return -1;
61 } 62 }
62 } 63 }
64 #endif
63 return 0; 65 return 0;
64 } 66 }
65 67
66 static int udp_ipv6_join_multicast_group(int sockfd, struct sockaddr *addr) { 68 static int udp_ipv6_join_multicast_group(int sockfd, struct sockaddr *addr) {
67 struct ip_mreq mreq; 69 #ifdef IP_ADD_MEMBERSHIP
68 struct ipv6_mreq mreq6;
69 if (addr->sa_family == AF_INET) { 70 if (addr->sa_family == AF_INET) {
71 struct ip_mreq mreq;
72
70 mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr; 73 mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
71 mreq.imr_interface.s_addr= INADDR_ANY; 74 mreq.imr_interface.s_addr= INADDR_ANY;
72 if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const void *)&mreq, sizeof(mreq)) < 0) { 75 if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const void *)&mreq, sizeof(mreq)) < 0) {
73 perror("setsockopt(IP_ADD_MEMBERSHIP)"); 76 perror("setsockopt(IP_ADD_MEMBERSHIP)");
74 return -1; 77 return -1;
75 } 78 }
76 } 79 }
80 #endif
81 #ifdef CONFIG_IPV6
77 if (addr->sa_family == AF_INET6) { 82 if (addr->sa_family == AF_INET6) {
83 struct ipv6_mreq mreq6;
84
78 memcpy(&mreq6.ipv6mr_multiaddr, &(((struct sockaddr_in6 *)addr)->sin6_addr), sizeof(struct in6_addr)); 85 memcpy(&mreq6.ipv6mr_multiaddr, &(((struct sockaddr_in6 *)addr)->sin6_addr), sizeof(struct in6_addr));
79 mreq6.ipv6mr_interface= 0; 86 mreq6.ipv6mr_interface= 0;
80 if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq6, sizeof(mreq6)) < 0) { 87 if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq6, sizeof(mreq6)) < 0) {
81 perror("setsockopt(IPV6_ADD_MEMBERSHIP)"); 88 perror("setsockopt(IPV6_ADD_MEMBERSHIP)");
82 return -1; 89 return -1;
83 } 90 }
84 } 91 }
92 #endif
85 return 0; 93 return 0;
86 } 94 }
87 95
88 static int udp_ipv6_leave_multicast_group(int sockfd, struct sockaddr *addr) { 96 static int udp_ipv6_leave_multicast_group(int sockfd, struct sockaddr *addr) {
89 struct ip_mreq mreq; 97 #ifdef IP_DROP_MEMBERSHIP
90 struct ipv6_mreq mreq6;
91 if (addr->sa_family == AF_INET) { 98 if (addr->sa_family == AF_INET) {
99 struct ip_mreq mreq;
100
92 mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr; 101 mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
93 mreq.imr_interface.s_addr= INADDR_ANY; 102 mreq.imr_interface.s_addr= INADDR_ANY;
94 if (setsockopt(sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP, (const void *)&mreq, sizeof(mreq)) < 0) { 103 if (setsockopt(sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP, (const void *)&mreq, sizeof(mreq)) < 0) {
95 perror("setsockopt(IP_DROP_MEMBERSHIP)"); 104 perror("setsockopt(IP_DROP_MEMBERSHIP)");
96 return -1; 105 return -1;
97 } 106 }
98 } 107 }
108 #endif
109 #ifdef CONFIG_IPV6
99 if (addr->sa_family == AF_INET6) { 110 if (addr->sa_family == AF_INET6) {
111 struct ipv6_mreq mreq6;
112
100 memcpy(&mreq6.ipv6mr_multiaddr, &(((struct sockaddr_in6 *)addr)->sin6_addr), sizeof(struct in6_addr)); 113 memcpy(&mreq6.ipv6mr_multiaddr, &(((struct sockaddr_in6 *)addr)->sin6_addr), sizeof(struct in6_addr));
101 mreq6.ipv6mr_interface= 0; 114 mreq6.ipv6mr_interface= 0;
102 if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mreq6, sizeof(mreq6)) < 0) { 115 if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, &mreq6, sizeof(mreq6)) < 0) {
103 perror("setsockopt(IPV6_DROP_MEMBERSHIP)"); 116 perror("setsockopt(IPV6_DROP_MEMBERSHIP)");
104 return -1; 117 return -1;
105 } 118 }
106 } 119 }
107 return 0; 120 #endif
108 } 121 return 0;
109 122 }
123
124 #ifdef CONFIG_IPV6
110 static struct addrinfo* udp_ipv6_resolve_host(const char *hostname, int port, int type, int family, int flags) { 125 static struct addrinfo* udp_ipv6_resolve_host(const char *hostname, int port, int type, int family, int flags) {
111 struct addrinfo hints, *res = 0; 126 struct addrinfo hints, *res = 0;
112 int error; 127 int error;
113 char sport[16]; 128 char sport[16];
114 const char *node = 0, *service = "0"; 129 const char *node = 0, *service = "0";
343 goto fail; 358 goto fail;
344 359
345 len = sizeof(my_addr1); 360 len = sizeof(my_addr1);
346 getsockname(udp_fd, (struct sockaddr *)&my_addr1, &len); 361 getsockname(udp_fd, (struct sockaddr *)&my_addr1, &len);
347 s->local_port = ntohs(my_addr1.sin_port); 362 s->local_port = ntohs(my_addr1.sin_port);
348
349 #ifdef IP_MULTICAST_TTL
350 if (s->is_multicast) {
351 if (h->flags & URL_WRONLY) {
352 /* output */
353 if (setsockopt(udp_fd, IPPROTO_IP, IP_MULTICAST_TTL,
354 &s->ttl, sizeof(s->ttl)) < 0) {
355 perror("IP_MULTICAST_TTL");
356 goto fail;
357 }
358 } else {
359 /* input */
360 memset(&s->mreq, 0, sizeof(s->mreq));
361 s->mreq.imr_multiaddr = s->dest_addr.sin_addr;
362 s->mreq.imr_interface.s_addr = htonl (INADDR_ANY);
363 if (setsockopt(udp_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
364 &s->mreq, sizeof(s->mreq)) < 0) {
365 perror("rtp: IP_ADD_MEMBERSHIP");
366 goto fail;
367 }
368 }
369 }
370 #endif
371 #else 363 #else
372 if (s->is_multicast && !(h->flags & URL_WRONLY)) 364 if (s->is_multicast && !(h->flags & URL_WRONLY))
373 s->local_port = port; 365 s->local_port = port;
374 udp_fd = udp_ipv6_set_local(h); 366 udp_fd = udp_ipv6_set_local(h);
375 if (udp_fd < 0) 367 if (udp_fd < 0)
376 goto fail; 368 goto fail;
369 #endif /* CONFIG_IPV6 */
377 if (s->is_multicast) { 370 if (s->is_multicast) {
378 if (h->flags & URL_WRONLY) { 371 if (h->flags & URL_WRONLY) {
372 /* output */
379 if (udp_ipv6_set_multicast_ttl(udp_fd, s->ttl, (struct sockaddr *)&s->dest_addr) < 0) 373 if (udp_ipv6_set_multicast_ttl(udp_fd, s->ttl, (struct sockaddr *)&s->dest_addr) < 0)
380 goto fail; 374 goto fail;
381 } else { 375 } else {
376 /* input */
382 if (udp_ipv6_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr) < 0) 377 if (udp_ipv6_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr) < 0)
383 goto fail; 378 goto fail;
384 } 379 }
385 } 380 }
386 #endif /* CONFIG_IPV6 */
387 381
388 if (is_output) { 382 if (is_output) {
389 /* limit the tx buf size to limit latency */ 383 /* limit the tx buf size to limit latency */
390 tmp = UDP_TX_BUF_SIZE; 384 tmp = UDP_TX_BUF_SIZE;
391 if (setsockopt(udp_fd, SOL_SOCKET, SO_SNDBUF, &tmp, sizeof(tmp)) < 0) { 385 if (setsockopt(udp_fd, SOL_SOCKET, SO_SNDBUF, &tmp, sizeof(tmp)) < 0) {
456 450
457 static int udp_close(URLContext *h) 451 static int udp_close(URLContext *h)
458 { 452 {
459 UDPContext *s = h->priv_data; 453 UDPContext *s = h->priv_data;
460 454
461 #ifndef CONFIG_IPV6
462 #ifdef IP_DROP_MEMBERSHIP
463 if (s->is_multicast && !(h->flags & URL_WRONLY)) {
464 if (setsockopt(s->udp_fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
465 &s->mreq, sizeof(s->mreq)) < 0) {
466 perror("IP_DROP_MEMBERSHIP");
467 }
468 }
469 #endif
470 #else
471 if (s->is_multicast && !(h->flags & URL_WRONLY)) 455 if (s->is_multicast && !(h->flags & URL_WRONLY))
472 udp_ipv6_leave_multicast_group(s->udp_fd, (struct sockaddr *)&s->dest_addr); 456 udp_ipv6_leave_multicast_group(s->udp_fd, (struct sockaddr *)&s->dest_addr);
473 #endif
474 closesocket(s->udp_fd); 457 closesocket(s->udp_fd);
475 ff_network_close(); 458 ff_network_close();
476 av_free(s); 459 av_free(s);
477 return 0; 460 return 0;
478 } 461 }