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