trying to port statvfs call to BSD
[oweals/gnunet.git] / src / util / connection.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/connection.c
23  * @brief  TCP connection management
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
34 #include "platform.h"
35 #include "gnunet_common.h"
36 #include "gnunet_connection_lib.h"
37 #include "gnunet_container_lib.h"
38 #include "gnunet_resolver_service.h"
39 #include "gnunet_scheduler_lib.h"
40 #include "gnunet_server_lib.h"
41
42 #define DEBUG_CONNECTION GNUNET_NO
43
44
45 /**
46  * Possible functions to call after connect failed or succeeded.
47  */
48 enum ConnectContinuations
49 {
50     /**
51      * Call nothing.
52      */
53   COCO_NONE = 0,
54
55     /**
56      * Call "receive_again".
57      */
58   COCO_RECEIVE_AGAIN = 1,
59
60     /**
61      * Call "transmit_ready".
62      */
63   COCO_TRANSMIT_READY = 2,
64
65     /**
66      * Call "destroy_continuation".
67      */
68   COCO_DESTROY_CONTINUATION = 4
69 };
70
71
72 /**
73  * Transmission handle.  There can only be one for each connection.
74  */
75 struct GNUNET_CONNECTION_TransmitHandle
76 {
77
78   /**
79    * Function to call if the send buffer has notify_size
80    * bytes available.
81    */
82   GNUNET_CONNECTION_TransmitReadyNotify notify_ready;
83
84   /**
85    * Closure for notify_ready.
86    */
87   void *notify_ready_cls;
88
89   /**
90    * Our socket handle.
91    */
92   struct GNUNET_CONNECTION_Handle *sh;
93
94   /**
95    * Timeout for receiving (in absolute time).
96    */
97   struct GNUNET_TIME_Absolute transmit_timeout;
98
99   /**
100    * Task called on timeout.
101    */
102   GNUNET_SCHEDULER_TaskIdentifier timeout_task;
103
104   /**
105    * At what number of bytes available in the
106    * write buffer should the notify method be called?
107    */
108   size_t notify_size;
109
110 };
111
112
113 /**
114  * During connect, we try multiple possible IP addresses
115  * to find out which one might work. 
116  */
117 struct AddressProbe
118 {
119
120   /**
121    * This is a linked list.
122    */
123   struct AddressProbe *next;
124
125   /**
126    * This is a doubly-linked list.
127    */
128   struct AddressProbe *prev;
129
130   /**
131    * The address; do not free (allocated at the end of this struct).
132    */
133   const struct sockaddr *addr;
134
135   /**
136    * Underlying OS's socket.
137    */
138   struct GNUNET_NETWORK_Handle *sock;
139
140   /**
141    * Connection for which we are probing.
142    */
143   struct GNUNET_CONNECTION_Handle *h;
144
145   /**
146    * Lenth of addr.
147    */
148   socklen_t addrlen;
149
150   /**
151    * Task waiting for the socket to finish connecting.
152    */
153   GNUNET_SCHEDULER_TaskIdentifier task;
154 };
155
156
157 /**
158  * @brief handle for a network socket
159  */
160 struct GNUNET_CONNECTION_Handle
161 {
162
163   /**
164    * Scheduler that was used for the connect task.
165    */
166   struct GNUNET_SCHEDULER_Handle *sched;
167
168   /**
169    * Configuration to use.
170    */
171   const struct GNUNET_CONFIGURATION_Handle *cfg;
172
173   /**
174    * Linked list of sockets we are currently trying out 
175    * (during connect).
176    */
177   struct AddressProbe *ap_head;
178
179   /**
180    * Linked list of sockets we are currently trying out 
181    * (during connect).
182    */
183   struct AddressProbe *ap_tail;
184
185   /**
186    * Network address of the other end-point, may be NULL.
187    */
188   struct sockaddr *addr;
189
190   /**
191    * Pointer to the hostname if socket was
192    * created using DNS lookup, otherwise NULL.
193    */
194   char *hostname;
195
196   /**
197    * Underlying OS's socket, set to NULL after fatal errors.
198    */
199   struct GNUNET_NETWORK_Handle *sock;
200
201   /**
202    * Function to call on data received, NULL if no receive is pending.
203    */
204   GNUNET_CONNECTION_Receiver receiver;
205
206   /**
207    * Closure for receiver.
208    */
209   void *receiver_cls;
210
211   /**
212    * Pointer to our write buffer.
213    */
214   char *write_buffer;
215
216   /**
217    * Size of our write buffer.
218    */
219   size_t write_buffer_size;
220
221   /**
222    * Current write-offset in write buffer (where
223    * would we write next).
224    */
225   size_t write_buffer_off;
226
227   /**
228    * Current read-offset in write buffer (how many
229    * bytes have already been send).
230    */
231   size_t write_buffer_pos;
232
233   /**
234    * Length of addr.
235    */
236   socklen_t addrlen;
237
238   /**
239    * Read task that we may need to wait for.
240    */
241   GNUNET_SCHEDULER_TaskIdentifier read_task;
242
243   /**
244    * Write task that we may need to wait for.
245    */
246   GNUNET_SCHEDULER_TaskIdentifier write_task;
247
248   /**
249    * Destroy task (if already scheduled).
250    */
251   GNUNET_SCHEDULER_TaskIdentifier destroy_task;
252
253   /**
254    * Handle to a pending DNS lookup request.
255    */
256   struct GNUNET_RESOLVER_RequestHandle *dns_active;
257
258   /**
259    * The handle we return for GNUNET_CONNECTION_notify_transmit_ready.
260    */
261   struct GNUNET_CONNECTION_TransmitHandle nth;
262
263   /**
264    * Timeout for receiving (in absolute time).
265    */
266   struct GNUNET_TIME_Absolute receive_timeout;
267
268   /**
269    * Functions to call after connect failed or succeeded.
270    */
271   enum ConnectContinuations ccs;
272
273   /**
274    * Maximum number of bytes to read (for receiving).
275    */
276   size_t max;
277
278   /**
279    * Ignore GNUNET_SCHEDULER_REASON_SHUTDOWN for this socket.
280    */
281   int ignore_shutdown;
282
283   /**
284    * Port to connect to.
285    */
286   uint16_t port;
287
288   /**
289    * When shutdown, do not ever actually close the socket, but
290    * free resources.  Only should ever be set if using program
291    * termination as a signal (because only then will the leaked
292    * socket be freed!)
293    */
294   int16_t persist;
295
296 };
297
298 /**
299  * Set the persist option on this connection handle.  Indicates
300  * that the underlying socket or fd should never really be closed.
301  * Used for indicating process death.
302  *
303  * @param sock the connection to set persistent
304  */
305 void GNUNET_CONNECTION_persist_(struct GNUNET_CONNECTION_Handle *sock)
306 {
307   sock->persist = GNUNET_YES;
308 }
309
310 /**
311  * Create a socket handle by boxing an existing OS socket.  The OS
312  * socket should henceforth be no longer used directly.
313  * GNUNET_socket_destroy will close it.
314  *
315  * @param sched scheduler to use
316  * @param osSocket existing socket to box
317  * @param maxbuf maximum write buffer size for the socket (use
318  *        0 for sockets that need no write buffers, such as listen sockets)
319  * @return the boxed socket handle
320  */
321 struct GNUNET_CONNECTION_Handle *
322 GNUNET_CONNECTION_create_from_existing (struct GNUNET_SCHEDULER_Handle
323                                         *sched,
324                                         struct GNUNET_NETWORK_Handle
325                                         *osSocket, size_t maxbuf)
326 {
327   struct GNUNET_CONNECTION_Handle *ret;
328   ret = GNUNET_malloc (sizeof (struct GNUNET_CONNECTION_Handle) + maxbuf);
329   ret->write_buffer = (char *) &ret[1];
330   GNUNET_assert (maxbuf < GNUNET_SERVER_MAX_MESSAGE_SIZE);
331   ret->write_buffer_size = maxbuf;
332   ret->sock = osSocket;
333   ret->sched = sched;
334   return ret;
335 }
336
337
338 /**
339  * Create a socket handle by accepting on a listen socket.  This
340  * function may block if the listen socket has no connection ready.
341  *
342  * @param sched scheduler to use
343  * @param access function to use to check if access is allowed
344  * @param access_cls closure for access
345  * @param lsock listen socket
346  * @param maxbuf maximum write buffer size for the socket (use
347  *        0 for sockets that need no write buffers, such as listen sockets)
348  * @return the socket handle, NULL on error
349  */
350 struct GNUNET_CONNECTION_Handle *
351 GNUNET_CONNECTION_create_from_accept (struct GNUNET_SCHEDULER_Handle
352                                       *sched,
353                                       GNUNET_CONNECTION_AccessCheck access,
354                                       void *access_cls,
355                                       struct GNUNET_NETWORK_Handle *lsock,
356                                       size_t maxbuf)
357 {
358   struct GNUNET_CONNECTION_Handle *ret;
359   char addr[128];
360   socklen_t addrlen;
361   struct GNUNET_NETWORK_Handle *sock;
362   int aret;
363   struct sockaddr_in *v4;
364   struct sockaddr_in6 *v6;
365   struct sockaddr *sa;
366   void *uaddr;
367
368   addrlen = sizeof (addr);
369   sock =
370     GNUNET_NETWORK_socket_accept (lsock, (struct sockaddr *) &addr, &addrlen);
371   if (NULL == sock)
372     {
373       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "accept");
374       return NULL;
375     }
376   if ( (addrlen > sizeof (addr)) ||
377        (addrlen < sizeof (sa_family_t)) )
378     {
379       GNUNET_break (0);
380       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
381       return NULL;
382     }
383
384   sa = (struct sockaddr *) addr;
385   v6 = (struct sockaddr_in6 *) addr;
386   if ((sa->sa_family == AF_INET6) && (IN6_IS_ADDR_V4MAPPED (&v6->sin6_addr)))
387     {
388       /* convert to V4 address */
389       v4 = GNUNET_malloc (sizeof (struct sockaddr_in));
390       memset (v4, 0, sizeof (struct sockaddr_in));
391       v4->sin_family = AF_INET;
392       memcpy (&v4->sin_addr,
393               &((char *) &v6->sin6_addr)[sizeof (struct in6_addr) -
394                                          sizeof (struct in_addr)],
395               sizeof (struct in_addr));
396       v4->sin_port = v6->sin6_port;
397       uaddr = v4;
398       addrlen = sizeof (struct sockaddr_in);
399     }
400   else
401     {
402       uaddr = GNUNET_malloc (addrlen);
403       memcpy (uaddr, addr, addrlen);
404     }
405
406   if ((access != NULL) &&
407       (GNUNET_YES != (aret = access (access_cls, uaddr, addrlen))))
408     {
409       if (aret == GNUNET_NO)
410         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
411                     _("Access denied to `%s'\n"),
412                     GNUNET_a2s (uaddr, addrlen));
413       GNUNET_break (GNUNET_OK ==
414                     GNUNET_NETWORK_socket_shutdown (sock, SHUT_RDWR));
415       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
416       GNUNET_free (uaddr);
417       return NULL;
418     }
419   ret = GNUNET_malloc (sizeof (struct GNUNET_CONNECTION_Handle) + maxbuf);
420   ret->write_buffer = (char *) &ret[1];
421   GNUNET_assert (maxbuf < GNUNET_SERVER_MAX_MESSAGE_SIZE);
422   ret->write_buffer_size = maxbuf;
423   ret->addr = uaddr;
424   ret->addrlen = addrlen;
425   ret->sock = sock;
426   ret->sched = sched;
427 #if DEBUG_CONNECTION
428   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
429               _("Accepting connection from `%s': %p\n"),
430               GNUNET_a2s (uaddr, addrlen), ret);
431 #endif
432   return ret;
433 }
434
435 /**
436  * Obtain the network address of the other party.
437  *
438  * @param sock the client to get the address for
439  * @param addr where to store the address
440  * @param addrlen where to store the length of the address
441  * @return GNUNET_OK on success
442  */
443 int
444 GNUNET_CONNECTION_get_address (struct GNUNET_CONNECTION_Handle *sock,
445                                void **addr, size_t * addrlen)
446 {
447   if ((sock->addr == NULL) || (sock->addrlen == 0))
448     return GNUNET_NO;
449   *addr = GNUNET_malloc (sock->addrlen);
450   memcpy (*addr, sock->addr, sock->addrlen);
451   *addrlen = sock->addrlen;
452   return GNUNET_OK;
453 }
454
455
456 /**
457  * This function is called after establishing a connection either has
458  * succeeded or timed out.  Note that it is possible that the attempt
459  * timed out and that we're immediately retrying.  If we are retrying,
460  * we need to wait again (or timeout); if we succeeded, we need to
461  * wait for data (or timeout).
462  *
463  * @param cls our connection handle
464  * @param tc task context describing why we are here
465  */
466 static void
467 receive_again (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
468
469
470 /**
471  * Scheduler let us know that the connect task is finished (or was
472  * cancelled due to shutdown).  Now really clean up.
473  *
474  * @param cls our "struct GNUNET_CONNECTION_Handle *"
475  * @param tc unused
476  */
477 static void
478 destroy_continuation (void *cls,
479                       const struct GNUNET_SCHEDULER_TaskContext *tc)
480 {
481   struct GNUNET_CONNECTION_Handle *sock = cls;
482   GNUNET_CONNECTION_TransmitReadyNotify notify;
483   struct AddressProbe *pos;
484   
485   sock->destroy_task = GNUNET_SCHEDULER_NO_TASK;
486   GNUNET_assert (sock->dns_active == NULL);
487   if (0 != (sock->ccs & COCO_TRANSMIT_READY))
488     {
489 #if DEBUG_CONNECTION
490       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
491                   "Destroy waits for CCS-TR to be done (%p)\n", sock);
492 #endif
493       sock->ccs |= COCO_DESTROY_CONTINUATION;
494       return;
495     }
496   if (sock->write_task != GNUNET_SCHEDULER_NO_TASK)
497     {
498 #if DEBUG_CONNECTION
499       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
500                   "Destroy waits for write_task to be done (%p)\n", sock);
501 #endif
502       GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == sock->destroy_task);
503       sock->destroy_task 
504         = GNUNET_SCHEDULER_add_after (sock->sched,
505                                       sock->write_task,
506                                       &destroy_continuation, sock);
507       return;
508     }
509   if (0 != (sock->ccs & COCO_RECEIVE_AGAIN))
510     {
511       sock->ccs |= COCO_DESTROY_CONTINUATION;
512       return;
513     }
514   if (sock->sock != NULL)
515     {
516 #if DEBUG_CONNECTION
517       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
518                   "Shutting down socket (%p)\n", sock);
519 #endif
520       if (sock->persist != GNUNET_YES)
521         GNUNET_NETWORK_socket_shutdown (sock->sock, SHUT_RDWR);
522     }
523   if (sock->read_task != GNUNET_SCHEDULER_NO_TASK)
524     {
525       GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == sock->destroy_task);
526       sock->destroy_task 
527         = GNUNET_SCHEDULER_add_after (sock->sched,
528                                       sock->read_task,
529                                       &destroy_continuation, sock);
530       return;
531     }
532 #if DEBUG_CONNECTION
533   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
534               "Destroy actually runs (%p)!\n", sock);
535 #endif
536   while (NULL != (pos = sock->ap_head))
537     {
538       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (pos->sock));
539       GNUNET_SCHEDULER_cancel (sock->sched, pos->task);
540       GNUNET_CONTAINER_DLL_remove (sock->ap_head, sock->ap_tail, pos);
541       GNUNET_free (pos);
542     }
543   GNUNET_assert (sock->nth.timeout_task == GNUNET_SCHEDULER_NO_TASK);
544   GNUNET_assert (sock->ccs == COCO_NONE);
545   if (NULL != (notify = sock->nth.notify_ready))
546     {
547       sock->nth.notify_ready = NULL;
548       notify (sock->nth.notify_ready_cls, 0, NULL);
549     }
550
551   if (sock->sock != NULL) 
552     {
553       if (sock->persist != GNUNET_YES)
554         GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock->sock));
555       else
556         GNUNET_free (sock->sock); /* at least no memory leak (we deliberately
557                                      leak the socket in this special case) ... */
558     }
559   GNUNET_free_non_null (sock->addr);
560   GNUNET_free_non_null (sock->hostname);
561   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == sock->destroy_task);
562 #if DEBUG_CONNECTION
563   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
564               "Freeing memory of connection %p.\n", sock);
565 #endif
566   GNUNET_free (sock);
567 }
568
569
570
571 /**
572  * See if we are now connected.  If not, wait longer for
573  * connect to succeed.  If connected, we should be able
574  * to write now as well, unless we timed out.
575  *
576  * @param cls our connection handle
577  * @param tc task context describing why we are here
578  */
579 static void
580 transmit_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
581
582
583 /**
584  * We've failed for good to establish a connection.
585  *
586  * @param h the connection we tried to establish
587  */
588 static void
589 connect_fail_continuation (struct GNUNET_CONNECTION_Handle *h)
590 {
591   GNUNET_log ((0 != strncmp (h->hostname, 
592                              "localhost:",
593                              10)) 
594               ? GNUNET_ERROR_TYPE_INFO 
595               : GNUNET_ERROR_TYPE_WARNING,
596               _("Failed to establish TCP connection to `%s:%u', no further addresses to try.\n"),
597               h->hostname, h->port);
598   /* connect failed / timed out */
599   GNUNET_break (h->ap_head == NULL);
600   GNUNET_break (h->ap_tail == NULL);
601   GNUNET_break (h->dns_active == GNUNET_NO);
602   GNUNET_break (h->sock == NULL);
603
604   /* trigger jobs that used to wait on "connect_task" */
605   if (0 != (h->ccs & COCO_RECEIVE_AGAIN))
606     {
607 #if DEBUG_CONNECTION
608       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
609                   "connect_fail_continuation triggers receive_again (%p)\n",
610                   h);
611 #endif
612       h->ccs -= COCO_RECEIVE_AGAIN;
613       h->read_task = GNUNET_SCHEDULER_add_after (h->sched,
614                                                  GNUNET_SCHEDULER_NO_TASK,
615                                                  &receive_again, h);
616     }
617   if (0 != (h->ccs & COCO_TRANSMIT_READY))
618     {
619 #if DEBUG_CONNECTION
620       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
621                   "connect_fail_continuation cancels timeout_task, triggers transmit_ready (%p)\n",
622                   h);
623 #endif
624       GNUNET_assert (h->nth.timeout_task != GNUNET_SCHEDULER_NO_TASK);
625       GNUNET_SCHEDULER_cancel (h->sched, h->nth.timeout_task);
626       h->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK;
627       h->ccs -= COCO_TRANSMIT_READY;
628       GNUNET_assert (h->write_task == GNUNET_SCHEDULER_NO_TASK);
629       h->write_task = GNUNET_SCHEDULER_add_after (h->sched,
630                                                   GNUNET_SCHEDULER_NO_TASK,
631                                                   &transmit_ready, h);
632     }
633   if (0 != (h->ccs & COCO_DESTROY_CONTINUATION))
634     {
635 #if DEBUG_CONNECTION
636       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
637                   "connect_fail_continuation runs destroy_continuation (%p)\n",
638                   h);
639 #endif
640       h->ccs -= COCO_DESTROY_CONTINUATION;
641       GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == h->destroy_task);
642       h->destroy_task
643         = GNUNET_SCHEDULER_add_now (h->sched,
644                                     &destroy_continuation,
645                                     h);
646     }
647 }
648
649
650 /**
651  * We've succeeded in establishing a connection.
652  *
653  * @param h the connection we tried to establish
654  */
655 static void
656 connect_success_continuation (struct GNUNET_CONNECTION_Handle *h)
657 {
658 #if DEBUG_CONNECTION
659   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
660               "Connection to `%s' succeeded! (%p)\n",
661               GNUNET_a2s (h->addr, h->addrlen), h);
662 #endif
663   /* trigger jobs that waited for the connection */
664   if (0 != (h->ccs & COCO_RECEIVE_AGAIN))
665     {
666 #if DEBUG_CONNECTION
667       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
668                   "connect_success_continuation runs receive_again (%p)\n",
669                   h);
670 #endif
671       h->ccs -= COCO_RECEIVE_AGAIN;
672       h->read_task = GNUNET_SCHEDULER_add_after (h->sched,
673                                                  GNUNET_SCHEDULER_NO_TASK,
674                                                  &receive_again, h);
675     }
676   if (0 != (h->ccs & COCO_TRANSMIT_READY))
677     {
678 #if DEBUG_CONNECTION
679       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
680                   "connect_success_continuation runs transmit_ready, cancels timeout_task (%p)\n",
681                   h);
682 #endif
683       GNUNET_assert (h->nth.timeout_task != GNUNET_SCHEDULER_NO_TASK);
684       GNUNET_SCHEDULER_cancel (h->sched, h->nth.timeout_task);
685       h->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK;
686       h->ccs -= COCO_TRANSMIT_READY;
687       GNUNET_assert (h->write_task == GNUNET_SCHEDULER_NO_TASK);
688       h->write_task =
689         GNUNET_SCHEDULER_add_write_net (h->sched,
690                                         GNUNET_TIME_absolute_get_remaining
691                                         (h->nth.transmit_timeout), h->sock,
692                                         &transmit_ready, h);
693     }
694   if (0 != (h->ccs & COCO_DESTROY_CONTINUATION))
695     {
696 #if DEBUG_CONNECTION
697       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
698                   "connect_success_continuation runs destroy_continuation (%p)\n",
699                   h);
700 #endif
701       h->ccs -= COCO_DESTROY_CONTINUATION;
702       GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == h->destroy_task);
703       h->destroy_task
704         = GNUNET_SCHEDULER_add_now (h->sched,
705                                     &destroy_continuation,
706                                     h);
707     }
708 }
709
710
711 /**
712  * Scheduler let us know that we're either ready to write on the
713  * socket OR connect timed out.  Do the right thing.
714  *
715  * @param cls the "struct AddressProbe*" with the address that we are probing
716  * @param tc success or failure info about the connect attempt.
717  */
718 static void
719 connect_probe_continuation (void *cls,
720                             const struct GNUNET_SCHEDULER_TaskContext *tc)
721 {
722   struct AddressProbe *ap = cls;
723   struct GNUNET_CONNECTION_Handle *h = ap->h;
724   struct AddressProbe *pos;
725   int error;
726   unsigned int len;
727
728   GNUNET_CONTAINER_DLL_remove (h->ap_head, h->ap_tail, ap);
729   len = sizeof (error);
730   errno = 0;
731   error = 0;
732   if ( (0 == (tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) ||
733        (GNUNET_OK !=
734         GNUNET_NETWORK_socket_getsockopt (ap->sock, SOL_SOCKET, SO_ERROR,
735                                           &error, &len)) ||
736        (error != 0) )
737     {
738       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (ap->sock));
739       GNUNET_free (ap);
740       if ((NULL == h->ap_head) && (h->dns_active == GNUNET_NO))
741         connect_fail_continuation (h);
742       return;
743     }
744   GNUNET_assert (h->sock == NULL);
745   GNUNET_assert (ap->sock != NULL);
746   h->sock = ap->sock;
747   GNUNET_assert (h->addr == NULL);
748   h->addr = GNUNET_malloc (ap->addrlen);
749   memcpy (h->addr, ap->addr, ap->addrlen);
750   h->addrlen = ap->addrlen;
751   GNUNET_free (ap);
752   /* cancel all other attempts */
753   while (NULL != (pos = h->ap_head))
754     {
755       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (pos->sock));
756       GNUNET_SCHEDULER_cancel (h->sched, pos->task);
757       GNUNET_CONTAINER_DLL_remove (h->ap_head, h->ap_tail, pos);
758       GNUNET_free (pos);
759     }
760   connect_success_continuation (h);
761 }
762
763
764 /**
765  * Try to establish a socket connection given the specified address.
766  * This function is called by the resolver once we have a DNS reply.
767  *
768  * @param cls our "struct GNUNET_CONNECTION_Handle *"
769  * @param addr address to try, NULL for "last call"
770  * @param addrlen length of addr
771  */
772 static void
773 try_connect_using_address (void *cls,
774                            const struct sockaddr *addr, socklen_t addrlen)
775 {
776   struct GNUNET_CONNECTION_Handle *h = cls;
777   struct AddressProbe *ap;
778   struct GNUNET_TIME_Relative delay;
779
780   if (addr == NULL)
781     {
782       h->dns_active = NULL;
783       if (NULL == h->ap_head)
784         connect_fail_continuation (h);
785       return;
786     }
787   if (h->sock != NULL)
788     return;                     /* already connected */
789   GNUNET_assert (h->addr == NULL);
790   /* try to connect */
791 #if DEBUG_CONNECTION
792   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
793               "Trying to connect using address `%s:%u/%s:%u'\n",
794               h->hostname, h->port, GNUNET_a2s (addr, addrlen), h->port);
795 #endif
796   ap = GNUNET_malloc (sizeof (struct AddressProbe) + addrlen);
797   ap->addr = (const struct sockaddr *) &ap[1];
798   memcpy (&ap[1], addr, addrlen);
799   ap->addrlen = addrlen;
800   ap->h = h;
801
802   switch (ap->addr->sa_family)
803     {
804     case AF_INET:
805       ((struct sockaddr_in *) ap->addr)->sin_port = htons (h->port);
806       break;
807     case AF_INET6:
808       ((struct sockaddr_in6 *) ap->addr)->sin6_port = htons (h->port);
809       break;
810     default:
811       GNUNET_break (0);
812       GNUNET_free (ap);
813       return;                   /* not supported by us */
814     }
815   ap->sock =
816     GNUNET_NETWORK_socket_create (ap->addr->sa_family, SOCK_STREAM, 0);
817   if (ap->sock == NULL)
818     {
819       GNUNET_free (ap);
820       return;                   /* not supported by OS */
821     }
822   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
823               _("Trying to connect to `%s' (%p)\n"),
824               GNUNET_a2s (ap->addr, ap->addrlen), h);
825   if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (ap->sock,
826                                                    ap->addr,
827                                                    ap->addrlen)) &&
828       (errno != EINPROGRESS))
829     {
830       /* maybe refused / unsupported address, try next */
831       GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO, "connect");
832       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (ap->sock));
833       GNUNET_free (ap);
834       return;
835     }
836   GNUNET_CONTAINER_DLL_insert (h->ap_head, h->ap_tail, ap);
837   delay = GNUNET_CONNECTION_CONNECT_RETRY_TIMEOUT;
838   if (h->nth.notify_ready != NULL)
839     delay = GNUNET_TIME_relative_min (delay,
840                                       GNUNET_TIME_absolute_get_remaining
841                                       (h->nth.transmit_timeout));
842   if (h->receiver != NULL)
843     delay = GNUNET_TIME_relative_min (delay,
844                                       GNUNET_TIME_absolute_get_remaining
845                                       (h->receive_timeout));
846   ap->task =
847     GNUNET_SCHEDULER_add_write_net (h->sched, delay, ap->sock,
848                                     &connect_probe_continuation, ap);
849 }
850
851
852 /**
853  * Create a socket handle by (asynchronously) connecting to a host.
854  * This function returns immediately, even if the connection has not
855  * yet been established.  This function only creates TCP connections.
856  *
857  * @param sched scheduler to use
858  * @param cfg configuration to use
859  * @param hostname name of the host to connect to
860  * @param port port to connect to
861  * @param maxbuf maximum write buffer size for the socket (use
862  *        0 for sockets that need no write buffers, such as listen sockets)
863  * @return the socket handle
864  */
865 struct GNUNET_CONNECTION_Handle *
866 GNUNET_CONNECTION_create_from_connect (struct GNUNET_SCHEDULER_Handle *sched,
867                                        const struct
868                                        GNUNET_CONFIGURATION_Handle *cfg,
869                                        const char *hostname, uint16_t port,
870                                        size_t maxbuf)
871 {
872   struct GNUNET_CONNECTION_Handle *ret;
873
874   GNUNET_assert (0 < strlen (hostname));        /* sanity check */
875   ret = GNUNET_malloc (sizeof (struct GNUNET_CONNECTION_Handle) + maxbuf);
876   ret->cfg = cfg;
877   ret->sched = sched;
878   ret->write_buffer = (char *) &ret[1];
879   GNUNET_assert (maxbuf < GNUNET_SERVER_MAX_MESSAGE_SIZE);
880   ret->write_buffer_size = maxbuf;
881   ret->port = port;
882   ret->hostname = GNUNET_strdup (hostname);
883   ret->dns_active = GNUNET_RESOLVER_ip_get (sched,
884                                             cfg,
885                                             ret->hostname,
886                                             AF_UNSPEC,
887                                             GNUNET_CONNECTION_CONNECT_RETRY_TIMEOUT,
888                                             &try_connect_using_address, ret);
889   return ret;
890 }
891
892
893 /**
894  * Create a socket handle by connecting to a UNIX domain service.
895  * This function returns immediately, even if the connection has not
896  * yet been established.  This function only creates UNIX connections.
897  *
898  * @param sched scheduler to use
899  * @param cfg configuration to use
900  * @param unixpath path to connect to
901  * @param maxbuf maximum write buffer size for the socket (use
902  *        0 for sockets that need no write buffers, such as listen sockets)
903  * @return the socket handle, NULL on systems without UNIX support
904  */
905 struct GNUNET_CONNECTION_Handle *
906 GNUNET_CONNECTION_create_from_connect_to_unixpath (struct GNUNET_SCHEDULER_Handle *sched,
907                                                    const struct
908                                                    GNUNET_CONFIGURATION_Handle *cfg,
909                                                    const char *unixpath,
910                                                    size_t maxbuf)
911 {
912 #ifdef AF_UNIX
913   struct GNUNET_CONNECTION_Handle *ret;
914   struct sockaddr_un *un;
915   size_t slen;
916
917   GNUNET_assert (0 < strlen (unixpath));        /* sanity check */
918   un = GNUNET_malloc (sizeof (struct sockaddr_un));
919   un->sun_family = AF_UNIX;
920   slen = strlen (unixpath) + 1;
921   if (slen >= sizeof (un->sun_path))
922     slen = sizeof (un->sun_path) - 1;
923   memcpy (un->sun_path,
924           unixpath,
925           slen);
926   un->sun_path[slen] = '\0';
927   slen += sizeof (sa_family_t);
928 #if LINUX
929   un->sun_path[0] = '\0';
930   slen = sizeof (struct sockaddr_un);
931 #endif
932   ret = GNUNET_malloc (sizeof (struct GNUNET_CONNECTION_Handle) + maxbuf);
933   ret->cfg = cfg;
934   ret->sched = sched;
935   ret->write_buffer = (char *) &ret[1];
936   GNUNET_assert (maxbuf < GNUNET_SERVER_MAX_MESSAGE_SIZE);
937   ret->write_buffer_size = maxbuf;
938   ret->port = 0;
939   ret->hostname = NULL;
940   ret->addr = (struct sockaddr*) un;
941   ret->addrlen = slen;
942   ret->sock = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
943   if (NULL == ret->sock)
944     {
945       GNUNET_free (un);
946       GNUNET_free (ret);
947       return NULL;
948     }
949   if (GNUNET_OK != GNUNET_NETWORK_socket_connect (ret->sock,
950                                                   ret->addr,
951                                                   ret->addrlen)) 
952     {
953       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (ret->sock));
954       GNUNET_free (ret->addr);
955       GNUNET_free (ret);
956       return NULL;
957     }
958   connect_success_continuation (ret);
959   return ret;
960 #else
961   return NULL;
962 #endif
963 }
964
965
966 /**
967  * Create a socket handle by (asynchronously) connecting to a host.
968  * This function returns immediately, even if the connection has not
969  * yet been established.  This function only creates TCP connections.
970  *
971  * @param sched scheduler to use
972  * @param af_family address family to use
973  * @param serv_addr server address
974  * @param addrlen length of server address
975  * @param maxbuf maximum write buffer size for the socket (use
976  *        0 for sockets that need no write buffers, such as listen sockets)
977  * @return the socket handle
978  */
979 struct GNUNET_CONNECTION_Handle *
980 GNUNET_CONNECTION_create_from_sockaddr (struct GNUNET_SCHEDULER_Handle
981                                         *sched, int af_family,
982                                         const struct sockaddr *serv_addr,
983                                         socklen_t addrlen, size_t maxbuf)
984 {
985   struct GNUNET_NETWORK_Handle *s;
986   struct GNUNET_CONNECTION_Handle *ret;
987
988   s = GNUNET_NETWORK_socket_create (af_family, SOCK_STREAM, 0);
989   if (s == NULL)
990     {
991       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING |
992                            GNUNET_ERROR_TYPE_BULK, "socket");
993       return NULL;
994     }
995   if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (s, serv_addr, addrlen))
996       && (errno != EINPROGRESS))
997     {
998       /* maybe refused / unsupported address, try next */
999       GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO, "connect");
1000       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (s));
1001       return NULL;
1002     }
1003   ret = GNUNET_CONNECTION_create_from_existing (sched, s, maxbuf);
1004   ret->addr = GNUNET_malloc (addrlen);
1005   memcpy (ret->addr, serv_addr, addrlen);
1006   ret->addrlen = addrlen;
1007 #if DEBUG_CONNECTION
1008   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1009               _("Trying to connect to `%s' (%p)\n"),
1010               GNUNET_a2s (serv_addr, addrlen), ret);
1011 #endif
1012   return ret;
1013 }
1014
1015
1016 /**
1017  * Check if socket is valid (no fatal errors have happened so far).
1018  * Note that a socket that is still trying to connect is considered
1019  * valid.
1020  *
1021  * @param sock socket to check
1022  * @return GNUNET_YES if valid, GNUNET_NO otherwise
1023  */
1024 int
1025 GNUNET_CONNECTION_check (struct GNUNET_CONNECTION_Handle *sock)
1026 {
1027   if ((sock->ap_head != NULL) || (sock->dns_active != NULL))
1028     return GNUNET_YES;          /* still trying to connect */
1029   return (sock->sock == NULL) ? GNUNET_NO : GNUNET_YES;
1030 }
1031
1032
1033 /**
1034  * Close the socket and free associated resources. Pending
1035  * transmissions may be completed or dropped depending on the
1036  * arguments.   If a receive call is pending and should 
1037  * NOT be completed, 'GNUNET_CONNECTION_receive_cancel'
1038  * should be called explicitly first.
1039  *
1040  * @param sock socket to destroy
1041  * @param finish_pending_write should pending writes be completed or aborted?
1042  *        (this applies to transmissions where the data has already been
1043  *        read from the application; all other transmissions should be
1044  *        aborted using 'GNUNET_CONNECTION_notify_transmit_ready_cancel').
1045  */
1046 void
1047 GNUNET_CONNECTION_destroy (struct GNUNET_CONNECTION_Handle *sock,
1048                            int finish_pending_write)
1049 {
1050   if (GNUNET_NO == finish_pending_write)
1051     {
1052       if (sock->write_task != GNUNET_SCHEDULER_NO_TASK)
1053         {
1054           GNUNET_SCHEDULER_cancel (sock->sched,
1055                                    sock->write_task);
1056           sock->write_task = GNUNET_SCHEDULER_NO_TASK;
1057           sock->write_buffer_off = 0;
1058         }
1059     }
1060   if ((sock->write_buffer_off == 0) && (sock->dns_active != NULL))
1061     {
1062       GNUNET_RESOLVER_request_cancel (sock->dns_active);
1063       sock->dns_active = NULL;
1064     }
1065   GNUNET_assert (sock->sched != NULL);
1066   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == sock->destroy_task);
1067   sock->destroy_task 
1068     = GNUNET_SCHEDULER_add_now (sock->sched,
1069                                 &destroy_continuation, sock);
1070 }
1071
1072
1073 /**
1074  * Tell the receiver callback that a timeout was reached.
1075  */
1076 static void
1077 signal_timeout (struct GNUNET_CONNECTION_Handle *sh)
1078 {
1079   GNUNET_CONNECTION_Receiver receiver;
1080
1081 #if DEBUG_CONNECTION
1082   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1083               "Network signals time out to receiver (%p)!\n", sh);
1084 #endif
1085   GNUNET_assert (NULL != (receiver = sh->receiver));
1086   sh->receiver = NULL;
1087   receiver (sh->receiver_cls, NULL, 0, NULL, 0, 0);
1088 }
1089
1090
1091 /**
1092  * Tell the receiver callback that we had an IO error.
1093  */
1094 static void
1095 signal_error (struct GNUNET_CONNECTION_Handle *sh, int errcode)
1096 {
1097   GNUNET_CONNECTION_Receiver receiver;
1098   GNUNET_assert (NULL != (receiver = sh->receiver));
1099   sh->receiver = NULL;
1100   receiver (sh->receiver_cls, NULL, 0, sh->addr, sh->addrlen, errcode);
1101 }
1102
1103
1104 /**
1105  * This function is called once we either timeout
1106  * or have data ready to read.
1107  */
1108 static void
1109 receive_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1110 {
1111   struct GNUNET_CONNECTION_Handle *sh = cls;
1112   struct GNUNET_TIME_Absolute now;
1113   char buffer[sh->max];
1114   ssize_t ret;
1115   GNUNET_CONNECTION_Receiver receiver;
1116
1117   sh->read_task = GNUNET_SCHEDULER_NO_TASK;
1118   if ( (GNUNET_YES == sh->ignore_shutdown) &&
1119        (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))) 
1120     {
1121       /* ignore shutdown request, go again immediately */
1122 #if DEBUG_CONNECTION
1123       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1124                   "Ignoring shutdown signal per configuration\n");
1125 #endif
1126       sh->read_task = GNUNET_SCHEDULER_add_read_net (tc->sched,
1127                                                      GNUNET_TIME_absolute_get_remaining
1128                                                      (sh->receive_timeout),
1129                                                      sh->sock,
1130                                                      &receive_ready, sh);
1131       return;
1132     }
1133   now = GNUNET_TIME_absolute_get ();
1134   if ((now.value > sh->receive_timeout.value) ||
1135       (0 != (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT)) ||
1136       (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)))
1137     {
1138 #if DEBUG_CONNECTION
1139       if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1140         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1141                     "Receive from `%s' encounters error: time out by %llums... (%p)\n",
1142                     GNUNET_a2s (sh->addr, sh->addrlen),
1143                     GNUNET_TIME_absolute_get_duration (sh->receive_timeout).
1144                     value, sh);
1145 #endif
1146       signal_timeout (sh);
1147       return;
1148     }
1149   if (sh->sock == NULL)
1150     {
1151       /* connect failed for good */
1152 #if DEBUG_CONNECTION
1153       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1154                   "Receive encounters error, socket closed... (%p)\n", sh);
1155 #endif
1156       signal_error (sh, ECONNREFUSED);
1157       return;
1158     }
1159   GNUNET_assert (GNUNET_NETWORK_fdset_isset (tc->read_ready, sh->sock));
1160 RETRY:
1161   ret = GNUNET_NETWORK_socket_recv (sh->sock, buffer, sh->max);
1162   if (ret == -1)
1163     {
1164       if (errno == EINTR)
1165         goto RETRY;
1166 #if DEBUG_CONNECTION
1167       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1168                   "Error receiving: %s\n", STRERROR (errno));
1169 #endif
1170       signal_error (sh, errno);
1171       return;
1172     }
1173 #if DEBUG_CONNECTION
1174   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1175               "receive_ready read %u/%u bytes from `%s' (%p)!\n",
1176               (unsigned int) ret,
1177               sh->max, GNUNET_a2s (sh->addr, sh->addrlen), sh);
1178 #endif
1179   GNUNET_assert (NULL != (receiver = sh->receiver));
1180   sh->receiver = NULL;
1181   receiver (sh->receiver_cls, buffer, ret, sh->addr, sh->addrlen, 0);
1182 }
1183
1184
1185 /**
1186  * This function is called after establishing a connection either has
1187  * succeeded or timed out.  Note that it is possible that the attempt
1188  * timed out and that we're immediately retrying.  If we are retrying,
1189  * we need to wait again (or timeout); if we succeeded, we need to
1190  * wait for data (or timeout).
1191  *
1192  * @param cls our connection handle
1193  * @param tc task context describing why we are here
1194  */
1195 static void
1196 receive_again (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1197 {
1198   struct GNUNET_CONNECTION_Handle *sh = cls;
1199   struct GNUNET_TIME_Absolute now;
1200
1201   sh->read_task = GNUNET_SCHEDULER_NO_TASK;
1202   if (sh->sock == NULL)
1203     {
1204       /* not connected and no longer trying */
1205 #if DEBUG_CONNECTION
1206       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1207                   "Receive encounters error, socket closed (%p)...\n", sh);
1208 #endif
1209       signal_error (sh, ECONNREFUSED);
1210       return;
1211     }
1212   now = GNUNET_TIME_absolute_get ();
1213   if ((now.value > sh->receive_timeout.value) ||
1214       (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)))
1215     {
1216 #if DEBUG_CONNECTION
1217       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1218                   "Receive encounters error: time out (%p)...\n", sh);
1219 #endif
1220       signal_timeout (sh);
1221       return;
1222     }
1223   GNUNET_assert (sh->sock != NULL);
1224   /* connect succeeded, wait for data! */
1225   sh->read_task = GNUNET_SCHEDULER_add_read_net (tc->sched,
1226                                                  GNUNET_TIME_absolute_get_remaining
1227                                                  (sh->receive_timeout),
1228                                                  sh->sock,
1229                                                  &receive_ready, sh);
1230 }
1231
1232
1233 /**
1234  * Receive data from the given socket.  Note that this function will
1235  * call "receiver" asynchronously using the scheduler.  It will
1236  * "immediately" return.  Note that there MUST only be one active
1237  * receive call per socket at any given point in time (so do not
1238  * call receive again until the receiver callback has been invoked).
1239  *
1240  * @param sock socket handle
1241  * @param max maximum number of bytes to read
1242  * @param timeout maximum amount of time to wait (use -1 for "forever")
1243  * @param receiver function to call with received data
1244  * @param receiver_cls closure for receiver
1245  */
1246 void
1247 GNUNET_CONNECTION_receive (struct GNUNET_CONNECTION_Handle *sock,
1248                            size_t max,
1249                            struct GNUNET_TIME_Relative timeout,
1250                            GNUNET_CONNECTION_Receiver receiver,
1251                            void *receiver_cls)
1252 {
1253   struct GNUNET_SCHEDULER_TaskContext tc;
1254
1255   GNUNET_assert ((sock->read_task == GNUNET_SCHEDULER_NO_TASK) &&
1256                  (0 == (sock->ccs & COCO_RECEIVE_AGAIN)) &&
1257                  (sock->receiver == NULL));
1258   sock->receiver = receiver;
1259   sock->receiver_cls = receiver_cls;
1260   sock->receive_timeout = GNUNET_TIME_relative_to_absolute (timeout);
1261   sock->max = max;
1262   if (sock->sock != NULL)
1263     {
1264       memset (&tc, 0, sizeof (tc));
1265       tc.sched = sock->sched;
1266       tc.reason = GNUNET_SCHEDULER_REASON_PREREQ_DONE;
1267       receive_again (sock, &tc);
1268       return;
1269     }
1270   if ((sock->dns_active == NULL) && (sock->ap_head == NULL))
1271     {
1272       receiver (receiver_cls, NULL, 0, NULL, 0, ETIMEDOUT);
1273       return;
1274     }
1275   sock->ccs += COCO_RECEIVE_AGAIN;
1276 }
1277
1278
1279 /**
1280  * Configure this connection to ignore shutdown signals.
1281  *
1282  * @param sock socket handle
1283  * @param do_ignore GNUNET_YES to ignore, GNUNET_NO to restore default
1284  */
1285 void
1286 GNUNET_CONNECTION_ignore_shutdown (struct GNUNET_CONNECTION_Handle *sock,
1287                                    int do_ignore)
1288 {
1289   sock->ignore_shutdown = do_ignore;
1290 }
1291
1292
1293 /**
1294  * Cancel receive job on the given socket.  Note that the
1295  * receiver callback must not have been called yet in order
1296  * for the cancellation to be valid.
1297  *
1298  * @param sock socket handle
1299  * @return closure of the original receiver callback closure
1300  */
1301 void *
1302 GNUNET_CONNECTION_receive_cancel (struct GNUNET_CONNECTION_Handle *sock)
1303 {
1304   if (sock->read_task != GNUNET_SCHEDULER_NO_TASK)
1305     {
1306       GNUNET_assert (sock == GNUNET_SCHEDULER_cancel (sock->sched,
1307                                                       sock->read_task));
1308       sock->read_task = GNUNET_SCHEDULER_NO_TASK;
1309     }
1310   else
1311     {
1312       GNUNET_assert (0 != (sock->ccs & COCO_RECEIVE_AGAIN));
1313       sock->ccs -= COCO_RECEIVE_AGAIN;
1314     }
1315   sock->receiver = NULL;
1316   return sock->receiver_cls;
1317 }
1318
1319
1320 /**
1321  * Try to call the transmit notify method (check if we do
1322  * have enough space available first)!
1323  *
1324  * @param sock socket for which we should do this processing
1325  * @return GNUNET_YES if we were able to call notify
1326  */
1327 static int
1328 process_notify (struct GNUNET_CONNECTION_Handle *sock)
1329 {
1330   size_t used;
1331   size_t avail;
1332   size_t size;
1333   GNUNET_CONNECTION_TransmitReadyNotify notify;
1334
1335   GNUNET_assert (sock->write_task == GNUNET_SCHEDULER_NO_TASK);
1336   if (NULL == (notify = sock->nth.notify_ready))
1337     return GNUNET_NO;
1338   used = sock->write_buffer_off - sock->write_buffer_pos;
1339   avail = sock->write_buffer_size - used;
1340   size = sock->nth.notify_size;
1341   if (sock->nth.notify_size > avail)
1342     return GNUNET_NO;
1343   sock->nth.notify_ready = NULL;
1344   if (sock->write_buffer_size - sock->write_buffer_off < size)
1345     {
1346       /* need to compact */
1347       memmove (sock->write_buffer,
1348                &sock->write_buffer[sock->write_buffer_pos], used);
1349       sock->write_buffer_off -= sock->write_buffer_pos;
1350       sock->write_buffer_pos = 0;
1351     }
1352   GNUNET_assert (sock->write_buffer_size - sock->write_buffer_off >= size);
1353   size = notify (sock->nth.notify_ready_cls,
1354                  sock->write_buffer_size - sock->write_buffer_off,
1355                  &sock->write_buffer[sock->write_buffer_off]);
1356   sock->write_buffer_off += size;
1357   return GNUNET_YES;
1358 }
1359
1360
1361 /**
1362  * Task invoked by the scheduler when a call to transmit
1363  * is timing out (we never got enough buffer space to call
1364  * the callback function before the specified timeout
1365  * expired).
1366  *
1367  * This task notifies the client about the timeout.
1368  */
1369 static void
1370 transmit_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1371 {
1372   struct GNUNET_CONNECTION_Handle *sock = cls;
1373   GNUNET_CONNECTION_TransmitReadyNotify notify;
1374
1375 #if DEBUG_CONNECTION
1376   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1377               "transmit_timeout running (%p)\n", sock);
1378 #endif
1379   sock->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK;
1380 #if DEBUG_CONNECTION
1381   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1382               "Transmit to `%s:%u/%s' fails, time out reached (%p).\n",
1383               sock->hostname,
1384               sock->port, GNUNET_a2s (sock->addr, sock->addrlen), sock);
1385 #endif
1386   GNUNET_assert (0 != (sock->ccs & COCO_TRANSMIT_READY));
1387   sock->ccs -= COCO_TRANSMIT_READY;     /* remove request */
1388   notify = sock->nth.notify_ready;
1389   sock->nth.notify_ready = NULL;
1390   notify (sock->nth.notify_ready_cls, 0, NULL);
1391 }
1392
1393
1394 /**
1395  * Task invoked by the scheduler when we failed to connect
1396  * at the time of being asked to transmit.
1397  *
1398  * This task notifies the client about the error.
1399  */
1400 static void
1401 connect_error (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1402 {
1403   struct GNUNET_CONNECTION_Handle *sock = cls;
1404   GNUNET_CONNECTION_TransmitReadyNotify notify;
1405
1406 #if DEBUG_CONNECTION
1407   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1408               "Transmission request of size %u fails, connection failed (%p).\n",
1409               sock->nth.notify_size, sock);
1410 #endif
1411   sock->write_task = GNUNET_SCHEDULER_NO_TASK;
1412   notify = sock->nth.notify_ready;
1413   sock->nth.notify_ready = NULL;
1414   notify (sock->nth.notify_ready_cls, 0, NULL);
1415 }
1416
1417
1418 static void
1419 transmit_error (struct GNUNET_CONNECTION_Handle *sock)
1420 {
1421   GNUNET_CONNECTION_TransmitReadyNotify notify;
1422
1423   if (NULL != sock->sock)
1424     {
1425       GNUNET_NETWORK_socket_shutdown (sock->sock, SHUT_RDWR);
1426       GNUNET_break (GNUNET_OK ==
1427                     GNUNET_NETWORK_socket_close (sock->sock));
1428       sock->sock = NULL;
1429     }
1430   if (sock->read_task != GNUNET_SCHEDULER_NO_TASK)
1431     {
1432       GNUNET_SCHEDULER_cancel (sock->sched,
1433                                sock->read_task);
1434       sock->read_task = GNUNET_SCHEDULER_NO_TASK;
1435       signal_timeout (sock);
1436       return;
1437     }
1438   if (sock->nth.notify_ready == NULL)
1439     return;                     /* nobody to tell about it */
1440   notify = sock->nth.notify_ready;
1441   sock->nth.notify_ready = NULL;
1442   notify (sock->nth.notify_ready_cls, 0, NULL);
1443 }
1444
1445
1446 /**
1447  * See if we are now connected.  If not, wait longer for
1448  * connect to succeed.  If connected, we should be able
1449  * to write now as well, unless we timed out.
1450  *
1451  * @param cls our connection handle
1452  * @param tc task context describing why we are here
1453  */
1454 static void
1455 transmit_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1456 {
1457   struct GNUNET_CONNECTION_Handle *sock = cls;
1458   GNUNET_CONNECTION_TransmitReadyNotify notify;
1459   ssize_t ret;
1460   size_t have;
1461
1462 #if DEBUG_CONNECTION
1463   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1464               "transmit_ready running (%p).\n", sock);
1465 #endif
1466   GNUNET_assert (sock->write_task != GNUNET_SCHEDULER_NO_TASK);
1467   sock->write_task = GNUNET_SCHEDULER_NO_TASK;
1468   GNUNET_assert (sock->nth.timeout_task == GNUNET_SCHEDULER_NO_TASK);
1469   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) 
1470     {
1471       if (sock->ignore_shutdown == GNUNET_YES)
1472         goto SCHEDULE_WRITE;    /* ignore shutdown, go again immediately */
1473 #if DEBUG_CONNECTION
1474       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1475                   "Transmit to `%s' fails, shutdown happened (%p).\n",
1476                   GNUNET_a2s (sock->addr, sock->addrlen), sock);
1477 #endif
1478       notify = sock->nth.notify_ready;
1479       sock->nth.notify_ready = NULL;
1480       notify (sock->nth.notify_ready_cls, 0, NULL);
1481       return;
1482     }
1483   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT))
1484     {
1485 #if DEBUG_CONNECTION
1486       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1487                   "Transmit to `%s' fails, time out reached (%p).\n",
1488                   GNUNET_a2s (sock->addr, sock->addrlen), sock);
1489 #endif
1490       notify = sock->nth.notify_ready;
1491       sock->nth.notify_ready = NULL;
1492       notify (sock->nth.notify_ready_cls, 0, NULL);
1493       return;
1494     }
1495   GNUNET_assert (NULL != sock->sock);
1496   if (tc->write_ready == NULL)
1497     {
1498       /* special circumstances (in particular,
1499          PREREQ_DONE after connect): not yet ready to write,
1500          but no "fatal" error either.  Hence retry.  */
1501       goto SCHEDULE_WRITE;
1502     }
1503   if (!GNUNET_NETWORK_fdset_isset (tc->write_ready, sock->sock))
1504     {
1505 #if DEBUG_CONNECTION
1506       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1507                   _
1508                   ("Could not satisfy pending transmission request, socket closed or connect failed (%p).\n"),
1509                   sock);
1510 #endif
1511       transmit_error (sock);
1512       return;                   /* connect failed for good, we're finished */
1513     }
1514   GNUNET_assert (sock->write_buffer_off >= sock->write_buffer_pos);
1515   process_notify (sock);
1516   have = sock->write_buffer_off - sock->write_buffer_pos;
1517   if (have == 0)
1518     {
1519       /* no data ready for writing, terminate write loop */
1520       return;
1521     }
1522   GNUNET_assert (have <= sock->write_buffer_size);
1523   GNUNET_assert (have + sock->write_buffer_pos <= sock->write_buffer_size);
1524   GNUNET_assert (sock->write_buffer_pos <= sock->write_buffer_size);
1525 RETRY:
1526   ret = GNUNET_NETWORK_socket_send (sock->sock,
1527                                     &sock->write_buffer[sock->
1528                                                         write_buffer_pos],
1529                                     have);
1530   if (ret == -1)
1531     {
1532       if (errno == EINTR)
1533         goto RETRY;
1534 #if 0
1535       int en = errno;
1536       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1537                   _("Failed to send to `%s': %s\n"),
1538                   GNUNET_a2s (sock->addr,
1539                               sock->addrlen),
1540                   STRERROR (en));
1541 #endif
1542 #if DEBUG_CONNECTION
1543       GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "send");
1544 #endif
1545       transmit_error (sock);
1546       return;
1547     }
1548 #if DEBUG_CONNECTION
1549   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1550               "transmit_ready transmitted %u/%u bytes to `%s' (%p)\n",
1551               (unsigned int) ret,
1552               have, GNUNET_a2s (sock->addr, sock->addrlen), sock);
1553 #endif
1554   sock->write_buffer_pos += ret;
1555   if (sock->write_buffer_pos == sock->write_buffer_off)
1556     {
1557       /* transmitted all pending data */
1558       sock->write_buffer_pos = 0;
1559       sock->write_buffer_off = 0;
1560     }
1561   if ((sock->write_buffer_off == 0) && (NULL == sock->nth.notify_ready))
1562     return;                     /* all data sent! */
1563   /* not done writing, schedule more */
1564 SCHEDULE_WRITE:
1565 #if DEBUG_CONNECTION
1566   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1567               "Re-scheduling transmit_ready (more to do) (%p).\n", sock);
1568 #endif
1569   if (sock->write_task == GNUNET_SCHEDULER_NO_TASK)
1570     sock->write_task =
1571       GNUNET_SCHEDULER_add_write_net (tc->sched,
1572                                       GNUNET_TIME_absolute_get_remaining
1573                                       (sock->nth.transmit_timeout),
1574                                       sock->sock, &transmit_ready, sock);
1575 }
1576
1577
1578 /**
1579  * Ask the socket to call us once the specified number of bytes
1580  * are free in the transmission buffer.  May call the notify
1581  * method immediately if enough space is available.
1582  *
1583  * @param sock socket
1584  * @param size number of bytes to send
1585  * @param timeout after how long should we give up (and call
1586  *        notify with buf NULL and size 0)?
1587  * @param notify function to call
1588  * @param notify_cls closure for notify
1589  * @return non-NULL if the notify callback was queued,
1590  *         NULL if we are already going to notify someone else (busy)
1591  */
1592 struct GNUNET_CONNECTION_TransmitHandle *
1593 GNUNET_CONNECTION_notify_transmit_ready (struct GNUNET_CONNECTION_Handle
1594                                          *sock, size_t size,
1595                                          struct GNUNET_TIME_Relative timeout,
1596                                          GNUNET_CONNECTION_TransmitReadyNotify
1597                                          notify, void *notify_cls)
1598 {
1599   if (sock->nth.notify_ready != NULL)
1600     return NULL;
1601   GNUNET_assert (notify != NULL);
1602   GNUNET_assert (sock->write_buffer_size >= size);
1603   GNUNET_assert (sock->write_buffer_off <= sock->write_buffer_size);
1604   GNUNET_assert (sock->write_buffer_pos <= sock->write_buffer_size);
1605   GNUNET_assert (sock->write_buffer_pos <= sock->write_buffer_off);
1606   sock->nth.notify_ready = notify;
1607   sock->nth.notify_ready_cls = notify_cls;
1608   sock->nth.sh = sock;
1609   sock->nth.notify_size = size;
1610   sock->nth.transmit_timeout = GNUNET_TIME_relative_to_absolute (timeout);
1611   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == sock->nth.timeout_task);
1612   if ((sock->sock == NULL) &&
1613       (sock->ap_head == NULL) && (sock->dns_active == NULL))
1614     {
1615       if (sock->write_task != GNUNET_SCHEDULER_NO_TASK)
1616         GNUNET_SCHEDULER_cancel (sock->sched,
1617                                  sock->write_task);
1618       sock->write_task = GNUNET_SCHEDULER_add_now (sock->sched,
1619                                                    &connect_error, sock);
1620       return &sock->nth;
1621     }
1622   if (GNUNET_SCHEDULER_NO_TASK != sock->write_task)
1623     return &sock->nth;
1624   if (sock->sock != NULL)
1625     {
1626 #if DEBUG_CONNECTION
1627       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1628                   "Scheduling transmit_ready (%p).\n", sock);
1629 #endif
1630       sock->write_task = GNUNET_SCHEDULER_add_write_net (sock->sched,
1631                                                          GNUNET_TIME_absolute_get_remaining
1632                                                          (sock->nth.
1633                                                           transmit_timeout),
1634                                                          sock->sock,
1635                                                          &transmit_ready,
1636                                                          sock);
1637     }
1638   else
1639     {
1640 #if DEBUG_CONNECTION
1641       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1642                   "CCS-Scheduling transmit_ready, adding timeout task (%p).\n",
1643                   sock);
1644 #endif
1645       sock->ccs |= COCO_TRANSMIT_READY;
1646       sock->nth.timeout_task = GNUNET_SCHEDULER_add_delayed (sock->sched,
1647                                                              timeout,
1648                                                              &transmit_timeout,
1649                                                              sock);
1650     }
1651   return &sock->nth;
1652 }
1653
1654
1655 /**
1656  * Cancel the specified transmission-ready
1657  * notification.
1658  */
1659 void
1660 GNUNET_CONNECTION_notify_transmit_ready_cancel (struct
1661                                                 GNUNET_CONNECTION_TransmitHandle
1662                                                 *h)
1663 {
1664   GNUNET_assert (h->notify_ready != NULL);
1665   if (0 != (h->sh->ccs & COCO_TRANSMIT_READY))
1666     {
1667 #if DEBUG_CONNECTION
1668       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1669                   "notify_transmit_ready_cancel cancels timeout_task (%p)\n",
1670                   h);
1671 #endif
1672       GNUNET_SCHEDULER_cancel (h->sh->sched, h->timeout_task);
1673       h->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1674       h->sh->ccs -= COCO_TRANSMIT_READY;
1675     }
1676   else
1677     {
1678       if (h->sh->write_task != GNUNET_SCHEDULER_NO_TASK)
1679         {
1680           GNUNET_SCHEDULER_cancel (h->sh->sched, h->sh->write_task);
1681           h->sh->write_task = GNUNET_SCHEDULER_NO_TASK;
1682         }
1683     }
1684   h->notify_ready = NULL;
1685 }
1686
1687 /* end of connection.c */