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