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