tolerate additional IPv4 address now available for gnunet.org
[oweals/gnunet.git] / src / util / client.c
index 06f6ebc329676c47342740b9d3794b5003c86801..05e05a328b26161116eabf4c6f48e893109e8d13 100644 (file)
@@ -2,20 +2,20 @@
      This file is part of GNUnet.
      Copyright (C) 2001-2016 GNUnet e.V.
 
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     or (at your option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
      WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
+     Affero General Public License for more details.
 
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-     Boston, MA 02110-1301, USA.
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
 */
 
 /**
 #include "gnunet_socks.h"
 
 
-#define LOG(kind,...) GNUNET_log_from (kind, "util",__VA_ARGS__)
+#define LOG(kind,...) GNUNET_log_from (kind, "util-client",__VA_ARGS__)
+
+/**
+ * Timeout we use on TCP connect before trying another
+ * result from the DNS resolver.  Actual value used
+ * is this value divided by the number of address families.
+ * Default is 5s.
+ */
+#define CONNECT_RETRY_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
+
 
 
 /**
@@ -249,17 +258,32 @@ transmit_ready (void *cls)
   int notify_in_flight;
 
   cstate->send_task = NULL;
+  if (GNUNET_YES == cstate->in_destroy)
+    return;
   pos = (const char *) cstate->msg;
   len = ntohs (cstate->msg->size);
   GNUNET_assert (cstate->msg_off < len);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "message of type %u trying to send with socket %p (MQ: %p\n",
+       ntohs(cstate->msg->type),
+       cstate->sock,
+       cstate->mq);
+
  RETRY:
   ret = GNUNET_NETWORK_socket_send (cstate->sock,
                                     &pos[cstate->msg_off],
                                     len - cstate->msg_off);
   if (-1 == ret)
   {
-    if (EINTR == errno)
+    LOG (GNUNET_ERROR_TYPE_WARNING,
+         "Error during sending message of type %u\n",
+         ntohs(cstate->msg->type));
+    if (EINTR == errno){
+      LOG (GNUNET_ERROR_TYPE_DEBUG,
+           "Retrying message of type %u\n",
+           ntohs(cstate->msg->type));
       goto RETRY;
+    }
     GNUNET_MQ_inject_error (cstate->mq,
                             GNUNET_MQ_ERROR_WRITE);
     return;
@@ -268,6 +292,9 @@ transmit_ready (void *cls)
   cstate->msg_off += ret;
   if (cstate->msg_off < len)
   {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "rescheduling message of type %u\n",
+         ntohs(cstate->msg->type));
     cstate->send_task
       = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
                                         cstate->sock,
@@ -277,6 +304,9 @@ transmit_ready (void *cls)
       GNUNET_MQ_impl_send_in_flight (cstate->mq);
     return;
   }
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "sending message of type %u successful\n",
+       ntohs(cstate->msg->type));
   cstate->msg = NULL;
   GNUNET_MQ_impl_send_continue (cstate->mq);
 }
@@ -288,7 +318,9 @@ transmit_ready (void *cls)
  *
  * @param cls the `struct ClientState`
  * @param msg message we received.
- * @return #GNUNET_OK on success, #GNUNET_SYSERR to stop further processing
+ * @return #GNUNET_OK on success,
+ *     #GNUNET_NO to stop further processing due to disconnect (no error)
+ *     #GNUNET_SYSERR to stop further processing due to error
  */
 static int
 recv_message (void *cls,
@@ -297,11 +329,16 @@ recv_message (void *cls,
   struct ClientState *cstate = cls;
 
   if (GNUNET_YES == cstate->in_destroy)
-    return GNUNET_SYSERR;
+    return GNUNET_NO;
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Received message of type %u and size %u from %s\n",
+       ntohs (msg->type),
+       ntohs (msg->size),
+       cstate->service_name);
   GNUNET_MQ_inject_message (cstate->mq,
                             msg);
   if (GNUNET_YES == cstate->in_destroy)
-    return GNUNET_SYSERR;
+    return GNUNET_NO;
   return GNUNET_OK;
 }
 
@@ -342,6 +379,22 @@ connection_client_destroy_impl (struct GNUNET_MQ_Handle *mq,
 {
   struct ClientState *cstate = impl_state;
 
+  (void) mq;
+  if (NULL != cstate->dns_active)
+  {
+    GNUNET_RESOLVER_request_cancel (cstate->dns_active);
+    cstate->dns_active = NULL;
+  }
+  if (NULL != cstate->send_task)
+  {
+    GNUNET_SCHEDULER_cancel (cstate->send_task);
+    cstate->send_task = NULL;
+  }
+  if (NULL != cstate->retry_task)
+  {
+    GNUNET_SCHEDULER_cancel (cstate->retry_task);
+    cstate->retry_task = NULL;
+  }
   if (GNUNET_SYSERR == cstate->in_destroy)
   {
     /* defer destruction */
@@ -349,16 +402,18 @@ connection_client_destroy_impl (struct GNUNET_MQ_Handle *mq,
     cstate->mq = NULL;
     return;
   }
-  if (NULL != cstate->dns_active)
-    GNUNET_RESOLVER_request_cancel (cstate->dns_active);
-  if (NULL != cstate->send_task)
-    GNUNET_SCHEDULER_cancel (cstate->send_task);
   if (NULL != cstate->recv_task)
+  {
     GNUNET_SCHEDULER_cancel (cstate->recv_task);
-  if (NULL != cstate->retry_task)
-    GNUNET_SCHEDULER_cancel (cstate->retry_task);
+    cstate->recv_task = NULL;
+  }
   if (NULL != cstate->sock)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "destroying socket: %p\n",
+         cstate->sock);
     GNUNET_NETWORK_socket_close (cstate->sock);
+  }
   cancel_aps (cstate);
   GNUNET_free (cstate->service_name);
   GNUNET_free_non_null (cstate->hostname);
@@ -491,8 +546,8 @@ try_unixpath (const char *service_name,
         s_un.sun_path[0] = '\0';
     }
 #endif
-#if HAVE_SOCKADDR_IN_SIN_LEN
-    un.sun_len = (u_char) sizeof (struct sockaddr_un);
+#if HAVE_SOCKADDR_UN_SUN_LEN
+    s_un.sun_len = (u_char) sizeof (struct sockaddr_un);
 #endif
     sock = GNUNET_NETWORK_socket_create (AF_UNIX,
                                          SOCK_STREAM,
@@ -651,7 +706,7 @@ try_connect_using_address (void *cls,
   GNUNET_CONTAINER_DLL_insert (cstate->ap_head,
                                cstate->ap_tail,
                                ap);
-  ap->task = GNUNET_SCHEDULER_add_write_net (GNUNET_CONNECTION_CONNECT_RETRY_TIMEOUT,
+  ap->task = GNUNET_SCHEDULER_add_write_net (CONNECT_RETRY_TIMEOUT,
                                             ap->sock,
                                             &connect_probe_continuation,
                                             ap);
@@ -683,6 +738,17 @@ test_service_configuration (const char *service_name,
                                                 &unixpath)) &&
       (0 < strlen (unixpath)))
     ret = GNUNET_OK;
+  else if ((GNUNET_OK ==
+            GNUNET_CONFIGURATION_have_value (cfg,
+                                             service_name,
+                                             "UNIXPATH")))
+  {
+    GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+                               service_name,
+                               "UNIXPATH",
+                               _("not a valid filename"));
+    return GNUNET_SYSERR; /* UNIXPATH specified but invalid! */
+  }
   GNUNET_free_non_null (unixpath);
 #endif
 
@@ -755,7 +821,7 @@ start_connect (void *cls)
   cstate->dns_active
     = GNUNET_RESOLVER_ip_get (cstate->hostname,
                              AF_UNSPEC,
-                              GNUNET_CONNECTION_CONNECT_RETRY_TIMEOUT,
+                              CONNECT_RETRY_TIMEOUT,
                               &try_connect_using_address,
                              cstate);
 }
@@ -775,13 +841,19 @@ connection_client_send_impl (struct GNUNET_MQ_Handle *mq,
 {
   struct ClientState *cstate = impl_state;
 
+  (void) mq;
   /* only one message at a time allowed */
   GNUNET_assert (NULL == cstate->msg);
   GNUNET_assert (NULL == cstate->send_task);
   cstate->msg = msg;
   cstate->msg_off = 0;
   if (NULL == cstate->sock)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "message of type %u waiting for socket\n",
+         ntohs(msg->type));
     return; /* still waiting for connection */
+  }
   cstate->send_task
     = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
                                       cstate->sock,
@@ -802,6 +874,7 @@ connection_client_cancel_impl (struct GNUNET_MQ_Handle *mq,
 {
   struct ClientState *cstate = impl_state;
 
+  (void) mq;
   GNUNET_assert (NULL != cstate->msg);
   GNUNET_assert (0 == cstate->msg_off);
   cstate->msg = NULL;