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