]> sjero.net Git - wget/blob - src/connect.c
[svn] Check for struct sockaddr_storage.
[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 #ifdef ENABLE_IPV6
432 # ifdef HAVE_IPV6_V6ONLY
433   if (family == AF_INET6)
434     setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, setopt_ptr, setopt_size);
435 # endif
436 #endif
437
438   xzero (ss);
439   sockaddr_set_data (sa, bind_address, *port);
440   if (bind (sock, sa, sockaddr_size (sa)) < 0)
441     {
442       fd_close (sock);
443       return -1;
444     }
445   DEBUGP (("Local socket fd %d bound.\n", sock));
446
447   /* If *PORT is 0, find out which port we've bound to.  */
448   if (*port == 0)
449     {
450       socklen_t sa_len = sockaddr_size (sa);
451       if (getsockname (sock, sa, &sa_len) < 0)
452         {
453           /* If we can't find out the socket's local address ("name"),
454              something is seriously wrong with the socket, and it's
455              unusable for us anyway because we must know the chosen
456              port.  */
457           fd_close (sock);
458           return -1;
459         }
460       sockaddr_get_data (sa, NULL, port);
461       DEBUGP (("binding to address %s using port %i.\n", 
462                pretty_print_address (bind_address), *port));
463     }
464   if (listen (sock, 1) < 0)
465     {
466       fd_close (sock);
467       return -1;
468     }
469   return sock;
470 }
471
472 /* Like a call to accept(), but with the added check for timeout.
473
474    In other words, accept a client connection on LOCAL_SOCK, and
475    return the new socket used for communication with the client.
476    LOCAL_SOCK should have been bound, e.g. using bind_local().
477
478    The caller is blocked until a connection is established.  If no
479    connection is established for opt.connect_timeout seconds, the
480    function exits with an error status.  */
481
482 int
483 accept_connection (int local_sock)
484 {
485   int sock;
486
487   /* We don't need the values provided by accept, but accept
488      apparently requires them to be present.  */
489   struct sockaddr_storage ss;
490   struct sockaddr *sa = (struct sockaddr *)&ss;
491   socklen_t addrlen = sizeof (ss);
492
493   if (opt.connect_timeout)
494     {
495       int test = select_fd (local_sock, opt.connect_timeout, WAIT_FOR_READ);
496       if (test == 0)
497         errno = ETIMEDOUT;
498       if (test <= 0)
499         return -1;
500     }
501   sock = accept (local_sock, sa, &addrlen);
502   DEBUGP (("Accepted client at socket %d.\n", sock));
503   return sock;
504 }
505
506 /* Get the IP address associated with the connection on FD and store
507    it to IP.  Return 1 on success, 0 otherwise.
508
509    If ENDPOINT is ENDPOINT_LOCAL, it returns the address of the local
510    (client) side of the socket.  Else if ENDPOINT is ENDPOINT_PEER, it
511    returns the address of the remote (peer's) side of the socket.  */
512
513 int
514 socket_ip_address (int sock, ip_address *ip, int endpoint)
515 {
516   struct sockaddr_storage storage;
517   struct sockaddr *sockaddr = (struct sockaddr *)&storage;
518   socklen_t addrlen = sizeof (storage);
519   int ret;
520
521   if (endpoint == ENDPOINT_LOCAL)
522     ret = getsockname (sock, sockaddr, &addrlen);
523   else if (endpoint == ENDPOINT_PEER)
524     ret = getpeername (sock, sockaddr, &addrlen);
525   else
526     abort ();
527   if (ret < 0)
528     return 0;
529
530   switch (sockaddr->sa_family)
531     {
532 #ifdef ENABLE_IPV6
533     case AF_INET6:
534       {
535         struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&storage;
536         ip->type = IPV6_ADDRESS;
537         ADDRESS_IPV6_IN6_ADDR (ip) = sa6->sin6_addr;
538 #ifdef HAVE_SOCKADDR_IN6_SCOPE_ID
539         ADDRESS_IPV6_SCOPE (ip) = sa6->sin6_scope_id;
540 #endif
541         DEBUGP (("conaddr is: %s\n", pretty_print_address (ip)));
542         return 1;
543       }
544 #endif
545     case AF_INET:
546       {
547         struct sockaddr_in *sa = (struct sockaddr_in *)&storage;
548         ip->type = IPV4_ADDRESS;
549         ADDRESS_IPV4_IN_ADDR (ip) = sa->sin_addr;
550         DEBUGP (("conaddr is: %s\n", pretty_print_address (ip)));
551         return 1;
552       }
553     default:
554       abort ();
555     }
556
557   return 0;
558 }
559
560 /* Return non-zero if the error from the connect code can be
561    considered retryable.  Wget normally retries after errors, but the
562    exception are the "unsupported protocol" type errors (possible on
563    IPv4/IPv6 dual family systems) and "connection refused".  */
564
565 int
566 retryable_socket_connect_error (int err)
567 {
568   /* Have to guard against some of these values not being defined.
569      Cannot use a switch statement because some of the values might be
570      equal.  */
571   if (0
572 #ifdef EAFNOSUPPORT
573       || err == EAFNOSUPPORT
574 #endif
575 #ifdef EPFNOSUPPORT
576       || err == EPFNOSUPPORT
577 #endif
578 #ifdef ESOCKTNOSUPPORT          /* no, "sockt" is not a typo! */
579       || err == ESOCKTNOSUPPORT
580 #endif
581 #ifdef EPROTONOSUPPORT
582       || err == EPROTONOSUPPORT
583 #endif
584 #ifdef ENOPROTOOPT
585       || err == ENOPROTOOPT
586 #endif
587       /* Apparently, older versions of Linux and BSD used EINVAL
588          instead of EAFNOSUPPORT and such.  */
589       || err == EINVAL
590       )
591     return 0;
592
593   if (err == ECONNREFUSED && !opt.retry_connrefused)
594     return 0;
595
596   return 1;
597 }
598
599 #ifdef ENABLE_IPV6
600 # ifndef HAVE_GETADDRINFO_AI_ADDRCONFIG
601
602 /* Return non-zero if the INET6 socket family is supported on the
603    system.
604
605    This doesn't guarantee that we're able to connect to IPv6 hosts,
606    but it's better than nothing.  It is only used on systems where
607    getaddrinfo doesn't support AI_ADDRCONFIG.  (See lookup_host.)  */
608
609 int
610 socket_has_inet6 (void)
611 {
612   static int supported = -1;
613   if (supported == -1)
614     {
615       int sock = socket (AF_INET6, SOCK_STREAM, 0);
616       if (sock < 0)
617         supported = 0;
618       else
619         {
620           fd_close (sock);
621           supported = 1;
622         }
623     }
624   return supported;
625 }
626
627 # endif/* not HAVE_GETADDRINFO_AI_ADDRCONFIG */
628 #endif /* ENABLE_IPV6 */
629
630 /* Wait for a single descriptor to become available, timing out after
631    MAXTIME seconds.  Returns 1 if FD is available, 0 for timeout and
632    -1 for error.  The argument WAIT_FOR can be a combination of
633    WAIT_FOR_READ and WAIT_FOR_WRITE.
634
635    This is a mere convenience wrapper around the select call, and
636    should be taken as such (for example, it doesn't implement Wget's
637    0-timeout-means-no-timeout semantics.)  */
638
639 int
640 select_fd (int fd, double maxtime, int wait_for)
641 {
642 #ifdef HAVE_SELECT
643   fd_set fdset;
644   fd_set *rd = NULL, *wr = NULL;
645   struct timeval tmout;
646   int result;
647
648   FD_ZERO (&fdset);
649   FD_SET (fd, &fdset);
650   if (wait_for & WAIT_FOR_READ)
651     rd = &fdset;
652   if (wait_for & WAIT_FOR_WRITE)
653     wr = &fdset;
654
655   tmout.tv_sec = (long) maxtime;
656   tmout.tv_usec = 1000000L * (maxtime - (long) maxtime);
657
658   do
659     result = select (fd + 1, rd, wr, NULL, &tmout);
660   while (result < 0 && errno == EINTR);
661
662   return result;
663
664 #else  /* not HAVE_SELECT */
665
666   /* If select() unavailable, just return 1.  In most usages in Wget,
667      this is the appropriate response -- "if we can't poll, go ahead
668      with the blocking operation".  If a specific part of code needs
669      different behavior, it can use #ifdef HAVE_SELECT to test whether
670      polling really occurs.  */
671   return 1;
672
673 #endif /* not HAVE_SELECT */
674 }
675
676 int
677 test_socket_open (int sock)
678 {
679 #ifdef HAVE_SELECT
680   fd_set check_set;
681   struct timeval to;
682
683   /* Check if we still have a valid (non-EOF) connection.  From Andrew
684    * Maholski's code in the Unix Socket FAQ.  */
685
686   FD_ZERO (&check_set);
687   FD_SET (sock, &check_set);
688
689   /* Wait one microsecond */
690   to.tv_sec = 0;
691   to.tv_usec = 1;
692
693   /* If we get a timeout, then that means still connected */
694   if (select (sock + 1, &check_set, NULL, NULL, &to) == 0)
695     {
696       /* Connection is valid (not EOF), so continue */
697       return 1;
698     }
699   else
700     return 0;
701 #else
702   /* Without select, it's hard to know for sure. */
703   return 1;
704 #endif
705 }
706 \f
707 /* Basic socket operations, mostly EINTR wrappers.  */
708
709 #ifdef WINDOWS
710 # define read(fd, buf, cnt) recv (fd, buf, cnt, 0)
711 # define write(fd, buf, cnt) send (fd, buf, cnt, 0)
712 # define close(fd) closesocket (fd)
713 #endif
714
715 #ifdef __BEOS__
716 # define read(fd, buf, cnt) recv (fd, buf, cnt, 0)
717 # define write(fd, buf, cnt) send (fd, buf, cnt, 0)
718 #endif
719
720 static int
721 sock_read (int fd, char *buf, int bufsize)
722 {
723   int res;
724   do
725     res = read (fd, buf, bufsize);
726   while (res == -1 && errno == EINTR);
727   return res;
728 }
729
730 static int
731 sock_write (int fd, char *buf, int bufsize)
732 {
733   int res;
734   do
735     res = write (fd, buf, bufsize);
736   while (res == -1 && errno == EINTR);
737   return res;
738 }
739
740 static int
741 sock_poll (int fd, double timeout, int wait_for)
742 {
743   return select_fd (fd, timeout, wait_for);
744 }
745
746 static int
747 sock_peek (int fd, char *buf, int bufsize)
748 {
749   int res;
750   do
751     res = recv (fd, buf, bufsize, MSG_PEEK);
752   while (res == -1 && errno == EINTR);
753   return res;
754 }
755
756 static void
757 sock_close (int fd)
758 {
759   close (fd);
760   DEBUGP (("Closed fd %d\n", fd));
761 }
762 #undef read
763 #undef write
764 #undef close
765 \f
766 /* Reading and writing from the network.  We build around the socket
767    (file descriptor) API, but support "extended" operations for things
768    that are not mere file descriptors under the hood, such as SSL
769    sockets.
770
771    That way the user code can call fd_read(fd, ...) and we'll run read
772    or SSL_read or whatever is necessary.  */
773
774 static struct hash_table *transport_map;
775 static int transport_map_modified_tick;
776
777 struct transport_info {
778   fd_reader_t reader;
779   fd_writer_t writer;
780   fd_poller_t poller;
781   fd_peeker_t peeker;
782   fd_closer_t closer;
783   void *ctx;
784 };
785
786 /* Register the transport layer operations that will be used when
787    reading, writing, and polling FD.
788
789    This should be used for transport layers like SSL that piggyback on
790    sockets.  FD should otherwise be a real socket, on which you can
791    call getpeername, etc.  */
792
793 void
794 fd_register_transport (int fd, fd_reader_t reader, fd_writer_t writer,
795                        fd_poller_t poller, fd_peeker_t peeker,
796                        fd_closer_t closer, void *ctx)
797 {
798   struct transport_info *info;
799
800   /* The file descriptor must be non-negative to be registered.
801      Negative values are ignored by fd_close(), and -1 cannot be used as
802      hash key.  */
803   assert (fd >= 0);
804
805   info = xnew (struct transport_info);
806   info->reader = reader;
807   info->writer = writer;
808   info->poller = poller;
809   info->peeker = peeker;
810   info->closer = closer;
811   info->ctx = ctx;
812   if (!transport_map)
813     transport_map = hash_table_new (0, NULL, NULL);
814   hash_table_put (transport_map, (void *) fd, info);
815   ++transport_map_modified_tick;
816 }
817
818 /* When fd_read/fd_write are called multiple times in a loop, they should
819    remember the INFO pointer instead of fetching it every time.  It is
820    not enough to compare FD to LAST_FD because FD might have been
821    closed and reopened.  modified_tick ensures that changes to
822    transport_map will not be unnoticed.
823
824    This is a macro because we want the static storage variables to be
825    per-function.  */
826
827 #define LAZY_RETRIEVE_INFO(info) do {                                   \
828   static struct transport_info *last_info;                              \
829   static int last_fd = -1, last_tick;                                   \
830   if (!transport_map)                                                   \
831     info = NULL;                                                        \
832   else if (last_fd == fd && last_tick == transport_map_modified_tick)   \
833     info = last_info;                                                   \
834   else                                                                  \
835     {                                                                   \
836       info = hash_table_get (transport_map, (void *) fd);               \
837       last_fd = fd;                                                     \
838       last_info = info;                                                 \
839       last_tick = transport_map_modified_tick;                          \
840     }                                                                   \
841 } while (0)
842
843 static int
844 poll_internal (int fd, struct transport_info *info, int wf, double timeout)
845 {
846   if (timeout == -1)
847     timeout = opt.read_timeout;
848   if (timeout)
849     {
850       int test;
851       if (info && info->poller)
852         test = info->poller (fd, timeout, wf, info->ctx);
853       else
854         test = sock_poll (fd, timeout, wf);
855       if (test == 0)
856         errno = ETIMEDOUT;
857       if (test <= 0)
858         return 0;
859     }
860   return 1;
861 }
862
863 /* Read no more than BUFSIZE bytes of data from FD, storing them to
864    BUF.  If TIMEOUT is non-zero, the operation aborts if no data is
865    received after that many seconds.  If TIMEOUT is -1, the value of
866    opt.timeout is used for TIMEOUT.  */
867
868 int
869 fd_read (int fd, char *buf, int bufsize, double timeout)
870 {
871   struct transport_info *info;
872   LAZY_RETRIEVE_INFO (info);
873   if (!poll_internal (fd, info, WAIT_FOR_READ, timeout))
874     return -1;
875   if (info && info->reader)
876     return info->reader (fd, buf, bufsize, info->ctx);
877   else
878     return sock_read (fd, buf, bufsize);
879 }
880
881 /* The same as xread, but don't actually read the data, just copy it
882    instead.  */
883
884 int
885 fd_peek (int fd, char *buf, int bufsize, double timeout)
886 {
887   struct transport_info *info;
888   LAZY_RETRIEVE_INFO (info);
889   if (!poll_internal (fd, info, WAIT_FOR_READ, timeout))
890     return -1;
891   if (info && info->peeker)
892     return info->peeker (fd, buf, bufsize, info->ctx);
893   else
894     return sock_peek (fd, buf, bufsize);
895 }
896
897 /* Write the entire contents of BUF to FD.  If TIMEOUT is non-zero,
898    the operation aborts if no data is received after that many
899    seconds.  If TIMEOUT is -1, the value of opt.timeout is used for
900    TIMEOUT.  */
901
902 int
903 fd_write (int fd, char *buf, int bufsize, double timeout)
904 {
905   int res;
906   struct transport_info *info;
907   LAZY_RETRIEVE_INFO (info);
908
909   /* `write' may write less than LEN bytes, thus the loop keeps trying
910      it until all was written, or an error occurred.  */
911   res = 0;
912   while (bufsize > 0)
913     {
914       if (!poll_internal (fd, info, WAIT_FOR_WRITE, timeout))
915         return -1;
916       if (info && info->writer)
917         res = info->writer (fd, buf, bufsize, info->ctx);
918       else
919         res = sock_write (fd, buf, bufsize);
920       if (res <= 0)
921         break;
922       buf += res;
923       bufsize -= res;
924     }
925   return res;
926 }
927
928 /* Close the file descriptor FD.  */
929
930 void
931 fd_close (int fd)
932 {
933   struct transport_info *info;
934   if (fd < 0)
935     return;
936
937   /* Don't use LAZY_RETRIEVE_INFO because fd_close() is only called once
938      per socket, so that particular optimization wouldn't work.  */
939   info = NULL;
940   if (transport_map)
941     info = hash_table_get (transport_map, (void *) fd);
942
943   if (info && info->closer)
944     info->closer (fd, info->ctx);
945   else
946     sock_close (fd);
947
948   if (info)
949     {
950       hash_table_remove (transport_map, (void *) fd);
951       xfree (info);
952       ++transport_map_modified_tick;
953     }
954 }