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