~ubuntu-branches/ubuntu/maverick/wget/maverick

« back to all changes in this revision

Viewing changes to src/connect.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Vogt
  • Date: 2008-05-27 11:49:54 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20080527114954-ame070pjhqtofeaf
Tags: 1.11.2-1ubuntu1
* Merge from debian unstable, remaining changes:
  - Add wget-udeb to ship wget.gnu as alternative to busybox wget
    implementation.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* Establishing and handling network connections.
2
 
   Copyright (C) 1995, 1996, 1997, 2001, 2002 Free Software Foundation, Inc.
 
2
   Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
 
3
   2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
3
4
 
4
5
This file is part of GNU Wget.
5
6
 
6
7
GNU Wget is free software; you can redistribute it and/or modify
7
8
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
the Free Software Foundation; either version 3 of the License, or
9
10
 (at your option) any later version.
10
11
 
11
12
GNU Wget is distributed in the hope that it will be useful,
14
15
GNU General Public License for more details.
15
16
 
16
17
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.  */
 
18
along with Wget.  If not, see <http://www.gnu.org/licenses/>.
 
19
 
 
20
Additional permission under GNU GPL version 3 section 7
 
21
 
 
22
If you modify this program, or any covered work, by linking or
 
23
combining it with the OpenSSL project's OpenSSL library (or a
 
24
modified version of that library), containing parts covered by the
 
25
terms of the OpenSSL or SSLeay licenses, the Free Software Foundation
 
26
grants you additional permission to convey the resulting work.
 
27
Corresponding Source for a non-source form of such a combination
 
28
shall include the source code for the parts of OpenSSL used as well
 
29
as that of the covered work.  */
29
30
 
30
31
#include <config.h>
31
32
 
32
33
#include <stdio.h>
33
34
#include <stdlib.h>
34
 
#include <sys/types.h>
35
35
#ifdef HAVE_UNISTD_H
36
36
# include <unistd.h>
37
37
#endif
47
47
#endif /* not WINDOWS */
48
48
 
49
49
#include <errno.h>
50
 
#ifdef HAVE_STRING_H
51
 
# include <string.h>
52
 
#else
53
 
# include <strings.h>
54
 
#endif /* HAVE_STRING_H */
 
50
#include <string.h>
55
51
#ifdef HAVE_SYS_SELECT_H
56
52
# include <sys/select.h>
57
53
#endif /* HAVE_SYS_SELECT_H */
 
54
#ifdef HAVE_SYS_TIME_H
 
55
# include <sys/time.h>
 
56
#endif
58
57
 
59
58
#include "wget.h"
60
59
#include "utils.h"
62
61
#include "connect.h"
63
62
#include "hash.h"
64
63
 
65
 
#ifndef errno
66
 
extern int errno;
67
 
#endif
68
 
 
69
64
/* Define sockaddr_storage where unavailable (presumably on IPv4-only
70
65
   hosts).  */
71
66
 
