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