123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566 |
- /*
- This file is part of GNUnet.
- (C)
- GNUnet is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 3, or (at your
- option) any later version.
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
- */
- /**
- * @file sensor/sensor_api.c
- * @brief API for sensor service
- * @author Omar Tarabai
- */
- #include "platform.h"
- #include "gnunet_util_lib.h"
- #include "sensor.h"
- #define LOG(kind,...) GNUNET_log_from (kind, "sensor-api",__VA_ARGS__)
- /**
- * Handle to the sensor service.
- */
- struct GNUNET_SENSOR_Handle
- {
- /**
- * Our configuration.
- */
- const struct GNUNET_CONFIGURATION_Handle *cfg;
- /**
- * Connection to the service.
- */
- struct GNUNET_CLIENT_Connection *client;
- /**
- * Head of iteration requests DLL.
- */
- struct GNUNET_SENSOR_IterateContext *ic_head;
- /**
- * Tail of iteration requests DLL.
- */
- struct GNUNET_SENSOR_IterateContext *ic_tail;
- /**
- * Head of force anomaly requests
- */
- struct GNUNET_SENSOR_ForceAnomalyContext *fa_head;
- /**
- * Tail of force anomaly requests
- */
- struct GNUNET_SENSOR_ForceAnomalyContext *fa_tail;
- /**
- * Message queue used to send data to service
- */
- struct GNUNET_MQ_Handle *mq;
- };
- /**
- * Context for an iteration request.
- */
- struct GNUNET_SENSOR_IterateContext
- {
- /**
- * Kept in a DLL.
- */
- struct GNUNET_SENSOR_IterateContext *next;
- /**
- * Kept in a DLL.
- */
- struct GNUNET_SENSOR_IterateContext *prev;
- /**
- * Handle to the SENSOR service.
- */
- struct GNUNET_SENSOR_Handle *h;
- /**
- * Function to call with the results.
- */
- GNUNET_SENSOR_SensorIterateCB callback;
- /**
- * Closure for 'callback'.
- */
- void *callback_cls;
- /**
- * Envelope containing iterate request.
- */
- struct GNUNET_MQ_Envelope *ev;
- /**
- * Is the request already sent? If yes, cannot be canceled.
- */
- int request_sent;
- /**
- * Are we expecting records from service?
- */
- int receiving;
- /**
- * Task responsible for timeout.
- */
- GNUNET_SCHEDULER_TaskIdentifier timeout_task;
- };
- /**
- * Context of a force anomaly request
- */
- struct GNUNET_SENSOR_ForceAnomalyContext
- {
- /**
- * DLL
- */
- struct GNUNET_SENSOR_ForceAnomalyContext *next;
- /**
- * DLL
- */
- struct GNUNET_SENSOR_ForceAnomalyContext *prev;
- /**
- * Handle to the SENSOR service.
- */
- struct GNUNET_SENSOR_Handle *h;
- /**
- * Envelope containing iterate request.
- */
- struct GNUNET_MQ_Envelope *ev;
- /**
- * User continuation function
- */
- GNUNET_SENSOR_Continuation cont;
- /**
- * Closure for cont
- */
- void *cont_cls;
- };
- /**
- * Notifier of an error encountered by MQ.
- *
- * @param cls Closure, service handle
- * @param error MQ error type
- */
- static void
- mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
- {
- struct GNUNET_SENSOR_Handle *h = cls;
- LOG (GNUNET_ERROR_TYPE_ERROR,
- _("Received an error notification from MQ of type: %d\n"), error);
- GNUNET_SENSOR_disconnect (h); //TODO: try to reconnect
- }
- /**
- * Handler to a message of type: #GNUNET_MESSAGE_TYPE_SENSOR_END
- *
- * @param cls Closure, service handle
- * @param msg Message received
- */
- static void
- handle_end (void *cls, const struct GNUNET_MessageHeader *msg)
- {
- struct GNUNET_SENSOR_Handle *h = cls;
- struct GNUNET_SENSOR_IterateContext *ic;
- GNUNET_SENSOR_SensorIterateCB cb;
- void *cb_cls;
- if (NULL == h->ic_head)
- {
- GNUNET_break_op (0);
- //TODO: reconnect
- return;
- }
- ic = h->ic_head;
- cb = ic->callback;
- cb_cls = ic->callback_cls;
- ic->receiving = GNUNET_NO;
- GNUNET_SENSOR_iterate_cancel (ic);
- if (NULL != cb)
- cb (cb_cls, NULL, NULL);
- }
- /**
- * Handler to a message of type: #GNUNET_MESSAGE_TYPE_SENSOR_INFO
- *
- * @param cls Closure, service handle
- * @param msg Message received
- */
- static void
- handle_sensor_info (void *cls, const struct GNUNET_MessageHeader *msg)
- {
- struct GNUNET_SENSOR_Handle *h = cls;
- struct GNUNET_SENSOR_IterateContext *ic;
- uint16_t msg_size;
- struct SensorInfoMessage *sensor_msg;
- uint16_t sensor_name_len;
- uint16_t sensor_desc_len;
- struct SensorInfoShort *sensor;
- void *dummy;
- if (NULL == h->ic_head)
- {
- GNUNET_break_op (0);
- //TODO: reconnect
- return;
- }
- ic = h->ic_head;
- if (NULL == ic->callback) /* no need to parse message */
- return;
- msg_size = ntohs (msg->size);
- if (msg_size < sizeof (struct SensorInfoMessage))
- {
- GNUNET_break_op (0);
- //TODO: reconnect
- return;
- }
- sensor_msg = (struct SensorInfoMessage *) msg;
- sensor_name_len = ntohs (sensor_msg->name_len);
- sensor_desc_len = ntohs (sensor_msg->description_len);
- if (msg_size !=
- sizeof (struct SensorInfoMessage) + sensor_name_len + sensor_desc_len)
- {
- GNUNET_break_op (0);
- //TODO: reconnect
- return;
- }
- sensor = GNUNET_new (struct SensorInfoShort);
- sensor->version_major = ntohs (sensor_msg->version_major);
- sensor->version_minor = ntohs (sensor_msg->version_minor);
- dummy = &sensor_msg[1];
- sensor->name = GNUNET_strndup (dummy, sensor_name_len);
- dummy += sensor_name_len;
- sensor->description = GNUNET_strndup (dummy, sensor_desc_len);
- ic->callback (ic->callback_cls, sensor, NULL);
- GNUNET_free (sensor->name);
- GNUNET_free (sensor->description);
- GNUNET_free (sensor);
- }
- /**
- * Disconnect from the sensor service.
- * Please disconnect only when all requests sent are complete or canceled.
- *
- * @param h handle to disconnect
- */
- void
- GNUNET_SENSOR_disconnect (struct GNUNET_SENSOR_Handle *h)
- {
- struct GNUNET_SENSOR_IterateContext *ic;
- GNUNET_SENSOR_SensorIterateCB ic_callback;
- void *ic_callback_cls;
- struct GNUNET_SENSOR_ForceAnomalyContext *fa;
- GNUNET_SENSOR_Continuation fa_cont;
- void *fa_cont_cls;
- ic = h->ic_head;
- while (NULL != ic)
- {
- ic_callback = ic->callback;
- ic_callback_cls = ic->callback_cls;
- GNUNET_SENSOR_iterate_cancel (ic);
- if (NULL != ic_callback)
- ic_callback (ic_callback_cls, NULL,
- _("Iterate request canceled due to disconnection.\n"));
- ic = h->ic_head;
- }
- fa = h->fa_head;
- while (NULL != fa)
- {
- fa_cont = fa->cont;
- fa_cont_cls = fa->cont_cls;
- GNUNET_SENSOR_force_anomaly_cancel (fa);
- if (NULL != fa_cont)
- fa_cont (fa_cont_cls,
- _("Force anomaly request canceled due to disconnection.\n"));
- fa = h->fa_head;
- }
- if (NULL != h->mq)
- {
- GNUNET_MQ_destroy (h->mq);
- h->mq = NULL;
- }
- if (NULL != h->client)
- {
- GNUNET_CLIENT_disconnect (h->client);
- h->client = NULL;
- }
- GNUNET_free (h);
- }
- /**
- * Connect to the sensor service.
- *
- * @return NULL on error
- */
- struct GNUNET_SENSOR_Handle *
- GNUNET_SENSOR_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
- {
- struct GNUNET_CLIENT_Connection *client;
- struct GNUNET_SENSOR_Handle *h;
- static const struct GNUNET_MQ_MessageHandler mq_handlers[] = {
- {&handle_sensor_info, GNUNET_MESSAGE_TYPE_SENSOR_INFO, 0},
- {&handle_end, GNUNET_MESSAGE_TYPE_SENSOR_END, 0},
- GNUNET_MQ_HANDLERS_END
- };
- client = GNUNET_CLIENT_connect ("sensor", cfg);
- if (NULL == client)
- return NULL;
- h = GNUNET_new (struct GNUNET_SENSOR_Handle);
- h->client = client;
- h->cfg = cfg;
- h->mq =
- GNUNET_MQ_queue_for_connection_client (h->client, mq_handlers,
- &mq_error_handler, h);
- return h;
- }
- /**
- * Iteration request has timed out.
- *
- * @param cls the 'struct GNUNET_SENSOR_SensorIteratorContext*'
- * @param tc scheduler context
- */
- static void
- signal_sensor_iteration_timeout (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
- {
- struct GNUNET_SENSOR_IterateContext *ic = cls;
- GNUNET_SENSOR_SensorIterateCB cb;
- void *cb_cls;
- ic->timeout_task = GNUNET_SCHEDULER_NO_TASK;
- cb = ic->callback;
- cb_cls = ic->callback_cls;
- GNUNET_SENSOR_iterate_cancel (ic);
- if (NULL != cb)
- cb (cb_cls, NULL,
- _("Timeout transmitting iteration request to `SENSOR' service."));
- }
- /**
- * Callback from MQ when the request has already been sent to the service.
- * Now it can not be canelled.
- *
- * @param cls closure
- */
- static void
- iterate_request_sent (void *cls)
- {
- struct GNUNET_SENSOR_IterateContext *ic = cls;
- ic->request_sent = GNUNET_YES;
- ic->ev = NULL;
- ic->receiving = GNUNET_YES;
- }
- /**
- * Cancel an iteration request.
- * This should be called before the iterate callback is called with a NULL value.
- *
- * @param ic context of the iterator to cancel
- */
- void
- GNUNET_SENSOR_iterate_cancel (struct GNUNET_SENSOR_IterateContext *ic)
- {
- struct GNUNET_SENSOR_Handle *h;
- h = ic->h;
- if (GNUNET_NO == ic->request_sent)
- {
- GNUNET_MQ_send_cancel (ic->ev);
- ic->ev = NULL;
- ic->request_sent = GNUNET_YES;
- }
- if (GNUNET_YES == ic->receiving)
- {
- /* don't remove since we are still expecting records */
- ic->callback = NULL;
- ic->callback_cls = NULL;
- return;
- }
- if (GNUNET_SCHEDULER_NO_TASK != ic->timeout_task)
- {
- GNUNET_SCHEDULER_cancel (ic->timeout_task);
- ic->timeout_task = GNUNET_SCHEDULER_NO_TASK;
- }
- GNUNET_CONTAINER_DLL_remove (h->ic_head, h->ic_tail, ic);
- GNUNET_free (ic);
- }
- /**
- * Get one or all sensors loaded by the sensor service.
- * The callback will be called with each sensor received and once with a NULL
- * value to signal end of iteration.
- *
- * @param h Handle to SENSOR service
- * @param timeout how long to wait until timing out
- * @param sensorname Name of the required sensor, NULL to get all
- * @param callback the function to call for each sensor
- * @param callback_cls closure for callback
- * @return iterator context
- */
- struct GNUNET_SENSOR_IterateContext *
- GNUNET_SENSOR_iterate (struct GNUNET_SENSOR_Handle *h,
- struct GNUNET_TIME_Relative timeout,
- const char *sensor_name,
- GNUNET_SENSOR_SensorIterateCB callback,
- void *callback_cls)
- {
- struct GNUNET_SENSOR_IterateContext *ic;
- struct GNUNET_MessageHeader *msg;
- struct GNUNET_MQ_Envelope *ev;
- size_t sensor_name_len;
- if (NULL == sensor_name)
- {
- ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SENSOR_GETALL);
- }
- else
- {
- sensor_name_len = strlen (sensor_name) + 1;
- ev = GNUNET_MQ_msg_extra (msg, sensor_name_len,
- GNUNET_MESSAGE_TYPE_SENSOR_GET);
- memcpy (&msg[1], sensor_name, sensor_name_len);
- }
- GNUNET_MQ_send (h->mq, ev);
- ic = GNUNET_new (struct GNUNET_SENSOR_IterateContext);
- ic->h = h;
- ic->ev = ev;
- ic->request_sent = GNUNET_NO;
- ic->receiving = GNUNET_NO;
- ic->callback = callback;
- ic->callback_cls = callback_cls;
- ic->timeout_task =
- GNUNET_SCHEDULER_add_delayed (timeout, &signal_sensor_iteration_timeout,
- ic);
- GNUNET_MQ_notify_sent (ev, &iterate_request_sent, ic);
- GNUNET_CONTAINER_DLL_insert_tail (h->ic_head, h->ic_tail, ic);
- return ic;
- }
- /**
- * Callback from MQ when the request has already been sent to the service.
- * Now it can not be canelled.
- *
- * @param cls closure
- */
- static void
- force_anomaly_sent (void *cls)
- {
- struct GNUNET_SENSOR_ForceAnomalyContext *fa = cls;
- GNUNET_SENSOR_Continuation cont;
- void *cont_cls;
- fa->ev = NULL;
- cont = fa->cont;
- cont_cls = fa->cont_cls;
- GNUNET_SENSOR_force_anomaly_cancel (fa);
- if (NULL != cont)
- cont (cont_cls, NULL);
- }
- /**
- * Cancel a force anomaly request.
- *
- * @param fa Force anomaly context returned by GNUNET_SENSOR_force_anomaly()
- */
- void
- GNUNET_SENSOR_force_anomaly_cancel (struct GNUNET_SENSOR_ForceAnomalyContext
- *fa)
- {
- struct GNUNET_SENSOR_Handle *h = fa->h;
- if (NULL != fa->ev)
- {
- GNUNET_MQ_send_cancel (fa->ev);
- fa->ev = NULL;
- }
- GNUNET_CONTAINER_DLL_remove (h->fa_head, h->fa_tail, fa);
- GNUNET_free (fa);
- }
- /**
- * Force an anomaly status change on a given sensor. If the sensor reporting
- * module is running, this will trigger the usual reporting logic, therefore,
- * please only use this in a test environment.
- *
- * Also, if the sensor analysis module is running, it might conflict and cause
- * undefined behaviour if it detects a real anomaly.
- *
- * @param h Service handle
- * @param sensor_name Sensor name to set the anomaly status
- * @param anomalous The desired status: #GNUNET_YES / #GNUNET_NO
- * @param cont Continuation function to be called after the request is sent
- * @param cont_cls Closure for cont
- */
- struct GNUNET_SENSOR_ForceAnomalyContext *
- GNUNET_SENSOR_force_anomaly (struct GNUNET_SENSOR_Handle *h, char *sensor_name,
- int anomalous, GNUNET_SENSOR_Continuation cont,
- void *cont_cls)
- {
- struct ForceAnomalyMessage *msg;
- struct GNUNET_MQ_Envelope *ev;
- struct GNUNET_SENSOR_ForceAnomalyContext *fa;
- ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SENSOR_ANOMALY_FORCE);
- GNUNET_CRYPTO_hash (sensor_name, strlen (sensor_name) + 1,
- &msg->sensor_name_hash);
- msg->anomalous = htons (anomalous);
- GNUNET_MQ_send (h->mq, ev);
- fa = GNUNET_new (struct GNUNET_SENSOR_ForceAnomalyContext);
- fa->h = h;
- fa->cont = cont;
- fa->cont_cls = cont_cls;
- fa->ev = ev;
- GNUNET_CONTAINER_DLL_insert_tail (h->fa_head, h->fa_tail, fa);
- GNUNET_MQ_notify_sent (ev, &force_anomaly_sent, fa);
- return fa;
- }
- /* end of sensor_api.c */
|