-fix (C) notices
[oweals/gnunet.git] / src / util / client.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2001-2013 GNUnet e.V.
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 3, 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., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, 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 #include "platform.h"
30 #include "gnunet_protocols.h"
31 #include "gnunet_util_lib.h"
32 #include "gnunet_socks.h"
33
34
35 /**
36  * How often do we re-try tranmsitting requests before giving up?
37  * Note that if we succeeded transmitting a request but failed to read
38  * a response, we do NOT re-try.
39  */
40 #define MAX_ATTEMPTS 50
41
42 #define LOG(kind,...) GNUNET_log_from (kind, "util",__VA_ARGS__)
43
44 /**
45  * Handle for a transmission request.
46  */
47 struct GNUNET_CLIENT_TransmitHandle
48 {
49   /**
50    * Connection state.
51    */
52   struct GNUNET_CLIENT_Connection *client;
53
54   /**
55    * Function to call to get the data for transmission.
56    */
57   GNUNET_CONNECTION_TransmitReadyNotify notify;
58
59   /**
60    * Closure for @e notify.
61    */
62   void *notify_cls;
63
64   /**
65    * Handle to the transmission with the underlying
66    * connection.
67    */
68   struct GNUNET_CONNECTION_TransmitHandle *th;
69
70   /**
71    * If we are re-trying and are delaying to do so,
72    * handle to the scheduled task managing the delay.
73    */
74   struct GNUNET_SCHEDULER_Task *reconnect_task;
75
76   /**
77    * Timeout for the operation overall.
78    */
79   struct GNUNET_TIME_Absolute timeout;
80
81   /**
82    * Number of bytes requested.
83    */
84   size_t size;
85
86   /**
87    * Are we allowed to re-try to connect without telling
88    * the user (of this API) about the connection troubles?
89    */
90   int auto_retry;
91
92   /**
93    * Number of attempts left for transmitting the request.  We may
94    * fail the first time (say because the service is not yet up), in
95    * which case (if auto_retry is set) we wait a bit and re-try
96    * (timeout permitting).
97    */
98   unsigned int attempts_left;
99
100 };
101
102
103 /**
104  * Context for processing
105  * "GNUNET_CLIENT_transmit_and_get_response" requests.
106  */
107 struct TransmitGetResponseContext
108 {
109   /**
110    * Client handle.
111    */
112   struct GNUNET_CLIENT_Connection *client;
113
114   /**
115    * Message to transmit; do not free, allocated
116    * right after this struct.
117    */
118   const struct GNUNET_MessageHeader *hdr;
119
120   /**
121    * Timeout to use.
122    */
123   struct GNUNET_TIME_Absolute timeout;
124
125   /**
126    * Function to call when done.
127    */
128   GNUNET_CLIENT_MessageHandler rn;
129
130   /**
131    * Closure for @e rn.
132    */
133   void *rn_cls;
134 };
135
136 /**
137  * Struct to refer to a GNUnet TCP connection.
138  * This is more than just a socket because if the server
139  * drops the connection, the client automatically tries
140  * to reconnect (and for that needs connection information).
141  */
142 struct GNUNET_CLIENT_Connection
143 {
144
145   /**
146    * The connection handle, NULL if not live
147    */
148   struct GNUNET_CONNECTION_Handle *connection;
149
150   /**
151    * Our configuration.
152    */
153   const struct GNUNET_CONFIGURATION_Handle *cfg;
154
155   /**
156    * Name of the service we interact with.
157    */
158   char *service_name;
159
160   /**
161    * Context of a transmit_and_get_response operation, NULL
162    * if no such operation is pending.
163    */
164   struct TransmitGetResponseContext *tag;
165
166   /**
167    * Handler for current receiver task.
168    */
169   GNUNET_CLIENT_MessageHandler receiver_handler;
170
171   /**
172    * Closure for @e receiver_handler.
173    */
174   void *receiver_handler_cls;
175
176   /**
177    * Handle for a pending transmission request, NULL if there is
178    * none pending.
179    */
180   struct GNUNET_CLIENT_TransmitHandle *th;
181
182   /**
183    * If we are re-trying and are delaying to do so,
184    * handle to the scheduled task managing the delay.
185    */
186   struct GNUNET_SCHEDULER_Task * receive_task;
187
188   /**
189    * Buffer for received message.
190    */
191   char *received_buf;
192
193   /**
194    * Timeout for receiving a response (absolute time).
195    */
196   struct GNUNET_TIME_Absolute receive_timeout;
197
198   /**
199    * Current value for our incremental back-off (for
200    * connect re-tries).
201    */
202   struct GNUNET_TIME_Relative back_off;
203
204   /**
205    * Number of bytes in received_buf that are valid.
206    */
207   size_t received_pos;
208
209   /**
210    * Size of received_buf.
211    */
212   unsigned int received_size;
213
214   /**
215    * Do we have a complete response in received_buf?
216    */
217   int msg_complete;
218
219   /**
220    * Are we currently busy doing receive-processing?
221    * #GNUNET_YES if so, #GNUNET_NO if not. #GNUNET_SYSERR
222    * if the connection has failed (but we may not have
223    * closed the handle itself yet).
224    */
225   int in_receive;
226
227   /**
228    * Is this the first message we are sending to the service?
229    */
230   int first_message;
231
232   /**
233    * How often have we tried to connect?
234    */
235   unsigned int attempts;
236
237 };
238
239
240 /**
241  * Try connecting to the server using UNIX domain sockets.
242  *
243  * @param service_name name of service to connect to
244  * @param cfg configuration to use
245  * @return NULL on error, connection to UNIX otherwise
246  */
247 static struct GNUNET_CONNECTION_Handle *
248 try_unixpath (const char *service_name,
249               const struct GNUNET_CONFIGURATION_Handle *cfg)
250 {
251 #if AF_UNIX
252   struct GNUNET_CONNECTION_Handle *connection;
253   char *unixpath;
254   struct sockaddr_un s_un;
255
256   unixpath = NULL;
257   if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg, service_name, "UNIXPATH", &unixpath)) &&
258       (0 < strlen (unixpath)))
259   {
260     /* We have a non-NULL unixpath, need to validate it */
261     if (strlen (unixpath) >= sizeof (s_un.sun_path))
262     {
263       LOG (GNUNET_ERROR_TYPE_WARNING,
264            _("UNIXPATH `%s' too long, maximum length is %llu\n"), unixpath,
265            (unsigned long long) sizeof (s_un.sun_path));
266       unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
267       LOG (GNUNET_ERROR_TYPE_INFO,
268            _("Using `%s' instead\n"), unixpath);
269       if (NULL == unixpath)
270         return NULL;
271     }
272     connection = GNUNET_CONNECTION_create_from_connect_to_unixpath (cfg, unixpath);
273     if (NULL != connection)
274     {
275       LOG (GNUNET_ERROR_TYPE_DEBUG, "Connected to unixpath `%s'!\n",
276            unixpath);
277       GNUNET_free (unixpath);
278       return connection;
279     }
280   }
281   GNUNET_free_non_null (unixpath);
282 #endif
283   return NULL;
284 }
285
286
287 /**
288  * Test whether the configuration has proper values for connection
289  * (UNIXPATH || (PORT && HOSTNAME)).
290  *
291  * @param service_name name of service to connect to
292  * @param cfg configuration to use
293  * @return #GNUNET_OK if the configuration is valid, #GNUNET_SYSERR if not
294  */
295 static int
296 test_service_configuration (const char *service_name,
297                             const struct GNUNET_CONFIGURATION_Handle *cfg)
298 {
299   int ret = GNUNET_SYSERR;
300   char *hostname = NULL;
301   unsigned long long port;
302 #if AF_UNIX
303   char *unixpath = NULL;
304
305   if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg, service_name, "UNIXPATH", &unixpath)) &&
306       (0 < strlen (unixpath)))
307     ret = GNUNET_OK;
308   GNUNET_free_non_null (unixpath);
309 #endif
310
311   if ( (GNUNET_YES ==
312         GNUNET_CONFIGURATION_have_value (cfg, service_name, "PORT")) &&
313        (GNUNET_OK ==
314         GNUNET_CONFIGURATION_get_value_number (cfg, service_name, "PORT", &port)) &&
315        (port <= 65535) && (0 != port) &&
316        (GNUNET_OK ==
317         GNUNET_CONFIGURATION_get_value_string (cfg, service_name, "HOSTNAME",
318                                                &hostname)) &&
319        (0 != strlen (hostname)) )
320     ret = GNUNET_OK;
321   GNUNET_free_non_null (hostname);
322   return ret;
323 }
324
325
326 /**
327  * Try to connect to the service.
328  *
329  * @param service_name name of service to connect to
330  * @param cfg configuration to use
331  * @param attempt counter used to alternate between IP and UNIX domain sockets
332  * @return NULL on error
333  */
334 static struct GNUNET_CONNECTION_Handle *
335 do_connect (const char *service_name,
336             const struct GNUNET_CONFIGURATION_Handle *cfg,
337             unsigned int attempt)
338 {
339   struct GNUNET_CONNECTION_Handle *connection;
340   char *hostname;
341   unsigned long long port;
342
343   /* Never use a local source if a proxy is configured */
344   if (GNUNET_YES == GNUNET_SOCKS_check_service (service_name,cfg))
345     return GNUNET_SOCKS_do_connect (service_name,cfg);
346
347   connection = NULL;
348   if (0 == (attempt % 2))
349   {
350     /* on even rounds, try UNIX first */
351     connection = try_unixpath (service_name, cfg);
352     if (NULL != connection)
353       return connection;
354   }
355   if (GNUNET_YES ==
356       GNUNET_CONFIGURATION_have_value (cfg, service_name, "PORT"))
357   {
358     if ((GNUNET_OK !=
359          GNUNET_CONFIGURATION_get_value_number (cfg, service_name, "PORT", &port))
360         || (port > 65535) ||
361         (GNUNET_OK !=
362          GNUNET_CONFIGURATION_get_value_string (cfg, service_name, "HOSTNAME",
363                                                 &hostname)))
364     {
365       LOG (GNUNET_ERROR_TYPE_WARNING,
366            _
367            ("Could not determine valid hostname and port for service `%s' from configuration.\n"),
368            service_name);
369       return NULL;
370     }
371     if (0 == strlen (hostname))
372     {
373       GNUNET_free (hostname);
374       LOG (GNUNET_ERROR_TYPE_WARNING,
375            _("Need a non-empty hostname for service `%s'.\n"), service_name);
376       return NULL;
377     }
378   }
379   else
380   {
381     /* unspecified means 0 (disabled) */
382     port = 0;
383     hostname = NULL;
384   }
385   if (0 == port)
386   {
387     /* if port is 0, try UNIX */
388     connection = try_unixpath (service_name, cfg);
389     if (NULL != connection)
390     {
391       GNUNET_free_non_null (hostname);
392       return connection;
393     }
394     LOG (GNUNET_ERROR_TYPE_DEBUG,
395          "Port is 0 for service `%s', UNIXPATH did not work, returning NULL!\n",
396          service_name);
397     GNUNET_free_non_null (hostname);
398     return NULL;
399   }
400   connection = GNUNET_CONNECTION_create_from_connect (cfg, hostname, port);
401   GNUNET_free (hostname);
402   return connection;
403 }
404
405
406 /**
407  * Get a connection with a service.
408  *
409  * @param service_name name of the service
410  * @param cfg configuration to use
411  * @return NULL on error (service unknown to configuration)
412  */
413 struct GNUNET_CLIENT_Connection *
414 GNUNET_CLIENT_connect (const char *service_name,
415                        const struct GNUNET_CONFIGURATION_Handle *cfg)
416 {
417   struct GNUNET_CLIENT_Connection *client;
418   struct GNUNET_CONNECTION_Handle *connection;
419
420   if (GNUNET_OK !=
421       test_service_configuration (service_name,
422                                   cfg))
423     return NULL;
424   connection = do_connect (service_name, cfg, 0);
425   client = GNUNET_new (struct GNUNET_CLIENT_Connection);
426   client->first_message = GNUNET_YES;
427   client->attempts = 1;
428   client->connection = connection;
429   client->service_name = GNUNET_strdup (service_name);
430   client->cfg = cfg;
431   client->back_off = GNUNET_TIME_UNIT_MILLISECONDS;
432   return client;
433 }
434
435
436 /**
437  * Destroy connection with the service.  This will automatically
438  * cancel any pending "receive" request (however, the handler will
439  * *NOT* be called, not even with a NULL message).  Any pending
440  * transmission request will also be cancelled UNLESS the callback for
441  * the transmission request has already been called, in which case the
442  * transmission 'finish_pending_write' argument determines whether or
443  * not the write is guaranteed to complete before the socket is fully
444  * destroyed (unless, of course, there is an error with the server in
445  * which case the message may still be lost).
446  *
447  * @param client handle to the service connection
448  */
449 void
450 GNUNET_CLIENT_disconnect (struct GNUNET_CLIENT_Connection *client)
451 {
452   if (GNUNET_YES == client->in_receive)
453   {
454     GNUNET_CONNECTION_receive_cancel (client->connection);
455     client->in_receive = GNUNET_NO;
456   }
457   if (NULL != client->th)
458   {
459     GNUNET_CLIENT_notify_transmit_ready_cancel (client->th);
460     client->th = NULL;
461   }
462   if (NULL != client->connection)
463   {
464     GNUNET_CONNECTION_destroy (client->connection);
465     client->connection = NULL;
466   }
467   if (NULL != client->receive_task)
468   {
469     GNUNET_SCHEDULER_cancel (client->receive_task);
470     client->receive_task = NULL;
471   }
472   if (NULL != client->tag)
473   {
474     GNUNET_free (client->tag);
475     client->tag = NULL;
476   }
477   client->receiver_handler = NULL;
478   GNUNET_array_grow (client->received_buf, client->received_size, 0);
479   GNUNET_free (client->service_name);
480   GNUNET_free (client);
481 }
482
483
484 /**
485  * Check if message is complete.  Sets the "msg_complete" member
486  * in the client struct.
487  *
488  * @param client connection with the buffer to check
489  */
490 static void
491 check_complete (struct GNUNET_CLIENT_Connection *client)
492 {
493   if ((client->received_pos >= sizeof (struct GNUNET_MessageHeader)) &&
494       (client->received_pos >=
495        ntohs (((const struct GNUNET_MessageHeader *) client->received_buf)->
496               size)))
497     client->msg_complete = GNUNET_YES;
498 }
499
500
501 /**
502  * Callback function for data received from the network.  Note that
503  * both @a available and @a errCode would be 0 if the read simply timed out.
504  *
505  * @param cls closure
506  * @param buf pointer to received data
507  * @param available number of bytes availabe in @a buf,
508  *        possibly 0 (on errors)
509  * @param addr address of the sender
510  * @param addrlen size of @a addr
511  * @param errCode value of errno (on errors receiving)
512  */
513 static void
514 receive_helper (void *cls,
515                 const void *buf,
516                 size_t available,
517                 const struct sockaddr *addr,
518                 socklen_t addrlen,
519                 int errCode)
520 {
521   struct GNUNET_CLIENT_Connection *client = cls;
522   struct GNUNET_TIME_Relative remaining;
523   GNUNET_CLIENT_MessageHandler receive_handler;
524   void *receive_handler_cls;
525
526   GNUNET_assert (GNUNET_NO == client->msg_complete);
527   GNUNET_assert (GNUNET_YES == client->in_receive);
528   client->in_receive = GNUNET_NO;
529   if ( (0 == available) ||
530        (NULL == client->connection) ||
531        (0 != errCode) )
532   {
533     /* signal timeout! */
534     LOG (GNUNET_ERROR_TYPE_DEBUG,
535          "Timeout in receive_helper, available %u, client->connection %s, errCode `%s'\n",
536          (unsigned int) available,
537          NULL == client->connection ? "NULL" : "non-NULL",
538          STRERROR (errCode));
539     /* remember failure */
540     client->in_receive = GNUNET_SYSERR;
541     if (NULL != (receive_handler = client->receiver_handler))
542     {
543       receive_handler_cls = client->receiver_handler_cls;
544       client->receiver_handler = NULL;
545       receive_handler (receive_handler_cls,
546                        NULL);
547     }
548     return;
549   }
550   /* FIXME: optimize for common fast case where buf contains the
551    * entire message and we need no copying... */
552
553   /* slow path: append to array */
554   if (client->received_size < client->received_pos + available)
555     GNUNET_array_grow (client->received_buf, client->received_size,
556                        client->received_pos + available);
557   memcpy (&client->received_buf[client->received_pos], buf, available);
558   client->received_pos += available;
559   check_complete (client);
560   /* check for timeout */
561   remaining = GNUNET_TIME_absolute_get_remaining (client->receive_timeout);
562   if (0 == remaining.rel_value_us)
563   {
564     /* signal timeout! */
565     if (NULL != (receive_handler = client->receiver_handler))
566     {
567       client->receiver_handler = NULL;
568       receive_handler (client->receiver_handler_cls, NULL);
569     }
570     return;
571   }
572   /* back to receive -- either for more data or to call callback! */
573   GNUNET_CLIENT_receive (client, client->receiver_handler,
574                          client->receiver_handler_cls, remaining);
575 }
576
577
578 /**
579  * Continuation to call the receive callback.
580  *
581  * @param cls  our handle to the client connection
582  * @param tc scheduler context
583  */
584 static void
585 receive_task (void *cls,
586               const struct GNUNET_SCHEDULER_TaskContext *tc)
587 {
588   struct GNUNET_CLIENT_Connection *client = cls;
589   GNUNET_CLIENT_MessageHandler handler = client->receiver_handler;
590   const struct GNUNET_MessageHeader *cmsg =
591       (const struct GNUNET_MessageHeader *) client->received_buf;
592   void *handler_cls = client->receiver_handler_cls;
593   uint16_t msize = ntohs (cmsg->size);
594   char mbuf[msize] GNUNET_ALIGN;
595   struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) mbuf;
596
597   client->receive_task = NULL;
598   if ( (GNUNET_SYSERR == client->in_receive) &&
599        (GNUNET_YES != client->msg_complete) )
600   {
601     /* Connection failure, signal to caller! */
602     client->receiver_handler = NULL;
603     if (NULL != handler)
604       handler (handler_cls,
605                NULL);
606     return;
607   }
608   LOG (GNUNET_ERROR_TYPE_DEBUG,
609        "Received message of type %u and size %u from %s service.\n",
610        ntohs (cmsg->type),
611        msize,
612        client->service_name);
613   GNUNET_assert (GNUNET_YES == client->msg_complete);
614   GNUNET_assert (client->received_pos >= msize);
615   memcpy (msg, cmsg, msize);
616   memmove (client->received_buf, &client->received_buf[msize],
617            client->received_pos - msize);
618   client->received_pos -= msize;
619   client->msg_complete = GNUNET_NO;
620   client->receiver_handler = NULL;
621   check_complete (client);
622   if (NULL != handler)
623     handler (handler_cls, msg);
624 }
625
626
627 /**
628  * Read from the service.
629  *
630  * @param client the service
631  * @param handler function to call with the message
632  * @param handler_cls closure for @a handler
633  * @param timeout how long to wait until timing out
634  */
635 void
636 GNUNET_CLIENT_receive (struct GNUNET_CLIENT_Connection *client,
637                        GNUNET_CLIENT_MessageHandler handler,
638                        void *handler_cls,
639                        struct GNUNET_TIME_Relative timeout)
640 {
641   if (NULL == client->connection)
642   {
643     /* already disconnected, fail instantly! */
644     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
645                 "Client API violation for service `%s'\n",
646                 client->service_name);
647     GNUNET_break (0);           /* this should not happen in well-written code! */
648     if (NULL != handler)
649       handler (handler_cls,
650                NULL);
651     return;
652   }
653   client->receiver_handler = handler;
654   client->receiver_handler_cls = handler_cls;
655   client->receive_timeout = GNUNET_TIME_relative_to_absolute (timeout);
656   if ( (GNUNET_YES == client->msg_complete) ||
657        (GNUNET_SYSERR == client->in_receive) )
658   {
659     GNUNET_assert (NULL == client->receive_task);
660     client->receive_task = GNUNET_SCHEDULER_add_now (&receive_task, client);
661     return;
662   }
663   LOG (GNUNET_ERROR_TYPE_DEBUG,
664        "calling GNUNET_CONNECTION_receive\n");
665   GNUNET_assert (GNUNET_NO == client->in_receive);
666   client->in_receive = GNUNET_YES;
667   GNUNET_CONNECTION_receive (client->connection,
668                              GNUNET_SERVER_MAX_MESSAGE_SIZE - 1,
669                              timeout,
670                              &receive_helper,
671                              client);
672 }
673
674
675 /**
676  * Handle for a test to check if a service is running.
677  */
678 struct GNUNET_CLIENT_TestHandle
679 {
680   /**
681    * Function to call with the result of the test.
682    */
683   GNUNET_CLIENT_TestResultCallback cb;
684
685   /**
686    * Closure for @e cb.
687    */
688   void *cb_cls;
689
690   /**
691    * Client connection we are using for the test, if any.
692    */
693   struct GNUNET_CLIENT_Connection *client;
694
695   /**
696    * Handle for the transmission request, if any.
697    */
698   struct GNUNET_CLIENT_TransmitHandle *th;
699
700   /**
701    * Deadline for calling @e cb.
702    */
703   struct GNUNET_TIME_Absolute test_deadline;
704
705   /**
706    * ID of task used for asynchronous operations.
707    */
708   struct GNUNET_SCHEDULER_Task * task;
709
710   /**
711    * Final result to report back (once known).
712    */
713   int result;
714 };
715
716
717 /**
718  * Abort testing for service.
719  *
720  * @param th test handle
721  */
722 void
723 GNUNET_CLIENT_service_test_cancel (struct GNUNET_CLIENT_TestHandle *th)
724 {
725   if (NULL != th->th)
726   {
727     GNUNET_CLIENT_notify_transmit_ready_cancel (th->th);
728     th->th = NULL;
729   }
730   if (NULL != th->client)
731   {
732     GNUNET_CLIENT_disconnect (th->client);
733     th->client = NULL;
734   }
735   if (NULL != th->task)
736   {
737     GNUNET_SCHEDULER_cancel (th->task);
738     th->task = NULL;
739   }
740   GNUNET_free (th);
741 }
742
743
744 /**
745  * Task that reports back the result by calling the callback
746  * and then cleans up.
747  *
748  * @param cls the `struct GNUNET_CLIENT_TestHandle`
749  * @param tc scheduler context
750  */
751 static void
752 report_result (void *cls,
753                const struct GNUNET_SCHEDULER_TaskContext *tc)
754 {
755   struct GNUNET_CLIENT_TestHandle *th = cls;
756
757   th->task = NULL;
758   th->cb (th->cb_cls, th->result);
759   GNUNET_CLIENT_service_test_cancel (th);
760 }
761
762
763 /**
764  * Report service test result asynchronously back to callback.
765  *
766  * @param th test handle with the result and the callback
767  * @param result result to report
768  */
769 static void
770 service_test_report (struct GNUNET_CLIENT_TestHandle *th,
771                      int result)
772 {
773   th->result = result;
774   th->task = GNUNET_SCHEDULER_add_now (&report_result,
775                                        th);
776 }
777
778
779 /**
780  * Receive confirmation from test, service is up.
781  *
782  * @param cls closure with the `struct GNUNET_CLIENT_TestHandle`
783  * @param msg message received, NULL on timeout or fatal error
784  */
785 static void
786 confirm_handler (void *cls,
787                  const struct GNUNET_MessageHeader *msg)
788 {
789   struct GNUNET_CLIENT_TestHandle *th = cls;
790
791   /* We may want to consider looking at the reply in more
792    * detail in the future, for example, is this the
793    * correct service? FIXME! */
794   if (NULL != msg)
795   {
796     LOG (GNUNET_ERROR_TYPE_DEBUG,
797          "Received confirmation that service is running.\n");
798     service_test_report (th, GNUNET_YES);
799   }
800   else
801   {
802     service_test_report (th, GNUNET_NO);
803   }
804 }
805
806
807 /**
808  * Send the 'TEST' message to the service.  If successful, prepare to
809  * receive the reply.
810  *
811  * @param cls the `struct GNUNET_CLIENT_TestHandle` of the test
812  * @param size number of bytes available in @a buf
813  * @param buf where to write the message
814  * @return number of bytes written to @a buf
815  */
816 static size_t
817 write_test (void *cls, size_t size, void *buf)
818 {
819   struct GNUNET_CLIENT_TestHandle *th = cls;
820   struct GNUNET_MessageHeader *msg;
821
822   th->th = NULL;
823   if (size < sizeof (struct GNUNET_MessageHeader))
824   {
825     LOG (GNUNET_ERROR_TYPE_DEBUG,
826          "Failed to transmit TEST request.\n");
827     service_test_report (th, GNUNET_NO);
828     return 0;                   /* client disconnected */
829   }
830   LOG (GNUNET_ERROR_TYPE_DEBUG,
831        "Transmitting `%s' request.\n",
832        "TEST");
833   msg = (struct GNUNET_MessageHeader *) buf;
834   msg->type = htons (GNUNET_MESSAGE_TYPE_TEST);
835   msg->size = htons (sizeof (struct GNUNET_MessageHeader));
836   GNUNET_CLIENT_receive (th->client,
837                          &confirm_handler, th,
838                          GNUNET_TIME_absolute_get_remaining
839                          (th->test_deadline));
840   return sizeof (struct GNUNET_MessageHeader);
841 }
842
843
844 /**
845  * Test if the service is running.  If we are given a UNIXPATH or a
846  * local address, we do this NOT by trying to connect to the service,
847  * but by trying to BIND to the same port.  If the BIND fails, we know
848  * the service is running.
849  *
850  * @param service name of the service to wait for
851  * @param cfg configuration to use
852  * @param timeout how long to wait at most
853  * @param cb function to call with the result
854  * @param cb_cls closure for @a cb
855  * @return handle to cancel the test
856  */
857 struct GNUNET_CLIENT_TestHandle *
858 GNUNET_CLIENT_service_test (const char *service,
859                             const struct GNUNET_CONFIGURATION_Handle *cfg,
860                             struct GNUNET_TIME_Relative timeout,
861                             GNUNET_CLIENT_TestResultCallback cb,
862                             void *cb_cls)
863 {
864   struct GNUNET_CLIENT_TestHandle *th;
865   char *hostname;
866   unsigned long long port;
867   struct GNUNET_NETWORK_Handle *sock;
868
869   th = GNUNET_new (struct GNUNET_CLIENT_TestHandle);
870   th->cb = cb;
871   th->cb_cls = cb_cls;
872   th->test_deadline = GNUNET_TIME_relative_to_absolute (timeout);
873   LOG (GNUNET_ERROR_TYPE_DEBUG,
874        "Testing if service `%s' is running.\n",
875        service);
876 #ifdef AF_UNIX
877   {
878     /* probe UNIX support */
879     struct sockaddr_un s_un;
880     char *unixpath;
881     int abstract;
882
883     unixpath = NULL;
884     if ((GNUNET_OK ==
885          GNUNET_CONFIGURATION_get_value_filename (cfg,
886                                                   service,
887                                                   "UNIXPATH",
888                                                   &unixpath)) &&
889         (0 < strlen (unixpath)))  /* We have a non-NULL unixpath, does that mean it's valid? */
890     {
891       if (strlen (unixpath) >= sizeof (s_un.sun_path))
892       {
893         LOG (GNUNET_ERROR_TYPE_WARNING,
894              _("UNIXPATH `%s' too long, maximum length is %llu\n"),
895              unixpath,
896              (unsigned long long) sizeof (s_un.sun_path));
897         unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
898         LOG (GNUNET_ERROR_TYPE_INFO,
899              _("Using `%s' instead\n"), unixpath);
900       }
901     }
902 #ifdef LINUX
903     abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg,
904                                                      "TESTING",
905                                                      "USE_ABSTRACT_SOCKETS");
906 #else
907     abstract = GNUNET_NO;
908 #endif
909     if ((NULL != unixpath) && (GNUNET_YES != abstract))
910     {
911       if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (unixpath))
912         GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
913                                   "mkdir", unixpath);
914     }
915     if (NULL != unixpath)
916     {
917       sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0);
918       if (NULL != sock)
919       {
920         memset (&s_un, 0, sizeof (s_un));
921         s_un.sun_family = AF_UNIX;
922         strncpy (s_un.sun_path, unixpath, sizeof (s_un.sun_path) - 1);
923         if (GNUNET_YES == abstract)
924           s_un.sun_path[0] = '\0';
925 #if HAVE_SOCKADDR_IN_SIN_LEN
926         s_un.sun_len = (u_char) sizeof (struct sockaddr_un);
927 #endif
928         if (GNUNET_OK !=
929             GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_un,
930                                         sizeof (struct sockaddr_un)))
931         {
932           /* failed to bind => service must be running */
933           GNUNET_free (unixpath);
934           (void) GNUNET_NETWORK_socket_close (sock);
935           service_test_report (th, GNUNET_YES);
936           return th;
937         }
938         (void) GNUNET_NETWORK_socket_close (sock);
939         /* let's try IP */
940       }
941     }
942     GNUNET_free_non_null (unixpath);
943   }
944 #endif
945
946   hostname = NULL;
947   if ((GNUNET_OK !=
948        GNUNET_CONFIGURATION_get_value_number (cfg, service, "PORT", &port)) ||
949       (port > 65535) ||
950       (GNUNET_OK !=
951        GNUNET_CONFIGURATION_get_value_string (cfg, service, "HOSTNAME",
952                                               &hostname)))
953   {
954     /* UNIXPATH failed (if possible) AND IP failed => error */
955     service_test_report (th, GNUNET_SYSERR);
956     return th;
957   }
958
959   if (0 == strcmp ("localhost", hostname)
960 #if !LINUX
961       && 0
962 #endif
963       )
964   {
965     /* can test using 'bind' */
966     struct sockaddr_in s_in;
967
968     memset (&s_in, 0, sizeof (s_in));
969 #if HAVE_SOCKADDR_IN_SIN_LEN
970     s_in.sin_len = sizeof (struct sockaddr_in);
971 #endif
972     s_in.sin_family = AF_INET;
973     s_in.sin_port = htons (port);
974
975     sock = GNUNET_NETWORK_socket_create (AF_INET, SOCK_STREAM, 0);
976     if (NULL != sock)
977     {
978       if (GNUNET_OK !=
979           GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_in,
980                                       sizeof (s_in)))
981       {
982         /* failed to bind => service must be running */
983         GNUNET_free (hostname);
984         (void) GNUNET_NETWORK_socket_close (sock);
985         service_test_report (th, GNUNET_YES);
986         return th;
987       }
988       (void) GNUNET_NETWORK_socket_close (sock);
989     }
990   }
991
992   if (0 == strcmp ("ip6-localhost", hostname)
993 #if !LINUX
994       && 0
995 #endif
996       )
997   {
998     /* can test using 'bind' */
999     struct sockaddr_in6 s_in6;
1000
1001     memset (&s_in6, 0, sizeof (s_in6));
1002 #if HAVE_SOCKADDR_IN_SIN_LEN
1003     s_in6.sin6_len = sizeof (struct sockaddr_in6);
1004 #endif
1005     s_in6.sin6_family = AF_INET6;
1006     s_in6.sin6_port = htons (port);
1007
1008     sock = GNUNET_NETWORK_socket_create (AF_INET6, SOCK_STREAM, 0);
1009     if (NULL != sock)
1010     {
1011       if (GNUNET_OK !=
1012           GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_in6,
1013                                       sizeof (s_in6)))
1014       {
1015         /* failed to bind => service must be running */
1016         GNUNET_free (hostname);
1017         (void) GNUNET_NETWORK_socket_close (sock);
1018         service_test_report (th, GNUNET_YES);
1019         return th;
1020       }
1021       (void) GNUNET_NETWORK_socket_close (sock);
1022     }
1023   }
1024
1025   if (((0 == strcmp ("localhost", hostname)) ||
1026        (0 == strcmp ("ip6-localhost", hostname)))
1027 #if !LINUX
1028       && 0
1029 #endif
1030       )
1031   {
1032     /* all binds succeeded => claim service not running right now */
1033     GNUNET_free_non_null (hostname);
1034     service_test_report (th, GNUNET_NO);
1035     return th;
1036   }
1037   GNUNET_free_non_null (hostname);
1038
1039   /* non-localhost, try 'connect' method */
1040   th->client = GNUNET_CLIENT_connect (service, cfg);
1041   if (NULL == th->client)
1042   {
1043     LOG (GNUNET_ERROR_TYPE_INFO,
1044          _("Could not connect to service `%s', configuration broken.\n"),
1045          service);
1046     service_test_report (th, GNUNET_SYSERR);
1047     return th;
1048   }
1049   th->th = GNUNET_CLIENT_notify_transmit_ready (th->client,
1050                                                 sizeof (struct GNUNET_MessageHeader),
1051                                                 timeout, GNUNET_YES,
1052                                                 &write_test, th);
1053   if (NULL == th->th)
1054   {
1055     LOG (GNUNET_ERROR_TYPE_WARNING,
1056          _("Failure to transmit request to service `%s'\n"), service);
1057     service_test_report (th, GNUNET_SYSERR);
1058     return th;
1059   }
1060   return th;
1061 }
1062
1063
1064 /**
1065  * Connection notifies us about failure or success of
1066  * a transmission request.  Either pass it on to our
1067  * user or, if possible, retry.
1068  *
1069  * @param cls our `struct GNUNET_CLIENT_TransmissionHandle`
1070  * @param size number of bytes available for transmission
1071  * @param buf where to write them
1072  * @return number of bytes written to @a buf
1073  */
1074 static size_t
1075 client_notify (void *cls, size_t size, void *buf);
1076
1077
1078 /**
1079  * This task is run if we should re-try connection to the
1080  * service after a while.
1081  *
1082  * @param cls our `struct GNUNET_CLIENT_TransmitHandle` of the request
1083  * @param tc unused
1084  */
1085 static void
1086 client_delayed_retry (void *cls,
1087                       const struct GNUNET_SCHEDULER_TaskContext *tc)
1088 {
1089   struct GNUNET_CLIENT_TransmitHandle *th = cls;
1090   struct GNUNET_TIME_Relative delay;
1091
1092   th->reconnect_task = NULL;
1093   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1094   {
1095     /* give up, was shutdown */
1096     th->client->th = NULL;
1097     th->notify (th->notify_cls, 0, NULL);
1098     GNUNET_free (th);
1099     return;
1100   }
1101   th->client->connection =
1102     do_connect (th->client->service_name,
1103                 th->client->cfg,
1104                 th->client->attempts++);
1105   th->client->first_message = GNUNET_YES;
1106   if (NULL == th->client->connection)
1107   {
1108     /* could happen if we're out of sockets */
1109     delay = GNUNET_TIME_relative_min (GNUNET_TIME_absolute_get_remaining (th->timeout),
1110                                       th->client->back_off);
1111     th->client->back_off = GNUNET_TIME_STD_BACKOFF (th->client->back_off);
1112     LOG (GNUNET_ERROR_TYPE_DEBUG,
1113          "Transmission failed %u times, trying again in %s.\n",
1114          MAX_ATTEMPTS - th->attempts_left,
1115          GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES));
1116     GNUNET_assert (NULL == th->th);
1117     GNUNET_assert (NULL == th->reconnect_task);
1118     th->reconnect_task =
1119         GNUNET_SCHEDULER_add_delayed (delay, &client_delayed_retry, th);
1120     return;
1121   }
1122   th->th =
1123       GNUNET_CONNECTION_notify_transmit_ready (th->client->connection, th->size,
1124                                                GNUNET_TIME_absolute_get_remaining
1125                                                (th->timeout), &client_notify,
1126                                                th);
1127   if (NULL == th->th)
1128   {
1129     GNUNET_break (0);
1130     th->client->th = NULL;
1131     th->notify (th->notify_cls, 0, NULL);
1132     GNUNET_free (th);
1133     return;
1134   }
1135 }
1136
1137
1138 /**
1139  * Connection notifies us about failure or success of a transmission
1140  * request.  Either pass it on to our user or, if possible, retry.
1141  *
1142  * @param cls our `struct GNUNET_CLIENT_TransmissionHandle`
1143  * @param size number of bytes available for transmission
1144  * @param buf where to write them
1145  * @return number of bytes written to @a buf
1146  */
1147 static size_t
1148 client_notify (void *cls,
1149                size_t size,
1150                void *buf)
1151 {
1152   struct GNUNET_CLIENT_TransmitHandle *th = cls;
1153   struct GNUNET_CLIENT_Connection *client = th->client;
1154   size_t ret;
1155   struct GNUNET_TIME_Relative delay;
1156
1157   LOG (GNUNET_ERROR_TYPE_DEBUG,
1158        "client_notify is running\n");
1159   th->th = NULL;
1160   client->th = NULL;
1161   if (NULL == buf)
1162   {
1163     delay = GNUNET_TIME_absolute_get_remaining (th->timeout);
1164     delay.rel_value_us /= 2;
1165     if ( (GNUNET_YES != th->auto_retry) ||
1166          (0 == --th->attempts_left) ||
1167          (delay.rel_value_us < 1)||
1168          (0 != (GNUNET_SCHEDULER_get_reason() & GNUNET_SCHEDULER_REASON_SHUTDOWN)))
1169     {
1170       LOG (GNUNET_ERROR_TYPE_DEBUG,
1171            "Transmission failed %u times, giving up.\n",
1172            MAX_ATTEMPTS - th->attempts_left);
1173       GNUNET_break (0 ==
1174                     th->notify (th->notify_cls, 0, NULL));
1175       GNUNET_free (th);
1176       return 0;
1177     }
1178     /* auto-retry */
1179     LOG (GNUNET_ERROR_TYPE_DEBUG,
1180          "Failed to connect to `%s', automatically trying again.\n",
1181          client->service_name);
1182     if (GNUNET_YES == client->in_receive)
1183     {
1184       GNUNET_CONNECTION_receive_cancel (client->connection);
1185       client->in_receive = GNUNET_NO;
1186     }
1187     GNUNET_CONNECTION_destroy (client->connection);
1188     client->connection = NULL;
1189     delay = GNUNET_TIME_relative_min (delay, client->back_off);
1190     client->back_off =
1191         GNUNET_TIME_relative_min (GNUNET_TIME_relative_multiply
1192                                   (client->back_off, 2),
1193                                   GNUNET_TIME_UNIT_SECONDS);
1194     LOG (GNUNET_ERROR_TYPE_DEBUG,
1195          "Transmission failed %u times, trying again in %s.\n",
1196          MAX_ATTEMPTS - th->attempts_left,
1197          GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES));
1198     client->th = th;
1199     GNUNET_assert (NULL == th->reconnect_task);
1200     GNUNET_assert (NULL == th->th);
1201     th->reconnect_task =
1202         GNUNET_SCHEDULER_add_delayed (delay, &client_delayed_retry, th);
1203     return 0;
1204   }
1205   GNUNET_assert (size >= th->size);
1206   ret = th->notify (th->notify_cls, size, buf);
1207   GNUNET_free (th);
1208   if (sizeof (struct GNUNET_MessageHeader) <= ret)
1209   {
1210     LOG (GNUNET_ERROR_TYPE_DEBUG,
1211          "Transmitting message of type %u and size %u to %s service.\n",
1212          ntohs (((struct GNUNET_MessageHeader *) buf)->type),
1213          ntohs (((struct GNUNET_MessageHeader *) buf)->size),
1214          client->service_name);
1215   }
1216   return ret;
1217 }
1218
1219
1220 /**
1221  * Ask the client to call us once the specified number of bytes
1222  * are free in the transmission buffer.  Will never call the @a notify
1223  * callback in this task, but always first go into the scheduler.
1224  *
1225  * @param client connection to the service
1226  * @param size number of bytes to send
1227  * @param timeout after how long should we give up (and call
1228  *        notify with buf NULL and size 0)?
1229  * @param auto_retry if the connection to the service dies, should we
1230  *        automatically re-connect and retry (within the timeout period)
1231  *        or should we immediately fail in this case?  Pass GNUNET_YES
1232  *        if the caller does not care about temporary connection errors,
1233  *        for example because the protocol is stateless
1234  * @param notify function to call
1235  * @param notify_cls closure for @a notify
1236  * @return NULL if our buffer will never hold size bytes,
1237  *         a handle if the notify callback was queued (can be used to cancel)
1238  */
1239 struct GNUNET_CLIENT_TransmitHandle *
1240 GNUNET_CLIENT_notify_transmit_ready (struct GNUNET_CLIENT_Connection *client,
1241                                      size_t size,
1242                                      struct GNUNET_TIME_Relative timeout,
1243                                      int auto_retry,
1244                                      GNUNET_CONNECTION_TransmitReadyNotify notify,
1245                                      void *notify_cls)
1246 {
1247   struct GNUNET_CLIENT_TransmitHandle *th;
1248
1249   if (NULL != client->th)
1250   {
1251     /* If this breaks, you most likley called this function twice without waiting
1252      * for completion or canceling the request */
1253     GNUNET_assert (0);
1254     return NULL;
1255   }
1256   th = GNUNET_new (struct GNUNET_CLIENT_TransmitHandle);
1257   th->client = client;
1258   th->size = size;
1259   th->timeout = GNUNET_TIME_relative_to_absolute (timeout);
1260   /* always auto-retry on first message to service */
1261   th->auto_retry = (GNUNET_YES == client->first_message) ? GNUNET_YES : auto_retry;
1262   client->first_message = GNUNET_NO;
1263   th->notify = notify;
1264   th->notify_cls = notify_cls;
1265   th->attempts_left = MAX_ATTEMPTS;
1266   client->th = th;
1267   if (NULL == client->connection)
1268   {
1269     GNUNET_assert (NULL == th->th);
1270     GNUNET_assert (NULL == th->reconnect_task);
1271     th->reconnect_task =
1272         GNUNET_SCHEDULER_add_delayed (client->back_off,
1273                                       &client_delayed_retry,
1274                                       th);
1275   }
1276   else
1277   {
1278     th->th = GNUNET_CONNECTION_notify_transmit_ready (client->connection,
1279                                                       size,
1280                                                       timeout,
1281                                                       &client_notify,
1282                                                       th);
1283     if (NULL == th->th)
1284     {
1285       GNUNET_break (0);
1286       GNUNET_free (th);
1287       client->th = NULL;
1288       return NULL;
1289     }
1290   }
1291   return th;
1292 }
1293
1294
1295 /**
1296  * Cancel a request for notification.
1297  *
1298  * @param th handle from the original request.
1299  */
1300 void
1301 GNUNET_CLIENT_notify_transmit_ready_cancel (struct GNUNET_CLIENT_TransmitHandle *th)
1302 {
1303   if (NULL != th->reconnect_task)
1304   {
1305     GNUNET_assert (NULL == th->th);
1306     GNUNET_SCHEDULER_cancel (th->reconnect_task);
1307     th->reconnect_task = NULL;
1308   }
1309   else
1310   {
1311     GNUNET_assert (NULL != th->th);
1312     GNUNET_CONNECTION_notify_transmit_ready_cancel (th->th);
1313   }
1314   th->client->th = NULL;
1315   GNUNET_free (th);
1316 }
1317
1318
1319 /**
1320  * Function called to notify a client about the socket
1321  * begin ready to queue the message.  @a buf will be
1322  * NULL and @a size zero if the socket was closed for
1323  * writing in the meantime.
1324  *
1325  * @param cls closure of type `struct TransmitGetResponseContext *`
1326  * @param size number of bytes available in @a buf
1327  * @param buf where the callee should write the message
1328  * @return number of bytes written to @a buf
1329  */
1330 static size_t
1331 transmit_for_response (void *cls,
1332                        size_t size,
1333                        void *buf)
1334 {
1335   struct TransmitGetResponseContext *tc = cls;
1336   uint16_t msize;
1337
1338   tc->client->tag = NULL;
1339   msize = ntohs (tc->hdr->size);
1340   if (NULL == buf)
1341   {
1342     LOG (GNUNET_ERROR_TYPE_DEBUG,
1343          "Could not submit request, not expecting to receive a response.\n");
1344     if (NULL != tc->rn)
1345       tc->rn (tc->rn_cls, NULL);
1346     GNUNET_free (tc);
1347     return 0;
1348   }
1349   GNUNET_assert (size >= msize);
1350   memcpy (buf, tc->hdr, msize);
1351   GNUNET_CLIENT_receive (tc->client,
1352                          tc->rn,
1353                          tc->rn_cls,
1354                          GNUNET_TIME_absolute_get_remaining (tc->timeout));
1355   GNUNET_free (tc);
1356   return msize;
1357 }
1358
1359
1360 /**
1361  * Convenience API that combines sending a request
1362  * to the service and waiting for a response.
1363  * If either operation times out, the callback
1364  * will be called with a "NULL" response (in which
1365  * case the connection should probably be destroyed).
1366  *
1367  * @param client connection to use
1368  * @param hdr message to transmit
1369  * @param timeout when to give up (for both transmission
1370  *         and for waiting for a response)
1371  * @param auto_retry if the connection to the service dies, should we
1372  *        automatically re-connect and retry (within the timeout period)
1373  *        or should we immediately fail in this case?  Pass GNUNET_YES
1374  *        if the caller does not care about temporary connection errors,
1375  *        for example because the protocol is stateless
1376  * @param rn function to call with the response
1377  * @param rn_cls closure for @a rn
1378  * @return #GNUNET_OK on success, #GNUNET_SYSERR if a request
1379  *         is already pending
1380  */
1381 int
1382 GNUNET_CLIENT_transmit_and_get_response (struct GNUNET_CLIENT_Connection *client,
1383                                          const struct GNUNET_MessageHeader *hdr,
1384                                          struct GNUNET_TIME_Relative timeout,
1385                                          int auto_retry,
1386                                          GNUNET_CLIENT_MessageHandler rn,
1387                                          void *rn_cls)
1388 {
1389   struct TransmitGetResponseContext *tc;
1390   uint16_t msize;
1391
1392   if (NULL != client->th)
1393     return GNUNET_SYSERR;
1394   GNUNET_assert (NULL == client->tag);
1395   msize = ntohs (hdr->size);
1396   tc = GNUNET_malloc (sizeof (struct TransmitGetResponseContext) + msize);
1397   tc->client = client;
1398   tc->hdr = (const struct GNUNET_MessageHeader *) &tc[1];
1399   memcpy (&tc[1], hdr, msize);
1400   tc->timeout = GNUNET_TIME_relative_to_absolute (timeout);
1401   tc->rn = rn;
1402   tc->rn_cls = rn_cls;
1403   if (NULL ==
1404       GNUNET_CLIENT_notify_transmit_ready (client, msize, timeout, auto_retry,
1405                                            &transmit_for_response, tc))
1406   {
1407     GNUNET_break (0);
1408     GNUNET_free (tc);
1409     return GNUNET_SYSERR;
1410   }
1411   client->tag = tc;
1412   return GNUNET_OK;
1413 }
1414
1415
1416 /*  end of client.c */