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