82
77
static void
83
78
sockaddr_set_data (struct sockaddr *sa, const ip_address *ip, int port)
84
79
{
85
 
  switch (ip->type)
 
80
  switch (ip->family)
86
81
    {
87
 
    case IPV4_ADDRESS:
 
82
    case AF_INET:
88
83
      {
89
 
        struct sockaddr_in *sin = (struct sockaddr_in *)sa;
90
 
        xzero (*sin);
91
 
        sin->sin_family = AF_INET;
92
 
        sin->sin_port = htons (port);
93
 
        sin->sin_addr = ADDRESS_IPV4_IN_ADDR (ip);
94
 
        break;
 
84
        struct sockaddr_in *sin = (struct sockaddr_in *)sa;
 
85
        xzero (*sin);
 
86
        sin->sin_family = AF_INET;
 
87
        sin->sin_port = htons (port);
 
88
        sin->sin_addr = ip->data.d4;
 
89
        break;
95
90
      }
96
91
#ifdef ENABLE_IPV6
97
 
    case IPV6_ADDRESS:
 
92
    case AF_INET6:
98
93
      {
99
 
        struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
100
 
        xzero (*sin6);
101
 
        sin6->sin6_family = AF_INET6;
102
 
        sin6->sin6_port = htons (port);
103
 
        sin6->sin6_addr = ADDRESS_IPV6_IN6_ADDR (ip);
 
94
        struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
 
95
        xzero (*sin6);
 
96
        sin6->sin6_family = AF_INET6;
 
97
        sin6->sin6_port = htons (port);
 
98
        sin6->sin6_addr = ip->data.d6;
104
99
#ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
105
 
        sin6->sin6_scope_id = ADDRESS_IPV6_SCOPE (ip);
 
100
        sin6->sin6_scope_id = ip->ipv6_scope;
106
101
#endif
107
 
        break;
 
102
        break;
108
103
      }
109
104
#endif /* ENABLE_IPV6 */
110
105
    default:
123
118
    {
124
119
    case AF_INET:
125
120
      {
126
 
        struct sockaddr_in *sin = (struct sockaddr_in *)sa;
127
 
        if (ip)
128
 
          {
129
 
            ip->type = IPV4_ADDRESS;
130
 
            ADDRESS_IPV4_IN_ADDR (ip) = sin->sin_addr;
131
 
          }
132
 
        if (port)
133
 
          *port = ntohs (sin->sin_port);
134
 
        break;
 
121
        struct sockaddr_in *sin = (struct sockaddr_in *)sa;
 
122
        if (ip)
 
123
          {
 
124
            ip->family = AF_INET;
 
125
            ip->data.d4 = sin->sin_addr;
 
126
          }
 
127
        if (port)
 
128
          *port = ntohs (sin->sin_port);
 
129
        break;
135
130
      }
136
131
#ifdef ENABLE_IPV6
137
132
    case AF_INET6:
138
133
      {
139
 
        struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
140
 
        if (ip)
141
 
          {
142
 
            ip->type = IPV6_ADDRESS;
143
 
            ADDRESS_IPV6_IN6_ADDR (ip) = sin6->sin6_addr;
 
134
        struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
 
135
        if (ip)
 
136
          {
 
137
            ip->family = AF_INET6;
 
138
            ip->data.d6 = sin6->sin6_addr;
144
139
#ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
145
 
            ADDRESS_IPV6_SCOPE (ip) = sin6->sin6_scope_id;
 
140
            ip->ipv6_scope = sin6->sin6_scope_id;
146
141
#endif
147
 
          }
148
 
        if (port)
149
 
          *port = ntohs (sin6->sin6_port);
150
 
        break;
 
142
          }
 
143
        if (port)
 
144
          *port = ntohs (sin6->sin6_port);
 
145
        break;
151
146
      }
152
147
#endif
153
148
    default:
174
169
    }
175
170
}
176
171
 
177
 
static int
 
172
/* Resolve the bind address specified via --bind-address and store it
 
173
   to SA.  The resolved value is stored in a static variable and
 
174
   reused after the first invocation of this function.
 
175
 
 
176
   Returns true on success, false on failure.  */
 
177
 
 
178
static bool
178
179
resolve_bind_address (struct sockaddr *sa)
179
180
{
180
181
  struct address_list *al;
181
182
 
182
183
  /* Make sure this is called only once.  opt.bind_address doesn't
183
184
     change during a Wget run.  */
184
 
  static int called, should_bind;
 
185
  static bool called, should_bind;
185
186
  static ip_address ip;
186
187
  if (called)
187
188
    {
188
189
      if (should_bind)
189
 
        sockaddr_set_data (sa, &ip, 0);
 
190
        sockaddr_set_data (sa, &ip, 0);
190
191
      return should_bind;
191
192
    }
192
 
  called = 1;
 
193
  called = true;
193
194
 
194
195
  al = lookup_host (opt.bind_address, LH_BIND | LH_SILENT);
195
196
  if (!al)
196
197
    {
197
198
      /* #### We should be able to print the error message here. */
198
199
      logprintf (LOG_NOTQUIET,
199
 
                 _("%s: unable to resolve bind address `%s'; disabling bind.\n"),
200
 
                 exec_name, opt.bind_address);
201
 
      should_bind = 0;
202
 
      return 0;
 
200
                 _("%s: unable to resolve bind address `%s'; disabling bind.\n"),
 
201
                 exec_name, opt.bind_address);
 
202
      should_bind = false;
 
203
      return false;
203
204
    }
204
205
 
205
206
  /* Pick the first address in the list and use it as bind address.
209
210
  address_list_release (al);
210
211
 
211
212
  sockaddr_set_data (sa, &ip, 0);
212
 
  should_bind = 1;
213
 
  return 1;
 
213
  should_bind = true;
 
214
  return true;
214
215
}
215
216
 
216
217
struct cwt_context {
233
234
 
234
235
static int
235
236
connect_with_timeout (int fd, const struct sockaddr *addr, socklen_t addrlen,
236
 
                      double timeout)
 
237
                      double timeout)
237
238
{
238
239
  struct cwt_context ctx;
239
240
  ctx.fd = fd;
266
267
     PRINT being the host name we're connecting to.  */
267
268
  if (print)
268
269
    {
269
 
      const char *txt_addr = pretty_print_address (ip);
 
270
      const char *txt_addr = print_address (ip);
270
271
      if (print && 0 != strcmp (print, txt_addr))
271
 
        logprintf (LOG_VERBOSE, _("Connecting to %s|%s|:%d... "),
272
 
                   escnonprint (print), txt_addr, port);
 
272
        logprintf (LOG_VERBOSE, _("Connecting to %s|%s|:%d... "),
 
273
                   escnonprint (print), txt_addr, port);
273
274
      else
274
 
        logprintf (LOG_VERBOSE, _("Connecting to %s:%d... "), txt_addr, port);
 
275
        logprintf (LOG_VERBOSE, _("Connecting to %s:%d... "), txt_addr, port);
275
276
    }
276
277
 
277
278
  /* Store the sockaddr info to SA.  */
287
288
    int on = 1;
288
289
    /* In case of error, we will go on anyway... */
289
290
    int err = setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on));
