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