-indentation
[oweals/gnunet.git] / src / testbed / gnunet-service-testbed-logger.c
index 7f3a42be2cc8ff7b5f87f6e24c994e5d6b498fe6..6bf33e681b9ecacaa65fbe9516f11299da3acce8 100644 (file)
@@ -4,7 +4,7 @@
 
   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 2, or (at your
+  by the Free Software Foundation; either version 3, or (at your
   option) any later version.
 
   GNUnet is distributed in the hope that it will be useful, but
@@ -65,11 +65,6 @@ struct MessageQueue
   struct MessageQueue *prev;
 };
 
-/**
- * Current Transmit Handle; NULL if no notify transmit exists currently
- */
-static struct GNUNET_SERVER_TransmitHandle *transmit_handle;
-
 /**
  * The message queue head
  */
@@ -90,75 +85,15 @@ struct GNUNET_BIO_WriteHandle *bio;
  */
 static GNUNET_SCHEDULER_TaskIdentifier shutdown_task_id;
 
-
 /**
- * Function called to notify a client about the connection begin ready to queue
- * more data.  "buf" will be NULL and "size" zero if the connection was closed
- * for writing in the meantime.
- *
- * @param cls NULL
- * @param size number of bytes available in buf
- * @param buf where the callee should write the message
- * @return number of bytes written to buf
+ * The number of connections we have
  */
-static size_t
-transmit_ready_notify (void *cls, size_t size, void *buf)
-{
-  struct MessageQueue *mq_entry;
-
-  transmit_handle = NULL;
-  mq_entry = mq_head;
-  GNUNET_assert (NULL != mq_entry);
-  if (0 == size)
-    return 0;
-  GNUNET_assert (ntohs (mq_entry->msg->size) <= size);
-  size = ntohs (mq_entry->msg->size);
-  memcpy (buf, mq_entry->msg, size);
-  GNUNET_free (mq_entry->msg);
-  GNUNET_SERVER_client_drop (mq_entry->client);
-  GNUNET_CONTAINER_DLL_remove (mq_head, mq_tail, mq_entry);
-  GNUNET_free (mq_entry);
-  mq_entry = mq_head;
-  if (NULL != mq_entry)
-    transmit_handle =
-        GNUNET_SERVER_notify_transmit_ready (mq_entry->client,
-                                             ntohs (mq_entry->msg->size),
-                                             GNUNET_TIME_UNIT_FOREVER_REL,
-                                             &transmit_ready_notify, NULL);
-  return size;
-}
-
+static unsigned int nconn;
 
 /**
- * Queues a message in send queue for sending to the service
- *
- * @param client the client to whom the queued message has to be sent
- * @param msg the message to queue
+ * Are we shutting down?
  */
-void
-queue_message (struct GNUNET_SERVER_Client *client,
-                   struct GNUNET_MessageHeader *msg)
-{
-  struct MessageQueue *mq_entry;
-  uint16_t type;
-  uint16_t size;
-
-  type = ntohs (msg->type);
-  size = ntohs (msg->size);
-  mq_entry = GNUNET_malloc (sizeof (struct MessageQueue));
-  mq_entry->msg = msg;
-  mq_entry->client = client;
-  GNUNET_SERVER_client_keep (client);
-  LOG_DEBUG ("Queueing message of type %u, size %u for sending\n", type,
-             ntohs (msg->size));
-  GNUNET_CONTAINER_DLL_insert_tail (mq_head, mq_tail, mq_entry);
-  if (NULL == transmit_handle)
-    transmit_handle =
-        GNUNET_SERVER_notify_transmit_ready (client, size,
-                                             GNUNET_TIME_UNIT_FOREVER_REL,
-                                             &transmit_ready_notify, NULL);
-}
-
+static int in_shutdown;
 
 /**
  * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
@@ -192,8 +127,15 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   struct MessageQueue *mq_entry;
 
   shutdown_task_id = GNUNET_SCHEDULER_NO_TASK;
-  if (NULL != transmit_handle)
-    GNUNET_SERVER_notify_transmit_ready_cancel (transmit_handle);
+  in_shutdown = GNUNET_YES;
+  if (0 != nconn)
+  {
+    /* Delay shutdown if there are active connections */
+    shutdown_task_id = GNUNET_SCHEDULER_add_delayed
+        (GNUNET_TIME_UNIT_FOREVER_REL,
+         &shutdown_task, NULL);
+    return;
+  }
   while (NULL != (mq_entry = mq_head))
   {
     GNUNET_free (mq_entry->msg);
@@ -201,7 +143,52 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
     GNUNET_CONTAINER_DLL_remove (mq_head, mq_tail, mq_entry);
     GNUNET_free (mq_entry);
   }
