Mercurial > mplayer.hg
annotate stream/tcp.c @ 29794:df1826dcdb2d
Disable audio when initializing the filter chain fails (can happen e.g. when the hwmpa
decoder is used but the hardware does not support hardware MPEG audio).
Otherwise this will lead to a crash later on when the decode code tries to access
the audio filter chain.
author | reimar |
---|---|
date | Fri, 06 Nov 2009 15:56:30 +0000 |
parents | d58878f243ea |
children | ce0122361a39 |
rev | line source |
---|---|
19542 | 1 /* |
2 * Network layer for MPlayer | |
3 * by Bertrand BAUDET <bertrand_baudet@yahoo.com> | |
4 * (C) 2001, MPlayer team. | |
5 */ | |
6 | |
7 #include <stdlib.h> | |
8 #include <string.h> | |
9 #include <unistd.h> | |
10 | |
11 #include <errno.h> | |
12 #include <ctype.h> | |
13 | |
14 #include <fcntl.h> | |
15 #include <sys/time.h> | |
16 #include <sys/types.h> | |
17 | |
18 #include "config.h" | |
19 | |
20 #include "mp_msg.h" | |
21 #include "help_mp.h" | |
27472
c0b233cd30ca
Revert moving closesocket definition and network headers to network.h.
diego
parents:
27464
diff
changeset
|
22 |
28402 | 23 #if !HAVE_WINSOCK2_H |
27472
c0b233cd30ca
Revert moving closesocket definition and network headers to network.h.
diego
parents:
27464
diff
changeset
|
24 #include <netdb.h> |
c0b233cd30ca
Revert moving closesocket definition and network headers to network.h.
diego
parents:
27464
diff
changeset
|
25 #include <netinet/in.h> |
c0b233cd30ca
Revert moving closesocket definition and network headers to network.h.
diego
parents:
27464
diff
changeset
|
26 #include <sys/socket.h> |
c0b233cd30ca
Revert moving closesocket definition and network headers to network.h.
diego
parents:
27464
diff
changeset
|
27 #include <arpa/inet.h> |
c0b233cd30ca
Revert moving closesocket definition and network headers to network.h.
diego
parents:
27464
diff
changeset
|
28 #else |
c0b233cd30ca
Revert moving closesocket definition and network headers to network.h.
diego
parents:
27464
diff
changeset
|
29 #include <winsock2.h> |
c0b233cd30ca
Revert moving closesocket definition and network headers to network.h.
diego
parents:
27464
diff
changeset
|
30 #include <ws2tcpip.h> |
c0b233cd30ca
Revert moving closesocket definition and network headers to network.h.
diego
parents:
27464
diff
changeset
|
31 #endif |
c0b233cd30ca
Revert moving closesocket definition and network headers to network.h.
diego
parents:
27464
diff
changeset
|
32 |
27473
ae5da477539e
Move '#define closesocket close' preprocessor directive to a common place
diego
parents:
27472
diff
changeset
|
33 #include "network.h" |
26751 | 34 #include "stream.h" |
19542 | 35 #include "tcp.h" |
29351 | 36 #include "libavutil/avstring.h" |
19542 | 37 |
38 /* IPv6 options */ | |
39 int network_prefer_ipv4 = 0; | |
40 | |
41 // Converts an address family constant to a string | |
42 | |
24841
44540930bf94
Make functions static if they aren't referenced externally.
zuxy
parents:
24559
diff
changeset
|
43 static const char *af2String(int af) { |
19542 | 44 switch (af) { |
45 case AF_INET: return "AF_INET"; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
46 |
19542 | 47 #ifdef HAVE_AF_INET6 |
48 case AF_INET6: return "AF_INET6"; | |
49 #endif | |
50 default: return "Unknown address family!"; | |
51 } | |
52 } | |
53 | |
54 | |
55 | |
56 // Connect to a server using a TCP connection, with specified address family | |
57 // return -2 for fatal error, like unable to resolve name, connection timeout... | |
58 // return -1 is unable to connect to a particular port | |
59 | |
24841
44540930bf94
Make functions static if they aren't referenced externally.
zuxy
parents:
24559
diff
changeset
|
60 static int |
19542 | 61 connect2Server_with_af(char *host, int port, int af,int verb) { |
62 int socket_server_fd; | |
63 int err; | |
64 socklen_t err_len; | |
65 int ret,count = 0; | |
66 fd_set set; | |
67 struct timeval tv; | |
68 union { | |
69 struct sockaddr_in four; | |
70 #ifdef HAVE_AF_INET6 | |
71 struct sockaddr_in6 six; | |
72 #endif | |
73 } server_address; | |
74 size_t server_address_size; | |
75 void *our_s_addr; // Pointer to sin_addr or sin6_addr | |
76 struct hostent *hp=NULL; | |
77 char buf[255]; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
78 |
28402 | 79 #if HAVE_WINSOCK2_H |
28162 | 80 unsigned long val; |
22379
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
81 int to; |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
82 #else |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
83 struct timeval to; |
19542 | 84 #endif |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
85 |
19542 | 86 socket_server_fd = socket(af, SOCK_STREAM, 0); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
87 |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
88 |
19542 | 89 if( socket_server_fd==-1 ) { |
90 // 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
|
91 return TCP_ERROR_FATAL; |
19542 | 92 } |
93 | |
22114 | 94 #if defined(SO_RCVTIMEO) && defined(SO_SNDTIMEO) |
28402 | 95 #if HAVE_WINSOCK2_H |
22379
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
96 /* timeout in milliseconds */ |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
97 to = 10 * 1000; |
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 to.tv_sec = 10; |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
100 to.tv_usec = 0; |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
101 #endif |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
102 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
|
103 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
|
104 #endif |
50c9dc00154d
Add timeout to tcp connections, avoid hanging forever.
rtogni
parents:
19543
diff
changeset
|
105 |
19542 | 106 switch (af) { |
107 case AF_INET: our_s_addr = (void *) &server_address.four.sin_addr; break; | |
108 #ifdef HAVE_AF_INET6 | |
109 case AF_INET6: our_s_addr = (void *) &server_address.six.sin6_addr; break; | |
110 #endif | |
111 default: | |
112 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
|
113 return TCP_ERROR_FATAL; |
19542 | 114 } |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
115 |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
116 |
19542 | 117 memset(&server_address, 0, sizeof(server_address)); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
118 |
28404
613f075b4ef0
Restructure network tests: Always check for both inet_aton and inet_pton.
diego
parents:
28402
diff
changeset
|
119 #if HAVE_INET_PTON |
613f075b4ef0
Restructure network tests: Always check for both inet_aton and inet_pton.
diego
parents:
28402
diff
changeset
|
120 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
|
121 #elif HAVE_INET_ATON |
19542 | 122 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
|
123 #elif HAVE_WINSOCK2_H |
19542 | 124 if ( inet_addr(host)==INADDR_NONE ) |
125 #endif | |
126 { | |
127 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
|
128 |
19542 | 129 #ifdef HAVE_GETHOSTBYNAME2 |
130 hp=(struct hostent*)gethostbyname2( host, af ); | |
131 #else | |
132 hp=(struct hostent*)gethostbyname( host ); | |
133 #endif | |
134 if( hp==NULL ) { | |
135 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
|
136 return TCP_ERROR_FATAL; |
19542 | 137 } |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
138 |
19542 | 139 memcpy( our_s_addr, (void*)hp->h_addr_list[0], hp->h_length ); |
140 } | |
28402 | 141 #if HAVE_WINSOCK2_H |
19542 | 142 else { |
143 unsigned long addr = inet_addr(host); | |
144 memcpy( our_s_addr, (void*)&addr, sizeof(addr) ); | |
145 } | |
146 #endif | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
147 |
19542 | 148 switch (af) { |
149 case AF_INET: | |
150 server_address.four.sin_family=af; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
151 server_address.four.sin_port=htons(port); |
19542 | 152 server_address_size = sizeof(server_address.four); |
153 break; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
154 #ifdef HAVE_AF_INET6 |
19542 | 155 case AF_INET6: |
156 server_address.six.sin6_family=af; | |
157 server_address.six.sin6_port=htons(port); | |
158 server_address_size = sizeof(server_address.six); | |
159 break; | |
160 #endif | |
161 default: | |
162 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
|
163 return TCP_ERROR_FATAL; |
19542 | 164 } |
165 | |
28400
9202b9245819
HAVE_ATON --> HAVE_INET_ATON to match FFmpeg and give it a 0/1 value.
diego
parents:
28162
diff
changeset
|
166 #if HAVE_INET_ATON || defined(HAVE_WINSOCK2_H) |
29351 | 167 av_strlcpy( buf, inet_ntoa( *((struct in_addr*)our_s_addr) ), 255); |
19542 | 168 #else |
169 inet_ntop(af, our_s_addr, buf, 255); | |
170 #endif | |
171 if(verb) mp_msg(MSGT_NETWORK,MSGL_STATUS,MSGTR_MPDEMUX_NW_ConnectingToServer, host, buf , port ); | |
172 | |
173 // Turn the socket as non blocking so we can timeout on the connection | |
28402 | 174 #if !HAVE_WINSOCK2_H |
19542 | 175 fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) | O_NONBLOCK ); |
176 #else | |
177 val = 1; | |
178 ioctlsocket( socket_server_fd, FIONBIO, &val ); | |
179 #endif | |
180 if( connect( socket_server_fd, (struct sockaddr*)&server_address, server_address_size )==-1 ) { | |
28402 | 181 #if !HAVE_WINSOCK2_H |
19542 | 182 if( errno!=EINPROGRESS ) { |
183 #else | |
184 if( (WSAGetLastError() != WSAEINPROGRESS) && (WSAGetLastError() != WSAEWOULDBLOCK) ) { | |
185 #endif | |
186 if(verb) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_CantConnect2Server, af2String(af)); | |
187 closesocket(socket_server_fd); | |
19543
e053647fbeec
Cosmetics: recommit patch changing return values to defines
reimar
parents:
19542
diff
changeset
|
188 return TCP_ERROR_PORT; |
19542 | 189 } |
190 } | |
191 tv.tv_sec = 0; | |
192 tv.tv_usec = 500000; | |
193 FD_ZERO( &set ); | |
194 FD_SET( socket_server_fd, &set ); | |
24558 | 195 // When the connection will be made, we will have a writeable fd |
19542 | 196 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
|
197 if(count > 30 || stream_check_interrupt(500)) { |
19542 | 198 if(count > 30) |
199 mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_ConnTimeout); | |
200 else | |
24558 | 201 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
|
202 return TCP_ERROR_TIMEOUT; |
19542 | 203 } |
204 count++; | |
205 FD_ZERO( &set ); | |
206 FD_SET( socket_server_fd, &set ); | |
207 tv.tv_sec = 0; | |
208 tv.tv_usec = 500000; | |
209 } | |
24559
7b6a3948f5f2
(Re)move idiotic checks, ret can't be < 0 or > 0 if the loop condition
reimar
parents:
24558
diff
changeset
|
210 if (ret < 0) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_SelectFailed); |
19542 | 211 |
212 // Turn back the socket as blocking | |
28402 | 213 #if !HAVE_WINSOCK2_H |
19542 | 214 fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) & ~O_NONBLOCK ); |
215 #else | |
216 val = 0; | |
217 ioctlsocket( socket_server_fd, FIONBIO, &val ); | |
218 #endif | |
24558 | 219 // Check if there were any errors |
19542 | 220 err_len = sizeof(int); |
221 ret = getsockopt(socket_server_fd,SOL_SOCKET,SO_ERROR,&err,&err_len); | |
222 if(ret < 0) { | |
223 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
|
224 return TCP_ERROR_FATAL; |
19542 | 225 } |
226 if(err > 0) { | |
227 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
|
228 return TCP_ERROR_PORT; |
19542 | 229 } |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
230 |
19542 | 231 return socket_server_fd; |
232 } | |
233 | |
234 // Connect to a server using a TCP connection | |
235 // return -2 for fatal error, like unable to resolve name, connection timeout... | |
236 // return -1 is unable to connect to a particular port | |
237 | |
238 | |
239 int | |
240 connect2Server(char *host, int port, int verb) { | |
241 #ifdef HAVE_AF_INET6 | |
242 int r; | |
19543
e053647fbeec
Cosmetics: recommit patch changing return values to defines
reimar
parents:
19542
diff
changeset
|
243 int s = TCP_ERROR_FATAL; |
19542 | 244 |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
245 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
|
246 if (r >= 0) return r; |
19542 | 247 |
248 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
|
249 if (s == TCP_ERROR_FATAL) return r; |
19542 | 250 return s; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
251 #else |
19542 | 252 return connect2Server_with_af(host, port, AF_INET,verb); |
253 #endif | |
254 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28404
diff
changeset
|
255 |
19542 | 256 } |