7fd6f6c47eb7773beff577d1e6a88b297a1db91d
[oweals/gnunet.git] / src / util / network.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 2, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file util/network/network.c
23  * @brief basic, low-level TCP networking interface
24  * @author Christian Grothoff
25  *
26  * This code is rather complex.  Only modify it if you
27  * 1) Have a NEW testcase showing that the new code
28  *    is needed and correct
29  * 2) All EXISTING testcases pass with the new code
30  * These rules should apply in general, but for this
31  * module they are VERY, VERY important.
32  *
33  * TODO:
34  * - can we merge receive_ready and receive_again?
35  * - can we integrate the nth.timeout_task with the write_task's timeout?
36  */
37
38 #include "platform.h"
39 #include "gnunet_common.h"
40 #include "gnunet_network_lib.h"
41 #include "gnunet_scheduler_lib.h"
42
43 #define DEBUG_NETWORK GNUNET_NO
44
45 struct GNUNET_NETWORK_TransmitHandle
46 {
47
48   /**
49    * Function to call if the send buffer has notify_size
50    * bytes available.
51    */
52   GNUNET_NETWORK_TransmitReadyNotify notify_ready;
53
54   /**
55    * Closure for notify_ready.
56    */
57   void *notify_ready_cls;
58
59   /**
60    * Our socket handle.
61    */
62   struct GNUNET_NETWORK_SocketHandle *sh;
63
64   /**
65    * Timeout for receiving (in absolute time).
66    */
67   struct GNUNET_TIME_Absolute transmit_timeout;
68
69   /**
70    * Task called on timeout.
71    */
72   GNUNET_SCHEDULER_TaskIdentifier timeout_task;
73
74   /**
75    * At what number of bytes available in the
76    * write buffer should the notify method be called?
77    */
78   size_t notify_size;
79
80 };
81
82 /**
83  * @brief handle for a network socket
84  */
85 struct GNUNET_NETWORK_SocketHandle
86 {
87
88   /**
89    * Scheduler that was used for the connect task.
90    */
91   struct GNUNET_SCHEDULER_Handle *sched;
92
93   /**
94    * Address information for connect (may be NULL).
95    */
96   struct addrinfo *ai;
97
98   /**
99    * Index for the next struct addrinfo for connect attempts (may be NULL)
100    */
101   struct addrinfo *ai_pos;
102
103   /**
104    * Network address of the other end-point, may be NULL.
105    */
106   struct sockaddr *addr;
107
108   /**
109    * Pointer to our write buffer.
110    */
111   char *write_buffer;
112
113   /**
114    * Size of our write buffer.
115    */
116   size_t write_buffer_size;
117
118   /**
119    * Current write-offset in write buffer (where
120    * would we write next).
121    */
122   size_t write_buffer_off;
123
124   /**
125    * Current read-offset in write buffer (how many
126    * bytes have already been send).
127    */
128   size_t write_buffer_pos;
129
130   /**
131    * Length of addr.
132    */
133   socklen_t addrlen;
134
135   /**
136    * Connect task that we may need to wait for.
137    */
138   GNUNET_SCHEDULER_TaskIdentifier connect_task;
139
140   /**
141    * Read task that we may need to wait for.
142    */
143   GNUNET_SCHEDULER_TaskIdentifier read_task;
144
145   /**
146    * Write task that we may need to wait for.
147    */
148   GNUNET_SCHEDULER_TaskIdentifier write_task;
149
150   /**
151    * The handle we return for GNUNET_NETWORK_notify_transmit_ready.
152    */
153   struct GNUNET_NETWORK_TransmitHandle nth;
154
155   /**
156    * Underlying OS's socket, set to -1 after fatal errors.
157    */
158   int sock;
159
160   /**
161    * Port to connect to.
162    */
163   uint16_t port;
164
165   /**
166    * Function to call on data received, NULL
167    * if no receive is pending.
168    */
169   GNUNET_NETWORK_Receiver receiver;
170
171   /**
172    * Closure for receiver.
173    */
174   void *receiver_cls;
175
176   /**
177    * Timeout for receiving (in absolute time).
178    */
179   struct GNUNET_TIME_Absolute receive_timeout;
180
181   /**
182    * Maximum number of bytes to read
183    * (for receiving).
184    */
185   size_t max;
186
187 };
188
189
190 /**
191  * Create a socket handle by boxing an existing OS socket.  The OS
192  * socket should henceforth be no longer used directly.
193  * GNUNET_socket_destroy will close it.
194  *
195  * @param sched scheduler to use
196  * @param osSocket existing socket to box
197  * @param maxbuf maximum write buffer size for the socket (use
198  *        0 for sockets that need no write buffers, such as listen sockets)
199  * @return the boxed socket handle
200  */
201 struct GNUNET_NETWORK_SocketHandle *
202 GNUNET_NETWORK_socket_create_from_existing (struct GNUNET_SCHEDULER_Handle
203                                             *sched, int osSocket,
204                                             size_t maxbuf)
205 {
206   struct GNUNET_NETWORK_SocketHandle *ret;
207   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_SocketHandle) + maxbuf);
208   ret->write_buffer = (char *) &ret[1];
209   ret->write_buffer_size = maxbuf;
210   ret->sock = osSocket;
211   ret->sched = sched;
212   return ret;
213 }
214
215
216 /**
217  * Create a socket handle by accepting on a listen socket.  This
218  * function may block if the listen socket has no connection ready.
219  *
220  * @param sched scheduler to use
221  * @param access function to use to check if access is allowed
222  * @param access_cls closure for access
223  * @param lsock listen socket
224  * @param maxbuf maximum write buffer size for the socket (use
225  *        0 for sockets that need no write buffers, such as listen sockets)
226  * @return the socket handle, NULL on error
227  */
228 struct GNUNET_NETWORK_SocketHandle *
229 GNUNET_NETWORK_socket_create_from_accept (struct GNUNET_SCHEDULER_Handle
230                                           *sched,
231                                           GNUNET_NETWORK_AccessCheck access,
232                                           void *access_cls, int lsock,
233                                           size_t maxbuf)
234 {
235   struct GNUNET_NETWORK_SocketHandle *ret;
236   char addr[32];
237   char msg[INET6_ADDRSTRLEN];
238   socklen_t addrlen;
239   int fam;
240   int fd;
241   int aret;
242   struct sockaddr_in *v4;
243   struct sockaddr_in6 *v6;
244   struct sockaddr *sa;
245   void *uaddr;
246
247   addrlen = sizeof (addr);
248   fd = accept (lsock, (struct sockaddr *) &addr, &addrlen);
249   if (fd == -1)
250     {
251       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "accept");
252       return NULL;
253     }
254   if (0 != fcntl (fd, F_SETFD, fcntl (fd, F_GETFD) | FD_CLOEXEC))
255     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
256                          "fcntl");
257   if (addrlen > sizeof (addr))
258     {
259       GNUNET_break (0);
260       GNUNET_break (0 == CLOSE (fd));
261       return NULL;
262     }
263
264   sa = (struct sockaddr *) addr;
265   v6 = (struct sockaddr_in6 *) addr;
266   if ((sa->sa_family == AF_INET6) && (IN6_IS_ADDR_V4MAPPED (&v6->sin6_addr)))
267     {
268       /* convert to V4 address */
269       v4 = GNUNET_malloc (sizeof (struct sockaddr_in));
270       memset (v4, 0, sizeof (struct sockaddr_in));
271       v4->sin_family = AF_INET;
272       memcpy (&v4->sin_addr,
273               &((char *) &v6->sin6_addr)[sizeof (struct in6_addr) -
274                                          sizeof (struct in_addr)],
275               sizeof (struct in_addr));
276       v4->sin_port = v6->sin6_port;
277       uaddr = v4;
278       addrlen = sizeof (struct sockaddr_in);
279     }
280   else
281     {
282       uaddr = GNUNET_malloc (addrlen);
283       memcpy (uaddr, addr, addrlen);
284     }
285
286   if ((access != NULL) &&
287       (GNUNET_YES != (aret = access (access_cls, uaddr, addrlen))))
288     {
289       if (aret == GNUNET_NO)
290         {
291           fam = ((struct sockaddr *) addr)->sa_family;
292           GNUNET_log (GNUNET_ERROR_TYPE_INFO,
293                       _("Access denied to `%s'\n"),
294                       inet_ntop (fam,
295                                  (fam == AF_INET6)
296                                  ? (const void *) &((struct sockaddr_in6 *)
297                                                     &addr)->sin6_addr : (const
298                                                                          void
299                                                                          *)
300                                  &((struct sockaddr_in *) &addr)->sin_addr,
301                                  msg, sizeof (msg)));
302         }
303       GNUNET_break (0 == SHUTDOWN (fd, SHUT_RDWR));
304       GNUNET_break (0 == CLOSE (fd));
305       GNUNET_free (uaddr);
306       return NULL;
307     }
308   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_SocketHandle) + maxbuf);
309   ret->write_buffer = (char *) &ret[1];
310   ret->write_buffer_size = maxbuf;
311   ret->addr = uaddr;
312   ret->addrlen = addrlen;
313   ret->sock = fd;
314   ret->sched = sched;
315   return ret;
316 }
317
318 /**
319  * Obtain the network address of the other party.
320  *
321  * @param sock the client to get the address for
322  * @param addr where to store the address
323  * @param addrlen where to store the length of the address
324  * @return GNUNET_OK on success
325  */
326 int
327 GNUNET_NETWORK_socket_get_address (struct GNUNET_NETWORK_SocketHandle *sock,
328                                    void **addr, size_t * addrlen)
329 {
330   if ((sock->addr == NULL) || (sock->addrlen == 0))
331     return GNUNET_NO;
332   *addr = GNUNET_malloc (sock->addrlen);
333   memcpy (*addr, sock->addr, sock->addrlen);
334   *addrlen = sock->addrlen;
335   return GNUNET_OK;
336 }
337
338
339 /**
340  * Set if a socket should use blocking or non-blocking IO.
341  *
342  * @return GNUNET_OK on success, GNUNET_SYSERR on error
343  */
344 static int
345 socket_set_blocking (int handle, int doBlock)
346 {
347 #if MINGW
348   u_long mode;
349   mode = !doBlock;
350 #if HAVE_PLIBC_FD
351   if (ioctlsocket (plibc_fd_get_handle (handle), FIONBIO, &mode) ==
352       SOCKET_ERROR)
353     {
354       SetErrnoFromWinsockError (WSAGetLastError ());
355       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "ioctlsocket");
356       return GNUNET_SYSERR;
357     }
358 #else
359   if (ioctlsocket (handle, FIONBIO, &mode) == SOCKET_ERROR)
360     {
361       SetErrnoFromWinsockError (WSAGetLastError ());
362       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "ioctlsocket");
363       return GNUNET_SYSERR;
364     }
365 #endif
366   /* store the blocking mode */
367 #if HAVE_PLIBC_FD
368   plibc_fd_set_blocking (handle, doBlock);
369 #else
370   __win_SetHandleBlockingMode (handle, doBlock);
371 #endif
372   return GNUNET_OK;
373
374 #else
375   /* not MINGW */
376   int flags = fcntl (handle, F_GETFL);
377   if (flags == -1)
378     {
379       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "fcntl");
380       return GNUNET_SYSERR;
381     }
382   if (doBlock)
383     flags &= ~O_NONBLOCK;
384   else
385     flags |= O_NONBLOCK;
386   if (0 != fcntl (handle, F_SETFL, flags))
387     {
388       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "fcntl");
389       return GNUNET_SYSERR;
390     }
391   return GNUNET_OK;
392 #endif
393 }
394
395
396 /**
397  * Initiate asynchronous TCP connect request.
398  *
399  * @param sock what socket to connect
400  * @return GNUNET_SYSERR error (no more addresses to try)
401  */
402 static int
403 try_connect (struct GNUNET_NETWORK_SocketHandle *sock)
404 {
405   int s;
406
407   if (sock->addr != NULL)
408     {
409       GNUNET_free (sock->addr);
410       sock->addr = NULL;
411       sock->addrlen = 0;
412     }
413   while (1)
414     {
415       if (sock->ai_pos == NULL)
416         {
417           /* no more addresses to try, fatal! */
418           return GNUNET_SYSERR;
419         }
420       switch (sock->ai_pos->ai_family)
421         {
422         case AF_INET:
423           ((struct sockaddr_in *) sock->ai_pos->ai_addr)->sin_port =
424             htons (sock->port);
425           break;
426         case AF_INET6:
427           ((struct sockaddr_in6 *) sock->ai_pos->ai_addr)->sin6_port =
428             htons (sock->port);
429           break;
430         default:
431           sock->ai_pos = sock->ai_pos->ai_next;
432           continue;
433         }
434       s = SOCKET (sock->ai_pos->ai_family, SOCK_STREAM, 0);
435       if (s == -1)
436         {
437           /* maybe unsupported address family, try next */
438           GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO, "socket");
439           sock->ai_pos = sock->ai_pos->ai_next;
440           continue;
441         }
442       if (0 != fcntl (s, F_SETFD, fcntl (s, F_GETFD) | FD_CLOEXEC))
443         GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
444                              "fcntl");
445       if (GNUNET_SYSERR == socket_set_blocking (s, GNUNET_NO))
446         {
447           /* we'll treat this one as fatal */
448           GNUNET_break (0 == CLOSE (s));
449           return GNUNET_SYSERR;
450         }
451       if ((0 != CONNECT (s,
452                          sock->ai_pos->ai_addr,
453                          sock->ai_pos->ai_addrlen)) && (errno != EINPROGRESS))
454         {
455           /* maybe refused / unsupported address, try next */
456           GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO, "connect");
457           GNUNET_break (0 == CLOSE (s));
458           continue;
459         }
460       break;
461     }
462   /* got one! copy address information! */
463   sock->addrlen = sock->ai_pos->ai_addrlen;
464   sock->addr = GNUNET_malloc (sock->addrlen);
465   memcpy (sock->addr, sock->ai_pos->ai_addr, sock->addrlen);
466   sock->ai_pos = sock->ai_pos->ai_next;
467   sock->sock = s;
468   return GNUNET_OK;
469 }
470
471
472 /**
473  * Scheduler let us know that we're either ready to
474  * write on the socket OR connect timed out.  Do the
475  * right thing.
476  */
477 static void
478 connect_continuation (void *cls,
479                       const struct GNUNET_SCHEDULER_TaskContext *tc)
480 {
481   struct GNUNET_NETWORK_SocketHandle *sock = cls;
482   unsigned int len;
483   int error;
484
485   /* nobody needs to wait for us anymore... */
486   sock->connect_task = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
487   /* Note: write-ready does NOT mean connect succeeded,
488      we need to use getsockopt to be sure */
489   len = sizeof (error);
490   errno = 0;
491   error = 0;
492   if ((0 == (tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) ||
493       (0 != getsockopt (sock->sock, SOL_SOCKET, SO_ERROR, &error, &len)) ||
494       (error != 0) || (errno != 0))
495     {
496       /* connect failed / timed out */
497       GNUNET_break (0 == CLOSE (sock->sock));
498       sock->sock = -1;
499       if (GNUNET_SYSERR == try_connect (sock))
500         {
501           /* failed for good */
502           GNUNET_break (sock->ai_pos == NULL);
503           freeaddrinfo (sock->ai);
504           sock->ai = NULL;
505           return;
506         }
507       sock->connect_task = GNUNET_SCHEDULER_add_write (tc->sched, GNUNET_NO,    /* abort on shutdown */
508                                                        GNUNET_SCHEDULER_PRIORITY_KEEP,
509                                                        GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
510                                                        GNUNET_NETWORK_CONNECT_RETRY_TIMEOUT,
511                                                        sock->sock,
512                                                        &connect_continuation,
513                                                        sock);
514       return;
515     }
516   /* connect succeeded! clean up "ai" */
517 #if DEBUG_NETWORK
518   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connection succeeded!\n");
519 #endif
520   freeaddrinfo (sock->ai);
521   sock->ai_pos = NULL;
522   sock->ai = NULL;
523 }
524
525
526 /**
527  * Create a socket handle by (asynchronously) connecting to a host.
528  * This function returns immediately, even if the connection has not
529  * yet been established.  This function only creates TCP connections.
530  *
531  * @param sched scheduler to use
532  * @param hostname name of the host to connect to
533  * @param port port to connect to
534  * @param maxbuf maximum write buffer size for the socket (use
535  *        0 for sockets that need no write buffers, such as listen sockets)
536  * @return the socket handle
537  */
538 struct GNUNET_NETWORK_SocketHandle *
539 GNUNET_NETWORK_socket_create_from_connect (struct GNUNET_SCHEDULER_Handle
540                                            *sched, const char *hostname,
541                                            uint16_t port, size_t maxbuf)
542 {
543   struct GNUNET_NETWORK_SocketHandle *ret;
544   struct addrinfo hints;
545   int ec;
546
547   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_SocketHandle) + maxbuf);
548   ret->sock = -1;
549   ret->sched = sched;
550   ret->write_buffer = (char *) &ret[1];
551   ret->write_buffer_size = maxbuf;
552   ret->port = port;
553   memset (&hints, 0, sizeof (hints));
554   hints.ai_family = AF_UNSPEC;
555   hints.ai_socktype = SOCK_STREAM;
556   if (0 != (ec = getaddrinfo (hostname, NULL, &hints, &ret->ai)))
557     {
558       GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK,
559                   "`%s' failed for hostname `%s': %s\n",
560                   "getaddrinfo", hostname, gai_strerror (ec));
561       GNUNET_free (ret);
562       return NULL;
563     }
564   ret->ai_pos = ret->ai;
565   if (GNUNET_SYSERR == try_connect (ret))
566     {
567       freeaddrinfo (ret->ai);
568       GNUNET_free (ret);
569       return NULL;
570     }
571   ret->connect_task = GNUNET_SCHEDULER_add_write (sched, GNUNET_NO,     /* abort on shutdown */
572                                                   GNUNET_SCHEDULER_PRIORITY_KEEP,
573                                                   GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
574                                                   GNUNET_NETWORK_CONNECT_RETRY_TIMEOUT,
575                                                   ret->sock,
576                                                   &connect_continuation, ret);
577   return ret;
578
579 }
580
581
582 /**
583  * Create a socket handle by (asynchronously) connecting to a host.
584  * This function returns immediately, even if the connection has not
585  * yet been established.  This function only creates TCP connections.
586  *
587  * @param sched scheduler to use
588  * @param af_family address family to use
589  * @param serv_addr server address
590  * @param addrlen length of server address
591  * @param maxbuf maximum write buffer size for the socket (use
592  *        0 for sockets that need no write buffers, such as listen sockets)
593  * @return the socket handle
594  */
595 struct GNUNET_NETWORK_SocketHandle *
596 GNUNET_NETWORK_socket_create_from_sockaddr (struct GNUNET_SCHEDULER_Handle
597                                             *sched, int af_family,
598                                             const struct sockaddr *serv_addr,
599                                             socklen_t addrlen, size_t maxbuf)
600 {
601   int s;
602
603   s = SOCKET (af_family, SOCK_STREAM, 0);
604   if (s == -1)
605     {
606       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING |
607                            GNUNET_ERROR_TYPE_BULK, "socket");
608       return NULL;
609     }
610   if (0 != fcntl (s, F_SETFD, fcntl (s, F_GETFD) | FD_CLOEXEC))
611     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
612                          "fcntl");
613   if (GNUNET_SYSERR == socket_set_blocking (s, GNUNET_NO))
614     {
615       /* we'll treat this one as fatal */
616       GNUNET_break (0 == CLOSE (s));
617       return NULL;
618     }
619   if ((0 != CONNECT (s, serv_addr, addrlen)) && (errno != EINPROGRESS))
620     {
621       /* maybe refused / unsupported address, try next */
622       GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO, "connect");
623       GNUNET_break (0 == CLOSE (s));
624       return NULL;
625     }
626   return GNUNET_NETWORK_socket_create_from_existing (sched, s, maxbuf);
627 }
628
629
630 /**
631  * Check if socket is valid (no fatal errors have happened so far).
632  * Note that a socket that is still trying to connect is considered
633  * valid.
634  *
635  * @param sock socket to check
636  * @return GNUNET_YES if valid, GNUNET_NO otherwise
637  */
638 int
639 GNUNET_NETWORK_socket_check (struct GNUNET_NETWORK_SocketHandle *sock)
640 {
641   if (sock->ai != NULL)
642     return GNUNET_YES;          /* still trying to connect */
643   return (sock->sock == -1) ? GNUNET_NO : GNUNET_YES;
644 }
645
646
647 /**
648  * Scheduler let us know that the connect task is finished (or was
649  * cancelled due to shutdown).  Now really clean up.
650  */
651 static void
652 destroy_continuation (void *cls,
653                       const struct GNUNET_SCHEDULER_TaskContext *tc)
654 {
655   struct GNUNET_NETWORK_SocketHandle *sock = cls;
656   GNUNET_NETWORK_TransmitReadyNotify notify;
657
658   if (sock->write_task != GNUNET_SCHEDULER_NO_PREREQUISITE_TASK)
659     {
660 #if DEBUG_NETWORK
661       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
662                   "Destroy code waiting for writes to complete.\n");
663 #endif
664       GNUNET_SCHEDULER_add_after (sock->sched,
665                                   GNUNET_YES,
666                                   GNUNET_SCHEDULER_PRIORITY_KEEP,
667                                   sock->write_task,
668                                   &destroy_continuation, sock);
669       return;
670     }
671   if (sock->sock != -1)
672     {
673 #if DEBUG_NETWORK
674       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down socket.\n");
675 #endif
676       SHUTDOWN (sock->sock, SHUT_RDWR);
677     }
678   if (sock->read_task != GNUNET_SCHEDULER_NO_PREREQUISITE_TASK)
679     {
680 #if DEBUG_NETWORK
681       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
682                   "Destroy code waiting for receive to complete.\n");
683 #endif
684       GNUNET_SCHEDULER_add_after (sock->sched,
685                                   GNUNET_YES,
686                                   GNUNET_SCHEDULER_PRIORITY_KEEP,
687                                   sock->read_task,
688                                   &destroy_continuation, sock);
689       return;
690     }
691   if (NULL != (notify = sock->nth.notify_ready))
692     {
693       sock->nth.notify_ready = NULL;
694       notify (sock->nth.notify_ready_cls, 0, NULL);
695       if (sock->nth.timeout_task != GNUNET_SCHEDULER_NO_PREREQUISITE_TASK)
696         {
697           GNUNET_SCHEDULER_cancel (sock->sched, sock->nth.timeout_task);
698           sock->nth.timeout_task = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
699         }
700     }
701   if (sock->sock != -1)
702     {
703 #if DEBUG_NETWORK
704       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Closing socket.\n");
705 #endif
706       GNUNET_break (0 == CLOSE (sock->sock));
707     }
708   GNUNET_free_non_null (sock->addr);
709   if (sock->ai != NULL)
710     freeaddrinfo (sock->ai);
711   GNUNET_free (sock);
712 }
713
714
715 /**
716  * Close the socket and free associated resources. Pending
717  * transmissions are simply dropped.  A pending receive call will be
718  * called with an error code of "EPIPE".
719  *
720  * @param sock socket to destroy
721  */
722 void
723 GNUNET_NETWORK_socket_destroy (struct GNUNET_NETWORK_SocketHandle *sock)
724 {
725 #if DEBUG_NETWORK
726   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
727               "Network asked to destroy socket %p\n", sock);
728 #endif
729   if (sock->write_buffer_off == 0)
730     sock->ai_pos = NULL;        /* if we're still trying to connect and have
731                                    no message pending, stop trying! */
732   GNUNET_assert (sock->sched != NULL);
733   GNUNET_SCHEDULER_add_after (sock->sched,
734                               GNUNET_YES,
735                               GNUNET_SCHEDULER_PRIORITY_KEEP,
736                               sock->connect_task,
737                               &destroy_continuation, sock);
738 }
739
740 /**
741  * Tell the receiver callback that a timeout was reached.
742  */
743 static void
744 signal_timeout (struct GNUNET_NETWORK_SocketHandle *sh)
745 {
746   GNUNET_NETWORK_Receiver receiver;
747
748 #if DEBUG_NETWORK
749   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
750               "Network signals timeout to receiver!\n");
751 #endif
752   GNUNET_assert (NULL != (receiver = sh->receiver));
753   sh->receiver = NULL;
754   receiver (sh->receiver_cls, NULL, 0, NULL, 0, 0);
755 }
756
757
758 /**
759  * Tell the receiver callback that we had an IO error.
760  */
761 static void
762 signal_error (struct GNUNET_NETWORK_SocketHandle *sh, int errcode)
763 {
764   GNUNET_NETWORK_Receiver receiver;
765   GNUNET_assert (NULL != (receiver = sh->receiver));
766   sh->receiver = NULL;
767   receiver (sh->receiver_cls, NULL, 0, sh->addr, sh->addrlen, errcode);
768 }
769
770
771 /**
772  * This function is called once we either timeout
773  * or have data ready to read.
774  */
775 static void
776 receive_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
777 {
778   struct GNUNET_NETWORK_SocketHandle *sh = cls;
779   struct GNUNET_TIME_Absolute now;
780   char buffer[sh->max];
781   ssize_t ret;
782   GNUNET_NETWORK_Receiver receiver;
783
784   sh->read_task = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
785   now = GNUNET_TIME_absolute_get ();
786   if ((now.value > sh->receive_timeout.value) ||
787       (0 != (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT)) ||
788       (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)))
789     {
790 #if DEBUG_NETWORK
791       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
792                   "Receive encounters error: timeout...\n");
793 #endif
794       signal_timeout (sh);
795       return;
796     }
797   if (sh->sock == -1)
798     {
799       /* connect failed for good */
800 #if DEBUG_NETWORK
801       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
802                   "Receive encounters error, socket closed...\n");
803 #endif
804       signal_error (sh, ECONNREFUSED);
805       return;
806     }
807   GNUNET_assert (FD_ISSET (sh->sock, tc->read_ready));
808 RETRY:
809   ret = RECV (sh->sock, buffer, sh->max, MSG_DONTWAIT);
810   if (ret == -1)
811     {
812       if (errno == EINTR)
813         goto RETRY;
814 #if DEBUG_NETWORK
815       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
816                   "Error receiving: %s\n", STRERROR (errno));
817 #endif
818       signal_error (sh, errno);
819       return;
820     }
821 #if DEBUG_NETWORK
822   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
823               "Receive got %d bytes from OS!\n", ret);
824 #endif
825   GNUNET_assert (NULL != (receiver = sh->receiver));
826   sh->receiver = NULL;
827   receiver (sh->receiver_cls, buffer, ret, sh->addr, sh->addrlen, 0);
828 }
829
830
831 /**
832  * This function is called after establishing a connection either has
833  * succeeded or timed out.  Note that it is possible that the attempt
834  * timed out and that we're immediately retrying.  If we are retrying,
835  * we need to wait again (or timeout); if we succeeded, we need to
836  * wait for data (or timeout).
837  */
838 static void
839 receive_again (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
840 {
841   struct GNUNET_NETWORK_SocketHandle *sh = cls;
842   struct GNUNET_TIME_Absolute now;
843
844   sh->read_task = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
845   if ((sh->sock == -1) &&
846       (sh->connect_task == GNUNET_SCHEDULER_NO_PREREQUISITE_TASK))
847     {
848       /* not connected and no longer trying */
849 #if DEBUG_NETWORK
850       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
851                   "Receive encounters error, socket closed...\n");
852 #endif
853       signal_error (sh, ECONNREFUSED);
854       return;
855     }
856   now = GNUNET_TIME_absolute_get ();
857   if ((now.value > sh->receive_timeout.value) ||
858       (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)))
859     {
860 #if DEBUG_NETWORK
861       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
862                   "Receive encounters error: timeout...\n");
863 #endif
864       signal_timeout (sh);
865       return;
866     }
867   if (sh->connect_task != GNUNET_SCHEDULER_NO_PREREQUISITE_TASK)
868     {
869       /* connect was retried */
870 #if DEBUG_NETWORK
871       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
872                   "Receive still waits on connect...\n");
873 #endif
874       sh->read_task = GNUNET_SCHEDULER_add_after (tc->sched,
875                                                   GNUNET_YES,
876                                                   GNUNET_SCHEDULER_PRIORITY_KEEP,
877                                                   sh->connect_task,
878                                                   &receive_again, sh);
879     }
880   else
881     {
882       /* connect succeeded, wait for data! */
883 #if DEBUG_NETWORK
884       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
885                   "Receive now waits for socket...\n");
886 #endif
887       sh->read_task = GNUNET_SCHEDULER_add_read (tc->sched,
888                                                  GNUNET_YES,
889                                                  GNUNET_SCHEDULER_PRIORITY_KEEP,
890                                                  sh->connect_task,
891                                                  GNUNET_TIME_absolute_get_remaining
892                                                  (sh->receive_timeout),
893                                                  sh->sock, &receive_ready,
894                                                  sh);
895     }
896 }
897
898
899 /**
900  * Receive data from the given socket.  Note that this function will
901  * call "receiver" asynchronously using the scheduler.  It will
902  * "immediately" return.  Note that there MUST only be one active
903  * receive call per socket at any given point in time (so do not
904  * call receive again until the receiver callback has been invoked).
905  *
906  * @param sched scheduler to use
907  * @param sock socket handle
908  * @param max maximum number of bytes to read
909  * @param timeout maximum amount of time to wait (use -1 for "forever")
910  * @param receiver function to call with received data
911  * @param receiver_cls closure for receiver
912  * @return scheduler task ID used for receiving, GNUNET_SCHEDULER_NO_PREREQUISITE_TASK on error
913  */
914 GNUNET_SCHEDULER_TaskIdentifier
915 GNUNET_NETWORK_receive (struct GNUNET_NETWORK_SocketHandle *sock,
916                         size_t max,
917                         struct GNUNET_TIME_Relative timeout,
918                         GNUNET_NETWORK_Receiver receiver, void *receiver_cls)
919 {
920   struct GNUNET_SCHEDULER_TaskContext tc;
921 #if DEBUG_NETWORK
922   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
923               "Network asked to receive from socket...\n");
924 #endif
925   GNUNET_assert ((sock->read_task == GNUNET_SCHEDULER_NO_PREREQUISITE_TASK) &&
926                  (sock->receiver == NULL));
927   sock->receiver = receiver;
928   sock->receiver_cls = receiver_cls;
929   sock->receive_timeout = GNUNET_TIME_relative_to_absolute (timeout);
930   sock->max = max;
931   memset (&tc, 0, sizeof (tc));
932   tc.sched = sock->sched;
933   tc.reason = GNUNET_SCHEDULER_REASON_PREREQ_DONE;
934   receive_again (sock, &tc);
935   return sock->read_task;
936 }
937
938
939 /**
940  * Cancel receive job on the given socket.  Note that the
941  * receiver callback must not have been called yet in order
942  * for the cancellation to be valid.
943  *
944  * @param sock socket handle
945  * @param task task identifier returned from the receive call
946  * @return closure of the original receiver callback
947  */
948 void *
949 GNUNET_NETWORK_receive_cancel (struct GNUNET_NETWORK_SocketHandle *sock,
950                                GNUNET_SCHEDULER_TaskIdentifier task)
951 {
952   GNUNET_assert (sock->read_task == task);
953   GNUNET_assert (sock == GNUNET_SCHEDULER_cancel (sock->sched, task));
954   sock->read_task = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
955   sock->receiver = NULL;
956   return sock->receiver_cls;
957 }
958
959
960 /**
961  * Try to call the transmit notify method (check if we do
962  * have enough space available first)!
963  *
964  * @param sock socket for which we should do this processing
965  * @return GNUNET_YES if we were able to call notify
966  */
967 static int
968 process_notify (struct GNUNET_NETWORK_SocketHandle *sock)
969 {
970   size_t used;
971   size_t avail;
972   size_t size;
973   GNUNET_NETWORK_TransmitReadyNotify notify;
974
975   GNUNET_assert (sock->write_task == GNUNET_SCHEDULER_NO_PREREQUISITE_TASK);
976   if (NULL == (notify = sock->nth.notify_ready))
977     return GNUNET_NO;
978   used = sock->write_buffer_off - sock->write_buffer_pos;
979   avail = sock->write_buffer_size - used;
980   size = sock->nth.notify_size;
981   if (sock->nth.notify_size > avail)
982     return GNUNET_NO;
983   sock->nth.notify_ready = NULL;
984   if (sock->nth.timeout_task != GNUNET_SCHEDULER_NO_PREREQUISITE_TASK)
985     {
986       GNUNET_SCHEDULER_cancel (sock->sched, sock->nth.timeout_task);
987       sock->nth.timeout_task = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
988     }
989   if (sock->write_buffer_size - sock->write_buffer_off < size)
990     {
991       /* need to compact */
992       memmove (sock->write_buffer,
993                &sock->write_buffer[sock->write_buffer_pos], used);
994       sock->write_buffer_off -= sock->write_buffer_pos;
995       sock->write_buffer_pos = 0;
996     }
997   GNUNET_assert (sock->write_buffer_size - sock->write_buffer_off >= size);
998   size = notify (sock->nth.notify_ready_cls,
999                  sock->write_buffer_size - sock->write_buffer_off,
1000                  &sock->write_buffer[sock->write_buffer_off]);
1001   sock->write_buffer_off += size;
1002   return GNUNET_YES;
1003 }
1004
1005
1006 /**
1007  * Task invoked by the scheduler when a call to transmit
1008  * is timing out (we never got enough buffer space to call
1009  * the callback function before the specified timeout
1010  * expired).
1011  *
1012  * This task notifies the client about the timeout.
1013  */
1014 static void
1015 transmit_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1016 {
1017   struct GNUNET_NETWORK_SocketHandle *sock = cls;
1018   GNUNET_NETWORK_TransmitReadyNotify notify;
1019
1020 #if DEBUG_NETWORK
1021   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmit fails, time out reached.\n");
1022 #endif
1023   notify = sock->nth.notify_ready;
1024   sock->nth.notify_ready = NULL;
1025   notify (sock->nth.notify_ready_cls, 0, NULL);
1026 }
1027
1028
1029 static void
1030 transmit_error (struct GNUNET_NETWORK_SocketHandle *sock)
1031 {
1032   if (sock->nth.notify_ready == NULL)
1033     return;                     /* nobody to tell about it */
1034   if (sock->nth.timeout_task != GNUNET_SCHEDULER_NO_PREREQUISITE_TASK)
1035     {
1036       GNUNET_SCHEDULER_cancel (sock->sched, sock->nth.timeout_task);
1037       sock->nth.timeout_task = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
1038     }
1039   transmit_timeout (sock, NULL);
1040 }
1041
1042
1043 /**
1044  * See if we are now connected.  If not, wait longer for
1045  * connect to succeed.  If connected, we should be able
1046  * to write now as well, unless we timed out.
1047  */
1048 static void
1049 transmit_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1050 {
1051   struct GNUNET_NETWORK_SocketHandle *sock = cls;
1052   ssize_t ret;
1053   size_t have;
1054
1055 #if DEBUG_NETWORK
1056   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1057               "Transmit ready called --- will try to send\n");
1058 #endif
1059   GNUNET_assert (sock->write_task != GNUNET_SCHEDULER_NO_PREREQUISITE_TASK);
1060   sock->write_task = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
1061   if (sock->connect_task != GNUNET_SCHEDULER_NO_PREREQUISITE_TASK)
1062     {
1063       /* still waiting for connect */
1064 #if DEBUG_NETWORK
1065       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1066                   "Transmission still waiting for connect...\n");
1067 #endif
1068       GNUNET_assert (sock->write_task ==
1069                      GNUNET_SCHEDULER_NO_PREREQUISITE_TASK);
1070       sock->write_task =
1071         GNUNET_SCHEDULER_add_delayed (tc->sched, GNUNET_NO,
1072                                       GNUNET_SCHEDULER_PRIORITY_KEEP,
1073                                       sock->connect_task,
1074                                       GNUNET_TIME_UNIT_ZERO, &transmit_ready,
1075                                       sock);
1076       return;
1077     }
1078   if (sock->sock == -1)
1079     {
1080       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1081                   _
1082                   ("Did not transmit request, socket closed or connect failed.\n"));
1083       transmit_error (sock);
1084       return;                   /* connect failed for good, we're finished */
1085     }
1086   if ((tc->write_ready == NULL) || (!FD_ISSET (sock->sock, tc->write_ready)))
1087     {
1088 #if DEBUG_NETWORK
1089       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1090                   "Socket not yet ready for writing, will wait for that.\n");
1091 #endif
1092       goto SCHEDULE_WRITE;
1093     }
1094   GNUNET_assert (sock->write_buffer_off >= sock->write_buffer_pos);
1095   process_notify (sock);
1096   have = sock->write_buffer_off - sock->write_buffer_pos;
1097   if (have == 0)
1098     {
1099 #if DEBUG_NETWORK
1100       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No data ready for writing.\n");
1101 #endif
1102       return;
1103     }
1104 RETRY:
1105   ret = SEND (sock->sock,
1106               &sock->write_buffer[sock->write_buffer_pos],
1107               have, MSG_DONTWAIT | MSG_NOSIGNAL);
1108   if (ret == -1)
1109     {
1110       if (errno == EINTR)
1111         goto RETRY;
1112 #if DEBUG_NETWORK
1113       GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "send");
1114 #endif
1115       SHUTDOWN (sock->sock, SHUT_RDWR);
1116       GNUNET_break (0 == CLOSE (sock->sock));
1117       sock->sock = -1;
1118       transmit_error (sock);
1119       return;
1120     }
1121 #if DEBUG_NETWORK
1122   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitted %d bytes to OS\n", ret);
1123 #endif
1124   sock->write_buffer_pos += ret;
1125   if (sock->write_buffer_pos == sock->write_buffer_off)
1126     {
1127       /* transmitted all pending data */
1128       sock->write_buffer_pos = 0;
1129       sock->write_buffer_off = 0;
1130 #if DEBUG_NETWORK
1131       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1132                   "Transmission buffer now empty.\n", ret);
1133 #endif
1134     }
1135   if ((sock->write_buffer_off == 0) && (NULL == sock->nth.notify_ready))
1136     return;                     /* all data sent! */
1137   /* not done writing, schedule more */
1138 #if DEBUG_NETWORK
1139   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1140               "More data ready for transmission, scheduling task again!\n");
1141 #endif
1142 SCHEDULE_WRITE:
1143   if (sock->write_task == GNUNET_SCHEDULER_NO_PREREQUISITE_TASK)
1144     sock->write_task =
1145       GNUNET_SCHEDULER_add_write (tc->sched,
1146                                   GNUNET_NO,
1147                                   GNUNET_SCHEDULER_PRIORITY_KEEP,
1148                                   GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
1149                                   GNUNET_TIME_UNIT_FOREVER_REL,
1150                                   sock->sock, &transmit_ready, sock);
1151 }
1152
1153
1154 /**
1155  * Ask the socket to call us once the specified number of bytes
1156  * are free in the transmission buffer.  May call the notify
1157  * method immediately if enough space is available.
1158  *
1159  * @param sock socket
1160  * @param size number of bytes to send
1161  * @param timeout after how long should we give up (and call
1162  *        notify with buf NULL and size 0)?
1163  * @param notify function to call
1164  * @param notify_cls closure for notify
1165  * @return non-NULL if the notify callback was queued,
1166  *         NULL if we are already going to notify someone else (busy)
1167  */
1168 struct GNUNET_NETWORK_TransmitHandle *
1169 GNUNET_NETWORK_notify_transmit_ready (struct GNUNET_NETWORK_SocketHandle
1170                                       *sock, size_t size,
1171                                       struct GNUNET_TIME_Relative timeout,
1172                                       GNUNET_NETWORK_TransmitReadyNotify
1173                                       notify, void *notify_cls)
1174 {
1175   if (sock->nth.notify_ready != NULL)
1176     return NULL;
1177   GNUNET_assert (notify != NULL);
1178   GNUNET_assert (sock->write_buffer_size >= size);
1179
1180   if ((sock->sock == -1) &&
1181       (sock->connect_task == GNUNET_SCHEDULER_NO_PREREQUISITE_TASK))
1182     {
1183 #if DEBUG_NETWORK
1184       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1185                   "Transmit fails, connection failed.\n");
1186 #endif
1187       notify (notify_cls, 0, NULL);
1188       return &sock->nth;
1189     }
1190   GNUNET_assert (sock->write_buffer_off <= sock->write_buffer_size);
1191   GNUNET_assert (sock->write_buffer_pos <= sock->write_buffer_size);
1192   GNUNET_assert (sock->write_buffer_pos <= sock->write_buffer_off);
1193   sock->nth.notify_ready = notify;
1194   sock->nth.notify_ready_cls = notify_cls;
1195   sock->nth.sh = sock;
1196   sock->nth.notify_size = size;
1197   sock->nth.transmit_timeout = GNUNET_TIME_relative_to_absolute (timeout);
1198   sock->nth.timeout_task = GNUNET_SCHEDULER_add_delayed (sock->sched,
1199                                                          GNUNET_NO,
1200                                                          GNUNET_SCHEDULER_PRIORITY_KEEP,
1201                                                          GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
1202                                                          timeout,
1203                                                          &transmit_timeout,
1204                                                          sock);
1205 #if DEBUG_NETWORK
1206   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1207               "Scheduling asynchronous transmission once connect is done...\n");
1208 #endif
1209   if (sock->write_task == GNUNET_SCHEDULER_NO_PREREQUISITE_TASK)
1210     sock->write_task = GNUNET_SCHEDULER_add_delayed (sock->sched,
1211                                                      GNUNET_NO,
1212                                                      GNUNET_SCHEDULER_PRIORITY_KEEP,
1213                                                      sock->connect_task,
1214                                                      GNUNET_TIME_UNIT_ZERO,
1215                                                      &transmit_ready, sock);
1216   return &sock->nth;
1217 }
1218
1219
1220 /**
1221  * Cancel the specified transmission-ready
1222  * notification.
1223  */
1224 void
1225 GNUNET_NETWORK_notify_transmit_ready_cancel (struct
1226                                              GNUNET_NETWORK_TransmitHandle *h)
1227 {
1228   GNUNET_assert (h->notify_ready != NULL);
1229   GNUNET_SCHEDULER_cancel (h->sh->sched, h->timeout_task);
1230   h->timeout_task = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
1231   h->notify_ready = NULL;
1232 }
1233
1234
1235 #if 0                           /* keep Emacsens' auto-indent happy */
1236 {
1237 #endif
1238 #ifdef __cplusplus
1239 }
1240 #endif