glitch in the license text detected by hyazinthe, thank you!
[oweals/gnunet.git] / src / testbed-logger / gnunet-service-testbed-logger.c
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 it
6   under the terms of the GNU Affero General Public License as published
7   by the Free Software Foundation, either version 3 of the License,
8   or (at your 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   Affero General Public License for more details.
14 */
15
16 /**
17  * @file testbed-logger/gnunet-service-testbed-logger.c
18  * @brief service for collecting messages and writing to a file
19  * @author Sree Harsha Totakura
20  */
21
22 #include "platform.h"
23 #include "gnunet_util_lib.h"
24
25 /**
26  * Generic logging shorthand
27  */
28 #define LOG(type, ...)                         \
29   GNUNET_log (type, __VA_ARGS__)
30
31 /**
32  * Debug logging shorthand
33  */
34 #define LOG_DEBUG(...)                          \
35   LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
36
37 /**
38  * Handle for buffered writing.
39  */
40 struct GNUNET_BIO_WriteHandle *bio;
41
42 /**
43  * The number of connections we have
44  */
45 static unsigned int nconn;
46
47 /**
48  * Are we shutting down?
49  */
50 static int in_shutdown;
51
52
53 /**
54  * Check #GNUNET_MESSAGE_TYPE_TESTBED_LOGGER_MSG messages
55  *
56  * @param cls client identification of the client
57  * @param msg the actual message
58  * @return #GNUNET_OK (they are all always OK)
59  */
60 static int
61 check_log_msg (void *cls,
62                const struct GNUNET_MessageHeader *msg)
63 {
64   return GNUNET_OK;
65 }
66
67
68 /**
69  * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_LOGGER_MSG messages
70  *
71  * @param cls client identification of the client
72  * @param msg the actual message
73  */
74 static void
75 handle_log_msg (void *cls,
76                 const struct GNUNET_MessageHeader *msg)
77 {
78   struct GNUNET_SERVICE_Client *client = cls;
79   uint16_t ms;
80
81   ms = ntohs (msg->size) - sizeof (struct GNUNET_MessageHeader);
82   GNUNET_BIO_write (bio,
83                     &msg[1],
84                     ms);
85   GNUNET_SERVICE_client_continue (client);
86 }
87
88
89 /**
90  * Task to clean up and shutdown nicely
91  *
92  * @param cls NULL
93  */
94 static void
95 shutdown_task (void *cls)
96 {
97   in_shutdown = GNUNET_YES;
98   if (0 != nconn)
99   {
100     /* Delay shutdown if there are active connections */
101     GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
102                                    NULL);
103     return;
104   }
105   GNUNET_break (GNUNET_OK ==
106                 GNUNET_BIO_write_close (bio));
107 }
108
109
110 /**
111  * Callback called when a client connects to the service.
112  *
113  * @param cls closure for the service
114  * @param c the new client that connected to the service
115  * @param mq the message queue used to send messages to the client
116  * @return @a c
117  */
118 static void *
119 client_connect_cb (void *cls,
120                    struct GNUNET_SERVICE_Client *c,
121                    struct GNUNET_MQ_Handle *mq)
122 {
123   /* FIXME: is this really what we want here? */
124   GNUNET_SERVICE_client_persist (c);
125   nconn++;
126   return c;
127 }
128
129
130 /**
131  * Callback called when a client disconnected from the service
132  *
133  * @param cls closure for the service
134  * @param c the client that disconnected
135  * @param internal_cls should be equal to @a c
136  */
137 static void
138 client_disconnect_cb (void *cls,
139                       struct GNUNET_SERVICE_Client *c,
140                       void *internal_cls)
141 {
142   nconn--;
143   if (GNUNET_YES == in_shutdown)
144     GNUNET_SCHEDULER_shutdown ();
145   GNUNET_assert (c == internal_cls);
146 }
147
148
149 /**
150  * Testbed setup
151  *
152  * @param cls closure
153  * @param cfg configuration to use
154  * @param service the initialized service
155  */
156 static void
157 logger_run (void *cls,
158             const struct GNUNET_CONFIGURATION_Handle *cfg,
159             struct GNUNET_SERVICE_Handle *service)
160 {
161   char *dir;
162   char *fn;
163   char *hname;
164   size_t hname_len;
165   pid_t pid;
166
167   if (GNUNET_OK !=
168       GNUNET_CONFIGURATION_get_value_filename (cfg,
169                                                "TESTBED-LOGGER",
170                                                "DIR",
171                                                &dir))
172   {
173     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
174                                "TESTBED-LOGGER",
175                                "DIR");
176     GNUNET_SCHEDULER_shutdown ();
177     return;
178   }
179   pid = getpid ();
180   hname_len = GNUNET_OS_get_hostname_max_length ();
181   hname = GNUNET_malloc (hname_len);
182   if (0 != gethostname (hname,
183                         hname_len))
184   {
185     LOG (GNUNET_ERROR_TYPE_ERROR,
186          "Cannot get hostname.  Exiting\n");
187     GNUNET_free (hname);
188     GNUNET_free (dir);
189     GNUNET_SCHEDULER_shutdown ();
190     return;
191   }
192   GNUNET_asprintf (&fn,
193                    "%s/%.*s_%jd.dat",
194                    dir,
195                    hname_len,
196                    hname,
197                    (intmax_t) pid);
198   GNUNET_free (hname);
199   GNUNET_free (dir);
200   if (NULL == (bio = GNUNET_BIO_write_open (fn)))
201   {
202     GNUNET_free (fn);
203     GNUNET_SCHEDULER_shutdown ();
204     return;
205   }
206   GNUNET_free (fn);
207   GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
208                                  NULL);
209   LOG_DEBUG ("TESTBED-LOGGER startup complete\n");
210 }
211
212
213 /**
214  * Define "main" method using service macro.
215  */
216 GNUNET_SERVICE_MAIN
217 ("testbed-logger",
218  GNUNET_SERVICE_OPTION_NONE,
219  &logger_run,
220  &client_connect_cb,
221  &client_disconnect_cb,
222  NULL,
223  GNUNET_MQ_hd_var_size (log_msg,
224                         GNUNET_MESSAGE_TYPE_TESTBED_LOGGER_MSG,
225                         struct GNUNET_MessageHeader,
226                         NULL),
227  GNUNET_MQ_handler_end ());
228
229
230 /* end of gnunet-service-testbed-logger.c */