2 This file is part of GNUnet.
3 (C) 2008--2013 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file testbed/gnunet-service-testbed-logger.c
23 * @brief service for collecting messages and writing to a file
24 * @author Sree Harsha Totakura
28 #include "gnunet_util_lib.h"
31 * Generic logging shorthand
33 #define LOG(type, ...) \
34 GNUNET_log (type, __VA_ARGS__)
37 * Debug logging shorthand
39 #define LOG_DEBUG(...) \
40 LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
43 * The message queue for sending messages to clients
48 * The message to be sent
50 struct GNUNET_MessageHeader *msg;
53 * The client to send the message to
55 struct GNUNET_SERVER_Client *client;
58 * next pointer for DLL
60 struct MessageQueue *next;
63 * prev pointer for DLL
65 struct MessageQueue *prev;
69 * The message queue head
71 static struct MessageQueue *mq_head;
74 * The message queue tail
76 static struct MessageQueue *mq_tail;
79 * Handle for buffered writing.
81 struct GNUNET_BIO_WriteHandle *bio;
84 * The shutdown task handle
86 static struct GNUNET_SCHEDULER_Task * shutdown_task_id;
89 * The number of connections we have
91 static unsigned int nconn;
94 * Are we shutting down?
96 static int in_shutdown;
99 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
102 * @param client identification of the client
103 * @param msg the actual message
106 handle_log_msg (void *cls, struct GNUNET_SERVER_Client *client,
107 const struct GNUNET_MessageHeader *msg)
111 ms = ntohs (msg->size);
112 ms -= sizeof (struct GNUNET_MessageHeader);
113 GNUNET_BIO_write (bio, &msg[1], ms);
114 GNUNET_SERVER_receive_done (client, GNUNET_OK);
119 * Task to clean up and shutdown nicely
122 * @param tc the TaskContext from scheduler
125 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
127 struct MessageQueue *mq_entry;
129 shutdown_task_id = NULL;
130 in_shutdown = GNUNET_YES;
133 /* Delay shutdown if there are active connections */
134 shutdown_task_id = GNUNET_SCHEDULER_add_delayed
135 (GNUNET_TIME_UNIT_FOREVER_REL,
136 &shutdown_task, NULL);
139 while (NULL != (mq_entry = mq_head))
141 GNUNET_free (mq_entry->msg);
142 GNUNET_SERVER_client_drop (mq_entry->client);
143 GNUNET_CONTAINER_DLL_remove (mq_head, mq_tail, mq_entry);
144 GNUNET_free (mq_entry);
146 GNUNET_break (GNUNET_OK == GNUNET_BIO_write_close (bio));
151 * Functions with this signature are called whenever a client
152 * is disconnected on the network level.
155 * @param client identification of the client; NULL
156 * for the last call when the server is destroyed
159 client_disconnected (void *cls, struct GNUNET_SERVER_Client *client)
163 GNUNET_break (0 == nconn);
167 if (GNUNET_YES != in_shutdown)
169 GNUNET_assert (NULL != shutdown_task_id);
170 GNUNET_SCHEDULER_cancel (shutdown_task_id);
171 shutdown_task_id = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
176 * Functions with this signature are called whenever a client
177 * is connected on the network level.
180 * @param client identification of the client
183 client_connected (void *cls, struct GNUNET_SERVER_Client *client)
187 GNUNET_break (0 == nconn);
190 GNUNET_SERVER_client_persist_ (client);
199 * @param server the initialized server
200 * @param cfg configuration to use
203 logger_run (void *cls, struct GNUNET_SERVER_Handle *server,
204 const struct GNUNET_CONFIGURATION_Handle *cfg)
206 static const struct GNUNET_SERVER_MessageHandler message_handlers[] = {
207 {&handle_log_msg, NULL, GNUNET_MESSAGE_TYPE_TESTBED_LOGGER_MSG, 0},
217 GNUNET_CONFIGURATION_get_value_filename (cfg, "TESTBED-LOGGER", "DIR",
220 LOG (GNUNET_ERROR_TYPE_ERROR, "Not logging directory definied. Exiting\n");
221 GNUNET_SCHEDULER_shutdown ();
225 hname_len = GNUNET_OS_get_hostname_max_length ();
226 hname = GNUNET_malloc (hname_len);
227 if (0 != gethostname (hname, hname_len))
229 LOG (GNUNET_ERROR_TYPE_ERROR, "Cannot get hostname. Exiting\n");
232 GNUNET_SCHEDULER_shutdown ();
235 (void) GNUNET_asprintf (&fn, "%s/%.*s_%jd.dat", dir, hname_len, hname,
239 if (NULL == (bio = GNUNET_BIO_write_open (fn)))
242 GNUNET_SCHEDULER_shutdown ();
246 GNUNET_SERVER_add_handlers (server, message_handlers);
247 GNUNET_SERVER_connect_notify (server, &client_connected, NULL);
248 GNUNET_SERVER_disconnect_notify (server, &client_disconnected, NULL);
250 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
251 &shutdown_task, NULL);
252 LOG_DEBUG ("TESTBED-LOGGER startup complete\n");
257 * The starting point of execution
260 main (int argc, char *const *argv)
262 //sleep (15); /* Debugging */
264 GNUNET_SERVICE_run (argc, argv, "testbed-logger",
265 GNUNET_SERVICE_OPTION_NONE,
266 &logger_run, NULL)) ? 0 : 1;
269 /* end of gnunet-service-testbed.c */