2 This file is part of GNUnet.
3 Copyright (C) 2001-2016 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__)
46 * Internal state for a client connected to a GNUnet service.
52 * During connect, we try multiple possible IP addresses
53 * to find out which one might work.
59 * This is a linked list.
61 struct AddressProbe *next;
64 * This is a doubly-linked list.
66 struct AddressProbe *prev;
69 * The address; do not free (allocated at the end of this struct).
71 const struct sockaddr *addr;
74 * Underlying OS's socket.
76 struct GNUNET_NETWORK_Handle *sock;
79 * Connection for which we are probing.
81 struct ClientState *cstate;
89 * Task waiting for the connection to finish connecting.
91 struct GNUNET_SCHEDULER_Task *task;
96 * Internal state for a client connected to a GNUnet service.
102 * The connection handle, NULL if not live
104 struct GNUNET_NETWORK_Handle *sock;
107 * Handle to a pending DNS lookup request, NULL if DNS is finished.
109 struct GNUNET_RESOLVER_RequestHandle *dns_active;
114 const struct GNUNET_CONFIGURATION_Handle *cfg;
117 * Linked list of sockets we are currently trying out
120 struct AddressProbe *ap_head;
123 * Linked list of sockets we are currently trying out
126 struct AddressProbe *ap_tail;
129 * Name of the service we interact with.
139 * Next message to transmit to the service. NULL for none.
141 const struct GNUNET_MessageHeader *msg;
144 * Task for trying to connect to the service.
146 struct GNUNET_SCHEDULER_Task *retry_task;
149 * Task for sending messages to the service.
151 struct GNUNET_SCHEDULER_Task *send_task;
154 * Task for sending messages to the service.
156 struct GNUNET_SCHEDULER_Task *recv_task;
159 * Tokenizer for inbound messages.
161 struct GNUNET_MessageStreamTokenizer *mst;
164 * Timeout for receiving a response (absolute time).
166 struct GNUNET_TIME_Absolute receive_timeout;
169 * Current value for our incremental back-off (for
172 struct GNUNET_TIME_Relative back_off;
175 * TCP port (0 for disabled).
177 unsigned long long port;
180 * Offset in the message where we are for transmission.
185 * Is this the first message we are sending to the service?
190 * How often have we tried to connect?
192 unsigned int attempts;
198 * Try to connect to the service.
200 * @param cls the `struct ClientState` to try to connect to the service
203 start_connect (void *cls);
207 * We've failed for good to establish a connection (timeout or
208 * no more addresses to try).
210 * @param cstate the connection we tried to establish
213 connect_fail_continuation (struct ClientState *cstate)
215 LOG (GNUNET_ERROR_TYPE_INFO,
216 "Failed to establish TCP connection to `%s:%u', no further addresses to try.\n",
219 GNUNET_break (NULL == cstate->ap_head);
220 GNUNET_break (NULL == cstate->ap_tail);
221 GNUNET_break (NULL == cstate->dns_active);
222 GNUNET_break (NULL == cstate->sock);
223 GNUNET_assert (NULL == cstate->write_task);
224 // GNUNET_assert (NULL == cstate->proxy_handshake);
227 = GNUNET_SCHEDULER_add_delayed (cstate->retry_delay,
234 * We are ready to send a message to the service.
236 * @param cls the `struct ClientState` with the `msg` to transmit
239 transmit_ready (void *cls)
241 struct ClientState *cstate = cls;
246 cstate->send_task = NULL;
247 pos = (const char *) cstate->msg;
248 len = ntohs (cstate->msg->size);
249 GNUNET_assert (cstate->msg_off < len);
251 ret = GNUNET_NETWORK_socket_send (cstate->sock,
252 &pos[cstate->msg_off],
253 len - cstate->msg_off);
258 GNUNET_MQ_inject_error (cstate->mq,
259 GNUNET_MQ_ERROR_WRITE);
262 if (0 == cstate->msg_off)
264 // FIXME: tell MQ that cancel is no longer possible!
266 cstate->msg_off += pos;
267 if (cstate->msg_off < len)
270 = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
277 GNUNET_MQ_impl_send_continue (cstate->mq);
282 * We have received a full message, pass to the MQ dispatcher.
283 * Called by the tokenizer via #receive_ready().
285 * @param cls the `struct ClientState`
286 * @param msg message we received.
289 recv_message (void *cls,
290 const struct GNUNET_MessageHeader *msg)
292 struct ClientState *cstate = cls;
294 GNUNET_MQ_inject_message (cstate->mq,
300 * This function is called once we have data ready to read.
302 * @param cls `struct ClientState` with connection to read from
305 receive_ready (void *cls)
307 struct ClientState *cstate = cls;
308 const struct GNUNET_SCHEDULER_TaskContext *tc;
311 connection->recv_task = NULL;
312 ret = GNUNET_MST_read (cstate->msg,
316 if (GNUNET_SYSERR == ret)
318 GNUNET_MQ_inject_error (cstate->mq,
319 GNUNET_MQ_ERROR_READ);
323 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
331 * We've succeeded in establishing a connection.
333 * @param cstate the connection we tried to establish
336 connect_success_continuation (struct ClientState *cstate)
338 GNUNET_assert (NULL == connection->read_task);
340 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
344 if (NULL != cstate->msg)
346 GNUNET_assert (NULL == cstate->send_task);
348 = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
357 * Try connecting to the server using UNIX domain sockets.
359 * @param service_name name of service to connect to
360 * @param cfg configuration to use
361 * @return NULL on error, socket connected to UNIX otherwise
363 static struct GNUNET_NETWORK_Handle *
364 try_unixpath (const char *service_name,
365 const struct GNUNET_CONFIGURATION_Handle *cfg)
368 struct GNUNET_NETWORK_Handle *sock;
370 struct sockaddr_un s_un;
374 GNUNET_CONFIGURATION_get_value_filename (cfg,
378 (0 < strlen (unixpath)))
380 /* We have a non-NULL unixpath, need to validate it */
381 if (strlen (unixpath) >= sizeof (s_un.sun_path))
383 LOG (GNUNET_ERROR_TYPE_WARNING,
384 _("UNIXPATH `%s' too long, maximum length is %llu\n"),
386 (unsigned long long) sizeof (s_un.sun_path));
387 unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
388 LOG (GNUNET_ERROR_TYPE_INFO,
389 _("Using `%s' instead\n"),
391 if (NULL == unixpath)
397 un.sun_family = AF_UNIX;
398 strncpy (un.sun_path,
400 sizeof (un->sun_path) - 1);
405 abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg,
407 "USE_ABSTRACT_SOCKETS");
408 if (GNUNET_YES == abstract)
409 un.sun_path[0] = '\0';
412 #if HAVE_SOCKADDR_IN_SIN_LEN
413 un.sun_len = (u_char) sizeof (struct sockaddr_un);
415 sock = GNUNET_NETWORK_socket_create (AF_UNIX,
419 GNUNET_NETWORK_socket_connect (sock,
420 (struct sockaddr *) &un,
422 (EINPROGRESS == errno) )
424 LOG (GNUNET_ERROR_TYPE_DEBUG,
425 "Successfully connected to unixpath `%s'!\n",
427 GNUNET_free (unixpath);
431 GNUNET_free_non_null (unixpath);
438 * Cancel all remaining connect attempts
440 * @param cstate handle of the client state to process
443 cancel_aps (struct ClientState *cstate)
445 struct AddressProbe *pos;
447 while (NULL != (pos = cstate->ap_head))
449 GNUNET_break (GNUNET_OK ==
450 GNUNET_NETWORK_socket_close (pos->sock));
451 GNUNET_SCHEDULER_cancel (pos->task);
452 GNUNET_CONTAINER_DLL_remove (cstate->ap_head,
461 * Scheduler let us know that we're either ready to write on the
462 * socket OR connect timed out. Do the right thing.
464 * @param cls the `struct AddressProbe *` with the address that we are probing
467 connect_probe_continuation (void *cls)
469 struct AddressProbe *ap = cls;
470 struct ClientState *cstate *connection = ap->cstate;
471 const struct GNUNET_SCHEDULER_TaskContext *tc;
476 GNUNET_assert (NULL != ap->sock);
477 GNUNET_CONTAINER_DLL_remove (connection->ap_head,
480 len = sizeof (error);
482 tc = GNUNET_SCHEDULER_get_task_context ();
483 if ( (0 == (tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) ||
485 GNUNET_NETWORK_socket_getsockopt (ap->sock,
492 GNUNET_break (GNUNET_OK ==
493 GNUNET_NETWORK_socket_close (ap->sock));
495 if ( (NULL == cstate->ap_head) &&
496 // (NULL == cstate->proxy_handshake) &&
497 (NULL == cstate->dns_active) )
498 connect_fail_continuation (cstate);
501 LOG (GNUNET_ERROR_TYPE_DEBUG,
502 "Connection to `%s' succeeded!\n",
503 GNUNET_a2s (cstate->addr,
505 /* trigger jobs that waited for the connection */
506 GNUNET_assert (NULL == cstate->sock);
507 cstate->sock = ap->sock;
510 connect_success_continuation (cstate);
515 * Try to establish a connection given the specified address.
516 * This function is called by the resolver once we have a DNS reply.
518 * @param cls our `struct GNUNET_CONNECTION_Handle *`
519 * @param addr address to try, NULL for "last call"
520 * @param addrlen length of @a addr
523 try_connect_using_address (void *cls,
524 const struct sockaddr *addr,
527 struct ClientState *cstate = cls;
528 struct AddressProbe *ap;
529 struct GNUNET_TIME_Relative delay;
533 cstate->dns_active = NULL;
534 if ( (NULL == cstate->ap_head) &&
535 // (NULL == cstate->proxy_handshake) &&
536 (NULL == cstate->sock) )
537 connect_fail_continuation (cstate);
540 if (NULL != cstate->sock)
541 return; /* already connected */
543 LOG (GNUNET_ERROR_TYPE_DEBUG,
544 "Trying to connect using address `%s:%u'\n",
548 ap = GNUNET_malloc (sizeof (struct AddressProbe) + addrlen);
549 ap->addr = (const struct sockaddr *) &ap[1];
550 GNUNET_memcpy (&ap[1],
553 ap->addrlen = addrlen;
554 ap->connection = connection;
556 switch (ap->addr->sa_family)
559 ((struct sockaddr_in *) ap->addr)->sin_port = htons (connection->port);
562 ((struct sockaddr_in6 *) ap->addr)->sin6_port = htons (connection->port);
567 return; /* not supported by us */
569 ap->sock = GNUNET_NETWORK_socket_create (ap->addr->sa_family,
572 if (NULL == ap->sock)
575 return; /* not supported by OS */
578 GNUNET_NETWORK_socket_connect (ap->sock,
581 (EINPROGRESS != errno) )
583 /* maybe refused / unsupported address, try next */
584 LOG_STRERROR (GNUNET_ERROR_TYPE_INFO,
586 GNUNET_break (GNUNET_OK ==
587 GNUNET_NETWORK_socket_close (ap->sock));
591 GNUNET_CONTAINER_DLL_insert (connection->ap_head,
594 ap->task = GNUNET_SCHEDULER_add_write_net (GNUNET_CONNECTION_CONNECT_RETRY_TIMEOUT,
596 &connect_probe_continuation,
602 * Test whether the configuration has proper values for connection
603 * (UNIXPATH || (PORT && HOSTNAME)).
605 * @param service_name name of service to connect to
606 * @param cfg configuration to use
607 * @return #GNUNET_OK if the configuration is valid, #GNUNET_SYSERR if not
610 test_service_configuration (const char *service_name,
611 const struct GNUNET_CONFIGURATION_Handle *cfg)
613 int ret = GNUNET_SYSERR;
614 char *hostname = NULL;
615 unsigned long long port;
617 char *unixpath = NULL;
620 GNUNET_CONFIGURATION_get_value_filename (cfg,
624 (0 < strlen (unixpath)))
626 GNUNET_free_non_null (unixpath);
630 GNUNET_CONFIGURATION_have_value (cfg,
634 GNUNET_CONFIGURATION_get_value_number (cfg,
641 GNUNET_CONFIGURATION_get_value_string (cfg,
645 (0 != strlen (hostname)) )
647 GNUNET_free_non_null (hostname);
653 * Try to connect to the service.
655 * @param cls the `struct ClientState` to try to connect to the service
658 start_connect (void *cls)
660 struct ClientState *cstate = cls;
662 cstate->retry_task = NULL;
664 /* Never use a local source if a proxy is configured */
666 GNUNET_SOCKS_check_service (service_name,
669 socks_connect (cstate);
674 if ( (0 == (cstate->attempts++ % 2)) ||
675 (0 == cstate->port) )
677 /* on even rounds, try UNIX first */
678 cstate->sock = try_unixpath (service_name,
680 if (NULL != cstate->sock)
682 connect_success_continuation (cstate);
687 = GNUNET_RESOLVER_ip_get (cstate->hostname,
689 GNUNET_CONNECTION_CONNECT_RETRY_TIMEOUT,
690 &try_connect_using_address,
698 * Implement the destruction of a message queue. Implementations must
699 * not free @a mq, but should take care of @a impl_state.
701 * @param mq the message queue to destroy
702 * @param impl_state our `struct ClientState`
705 connection_client_destroy_impl (struct GNUNET_MQ_Handle *mq,
708 struct ClientState *cstate = impl_state;
710 if (NULL != cstate->dns_active)
711 GNUNET_RESOLVER_ip_get_cancel (cstate->dns_active);
712 if (NULL != cstate->sock)
713 GNUNET_NETWORK_socket_close (cstate->sock);
715 GNUNET_free (cstate->service_name);
716 GNUNET_free_non_null (cstate->hostname);
717 GNUNET_MST_destroy (cstate->mst);
718 GNUNET_free (cstate);
723 * Implements the transmission functionality of a message queue.
725 * @param mq the message queue
726 * @param msg the message to send
727 * @param impl_state our `struct ClientState`
730 connection_client_send_impl (struct GNUNET_MQ_Handle *mq,
731 const struct GNUNET_MessageHeader *msg,
734 struct ClientState *cstate = impl_state;
736 /* only one message at a time allowed */
737 GNUNET_assert (NULL == cstate->msg);
738 GNUNET_assert (NULL == cstate->send_task);
742 = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
750 * Cancel the currently sent message.
752 * @param mq message queue
753 * @param impl_state our `struct ClientState`
756 connection_client_cancel_impl (struct GNUNET_MQ_Handle *mq,
759 struct ClientState *cstate = impl_state;
761 GNUNET_assert (NULL != cstate->msg);
762 GNUNET_assert (0 == cstate->msg_off);
764 GNUNET_SCHEDULER_cancel (cstate->send_task);
765 cstate->send_task = NULL;
770 * Create a message queue to connect to a GNUnet service.
771 * If handlers are specfied, receive messages from the connection.
773 * @param connection the client connection
774 * @param handlers handlers for receiving messages, can be NULL
775 * @param error_handler error handler
776 * @param error_handler_cls closure for the @a error_handler
777 * @return the message queue, NULL on error
779 struct GNUNET_MQ_Handle *
780 GNUNET_CLIENT_connecT2 (const struct GNUNET_CONFIGURATION_Handle *cfg,
781 const char *service_name,
782 const struct GNUNET_MQ_MessageHandler *handlers,
783 GNUNET_MQ_ErrorHandler error_handler,
784 void *error_handler_cls)
786 struct ClientState *cstate;
789 test_service_configuration (service_name,
792 cstate = GNUNET_new (struct ClientState);
793 cstate->service_name = GNUNET_strdup (service_name);
795 cstate->retry_task = GNUNET_SCHEDULER_add_now (&start_connect,
797 cstate->msg = GNUNET_MST_create (&recv_message,
800 GNUNET_CONFIGURATION_have_value (cfg,
805 GNUNET_CONFIGURATION_get_value_number (cfg,
809 (cstate->port > 65535) ||
811 GNUNET_CONFIGURATION_get_value_string (cfg,
814 &cstate->hostname)) )
816 if (0 == strlen (cstate->hostname))
818 GNUNET_free (cstate->hostname);
819 cstate->hostname = NULL;
820 LOG (GNUNET_ERROR_TYPE_WARNING,
821 _("Need a non-empty hostname for service `%s'.\n"),
827 return GNUNET_MQ_queue_for_callbacks (&connection_client_send_impl,
828 &connection_client_destroy_impl,
829 &connection_client_cancel_impl,
836 /* end of client_new.c */