290
 
#ifdef ENABLE_DEBUG
291
 
    if (err < 0) 
292
 
      DEBUGP (("Failed setting IPV6_V6ONLY: %s", strerror (errno)));
293
 
#endif
 
291
    IF_DEBUG
 
292
      if (err < 0) 
 
293
        DEBUGP (("Failed setting IPV6_V6ONLY: %s", strerror (errno)));
294
294
  }
295
295
#endif
296
296
 
302
302
    {
303
303
      int bufsize = opt.limit_rate;
304
304
      if (bufsize < 512)
305
 
        bufsize = 512;          /* avoid pathologically small values */
 
305
        bufsize = 512;          /* avoid pathologically small values */
306
306
#ifdef SO_RCVBUF
307
307
      setsockopt (sock, SOL_SOCKET, SO_RCVBUF,
308
 
                  (void *)&bufsize, (socklen_t)sizeof (bufsize));
 
308
                  (void *)&bufsize, (socklen_t)sizeof (bufsize));
309
309
#endif
310
310
      /* When we add limit_rate support for writing, which is useful
311
 
         for POST, we should also set SO_SNDBUF here.  */
 
311
         for POST, we should also set SO_SNDBUF here.  */
312
312
    }
313
313
 
314
314
  if (opt.bind_address)
315
315
    {
316
316
      /* Bind the client side of the socket to the requested
317
 
         address.  */
 
317
         address.  */
318
318
      struct sockaddr_storage bind_ss;
319
319
      struct sockaddr *bind_sa = (struct sockaddr *)&bind_ss;
320
320
      if (resolve_bind_address (bind_sa))
321
 
        {
 
321
        {
322
322
          if (bind (sock, bind_sa, sockaddr_size (bind_sa)) < 0)
323
 
            goto err;
324
 
        }
 
323
            goto err;
 
324
        }
325
325
    }
326
326
 
327
327
  /* Connect the socket to the remote endpoint.  */
328
328
  if (connect_with_timeout (sock, sa, sockaddr_size (sa),
329
 
                            opt.connect_timeout) < 0)
 
329
                            opt.connect_timeout) < 0)
