]> sjero.net Git - wget/blob - src/connect.c
d95ad74f44c72f3efe1d91343b7af0c7876934fe
[wget] / src / connect.c
1 /* Establishing and handling network connections.
2    Copyright (C) 1995, 1996, 1997, 2001, 2002 Free Software Foundation, Inc.
3
4 This file is part of GNU Wget.
5
6 GNU Wget is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 GNU Wget is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Wget; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 #include <config.h>
21
22 #include <stdio.h>
23 #include <sys/types.h>
24 #ifdef HAVE_UNISTD_H
25 # include <unistd.h>
26 #endif
27 #include <assert.h>
28
29 #ifdef WINDOWS
30 # include <winsock.h>
31 #else
32 # include <sys/socket.h>
33 # include <netdb.h>
34 # include <netinet/in.h>
35 #ifndef __BEOS__
36 # include <arpa/inet.h>
37 #endif
38 #endif /* WINDOWS */
39
40 #include <errno.h>
41 #ifdef HAVE_STRING_H
42 # include <string.h>
43 #else
44 # include <strings.h>
45 #endif /* HAVE_STRING_H */
46 #ifdef HAVE_SYS_SELECT_H
47 # include <sys/select.h>
48 #endif /* HAVE_SYS_SELECT_H */
49
50 /* To implement connect with timeout, we need signal and either
51    sigsetjmp or sigblock. */
52 #undef UNIX_CONNECT_TIMEOUT
53 #ifdef HAVE_SIGNAL_H
54 # include <signal.h>
55 #endif
56 #ifdef HAVE_SETJMP_H
57 # include <setjmp.h>
58 #endif
59 /* If sigsetjmp is a macro, configure won't pick it up. */
60 #ifdef sigsetjmp
61 # define HAVE_SIGSETJMP
62 #endif
63 #ifdef HAVE_SIGNAL
64 # ifdef HAVE_SIGSETJMP
65 #  define UNIX_CONNECT_TIMEOUT
66 # endif
67 # ifdef HAVE_SIGBLOCK
68 #  define UNIX_CONNECT_TIMEOUT
69 # endif
70 #endif
71
72 #include "wget.h"
73 #include "host.h"
74 #include "connect.h"
75
76 #ifndef errno
77 extern int errno;
78 #endif
79
80 /* Variables shared by bindport and acceptport: */
81 static int msock = -1;
82 static struct sockaddr *addr;
83
84 static ip_address bind_address;
85 static int bind_address_resolved;
86
87 static void
88 resolve_bind_address (void)
89 {
90   struct address_list *al;
91
92   if (bind_address_resolved || opt.bind_address == NULL)
93     /* Nothing to do. */
94     return;
95
96   al = lookup_host (opt.bind_address, 1);
97   if (!al)
98     {
99       logprintf (LOG_NOTQUIET,
100                  _("Unable to convert `%s' to a bind address.  Reverting to ANY.\n"),
101                  opt.bind_address);
102       return;
103     }
104
105   address_list_copy_one (al, 0, &bind_address);
106   address_list_release (al);
107   bind_address_resolved = 1;
108 }
109 \f
110 #ifndef UNIX_CONNECT_TIMEOUT
111 static int
112 connect_with_timeout (int fd, const struct sockaddr *addr, int addrlen,
113                       int timeout)
114 {
115   return connect (fd, addr, addrlen);
116 }
117 #else  /* UNIX_CONNECT_TIMEOUT */
118 /* Implementation of connect with timeout. */
119
120 #ifdef HAVE_SIGSETJMP
121 #define SETJMP(env) sigsetjmp (env, 1)
122
123 static sigjmp_buf abort_connect_env;
124
125 RETSIGTYPE
126 abort_connect (int ignored)
127 {
128   siglongjmp (abort_connect_env, -1);
129 }
130 #else  /* not HAVE_SIGSETJMP */
131 #define SETJMP(env) setjmp (env)
132
133 static jmp_buf abort_connect_env;
134
135 RETSIGTYPE
136 abort_connect (int ignored)
137 {
138   /* We don't have siglongjmp to preserve the set of blocked signals;
139      if we longjumped out of the handler at this point, SIGALRM would
140      remain blocked.  We must unblock it manually. */
141   int mask = siggetmask ();
142   mask &= ~sigmask(SIGALRM);
143   sigsetmask (mask);
144
145   /* Now it's safe to longjump. */
146   longjmp (abort_connect_env, -1);
147 }
148 #endif /* not HAVE_SIGSETJMP */
149
150 /* Like connect, but specifies a timeout.  If connecting takes longer
151    than TIMEOUT seconds, -1 is returned and errno is set to
152    ETIMEDOUT.  */
153
154 static int
155 connect_with_timeout (int fd, const struct sockaddr *addr, int addrlen,
156                       int timeout)
157 {
158   int result, saved_errno;
159
160   if (timeout == 0)
161     return connect (fd, addr, addrlen);
162
163   signal (SIGALRM, abort_connect);
164   if (SETJMP (abort_connect_env) != 0)
165     {
166       /* Longjumped out of connect with a timeout. */
167       signal (SIGALRM, SIG_DFL);
168       errno = ETIMEDOUT;
169       return -1;
170     }
171
172   alarm (timeout);
173   result = connect (fd, addr, addrlen);
174
175   saved_errno = errno;          /* In case alarm() or signal() change
176                                    errno. */
177   alarm (0);
178   signal (SIGALRM, SIG_DFL);
179   errno = saved_errno;
180
181   return result;
182 }
183 #endif /* UNIX_CONNECT_TIMEOUT */
184 \f
185 /* A kludge, but still better than passing the host name all the way
186    to connect_to_one.  */
187 static const char *connection_host_name;
188
189 void
190 set_connection_host_name (const char *host)
191 {
192   if (host)
193     assert (connection_host_name == NULL);
194   else
195     assert (connection_host_name != NULL);
196
197   connection_host_name = host;
198 }
199
200 /* Connect to a remote host whose address has been resolved. */
201 int
202 connect_to_one (ip_address *addr, unsigned short port, int silent)
203 {
204   wget_sockaddr sa;
205   int sock, save_errno;
206
207   /* Set port and protocol */
208   wget_sockaddr_set_address (&sa, ip_default_family, port, addr);
209
210   if (!silent)
211     {
212       char *pretty_addr = pretty_print_address (addr);
213       if (connection_host_name
214           && 0 != strcmp (connection_host_name, pretty_addr))
215         logprintf (LOG_VERBOSE, _("Connecting to %s[%s]:%hu... "),
216                    connection_host_name, pretty_addr, port);
217       else
218         logprintf (LOG_VERBOSE, _("Connecting to %s:%hu... "),
219                    pretty_addr, port);
220     }
221
222   /* Make an internet socket, stream type.  */
223   sock = socket (ip_default_family, SOCK_STREAM, 0);
224   if (sock < 0)
225     goto out;
226
227   resolve_bind_address ();
228   if (bind_address_resolved)
229     {
230       /* Bind the client side to the requested address. */
231       wget_sockaddr bsa;
232       wget_sockaddr_set_address (&bsa, ip_default_family, 0, &bind_address);
233       if (bind (sock, &bsa.sa, sockaddr_len ()))
234         {
235           close (sock);
236           sock = -1;
237           goto out;
238         }
239     }
240
241   /* Connect the socket to the remote host.  */
242   if (connect_with_timeout (sock, &sa.sa, sockaddr_len (), opt.timeout) < 0)
243     {
244       close (sock);
245       sock = -1;
246       goto out;
247     }
248
249  out:
250   if (sock >= 0)
251     {
252       /* Success. */
253       if (!silent)
254         logprintf (LOG_VERBOSE, _("connected.\n"));
255       DEBUGP (("Created socket %d.\n", sock));
256     }
257   else
258     {
259       save_errno = errno;
260       if (!silent)
261         logprintf (LOG_VERBOSE, "failed: %s.\n", strerror (errno));
262       errno = save_errno;
263     }
264
265   return sock;
266 }
267
268 /* Connect to a remote host whose address has been resolved. */
269 int
270 connect_to_many (struct address_list *al, unsigned short port, int silent)
271 {
272   int i, start, end;
273
274   address_list_get_bounds (al, &start, &end);
275   for (i = start; i < end; i++)
276     {
277       ip_address addr;
278       int sock;
279       address_list_copy_one (al, i, &addr);
280
281       sock = connect_to_one (&addr, port, silent);
282       if (sock >= 0)
283         /* Success. */
284         return sock;
285
286       address_list_set_faulty (al, i);
287
288       /* The attempt to connect has failed.  Continue with the loop
289          and try next address. */
290     }
291
292   return -1;
293 }
294
295 int
296 test_socket_open (int sock)
297 {
298 #ifdef HAVE_SELECT
299   fd_set check_set;
300   struct timeval to;
301
302   /* Check if we still have a valid (non-EOF) connection.  From Andrew
303    * Maholski's code in the Unix Socket FAQ.  */
304
305   FD_ZERO (&check_set);
306   FD_SET (sock, &check_set);
307
308   /* Wait one microsecond */
309   to.tv_sec = 0;
310   to.tv_usec = 1;
311
312   /* If we get a timeout, then that means still connected */
313   if (select (sock + 1, &check_set, NULL, NULL, &to) == 0)
314     {
315       /* Connection is valid (not EOF), so continue */
316       return 1;
317     }
318   else
319     return 0;
320 #else
321   /* Without select, it's hard to know for sure. */
322   return 1;
323 #endif
324 }
325
326 /* Bind the local port PORT.  This does all the necessary work, which
327    is creating a socket, setting SO_REUSEADDR option on it, then
328    calling bind() and listen().  If *PORT is 0, a random port is
329    chosen by the system, and its value is stored to *PORT.  The
330    internal variable MPORT is set to the value of the ensuing master
331    socket.  Call acceptport() to block for and accept a connection.  */
332 uerr_t
333 bindport (unsigned short *port, int family)
334 {
335   int optval = 1;
336   wget_sockaddr srv;
337   memset (&srv, 0, sizeof (wget_sockaddr));
338
339   msock = -1;
340
341   if ((msock = socket (family, SOCK_STREAM, 0)) < 0)
342     return CONSOCKERR;
343   if (setsockopt (msock, SOL_SOCKET, SO_REUSEADDR,
344                   (char *)&optval, sizeof (optval)) < 0)
345     return CONSOCKERR;
346
347   resolve_bind_address ();
348   wget_sockaddr_set_address (&srv, ip_default_family, htons (*port),
349                              bind_address_resolved ? &bind_address : NULL);
350   if (bind (msock, &srv.sa, sockaddr_len ()) < 0)
351     {
352       CLOSE (msock);
353       msock = -1;
354       return BINDERR;
355     }
356   DEBUGP (("Master socket fd %d bound.\n", msock));
357   if (!*port)
358     {
359       /* #### addrlen should be a 32-bit type, which int is not
360          guaranteed to be.  Oh, and don't try to make it a size_t,
361          because that can be 64-bit.  */
362       int sa_len = sockaddr_len ();
363       if (getsockname (msock, &srv.sa, &sa_len) < 0)
364         {
365           CLOSE (msock);
366           msock = -1;
367           return CONPORTERR;
368         }
369       *port = wget_sockaddr_get_port (&srv);
370       DEBUGP (("using port %i.\n", *port));
371     }
372   if (listen (msock, 1) < 0)
373     {
374       CLOSE (msock);
375       msock = -1;
376       return LISTENERR;
377     }
378   return BINDOK;
379 }
380
381 #ifdef HAVE_SELECT
382 /* Wait for file descriptor FD to be readable, MAXTIME being the
383    timeout in seconds.  If WRITEP is non-zero, checks for FD being
384    writable instead.
385
386    Returns 1 if FD is accessible, 0 for timeout and -1 for error in
387    select().  */
388 int
389 select_fd (int fd, int maxtime, int writep)
390 {
391   fd_set fds, exceptfds;
392   struct timeval timeout;
393
394   FD_ZERO (&fds);
395   FD_SET (fd, &fds);
396   FD_ZERO (&exceptfds);
397   FD_SET (fd, &exceptfds);
398   timeout.tv_sec = maxtime;
399   timeout.tv_usec = 0;
400   /* HPUX reportedly warns here.  What is the correct incantation?  */
401   return select (fd + 1, writep ? NULL : &fds, writep ? &fds : NULL,
402                  &exceptfds, &timeout);
403 }
404 #endif /* HAVE_SELECT */
405
406 /* Call accept() on MSOCK and store the result to *SOCK.  This assumes
407    that bindport() has been used to initialize MSOCK to a correct
408    value.  It blocks the caller until a connection is established.  If
409    no connection is established for OPT.TIMEOUT seconds, the function
410    exits with an error status.  */
411 uerr_t
412 acceptport (int *sock)
413 {
414   int addrlen = sockaddr_len ();
415
416 #ifdef HAVE_SELECT
417   if (select_fd (msock, opt.timeout, 0) <= 0)
418     return ACCEPTERR;
419 #endif
420   if ((*sock = accept (msock, addr, &addrlen)) < 0)
421     return ACCEPTERR;
422   DEBUGP (("Created socket fd %d.\n", *sock));
423   return ACCEPTOK;
424 }
425
426 /* Close SOCK, as well as the most recently remembered MSOCK, created
427    via bindport().  If SOCK is -1, close MSOCK only.  */
428 void
429 closeport (int sock)
430 {
431   /*shutdown (sock, 2);*/
432   if (sock != -1)
433     CLOSE (sock);
434   if (msock != -1)
435     CLOSE (msock);
436   msock = -1;
437 }
438
439 /* Return the local IP address associated with the connection on FD.  */
440
441 int
442 conaddr (int fd, ip_address *ip)
443 {
444   wget_sockaddr mysrv;
445
446   /* see bindport() for discussion of using `int' here. */
447   int addrlen = sizeof (mysrv); 
448
449   if (getsockname (fd, &mysrv.sa, (int *)&addrlen) < 0)
450     return 0;
451
452   switch (mysrv.sa.sa_family)
453     {
454 #ifdef INET6
455     case AF_INET6:
456       memcpy (ip, &mysrv.sin6.sin6_addr, 16);
457       return 1;
458 #endif
459     case AF_INET:
460       map_ipv4_to_ip ((ip4_address *)&mysrv.sin.sin_addr, ip);
461       return 1;
462     default:
463       abort ();
464     }
465   return 0;
466 }
467
468 /* Read at most LEN bytes from FD, storing them to BUF.  This is
469    virtually the same as read(), but takes care of EINTR braindamage
470    and uses select() to timeout the stale connections (a connection is
471    stale if more than OPT.TIMEOUT time is spent in select() or
472    read()).  */
473 int
474 iread (int fd, char *buf, int len)
475 {
476   int res;
477
478   do
479     {
480 #ifdef HAVE_SELECT
481       if (opt.timeout)
482         {
483           do
484             {
485               res = select_fd (fd, opt.timeout, 0);
486             }
487           while (res == -1 && errno == EINTR);
488           if (res <= 0)
489             {
490               /* Set errno to ETIMEDOUT on timeout.  */
491               if (res == 0)
492                 /* #### Potentially evil!  */
493                 errno = ETIMEDOUT;
494               return -1;
495             }
496         }
497 #endif
498       res = READ (fd, buf, len);
499     }
500   while (res == -1 && errno == EINTR);
501
502   return res;
503 }
504
505 /* Write LEN bytes from BUF to FD.  This is similar to iread(), but
506    doesn't bother with select().  Unlike iread(), it makes sure that
507    all of BUF is actually written to FD, so callers needn't bother
508    with checking that the return value equals to LEN.  Instead, you
509    should simply check for -1.  */
510 int
511 iwrite (int fd, char *buf, int len)
512 {
513   int res = 0;
514
515   /* `write' may write less than LEN bytes, thus the outward loop
516      keeps trying it until all was written, or an error occurred.  The
517      inner loop is reserved for the usual EINTR f*kage, and the
518      innermost loop deals with the same during select().  */
519   while (len > 0)
520     {
521       do
522         {
523 #ifdef HAVE_SELECT
524           if (opt.timeout)
525             {
526               do
527                 {
528                   res = select_fd (fd, opt.timeout, 1);
529                 }
530               while (res == -1 && errno == EINTR);
531               if (res <= 0)
532                 {
533                   /* Set errno to ETIMEDOUT on timeout.  */
534                   if (res == 0)
535                     /* #### Potentially evil!  */
536                     errno = ETIMEDOUT;
537                   return -1;
538                 }
539             }
540 #endif
541           res = WRITE (fd, buf, len);
542         }
543       while (res == -1 && errno == EINTR);
544       if (res <= 0)
545         break;
546       buf += res;
547       len -= res;
548     }
549   return res;
550 }