sensor_api.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. /*
  2. This file is part of GNUnet.
  3. (C)
  4. GNUnet is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published
  6. by the Free Software Foundation; either version 3, or (at your
  7. option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNUnet; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  15. Boston, MA 02111-1307, USA.
  16. */
  17. /**
  18. * @file sensor/sensor_api.c
  19. * @brief API for sensor service
  20. * @author Omar Tarabai
  21. */
  22. #include "platform.h"
  23. #include "gnunet_util_lib.h"
  24. #include "sensor.h"
  25. #define LOG(kind,...) GNUNET_log_from (kind, "sensor-api",__VA_ARGS__)
  26. /**
  27. * Handle to the sensor service.
  28. */
  29. struct GNUNET_SENSOR_Handle
  30. {
  31. /**
  32. * Our configuration.
  33. */
  34. const struct GNUNET_CONFIGURATION_Handle *cfg;
  35. /**
  36. * Connection to the service.
  37. */
  38. struct GNUNET_CLIENT_Connection *client;
  39. /**
  40. * Head of iteration requests DLL.
  41. */
  42. struct GNUNET_SENSOR_IterateContext *ic_head;
  43. /**
  44. * Tail of iteration requests DLL.
  45. */
  46. struct GNUNET_SENSOR_IterateContext *ic_tail;
  47. /**
  48. * Head of force anomaly requests
  49. */
  50. struct GNUNET_SENSOR_ForceAnomalyContext *fa_head;
  51. /**
  52. * Tail of force anomaly requests
  53. */
  54. struct GNUNET_SENSOR_ForceAnomalyContext *fa_tail;
  55. /**
  56. * Message queue used to send data to service
  57. */
  58. struct GNUNET_MQ_Handle *mq;
  59. };
  60. /**
  61. * Context for an iteration request.
  62. */
  63. struct GNUNET_SENSOR_IterateContext
  64. {
  65. /**
  66. * Kept in a DLL.
  67. */
  68. struct GNUNET_SENSOR_IterateContext *next;
  69. /**
  70. * Kept in a DLL.
  71. */
  72. struct GNUNET_SENSOR_IterateContext *prev;
  73. /**
  74. * Handle to the SENSOR service.
  75. */
  76. struct GNUNET_SENSOR_Handle *h;
  77. /**
  78. * Function to call with the results.
  79. */
  80. GNUNET_SENSOR_SensorIterateCB callback;
  81. /**
  82. * Closure for 'callback'.
  83. */
  84. void *callback_cls;
  85. /**
  86. * Envelope containing iterate request.
  87. */
  88. struct GNUNET_MQ_Envelope *ev;
  89. /**
  90. * Is the request already sent? If yes, cannot be canceled.
  91. */
  92. int request_sent;
  93. /**
  94. * Are we expecting records from service?
  95. */
  96. int receiving;
  97. /**
  98. * Task responsible for timeout.
  99. */
  100. GNUNET_SCHEDULER_TaskIdentifier timeout_task;
  101. };
  102. /**
  103. * Context of a force anomaly request
  104. */
  105. struct GNUNET_SENSOR_ForceAnomalyContext
  106. {
  107. /**
  108. * DLL
  109. */
  110. struct GNUNET_SENSOR_ForceAnomalyContext *next;
  111. /**
  112. * DLL
  113. */
  114. struct GNUNET_SENSOR_ForceAnomalyContext *prev;
  115. /**
  116. * Handle to the SENSOR service.
  117. */
  118. struct GNUNET_SENSOR_Handle *h;
  119. /**
  120. * Envelope containing iterate request.
  121. */
  122. struct GNUNET_MQ_Envelope *ev;
  123. /**
  124. * User continuation function
  125. */
  126. GNUNET_SENSOR_Continuation cont;
  127. /**
  128. * Closure for cont
  129. */
  130. void *cont_cls;
  131. };
  132. /**
  133. * Notifier of an error encountered by MQ.
  134. *
  135. * @param cls Closure, service handle
  136. * @param error MQ error type
  137. */
  138. static void
  139. mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
  140. {
  141. struct GNUNET_SENSOR_Handle *h = cls;
  142. LOG (GNUNET_ERROR_TYPE_ERROR,
  143. _("Received an error notification from MQ of type: %d\n"), error);
  144. GNUNET_SENSOR_disconnect (h); //TODO: try to reconnect
  145. }
  146. /**
  147. * Handler to a message of type: #GNUNET_MESSAGE_TYPE_SENSOR_END
  148. *
  149. * @param cls Closure, service handle
  150. * @param msg Message received
  151. */
  152. static void
  153. handle_end (void *cls, const struct GNUNET_MessageHeader *msg)
  154. {
  155. struct GNUNET_SENSOR_Handle *h = cls;
  156. struct GNUNET_SENSOR_IterateContext *ic;
  157. GNUNET_SENSOR_SensorIterateCB cb;
  158. void *cb_cls;
  159. if (NULL == h->ic_head)
  160. {
  161. GNUNET_break_op (0);
  162. //TODO: reconnect
  163. return;
  164. }
  165. ic = h->ic_head;
  166. cb = ic->callback;
  167. cb_cls = ic->callback_cls;
  168. ic->receiving = GNUNET_NO;
  169. GNUNET_SENSOR_iterate_cancel (ic);
  170. if (NULL != cb)
  171. cb (cb_cls, NULL, NULL);
  172. }
  173. /**
  174. * Handler to a message of type: #GNUNET_MESSAGE_TYPE_SENSOR_INFO
  175. *
  176. * @param cls Closure, service handle
  177. * @param msg Message received
  178. */
  179. static void
  180. handle_sensor_info (void *cls, const struct GNUNET_MessageHeader *msg)
  181. {
  182. struct GNUNET_SENSOR_Handle *h = cls;
  183. struct GNUNET_SENSOR_IterateContext *ic;
  184. uint16_t msg_size;
  185. struct SensorInfoMessage *sensor_msg;
  186. uint16_t sensor_name_len;
  187. uint16_t sensor_desc_len;
  188. struct SensorInfoShort *sensor;
  189. void *dummy;
  190. if (NULL == h->ic_head)
  191. {
  192. GNUNET_break_op (0);
  193. //TODO: reconnect
  194. return;
  195. }
  196. ic = h->ic_head;
  197. if (NULL == ic->callback) /* no need to parse message */
  198. return;
  199. msg_size = ntohs (msg->size);
  200. if (msg_size < sizeof (struct SensorInfoMessage))
  201. {
  202. GNUNET_break_op (0);
  203. //TODO: reconnect
  204. return;
  205. }
  206. sensor_msg = (struct SensorInfoMessage *) msg;
  207. sensor_name_len = ntohs (sensor_msg->name_len);
  208. sensor_desc_len = ntohs (sensor_msg->description_len);
  209. if (msg_size !=
  210. sizeof (struct SensorInfoMessage) + sensor_name_len + sensor_desc_len)
  211. {
  212. GNUNET_break_op (0);
  213. //TODO: reconnect
  214. return;
  215. }
  216. sensor = GNUNET_new (struct SensorInfoShort);
  217. sensor->version_major = ntohs (sensor_msg->version_major);
  218. sensor->version_minor = ntohs (sensor_msg->version_minor);
  219. dummy = &sensor_msg[1];
  220. sensor->name = GNUNET_strndup (dummy, sensor_name_len);
  221. dummy += sensor_name_len;
  222. sensor->description = GNUNET_strndup (dummy, sensor_desc_len);
  223. ic->callback (ic->callback_cls, sensor, NULL);
  224. GNUNET_free (sensor->name);
  225. GNUNET_free (sensor->description);
  226. GNUNET_free (sensor);
  227. }
  228. /**
  229. * Disconnect from the sensor service.
  230. * Please disconnect only when all requests sent are complete or canceled.
  231. *
  232. * @param h handle to disconnect
  233. */
  234. void
  235. GNUNET_SENSOR_disconnect (struct GNUNET_SENSOR_Handle *h)
  236. {
  237. struct GNUNET_SENSOR_IterateContext *ic;
  238. GNUNET_SENSOR_SensorIterateCB ic_callback;
  239. void *ic_callback_cls;
  240. struct GNUNET_SENSOR_ForceAnomalyContext *fa;
  241. GNUNET_SENSOR_Continuation fa_cont;
  242. void *fa_cont_cls;
  243. ic = h->ic_head;
  244. while (NULL != ic)
  245. {
  246. ic_callback = ic->callback;
  247. ic_callback_cls = ic->callback_cls;
  248. GNUNET_SENSOR_iterate_cancel (ic);
  249. if (NULL != ic_callback)
  250. ic_callback (ic_callback_cls, NULL,
  251. _("Iterate request canceled due to disconnection.\n"));
  252. ic = h->ic_head;
  253. }
  254. fa = h->fa_head;
  255. while (NULL != fa)
  256. {
  257. fa_cont = fa->cont;
  258. fa_cont_cls = fa->cont_cls;
  259. GNUNET_SENSOR_force_anomaly_cancel (fa);
  260. if (NULL != fa_cont)
  261. fa_cont (fa_cont_cls,
  262. _("Force anomaly request canceled due to disconnection.\n"));
  263. fa = h->fa_head;
  264. }
  265. if (NULL != h->mq)
  266. {
  267. GNUNET_MQ_destroy (h->mq);
  268. h->mq = NULL;
  269. }
  270. if (NULL != h->client)
  271. {
  272. GNUNET_CLIENT_disconnect (h->client);
  273. h->client = NULL;
  274. }
  275. GNUNET_free (h);
  276. }
  277. /**
  278. * Connect to the sensor service.
  279. *
  280. * @return NULL on error
  281. */
  282. struct GNUNET_SENSOR_Handle *
  283. GNUNET_SENSOR_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
  284. {
  285. struct GNUNET_CLIENT_Connection *client;
  286. struct GNUNET_SENSOR_Handle *h;
  287. static const struct GNUNET_MQ_MessageHandler mq_handlers[] = {
  288. {&handle_sensor_info, GNUNET_MESSAGE_TYPE_SENSOR_INFO, 0},
  289. {&handle_end, GNUNET_MESSAGE_TYPE_SENSOR_END, 0},
  290. GNUNET_MQ_HANDLERS_END
  291. };
  292. client = GNUNET_CLIENT_connect ("sensor", cfg);
  293. if (NULL == client)
  294. return NULL;
  295. h = GNUNET_new (struct GNUNET_SENSOR_Handle);
  296. h->client = client;
  297. h->cfg = cfg;
  298. h->mq =
  299. GNUNET_MQ_queue_for_connection_client (h->client, mq_handlers,
  300. &mq_error_handler, h);
  301. return h;
  302. }
  303. /**
  304. * Iteration request has timed out.
  305. *
  306. * @param cls the 'struct GNUNET_SENSOR_SensorIteratorContext*'
  307. * @param tc scheduler context
  308. */
  309. static void
  310. signal_sensor_iteration_timeout (void *cls,
  311. const struct GNUNET_SCHEDULER_TaskContext *tc)
  312. {
  313. struct GNUNET_SENSOR_IterateContext *ic = cls;
  314. GNUNET_SENSOR_SensorIterateCB cb;
  315. void *cb_cls;
  316. ic->timeout_task = GNUNET_SCHEDULER_NO_TASK;
  317. cb = ic->callback;
  318. cb_cls = ic->callback_cls;
  319. GNUNET_SENSOR_iterate_cancel (ic);
  320. if (NULL != cb)
  321. cb (cb_cls, NULL,
  322. _("Timeout transmitting iteration request to `SENSOR' service."));
  323. }
  324. /**
  325. * Callback from MQ when the request has already been sent to the service.
  326. * Now it can not be canelled.
  327. *
  328. * @param cls closure
  329. */
  330. static void
  331. iterate_request_sent (void *cls)
  332. {
  333. struct GNUNET_SENSOR_IterateContext *ic = cls;
  334. ic->request_sent = GNUNET_YES;
  335. ic->ev = NULL;
  336. ic->receiving = GNUNET_YES;
  337. }
  338. /**
  339. * Cancel an iteration request.
  340. * This should be called before the iterate callback is called with a NULL value.
  341. *
  342. * @param ic context of the iterator to cancel
  343. */
  344. void
  345. GNUNET_SENSOR_iterate_cancel (struct GNUNET_SENSOR_IterateContext *ic)
  346. {
  347. struct GNUNET_SENSOR_Handle *h;
  348. h = ic->h;
  349. if (GNUNET_NO == ic->request_sent)
  350. {
  351. GNUNET_MQ_send_cancel (ic->ev);
  352. ic->ev = NULL;
  353. ic->request_sent = GNUNET_YES;
  354. }
  355. if (GNUNET_YES == ic->receiving)
  356. {
  357. /* don't remove since we are still expecting records */
  358. ic->callback = NULL;
  359. ic->callback_cls = NULL;
  360. return;
  361. }
  362. if (GNUNET_SCHEDULER_NO_TASK != ic->timeout_task)
  363. {
  364. GNUNET_SCHEDULER_cancel (ic->timeout_task);
  365. ic->timeout_task = GNUNET_SCHEDULER_NO_TASK;
  366. }
  367. GNUNET_CONTAINER_DLL_remove (h->ic_head, h->ic_tail, ic);
  368. GNUNET_free (ic);
  369. }
  370. /**
  371. * Get one or all sensors loaded by the sensor service.
  372. * The callback will be called with each sensor received and once with a NULL
  373. * value to signal end of iteration.
  374. *
  375. * @param h Handle to SENSOR service
  376. * @param timeout how long to wait until timing out
  377. * @param sensorname Name of the required sensor, NULL to get all
  378. * @param callback the function to call for each sensor
  379. * @param callback_cls closure for callback
  380. * @return iterator context
  381. */
  382. struct GNUNET_SENSOR_IterateContext *
  383. GNUNET_SENSOR_iterate (struct GNUNET_SENSOR_Handle *h,
  384. struct GNUNET_TIME_Relative timeout,
  385. const char *sensor_name,
  386. GNUNET_SENSOR_SensorIterateCB callback,
  387. void *callback_cls)
  388. {
  389. struct GNUNET_SENSOR_IterateContext *ic;
  390. struct GNUNET_MessageHeader *msg;
  391. struct GNUNET_MQ_Envelope *ev;
  392. size_t sensor_name_len;
  393. if (NULL == sensor_name)
  394. {
  395. ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SENSOR_GETALL);
  396. }
  397. else
  398. {
  399. sensor_name_len = strlen (sensor_name) + 1;
  400. ev = GNUNET_MQ_msg_extra (msg, sensor_name_len,
  401. GNUNET_MESSAGE_TYPE_SENSOR_GET);
  402. memcpy (&msg[1], sensor_name, sensor_name_len);
  403. }
  404. GNUNET_MQ_send (h->mq, ev);
  405. ic = GNUNET_new (struct GNUNET_SENSOR_IterateContext);
  406. ic->h = h;
  407. ic->ev = ev;
  408. ic->request_sent = GNUNET_NO;
  409. ic->receiving = GNUNET_NO;
  410. ic->callback = callback;
  411. ic->callback_cls = callback_cls;
  412. ic->timeout_task =
  413. GNUNET_SCHEDULER_add_delayed (timeout, &signal_sensor_iteration_timeout,
  414. ic);
  415. GNUNET_MQ_notify_sent (ev, &iterate_request_sent, ic);
  416. GNUNET_CONTAINER_DLL_insert_tail (h->ic_head, h->ic_tail, ic);
  417. return ic;
  418. }
  419. /**
  420. * Callback from MQ when the request has already been sent to the service.
  421. * Now it can not be canelled.
  422. *
  423. * @param cls closure
  424. */
  425. static void
  426. force_anomaly_sent (void *cls)
  427. {
  428. struct GNUNET_SENSOR_ForceAnomalyContext *fa = cls;
  429. GNUNET_SENSOR_Continuation cont;
  430. void *cont_cls;
  431. fa->ev = NULL;
  432. cont = fa->cont;
  433. cont_cls = fa->cont_cls;
  434. GNUNET_SENSOR_force_anomaly_cancel (fa);
  435. if (NULL != cont)
  436. cont (cont_cls, NULL);
  437. }
  438. /**
  439. * Cancel a force anomaly request.
  440. *
  441. * @param fa Force anomaly context returned by GNUNET_SENSOR_force_anomaly()
  442. */
  443. void
  444. GNUNET_SENSOR_force_anomaly_cancel (struct GNUNET_SENSOR_ForceAnomalyContext
  445. *fa)
  446. {
  447. struct GNUNET_SENSOR_Handle *h = fa->h;
  448. if (NULL != fa->ev)
  449. {
  450. GNUNET_MQ_send_cancel (fa->ev);
  451. fa->ev = NULL;
  452. }
  453. GNUNET_CONTAINER_DLL_remove (h->fa_head, h->fa_tail, fa);
  454. GNUNET_free (fa);
  455. }
  456. /**
  457. * Force an anomaly status change on a given sensor. If the sensor reporting
  458. * module is running, this will trigger the usual reporting logic, therefore,
  459. * please only use this in a test environment.
  460. *
  461. * Also, if the sensor analysis module is running, it might conflict and cause
  462. * undefined behaviour if it detects a real anomaly.
  463. *
  464. * @param h Service handle
  465. * @param sensor_name Sensor name to set the anomaly status
  466. * @param anomalous The desired status: #GNUNET_YES / #GNUNET_NO
  467. * @param cont Continuation function to be called after the request is sent
  468. * @param cont_cls Closure for cont
  469. */
  470. struct GNUNET_SENSOR_ForceAnomalyContext *
  471. GNUNET_SENSOR_force_anomaly (struct GNUNET_SENSOR_Handle *h, char *sensor_name,
  472. int anomalous, GNUNET_SENSOR_Continuation cont,
  473. void *cont_cls)
  474. {
  475. struct ForceAnomalyMessage *msg;
  476. struct GNUNET_MQ_Envelope *ev;
  477. struct GNUNET_SENSOR_ForceAnomalyContext *fa;
  478. ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SENSOR_ANOMALY_FORCE);
  479. GNUNET_CRYPTO_hash (sensor_name, strlen (sensor_name) + 1,
  480. &msg->sensor_name_hash);
  481. msg->anomalous = htons (anomalous);
  482. GNUNET_MQ_send (h->mq, ev);
  483. fa = GNUNET_new (struct GNUNET_SENSOR_ForceAnomalyContext);
  484. fa->h = h;
  485. fa->cont = cont;
  486. fa->cont_cls = cont_cls;
  487. fa->ev = ev;
  488. GNUNET_CONTAINER_DLL_insert_tail (h->fa_head, h->fa_tail, fa);
  489. GNUNET_MQ_notify_sent (ev, &force_anomaly_sent, fa);
  490. return fa;
  491. }
  492. /* end of sensor_api.c */