Mercurial > mplayer.hg
annotate stream/tcp.c @ 30671:38daf6b55b45
Update my (Jason Tackaberry) email address and contributions in AUTHORS
file.
author | tack |
---|---|
date | Mon, 22 Feb 2010 17:06:24 +0000 |
parents | 2fa6d8411b07 |
children | 1bd903001629 |
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 | |
28400
9202b9245819
HAVE_ATON --> HAVE_INET_ATON to match FFmpeg and give it a 0/1 value.
diego
parents:
28162
diff
changeset
|
190 #if HAVE_INET_ATON || defined(HAVE_WINSOCK2_H) |
29351 | 191 av_strlcpy( buf, inet_ntoa( *((struct in_addr*)our_s_addr) ), 255); |
19542 | 192 #else |
193 inet_ntop(af, our_s_addr, buf, 255); | |
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 } |