bad commit fix
[oweals/gnunet.git] / src / util / client.c
1 /*
2      This file is part of GNUnet.
3      (C) 2001, 2002, 2006, 2008, 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/client.c
23  * @brief code for access to services
24  * @author Christian Grothoff
25  *
26  * Generic TCP code for reliable, record-oriented TCP
27  * connections between clients and service providers.
28  */
29
30 #include "platform.h"
31 #include "gnunet_common.h"
32 #include "gnunet_client_lib.h"
33 #include "gnunet_protocols.h"
34 #include "gnunet_server_lib.h"
35 #include "gnunet_scheduler_lib.h"
36
37 #define DEBUG_CLIENT GNUNET_NO
38
39 /**
40  * How often do we re-try tranmsitting requests before giving up?
41  * Note that if we succeeded transmitting a request but failed to read
42  * a response, we do NOT re-try.
43  */
44 #define MAX_ATTEMPTS 50
45
46
47 /**
48  * Handle for a transmission request.
49  */
50 struct GNUNET_CLIENT_TransmitHandle
51 {
52   /**
53    * Connection state.
54    */
55   struct GNUNET_CLIENT_Connection *sock;
56
57   /**
58    * Function to call to get the data for transmission.
59    */
60   GNUNET_CONNECTION_TransmitReadyNotify notify;
61
62   /**
63    * Closure for notify.
64    */
65   void *notify_cls;
66
67   /**
68    * Handle to the transmission with the underlying
69    * connection.
70    */
71   struct GNUNET_CONNECTION_TransmitHandle *th;
72
73   /**
74    * If we are re-trying and are delaying to do so,
75    * handle to the scheduled task managing the delay.
76    */
77   GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
78
79   /**
80    * Timeout for the operation overall.
81    */
82   struct GNUNET_TIME_Absolute timeout;
83
84   /**
85    * Number of bytes requested.
86    */
87   size_t size;
88
89   /**
90    * Are we allowed to re-try to connect without telling
91    * the user (of this API) about the connection troubles?
92    */
93   int auto_retry;
94
95   /**
96    * Number of attempts left for transmitting the request.  We may
97    * fail the first time (say because the service is not yet up), in
98    * which case (if auto_retry is set) we wait a bit and re-try
99    * (timeout permitting).
100    */
101   unsigned int attempts_left;
102
103 };
104
105
106 /**
107  * Context for processing 
108  * "GNUNET_CLIENT_transmit_and_get_response" requests.
109  */
110 struct TransmitGetResponseContext
111 {
112   /**
113    * Client handle.
114    */
115   struct GNUNET_CLIENT_Connection *sock;
116
117   /**
118    * Message to transmit; do not free, allocated
119    * right after this struct.
120    */
121   const struct GNUNET_MessageHeader *hdr;
122
123   /**
124    * Timeout to use.
125    */
126   struct GNUNET_TIME_Absolute timeout;
127
128   /**
129    * Function to call when done.
130    */
131   GNUNET_CLIENT_MessageHandler rn;
132
133   /**
134    * Closure for "rn".
135    */
136   void *rn_cls;
137 };
138
139 /**
140  * Struct to refer to a GNUnet TCP connection.
141  * This is more than just a socket because if the server
142  * drops the connection, the client automatically tries
143  * to reconnect (and for that needs connection information).
144  */
145 struct GNUNET_CLIENT_Connection
146 {
147
148   /**
149    * the socket handle, NULL if not live
150    */
151   struct GNUNET_CONNECTION_Handle *sock;
152
153   /**
154    * Our scheduler.
155    */
156   struct GNUNET_SCHEDULER_Handle *sched;
157
158   /**
159    * Our configuration.
160    * FIXME: why do we DUP the configuration? Avoid this!
161    */
162   struct GNUNET_CONFIGURATION_Handle *cfg;
163
164   /**
165    * Name of the service we interact with.
166    */
167   char *service_name;
168
169   /**
170    * Context of a transmit_and_get_response operation, NULL
171    * if no such operation is pending.
172    */
173   struct TransmitGetResponseContext *tag;
174
175   /**
176    * Handler for current receiver task.
177    */
178   GNUNET_CLIENT_MessageHandler receiver_handler;
179
180   /**
181    * Closure for receiver_handler.
182    */
183   void *receiver_handler_cls;
184
185   /**
186    * Handle for a pending transmission request, NULL if there is
187    * none pending.
188    */
189   struct GNUNET_CLIENT_TransmitHandle *th;
190
191   /**
192    * Handler for service test completion (NULL unless in service_test)
193    */
194   GNUNET_SCHEDULER_Task test_cb;
195
196   /**
197    * Deadline for calling 'test_cb'.
198    */
199   struct GNUNET_TIME_Absolute test_deadline;
200
201   /**
202    * If we are re-trying and are delaying to do so,
203    * handle to the scheduled task managing the delay.
204    */
205   GNUNET_SCHEDULER_TaskIdentifier receive_task;
206
207   /**
208    * Closure for test_cb (NULL unless in service_test)
209    */
210   void *test_cb_cls;
211
212   /**
213    * Buffer for received message.
214    */
215   char *received_buf;
216
217   /**
218    * Timeout for receiving a response (absolute time).
219    */
220   struct GNUNET_TIME_Absolute receive_timeout;
221
222   /**
223    * Current value for our incremental back-off (for
224    * connect re-tries).
225    */
226   struct GNUNET_TIME_Relative back_off;
227
228   /**
229    * Number of bytes in received_buf that are valid.
230    */
231   size_t received_pos;
232
233   /**
234    * Size of received_buf.
235    */
236   unsigned int received_size;
237
238   /**
239    * Do we have a complete response in received_buf?
240    */
241   int msg_complete;
242
243   /**
244    * Are we currently busy doing receive-processing?
245    * GNUNET_YES if so, GNUNET_NO if not.
246    */
247   int in_receive;
248
249   /**
250    * Are we ignoring shutdown signals?
251    */
252   int ignore_shutdown;
253   
254   /**
255    * How often have we tried to connect?
256    */
257   unsigned int attempts;
258
259 };
260
261
262 /**
263  * Try to connect to the service.
264  *
265  * @param sched scheduler to use
266  * @param service_name name of service to connect to
267  * @param cfg configuration to use
268  * @param attempt counter used to alternate between IP and UNIX domain sockets
269  * @return NULL on error
270  */
271 static struct GNUNET_CONNECTION_Handle *
272 do_connect (struct GNUNET_SCHEDULER_Handle *sched,
273             const char *service_name,
274             const struct GNUNET_CONFIGURATION_Handle *cfg,
275             unsigned int attempt)
276 {
277   struct GNUNET_CONNECTION_Handle *sock;
278   char *hostname;
279   char *unixpath;
280   unsigned long long port;
281
282 #if AF_UNIX
283   if (0 == attempt % 2)
284     {
285       /* on even rounds, try UNIX */
286       if (GNUNET_OK ==
287           GNUNET_CONFIGURATION_get_value_string (cfg,
288                                                  service_name,
289                                                  "UNIXPATH", &unixpath))
290         {
291           sock = GNUNET_CONNECTION_create_from_connect_to_unixpath (sched,
292                                                                     cfg,
293                                                                     unixpath);
294           GNUNET_free (unixpath);
295           if (sock != NULL)
296             return sock;
297         }
298     }
299 #endif
300
301   if ((GNUNET_OK !=
302        GNUNET_CONFIGURATION_get_value_number (cfg,
303                                               service_name,
304                                               "PORT",
305                                               &port)) ||
306       (port > 65535) ||
307       (GNUNET_OK !=
308        GNUNET_CONFIGURATION_get_value_string (cfg,
309                                               service_name,
310                                               "HOSTNAME", &hostname)))
311     {
312       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
313                   _
314                   ("Could not determine valid hostname and port for service `%s' from configuration.\n"),
315                   service_name);
316       return NULL;
317     }
318   if (0 == strlen (hostname))
319     {
320       GNUNET_free (hostname);
321       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
322                   _("Need a non-empty hostname for service `%s'.\n"),
323                   service_name);
324       return NULL;
325     }
326   sock = GNUNET_CONNECTION_create_from_connect (sched,
327                                                 cfg,
328                                                 hostname,
329                                                 port);
330   GNUNET_free (hostname);
331   return sock;
332 }
333
334
335 /**
336  * Get a connection with a service.
337  *
338  * @param sched scheduler to use
339  * @param service_name name of the service
340  * @param cfg configuration to use
341  * @return NULL on error (service unknown to configuration)
342  */
343 struct GNUNET_CLIENT_Connection *
344 GNUNET_CLIENT_connect (struct GNUNET_SCHEDULER_Handle *sched,
345                        const char *service_name,
346                        const struct GNUNET_CONFIGURATION_Handle *cfg)
347 {
348   struct GNUNET_CLIENT_Connection *ret;
349   struct GNUNET_CONNECTION_Handle *sock;
350
351   sock = do_connect (sched, 
352                      service_name, 
353                      cfg, 0);
354   if (sock == NULL)
355     return NULL;
356   ret = GNUNET_malloc (sizeof (struct GNUNET_CLIENT_Connection));
357   ret->attempts = 1;
358   ret->sock = sock;
359   ret->sched = sched;
360   ret->service_name = GNUNET_strdup (service_name);
361   ret->cfg = GNUNET_CONFIGURATION_dup (cfg);
362   ret->back_off = GNUNET_TIME_UNIT_MILLISECONDS;
363   return ret;
364 }
365
366
367 /**
368  * Configure this connection to ignore shutdown signals.
369  *
370  * @param h client handle
371  * @param do_ignore GNUNET_YES to ignore, GNUNET_NO to restore default
372  */
373 void
374 GNUNET_CLIENT_ignore_shutdown (struct GNUNET_CLIENT_Connection *h,
375                                int do_ignore)
376 {
377   h->ignore_shutdown = do_ignore;
378   if (h->sock != NULL)
379     GNUNET_CONNECTION_ignore_shutdown (h->sock,
380                                        do_ignore);
381 }
382
383
384 /**
385  * Destroy connection with the service.  This will automatically
386  * cancel any pending "receive" request (however, the handler will
387  * *NOT* be called, not even with a NULL message).  Any pending
388  * transmission request will also be cancelled UNLESS the callback for
389  * the transmission request has already been called, in which case the
390  * transmission 'finish_pending_write' argument determines whether or
391  * not the write is guaranteed to complete before the socket is fully
392  * destroyed (unless, of course, there is an error with the server in
393  * which case the message may still be lost).
394  *
395  * @param finish_pending_write should a transmission already passed to the
396  *          handle be completed?
397  * @param sock handle to the service connection
398  */
399 void
400 GNUNET_CLIENT_disconnect (struct GNUNET_CLIENT_Connection *sock,
401                           int finish_pending_write)
402 {
403   GNUNET_assert (sock->sock != NULL);
404   if (sock->in_receive == GNUNET_YES)
405     {
406       GNUNET_CONNECTION_receive_cancel (sock->sock);
407       sock->in_receive = GNUNET_NO;
408     }
409   GNUNET_CONNECTION_destroy (sock->sock, finish_pending_write);
410   sock->sock = NULL;
411   if (sock->tag != NULL)
412     {
413       GNUNET_free (sock->tag);
414       sock->tag = NULL;
415     }
416   sock->receiver_handler = NULL;
417   if (sock->th != NULL)
418     GNUNET_CLIENT_notify_transmit_ready_cancel (sock->th);
419   if (sock->receive_task != GNUNET_SCHEDULER_NO_TASK)
420     {
421       GNUNET_SCHEDULER_cancel (sock->sched, sock->receive_task);
422       sock->receive_task = GNUNET_SCHEDULER_NO_TASK;
423     }
424   GNUNET_array_grow (sock->received_buf, sock->received_size, 0);
425   GNUNET_free (sock->service_name);
426   GNUNET_CONFIGURATION_destroy (sock->cfg);
427   GNUNET_free (sock);
428 }
429
430
431 /**
432  * Check if message is complete
433  */
434 static void
435 check_complete (struct GNUNET_CLIENT_Connection *conn)
436 {
437   if ((conn->received_pos >= sizeof (struct GNUNET_MessageHeader)) &&
438       (conn->received_pos >=
439        ntohs (((const struct GNUNET_MessageHeader *) conn->received_buf)->
440               size)))
441     conn->msg_complete = GNUNET_YES;
442 }
443
444
445 /**
446  * Callback function for data received from the network.  Note that
447  * both "available" and "errCode" would be 0 if the read simply timed out.
448  *
449  * @param cls closure
450  * @param buf pointer to received data
451  * @param available number of bytes availabe in "buf",
452  *        possibly 0 (on errors)
453  * @param addr address of the sender
454  * @param addrlen size of addr
455  * @param errCode value of errno (on errors receiving)
456  */
457 static void
458 receive_helper (void *cls,
459                 const void *buf,
460                 size_t available,
461                 const struct sockaddr *addr, socklen_t addrlen, int errCode)
462 {
463   struct GNUNET_CLIENT_Connection *conn = cls;
464   struct GNUNET_TIME_Relative remaining;
465   GNUNET_CLIENT_MessageHandler receive_handler;
466   void *receive_handler_cls;
467
468   GNUNET_assert (conn->msg_complete == GNUNET_NO);
469   conn->in_receive = GNUNET_NO;
470   if ((available == 0) || (conn->sock == NULL) || (errCode != 0))
471     {
472       /* signal timeout! */
473       if (NULL != (receive_handler = conn->receiver_handler))
474         {
475           receive_handler_cls = conn->receiver_handler_cls;
476           conn->receiver_handler = NULL;
477           receive_handler (receive_handler_cls, NULL);
478         }
479       return;
480     }
481
482   /* FIXME: optimize for common fast case where buf contains the
483      entire message and we need no copying... */
484
485
486   /* slow path: append to array */
487   if (conn->received_size < conn->received_pos + available)
488     GNUNET_array_grow (conn->received_buf,
489                        conn->received_size, conn->received_pos + available);
490   memcpy (&conn->received_buf[conn->received_pos], buf, available);
491   conn->received_pos += available;
492   check_complete (conn);
493   /* check for timeout */
494   remaining = GNUNET_TIME_absolute_get_remaining (conn->receive_timeout);
495   if (remaining.value == 0)
496     {
497       /* signal timeout! */
498       conn->receiver_handler (conn->receiver_handler_cls, NULL);
499       return;
500     }
501   /* back to receive -- either for more data or to call callback! */
502   GNUNET_CLIENT_receive (conn,
503                          conn->receiver_handler,
504                          conn->receiver_handler_cls, remaining);
505 }
506
507
508 /**
509  * Continuation to call the receive callback.
510  *
511  * @param cls  our handle to the client connection
512  * @param tc scheduler context
513  */
514 static void
515 receive_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
516 {
517   struct GNUNET_CLIENT_Connection *sock = cls;
518   GNUNET_CLIENT_MessageHandler handler = sock->receiver_handler;
519   const struct GNUNET_MessageHeader *cmsg =
520     (const struct GNUNET_MessageHeader *) sock->received_buf;
521   void *handler_cls = sock->receiver_handler_cls;
522   uint16_t msize = ntohs (cmsg->size);
523   char mbuf[msize];
524   struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) mbuf;
525
526 #if DEBUG_CLIENT
527   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
528               "Received message of size %u\n",
529               msize);
530 #endif
531   sock->receive_task = GNUNET_SCHEDULER_NO_TASK;
532   GNUNET_assert (GNUNET_YES == sock->msg_complete);
533   GNUNET_assert (sock->received_pos >= msize);
534   memcpy (msg, cmsg, msize);
535   memmove (sock->received_buf,
536            &sock->received_buf[msize], sock->received_pos - msize);
537   sock->received_pos -= msize;
538   sock->msg_complete = GNUNET_NO;
539   sock->receiver_handler = NULL;
540   check_complete (sock);
541   if (handler != NULL)
542     handler (handler_cls, msg);
543 }
544
545
546 /**
547  * Read from the service.
548  *
549  * @param sock the service
550  * @param handler function to call with the message
551  * @param handler_cls closure for handler
552  * @param timeout how long to wait until timing out
553  */
554 void
555 GNUNET_CLIENT_receive (struct GNUNET_CLIENT_Connection *sock,
556                        GNUNET_CLIENT_MessageHandler handler,
557                        void *handler_cls, struct GNUNET_TIME_Relative timeout)
558 {
559   if (sock->sock == NULL)
560     {
561       /* already disconnected, fail instantly! */
562       GNUNET_break (0);         /* this should not happen in well-written code! */
563       handler (handler_cls, NULL);
564       return;
565     }
566   sock->receiver_handler = handler;
567   sock->receiver_handler_cls = handler_cls;
568   sock->receive_timeout = GNUNET_TIME_relative_to_absolute (timeout);
569   if (GNUNET_YES == sock->msg_complete)
570     {
571       sock->receive_task = GNUNET_SCHEDULER_add_after (sock->sched,
572                                                        GNUNET_SCHEDULER_NO_TASK,
573                                                        &receive_task, sock);
574     }
575   else
576     {
577       GNUNET_assert (sock->in_receive == GNUNET_NO);
578       sock->in_receive = GNUNET_YES;
579       GNUNET_CONNECTION_receive (sock->sock,
580                                  GNUNET_SERVER_MAX_MESSAGE_SIZE - 1,
581                                  timeout, &receive_helper, sock);
582     }
583 }
584
585
586 /**
587  * Report service unavailable.
588  */
589 static void
590 service_test_error (struct GNUNET_SCHEDULER_Handle *s,
591                     GNUNET_SCHEDULER_Task task, void *task_cls)
592 {
593   GNUNET_SCHEDULER_add_continuation (s,
594                                      task,
595                                      task_cls,
596                                      GNUNET_SCHEDULER_REASON_TIMEOUT);
597 }
598
599
600 /**
601  * Receive confirmation from test, service is up.
602  *
603  * @param cls closure
604  * @param msg message received, NULL on timeout or fatal error
605  */
606 static void
607 confirm_handler (void *cls, const struct GNUNET_MessageHeader *msg)
608 {
609   struct GNUNET_CLIENT_Connection *conn = cls;
610   /* We may want to consider looking at the reply in more
611      detail in the future, for example, is this the
612      correct service? FIXME! */
613   if (msg != NULL)
614     {
615 #if DEBUG_CLIENT
616       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
617                   "Received confirmation that service is running.\n");
618 #endif
619       GNUNET_SCHEDULER_add_continuation (conn->sched,
620                                          conn->test_cb,
621                                          conn->test_cb_cls,
622                                          GNUNET_SCHEDULER_REASON_PREREQ_DONE);
623     }
624   else
625     {
626       service_test_error (conn->sched, conn->test_cb, conn->test_cb_cls);
627     }
628   GNUNET_CLIENT_disconnect (conn, GNUNET_NO);
629 }
630
631
632 static size_t
633 write_test (void *cls, size_t size, void *buf)
634 {
635   struct GNUNET_CLIENT_Connection *conn = cls;
636   struct GNUNET_MessageHeader *msg;
637
638   if (size < sizeof (struct GNUNET_MessageHeader))
639     {
640 #if DEBUG_CLIENT
641       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
642                   _("Failure to transmit TEST request.\n"));
643 #endif
644       service_test_error (conn->sched, conn->test_cb, conn->test_cb_cls);
645       GNUNET_CLIENT_disconnect (conn, GNUNET_NO);
646       return 0;                 /* client disconnected */
647     }
648 #if DEBUG_CLIENT
649   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
650               "Transmitting `%s' request.\n", "TEST");
651 #endif
652   msg = (struct GNUNET_MessageHeader *) buf;
653   msg->type = htons (GNUNET_MESSAGE_TYPE_TEST);
654   msg->size = htons (sizeof (struct GNUNET_MessageHeader));
655   GNUNET_CLIENT_receive (conn, 
656                          &confirm_handler, 
657                          conn, 
658                          GNUNET_TIME_absolute_get_remaining (conn->test_deadline));
659   return sizeof (struct GNUNET_MessageHeader);
660 }
661
662
663 /**
664  * Wait until the service is running.
665  *
666  * @param sched scheduler to use
667  * @param service name of the service to wait for
668  * @param cfg configuration to use
669  * @param timeout how long to wait at most in ms
670  * @param task task to run if service is running
671  *        (reason will be "PREREQ_DONE" (service running)
672  *         or "TIMEOUT" (service not known to be running))
673  * @param task_cls closure for task
674  */
675 void
676 GNUNET_CLIENT_service_test (struct GNUNET_SCHEDULER_Handle *sched,
677                             const char *service,
678                             const struct GNUNET_CONFIGURATION_Handle *cfg,
679                             struct GNUNET_TIME_Relative timeout,
680                             GNUNET_SCHEDULER_Task task, void *task_cls)
681 {
682   struct GNUNET_CLIENT_Connection *conn;
683
684 #if DEBUG_CLIENT
685   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
686               "Testing if service `%s' is running.\n", service);
687 #endif
688   conn = GNUNET_CLIENT_connect (sched, service, cfg);
689   if (conn == NULL)
690     {
691       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
692                   _
693                   ("Could not connect to service `%s', must not be running.\n"),
694                   service);
695       service_test_error (sched, task, task_cls);
696       return;
697     }
698   conn->test_cb = task;
699   conn->test_cb_cls = task_cls;
700   conn->test_deadline = GNUNET_TIME_relative_to_absolute (timeout);
701
702   if (NULL == GNUNET_CLIENT_notify_transmit_ready (conn,
703                                                    sizeof (struct GNUNET_MessageHeader),
704                                                    timeout,
705                                                    GNUNET_YES,
706                                                    &write_test, conn))  
707     {
708       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
709                   _("Failure to transmit request to service `%s'\n"),
710                   service);
711       service_test_error (sched, task, task_cls);
712       GNUNET_CLIENT_disconnect (conn, GNUNET_NO);
713       return;
714     }
715 }
716
717
718 /**
719  * Connection notifies us about failure or success of
720  * a transmission request.  Either pass it on to our
721  * user or, if possible, retry.
722  *
723  * @param cls our "struct GNUNET_CLIENT_TransmissionHandle"
724  * @param size number of bytes available for transmission
725  * @param buf where to write them
726  * @return number of bytes written to buf
727  */
728 static size_t client_notify (void *cls, size_t size, void *buf);
729
730
731 /**
732  * This task is run if we should re-try connection to the
733  * service after a while.
734  *
735  * @param cls our "struct GNUNET_CLIENT_TransmitHandle" of the request
736  * @param tc unused
737  */
738 static void
739 client_delayed_retry (void *cls,
740                       const struct GNUNET_SCHEDULER_TaskContext *tc)
741 {
742   struct GNUNET_CLIENT_TransmitHandle *th = cls;
743
744   th->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
745   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
746     {
747 #if DEBUG_CLIENT
748       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
749                   "Transmission failed due to shutdown.\n");
750 #endif
751       th->sock->th = NULL;
752       th->notify (th->notify_cls, 0, NULL);
753       GNUNET_free (th);
754       return;
755     }
756   th->th = GNUNET_CONNECTION_notify_transmit_ready (th->sock->sock,
757                                                     th->size,
758                                                     GNUNET_TIME_absolute_get_remaining
759                                                     (th->timeout),
760                                                     &client_notify, th);
761   if (th->th == NULL)
762     {
763       GNUNET_break (0);
764       th->notify (th->notify_cls, 0, NULL);
765       GNUNET_free (th);
766       return;
767     }
768 }
769
770
771 /**
772  * Connection notifies us about failure or success of a transmission
773  * request.  Either pass it on to our user or, if possible, retry.
774  *
775  * @param cls our "struct GNUNET_CLIENT_TransmissionHandle"
776  * @param size number of bytes available for transmission
777  * @param buf where to write them
778  * @return number of bytes written to buf
779  */
780 static size_t
781 client_notify (void *cls, size_t size, void *buf)
782 {
783   struct GNUNET_CLIENT_TransmitHandle *th = cls;
784   size_t ret;
785   struct GNUNET_TIME_Relative delay;
786
787   th->th = NULL;
788   th->sock->th = NULL;
789   if (buf == NULL)
790     {
791       delay = GNUNET_TIME_absolute_get_remaining (th->timeout);
792       delay.value /= 2;
793       if ( (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & GNUNET_SCHEDULER_get_reason (th->sock->sched))) ||
794            (GNUNET_YES != th->auto_retry) ||
795            (0 == --th->attempts_left) || 
796            (delay.value < 1) )
797         {
798 #if DEBUG_CLIENT
799           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
800                       "Transmission failed %u times, giving up.\n",
801                       MAX_ATTEMPTS - th->attempts_left);
802 #endif
803           GNUNET_break (0 == th->notify (th->notify_cls, 0, NULL));
804           GNUNET_free (th);
805           return 0;
806         }
807       /* auto-retry */
808       GNUNET_CONNECTION_destroy (th->sock->sock, GNUNET_NO);
809       th->sock->sock = do_connect (th->sock->sched,
810                                    th->sock->service_name, 
811                                    th->sock->cfg,
812                                    th->sock->attempts++);
813       GNUNET_assert (NULL != th->sock->sock);
814       GNUNET_CONNECTION_ignore_shutdown (th->sock->sock,
815                                          th->sock->ignore_shutdown);
816       delay = GNUNET_TIME_relative_min (delay, th->sock->back_off);
817       th->sock->back_off 
818           = GNUNET_TIME_relative_min (GNUNET_TIME_relative_multiply (th->sock->back_off, 2),
819                                     GNUNET_TIME_UNIT_SECONDS);
820 #if DEBUG_CLIENT
821       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
822                   "Transmission failed %u times, trying again in %llums.\n",
823                   MAX_ATTEMPTS - th->attempts_left,
824                   (unsigned long long) delay.value);
825 #endif
826       th->reconnect_task = GNUNET_SCHEDULER_add_delayed (th->sock->sched,
827                                                          delay,
828                                                          &client_delayed_retry,
829                                                          th);
830       th->sock->th = th;
831       return 0;
832     }
833   GNUNET_assert (size >= th->size);
834   ret = th->notify (th->notify_cls, size, buf);
835   GNUNET_free (th);
836   return ret;
837 }
838
839
840 /**
841  * Ask the client to call us once the specified number of bytes
842  * are free in the transmission buffer.  May call the notify
843  * method immediately if enough space is available.
844  *
845  * @param sock connection to the service
846  * @param size number of bytes to send
847  * @param timeout after how long should we give up (and call
848  *        notify with buf NULL and size 0)?
849  * @param auto_retry if the connection to the service dies, should we
850  *        automatically re-connect and retry (within the timeout period)
851  *        or should we immediately fail in this case?  Pass GNUNET_YES
852  *        if the caller does not care about temporary connection errors,
853  *        for example because the protocol is stateless
854  * @param notify function to call
855  * @param notify_cls closure for notify
856  * @return NULL if our buffer will never hold size bytes,
857  *         a handle if the notify callback was queued (can be used to cancel)
858  */
859 struct GNUNET_CLIENT_TransmitHandle *
860 GNUNET_CLIENT_notify_transmit_ready (struct GNUNET_CLIENT_Connection *sock,
861                                      size_t size,
862                                      struct GNUNET_TIME_Relative timeout,
863                                      int auto_retry,
864                                      GNUNET_CONNECTION_TransmitReadyNotify
865                                      notify, void *notify_cls)
866 {
867   struct GNUNET_CLIENT_TransmitHandle *th;
868
869   if (NULL != sock->th)
870     return NULL;
871   th = GNUNET_malloc (sizeof (struct GNUNET_CLIENT_TransmitHandle));
872   th->sock = sock;
873   th->size = size;
874   th->timeout = GNUNET_TIME_relative_to_absolute (timeout);
875   th->auto_retry = auto_retry;
876   th->notify = notify;
877   th->notify_cls = notify_cls;
878   th->attempts_left = MAX_ATTEMPTS;
879   th->th = GNUNET_CONNECTION_notify_transmit_ready (sock->sock,
880                                                     size,
881                                                     timeout,
882                                                     &client_notify, th);
883   if (NULL == th->th)
884     {
885       GNUNET_break (0);
886       GNUNET_free (th);
887       return NULL;
888     }
889   sock->th = th;
890   return th;
891 }
892
893
894 /**
895  * Cancel a request for notification.
896  * 
897  * @param th handle from the original request.
898  */
899 void
900 GNUNET_CLIENT_notify_transmit_ready_cancel (struct
901                                             GNUNET_CLIENT_TransmitHandle *th)
902 {
903   if (th->reconnect_task != GNUNET_SCHEDULER_NO_TASK)
904     {
905       GNUNET_break (NULL == th->th);
906       GNUNET_SCHEDULER_cancel (th->sock->sched, th->reconnect_task);
907       th->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
908     }
909   else
910     {
911       GNUNET_break (NULL != th->th);
912       GNUNET_CONNECTION_notify_transmit_ready_cancel (th->th);
913     }
914   th->sock->th = NULL;
915   GNUNET_free (th);
916 }
917
918
919 /**
920  * Function called to notify a client about the socket
921  * begin ready to queue the message.  "buf" will be
922  * NULL and "size" zero if the socket was closed for
923  * writing in the meantime.
924  *
925  * @param cls closure of type "struct TransmitGetResponseContext*"
926  * @param size number of bytes available in buf
927  * @param buf where the callee should write the message
928  * @return number of bytes written to buf
929  */
930 static size_t
931 transmit_for_response (void *cls, size_t size, void *buf)
932 {
933   struct TransmitGetResponseContext *tc = cls;
934   uint16_t msize;
935
936   tc->sock->tag = NULL;
937   msize = ntohs (tc->hdr->size);
938   if (NULL == buf)
939     {
940 #if DEBUG_CLIENT
941       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
942                   _("Could not submit request, not expecting to receive a response.\n"));
943 #endif
944       tc->rn (tc->rn_cls, NULL);
945       GNUNET_free (tc);
946       return 0;
947     }
948   GNUNET_assert (size >= msize);
949   memcpy (buf, tc->hdr, msize);
950   GNUNET_CLIENT_receive (tc->sock,
951                          tc->rn,
952                          tc->rn_cls,
953                          GNUNET_TIME_absolute_get_remaining (tc->timeout));
954   GNUNET_free (tc);
955   return msize;
956 }
957
958
959 /**
960  * Convenience API that combines sending a request
961  * to the service and waiting for a response.
962  * If either operation times out, the callback
963  * will be called with a "NULL" response (in which
964  * case the connection should probably be destroyed).
965  *
966  * @param sock connection to use
967  * @param hdr message to transmit
968  * @param timeout when to give up (for both transmission
969  *         and for waiting for a response)
970  * @param auto_retry if the connection to the service dies, should we
971  *        automatically re-connect and retry (within the timeout period)
972  *        or should we immediately fail in this case?  Pass GNUNET_YES
973  *        if the caller does not care about temporary connection errors,
974  *        for example because the protocol is stateless
975  * @param rn function to call with the response
976  * @param rn_cls closure for rn 
977  * @return GNUNET_OK on success, GNUNET_SYSERR if a request
978  *         is already pending
979  */
980 int
981 GNUNET_CLIENT_transmit_and_get_response (struct GNUNET_CLIENT_Connection
982                                          *sock,
983                                          const struct GNUNET_MessageHeader
984                                          *hdr,
985                                          struct GNUNET_TIME_Relative timeout,
986                                          int auto_retry,
987                                          GNUNET_CLIENT_MessageHandler rn,
988                                          void *rn_cls)
989 {
990   struct TransmitGetResponseContext *tc;
991   uint16_t msize;
992
993   if (NULL != sock->th)
994     return GNUNET_SYSERR;
995   GNUNET_assert (sock->tag == NULL);
996   msize = ntohs (hdr->size);
997   tc = GNUNET_malloc (sizeof (struct TransmitGetResponseContext) + msize);
998   tc->sock = sock;
999   tc->hdr = (const struct GNUNET_MessageHeader *) &tc[1];
1000   memcpy (&tc[1], hdr, msize);
1001   tc->timeout = GNUNET_TIME_relative_to_absolute (timeout);
1002   tc->rn = rn;
1003   tc->rn_cls = rn_cls;
1004   if (NULL == GNUNET_CLIENT_notify_transmit_ready (sock,
1005                                                    msize,
1006                                                    timeout,
1007                                                    auto_retry,
1008                                                    &transmit_for_response,
1009                                                    tc))
1010     {
1011       GNUNET_break (0);
1012       GNUNET_free (tc);
1013       return GNUNET_SYSERR;
1014     }
1015   sock->tag = tc;
1016   return GNUNET_OK;
1017 }
1018
1019
1020
1021 /*  end of client.c */