-makefile for new test_stream_local (commented)
[oweals/gnunet.git] / src / transport / plugin_transport_unix.c
index 317ff20890302340d992f55726aecda9dde2145d..b7239ee9a24eccab9021bb5b47d47272ea3ab500 100644 (file)
@@ -223,6 +223,8 @@ struct Plugin
    */
   struct GNUNET_NETWORK_FDSet *ws;
 
+  int with_ws;
+
   /**
    * socket that we transmit all data with
    */
@@ -315,7 +317,7 @@ unix_transport_server_stop (void *cls)
   GNUNET_break (GNUNET_OK ==
                 GNUNET_NETWORK_socket_close (plugin->unix_sock.desc));
   plugin->unix_sock.desc = NULL;
-
+  plugin->with_ws = GNUNET_NO;
   return GNUNET_OK;
 }
 
@@ -635,17 +637,20 @@ unix_plugin_send (void *cls,
               (char *) session->addr);
 #endif
 
-  if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK)
-    GNUNET_SCHEDULER_cancel(plugin->select_task);
-
-  plugin->select_task =
-      GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
-                                   GNUNET_SCHEDULER_NO_TASK,
-                                   GNUNET_TIME_UNIT_FOREVER_REL,
-                                   plugin->rs,
-                                   plugin->ws,
-                                   &unix_plugin_select, plugin);
-
+  if (plugin->with_ws == GNUNET_NO)
+  {
+    if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK)
+      GNUNET_SCHEDULER_cancel(plugin->select_task);
+
+    plugin->select_task =
+        GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
+                                     GNUNET_SCHEDULER_NO_TASK,
+                                     GNUNET_TIME_UNIT_FOREVER_REL,
+                                     plugin->rs,
+                                     plugin->ws,
+                                     &unix_plugin_select, plugin);
+    plugin->with_ws = GNUNET_YES;
+  }
   return ssize;
 }
 
@@ -705,6 +710,9 @@ unix_plugin_select_read (struct Plugin * plugin)
       GNUNET_NETWORK_socket_recvfrom (plugin->unix_sock.desc, buf, sizeof (buf),
                                       (struct sockaddr *) &un, &addrlen);
 
+  if ((GNUNET_SYSERR == ret) && ((errno == EAGAIN) || (errno == ENOBUFS)))
+    return;
+
   if (ret == GNUNET_SYSERR)
   {
     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "recvfrom");
@@ -807,7 +815,7 @@ unix_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
     return;
 
-
+  plugin->with_ws = GNUNET_NO;
   if ((tc->reason & GNUNET_SCHEDULER_REASON_WRITE_READY) != 0)
   {
     GNUNET_assert (GNUNET_NETWORK_fdset_isset
@@ -823,6 +831,8 @@ unix_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
     unix_plugin_select_read (plugin);
   }
 
+  if (plugin->select_task != GNUNET_SCHEDULER_NO_TASK)
+    GNUNET_SCHEDULER_cancel (plugin->select_task);
   plugin->select_task =
       GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
                                    GNUNET_SCHEDULER_NO_TASK,
@@ -830,6 +840,8 @@ unix_plugin_select (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
                                    plugin->rs,
                                    (plugin->msg_head != NULL) ? plugin->ws : NULL,
                                    &unix_plugin_select, plugin);
+  if (plugin->msg_head != NULL)
+    plugin->with_ws = GNUNET_YES;
 }
 
 /**
@@ -895,8 +907,12 @@ unix_transport_server_start (void *cls)
   plugin->select_task =
       GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
                                    GNUNET_SCHEDULER_NO_TASK,
-                                   GNUNET_TIME_UNIT_FOREVER_REL, plugin->rs,
-                                   plugin->ws, &unix_plugin_select, plugin);
+                                   GNUNET_TIME_UNIT_FOREVER_REL,
+                                   plugin->rs,
+                                   NULL,
+                                   &unix_plugin_select, plugin);
+  plugin->with_ws = GNUNET_NO;
+
   return 1;
 }
 
@@ -962,6 +978,42 @@ unix_plugin_address_pretty_printer (void *cls, const char *type,
 
 }
 
+/**
+ * Function called to convert a string address to
+ * a binary address.
+ *
+ * @param cls closure ('struct Plugin*')
+ * @param addr string address
+ * @param addrlen length of the address
+ * @param buf location to store the buffer
+ *        If the function returns GNUNET_SYSERR, its contents are undefined.
+ * @param added length of created address
+ * @return GNUNET_OK on success, GNUNET_SYSERR on failure
+ */
+int
+unix_string_to_address (void *cls, const char *addr, uint16_t addrlen,
+    void **buf, size_t *added)
+{
+  if ((NULL == addr) || (addrlen == 0))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+
+  if ((strlen (addr) + 1) != addrlen)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+
+  (*buf) = strdup (addr);
+  (*added) = strlen (addr) + 1;
+  return GNUNET_OK;
+}
+
+
+
+
 /**
  * Function called for a quick conversion of the binary address to
  * a numeric address.  Note that the caller must not free the
@@ -1011,6 +1063,18 @@ libgnunet_plugin_transport_unix_init (void *cls)
   struct Plugin *plugin;
   int sockets_created;
 
+  if (NULL == env->receive)
+  {
+    /* run in 'stub' mode (i.e. as part of gnunet-peerinfo), don't fully
+       initialze the plugin or the API */
+    api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
+    api->cls = NULL;
+    api->address_pretty_printer = &unix_plugin_address_pretty_printer;
+    api->address_to_string = &unix_address_to_string;
+    api->string_to_address = NULL; // FIXME!
+    return api;
+  }
+
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_number (env->cfg, "transport-unix", "PORT",
                                              &port))
@@ -1030,6 +1094,7 @@ libgnunet_plugin_transport_unix_init (void *cls)
   api->address_pretty_printer = &unix_plugin_address_pretty_printer;
   api->address_to_string = &unix_address_to_string;
   api->check_address = &unix_check_address;
+  api->string_to_address = &unix_string_to_address;
   sockets_created = unix_transport_server_start (plugin);
   if (sockets_created == 0)
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Failed to open UNIX sockets\n"));
@@ -1046,6 +1111,11 @@ libgnunet_plugin_transport_unix_done (void *cls)
   struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
   struct Plugin *plugin = api->cls;
 
+  if (NULL == plugin)
+  {
+    GNUNET_free (api);
+    return NULL;
+  }
   unix_transport_server_stop (plugin);
 
   GNUNET_CONTAINER_multihashmap_iterate (plugin->session_map, &get_session_delete_it, plugin);