330
330
    goto err;
331
331
 
332
332
  /* Success. */
366
366
 
367
367
 retry:
368
368
  if (!al)
369
 
    return E_HOST;
 
369
    {
 
370
      logprintf (LOG_NOTQUIET,
 
371
                 _("%s: unable to resolve host address `%s'\n"),
 
372
                 exec_name, host);
 
373
      return E_HOST;
 
374
    }
370
375
 
371
376
  address_list_get_bounds (al, &start, &end);
372
377
  for (i = start; i < end; i++)
374
379
      const ip_address *ip = address_list_address_at (al, i);
375
380
      sock = connect_to_ip (ip, port, host);
376
381
      if (sock >= 0)
377
 
        {
378
 
          /* Success. */
379
 
          address_list_set_connected (al);
380
 
          address_list_release (al);
381
 
          return sock;
382
 
        }
 
382
        {
 
383
          /* Success. */
 
384
          address_list_set_connected (al);
 
385
          address_list_release (al);
 
386
          return sock;
 
387
        }
383
388
 
384
389
      /* The attempt to connect has failed.  Continue with the loop
385
 
         and try next address. */
 
390
         and try next address. */
386
391
 
387
392
      address_list_set_faulty (al, i);
388
393
    }
392
397
  if (address_list_connected_p (al))
