- fix error messages
[oweals/gnunet.git] / src / transport / plugin_transport_udp_broadcasting.c
index c53665f10fa123239052255488fbc71ae697f2a4..c17a3ccfff1ca80e734c71a91b9d76c8753c42bc 100644 (file)
 
 #define LOG(kind,...) GNUNET_log_from (kind, "transport-udp", __VA_ARGS__)
 
+/* *********** Cryogenic ********** */
+#if LINUX
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <sys/ioctl.h>
+#include <sys/select.h>
+#include <sys/time.h>
+
+#define PM_MAGIC 'k'
+#define PM_SET_DELAY_AND_TIMEOUT _IOW(PM_MAGIC, 1, struct pm_times)
+
+struct pm_times {
+       unsigned long delay_msecs;
+       unsigned long timeout_msecs;
+};
+#endif
+/************************************/
+
 
 struct UDP_Beacon_Message
 {
@@ -72,6 +91,18 @@ struct BroadcastAddress
   void *addr;
 
   socklen_t addrlen;
+
+#if LINUX
+  /**
+   * Cryogenic handle.
+   */
+  struct GNUNET_DISK_FileHandle *cryogenic_fd;
+
+  /**
+   * Time out for cryogenic.
+   */
+  struct pm_times cryogenic_times;
+#endif
 };
 
 
@@ -211,7 +242,7 @@ udp_broadcast_receive (struct Plugin *plugin,
          size, GNUNET_a2s ((const struct sockaddr *) addr, addrlen));
     struct Mstv4Context *mc;
 
-    mc = GNUNET_malloc (sizeof (struct Mstv4Context));
+    mc = GNUNET_new (struct Mstv4Context);
     struct sockaddr_in *av4 = (struct sockaddr_in *) addr;
 
     mc->addr.ipv4_addr = av4->sin_addr.s_addr;
@@ -232,7 +263,7 @@ udp_broadcast_receive (struct Plugin *plugin,
          size, GNUNET_a2s ((const struct sockaddr *) &addr, addrlen));
     struct Mstv6Context *mc;
 
-    mc = GNUNET_malloc (sizeof (struct Mstv6Context));
+    mc = GNUNET_new (struct Mstv6Context);
     struct sockaddr_in6 *av6 = (struct sockaddr_in6 *) addr;
 
     mc->addr.ipv6_addr = av6->sin6_addr;
@@ -315,13 +346,37 @@ udp_ipv4_broadcast_send (void *cls,
            GNUNET_a2s (baddr->addr, baddr->addrlen));
     }
   }
-  // if (-1 != baddr->cryogenic_fd) {
-  //   ioctl (baddr->cryogenic_fd, broadcast_interval +/- X)
-  //   GNUNET_SCHEDULER_add_write_file (baddr->cryogenic_fd, &udp_ipv4_broadcast_send, baddr);
-  // } else
-  baddr->broadcast_task =
-    GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval,
-                                  &udp_ipv4_broadcast_send, baddr);
+
+#if LINUX
+  /*
+   * Cryogenic
+   */
+  if (NULL != baddr->cryogenic_fd)
+  {
+    baddr->cryogenic_times.delay_msecs = (plugin->broadcast_interval.rel_value_us/1000.0)*0.5;
+    baddr->cryogenic_times.timeout_msecs = (plugin->broadcast_interval.rel_value_us/1000.0)*1.5;
+
+    if (ioctl(baddr->cryogenic_fd->fd,
+                 PM_SET_DELAY_AND_TIMEOUT,
+                 &baddr->cryogenic_times) < 0)
+    {
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "ioctl");
+      baddr->broadcast_task =
+          GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval,
+                                       &udp_ipv4_broadcast_send, baddr);
+    }
+    else
+      GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
+                                          baddr->cryogenic_fd,
+                                              &udp_ipv4_broadcast_send,
+                                              baddr);
+
+  }
+  else
+#endif
+    baddr->broadcast_task =
+        GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval,
+                                         &udp_ipv4_broadcast_send, baddr);
 }
 
 
@@ -376,10 +431,35 @@ udp_ipv6_broadcast_send (void *cls,
          GNUNET_a2s ((const struct sockaddr *) &plugin->ipv6_multicast_address,
                      sizeof (struct sockaddr_in6)));
   }
