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