aboutsummaryrefslogtreecommitdiff
path: root/src/testbed-logger/gnunet-service-testbed-logger.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/testbed-logger/gnunet-service-testbed-logger.c')
-rw-r--r--src/testbed-logger/gnunet-service-testbed-logger.c270
1 files changed, 270 insertions, 0 deletions
diff --git a/src/testbed-logger/gnunet-service-testbed-logger.c b/src/testbed-logger/gnunet-service-testbed-logger.c
new file mode 100644
index 000000000..1c250b306
--- /dev/null
+++ b/src/testbed-logger/gnunet-service-testbed-logger.c
@@ -0,0 +1,270 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2008--2013 GNUnet e.V.
4
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.
9
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.
14
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., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file testbed-logger/gnunet-service-testbed-logger.c
23 * @brief service for collecting messages and writing to a file
24 * @author Sree Harsha Totakura
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29
30/**
31 * Generic logging shorthand
32 */
33#define LOG(type, ...) \
34 GNUNET_log (type, __VA_ARGS__)
35
36/**
37 * Debug logging shorthand
38 */
39#define LOG_DEBUG(...) \
40 LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
41
42/**
43 * The message queue for sending messages to clients
44 */
45struct MessageQueue
46{
47 /**
48 * The message to be sent
49 */
50 struct GNUNET_MessageHeader *msg;
51
52 /**
53 * The client to send the message to
54 */
55 struct GNUNET_SERVER_Client *client;
56
57 /**
58 * next pointer for DLL
59 */
60 struct MessageQueue *next;
61
62 /**
63 * prev pointer for DLL
64 */
65 struct MessageQueue *prev;
66};
67
68/**
69 * The message queue head
70 */
71static struct MessageQueue *mq_head;
72
73/**
74 * The message queue tail
75 */
76static struct MessageQueue *mq_tail;
77
78/**
79 * Handle for buffered writing.
80 */
81struct GNUNET_BIO_WriteHandle *bio;
82
83/**
84 * The number of connections we have
85 */
86static unsigned int nconn;
87
88/**
89 * Are we shutting down?
90 */
91static int in_shutdown;
92
93
94/**
95 * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
96 *
97 * @param cls NULL
98 * @param client identification of the client
99 * @param msg the actual message
100 */
101static void
102handle_log_msg (void *cls,
103 struct GNUNET_SERVER_Client *client,
104 const struct GNUNET_MessageHeader *msg)
105{
106 uint16_t ms;
107
108 ms = ntohs (msg->size);
109 ms -= sizeof (struct GNUNET_MessageHeader);
110 GNUNET_BIO_write (bio, &msg[1], ms);
111 GNUNET_SERVER_receive_done (client, GNUNET_OK);
112}
113
114
115/**
116 * Task to clean up and shutdown nicely
117 *
118 * @param cls NULL
119 */
120static void
121shutdown_task (void *cls)
122{
123 struct MessageQueue *mq_entry;
124
125 in_shutdown = GNUNET_YES;
126 if (0 != nconn)
127 {
128 /* Delay shutdown if there are active connections */
129 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
130 return;
131 }
132 while (NULL != (mq_entry = mq_head))
133 {
134 GNUNET_free (mq_entry->msg);
135 GNUNET_SERVER_client_drop (mq_entry->client);
136 GNUNET_CONTAINER_DLL_remove (mq_head,
137 mq_tail,
138 mq_entry);
139 GNUNET_free (mq_entry);
140 }
141 GNUNET_break (GNUNET_OK == GNUNET_BIO_write_close (bio));
142}
143
144
145/**
146x * Functions with this signature are called whenever a client
147 * is disconnected on the network level.
148 *
149 * @param cls closure
150 * @param client identification of the client; NULL
151 * for the last call when the server is destroyed
152 */
153static void
154client_disconnected (void *cls,
155 struct GNUNET_SERVER_Client *client)
156{
157 if (NULL == client)
158 {
159 GNUNET_break (0 == nconn);
160 return;
161 }
162 nconn--;
163 if (GNUNET_YES == in_shutdown)
164 GNUNET_SCHEDULER_shutdown ();
165}
166
167
168/**
169 * Functions with this signature are called whenever a client
170 * is connected on the network level.
171 *
172 * @param cls closure
173 * @param client identification of the client
174 */
175static void
176client_connected (void *cls,
177 struct GNUNET_SERVER_Client *client)
178{
179 if (NULL == client)
180 {
181 GNUNET_break (0 == nconn);
182 return;
183 }
184 GNUNET_SERVER_client_persist_ (client);
185 nconn++;
186}
187
188
189/**
190 * Testbed setup
191 *
192 * @param cls closure
193 * @param server the initialized server
194 * @param cfg configuration to use
195 */
196static void
197logger_run (void *cls,
198 struct GNUNET_SERVER_Handle *server,
199 const struct GNUNET_CONFIGURATION_Handle *cfg)
200{
201 static const struct GNUNET_SERVER_MessageHandler message_handlers[] = {
202 {&handle_log_msg, NULL, GNUNET_MESSAGE_TYPE_TESTBED_LOGGER_MSG, 0},
203 {NULL, NULL, 0, 0}
204 };
205 char *dir;
206 char *fn;
207 char *hname;
208 size_t hname_len;
209 pid_t pid;
210
211 if (GNUNET_OK !=
212 GNUNET_CONFIGURATION_get_value_filename (cfg,
213 "TESTBED-LOGGER",
214 "DIR",
215 &dir))
216 {
217 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
218 "TESTBED-LOGGER",
219 "DIR");
220 GNUNET_SCHEDULER_shutdown ();
221 return;
222 }
223 pid = getpid ();
224 hname_len = GNUNET_OS_get_hostname_max_length ();
225 hname = GNUNET_malloc (hname_len);
226 if (0 != gethostname (hname, hname_len))
227 {
228 LOG (GNUNET_ERROR_TYPE_ERROR,
229 "Cannot get hostname. Exiting\n");
230 GNUNET_free (hname);
231 GNUNET_free (dir);
232 GNUNET_SCHEDULER_shutdown ();
233 return;
234 }
235 GNUNET_asprintf (&fn,
236 "%s/%.*s_%jd.dat",
237 dir,
238 hname_len,
239 hname,
240 (intmax_t) pid);
241 GNUNET_free (hname);
242 GNUNET_free (dir);
243 if (NULL == (bio = GNUNET_BIO_write_open (fn)))
244 {
245 GNUNET_free (fn);
246 GNUNET_SCHEDULER_shutdown ();
247 return;
248 }
249 GNUNET_free (fn);
250 GNUNET_SERVER_add_handlers (server, message_handlers);
251 GNUNET_SERVER_connect_notify (server, &client_connected, NULL);
252 GNUNET_SERVER_disconnect_notify (server, &client_disconnected, NULL);
253 GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
254 LOG_DEBUG ("TESTBED-LOGGER startup complete\n");
255}
256
257
258/**
259 * The starting point of execution
260 */
261int
262main (int argc, char *const *argv)
263{
264 return (GNUNET_OK ==
265 GNUNET_SERVICE_run (argc, argv, "testbed-logger",
266 GNUNET_SERVICE_OPTION_NONE,
267 &logger_run, NULL)) ? 0 : 1;
268}
269
270/* end of gnunet-service-testbed-logger.c */