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