add copyright headers, fix includes
[oweals/gnunet.git] / src / sensor / gnunet-service-sensor.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C)
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 sensor/gnunet-service-sensor.c
23  * @brief sensor service implementation
24  * @author Omar Tarabai
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "sensor.h"
29
30 /**
31  * Our configuration.
32  */
33 static const struct GNUNET_CONFIGURATION_Handle *cfg;
34
35 /**
36  * Path to sensor definitions directory
37  */
38 static char *sensor_dir;
39
40 /**
41  * Hashmap of loaded sensor definitions
42  */
43 static struct GNUNET_CONTAINER_MultiHashMap *sensors;
44
45 /**
46  * Start the monitoring module ?
47  */
48 static int start_monitoring;
49
50 /**
51  * Start the analysis module ?
52  */
53 static int start_analysis;
54
55 /**
56  * Start the reporting module ?
57  */
58 static int start_reporting;
59
60 /**
61  * Start the update module ?
62  */
63 static int start_update;
64
65
66 /**
67  * Resets the service by stopping components, reloading sensors and starting
68  * components. This is needed when we receive new sensor updates.
69  */
70 static void
71 reset ();
72
73
74 /**
75  * Stops components and destroys sensors
76  */
77 static void
78 stop ()
79 {
80   if (GNUNET_YES == start_update)
81     SENSOR_update_stop ();
82   if (GNUNET_YES == start_analysis)
83     SENSOR_analysis_stop ();
84   if (GNUNET_YES == start_reporting)
85     SENSOR_reporting_stop ();
86   if (GNUNET_YES == start_monitoring)
87     SENSOR_monitoring_stop ();
88   GNUNET_SENSOR_destroy_sensors (sensors);
89 }
90
91
92 /**
93  * Task run during shutdown.
94  *
95  * @param cls unused
96  * @param tc unused
97  */
98 static void
99 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
100 {
101   stop ();
102   if (NULL != sensor_dir)
103   {
104     GNUNET_free (sensor_dir);
105     sensor_dir = NULL;
106   }
107   GNUNET_SCHEDULER_shutdown ();
108 }
109
110
111 /**
112  * Handle a force anomaly request from client.
113  *
114  * @param cls closure
115  * @param client identification of the client
116  * @param message the actual message
117  */
118 static void
119 handle_anomaly_force (void *cls, struct GNUNET_SERVER_Client *client,
120                       const struct GNUNET_MessageHeader *message)
121 {
122   struct ForceAnomalyMessage *anomaly_msg;
123   struct GNUNET_SENSOR_SensorInfo *sensor;
124
125   anomaly_msg = (struct ForceAnomalyMessage *) message;
126   sensor =
127       GNUNET_CONTAINER_multihashmap_get (sensors,
128                                          &anomaly_msg->sensor_name_hash);
129   if (NULL == sensor)
130   {
131     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
132                 "Force anomaly message received for a sensor we don't have.\n");
133     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
134     return;
135   }
136   SENSOR_reporting_anomaly_update (sensor, ntohs (anomaly_msg->anomalous));
137   GNUNET_SERVER_receive_done (client, GNUNET_YES);
138 }
139
140
141 /**
142  * Creates a structure with basic sensor info to be sent to a client.
143  *
144  * @param sensor sensor information
145  * @return message ready to be sent to client
146  */
147 static struct SensorInfoMessage *
148 create_sensor_info_msg (struct GNUNET_SENSOR_SensorInfo *sensor)
149 {
150   struct SensorInfoMessage *msg;
151   uint16_t len;
152   size_t name_len;
153   size_t desc_len;
154   char *str_ptr;
155
156   name_len = strlen (sensor->name);
157   if (NULL == sensor->description)
158     desc_len = 0;
159   else
160     desc_len = strlen (sensor->description) + 1;
161   len = 0;
162   len += sizeof (struct SensorInfoMessage);
163   len += name_len;
164   len += desc_len;
165   msg = GNUNET_malloc (len);
166   msg->header.size = htons (len);
167   msg->header.type = htons (GNUNET_MESSAGE_TYPE_SENSOR_INFO);
168   msg->name_len = htons (name_len);
169   msg->description_len = htons (desc_len);
170   msg->version_major = htons (sensor->version_major);
171   msg->version_minor = htons (sensor->version_minor);
172   str_ptr = (char *) &msg[1];
173   memcpy (str_ptr, sensor->name, name_len);
174   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending sensor name (%d): %.*s\n",
175               name_len, name_len, str_ptr);
176   str_ptr += name_len;
177   memcpy (str_ptr, sensor->description, desc_len);
178   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
179               "Sending sensor description (%d): %.*s\n", desc_len, desc_len,
180               str_ptr);
181   return msg;
182 }
183
184
185 /**
186  * Handle GET SENSOR message.
187  *
188  * @param cls closure
189  * @param client identification of the client
190  * @param message the actual message
191  */
192 static void
193 handle_get_sensor (void *cls, struct GNUNET_SERVER_Client *client,
194                    const struct GNUNET_MessageHeader *message)
195 {
196   struct GNUNET_SERVER_TransmitContext *tc;
197   char *sensorname;
198   size_t sensorname_len;
199   struct GNUNET_HashCode key;
200   struct GNUNET_SENSOR_SensorInfo *sensorinfo;
201   struct SensorInfoMessage *msg;
202
203   sensorname = (char *) &message[1];
204   sensorname_len = ntohs (message->size) - sizeof (struct GNUNET_MessageHeader);
205   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
206               "`%s' message received for sensor (%d) `%.*s'\n", "GET SENSOR",
207               sensorname_len, sensorname_len, sensorname);
208   tc = GNUNET_SERVER_transmit_context_create (client);
209   GNUNET_CRYPTO_hash (sensorname, sensorname_len, &key);
210   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
211               "Created key hash for requested sensor\n");
212   sensorinfo =
213       (struct GNUNET_SENSOR_SensorInfo *)
214       GNUNET_CONTAINER_multihashmap_get (sensors, &key);
215   if (NULL != sensorinfo)
216   {
217     msg = create_sensor_info_msg (sensorinfo);
218     GNUNET_SERVER_transmit_context_append_message (tc,
219                                                    (struct GNUNET_MessageHeader
220                                                     *) msg);
221     GNUNET_free (msg);
222   }
223   else
224     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
225                 "Requested sensor `%.*s' was not found\n", sensorname_len,
226                 sensorname);
227   GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
228                                               GNUNET_MESSAGE_TYPE_SENSOR_END);
229   GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
230 }
231
232
233 /**
234  * Iterator for sensors and adds them to transmit context
235  *
236  * @param cls a `struct GNUNET_SERVER_TransmitContext *`
237  * @param key hash of sensor name, key to hashmap
238  * @param value a `struct GNUNET_SENSOR_SensorInfo *`
239  */
240 static int
241 add_sensor_to_tc (void *cls, const struct GNUNET_HashCode *key, void *value)
242 {
243   struct GNUNET_SERVER_TransmitContext *tc = cls;
244   struct GNUNET_SENSOR_SensorInfo *sensorinfo = value;
245   struct SensorInfoMessage *msg;
246
247   msg = create_sensor_info_msg (sensorinfo);
248   GNUNET_SERVER_transmit_context_append_message (tc,
249                                                  (struct GNUNET_MessageHeader *)
250                                                  msg);
251
252   GNUNET_free (msg);
253   return GNUNET_YES;
254 }
255
256
257 /**
258  * Handle GET ALL SENSORS message.
259  *
260  * @param cls closure
261  * @param client identification of the client
262  * @param message the actual message
263  */
264 static void
265 handle_get_all_sensors (void *cls, struct GNUNET_SERVER_Client *client,
266                         const struct GNUNET_MessageHeader *message)
267 {
268   struct GNUNET_SERVER_TransmitContext *tc;
269
270   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "`%s' message received.\n",
271               "GET ALL SENSOR");
272   tc = GNUNET_SERVER_transmit_context_create (client);
273   GNUNET_CONTAINER_multihashmap_iterate (sensors, &add_sensor_to_tc, tc);
274   GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
275                                               GNUNET_MESSAGE_TYPE_SENSOR_END);
276   GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
277 }
278
279
280 /**
281  * Loads sensors and starts different service components
282  */
283 static void
284 start ()
285 {
286   sensors = GNUNET_SENSOR_load_all_sensors (sensor_dir);
287   if (GNUNET_YES == start_monitoring)
288     SENSOR_monitoring_start (cfg, sensors);
289   if (GNUNET_YES == start_reporting)
290     SENSOR_reporting_start (cfg, sensors);
291   if (GNUNET_YES == start_analysis)
292     SENSOR_analysis_start (cfg, sensors);
293   if (GNUNET_YES == start_update)
294     SENSOR_update_start (cfg, sensors, &reset);
295 }
296
297
298 /**
299  * Process statistics requests.
300  *
301  * @param cls closure
302  * @param server the initialized server
303  * @param c configuration to use
304  */
305 static void
306 run (void *cls, struct GNUNET_SERVER_Handle *server,
307      const struct GNUNET_CONFIGURATION_Handle *c)
308 {
309   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
310     {&handle_get_sensor, NULL, GNUNET_MESSAGE_TYPE_SENSOR_GET,
311      0},
312     {&handle_get_all_sensors, NULL, GNUNET_MESSAGE_TYPE_SENSOR_GETALL,
313      sizeof (struct GNUNET_MessageHeader)},
314     {
315      &handle_anomaly_force, NULL, GNUNET_MESSAGE_TYPE_SENSOR_ANOMALY_FORCE,
316      sizeof (struct ForceAnomalyMessage)},
317     {NULL, NULL, 0, 0}
318   };
319
320   cfg = c;
321   if (GNUNET_OK !=
322       GNUNET_CONFIGURATION_get_value_filename (cfg, "sensor", "SENSOR_DIR",
323                                                &sensor_dir))
324   {
325     sensor_dir = GNUNET_SENSOR_get_default_sensor_dir ();
326   }
327   start_monitoring = GNUNET_YES;
328   start_analysis = GNUNET_YES;
329   start_reporting = GNUNET_YES;
330   start_update = GNUNET_YES;
331   if (GNUNET_NO ==
332       GNUNET_CONFIGURATION_get_value_yesno (cfg, "sensor", "START_MONITORING"))
333   {
334     start_monitoring = GNUNET_NO;
335   }
336   if (GNUNET_NO ==
337       GNUNET_CONFIGURATION_get_value_yesno (cfg, "sensor", "START_REPORTING"))
338   {
339     start_reporting = GNUNET_NO;
340   }
341   if (GNUNET_NO ==
342       GNUNET_CONFIGURATION_get_value_yesno (cfg, "sensor", "START_ANALYSIS"))
343   {
344     start_analysis = GNUNET_NO;
345   }
346   if (GNUNET_NO ==
347       GNUNET_CONFIGURATION_get_value_yesno (cfg, "sensor", "START_UPDATE"))
348   {
349     start_update = GNUNET_NO;
350   }
351   GNUNET_SERVER_add_handlers (server, handlers);
352   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
353                                 NULL);
354   start ();
355 }
356
357
358 /**
359  * Resets the service by stopping components, reloading sensors and starting
360  * components. This is needed when we receive new sensor updates.
361  */
362 static void
363 reset ()
364 {
365   stop ();
366   start ();
367 }
368
369
370 /**
371  * The main function for the sensor service.
372  *
373  * @param argc number of arguments from the command line
374  * @param argv command line arguments
375  * @return 0 ok, 1 on error
376  */
377 int
378 main (int argc, char *const *argv)
379 {
380   return (GNUNET_OK ==
381           GNUNET_SERVICE_run (argc, argv, "sensor", GNUNET_SERVICE_OPTION_NONE,
382                               &run, NULL)) ? 0 : 1;
383 }
384
385 /* end of gnunet-service-sensor.c */