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 2, 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 * Current Transmit Handle; NULL if no notify transmit exists currently
71 static struct GNUNET_SERVER_TransmitHandle *transmit_handle;
74 * The message queue head
76 static struct MessageQueue *mq_head;
79 * The message queue tail
81 static struct MessageQueue *mq_tail;
84 * Handle for buffered writing.
86 struct GNUNET_BIO_WriteHandle *bio;
89 * The shutdown task handle
91 static GNUNET_SCHEDULER_TaskIdentifier shutdown_task_id;
95 * Function called to notify a client about the connection begin ready to queue
96 * more data. "buf" will be NULL and "size" zero if the connection was closed
97 * for writing in the meantime.
100 * @param size number of bytes available in buf
101 * @param buf where the callee should write the message
102 * @return number of bytes written to buf
105 transmit_ready_notify (void *cls, size_t size, void *buf)
107 struct MessageQueue *mq_entry;
109 transmit_handle = NULL;
111 GNUNET_assert (NULL != mq_entry);
114 GNUNET_assert (ntohs (mq_entry->msg->size) <= size);
115 size = ntohs (mq_entry->msg->size);
116 memcpy (buf, mq_entry->msg, size);
117 GNUNET_free (mq_entry->msg);
118 GNUNET_SERVER_client_drop (mq_entry->client);
119 GNUNET_CONTAINER_DLL_remove (mq_head, mq_tail, mq_entry);
120 GNUNET_free (mq_entry);
122 if (NULL != mq_entry)
124 GNUNET_SERVER_notify_transmit_ready (mq_entry->client,
125 ntohs (mq_entry->msg->size),
126 GNUNET_TIME_UNIT_FOREVER_REL,
127 &transmit_ready_notify, NULL);
133 * Queues a message in send queue for sending to the service
135 * @param client the client to whom the queued message has to be sent
136 * @param msg the message to queue
139 queue_message (struct GNUNET_SERVER_Client *client,
140 struct GNUNET_MessageHeader *msg)
142 struct MessageQueue *mq_entry;
146 type = ntohs (msg->type);
147 size = ntohs (msg->size);
148 mq_entry = GNUNET_malloc (sizeof (struct MessageQueue));
150 mq_entry->client = client;
151 GNUNET_SERVER_client_keep (client);
152 LOG_DEBUG ("Queueing message of type %u, size %u for sending\n", type,
154 GNUNET_CONTAINER_DLL_insert_tail (mq_head, mq_tail, mq_entry);
155 if (NULL == transmit_handle)
157 GNUNET_SERVER_notify_transmit_ready (client, size,
158 GNUNET_TIME_UNIT_FOREVER_REL,
159 &transmit_ready_notify, NULL);
164 * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
167 * @param client identification of the client
168 * @param message the actual message
171 handle_log_msg (void *cls, struct GNUNET_SERVER_Client *client,
172 const struct GNUNET_MessageHeader *msg)
176 ms = ntohs (msg->size);
177 ms -= sizeof (struct GNUNET_MessageHeader);
178 GNUNET_BIO_write (bio, &msg[1], ms);
179 GNUNET_SERVER_receive_done (client, GNUNET_OK);
184 * Task to clean up and shutdown nicely
187 * @param tc the TaskContext from scheduler
190 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
192 struct MessageQueue *mq_entry;
194 shutdown_task_id = GNUNET_SCHEDULER_NO_TASK;
195 if (NULL != transmit_handle)
196 GNUNET_SERVER_notify_transmit_ready_cancel (transmit_handle);
197 while (NULL != (mq_entry = mq_head))
199 GNUNET_free (mq_entry->msg);
200 GNUNET_SERVER_client_drop (mq_entry->client);
201 GNUNET_CONTAINER_DLL_remove (mq_head, mq_tail, mq_entry);
202 GNUNET_free (mq_entry);
204 GNUNET_BIO_write_close (bio);
212 * @param server the initialized server
213 * @param cfg configuration to use
216 logger_run (void *cls, struct GNUNET_SERVER_Handle *server,
217 const struct GNUNET_CONFIGURATION_Handle *cfg)
219 static const struct GNUNET_SERVER_MessageHandler message_handlers[] = {
220 {&handle_log_msg, NULL, GNUNET_MESSAGE_TYPE_TESTBED_LOGGER_MSG, 0},
228 GNUNET_CONFIGURATION_get_value_filename (cfg, "TESTBED-LOGGER", "DIR",
231 LOG (GNUNET_ERROR_TYPE_ERROR, "Not logging directory definied. Exiting\n");
235 (void) GNUNET_asprintf (&fn, "%s/%jd.dat", dir, (intmax_t) pid);
237 if (NULL == (bio = GNUNET_BIO_write_open (fn)))
243 GNUNET_SERVER_add_handlers (server, message_handlers);
245 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
246 &shutdown_task, NULL);
247 LOG_DEBUG ("TESTBED-LOGGER startup complete\n");
252 * The starting point of execution
255 main (int argc, char *const *argv)
257 //sleep (15); /* Debugging */
259 GNUNET_SERVICE_run (argc, argv, "testbed-logger",
260 GNUNET_SERVICE_OPTION_NONE,
261 &logger_run, NULL)) ? 0 : 1;
264 /* end of gnunet-service-testbed.c */