-  // cryogenic...
-  baddr->broadcast_task =
-    GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval,
-                                  &udp_ipv6_broadcast_send, baddr);
+#if LINUX
+  /*
+   * Cryogenic
+   */
+  if (NULL != baddr->cryogenic_fd)
+  {
+    baddr->cryogenic_times.delay_msecs = (plugin->broadcast_interval.rel_value_us/1000.0)*0.5;
+    baddr->cryogenic_times.timeout_msecs = (plugin->broadcast_interval.rel_value_us/1000.0)*1.5;
+
+    if (ioctl(baddr->cryogenic_fd->fd,
+                 PM_SET_DELAY_AND_TIMEOUT,
+                 &baddr->cryogenic_times) < 0)
+    {
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "ioctl");
+      baddr->broadcast_task =
+          GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval,
+                                        &udp_ipv6_broadcast_send, baddr);
+    }
+    else
+      GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL,
+                                      baddr->cryogenic_fd,
+                                       &udp_ipv4_broadcast_send,
+                                       baddr);
+  }
+  else
+#endif
+    baddr->broadcast_task =
+        GNUNET_SCHEDULER_add_delayed (plugin->broadcast_interval,
+                                      &udp_ipv6_broadcast_send, baddr);
 }
 
 
@@ -428,15 +508,26 @@ iface_proc (void *cls,
        (NULL != plugin->sockv4) &&
        (addrlen == sizeof (struct sockaddr_in)) )
   {
+#if LINUX
+    /*
+     * setup Cryogenic FD for ipv4 broadcasting
+     */
     char *filename;
 
     GNUNET_asprintf (&filename,
-                     "/dev/power/net-%s",
+                     "/dev/cryogenic/%s",
                      name);
-    // ba->cryogenic_fd = GNUNET_DISK_file_open (filename, ...);
+    if (0 == ACCESS (name, R_OK))
+    {
+      ba->cryogenic_fd =
+        GNUNET_DISK_file_open (filename,
+                               GNUNET_DISK_OPEN_WRITE,
+                               GNUNET_DISK_PERM_NONE);
+    }
     GNUNET_free (filename);
+#endif
     ba->broadcast_task =
-      GNUNET_SCHEDULER_add_now (&udp_ipv4_broadcast_send, ba);
+        GNUNET_SCHEDULER_add_now (&udp_ipv4_broadcast_send, ba);
   }
   if ((GNUNET_YES == plugin->enable_ipv6) &&
       (NULL != plugin->sockv6) &&
@@ -472,9 +563,24 @@ iface_proc (void *cls,
     }
     else
     {
-      LOG (GNUNET_ERROR_TYPE_DEBUG,
-           "IPv6 multicasting running\n");
-      // setup cryogenic FD...
+#if LINUX
+      /*
+       * setup Cryogenic FD for ipv6 broadcasting
+       */
+      char *filename;
+
+      GNUNET_asprintf (&filename,
+                       "/dev/cryogenic/%s",
+                       name);
+      if (0 == ACCESS (name, R_OK))
+      {
+        ba->cryogenic_fd =
+          GNUNET_DISK_file_open (filename,
+                                 GNUNET_DISK_OPEN_WRITE,
+                                 GNUNET_DISK_PERM_NONE);
+      }
+      GNUNET_free (filename);
+#endif
       ba->broadcast_task =
           GNUNET_SCHEDULER_add_now (&udp_ipv6_broadcast_send, ba);
     }
@@ -493,13 +599,23 @@ setup_broadcast (struct Plugin *plugin,
   const struct GNUNET_MessageHeader *hello;
 
   hello = plugin->env->get_our_hello ();
-  if (GNUNET_YES == GNUNET_HELLO_is_friend_only((const struct GNUNET_HELLO_Message *) hello))
+  if (GNUNET_YES ==
+      GNUNET_HELLO_is_friend_only ((const struct GNUNET_HELLO_Message *) hello))
   {
     LOG (GNUNET_ERROR_TYPE_WARNING,
          _("Disabling HELLO broadcasting due to friend-to-friend only configuration!\n"));
     return;
   }
 
+  /* always create tokenizers */
+  plugin->broadcast_ipv4_mst =
+    GNUNET_SERVER_mst_create (&broadcast_ipv4_mst_cb, plugin);
+  plugin->broadcast_ipv6_mst =
+    GNUNET_SERVER_mst_create (&broadcast_ipv6_mst_cb, plugin);
+
+  if (GNUNET_YES != plugin->enable_broadcasting)
+    return; /* We do not send, just receive */
+
   /* create IPv4 broadcast socket */
   if ((GNUNET_YES == plugin->enable_ipv4) && (NULL != plugin->sockv4))
   {
@@ -513,13 +629,8 @@ setup_broadcast (struct Plugin *plugin,
            _("Failed to set IPv4 broadcast option for broadcast socket on port %d\n"),
            ntohs (server_addrv4->sin_port));
     }
-    else
-    {
-      plugin->broadcast_ipv4_mst =
-          GNUNET_SERVER_mst_create (broadcast_ipv4_mst_cb, plugin);
-      LOG (GNUNET_ERROR_TYPE_DEBUG, "IPv4 Broadcasting running\n");
-    }
   }
+  /* create IPv6 multicast socket */
   if ((GNUNET_YES == plugin->enable_ipv6) && (plugin->sockv6 != NULL))
   {
     memset (&plugin->ipv6_multicast_address, 0, sizeof (struct sockaddr_in6));
@@ -528,8 +639,6 @@ setup_broadcast (struct Plugin *plugin,
                               &plugin->ipv6_multicast_address.sin6_addr));
     plugin->ipv6_multicast_address.sin6_family = AF_INET6;
     plugin->ipv6_multicast_address.sin6_port = htons (plugin->port);
-    plugin->broadcast_ipv6_mst =
-      GNUNET_SERVER_mst_create (broadcast_ipv6_mst_cb, plugin);
   }
   GNUNET_OS_network_interfaces_list (&iface_proc, plugin);
 }
