wip
[oweals/gnunet.git] / src / transport / plugin_transport_unix.c
index 790e4451f00a51f92c781d211d892cc138cffc73..f4a69d84ec2b6206a35ad6738e1c16574f939864 100644 (file)
@@ -80,6 +80,24 @@ struct UNIXMessage
 
 };
 
+struct RetryList
+{
+  /**
+   * Pointer to next element.
+   */
+  struct RetryList *next;
+
+  /**
+   * Pointer to previous element.
+   */
+  struct RetryList *prev;
+
+  /**
+   * The actual retry context.
+   */
+  struct RetrySendContext *retry_ctx;
+};
+
 /**
  * Network format for IPv4 addresses.
  */
@@ -191,6 +209,11 @@ struct RetrySendContext
    * The priority of the message.
    */
   unsigned int priority;
+
+  /**
+   * Entry in the DLL of retry items.
+   */
+  struct RetryList *retry_list_entry;
 };
 
 /**
@@ -342,6 +365,16 @@ struct Plugin
 
 };
 
+/**
+ * Head of retry DLL.
+ */
+static struct RetryList *retry_list_head;
+
+/**
+ * Tail of retry DLL.
+ */
+static struct RetryList *retry_list_tail;
+
 
 /**
  * Disconnect from a remote node.  Clean up session if we have one for this peer
@@ -370,6 +403,22 @@ static int
 unix_transport_server_stop (void *cls)
 {
   struct Plugin *plugin = cls;
+  struct RetryList *pos;
+
+  pos = retry_list_head;
+
+  while(NULL != (pos = retry_list_head))
+    {
+      GNUNET_CONTAINER_DLL_remove(retry_list_head, retry_list_tail, pos);
+      if (GNUNET_SCHEDULER_NO_TASK != pos->retry_ctx->retry_task)
+        {
+          GNUNET_SCHEDULER_cancel(pos->retry_ctx->retry_task);
+        }
+      GNUNET_free(pos->retry_ctx->msg);
+      GNUNET_free(pos->retry_ctx->addr);
+      GNUNET_free(pos->retry_ctx);
+      GNUNET_free(pos);
+    }
 
   if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK)
     {
@@ -427,8 +476,14 @@ void retry_send_message (void *cls,
 {
   struct RetrySendContext *retry_ctx = cls;
 
-  if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
-    return;
+  if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
+    {
+      GNUNET_free(retry_ctx->msg);
+      GNUNET_free(retry_ctx->addr);
+      GNUNET_free(retry_ctx);
+      return;
+    }
+
   unix_real_send (retry_ctx->plugin,
                   retry_ctx,
                   retry_ctx->send_handle,
@@ -489,6 +544,7 @@ unix_real_send (void *cls,
   size_t sbs;
   struct sockaddr_un un;
   size_t slen;
+  struct RetryList *retry_list_entry;
 
   if (send_handle == NULL)
     {
@@ -542,6 +598,7 @@ unix_real_send (void *cls,
     {
       if (incoming_retry_context == NULL)
         {
+          retry_list_entry = GNUNET_malloc(sizeof(struct RetryList));
           retry_ctx = GNUNET_malloc(sizeof(struct RetrySendContext));
           retry_ctx->addr = GNUNET_malloc(addrlen);
           retry_ctx->msg = GNUNET_malloc(msgbuf_size);
@@ -557,6 +614,9 @@ unix_real_send (void *cls,
           retry_ctx->timeout = GNUNET_TIME_relative_to_absolute(timeout);
           memcpy(&retry_ctx->target, target, sizeof(struct GNUNET_PeerIdentity));
           retry_ctx->delay = GNUNET_TIME_UNIT_MILLISECONDS;
+          retry_ctx->retry_list_entry = retry_list_entry;
+          retry_list_entry->retry_ctx = retry_ctx;
+          GNUNET_CONTAINER_DLL_insert(retry_list_head, retry_list_tail, retry_list_entry);
         }
       else
         {
@@ -597,6 +657,8 @@ unix_real_send (void *cls,
 
   if (incoming_retry_context != NULL)
     {
+      GNUNET_CONTAINER_DLL_remove(retry_list_head, retry_list_tail, incoming_retry_context->retry_list_entry);
+      GNUNET_free(incoming_retry_context->retry_list_entry);
       GNUNET_free(incoming_retry_context->msg);
       GNUNET_free(incoming_retry_context->addr);
       GNUNET_free(incoming_retry_context);
@@ -755,7 +817,7 @@ unix_plugin_select (void *cls,
   uint16_t csize;
 
   plugin->select_task = GNUNET_SCHEDULER_NO_TASK;
-  if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+  if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
     return;
 
   addrlen = sizeof(un);
@@ -835,10 +897,8 @@ static int
 unix_transport_server_start (void *cls)
 {
   struct Plugin *plugin = cls;
-
   struct sockaddr *serverAddr;
   socklen_t addrlen;
-  int sockets_created;
   struct sockaddr_un un;
   size_t slen;
 
@@ -852,7 +912,6 @@ unix_transport_server_start (void *cls)
   slen += sizeof (sa_family_t);
   serverAddr = (struct sockaddr*) &un;
   addrlen = slen;
-  sockets_created = 0;
 #if LINUX
   un.sun_path[0] = '\0';
 #endif
@@ -860,24 +919,23 @@ unix_transport_server_start (void *cls)
   plugin->unix_sock.desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_DGRAM, 0);
   if (NULL == plugin->unix_sock.desc)
     {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "socket");
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "socket");
+      return GNUNET_SYSERR;
     }
-  else
+  if (GNUNET_NETWORK_socket_bind (plugin->unix_sock.desc, serverAddr, addrlen) !=
+      GNUNET_OK)
     {
-      if (GNUNET_NETWORK_socket_bind (plugin->unix_sock.desc, serverAddr, addrlen) !=
-            GNUNET_OK)
-       {
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
+      GNUNET_NETWORK_socket_close (plugin->unix_sock.desc);
+      plugin->unix_sock.desc = NULL;
+      return GNUNET_SYSERR;
+    }
 #if DEBUG_UNIX
-         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                          "UNIX Binding failed!\n");
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, 
+                  "unix",
+                  "Bound to `%s'\n",
+                  &un.sun_path[0]);
 #endif
-       }
-      else
-        GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Bound to `%s'\n", &un.sun_path[0]);
-      if (plugin->unix_sock.desc != NULL)
-        sockets_created++;
-    }
-
   plugin->rs = GNUNET_NETWORK_fdset_create ();
   GNUNET_NETWORK_fdset_zero (plugin->rs);
   GNUNET_NETWORK_fdset_set (plugin->rs,
@@ -888,7 +946,7 @@ unix_transport_server_start (void *cls)
                                  GNUNET_SCHEDULER_NO_TASK,
                                  GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
                                  NULL, &unix_plugin_select, plugin);
-  return sockets_created;
+  return 1;
 }