2 This file is part of GNUnet.
3 Copyright (C) 2001-2013 GNUnet e.V.
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.
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.
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.
23 * @brief code for access to services
24 * @author Christian Grothoff
26 * Generic TCP code for reliable, record-oriented TCP
27 * connections between clients and service providers.
30 #include "gnunet_protocols.h"
31 #include "gnunet_util_lib.h"
32 #include "gnunet_socks.h"
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.
40 #define MAX_ATTEMPTS 50
42 #define LOG(kind,...) GNUNET_log_from (kind, "util",__VA_ARGS__)
45 * Handle for a transmission request.
47 struct GNUNET_CLIENT_TransmitHandle
52 struct GNUNET_CLIENT_Connection *client;
55 * Function to call to get the data for transmission.
57 GNUNET_CONNECTION_TransmitReadyNotify notify;
60 * Closure for @e notify.
65 * Handle to the transmission with the underlying
68 struct GNUNET_CONNECTION_TransmitHandle *th;
71 * If we are re-trying and are delaying to do so,
72 * handle to the scheduled task managing the delay.
74 struct GNUNET_SCHEDULER_Task *reconnect_task;
77 * Timeout for the operation overall.
79 struct GNUNET_TIME_Absolute timeout;
82 * Number of bytes requested.
87 * Are we allowed to re-try to connect without telling
88 * the user (of this API) about the connection troubles?
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).
98 unsigned int attempts_left;
104 * Struct to refer to a GNUnet TCP connection.
105 * This is more than just a socket because if the server
106 * drops the connection, the client automatically tries
107 * to reconnect (and for that needs connection information).
109 struct GNUNET_CLIENT_Connection
113 * The connection handle, NULL if not live
115 struct GNUNET_CONNECTION_Handle *connection;
120 const struct GNUNET_CONFIGURATION_Handle *cfg;
123 * Name of the service we interact with.
128 * Handler for current receiver task.
130 GNUNET_CLIENT_MessageHandler receiver_handler;
133 * Closure for @e receiver_handler.
135 void *receiver_handler_cls;
138 * Handle for a pending transmission request, NULL if there is
141 struct GNUNET_CLIENT_TransmitHandle *th;
144 * If we are re-trying and are delaying to do so,
145 * handle to the scheduled task managing the delay.
147 struct GNUNET_SCHEDULER_Task * receive_task;
150 * Buffer for received message.
155 * Timeout for receiving a response (absolute time).
157 struct GNUNET_TIME_Absolute receive_timeout;
160 * Current value for our incremental back-off (for
163 struct GNUNET_TIME_Relative back_off;
166 * Number of bytes in received_buf that are valid.
171 * Size of received_buf.
173 unsigned int received_size;
176 * Do we have a complete response in received_buf?
181 * Are we currently busy doing receive-processing?
182 * #GNUNET_YES if so, #GNUNET_NO if not. #GNUNET_SYSERR
183 * if the connection has failed (but we may not have
184 * closed the handle itself yet).
189 * Is this the first message we are sending to the service?
194 * How often have we tried to connect?
196 unsigned int attempts;
202 * Try connecting to the server using UNIX domain sockets.
204 * @param service_name name of service to connect to
205 * @param cfg configuration to use
206 * @return NULL on error, connection to UNIX otherwise
208 static struct GNUNET_CONNECTION_Handle *
209 try_unixpath (const char *service_name,
210 const struct GNUNET_CONFIGURATION_Handle *cfg)
213 struct GNUNET_CONNECTION_Handle *connection;
215 struct sockaddr_un s_un;
218 if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg, service_name, "UNIXPATH", &unixpath)) &&
219 (0 < strlen (unixpath)))
221 /* We have a non-NULL unixpath, need to validate it */
222 if (strlen (unixpath) >= sizeof (s_un.sun_path))
224 LOG (GNUNET_ERROR_TYPE_WARNING,
225 _("UNIXPATH `%s' too long, maximum length is %llu\n"), unixpath,
226 (unsigned long long) sizeof (s_un.sun_path));
227 unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
228 LOG (GNUNET_ERROR_TYPE_INFO,
229 _("Using `%s' instead\n"), unixpath);
230 if (NULL == unixpath)
233 connection = GNUNET_CONNECTION_create_from_connect_to_unixpath (cfg, unixpath);
234 if (NULL != connection)
236 LOG (GNUNET_ERROR_TYPE_DEBUG, "Connected to unixpath `%s'!\n",
238 GNUNET_free (unixpath);
242 GNUNET_free_non_null (unixpath);
249 * Test whether the configuration has proper values for connection
250 * (UNIXPATH || (PORT && HOSTNAME)).
252 * @param service_name name of service to connect to
253 * @param cfg configuration to use
254 * @return #GNUNET_OK if the configuration is valid, #GNUNET_SYSERR if not
257 test_service_configuration (const char *service_name,
258 const struct GNUNET_CONFIGURATION_Handle *cfg)
260 int ret = GNUNET_SYSERR;
261 char *hostname = NULL;
262 unsigned long long port;
264 char *unixpath = NULL;
266 if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg, service_name, "UNIXPATH", &unixpath)) &&
267 (0 < strlen (unixpath)))
269 GNUNET_free_non_null (unixpath);
273 GNUNET_CONFIGURATION_have_value (cfg, service_name, "PORT")) &&
275 GNUNET_CONFIGURATION_get_value_number (cfg, service_name, "PORT", &port)) &&
276 (port <= 65535) && (0 != port) &&
278 GNUNET_CONFIGURATION_get_value_string (cfg, service_name, "HOSTNAME",
280 (0 != strlen (hostname)) )
282 GNUNET_free_non_null (hostname);
288 * Try to connect to the service.
290 * @param service_name name of service to connect to
291 * @param cfg configuration to use
292 * @param attempt counter used to alternate between IP and UNIX domain sockets
293 * @return NULL on error
295 static struct GNUNET_CONNECTION_Handle *
296 do_connect (const char *service_name,
297 const struct GNUNET_CONFIGURATION_Handle *cfg,
298 unsigned int attempt)
300 struct GNUNET_CONNECTION_Handle *connection;
302 unsigned long long port;
304 /* Never use a local source if a proxy is configured */
305 if (GNUNET_YES == GNUNET_SOCKS_check_service (service_name,cfg))
306 return GNUNET_SOCKS_do_connect (service_name,cfg);
309 if (0 == (attempt % 2))
311 /* on even rounds, try UNIX first */
312 connection = try_unixpath (service_name, cfg);
313 if (NULL != connection)
317 GNUNET_CONFIGURATION_have_value (cfg, service_name, "PORT"))
320 GNUNET_CONFIGURATION_get_value_number (cfg, service_name, "PORT", &port))
323 GNUNET_CONFIGURATION_get_value_string (cfg, service_name, "HOSTNAME",
326 LOG (GNUNET_ERROR_TYPE_WARNING,
328 ("Could not determine valid hostname and port for service `%s' from configuration.\n"),
332 if (0 == strlen (hostname))
334 GNUNET_free (hostname);
335 LOG (GNUNET_ERROR_TYPE_WARNING,
336 _("Need a non-empty hostname for service `%s'.\n"), service_name);
342 /* unspecified means 0 (disabled) */
348 /* if port is 0, try UNIX */
349 connection = try_unixpath (service_name, cfg);
350 if (NULL != connection)
352 GNUNET_free_non_null (hostname);
355 LOG (GNUNET_ERROR_TYPE_DEBUG,
356 "Port is 0 for service `%s', UNIXPATH did not work, returning NULL!\n",
358 GNUNET_free_non_null (hostname);
361 connection = GNUNET_CONNECTION_create_from_connect (cfg, hostname, port);
362 GNUNET_free (hostname);
368 * Create a message queue to connect to a GNUnet service.
369 * If handlers are specfied, receive messages from the connection.
371 * @param connection the client connection
372 * @param handlers handlers for receiving messages, can be NULL
373 * @param error_handler error handler
374 * @param error_handler_cls closure for the @a error_handler
375 * @return the message queue, NULL on error
377 struct GNUNET_MQ_Handle *
378 GNUNET_CLIENT_connecT (const struct GNUNET_CONFIGURATION_Handle *cfg,
379 const char *service_name,
380 const struct GNUNET_MQ_MessageHandler *handlers,
381 GNUNET_MQ_ErrorHandler error_handler,
382 void *error_handler_cls)
384 struct GNUNET_CLIENT_Connection *c;
386 c = GNUNET_CLIENT_connect (service_name,
390 return GNUNET_MQ_queue_for_connection_client (c,
398 * Get a connection with a service.
400 * @param service_name name of the service
401 * @param cfg configuration to use
402 * @return NULL on error (service unknown to configuration)
404 struct GNUNET_CLIENT_Connection *
405 GNUNET_CLIENT_connect (const char *service_name,
406 const struct GNUNET_CONFIGURATION_Handle *cfg)
408 struct GNUNET_CLIENT_Connection *client;
409 struct GNUNET_CONNECTION_Handle *connection;
412 test_service_configuration (service_name,
415 connection = do_connect (service_name, cfg, 0);
416 client = GNUNET_new (struct GNUNET_CLIENT_Connection);
417 client->first_message = GNUNET_YES;
418 client->attempts = 1;
419 client->connection = connection;
420 client->service_name = GNUNET_strdup (service_name);
422 client->back_off = GNUNET_TIME_UNIT_MILLISECONDS;
428 * Destroy connection with the service. This will automatically
429 * cancel any pending "receive" request (however, the handler will
430 * *NOT* be called, not even with a NULL message). Any pending
431 * transmission request will also be cancelled UNLESS the callback for
432 * the transmission request has already been called, in which case the
433 * transmission 'finish_pending_write' argument determines whether or
434 * not the write is guaranteed to complete before the socket is fully
435 * destroyed (unless, of course, there is an error with the server in
436 * which case the message may still be lost).
438 * @param client handle to the service connection
441 GNUNET_CLIENT_disconnect (struct GNUNET_CLIENT_Connection *client)
443 if (GNUNET_YES == client->in_receive)
445 GNUNET_CONNECTION_receive_cancel (client->connection);
446 client->in_receive = GNUNET_NO;
448 if (NULL != client->th)
450 GNUNET_CLIENT_notify_transmit_ready_cancel (client->th);
453 if (NULL != client->connection)
455 GNUNET_CONNECTION_destroy (client->connection);
456 client->connection = NULL;
458 if (NULL != client->receive_task)
460 GNUNET_SCHEDULER_cancel (client->receive_task);
461 client->receive_task = NULL;
463 client->receiver_handler = NULL;
464 GNUNET_array_grow (client->received_buf,
465 client->received_size,
467 GNUNET_free (client->service_name);
468 GNUNET_free (client);
473 * Check if message is complete. Sets the "msg_complete" member
474 * in the client struct.
476 * @param client connection with the buffer to check
479 check_complete (struct GNUNET_CLIENT_Connection *client)
481 if ((client->received_pos >= sizeof (struct GNUNET_MessageHeader)) &&
482 (client->received_pos >=
483 ntohs (((const struct GNUNET_MessageHeader *) client->received_buf)->
485 client->msg_complete = GNUNET_YES;
490 * Callback function for data received from the network. Note that
491 * both @a available and @a errCode would be 0 if the read simply timed out.
494 * @param buf pointer to received data
495 * @param available number of bytes availabe in @a buf,
496 * possibly 0 (on errors)
497 * @param addr address of the sender
498 * @param addrlen size of @a addr
499 * @param errCode value of errno (on errors receiving)
502 receive_helper (void *cls,
505 const struct sockaddr *addr,
509 struct GNUNET_CLIENT_Connection *client = cls;
510 struct GNUNET_TIME_Relative remaining;
511 GNUNET_CLIENT_MessageHandler receive_handler;
512 void *receive_handler_cls;
514 GNUNET_assert (GNUNET_NO == client->msg_complete);
515 GNUNET_assert (GNUNET_YES == client->in_receive);
516 client->in_receive = GNUNET_NO;
517 if ( (0 == available) ||
518 (NULL == client->connection) ||
521 /* signal timeout! */
522 LOG (GNUNET_ERROR_TYPE_DEBUG,
523 "Timeout in receive_helper, available %u, client->connection %s, errCode `%s'\n",
524 (unsigned int) available,
525 NULL == client->connection ? "NULL" : "non-NULL",
527 /* remember failure */
528 client->in_receive = GNUNET_SYSERR;
529 if (NULL != (receive_handler = client->receiver_handler))
531 receive_handler_cls = client->receiver_handler_cls;
532 client->receiver_handler = NULL;
533 receive_handler (receive_handler_cls,
538 /* FIXME: optimize for common fast case where buf contains the
539 * entire message and we need no copying... */
541 /* slow path: append to array */
542 if (client->received_size < client->received_pos + available)
543 GNUNET_array_grow (client->received_buf, client->received_size,
544 client->received_pos + available);
545 GNUNET_memcpy (&client->received_buf[client->received_pos], buf, available);
546 client->received_pos += available;
547 check_complete (client);
548 /* check for timeout */
549 remaining = GNUNET_TIME_absolute_get_remaining (client->receive_timeout);
550 if (0 == remaining.rel_value_us)
552 /* signal timeout! */
553 if (NULL != (receive_handler = client->receiver_handler))
555 client->receiver_handler = NULL;
556 receive_handler (client->receiver_handler_cls, NULL);
560 /* back to receive -- either for more data or to call callback! */
561 GNUNET_CLIENT_receive (client, client->receiver_handler,
562 client->receiver_handler_cls, remaining);
567 * Continuation to call the receive callback.
569 * @param cls our handle to the client connection
572 receive_task (void *cls)
574 struct GNUNET_CLIENT_Connection *client = cls;
575 GNUNET_CLIENT_MessageHandler handler = client->receiver_handler;
576 const struct GNUNET_MessageHeader *cmsg =
577 (const struct GNUNET_MessageHeader *) client->received_buf;
578 void *handler_cls = client->receiver_handler_cls;
579 uint16_t msize = ntohs (cmsg->size);
580 char mbuf[msize] GNUNET_ALIGN;
581 struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) mbuf;
583 client->receive_task = NULL;
584 if ( (GNUNET_SYSERR == client->in_receive) &&
585 (GNUNET_YES != client->msg_complete) )
587 /* Connection failure, signal to caller! */
588 client->receiver_handler = NULL;
590 handler (handler_cls,
594 LOG (GNUNET_ERROR_TYPE_DEBUG,
595 "Received message of type %u and size %u from %s service.\n",
598 client->service_name);
599 GNUNET_assert (GNUNET_YES == client->msg_complete);
600 GNUNET_assert (client->received_pos >= msize);
601 GNUNET_memcpy (msg, cmsg, msize);
602 memmove (client->received_buf,
603 &client->received_buf[msize],
604 client->received_pos - msize);
605 client->received_pos -= msize;
606 client->msg_complete = GNUNET_NO;
607 client->receiver_handler = NULL;
608 check_complete (client);
610 handler (handler_cls, msg);
615 * Read from the service.
617 * @param client the service
618 * @param handler function to call with the message
619 * @param handler_cls closure for @a handler
620 * @param timeout how long to wait until timing out
623 GNUNET_CLIENT_receive (struct GNUNET_CLIENT_Connection *client,
624 GNUNET_CLIENT_MessageHandler handler,
626 struct GNUNET_TIME_Relative timeout)
628 if (NULL == client->connection)
630 /* already disconnected, fail instantly! */
631 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
632 "Client API violation for service `%s'\n",
633 client->service_name);
634 GNUNET_break (0); /* this should not happen in well-written code! */
636 handler (handler_cls,
640 client->receiver_handler = handler;
641 client->receiver_handler_cls = handler_cls;
642 client->receive_timeout = GNUNET_TIME_relative_to_absolute (timeout);
643 if ( (GNUNET_YES == client->msg_complete) ||
644 (GNUNET_SYSERR == client->in_receive) )
646 GNUNET_assert (NULL == client->receive_task);
647 client->receive_task = GNUNET_SCHEDULER_add_now (&receive_task,
651 LOG (GNUNET_ERROR_TYPE_DEBUG,
652 "calling GNUNET_CONNECTION_receive\n");
653 GNUNET_assert (GNUNET_NO == client->in_receive);
654 client->in_receive = GNUNET_YES;
655 GNUNET_CONNECTION_receive (client->connection,
656 GNUNET_SERVER_MAX_MESSAGE_SIZE - 1,
664 * Handle for a test to check if a service is running.
666 struct GNUNET_CLIENT_TestHandle
669 * Function to call with the result of the test.
671 GNUNET_CLIENT_TestResultCallback cb;
679 * Client connection we are using for the test, if any.
681 struct GNUNET_CLIENT_Connection *client;
684 * Handle for the transmission request, if any.
686 struct GNUNET_CLIENT_TransmitHandle *th;
689 * Deadline for calling @e cb.
691 struct GNUNET_TIME_Absolute test_deadline;
694 * ID of task used for asynchronous operations.
696 struct GNUNET_SCHEDULER_Task *task;
699 * Final result to report back (once known).
706 * Abort testing for service.
708 * @param th test handle
711 GNUNET_CLIENT_service_test_cancel (struct GNUNET_CLIENT_TestHandle *th)
715 GNUNET_CLIENT_notify_transmit_ready_cancel (th->th);
718 if (NULL != th->client)
720 GNUNET_CLIENT_disconnect (th->client);
723 if (NULL != th->task)
725 GNUNET_SCHEDULER_cancel (th->task);
733 * Task that reports back the result by calling the callback
734 * and then cleans up.
736 * @param cls the `struct GNUNET_CLIENT_TestHandle`
739 report_result (void *cls)
741 struct GNUNET_CLIENT_TestHandle *th = cls;
744 th->cb (th->cb_cls, th->result);
745 GNUNET_CLIENT_service_test_cancel (th);
750 * Report service test result asynchronously back to callback.
752 * @param th test handle with the result and the callback
753 * @param result result to report
756 service_test_report (struct GNUNET_CLIENT_TestHandle *th,
760 th->task = GNUNET_SCHEDULER_add_now (&report_result,
766 * Receive confirmation from test, service is up.
768 * @param cls closure with the `struct GNUNET_CLIENT_TestHandle`
769 * @param msg message received, NULL on timeout or fatal error
772 confirm_handler (void *cls,
773 const struct GNUNET_MessageHeader *msg)
775 struct GNUNET_CLIENT_TestHandle *th = cls;
777 /* We may want to consider looking at the reply in more
778 * detail in the future, for example, is this the
779 * correct service? FIXME! */
782 LOG (GNUNET_ERROR_TYPE_DEBUG,
783 "Received confirmation that service is running.\n");
784 service_test_report (th, GNUNET_YES);
788 service_test_report (th, GNUNET_NO);
794 * Send the 'TEST' message to the service. If successful, prepare to
797 * @param cls the `struct GNUNET_CLIENT_TestHandle` of the test
798 * @param size number of bytes available in @a buf
799 * @param buf where to write the message
800 * @return number of bytes written to @a buf
803 write_test (void *cls, size_t size, void *buf)
805 struct GNUNET_CLIENT_TestHandle *th = cls;
806 struct GNUNET_MessageHeader *msg;
809 if (size < sizeof (struct GNUNET_MessageHeader))
811 LOG (GNUNET_ERROR_TYPE_DEBUG,
812 "Failed to transmit TEST request.\n");
813 service_test_report (th, GNUNET_NO);
814 return 0; /* client disconnected */
816 LOG (GNUNET_ERROR_TYPE_DEBUG,
817 "Transmitting `%s' request.\n",
819 msg = (struct GNUNET_MessageHeader *) buf;
820 msg->type = htons (GNUNET_MESSAGE_TYPE_TEST);
821 msg->size = htons (sizeof (struct GNUNET_MessageHeader));
822 GNUNET_CLIENT_receive (th->client,
823 &confirm_handler, th,
824 GNUNET_TIME_absolute_get_remaining
825 (th->test_deadline));
826 return sizeof (struct GNUNET_MessageHeader);
831 * Test if the service is running. If we are given a UNIXPATH or a
832 * local address, we do this NOT by trying to connect to the service,
833 * but by trying to BIND to the same port. If the BIND fails, we know
834 * the service is running.
836 * @param service name of the service to wait for
837 * @param cfg configuration to use
838 * @param timeout how long to wait at most
839 * @param cb function to call with the result
840 * @param cb_cls closure for @a cb
841 * @return handle to cancel the test
843 struct GNUNET_CLIENT_TestHandle *
844 GNUNET_CLIENT_service_test (const char *service,
845 const struct GNUNET_CONFIGURATION_Handle *cfg,
846 struct GNUNET_TIME_Relative timeout,
847 GNUNET_CLIENT_TestResultCallback cb,
850 struct GNUNET_CLIENT_TestHandle *th;
852 unsigned long long port;
853 struct GNUNET_NETWORK_Handle *sock;
855 th = GNUNET_new (struct GNUNET_CLIENT_TestHandle);
858 th->test_deadline = GNUNET_TIME_relative_to_absolute (timeout);
859 LOG (GNUNET_ERROR_TYPE_DEBUG,
860 "Testing if service `%s' is running.\n",
864 /* probe UNIX support */
865 struct sockaddr_un s_un;
871 GNUNET_CONFIGURATION_get_value_filename (cfg,
875 (0 < strlen (unixpath))) /* We have a non-NULL unixpath, does that mean it's valid? */
877 if (strlen (unixpath) >= sizeof (s_un.sun_path))
879 LOG (GNUNET_ERROR_TYPE_WARNING,
880 _("UNIXPATH `%s' too long, maximum length is %llu\n"),
882 (unsigned long long) sizeof (s_un.sun_path));
883 unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
884 LOG (GNUNET_ERROR_TYPE_INFO,
885 _("Using `%s' instead\n"), unixpath);
889 abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg,
891 "USE_ABSTRACT_SOCKETS");
893 abstract = GNUNET_NO;
895 if ((NULL != unixpath) && (GNUNET_YES != abstract))
897 if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (unixpath))
898 GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
901 if (NULL != unixpath)
903 sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0);
906 memset (&s_un, 0, sizeof (s_un));
907 s_un.sun_family = AF_UNIX;
908 strncpy (s_un.sun_path, unixpath, sizeof (s_un.sun_path) - 1);
909 if (GNUNET_YES == abstract)
910 s_un.sun_path[0] = '\0';
911 #if HAVE_SOCKADDR_IN_SIN_LEN
912 s_un.sun_len = (u_char) sizeof (struct sockaddr_un);
915 GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_un,
916 sizeof (struct sockaddr_un)))
918 /* failed to bind => service must be running */
919 GNUNET_free (unixpath);
920 (void) GNUNET_NETWORK_socket_close (sock);
921 service_test_report (th, GNUNET_YES);
924 (void) GNUNET_NETWORK_socket_close (sock);
928 GNUNET_free_non_null (unixpath);
934 GNUNET_CONFIGURATION_get_value_number (cfg, service, "PORT", &port)) ||
937 GNUNET_CONFIGURATION_get_value_string (cfg, service, "HOSTNAME",
940 /* UNIXPATH failed (if possible) AND IP failed => error */
941 service_test_report (th, GNUNET_SYSERR);
945 if (0 == strcmp ("localhost", hostname)
951 /* can test using 'bind' */
952 struct sockaddr_in s_in;
954 memset (&s_in, 0, sizeof (s_in));
955 #if HAVE_SOCKADDR_IN_SIN_LEN
956 s_in.sin_len = sizeof (struct sockaddr_in);
958 s_in.sin_family = AF_INET;
959 s_in.sin_port = htons (port);
961 sock = GNUNET_NETWORK_socket_create (AF_INET, SOCK_STREAM, 0);
965 GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_in,
968 /* failed to bind => service must be running */
969 GNUNET_free (hostname);
970 (void) GNUNET_NETWORK_socket_close (sock);
971 service_test_report (th, GNUNET_YES);
974 (void) GNUNET_NETWORK_socket_close (sock);
978 if (0 == strcmp ("ip6-localhost", hostname)
984 /* can test using 'bind' */
985 struct sockaddr_in6 s_in6;
987 memset (&s_in6, 0, sizeof (s_in6));
988 #if HAVE_SOCKADDR_IN_SIN_LEN
989 s_in6.sin6_len = sizeof (struct sockaddr_in6);
991 s_in6.sin6_family = AF_INET6;
992 s_in6.sin6_port = htons (port);
994 sock = GNUNET_NETWORK_socket_create (AF_INET6, SOCK_STREAM, 0);
998 GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) &s_in6,
1001 /* failed to bind => service must be running */
1002 GNUNET_free (hostname);
1003 (void) GNUNET_NETWORK_socket_close (sock);
1004 service_test_report (th, GNUNET_YES);
1007 (void) GNUNET_NETWORK_socket_close (sock);
1011 if (((0 == strcmp ("localhost", hostname)) ||
1012 (0 == strcmp ("ip6-localhost", hostname)))
1018 /* all binds succeeded => claim service not running right now */
1019 GNUNET_free_non_null (hostname);
1020 service_test_report (th, GNUNET_NO);
1023 GNUNET_free_non_null (hostname);
1025 /* non-localhost, try 'connect' method */
1026 th->client = GNUNET_CLIENT_connect (service, cfg);
1027 if (NULL == th->client)
1029 LOG (GNUNET_ERROR_TYPE_INFO,
1030 _("Could not connect to service `%s', configuration broken.\n"),
1032 service_test_report (th, GNUNET_SYSERR);
1035 th->th = GNUNET_CLIENT_notify_transmit_ready (th->client,
1036 sizeof (struct GNUNET_MessageHeader),
1037 timeout, GNUNET_YES,
1041 LOG (GNUNET_ERROR_TYPE_WARNING,
1042 _("Failure to transmit request to service `%s'\n"), service);
1043 service_test_report (th, GNUNET_SYSERR);
1051 * Connection notifies us about failure or success of
1052 * a transmission request. Either pass it on to our
1053 * user or, if possible, retry.
1055 * @param cls our `struct GNUNET_CLIENT_TransmissionHandle`
1056 * @param size number of bytes available for transmission
1057 * @param buf where to write them
1058 * @return number of bytes written to @a buf
1061 client_notify (void *cls, size_t size, void *buf);
1065 * This task is run if we should re-try connection to the
1066 * service after a while.
1068 * @param cls our `struct GNUNET_CLIENT_TransmitHandle` of the request
1071 client_delayed_retry (void *cls)
1073 struct GNUNET_CLIENT_TransmitHandle *th = cls;
1074 struct GNUNET_TIME_Relative delay;
1076 th->reconnect_task = NULL;
1077 th->client->connection =
1078 do_connect (th->client->service_name,
1080 th->client->attempts++);
1081 th->client->first_message = GNUNET_YES;
1082 if (NULL == th->client->connection)
1084 /* could happen if we're out of sockets */
1085 delay = GNUNET_TIME_relative_min (GNUNET_TIME_absolute_get_remaining (th->timeout),
1086 th->client->back_off);
1087 th->client->back_off = GNUNET_TIME_STD_BACKOFF (th->client->back_off);
1088 LOG (GNUNET_ERROR_TYPE_DEBUG,
1089 "Transmission failed %u times, trying again in %s.\n",
1090 MAX_ATTEMPTS - th->attempts_left,
1091 GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES));
1092 GNUNET_assert (NULL == th->th);
1093 GNUNET_assert (NULL == th->reconnect_task);
1094 th->reconnect_task =
1095 GNUNET_SCHEDULER_add_delayed (delay,
1096 &client_delayed_retry,
1101 GNUNET_CONNECTION_notify_transmit_ready (th->client->connection, th->size,
1102 GNUNET_TIME_absolute_get_remaining
1109 th->client->th = NULL;
1110 th->notify (th->notify_cls, 0, NULL);
1118 * Connection notifies us about failure or success of a transmission
1119 * request. Either pass it on to our user or, if possible, retry.
1121 * @param cls our `struct GNUNET_CLIENT_TransmissionHandle`
1122 * @param size number of bytes available for transmission
1123 * @param buf where to write them
1124 * @return number of bytes written to @a buf
1127 client_notify (void *cls,
1131 struct GNUNET_CLIENT_TransmitHandle *th = cls;
1132 struct GNUNET_CLIENT_Connection *client = th->client;
1134 struct GNUNET_TIME_Relative delay;
1136 LOG (GNUNET_ERROR_TYPE_DEBUG,
1137 "client_notify is running\n");
1142 delay = GNUNET_TIME_absolute_get_remaining (th->timeout);
1143 delay.rel_value_us /= 2;
1144 if ( (GNUNET_YES != th->auto_retry) ||
1145 (0 == --th->attempts_left) ||
1146 (delay.rel_value_us < 1) )
1148 LOG (GNUNET_ERROR_TYPE_DEBUG,
1149 "Transmission failed %u times, giving up.\n",
1150 MAX_ATTEMPTS - th->attempts_left);
1152 th->notify (th->notify_cls, 0, NULL));
1157 LOG (GNUNET_ERROR_TYPE_DEBUG,
1158 "Failed to connect to `%s', automatically trying again.\n",
1159 client->service_name);
1160 if (GNUNET_YES == client->in_receive)
1162 GNUNET_CONNECTION_receive_cancel (client->connection);
1163 client->in_receive = GNUNET_NO;
1165 GNUNET_CONNECTION_destroy (client->connection);
1166 client->connection = NULL;
1167 delay = GNUNET_TIME_relative_min (delay, client->back_off);
1169 GNUNET_TIME_relative_min (GNUNET_TIME_relative_multiply
1170 (client->back_off, 2),
1171 GNUNET_TIME_UNIT_SECONDS);
1172 LOG (GNUNET_ERROR_TYPE_DEBUG,
1173 "Transmission failed %u times, trying again in %s.\n",
1174 MAX_ATTEMPTS - th->attempts_left,
1175 GNUNET_STRINGS_relative_time_to_string (delay, GNUNET_YES));
1177 GNUNET_assert (NULL == th->reconnect_task);
1178 GNUNET_assert (NULL == th->th);
1179 th->reconnect_task =
1180 GNUNET_SCHEDULER_add_delayed (delay,
1181 &client_delayed_retry,
1185 GNUNET_assert (size >= th->size);
1186 ret = th->notify (th->notify_cls, size, buf);
1188 if (sizeof (struct GNUNET_MessageHeader) <= ret)
1190 LOG (GNUNET_ERROR_TYPE_DEBUG,
1191 "Transmitting message of type %u and size %u to %s service.\n",
1192 ntohs (((struct GNUNET_MessageHeader *) buf)->type),
1193 ntohs (((struct GNUNET_MessageHeader *) buf)->size),
1194 client->service_name);
1201 * Ask the client to call us once the specified number of bytes
1202 * are free in the transmission buffer. Will never call the @a notify
1203 * callback in this task, but always first go into the scheduler.
1205 * @param client connection to the service
1206 * @param size number of bytes to send
1207 * @param timeout after how long should we give up (and call
1208 * notify with buf NULL and size 0)?
1209 * @param auto_retry if the connection to the service dies, should we
1210 * automatically re-connect and retry (within the timeout period)
1211 * or should we immediately fail in this case? Pass GNUNET_YES
1212 * if the caller does not care about temporary connection errors,
1213 * for example because the protocol is stateless
1214 * @param notify function to call
1215 * @param notify_cls closure for @a notify
1216 * @return NULL if our buffer will never hold size bytes,
1217 * a handle if the notify callback was queued (can be used to cancel)
1219 struct GNUNET_CLIENT_TransmitHandle *
1220 GNUNET_CLIENT_notify_transmit_ready (struct GNUNET_CLIENT_Connection *client,
1222 struct GNUNET_TIME_Relative timeout,
1224 GNUNET_CONNECTION_TransmitReadyNotify notify,
1227 struct GNUNET_CLIENT_TransmitHandle *th;
1229 if (NULL != client->th)
1231 /* If this breaks, you most likley called this function twice without waiting
1232 * for completion or canceling the request */
1236 th = GNUNET_new (struct GNUNET_CLIENT_TransmitHandle);
1237 th->client = client;
1239 th->timeout = GNUNET_TIME_relative_to_absolute (timeout);
1240 /* always auto-retry on first message to service */
1241 th->auto_retry = (GNUNET_YES == client->first_message) ? GNUNET_YES : auto_retry;
1242 client->first_message = GNUNET_NO;
1243 th->notify = notify;
1244 th->notify_cls = notify_cls;
1245 th->attempts_left = MAX_ATTEMPTS;
1247 if (NULL == client->connection)
1249 GNUNET_assert (NULL == th->th);
1250 GNUNET_assert (NULL == th->reconnect_task);
1251 th->reconnect_task =
1252 GNUNET_SCHEDULER_add_delayed (client->back_off,
1253 &client_delayed_retry,
1258 th->th = GNUNET_CONNECTION_notify_transmit_ready (client->connection,
1276 * Cancel a request for notification.
1278 * @param th handle from the original request.
1281 GNUNET_CLIENT_notify_transmit_ready_cancel (struct GNUNET_CLIENT_TransmitHandle *th)
1283 if (NULL != th->reconnect_task)
1285 GNUNET_assert (NULL == th->th);
1286 GNUNET_SCHEDULER_cancel (th->reconnect_task);
1287 th->reconnect_task = NULL;
1291 GNUNET_assert (NULL != th->th);
1292 GNUNET_CONNECTION_notify_transmit_ready_cancel (th->th);
1294 th->client->th = NULL;
1299 /* end of client.c */