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