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