393
398
    {
394
399
      /* We connected to AL before, but cannot do so now.  That might
395
 
         indicate that our DNS cache entry for HOST has expired.  */
 
400
         indicate that our DNS cache entry for HOST has expired.  */
396
401
      address_list_release (al);
397
402
      al = lookup_host (host, LH_REFRESH);
398
403
      goto retry;
419
424
bind_local (const ip_address *bind_address, int *port)
420
425
{
421
426
  int sock;
422
 
  int family = AF_INET;
423
427
  struct sockaddr_storage ss;
424
428
  struct sockaddr *sa = (struct sockaddr *)&ss;
425
429
 
428
432
  void *setopt_ptr = (void *)&setopt_val;
429
433
  socklen_t setopt_size = sizeof (setopt_val);
430
434
 
431
 
#ifdef ENABLE_IPV6
432
 
  if (bind_address->type == IPV6_ADDRESS) 
433
 
    family = AF_INET6;
434
 
#endif
435
 
 
436
 
  sock = socket (family, SOCK_STREAM, 0);
 
435
  sock = socket (bind_address->family, SOCK_STREAM, 0);
437
436
  if (sock < 0)
438
437
    return -1;
439
438
 
455
454
    {
456
455
      socklen_t addrlen = sockaddr_size (sa);
457
456
      if (getsockname (sock, sa, &addrlen) < 0)
458
 
        {
459
 
          /* If we can't find out the socket's local address ("name"),
460
 
             something is seriously wrong with the socket, and it's
461
 
             unusable for us anyway because we must know the chosen
462
 
             port.  */
463
 
          fd_close (sock);
464
 
          return -1;
465
 
        }
 
457
        {
 
458
          /* If we can't find out the socket's local address ("name"),
 
459
             something is seriously wrong with the socket, and it's
 
460
             unusable for us anyway because we must know the chosen
 
461
             port.  */
 
462
          fd_close (sock);
 
463
          return -1;
 
464
        }
466
465
      sockaddr_get_data (sa, NULL, port);
467
 
      DEBUGP (("binding to address %s using port %i.\n", 
468
 
               pretty_print_address (bind_address), *port));
 
466
      DEBUGP (("binding to address %s using port %i.\n",
 
467
               print_address (bind_address), *port));
469
468
    }
470
469
  if (listen (sock, 1) < 0)
471
470
    {
500
499
    {
501
500
      int test = select_fd (local_sock, opt.connect_timeout, WAIT_FOR_READ);
502
501
      if (test == 0)
503
 
        errno = ETIMEDOUT;
 
502
        errno = ETIMEDOUT;
504
503
      if (test <= 0)
505
 
        return -1;
 
504
        return -1;
506
505
    }
507
506
  sock = accept (local_sock, sa, &addrlen);
508
507
  DEBUGP (("Accepted client at socket %d.\n", sock));
510
509
}
511
510
 
512
511
/* Get the IP address associated with the connection on FD and store
513
 
   it to IP.  Return 1 on success, 0 otherwise.
 
512
   it to IP.  Return true on success, false otherwise.
514
513
 
515
514
   If ENDPOINT is ENDPOINT_LOCAL, it returns the address of the local
516
515
   (client) side of the socket.  Else if ENDPOINT is ENDPOINT_PEER, it
517
516
   returns the address of the remote (peer's) side of the socket.  */
518
517
 
519
 
int
 
518
bool
520
519
socket_ip_address (int sock, ip_address *ip, int endpoint)
521
520
{
522
521
  struct sockaddr_storage storage;
531
530
  else
532
531
    abort ();
533
532
  if (ret < 0)
534
 
    return 0;
 
533
    return false;
535
534
 
 
535
  ip->family = sockaddr->sa_family;
536
536
  switch (sockaddr->sa_family)
537
537
    {
538
538
#ifdef ENABLE_IPV6
539
539
    case AF_INET6:
540
540
      {
541
 
        struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&storage;
542
 
        ip->type = IPV6_ADDRESS;
543
 
        ADDRESS_IPV6_IN6_ADDR (ip) = sa6->sin6_addr;
 
541
        struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&storage;
 
542
        ip->data.d6 = sa6->sin6_addr;
544
543
#ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
545
 
        ADDRESS_IPV6_SCOPE (ip) = sa6->sin6_scope_id;
 
544
        ip->ipv6_scope = sa6->sin6_scope_id;
546
545
#endif
547
 
        DEBUGP (("conaddr is: %s\n", pretty_print_address (ip)));
548
 
        return 1;
 
546
        DEBUGP (("conaddr is: %s\n", print_address (ip)));
 
547
        return true;
549
548
      }
550
549
#endif
551
550
    case AF_INET:
552
551
      {
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;
 
552
        struct sockaddr_in *sa = (struct sockaddr_in *)&storage;
 
553
        ip->data.d4 = sa->sin_addr;
 
554
        DEBUGP (("conaddr is: %s\n", print_address (ip)));
 
555
        return true;
558
556
      }
559
557
    default:
560
558
      abort ();
561
559
    }
562
560
}
563
561
 
564
 
/* Return non-zero if the error from the connect code can be
565
 
   considered retryable.  Wget normally retries after errors, but the
566
 
   exception are the "unsupported protocol" type errors (possible on
567
 
   IPv4/IPv6 dual family systems) and "connection refused".  */
 
562
/* Return true if the error from the connect code can be considered
 
563
   retryable.  Wget normally retries after errors, but the exception
 
564
   are the "unsupported protocol" type errors (possible on IPv4/IPv6
 
565
   dual family systems) and "connection refused".  */
568
566
 
569
 
int
 
567
bool
570
568
retryable_socket_connect_error (int err)
571
569
{
572
570
  /* Have to guard against some of these values not being defined.
573
571
     Cannot use a switch statement because some of the values might be
574
572
     equal.  */
575
 
  if (0
 
573
  if (false
576
574
#ifdef EAFNOSUPPORT
577
575
      || err == EAFNOSUPPORT
578
576
#endif
579
577
#ifdef EPFNOSUPPORT
580
578
      || err == EPFNOSUPPORT
581
579
#endif
582
 
#ifdef ESOCKTNOSUPPORT          /* no, "sockt" is not a typo! */
 
580
#ifdef ESOCKTNOSUPPORT          /* no, "sockt" is not a typo! */
583
581
      || err == ESOCKTNOSUPPORT
584
582
#endif
585
583
#ifdef EPROTONOSUPPORT
589
587
      || err == ENOPROTOOPT
590
588
#endif
591
589
      /* Apparently, older versions of Linux and BSD used EINVAL
592
 
         instead of EAFNOSUPPORT and such.  */
 
590
         instead of EAFNOSUPPORT and such.  */
593
591
      || err == EINVAL
594
592
      )
595
 
    return 0;
 
593
    return false;
596
594
 
597
595
  if (!opt.retry_connrefused)
598
596
    if (err == ECONNREFUSED
599
597
#ifdef ENETUNREACH
600
 
        || err == ENETUNREACH   /* network is unreachable */
 
598
        || err == ENETUNREACH   /* network is unreachable */
601
599
#endif
602
600
#ifdef EHOSTUNREACH
603
 
        || err == EHOSTUNREACH  /* host is unreachable */
 
601
        || err == EHOSTUNREACH  /* host is unreachable */
604
602
#endif
605
 
        )
606
 
      return 0;
 
603
        )
 
604
      return false;
607
605
 
608
 
  return 1;
 
606
  return true;
609
607
}
610
608
 
611
609
/* Wait for a single descriptor to become available, timing out after
620
618
int
621
619
select_fd (int fd, double maxtime, int wait_for)
622
620
{
623
 
#ifdef HAVE_SELECT
624
621
  fd_set fdset;
625
622
  fd_set *rd = NULL, *wr = NULL;
626
623
  struct timeval tmout;
641
638
  while (result < 0 && errno == EINTR);
642
639
 
643
640
  return result;
644
 
 
645
 
#else  /* not HAVE_SELECT */
646
 
 
647
 
  /* If select() unavailable, just return 1.  In most usages in Wget,
648
 
     this is the appropriate response -- "if we can't poll, go ahead
649
 
     with the blocking operation".  If a specific part of code needs
650
 
     different behavior, it can use #ifdef HAVE_SELECT to test whether
651
 
     polling really occurs.  */
652
 
  return 1;
653
 
 
654
 
#endif /* not HAVE_SELECT */
655
641
}
656
642
 
657
 
int
 
643
/* Return true iff the connection to the remote site established
 
644
   through SOCK is still open.
 
645
 
 
646
   Specifically, this function returns true if SOCK is not ready for
 
647
   reading.  This is because, when the connection closes, the socket
 
648
   is ready for reading because EOF is about to be delivered.  A side
 
649
   effect of this method is that sockets that have pending data are
 
650
   considered non-open.  This is actually a good thing for callers of
 
651
   this function, where such pending data can only be unwanted
 
652
   leftover from a previous request.  */
 
653
 
 
654
bool
658
655
test_socket_open (int sock)
659
656
{
660
 
#ifdef HAVE_SELECT
661
657
  fd_set check_set;
662
658
  struct timeval to;
663
659
 
671
667
  to.tv_sec = 0;
672
668
  to.tv_usec = 1;
673
669
 
674
 
  /* If we get a timeout, then that means still connected */
675
670
  if (select (sock + 1, &check_set, NULL, NULL, &to) == 0)
676
 
    {
677
 
      /* Connection is valid (not EOF), so continue */
678
 
      return 1;
679
 
    }
 
671
    /* We got a timeout, it means we're still connected. */
 
672
    return true;
680
673
  else
681
 
    return 0;
682
 
#else
683
 
  /* Without select, it's hard to know for sure. */
684
 
  return 1;
685
 
#endif
 
674
    /* Read now would not wait, it means we have either pending data
 
675
       or EOF/error. */
 
676
    return false;
686
677
}
687
678
 
688
679
/* Basic socket operations, mostly EINTR wrappers.  */
689
680
 
690
 
#ifdef WINDOWS
 
681
#if defined(WINDOWS) || defined(MSDOS)
691
682
# define read(fd, buf, cnt) recv (fd, buf, cnt, 0)
692
683
# define write(fd, buf, cnt) send (fd, buf, cnt, 0)
693
684
# define close(fd) closesocket (fd)
753
744
   or SSL_read or whatever is necessary.  */
754
745
 
755
746
static struct hash_table *transport_map;
756
 
static int transport_map_modified_tick;
 
747
static unsigned int transport_map_modified_tick;
757
748
 
758
749
struct transport_info {
759
 
  fd_reader_t reader;
760
 
  fd_writer_t writer;
761
 
  fd_poller_t poller;
762
 
  fd_peeker_t peeker;
763
 
  fd_closer_t closer;
 
750
  struct transport_implementation *imp;
764
751
  void *ctx;
765
752
};
766
753
 
772
759
   call getpeername, etc.  */
773
760
 
774
761
void
775
 
fd_register_transport (int fd, fd_reader_t reader, fd_writer_t writer,
776
 
                       fd_poller_t poller, fd_peeker_t peeker,
777
 
                       fd_closer_t closer, void *ctx)
 
762
fd_register_transport (int fd, struct transport_implementation *imp, void *ctx)
778
763
{
779
764
  struct transport_info *info;
780
765
 
784
769
  assert (fd >= 0);
785
770
 
786
771
  info = xnew (struct transport_info);
787
 
  info->reader = reader;
788
 
  info->writer = writer;
789
 
  info->poller = poller;
790
 
  info->peeker = peeker;
791
 
  info->closer = closer;
 
772
  info->imp = imp;
792
773
  info->ctx = ctx;
793
774
  if (!transport_map)
794
775
    transport_map = hash_table_new (0, NULL, NULL);
795
 
  hash_table_put (transport_map, (void *) fd, info);
 
776
  hash_table_put (transport_map, (void *)(intptr_t) fd, info);
796
777
  ++transport_map_modified_tick;
797
778
}
798
779
 
803
784
void *
804
785
fd_transport_context (int fd)
805
786
{
806
 
  struct transport_info *info = hash_table_get (transport_map, (void *) fd);
 
787
  struct transport_info *info = hash_table_get (transport_map, (void *)(intptr_t) fd);
807
788
  return info->ctx;
808
789
}
809
790
 
816
797
   This is a macro because we want the static storage variables to be
817
798
   per-function.  */
818
799
 
819
 
#define LAZY_RETRIEVE_INFO(info) do {                                   \
820
 
  static struct transport_info *last_info;                              \
821
 
  static int last_fd = -1, last_tick;                                   \
822
 
  if (!transport_map)                                                   \
823
 
    info = NULL;                                                        \
824
 
  else if (last_fd == fd && last_tick == transport_map_modified_tick)   \
825
 
    info = last_info;                                                   \
826
 
  else                                                                  \
827
 
    {                                                                   \
828
 
      info = hash_table_get (transport_map, (void *) fd);               \
829
 
      last_fd = fd;                                                     \
830
 
      last_info = info;                                                 \
831
 
      last_tick = transport_map_modified_tick;                          \
832
 
    }                                                                   \
 
800
#define LAZY_RETRIEVE_INFO(info) do {                                   \
 
801
  static struct transport_info *last_info;                              \
 
802
  static int last_fd = -1;                                              \
 
803
  static unsigned int last_tick;                                        \
 
804
  if (!transport_map)                                                   \
 
805
    info = NULL;                                                        \
 
806
  else if (last_fd == fd && last_tick == transport_map_modified_tick)   \
 
807
    info = last_info;                                                   \
 
808
  else                                                                  \
 
809
    {                                                                   \
 
810
      info = hash_table_get (transport_map, (void *)(intptr_t) fd);     \
 
811
      last_fd = fd;                                                     \
 
812
      last_info = info;                                                 \
 
813
      last_tick = transport_map_modified_tick;                          \
 
814
    }                                                                   \
833
815
} while (0)
834
816
 
