- implementation for mantis 0002485
[oweals/gnunet.git] / src / transport / plugin_transport_udp.c
index 474180db509cb89707b87d172f104df0f59db4ac..940bed254f220887257959352ac401bf2afa595d 100644 (file)
@@ -690,7 +690,7 @@ free_session (struct Session *s)
  * to close a session due to a disconnect or failure to
  * establish a connection.
  *
- * @param session session to close down
+ * @param s session to close down
  */
 static void
 disconnect_session (struct Session *s)
@@ -704,7 +704,7 @@ disconnect_session (struct Session *s)
          s,
          GNUNET_i2s (&s->target),
          GNUNET_a2s (s->sock_addr, s->addrlen));
-  stop_session_timeout(s);
+  stop_session_timeout (s);
   next = plugin->ipv4_queue_head;
   while (NULL != (udpw = next))
   {
@@ -764,7 +764,7 @@ disconnect_session (struct Session *s)
  * @return GNUNET_OK (continue to iterate)
  */
 static int
-disconnect_and_free_it (void *cls, const GNUNET_HashCode * key, void *value)
+disconnect_and_free_it (void *cls, const struct GNUNET_HashCode * key, void *value)
 {
   disconnect_session(value);
   return GNUNET_OK;
@@ -857,7 +857,7 @@ create_session (struct Plugin *plugin, const struct GNUNET_PeerIdentity *target,
 
 static int
 session_cmp_it (void *cls,
-               const GNUNET_HashCode * key,
+               const struct GNUNET_HashCode * key,
                void *value)
 {
   struct SessionCompareContext * cctx = cls;
@@ -1311,7 +1311,7 @@ process_inbound_tokenized_messages (void *cls, void *client,
                                &si->sender,
                                hdr,
                                (const struct GNUNET_ATS_Information *) &ats, 2,
-                               NULL,
+                               si->session,
                                si->arg,
                                si->args);
   si->session->flow_delay_for_other_peer = delay;
@@ -1461,7 +1461,7 @@ struct LookupContext
 
 
 static int
-lookup_session_by_addr_it (void *cls, const GNUNET_HashCode * key, void *value)
+lookup_session_by_addr_it (void *cls, const struct GNUNET_HashCode * key, void *value)
 {
   struct LookupContext *l_ctx = cls;
   struct Session * s = value;
@@ -1741,8 +1741,15 @@ udp_select_read (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *rsock)
   memset (&addr, 0, sizeof (addr));
   size = GNUNET_NETWORK_socket_recvfrom (rsock, buf, sizeof (buf),
                                       (struct sockaddr *) &addr, &fromlen);
-
-  if (size < sizeof (struct GNUNET_MessageHeader))
+#if MINGW
+  /* On SOCK_DGRAM UDP sockets recvfrom might fail with a
+   * WSAECONNRESET error to indicate that previous sendto() (???)
+   * on this socket has failed.
+   */
+  if ( (-1 == size) && (ECONNRESET == errno) )
+    return;
+#endif
+  if ( (-1 == size) || (size < sizeof (struct GNUNET_MessageHeader)))
   {
     GNUNET_break_op (0);
     return;
@@ -1791,6 +1798,7 @@ udp_select_send (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *sock)
   size_t slen;
   struct GNUNET_TIME_Absolute max;
   struct UDPMessageWrapper *udpw = NULL;
+  static int network_down_error;
 
   if (sock == plugin->sockv4)
   {
@@ -1882,24 +1890,39 @@ udp_select_send (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *sock)
     const struct GNUNET_ATS_Information type = plugin->env->get_address_type
         (plugin->env->cls,sa, slen);
 
-    if ((GNUNET_ATS_NET_WAN == type.value) &&
+    if (((GNUNET_ATS_NET_LAN == ntohl(type.value)) || (GNUNET_ATS_NET_WAN == ntohl(type.value))) &&
         ((ENETUNREACH == errno) || (ENETDOWN == errno)))
     {
-      /* "Network unreachable" or "Network down" */
-      /*
-       * This indicates that this system is IPv6 enabled, but does not
-       * have a valid global IPv6 address assigned
-       */
-       LOG (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
-           _("UDP could not message to `%s': `%s'. "
+      if ((network_down_error == GNUNET_NO) && (slen == sizeof (struct sockaddr_in)))
+      {
+        /* IPv4: "Network unreachable" or "Network down"
+         *
+         * This indicates we do not have connectivity
+         */
+        LOG (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
+            _("UDP could not transmit message to `%s': "
+              "Network seems down, please check your network configuration\n"),
+            GNUNET_a2s (sa, slen));
+      }
+      if ((network_down_error == GNUNET_NO) && (slen == sizeof (struct sockaddr_in6)))
+      {
+        /* IPv6: "Network unreachable" or "Network down"
+         *
+         * This indicates that this system is IPv6 enabled, but does not
+         * have a valid global IPv6 address assigned or we do not have
+         * connectivity
+         */
+
+       LOG (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
+           _("UDP could not transmit message to `%s': "
             "Please check your network configuration and disable IPv6 if your "
             "connection does not have a global IPv6 address\n"),
-           GNUNET_a2s (sa, slen),
-           STRERROR (errno));
+          GNUNET_a2s (sa, slen));
+      }
     }
     else
     {
-      LOG (GNUNET_ERROR_TYPE_ERROR,
+      LOG (GNUNET_ERROR_TYPE_WARNING,
          "UDP could not transmit %u-byte message to `%s': `%s'\n",
          (unsigned int) (udpw->msg_size), GNUNET_a2s (sa, slen),
          STRERROR (errno));
@@ -1913,6 +1936,7 @@ udp_select_send (struct Plugin *plugin, struct GNUNET_NETWORK_Handle *sock)
          (unsigned int) (udpw->msg_size), GNUNET_a2s (sa, slen), (int) sent,
          (sent < 0) ? STRERROR (errno) : "ok");
     call_continuation(udpw, GNUNET_OK);
+    network_down_error = GNUNET_NO;
   }
 
   if (sock == plugin->sockv4)
@@ -2185,15 +2209,14 @@ session_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   struct Session *s = cls;
 
   s->timeout_task = GNUNET_SCHEDULER_NO_TASK;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Session %p was idle for %llu, disconnecting\n",
-      s, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value);
-
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Session %p was idle for %llu ms, disconnecting\n",
+              s, (unsigned long long) GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value);
   /* call session destroy function */
   disconnect_session(s);
-
 }
 
+
 /**
  * Start session timeout
  */
@@ -2202,15 +2225,15 @@ start_session_timeout (struct Session *s)
 {
   GNUNET_assert (NULL != s);
   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == s->timeout_task);
-
   s->timeout_task =  GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
                                                    &session_timeout,
                                                    s);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Timeout for session %p set to %llu\n",
-      s, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Timeout for session %p set to %llu ms\n",
+              s,  (unsigned long long) GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value);
 }
 
+
 /**
  * Increment session timeout due to activity
  */
@@ -2224,11 +2247,12 @@ reschedule_session_timeout (struct Session *s)
   s->timeout_task =  GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
                                                    &session_timeout,
                                                    s);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Timeout rescheduled for session %p set to %llu\n",
-      s, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Timeout rescheduled for session %p set to %llu ms\n",
+              s, (unsigned long long) GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value);
 }
 
