]> sjero.net Git - wget/blob - src/connect.c
[svn] Cosmetic change.
[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 available, timing out after
468    MAXTIME seconds.  "Available" means readable if writep is 0,
469    writeable otherwise.
470
471    Returns 1 if FD is available, 0 for timeout and -1 for error.  */
472
473 int
474 select_fd (int fd, double maxtime, int writep)
475 {
476   fd_set fds;
477   fd_set *rd = NULL, *wrt = NULL;
478   struct timeval tmout;
479   int result;
480
481   FD_ZERO (&fds);
482   FD_SET (fd, &fds);
483   *(writep ? &wrt : &rd) = &fds;
484
485   tmout.tv_sec = (long)maxtime;
486   tmout.tv_usec = 1000000L * (maxtime - (long)maxtime);
487
488   do
489     result = select (fd + 1, rd, wrt, NULL, &tmout);
490   while (result < 0 && errno == EINTR);
491
492   /* When we've timed out, set errno to ETIMEDOUT for the convenience
493      of the caller. */
494   if (result == 0)
495     errno = ETIMEDOUT;
496
497   return result;
498 }
499 #endif /* HAVE_SELECT */
500
501 /* Accept a connection on LOCAL_SOCK, and store the new socket to
502    *SOCK.  It blocks the caller until a connection is established.  If
503    no connection is established for opt.connect_timeout seconds, the
504    function exits with an error status.  */
505
506 uerr_t
507 acceptport (int local_sock, int *sock)
508 {
509   struct sockaddr_storage ss;
510   struct sockaddr *sa = (struct sockaddr *)&ss;
511   socklen_t addrlen = sizeof (ss);
512
513 #ifdef HAVE_SELECT
514   if (opt.connect_timeout)
515     if (select_fd (local_sock, opt.connect_timeout, 0) <= 0)
516       return ACCEPTERR;
517 #endif
518   if ((*sock = accept (local_sock, sa, &addrlen)) < 0)
519     return ACCEPTERR;
520   DEBUGP (("Created socket fd %d.\n", *sock));
521   return ACCEPTOK;
522 }
523
524 /* Return the local IP address associated with the connection on FD.  */
525
526 int
527 conaddr (int fd, ip_address *ip)
528 {
529   struct sockaddr_storage storage;
530   struct sockaddr *sockaddr = (struct sockaddr *)&storage;
531   socklen_t addrlen = sizeof (storage);
532
533   if (getsockname (fd, sockaddr, &addrlen) < 0)
534     return 0;
535
536   switch (sockaddr->sa_family)
537     {
538 #ifdef ENABLE_IPV6
539     case AF_INET6:
540       {
541         struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&storage;
542         ip->type = IPV6_ADDRESS;
543         ADDRESS_IPV6_IN6_ADDR (ip) = sa6->sin6_addr;
544 #ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
545         ADDRESS_IPV6_SCOPE (ip) = sa6->sin6_scope_id;
546 #endif
547         DEBUGP (("conaddr is: %s\n", pretty_print_address (ip)));
548         return 1;
549       }
550 #endif
551     case AF_INET:
552       {
553         struct sockaddr_in *sa = (struct sockaddr_in *)&storage;
554         ip->type = IPV4_ADDRESS;
555         ADDRESS_IPV4_IN_ADDR (ip) = sa->sin_addr;
556         DEBUGP (("conaddr is: %s\n", pretty_print_address (ip)));
557         return 1;
558       }
559     default:
560       abort ();
561     }
562
563   return 0;
564 }
565
566 /* Read at most LEN bytes from FD, storing them to BUF.  This is
567    virtually the same as read(), but takes care of EINTR braindamage
568    and uses select() to timeout the stale connections (a connection is
569    stale if more than OPT.READ_TIMEOUT time is spent in select() or
570    read()).  */
571
572 int
573 iread (int fd, char *buf, int len)
574 {
575   int res;
576
577 #ifdef HAVE_SELECT
578   if (opt.read_timeout)
579     if (select_fd (fd, opt.read_timeout, 0) <= 0)
580       return -1;
581 #endif
582   do
583     res = READ (fd, buf, len);
584   while (res == -1 && errno == EINTR);
585
586   return res;
587 }
588
589 /* Write LEN bytes from BUF to FD.  This is similar to iread(), but
590    unlike iread(), it makes sure that all of BUF is actually written
591    to FD, so callers needn't bother with checking that the return
592    value equals to LEN.  Instead, you should simply check for -1.  */
593
594 int
595 iwrite (int fd, char *buf, int len)
596 {
597   int res = 0;
598
599   /* `write' may write less than LEN bytes, thus the outward loop
600      keeps trying it until all was written, or an error occurred.  The
601      inner loop is reserved for the usual EINTR f*kage, and the
602      innermost loop deals with the same during select().  */
603   while (len > 0)
604     {
605 #ifdef HAVE_SELECT
606       if (opt.read_timeout)
607         if (select_fd (fd, opt.read_timeout, 1) <= 0)
608           return -1;
609 #endif
610       do
611         res = WRITE (fd, buf, len);
612       while (res == -1 && errno == EINTR);
613       if (res <= 0)
614         break;
615       buf += res;
616       len -= res;
617     }
618   return res;
619 }