835
 
static int
 
817
static bool
836
818
poll_internal (int fd, struct transport_info *info, int wf, double timeout)
837
819
{
838
820
  if (timeout == -1)
840
822
  if (timeout)
841
823
    {
842
824
      int test;
843
 
      if (info && info->poller)
844
 
        test = info->poller (fd, timeout, wf, info->ctx);
 
825
      if (info && info->imp->poller)
 
826
        test = info->imp->poller (fd, timeout, wf, info->ctx);
845
827
      else
846
 
        test = sock_poll (fd, timeout, wf);
 
828
        test = sock_poll (fd, timeout, wf);
847
829
      if (test == 0)
848
 
        errno = ETIMEDOUT;
 
830
        errno = ETIMEDOUT;
849
831
      if (test <= 0)
850
 
        return 0;
 
832
        return false;
851
833
    }
852
 
  return 1;
 
834
  return true;
853
835
}
854
836
 
855
837
/* Read no more than BUFSIZE bytes of data from FD, storing them to
864
846
  LAZY_RETRIEVE_INFO (info);
865
847
  if (!poll_internal (fd, info, WAIT_FOR_READ, timeout))
866
848
    return -1;
867
 
  if (info && info->reader)
868
 
    return info->reader (fd, buf, bufsize, info->ctx);
 
849
  if (info && info->imp->reader)
 
850
    return info->imp->reader (fd, buf, bufsize, info->ctx);
869
851
  else
870
852
    return sock_read (fd, buf, bufsize);
871
853
}
889
871
  LAZY_RETRIEVE_INFO (info);
890
872
  if (!poll_internal (fd, info, WAIT_FOR_READ, timeout))
891
873
    return -1;
892
 
  if (info && info->peeker)
893
 
    return info->peeker (fd, buf, bufsize, info->ctx);
 
874
  if (info && info->imp->peeker)
 
875
    return info->imp->peeker (fd, buf, bufsize, info->ctx);
894
876
  else
895
877
    return sock_peek (fd, buf, bufsize);
896
878
}
913
895
  while (bufsize > 0)
914
896
    {
915
897
      if (!poll_internal (fd, info, WAIT_FOR_WRITE, timeout))
916
 
        return -1;
917
 
      if (info && info->writer)
918
 
        res = info->writer (fd, buf, bufsize, info->ctx);
 
898
        return -1;
 
899
      if (info && info->imp->writer)
 
900
        res = info->imp->writer (fd, buf, bufsize, info->ctx);
919
901
      else
920
 
        res = sock_write (fd, buf, bufsize);
 
902
        res = sock_write (fd, buf, bufsize);
921
903
      if (res <= 0)
922
 
        break;
 
904
        break;
923
905
      buf += res;
924
906
      bufsize -= res;
925
907
    }
926
908
  return res;
927
909
}
928
910
 
 
911
/* Report the most recent error(s) on FD.  This should only be called
 
912
   after fd_* functions, such as fd_read and fd_write, and only if
 
913
   they return a negative result.  For errors coming from other calls
 
914
   such as setsockopt or fopen, strerror should continue to be
 
915
   used.
 
916
 
 
917
   If the transport doesn't support error messages or doesn't supply
 
918
   one, strerror(errno) is returned.  The returned error message
 
919
   should not be used after fd_close has been called.  */
 
