2 This file is part of GNUnet.
3 Copyright (C) 2001-2016, 2019 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
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_resolver_service.h"
33 #include "gnunet_socks.h"
36 #define LOG(kind, ...) GNUNET_log_from (kind, "util-client", __VA_ARGS__)
39 * Timeout we use on TCP connect before trying another
40 * result from the DNS resolver. Actual value used
41 * is this value divided by the number of address families.
44 #define CONNECT_RETRY_TIMEOUT GNUNET_TIME_relative_multiply ( \
45 GNUNET_TIME_UNIT_SECONDS, 5)
49 * Internal state for a client connected to a GNUnet service.
55 * During connect, we try multiple possible IP addresses
56 * to find out which one might work.
61 * This is a linked list.
63 struct AddressProbe *next;
66 * This is a doubly-linked list.
68 struct AddressProbe *prev;
71 * The address; do not free (allocated at the end of this struct).
73 const struct sockaddr *addr;
76 * Underlying OS's socket.
78 struct GNUNET_NETWORK_Handle *sock;
81 * Connection for which we are probing.
83 struct ClientState *cstate;
91 * Task waiting for the connection to finish connecting.
93 struct GNUNET_SCHEDULER_Task *task;
98 * Internal state for a client connected to a GNUnet service.
103 * The connection handle, NULL if not live
105 struct GNUNET_NETWORK_Handle *sock;
108 * Handle to a pending DNS lookup request, NULL if DNS is finished.
110 struct GNUNET_RESOLVER_RequestHandle *dns_active;
115 const struct GNUNET_CONFIGURATION_Handle *cfg;
118 * Linked list of sockets we are currently trying out
121 struct AddressProbe *ap_head;
124 * Linked list of sockets we are currently trying out
127 struct AddressProbe *ap_tail;
130 * Name of the service we interact with.
140 * Next message to transmit to the service. NULL for none.
142 const struct GNUNET_MessageHeader *msg;
145 * Task for trying to connect to the service.
147 struct GNUNET_SCHEDULER_Task *retry_task;
150 * Task for sending messages to the service.
152 struct GNUNET_SCHEDULER_Task *send_task;
155 * Task for sending messages to the service.
157 struct GNUNET_SCHEDULER_Task *recv_task;
160 * Tokenizer for inbound messages.
162 struct GNUNET_MessageStreamTokenizer *mst;
165 * Message queue under our control.
167 struct GNUNET_MQ_Handle *mq;
170 * Timeout for receiving a response (absolute time).
172 struct GNUNET_TIME_Absolute receive_timeout;
175 * Current value for our incremental back-off (for
178 struct GNUNET_TIME_Relative back_off;
181 * TCP port (0 for disabled).
183 unsigned long long port;
186 * Offset in the message where we are for transmission.
191 * How often have we tried to connect?
193 unsigned int attempts;
196 * Are we supposed to die? #GNUNET_SYSERR if destruction must be
197 * deferred, #GNUNET_NO by default, #GNUNET_YES if destruction was
205 * Try to connect to the service.
207 * @param cls the `struct ClientState` to try to connect to the service
210 start_connect (void *cls);
214 * We've failed for good to establish a connection (timeout or
215 * no more addresses to try).
217 * @param cstate the connection we tried to establish
220 connect_fail_continuation (struct ClientState *cstate)
222 GNUNET_break (NULL == cstate->ap_head);
223 GNUNET_break (NULL == cstate->ap_tail);
224 GNUNET_break (NULL == cstate->dns_active);
225 GNUNET_break (NULL == cstate->sock);
226 GNUNET_assert (NULL == cstate->send_task);
227 GNUNET_assert (NULL == cstate->recv_task);
228 // GNUNET_assert (NULL == cstate->proxy_handshake);
230 cstate->back_off = GNUNET_TIME_STD_BACKOFF (cstate->back_off);
231 LOG (GNUNET_ERROR_TYPE_DEBUG,
232 "Failed to establish connection to `%s', no further addresses to try, will try again in %s.\n",
233 cstate->service_name,
234 GNUNET_STRINGS_relative_time_to_string (cstate->back_off,
237 = GNUNET_SCHEDULER_add_delayed (cstate->back_off,
244 * We are ready to send a message to the service.
246 * @param cls the `struct ClientState` with the `msg` to transmit
249 transmit_ready (void *cls)
251 struct ClientState *cstate = cls;
255 int notify_in_flight;
257 cstate->send_task = NULL;
258 if (GNUNET_YES == cstate->in_destroy)
260 pos = (const char *) cstate->msg;
261 len = ntohs (cstate->msg->size);
262 GNUNET_assert (cstate->msg_off < len);
263 LOG (GNUNET_ERROR_TYPE_DEBUG,
264 "message of type %u trying to send with socket %p (MQ: %p\n",
265 ntohs (cstate->msg->type),
270 ret = GNUNET_NETWORK_socket_send (cstate->sock,
271 &pos[cstate->msg_off],
272 len - cstate->msg_off);
274 ( (EAGAIN == errno) ||
282 LOG (GNUNET_ERROR_TYPE_WARNING,
283 "Error during sending message of type %u: %s\n",
284 ntohs (cstate->msg->type),
288 LOG (GNUNET_ERROR_TYPE_DEBUG,
289 "Retrying message of type %u\n",
290 ntohs (cstate->msg->type));
293 GNUNET_MQ_inject_error (cstate->mq,
294 GNUNET_MQ_ERROR_WRITE);
297 notify_in_flight = (0 == cstate->msg_off);
298 cstate->msg_off += ret;
299 if (cstate->msg_off < len)
301 LOG (GNUNET_ERROR_TYPE_DEBUG,
302 "rescheduling message of type %u\n",
303 ntohs (cstate->msg->type));
305 = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
309 if (notify_in_flight)
310 GNUNET_MQ_impl_send_in_flight (cstate->mq);
313 LOG (GNUNET_ERROR_TYPE_DEBUG,
314 "sending message of type %u successful\n",
315 ntohs (cstate->msg->type));
317 GNUNET_MQ_impl_send_continue (cstate->mq);
322 * We have received a full message, pass to the MQ dispatcher.
323 * Called by the tokenizer via #receive_ready().
325 * @param cls the `struct ClientState`
326 * @param msg message we received.
327 * @return #GNUNET_OK on success,
328 * #GNUNET_NO to stop further processing due to disconnect (no error)
329 * #GNUNET_SYSERR to stop further processing due to error
332 recv_message (void *cls,
333 const struct GNUNET_MessageHeader *msg)
335 struct ClientState *cstate = cls;
337 if (GNUNET_YES == cstate->in_destroy)
339 LOG (GNUNET_ERROR_TYPE_DEBUG,
340 "Received message of type %u and size %u from %s\n",
343 cstate->service_name);
344 GNUNET_MQ_inject_message (cstate->mq,
346 if (GNUNET_YES == cstate->in_destroy)
353 * Cancel all remaining connect attempts
355 * @param cstate handle of the client state to process
358 cancel_aps (struct ClientState *cstate)
360 struct AddressProbe *pos;
362 while (NULL != (pos = cstate->ap_head))
364 GNUNET_break (GNUNET_OK ==
365 GNUNET_NETWORK_socket_close (pos->sock));
366 GNUNET_SCHEDULER_cancel (pos->task);
367 GNUNET_CONTAINER_DLL_remove (cstate->ap_head,
376 * Implement the destruction of a message queue. Implementations must
377 * not free @a mq, but should take care of @a impl_state.
379 * @param mq the message queue to destroy
380 * @param impl_state our `struct ClientState`
383 connection_client_destroy_impl (struct GNUNET_MQ_Handle *mq,
386 struct ClientState *cstate = impl_state;
389 if (NULL != cstate->dns_active)
391 GNUNET_RESOLVER_request_cancel (cstate->dns_active);
392 cstate->dns_active = NULL;
394 if (NULL != cstate->send_task)
396 GNUNET_SCHEDULER_cancel (cstate->send_task);
397 cstate->send_task = NULL;
399 if (NULL != cstate->retry_task)
401 GNUNET_SCHEDULER_cancel (cstate->retry_task);
402 cstate->retry_task = NULL;
404 if (GNUNET_SYSERR == cstate->in_destroy)
406 /* defer destruction */
407 cstate->in_destroy = GNUNET_YES;
411 if (NULL != cstate->recv_task)
413 GNUNET_SCHEDULER_cancel (cstate->recv_task);
414 cstate->recv_task = NULL;
416 if (NULL != cstate->sock)
418 LOG (GNUNET_ERROR_TYPE_DEBUG,
419 "destroying socket: %p\n",
421 GNUNET_NETWORK_socket_close (cstate->sock);
424 GNUNET_free (cstate->service_name);
425 GNUNET_free_non_null (cstate->hostname);
426 GNUNET_MST_destroy (cstate->mst);
427 GNUNET_free (cstate);
432 * This function is called once we have data ready to read.
434 * @param cls `struct ClientState` with connection to read from
437 receive_ready (void *cls)
439 struct ClientState *cstate = cls;
442 cstate->recv_task = NULL;
443 cstate->in_destroy = GNUNET_SYSERR;
444 ret = GNUNET_MST_read (cstate->mst,
448 if (GNUNET_SYSERR == ret)
450 if (NULL != cstate->mq)
451 GNUNET_MQ_inject_error (cstate->mq,
452 GNUNET_MQ_ERROR_READ);
453 if (GNUNET_YES == cstate->in_destroy)
454 connection_client_destroy_impl (cstate->mq,
458 if (GNUNET_YES == cstate->in_destroy)
460 connection_client_destroy_impl (cstate->mq,
464 cstate->in_destroy = GNUNET_NO;
466 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
474 * We've succeeded in establishing a connection.
476 * @param cstate the connection we tried to establish
479 connect_success_continuation (struct ClientState *cstate)
481 GNUNET_assert (NULL == cstate->recv_task);
483 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
487 if (NULL != cstate->msg)
489 GNUNET_assert (NULL == cstate->send_task);
491 = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
500 * Try connecting to the server using UNIX domain sockets.
502 * @param service_name name of service to connect to
503 * @param cfg configuration to use
504 * @return NULL on error, socket connected to UNIX otherwise
506 static struct GNUNET_NETWORK_Handle *
507 try_unixpath (const char *service_name,
508 const struct GNUNET_CONFIGURATION_Handle *cfg)
511 struct GNUNET_NETWORK_Handle *sock;
513 struct sockaddr_un s_un;
517 GNUNET_CONFIGURATION_get_value_filename (cfg,
521 (0 < strlen (unixpath)))
523 /* We have a non-NULL unixpath, need to validate it */
524 if (strlen (unixpath) >= sizeof(s_un.sun_path))
526 LOG (GNUNET_ERROR_TYPE_WARNING,
527 _ ("UNIXPATH `%s' too long, maximum length is %llu\n"),
529 (unsigned long long) sizeof(s_un.sun_path));
530 unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
531 LOG (GNUNET_ERROR_TYPE_INFO,
532 _ ("Using `%s' instead\n"),
534 if (NULL == unixpath)
540 s_un.sun_family = AF_UNIX;
541 GNUNET_strlcpy (s_un.sun_path,
543 sizeof(s_un.sun_path));
544 #if HAVE_SOCKADDR_UN_SUN_LEN
545 s_un.sun_len = (u_char) sizeof(struct sockaddr_un);
547 sock = GNUNET_NETWORK_socket_create (AF_UNIX,
550 if ((NULL != sock) &&
552 GNUNET_NETWORK_socket_connect (sock,
553 (struct sockaddr *) &s_un,
555 (EINPROGRESS == errno)))
557 LOG (GNUNET_ERROR_TYPE_DEBUG,
558 "Successfully connected to unixpath `%s'!\n",
560 GNUNET_free (unixpath);
564 GNUNET_NETWORK_socket_close (sock);
566 GNUNET_free_non_null (unixpath);
573 * Scheduler let us know that we're either ready to write on the
574 * socket OR connect timed out. Do the right thing.
576 * @param cls the `struct AddressProbe *` with the address that we are probing
579 connect_probe_continuation (void *cls)
581 struct AddressProbe *ap = cls;
582 struct ClientState *cstate = ap->cstate;
583 const struct GNUNET_SCHEDULER_TaskContext *tc;
588 GNUNET_assert (NULL != ap->sock);
589 GNUNET_CONTAINER_DLL_remove (cstate->ap_head,
594 tc = GNUNET_SCHEDULER_get_task_context ();
595 if ((0 == (tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) ||
597 GNUNET_NETWORK_socket_getsockopt (ap->sock,
604 GNUNET_break (GNUNET_OK ==
605 GNUNET_NETWORK_socket_close (ap->sock));
607 if ((NULL == cstate->ap_head) &&
608 // (NULL == cstate->proxy_handshake) &&
609 (NULL == cstate->dns_active))
610 connect_fail_continuation (cstate);
613 LOG (GNUNET_ERROR_TYPE_DEBUG,
614 "Connection to `%s' succeeded!\n",
615 cstate->service_name);
616 /* trigger jobs that waited for the connection */
617 GNUNET_assert (NULL == cstate->sock);
618 cstate->sock = ap->sock;
621 connect_success_continuation (cstate);
626 * Try to establish a connection given the specified address.
627 * This function is called by the resolver once we have a DNS reply.
629 * @param cls our `struct ClientState *`
630 * @param addr address to try, NULL for "last call"
631 * @param addrlen length of @a addr
634 try_connect_using_address (void *cls,
635 const struct sockaddr *addr,
638 struct ClientState *cstate = cls;
639 struct AddressProbe *ap;
643 cstate->dns_active = NULL;
644 if ((NULL == cstate->ap_head) &&
645 // (NULL == cstate->proxy_handshake) &&
646 (NULL == cstate->sock))
647 connect_fail_continuation (cstate);
650 if (NULL != cstate->sock)
651 return; /* already connected */
653 LOG (GNUNET_ERROR_TYPE_DEBUG,
654 "Trying to connect using address `%s:%u'\n",
658 ap = GNUNET_malloc (sizeof(struct AddressProbe) + addrlen);
659 ap->addr = (const struct sockaddr *) &ap[1];
660 GNUNET_memcpy (&ap[1],
663 ap->addrlen = addrlen;
666 switch (ap->addr->sa_family)
669 ((struct sockaddr_in *) ap->addr)->sin_port = htons (cstate->port);
673 ((struct sockaddr_in6 *) ap->addr)->sin6_port = htons (cstate->port);
679 return; /* not supported by us */
681 ap->sock = GNUNET_NETWORK_socket_create (ap->addr->sa_family,
684 if (NULL == ap->sock)
687 return; /* not supported by OS */
690 GNUNET_NETWORK_socket_connect (ap->sock,
693 (EINPROGRESS != errno))
695 /* maybe refused / unsupported address, try next */
696 GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO,
698 GNUNET_break (GNUNET_OK ==
699 GNUNET_NETWORK_socket_close (ap->sock));
703 GNUNET_CONTAINER_DLL_insert (cstate->ap_head,
706 ap->task = GNUNET_SCHEDULER_add_write_net (CONNECT_RETRY_TIMEOUT,
708 &connect_probe_continuation,
714 * Test whether the configuration has proper values for connection
715 * (UNIXPATH || (PORT && HOSTNAME)).
717 * @param service_name name of service to connect to
718 * @param cfg configuration to use
719 * @return #GNUNET_OK if the configuration is valid, #GNUNET_SYSERR if not
722 test_service_configuration (const char *service_name,
723 const struct GNUNET_CONFIGURATION_Handle *cfg)
725 int ret = GNUNET_SYSERR;
726 char *hostname = NULL;
727 unsigned long long port;
730 char *unixpath = NULL;
733 GNUNET_CONFIGURATION_get_value_filename (cfg,
737 (0 < strlen (unixpath)))
739 else if ((GNUNET_OK ==
740 GNUNET_CONFIGURATION_have_value (cfg,
744 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
747 _ ("not a valid filename"));
748 return GNUNET_SYSERR; /* UNIXPATH specified but invalid! */
750 GNUNET_free_non_null (unixpath);
754 GNUNET_CONFIGURATION_have_value (cfg,
758 GNUNET_CONFIGURATION_get_value_number (cfg,
765 GNUNET_CONFIGURATION_get_value_string (cfg,
769 (0 != strlen (hostname)))
771 GNUNET_free_non_null (hostname);
777 * Try to connect to the service.
779 * @param cls the `struct ClientState` to try to connect to the service
782 start_connect (void *cls)
784 struct ClientState *cstate = cls;
786 cstate->retry_task = NULL;
788 /* Never use a local source if a proxy is configured */
790 GNUNET_SOCKS_check_service (cstate->service_name,
793 socks_connect (cstate);
798 if ((0 == (cstate->attempts++ % 2)) ||
799 (0 == cstate->port) ||
800 (NULL == cstate->hostname))
802 /* on even rounds, try UNIX first, or always
803 if we do not have a DNS name and TCP port. */
804 cstate->sock = try_unixpath (cstate->service_name,
806 if (NULL != cstate->sock)
808 connect_success_continuation (cstate);
812 if ((NULL == cstate->hostname) ||
815 /* All options failed. Boo! */
816 connect_fail_continuation (cstate);
820 = GNUNET_RESOLVER_ip_get (cstate->hostname,
822 CONNECT_RETRY_TIMEOUT,
823 &try_connect_using_address,
829 * Implements the transmission functionality of a message queue.
831 * @param mq the message queue
832 * @param msg the message to send
833 * @param impl_state our `struct ClientState`
836 connection_client_send_impl (struct GNUNET_MQ_Handle *mq,
837 const struct GNUNET_MessageHeader *msg,
840 struct ClientState *cstate = impl_state;
843 /* only one message at a time allowed */
844 GNUNET_assert (NULL == cstate->msg);
845 GNUNET_assert (NULL == cstate->send_task);
848 if (NULL == cstate->sock)
850 LOG (GNUNET_ERROR_TYPE_DEBUG,
851 "message of type %u waiting for socket\n",
853 return; /* still waiting for connection */
856 = GNUNET_SCHEDULER_add_now (&transmit_ready,
862 * Cancel the currently sent message.
864 * @param mq message queue
865 * @param impl_state our `struct ClientState`
868 connection_client_cancel_impl (struct GNUNET_MQ_Handle *mq,
871 struct ClientState *cstate = impl_state;
874 GNUNET_assert (NULL != cstate->msg);
875 GNUNET_assert (0 == cstate->msg_off);
877 if (NULL != cstate->send_task)
879 GNUNET_SCHEDULER_cancel (cstate->send_task);
880 cstate->send_task = NULL;
886 * Test if the port or UNIXPATH of the given @a service_name
887 * is in use and thus (most likely) the respective service is up.
889 * @param cfg our configuration
890 * @param service_name name of the service to connect to
891 * @return #GNUNET_YES if the service is (likely) up,
892 * #GNUNET_NO if the service is (definitively) down,
893 * #GNUNET_SYSERR if the configuration does not give us
894 * the necessary information about the service, or if
895 * we could not check (i.e. socket() failed)
898 GNUNET_CLIENT_test (const struct GNUNET_CONFIGURATION_Handle *cfg,
899 const char *service_name)
901 char *hostname = NULL;
902 unsigned long long port;
907 char *unixpath = NULL;
910 GNUNET_CONFIGURATION_get_value_filename (cfg,
915 if (0 == strlen (unixpath))
917 GNUNET_free (unixpath);
918 return GNUNET_SYSERR; /* empty string not OK */
920 if (0 == access (unixpath,
923 GNUNET_free (unixpath);
924 return GNUNET_OK; /* file exists, we assume service is running */
926 GNUNET_free (unixpath);
928 else if (GNUNET_OK ==
929 GNUNET_CONFIGURATION_have_value (cfg,
933 /* UNIXPATH specified but not a valid path! */
934 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
937 _ ("not a valid filename"));
938 return GNUNET_SYSERR;
944 GNUNET_CONFIGURATION_get_value_number (cfg,
951 return GNUNET_SYSERR;
954 GNUNET_CONFIGURATION_get_value_string (cfg,
959 /* We always assume remotes are up */
964 /* We look for evidence the service is up */
967 if ( (NULL == hostname) ||
968 (0 == strcasecmp (hostname,
970 (0 == strcasecmp (hostname,
973 /* service runs on loopback */
974 struct sockaddr_in v4;
975 struct sockaddr_in6 v6;
978 memset (&v4, 0, sizeof (v4));
979 memset (&v6, 0, sizeof (v6));
980 v4.sin_family = AF_INET;
981 v4.sin_port = htons ((uint16_t) port);
982 #if HAVE_SOCKADDR_IN_SUN_LEN
983 v4.sin_len = (u_char) sizeof(struct sockaddr_in);
989 sock = socket (AF_INET,
995 (struct sockaddr *) &v4,
998 /* bind failed, so someone is listening! */
1001 (void) close (sock);
1005 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
1007 if (GNUNET_NO == ret)
1008 ret = GNUNET_SYSERR;
1010 v6.sin6_family = AF_INET6;
1011 v6.sin6_port = htons ((uint16_t) port);
1012 #if HAVE_SOCKADDR_IN_SUN_LEN
1013 v6.sin6_len = (u_char) sizeof(struct sockaddr_in6);
1015 inet_pton (AF_INET6,
1018 sock = socket (AF_INET6,
1023 if (0 != bind (sock,
1024 (struct sockaddr *) &v6,
1027 /* bind failed, so someone is listening! */
1030 (void) close (sock);
1034 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
1036 /* not changing 'ret' intentionally here, as
1037 v4 succeeding and v6 failing just means we
1043 /* service running remotely */
1046 GNUNET_free_non_null (hostname);
1052 * Create a message queue to connect to a GNUnet service.
1053 * If handlers are specfied, receive messages from the connection.
1055 * @param cfg our configuration
1056 * @param service_name name of the service to connect to
1057 * @param handlers handlers for receiving messages, can be NULL
1058 * @param error_handler error handler
1059 * @param error_handler_cls closure for the @a error_handler
1060 * @return the message queue, NULL on error
1062 struct GNUNET_MQ_Handle *
1063 GNUNET_CLIENT_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
1064 const char *service_name,
1065 const struct GNUNET_MQ_MessageHandler *handlers,
1066 GNUNET_MQ_ErrorHandler error_handler,
1067 void *error_handler_cls)
1069 struct ClientState *cstate;
1072 test_service_configuration (service_name,
1075 cstate = GNUNET_new (struct ClientState);
1076 cstate->service_name = GNUNET_strdup (service_name);
1078 cstate->retry_task = GNUNET_SCHEDULER_add_now (&start_connect,
1080 cstate->mst = GNUNET_MST_create (&recv_message,
1083 GNUNET_CONFIGURATION_have_value (cfg,
1087 if (! ((GNUNET_OK !=
1088 GNUNET_CONFIGURATION_get_value_number (cfg,
1092 (cstate->port > 65535) ||
1094 GNUNET_CONFIGURATION_get_value_string (cfg,
1097 &cstate->hostname))) &&
1098 (0 == strlen (cstate->hostname)))
1100 GNUNET_free (cstate->hostname);
1101 cstate->hostname = NULL;
1102 LOG (GNUNET_ERROR_TYPE_WARNING,
1103 _ ("Need a non-empty hostname for service `%s'.\n"),
1107 cstate->mq = GNUNET_MQ_queue_for_callbacks (&connection_client_send_impl,
1108 &connection_client_destroy_impl,
1109 &connection_client_cancel_impl,
1118 /* end of client.c */