Mercurial > mplayer.hg
annotate stream/tcp.c @ 36879:8c1bbe0536ea
kva: make sure that image parameters are setup whenever config() is called
author | komh |
---|---|
date | Wed, 05 Mar 2014 03:17:56 +0000 |
parents | 67e2b2a5ce42 |
children |
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 | |
36266 | 23 #define _BSD_SOURCE |
24 | |
19542 | 25 #include <stdlib.h> |
26 #include <string.h> | |
27 #include <unistd.h> | |
28 | |
29 #include <errno.h> | |
30 #include <ctype.h> | |
31 | |
32 #include <fcntl.h> | |
33 #include <sys/time.h> | |
34 #include <sys/types.h> | |
35 | |
36 #include "config.h" | |
37 | |
38 #include "mp_msg.h" | |
39 #include "help_mp.h" | |
27472
c0b233cd30ca
Revert moving closesocket definition and network headers to network.h.
diego
parents:
27464
diff
changeset
|
40 |
28402 | 41 #if !HAVE_WINSOCK2_H |
27472
c0b233cd30ca
Revert moving closesocket definition and network headers to network.h.
diego
parents:
27464
diff
changeset
|
42 #include <netdb.h> |
c0b233cd30ca
Revert moving closesocket definition and network headers to network.h.
diego
parents:
27464
diff
changeset
|
43 #include <netinet/in.h> |
c0b233cd30ca
Revert moving closesocket definition and network headers to network.h.
diego
parents:
27464
diff
changeset
|
44 #include <sys/socket.h> |
c0b233cd30ca
Revert moving closesocket definition and network headers to network.h.
diego
parents:
27464
diff
changeset
|
45 #include <arpa/inet.h> |
c0b233cd30ca
Revert moving closesocket definition and network headers to network.h.
diego
parents:
27464
diff
changeset
|
46 #else |
c0b233cd30ca
Revert moving closesocket definition and network headers to network.h.
diego
parents:
27464
diff
changeset
|
47 #include <winsock2.h> |
c0b233cd30ca
Revert moving closesocket definition and network headers to network.h.
diego
parents:
27464
diff
changeset
|
48 #include <ws2tcpip.h> |
c0b233cd30ca
Revert moving closesocket definition and network headers to network.h.
diego
parents:
27464
diff
changeset
|
49 #endif |
c0b233cd30ca
Revert moving closesocket definition and network headers to network.h.
diego
parents:
27464
diff
changeset
|
50 |
27473
ae5da477539e
Move '#define closesocket close' preprocessor directive to a common place
diego
parents:
27472
diff
changeset
|
51 #include "network.h" |
26751 | 52 #include "stream.h" |
19542 | 53 #include "tcp.h" |
29351 | 54 #include "libavutil/avstring.h" |
19542 | 55 |
56 /* IPv6 options */ | |
57 int network_prefer_ipv4 = 0; | |
58 | |
59 // Converts an address family constant to a string | |
60 | |
24841
44540930bf94
Make functions static if they aren't referenced externally.
zuxy
parents:
24559
diff
changeset
|
61 static const char *af2String(int af) { |
19542 | 62 switch (af) { |
63 case AF_INET: return "AF_INET"; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
64 |
19542 | 65 #ifdef HAVE_AF_INET6 |
66 case AF_INET6: return "AF_INET6"; | |
67 #endif | |
68 default: return "Unknown address family!"; | |
69 } | |
70 } | |
71 | |
72 | |
73 | |
74 // Connect to a server using a TCP connection, with specified address family | |
75 // return -2 for fatal error, like unable to resolve name, connection timeout... | |
76 // return -1 is unable to connect to a particular port | |
77 | |
24841
44540930bf94
Make functions static if they aren't referenced externally.
zuxy
parents:
24559
diff
changeset
|
78 static int |
19542 | 79 connect2Server_with_af(char *host, int port, int af,int verb) { |
36560 | 80 int err_res = TCP_ERROR_FATAL; |
81 int socket_server_fd = -1; | |
19542 | 82 int err; |
83 socklen_t err_len; | |
84 int ret,count = 0; | |
85 fd_set set; | |
86 struct timeval tv; | |
87 union { | |
88 struct sockaddr_in four; | |
89 #ifdef HAVE_AF_INET6 | |
90 struct sockaddr_in6 six; | |
91 #endif | |
92 } server_address; | |
93 size_t server_address_size; | |
94 void *our_s_addr; // Pointer to sin_addr or sin6_addr | |
95 struct hostent *hp=NULL; | |
96 char buf[255]; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
97 |
28402 | 98 #if HAVE_WINSOCK2_H |
28162 | 99 unsigned long val; |
22379
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
100 int to; |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
101 #else |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
102 struct timeval to; |
19542 | 103 #endif |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
104 |
30619
2fa6d8411b07
Make sure we do not try to use IPv6 with winsock2, we end up connecting
reimar
parents:
30426
diff
changeset
|
105 #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
|
106 // 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
|
107 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
|
108 mp_msg(MSGT_NETWORK, MSGL_WARN, "IPv6 not supported for winsock2\n"); |
36560 | 109 goto err_out; |
30619
2fa6d8411b07
Make sure we do not try to use IPv6 with winsock2, we end up connecting
reimar
parents:
30426
diff
changeset
|
110 } |
2fa6d8411b07
Make sure we do not try to use IPv6 with winsock2, we end up connecting
reimar
parents:
30426
diff
changeset
|
111 #endif |
2fa6d8411b07
Make sure we do not try to use IPv6 with winsock2, we end up connecting
reimar
parents:
30426
diff
changeset
|
112 |
19542 | 113 socket_server_fd = socket(af, SOCK_STREAM, 0); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
114 |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
115 |
19542 | 116 if( socket_server_fd==-1 ) { |
117 // mp_msg(MSGT_NETWORK,MSGL_ERR,"Failed to create %s socket:\n", af2String(af)); | |
36560 | 118 goto err_out; |
19542 | 119 } |
120 | |
22114 | 121 #if defined(SO_RCVTIMEO) && defined(SO_SNDTIMEO) |
28402 | 122 #if HAVE_WINSOCK2_H |
22379
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
123 /* timeout in milliseconds */ |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
124 to = 10 * 1000; |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
125 #else |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
126 to.tv_sec = 10; |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
127 to.tv_usec = 0; |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
128 #endif |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
129 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
|
130 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
|
131 #endif |
50c9dc00154d
Add timeout to tcp connections, avoid hanging forever.
rtogni
parents:
19543
diff
changeset
|
132 |
19542 | 133 switch (af) { |
35249 | 134 case AF_INET: our_s_addr = &server_address.four.sin_addr; break; |
19542 | 135 #ifdef HAVE_AF_INET6 |
35249 | 136 case AF_INET6: our_s_addr = &server_address.six.sin6_addr; break; |
19542 | 137 #endif |
138 default: | |
139 mp_msg(MSGT_NETWORK,MSGL_ERR, MSGTR_MPDEMUX_NW_UnknownAF, af); | |
36560 | 140 goto err_out; |
19542 | 141 } |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
142 |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
143 |
19542 | 144 memset(&server_address, 0, sizeof(server_address)); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
145 |
28404
613f075b4ef0
Restructure network tests: Always check for both inet_aton and inet_pton.
diego
parents:
28402
diff
changeset
|
146 #if HAVE_INET_PTON |
613f075b4ef0
Restructure network tests: Always check for both inet_aton and inet_pton.
diego
parents:
28402
diff
changeset
|
147 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
|
148 #elif HAVE_INET_ATON |
19542 | 149 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
|
150 #elif HAVE_WINSOCK2_H |
19542 | 151 if ( inet_addr(host)==INADDR_NONE ) |
152 #endif | |
153 { | |
154 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
|
155 |
19542 | 156 #ifdef HAVE_GETHOSTBYNAME2 |
35249 | 157 hp=gethostbyname2( host, af ); |
19542 | 158 #else |
35249 | 159 hp=gethostbyname( host ); |
19542 | 160 #endif |
161 if( hp==NULL ) { | |
162 if(verb) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_CantResolv, af2String(af), host); | |
36560 | 163 goto err_out; |
19542 | 164 } |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
165 |
36560 | 166 if (af != hp->h_addrtype) goto err_out; |
36260
a2750366a255
stream/tcp: Check that host object has the right AF before connect
al
parents:
35249
diff
changeset
|
167 |
35249 | 168 memcpy( our_s_addr, hp->h_addr_list[0], hp->h_length ); |
19542 | 169 } |
28402 | 170 #if HAVE_WINSOCK2_H |
19542 | 171 else { |
172 unsigned long addr = inet_addr(host); | |
35249 | 173 memcpy( our_s_addr, &addr, sizeof(addr) ); |
19542 | 174 } |
175 #endif | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
176 |
19542 | 177 switch (af) { |
178 case AF_INET: | |
179 server_address.four.sin_family=af; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
180 server_address.four.sin_port=htons(port); |
19542 | 181 server_address_size = sizeof(server_address.four); |
182 break; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
183 #ifdef HAVE_AF_INET6 |
19542 | 184 case AF_INET6: |
185 server_address.six.sin6_family=af; | |
186 server_address.six.sin6_port=htons(port); | |
187 server_address_size = sizeof(server_address.six); | |
188 break; | |
189 #endif | |
190 default: | |
191 mp_msg(MSGT_NETWORK,MSGL_ERR, MSGTR_MPDEMUX_NW_UnknownAF, af); | |
36560 | 192 goto err_out; |
19542 | 193 } |
194 | |
31432
1bd903001629
Prefere the use of inet_ntop over inet_ntoa, as the former is ipv6 safe.
attila
parents:
30619
diff
changeset
|
195 #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
|
196 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
|
197 #elif HAVE_INET_ATON || defined(HAVE_WINSOCK2_H) |
29351 | 198 av_strlcpy( buf, inet_ntoa( *((struct in_addr*)our_s_addr) ), 255); |
19542 | 199 #endif |
200 if(verb) mp_msg(MSGT_NETWORK,MSGL_STATUS,MSGTR_MPDEMUX_NW_ConnectingToServer, host, buf , port ); | |
201 | |
202 // Turn the socket as non blocking so we can timeout on the connection | |
28402 | 203 #if !HAVE_WINSOCK2_H |
19542 | 204 fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) | O_NONBLOCK ); |
205 #else | |
206 val = 1; | |
207 ioctlsocket( socket_server_fd, FIONBIO, &val ); | |
208 #endif | |
209 if( connect( socket_server_fd, (struct sockaddr*)&server_address, server_address_size )==-1 ) { | |
28402 | 210 #if !HAVE_WINSOCK2_H |
19542 | 211 if( errno!=EINPROGRESS ) { |
212 #else | |
213 if( (WSAGetLastError() != WSAEINPROGRESS) && (WSAGetLastError() != WSAEWOULDBLOCK) ) { | |
214 #endif | |
215 if(verb) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_CantConnect2Server, af2String(af)); | |
36560 | 216 err_res = TCP_ERROR_PORT; |
217 goto err_out; | |
19542 | 218 } |
219 } | |
220 tv.tv_sec = 0; | |
221 tv.tv_usec = 500000; | |
222 FD_ZERO( &set ); | |
223 FD_SET( socket_server_fd, &set ); | |
24558 | 224 // When the connection will be made, we will have a writeable fd |
19542 | 225 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
|
226 if(count > 30 || stream_check_interrupt(500)) { |
19542 | 227 if(count > 30) |
228 mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_ConnTimeout); | |
229 else | |
24558 | 230 mp_msg(MSGT_NETWORK,MSGL_V,"Connection interrupted by user\n"); |
36560 | 231 err_res = TCP_ERROR_TIMEOUT; |
232 goto err_out; | |
19542 | 233 } |
234 count++; | |
235 FD_ZERO( &set ); | |
236 FD_SET( socket_server_fd, &set ); | |
237 tv.tv_sec = 0; | |
238 tv.tv_usec = 500000; | |
239 } | |
24559
7b6a3948f5f2
(Re)move idiotic checks, ret can't be < 0 or > 0 if the loop condition
reimar
parents:
24558
diff
changeset
|
240 if (ret < 0) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_SelectFailed); |
19542 | 241 |
242 // Turn back the socket as blocking | |
28402 | 243 #if !HAVE_WINSOCK2_H |
19542 | 244 fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) & ~O_NONBLOCK ); |
245 #else | |
246 val = 0; | |
247 ioctlsocket( socket_server_fd, FIONBIO, &val ); | |
248 #endif | |
24558 | 249 // Check if there were any errors |
19542 | 250 err_len = sizeof(int); |
251 ret = getsockopt(socket_server_fd,SOL_SOCKET,SO_ERROR,&err,&err_len); | |
252 if(ret < 0) { | |
253 mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_GetSockOptFailed,strerror(errno)); | |
36560 | 254 goto err_out; |
19542 | 255 } |
256 if(err > 0) { | |
257 mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_ConnectError,strerror(err)); | |
36560 | 258 err_res = TCP_ERROR_PORT; |
259 goto err_out; | |
19542 | 260 } |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
261 |
19542 | 262 return socket_server_fd; |
36560 | 263 |
264 err_out: | |
265 if (socket_server_fd >= 0) closesocket(socket_server_fd); | |
266 return err_res; | |
19542 | 267 } |
268 | |
269 // Connect to a server using a TCP connection | |
270 // return -2 for fatal error, like unable to resolve name, connection timeout... | |
271 // return -1 is unable to connect to a particular port | |
272 | |
273 | |
274 int | |
275 connect2Server(char *host, int port, int verb) { | |
276 #ifdef HAVE_AF_INET6 | |
277 int r; | |
19543
e053647fbeec
Cosmetics: recommit patch changing return values to defines
reimar
parents:
19542
diff
changeset
|
278 int s = TCP_ERROR_FATAL; |
19542 | 279 |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
280 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
|
281 if (r >= 0) return r; |
19542 | 282 |
283 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
|
284 if (s == TCP_ERROR_FATAL) return r; |
19542 | 285 return s; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
286 #else |
19542 | 287 return connect2Server_with_af(host, port, AF_INET,verb); |
288 #endif | |
289 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
290 |
19542 | 291 } |