From d26fff163ec1d081db3293daf9dd566e74f3fde5 Mon Sep 17 00:00:00 2001 From: Omar Tarabai Date: Mon, 11 Aug 2014 18:39:39 +0000 Subject: sensor: api changes --- src/include/gnunet_protocols.h | 6 + src/include/gnunet_sensor_service.h | 45 ++- src/sensor/gnunet-sensor.c | 14 +- src/sensor/gnunet-service-sensor.c | 10 +- src/sensor/sensor.conf.in | 2 +- src/sensor/sensor.h | 31 +- src/sensor/sensor_api.c | 632 ++++++++++++------------------------ 7 files changed, 293 insertions(+), 447 deletions(-) (limited to 'src') diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h index 246f7f836..176391580 100644 --- a/src/include/gnunet_protocols.h +++ b/src/include/gnunet_protocols.h @@ -2452,6 +2452,12 @@ extern "C" */ #define GNUNET_MESSAGE_TYPE_SENSOR_ANOMALY_REPORT 809 +/** + * Message sent from API to service to force a new sensor anomaly status + * (For testing purposes only) + */ +#define GNUNET_MESSAGE_TYPE_SENSOR_ANOMALY_FORCE 810 + /******************************************************************************* * PEERSTORE message types diff --git a/src/include/gnunet_sensor_service.h b/src/include/gnunet_sensor_service.h index 4ef2885e6..a31b20e52 100644 --- a/src/include/gnunet_sensor_service.h +++ b/src/include/gnunet_sensor_service.h @@ -43,6 +43,11 @@ extern "C" */ struct GNUNET_SENSOR_Handle; +/** + * Context for an iteration request. + */ +struct GNUNET_SENSOR_IterateContext; + /** * Structure containing brief info about sensor */ @@ -72,13 +77,13 @@ struct SensorInfoShort }; /** - * Type of an iterator over sensor definitions. + * Sensor iterate request callback. * * @param cls closure - * @param hello hello message for the peer (can be NULL) + * @param sensor Brief sensor information * @param error message */ -typedef void (*GNUNET_SENSOR_SensorIteratorCB) (void *cls, +typedef void (*GNUNET_SENSOR_SensorIterateCB) (void *cls, const struct SensorInfoShort * sensor, const char *err_msg); @@ -92,6 +97,15 @@ typedef void (*GNUNET_SENSOR_SensorIteratorCB) (void *cls, typedef void (*GNUNET_SENSOR_Continuation) (void *cls, const char *emsg); +/** + * Disconnect from the sensor service + * + * @param h handle to disconnect + */ +void +GNUNET_SENSOR_disconnect (struct GNUNET_SENSOR_Handle *h); + + /** * Connect to the sensor service. * @@ -102,30 +116,33 @@ GNUNET_SENSOR_connect (const struct GNUNET_CONFIGURATION_Handle *cfg); /** - * Disconnect from the sensor service + * Cancel an iteration request. + * This should be called before the iterate callback is called with a NULL value. * - * @param h handle to disconnect + * @param ic context of the iterator to cancel */ void -GNUNET_SENSOR_disconnect (struct GNUNET_SENSOR_Handle *h); +GNUNET_SENSOR_iterate_cancel (struct GNUNET_SENSOR_IterateContext + *ic); /** - * Client asking to iterate all available sensors + * 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 information on one sensor only, can be NULL to get all - * @param sensorname_len length of the sensorname parameter - * @param callback the method to call for each sensor + * @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_SensorIteratorContext * -GNUNET_SENSOR_iterate_sensors (struct GNUNET_SENSOR_Handle *h, +struct GNUNET_SENSOR_IterateContext * +GNUNET_SENSOR_iterate (struct GNUNET_SENSOR_Handle *h, struct GNUNET_TIME_Relative timeout, - const char *sensorname, size_t sensorname_len, - GNUNET_SENSOR_SensorIteratorCB callback, + const char *sensor_name, + GNUNET_SENSOR_SensorIterateCB callback, void *callback_cls); #if 0 /* keep Emacsens' auto-indent happy */ diff --git a/src/sensor/gnunet-sensor.c b/src/sensor/gnunet-sensor.c index ffd61f8b4..ec7b5cb9e 100644 --- a/src/sensor/gnunet-sensor.c +++ b/src/sensor/gnunet-sensor.c @@ -79,7 +79,10 @@ print_sensor_info (void *cls, const struct SensorInfoShort *sensor, return; } if (NULL == sensor) /* no more sensors from service */ + { + GNUNET_SCHEDULER_shutdown (); return; + } printf ("Name: %s\nVersion: %d.%d\n", sensor->name, sensor->version_major, sensor->version_minor); if (NULL != sensor->description) @@ -107,17 +110,14 @@ run (void *cls, char *const *args, const char *cfgfile, GNUNET_assert (NULL != sensor_handle); if (GNUNET_YES == get_all) { - GNUNET_SENSOR_iterate_sensors (sensor_handle, GNUNET_TIME_UNIT_FOREVER_REL, - NULL, 0, &print_sensor_info, NULL); + GNUNET_SENSOR_iterate (sensor_handle, GNUNET_TIME_UNIT_FOREVER_REL, NULL, + &print_sensor_info, NULL); } else if (NULL != get_sensor) { - GNUNET_SENSOR_iterate_sensors (sensor_handle, GNUNET_TIME_UNIT_FOREVER_REL, - get_sensor, strlen (get_sensor), - &print_sensor_info, NULL); + GNUNET_SENSOR_iterate (sensor_handle, GNUNET_TIME_UNIT_FOREVER_REL, + get_sensor, &print_sensor_info, NULL); } - - GNUNET_SCHEDULER_shutdown (); ret = 0; } diff --git a/src/sensor/gnunet-service-sensor.c b/src/sensor/gnunet-service-sensor.c index b404d4806..ce6fa04fc 100644 --- a/src/sensor/gnunet-service-sensor.c +++ b/src/sensor/gnunet-service-sensor.c @@ -286,7 +286,7 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, cfg = c; if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_filename (cfg, "SENSOR", "SENSOR_DIR", + GNUNET_CONFIGURATION_get_value_filename (cfg, "sensor", "SENSOR_DIR", &sensor_dir)) { sensor_dir = GNUNET_SENSOR_get_default_sensor_dir (); @@ -296,22 +296,22 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, start_reporting = GNUNET_YES; start_update = GNUNET_YES; if (GNUNET_NO == - GNUNET_CONFIGURATION_get_value_yesno (cfg, "SENSOR", "START_MONITORING")) + GNUNET_CONFIGURATION_get_value_yesno (cfg, "sensor", "START_MONITORING")) { start_monitoring = GNUNET_NO; } if (GNUNET_NO == - GNUNET_CONFIGURATION_get_value_yesno (cfg, "SENSOR", "START_REPORTING")) + GNUNET_CONFIGURATION_get_value_yesno (cfg, "sensor", "START_REPORTING")) { start_reporting = GNUNET_NO; } if (GNUNET_NO == - GNUNET_CONFIGURATION_get_value_yesno (cfg, "SENSOR", "START_ANALYSIS")) + GNUNET_CONFIGURATION_get_value_yesno (cfg, "sensor", "START_ANALYSIS")) { start_analysis = GNUNET_NO; } if (GNUNET_NO == - GNUNET_CONFIGURATION_get_value_yesno (cfg, "SENSOR", "START_UPDATE")) + GNUNET_CONFIGURATION_get_value_yesno (cfg, "sensor", "START_UPDATE")) { start_update = GNUNET_NO; } diff --git a/src/sensor/sensor.conf.in b/src/sensor/sensor.conf.in index 12b5b4d35..a2bfe8a8e 100644 --- a/src/sensor/sensor.conf.in +++ b/src/sensor/sensor.conf.in @@ -9,7 +9,7 @@ UNIX_MATCH_GID = YES START_MONITORING = YES START_REPORTING = YES START_ANALYSIS = YES -STARTING_UPDATE = YES +START_UPDATE = YES # Path to directory containing sensor definitions. # If not set, will load from default location. diff --git a/src/sensor/sensor.h b/src/sensor/sensor.h index 0b8daaa2c..521f931ce 100644 --- a/src/sensor/sensor.h +++ b/src/sensor/sensor.h @@ -40,9 +40,9 @@ GNUNET_NETWORK_STRUCT_BEGIN struct GNUNET_MessageHeader header; /** - * Length of sensor name (name follows the struct) + * Length of sensor name. Allocated at position 0 after this struct. */ - size_t name_len; + uint16_t name_len; /** * First part of version number @@ -55,9 +55,32 @@ GNUNET_NETWORK_STRUCT_BEGIN uint16_t version_minor; /** - * Length of sensor description (description itself follows) + * Length of sensor description. Allocated at position 1 after this struct. */ - size_t description_len; + uint16_t description_len; +}; + +/** + * A message sent to the sensor service to force an anomaly status on a sensor. + */ +struct ForceAnomalyMessage +{ + + /** + * Message header + */ + struct GNUNET_MessageHeader header; + + /** + * Hash of the sensor name + */ + struct GNUNET_HashCode sensor_name_hash; + + /** + * New status + */ + uint16_t anomalous; + }; GNUNET_NETWORK_STRUCT_END diff --git a/src/sensor/sensor_api.c b/src/sensor/sensor_api.c index a143df087..b7ee55fb6 100644 --- a/src/sensor/sensor_api.c +++ b/src/sensor/sensor_api.c @@ -20,7 +20,7 @@ /** * @file sensor/sensor_api.c - * @brief API for sensor + * @brief API for sensor service * @author Omar Tarabai */ #include "platform.h" @@ -29,10 +29,6 @@ #define LOG(kind,...) GNUNET_log_from (kind, "sensor-api",__VA_ARGS__) -/******************************************************************************/ -/************************ DATA STRUCTURES ****************************/ -/******************************************************************************/ - /** * Handle to the sensor service. */ @@ -49,96 +45,38 @@ struct GNUNET_SENSOR_Handle */ struct GNUNET_CLIENT_Connection *client; - /** - * Head of transmission queue. - */ - struct GNUNET_SENSOR_RequestContext *rc_head; - - /** - * Tail of transmission queue. - */ - struct GNUNET_SENSOR_RequestContext *rc_tail; - - /** - * Handle for the current transmission request, or NULL if none is pending. - */ - struct GNUNET_CLIENT_TransmitHandle *th; - /** * Head of iterator DLL. */ - struct GNUNET_SENSOR_SensorIteratorContext *ic_head; + struct GNUNET_SENSOR_IterateContext *ic_head; /** * Tail of iterator DLL. */ - struct GNUNET_SENSOR_SensorIteratorContext *ic_tail; - - /** - * ID for a reconnect task. - */ - GNUNET_SCHEDULER_TaskIdentifier r_task; + struct GNUNET_SENSOR_IterateContext *ic_tail; /** - * Are we now receiving? + * Message queue used to send data to service */ - int in_receive; - -}; - -/** - * Entry in the transmission queue to SENSOR service. - * - */ -struct GNUNET_SENSOR_RequestContext -{ - /** - * This is a linked list. - */ - struct GNUNET_SENSOR_RequestContext *next; - - /** - * This is a linked list. - */ - struct GNUNET_SENSOR_RequestContext *prev; - - /** - * Handle to the SENSOR service. - */ - struct GNUNET_SENSOR_Handle *h; - - /** - * Function to call after request has been transmitted, or NULL. - */ - GNUNET_SENSOR_Continuation cont; - - /** - * Closure for 'cont'. - */ - void *cont_cls; - - /** - * Number of bytes of the request message (follows after this struct). - */ - size_t size; + struct GNUNET_MQ_Handle *mq; }; /** * Context for an iteration request. */ -struct GNUNET_SENSOR_SensorIteratorContext +struct GNUNET_SENSOR_IterateContext { /** * Kept in a DLL. */ - struct GNUNET_SENSOR_SensorIteratorContext *next; + struct GNUNET_SENSOR_IterateContext *next; /** * Kept in a DLL. */ - struct GNUNET_SENSOR_SensorIteratorContext *prev; + struct GNUNET_SENSOR_IterateContext *prev; /** * Handle to the SENSOR service. @@ -148,7 +86,7 @@ struct GNUNET_SENSOR_SensorIteratorContext /** * Function to call with the results. */ - GNUNET_SENSOR_SensorIteratorCB callback; + GNUNET_SENSOR_SensorIterateCB callback; /** * Closure for 'callback'. @@ -156,174 +94,193 @@ struct GNUNET_SENSOR_SensorIteratorContext void *callback_cls; /** - * Our entry in the transmission queue. + * Envelope containing iterate request. */ - struct GNUNET_SENSOR_RequestContext *rc; + struct GNUNET_MQ_Envelope *ev; /** - * Task responsible for timeout. + * Is the request already sent? If yes, cannot be canceled. */ - GNUNET_SCHEDULER_TaskIdentifier timeout_task; + int request_sent; /** - * Timeout for the operation. + * Are we expecting records from service? */ - struct GNUNET_TIME_Absolute timeout; + int receiving; /** - * Set to GNUNET_YES if we are currently receiving replies from the - * service. + * Task responsible for timeout. */ - int request_transmitted; + GNUNET_SCHEDULER_TaskIdentifier timeout_task; }; -/******************************************************************************/ -/*********************** DECLARATIONS *************************/ -/******************************************************************************/ - -/** - * Close the existing connection to SENSOR and reconnect. - * - * @param h handle to the service - */ -static void -reconnect (struct GNUNET_SENSOR_Handle *h); - /** - * Check if we have a request pending in the transmission queue and are - * able to transmit it right now. If so, schedule transmission. + * Notifier of an error encountered by MQ. * - * @param h handle to the service + * @param cls Closure, service handle + * @param error MQ error type */ static void -trigger_transmit (struct GNUNET_SENSOR_Handle *h); - -/******************************************************************************/ -/******************* CONNECTION FUNCTIONS *********************/ -/******************************************************************************/ - -/** - * Connect to the sensor service. - * - * @return NULL on error - */ -struct GNUNET_SENSOR_Handle * -GNUNET_SENSOR_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) +mq_error_handler (void *cls, enum GNUNET_MQ_Error error) { - struct GNUNET_CLIENT_Connection *client; - struct GNUNET_SENSOR_Handle *h; + struct GNUNET_SENSOR_Handle *h = cls; - client = GNUNET_CLIENT_connect ("sensor", cfg); - if (NULL == client) - return NULL; - h = GNUNET_new (struct GNUNET_SENSOR_Handle); - h->client = client; - h->cfg = cfg; - return h; + LOG (GNUNET_ERROR_TYPE_ERROR, + _("Received an error notification from MQ of type: %d\n"), error); + GNUNET_SENSOR_disconnect (h); //TODO: try to reconnect } /** - * Disconnect from the sensor service + * Handler to a message of type: #GNUNET_MESSAGE_TYPE_SENSOR_END * - * @param h handle to disconnect + * @param cls Closure, service handle + * @param msg Message received */ -void -GNUNET_SENSOR_disconnect (struct GNUNET_SENSOR_Handle *h) +static void +handle_end (void *cls, const struct GNUNET_MessageHeader *msg) { - if (NULL != h->client) + struct GNUNET_SENSOR_Handle *h = cls; + struct GNUNET_SENSOR_IterateContext *ic; + GNUNET_SENSOR_SensorIterateCB cb; + void *cb_cls; + + if (NULL == h->ic_head) { - GNUNET_CLIENT_disconnect (h->client); - h->client = NULL; + GNUNET_break_op (0); + //TODO: reconnect + return; } - GNUNET_free (h); + 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); } /** - * Task scheduled to re-try connecting to the sensor service. + * Handler to a message of type: #GNUNET_MESSAGE_TYPE_SENSOR_INFO * - * @param cls the 'struct GNUNET_SENSOR_Handle' - * @param tc scheduler context + * @param cls Closure, service handle + * @param msg Message received */ static void -reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +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; - h->r_task = GNUNET_SCHEDULER_NO_TASK; - reconnect (h); + 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); } /** - * Close the existing connection to SENSOR and reconnect. + * Disconnect from the sensor service * - * @param h handle to the service + * @param h handle to disconnect */ -static void -reconnect (struct GNUNET_SENSOR_Handle *h) +void +GNUNET_SENSOR_disconnect (struct GNUNET_SENSOR_Handle *h) { - if (GNUNET_SCHEDULER_NO_TASK != h->r_task) + struct GNUNET_SENSOR_IterateContext *ic; + + ic = h->ic_head; + while (NULL != ic) { - GNUNET_SCHEDULER_cancel (h->r_task); - h->r_task = GNUNET_SCHEDULER_NO_TASK; + if (NULL != ic->callback) + ic->callback (ic->callback_cls, NULL, + _("Iterate request canceled due to disconnection.\n")); + GNUNET_SENSOR_iterate_cancel (ic); + ic = h->ic_head; } - if (NULL != h->th) + if (NULL != h->mq) { - GNUNET_CLIENT_notify_transmit_ready_cancel (h->th); - h->th = NULL; + GNUNET_MQ_destroy (h->mq); + h->mq = NULL; } if (NULL != h->client) { GNUNET_CLIENT_disconnect (h->client); h->client = NULL; } - h->in_receive = GNUNET_NO; - h->client = GNUNET_CLIENT_connect ("sensor", h->cfg); - if (NULL == h->client) - { - h->r_task = - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &reconnect_task, - h); - return; - } - trigger_transmit (h); + GNUNET_free (h); } -/******************************************************************************/ -/****************** SENSOR DATA FUNCTIONS *********************/ -/******************************************************************************/ /** - * Cancel an iteration over sensor information. + * Connect to the sensor service. * - * @param ic context of the iterator to cancel + * @return NULL on error */ -void -GNUNET_SENSOR_iterate_sensor_cancel (struct GNUNET_SENSOR_SensorIteratorContext - *ic) +struct GNUNET_SENSOR_Handle * +GNUNET_SENSOR_connect (const struct GNUNET_CONFIGURATION_Handle *cfg) { + struct GNUNET_CLIENT_Connection *client; struct GNUNET_SENSOR_Handle *h; - h = ic->h; - if (GNUNET_SCHEDULER_NO_TASK != ic->timeout_task) - { - GNUNET_SCHEDULER_cancel (ic->timeout_task); - ic->timeout_task = GNUNET_SCHEDULER_NO_TASK; - } - ic->callback = NULL; - if (GNUNET_YES == ic->request_transmitted) - return; /* need to finish processing */ - GNUNET_CONTAINER_DLL_remove (h->ic_head, h->ic_tail, ic); - if (NULL != ic->rc) - { - GNUNET_CONTAINER_DLL_remove (h->rc_head, h->rc_tail, ic->rc); - GNUNET_free (ic->rc); - } - GNUNET_free (ic); + 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; } @@ -337,14 +294,14 @@ static void signal_sensor_iteration_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - struct GNUNET_SENSOR_SensorIteratorContext *ic = cls; - GNUNET_SENSOR_SensorIteratorCB cb; + 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_sensor_cancel (ic); + GNUNET_SENSOR_iterate_cancel (ic); if (NULL != cb) cb (cb_cls, NULL, _("Timeout transmitting iteration request to `SENSOR' service.")); @@ -352,289 +309,132 @@ signal_sensor_iteration_timeout (void *cls, /** - * Type of a function to call when we receive a message from the - * service. Call the iterator with the result and (if applicable) - * continue to receive more messages or trigger processing the next - * event (if applicable). + * Callback from MQ when the request has already been sent to the service. + * Now it can not be canelled. * * @param cls closure - * @param msg message received, NULL on timeout or fatal error */ static void -sensor_handler (void *cls, const struct GNUNET_MessageHeader *msg) +iterate_request_sent (void *cls) { - struct GNUNET_SENSOR_Handle *h = cls; - struct GNUNET_SENSOR_SensorIteratorContext *ic = h->ic_head; - GNUNET_SENSOR_SensorIteratorCB cb; - void *cb_cls; - uint16_t ms; - const struct SensorInfoMessage *im; - struct SensorInfoShort *sensor; - size_t name_len; - size_t desc_len; - char *str_ptr; + struct GNUNET_SENSOR_IterateContext *ic = cls; - h->in_receive = GNUNET_NO; - if (NULL == msg) - { - /* sensor service died, signal error */ - if (NULL != ic) - { - cb = ic->callback; - cb_cls = ic->callback_cls; - GNUNET_SENSOR_iterate_sensor_cancel (ic); - } - else - { - cb = NULL; - } - reconnect (h); - if (NULL != cb) - cb (cb_cls, NULL, _("Failed to receive response from `SENSOR' service.")); - return; - } - if (NULL == ic) - { - /* didn't expect a response, reconnect */ - reconnect (h); - return; - } - ic->request_transmitted = GNUNET_NO; - cb = ic->callback; - cb_cls = ic->callback_cls; - if (GNUNET_MESSAGE_TYPE_SENSOR_END == ntohs (msg->type)) - { - /* normal end of list of sensors, signal end, process next pending request */ - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Received end of list of sensors from `%s' service\n", "SENSOR"); - GNUNET_SENSOR_iterate_sensor_cancel (ic); - trigger_transmit (h); - if ((GNUNET_NO == h->in_receive) && (NULL != h->ic_head)) - { - h->in_receive = GNUNET_YES; - GNUNET_CLIENT_receive (h->client, &sensor_handler, h, - GNUNET_TIME_absolute_get_remaining (h-> - ic_head->timeout)); - } - if (NULL != cb) - cb (cb_cls, NULL, NULL); - return; - } - ms = ntohs (msg->size); - im = (const struct SensorInfoMessage *) msg; - name_len = ntohs (im->name_len); - desc_len = ntohs (im->description_len); - if ((ms != sizeof (struct SensorInfoMessage) + name_len + desc_len) || - (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_SENSOR_INFO)) - { - /* malformed message */ - GNUNET_break (0); - GNUNET_SENSOR_iterate_sensor_cancel (ic); - reconnect (h); - if (NULL != cb) - cb (cb_cls, NULL, _("Received invalid message from `SENSOR' service.")); - return; - } - sensor = GNUNET_new (struct SensorInfoShort); - str_ptr = (char *) &im[1]; - sensor->name = GNUNET_strndup (str_ptr, name_len); - LOG (GNUNET_ERROR_TYPE_DEBUG, "Received sensor name (%d): %.*s\n", name_len, - name_len, str_ptr); - str_ptr += name_len; - if (desc_len > 0) - { - LOG (GNUNET_ERROR_TYPE_DEBUG, "Received sensor description (%d): %.*s\n", - desc_len, desc_len, str_ptr); - sensor->description = GNUNET_strndup (str_ptr, desc_len); - } - sensor->version_major = ntohs (im->version_major); - sensor->version_minor = ntohs (im->version_minor); - h->in_receive = GNUNET_YES; - GNUNET_CLIENT_receive (h->client, &sensor_handler, h, - GNUNET_TIME_absolute_get_remaining (ic->timeout)); - if (NULL != cb) - cb (cb_cls, sensor, NULL); + ic->request_sent = GNUNET_YES; + ic->ev = NULL; + ic->receiving = GNUNET_YES; } /** - * We've transmitted the iteration request. Now get ready to process - * the results (or handle transmission error). + * Cancel an iteration request. + * This should be called before the iterate callback is called with a NULL value. * - * @param cls the 'struct GNUNET_SENSOR_SensorIteratorContext' - * @param emsg error message, NULL if transmission worked - */ -static void -sensor_iterator_start_receive (void *cls, const char *emsg) -{ - struct GNUNET_SENSOR_SensorIteratorContext *ic = cls; - struct GNUNET_SENSOR_Handle *h = ic->h; - GNUNET_SENSOR_SensorIteratorCB cb; - void *cb_cls; - - ic->rc = NULL; - if (NULL != emsg) - { - cb = ic->callback; - cb_cls = ic->callback_cls; - GNUNET_SENSOR_iterate_sensor_cancel (ic); - reconnect (h); - if (NULL != cb) - cb (cb_cls, NULL, emsg); - return; - } - LOG (GNUNET_ERROR_TYPE_DEBUG, "Waiting for response from `%s' service.\n", - "SENSOR"); - ic->request_transmitted = GNUNET_YES; - if (GNUNET_NO == h->in_receive) - { - h->in_receive = GNUNET_YES; - GNUNET_CLIENT_receive (h->client, &sensor_handler, h, - GNUNET_TIME_absolute_get_remaining (ic->timeout)); - } -} - - -/** - * Transmit the request at the head of the transmission queue - * and trigger continuation (if any). - * - * @param cls the 'struct GNUNET_SENSOR_Handle' (with the queue) - * @param size size of the buffer (0 on error) - * @param buf where to copy the message - * @return number of bytes copied to buf + * @param ic context of the iterator to cancel */ -static size_t -do_transmit (void *cls, size_t size, void *buf) +void +GNUNET_SENSOR_iterate_cancel (struct GNUNET_SENSOR_IterateContext *ic) { - struct GNUNET_SENSOR_Handle *h = cls; - struct GNUNET_SENSOR_RequestContext *rc = h->rc_head; - size_t ret; + struct GNUNET_SENSOR_Handle *h; - h->th = NULL; - if (NULL == rc) - return 0; /* request was cancelled in the meantime */ - if (NULL == buf) + h = ic->h; + if (GNUNET_NO == ic->request_sent) { - /* sensor service died */ - LOG (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK, - "Failed to transmit message to `%s' service.\n", "SENSOR"); - GNUNET_CONTAINER_DLL_remove (h->rc_head, h->rc_tail, rc); - reconnect (h); - if (NULL != rc->cont) - rc->cont (rc->cont_cls, _("failed to transmit request (service down?)")); - GNUNET_free (rc); - return 0; + GNUNET_MQ_send_cancel (ic->ev); + ic->ev = NULL; + ic->request_sent = GNUNET_YES; } - ret = rc->size; - if (size < ret) + if (GNUNET_YES == ic->receiving) { - /* change in head of queue (i.e. cancel + add), try again */ - trigger_transmit (h); - return 0; + /* don't remove since we are still expecting records */ + ic->callback = NULL; + ic->callback_cls = NULL; + return; } - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Transmitting request of size %u to `%s' service.\n", ret, "SENSOR"); - memcpy (buf, &rc[1], ret); - GNUNET_CONTAINER_DLL_remove (h->rc_head, h->rc_tail, rc); - trigger_transmit (h); - if (NULL != rc->cont) - rc->cont (rc->cont_cls, NULL); - GNUNET_free (rc); - return ret; -} - - -/** - * Check if we have a request pending in the transmission queue and are - * able to transmit it right now. If so, schedule transmission. - * - * @param h handle to the service - */ -static void -trigger_transmit (struct GNUNET_SENSOR_Handle *h) -{ - struct GNUNET_SENSOR_RequestContext *rc; - - if (NULL == (rc = h->rc_head)) - return; /* no requests queued */ - if (NULL != h->th) - return; /* request already pending */ - if (NULL == h->client) + if (GNUNET_SCHEDULER_NO_TASK != ic->timeout_task) { - /* disconnected, try to reconnect */ - reconnect (h); - return; + GNUNET_SCHEDULER_cancel (ic->timeout_task); + ic->timeout_task = GNUNET_SCHEDULER_NO_TASK; } - h->th = - GNUNET_CLIENT_notify_transmit_ready (h->client, rc->size, - GNUNET_TIME_UNIT_FOREVER_REL, - GNUNET_YES, &do_transmit, h); + GNUNET_CONTAINER_DLL_remove (h->ic_head, h->ic_tail, ic); + GNUNET_free (ic); } /** - * Client asking to iterate all available sensors + * 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 information on one sensor only, can be NULL to get all - * @param sensorname_len length of the sensorname parameter - * @param callback the method to call for each sensor + * @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_SensorIteratorContext * -GNUNET_SENSOR_iterate_sensors (struct GNUNET_SENSOR_Handle *h, - struct GNUNET_TIME_Relative timeout, - const char *sensorname, size_t sensorname_len, - GNUNET_SENSOR_SensorIteratorCB callback, - void *callback_cls) +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_SensorIteratorContext *ic; - struct GNUNET_SENSOR_RequestContext *rc; - struct GNUNET_MessageHeader *mh; - - ic = GNUNET_new (struct GNUNET_SENSOR_SensorIteratorContext); + struct GNUNET_SENSOR_IterateContext *ic; + struct GNUNET_MessageHeader *msg; + struct GNUNET_MQ_Envelope *ev; + size_t sensor_name_len; - if (NULL == sensorname) + if (NULL == sensor_name) { - LOG (GNUNET_ERROR_TYPE_INFO, - "Requesting list of sensors from SENSOR service\n"); - rc = GNUNET_malloc (sizeof (struct GNUNET_SENSOR_RequestContext) + - sizeof (struct GNUNET_MessageHeader)); - rc->size = sizeof (struct GNUNET_MessageHeader); - mh = (struct GNUNET_MessageHeader *) &rc[1]; - mh->size = htons (sizeof (struct GNUNET_MessageHeader)); - mh->type = htons (GNUNET_MESSAGE_TYPE_SENSOR_GETALL); + ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SENSOR_GETALL); } else { - LOG (GNUNET_ERROR_TYPE_INFO, - "Requesting information on sensor `%s' from SENSOR service\n", - sensorname); - rc = GNUNET_malloc (sizeof (struct GNUNET_SENSOR_RequestContext) + - sizeof (struct GNUNET_MessageHeader) + sensorname_len); - rc->size = sizeof (struct GNUNET_MessageHeader) + sensorname_len; - mh = (struct GNUNET_MessageHeader *) &rc[1]; - mh->size = htons (rc->size); - mh->type = htons (GNUNET_MESSAGE_TYPE_SENSOR_GET); - memcpy (&mh[1], sensorname, sensorname_len); + 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->rc = rc; + ic->ev = ev; + ic->request_sent = GNUNET_NO; + ic->receiving = GNUNET_NO; ic->callback = callback; ic->callback_cls = callback_cls; - ic->timeout = GNUNET_TIME_relative_to_absolute (timeout); ic->timeout_task = GNUNET_SCHEDULER_add_delayed (timeout, &signal_sensor_iteration_timeout, ic); - rc->cont = &sensor_iterator_start_receive; - rc->cont_cls = ic; - GNUNET_CONTAINER_DLL_insert_tail (h->rc_head, h->rc_tail, rc); + GNUNET_MQ_notify_sent (ev, &iterate_request_sent, ic); GNUNET_CONTAINER_DLL_insert_tail (h->ic_head, h->ic_tail, ic); - trigger_transmit (h); return ic; } + +/** + * 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 + */ +void +GNUNET_SENSOR_force_anomaly (struct GNUNET_SENSOR_Handle *h, + char *sensor_name, int anomalous) +{ + struct ForceAnomalyMessage *msg; + struct GNUNET_MQ_Envelope *ev; + + ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SENSOR_ANOMALY_REPORT); + GNUNET_MQ_send (h->mq, ev); +} + + /* end of sensor_api.c */ -- cgit v1.2.3