@@ -538,50 +647,65 @@ setup_broadcast (struct Plugin *plugin,
 void
 stop_broadcast (struct Plugin *plugin)
 {
-  while (plugin->broadcast_head != NULL)
+  if (GNUNET_YES == plugin->enable_broadcasting)
   {
-    struct BroadcastAddress *p = plugin->broadcast_head;
-
-    if (p->broadcast_task != GNUNET_SCHEDULER_NO_TASK)
-    {
-      GNUNET_SCHEDULER_cancel (p->broadcast_task);
-      p->broadcast_task = GNUNET_SCHEDULER_NO_TASK;
-    }
-    if ((GNUNET_YES == plugin->enable_ipv6) &&
-        (NULL != plugin->sockv6) &&
-        (p->addrlen == sizeof (struct sockaddr_in6)))
+    /* Disable broadcasting */
+    while (plugin->broadcast_head != NULL)
     {
-      /* Create IPv6 multicast request */
-      struct ipv6_mreq multicastRequest;
-      const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) p->addr;
+      struct BroadcastAddress *p = plugin->broadcast_head;
 
-      multicastRequest.ipv6mr_multiaddr =
-        plugin->ipv6_multicast_address.sin6_addr;
-      multicastRequest.ipv6mr_interface = s6->sin6_scope_id;
-
-      /* Leave the multicast group */
-      if (GNUNET_OK ==
-          GNUNET_NETWORK_socket_setsockopt
-          (plugin->sockv6, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
-           &multicastRequest, sizeof (multicastRequest)))
+      if (p->broadcast_task != GNUNET_SCHEDULER_NO_TASK)
       {
-        GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, setsockopt);
+        GNUNET_SCHEDULER_cancel (p->broadcast_task);
+        p->broadcast_task = GNUNET_SCHEDULER_NO_TASK;
       }
-      else
+      if ((GNUNET_YES == plugin->enable_ipv6) &&
+          (NULL != plugin->sockv6) &&
+          (p->addrlen == sizeof (struct sockaddr_in6)))
       {
-        LOG (GNUNET_ERROR_TYPE_DEBUG, "IPv6 multicasting stopped\n");
+        /* Create IPv6 multicast request */
+        struct ipv6_mreq multicastRequest;
+        const struct sockaddr_in6 *s6 = (const struct sockaddr_in6 *) p->addr;
+
+        multicastRequest.ipv6mr_multiaddr =
+          plugin->ipv6_multicast_address.sin6_addr;
+        multicastRequest.ipv6mr_interface = s6->sin6_scope_id;
+
+        /* Leave the multicast group */
+        if (GNUNET_OK ==
+            GNUNET_NETWORK_socket_setsockopt
+            (plugin->sockv6, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
+             &multicastRequest, sizeof (multicastRequest)))
+        {
+          GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, setsockopt);
+        }
+        else
+        {
+          LOG (GNUNET_ERROR_TYPE_DEBUG, "IPv6 multicasting stopped\n");
+        }
       }
+
+#if LINUX
+    GNUNET_DISK_file_close(p->cryogenic_fd);
+#endif
+      GNUNET_CONTAINER_DLL_remove (plugin->broadcast_head,
+                                   plugin->broadcast_tail, p);
+      GNUNET_free (p->addr);
+      GNUNET_free (p);
     }
-    // close cryogenic FD...
-    GNUNET_CONTAINER_DLL_remove (plugin->broadcast_head,
-                                 plugin->broadcast_tail, p);
-    GNUNET_free (p->addr);
-    GNUNET_free (p);
   }
-  if (plugin->broadcast_ipv4_mst != NULL)
+
+  /* Destroy MSTs */
+  if (NULL != plugin->broadcast_ipv4_mst)
+  {
     GNUNET_SERVER_mst_destroy (plugin->broadcast_ipv4_mst);
-  if (plugin->broadcast_ipv6_mst != NULL)
+    plugin->broadcast_ipv4_mst = NULL;
+  }
+  if (NULL != plugin->broadcast_ipv6_mst)
+  {
     GNUNET_SERVER_mst_destroy (plugin->broadcast_ipv6_mst);
+    plugin->broadcast_ipv6_mst = NULL;
+  }
 }
 
 /* end of plugin_transport_udp_broadcasting.c */