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