]> sjero.net Git - wget/blob - src/connect.c
[svn] Remove the "rbuf" buffering layer. Provide peeking primitives instead.
[wget] / src / connect.c
1 /* Establishing and handling network connections.
2    Copyright (C) 1995, 1996, 1997, 2001, 2002 Free Software Foundation, Inc.
3
4 This file is part of GNU Wget.
5
6 GNU Wget is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10
11 GNU Wget is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Wget; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
20 In addition, as a special exception, the Free Software Foundation
21 gives permission to link the code of its release of Wget with the
22 OpenSSL project's "OpenSSL" library (or with modified versions of it
23 that use the same license as the "OpenSSL" library), and distribute
24 the linked executables.  You must obey the GNU General Public License
25 in all respects for all of the code used other than "OpenSSL".  If you
26 modify this file, you may extend this exception to your version of the
27 file, but you are not obligated to do so.  If you do not wish to do
28 so, delete this exception statement from your version.  */
29
30 #include <config.h>
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <sys/types.h>
35 #ifdef HAVE_UNISTD_H
36 # include <unistd.h>
37 #endif
38 #include <assert.h>
39
40 #ifndef WINDOWS
41 # include <sys/socket.h>
42 # include <netdb.h>
43 # include <netinet/in.h>
44 # ifndef __BEOS__
45 #  include <arpa/inet.h>
46 # endif
47 #endif /* not WINDOWS */
48
49 #include <errno.h>
50 #ifdef HAVE_STRING_H
51 # include <string.h>
52 #else
53 # include <strings.h>
54 #endif /* HAVE_STRING_H */
55 #ifdef HAVE_SYS_SELECT_H
56 # include <sys/select.h>
57 #endif /* HAVE_SYS_SELECT_H */
58
59 #include "wget.h"
60 #include "utils.h"
61 #include "host.h"
62 #include "connect.h"
63 #include "hash.h"
64
65 #ifndef errno
66 extern int errno;
67 #endif
68
69 \f
70 /* Fill SA as per the data in IP and PORT.  SA shoult point to struct
71    sockaddr_storage if ENABLE_IPV6 is defined, to struct sockaddr_in
72    otherwise.  */
73
74 static void
75 sockaddr_set_data (struct sockaddr *sa, const ip_address *ip, int port)
76 {
77   switch (ip->type)
78     {
79     case IPV4_ADDRESS:
80       {
81         struct sockaddr_in *sin = (struct sockaddr_in *)sa;
82         sin->sin_family = AF_INET;
83         sin->sin_port = htons (port);
84         sin->sin_addr = ADDRESS_IPV4_IN_ADDR (ip);
85         break;
86       }
87 #ifdef ENABLE_IPV6
88     case IPV6_ADDRESS:
89       {
90         struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
91         sin6->sin6_family = AF_INET6;
92         sin6->sin6_port = htons (port);
93         sin6->sin6_addr = ADDRESS_IPV6_IN6_ADDR (ip);
94 #ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
95         sin6->sin6_scope_id = ADDRESS_IPV6_SCOPE (ip);
96 #endif
97         break;
98       }
99 #endif /* ENABLE_IPV6 */
100     default:
101       abort ();
102     }
103 }
104
105 /* Get the data of SA, specifically the IP address and the port.  If
106    you're not interested in one or the other information, pass NULL as
107    the pointer.  */
108
109 static void
110 sockaddr_get_data (const struct sockaddr *sa, ip_address *ip, int *port)
111 {
112   switch (sa->sa_family)
113     {
114     case AF_INET:
115       {
116         struct sockaddr_in *sin = (struct sockaddr_in *)sa;
117         if (ip)
118           {
119             ip->type = IPV4_ADDRESS;
120             ADDRESS_IPV4_IN_ADDR (ip) = sin->sin_addr;
121           }
122         if (port)
123           *port = ntohs (sin->sin_port);
124         break;
125       }
126 #ifdef ENABLE_IPV6
127     case AF_INET6:
128       {
129         struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
130         if (ip)
131           {
132             ip->type = IPV6_ADDRESS;
133             ADDRESS_IPV6_IN6_ADDR (ip) = sin6->sin6_addr;
134 #ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
135             ADDRESS_IPV6_SCOPE (ip) = sin6->sin6_scope_id;
136 #endif
137           }
138         if (port)
139           *port = ntohs (sin6->sin6_port);
140         break;
141       }
142 #endif
143     default:
144       abort ();
145     }
146 }
147
148 /* Return the size of the sockaddr structure depending on its
149    family.  */
150
151 static socklen_t
152 sockaddr_size (const struct sockaddr *sa)
153 {
154   switch (sa->sa_family)
155     {
156     case AF_INET:
157       return sizeof (struct sockaddr_in);
158 #ifdef ENABLE_IPV6
159     case AF_INET6:
160       return sizeof (struct sockaddr_in6);
161 #endif
162     default:
163       abort ();
164       return 0;                 /* so the compiler shuts up. */
165     }
166 }
167 \f
168 static int
169 resolve_bind_address (struct sockaddr *sa)
170 {
171   struct address_list *al;
172
173   /* Make sure this is called only once.  opt.bind_address doesn't
174      change during a Wget run.  */
175   static int called, should_bind;
176   static ip_address ip;
177   if (called)
178     {
179       if (should_bind)
180         sockaddr_set_data (sa, &ip, 0);
181       return should_bind;
182     }
183   called = 1;
184
185   al = lookup_host (opt.bind_address, LH_BIND | LH_SILENT);
186   if (!al)
187     {
188       /* #### We should be able to print the error message here. */
189       logprintf (LOG_NOTQUIET,
190                  _("%s: unable to resolve bind address `%s'; disabling bind.\n"),
191                  exec_name, opt.bind_address);
192       should_bind = 0;
193       return 0;
194     }
195
196   /* Pick the first address in the list and use it as bind address.
197      Perhaps we should try multiple addresses in succession, but I
198      don't think that's necessary in practice.  */
199   ip = *address_list_address_at (al, 0);
200   address_list_release (al);
201
202   sockaddr_set_data (sa, &ip, 0);
203   should_bind = 1;
204   return 1;
205 }
206 \f
207 struct cwt_context {
208   int fd;
209   const struct sockaddr *addr;
210   socklen_t addrlen;
211   int result;
212 };
213
214 static void
215 connect_with_timeout_callback (void *arg)
216 {
217   struct cwt_context *ctx = (struct cwt_context *)arg;
218   ctx->result = connect (ctx->fd, ctx->addr, ctx->addrlen);
219 }
220
221 /* Like connect, but specifies a timeout.  If connecting takes longer
222    than TIMEOUT seconds, -1 is returned and errno is set to
223    ETIMEDOUT.  */
224
225 static int
226 connect_with_timeout (int fd, const struct sockaddr *addr, socklen_t addrlen,
227                       double timeout)
228 {
229   struct cwt_context ctx;
230   ctx.fd = fd;
231   ctx.addr = addr;
232   ctx.addrlen = addrlen;
233
234   if (run_with_timeout (timeout, connect_with_timeout_callback, &ctx))
235     {
236       errno = ETIMEDOUT;
237       return -1;
238     }
239   if (ctx.result == -1 && errno == EINTR)
240     errno = ETIMEDOUT;
241   return ctx.result;
242 }
243 \f
244 /* Connect 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 = -1;
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,
263                    _("Connecting to %s|%s|:%d... "), 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   /* For very small rate limits, set the buffer size (and hence,
277      hopefully, the kernel's TCP window size) to the per-second limit.
278      That way we should never have to sleep for more than 1s between
279      network reads.  */
280   if (opt.limit_rate && opt.limit_rate < 8192)
281     {
282       int bufsize = opt.limit_rate;
283       if (bufsize < 512)
284         bufsize = 512;          /* avoid pathologically small values */
285 #ifdef SO_RCVBUF
286       setsockopt (sock, SOL_SOCKET, SO_RCVBUF,
287                   (void *)&bufsize, (socklen_t)sizeof (bufsize));
288 #endif
289       /* When we add limit_rate support for writing, which is useful
290          for POST, we should also set SO_SNDBUF here.  */
291     }
292
293   if (opt.bind_address)
294     {
295       /* Bind the client side of the socket to the requested
296          address.  */
297       struct sockaddr_storage bind_ss;
298       struct sockaddr *bind_sa = (struct sockaddr *)&bind_ss;
299       if (resolve_bind_address (bind_sa))
300         {
301           if (bind (sock, bind_sa, sockaddr_size (bind_sa)) < 0)
302             goto err;
303         }
304     }
305
306   /* Connect the socket to the remote endpoint.  */
307   if (connect_with_timeout (sock, sa, sockaddr_size (sa),
308                             opt.connect_timeout) < 0)
309     goto err;
310
311   /* Success. */
312   assert (sock >= 0);
313   if (print)
314     logprintf (LOG_VERBOSE, _("connected.\n"));
315   DEBUGP (("Created socket %d.\n", sock));
316   return sock;
317
318  err:
319   {
320     /* Protect errno from possible modifications by close and
321        logprintf.  */
322     int save_errno = errno;
323     if (sock >= 0)
324       fd_close (sock);
325     if (print)
326       logprintf (LOG_VERBOSE, "failed: %s.\n", strerror (errno));
327     errno = save_errno;
328     return -1;
329   }
330 }
331
332 /* Connect via TCP to a remote host on the specified port.
333
334    HOST is resolved as an Internet host name.  If HOST resolves to
335    more than one IP address, they are tried in the order returned by
336    DNS until connecting to one of them succeeds.  */
337
338 int
339 connect_to_host (const char *host, int port)
340 {
341   int i, start, end;
342   int sock;
343
344   struct address_list *al = lookup_host (host, 0);
345
346  retry:
347   if (!al)
348     return E_HOST;
349
350   address_list_get_bounds (al, &start, &end);
351   for (i = start; i < end; i++)
352     {
353       const ip_address *ip = address_list_address_at (al, i);
354       sock = connect_to_ip (ip, port, host);
355       if (sock >= 0)
356         {
357           /* Success. */
358           address_list_set_connected (al);
359           address_list_release (al);
360           return sock;
361         }
362
363       /* The attempt to connect has failed.  Continue with the loop
364          and try next address. */
365
366       address_list_set_faulty (al, i);
367     }
368
369   /* Failed to connect to any of the addresses in AL. */
370
371   if (address_list_connected_p (al))
372     {
373       /* We connected to AL before, but cannot do so now.  That might
374          indicate that our DNS cache entry for HOST has expired.  */
375       address_list_release (al);
376       al = lookup_host (host, LH_REFRESH);
377       goto retry;
378     }
379   address_list_release (al);
380
381   return -1;
382 }
383 \f
384 /* Create a socket, bind it to local interface BIND_ADDRESS on port
385    *PORT, set up a listen backlog, and return the resulting socket, or
386    -1 in case of error.
387
388    BIND_ADDRESS is the address of the interface to bind to.  If it is
389    NULL, the socket is bound to the default address.  PORT should
390    point to the port number that will be used for the binding.  If
391    that number is 0, the system will choose a suitable port, and the
392    chosen value will be written to *PORT.
393
394    Calling accept() on such a socket waits for and accepts incoming
395    TCP connections.  */
396
397 int
398 bind_local (const ip_address *bind_address, int *port)
399 {
400   int sock;
401   int family = AF_INET;
402   struct sockaddr_storage ss;
403   struct sockaddr *sa = (struct sockaddr *)&ss;
404
405   /* For setting options with setsockopt. */
406   int setopt_val = 1;
407   void *setopt_ptr = (void *)&setopt_val;
408   socklen_t setopt_size = sizeof (setopt_val);
409
410 #ifdef ENABLE_IPV6
411   if (bind_address->type == IPV6_ADDRESS) 
412     family = AF_INET6;
413 #endif
414
415   sock = socket (family, SOCK_STREAM, 0);
416   if (sock < 0)
417     return -1;
418
419 #ifdef SO_REUSEADDR
420   setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, setopt_ptr, setopt_size);
421 #endif
422
423 #ifdef ENABLE_IPV6
424 # ifdef HAVE_IPV6_V6ONLY
425   if (family == AF_INET6)
426     setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, setopt_ptr, setopt_size);
427 # endif
428 #endif
429
430   xzero (ss);
431   sockaddr_set_data (sa, bind_address, *port);
432   if (bind (sock, sa, sockaddr_size (sa)) < 0)
433     {
434       fd_close (sock);
435       return -1;
436     }
437   DEBUGP (("Local socket fd %d bound.\n", sock));
438
439   /* If *PORT is 0, find out which port we've bound to.  */
440   if (*port == 0)
441     {
442       socklen_t sa_len = sockaddr_size (sa);
443       if (getsockname (sock, sa, &sa_len) < 0)
444         {
445           /* If we can't find out the socket's local address ("name"),
446              something is seriously wrong with the socket, and it's
447              unusable for us anyway because we must know the chosen
448              port.  */
449           fd_close (sock);
450           return -1;
451         }
452       sockaddr_get_data (sa, NULL, port);
453       DEBUGP (("binding to address %s using port %i.\n", 
454                pretty_print_address (bind_address), *port));
455     }
456   if (listen (sock, 1) < 0)
457     {
458       fd_close (sock);
459       return -1;
460     }
461   return sock;
462 }
463
464 /* Like a call to accept(), but with the added check for timeout.
465
466    In other words, accept a client connection on LOCAL_SOCK, and
467    return the new socket used for communication with the client.
468    LOCAL_SOCK should have been bound, e.g. using bind_local().
469
470    The caller is blocked until a connection is established.  If no
471    connection is established for opt.connect_timeout seconds, the
472    function exits with an error status.  */
473
474 int
475 accept_connection (int local_sock)
476 {
477   int sock;
478
479   /* We don't need the values provided by accept, but accept
480      apparently requires them to be present.  */
481   struct sockaddr_storage ss;
482   struct sockaddr *sa = (struct sockaddr *)&ss;
483   socklen_t addrlen = sizeof (ss);
484
485   if (opt.connect_timeout)
486     {
487       int test = select_fd (local_sock, opt.connect_timeout, WAIT_FOR_READ);
488       if (test == 0)
489         errno = ETIMEDOUT;
490       if (test <= 0)
491         return -1;
492     }
493   sock = accept (local_sock, sa, &addrlen);
494   DEBUGP (("Accepted client at socket %d.\n", sock));
495   return sock;
496 }
497
498 /* Get the IP address associated with the connection on FD and store
499    it to IP.  Return 1 on success, 0 otherwise.
500
501    If ENDPOINT is ENDPOINT_LOCAL, it returns the address of the local
502    (client) side of the socket.  Else if ENDPOINT is ENDPOINT_PEER, it
503    returns the address of the remote (peer's) side of the socket.  */
504
505 int
506 socket_ip_address (int sock, ip_address *ip, int endpoint)
507 {
508   struct sockaddr_storage storage;
509   struct sockaddr *sockaddr = (struct sockaddr *)&storage;
510   socklen_t addrlen = sizeof (storage);
511   int ret;
512
513   if (endpoint == ENDPOINT_LOCAL)
514     ret = getsockname (sock, sockaddr, &addrlen);
515   else if (endpoint == ENDPOINT_PEER)
516     ret = getpeername (sock, sockaddr, &addrlen);
517   else
518     abort ();
519   if (ret < 0)
520     return 0;
521
522   switch (sockaddr->sa_family)
523     {
524 #ifdef ENABLE_IPV6
525     case AF_INET6:
526       {
527         struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&storage;
528         ip->type = IPV6_ADDRESS;
529         ADDRESS_IPV6_IN6_ADDR (ip) = sa6->sin6_addr;
530 #ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
531         ADDRESS_IPV6_SCOPE (ip) = sa6->sin6_scope_id;
532 #endif
533         DEBUGP (("conaddr is: %s\n", pretty_print_address (ip)));
534         return 1;
535       }
536 #endif
537     case AF_INET:
538       {
539         struct sockaddr_in *sa = (struct sockaddr_in *)&storage;
540         ip->type = IPV4_ADDRESS;
541         ADDRESS_IPV4_IN_ADDR (ip) = sa->sin_addr;
542         DEBUGP (("conaddr is: %s\n", pretty_print_address (ip)));
543         return 1;
544       }
545     default:
546       abort ();
547     }
548
549   return 0;
550 }
551
552 /* Return non-zero if the error from the connect code can be
553    considered retryable.  Wget normally retries after errors, but the
554    exception are the "unsupported protocol" type errors (possible on
555    IPv4/IPv6 dual family systems) and "connection refused".  */
556
557 int
558 retryable_socket_connect_error (int err)
559 {
560   /* Have to guard against some of these values not being defined.
561      Cannot use a switch statement because some of the values might be
562      equal.  */
563   if (0
564 #ifdef EAFNOSUPPORT
565       || err == EAFNOSUPPORT
566 #endif
567 #ifdef EPFNOSUPPORT
568       || err == EPFNOSUPPORT
569 #endif
570 #ifdef ESOCKTNOSUPPORT          /* no, "sockt" is not a typo! */
571       || err == ESOCKTNOSUPPORT
572 #endif
573 #ifdef EPROTONOSUPPORT
574       || err == EPROTONOSUPPORT
575 #endif
576 #ifdef ENOPROTOOPT
577       || err == ENOPROTOOPT
578 #endif
579       /* Apparently, older versions of Linux and BSD used EINVAL
580          instead of EAFNOSUPPORT and such.  */
581       || err == EINVAL
582       )
583     return 0;
584
585   if (err == ECONNREFUSED && !opt.retry_connrefused)
586     return 0;
587
588   return 1;
589 }
590
591 #ifdef ENABLE_IPV6
592 # ifndef HAVE_GETADDRINFO_AI_ADDRCONFIG
593
594 /* Return non-zero if the INET6 socket family is supported on the
595    system.
596
597    This doesn't guarantee that we're able to connect to IPv6 hosts,
598    but it's better than nothing.  It is only used on systems where
599    getaddrinfo doesn't support AI_ADDRCONFIG.  (See lookup_host.)  */
600
601 int
602 socket_has_inet6 (void)
603 {
604   static int supported = -1;
605   if (supported == -1)
606     {
607       int sock = socket (AF_INET6, SOCK_STREAM, 0);
608       if (sock < 0)
609         supported = 0;
610       else
611         {
612           fd_close (sock);
613           supported = 1;
614         }
615     }
616   return supported;
617 }
618
619 # endif/* not HAVE_GETADDRINFO_AI_ADDRCONFIG */
620 #endif /* ENABLE_IPV6 */
621
622 /* Wait for a single descriptor to become available, timing out after
623    MAXTIME seconds.  Returns 1 if FD is available, 0 for timeout and
624    -1 for error.  The argument WAIT_FOR can be a combination of
625    WAIT_FOR_READ and WAIT_FOR_WRITE.
626
627    This is a mere convenience wrapper around the select call, and
628    should be taken as such (for example, it doesn't implement Wget's
629    0-timeout-means-no-timeout semantics.)  */
630
631 int
632 select_fd (int fd, double maxtime, int wait_for)
633 {
634 #ifdef HAVE_SELECT
635   fd_set fdset;
636   fd_set *rd = NULL, *wr = NULL;
637   struct timeval tmout;
638   int result;
639
640   FD_ZERO (&fdset);
641   FD_SET (fd, &fdset);
642   if (wait_for & WAIT_FOR_READ)
643     rd = &fdset;
644   if (wait_for & WAIT_FOR_WRITE)
645     wr = &fdset;
646
647   tmout.tv_sec = (long) maxtime;
648   tmout.tv_usec = 1000000L * (maxtime - (long) maxtime);
649
650   do
651     result = select (fd + 1, rd, wr, NULL, &tmout);
652   while (result < 0 && errno == EINTR);
653
654   return result;
655
656 #else  /* not HAVE_SELECT */
657
658   /* If select() unavailable, just return 1.  In most usages in Wget,
659      this is the appropriate response -- "if we can't poll, go ahead
660      with the blocking operation".  If a specific part of code needs
661      different behavior, it can use #ifdef HAVE_SELECT to test whether
662      polling really occurs.  */
663   return 1;
664
665 #endif /* not HAVE_SELECT */
666 }
667
668 int
669 test_socket_open (int sock)
670 {
671 #ifdef HAVE_SELECT
672   fd_set check_set;
673   struct timeval to;
674
675   /* Check if we still have a valid (non-EOF) connection.  From Andrew
676    * Maholski's code in the Unix Socket FAQ.  */
677
678   FD_ZERO (&check_set);
679   FD_SET (sock, &check_set);
680
681   /* Wait one microsecond */
682   to.tv_sec = 0;
683   to.tv_usec = 1;
684
685   /* If we get a timeout, then that means still connected */
686   if (select (sock + 1, &check_set, NULL, NULL, &to) == 0)
687     {
688       /* Connection is valid (not EOF), so continue */
689       return 1;
690     }
691   else
692     return 0;
693 #else
694   /* Without select, it's hard to know for sure. */
695   return 1;
696 #endif
697 }
698 \f
699 /* Basic socket operations, mostly EINTR wrappers.  */
700
701 #ifdef WINDOWS
702 # define read(fd, buf, cnt) recv (fd, buf, cnt, 0)
703 # define write(fd, buf, cnt) send (fd, buf, cnt, 0)
704 # define close(fd) closesocket (fd)
705 #endif
706
707 #ifdef __BEOS__
708 # define read(fd, buf, cnt) recv (fd, buf, cnt, 0)
709 # define write(fd, buf, cnt) send (fd, buf, cnt, 0)
710 #endif
711
712 static int
713 sock_read (int fd, char *buf, int bufsize)
714 {
715   int res;
716   do
717     res = read (fd, buf, bufsize);
718   while (res == -1 && errno == EINTR);
719   return res;
720 }
721
722 static int
723 sock_write (int fd, char *buf, int bufsize)
724 {
725   int res;
726   do
727     res = write (fd, buf, bufsize);
728   while (res == -1 && errno == EINTR);
729   return res;
730 }
731
732 static int
733 sock_poll (int fd, double timeout, int wait_for)
734 {
735   return select_fd (fd, timeout, wait_for);
736 }
737
738 static int
739 sock_peek (int fd, char *buf, int bufsize)
740 {
741   int res;
742   do
743     res = recv (fd, buf, bufsize, MSG_PEEK);
744   while (res == -1 && errno == EINTR);
745   return res;
746 }
747
748 static void
749 sock_close (int fd)
750 {
751   close (fd);
752   DEBUGP (("Closed fd %d\n", fd));
753 }
754 #undef read
755 #undef write
756 #undef close
757 \f
758 /* Reading and writing from the network.  We build around the socket
759    (file descriptor) API, but support "extended" operations for things
760    that are not mere file descriptors under the hood, such as SSL
761    sockets.
762
763    That way the user code can call fd_read(fd, ...) and we'll run read
764    or SSL_read or whatever is necessary.  */
765
766 static struct hash_table *transport_map;
767 static int transport_map_modified_tick;
768
769 struct transport_info {
770   fd_reader_t reader;
771   fd_writer_t writer;
772   fd_poller_t poller;
773   fd_peeker_t peeker;
774   fd_closer_t closer;
775   void *ctx;
776 };
777
778 /* Register the transport layer operations that will be used when
779    reading, writing, and polling FD.
780
781    This should be used for transport layers like SSL that piggyback on
782    sockets.  FD should otherwise be a real socket, on which you can
783    call getpeername, etc.  */
784
785 void
786 fd_register_transport (int fd, fd_reader_t reader, fd_writer_t writer,
787                        fd_poller_t poller, fd_peeker_t peeker,
788                        fd_closer_t closer, void *ctx)
789 {
790   struct transport_info *info;
791
792   /* The file descriptor must be non-negative to be registered.
793      Negative values are ignored by fd_close(), and -1 cannot be used as
794      hash key.  */
795   assert (fd >= 0);
796
797   info = xnew (struct transport_info);
798   info->reader = reader;
799   info->writer = writer;
800   info->poller = poller;
801   info->peeker = peeker;
802   info->closer = closer;
803   info->ctx = ctx;
804   if (!transport_map)
805     transport_map = hash_table_new (0, NULL, NULL);
806   hash_table_put (transport_map, (void *) fd, info);
807   ++transport_map_modified_tick;
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 /* The same as xread, but don't actually read the data, just copy it
874    instead.  */
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 }