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