2 This file is part of GNUnet.
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.
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.
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.
22 * @file sensor/sensor_api.c
23 * @brief API for sensor service
24 * @author Omar Tarabai
27 #include "gnunet_util_lib.h"
30 #define LOG(kind,...) GNUNET_log_from (kind, "sensor-api",__VA_ARGS__)
33 * Handle to the sensor service.
35 struct GNUNET_SENSOR_Handle
41 const struct GNUNET_CONFIGURATION_Handle *cfg;
44 * Connection to the service.
46 struct GNUNET_CLIENT_Connection *client;
49 * Head of iterator DLL.
51 struct GNUNET_SENSOR_IterateContext *ic_head;
54 * Tail of iterator DLL.
56 struct GNUNET_SENSOR_IterateContext *ic_tail;
59 * Message queue used to send data to service
61 struct GNUNET_MQ_Handle *mq;
66 * Context for an iteration request.
68 struct GNUNET_SENSOR_IterateContext
74 struct GNUNET_SENSOR_IterateContext *next;
79 struct GNUNET_SENSOR_IterateContext *prev;
82 * Handle to the SENSOR service.
84 struct GNUNET_SENSOR_Handle *h;
87 * Function to call with the results.
89 GNUNET_SENSOR_SensorIterateCB callback;
92 * Closure for 'callback'.
97 * Envelope containing iterate request.
99 struct GNUNET_MQ_Envelope *ev;
102 * Is the request already sent? If yes, cannot be canceled.
107 * Are we expecting records from service?
112 * Task responsible for timeout.
114 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
120 * Notifier of an error encountered by MQ.
122 * @param cls Closure, service handle
123 * @param error MQ error type
126 mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
128 struct GNUNET_SENSOR_Handle *h = cls;
130 LOG (GNUNET_ERROR_TYPE_ERROR,
131 _("Received an error notification from MQ of type: %d\n"), error);
132 GNUNET_SENSOR_disconnect (h); //TODO: try to reconnect
137 * Handler to a message of type: #GNUNET_MESSAGE_TYPE_SENSOR_END
139 * @param cls Closure, service handle
140 * @param msg Message received
143 handle_end (void *cls, const struct GNUNET_MessageHeader *msg)
145 struct GNUNET_SENSOR_Handle *h = cls;
146 struct GNUNET_SENSOR_IterateContext *ic;
147 GNUNET_SENSOR_SensorIterateCB cb;
150 if (NULL == h->ic_head)
158 cb_cls = ic->callback_cls;
159 ic->receiving = GNUNET_NO;
160 GNUNET_SENSOR_iterate_cancel (ic);
162 cb (cb_cls, NULL, NULL);
167 * Handler to a message of type: #GNUNET_MESSAGE_TYPE_SENSOR_INFO
169 * @param cls Closure, service handle
170 * @param msg Message received
173 handle_sensor_info (void *cls, const struct GNUNET_MessageHeader *msg)
175 struct GNUNET_SENSOR_Handle *h = cls;
176 struct GNUNET_SENSOR_IterateContext *ic;
178 struct SensorInfoMessage *sensor_msg;
179 uint16_t sensor_name_len;
180 uint16_t sensor_desc_len;
181 struct SensorInfoShort *sensor;
184 if (NULL == h->ic_head)
191 if (NULL == ic->callback) /* no need to parse message */
193 msg_size = ntohs (msg->size);
194 if (msg_size < sizeof (struct SensorInfoMessage))
200 sensor_msg = (struct SensorInfoMessage *) msg;
201 sensor_name_len = ntohs (sensor_msg->name_len);
202 sensor_desc_len = ntohs (sensor_msg->description_len);
204 sizeof (struct SensorInfoMessage) + sensor_name_len + sensor_desc_len)
210 sensor = GNUNET_new (struct SensorInfoShort);
211 sensor->version_major = ntohs (sensor_msg->version_major);
212 sensor->version_minor = ntohs (sensor_msg->version_minor);
213 dummy = &sensor_msg[1];
214 sensor->name = GNUNET_strndup (dummy, sensor_name_len);
215 dummy += sensor_name_len;
216 sensor->description = GNUNET_strndup (dummy, sensor_desc_len);
217 ic->callback (ic->callback_cls, sensor, NULL);
218 GNUNET_free (sensor->name);
219 GNUNET_free (sensor->description);
220 GNUNET_free (sensor);
225 * Disconnect from the sensor service
227 * @param h handle to disconnect
230 GNUNET_SENSOR_disconnect (struct GNUNET_SENSOR_Handle *h)
232 struct GNUNET_SENSOR_IterateContext *ic;
237 if (NULL != ic->callback)
238 ic->callback (ic->callback_cls, NULL,
239 _("Iterate request canceled due to disconnection.\n"));
240 GNUNET_SENSOR_iterate_cancel (ic);
245 GNUNET_MQ_destroy (h->mq);
248 if (NULL != h->client)
250 GNUNET_CLIENT_disconnect (h->client);
258 * Connect to the sensor service.
260 * @return NULL on error
262 struct GNUNET_SENSOR_Handle *
263 GNUNET_SENSOR_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
265 struct GNUNET_CLIENT_Connection *client;
266 struct GNUNET_SENSOR_Handle *h;
268 static const struct GNUNET_MQ_MessageHandler mq_handlers[] = {
269 {&handle_sensor_info, GNUNET_MESSAGE_TYPE_SENSOR_INFO, 0},
270 {&handle_end, GNUNET_MESSAGE_TYPE_SENSOR_END, 0},
271 GNUNET_MQ_HANDLERS_END
274 client = GNUNET_CLIENT_connect ("sensor", cfg);
277 h = GNUNET_new (struct GNUNET_SENSOR_Handle);
281 GNUNET_MQ_queue_for_connection_client (h->client, mq_handlers,
282 &mq_error_handler, h);
288 * Iteration request has timed out.
290 * @param cls the 'struct GNUNET_SENSOR_SensorIteratorContext*'
291 * @param tc scheduler context
294 signal_sensor_iteration_timeout (void *cls,
295 const struct GNUNET_SCHEDULER_TaskContext *tc)
297 struct GNUNET_SENSOR_IterateContext *ic = cls;
298 GNUNET_SENSOR_SensorIterateCB cb;
301 ic->timeout_task = GNUNET_SCHEDULER_NO_TASK;
303 cb_cls = ic->callback_cls;
304 GNUNET_SENSOR_iterate_cancel (ic);
307 _("Timeout transmitting iteration request to `SENSOR' service."));
312 * Callback from MQ when the request has already been sent to the service.
313 * Now it can not be canelled.
318 iterate_request_sent (void *cls)
320 struct GNUNET_SENSOR_IterateContext *ic = cls;
322 ic->request_sent = GNUNET_YES;
324 ic->receiving = GNUNET_YES;
329 * Cancel an iteration request.
330 * This should be called before the iterate callback is called with a NULL value.
332 * @param ic context of the iterator to cancel
335 GNUNET_SENSOR_iterate_cancel (struct GNUNET_SENSOR_IterateContext *ic)
337 struct GNUNET_SENSOR_Handle *h;
340 if (GNUNET_NO == ic->request_sent)
342 GNUNET_MQ_send_cancel (ic->ev);
344 ic->request_sent = GNUNET_YES;
346 if (GNUNET_YES == ic->receiving)
348 /* don't remove since we are still expecting records */
350 ic->callback_cls = NULL;
353 if (GNUNET_SCHEDULER_NO_TASK != ic->timeout_task)
355 GNUNET_SCHEDULER_cancel (ic->timeout_task);
356 ic->timeout_task = GNUNET_SCHEDULER_NO_TASK;
358 GNUNET_CONTAINER_DLL_remove (h->ic_head, h->ic_tail, ic);
364 * Get one or all sensors loaded by the sensor service.
365 * The callback will be called with each sensor received and once with a NULL
366 * value to signal end of iteration.
368 * @param h Handle to SENSOR service
369 * @param timeout how long to wait until timing out
370 * @param sensorname Name of the required sensor, NULL to get all
371 * @param callback the function to call for each sensor
372 * @param callback_cls closure for callback
373 * @return iterator context
375 struct GNUNET_SENSOR_IterateContext *
376 GNUNET_SENSOR_iterate (struct GNUNET_SENSOR_Handle *h,
377 struct GNUNET_TIME_Relative timeout,
378 const char *sensor_name,
379 GNUNET_SENSOR_SensorIterateCB callback,
382 struct GNUNET_SENSOR_IterateContext *ic;
383 struct GNUNET_MessageHeader *msg;
384 struct GNUNET_MQ_Envelope *ev;
385 size_t sensor_name_len;
387 if (NULL == sensor_name)
389 ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SENSOR_GETALL);
393 sensor_name_len = strlen (sensor_name) + 1;
394 ev = GNUNET_MQ_msg_extra (msg, sensor_name_len,
395 GNUNET_MESSAGE_TYPE_SENSOR_GET);
396 memcpy (&msg[1], sensor_name, sensor_name_len);
398 GNUNET_MQ_send (h->mq, ev);
399 ic = GNUNET_new (struct GNUNET_SENSOR_IterateContext);
403 ic->request_sent = GNUNET_NO;
404 ic->receiving = GNUNET_NO;
405 ic->callback = callback;
406 ic->callback_cls = callback_cls;
408 GNUNET_SCHEDULER_add_delayed (timeout, &signal_sensor_iteration_timeout,
410 GNUNET_MQ_notify_sent (ev, &iterate_request_sent, ic);
411 GNUNET_CONTAINER_DLL_insert_tail (h->ic_head, h->ic_tail, ic);
417 * Force an anomaly status change on a given sensor. If the sensor reporting
418 * module is running, this will trigger the usual reporting logic, therefore,
419 * please only use this in a test environment.
421 * Also, if the sensor analysis module is running, it might conflict and cause
422 * undefined behaviour if it detects a real anomaly.
424 * @param h Service handle
425 * @param sensor_name Sensor name to set the anomaly status
426 * @param anomalous The desired status: #GNUNET_YES / #GNUNET_NO
429 GNUNET_SENSOR_force_anomaly (struct GNUNET_SENSOR_Handle *h, char *sensor_name,
432 struct ForceAnomalyMessage *msg;
433 struct GNUNET_MQ_Envelope *ev;
435 ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SENSOR_ANOMALY_FORCE);
436 GNUNET_CRYPTO_hash (sensor_name, strlen (sensor_name) + 1,
437 &msg->sensor_name_hash);
438 msg->anomalous = htons (anomalous);
439 GNUNET_MQ_send (h->mq, ev);
443 /* end of sensor_api.c */