Merge branch 'cadet-new-options'
[oweals/gnunet.git] / src / util / client.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2001-2016 GNUnet e.V.
4
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.
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      Affero General Public License for more details.
14
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/>.
17
18      SPDX-License-Identifier: AGPL3.0-or-later
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_resolver_service.h"
33 #include "gnunet_socks.h"
34
35
36 #define LOG(kind,...) GNUNET_log_from (kind, "util-client",__VA_ARGS__)
37
38 /**
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.
42  * Default is 5s.
43  */
44 #define CONNECT_RETRY_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
45
46
47
48 /**
49  * Internal state for a client connected to a GNUnet service.
50  */
51 struct ClientState;
52
53
54 /**
55  * During connect, we try multiple possible IP addresses
56  * to find out which one might work.
57  */
58 struct AddressProbe
59 {
60
61   /**
62    * This is a linked list.
63    */
64   struct AddressProbe *next;
65
66   /**
67    * This is a doubly-linked list.
68    */
69   struct AddressProbe *prev;
70
71   /**
72    * The address; do not free (allocated at the end of this struct).
73    */
74   const struct sockaddr *addr;
75
76   /**
77    * Underlying OS's socket.
78    */
79   struct GNUNET_NETWORK_Handle *sock;
80
81   /**
82    * Connection for which we are probing.
83    */
84   struct ClientState *cstate;
85
86   /**
87    * Lenth of addr.
88    */
89   socklen_t addrlen;
90
91   /**
92    * Task waiting for the connection to finish connecting.
93    */
94   struct GNUNET_SCHEDULER_Task *task;
95 };
96
97
98 /**
99  * Internal state for a client connected to a GNUnet service.
100  */
101 struct ClientState
102 {
103
104   /**
105    * The connection handle, NULL if not live
106    */
107   struct GNUNET_NETWORK_Handle *sock;
108
109   /**
110    * Handle to a pending DNS lookup request, NULL if DNS is finished.
111    */
112   struct GNUNET_RESOLVER_RequestHandle *dns_active;
113
114   /**
115    * Our configuration.
116    */
117   const struct GNUNET_CONFIGURATION_Handle *cfg;
118
119   /**
120    * Linked list of sockets we are currently trying out
121    * (during connect).
122    */
123   struct AddressProbe *ap_head;
124
125   /**
126    * Linked list of sockets we are currently trying out
127    * (during connect).
128    */
129   struct AddressProbe *ap_tail;
130
131   /**
132    * Name of the service we interact with.
133    */
134   char *service_name;
135
136   /**
137    * Hostname, if any.
138    */
139   char *hostname;
140
141   /**
142    * Next message to transmit to the service. NULL for none.
143    */
144   const struct GNUNET_MessageHeader *msg;
145
146   /**
147    * Task for trying to connect to the service.
148    */
149   struct GNUNET_SCHEDULER_Task *retry_task;
150
151   /**
152    * Task for sending messages to the service.
153    */
154   struct GNUNET_SCHEDULER_Task *send_task;
155
156   /**
157    * Task for sending messages to the service.
158    */
159   struct GNUNET_SCHEDULER_Task *recv_task;
160
161   /**
162    * Tokenizer for inbound messages.
163    */
164   struct GNUNET_MessageStreamTokenizer *mst;
165
166   /**
167    * Message queue under our control.
168    */
169   struct GNUNET_MQ_Handle *mq;
170
171   /**
172    * Timeout for receiving a response (absolute time).
173    */
174   struct GNUNET_TIME_Absolute receive_timeout;
175
176   /**
177    * Current value for our incremental back-off (for
178    * connect re-tries).
179    */
180   struct GNUNET_TIME_Relative back_off;
181
182   /**
183    * TCP port (0 for disabled).
184    */
185   unsigned long long port;
186
187   /**
188    * Offset in the message where we are for transmission.
189    */
190   size_t msg_off;
191
192   /**
193    * How often have we tried to connect?
194    */
195   unsigned int attempts;
196
197   /**
198    * Are we supposed to die?  #GNUNET_SYSERR if destruction must be
199    * deferred, #GNUNET_NO by default, #GNUNET_YES if destruction was
200    * deferred.
201    */
202   int in_destroy;
203
204 };
205
206
207 /**
208  * Try to connect to the service.
209  *
210  * @param cls the `struct ClientState` to try to connect to the service
211  */
212 static void
213 start_connect (void *cls);
214
215
216 /**
217  * We've failed for good to establish a connection (timeout or
218  * no more addresses to try).
219  *
220  * @param cstate the connection we tried to establish
221  */
222 static void
223 connect_fail_continuation (struct ClientState *cstate)
224 {
225   GNUNET_break (NULL == cstate->ap_head);
226   GNUNET_break (NULL == cstate->ap_tail);
227   GNUNET_break (NULL == cstate->dns_active);
228   GNUNET_break (NULL == cstate->sock);
229   GNUNET_assert (NULL == cstate->send_task);
230   GNUNET_assert (NULL == cstate->recv_task);
231   // GNUNET_assert (NULL == cstate->proxy_handshake);
232
233   cstate->back_off = GNUNET_TIME_STD_BACKOFF (cstate->back_off);
234   LOG (GNUNET_ERROR_TYPE_DEBUG,
235        "Failed to establish connection to `%s', no further addresses to try, will try again in %s.\n",
236        cstate->service_name,
237        GNUNET_STRINGS_relative_time_to_string (cstate->back_off,
238                                                GNUNET_YES));
239   cstate->retry_task
240     = GNUNET_SCHEDULER_add_delayed (cstate->back_off,
241                                     &start_connect,
242                                     cstate);
243 }
244
245
246 /**
247  * We are ready to send a message to the service.
248  *
249  * @param cls the `struct ClientState` with the `msg` to transmit
250  */
251 static void
252 transmit_ready (void *cls)
253 {
254   struct ClientState *cstate = cls;
255   ssize_t ret;
256   size_t len;
257   const char *pos;
258   int notify_in_flight;
259
260   cstate->send_task = NULL;
261   if (GNUNET_YES == cstate->in_destroy)
262     return;
263   pos = (const char *) cstate->msg;
264   len = ntohs (cstate->msg->size);
265   GNUNET_assert (cstate->msg_off < len);
266   LOG (GNUNET_ERROR_TYPE_DEBUG,
267        "message of type %u trying to send with socket %p (MQ: %p\n",
268        ntohs(cstate->msg->type),
269        cstate->sock,
270        cstate->mq);
271
272  RETRY:
273   ret = GNUNET_NETWORK_socket_send (cstate->sock,
274                                     &pos[cstate->msg_off],
275                                     len - cstate->msg_off);
276   if (-1 == ret)
277   {
278     LOG (GNUNET_ERROR_TYPE_WARNING,
279          "Error during sending message of type %u\n",
280          ntohs(cstate->msg->type));
281     if (EINTR == errno){
282       LOG (GNUNET_ERROR_TYPE_DEBUG,
283            "Retrying message of type %u\n",
284            ntohs(cstate->msg->type));
285       goto RETRY;
286     }
287     GNUNET_MQ_inject_error (cstate->mq,
288                             GNUNET_MQ_ERROR_WRITE);
289     return;
290   }
291   notify_in_flight = (0 == cstate->msg_off);
292   cstate->msg_off += ret;
293   if (cstate->msg_off < len)
294   {
295     LOG (GNUNET_ERROR_TYPE_DEBUG,
296          "rescheduling message of type %u\n",
297          ntohs(cstate->msg->type));
298     cstate->send_task
299       = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
300                                         cstate->sock,
301                                         &transmit_ready,
302                                         cstate);
303     if (notify_in_flight)
304       GNUNET_MQ_impl_send_in_flight (cstate->mq);
305     return;
306   }
307   LOG (GNUNET_ERROR_TYPE_DEBUG,
308        "sending message of type %u successful\n",
309        ntohs(cstate->msg->type));
310   cstate->msg = NULL;
311   GNUNET_MQ_impl_send_continue (cstate->mq);
312 }
313
314
315 /**
316  * We have received a full message, pass to the MQ dispatcher.
317  * Called by the tokenizer via #receive_ready().
318  *
319  * @param cls the `struct ClientState`
320  * @param msg message we received.
321  * @return #GNUNET_OK on success,
322  *     #GNUNET_NO to stop further processing due to disconnect (no error)
323  *     #GNUNET_SYSERR to stop further processing due to error
324  */
325 static int
326 recv_message (void *cls,
327               const struct GNUNET_MessageHeader *msg)
328 {
329   struct ClientState *cstate = cls;
330
331   if (GNUNET_YES == cstate->in_destroy)
332     return GNUNET_NO;
333   LOG (GNUNET_ERROR_TYPE_DEBUG,
334        "Received message of type %u and size %u from %s\n",
335        ntohs (msg->type),
336        ntohs (msg->size),
337        cstate->service_name);
338   GNUNET_MQ_inject_message (cstate->mq,
339                             msg);
340   if (GNUNET_YES == cstate->in_destroy)
341     return GNUNET_NO;
342   return GNUNET_OK;
343 }
344
345
346 /**
347  * Cancel all remaining connect attempts
348  *
349  * @param cstate handle of the client state to process
350  */
351 static void
352 cancel_aps (struct ClientState *cstate)
353 {
354   struct AddressProbe *pos;
355
356   while (NULL != (pos = cstate->ap_head))
357   {
358     GNUNET_break (GNUNET_OK ==
359                   GNUNET_NETWORK_socket_close (pos->sock));
360     GNUNET_SCHEDULER_cancel (pos->task);
361     GNUNET_CONTAINER_DLL_remove (cstate->ap_head,
362                                  cstate->ap_tail,
363                                  pos);
364     GNUNET_free (pos);
365   }
366 }
367
368
369 /**
370  * Implement the destruction of a message queue.  Implementations must
371  * not free @a mq, but should take care of @a impl_state.
372  *
373  * @param mq the message queue to destroy
374  * @param impl_state our `struct ClientState`
375  */
376 static void
377 connection_client_destroy_impl (struct GNUNET_MQ_Handle *mq,
378                                 void *impl_state)
379 {
380   struct ClientState *cstate = impl_state;
381
382   (void) mq;
383   if (NULL != cstate->dns_active)
384   {
385     GNUNET_RESOLVER_request_cancel (cstate->dns_active);
386     cstate->dns_active = NULL;
387   }
388   if (NULL != cstate->send_task)
389   {
390     GNUNET_SCHEDULER_cancel (cstate->send_task);
391     cstate->send_task = NULL;
392   }
393   if (NULL != cstate->retry_task)
394   {
395     GNUNET_SCHEDULER_cancel (cstate->retry_task);
396     cstate->retry_task = NULL;
397   }
398   if (GNUNET_SYSERR == cstate->in_destroy)
399   {
400     /* defer destruction */
401     cstate->in_destroy = GNUNET_YES;
402     cstate->mq = NULL;
403     return;
404   }
405   if (NULL != cstate->recv_task)
406   {
407     GNUNET_SCHEDULER_cancel (cstate->recv_task);
408     cstate->recv_task = NULL;
409   }
410   if (NULL != cstate->sock)
411   {
412     LOG (GNUNET_ERROR_TYPE_DEBUG,
413          "destroying socket: %p\n",
414          cstate->sock);
415     GNUNET_NETWORK_socket_close (cstate->sock);
416   }
417   cancel_aps (cstate);
418   GNUNET_free (cstate->service_name);
419   GNUNET_free_non_null (cstate->hostname);
420   GNUNET_MST_destroy (cstate->mst);
421   GNUNET_free (cstate);
422 }
423
424
425 /**
426  * This function is called once we have data ready to read.
427  *
428  * @param cls `struct ClientState` with connection to read from
429  */
430 static void
431 receive_ready (void *cls)
432 {
433   struct ClientState *cstate = cls;
434   int ret;
435
436   cstate->recv_task = NULL;
437   cstate->in_destroy = GNUNET_SYSERR;
438   ret = GNUNET_MST_read (cstate->mst,
439                          cstate->sock,
440                          GNUNET_NO,
441                          GNUNET_NO);
442   if (GNUNET_SYSERR == ret)
443   {
444     if (NULL != cstate->mq)
445       GNUNET_MQ_inject_error (cstate->mq,
446                               GNUNET_MQ_ERROR_READ);
447     if (GNUNET_YES == cstate->in_destroy)
448       connection_client_destroy_impl (cstate->mq,
449                                       cstate);
450     return;
451   }
452   if (GNUNET_YES == cstate->in_destroy)
453   {
454     connection_client_destroy_impl (cstate->mq,
455                                     cstate);
456     return;
457   }
458   cstate->in_destroy = GNUNET_NO;
459   cstate->recv_task
460     = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
461                                      cstate->sock,
462                                      &receive_ready,
463                                      cstate);
464 }
465
466
467 /**
468  * We've succeeded in establishing a connection.
469  *
470  * @param cstate the connection we tried to establish
471  */
472 static void
473 connect_success_continuation (struct ClientState *cstate)
474 {
475   GNUNET_assert (NULL == cstate->recv_task);
476   cstate->recv_task
477     = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
478                                      cstate->sock,
479                                      &receive_ready,
480                                      cstate);
481   if (NULL != cstate->msg)
482   {
483     GNUNET_assert (NULL == cstate->send_task);
484     cstate->send_task
485       = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
486                                         cstate->sock,
487                                         &transmit_ready,
488                                         cstate);
489   }
490 }
491
492
493 /**
494  * Try connecting to the server using UNIX domain sockets.
495  *
496  * @param service_name name of service to connect to
497  * @param cfg configuration to use
498  * @return NULL on error, socket connected to UNIX otherwise
499  */
500 static struct GNUNET_NETWORK_Handle *
501 try_unixpath (const char *service_name,
502               const struct GNUNET_CONFIGURATION_Handle *cfg)
503 {
504 #if AF_UNIX
505   struct GNUNET_NETWORK_Handle *sock;
506   char *unixpath;
507   struct sockaddr_un s_un;
508
509   unixpath = NULL;
510   if ((GNUNET_OK ==
511        GNUNET_CONFIGURATION_get_value_filename (cfg,
512                                                 service_name,
513                                                 "UNIXPATH",
514                                                 &unixpath)) &&
515       (0 < strlen (unixpath)))
516   {
517     /* We have a non-NULL unixpath, need to validate it */
518     if (strlen (unixpath) >= sizeof (s_un.sun_path))
519     {
520       LOG (GNUNET_ERROR_TYPE_WARNING,
521            _("UNIXPATH `%s' too long, maximum length is %llu\n"),
522            unixpath,
523            (unsigned long long) sizeof (s_un.sun_path));
524       unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
525       LOG (GNUNET_ERROR_TYPE_INFO,
526            _("Using `%s' instead\n"),
527            unixpath);
528       if (NULL == unixpath)
529         return NULL;
530     }
531     memset (&s_un,
532             0,
533             sizeof (s_un));
534     s_un.sun_family = AF_UNIX;
535     GNUNET_strlcpy (s_un.sun_path,
536                     unixpath,
537                     sizeof (s_un.sun_path));
538 #ifdef LINUX
539     {
540       int abstract;
541
542       abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg,
543                                                        "TESTING",
544                                                        "USE_ABSTRACT_SOCKETS");
545       if (GNUNET_YES == abstract)
546         s_un.sun_path[0] = '\0';
547     }
548 #endif
549 #if HAVE_SOCKADDR_UN_SUN_LEN
550     s_un.sun_len = (u_char) sizeof (struct sockaddr_un);
551 #endif
552     sock = GNUNET_NETWORK_socket_create (AF_UNIX,
553                                          SOCK_STREAM,
554                                          0);
555     if ( (NULL != sock) &&
556          ( (GNUNET_OK ==
557             GNUNET_NETWORK_socket_connect (sock,
558                                            (struct sockaddr *) &s_un,
559                                            sizeof (s_un))) ||
560            (EINPROGRESS == errno) ) )
561     {
562       LOG (GNUNET_ERROR_TYPE_DEBUG,
563            "Successfully connected to unixpath `%s'!\n",
564            unixpath);
565       GNUNET_free (unixpath);
566       return sock;
567     }
568     if (NULL != sock)
569       GNUNET_NETWORK_socket_close (sock);
570   }
571   GNUNET_free_non_null (unixpath);
572 #endif
573   return NULL;
574 }
575
576
577 /**
578  * Scheduler let us know that we're either ready to write on the
579  * socket OR connect timed out.  Do the right thing.
580  *
581  * @param cls the `struct AddressProbe *` with the address that we are probing
582  */
583 static void
584 connect_probe_continuation (void *cls)
585 {
586   struct AddressProbe *ap = cls;
587   struct ClientState *cstate = ap->cstate;
588   const struct GNUNET_SCHEDULER_TaskContext *tc;
589   int error;
590   socklen_t len;
591
592   ap->task = NULL;
593   GNUNET_assert (NULL != ap->sock);
594   GNUNET_CONTAINER_DLL_remove (cstate->ap_head,
595                                cstate->ap_tail,
596                                ap);
597   len = sizeof (error);
598   error = 0;
599   tc = GNUNET_SCHEDULER_get_task_context ();
600   if ( (0 == (tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY)) ||
601        (GNUNET_OK !=
602         GNUNET_NETWORK_socket_getsockopt (ap->sock,
603                                           SOL_SOCKET,
604                                           SO_ERROR,
605                                           &error,
606                                           &len)) ||
607        (0 != error) )
608   {
609     GNUNET_break (GNUNET_OK ==
610                   GNUNET_NETWORK_socket_close (ap->sock));
611     GNUNET_free (ap);
612     if ( (NULL == cstate->ap_head) &&
613          //      (NULL == cstate->proxy_handshake) &&
614          (NULL == cstate->dns_active) )
615       connect_fail_continuation (cstate);
616     return;
617   }
618   LOG (GNUNET_ERROR_TYPE_DEBUG,
619        "Connection to `%s' succeeded!\n",
620        cstate->service_name);
621   /* trigger jobs that waited for the connection */
622   GNUNET_assert (NULL == cstate->sock);
623   cstate->sock = ap->sock;
624   GNUNET_free (ap);
625   cancel_aps (cstate);
626   connect_success_continuation (cstate);
627 }
628
629
630 /**
631  * Try to establish a connection given the specified address.
632  * This function is called by the resolver once we have a DNS reply.
633  *
634  * @param cls our `struct ClientState *`
635  * @param addr address to try, NULL for "last call"
636  * @param addrlen length of @a addr
637  */
638 static void
639 try_connect_using_address (void *cls,
640                            const struct sockaddr *addr,
641                            socklen_t addrlen)
642 {
643   struct ClientState *cstate = cls;
644   struct AddressProbe *ap;
645
646   if (NULL == addr)
647   {
648     cstate->dns_active = NULL;
649     if ( (NULL == cstate->ap_head) &&
650          //  (NULL == cstate->proxy_handshake) &&
651          (NULL == cstate->sock) )
652       connect_fail_continuation (cstate);
653     return;
654   }
655   if (NULL != cstate->sock)
656     return;                     /* already connected */
657   /* try to connect */
658   LOG (GNUNET_ERROR_TYPE_DEBUG,
659        "Trying to connect using address `%s:%u'\n",
660        GNUNET_a2s (addr,
661                    addrlen),
662        cstate->port);
663   ap = GNUNET_malloc (sizeof (struct AddressProbe) + addrlen);
664   ap->addr = (const struct sockaddr *) &ap[1];
665   GNUNET_memcpy (&ap[1],
666                  addr,
667                  addrlen);
668   ap->addrlen = addrlen;
669   ap->cstate = cstate;
670
671   switch (ap->addr->sa_family)
672   {
673   case AF_INET:
674     ((struct sockaddr_in *) ap->addr)->sin_port = htons (cstate->port);
675     break;
676   case AF_INET6:
677     ((struct sockaddr_in6 *) ap->addr)->sin6_port = htons (cstate->port);
678     break;
679   default:
680     GNUNET_break (0);
681     GNUNET_free (ap);
682     return;                     /* not supported by us */
683   }
684   ap->sock = GNUNET_NETWORK_socket_create (ap->addr->sa_family,
685                                            SOCK_STREAM,
686                                            0);
687   if (NULL == ap->sock)
688   {
689     GNUNET_free (ap);
690     return;                     /* not supported by OS */
691   }
692   if ( (GNUNET_OK !=
693         GNUNET_NETWORK_socket_connect (ap->sock,
694                                        ap->addr,
695                                        ap->addrlen)) &&
696        (EINPROGRESS != errno) )
697   {
698     /* maybe refused / unsupported address, try next */
699     GNUNET_log_strerror (GNUNET_ERROR_TYPE_INFO,
700                          "connect");
701     GNUNET_break (GNUNET_OK ==
702                   GNUNET_NETWORK_socket_close (ap->sock));
703     GNUNET_free (ap);
704     return;
705   }
706   GNUNET_CONTAINER_DLL_insert (cstate->ap_head,
707                                cstate->ap_tail,
708                                ap);
709   ap->task = GNUNET_SCHEDULER_add_write_net (CONNECT_RETRY_TIMEOUT,
710                                              ap->sock,
711                                              &connect_probe_continuation,
712                                              ap);
713 }
714
715
716 /**
717  * Test whether the configuration has proper values for connection
718  * (UNIXPATH || (PORT && HOSTNAME)).
719  *
720  * @param service_name name of service to connect to
721  * @param cfg configuration to use
722  * @return #GNUNET_OK if the configuration is valid, #GNUNET_SYSERR if not
723  */
724 static int
725 test_service_configuration (const char *service_name,
726                             const struct GNUNET_CONFIGURATION_Handle *cfg)
727 {
728   int ret = GNUNET_SYSERR;
729   char *hostname = NULL;
730   unsigned long long port;
731 #if AF_UNIX
732   char *unixpath = NULL;
733
734   if ((GNUNET_OK ==
735        GNUNET_CONFIGURATION_get_value_filename (cfg,
736                                                 service_name,
737                                                 "UNIXPATH",
738                                                 &unixpath)) &&
739       (0 < strlen (unixpath)))
740     ret = GNUNET_OK;
741   else if ((GNUNET_OK ==
742             GNUNET_CONFIGURATION_have_value (cfg,
743                                              service_name,
744                                              "UNIXPATH")))
745   {
746     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
747                                service_name,
748                                "UNIXPATH",
749                                _("not a valid filename"));
750     return GNUNET_SYSERR; /* UNIXPATH specified but invalid! */
751   }
752   GNUNET_free_non_null (unixpath);
753 #endif
754
755   if ( (GNUNET_YES ==
756         GNUNET_CONFIGURATION_have_value (cfg,
757                                          service_name,
758                                          "PORT")) &&
759        (GNUNET_OK ==
760         GNUNET_CONFIGURATION_get_value_number (cfg,
761                                                service_name,
762                                                "PORT",
763                                                &port)) &&
764        (port <= 65535) &&
765        (0 != port) &&
766        (GNUNET_OK ==
767         GNUNET_CONFIGURATION_get_value_string (cfg,
768                                                service_name,
769                                                "HOSTNAME",
770                                                &hostname)) &&
771        (0 != strlen (hostname)) )
772     ret = GNUNET_OK;
773   GNUNET_free_non_null (hostname);
774   return ret;
775 }
776
777
778 /**
779  * Try to connect to the service.
780  *
781  * @param cls the `struct ClientState` to try to connect to the service
782  */
783 static void
784 start_connect (void *cls)
785 {
786   struct ClientState *cstate = cls;
787
788   cstate->retry_task = NULL;
789 #if 0
790   /* Never use a local source if a proxy is configured */
791   if (GNUNET_YES ==
792       GNUNET_SOCKS_check_service (cstate->service_name,
793                                   cstate->cfg))
794   {
795     socks_connect (cstate);
796     return;
797   }
798 #endif
799
800   if ( (0 == (cstate->attempts++ % 2)) ||
801        (0 == cstate->port) ||
802        (NULL == cstate->hostname) )
803   {
804     /* on even rounds, try UNIX first, or always
805        if we do not have a DNS name and TCP port. */
806     cstate->sock = try_unixpath (cstate->service_name,
807                                  cstate->cfg);
808     if (NULL != cstate->sock)
809     {
810       connect_success_continuation (cstate);
811       return;
812     }
813   }
814   if ( (NULL == cstate->hostname) ||
815        (0 == cstate->port) )
816   {
817     /* All options failed. Boo! */
818     connect_fail_continuation (cstate);
819     return;
820   }
821   cstate->dns_active
822     = GNUNET_RESOLVER_ip_get (cstate->hostname,
823                               AF_UNSPEC,
824                               CONNECT_RETRY_TIMEOUT,
825                               &try_connect_using_address,
826                               cstate);
827 }
828
829
830 /**
831  * Implements the transmission functionality of a message queue.
832  *
833  * @param mq the message queue
834  * @param msg the message to send
835  * @param impl_state our `struct ClientState`
836  */
837 static void
838 connection_client_send_impl (struct GNUNET_MQ_Handle *mq,
839                              const struct GNUNET_MessageHeader *msg,
840                              void *impl_state)
841 {
842   struct ClientState *cstate = impl_state;
843
844   (void) mq;
845   /* only one message at a time allowed */
846   GNUNET_assert (NULL == cstate->msg);
847   GNUNET_assert (NULL == cstate->send_task);
848   cstate->msg = msg;
849   cstate->msg_off = 0;
850   if (NULL == cstate->sock)
851   {
852     LOG (GNUNET_ERROR_TYPE_DEBUG,
853          "message of type %u waiting for socket\n",
854          ntohs(msg->type));
855     return; /* still waiting for connection */
856   }
857   cstate->send_task
858     = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
859                                       cstate->sock,
860                                       &transmit_ready,
861                                       cstate);
862 }
863
864
865 /**
866  * Cancel the currently sent message.
867  *
868  * @param mq message queue
869  * @param impl_state our `struct ClientState`
870  */
871 static void
872 connection_client_cancel_impl (struct GNUNET_MQ_Handle *mq,
873                                void *impl_state)
874 {
875   struct ClientState *cstate = impl_state;
876
877   (void) mq;
878   GNUNET_assert (NULL != cstate->msg);
879   GNUNET_assert (0 == cstate->msg_off);
880   cstate->msg = NULL;
881   if (NULL != cstate->send_task)
882   {
883     GNUNET_SCHEDULER_cancel (cstate->send_task);
884     cstate->send_task = NULL;
885   }
886 }
887
888
889 /**
890  * Create a message queue to connect to a GNUnet service.
891  * If handlers are specfied, receive messages from the connection.
892  *
893  * @param cfg our configuration
894  * @param service_name name of the service to connect to
895  * @param handlers handlers for receiving messages, can be NULL
896  * @param error_handler error handler
897  * @param error_handler_cls closure for the @a error_handler
898  * @return the message queue, NULL on error
899  */
900 struct GNUNET_MQ_Handle *
901 GNUNET_CLIENT_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
902                        const char *service_name,
903                        const struct GNUNET_MQ_MessageHandler *handlers,
904                        GNUNET_MQ_ErrorHandler error_handler,
905                        void *error_handler_cls)
906 {
907   struct ClientState *cstate;
908
909   if (GNUNET_OK !=
910       test_service_configuration (service_name,
911                                   cfg))
912     return NULL;
913   cstate = GNUNET_new (struct ClientState);
914   cstate->service_name = GNUNET_strdup (service_name);
915   cstate->cfg = cfg;
916   cstate->retry_task = GNUNET_SCHEDULER_add_now (&start_connect,
917                                                  cstate);
918   cstate->mst = GNUNET_MST_create (&recv_message,
919                                    cstate);
920   if (GNUNET_YES ==
921       GNUNET_CONFIGURATION_have_value (cfg,
922                                        service_name,
923                                        "PORT"))
924   {
925     if (! ( (GNUNET_OK !=
926              GNUNET_CONFIGURATION_get_value_number (cfg,
927                                                     service_name,
928                                                     "PORT",
929                                                     &cstate->port)) ||
930             (cstate->port > 65535) ||
931             (GNUNET_OK !=
932              GNUNET_CONFIGURATION_get_value_string (cfg,
933                                                     service_name,
934                                                     "HOSTNAME",
935                                                     &cstate->hostname)) ) &&
936         (0 == strlen (cstate->hostname)) )
937     {
938       GNUNET_free (cstate->hostname);
939       cstate->hostname = NULL;
940       LOG (GNUNET_ERROR_TYPE_WARNING,
941            _("Need a non-empty hostname for service `%s'.\n"),
942            service_name);
943     }
944   }
945   cstate->mq = GNUNET_MQ_queue_for_callbacks (&connection_client_send_impl,
946                                               &connection_client_destroy_impl,
947                                               &connection_client_cancel_impl,
948                                               cstate,
949                                               handlers,
950                                               error_handler,
951                                               error_handler_cls);
952   return cstate->mq;
953 }
954
955 /* end of client.c */