-rps: logging
[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  */
583 static void
584 receive_task (void *cls)
585 {
586   struct GNUNET_CLIENT_Connection *client = cls;
587   GNUNET_CLIENT_MessageHandler handler = client->receiver_handler;
588   const struct GNUNET_MessageHeader *cmsg =
589       (const struct GNUNET_MessageHeader *) client->received_buf;
590   void *handler_cls = client->receiver_handler_cls;
591   uint16_t msize = ntohs (cmsg->size);
592   char mbuf[msize] GNUNET_ALIGN;
593   struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) mbuf;
594
595   client->receive_task = NULL;
596   if ( (GNUNET_SYSERR == client->in_receive) &&
597        (GNUNET_YES != client->msg_complete) )
598   {
599     /* Connection failure, signal to caller! */
600     client->receiver_handler = NULL;
601     if (NULL != handler)
602       handler (handler_cls,
603                NULL);
604     return;
605   }
606   LOG (GNUNET_ERROR_TYPE_DEBUG,
607        "Received message of type %u and size %u from %s service.\n",
608        ntohs (cmsg->type),
609        msize,
610        client->service_name);
611   GNUNET_assert (GNUNET_YES == client->msg_complete);
612   GNUNET_assert (client->received_pos >= msize);
613   memcpy (msg, cmsg, msize);
614   memmove (client->received_buf,
615            &client->received_buf[msize],
616            client->received_pos - msize);
617   client->received_pos -= msize;
618   client->msg_complete = GNUNET_NO;
619   client->receiver_handler = NULL;
620   check_complete (client);
621   if (NULL != handler)
622     handler (handler_cls, msg);
623 }
624
625
626 /**
627  * Read from the service.
628  *
629  * @param client the service
630  * @param handler function to call with the message
631  * @param handler_cls closure for @a handler
632  * @param timeout how long to wait until timing out
633  */
634 void
635 GNUNET_CLIENT_receive (struct GNUNET_CLIENT_Connection *client,
636                        GNUNET_CLIENT_MessageHandler handler,
637                        void *handler_cls,
638                        struct GNUNET_TIME_Relative timeout)
639 {
640   if (NULL == client->connection)
641   {
642     /* already disconnected, fail instantly! */
643     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
644                 "Client API violation for service `%s'\n",
645                 client->service_name);
646     GNUNET_break (0);           /* this should not happen in well-written code! */
647     if (NULL != handler)
648       handler (handler_cls,
649                NULL);
650     return;
651   }
652   client->receiver_handler = handler;
653   client->receiver_handler_cls = handler_cls;
654   client->receive_timeout = GNUNET_TIME_relative_to_absolute (timeout);
655   if ( (GNUNET_YES == client->msg_complete) ||
656        (GNUNET_SYSERR == client->in_receive) )
657   {
658     GNUNET_assert (NULL == client->receive_task);
659     client->receive_task = GNUNET_SCHEDULER_add_now (&receive_task,
660                                                      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  */
750 static void
751 report_result (void *cls)
752 {
753   struct GNUNET_CLIENT_TestHandle *th = cls;
754
755   th->task = NULL;
756   th->cb (th->cb_cls, th->result);
757   GNUNET_CLIENT_service_test_cancel (th);
758 }
759
760
761 /**
762  * Report service test result asynchronously back to callback.
763  *
764  * @param th test handle with the result and the callback
765  * @param result result to report
766  */
767 static void
768 service_test_report (struct GNUNET_CLIENT_TestHandle *th,
769                      int result)
770 {
771   th->result = result;
772   th->task = GNUNET_SCHEDULER_add_now (&report_result,
773                                        th);
774 }
775
776
777 /**
778  * Receive confirmation from test, service is up.
779  *
780  * @param cls closure with the `struct GNUNET_CLIENT_TestHandle`
781  * @param msg message received, NULL on timeout or fatal error
782  */
783 static void
784 confirm_handler (void *cls,
785                  const struct GNUNET_MessageHeader *msg)
786 {
787   struct GNUNET_CLIENT_TestHandle *th = cls;
788
789   /* We may want to consider looking at the reply in more
790    * detail in the future, for example, is this the
791    * correct service? FIXME! */
792   if (NULL != msg)
793   {
794     LOG (GNUNET_ERROR_TYPE_DEBUG,
795          "Received confirmation that service is running.\n");
796     service_test_report (th, GNUNET_YES);
797   }
798   else
799   {
800     service_test_report (th, GNUNET_NO);
801   }
802 }
803
804
805 /**
806  * Send the 'TEST' message to the service.  If successful, prepare to
807  * receive the reply.
808  *
809  * @param cls the `struct GNUNET_CLIENT_TestHandle` of the test
810  * @param size number of bytes available in @a buf
811  * @param buf where to write the message
812  * @return number of bytes written to @a buf
813  */
814 static size_t
815 write_test (void *cls, size_t size, void *buf)
816 {
817   struct GNUNET_CLIENT_TestHandle *th = cls;
818   struct GNUNET_MessageHeader *msg;
819
820   th->th = NULL;
821   if (size < sizeof (struct GNUNET_MessageHeader))
822   {
823     LOG (GNUNET_ERROR_TYPE_DEBUG,
824          "Failed to transmit TEST request.\n");
825     service_test_report (th, GNUNET_NO);
826     return 0;                   /* client disconnected */
827   }
828   LOG (GNUNET_ERROR_TYPE_DEBUG,
829        "Transmitting `%s' request.\n",
830        "TEST");
831   msg = (struct GNUNET_MessageHeader *) buf;
832   msg->type = htons (GNUNET_MESSAGE_TYPE_TEST);
833   msg->size = htons (sizeof (struct GNUNET_MessageHeader));
834   GNUNET_CLIENT_receive (th->client,
835                          &confirm_handler, th,
836                          GNUNET_TIME_absolute_get_remaining
837                          (th->test_deadline));
838   return sizeof (struct GNUNET_MessageHeader);
839 }
840
841
842 /**
843  * Test if the service is running.  If we are given a UNIXPATH or a
844  * local address, we do this NOT by trying to connect to the service,
845  * but by trying to BIND to the same port.  If the BIND fails, we know
846  * the service is running.
847  *
848  * @param service name of the service to wait for
849  * @param cfg configuration to use
850  * @param timeout how long to wait at most
851  * @param cb function to call with the result
852  * @param cb_cls closure for @a cb
853  * @return handle to cancel the test
854  */
855 struct GNUNET_CLIENT_TestHandle *
856 GNUNET_CLIENT_service_test (const char *service,
857                             const struct GNUNET_CONFIGURATION_Handle *cfg,
858                             struct GNUNET_TIME_Relative timeout,
859                             GNUNET_CLIENT_TestResultCallback cb,
860                             void *cb_cls)
861 {
862   struct GNUNET_CLIENT_TestHandle *th;
863   char *hostname;
864   unsigned long long port;
865   struct GNUNET_NETWORK_Handle *sock;
866
867   th = GNUNET_new (struct GNUNET_CLIENT_TestHandle);
868   th->cb = cb;
869   th->cb_cls = cb_cls;
870   th->test_deadline = GNUNET_TIME_relative_to_absolute (timeout);
871   LOG (GNUNET_ERROR_TYPE_DEBUG,
872        "Testing if service `%s' is running.\n",
873        service);
874 #ifdef AF_UNIX
875   {
876     /* probe UNIX support */
877     struct sockaddr_un s_un;
878     char *unixpath;
879     int abstract;
880
881     unixpath = NULL;
882     if ((GNUNET_OK ==
883          GNUNET_CONFIGURATION_get_value_filename (cfg,
884                                                   service,
885                                                   "UNIXPATH",
886                                                   &unixpath)) &&
887         (0 < strlen (unixpath)))  /* We have a non-NULL unixpath, does that mean it's valid? */
888     {
889       if (strlen (unixpath) >= sizeof (s_un.sun_path))
890       {
891         LOG (GNUNET_ERROR_TYPE_WARNING,
892              _("UNIXPATH `%s' too long, maximum length is %llu\n"),
893              unixpath,
894              (unsigned long long) sizeof (s_un.sun_path));
895         unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
896         LOG (GNUNET_ERROR_TYPE_INFO,
897              _("Using `%s' instead\n"), unixpath);
898       }
899     }
900 #ifdef LINUX
901     abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg,
902                                                      "TESTING",
903                                                      "USE_ABSTRACT_SOCKETS");
904 #else
905     abstract = GNUNET_NO;
906 #endif
907     if ((NULL != unixpath) && (GNUNET_YES != abstract))
908     {
909       if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (unixpath))
910         GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
911                                   "mkdir", unixpath);
912     }
913     if (NULL != unixpath)
914     {
915       sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0);
916       if (NULL != sock)
917       {
918         memset (&s_un, 0, sizeof (s_un));
919         s_un.sun_family = AF_UNIX;
920         strncpy (s_un.sun_path, unixpath, sizeof (s_un.sun_path) - 1);
921         if (GNUNET_YES == abstract)
922           s_un.sun_path[0] = '\0';
923 #if HAVE_SOCKADDR_IN_SIN_LEN
924         s_un.sun_len = (u_char) sizeof (struct sockaddr_un);
925 #endif
926         if (GNUNET_OK !=
927             GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_un,
928                                         sizeof (struct sockaddr_un)))
929         {
930           /* failed to bind => service must be running */
931           GNUNET_free (unixpath);
932           (void) GNUNET_NETWORK_socket_close (sock);
933           service_test_report (th, GNUNET_YES);
934           return th;
935         }
936         (void) GNUNET_NETWORK_socket_close (sock);
937         /* let's try IP */
938       }
939     }
940     GNUNET_free_non_null (unixpath);
941   }
942 #endif
943
944   hostname = NULL;
945   if ((GNUNET_OK !=
946        GNUNET_CONFIGURATION_get_value_number (cfg, service, "PORT", &port)) ||
947       (port > 65535) ||
948       (GNUNET_OK !=
949        GNUNET_CONFIGURATION_get_value_string (cfg, service, "HOSTNAME",
950                                               &hostname)))
951   {
952     /* UNIXPATH failed (if possible) AND IP failed => error */
953     service_test_report (th, GNUNET_SYSERR);
954     return th;
955   }
956
957   if (0 == strcmp ("localhost", hostname)
958 #if !LINUX
959       && 0
960 #endif
961       )
962   {
963     /* can test using 'bind' */
964     struct sockaddr_in s_in;
965
966     memset (&s_in, 0, sizeof (s_in));
967 #if HAVE_SOCKADDR_IN_SIN_LEN
968     s_in.sin_len = sizeof (struct sockaddr_in);
969 #endif
970     s_in.sin_family = AF_INET;
971     s_in.sin_port = htons (port);
972
973     sock = GNUNET_NETWORK_socket_create (AF_INET, SOCK_STREAM, 0);
974     if (NULL != sock)
975     {
976       if (GNUNET_OK !=
977           GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_in,
978                                       sizeof (s_in)))
979       {
980         /* failed to bind => service must be running */
981         GNUNET_free (hostname);
982         (void) GNUNET_NETWORK_socket_close (sock);
983         service_test_report (th, GNUNET_YES);
984         return th;
985       }
986       (void) GNUNET_NETWORK_socket_close (sock);
987     }
988   }
989
990   if (0 == strcmp ("ip6-localhost", hostname)
991 #if !LINUX
992       && 0
993 #endif
994       )
995   {
996     /* can test using 'bind' */
997     struct sockaddr_in6 s_in6;
998
999     memset (&s_in6, 0, sizeof (s_in6));
1000 #if HAVE_SOCKADDR_IN_SIN_LEN
1001     s_in6.sin6_len = sizeof (struct sockaddr_in6);
1002 #endif
1003     s_in6.sin6_family = AF_INET6;
1004     s_in6.sin6_port = htons (port);
1005
1006     sock = GNUNET_NETWORK_socket_create (AF_INET6, SOCK_STREAM, 0);
1007     if (NULL != sock)
1008     {
1009       if (GNUNET_OK !=
1010           GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_in6,
1011                                       sizeof (s_in6)))
1012       {
1013         /* failed to bind => service must be running */
1014         GNUNET_free (hostname);
1015         (void) GNUNET_NETWORK_socket_close (sock);
1016         service_test_report (th, GNUNET_YES);
1017         return th;
1018       }
1019       (void) GNUNET_NETWORK_socket_close (sock);
1020     }
1021   }
1022
1023   if (((0 == strcmp ("localhost", hostname)) ||
1024        (0 == strcmp ("ip6-localhost", hostname)))
1025 #if !LINUX
1026       && 0
1027 #endif
1028       )
1029   {
1030     /* all binds succeeded => claim service not running right now */
1031     GNUNET_free_non_null (hostname);
1032     service_test_report (th, GNUNET_NO);
1033     return th;
1034   }
1035   GNUNET_free_non_null (hostname);
1036
1037   /* non-localhost, try 'connect' method */
1038   th->client = GNUNET_CLIENT_connect (service, cfg);
1039   if (NULL == th->client)
1040   {
1041     LOG (GNUNET_ERROR_TYPE_INFO,
1042          _("Could not connect to service `%s', configuration broken.\n"),
1043          service);
1044     service_test_report (th, GNUNET_SYSERR);
1045     return th;
1046   }
1047   th->th = GNUNET_CLIENT_notify_transmit_ready (th->client,
1048                                                 sizeof (struct GNUNET_MessageHeader),
1049                                                 timeout, GNUNET_YES,
1050                                                 &write_test, th);
1051   if (NULL == th->th)
1052   {
1053     LOG (GNUNET_ERROR_TYPE_WARNING,
1054          _("Failure to transmit request to service `%s'\n"), service);
1055     service_test_report (th, GNUNET_SYSERR);
1056     return th;
1057   }
1058   return th;
1059 }
1060
1061
1062 /**
1063  * Connection notifies us about failure or success of
1064  * a transmission request.  Either pass it on to our
1065  * user or, if possible, retry.
1066  *
1067  * @param cls our `struct GNUNET_CLIENT_TransmissionHandle`
1068  * @param size number of bytes available for transmission
1069  * @param buf where to write them
1070  * @return number of bytes written to @a buf
1071  */
1072 static size_t
1073 client_notify (void *cls, size_t size, void *buf);
1074
1075
1076 /**
1077  * This task is run if we should re-try connection to the
1078  * service after a while.
1079  *
1080  * @param cls our `struct GNUNET_CLIENT_TransmitHandle` of the request
1081  */
1082 static void
1083 client_delayed_retry (void *cls)
1084 {
1085   struct GNUNET_CLIENT_TransmitHandle *th = cls;
1086   struct GNUNET_TIME_Relative delay;
1087
1088   th->reconnect_task = NULL;
1089   th->client->connection =
1090     do_connect (th->client->service_name,
1091                 th->client->cfg,
1092                 th->client->attempts++);
1093   th->client->first_message = GNUNET_YES;
1094   if (NULL == th->client->connection)
1095   {
1096     /* could happen if we're out of sockets */
1097     delay = GNUNET_TIME_relative_min (GNUNET_TIME_absolute_get_remaining (th->timeout),
1098                                       th->client->back_off);
1099     th->client->back_off = GNUNET_TIME_STD_BACKOFF (th->client->back_off);
1100     LOG (GNUNET_ERROR_TYPE_DEBUG,
1101          "Transmission failed %u times, trying again in %s.\n",
1102          MAX_ATTEMPTS - th->attempts_left,
1103          GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES));
1104     GNUNET_assert (NULL == th->th);
1105     GNUNET_assert (NULL == th->reconnect_task);
1106     th->reconnect_task =
1107         GNUNET_SCHEDULER_add_delayed (delay,
1108                                       &client_delayed_retry,
1109                                       th);
1110     return;
1111   }
1112   th->th =
1113       GNUNET_CONNECTION_notify_transmit_ready (th->client->connection, th->size,
1114                                                GNUNET_TIME_absolute_get_remaining
1115                                                (th->timeout),
1116                                                &client_notify,
1117                                                th);
1118   if (NULL == th->th)
1119   {
1120     GNUNET_break (0);
1121     th->client->th = NULL;
1122     th->notify (th->notify_cls, 0, NULL);
1123     GNUNET_free (th);
1124     return;
1125   }
1126 }
1127
1128
1129 /**
1130  * Connection notifies us about failure or success of a transmission
1131  * request.  Either pass it on to our user or, if possible, retry.
1132  *
1133  * @param cls our `struct GNUNET_CLIENT_TransmissionHandle`
1134  * @param size number of bytes available for transmission
1135  * @param buf where to write them
1136  * @return number of bytes written to @a buf
1137  */
1138 static size_t
1139 client_notify (void *cls,
1140                size_t size,
1141                void *buf)
1142 {
1143   struct GNUNET_CLIENT_TransmitHandle *th = cls;
1144   struct GNUNET_CLIENT_Connection *client = th->client;
1145   size_t ret;
1146   struct GNUNET_TIME_Relative delay;
1147
1148   LOG (GNUNET_ERROR_TYPE_DEBUG,
1149        "client_notify is running\n");
1150   th->th = NULL;
1151   client->th = NULL;
1152   if (NULL == buf)
1153   {
1154     delay = GNUNET_TIME_absolute_get_remaining (th->timeout);
1155     delay.rel_value_us /= 2;
1156     if ( (GNUNET_YES != th->auto_retry) ||
1157          (0 == --th->attempts_left) ||
1158          (delay.rel_value_us < 1) )
1159     {
1160       LOG (GNUNET_ERROR_TYPE_DEBUG,
1161            "Transmission failed %u times, giving up.\n",
1162            MAX_ATTEMPTS - th->attempts_left);
1163       GNUNET_break (0 ==
1164                     th->notify (th->notify_cls, 0, NULL));
1165       GNUNET_free (th);
1166       return 0;
1167     }
1168     /* auto-retry */
1169     LOG (GNUNET_ERROR_TYPE_DEBUG,
1170          "Failed to connect to `%s', automatically trying again.\n",
1171          client->service_name);
1172     if (GNUNET_YES == client->in_receive)
1173     {
1174       GNUNET_CONNECTION_receive_cancel (client->connection);
1175       client->in_receive = GNUNET_NO;
1176     }
1177     GNUNET_CONNECTION_destroy (client->connection);
1178     client->connection = NULL;
1179     delay = GNUNET_TIME_relative_min (delay, client->back_off);
1180     client->back_off =
1181         GNUNET_TIME_relative_min (GNUNET_TIME_relative_multiply
1182                                   (client->back_off, 2),
1183                                   GNUNET_TIME_UNIT_SECONDS);
1184     LOG (GNUNET_ERROR_TYPE_DEBUG,
1185          "Transmission failed %u times, trying again in %s.\n",
1186          MAX_ATTEMPTS - th->attempts_left,
1187          GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES));
1188     client->th = th;
1189     GNUNET_assert (NULL == th->reconnect_task);
1190     GNUNET_assert (NULL == th->th);
1191     th->reconnect_task =
1192         GNUNET_SCHEDULER_add_delayed (delay,
1193                                       &client_delayed_retry,
1194                                       th);
1195     return 0;
1196   }
1197   GNUNET_assert (size >= th->size);
1198   ret = th->notify (th->notify_cls, size, buf);
1199   GNUNET_free (th);
1200   if (sizeof (struct GNUNET_MessageHeader) <= ret)
1201   {
1202     LOG (GNUNET_ERROR_TYPE_DEBUG,
1203          "Transmitting message of type %u and size %u to %s service.\n",
1204          ntohs (((struct GNUNET_MessageHeader *) buf)->type),
1205          ntohs (((struct GNUNET_MessageHeader *) buf)->size),
1206          client->service_name);
1207   }
1208   return ret;
1209 }
1210
1211
1212 /**
1213  * Ask the client to call us once the specified number of bytes
1214  * are free in the transmission buffer.  Will never call the @a notify
1215  * callback in this task, but always first go into the scheduler.
1216  *
1217  * @param client connection to the service
1218  * @param size number of bytes to send
1219  * @param timeout after how long should we give up (and call
1220  *        notify with buf NULL and size 0)?
1221  * @param auto_retry if the connection to the service dies, should we
1222  *        automatically re-connect and retry (within the timeout period)
1223  *        or should we immediately fail in this case?  Pass GNUNET_YES
1224  *        if the caller does not care about temporary connection errors,
1225  *        for example because the protocol is stateless
1226  * @param notify function to call
1227  * @param notify_cls closure for @a notify
1228  * @return NULL if our buffer will never hold size bytes,
1229  *         a handle if the notify callback was queued (can be used to cancel)
1230  */
1231 struct GNUNET_CLIENT_TransmitHandle *
1232 GNUNET_CLIENT_notify_transmit_ready (struct GNUNET_CLIENT_Connection *client,
1233                                      size_t size,
1234                                      struct GNUNET_TIME_Relative timeout,
1235                                      int auto_retry,
1236                                      GNUNET_CONNECTION_TransmitReadyNotify notify,
1237                                      void *notify_cls)
1238 {
1239   struct GNUNET_CLIENT_TransmitHandle *th;
1240
1241   if (NULL != client->th)
1242   {
1243     /* If this breaks, you most likley called this function twice without waiting
1244      * for completion or canceling the request */
1245     GNUNET_assert (0);
1246     return NULL;
1247   }
1248   th = GNUNET_new (struct GNUNET_CLIENT_TransmitHandle);
1249   th->client = client;
1250   th->size = size;
1251   th->timeout = GNUNET_TIME_relative_to_absolute (timeout);
1252   /* always auto-retry on first message to service */
1253   th->auto_retry = (GNUNET_YES == client->first_message) ? GNUNET_YES : auto_retry;
1254   client->first_message = GNUNET_NO;
1255   th->notify = notify;
1256   th->notify_cls = notify_cls;
1257   th->attempts_left = MAX_ATTEMPTS;
1258   client->th = th;
1259   if (NULL == client->connection)
1260   {
1261     GNUNET_assert (NULL == th->th);
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 */