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