sensor: separate monitoring functions
[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 /**
47  * Resets the service by stopping components, reloading sensors and starting
48  * components. This is needed when we receive new sensor updates.
49  */
50 static void
51 reset ();
52
53
54 /**
55  * Stops components and destroys sensors
56  */
57 static void
58 stop ()
59 {
60   SENSOR_update_stop ();
61   SENSOR_analysis_stop ();
62   SENSOR_reporting_stop ();
63   SENSOR_monitoring_stop ();
64   GNUNET_SENSOR_destroy_sensors (sensors);
65 }
66
67
68 /**
69  * Task run during shutdown.
70  *
71  * @param cls unused
72  * @param tc unused
73  */
74 static void
75 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
76 {
77   stop ();
78   if (NULL != sensor_dir)
79   {
80     GNUNET_free (sensor_dir);
81     sensor_dir = NULL;
82   }
83   GNUNET_SCHEDULER_shutdown ();
84 }
85
86
87 /**
88  * Creates a structure with basic sensor info to be sent to a client.
89  *
90  * @param sensor sensor information
91  * @return message ready to be sent to client
92  */
93 static struct SensorInfoMessage *
94 create_sensor_info_msg (struct GNUNET_SENSOR_SensorInfo *sensor)
95 {
96   struct SensorInfoMessage *msg;
97   uint16_t len;
98   size_t name_len;
99   size_t desc_len;
100   char *str_ptr;
101
102   name_len = strlen (sensor->name);
103   if (NULL == sensor->description)
104     desc_len = 0;
105   else
106     desc_len = strlen (sensor->description) + 1;
107   len = 0;
108   len += sizeof (struct SensorInfoMessage);
109   len += name_len;
110   len += desc_len;
111   msg = GNUNET_malloc (len);
112   msg->header.size = htons (len);
113   msg->header.type = htons (GNUNET_MESSAGE_TYPE_SENSOR_INFO);
114   msg->name_len = htons (name_len);
115   msg->description_len = htons (desc_len);
116   msg->version_major = htons (sensor->version_major);
117   msg->version_minor = htons (sensor->version_minor);
118   str_ptr = (char *) &msg[1];
119   memcpy (str_ptr, sensor->name, name_len);
120   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending sensor name (%d): %.*s\n",
121               name_len, name_len, str_ptr);
122   str_ptr += name_len;
123   memcpy (str_ptr, sensor->description, desc_len);
124   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
125               "Sending sensor description (%d): %.*s\n", desc_len, desc_len,
126               str_ptr);
127   return msg;
128 }
129
130
131 /**
132  * Handle GET SENSOR message.
133  *
134  * @param cls closure
135  * @param client identification of the client
136  * @param message the actual message
137  */
138 static void
139 handle_get_sensor (void *cls, struct GNUNET_SERVER_Client *client,
140                    const struct GNUNET_MessageHeader *message)
141 {
142   struct GNUNET_SERVER_TransmitContext *tc;
143   char *sensorname;
144   size_t sensorname_len;
145   struct GNUNET_HashCode key;
146   struct GNUNET_SENSOR_SensorInfo *sensorinfo;
147   struct SensorInfoMessage *msg;
148
149   sensorname = (char *) &message[1];
150   sensorname_len = ntohs (message->size) - sizeof (struct GNUNET_MessageHeader);
151   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
152               "`%s' message received for sensor (%d) `%.*s'\n", "GET SENSOR",
153               sensorname_len, sensorname_len, sensorname);
154   tc = GNUNET_SERVER_transmit_context_create (client);
155   GNUNET_CRYPTO_hash (sensorname, sensorname_len, &key);
156   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
157               "Created key hash for requested sensor\n");
158   sensorinfo =
159       (struct GNUNET_SENSOR_SensorInfo *)
160       GNUNET_CONTAINER_multihashmap_get (sensors, &key);
161   if (NULL != sensorinfo)
162   {
163     msg = create_sensor_info_msg (sensorinfo);
164     GNUNET_SERVER_transmit_context_append_message (tc,
165                                                    (struct GNUNET_MessageHeader
166                                                     *) msg);
167     GNUNET_free (msg);
168   }
169   else
170     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
171                 "Requested sensor `%.*s' was not found\n", sensorname_len,
172                 sensorname);
173   GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
174                                               GNUNET_MESSAGE_TYPE_SENSOR_END);
175   GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
176 }
177
178
179 /**
180  * Iterator for sensors and adds them to transmit context
181  *
182  * @param cls a `struct GNUNET_SERVER_TransmitContext *`
183  * @param key hash of sensor name, key to hashmap
184  * @param value a `struct GNUNET_SENSOR_SensorInfo *`
185  */
186 static int
187 add_sensor_to_tc (void *cls, const struct GNUNET_HashCode *key, void *value)
188 {
189   struct GNUNET_SERVER_TransmitContext *tc = cls;
190   struct GNUNET_SENSOR_SensorInfo *sensorinfo = value;
191   struct SensorInfoMessage *msg;
192
193   msg = create_sensor_info_msg (sensorinfo);
194   GNUNET_SERVER_transmit_context_append_message (tc,
195                                                  (struct GNUNET_MessageHeader *)
196                                                  msg);
197
198   GNUNET_free (msg);
199   return GNUNET_YES;
200 }
201
202
203 /**
204  * Handle GET ALL SENSORS message.
205  *
206  * @param cls closure
207  * @param client identification of the client
208  * @param message the actual message
209  */
210 static void
211 handle_get_all_sensors (void *cls, struct GNUNET_SERVER_Client *client,
212                         const struct GNUNET_MessageHeader *message)
213 {
214   struct GNUNET_SERVER_TransmitContext *tc;
215
216   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "`%s' message received.\n",
217               "GET ALL SENSOR");
218   tc = GNUNET_SERVER_transmit_context_create (client);
219   GNUNET_CONTAINER_multihashmap_iterate (sensors, &add_sensor_to_tc, tc);
220   GNUNET_SERVER_transmit_context_append_data (tc, NULL, 0,
221                                               GNUNET_MESSAGE_TYPE_SENSOR_END);
222   GNUNET_SERVER_transmit_context_run (tc, GNUNET_TIME_UNIT_FOREVER_REL);
223 }
224
225
226 /**
227  * Loads sensors and starts different service components
228  */
229 static void
230 start ()
231 {
232   sensors = GNUNET_SENSOR_load_all_sensors (sensor_dir);
233   SENSOR_monitoring_start (cfg, sensors);
234   SENSOR_reporting_start (cfg, sensors);
235   SENSOR_analysis_start (cfg, sensors);
236   SENSOR_update_start (cfg, sensors, &reset);
237 }
238
239
240 /**
241  * Process statistics requests.
242  *
243  * @param cls closure
244  * @param server the initialized server
245  * @param c configuration to use
246  */
247 static void
248 run (void *cls, struct GNUNET_SERVER_Handle *server,
249      const struct GNUNET_CONFIGURATION_Handle *c)
250 {
251   static const struct GNUNET_SERVER_MessageHandler handlers[] = {
252     {&handle_get_sensor, NULL, GNUNET_MESSAGE_TYPE_SENSOR_GET,
253      0},
254     {&handle_get_all_sensors, NULL, GNUNET_MESSAGE_TYPE_SENSOR_GETALL,
255      sizeof (struct GNUNET_MessageHeader)},
256     {NULL, NULL, 0, 0}
257   };
258
259   cfg = c;
260   if (GNUNET_OK !=
261       GNUNET_CONFIGURATION_get_value_filename (cfg, "SENSOR", "SENSOR_DIR",
262                                                &sensor_dir))
263   {
264     sensor_dir = GNUNET_SENSOR_get_default_sensor_dir ();
265   }
266   GNUNET_SERVER_add_handlers (server, handlers);
267   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
268                                 NULL);
269   start ();
270 }
271
272
273 /**
274  * Resets the service by stopping components, reloading sensors and starting
275  * components. This is needed when we receive new sensor updates.
276  */
277 static void
278 reset ()
279 {
280   stop ();
281   start ();
282 }
283
284
285 /**
286  * The main function for the sensor service.
287  *
288  * @param argc number of arguments from the command line
289  * @param argv command line arguments
290  * @return 0 ok, 1 on error
291  */
292 int
293 main (int argc, char *const *argv)
294 {
295   return (GNUNET_OK ==
296           GNUNET_SERVICE_run (argc, argv, "sensor", GNUNET_SERVICE_OPTION_NONE,
297                               &run, NULL)) ? 0 : 1;
298 }
299
300 /* end of gnunet-service-sensor.c */