-  GNUNET_BIO_write_close (bio);
+  GNUNET_break (GNUNET_OK == GNUNET_BIO_write_close (bio));
+}
+
+
+/**
+ * Functions with this signature are called whenever a client
+ * is disconnected on the network level.
+ *
+ * @param cls closure
+ * @param client identification of the client; NULL
+ *        for the last call when the server is destroyed
+ */
+static void 
+client_disconnected (void *cls, struct GNUNET_SERVER_Client *client)
+{
+  if (NULL == client)
+  {
+    GNUNET_break (0 == nconn);
+    return;
+  }
+  nconn--;
+  if (GNUNET_YES != in_shutdown)
+    return;
+  GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != shutdown_task_id);
+  GNUNET_SCHEDULER_cancel (shutdown_task_id);
+  shutdown_task_id = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
+}
+
+
+/**
+ * Functions with this signature are called whenever a client
+ * is connected on the network level.
+ *
+ * @param cls closure
+ * @param client identification of the client
+ */
+static void
+client_connected (void *cls, struct GNUNET_SERVER_Client *client)
+{
+  if (NULL == client)
+  {
+    GNUNET_break (0 == nconn);
+    return;
+  }
+  GNUNET_SERVER_client_persist_ (client);
+  nconn++;
 }
 
 
@@ -222,25 +209,43 @@ logger_run (void *cls, struct GNUNET_SERVER_Handle *server,
   };
   char *dir;
   char *fn;
+  char *hname;
+  size_t hname_len;
   pid_t pid;
 
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_filename (cfg, "TESTBED-LOGGER", "DIR",
                                                &dir))
   {
-    LOG (GNUNET_ERROR_TYPE_ERROR, "Not logging directory definied.  Exiting\n");    
+    LOG (GNUNET_ERROR_TYPE_ERROR, "Not logging directory definied.  Exiting\n");
+    GNUNET_SCHEDULER_shutdown ();
     return;
   }
   pid = getpid ();
-  (void) GNUNET_asprintf (&fn, "%s/%jd.dat", dir, (intmax_t) pid);
+  hname_len = GNUNET_OS_get_hostname_max_length ();
+  hname = GNUNET_malloc (hname_len);
+  if (0 != gethostname (hname, hname_len))
+  {
+    LOG (GNUNET_ERROR_TYPE_ERROR, "Cannot get hostname.  Exiting\n");
+    GNUNET_free (hname);
+    GNUNET_free (dir);
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  (void) GNUNET_asprintf (&fn, "%s/%.*s_%jd.dat", dir, hname_len, hname,
+                          (intmax_t) pid);
+  GNUNET_free (hname);
   GNUNET_free (dir);
   if (NULL == (bio = GNUNET_BIO_write_open (fn)))
   {
     GNUNET_free (fn);
+    GNUNET_SCHEDULER_shutdown ();
     return;
   }
   GNUNET_free (fn);
   GNUNET_SERVER_add_handlers (server, message_handlers);
+  GNUNET_SERVER_connect_notify (server, &client_connected, NULL);
+  GNUNET_SERVER_disconnect_notify (server, &client_disconnected, NULL);
   shutdown_task_id =
       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
                                     &shutdown_task, NULL);
@@ -256,7 +261,7 @@ main (int argc, char *const *argv)
 {
   //sleep (15);                 /* Debugging */
   return (GNUNET_OK ==
-          GNUNET_SERVICE_run (argc, argv, "testbed-logger", 
+          GNUNET_SERVICE_run (argc, argv, "testbed-logger",
                               GNUNET_SERVICE_OPTION_NONE,
                               &logger_run, NULL)) ? 0 : 1;
 }