]> sjero.net Git - wget/blob - src/connect.c
[svn] Generalized the third argument to select_fd.
[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 In addition, as a special exception, the Free Software Foundation
21 gives permission to link the code of its release of Wget with the
22 OpenSSL project's "OpenSSL" library (or with modified versions of it
23 that use the same license as the "OpenSSL" library), and distribute
24 the linked executables.  You must obey the GNU General Public License
25 in all respects for all of the code used other than "OpenSSL".  If you
26 modify this file, you may extend this exception to your version of the
27 file, but you are not obligated to do so.  If you do not wish to do
28 so, delete this exception statement from your version.  */
29
30 #include <config.h>
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <sys/types.h>
35 #ifdef HAVE_UNISTD_H
36 # include <unistd.h>
37 #endif
38 #include <assert.h>
39
40 #ifndef WINDOWS
41 # include <sys/socket.h>
42 # include <netdb.h>
43 # include <netinet/in.h>
44 # ifndef __BEOS__
45 #  include <arpa/inet.h>
46 # endif
47 #endif /* not WINDOWS */
48
49 #include <errno.h>
50 #ifdef HAVE_STRING_H
51 # include <string.h>
52 #else
53 # include <strings.h>
54 #endif /* HAVE_STRING_H */
55 #ifdef HAVE_SYS_SELECT_H
56 # include <sys/select.h>
57 #endif /* HAVE_SYS_SELECT_H */
58
59 #include "wget.h"
60 #include "utils.h"
61 #include "host.h"
62 #include "connect.h"
63
64 #ifndef errno
65 extern int errno;
66 #endif
67
68 \f
69 /* Fill SA as per the data in IP and PORT.  SA shoult point to struct
70    sockaddr_storage if ENABLE_IPV6 is defined, to struct sockaddr_in
71    otherwise.  */
72
73 static void
74 sockaddr_set_data (struct sockaddr *sa, const ip_address *ip, int port)
75 {
76   switch (ip->type)
77     {
78     case IPV4_ADDRESS:
79       {
80         struct sockaddr_in *sin = (struct sockaddr_in *)sa;
81         sin->sin_family = AF_INET;
82         sin->sin_port = htons (port);
83         sin->sin_addr = ADDRESS_IPV4_IN_ADDR (ip);
84         break;
85       }
86 #ifdef ENABLE_IPV6
87     case IPV6_ADDRESS:
88       {
89         struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
90         sin6->sin6_family = AF_INET6;
91         sin6->sin6_port = htons (port);
92         sin6->sin6_addr = ADDRESS_IPV6_IN6_ADDR (ip);
93 #ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
94         sin6->sin6_scope_id = ADDRESS_IPV6_SCOPE (ip);
95 #endif
96         break;
97       }
98 #endif /* ENABLE_IPV6 */
99     default:
100       abort ();
101     }
102 }
103
104 /* Get the data of SA, specifically the IP address and the port.  If
105    you're not interested in one or the other information, pass NULL as
106    the pointer.  */
107
108 void
109 sockaddr_get_data (const struct sockaddr *sa, ip_address *ip, int *port)
110 {
111   switch (sa->sa_family)
112     {
113     case AF_INET:
114       {
115         struct sockaddr_in *sin = (struct sockaddr_in *)sa;
116         if (ip)
117           {
118             ip->type = IPV4_ADDRESS;
119             ADDRESS_IPV4_IN_ADDR (ip) = sin->sin_addr;
120           }
121         if (port)
122           *port = ntohs (sin->sin_port);
123         break;
124       }
125 #ifdef ENABLE_IPV6
126     case AF_INET6:
127       {
128         struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
129         if (ip)
130           {
131             ip->type = IPV6_ADDRESS;
132             ADDRESS_IPV6_IN6_ADDR (ip) = sin6->sin6_addr;
133 #ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
134             ADDRESS_IPV6_SCOPE (ip) = sin6->sin6_scope_id;
135 #endif
136           }
137         if (port)
138           *port = ntohs (sin6->sin6_port);
139         break;
140       }
141 #endif
142     default:
143       abort ();
144     }
145 }
146
147 /* Return the size of the sockaddr structure depending on its
148    family.  */
149
150 static socklen_t
151 sockaddr_size (const struct sockaddr *sa)
152 {
153   switch (sa->sa_family)
154     {
155     case AF_INET:
156       return sizeof (struct sockaddr_in);
157 #ifdef ENABLE_IPV6
158     case AF_INET6:
159       return sizeof (struct sockaddr_in6);
160 #endif
161     default:
162       abort ();
163       return 0;                 /* so the compiler shuts up. */
164     }
165 }
166 \f
167 static int
168 resolve_bind_address (const char *host, struct sockaddr *sa, int flags)
169 {
170   struct address_list *al;
171
172   /* #### Shouldn't we do this only once?  opt.bind_address won't
173      change during a Wget run!  */
174
175   al = lookup_host (host, flags | LH_SILENT | LH_PASSIVE);
176   if (al == NULL)
177     {
178       logprintf (LOG_NOTQUIET,
179                  _("Unable to convert `%s' to a bind address.  Reverting to ANY.\n"),
180                  opt.bind_address);
181       return 0;
182     }
183
184   /* Pick the first address in the list and use it as bind address.
185      Perhaps we should try multiple addresses, but I don't think
186      that's necessary in practice.  */
187   sockaddr_set_data (sa, address_list_address_at (al, 0), 0);
188   address_list_release (al);
189   return 1;
190 }
191 \f
192 struct cwt_context {
193   int fd;
194   const struct sockaddr *addr;
195   socklen_t addrlen;
196   int result;
197 };
198
199 static void
200 connect_with_timeout_callback (void *arg)
201 {
202   struct cwt_context *ctx = (struct cwt_context *)arg;
203   ctx->result = connect (ctx->fd, ctx->addr, ctx->addrlen);
204 }
205
206 /* Like connect, but specifies a timeout.  If connecting takes longer
207    than TIMEOUT seconds, -1 is returned and errno is set to
208    ETIMEDOUT.  */
209
210 static int
211 connect_with_timeout (int fd, const struct sockaddr *addr, socklen_t addrlen,
212                       double timeout)
213 {
214   struct cwt_context ctx;
215   ctx.fd = fd;
216   ctx.addr = addr;
217   ctx.addrlen = addrlen;
218
219   if (run_with_timeout (timeout, connect_with_timeout_callback, &ctx))
220     {
221       errno = ETIMEDOUT;
222       return -1;
223     }
224   if (ctx.result == -1 && errno == EINTR)
225     errno = ETIMEDOUT;
226   return ctx.result;
227 }
228 \f
229 /* Connect to a remote endpoint whose IP address is known.  */
230
231 int
232 connect_to_ip (const ip_address *ip, int port, const char *print)
233 {
234   struct sockaddr_storage ss;
235   struct sockaddr *sa = (struct sockaddr *)&ss;
236   int sock, save_errno;
237
238   /* If PRINT is non-NULL, print the "Connecting to..." line, with
239      PRINT being the host name we're connecting to.  */
240   if (print)
241     {
242       const char *txt_addr = pretty_print_address (ip);
243       if (print && 0 != strcmp (print, txt_addr))
244         logprintf (LOG_VERBOSE,
245                    _("Connecting to %s|%s|:%d... "), print, txt_addr, port);
246       else
247         logprintf (LOG_VERBOSE, _("Connecting to %s:%d... "), txt_addr, port);
248     }
249
250   /* Store the sockaddr info to SA.  */
251   sockaddr_set_data (sa, ip, port);
252
253   /* Create the socket of the family appropriate for the address.  */
254   sock = socket (sa->sa_family, SOCK_STREAM, 0);
255   if (sock < 0)
256     goto out;
257
258   /* For very small rate limits, set the buffer size (and hence,
259      hopefully, the kernel's TCP window size) to the per-second limit.
260      That way we should never have to sleep for more than 1s between
261      network reads.  */
262   if (opt.limit_rate && opt.limit_rate < 8192)
263     {
264       int bufsize = opt.limit_rate;
265       if (bufsize < 512)
266         bufsize = 512;          /* avoid pathologically small values */
267 #ifdef SO_RCVBUF
268       setsockopt (sock, SOL_SOCKET, SO_RCVBUF,
269                   (void *)&bufsize, (socklen_t)sizeof (bufsize));
270 #endif
271       /* When we add limit_rate support for writing, which is useful
272          for POST, we should also set SO_SNDBUF here.  */
273     }
274
275   if (opt.bind_address)
276     {
277       /* Bind the client side of the socket to the requested
278          address.  */
279       struct sockaddr_storage bind_ss;
280       struct sockaddr *bind_sa = (struct sockaddr *)&bind_ss;
281       if (resolve_bind_address (opt.bind_address, bind_sa, 0))
282         {
283           if (bind (sock, bind_sa, sockaddr_size (bind_sa)) < 0)
284             {
285               CLOSE (sock);
286               sock = -1;
287               goto out;
288             }
289         }
290     }
291
292   /* Connect the socket to the remote endpoint.  */
293   if (connect_with_timeout (sock, sa, sockaddr_size (sa),
294                             opt.connect_timeout) < 0)
295     {
296       CLOSE (sock);
297       sock = -1;
298       goto out;
299     }
300
301  out:
302   if (sock >= 0)
303     {
304       /* Success. */
305       if (print)
306         logprintf (LOG_VERBOSE, _("connected.\n"));
307       DEBUGP (("Created socket %d.\n", sock));
308     }
309   else
310     {
311       save_errno = errno;
312       if (print)
313         logprintf (LOG_VERBOSE, "failed: %s.\n", strerror (errno));
314       errno = save_errno;
315     }
316
317   return sock;
318 }
319
320 /* Connect to a remote endpoint specified by host name.  */
321
322 int
323 connect_to_host (const char *host, int port)
324 {
325   int i, start, end;
326   struct address_list *al;
327   int sock = -1;
328
329  again:
330   al = lookup_host (host, 0);
331   if (!al)
332     return E_HOST;
333
334   address_list_get_bounds (al, &start, &end);
335   for (i = start; i < end; i++)
336     {
337       const ip_address *ip = address_list_address_at (al, i);
338       sock = connect_to_ip (ip, port, host);
339       if (sock >= 0)
340         /* Success. */
341         break;
342
343       address_list_set_faulty (al, i);
344
345       /* The attempt to connect has failed.  Continue with the loop
346          and try next address. */
347     }
348   address_list_release (al);
349
350   if (sock < 0 && address_list_cached_p (al))
351     {
352       /* We were unable to connect to any address in a list we've
353          obtained from cache.  There is a possibility that the host is
354          under dynamic DNS and has changed its address.  Resolve it
355          again.  */
356       forget_host_lookup (host);
357       goto again;
358     }
359
360   return sock;
361 }
362
363 int
364 test_socket_open (int sock)
365 {
366 #ifdef HAVE_SELECT
367   fd_set check_set;
368   struct timeval to;
369
370   /* Check if we still have a valid (non-EOF) connection.  From Andrew
371    * Maholski's code in the Unix Socket FAQ.  */
372
373   FD_ZERO (&check_set);
374   FD_SET (sock, &check_set);
375
376   /* Wait one microsecond */
377   to.tv_sec = 0;
378   to.tv_usec = 1;
379
380   /* If we get a timeout, then that means still connected */
381   if (select (sock + 1, &check_set, NULL, NULL, &to) == 0)
382     {
383       /* Connection is valid (not EOF), so continue */
384       return 1;
385     }
386   else
387     return 0;
388 #else
389   /* Without select, it's hard to know for sure. */
390   return 1;
391 #endif
392 }
393
394 /* Create a socket and bind it to PORT locally.  Calling accept() on
395    such a socket waits for and accepts incoming TCP connections.  The
396    resulting socket is stored to LOCAL_SOCK.  */
397
398 uerr_t
399 bindport (const ip_address *bind_address, int *port, int *local_sock)
400 {
401   int msock;
402   int family = AF_INET;
403   int optval;
404   struct sockaddr_storage ss;
405   struct sockaddr *sa = (struct sockaddr *)&ss;
406   xzero (ss);
407
408 #ifdef ENABLE_IPV6
409   if (bind_address->type == IPV6_ADDRESS) 
410     family = AF_INET6;
411 #endif
412
413   if ((msock = socket (family, SOCK_STREAM, 0)) < 0)
414     return CONSOCKERR;
415
416 #ifdef SO_REUSEADDR
417   optval = 1;
418   if (setsockopt (msock, SOL_SOCKET, SO_REUSEADDR,
419                   (void *)&optval, (socklen_t)sizeof (optval)) < 0)
420     {
421       CLOSE (msock);
422       return CONSOCKERR;
423     }
424 #endif
425
426 #ifdef ENABLE_IPV6
427 # ifdef HAVE_IPV6_V6ONLY
428   if (family == AF_INET6)
429     {
430       optval = 1;
431       /* if setsockopt fails, go on anyway */
432       setsockopt (msock, IPPROTO_IPV6, IPV6_V6ONLY,
433                   (void *)&optval, (socklen_t)sizeof (optval));
434     }
435 # endif
436 #endif
437
438   sockaddr_set_data (sa, bind_address, *port);
439   if (bind (msock, sa, sockaddr_size (sa)) < 0)
440     {
441       CLOSE (msock);
442       return BINDERR;
443     }
444   DEBUGP (("Local socket fd %d bound.\n", msock));
445   if (!*port)
446     {
447       socklen_t sa_len = sockaddr_size (sa);
448       if (getsockname (msock, sa, &sa_len) < 0)
449         {
450           CLOSE (msock);
451           return CONPORTERR;
452         }
453       sockaddr_get_data (sa, NULL, port);
454       DEBUGP (("binding to address %s using port %i.\n", 
455                pretty_print_address (bind_address), *port));
456     }
457   if (listen (msock, 1) < 0)
458     {
459       CLOSE (msock);
460       return LISTENERR;
461     }
462   *local_sock = msock;
463   return BINDOK;
464 }
465
466 #ifdef HAVE_SELECT
467 /* Wait for file descriptor FD to be readable or writable or both,
468    timing out after MAXTIME seconds.  Returns 1 if FD is available, 0
469    for timeout and -1 for error.  The argument WHAT can be a
470    combination of WAIT_READ and WAIT_WRITE.
471
472    This is a mere convenience wrapper around the select call, and
473    should be taken as such.  */
474
475 int
476 select_fd (int fd, double maxtime, int wait)
477 {
478   fd_set fdset;
479   fd_set *rd = NULL, *wr = NULL;
480   struct timeval tmout;
481   int result;
482
483   FD_ZERO (&fdset);
484   FD_SET (fd, &fdset);
485   if (wait & WAIT_READ)
486     rd = &fdset;
487   if (wait & WAIT_WRITE)
488     wr = &fdset;
489
490   tmout.tv_sec = (long)maxtime;
491   tmout.tv_usec = 1000000L * (maxtime - (long)maxtime);
492
493   do
494     result = select (fd + 1, rd, wr, NULL, &tmout);
495   while (result < 0 && errno == EINTR);
496
497   /* When we've timed out, set errno to ETIMEDOUT for the convenience
498      of the caller. */
499   if (result == 0)
500     errno = ETIMEDOUT;
501
502   return result;
503 }
504 #endif /* HAVE_SELECT */
505
506 /* Accept a connection on LOCAL_SOCK, and store the new socket to
507    *SOCK.  It blocks the caller until a connection is established.  If
508    no connection is established for opt.connect_timeout seconds, the
509    function exits with an error status.  */
510
511 uerr_t
512 acceptport (int local_sock, int *sock)
513 {
514   struct sockaddr_storage ss;
515   struct sockaddr *sa = (struct sockaddr *)&ss;
516   socklen_t addrlen = sizeof (ss);
517
518 #ifdef HAVE_SELECT
519   if (opt.connect_timeout)
520     if (select_fd (local_sock, opt.connect_timeout, WAIT_READ) <= 0)
521       return ACCEPTERR;
522 #endif
523   if ((*sock = accept (local_sock, sa, &addrlen)) < 0)
524     return ACCEPTERR;
525   DEBUGP (("Created socket fd %d.\n", *sock));
526   return ACCEPTOK;
527 }
528
529 /* Return the local IP address associated with the connection on FD.  */
530
531 int
532 conaddr (int fd, ip_address *ip)
533 {
534   struct sockaddr_storage storage;
535   struct sockaddr *sockaddr = (struct sockaddr *)&storage;
536   socklen_t addrlen = sizeof (storage);
537
538   if (getsockname (fd, sockaddr, &addrlen) < 0)
539     return 0;
540
541   switch (sockaddr->sa_family)
542     {
543 #ifdef ENABLE_IPV6
544     case AF_INET6:
545       {
546         struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&storage;
547         ip->type = IPV6_ADDRESS;
548         ADDRESS_IPV6_IN6_ADDR (ip) = sa6->sin6_addr;
549 #ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
550         ADDRESS_IPV6_SCOPE (ip) = sa6->sin6_scope_id;
551 #endif
552         DEBUGP (("conaddr is: %s\n", pretty_print_address (ip)));
553         return 1;
554       }
555 #endif
556     case AF_INET:
557       {
558         struct sockaddr_in *sa = (struct sockaddr_in *)&storage;
559         ip->type = IPV4_ADDRESS;
560         ADDRESS_IPV4_IN_ADDR (ip) = sa->sin_addr;
561         DEBUGP (("conaddr is: %s\n", pretty_print_address (ip)));
562         return 1;
563       }
564     default:
565       abort ();
566     }
567
568   return 0;
569 }
570
571 /* Read at most LEN bytes from FD, storing them to BUF.  This is
572    virtually the same as read(), but takes care of EINTR braindamage
573    and uses select() to timeout the stale connections (a connection is
574    stale if more than OPT.READ_TIMEOUT time is spent in select() or
575    read()).  */
576
577 int
578 iread (int fd, char *buf, int len)
579 {
580   int res;
581
582 #ifdef HAVE_SELECT
583   if (opt.read_timeout)
584     if (select_fd (fd, opt.read_timeout, WAIT_READ) <= 0)
585       return -1;
586 #endif
587   do
588     res = READ (fd, buf, len);
589   while (res == -1 && errno == EINTR);
590
591   return res;
592 }
593
594 /* Write LEN bytes from BUF to FD.  This is similar to iread(), but
595    unlike iread(), it makes sure that all of BUF is actually written
596    to FD, so callers needn't bother with checking that the return
597    value equals to LEN.  Instead, you should simply check for -1.  */
598
599 int
600 iwrite (int fd, char *buf, int len)
601 {
602   int res = 0;
603
604   /* `write' may write less than LEN bytes, thus the outward loop
605      keeps trying it until all was written, or an error occurred.  The
606      inner loop is reserved for the usual EINTR f*kage, and the
607      innermost loop deals with the same during select().  */
608   while (len > 0)
609     {
610 #ifdef HAVE_SELECT
611       if (opt.read_timeout)
612         if (select_fd (fd, opt.read_timeout, WAIT_WRITE) <= 0)
613           return -1;
614 #endif
615       do
616         res = WRITE (fd, buf, len);
617       while (res == -1 && errno == EINTR);
618       if (res <= 0)
619         break;
620       buf += res;
621       len -= res;
622     }
623   return res;
624 }