Mercurial > mplayer.hg
annotate stream/tcp.c @ 27464:be85aae103f2
Move duplicated '#define closesocket close' into network.h along with
network-related #include #ifdeffery.
author | diego |
---|---|
date | Fri, 29 Aug 2008 22:55:39 +0000 |
parents | 5a30f5bc23a0 |
children | c0b233cd30ca |
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" | |
27464
be85aae103f2
Move duplicated '#define closesocket close' into network.h along with
diego
parents:
27461
diff
changeset
|
22 #include "network.h" |
26751 | 23 #include "stream.h" |
19542 | 24 #include "tcp.h" |
25 | |
26 /* IPv6 options */ | |
27 int network_prefer_ipv4 = 0; | |
28 | |
29 // Converts an address family constant to a string | |
30 | |
24841
44540930bf94
Make functions static if they aren't referenced externally.
zuxy
parents:
24559
diff
changeset
|
31 static const char *af2String(int af) { |
19542 | 32 switch (af) { |
33 case AF_INET: return "AF_INET"; | |
34 | |
35 #ifdef HAVE_AF_INET6 | |
36 case AF_INET6: return "AF_INET6"; | |
37 #endif | |
38 default: return "Unknown address family!"; | |
39 } | |
40 } | |
41 | |
42 | |
43 | |
44 // Connect to a server using a TCP connection, with specified address family | |
45 // return -2 for fatal error, like unable to resolve name, connection timeout... | |
46 // return -1 is unable to connect to a particular port | |
47 | |
24841
44540930bf94
Make functions static if they aren't referenced externally.
zuxy
parents:
24559
diff
changeset
|
48 static int |
19542 | 49 connect2Server_with_af(char *host, int port, int af,int verb) { |
50 int socket_server_fd; | |
51 int err; | |
52 socklen_t err_len; | |
53 int ret,count = 0; | |
54 fd_set set; | |
55 struct timeval tv; | |
56 union { | |
57 struct sockaddr_in four; | |
58 #ifdef HAVE_AF_INET6 | |
59 struct sockaddr_in6 six; | |
60 #endif | |
61 } server_address; | |
62 size_t server_address_size; | |
63 void *our_s_addr; // Pointer to sin_addr or sin6_addr | |
64 struct hostent *hp=NULL; | |
65 char buf[255]; | |
66 | |
27461
5a30f5bc23a0
Rename HAVE_WINSOCK preprocessor condition to HAVE_WINSOCK_H.
diego
parents:
27359
diff
changeset
|
67 #ifdef HAVE_WINSOCK2_H |
19542 | 68 u_long val; |
22379
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
69 int to; |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
70 #else |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
71 struct timeval to; |
19542 | 72 #endif |
73 | |
74 socket_server_fd = socket(af, SOCK_STREAM, 0); | |
75 | |
76 | |
77 if( socket_server_fd==-1 ) { | |
78 // 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
|
79 return TCP_ERROR_FATAL; |
19542 | 80 } |
81 | |
22114 | 82 #if defined(SO_RCVTIMEO) && defined(SO_SNDTIMEO) |
27461
5a30f5bc23a0
Rename HAVE_WINSOCK preprocessor condition to HAVE_WINSOCK_H.
diego
parents:
27359
diff
changeset
|
83 #ifdef HAVE_WINSOCK2_H |
22379
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
84 /* timeout in milliseconds */ |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
85 to = 10 * 1000; |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
86 #else |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
87 to.tv_sec = 10; |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
88 to.tv_usec = 0; |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
89 #endif |
6b245d6e56a9
winsocks expects an int in milliseconds instead of struct timeval to set
ivo
parents:
22142
diff
changeset
|
90 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
|
91 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
|
92 #endif |
50c9dc00154d
Add timeout to tcp connections, avoid hanging forever.
rtogni
parents:
19543
diff
changeset
|
93 |
19542 | 94 switch (af) { |
95 case AF_INET: our_s_addr = (void *) &server_address.four.sin_addr; break; | |
96 #ifdef HAVE_AF_INET6 | |
97 case AF_INET6: our_s_addr = (void *) &server_address.six.sin6_addr; break; | |
98 #endif | |
99 default: | |
100 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
|
101 return TCP_ERROR_FATAL; |
19542 | 102 } |
103 | |
104 | |
105 memset(&server_address, 0, sizeof(server_address)); | |
106 | |
27461
5a30f5bc23a0
Rename HAVE_WINSOCK preprocessor condition to HAVE_WINSOCK_H.
diego
parents:
27359
diff
changeset
|
107 #ifndef HAVE_WINSOCK2_H |
27359
d788e177a35e
Rename some preprocessor directives from CONFIG_* to HAVE_* where appropriate;
diego
parents:
27341
diff
changeset
|
108 #ifdef HAVE_ATON |
19542 | 109 if (inet_aton(host, our_s_addr)!=1) |
110 #else | |
111 if (inet_pton(af, host, our_s_addr)!=1) | |
112 #endif | |
113 #else | |
114 if ( inet_addr(host)==INADDR_NONE ) | |
115 #endif | |
116 { | |
117 if(verb) mp_msg(MSGT_NETWORK,MSGL_STATUS,MSGTR_MPDEMUX_NW_ResolvingHostForAF, host, af2String(af)); | |
118 | |
119 #ifdef HAVE_GETHOSTBYNAME2 | |
120 hp=(struct hostent*)gethostbyname2( host, af ); | |
121 #else | |
122 hp=(struct hostent*)gethostbyname( host ); | |
123 #endif | |
124 if( hp==NULL ) { | |
125 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
|
126 return TCP_ERROR_FATAL; |
19542 | 127 } |
128 | |
129 memcpy( our_s_addr, (void*)hp->h_addr_list[0], hp->h_length ); | |
130 } | |
27461
5a30f5bc23a0
Rename HAVE_WINSOCK preprocessor condition to HAVE_WINSOCK_H.
diego
parents:
27359
diff
changeset
|
131 #ifdef HAVE_WINSOCK2_H |
19542 | 132 else { |
133 unsigned long addr = inet_addr(host); | |
134 memcpy( our_s_addr, (void*)&addr, sizeof(addr) ); | |
135 } | |
136 #endif | |
137 | |
138 switch (af) { | |
139 case AF_INET: | |
140 server_address.four.sin_family=af; | |
141 server_address.four.sin_port=htons(port); | |
142 server_address_size = sizeof(server_address.four); | |
143 break; | |
144 #ifdef HAVE_AF_INET6 | |
145 case AF_INET6: | |
146 server_address.six.sin6_family=af; | |
147 server_address.six.sin6_port=htons(port); | |
148 server_address_size = sizeof(server_address.six); | |
149 break; | |
150 #endif | |
151 default: | |
152 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
|
153 return TCP_ERROR_FATAL; |
19542 | 154 } |
155 | |
27461
5a30f5bc23a0
Rename HAVE_WINSOCK preprocessor condition to HAVE_WINSOCK_H.
diego
parents:
27359
diff
changeset
|
156 #if defined(HAVE_ATON) || defined(HAVE_WINSOCK2_H) |
19542 | 157 strncpy( buf, inet_ntoa( *((struct in_addr*)our_s_addr) ), 255); |
158 #else | |
159 inet_ntop(af, our_s_addr, buf, 255); | |
160 #endif | |
161 if(verb) mp_msg(MSGT_NETWORK,MSGL_STATUS,MSGTR_MPDEMUX_NW_ConnectingToServer, host, buf , port ); | |
162 | |
163 // Turn the socket as non blocking so we can timeout on the connection | |
27461
5a30f5bc23a0
Rename HAVE_WINSOCK preprocessor condition to HAVE_WINSOCK_H.
diego
parents:
27359
diff
changeset
|
164 #ifndef HAVE_WINSOCK2_H |
19542 | 165 fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) | O_NONBLOCK ); |
166 #else | |
167 val = 1; | |
168 ioctlsocket( socket_server_fd, FIONBIO, &val ); | |
169 #endif | |
170 if( connect( socket_server_fd, (struct sockaddr*)&server_address, server_address_size )==-1 ) { | |
27461
5a30f5bc23a0
Rename HAVE_WINSOCK preprocessor condition to HAVE_WINSOCK_H.
diego
parents:
27359
diff
changeset
|
171 #ifndef HAVE_WINSOCK2_H |
19542 | 172 if( errno!=EINPROGRESS ) { |
173 #else | |
174 if( (WSAGetLastError() != WSAEINPROGRESS) && (WSAGetLastError() != WSAEWOULDBLOCK) ) { | |
175 #endif | |
176 if(verb) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_CantConnect2Server, af2String(af)); | |
177 closesocket(socket_server_fd); | |
19543
e053647fbeec
Cosmetics: recommit patch changing return values to defines
reimar
parents:
19542
diff
changeset
|
178 return TCP_ERROR_PORT; |
19542 | 179 } |
180 } | |
181 tv.tv_sec = 0; | |
182 tv.tv_usec = 500000; | |
183 FD_ZERO( &set ); | |
184 FD_SET( socket_server_fd, &set ); | |
24558 | 185 // When the connection will be made, we will have a writeable fd |
19542 | 186 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
|
187 if(count > 30 || stream_check_interrupt(500)) { |
19542 | 188 if(count > 30) |
189 mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_ConnTimeout); | |
190 else | |
24558 | 191 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
|
192 return TCP_ERROR_TIMEOUT; |
19542 | 193 } |
194 count++; | |
195 FD_ZERO( &set ); | |
196 FD_SET( socket_server_fd, &set ); | |
197 tv.tv_sec = 0; | |
198 tv.tv_usec = 500000; | |
199 } | |
24559
7b6a3948f5f2
(Re)move idiotic checks, ret can't be < 0 or > 0 if the loop condition
reimar
parents:
24558
diff
changeset
|
200 if (ret < 0) mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_NW_SelectFailed); |
19542 | 201 |
202 // Turn back the socket as blocking | |
27461
5a30f5bc23a0
Rename HAVE_WINSOCK preprocessor condition to HAVE_WINSOCK_H.
diego
parents:
27359
diff
changeset
|
203 #ifndef HAVE_WINSOCK2_H |
19542 | 204 fcntl( socket_server_fd, F_SETFL, fcntl(socket_server_fd, F_GETFL) & ~O_NONBLOCK ); |
205 #else | |
206 val = 0; | |
207 ioctlsocket( socket_server_fd, FIONBIO, &val ); | |
208 #endif | |
24558 | 209 // Check if there were any errors |
19542 | 210 err_len = sizeof(int); |
211 ret = getsockopt(socket_server_fd,SOL_SOCKET,SO_ERROR,&err,&err_len); | |
212 if(ret < 0) { | |
213 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
|
214 return TCP_ERROR_FATAL; |
19542 | 215 } |
216 if(err > 0) { | |
217 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
|
218 return TCP_ERROR_PORT; |
19542 | 219 } |
220 | |
221 return socket_server_fd; | |
222 } | |
223 | |
224 // Connect to a server using a TCP connection | |
225 // return -2 for fatal error, like unable to resolve name, connection timeout... | |
226 // return -1 is unable to connect to a particular port | |
227 | |
228 | |
229 int | |
230 connect2Server(char *host, int port, int verb) { | |
231 #ifdef HAVE_AF_INET6 | |
232 int r; | |
19543
e053647fbeec
Cosmetics: recommit patch changing return values to defines
reimar
parents:
19542
diff
changeset
|
233 int s = TCP_ERROR_FATAL; |
19542 | 234 |
235 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
|
236 if (r >= 0) return r; |
19542 | 237 |
238 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
|
239 if (s == TCP_ERROR_FATAL) return r; |
19542 | 240 return s; |
241 #else | |
242 return connect2Server_with_af(host, port, AF_INET,verb); | |
243 #endif | |
244 | |
245 | |
246 } |