]> sjero.net Git - wget/blob - src/connect.c
[svn] Look for and use socklen_t.
[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 /* Variables shared by bindport and acceptport: */
69 static int msock = -1;
70 static struct sockaddr *addr;
71
72 static ip_address bind_address;
73 static int bind_address_resolved;
74
75 static void
76 resolve_bind_address (void)
77 {
78   struct address_list *al;
79
80   if (bind_address_resolved || opt.bind_address == NULL)
81     /* Nothing to do. */
82     return;
83
84   al = lookup_host (opt.bind_address, 1);
85   if (!al)
86     {
87       logprintf (LOG_NOTQUIET,
88                  _("Unable to convert `%s' to a bind address.  Reverting to ANY.\n"),
89                  opt.bind_address);
90       return;
91     }
92
93   address_list_copy_one (al, 0, &bind_address);
94   address_list_release (al);
95   bind_address_resolved = 1;
96 }
97 \f
98 struct cwt_context {
99   int fd;
100   const struct sockaddr *addr;
101   socklen_t addrlen;
102   int result;
103 };
104
105 static void
106 connect_with_timeout_callback (void *arg)
107 {
108   struct cwt_context *ctx = (struct cwt_context *)arg;
109   ctx->result = connect (ctx->fd, ctx->addr, ctx->addrlen);
110 }
111
112 /* Like connect, but specifies a timeout.  If connecting takes longer
113    than TIMEOUT seconds, -1 is returned and errno is set to
114    ETIMEDOUT.  */
115
116 static int
117 connect_with_timeout (int fd, const struct sockaddr *addr, socklen_t addrlen,
118                       double timeout)
119 {
120   struct cwt_context ctx;
121   ctx.fd = fd;
122   ctx.addr = addr;
123   ctx.addrlen = addrlen;
124
125   if (run_with_timeout (timeout, connect_with_timeout_callback, &ctx))
126     {
127       errno = ETIMEDOUT;
128       return -1;
129     }
130   if (ctx.result == -1 && errno == EINTR)
131     errno = ETIMEDOUT;
132   return ctx.result;
133 }
134 \f
135 /* A kludge, but still better than passing the host name all the way
136    to connect_to_one.  */
137 static const char *connection_host_name;
138
139 void
140 set_connection_host_name (const char *host)
141 {
142   if (host)
143     assert (connection_host_name == NULL);
144   else
145     assert (connection_host_name != NULL);
146
147   connection_host_name = host;
148 }
149
150 /* Connect to a remote host whose address has been resolved. */
151 int
152 connect_to_one (ip_address *addr, unsigned short port, int silent)
153 {
154   wget_sockaddr sa;
155   int sock, save_errno;
156
157   /* Set port and protocol */
158   wget_sockaddr_set_address (&sa, ip_default_family, port, addr);
159
160   if (!silent)
161     {
162       char *pretty_addr = pretty_print_address (addr);
163       if (connection_host_name
164           && 0 != strcmp (connection_host_name, pretty_addr))
165         logprintf (LOG_VERBOSE, _("Connecting to %s[%s]:%hu... "),
166                    connection_host_name, pretty_addr, port);
167       else
168         logprintf (LOG_VERBOSE, _("Connecting to %s:%hu... "),
169                    pretty_addr, port);
170     }
171
172   /* Make an internet socket, stream type.  */
173   sock = socket (ip_default_family, SOCK_STREAM, 0);
174   if (sock < 0)
175     goto out;
176
177   /* For very small rate limits, set the buffer size (and hence,
178      hopefully, the size of the kernel window) to the size of the
179      limit.  That way we don't sleep for more than 1s between network
180      reads.  */
181   if (opt.limit_rate && opt.limit_rate < 8192)
182     {
183       int bufsize = opt.limit_rate;
184       if (bufsize < 512)
185         bufsize = 512;
186 #ifdef SO_RCVBUF
187       setsockopt (sock, SOL_SOCKET, SO_RCVBUF,
188                   (char *)&bufsize, sizeof (bufsize));
189 #endif
190       /* When we add opt.limit_rate support for writing, as with
191          `--post-file', also set SO_SNDBUF here.  */
192     }
193
194   resolve_bind_address ();
195   if (bind_address_resolved)
196     {
197       /* Bind the client side to the requested address. */
198       wget_sockaddr bsa;
199       wget_sockaddr_set_address (&bsa, ip_default_family, 0, &bind_address);
200       if (bind (sock, &bsa.sa, sockaddr_len ()))
201         {
202           CLOSE (sock);
203           sock = -1;
204           goto out;
205         }
206     }
207
208   /* Connect the socket to the remote host.  */
209   if (connect_with_timeout (sock, &sa.sa, sockaddr_len (),
210                             opt.connect_timeout) < 0)
211     {
212       CLOSE (sock);
213       sock = -1;
214       goto out;
215     }
216
217  out:
218   if (sock >= 0)
219     {
220       /* Success. */
221       if (!silent)
222         logprintf (LOG_VERBOSE, _("connected.\n"));
223       DEBUGP (("Created socket %d.\n", sock));
224     }
225   else
226     {
227       save_errno = errno;
228       if (!silent)
229         logprintf (LOG_VERBOSE, "failed: %s.\n", strerror (errno));
230       errno = save_errno;
231     }
232
233   return sock;
234 }
235
236 /* Connect to a remote host whose address has been resolved. */
237 int
238 connect_to_many (struct address_list *al, unsigned short port, int silent)
239 {
240   int i, start, end;
241
242   address_list_get_bounds (al, &start, &end);
243   for (i = start; i < end; i++)
244     {
245       ip_address addr;
246       int sock;
247       address_list_copy_one (al, i, &addr);
248
249       sock = connect_to_one (&addr, port, silent);
250       if (sock >= 0)
251         /* Success. */
252         return sock;
253
254       address_list_set_faulty (al, i);
255
256       /* The attempt to connect has failed.  Continue with the loop
257          and try next address. */
258     }
259
260   return -1;
261 }
262
263 int
264 test_socket_open (int sock)
265 {
266 #ifdef HAVE_SELECT
267   fd_set check_set;
268   struct timeval to;
269
270   /* Check if we still have a valid (non-EOF) connection.  From Andrew
271    * Maholski's code in the Unix Socket FAQ.  */
272
273   FD_ZERO (&check_set);
274   FD_SET (sock, &check_set);
275
276   /* Wait one microsecond */
277   to.tv_sec = 0;
278   to.tv_usec = 1;
279
280   /* If we get a timeout, then that means still connected */
281   if (select (sock + 1, &check_set, NULL, NULL, &to) == 0)
282     {
283       /* Connection is valid (not EOF), so continue */
284       return 1;
285     }
286   else
287     return 0;
288 #else
289   /* Without select, it's hard to know for sure. */
290   return 1;
291 #endif
292 }
293
294 /* Bind the local port PORT.  This does all the necessary work, which
295    is creating a socket, setting SO_REUSEADDR option on it, then
296    calling bind() and listen().  If *PORT is 0, a random port is
297    chosen by the system, and its value is stored to *PORT.  The
298    internal variable MPORT is set to the value of the ensuing master
299    socket.  Call acceptport() to block for and accept a connection.  */
300 uerr_t
301 bindport (unsigned short *port, int family)
302 {
303   int optval = 1;
304   wget_sockaddr srv;
305   memset (&srv, 0, sizeof (wget_sockaddr));
306
307   msock = -1;
308
309   if ((msock = socket (family, SOCK_STREAM, 0)) < 0)
310     return CONSOCKERR;
311
312 #ifdef SO_REUSEADDR
313   if (setsockopt (msock, SOL_SOCKET, SO_REUSEADDR,
314                   (char *)&optval, sizeof (optval)) < 0)
315     return CONSOCKERR;
316 #endif
317
318   resolve_bind_address ();
319   wget_sockaddr_set_address (&srv, ip_default_family, htons (*port),
320                              bind_address_resolved ? &bind_address : NULL);
321   if (bind (msock, &srv.sa, sockaddr_len ()) < 0)
322     {
323       CLOSE (msock);
324       msock = -1;
325       return BINDERR;
326     }
327   DEBUGP (("Master socket fd %d bound.\n", msock));
328   if (!*port)
329     {
330       socklen_t sa_len = sockaddr_len ();
331       if (getsockname (msock, &srv.sa, &sa_len) < 0)
332         {
333           CLOSE (msock);
334           msock = -1;
335           return CONPORTERR;
336         }
337       *port = wget_sockaddr_get_port (&srv);
338       DEBUGP (("using port %i.\n", *port));
339     }
340   if (listen (msock, 1) < 0)
341     {
342       CLOSE (msock);
343       msock = -1;
344       return LISTENERR;
345     }
346   return BINDOK;
347 }
348
349 #ifdef HAVE_SELECT
350 /* Wait for file descriptor FD to be available, timing out after
351    MAXTIME seconds.  "Available" means readable if writep is 0,
352    writeable otherwise.
353
354    Returns 1 if FD is available, 0 for timeout and -1 for error.  */
355
356 int
357 select_fd (int fd, double maxtime, int writep)
358 {
359   fd_set fds;
360   fd_set *rd = NULL, *wrt = NULL;
361   struct timeval tmout;
362   int result;
363
364   FD_ZERO (&fds);
365   FD_SET (fd, &fds);
366   *(writep ? &wrt : &rd) = &fds;
367
368   tmout.tv_sec = (long)maxtime;
369   tmout.tv_usec = 1000000L * (maxtime - (long)maxtime);
370
371   do
372     result = select (fd + 1, rd, wrt, NULL, &tmout);
373   while (result < 0 && errno == EINTR);
374
375   /* When we've timed out, set errno to ETIMEDOUT for the convenience
376      of the caller. */
377   if (result == 0)
378     errno = ETIMEDOUT;
379
380   return result;
381 }
382 #endif /* HAVE_SELECT */
383
384 /* Call accept() on MSOCK and store the result to *SOCK.  This assumes
385    that bindport() has been used to initialize MSOCK to a correct
386    value.  It blocks the caller until a connection is established.  If
387    no connection is established for OPT.CONNECT_TIMEOUT seconds, the
388    function exits with an error status.  */
389 uerr_t
390 acceptport (int *sock)
391 {
392   socklen_t addrlen = sockaddr_len ();
393
394 #ifdef HAVE_SELECT
395   if (select_fd (msock, opt.connect_timeout, 0) <= 0)
396     return ACCEPTERR;
397 #endif
398   if ((*sock = accept (msock, addr, &addrlen)) < 0)
399     return ACCEPTERR;
400   DEBUGP (("Created socket fd %d.\n", *sock));
401   return ACCEPTOK;
402 }
403
404 /* Close SOCK, as well as the most recently remembered MSOCK, created
405    via bindport().  If SOCK is -1, close MSOCK only.  */
406 void
407 closeport (int sock)
408 {
409   /*shutdown (sock, 2);*/
410   if (sock != -1)
411     CLOSE (sock);
412   if (msock != -1)
413     CLOSE (msock);
414   msock = -1;
415 }
416
417 /* Return the local IP address associated with the connection on FD.  */
418
419 int
420 conaddr (int fd, ip_address *ip)
421 {
422   wget_sockaddr mysrv;
423   socklen_t addrlen = sizeof (mysrv);   
424   if (getsockname (fd, &mysrv.sa, &addrlen) < 0)
425     return 0;
426
427   switch (mysrv.sa.sa_family)
428     {
429 #ifdef ENABLE_IPV6
430     case AF_INET6:
431       memcpy (ip, &mysrv.sin6.sin6_addr, 16);
432       return 1;
433 #endif
434     case AF_INET:
435       map_ipv4_to_ip ((ip4_address *)&mysrv.sin.sin_addr, ip);
436       return 1;
437     default:
438       abort ();
439     }
440   return 0;
441 }
442
443 /* Read at most LEN bytes from FD, storing them to BUF.  This is
444    virtually the same as read(), but takes care of EINTR braindamage
445    and uses select() to timeout the stale connections (a connection is
446    stale if more than OPT.READ_TIMEOUT time is spent in select() or
447    read()).  */
448
449 int
450 iread (int fd, char *buf, int len)
451 {
452   int res;
453
454 #ifdef HAVE_SELECT
455   if (opt.read_timeout)
456     if (select_fd (fd, opt.read_timeout, 0) <= 0)
457       return -1;
458 #endif
459   do
460     res = READ (fd, buf, len);
461   while (res == -1 && errno == EINTR);
462
463   return res;
464 }
465
466 /* Write LEN bytes from BUF to FD.  This is similar to iread(), but
467    unlike iread(), it makes sure that all of BUF is actually written
468    to FD, so callers needn't bother with checking that the return
469    value equals to LEN.  Instead, you should simply check for -1.  */
470
471 int
472 iwrite (int fd, char *buf, int len)
473 {
474   int res = 0;
475
476   /* `write' may write less than LEN bytes, thus the outward loop
477      keeps trying it until all was written, or an error occurred.  The
478      inner loop is reserved for the usual EINTR f*kage, and the
479      innermost loop deals with the same during select().  */
480   while (len > 0)
481     {
482 #ifdef HAVE_SELECT
483       if (opt.read_timeout)
484         if (select_fd (fd, opt.read_timeout, 1) <= 0)
485           return -1;
486 #endif
487       do
488         res = WRITE (fd, buf, len);
489       while (res == -1 && errno == EINTR);
490       if (res <= 0)
491         break;
492       buf += res;
493       len -= res;
494     }
495   return res;
496 }