]> sjero.net Git - wget/blob - src/connect.c
[svn] Make select_fd return 1 if select is unavailable.
[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 #include "hash.h"
64
65 #ifndef errno
66 extern int errno;
67 #endif
68
69 \f
70 /* Fill SA as per the data in IP and PORT.  SA shoult point to struct
71    sockaddr_storage if ENABLE_IPV6 is defined, to struct sockaddr_in
72    otherwise.  */
73
74 static void
75 sockaddr_set_data (struct sockaddr *sa, const ip_address *ip, int port)
76 {
77   switch (ip->type)
78     {
79     case IPV4_ADDRESS:
80       {
81         struct sockaddr_in *sin = (struct sockaddr_in *)sa;
82         sin->sin_family = AF_INET;
83         sin->sin_port = htons (port);
84         sin->sin_addr = ADDRESS_IPV4_IN_ADDR (ip);
85         break;
86       }
87 #ifdef ENABLE_IPV6
88     case IPV6_ADDRESS:
89       {
90         struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
91         sin6->sin6_family = AF_INET6;
92         sin6->sin6_port = htons (port);
93         sin6->sin6_addr = ADDRESS_IPV6_IN6_ADDR (ip);
94 #ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
95         sin6->sin6_scope_id = ADDRESS_IPV6_SCOPE (ip);
96 #endif
97         break;
98       }
99 #endif /* ENABLE_IPV6 */
100     default:
101       abort ();
102     }
103 }
104
105 /* Get the data of SA, specifically the IP address and the port.  If
106    you're not interested in one or the other information, pass NULL as
107    the pointer.  */
108
109 static void
110 sockaddr_get_data (const struct sockaddr *sa, ip_address *ip, int *port)
111 {
112   switch (sa->sa_family)
113     {
114     case AF_INET:
115       {
116         struct sockaddr_in *sin = (struct sockaddr_in *)sa;
117         if (ip)
118           {
119             ip->type = IPV4_ADDRESS;
120             ADDRESS_IPV4_IN_ADDR (ip) = sin->sin_addr;
121           }
122         if (port)
123           *port = ntohs (sin->sin_port);
124         break;
125       }
126 #ifdef ENABLE_IPV6
127     case AF_INET6:
128       {
129         struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
130         if (ip)
131           {
132             ip->type = IPV6_ADDRESS;
133             ADDRESS_IPV6_IN6_ADDR (ip) = sin6->sin6_addr;
134 #ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
135             ADDRESS_IPV6_SCOPE (ip) = sin6->sin6_scope_id;
136 #endif
137           }
138         if (port)
139           *port = ntohs (sin6->sin6_port);
140         break;
141       }
142 #endif
143     default:
144       abort ();
145     }
146 }
147
148 /* Return the size of the sockaddr structure depending on its
149    family.  */
150
151 static socklen_t
152 sockaddr_size (const struct sockaddr *sa)
153 {
154   switch (sa->sa_family)
155     {
156     case AF_INET:
157       return sizeof (struct sockaddr_in);
158 #ifdef ENABLE_IPV6
159     case AF_INET6:
160       return sizeof (struct sockaddr_in6);
161 #endif
162     default:
163       abort ();
164       return 0;                 /* so the compiler shuts up. */
165     }
166 }
167 \f
168 static int
169 resolve_bind_address (struct sockaddr *sa)
170 {
171   struct address_list *al;
172
173   /* Make sure this is called only once.  opt.bind_address doesn't
174      change during a Wget run.  */
175   static int called, should_bind;
176   static ip_address ip;
177   if (called)
178     {
179       if (should_bind)
180         sockaddr_set_data (sa, &ip, 0);
181       return should_bind;
182     }
183   called = 1;
184
185   al = lookup_host (opt.bind_address, LH_BIND | LH_SILENT);
186   if (!al)
187     {
188       /* #### We should be able to print the error message here. */
189       logprintf (LOG_NOTQUIET,
190                  _("%s: unable to resolve bind address `%s'; disabling bind.\n"),
191                  exec_name, opt.bind_address);
192       should_bind = 0;
193       return 0;
194     }
195
196   /* Pick the first address in the list and use it as bind address.
197      Perhaps we should try multiple addresses in succession, but I
198      don't think that's necessary in practice.  */
199   ip = *address_list_address_at (al, 0);
200   address_list_release (al);
201
202   sockaddr_set_data (sa, &ip, 0);
203   should_bind = 1;
204   return 1;
205 }
206 \f
207 struct cwt_context {
208   int fd;
209   const struct sockaddr *addr;
210   socklen_t addrlen;
211   int result;
212 };
213
214 static void
215 connect_with_timeout_callback (void *arg)
216 {
217   struct cwt_context *ctx = (struct cwt_context *)arg;
218   ctx->result = connect (ctx->fd, ctx->addr, ctx->addrlen);
219 }
220
221 /* Like connect, but specifies a timeout.  If connecting takes longer
222    than TIMEOUT seconds, -1 is returned and errno is set to
223    ETIMEDOUT.  */
224
225 static int
226 connect_with_timeout (int fd, const struct sockaddr *addr, socklen_t addrlen,
227                       double timeout)
228 {
229   struct cwt_context ctx;
230   ctx.fd = fd;
231   ctx.addr = addr;
232   ctx.addrlen = addrlen;
233
234   if (run_with_timeout (timeout, connect_with_timeout_callback, &ctx))
235     {
236       errno = ETIMEDOUT;
237       return -1;
238     }
239   if (ctx.result == -1 && errno == EINTR)
240     errno = ETIMEDOUT;
241   return ctx.result;
242 }
243 \f
244 /* Connect to a remote endpoint whose IP address is known.  */
245
246 int
247 connect_to_ip (const ip_address *ip, int port, const char *print)
248 {
249   struct sockaddr_storage ss;
250   struct sockaddr *sa = (struct sockaddr *)&ss;
251   int sock = -1;
252
253   /* If PRINT is non-NULL, print the "Connecting to..." line, with
254      PRINT being the host name we're connecting to.  */
255   if (print)
256     {
257       const char *txt_addr = pretty_print_address (ip);
258       if (print && 0 != strcmp (print, txt_addr))
259         logprintf (LOG_VERBOSE,
260                    _("Connecting to %s|%s|:%d... "), print, txt_addr, port);
261       else
262         logprintf (LOG_VERBOSE, _("Connecting to %s:%d... "), txt_addr, port);
263     }
264
265   /* Store the sockaddr info to SA.  */
266   sockaddr_set_data (sa, ip, port);
267
268   /* Create the socket of the family appropriate for the address.  */
269   sock = socket (sa->sa_family, SOCK_STREAM, 0);
270   if (sock < 0)
271     goto err;
272
273   /* For very small rate limits, set the buffer size (and hence,
274      hopefully, the kernel's TCP window size) to the per-second limit.
275      That way we should never have to sleep for more than 1s between
276      network reads.  */
277   if (opt.limit_rate && opt.limit_rate < 8192)
278     {
279       int bufsize = opt.limit_rate;
280       if (bufsize < 512)
281         bufsize = 512;          /* avoid pathologically small values */
282 #ifdef SO_RCVBUF
283       setsockopt (sock, SOL_SOCKET, SO_RCVBUF,
284                   (void *)&bufsize, (socklen_t)sizeof (bufsize));
285 #endif
286       /* When we add limit_rate support for writing, which is useful
287          for POST, we should also set SO_SNDBUF here.  */
288     }
289
290   if (opt.bind_address)
291     {
292       /* Bind the client side of the socket to the requested
293          address.  */
294       struct sockaddr_storage bind_ss;
295       struct sockaddr *bind_sa = (struct sockaddr *)&bind_ss;
296       if (resolve_bind_address (bind_sa))
297         {
298           if (bind (sock, bind_sa, sockaddr_size (bind_sa)) < 0)
299             goto err;
300         }
301     }
302
303   /* Connect the socket to the remote endpoint.  */
304   if (connect_with_timeout (sock, sa, sockaddr_size (sa),
305                             opt.connect_timeout) < 0)
306     goto err;
307
308   /* Success. */
309   assert (sock >= 0);
310   if (print)
311     logprintf (LOG_VERBOSE, _("connected.\n"));
312   DEBUGP (("Created socket %d.\n", sock));
313   return sock;
314
315  err:
316   {
317     /* Protect errno from possible modifications by close and
318        logprintf.  */
319     int save_errno = errno;
320     if (sock >= 0)
321       xclose (sock);
322     if (print)
323       logprintf (LOG_VERBOSE, "failed: %s.\n", strerror (errno));
324     errno = save_errno;
325     return -1;
326   }
327 }
328
329 /* Connect to a remote endpoint specified by host name.  */
330
331 int
332 connect_to_host (const char *host, int port)
333 {
334   int i, start, end;
335   int sock;
336
337   struct address_list *al = lookup_host (host, 0);
338
339  retry:
340   if (!al)
341     return E_HOST;
342
343   address_list_get_bounds (al, &start, &end);
344   for (i = start; i < end; i++)
345     {
346       const ip_address *ip = address_list_address_at (al, i);
347       sock = connect_to_ip (ip, port, host);
348       if (sock >= 0)
349         {
350           /* Success. */
351           address_list_set_connected (al);
352           address_list_release (al);
353           return sock;
354         }
355
356       /* The attempt to connect has failed.  Continue with the loop
357          and try next address. */
358
359       address_list_set_faulty (al, i);
360     }
361
362   /* Failed to connect to any of the addresses in AL. */
363
364   if (address_list_connected_p (al))
365     {
366       /* We connected to AL before, but cannot do so now.  That might
367          indicate that our DNS cache entry for HOST has expired.  */
368       address_list_release (al);
369       al = lookup_host (host, LH_REFRESH);
370       goto retry;
371     }
372   address_list_release (al);
373
374   return -1;
375 }
376
377 int
378 test_socket_open (int sock)
379 {
380 #ifdef HAVE_SELECT
381   fd_set check_set;
382   struct timeval to;
383
384   /* Check if we still have a valid (non-EOF) connection.  From Andrew
385    * Maholski's code in the Unix Socket FAQ.  */
386
387   FD_ZERO (&check_set);
388   FD_SET (sock, &check_set);
389
390   /* Wait one microsecond */
391   to.tv_sec = 0;
392   to.tv_usec = 1;
393
394   /* If we get a timeout, then that means still connected */
395   if (select (sock + 1, &check_set, NULL, NULL, &to) == 0)
396     {
397       /* Connection is valid (not EOF), so continue */
398       return 1;
399     }
400   else
401     return 0;
402 #else
403   /* Without select, it's hard to know for sure. */
404   return 1;
405 #endif
406 }
407
408 /* Create a socket, bind it to local interface BIND_ADDRESS on port
409    *PORT, set up a listen backlog, and return the resulting socket, or
410    -1 in case of error.
411
412    BIND_ADDRESS is the address of the interface to bind to.  If it is
413    NULL, the socket is bound to the default address.  PORT should
414    point to the port number that will be used for the binding.  If
415    that number is 0, the system will choose a suitable port, and the
416    chosen value will be written to *PORT.
417
418    Calling accept() on such a socket waits for and accepts incoming
419    TCP connections.  */
420
421 int
422 bind_local (const ip_address *bind_address, int *port)
423 {
424   int sock;
425   int family = AF_INET;
426   struct sockaddr_storage ss;
427   struct sockaddr *sa = (struct sockaddr *)&ss;
428
429   /* For setting options with setsockopt. */
430   int setopt_val = 1;
431   void *setopt_ptr = (void *)&setopt_val;
432   socklen_t setopt_size = sizeof (setopt_val);
433
434 #ifdef ENABLE_IPV6
435   if (bind_address->type == IPV6_ADDRESS) 
436     family = AF_INET6;
437 #endif
438
439   sock = socket (family, SOCK_STREAM, 0);
440   if (sock < 0)
441     return -1;
442
443 #ifdef SO_REUSEADDR
444   setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, setopt_ptr, setopt_size);
445 #endif
446
447 #ifdef ENABLE_IPV6
448 # ifdef HAVE_IPV6_V6ONLY
449   if (family == AF_INET6)
450     setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, setopt_ptr, setopt_size);
451 # endif
452 #endif
453
454   xzero (ss);
455   sockaddr_set_data (sa, bind_address, *port);
456   if (bind (sock, sa, sockaddr_size (sa)) < 0)
457     {
458       xclose (sock);
459       return -1;
460     }
461   DEBUGP (("Local socket fd %d bound.\n", sock));
462
463   /* If *PORT is 0, find out which port we've bound to.  */
464   if (*port == 0)
465     {
466       socklen_t sa_len = sockaddr_size (sa);
467       if (getsockname (sock, sa, &sa_len) < 0)
468         {
469           /* If we can't find out the socket's local address ("name"),
470              something is seriously wrong with the socket, and it's
471              unusable for us anyway because we must know the chosen
472              port.  */
473           xclose (sock);
474           return -1;
475         }
476       sockaddr_get_data (sa, NULL, port);
477       DEBUGP (("binding to address %s using port %i.\n", 
478                pretty_print_address (bind_address), *port));
479     }
480   if (listen (sock, 1) < 0)
481     {
482       xclose (sock);
483       return -1;
484     }
485   return sock;
486 }
487
488 /* Like a call to accept(), but with the added check for timeout.
489
490    In other words, accept a client connection on LOCAL_SOCK, and
491    return the new socket used for communication with the client.
492    LOCAL_SOCK should have been bound, e.g. using bind_local().
493
494    The caller is blocked until a connection is established.  If no
495    connection is established for opt.connect_timeout seconds, the
496    function exits with an error status.  */
497
498 int
499 accept_connection (int local_sock)
500 {
501   int sock;
502
503   /* We don't need the values provided by accept, but accept
504      apparently requires them to be present.  */
505   struct sockaddr_storage ss;
506   struct sockaddr *sa = (struct sockaddr *)&ss;
507   socklen_t addrlen = sizeof (ss);
508
509   if (opt.connect_timeout)
510     {
511       int test = select_fd (local_sock, opt.connect_timeout, WAIT_FOR_READ);
512       if (test == 0)
513         errno = ETIMEDOUT;
514       if (test <= 0)
515         return -1;
516     }
517   sock = accept (local_sock, sa, &addrlen);
518   DEBUGP (("Accepted client at socket %d.\n", sock));
519   return sock;
520 }
521
522 /* Get the IP address associated with the connection on FD and store
523    it to IP.  Return 1 on success, 0 otherwise.
524
525    If ENDPOINT is ENDPOINT_LOCAL, it returns the address of the local
526    (client) side of the socket.  Else if ENDPOINT is ENDPOINT_PEER, it
527    returns the address of the remote (peer's) side of the socket.  */
528
529 int
530 socket_ip_address (int sock, ip_address *ip, int endpoint)
531 {
532   struct sockaddr_storage storage;
533   struct sockaddr *sockaddr = (struct sockaddr *)&storage;
534   socklen_t addrlen = sizeof (storage);
535   int ret;
536
537   if (endpoint == ENDPOINT_LOCAL)
538     ret = getsockname (sock, sockaddr, &addrlen);
539   else if (endpoint == ENDPOINT_PEER)
540     ret = getpeername (sock, sockaddr, &addrlen);
541   else
542     abort ();
543   if (ret < 0)
544     return 0;
545
546   switch (sockaddr->sa_family)
547     {
548 #ifdef ENABLE_IPV6
549     case AF_INET6:
550       {
551         struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&storage;
552         ip->type = IPV6_ADDRESS;
553         ADDRESS_IPV6_IN6_ADDR (ip) = sa6->sin6_addr;
554 #ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
555         ADDRESS_IPV6_SCOPE (ip) = sa6->sin6_scope_id;
556 #endif
557         DEBUGP (("conaddr is: %s\n", pretty_print_address (ip)));
558         return 1;
559       }
560 #endif
561     case AF_INET:
562       {
563         struct sockaddr_in *sa = (struct sockaddr_in *)&storage;
564         ip->type = IPV4_ADDRESS;
565         ADDRESS_IPV4_IN_ADDR (ip) = sa->sin_addr;
566         DEBUGP (("conaddr is: %s\n", pretty_print_address (ip)));
567         return 1;
568       }
569     default:
570       abort ();
571     }
572
573   return 0;
574 }
575
576 /* Return non-zero if the error from the connect code can be
577    considered retryable.  Wget normally retries after errors, but the
578    exception are the "unsupported protocol" type errors (possible on
579    IPv4/IPv6 dual family systems) and "connection refused".  */
580
581 int
582 retryable_socket_connect_error (int err)
583 {
584   /* Have to guard against some of these values not being defined.
585      Cannot use a switch statement because some of the values might be
586      equal.  */
587   if (0
588 #ifdef EAFNOSUPPORT
589       || err == EAFNOSUPPORT
590 #endif
591 #ifdef EPFNOSUPPORT
592       || err == EPFNOSUPPORT
593 #endif
594 #ifdef ESOCKTNOSUPPORT          /* no, "sockt" is not a typo! */
595       || err == ESOCKTNOSUPPORT
596 #endif
597 #ifdef EPROTONOSUPPORT
598       || err == EPROTONOSUPPORT
599 #endif
600 #ifdef ENOPROTOOPT
601       || err == ENOPROTOOPT
602 #endif
603       /* Apparently, older versions of Linux and BSD used EINVAL
604          instead of EAFNOSUPPORT and such.  */
605       || err == EINVAL
606       )
607     return 0;
608
609   if (err == ECONNREFUSED && !opt.retry_connrefused)
610     return 0;
611
612   return 1;
613 }
614
615 /* Return non-zero if the INET6 socket family is supported on the
616    system.
617
618    This doesn't guarantee that we're able to connect to IPv6 hosts,
619    but it's better than nothing.  It is only used on systems where
620    getaddrinfo doesn't support AI_ADDRCONFIG.  (See lookup_host.)  */
621
622 int
623 socket_has_inet6 (void)
624 {
625   static int supported = -1;
626   if (supported == -1)
627     {
628       int sock = socket (AF_INET6, SOCK_STREAM, 0);
629       if (sock < 0)
630         supported = 0;
631       else
632         {
633           xclose (sock);
634           supported = 1;
635         }
636     }
637   return supported;
638 }
639
640 /* Wait for a single descriptor to become available, timing out after
641    MAXTIME seconds.  Returns 1 if FD is available, 0 for timeout and
642    -1 for error.  The argument WAIT_FOR can be a combination of
643    WAIT_FOR_READ and WAIT_FOR_WRITE.
644
645    This is a mere convenience wrapper around the select call, and
646    should be taken as such (for example, it doesn't implement Wget's
647    0-timeout-means-no-timeout semantics.)  */
648
649 int
650 select_fd (int fd, double maxtime, int wait_for)
651 {
652 #ifdef HAVE_SELECT
653   fd_set fdset;
654   fd_set *rd = NULL, *wr = NULL;
655   struct timeval tmout;
656   int result;
657
658   FD_ZERO (&fdset);
659   FD_SET (fd, &fdset);
660   if (wait_for & WAIT_FOR_READ)
661     rd = &fdset;
662   if (wait_for & WAIT_FOR_WRITE)
663     wr = &fdset;
664
665   tmout.tv_sec = (long) maxtime;
666   tmout.tv_usec = 1000000L * (maxtime - (long) maxtime);
667
668   do
669     result = select (fd + 1, rd, wr, NULL, &tmout);
670   while (result < 0 && errno == EINTR);
671
672   return result;
673
674 #else  /* not HAVE_SELECT */
675
676   /* If select() unavailable, just return 1.  In most usages in Wget,
677      this is the appropriate response -- "if we can't poll, go ahead
678      with the blocking operation".  If a specific part of code needs
679      different behavior, it can use #ifdef HAVE_SELECT to test whether
680      polling really occurs.  */
681   return 1;
682
683 #endif /* not HAVE_SELECT */
684 }
685 \f
686 /* Basic socket operations, mostly EINTR wrappers.  */
687
688 #ifdef WINDOWS
689 # define read(fd, buf, cnt) recv (fd, buf, cnt, 0)
690 # define write(fd, buf, cnt) send (fd, buf, cnt, 0)
691 # define close(fd) closesocket (fd)
692 #endif
693
694 #ifdef __BEOS__
695 # define read(fd, buf, cnt) recv (fd, buf, cnt, 0)
696 # define write(fd, buf, cnt) send (fd, buf, cnt, 0)
697 #endif
698
699 static int
700 sock_read (int fd, char *buf, int bufsize)
701 {
702   int res;
703   do
704     res = read (fd, buf, bufsize);
705   while (res == -1 && errno == EINTR);
706   return res;
707 }
708
709 static int
710 sock_write (int fd, char *buf, int bufsize)
711 {
712   int res = 0;
713   do
714     res = write (fd, buf, bufsize);
715   while (res == -1 && errno == EINTR);
716   return res;
717 }
718
719 static int
720 sock_poll (int fd, double timeout, int wait_for)
721 {
722   return select_fd (fd, timeout, wait_for);
723 }
724
725 static void
726 sock_close (int fd)
727 {
728   close (fd);
729   DEBUGP (("Closed fd %d\n", fd));
730 }
731 #undef read
732 #undef write
733 #undef close
734 \f
735 /* Reading and writing from the network.  We build around the socket
736    (file descriptor) API, but support "extended" operations for things
737    that are not mere file descriptors under the hood, such as SSL
738    sockets.
739
740    That way the user code can call xread(fd, ...) and we'll run read
741    or SSL_read or whatever is necessary.  */
742
743 static struct hash_table *transport_map;
744 static int transport_map_modified_tick;
745
746 struct transport_info {
747   xreader_t reader;
748   xwriter_t writer;
749   xpoller_t poller;
750   xcloser_t closer;
751   void *ctx;
752 };
753
754 /* Register the transport layer operations that will be used when
755    reading, writing, and polling FD.
756
757    This should be used for transport layers like SSL that piggyback on
758    sockets.  FD should otherwise be a real socket, on which you can
759    call getpeername, etc.  */
760
761 void
762 register_transport (int fd, xreader_t reader, xwriter_t writer,
763                     xpoller_t poller, xcloser_t closer, void *ctx)
764 {
765   struct transport_info *info;
766
767   /* The file descriptor must be non-negative to be registered.
768      Negative values are ignored by xclose(), and -1 cannot be used as
769      hash key.  */
770   assert (fd >= 0);
771
772   info = xnew (struct transport_info);
773   info->reader = reader;
774   info->writer = writer;
775   info->poller = poller;
776   info->closer = closer;
777   info->ctx = ctx;
778   if (!transport_map)
779     transport_map = hash_table_new (0, NULL, NULL);
780   hash_table_put (transport_map, (void *) fd, info);
781   ++transport_map_modified_tick;
782 }
783
784 /* When xread/xwrite are called multiple times in a loop, they should
785    remember the INFO pointer instead of fetching it every time.  It is
786    not enough to compare FD to LAST_FD because FD might have been
787    closed and reopened.  modified_tick ensures that changes to
788    transport_map will not be unnoticed.
789
790    This is a macro because we want the static storage variables to be
791    per-function.  */
792
793 #define LAZY_RETRIEVE_INFO(info) do {                                   \
794   static struct transport_info *last_info;                              \
795   static int last_fd = -1, last_tick;                                   \
796   if (!transport_map)                                                   \
797     info = NULL;                                                        \
798   else if (last_fd == fd && last_tick == transport_map_modified_tick)   \
799     info = last_info;                                                   \
800   else                                                                  \
801     {                                                                   \
802       info = hash_table_get (transport_map, (void *) fd);               \
803       last_fd = fd;                                                     \
804       last_info = info;                                                 \
805       last_tick = transport_map_modified_tick;                          \
806     }                                                                   \
807 } while (0)
808
809 /* Read no more than BUFSIZE bytes of data from FD, storing them to
810    BUF.  If TIMEOUT is non-zero, the operation aborts if no data is
811    received after that many seconds.  If TIMEOUT is -1, the value of
812    opt.timeout is used for TIMEOUT.  */
813
814 int
815 xread (int fd, char *buf, int bufsize, double timeout)
816 {
817   struct transport_info *info;
818   LAZY_RETRIEVE_INFO (info);
819   if (timeout == -1)
820     timeout = opt.read_timeout;
821   if (timeout)
822     {
823       int test;
824       if (info && info->poller)
825         test = info->poller (fd, timeout, WAIT_FOR_READ, info->ctx);
826       else
827         test = sock_poll (fd, timeout, WAIT_FOR_READ);
828       if (test == 0)
829         errno = ETIMEDOUT;
830       if (test <= 0)
831         return -1;
832     }
833   if (info && info->reader)
834     return info->reader (fd, buf, bufsize, info->ctx);
835   else
836     return sock_read (fd, buf, bufsize);
837 }
838
839 /* Write the entire contents of BUF to FD.  If TIMEOUT is non-zero,
840    the operation aborts if no data is received after that many
841    seconds.  If TIMEOUT is -1, the value of opt.timeout is used for
842    TIMEOUT.  */
843
844 int
845 xwrite (int fd, char *buf, int bufsize, double timeout)
846 {
847   int res;
848   struct transport_info *info;
849   LAZY_RETRIEVE_INFO (info);
850   if (timeout == -1)
851     timeout = opt.read_timeout;
852
853   /* `write' may write less than LEN bytes, thus the loop keeps trying
854      it until all was written, or an error occurred.  */
855   res = 0;
856   while (bufsize > 0)
857     {
858       if (timeout)
859         {
860           int test;
861           if (info && info->poller)
862             test = info->poller (fd, timeout, WAIT_FOR_WRITE, info->ctx);
863           else
864             test = sock_poll (fd, timeout, WAIT_FOR_WRITE);
865           if (test == 0)
866             errno = ETIMEDOUT;
867           if (test <= 0)
868             return -1;
869         }
870       if (info && info->writer)
871         res = info->writer (fd, buf, bufsize, info->ctx);
872       else
873         res = sock_write (fd, buf, bufsize);
874       if (res <= 0)
875         break;
876       buf += res;
877       bufsize -= res;
878     }
879   return res;
880 }
881
882 /* Close the file descriptor FD.  */
883
884 void
885 xclose (int fd)
886 {
887   struct transport_info *info;
888   if (fd < 0)
889     return;
890
891   /* Don't use LAZY_RETRIEVE_INFO because xclose() is only called once
892      per socket, so that particular optimization wouldn't work.  */
893   info = NULL;
894   if (transport_map)
895     info = hash_table_get (transport_map, (void *) fd);
896
897   if (info && info->closer)
898     info->closer (fd, info->ctx);
899   else
900     sock_close (fd);
901
902   if (info)
903     {
904       hash_table_remove (transport_map, (void *) fd);
905       xfree (info);
906       ++transport_map_modified_tick;
907     }
908 }