22c1ca632ee3e38f99a3ba76149f53bfab47a674
[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)->
298                                  sin6_addr : (const void *)
299                                  &((struct sockaddr_in *) &addr)->sin_addr,
300                                  msg, sizeof (msg)));
301         }
302       GNUNET_break (0 == SHUTDOWN (fd, SHUT_RDWR));
303       GNUNET_break (0 == CLOSE (fd));
304       GNUNET_free (uaddr);
305       return NULL;
306     }
307   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_SocketHandle) + maxbuf);
308   ret->write_buffer = (char *) &ret[1];
309   ret->write_buffer_size = maxbuf;
310   ret->addr = uaddr;
311   ret->addrlen = addrlen;
312   ret->sock = fd;
313   ret->sched = sched;
314   return ret;
315 }
316
317 /**
318  * Obtain the network address of the other party.
319  *
320  * @param sock the client to get the address for
321  * @param addr where to store the address
322  * @param addrlen where to store the length of the address
323  * @return GNUNET_OK on success
324  */
325 int
326 GNUNET_NETWORK_socket_get_address (struct GNUNET_NETWORK_SocketHandle *sock,
327                                    void **addr, size_t * addrlen)
328 {
329   if ((sock->addr == NULL) || (sock->addrlen == 0))
330     return GNUNET_NO;
331   *addr = GNUNET_malloc (sock->addrlen);
332   memcpy (*addr, sock->addr, sock->addrlen);
333   *addrlen = sock->addrlen;
334   return GNUNET_OK;
335 }
336
337
338 /**
339  * Set if a socket should use blocking or non-blocking IO.
340  *
341  * @return GNUNET_OK on success, GNUNET_SYSERR on error
342  */
343 static int
344 socket_set_blocking (int handle, int doBlock)
345 {
346 #if MINGW
347   u_long mode;
348   mode = !doBlock;
349 #if HAVE_PLIBC_FD
350   if (ioctlsocket (plibc_fd_get_handle (handle), FIONBIO, &mode) ==
351       SOCKET_ERROR)
352     {
353       SetErrnoFromWinsockError (WSAGetLastError ());
354       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "ioctlsocket");
355       return GNUNET_SYSERR;
356     }
357 #else
358   if (ioctlsocket (handle, FIONBIO, &mode) == SOCKET_ERROR)
359     {
360       SetErrnoFromWinsockError (WSAGetLastError ());
361       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "ioctlsocket");
362       return GNUNET_SYSERR;
363     }
364 #endif
365   /* store the blocking mode */
366 #if HAVE_PLIBC_FD
367   plibc_fd_set_blocking (handle, doBlock);
368 #else
369   __win_SetHandleBlockingMode (handle, doBlock);
370 #endif
371   return GNUNET_OK;
372
373 #else
374   /* not MINGW */
375   int flags = fcntl (handle, F_GETFL);
376   if (flags == -1)
377     {
378       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "fcntl");
379       return GNUNET_SYSERR;
380     }
381   if (doBlock)
382     flags &= ~O_NONBLOCK;
383   else
384     flags |= O_NONBLOCK;
385   if (0 != fcntl (handle, F_SETFL, flags))
386     {
387       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "fcntl");
388       return GNUNET_SYSERR;
389     }
390   return GNUNET_OK;
391 #endif
392 }
393
394
395 /**
396  * Initiate asynchronous TCP connect request.
397  *
398  * @param sock what socket to connect
399  * @return GNUNET_SYSERR error (no more addresses to try)
400  */
401 static int
402 try_connect (struct GNUNET_NETWORK_SocketHandle *sock)
403 {
404   int s;
405
406   if (sock->addr != NULL)
407     {
408       GNUNET_free (sock->addr);
409       sock->addr = NULL;
410       sock->addrlen = 0;
411     }
412   while (1)
413     {
414       if (sock->ai_pos == NULL)
415         {
416           /* no more addresses to try, fatal! */
417           return GNUNET_SYSERR;
418         }
419       switch (sock->ai_pos->ai_family)
420         {
421         case AF_INET:
422           ((struct sockaddr_in *) sock->ai_pos->ai_addr)->sin_port =
423             htons (sock->port);
424           break;
425         case AF_INET6:
426           ((struct sockaddr_in6 *) sock->ai_pos->ai_addr)->sin6_port =
427             htons (sock->port);
428           break;
429         default:
430           sock->ai_pos = sock->ai_pos->ai_next;
431           continue;
432         }
433       s = SOCKET (sock->ai_pos->ai_family, SOCK_STREAM, 0);
434       if (s == -1)
435         {
436           /* maybe unsupported address family, try next */
437           GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO, "socket");
438           sock->ai_pos = sock->ai_pos->ai_next;
439           continue;
440         }
441       if (0 != fcntl (s, F_SETFD, fcntl (s, F_GETFD) | FD_CLOEXEC))
442         GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
443                              "fcntl");
444       if (GNUNET_SYSERR == socket_set_blocking (s, GNUNET_NO))
445         {
446           /* we'll treat this one as fatal */
447           GNUNET_break (0 == CLOSE (s));
448           return GNUNET_SYSERR;
449         }
450       if ((0 != CONNECT (s,
451                          sock->ai_pos->ai_addr,
452                          sock->ai_pos->ai_addrlen)) && (errno != EINPROGRESS))
453         {
454           /* maybe refused / unsupported address, try next */
455           GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO, "connect");
456           GNUNET_break (0 == CLOSE (s));
457           continue;
458         }
459       break;
460     }
461   /* got one! copy address information! */
462   sock->addrlen = sock->ai_pos->ai_addrlen;
463   sock->addr = GNUNET_malloc (sock->addrlen);
464   memcpy (sock->addr, sock->ai_pos->ai_addr, sock->addrlen);
465   sock->ai_pos = sock->ai_pos->ai_next;
466   sock->sock = s;
467   return GNUNET_OK;
468 }
469
470
471 /**
472  * Scheduler let us know that we're either ready to
473  * write on the socket OR connect timed out.  Do the
474  * right thing.
475  */
476 static void
477 connect_continuation (void *cls,
478                       const struct GNUNET_SCHEDULER_TaskContext *tc)
479 {
480   struct GNUNET_NETWORK_SocketHandle *sock = cls;
481   unsigned int len;
482   int error;
483
484   /* nobody needs to wait for us anymore... */
485   sock->connect_task = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
486   /* Note: write-ready does NOT mean connect succeeded,
487      we need to use getsockopt to be sure */
488   len = sizeof (error);
489   errno = 0;
490   error = 0;
491   if ((0 == (tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) ||
492       (0 != getsockopt (sock->sock, SOL_SOCKET, SO_ERROR, &error, &len)) ||
493       (error != 0) || (errno != 0))
494     {
495       /* connect failed / timed out */
496       GNUNET_break (0 == CLOSE (sock->sock));
497       sock->sock = -1;
498       if (GNUNET_SYSERR == try_connect (sock))
499         {
500           /* failed for good */
501           GNUNET_break (sock->ai_pos == NULL);
502           freeaddrinfo (sock->ai);
503           sock->ai = NULL;
504           return;
505         }
506       sock->connect_task = GNUNET_SCHEDULER_add_write (tc->sched, GNUNET_NO,    /* abort on shutdown */
507                                                        GNUNET_SCHEDULER_PRIORITY_KEEP,
508                                                        GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
509                                                        GNUNET_NETWORK_CONNECT_RETRY_TIMEOUT,
510                                                        sock->sock,
511                                                        &connect_continuation,
512                                                        sock);
513       return;
514     }
515   /* connect succeeded! clean up "ai" */
516 #if DEBUG_NETWORK
517   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connection succeeded!\n");
518 #endif
519   freeaddrinfo (sock->ai);
520   sock->ai_pos = NULL;
521   sock->ai = NULL;
522 }
523
524
525 /**
526  * Create a socket handle by (asynchronously) connecting to a host.
527  * This function returns immediately, even if the connection has not
528  * yet been established.  This function only creates TCP connections.
529  *
530  * @param sched scheduler to use
531  * @param hostname name of the host to connect to
532  * @param port port to connect to
533  * @param maxbuf maximum write buffer size for the socket (use
534  *        0 for sockets that need no write buffers, such as listen sockets)
535  * @return the socket handle
536  */
537 struct GNUNET_NETWORK_SocketHandle *
538 GNUNET_NETWORK_socket_create_from_connect (struct GNUNET_SCHEDULER_Handle
539                                            *sched, const char *hostname,
540                                            uint16_t port, size_t maxbuf)
541 {
542   struct GNUNET_NETWORK_SocketHandle *ret;
543   struct addrinfo hints;
544   int ec;
545
546   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_SocketHandle) + maxbuf);
547   ret->sock = -1;
548   ret->sched = sched;
549   ret->write_buffer = (char *) &ret[1];
550   ret->write_buffer_size = maxbuf;
551   ret->port = port;
552   memset (&hints, 0, sizeof (hints));
553   hints.ai_family = AF_UNSPEC;
554   hints.ai_socktype = SOCK_STREAM;
555   if (0 != (ec = getaddrinfo (hostname, NULL, &hints, &ret->ai)))
556     {
557       GNUNET_log (GNUNET_ERROR_TYPE_INFO | GNUNET_ERROR_TYPE_BULK,
558                   "`%s' failed for hostname `%s': %s\n",
559                   "getaddrinfo", hostname, gai_strerror (ec));
560       GNUNET_free (ret);
561       return NULL;
562     }
563   ret->ai_pos = ret->ai;
564   if (GNUNET_SYSERR == try_connect (ret))
565     {
566       freeaddrinfo (ret->ai);
567       GNUNET_free (ret);
568       return NULL;
569     }
570   ret->connect_task = GNUNET_SCHEDULER_add_write (sched, GNUNET_NO,     /* abort on shutdown */
571                                                   GNUNET_SCHEDULER_PRIORITY_KEEP,
572                                                   GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
573                                                   GNUNET_NETWORK_CONNECT_RETRY_TIMEOUT,
574                                                   ret->sock,
575                                                   &connect_continuation, ret);
576   return ret;
577
578 }
579
580
581 /**
582  * Create a socket handle by (asynchronously) connecting to a host.
583  * This function returns immediately, even if the connection has not
584  * yet been established.  This function only creates TCP connections.
585  *
586  * @param sched scheduler to use
587  * @param af_family address family to use
588  * @param serv_addr server address
589  * @param addrlen length of server address
590  * @param maxbuf maximum write buffer size for the socket (use
591  *        0 for sockets that need no write buffers, such as listen sockets)
592  * @return the socket handle
593  */
594 struct GNUNET_NETWORK_SocketHandle *
595 GNUNET_NETWORK_socket_create_from_sockaddr (struct GNUNET_SCHEDULER_Handle
596                                             *sched, int af_family,
597                                             const struct sockaddr *serv_addr,
598                                             socklen_t addrlen, size_t maxbuf)
599 {
600   int s;
601
602   s = SOCKET (af_family, SOCK_STREAM, 0);
603   if (s == -1)
604     {
605       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING |
606                            GNUNET_ERROR_TYPE_BULK, "socket");
607       return NULL;
608     }
609   if (0 != fcntl (s, F_SETFD, fcntl (s, F_GETFD) | FD_CLOEXEC))
610     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
611                          "fcntl");
612   if (GNUNET_SYSERR == socket_set_blocking (s, GNUNET_NO))
613     {
614       /* we'll treat this one as fatal */
615       GNUNET_break (0 == CLOSE (s));
616       return NULL;
617     }
618   if ((0 != CONNECT (s, serv_addr, addrlen)) && (errno != EINPROGRESS))
619     {
620       /* maybe refused / unsupported address, try next */
621       GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO, "connect");
622       GNUNET_break (0 == CLOSE (s));
623       return NULL;
624     }
625   return GNUNET_NETWORK_socket_create_from_existing (sched, s, maxbuf);
626 }
627
628
629 /**
630  * Check if socket is valid (no fatal errors have happened so far).
631  * Note that a socket that is still trying to connect is considered
632  * valid.
633  *
634  * @param sock socket to check
635  * @return GNUNET_YES if valid, GNUNET_NO otherwise
636  */
637 int
638 GNUNET_NETWORK_socket_check (struct GNUNET_NETWORK_SocketHandle *sock)
639 {
640   if (sock->ai != NULL)
641     return GNUNET_YES;          /* still trying to connect */
642   return (sock->sock == -1) ? GNUNET_NO : GNUNET_YES;
643 }
644
645
646 /**
647  * Scheduler let us know that the connect task is finished (or was
648  * cancelled due to shutdown).  Now really clean up.
649  */
650 static void
651 destroy_continuation (void *cls,
652                       const struct GNUNET_SCHEDULER_TaskContext *tc)
653 {
654   struct GNUNET_NETWORK_SocketHandle *sock = cls;
655   GNUNET_NETWORK_TransmitReadyNotify notify;
656
657   if (sock->write_task != GNUNET_SCHEDULER_NO_PREREQUISITE_TASK)
658     {
659 #if DEBUG_NETWORK
660       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
661                   "Destroy code waiting for writes to complete.\n");
662 #endif
663       GNUNET_SCHEDULER_add_after (sock->sched,
664                                   GNUNET_YES,
665                                   GNUNET_SCHEDULER_PRIORITY_KEEP,
666                                   sock->write_task,
667                                   &destroy_continuation, sock);
668       return;
669     }
670   if (sock->sock != -1)
671     {
672 #if DEBUG_NETWORK
673       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutting down socket.\n");
674 #endif
675       SHUTDOWN (sock->sock, SHUT_RDWR);
676     }
677   if (sock->read_task != GNUNET_SCHEDULER_NO_PREREQUISITE_TASK)
678     {
679 #if DEBUG_NETWORK
680       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
681                   "Destroy code waiting for receive to complete.\n");
682 #endif
683       GNUNET_SCHEDULER_add_after (sock->sched,
684                                   GNUNET_YES,
685                                   GNUNET_SCHEDULER_PRIORITY_KEEP,
686                                   sock->read_task,
687                                   &destroy_continuation, sock);
688       return;
689     }
690   if (NULL != (notify = sock->nth.notify_ready))
691     {
692       sock->nth.notify_ready = NULL;
693       notify (sock->nth.notify_ready_cls, 0, NULL);
694       if (sock->nth.timeout_task != GNUNET_SCHEDULER_NO_PREREQUISITE_TASK)
695         {
696           GNUNET_SCHEDULER_cancel (sock->sched, sock->nth.timeout_task);
697           sock->nth.timeout_task = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
698         }
699     }
700   if (sock->sock != -1)
701     {
702 #if DEBUG_NETWORK
703       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Closing socket.\n");
704 #endif
705       GNUNET_break (0 == CLOSE (sock->sock));
706     }
707   GNUNET_free_non_null (sock->addr);
708   if (sock->ai != NULL)
709     freeaddrinfo (sock->ai);
710   GNUNET_free (sock);
711 }
712
713
714 /**
715  * Close the socket and free associated resources. Pending
716  * transmissions are simply dropped.  A pending receive call will be
717  * called with an error code of "EPIPE".
718  *
719  * @param sock socket to destroy
720  */
721 void
722 GNUNET_NETWORK_socket_destroy (struct GNUNET_NETWORK_SocketHandle *sock)
723 {
724 #if DEBUG_NETWORK
725   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
726               "Network asked to destroy socket %p\n", sock);
727 #endif
728   if (sock->write_buffer_off == 0)
729     sock->ai_pos = NULL;        /* if we're still trying to connect and have
730                                    no message pending, stop trying! */
731   GNUNET_assert (sock->sched != NULL);
732   GNUNET_SCHEDULER_add_after (sock->sched,
733                               GNUNET_YES,
734                               GNUNET_SCHEDULER_PRIORITY_KEEP,
735                               sock->connect_task,
736                               &destroy_continuation, sock);
737 }
738
739 /**
740  * Tell the receiver callback that a timeout was reached.
741  */
742 static void
743 signal_timeout (struct GNUNET_NETWORK_SocketHandle *sh)
744 {
745   GNUNET_NETWORK_Receiver receiver;
746
747 #if DEBUG_NETWORK
748   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
749               "Network signals timeout to receiver!\n");
750 #endif
751   GNUNET_assert (NULL != (receiver = sh->receiver));
752   sh->receiver = NULL;
753   receiver (sh->receiver_cls, NULL, 0, NULL, 0, 0);
754 }
755
756
757 /**
758  * Tell the receiver callback that we had an IO error.
759  */
760 static void
761 signal_error (struct GNUNET_NETWORK_SocketHandle *sh, int errcode)
762 {
763   GNUNET_NETWORK_Receiver receiver;
764   GNUNET_assert (NULL != (receiver = sh->receiver));
765   sh->receiver = NULL;
766   receiver (sh->receiver_cls, NULL, 0, sh->addr, sh->addrlen, errcode);
767 }
768
769
770 /**
771  * This function is called once we either timeout
772  * or have data ready to read.
773  */
774 static void
775 receive_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
776 {
777   struct GNUNET_NETWORK_SocketHandle *sh = cls;
778   struct GNUNET_TIME_Absolute now;
779   char buffer[sh->max];
780   ssize_t ret;
781   GNUNET_NETWORK_Receiver receiver;
782
783   sh->read_task = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
784   now = GNUNET_TIME_absolute_get ();
785   if ((now.value > sh->receive_timeout.value) ||
786       (0 != (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT)) ||
787       (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)))
788     {
789 #if DEBUG_NETWORK
790       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
791                   "Receive encounters error: timeout...\n");
792 #endif
793       signal_timeout (sh);
794       return;
795     }
796   if (sh->sock == -1)
797     {
798       /* connect failed for good */
799 #if DEBUG_NETWORK
800       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
801                   "Receive encounters error, socket closed...\n");
802 #endif
803       signal_error (sh, ECONNREFUSED);
804       return;
805     }
806   GNUNET_assert (FD_ISSET (sh->sock, tc->read_ready));
807 RETRY:
808   ret = RECV (sh->sock, buffer, sh->max, MSG_DONTWAIT);
809   if (ret == -1)
810     {
811       if (errno == EINTR)
812         goto RETRY;
813 #if DEBUG_NETWORK
814       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
815                   "Error receiving: %s\n", STRERROR (errno));
816 #endif
817       signal_error (sh, errno);
818       return;
819     }
820 #if DEBUG_NETWORK
821   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
822               "Receive got %d bytes from OS!\n", ret);
823 #endif
824   GNUNET_assert (NULL != (receiver = sh->receiver));
825   sh->receiver = NULL;
826   receiver (sh->receiver_cls, buffer, ret, sh->addr, sh->addrlen, 0);
827 }
828
829
830 /**
831  * This function is called after establishing a connection either has
832  * succeeded or timed out.  Note that it is possible that the attempt
833  * timed out and that we're immediately retrying.  If we are retrying,
834  * we need to wait again (or timeout); if we succeeded, we need to
835  * wait for data (or timeout).
836  */
837 static void
838 receive_again (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
839 {
840   struct GNUNET_NETWORK_SocketHandle *sh = cls;
841   struct GNUNET_TIME_Absolute now;
842
843   sh->read_task = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
844   if ((sh->sock == -1) &&
845       (sh->connect_task == GNUNET_SCHEDULER_NO_PREREQUISITE_TASK))
846     {
847       /* not connected and no longer trying */
848 #if DEBUG_NETWORK
849       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
850                   "Receive encounters error, socket closed...\n");
851 #endif
852       signal_error (sh, ECONNREFUSED);
853       return;
854     }
855   now = GNUNET_TIME_absolute_get ();
856   if ((now.value > sh->receive_timeout.value) ||
857       (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)))
858     {
859 #if DEBUG_NETWORK
860       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
861                   "Receive encounters error: timeout...\n");
862 #endif
863       signal_timeout (sh);
864       return;
865     }
866   if (sh->connect_task != GNUNET_SCHEDULER_NO_PREREQUISITE_TASK)
867     {
868       /* connect was retried */
869 #if DEBUG_NETWORK
870       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
871                   "Receive still waits on connect...\n");
872 #endif
873       sh->read_task = GNUNET_SCHEDULER_add_after (tc->sched,
874                                                   GNUNET_YES,
875                                                   GNUNET_SCHEDULER_PRIORITY_KEEP,
876                                                   sh->connect_task,
877                                                   &receive_again, sh);
878     }
879   else
880     {
881       /* connect succeeded, wait for data! */
882 #if DEBUG_NETWORK
883       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
884                   "Receive now waits for socket...\n");
885 #endif
886       sh->read_task = GNUNET_SCHEDULER_add_read (tc->sched,
887                                                  GNUNET_YES,
888                                                  GNUNET_SCHEDULER_PRIORITY_KEEP,
889                                                  sh->connect_task,
890                                                  GNUNET_TIME_absolute_get_remaining
891                                                  (sh->receive_timeout),
892                                                  sh->sock, &receive_ready,
893                                                  sh);
894     }
895 }
896
897
898 /**
899  * Receive data from the given socket.  Note that this function will
900  * call "receiver" asynchronously using the scheduler.  It will
901  * "immediately" return.  Note that there MUST only be one active
902  * receive call per socket at any given point in time (so do not
903  * call receive again until the receiver callback has been invoked).
904  *
905  * @param sched scheduler to use
906  * @param sock socket handle
907  * @param max maximum number of bytes to read
908  * @param timeout maximum amount of time to wait (use -1 for "forever")
909  * @param receiver function to call with received data
910  * @param receiver_cls closure for receiver
911  * @return scheduler task ID used for receiving, GNUNET_SCHEDULER_NO_PREREQUISITE_TASK on error
912  */
913 GNUNET_SCHEDULER_TaskIdentifier
914 GNUNET_NETWORK_receive (struct GNUNET_NETWORK_SocketHandle *sock,
915                         size_t max,
916                         struct GNUNET_TIME_Relative timeout,
917                         GNUNET_NETWORK_Receiver receiver, void *receiver_cls)
918 {
919   struct GNUNET_SCHEDULER_TaskContext tc;
920 #if DEBUG_NETWORK
921   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
922               "Network asked to receive from socket...\n");
923 #endif
924   GNUNET_assert ((sock->read_task == GNUNET_SCHEDULER_NO_PREREQUISITE_TASK) &&
925                  (sock->receiver == NULL));
926   sock->receiver = receiver;
927   sock->receiver_cls = receiver_cls;
928   sock->receive_timeout = GNUNET_TIME_relative_to_absolute (timeout);
929   sock->max = max;
930   memset (&tc, 0, sizeof (tc));
931   tc.sched = sock->sched;
932   tc.reason = GNUNET_SCHEDULER_REASON_PREREQ_DONE;
933   receive_again (sock, &tc);
934   return sock->read_task;
935 }
936
937
938 /**
939  * Cancel receive job on the given socket.  Note that the
940  * receiver callback must not have been called yet in order
941  * for the cancellation to be valid.
942  *
943  * @param sock socket handle
944  * @param task task identifier returned from the receive call
945  * @return closure of the original receiver callback
946  */
947 void *
948 GNUNET_NETWORK_receive_cancel (struct GNUNET_NETWORK_SocketHandle *sock,
949                                GNUNET_SCHEDULER_TaskIdentifier task)
950 {
951   GNUNET_assert (sock->read_task == task);
952   GNUNET_assert (sock == GNUNET_SCHEDULER_cancel (sock->sched, task));
953   sock->read_task = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
954   sock->receiver = NULL;
955   return sock->receiver_cls;
956 }
957
958
959 /**
960  * Try to call the transmit notify method (check if we do
961  * have enough space available first)!
962  *
963  * @param sock socket for which we should do this processing
964  * @return GNUNET_YES if we were able to call notify
965  */
966 static int
967 process_notify (struct GNUNET_NETWORK_SocketHandle *sock)
968 {
969   size_t used;
970   size_t avail;
971   size_t size;
972   GNUNET_NETWORK_TransmitReadyNotify notify;
973
974   GNUNET_assert (sock->write_task == GNUNET_SCHEDULER_NO_PREREQUISITE_TASK);
975   if (NULL == (notify = sock->nth.notify_ready))
976     return GNUNET_NO;
977   used = sock->write_buffer_off - sock->write_buffer_pos;
978   avail = sock->write_buffer_size - used;
979   size = sock->nth.notify_size;
980   if (sock->nth.notify_size > avail)
981     return GNUNET_NO;
982   sock->nth.notify_ready = NULL;
983   if (sock->nth.timeout_task != GNUNET_SCHEDULER_NO_PREREQUISITE_TASK)
984     {
985       GNUNET_SCHEDULER_cancel (sock->sched, sock->nth.timeout_task);
986       sock->nth.timeout_task = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
987     }
988   if (sock->write_buffer_size - sock->write_buffer_off < size)
989     {
990       /* need to compact */
991       memmove (sock->write_buffer,
992                &sock->write_buffer[sock->write_buffer_pos], used);
993       sock->write_buffer_off -= sock->write_buffer_pos;
994       sock->write_buffer_pos = 0;
995     }
996   GNUNET_assert (sock->write_buffer_size - sock->write_buffer_off >= size);
997   size = notify (sock->nth.notify_ready_cls,
998                  sock->write_buffer_size - sock->write_buffer_off,
999                  &sock->write_buffer[sock->write_buffer_off]);
1000   sock->write_buffer_off += size;
1001   return GNUNET_YES;
1002 }
1003
1004
1005 /**
1006  * Task invoked by the scheduler when a call to transmit
1007  * is timing out (we never got enough buffer space to call
1008  * the callback function before the specified timeout
1009  * expired).
1010  *
1011  * This task notifies the client about the timeout.
1012  */
1013 static void
1014 transmit_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1015 {
1016   struct GNUNET_NETWORK_SocketHandle *sock = cls;
1017   GNUNET_NETWORK_TransmitReadyNotify notify;
1018
1019 #if DEBUG_NETWORK
1020   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmit fails, time out reached.\n");
1021 #endif
1022   notify = sock->nth.notify_ready;
1023   sock->nth.notify_ready = NULL;
1024   notify (sock->nth.notify_ready_cls, 0, NULL);
1025 }
1026
1027
1028 static void
1029 transmit_error (struct GNUNET_NETWORK_SocketHandle *sock)
1030 {
1031   if (sock->nth.notify_ready == NULL)
1032     return;                     /* nobody to tell about it */
1033   if (sock->nth.timeout_task != GNUNET_SCHEDULER_NO_PREREQUISITE_TASK)
1034     {
1035       GNUNET_SCHEDULER_cancel (sock->sched, sock->nth.timeout_task);
1036       sock->nth.timeout_task = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
1037     }
1038   transmit_timeout (sock, NULL);
1039 }
1040
1041
1042 /**
1043  * See if we are now connected.  If not, wait longer for
1044  * connect to succeed.  If connected, we should be able
1045  * to write now as well, unless we timed out.
1046  */
1047 static void
1048 transmit_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1049 {
1050   struct GNUNET_NETWORK_SocketHandle *sock = cls;
1051   ssize_t ret;
1052   size_t have;
1053
1054 #if DEBUG_NETWORK
1055   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1056               "Transmit ready called --- will try to send\n");
1057 #endif
1058   GNUNET_assert (sock->write_task != GNUNET_SCHEDULER_NO_PREREQUISITE_TASK);
1059   sock->write_task = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
1060   if (sock->connect_task != GNUNET_SCHEDULER_NO_PREREQUISITE_TASK)
1061     {
1062       /* still waiting for connect */
1063 #if DEBUG_NETWORK
1064       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1065                   "Transmission still waiting for connect...\n");
1066 #endif
1067       GNUNET_assert (sock->write_task ==
1068                      GNUNET_SCHEDULER_NO_PREREQUISITE_TASK);
1069       sock->write_task =
1070         GNUNET_SCHEDULER_add_delayed (tc->sched, GNUNET_NO,
1071                                       GNUNET_SCHEDULER_PRIORITY_KEEP,
1072                                       sock->connect_task,
1073                                       GNUNET_TIME_UNIT_ZERO, &transmit_ready,
1074                                       sock);
1075       return;
1076     }
1077   if (sock->sock == -1)
1078     {
1079       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1080                   _
1081                   ("Did not transmit request, socket closed or connect failed.\n"));
1082       transmit_error (sock);
1083       return;                   /* connect failed for good, we're finished */
1084     }
1085   if ((tc->write_ready == NULL) || (!FD_ISSET (sock->sock, tc->write_ready)))
1086     {
1087 #if DEBUG_NETWORK
1088       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1089                   "Socket not yet ready for writing, will wait for that.\n");
1090 #endif
1091       goto SCHEDULE_WRITE;
1092     }
1093   GNUNET_assert (sock->write_buffer_off >= sock->write_buffer_pos);
1094   process_notify (sock);
1095   have = sock->write_buffer_off - sock->write_buffer_pos;
1096   if (have == 0)
1097     {
1098 #if DEBUG_NETWORK
1099       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No data ready for writing.\n");
1100 #endif
1101       return;
1102     }
1103 RETRY:
1104   ret = SEND (sock->sock,
1105               &sock->write_buffer[sock->write_buffer_pos],
1106               have, MSG_DONTWAIT | MSG_NOSIGNAL);
1107   if (ret == -1)
1108     {
1109       if (errno == EINTR)
1110         goto RETRY;
1111 #if DEBUG_NETWORK
1112       GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "send");
1113 #endif
1114       SHUTDOWN (sock->sock, SHUT_RDWR);
1115       GNUNET_break (0 == CLOSE (sock->sock));
1116       sock->sock = -1;
1117       transmit_error (sock);
1118       return;
1119     }
1120 #if DEBUG_NETWORK
1121   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transmitted %d bytes to OS\n", ret);
1122 #endif
1123   sock->write_buffer_pos += ret;
1124   if (sock->write_buffer_pos == sock->write_buffer_off)
1125     {
1126       /* transmitted all pending data */
1127       sock->write_buffer_pos = 0;
1128       sock->write_buffer_off = 0;
1129 #if DEBUG_NETWORK
1130       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1131                   "Transmission buffer now empty.\n", ret);
1132 #endif
1133     }
1134   if ((sock->write_buffer_off == 0) && (NULL == sock->nth.notify_ready))
1135     return;                     /* all data sent! */
1136   /* not done writing, schedule more */
1137 #if DEBUG_NETWORK
1138   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1139               "More data ready for transmission, scheduling task again!\n");
1140 #endif
1141 SCHEDULE_WRITE:
1142   if (sock->write_task == GNUNET_SCHEDULER_NO_PREREQUISITE_TASK)
1143     sock->write_task =
1144       GNUNET_SCHEDULER_add_write (tc->sched,
1145                                   GNUNET_NO,
1146                                   GNUNET_SCHEDULER_PRIORITY_KEEP,
1147                                   GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
1148                                   GNUNET_TIME_UNIT_FOREVER_REL,
1149                                   sock->sock, &transmit_ready, sock);
1150 }
1151
1152
1153 /**
1154  * Ask the socket to call us once the specified number of bytes
1155  * are free in the transmission buffer.  May call the notify
1156  * method immediately if enough space is available.
1157  *
1158  * @param sock socket
1159  * @param size number of bytes to send
1160  * @param timeout after how long should we give up (and call
1161  *        notify with buf NULL and size 0)?
1162  * @param notify function to call
1163  * @param notify_cls closure for notify
1164  * @return non-NULL if the notify callback was queued,
1165  *         NULL if we are already going to notify someone else (busy)
1166  */
1167 struct GNUNET_NETWORK_TransmitHandle *
1168 GNUNET_NETWORK_notify_transmit_ready (struct GNUNET_NETWORK_SocketHandle
1169                                       *sock, size_t size,
1170                                       struct GNUNET_TIME_Relative timeout,
1171                                       GNUNET_NETWORK_TransmitReadyNotify
1172                                       notify, void *notify_cls)
1173 {
1174   if (sock->nth.notify_ready != NULL)
1175     return NULL;
1176   GNUNET_assert (notify != NULL);
1177   GNUNET_assert (sock->write_buffer_size >= size);
1178
1179   if ((sock->sock == -1) &&
1180       (sock->connect_task == GNUNET_SCHEDULER_NO_PREREQUISITE_TASK))
1181     {
1182 #if DEBUG_NETWORK
1183       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1184                   "Transmit fails, connection failed.\n");
1185 #endif
1186       notify (notify_cls, 0, NULL);
1187       return &sock->nth;
1188     }
1189   GNUNET_assert (sock->write_buffer_off <= sock->write_buffer_size);
1190   GNUNET_assert (sock->write_buffer_pos <= sock->write_buffer_size);
1191   GNUNET_assert (sock->write_buffer_pos <= sock->write_buffer_off);
1192   sock->nth.notify_ready = notify;
1193   sock->nth.notify_ready_cls = notify_cls;
1194   sock->nth.sh = sock;
1195   sock->nth.notify_size = size;
1196   sock->nth.transmit_timeout = GNUNET_TIME_relative_to_absolute (timeout);
1197   sock->nth.timeout_task = GNUNET_SCHEDULER_add_delayed (sock->sched,
1198                                                          GNUNET_NO,
1199                                                          GNUNET_SCHEDULER_PRIORITY_KEEP,
1200                                                          GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
1201                                                          timeout,
1202                                                          &transmit_timeout,
1203                                                          sock);
1204 #if DEBUG_NETWORK
1205   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1206               "Scheduling asynchronous transmission once connect is done...\n");
1207 #endif
1208   if (sock->write_task == GNUNET_SCHEDULER_NO_PREREQUISITE_TASK)
1209     sock->write_task = GNUNET_SCHEDULER_add_delayed (sock->sched,
1210                                                      GNUNET_NO,
1211                                                      GNUNET_SCHEDULER_PRIORITY_KEEP,
1212                                                      sock->connect_task,
1213                                                      GNUNET_TIME_UNIT_ZERO,
1214                                                      &transmit_ready, sock);
1215   return &sock->nth;
1216 }
1217
1218
1219 /**
1220  * Cancel the specified transmission-ready
1221  * notification.
1222  */
1223 void
1224 GNUNET_NETWORK_notify_transmit_ready_cancel (struct
1225                                              GNUNET_NETWORK_TransmitHandle *h)
1226 {
1227   GNUNET_assert (h->notify_ready != NULL);
1228   GNUNET_SCHEDULER_cancel (h->sh->sched, h->timeout_task);
1229   h->timeout_task = GNUNET_SCHEDULER_NO_PREREQUISITE_TASK;
1230   h->notify_ready = NULL;
1231 }
1232
1233
1234 #if 0                           /* keep Emacsens' auto-indent happy */
1235 {
1236 #endif
1237 #ifdef __cplusplus
1238 }
1239 #endif