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