comparison stream/udp.c @ 19318:a3ddd3320b47

removed udp socket creation code from rtp stack to a new dedicated udp helper file
author ben
date Fri, 04 Aug 2006 19:31:53 +0000
parents
children 6f58dd7a5520
comparison
equal deleted inserted replaced
19317:e0b496cf9863 19318:a3ddd3320b47
1 /*
2 * Copyright (C) 2006 Benjamin Zores
3 * Network helpers for UDP connections (originally borrowed from rtp.c).
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 #include "config.h"
21
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <unistd.h>
26 #include <stdlib.h>
27 #include <sys/types.h>
28 #include <ctype.h>
29 #include <netdb.h>
30
31 #ifndef HAVE_WINSOCK2
32 #include <netinet/in.h>
33 #include <sys/socket.h>
34 #include <arpa/inet.h>
35 #define closesocket close
36 #else
37 #include <winsock2.h>
38 #include <ws2tcpip.h>
39 #endif
40
41 #include "mp_msg.h"
42 #include "url.h"
43 #include "udp.h"
44
45 /* Start listening on a UDP port. If multicast, join the group. */
46 int
47 udp_open_socket (URL_t *url)
48 {
49 int socket_server_fd, rxsockbufsz;
50 int err, err_len;
51 fd_set set;
52 struct sockaddr_in server_address;
53 struct ip_mreq mcast;
54 struct timeval tv;
55 struct hostent *hp;
56
57 mp_msg (MSGT_NETWORK, MSGL_V,
58 "Listening for traffic on %s:%d ...\n", url->hostname, url->port);
59
60 socket_server_fd = socket (AF_INET, SOCK_DGRAM, 0);
61 if (socket_server_fd == -1)
62 {
63 mp_msg (MSGT_NETWORK, MSGL_ERR, "Failed to create socket\n");
64 return -1;
65 }
66
67 if (isalpha (url->hostname[0]))
68 {
69 #ifndef HAVE_WINSOCK2
70 hp = (struct hostent *) gethostbyname (url->hostname);
71 if (!hp)
72 {
73 mp_msg (MSGT_NETWORK, MSGL_ERR,
74 "Counldn't resolve name: %s\n", url->hostname);
75 closesocket (socket_server_fd);
76 return -1;
77 }
78 memcpy ((void *) &server_address.sin_addr.s_addr,
79 (void *) hp->h_addr_list[0], hp->h_length);
80 #else
81 server_address.sin_addr.s_addr = htonl (INADDR_ANY);
82 #endif /* HAVE_WINSOCK2 */
83 }
84 else
85 {
86 #ifndef HAVE_WINSOCK2
87 #ifdef USE_ATON
88 inet_aton (url->hostname, &server_address.sin_addr);
89 #else
90 inet_pton (AF_INET, url->hostname, &server_address.sin_addr);
91 #endif /* USE_ATON */
92 #else
93 server_address.sin_addr.s_addr = htonl(INADDR_ANY);
94 #endif /* HAVE_WINSOCK2 */
95 }
96 server_address.sin_family = AF_INET;
97 server_address.sin_port = htons (url->port);
98
99 if (bind (socket_server_fd, (struct sockaddr *) &server_address,
100 sizeof (server_address)) == -1)
101 {
102 #ifndef HAVE_WINSOCK2
103 if (errno != EINPROGRESS)
104 #else
105 if (WSAGetLastError () != WSAEINPROGRESS)
106 #endif /* HAVE_WINSOCK2 */
107 {
108 mp_msg (MSGT_NETWORK, MSGL_ERR, "Failed to connect to server\n");
109 closesocket (socket_server_fd);
110 return -1;
111 }
112 }
113
114 #ifdef HAVE_WINSOCK2
115 if (isalpha (url->hostname[0]))
116 {
117 hp = (struct hostent *) gethostbyname (url->hostname);
118 if (!hp)
119 {
120 mp_msg (MSGT_NETWORK, MSGL_ERR,
121 "Counldn't resolve name: %s\n", url->hostname);
122 closesocket (socket_server_fd);
123 return -1;
124 }
125 memcpy ((void *) &server_address.sin_addr.s_addr,
126 (void *) hp->h_addr, hp->h_length);
127 }
128 else
129 {
130 unsigned int addr = inet_addr (url->hostname);
131 memcpy ((void *) &server_address.sin_addr, (void *) &addr, sizeof (addr));
132 }
133 #endif /* HAVE_WINSOCK2 */
134
135 /* Increase the socket rx buffer size to maximum -- this is UDP */
136 rxsockbufsz = 240 * 1024;
137 if (setsockopt (socket_server_fd, SOL_SOCKET, SO_RCVBUF,
138 &rxsockbufsz, sizeof (rxsockbufsz)))
139 {
140 mp_msg (MSGT_NETWORK, MSGL_ERR,
141 "Couldn't set receive socket buffer size\n");
142 }
143
144 if ((ntohl (server_address.sin_addr.s_addr) >> 28) == 0xe)
145 {
146 mcast.imr_multiaddr.s_addr = server_address.sin_addr.s_addr;
147 mcast.imr_interface.s_addr = 0;
148
149 if (setsockopt (socket_server_fd, IPPROTO_IP,
150 IP_ADD_MEMBERSHIP, &mcast, sizeof (mcast)))
151 {
152 mp_msg (MSGT_NETWORK, MSGL_ERR, "IP_ADD_MEMBERSHIP failed (do you have multicasting enabled in your kernel?)\n");
153 closesocket (socket_server_fd);
154 return -1;
155 }
156 }
157
158 tv.tv_sec = 0;
159 tv.tv_usec = (1 * 1000000); /* 1 second timeout */
160
161 FD_ZERO (&set);
162 FD_SET (socket_server_fd, &set);
163
164 err = select (socket_server_fd + 1, &set, NULL, NULL, &tv);
165 if (err < 0)
166 {
167 mp_msg (MSGT_NETWORK, MSGL_FATAL,
168 "Select failed: %s\n", strerror (errno));
169 closesocket (socket_server_fd);
170 return -1;
171 }
172
173 if (err == 0)
174 {
175 mp_msg (MSGT_NETWORK, MSGL_ERR,
176 "Timeout! No data from host %s\n", url->hostname);
177 closesocket (socket_server_fd);
178 return -1;
179 }
180
181 err_len = sizeof (err);
182 getsockopt (socket_server_fd, SOL_SOCKET, SO_ERROR, &err, &err_len);
183 if (err)
184 {
185 mp_msg (MSGT_NETWORK, MSGL_DBG2, "Socket error: %d\n", err);
186 closesocket (socket_server_fd);
187 return -1;
188 }
189
190 return socket_server_fd;
191 }