Mercurial > mplayer.hg
annotate stream/tcp.c @ 31523:7ab5787e625c
configure: Fix detection of SDL backend for vo_gl on OS X
SDL overrides main, and provides a prototype for SDL_main
which uses argc and argv. Since the prototype didn't match
the main() in the test program, it failed to compile, making
the test fail when it should have worked.
author | astrange |
---|---|
date | Wed, 30 Jun 2010 09:27:03 +0000 |
parents | 1bd903001629 |
children | 4f9bc9acf17e |
rev | line source |
---|---|
19542 | 1 /* |
2 * Network layer for MPlayer | |
30426
ce0122361a39
Add license header to all files missing it in the stream subdirectory.
diego
parents:
29351
diff
changeset
|
3 * |
ce0122361a39
Add license header to all files missing it in the stream subdirectory.
diego
parents:
29351
diff
changeset
|
4 * Copyright (C) 2001 Bertrand BAUDET <bertrand_baudet@yahoo.com> |
ce0122361a39
Add license header to all files missing it in the stream subdirectory.
diego
parents:
29351
diff
changeset
|
5 * |
ce0122361a39
Add license header to all files missing it in the stream subdirectory.
diego
parents:
29351
diff
changeset
|
6 * This file is part of MPlayer. |
ce0122361a39
Add license header to all files missing it in the stream subdirectory.
diego
parents:
29351
diff
changeset
|
7 * |
ce0122361a39
Add license header to all files missing it in the stream subdirectory.
diego
parents:
29351
diff
changeset
|
8 * MPlayer is free software; you can redistribute it and/or modify |
ce0122361a39
Add license header to all files missing it in the stream subdirectory.
diego
parents:
29351
diff
changeset
|
9 * it under the terms of the GNU General Public License as published by |
ce0122361a39
Add license header to all files missing it in the stream subdirectory.
diego
parents:
29351
diff
changeset
|
10 * the Free Software Foundation; either version 2 of the License, or |
ce0122361a39
Add license header to all files missing it in the stream subdirectory.
diego
parents:
29351
diff
changeset
|
11 * (at your option) any later version. |
ce0122361a39
Add license header to all files missing it in the stream subdirectory.
diego
parents:
29351
diff
changeset
|
12 * |
ce0122361a39
Add license header to all files missing it in the stream subdirectory.
diego
parents:
29351
diff
changeset
|
13 * MPlayer is distributed in the hope that it will be useful, |
ce0122361a39
Add license header to all files missing it in the stream subdirectory.
diego
parents:
29351
diff
changeset
|
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
ce0122361a39
Add license header to all files missing it in the stream subdirectory.
diego
parents:
29351
diff
changeset
|
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
ce0122361a39
Add license header to all files missing it in the stream subdirectory.
diego
parents:
29351
diff
changeset
|
16 * GNU General Public License for more details. |
ce0122361a39
Add license header to all files missing it in the stream subdirectory.
diego
parents:
29351
diff
changeset
|
17 * |
ce0122361a39
Add license header to all files missing it in the stream subdirectory.
diego
parents:
29351
diff
changeset
|
18 * You should have received a copy of the GNU General Public License along |
ce0122361a39
Add license header to all files missing it in the stream subdirectory.
diego
parents:
29351
diff
changeset
|
19 * with MPlayer; if not, write to the Free Software Foundation, Inc., |
ce0122361a39
Add license header to all files missing it in the stream subdirectory.
diego
parents:
29351
diff
changeset
|
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
19542 | 21 */ |
22 | |
23 #include <stdlib.h> | |
24 #include <string.h> | |
25 #include <unistd.h> | |
26 | |
27 #include <errno.h> | |
28 #include <ctype.h> | |
29 | |
30 #include <fcntl.h> | |
31 #include <sys/time.h> | |
32 #include <sys/types.h> | |
33 | |
34 #include "config.h" | |
35 | |
36 #include "mp_msg.h" | |
37 #include "help_mp.h" | |
27472
c0b233cd30ca
Revert moving closesocket definition and network headers to network.h.
diego
parents:
27464
diff
changeset
|
38 |
28402 | 39 #if !HAVE_WINSOCK2_H |
27472
c0b233cd30ca
Revert moving closesocket definition and network headers to network.h.
diego
parents:
27464
diff
changeset
|
40 #include <netdb.h> |
c0b233cd30ca
Revert moving closesocket definition and network headers to network.h.
diego
parents:
27464
diff
changeset
|
41 #include <netinet/in.h> |
c0b233cd30ca
Revert moving closesocket definition and network headers to network.h.
diego
parents:
27464
diff
changeset
|
42 #include <sys/socket.h> |
c0b233cd30ca
Revert moving closesocket definition and network headers to network.h.
diego
parents:
27464
diff
changeset
|
43 #include <arpa/inet.h> |
c0b233cd30ca
Revert moving closesocket definition and network headers to network.h.
diego
parents:
27464
diff
changeset
|
44 #else |
c0b233cd30ca
Revert moving closesocket definition and network headers to network.h.
diego
parents:
27464
diff
changeset
|
45 #include <winsock2.h> |
c0b233cd30ca
Revert moving closesocket definition and network headers to network.h.
diego
parents:
27464
diff
changeset
|
46 #include <ws2tcpip.h> |
c0b233cd30ca
Revert moving closesocket definition and network headers to network.h.
diego
parents:
27464
diff
changeset
|
47 #endif |
c0b233cd30ca
Revert moving closesocket definition and network headers to network.h.
diego
parents:
27464
diff
changeset
|
48 |
27473
ae5da477539e
Move '#define closesocket close' preprocessor directive to a common place
diego
parents:
27472
diff
changeset
|
49 #include "network.h" |
26751 | 50 #include "stream.h" |
19542 | 51 #include "tcp.h" |
29351 | 52 #include "libavutil/avstring.h" |
19542 | 53 |
54 /* IPv6 options */ | |
55 int network_prefer_ipv4 = 0; | |
56 | |
57 // Converts an address family constant to a string | |
58 | |
24841
44540930bf94
Make functions static if they aren't referenced externally.
zuxy
parents:
24559
diff
changeset
|
59 static const char *af2String(int af) { |
19542 | 60 switch (af) { |
61 case AF_INET: return "AF_INET"; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
62 |
19542 | 63 #ifdef HAVE_AF_INET6 |
64 case AF_INET6: return "AF_INET6"; | |
65 #endif | |
66 default: return "Unknown address family!"; | |
67 } | |
68 } | |
69 | |
70 | |
71 | |
72 // Connect to a server using a TCP connection, with specified address family | |
73 // return -2 for fatal error, like unable to resolve name, connection timeout... | |
74 // return -1 is unable to connect to a particular port | |
75 | |
24841
44540930bf94
Make functions static if they aren't referenced externally.
zuxy
parents:
24559
diff
changeset
|
76 static int |
19542 | 77 connect2Server_with_af(char *host, int port, int af,int verb) { |
78 int socket_server_fd; | |
79 int err; | |
80 socklen_t err_len; | |
81 int ret,count = 0; | |
82 fd_set set; | |
83 struct timeval tv; | |
84 union { | |
85 struct sockaddr_in four; | |
86 #ifdef HAVE_AF_INET6 | |
87 struct sockaddr_in6 six; | |
88 #endif | |
89 } server_address; | |
90 size_t server_address_size; | |
91 void *our_s_addr; // Pointer to sin_addr or sin6_addr | |
92 struct hostent *hp=NULL; | |
93 char buf[255]; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
94 |
28402 | 95 #if HAVE_WINSOCK2_H |
28162 | 96 unsigned long val; |
22379
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
97 int to; |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
98 #else |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
99 struct timeval to; |
19542 | 100 #endif |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
101 |
30619
2fa6d8411b07
Make sure we do not try to use IPv6 with winsock2, we end up connecting
reimar
parents:
30426
diff
changeset
|
102 #if HAVE_WINSOCK2_H && defined(HAVE_AF_INET6) |
2fa6d8411b07
Make sure we do not try to use IPv6 with winsock2, we end up connecting
reimar
parents:
30426
diff
changeset
|
103 // our winsock name resolution code can not handle IPv6 |
2fa6d8411b07
Make sure we do not try to use IPv6 with winsock2, we end up connecting
reimar
parents:
30426
diff
changeset
|
104 if (af == AF_INET6) { |
2fa6d8411b07
Make sure we do not try to use IPv6 with winsock2, we end up connecting
reimar
parents:
30426
diff
changeset
|
105 mp_msg(MSGT_NETWORK, MSGL_WARN, "IPv6 not supported for winsock2\n"); |
2fa6d8411b07
Make sure we do not try to use IPv6 with winsock2, we end up connecting
reimar
parents:
30426
diff
changeset
|
106 return TCP_ERROR_FATAL; |
2fa6d8411b07
Make sure we do not try to use IPv6 with winsock2, we end up connecting
reimar
parents:
30426
diff
changeset
|
107 } |
2fa6d8411b07
Make sure we do not try to use IPv6 with winsock2, we end up connecting
reimar
parents:
30426
diff
changeset
|
108 #endif |
2fa6d8411b07
Make sure we do not try to use IPv6 with winsock2, we end up connecting
reimar
parents:
30426
diff
changeset
|
109 |
19542 | 110 socket_server_fd = socket(af, SOCK_STREAM, 0); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
111 |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
112 |
19542 | 113 if( socket_server_fd==-1 ) { |
114 // mp_msg(MSGT_NETWORK,MSGL_ERR,"Failed to create %s socket:\n", af2String(af)); | |
19543
e053647fbeec
Cosmetics: recommit patch changing return values to defines
reimar
parents:
19542
diff
changeset
|
115 return TCP_ERROR_FATAL; |
19542 | 116 } |
117 | |
22114 | 118 #if defined(SO_RCVTIMEO) && defined(SO_SNDTIMEO) |
28402 | 119 #if HAVE_WINSOCK2_H |
22379
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
120 /* timeout in milliseconds */ |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
121 to = 10 * 1000; |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
122 #else |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
123 to.tv_sec = 10; |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
124 to.tv_usec = 0; |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
125 #endif |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
126 setsockopt(socket_server_fd, SOL_SOCKET, SO_RCVTIMEO, &to, sizeof(to)); |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
127 setsockopt(socket_server_fd, SOL_SOCKET, SO_SNDTIMEO, &to, sizeof(to)); |
22113
50c9dc00154d
Add timeout to tcp connections, avoid hanging forever.
rtogni
parents:
19543
diff
changeset
|
128 #endif |
50c9dc00154d
Add timeout to tcp connections, avoid hanging forever.
rtogni
parents:
19543
diff
changeset
|
129 |
19542 | 130 switch (af) { |
131 case AF_INET: our_s_addr = (void *) &server_address.four.sin_addr; break; | |
132 #ifdef HAVE_AF_INET6 | |
133 case AF_INET6: our_s_addr = (void *) &server_address.six.sin6_addr; break; | |
134 #endif | |
135 default: | |
136 mp_msg(MSGT_NETWORK,MSGL_ERR, MSGTR_MPDEMUX_NW_UnknownAF, af); | |
19543
e053647fbeec
Cosmetics: recommit patch changing return values to defines
reimar
parents:
19542
diff
changeset
|
137 return TCP_ERROR_FATAL; |
19542 | 138 } |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
139 |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
140 |
19542 | 141 memset(&server_address, 0, sizeof(server_address)); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
142 |
28404
613f075b4ef0
Restructure network tests: Always check for both inet_aton and inet_pton.
diego
parents:
28402
diff
changeset
|
143 #if HAVE_INET_PTON |
613f075b4ef0
Restructure network tests: Always check for both inet_aton and inet_pton.
diego
parents:
28402
diff
changeset
|
144 if (inet_pton(af, host, our_s_addr)!=1) |
613f075b4ef0
Restructure network tests: Always check for both inet_aton and inet_pton.
diego
parents:
28402
diff
changeset
|
145 #elif HAVE_INET_ATON |
19542 | 146 if (inet_aton(host, our_s_addr)!=1) |
28404
613f075b4ef0
Restructure network tests: Always check for both inet_aton and inet_pton.
diego
parents:
28402
diff
changeset
|
147 #elif HAVE_WINSOCK2_H |
19542 | 148 if ( inet_addr(host)==INADDR_NONE ) |
149 #endif | |
150 { | |
151 if(verb) mp_msg(MSGT_NETWORK,MSGL_STATUS,MSGTR_MPDEMUX_NW_ResolvingHostForAF, host, af2String(af)); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
152 |
19542 | 153 #ifdef HAVE_GETHOSTBYNAME2 |
154 hp=(struct hostent*)gethostbyname2( host, af ); | |
155 #else | |
156 hp=(struct hostent*)gethostbyname( host ); | |
157 #endif | |
158 if( hp==NULL ) { | |
159 if(verb) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_CantResolv, af2String(af), host); | |
19543
e053647fbeec
Cosmetics: recommit patch changing return values to defines
reimar
parents:
19542
diff
changeset
|
160 return TCP_ERROR_FATAL; |
19542 | 161 } |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
162 |
19542 | 163 memcpy( our_s_addr, (void*)hp->h_addr_list[0], hp->h_length ); |
164 } | |
28402 | 165 #if HAVE_WINSOCK2_H |
19542 | 166 else { |
167 unsigned long addr = inet_addr(host); | |
168 memcpy( our_s_addr, (void*)&addr, sizeof(addr) ); | |
169 } | |
170 #endif | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
171 |
19542 | 172 switch (af) { |
173 case AF_INET: | |
174 server_address.four.sin_family=af; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
175 server_address.four.sin_port=htons(port); |
19542 | 176 server_address_size = sizeof(server_address.four); |
177 break; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
178 #ifdef HAVE_AF_INET6 |
19542 | 179 case AF_INET6: |
180 server_address.six.sin6_family=af; | |
181 server_address.six.sin6_port=htons(port); | |
182 server_address_size = sizeof(server_address.six); | |
183 break; | |
184 #endif | |
185 default: | |
186 mp_msg(MSGT_NETWORK,MSGL_ERR, MSGTR_MPDEMUX_NW_UnknownAF, af); | |
19543
e053647fbeec
Cosmetics: recommit patch changing return values to defines
reimar
parents:
19542
diff
changeset
|
187 return TCP_ERROR_FATAL; |
19542 | 188 } |
189 | |
31432
1bd903001629
Prefere the use of inet_ntop over inet_ntoa, as the former is ipv6 safe.
attila
parents:
30619
diff
changeset
|
190 #if HAVE_INET_PTON |
1bd903001629
Prefere the use of inet_ntop over inet_ntoa, as the former is ipv6 safe.
attila
parents:
30619
diff
changeset
|
191 inet_ntop(af, our_s_addr, buf, 255); |
1bd903001629
Prefere the use of inet_ntop over inet_ntoa, as the former is ipv6 safe.
attila
parents:
30619
diff
changeset
|
192 #elif HAVE_INET_ATON || defined(HAVE_WINSOCK2_H) |
29351 | 193 av_strlcpy( buf, inet_ntoa( *((struct in_addr*)our_s_addr) ), 255); |
19542 | 194 #endif |
195 if(verb) mp_msg(MSGT_NETWORK,MSGL_STATUS,MSGTR_MPDEMUX_NW_ConnectingToServer, host, buf , port ); | |
196 | |
197 // Turn the socket as non blocking so we can timeout on the connection | |
28402 | 198 #if !HAVE_WINSOCK2_H |
19542 | 199 fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) | O_NONBLOCK ); |
200 #else | |
201 val = 1; | |
202 ioctlsocket( socket_server_fd, FIONBIO, &val ); | |
203 #endif | |
204 if( connect( socket_server_fd, (struct sockaddr*)&server_address, server_address_size )==-1 ) { | |
28402 | 205 #if !HAVE_WINSOCK2_H |
19542 | 206 if( errno!=EINPROGRESS ) { |
207 #else | |
208 if( (WSAGetLastError() != WSAEINPROGRESS) && (WSAGetLastError() != WSAEWOULDBLOCK) ) { | |
209 #endif | |
210 if(verb) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_CantConnect2Server, af2String(af)); | |
211 closesocket(socket_server_fd); | |
19543
e053647fbeec
Cosmetics: recommit patch changing return values to defines
reimar
parents:
19542
diff
changeset
|
212 return TCP_ERROR_PORT; |
19542 | 213 } |
214 } | |
215 tv.tv_sec = 0; | |
216 tv.tv_usec = 500000; | |
217 FD_ZERO( &set ); | |
218 FD_SET( socket_server_fd, &set ); | |
24558 | 219 // When the connection will be made, we will have a writeable fd |
19542 | 220 while((ret = select(socket_server_fd+1, NULL, &set, NULL, &tv)) == 0) { |
26326
5bfc1d8bece9
Remove the need for code using stream to export an mp_input_check_interrupt()
albeu
parents:
24841
diff
changeset
|
221 if(count > 30 || stream_check_interrupt(500)) { |
19542 | 222 if(count > 30) |
223 mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_ConnTimeout); | |
224 else | |
24558 | 225 mp_msg(MSGT_NETWORK,MSGL_V,"Connection interrupted by user\n"); |
19543
e053647fbeec
Cosmetics: recommit patch changing return values to defines
reimar
parents:
19542
diff
changeset
|
226 return TCP_ERROR_TIMEOUT; |
19542 | 227 } |
228 count++; | |
229 FD_ZERO( &set ); | |
230 FD_SET( socket_server_fd, &set ); | |
231 tv.tv_sec = 0; | |
232 tv.tv_usec = 500000; | |
233 } | |
24559
7b6a3948f5f2
(Re)move idiotic checks, ret can't be < 0 or > 0 if the loop condition
reimar
parents:
24558
diff
changeset
|
234 if (ret < 0) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_SelectFailed); |
19542 | 235 |
236 // Turn back the socket as blocking | |
28402 | 237 #if !HAVE_WINSOCK2_H |
19542 | 238 fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) & ~O_NONBLOCK ); |
239 #else | |
240 val = 0; | |
241 ioctlsocket( socket_server_fd, FIONBIO, &val ); | |
242 #endif | |
24558 | 243 // Check if there were any errors |
19542 | 244 err_len = sizeof(int); |
245 ret = getsockopt(socket_server_fd,SOL_SOCKET,SO_ERROR,&err,&err_len); | |
246 if(ret < 0) { | |
247 mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_GetSockOptFailed,strerror(errno)); | |
19543
e053647fbeec
Cosmetics: recommit patch changing return values to defines
reimar
parents:
19542
diff
changeset
|
248 return TCP_ERROR_FATAL; |
19542 | 249 } |
250 if(err > 0) { | |
251 mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_ConnectError,strerror(err)); | |
19543
e053647fbeec
Cosmetics: recommit patch changing return values to defines
reimar
parents:
19542
diff
changeset
|
252 return TCP_ERROR_PORT; |
19542 | 253 } |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
254 |
19542 | 255 return socket_server_fd; |
256 } | |
257 | |
258 // Connect to a server using a TCP connection | |
259 // return -2 for fatal error, like unable to resolve name, connection timeout... | |
260 // return -1 is unable to connect to a particular port | |
261 | |
262 | |
263 int | |
264 connect2Server(char *host, int port, int verb) { | |
265 #ifdef HAVE_AF_INET6 | |
266 int r; | |
19543
e053647fbeec
Cosmetics: recommit patch changing return values to defines
reimar
parents:
19542
diff
changeset
|
267 int s = TCP_ERROR_FATAL; |
19542 | 268 |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
269 r = connect2Server_with_af(host, port, network_prefer_ipv4 ? AF_INET:AF_INET6,verb); |
19543
e053647fbeec
Cosmetics: recommit patch changing return values to defines
reimar
parents:
19542
diff
changeset
|
270 if (r >= 0) return r; |
19542 | 271 |
272 s = connect2Server_with_af(host, port, network_prefer_ipv4 ? AF_INET6:AF_INET,verb); | |
19543
e053647fbeec
Cosmetics: recommit patch changing return values to defines
reimar
parents:
19542
diff
changeset
|
273 if (s == TCP_ERROR_FATAL) return r; |
19542 | 274 return s; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
275 #else |
19542 | 276 return connect2Server_with_af(host, port, AF_INET,verb); |
277 #endif | |
278 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
279 |
19542 | 280 } |