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