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