Mercurial > mplayer.hg
comparison stream/network.c @ 19335:2a9d669e5ff6
isolated tcp socket code from network.c to a dedicated file
author | ben |
---|---|
date | Sat, 05 Aug 2006 10:30:06 +0000 |
parents | dcda8b4092b3 |
children | e7f56cc4505e |
comparison
equal
deleted
inserted
replaced
19334:c95db0988ded | 19335:2a9d669e5ff6 |
---|---|
29 #include "stream.h" | 29 #include "stream.h" |
30 #include "libmpdemux/demuxer.h" | 30 #include "libmpdemux/demuxer.h" |
31 #include "m_config.h" | 31 #include "m_config.h" |
32 | 32 |
33 #include "network.h" | 33 #include "network.h" |
34 #include "tcp.h" | |
34 #include "http.h" | 35 #include "http.h" |
35 #include "cookies.h" | 36 #include "cookies.h" |
36 #include "url.h" | 37 #include "url.h" |
37 | 38 |
38 #include "version.h" | 39 #include "version.h" |
49 int network_bandwidth=0; | 50 int network_bandwidth=0; |
50 int network_cookies_enabled = 0; | 51 int network_cookies_enabled = 0; |
51 char *network_useragent=NULL; | 52 char *network_useragent=NULL; |
52 | 53 |
53 /* IPv6 options */ | 54 /* IPv6 options */ |
54 int network_prefer_ipv4 = 0; | |
55 int network_ipv4_only_proxy = 0; | 55 int network_ipv4_only_proxy = 0; |
56 | 56 |
57 | 57 |
58 mime_struct_t mime_type_table[] = { | 58 mime_struct_t mime_type_table[] = { |
59 // MP3 streaming, some MP3 streaming server answer with audio/mpeg | 59 // MP3 streaming, some MP3 streaming server answer with audio/mpeg |
112 if( streaming_ctrl->buffer ) free( streaming_ctrl->buffer ); | 112 if( streaming_ctrl->buffer ) free( streaming_ctrl->buffer ); |
113 if( streaming_ctrl->data ) free( streaming_ctrl->data ); | 113 if( streaming_ctrl->data ) free( streaming_ctrl->data ); |
114 free( streaming_ctrl ); | 114 free( streaming_ctrl ); |
115 } | 115 } |
116 | 116 |
117 | |
118 // Converts an address family constant to a string | |
119 | |
120 const char *af2String(int af) { | |
121 switch (af) { | |
122 case AF_INET: return "AF_INET"; | |
123 | |
124 #ifdef HAVE_AF_INET6 | |
125 case AF_INET6: return "AF_INET6"; | |
126 #endif | |
127 default: return "Unknown address family!"; | |
128 } | |
129 } | |
130 | |
131 | |
132 | |
133 // Connect to a server using a TCP connection, with specified address family | |
134 // return -2 for fatal error, like unable to resolve name, connection timeout... | |
135 // return -1 is unable to connect to a particular port | |
136 | |
137 int | |
138 connect2Server_with_af(char *host, int port, int af,int verb) { | |
139 int socket_server_fd; | |
140 int err; | |
141 socklen_t err_len; | |
142 int ret,count = 0; | |
143 fd_set set; | |
144 struct timeval tv; | |
145 union { | |
146 struct sockaddr_in four; | |
147 #ifdef HAVE_AF_INET6 | |
148 struct sockaddr_in6 six; | |
149 #endif | |
150 } server_address; | |
151 size_t server_address_size; | |
152 void *our_s_addr; // Pointer to sin_addr or sin6_addr | |
153 struct hostent *hp=NULL; | |
154 char buf[255]; | |
155 | |
156 #ifdef HAVE_WINSOCK2 | |
157 u_long val; | |
158 #endif | |
159 | |
160 socket_server_fd = socket(af, SOCK_STREAM, 0); | |
161 | |
162 | |
163 if( socket_server_fd==-1 ) { | |
164 // mp_msg(MSGT_NETWORK,MSGL_ERR,"Failed to create %s socket:\n", af2String(af)); | |
165 return -2; | |
166 } | |
167 | |
168 switch (af) { | |
169 case AF_INET: our_s_addr = (void *) &server_address.four.sin_addr; break; | |
170 #ifdef HAVE_AF_INET6 | |
171 case AF_INET6: our_s_addr = (void *) &server_address.six.sin6_addr; break; | |
172 #endif | |
173 default: | |
174 mp_msg(MSGT_NETWORK,MSGL_ERR, MSGTR_MPDEMUX_NW_UnknownAF, af); | |
175 return -2; | |
176 } | |
177 | |
178 | |
179 memset(&server_address, 0, sizeof(server_address)); | |
180 | |
181 #ifndef HAVE_WINSOCK2 | |
182 #ifdef USE_ATON | |
183 if (inet_aton(host, our_s_addr)!=1) | |
184 #else | |
185 if (inet_pton(af, host, our_s_addr)!=1) | |
186 #endif | |
187 #else | |
188 if ( inet_addr(host)==INADDR_NONE ) | |
189 #endif | |
190 { | |
191 if(verb) mp_msg(MSGT_NETWORK,MSGL_STATUS,MSGTR_MPDEMUX_NW_ResolvingHostForAF, host, af2String(af)); | |
192 | |
193 #ifdef HAVE_GETHOSTBYNAME2 | |
194 hp=(struct hostent*)gethostbyname2( host, af ); | |
195 #else | |
196 hp=(struct hostent*)gethostbyname( host ); | |
197 #endif | |
198 if( hp==NULL ) { | |
199 if(verb) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_CantResolv, af2String(af), host); | |
200 return -2; | |
201 } | |
202 | |
203 memcpy( our_s_addr, (void*)hp->h_addr_list[0], hp->h_length ); | |
204 } | |
205 #ifdef HAVE_WINSOCK2 | |
206 else { | |
207 unsigned long addr = inet_addr(host); | |
208 memcpy( our_s_addr, (void*)&addr, sizeof(addr) ); | |
209 } | |
210 #endif | |
211 | |
212 switch (af) { | |
213 case AF_INET: | |
214 server_address.four.sin_family=af; | |
215 server_address.four.sin_port=htons(port); | |
216 server_address_size = sizeof(server_address.four); | |
217 break; | |
218 #ifdef HAVE_AF_INET6 | |
219 case AF_INET6: | |
220 server_address.six.sin6_family=af; | |
221 server_address.six.sin6_port=htons(port); | |
222 server_address_size = sizeof(server_address.six); | |
223 break; | |
224 #endif | |
225 default: | |
226 mp_msg(MSGT_NETWORK,MSGL_ERR, MSGTR_MPDEMUX_NW_UnknownAF, af); | |
227 return -2; | |
228 } | |
229 | |
230 #if defined(USE_ATON) || defined(HAVE_WINSOCK2) | |
231 strncpy( buf, inet_ntoa( *((struct in_addr*)our_s_addr) ), 255); | |
232 #else | |
233 inet_ntop(af, our_s_addr, buf, 255); | |
234 #endif | |
235 if(verb) mp_msg(MSGT_NETWORK,MSGL_STATUS,MSGTR_MPDEMUX_NW_ConnectingToServer, host, buf , port ); | |
236 | |
237 // Turn the socket as non blocking so we can timeout on the connection | |
238 #ifndef HAVE_WINSOCK2 | |
239 fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) | O_NONBLOCK ); | |
240 #else | |
241 val = 1; | |
242 ioctlsocket( socket_server_fd, FIONBIO, &val ); | |
243 #endif | |
244 if( connect( socket_server_fd, (struct sockaddr*)&server_address, server_address_size )==-1 ) { | |
245 #ifndef HAVE_WINSOCK2 | |
246 if( errno!=EINPROGRESS ) { | |
247 #else | |
248 if( (WSAGetLastError() != WSAEINPROGRESS) && (WSAGetLastError() != WSAEWOULDBLOCK) ) { | |
249 #endif | |
250 if(verb) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_CantConnect2Server, af2String(af)); | |
251 closesocket(socket_server_fd); | |
252 return -1; | |
253 } | |
254 } | |
255 tv.tv_sec = 0; | |
256 tv.tv_usec = 500000; | |
257 FD_ZERO( &set ); | |
258 FD_SET( socket_server_fd, &set ); | |
259 // When the connection will be made, we will have a writable fd | |
260 while((ret = select(socket_server_fd+1, NULL, &set, NULL, &tv)) == 0) { | |
261 if( ret<0 ) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_SelectFailed); | |
262 else if(ret > 0) break; | |
263 else if(count > 30 || mp_input_check_interrupt(500)) { | |
264 if(count > 30) | |
265 mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_ConnTimeout); | |
266 else | |
267 mp_msg(MSGT_NETWORK,MSGL_V,"Connection interuppted by user\n"); | |
268 return -3; | |
269 } | |
270 count++; | |
271 FD_ZERO( &set ); | |
272 FD_SET( socket_server_fd, &set ); | |
273 tv.tv_sec = 0; | |
274 tv.tv_usec = 500000; | |
275 } | |
276 | |
277 // Turn back the socket as blocking | |
278 #ifndef HAVE_WINSOCK2 | |
279 fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) & ~O_NONBLOCK ); | |
280 #else | |
281 val = 0; | |
282 ioctlsocket( socket_server_fd, FIONBIO, &val ); | |
283 #endif | |
284 // Check if there were any error | |
285 err_len = sizeof(int); | |
286 ret = getsockopt(socket_server_fd,SOL_SOCKET,SO_ERROR,&err,&err_len); | |
287 if(ret < 0) { | |
288 mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_GetSockOptFailed,strerror(errno)); | |
289 return -2; | |
290 } | |
291 if(err > 0) { | |
292 mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_ConnectError,strerror(err)); | |
293 return -1; | |
294 } | |
295 | |
296 return socket_server_fd; | |
297 } | |
298 | |
299 // Connect to a server using a TCP connection | |
300 // return -2 for fatal error, like unable to resolve name, connection timeout... | |
301 // return -1 is unable to connect to a particular port | |
302 | |
303 | |
304 int | |
305 connect2Server(char *host, int port, int verb) { | |
306 #ifdef HAVE_AF_INET6 | |
307 int r; | |
308 int s = -2; | |
309 | |
310 r = connect2Server_with_af(host, port, network_prefer_ipv4 ? AF_INET:AF_INET6,verb); | |
311 if (r > -1) return r; | |
312 | |
313 s = connect2Server_with_af(host, port, network_prefer_ipv4 ? AF_INET6:AF_INET,verb); | |
314 if (s == -2) return r; | |
315 return s; | |
316 #else | |
317 return connect2Server_with_af(host, port, AF_INET,verb); | |
318 #endif | |
319 | |
320 | |
321 } | |
322 | |
323 URL_t* | 117 URL_t* |
324 check4proxies( URL_t *url ) { | 118 check4proxies( URL_t *url ) { |
325 URL_t *url_out = NULL; | 119 URL_t *url_out = NULL; |
326 if( url==NULL ) return NULL; | 120 if( url==NULL ) return NULL; |
327 url_out = url_new( url->url ); | 121 url_out = url_new( url->url ); |