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/gnunet-service-sensor_reporting_anomaly.c
23 * @brief sensor service anomaly reporting functionality
24 * @author Omar Tarabai
27 #include "gnunet_util_lib.h"
29 #include "gnunet_peerstore_service.h"
30 #include "gnunet_core_service.h"
32 #define LOG(kind,...) GNUNET_log_from (kind, "sensor-reporting-anomaly",__VA_ARGS__)
40 struct AnomalyInfo *prev;
45 struct AnomalyInfo *next;
50 struct GNUNET_SENSOR_SensorInfo *sensor;
53 * Current anomalous status of sensor
58 * List of peers that reported an anomaly for this sensor
60 struct GNUNET_CONTAINER_MultiPeerMap *anomalous_neighbors;
65 * Information about a connected CORE peer.
66 * Note that we only know about a connected peer if it is running the same
67 * application (sensor anomaly reporting) as us.
75 struct CorePeer *prev;
80 struct CorePeer *next;
83 * Peer identity of connected peer
85 struct GNUNET_PeerIdentity *peerid;
88 * Message queue for messages to be sent to this peer
90 struct GNUNET_MQ_Handle *mq;
98 static const struct GNUNET_CONFIGURATION_Handle *cfg;
101 * Multihashmap of loaded sensors
103 static struct GNUNET_CONTAINER_MultiHashMap *sensors;
106 * Handle to core service
108 static struct GNUNET_CORE_Handle *core;
113 static struct GNUNET_PeerIdentity mypeerid;
116 * Head of DLL of anomaly info structs
118 static struct AnomalyInfo *ai_head;
121 * Tail of DLL of anomaly info structs
123 static struct AnomalyInfo *ai_tail;
126 * Head of DLL of CORE peers
128 static struct CorePeer *cp_head;
131 * Tail of DLL of CORE peers
133 static struct CorePeer *cp_tail;
136 * Is the module started?
138 static int module_running = GNUNET_NO;
141 * Number of known neighborhood peers
143 static int neighborhood;
147 * Destroy anomaly info struct
149 * @param ai struct to destroy
152 destroy_anomaly_info (struct AnomalyInfo *ai)
154 if (NULL != ai->anomalous_neighbors)
155 GNUNET_CONTAINER_multipeermap_destroy (ai->anomalous_neighbors);
161 * Destroy core peer struct
163 * @param cp struct to destroy
166 destroy_core_peer (struct CorePeer *cp)
168 struct AnomalyInfo *ai;
172 GNUNET_MQ_destroy (cp->mq);
178 GNUNET_assert (NULL != ai->anomalous_neighbors);
179 GNUNET_CONTAINER_multipeermap_remove_all (ai->anomalous_neighbors,
188 * Stop sensor anomaly reporting module
191 SENSOR_reporting_anomaly_stop ()
193 struct AnomalyInfo *ai;
196 LOG (GNUNET_ERROR_TYPE_DEBUG, "Stopping sensor anomaly reporting module.\n");
197 module_running = GNUNET_NO;
201 GNUNET_CONTAINER_DLL_remove (ai_head, ai_tail, ai);
202 destroy_anomaly_info (ai);
208 GNUNET_CONTAINER_DLL_remove (cp_head, cp_tail, cp);
209 destroy_core_peer (cp);
215 GNUNET_CORE_disconnect (core);
222 * Gets the anomaly info struct related to the given sensor
224 * @param sensor Sensor to search by
226 static struct AnomalyInfo *
227 get_anomaly_info_by_sensor (struct GNUNET_SENSOR_SensorInfo *sensor)
229 struct AnomalyInfo *ai;
234 if (ai->sensor == sensor)
245 * Create an anomaly report message from a given anomaly info structb inside an
248 * @param ai Anomaly info struct to use
251 static struct GNUNET_MQ_Envelope *
252 create_anomaly_report_message (struct AnomalyInfo *ai)
254 struct AnomalyReportMessage *arm;
255 struct GNUNET_MQ_Envelope *ev;
257 ev = GNUNET_MQ_msg (arm, GNUNET_MESSAGE_TYPE_SENSOR_ANOMALY_REPORT);
258 GNUNET_CRYPTO_hash (ai->sensor->name, strlen (ai->sensor->name) + 1,
259 &arm->sensorname_hash);
260 arm->sensorversion_major = ai->sensor->version_major;
261 arm->sensorversion_minor = ai->sensor->version_minor;
262 arm->anomalous = ai->anomalous;
263 arm->anomalous_neighbors =
264 ((float) GNUNET_CONTAINER_multipeermap_size (ai->anomalous_neighbors)) /
271 * Send given anomaly info report to given core peer.
273 * @param cp Core peer to send the report to
274 * @param ai Anomaly info to report
277 send_anomaly_report (struct CorePeer *cp, struct AnomalyInfo *ai)
279 struct GNUNET_MQ_Envelope *ev;
281 GNUNET_assert (NULL != cp->mq);
282 ev = create_anomaly_report_message (ai);
283 GNUNET_MQ_send (cp->mq, ev);
288 * An inbound anomaly report is received from a peer through CORE.
290 * @param cls closure (unused)
291 * @param peer the other peer involved
292 * @param message the actual message
293 * @return #GNUNET_OK to keep the connection open,
294 * #GNUNET_SYSERR to close connection to the peer (signal serious error)
297 handle_anomaly_report (void *cls, const struct GNUNET_PeerIdentity *other,
298 const struct GNUNET_MessageHeader *message)
300 struct AnomalyReportMessage *arm;
301 struct GNUNET_SENSOR_SensorInfo *sensor;
302 struct AnomalyInfo *ai;
305 arm = (struct AnomalyReportMessage *) message;
306 sensor = GNUNET_CONTAINER_multihashmap_get (sensors, &arm->sensorname_hash);
307 if (NULL == sensor || sensor->version_major != arm->sensorversion_major ||
308 sensor->version_minor != arm->sensorversion_minor)
310 LOG (GNUNET_ERROR_TYPE_WARNING,
311 "I don't have the sensor reported by the peer `%s'.\n",
315 ai = get_anomaly_info_by_sensor (sensor);
316 GNUNET_assert (NULL != ai);
318 GNUNET_CONTAINER_multipeermap_contains (ai->anomalous_neighbors, other);
319 if (GNUNET_YES == ai->anomalous)
321 if (GNUNET_YES == peer_in_list)
324 GNUNET_CONTAINER_multipeermap_put (ai->anomalous_neighbors, other, NULL,
325 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
329 if (GNUNET_NO == peer_in_list)
332 GNUNET_CONTAINER_multipeermap_remove_all (ai->anomalous_neighbors, other);
334 //TODO: report to collection point if anomalous neigbors jump up or down
335 // by a configurable percentage or is now 0% or 100%
341 * Method called whenever a CORE peer disconnects.
343 * @param cls closure (unused)
344 * @param peer peer identity this notification is about
347 core_disconnect_cb (void *cls, const struct GNUNET_PeerIdentity *peer)
351 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&mypeerid, peer))
357 if (peer == cp->peerid)
359 GNUNET_CONTAINER_DLL_remove (cp_head, cp_tail, cp);
360 destroy_core_peer (cp);
365 LOG (GNUNET_ERROR_TYPE_ERROR,
366 _("Received disconnect notification from CORE"
367 " for a peer we didn't know about.\n"));
372 * Method called whenever a given peer connects through CORE.
374 * @param cls closure (unused)
375 * @param peer peer identity this notification is about
378 core_connect_cb (void *cls, const struct GNUNET_PeerIdentity *peer)
381 struct AnomalyInfo *ai;
383 if (0 == GNUNET_CRYPTO_cmp_peer_identity (&mypeerid, peer))
386 cp = GNUNET_new (struct CorePeer);
387 cp->peerid = (struct GNUNET_PeerIdentity *) peer;
388 cp->mq = GNUNET_CORE_mq_create (core, peer);
389 GNUNET_CONTAINER_DLL_insert (cp_head, cp_tail, cp);
390 /* Send any locally anomalous sensors to the new peer */
394 if (GNUNET_YES == ai->anomalous)
395 send_anomaly_report (cp, ai);
402 * Function called after #GNUNET_CORE_connect has succeeded (or failed
403 * for good). Note that the private key of the peer is intentionally
404 * not exposed here; if you need it, your process should try to read
405 * the private key file directly (which should work if you are
406 * authorized...). Implementations of this function must not call
407 * #GNUNET_CORE_disconnect (other than by scheduling a new task to
410 * @param cls closure (unused)
411 * @param my_identity ID of this peer, NULL if we failed
414 core_startup_cb (void *cls, const struct GNUNET_PeerIdentity *my_identity)
416 if (NULL == my_identity)
418 LOG (GNUNET_ERROR_TYPE_ERROR, _("Failed to connect to CORE service.\n"));
419 SENSOR_reporting_anomaly_stop ();
422 if (0 != GNUNET_CRYPTO_cmp_peer_identity (&mypeerid, my_identity))
424 LOG (GNUNET_ERROR_TYPE_ERROR,
425 _("Peer identity received from CORE init doesn't match ours.\n"));
426 SENSOR_reporting_anomaly_stop ();
433 * Used by the analysis module to tell the reporting module about a change in
434 * the anomaly status of a sensor.
436 * @param sensor Related sensor
437 * @param anomalous The new sensor anomalous status
440 SENSOR_reporting_anomaly_update (struct GNUNET_SENSOR_SensorInfo *sensor,
443 struct AnomalyInfo *ai;
446 if (GNUNET_NO == module_running)
448 ai = get_anomaly_info_by_sensor (sensor);
449 GNUNET_assert (NULL != ai);
450 ai->anomalous = anomalous;
451 /* Report change to all neighbors */
455 send_anomaly_report (cp, ai);
458 //TODO: report change to collection point if report_anomalies
463 * Iterator for defined sensors and creates anomaly info context
467 * @param value a `struct GNUNET_SENSOR_SensorInfo *` with sensor information
468 * @return #GNUNET_YES to continue iterations
471 init_sensor_reporting (void *cls, const struct GNUNET_HashCode *key,
474 struct GNUNET_SENSOR_SensorInfo *sensor = value;
475 struct AnomalyInfo *ai;
477 ai = GNUNET_new (struct AnomalyInfo);
480 ai->anomalous = GNUNET_NO;
481 ai->anomalous_neighbors =
482 GNUNET_CONTAINER_multipeermap_create (10, GNUNET_NO);
483 GNUNET_CONTAINER_DLL_insert (ai_head, ai_tail, ai);
489 * Start the sensor anomaly reporting module
491 * @param c our service configuration
492 * @param s multihashmap of loaded sensors
493 * @return #GNUNET_OK if started successfully, #GNUNET_SYSERR otherwise
496 SENSOR_reporting_anomaly_start (const struct GNUNET_CONFIGURATION_Handle *c,
497 struct GNUNET_CONTAINER_MultiHashMap *s)
499 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
500 {&handle_anomaly_report, GNUNET_MESSAGE_TYPE_SENSOR_ANOMALY_REPORT,
501 sizeof (struct AnomalyReportMessage)},
505 LOG (GNUNET_ERROR_TYPE_DEBUG, "Starting sensor anomaly reporting module.\n");
506 GNUNET_assert (NULL != s);
510 GNUNET_CORE_connect (cfg, NULL, &core_startup_cb, core_connect_cb,
511 &core_disconnect_cb, NULL, GNUNET_YES, NULL,
512 GNUNET_YES, core_handlers);
515 LOG (GNUNET_ERROR_TYPE_ERROR, _("Failed to connect to CORE service.\n"));
516 SENSOR_reporting_anomaly_stop ();
517 return GNUNET_SYSERR;
519 GNUNET_CRYPTO_get_peer_identity (cfg, &mypeerid);
520 GNUNET_CONTAINER_multihashmap_iterate (sensors, &init_sensor_reporting, NULL);
522 module_running = GNUNET_YES;
526 /* end of gnunet-service-sensor_reporting_anomaly.c */