920
 
 
921
const char *
 
922
fd_errstr (int fd)
 
923
{
 
924
  /* Don't bother with LAZY_RETRIEVE_INFO, as this will only be called
 
925
     in case of error, never in a tight loop.  */
 
926
  struct transport_info *info = NULL;
 
927
  if (transport_map)
 
928
    info = hash_table_get (transport_map, (void *)(intptr_t) fd);
 
929
 
 
930
  if (info && info->imp->errstr)
 
931
    {
 
932
      const char *err = info->imp->errstr (fd, info->ctx);
 
933
      if (err)
 
934
        return err;
 
935
      /* else, fall through and print the system error. */
 
936
    }
 
937
  return strerror (errno);
 
938
}
 
939
 
929
940
/* Close the file descriptor FD.  */
930
941
 
931
942
void
939
950
     per socket, so that particular optimization wouldn't work.  */
940
951
  info = NULL;
941
952
  if (transport_map)
942
 
    info = hash_table_get (transport_map, (void *) fd);
 
953
    info = hash_table_get (transport_map, (void *)(intptr_t) fd);
943
954
 
944
 
  if (info && info->closer)
945
 
    info->closer (fd, info->ctx);
 
955
  if (info && info->imp->closer)
 
956
    info->imp->closer (fd, info->ctx);
946
957
  else
947
958
    sock_close (fd);
948
959
 
949
960
  if (info)
950
961
    {
951
 
      hash_table_remove (transport_map, (void *) fd);
 
962
      hash_table_remove (transport_map, (void *)(intptr_t) fd);
952
963
      xfree (info);
953
964
      ++transport_map_modified_tick;
954
965
    }