/*
This file is part of GNUnet.
- (C) 2008--2013 Christian Grothoff (and other contributing authors)
+ Copyright (C) 2008--2013 GNUnet e.V.
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
You should have received a copy of the GNU General Public License
along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
*/
/**
struct MessageQueue *prev;
};
-/**
- * Current Transmit Handle; NULL if no notify transmit exists currently
- */
-static struct GNUNET_SERVER_TransmitHandle *transmit_handle;
-
/**
* The message queue head
*/
struct GNUNET_BIO_WriteHandle *bio;
/**
- * The shutdown task handle
- */
-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
+ * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
*
* @param cls NULL
* @param client identification of the client
* @param msg the actual message
*/
static void
-handle_log_msg (void *cls, struct GNUNET_SERVER_Client *client,
+handle_log_msg (void *cls,
+ struct GNUNET_SERVER_Client *client,
const struct GNUNET_MessageHeader *msg)
{
uint16_t ms;
* Task to clean up and shutdown nicely
*
* @param cls NULL
- * @param tc the TaskContext from scheduler
*/
static void
-shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+shutdown_task (void *cls)
{
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 */
+ GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
+ return;
+ }
while (NULL != (mq_entry = mq_head))
{
GNUNET_free (mq_entry->msg);
GNUNET_SERVER_client_drop (mq_entry->client);
- GNUNET_CONTAINER_DLL_remove (mq_head, mq_tail, mq_entry);
+ GNUNET_CONTAINER_DLL_remove (mq_head,
+ mq_tail,
+ mq_entry);
GNUNET_free (mq_entry);
}
GNUNET_break (GNUNET_OK == GNUNET_BIO_write_close (bio));
}
+/**
+x * 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)
+ GNUNET_SCHEDULER_shutdown ();
+}
+
+
+/**
+ * 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++;
+}
+
+
/**
* Testbed setup
*
* @param cfg configuration to use
*/
static void
-logger_run (void *cls, struct GNUNET_SERVER_Handle *server,
- const struct GNUNET_CONFIGURATION_Handle *cfg)
+logger_run (void *cls,
+ struct GNUNET_SERVER_Handle *server,
+ const struct GNUNET_CONFIGURATION_Handle *cfg)
{
static const struct GNUNET_SERVER_MessageHandler message_handlers[] = {
{&handle_log_msg, NULL, GNUNET_MESSAGE_TYPE_TESTBED_LOGGER_MSG, 0},
pid_t pid;
if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_filename (cfg, "TESTBED-LOGGER", "DIR",
+ GNUNET_CONFIGURATION_get_value_filename (cfg,
+ "TESTBED-LOGGER",
+ "DIR",
&dir))
{
- LOG (GNUNET_ERROR_TYPE_ERROR, "Not logging directory definied. Exiting\n");
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "TESTBED-LOGGER",
+ "DIR");
GNUNET_SCHEDULER_shutdown ();
return;
}
hname = GNUNET_malloc (hname_len);
if (0 != gethostname (hname, hname_len))
{
- LOG (GNUNET_ERROR_TYPE_ERROR, "Cannot get hostname. Exiting\n");
+ 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_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_SERVER_add_handlers (server, message_handlers);
- shutdown_task_id =
- GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
- &shutdown_task, NULL);
+ GNUNET_SERVER_connect_notify (server, &client_connected, NULL);
+ GNUNET_SERVER_disconnect_notify (server, &client_disconnected, NULL);
+ GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
LOG_DEBUG ("TESTBED-LOGGER startup complete\n");
}
int
main (int argc, char *const *argv)
{
- //sleep (15); /* Debugging */
return (GNUNET_OK ==
GNUNET_SERVICE_run (argc, argv, "testbed-logger",
GNUNET_SERVICE_OPTION_NONE,
&logger_run, NULL)) ? 0 : 1;
}
-/* end of gnunet-service-testbed.c */
+/* end of gnunet-service-testbed-logger.c */