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