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