Mercurial > mplayer.hg
annotate stream/tcp.c @ 30447:c84c27c3eafb
Add support for autodetection during preinit and use that to detect a default
value for the yuv suboption.
author | reimar |
---|---|
date | Tue, 02 Feb 2010 20:37:48 +0000 |
parents | ce0122361a39 |
children | 2fa6d8411b07 |
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 |
19542 | 102 socket_server_fd = socket(af, SOCK_STREAM, 0); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
103 |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
104 |
19542 | 105 if( socket_server_fd==-1 ) { |
106 // 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
|
107 return TCP_ERROR_FATAL; |
19542 | 108 } |
109 | |
22114 | 110 #if defined(SO_RCVTIMEO) && defined(SO_SNDTIMEO) |
28402 | 111 #if HAVE_WINSOCK2_H |
22379
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
112 /* timeout in milliseconds */ |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
113 to = 10 * 1000; |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
114 #else |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
115 to.tv_sec = 10; |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
116 to.tv_usec = 0; |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
117 #endif |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
118 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
|
119 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
|
120 #endif |
50c9dc00154d
Add timeout to tcp connections, avoid hanging forever.
rtogni
parents:
19543
diff
changeset
|
121 |
19542 | 122 switch (af) { |
123 case AF_INET: our_s_addr = (void *) &server_address.four.sin_addr; break; | |
124 #ifdef HAVE_AF_INET6 | |
125 case AF_INET6: our_s_addr = (void *) &server_address.six.sin6_addr; break; | |
126 #endif | |
127 default: | |
128 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
|
129 return TCP_ERROR_FATAL; |
19542 | 130 } |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
131 |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
132 |
19542 | 133 memset(&server_address, 0, sizeof(server_address)); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
134 |
28404
613f075b4ef0
Restructure network tests: Always check for both inet_aton and inet_pton.
diego
parents:
28402
diff
changeset
|
135 #if HAVE_INET_PTON |
613f075b4ef0
Restructure network tests: Always check for both inet_aton and inet_pton.
diego
parents:
28402
diff
changeset
|
136 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
|
137 #elif HAVE_INET_ATON |
19542 | 138 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
|
139 #elif HAVE_WINSOCK2_H |
19542 | 140 if ( inet_addr(host)==INADDR_NONE ) |
141 #endif | |
142 { | |
143 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
|
144 |
19542 | 145 #ifdef HAVE_GETHOSTBYNAME2 |
146 hp=(struct hostent*)gethostbyname2( host, af ); | |
147 #else | |
148 hp=(struct hostent*)gethostbyname( host ); | |
149 #endif | |
150 if( hp==NULL ) { | |
151 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
|
152 return TCP_ERROR_FATAL; |
19542 | 153 } |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
154 |
19542 | 155 memcpy( our_s_addr, (void*)hp->h_addr_list[0], hp->h_length ); |
156 } | |
28402 | 157 #if HAVE_WINSOCK2_H |
19542 | 158 else { |
159 unsigned long addr = inet_addr(host); | |
160 memcpy( our_s_addr, (void*)&addr, sizeof(addr) ); | |
161 } | |
162 #endif | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
163 |
19542 | 164 switch (af) { |
165 case AF_INET: | |
166 server_address.four.sin_family=af; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
167 server_address.four.sin_port=htons(port); |
19542 | 168 server_address_size = sizeof(server_address.four); |
169 break; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
170 #ifdef HAVE_AF_INET6 |
19542 | 171 case AF_INET6: |
172 server_address.six.sin6_family=af; | |
173 server_address.six.sin6_port=htons(port); | |
174 server_address_size = sizeof(server_address.six); | |
175 break; | |
176 #endif | |
177 default: | |
178 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
|
179 return TCP_ERROR_FATAL; |
19542 | 180 } |
181 | |
28400
9202b9245819
HAVE_ATON --> HAVE_INET_ATON to match FFmpeg and give it a 0/1 value.
diego
parents:
28162
diff
changeset
|
182 #if HAVE_INET_ATON || defined(HAVE_WINSOCK2_H) |
29351 | 183 av_strlcpy( buf, inet_ntoa( *((struct in_addr*)our_s_addr) ), 255); |
19542 | 184 #else |
185 inet_ntop(af, our_s_addr, buf, 255); | |
186 #endif | |
187 if(verb) mp_msg(MSGT_NETWORK,MSGL_STATUS,MSGTR_MPDEMUX_NW_ConnectingToServer, host, buf , port ); | |
188 | |
189 // Turn the socket as non blocking so we can timeout on the connection | |
28402 | 190 #if !HAVE_WINSOCK2_H |
19542 | 191 fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) | O_NONBLOCK ); |
192 #else | |
193 val = 1; | |
194 ioctlsocket( socket_server_fd, FIONBIO, &val ); | |
195 #endif | |
196 if( connect( socket_server_fd, (struct sockaddr*)&server_address, server_address_size )==-1 ) { | |
28402 | 197 #if !HAVE_WINSOCK2_H |
19542 | 198 if( errno!=EINPROGRESS ) { |
199 #else | |
200 if( (WSAGetLastError() != WSAEINPROGRESS) && (WSAGetLastError() != WSAEWOULDBLOCK) ) { | |
201 #endif | |
202 if(verb) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_CantConnect2Server, af2String(af)); | |
203 closesocket(socket_server_fd); | |
19543
e053647fbeec
Cosmetics: recommit patch changing return values to defines
reimar
parents:
19542
diff
changeset
|
204 return TCP_ERROR_PORT; |
19542 | 205 } |
206 } | |
207 tv.tv_sec = 0; | |
208 tv.tv_usec = 500000; | |
209 FD_ZERO( &set ); | |
210 FD_SET( socket_server_fd, &set ); | |
24558 | 211 // When the connection will be made, we will have a writeable fd |
19542 | 212 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
|
213 if(count > 30 || stream_check_interrupt(500)) { |
19542 | 214 if(count > 30) |
215 mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_ConnTimeout); | |
216 else | |
24558 | 217 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
|
218 return TCP_ERROR_TIMEOUT; |
19542 | 219 } |
220 count++; | |
221 FD_ZERO( &set ); | |
222 FD_SET( socket_server_fd, &set ); | |
223 tv.tv_sec = 0; | |
224 tv.tv_usec = 500000; | |
225 } | |
24559
7b6a3948f5f2
(Re)move idiotic checks, ret can't be < 0 or > 0 if the loop condition
reimar
parents:
24558
diff
changeset
|
226 if (ret < 0) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_SelectFailed); |
19542 | 227 |
228 // Turn back the socket as blocking | |
28402 | 229 #if !HAVE_WINSOCK2_H |
19542 | 230 fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) & ~O_NONBLOCK ); |
231 #else | |
232 val = 0; | |
233 ioctlsocket( socket_server_fd, FIONBIO, &val ); | |
234 #endif | |
24558 | 235 // Check if there were any errors |
19542 | 236 err_len = sizeof(int); |
237 ret = getsockopt(socket_server_fd,SOL_SOCKET,SO_ERROR,&err,&err_len); | |
238 if(ret < 0) { | |
239 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
|
240 return TCP_ERROR_FATAL; |
19542 | 241 } |
242 if(err > 0) { | |
243 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
|
244 return TCP_ERROR_PORT; |
19542 | 245 } |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
246 |
19542 | 247 return socket_server_fd; |
248 } | |
249 | |
250 // Connect to a server using a TCP connection | |
251 // return -2 for fatal error, like unable to resolve name, connection timeout... | |
252 // return -1 is unable to connect to a particular port | |
253 | |
254 | |
255 int | |
256 connect2Server(char *host, int port, int verb) { | |
257 #ifdef HAVE_AF_INET6 | |
258 int r; | |
19543
e053647fbeec
Cosmetics: recommit patch changing return values to defines
reimar
parents:
19542
diff
changeset
|
259 int s = TCP_ERROR_FATAL; |
19542 | 260 |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
261 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
|
262 if (r >= 0) return r; |
19542 | 263 |
264 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
|
265 if (s == TCP_ERROR_FATAL) return r; |
19542 | 266 return s; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
267 #else |
19542 | 268 return connect2Server_with_af(host, port, AF_INET,verb); |
269 #endif | |
270 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
271 |
19542 | 272 } |