12969b3ba23e9cbb9a93bf46edca14111a49a511
[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       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (ret->sock));
969       GNUNET_free (ret->addr);
970       GNUNET_free (ret->write_buffer);
971       GNUNET_free (ret);
972       return NULL;
973     }
974   connect_success_continuation (ret);
975   return ret;
976 #else
977   return NULL;
978 #endif
979 }
980
981
982 /**
983  * Create a socket handle by (asynchronously) connecting to a host.
984  * This function returns immediately, even if the connection has not
985  * yet been established.  This function only creates TCP connections.
986  *
987  * @param af_family address family to use
988  * @param serv_addr server address
989  * @param addrlen length of server address
990  * @return the socket handle
991  */
992 struct GNUNET_CONNECTION_Handle *
993 GNUNET_CONNECTION_create_from_sockaddr (int af_family,
994                                         const struct sockaddr *serv_addr,
995                                         socklen_t addrlen)
996 {
997   struct GNUNET_NETWORK_Handle *s;
998   struct GNUNET_CONNECTION_Handle *ret;
999
1000
1001   s = GNUNET_NETWORK_socket_create (af_family, SOCK_STREAM, 0);
1002   if (s == NULL)
1003     {
1004       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING |
1005                            GNUNET_ERROR_TYPE_BULK, "socket");
1006       return NULL;
1007     }
1008   if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (s, serv_addr, addrlen))
1009       && (errno != EINPROGRESS))
1010     {
1011       /* maybe refused / unsupported address, try next */
1012       GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO, "connect");
1013       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (s));
1014       return NULL;
1015     }
1016   ret = GNUNET_CONNECTION_create_from_existing (s);
1017   ret->addr = GNUNET_malloc (addrlen);
1018   memcpy (ret->addr, serv_addr, addrlen);
1019   ret->addrlen = addrlen;
1020 #if DEBUG_CONNECTION
1021   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1022               _("Trying to connect to `%s' (%p)\n"),
1023               GNUNET_a2s (serv_addr, addrlen), ret);
1024 #endif
1025   return ret;
1026 }
1027
1028
1029 /**
1030  * Check if socket is valid (no fatal errors have happened so far).
1031  * Note that a socket that is still trying to connect is considered
1032  * valid.
1033  *
1034  * @param sock socket to check
1035  * @return GNUNET_YES if valid, GNUNET_NO otherwise
1036  */
1037 int
1038 GNUNET_CONNECTION_check (struct GNUNET_CONNECTION_Handle *sock)
1039 {
1040   if ((sock->ap_head != NULL) || (sock->dns_active != NULL))
1041     return GNUNET_YES;          /* still trying to connect */
1042   return (sock->sock == NULL) ? GNUNET_NO : GNUNET_YES;
1043 }
1044
1045
1046 /**
1047  * Close the socket and free associated resources. Pending
1048  * transmissions may be completed or dropped depending on the
1049  * arguments.   If a receive call is pending and should 
1050  * NOT be completed, 'GNUNET_CONNECTION_receive_cancel'
1051  * should be called explicitly first.
1052  *
1053  * @param sock socket to destroy
1054  * @param finish_pending_write should pending writes be completed or aborted?
1055  *        (this applies to transmissions where the data has already been
1056  *        read from the application; all other transmissions should be
1057  *        aborted using 'GNUNET_CONNECTION_notify_transmit_ready_cancel').
1058  */
1059 void
1060 GNUNET_CONNECTION_destroy (struct GNUNET_CONNECTION_Handle *sock,
1061                            int finish_pending_write)
1062 {
1063   if (GNUNET_NO == finish_pending_write)
1064     {
1065       if (sock->write_task != GNUNET_SCHEDULER_NO_TASK)
1066         {
1067           GNUNET_SCHEDULER_cancel (sock->write_task);
1068           sock->write_task = GNUNET_SCHEDULER_NO_TASK;
1069           sock->write_buffer_off = 0;
1070         }
1071     }
1072   if ((sock->write_buffer_off == 0) && (sock->dns_active != NULL))
1073     {
1074       GNUNET_RESOLVER_request_cancel (sock->dns_active);
1075       sock->dns_active = NULL;
1076     }
1077
1078   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == sock->destroy_task);
1079   sock->destroy_task 
1080     = GNUNET_SCHEDULER_add_now (&destroy_continuation, sock);
1081 }
1082
1083
1084 /**
1085  * Tell the receiver callback that a timeout was reached.
1086  */
1087 static void
1088 signal_timeout (struct GNUNET_CONNECTION_Handle *sh)
1089 {
1090   GNUNET_CONNECTION_Receiver receiver;
1091
1092 #if DEBUG_CONNECTION
1093   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1094               "Network signals time out to receiver (%p)!\n", sh);
1095 #endif
1096   GNUNET_assert (NULL != (receiver = sh->receiver));
1097   sh->receiver = NULL;
1098   receiver (sh->receiver_cls, NULL, 0, NULL, 0, 0);
1099 }
1100
1101
1102 /**
1103  * Tell the receiver callback that we had an IO error.
1104  */
1105 static void
1106 signal_error (struct GNUNET_CONNECTION_Handle *sh, int errcode)
1107 {
1108   GNUNET_CONNECTION_Receiver receiver;
1109   GNUNET_assert (NULL != (receiver = sh->receiver));
1110   sh->receiver = NULL;
1111   receiver (sh->receiver_cls, NULL, 0, sh->addr, sh->addrlen, errcode);
1112 }
1113
1114
1115 /**
1116  * This function is called once we either timeout
1117  * or have data ready to read.
1118  */
1119 static void
1120 receive_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1121 {
1122   struct GNUNET_CONNECTION_Handle *sh = cls;
1123   struct GNUNET_TIME_Absolute now;
1124   char buffer[sh->max];
1125   ssize_t ret;
1126   GNUNET_CONNECTION_Receiver receiver;
1127
1128   sh->read_task = GNUNET_SCHEDULER_NO_TASK;
1129   if ( (GNUNET_YES == sh->ignore_shutdown) &&
1130        (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))) 
1131     {
1132       /* ignore shutdown request, go again immediately */
1133 #if DEBUG_CONNECTION
1134       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1135                   "Ignoring shutdown signal per configuration\n");
1136 #endif
1137       sh->read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_absolute_get_remaining
1138                                                      (sh->receive_timeout),
1139                                                      sh->sock,
1140                                                      &receive_ready, sh);
1141       return;
1142     }
1143   now = GNUNET_TIME_absolute_get ();
1144   if ((now.abs_value > sh->receive_timeout.abs_value) ||
1145       (0 != (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT)) ||
1146       (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)))
1147     {
1148 #if DEBUG_CONNECTION
1149       if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1150         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1151                     "Receive from `%s' encounters error: time out by %llums... (%p)\n",
1152                     GNUNET_a2s (sh->addr, sh->addrlen),
1153                     GNUNET_TIME_absolute_get_duration (sh->receive_timeout).
1154                     rel_value, sh);
1155 #endif
1156       signal_timeout (sh);
1157       return;
1158     }
1159   if (sh->sock == NULL)
1160     {
1161       /* connect failed for good */
1162 #if DEBUG_CONNECTION
1163       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1164                   "Receive encounters error, socket closed... (%p)\n", sh);
1165 #endif
1166       signal_error (sh, ECONNREFUSED);
1167       return;
1168     }
1169   GNUNET_assert (GNUNET_NETWORK_fdset_isset (tc->read_ready, sh->sock));
1170 RETRY:
1171   ret = GNUNET_NETWORK_socket_recv (sh->sock, buffer, sh->max);
1172   if (ret == -1)
1173     {
1174       if (errno == EINTR)
1175         goto RETRY;
1176 #if DEBUG_CONNECTION
1177       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1178                   "Error receiving: %s\n", STRERROR (errno));
1179 #endif
1180       signal_error (sh, errno);
1181       return;
1182     }
1183 #if DEBUG_CONNECTION
1184   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1185               "receive_ready read %u/%u bytes from `%s' (%p)!\n",
1186               (unsigned int) ret,
1187               sh->max, GNUNET_a2s (sh->addr, sh->addrlen), sh);
1188 #endif
1189   GNUNET_assert (NULL != (receiver = sh->receiver));
1190   sh->receiver = NULL;
1191   receiver (sh->receiver_cls, buffer, ret, sh->addr, sh->addrlen, 0);
1192 }
1193
1194
1195 /**
1196  * This function is called after establishing a connection either has
1197  * succeeded or timed out.  Note that it is possible that the attempt
1198  * timed out and that we're immediately retrying.  If we are retrying,
1199  * we need to wait again (or timeout); if we succeeded, we need to
1200  * wait for data (or timeout).
1201  *
1202  * @param cls our connection handle
1203  * @param tc task context describing why we are here
1204  */
1205 static void
1206 receive_again (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1207 {
1208   struct GNUNET_CONNECTION_Handle *sh = cls;
1209   struct GNUNET_TIME_Absolute now;
1210
1211   sh->read_task = GNUNET_SCHEDULER_NO_TASK;
1212   if (sh->sock == NULL)
1213     {
1214       /* not connected and no longer trying */
1215 #if DEBUG_CONNECTION
1216       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1217                   "Receive encounters error, socket closed (%p)...\n", sh);
1218 #endif
1219       signal_error (sh, ECONNREFUSED);
1220       return;
1221     }
1222   now = GNUNET_TIME_absolute_get ();
1223   if ((now.abs_value > sh->receive_timeout.abs_value) ||
1224       (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)))
1225     {
1226 #if DEBUG_CONNECTION
1227       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1228                   "Receive encounters error: time out (%p)...\n", sh);
1229 #endif
1230       signal_timeout (sh);
1231       return;
1232     }
1233   GNUNET_assert (sh->sock != NULL);
1234   /* connect succeeded, wait for data! */
1235   sh->read_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_absolute_get_remaining
1236                                                  (sh->receive_timeout),
1237                                                  sh->sock,
1238                                                  &receive_ready, sh);
1239 }
1240
1241
1242 /**
1243  * Receive data from the given socket.  Note that this function will
1244  * call "receiver" asynchronously using the scheduler.  It will
1245  * "immediately" return.  Note that there MUST only be one active
1246  * receive call per socket at any given point in time (so do not
1247  * call receive again until the receiver callback has been invoked).
1248  *
1249  * @param sock socket handle
1250  * @param max maximum number of bytes to read
1251  * @param timeout maximum amount of time to wait (use -1 for "forever")
1252  * @param receiver function to call with received data
1253  * @param receiver_cls closure for receiver
1254  */
1255 void
1256 GNUNET_CONNECTION_receive (struct GNUNET_CONNECTION_Handle *sock,
1257                            size_t max,
1258                            struct GNUNET_TIME_Relative timeout,
1259                            GNUNET_CONNECTION_Receiver receiver,
1260                            void *receiver_cls)
1261 {
1262   struct GNUNET_SCHEDULER_TaskContext tc;
1263
1264   GNUNET_assert ((sock->read_task == GNUNET_SCHEDULER_NO_TASK) &&
1265                  (0 == (sock->ccs & COCO_RECEIVE_AGAIN)) &&
1266                  (sock->receiver == NULL));
1267   sock->receiver = receiver;
1268   sock->receiver_cls = receiver_cls;
1269   sock->receive_timeout = GNUNET_TIME_relative_to_absolute (timeout);
1270   sock->max = max;
1271   if (sock->sock != NULL)
1272     {
1273       memset (&tc, 0, sizeof (tc));
1274       tc.reason = GNUNET_SCHEDULER_REASON_PREREQ_DONE;
1275       receive_again (sock, &tc);
1276       return;
1277     }
1278   if ((sock->dns_active == NULL) && (sock->ap_head == NULL))
1279     {
1280       receiver (receiver_cls, NULL, 0, NULL, 0, ETIMEDOUT);
1281       return;
1282     }
1283   sock->ccs += COCO_RECEIVE_AGAIN;
1284 }
1285
1286
1287 /**
1288  * Configure this connection to ignore shutdown signals.
1289  *
1290  * @param sock socket handle
1291  * @param do_ignore GNUNET_YES to ignore, GNUNET_NO to restore default
1292  */
1293 void
1294 GNUNET_CONNECTION_ignore_shutdown (struct GNUNET_CONNECTION_Handle *sock,
1295                                    int do_ignore)
1296 {
1297   sock->ignore_shutdown = do_ignore;
1298 }
1299
1300
1301 /**
1302  * Cancel receive job on the given socket.  Note that the
1303  * receiver callback must not have been called yet in order
1304  * for the cancellation to be valid.
1305  *
1306  * @param sock socket handle
1307  * @return closure of the original receiver callback closure
1308  */
1309 void *
1310 GNUNET_CONNECTION_receive_cancel (struct GNUNET_CONNECTION_Handle *sock)
1311 {
1312   if (sock->read_task != GNUNET_SCHEDULER_NO_TASK)
1313     {
1314       GNUNET_assert (sock == GNUNET_SCHEDULER_cancel (sock->read_task));
1315       sock->read_task = GNUNET_SCHEDULER_NO_TASK;
1316     }
1317   else
1318     {
1319       GNUNET_assert (0 != (sock->ccs & COCO_RECEIVE_AGAIN));
1320       sock->ccs -= COCO_RECEIVE_AGAIN;
1321     }
1322   sock->receiver = NULL;
1323   return sock->receiver_cls;
1324 }
1325
1326
1327 /**
1328  * Try to call the transmit notify method (check if we do
1329  * have enough space available first)!
1330  *
1331  * @param sock socket for which we should do this processing
1332  * @return GNUNET_YES if we were able to call notify
1333  */
1334 static int
1335 process_notify (struct GNUNET_CONNECTION_Handle *sock)
1336 {
1337   size_t used;
1338   size_t avail;
1339   size_t size;
1340   GNUNET_CONNECTION_TransmitReadyNotify notify;
1341
1342   GNUNET_assert (sock->write_task == GNUNET_SCHEDULER_NO_TASK);
1343   if (NULL == (notify = sock->nth.notify_ready))
1344     return GNUNET_NO;
1345   used = sock->write_buffer_off - sock->write_buffer_pos;
1346   avail = sock->write_buffer_size - used;
1347   size = sock->nth.notify_size;
1348   if (size > avail)
1349     return GNUNET_NO;
1350   sock->nth.notify_ready = NULL;
1351   if (sock->write_buffer_size - sock->write_buffer_off < size)
1352     {
1353       /* need to compact */
1354       memmove (sock->write_buffer,
1355                &sock->write_buffer[sock->write_buffer_pos], used);
1356       sock->write_buffer_off -= sock->write_buffer_pos;
1357       sock->write_buffer_pos = 0;
1358     }
1359   avail = sock->write_buffer_size - sock->write_buffer_off;
1360   GNUNET_assert (avail >= size);
1361   size = notify (sock->nth.notify_ready_cls,
1362                  avail,
1363                  &sock->write_buffer[sock->write_buffer_off]);
1364   GNUNET_assert (size <= avail);
1365   sock->write_buffer_off += size;
1366   return GNUNET_YES;
1367 }
1368
1369
1370 /**
1371  * Task invoked by the scheduler when a call to transmit
1372  * is timing out (we never got enough buffer space to call
1373  * the callback function before the specified timeout
1374  * expired).
1375  *
1376  * This task notifies the client about the timeout.
1377  */
1378 static void
1379 transmit_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1380 {
1381   struct GNUNET_CONNECTION_Handle *sock = cls;
1382   GNUNET_CONNECTION_TransmitReadyNotify notify;
1383
1384 #if DEBUG_CONNECTION
1385   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1386               "transmit_timeout running (%p)\n", sock);
1387 #endif
1388   sock->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK;
1389 #if DEBUG_CONNECTION
1390   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1391               "Transmit to `%s:%u/%s' fails, time out reached (%p).\n",
1392               sock->hostname,
1393               sock->port, GNUNET_a2s (sock->addr, sock->addrlen), sock);
1394 #endif
1395   GNUNET_assert (0 != (sock->ccs & COCO_TRANSMIT_READY));
1396   sock->ccs -= COCO_TRANSMIT_READY;     /* remove request */
1397   notify = sock->nth.notify_ready;
1398   sock->nth.notify_ready = NULL;
1399   notify (sock->nth.notify_ready_cls, 0, NULL);
1400 }
1401
1402
1403 /**
1404  * Task invoked by the scheduler when we failed to connect
1405  * at the time of being asked to transmit.
1406  *
1407  * This task notifies the client about the error.
1408  */
1409 static void
1410 connect_error (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1411 {
1412   struct GNUNET_CONNECTION_Handle *sock = cls;
1413   GNUNET_CONNECTION_TransmitReadyNotify notify;
1414
1415 #if DEBUG_CONNECTION
1416   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1417               "Transmission request of size %u fails, connection failed (%p).\n",
1418               sock->nth.notify_size, sock);
1419 #endif
1420   sock->write_task = GNUNET_SCHEDULER_NO_TASK;
1421   notify = sock->nth.notify_ready;
1422   sock->nth.notify_ready = NULL;
1423   notify (sock->nth.notify_ready_cls, 0, NULL);
1424 }
1425
1426
1427 static void
1428 transmit_error (struct GNUNET_CONNECTION_Handle *sock)
1429 {
1430   GNUNET_CONNECTION_TransmitReadyNotify notify;
1431
1432   if (NULL != sock->sock)
1433     {
1434       GNUNET_NETWORK_socket_shutdown (sock->sock, SHUT_RDWR);
1435       GNUNET_break (GNUNET_OK ==
1436                     GNUNET_NETWORK_socket_close (sock->sock));
1437       sock->sock = NULL;
1438     }
1439   if (sock->read_task != GNUNET_SCHEDULER_NO_TASK)
1440     {
1441       GNUNET_SCHEDULER_cancel (sock->read_task);
1442       sock->read_task = GNUNET_SCHEDULER_NO_TASK;
1443       signal_timeout (sock);
1444       return;
1445     }
1446   if (sock->nth.notify_ready == NULL)
1447     return;                     /* nobody to tell about it */
1448   notify = sock->nth.notify_ready;
1449   sock->nth.notify_ready = NULL;
1450   notify (sock->nth.notify_ready_cls, 0, NULL);
1451 }
1452
1453
1454 /**
1455  * See if we are now connected.  If not, wait longer for
1456  * connect to succeed.  If connected, we should be able
1457  * to write now as well, unless we timed out.
1458  *
1459  * @param cls our connection handle
1460  * @param tc task context describing why we are here
1461  */
1462 static void
1463 transmit_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1464 {
1465   struct GNUNET_CONNECTION_Handle *sock = cls;
1466   GNUNET_CONNECTION_TransmitReadyNotify notify;
1467   ssize_t ret;
1468   size_t have;
1469
1470 #if DEBUG_CONNECTION
1471   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1472               "transmit_ready running (%p).\n", sock);
1473 #endif
1474   GNUNET_assert (sock->write_task != GNUNET_SCHEDULER_NO_TASK);
1475   sock->write_task = GNUNET_SCHEDULER_NO_TASK;
1476   GNUNET_assert (sock->nth.timeout_task == GNUNET_SCHEDULER_NO_TASK);
1477   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) 
1478     {
1479       if (sock->ignore_shutdown == GNUNET_YES)
1480         goto SCHEDULE_WRITE;    /* ignore shutdown, go again immediately */
1481 #if DEBUG_CONNECTION
1482       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1483                   "Transmit to `%s' fails, shutdown happened (%p).\n",
1484                   GNUNET_a2s (sock->addr, sock->addrlen), sock);
1485 #endif
1486       notify = sock->nth.notify_ready;
1487       sock->nth.notify_ready = NULL;
1488       notify (sock->nth.notify_ready_cls, 0, NULL);
1489       return;
1490     }
1491   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT))
1492     {
1493 #if DEBUG_CONNECTION
1494       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1495                   "Transmit to `%s' fails, time out reached (%p).\n",
1496                   GNUNET_a2s (sock->addr, sock->addrlen), sock);
1497 #endif
1498       notify = sock->nth.notify_ready;
1499       sock->nth.notify_ready = NULL;
1500       notify (sock->nth.notify_ready_cls, 0, NULL);
1501       return;
1502     }
1503   GNUNET_assert (NULL != sock->sock);
1504   if (tc->write_ready == NULL)
1505     {
1506       /* special circumstances (in particular,
1507          PREREQ_DONE after connect): not yet ready to write,
1508          but no "fatal" error either.  Hence retry.  */
1509       goto SCHEDULE_WRITE;
1510     }
1511   if (!GNUNET_NETWORK_fdset_isset (tc->write_ready, sock->sock))
1512     {
1513 #if DEBUG_CONNECTION
1514       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1515                   _
1516                   ("Could not satisfy pending transmission request, socket closed or connect failed (%p).\n"),
1517                   sock);
1518 #endif
1519       transmit_error (sock);
1520       return;                   /* connect failed for good, we're finished */
1521     }
1522   GNUNET_assert (sock->write_buffer_off >= sock->write_buffer_pos);
1523   if ( (sock->nth.notify_ready != NULL) &&
1524        (sock->write_buffer_size < sock->nth.notify_size) )
1525     {
1526       sock->write_buffer = GNUNET_realloc(sock->write_buffer, 
1527                                           sock->nth.notify_size);
1528       sock->write_buffer_size = sock->nth.notify_size;
1529     }    
1530   process_notify (sock);
1531   have = sock->write_buffer_off - sock->write_buffer_pos;
1532   if (have == 0)
1533     {
1534       /* no data ready for writing, terminate write loop */
1535       return;
1536     }
1537   GNUNET_assert (have <= sock->write_buffer_size);
1538   GNUNET_assert (have + sock->write_buffer_pos <= sock->write_buffer_size);
1539   GNUNET_assert (sock->write_buffer_pos <= sock->write_buffer_size);
1540 RETRY:
1541   ret = GNUNET_NETWORK_socket_send (sock->sock,
1542                                     &sock->write_buffer[sock->
1543                                                         write_buffer_pos],
1544                                     have);
1545   if (ret == -1)
1546     {
1547       if (errno == EINTR)
1548         goto RETRY;
1549 #if 0
1550       int en = errno;
1551       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1552                   _("Failed to send to `%s': %s\n"),
1553                   GNUNET_a2s (sock->addr,
1554                               sock->addrlen),
1555                   STRERROR (en));
1556 #endif
1557 #if DEBUG_CONNECTION
1558       GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "send");
1559 #endif
1560       transmit_error (sock);
1561       return;
1562     }
1563 #if DEBUG_CONNECTION
1564   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1565               "transmit_ready transmitted %u/%u bytes to `%s' (%p)\n",
1566               (unsigned int) ret,
1567               have, GNUNET_a2s (sock->addr, sock->addrlen), sock);
1568 #endif
1569   sock->write_buffer_pos += ret;
1570   if (sock->write_buffer_pos == sock->write_buffer_off)
1571     {
1572       /* transmitted all pending data */
1573       sock->write_buffer_pos = 0;
1574       sock->write_buffer_off = 0;
1575     }
1576   if ((sock->write_buffer_off == 0) && (NULL == sock->nth.notify_ready))
1577     return;                     /* all data sent! */
1578   /* not done writing, schedule more */
1579 SCHEDULE_WRITE:
1580 #if DEBUG_CONNECTION
1581   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1582               "Re-scheduling transmit_ready (more to do) (%p).\n", sock);
1583 #endif
1584   if (sock->write_task == GNUNET_SCHEDULER_NO_TASK)
1585     sock->write_task =
1586       GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_absolute_get_remaining
1587                                       (sock->nth.transmit_timeout),
1588                                       sock->sock, &transmit_ready, sock);
1589 }
1590
1591
1592 /**
1593  * Ask the socket to call us once the specified number of bytes
1594  * are free in the transmission buffer.  May call the notify
1595  * method immediately if enough space is available.
1596  *
1597  * @param sock socket
1598  * @param size number of bytes to send
1599  * @param timeout after how long should we give up (and call
1600  *        notify with buf NULL and size 0)?
1601  * @param notify function to call
1602  * @param notify_cls closure for notify
1603  * @return non-NULL if the notify callback was queued,
1604  *         NULL if we are already going to notify someone else (busy)
1605  */
1606 struct GNUNET_CONNECTION_TransmitHandle *
1607 GNUNET_CONNECTION_notify_transmit_ready (struct GNUNET_CONNECTION_Handle
1608                                          *sock, size_t size,
1609                                          struct GNUNET_TIME_Relative timeout,
1610                                          GNUNET_CONNECTION_TransmitReadyNotify
1611                                          notify, void *notify_cls)
1612 {
1613   if (sock->nth.notify_ready != NULL)
1614     return NULL;
1615   GNUNET_assert (notify != NULL);
1616   GNUNET_assert (size < GNUNET_SERVER_MAX_MESSAGE_SIZE);
1617   GNUNET_assert (sock->write_buffer_off <= sock->write_buffer_size);
1618   GNUNET_assert (sock->write_buffer_pos <= sock->write_buffer_size);
1619   GNUNET_assert (sock->write_buffer_pos <= sock->write_buffer_off);
1620   sock->nth.notify_ready = notify;
1621   sock->nth.notify_ready_cls = notify_cls;
1622   sock->nth.sh = sock;
1623   sock->nth.notify_size = size;
1624   sock->nth.transmit_timeout = GNUNET_TIME_relative_to_absolute (timeout);
1625   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == sock->nth.timeout_task);
1626   if ((sock->sock == NULL) &&
1627       (sock->ap_head == NULL) && (sock->dns_active == NULL))
1628     {
1629       if (sock->write_task != GNUNET_SCHEDULER_NO_TASK)
1630         GNUNET_SCHEDULER_cancel (sock->write_task);
1631       sock->write_task = GNUNET_SCHEDULER_add_now (&connect_error, sock);
1632       return &sock->nth;
1633     }
1634   if (GNUNET_SCHEDULER_NO_TASK != sock->write_task)
1635     return &sock->nth;
1636   if (sock->sock != NULL)
1637     {
1638 #if DEBUG_CONNECTION
1639       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1640                   "Scheduling transmit_ready (%p).\n", sock);
1641 #endif
1642       sock->write_task = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_absolute_get_remaining
1643                                                          (sock->nth.
1644                                                           transmit_timeout),
1645                                                          sock->sock,
1646                                                          &transmit_ready,
1647                                                          sock);
1648     }
1649   else
1650     {
1651 #if DEBUG_CONNECTION
1652       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1653                   "CCS-Scheduling transmit_ready, adding timeout task (%p).\n",
1654                   sock);
1655 #endif
1656       sock->ccs |= COCO_TRANSMIT_READY;
1657       sock->nth.timeout_task = GNUNET_SCHEDULER_add_delayed (timeout,
1658                                                              &transmit_timeout,
1659                                                              sock);
1660     }
1661   return &sock->nth;
1662 }
1663
1664
1665 /**
1666  * Cancel the specified transmission-ready
1667  * notification.
1668  */
1669 void
1670 GNUNET_CONNECTION_notify_transmit_ready_cancel (struct
1671                                                 GNUNET_CONNECTION_TransmitHandle
1672                                                 *h)
1673 {
1674   GNUNET_assert (h->notify_ready != NULL);
1675   if (0 != (h->sh->ccs & COCO_TRANSMIT_READY))
1676     {
1677 #if DEBUG_CONNECTION
1678       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1679                   "notify_transmit_ready_cancel cancels timeout_task (%p)\n",
1680                   h);
1681 #endif
1682       GNUNET_SCHEDULER_cancel (h->timeout_task);
1683       h->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1684       h->sh->ccs -= COCO_TRANSMIT_READY;
1685     }
1686   else
1687     {
1688       if (h->sh->write_task != GNUNET_SCHEDULER_NO_TASK)
1689         {
1690           GNUNET_SCHEDULER_cancel (h->sh->write_task);
1691           h->sh->write_task = GNUNET_SCHEDULER_NO_TASK;
1692         }
1693     }
1694   h->notify_ready = NULL;
1695 }
1696
1697 /* end of connection.c */