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 );