+
 /**
  * Cancel timeout
  */
@@ -2241,17 +2265,14 @@ stop_session_timeout (struct Session *s)
   {
     GNUNET_SCHEDULER_cancel (s->timeout_task);
     s->timeout_task = GNUNET_SCHEDULER_NO_TASK;
-
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Timeout rescheduled for session %p canceled\n",
-      s, GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value);
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Timeout for session %p was not active\n",
-      s);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Timeout stopped for session %p canceled\n",
+                s, (unsigned long long) GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value);
   }
 }
 
+
+
 /**
  * The exported method. Makes the core api available via a global and
  * returns the udp transport API.
@@ -2272,6 +2293,7 @@ libgnunet_plugin_transport_udp_init (void *cls)
   unsigned long long enable_v6;
   char * bind4_address;
   char * bind6_address;
+  char * fancy_interval;
   struct GNUNET_TIME_Relative interval;
   struct sockaddr_in serverAddrv4;
   struct sockaddr_in6 serverAddrv6;
@@ -2360,11 +2382,19 @@ libgnunet_plugin_transport_udp_init (void *cls)
   if (broadcast == GNUNET_SYSERR)
     broadcast = GNUNET_NO;
 
-  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_time (env->cfg, "transport-udp",
-                                           "BROADCAST_INTERVAL", &interval))
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (env->cfg, "transport-udp",
+                                           "BROADCAST_INTERVAL", &fancy_interval))
   {
     interval = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10);
   }
+  else
+  {
+     if (GNUNET_SYSERR == GNUNET_STRINGS_fancy_time_to_relative(fancy_interval, &interval))
+     {
+       interval = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30);
+     }
+     GNUNET_free (fancy_interval);
+  }
 
   /* Maximum datarate */
   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-udp",