sensor: force fake anomaly
[oweals/gnunet.git] / src / sensor / gnunet-service-sensor.c
1 /*
2      This file is part of GNUnet.
3      (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., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, 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     return;
134   }
135   SENSOR_reporting_anomaly_update (sensor, ntohs (anomaly_msg->anomalous));
136 }
137
138
139 /**
140  * Creates a structure with basic sensor info to be sent to a client.
141  *
142  * @param sensor sensor information
143  * @return message ready to be sent to client
144  */
145 static struct SensorInfoMessage *
146 create_sensor_info_msg (struct GNUNET_SENSOR_SensorInfo *sensor)
147 {
148   struct SensorInfoMessage *msg;
149   uint16_t len;
150   size_t name_len;
151   size_t desc_len;
152   char *str_ptr;
153
154   name_len = strlen (sensor->name);
155   if (NULL == sensor->description)
156     desc_len = 0;
157   else
158     desc_len = strlen (sensor->description) + 1;
159   len = 0;
160   len += sizeof (struct SensorInfoMessage);
161   len += name_len;
162   len += desc_len;
163   msg = GNUNET_malloc (len);
164   msg->header.size = htons (len);
165   msg->header.type = htons (GNUNET_MESSAGE_TYPE_SENSOR_INFO);
166   msg->name_len = htons (name_len);
167   msg->description_len = htons (desc_len);
168   msg->version_major = htons (sensor->version_major);
169   msg->version_minor = htons (sensor->version_minor);
170   str_ptr = (char *) &msg[1];
171   memcpy (str_ptr, sensor->name, name_len);
172   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending sensor name (%d): %.*s\n",
173               name_len, name_len, str_ptr);
174   str_ptr += name_len;
175   memcpy (str_ptr, sensor->description, desc_len);
176   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
177               "Sending sensor description (%d): %.*s\n", desc_len, desc_len,
178               str_ptr);
179   return msg;
180 }
181
182
183 /**
184  * Handle GET SENSOR message.
185  *
186  * @param cls closure
187  * @param client identification of the client
188  * @param message the actual message
189  */
190 static void
191 handle_get_sensor (void *cls, struct GNUNET_SERVER_Client *client,
192                    const struct GNUNET_MessageHeader *message)
193 {
194   struct GNUNET_SERVER_TransmitContext *tc;
195   char *sensorname;
196   size_t sensorname_len;
197   struct GNUNET_HashCode key;
198   struct GNUNET_SENSOR_SensorInfo *sensorinfo;
199   struct SensorInfoMessage *msg;
200
201   sensorname = (char *) &message[1];
202   sensorname_len = ntohs (message->size) - sizeof (struct GNUNET_MessageHeader);
203   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
204               "`%s' message received for sensor (%d) `%.*s'\n", "GET SENSOR",
205               sensorname_len, sensorname_len, sensorname);
206   tc = GNUNET_SERVER_transmit_context_create (client);
207   GNUNET_CRYPTO_hash (sensorname, sensorname_len, &key);
208   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
209               "Created key hash for requested sensor\n");
210   sensorinfo =
211       (struct GNUNET_SENSOR_SensorInfo *)
212       GNUNET_CONTAINER_multihashmap_get (sensors, &key);
213   if (NULL != sensorinfo)
214   {
215     msg = create_sensor_info_msg (sensorinfo);
216     GNUNET_SERVER_transmit_context_append_message (tc,
217                                                    (struct GNUNET_MessageHeader
218                                                     *) msg);
219     GNUNET_free (msg);
220   }
221   else
222     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
223                 "Requested sensor `%.*s' was not found\n", sensorname_len,
224                 sensorname);
225   GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
226                                               GNUNET_MESSAGE_TYPE_SENSOR_END);
227   GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
228 }
229
230
231 /**
232  * Iterator for sensors and adds them to transmit context
233  *
234  * @param cls a `struct GNUNET_SERVER_TransmitContext *`
235  * @param key hash of sensor name, key to hashmap
236  * @param value a `struct GNUNET_SENSOR_SensorInfo *`
237  */
238 static int
239 add_sensor_to_tc (void *cls, const struct GNUNET_HashCode *key, void *value)
240 {
241   struct GNUNET_SERVER_TransmitContext *tc = cls;
242   struct GNUNET_SENSOR_SensorInfo *sensorinfo = value;
243   struct SensorInfoMessage *msg;
244
245   msg = create_sensor_info_msg (sensorinfo);
246   GNUNET_SERVER_transmit_context_append_message (tc,
247                                                  (struct GNUNET_MessageHeader *)
248                                                  msg);
249
250   GNUNET_free (msg);
251   return GNUNET_YES;
252 }
253
254
255 /**
256  * Handle GET ALL SENSORS message.
257  *
258  * @param cls closure
259  * @param client identification of the client
260  * @param message the actual message
261  */
262 static void
263 handle_get_all_sensors (void *cls, struct GNUNET_SERVER_Client *client,
264                         const struct GNUNET_MessageHeader *message)
265 {
266   struct GNUNET_SERVER_TransmitContext *tc;
267
268   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "`%s' message received.\n",
269               "GET ALL SENSOR");
270   tc = GNUNET_SERVER_transmit_context_create (client);
271   GNUNET_CONTAINER_multihashmap_iterate (sensors, &add_sensor_to_tc, tc);
272   GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
273                                               GNUNET_MESSAGE_TYPE_SENSOR_END);
274   GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
275 }
276
277
278 /**
279  * Loads sensors and starts different service components
280  */
281 static void
282 start ()
283 {
284   sensors = GNUNET_SENSOR_load_all_sensors (sensor_dir);
285   if (GNUNET_YES == start_monitoring)
286     SENSOR_monitoring_start (cfg, sensors);
287   if (GNUNET_YES == start_reporting)
288     SENSOR_reporting_start (cfg, sensors);
289   if (GNUNET_YES == start_analysis)
290     SENSOR_analysis_start (cfg, sensors);
291   if (GNUNET_YES == start_update)
292     SENSOR_update_start (cfg, sensors, &reset);
293 }
294
295
296 /**
297  * Process statistics requests.
298  *
299  * @param cls closure
300  * @param server the initialized server
301  * @param c configuration to use
302  */
303 static void
304 run (void *cls, struct GNUNET_SERVER_Handle *server,
305      const struct GNUNET_CONFIGURATION_Handle *c)
306 {
307   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
308     {&handle_get_sensor, NULL, GNUNET_MESSAGE_TYPE_SENSOR_GET,
309      0},
310     {&handle_get_all_sensors, NULL, GNUNET_MESSAGE_TYPE_SENSOR_GETALL,
311      sizeof (struct GNUNET_MessageHeader)},
312     {
313      &handle_anomaly_force, NULL, GNUNET_MESSAGE_TYPE_SENSOR_ANOMALY_FORCE,
314      sizeof (struct ForceAnomalyMessage)},
315     {NULL, NULL, 0, 0}
316   };
317
318   cfg = c;
319   if (GNUNET_OK !=
320       GNUNET_CONFIGURATION_get_value_filename (cfg, "sensor", "SENSOR_DIR",
321                                                &sensor_dir))
322   {
323     sensor_dir = GNUNET_SENSOR_get_default_sensor_dir ();
324   }
325   start_monitoring = GNUNET_YES;
326   start_analysis = GNUNET_YES;
327   start_reporting = GNUNET_YES;
328   start_update = GNUNET_YES;
329   if (GNUNET_NO ==
330       GNUNET_CONFIGURATION_get_value_yesno (cfg, "sensor", "START_MONITORING"))
331   {
332     start_monitoring = GNUNET_NO;
333   }
334   if (GNUNET_NO ==
335       GNUNET_CONFIGURATION_get_value_yesno (cfg, "sensor", "START_REPORTING"))
336   {
337     start_reporting = GNUNET_NO;
338   }
339   if (GNUNET_NO ==
340       GNUNET_CONFIGURATION_get_value_yesno (cfg, "sensor", "START_ANALYSIS"))
341   {
342     start_analysis = GNUNET_NO;
343   }
344   if (GNUNET_NO ==
345       GNUNET_CONFIGURATION_get_value_yesno (cfg, "sensor", "START_UPDATE"))
346   {
347     start_update = GNUNET_NO;
348   }
349   GNUNET_SERVER_add_handlers (server, handlers);
350   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
351                                 NULL);
352   start ();
353 }
354
355
356 /**
357  * Resets the service by stopping components, reloading sensors and starting
358  * components. This is needed when we receive new sensor updates.
359  */
360 static void
361 reset ()
362 {
363   stop ();
364   start ();
365 }
366
367
368 /**
369  * The main function for the sensor service.
370  *
371  * @param argc number of arguments from the command line
372  * @param argv command line arguments
373  * @return 0 ok, 1 on error
374  */
375 int
376 main (int argc, char *const *argv)
377 {
378   return (GNUNET_OK ==
379           GNUNET_SERVICE_run (argc, argv, "sensor", GNUNET_SERVICE_OPTION_NONE,
380                               &run, NULL)) ? 0 : 1;
381 }
382
383 /* end of gnunet-service-sensor.c */