namestore_api_monitor.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2013, 2016, 2018 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your 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. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file namestore/namestore_api_monitor.c
  18. * @brief API to monitor changes in the NAMESTORE
  19. * @author Christian Grothoff
  20. */
  21. #include "platform.h"
  22. #include "gnunet_util_lib.h"
  23. #include "gnunet_crypto_lib.h"
  24. #include "gnunet_constants.h"
  25. #include "gnunet_dnsparser_lib.h"
  26. #include "gnunet_arm_service.h"
  27. #include "gnunet_signatures.h"
  28. #include "gnunet_namestore_service.h"
  29. #include "namestore.h"
  30. /**
  31. * Handle for a monitoring activity.
  32. */
  33. struct GNUNET_NAMESTORE_ZoneMonitor
  34. {
  35. /**
  36. * Configuration (to reconnect).
  37. */
  38. const struct GNUNET_CONFIGURATION_Handle *cfg;
  39. /**
  40. * Handle to namestore service.
  41. */
  42. struct GNUNET_MQ_Handle *mq;
  43. /**
  44. * Function to call on errors.
  45. */
  46. GNUNET_SCHEDULER_TaskCallback error_cb;
  47. /**
  48. * Closure for @e error_cb.
  49. */
  50. void *error_cb_cls;
  51. /**
  52. * Function to call on events.
  53. */
  54. GNUNET_NAMESTORE_RecordMonitor monitor;
  55. /**
  56. * Closure for @e monitor.
  57. */
  58. void *monitor_cls;
  59. /**
  60. * Function called when we've synchronized.
  61. */
  62. GNUNET_SCHEDULER_TaskCallback sync_cb;
  63. /**
  64. * Closure for @e sync_cb.
  65. */
  66. void *sync_cb_cls;
  67. /**
  68. * Monitored zone.
  69. */
  70. struct GNUNET_CRYPTO_EcdsaPrivateKey zone;
  71. /**
  72. * Do we first iterate over all existing records?
  73. */
  74. int iterate_first;
  75. };
  76. /**
  77. * Reconnect to the namestore service.
  78. *
  79. * @param zm monitor to reconnect
  80. */
  81. static void
  82. reconnect (struct GNUNET_NAMESTORE_ZoneMonitor *zm);
  83. /**
  84. * Handle SYNC message from the namestore service.
  85. *
  86. * @param cls the monitor
  87. * @param msg the sync message
  88. */
  89. static void
  90. handle_sync (void *cls,
  91. const struct GNUNET_MessageHeader *msg)
  92. {
  93. struct GNUNET_NAMESTORE_ZoneMonitor *zm = cls;
  94. (void) cls;
  95. (void) msg;
  96. if (NULL != zm->sync_cb)
  97. zm->sync_cb (zm->sync_cb_cls);
  98. }
  99. /**
  100. * We've received a notification about a change to our zone.
  101. * Check that it is well-formed.
  102. *
  103. * @param cls the zone monitor handle
  104. * @param lrm the message from the service.
  105. */
  106. static int
  107. check_result (void *cls,
  108. const struct RecordResultMessage *lrm)
  109. {
  110. static struct GNUNET_CRYPTO_EcdsaPrivateKey zero;
  111. struct GNUNET_NAMESTORE_ZoneMonitor *zm = cls;
  112. size_t lrm_len;
  113. size_t exp_lrm_len;
  114. size_t name_len;
  115. size_t rd_len;
  116. unsigned rd_count;
  117. const char *name_tmp;
  118. const char *rd_ser_tmp;
  119. (void) cls;
  120. if ( (0 != memcmp (&lrm->private_key,
  121. &zm->zone,
  122. sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) &&
  123. (0 != memcmp (&zero,
  124. &zm->zone,
  125. sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) )
  126. {
  127. GNUNET_break (0);
  128. return GNUNET_SYSERR;
  129. }
  130. lrm_len = ntohs (lrm->gns_header.header.size);
  131. rd_len = ntohs (lrm->rd_len);
  132. rd_count = ntohs (lrm->rd_count);
  133. name_len = ntohs (lrm->name_len);
  134. if (name_len > MAX_NAME_LEN)
  135. {
  136. GNUNET_break (0);
  137. return GNUNET_SYSERR;
  138. }
  139. exp_lrm_len = sizeof (struct RecordResultMessage) + name_len + rd_len;
  140. if (lrm_len != exp_lrm_len)
  141. {
  142. GNUNET_break (0);
  143. return GNUNET_SYSERR;
  144. }
  145. if (0 == name_len)
  146. {
  147. GNUNET_break (0);
  148. return GNUNET_SYSERR;
  149. }
  150. name_tmp = (const char *) &lrm[1];
  151. if (name_tmp[name_len -1] != '\0')
  152. {
  153. GNUNET_break (0);
  154. return GNUNET_SYSERR;
  155. }
  156. rd_ser_tmp = (const char *) &name_tmp[name_len];
  157. {
  158. struct GNUNET_GNSRECORD_Data rd[rd_count];
  159. if (GNUNET_OK !=
  160. GNUNET_GNSRECORD_records_deserialize (rd_len,
  161. rd_ser_tmp,
  162. rd_count,
  163. rd))
  164. {
  165. GNUNET_break (0);
  166. return GNUNET_SYSERR;
  167. }
  168. }
  169. return GNUNET_OK;
  170. }
  171. /**
  172. * We've received a notification about a change to our zone.
  173. * Forward to monitor callback.
  174. *
  175. * @param cls the zone monitor handle
  176. * @param lrm the message from the service.
  177. */
  178. static void
  179. handle_result (void *cls,
  180. const struct RecordResultMessage *lrm)
  181. {
  182. struct GNUNET_NAMESTORE_ZoneMonitor *zm = cls;
  183. size_t name_len;
  184. size_t rd_len;
  185. unsigned rd_count;
  186. const char *name_tmp;
  187. const char *rd_ser_tmp;
  188. rd_len = ntohs (lrm->rd_len);
  189. rd_count = ntohs (lrm->rd_count);
  190. name_len = ntohs (lrm->name_len);
  191. name_tmp = (const char *) &lrm[1];
  192. rd_ser_tmp = (const char *) &name_tmp[name_len];
  193. {
  194. struct GNUNET_GNSRECORD_Data rd[rd_count];
  195. GNUNET_assert (GNUNET_OK ==
  196. GNUNET_GNSRECORD_records_deserialize (rd_len,
  197. rd_ser_tmp,
  198. rd_count,
  199. rd));
  200. zm->monitor (zm->monitor_cls,
  201. &lrm->private_key,
  202. name_tmp,
  203. rd_count,
  204. rd);
  205. }
  206. }
  207. /**
  208. * Generic error handler, called with the appropriate error code and
  209. * the same closure specified at the creation of the message queue.
  210. * Not every message queue implementation supports an error handler.
  211. *
  212. * @param cls closure with the `struct GNUNET_NAMESTORE_ZoneMonitor *`
  213. * @param error error code
  214. */
  215. static void
  216. mq_error_handler (void *cls,
  217. enum GNUNET_MQ_Error error)
  218. {
  219. struct GNUNET_NAMESTORE_ZoneMonitor *zm = cls;
  220. (void) error;
  221. reconnect (zm);
  222. }
  223. /**
  224. * Reconnect to the namestore service.
  225. *
  226. * @param zm monitor to reconnect
  227. */
  228. static void
  229. reconnect (struct GNUNET_NAMESTORE_ZoneMonitor *zm)
  230. {
  231. struct GNUNET_MQ_MessageHandler handlers[] = {
  232. GNUNET_MQ_hd_fixed_size (sync,
  233. GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_SYNC,
  234. struct GNUNET_MessageHeader,
  235. zm),
  236. GNUNET_MQ_hd_var_size (result,
  237. GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT,
  238. struct RecordResultMessage,
  239. zm),
  240. GNUNET_MQ_handler_end ()
  241. };
  242. struct GNUNET_MQ_Envelope *env;
  243. struct ZoneMonitorStartMessage *sm;
  244. if (NULL != zm->mq)
  245. {
  246. GNUNET_MQ_destroy (zm->mq);
  247. zm->error_cb (zm->error_cb_cls);
  248. }
  249. zm->mq = GNUNET_CLIENT_connect (zm->cfg,
  250. "namestore",
  251. handlers,
  252. &mq_error_handler,
  253. zm);
  254. if (NULL == zm->mq)
  255. return;
  256. env = GNUNET_MQ_msg (sm,
  257. GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START);
  258. sm->iterate_first = htonl (zm->iterate_first);
  259. sm->zone = zm->zone;
  260. GNUNET_MQ_send (zm->mq,
  261. env);
  262. }
  263. /**
  264. * Begin monitoring a zone for changes. If @a iterate_first is set,
  265. * we Will first call the @a monitor function on all existing records
  266. * in the selected zone(s). In any case, we will call @a sync and
  267. * afterwards call @a monitor whenever a record changes.
  268. *
  269. * @param cfg configuration to use to connect to namestore
  270. * @param zone zone to monitor
  271. * @param iterate_first #GNUNET_YES to first iterate over all existing records,
  272. * #GNUNET_NO to only return changes that happen from now on
  273. * @param error_cb function to call on error (i.e. disconnect); note that
  274. * unlike the other error callbacks in this API, a call to this
  275. * function does NOT destroy the monitor handle, it merely signals
  276. * that monitoring is down. You need to still explicitly call
  277. * #GNUNET_NAMESTORE_zone_monitor_stop().
  278. * @param error_cb_cls closure for @a error_cb
  279. * @param monitor function to call on zone changes
  280. * @param monitor_cls closure for @a monitor
  281. * @param sync_cb function called when we're in sync with the namestore
  282. * @param cls closure for @a sync_cb
  283. * @return handle to stop monitoring
  284. */
  285. struct GNUNET_NAMESTORE_ZoneMonitor *
  286. GNUNET_NAMESTORE_zone_monitor_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
  287. const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
  288. int iterate_first,
  289. GNUNET_SCHEDULER_TaskCallback error_cb,
  290. void *error_cb_cls,
  291. GNUNET_NAMESTORE_RecordMonitor monitor,
  292. void *monitor_cls,
  293. GNUNET_SCHEDULER_TaskCallback sync_cb,
  294. void *sync_cb_cls)
  295. {
  296. struct GNUNET_NAMESTORE_ZoneMonitor *zm;
  297. zm = GNUNET_new (struct GNUNET_NAMESTORE_ZoneMonitor);
  298. if (NULL != zone)
  299. zm->zone = *zone;
  300. zm->iterate_first = iterate_first;
  301. zm->error_cb = error_cb;
  302. zm->error_cb_cls = error_cb_cls;
  303. zm->monitor = monitor;
  304. zm->monitor_cls = monitor_cls;
  305. zm->sync_cb = sync_cb;
  306. zm->sync_cb_cls = sync_cb_cls;
  307. zm->cfg = cfg;
  308. reconnect (zm);
  309. if (NULL == zm->mq)
  310. {
  311. GNUNET_free (zm);
  312. return NULL;
  313. }
  314. return zm;
  315. }
  316. /**
  317. * Calls the monitor processor specified in #GNUNET_NAMESTORE_zone_monitor_start
  318. * for the next record(s). This function is used to allow clients that merely
  319. * monitor the NAMESTORE to still throttle namestore operations, so we can be
  320. * sure that the monitors can keep up.
  321. *
  322. * Note that #GNUNET_NAMESTORE_records_store() only waits for this
  323. * call if the previous limit set by the client was already reached.
  324. * Thus, by using a @a limit greater than 1, monitors basically enable
  325. * a queue of notifications to be processed asynchronously with some
  326. * delay. Note that even with a limit of 1 the
  327. * #GNUNET_NAMESTORE_records_store() function will run asynchronously
  328. * and the continuation may be invoked before the monitors completed
  329. * (or even started) processing the notification. Thus, monitors will
  330. * only closely track the current state of the namestore, but not
  331. * be involved in the transactions.
  332. *
  333. * @param zm the monitor
  334. * @param limit number of records to return to the iterator in one shot
  335. * (before #GNUNET_NAMESTORE_zone_monitor_next is to be called again)
  336. */
  337. void
  338. GNUNET_NAMESTORE_zone_monitor_next (struct GNUNET_NAMESTORE_ZoneMonitor *zm,
  339. uint64_t limit)
  340. {
  341. struct GNUNET_MQ_Envelope *env;
  342. struct ZoneMonitorNextMessage *nm;
  343. env = GNUNET_MQ_msg (nm,
  344. GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT);
  345. nm->limit = GNUNET_htonll (limit);
  346. GNUNET_MQ_send (zm->mq,
  347. env);
  348. }
  349. /**
  350. * Stop monitoring a zone for changes.
  351. *
  352. * @param zm handle to the monitor activity to stop
  353. */
  354. void
  355. GNUNET_NAMESTORE_zone_monitor_stop (struct GNUNET_NAMESTORE_ZoneMonitor *zm)
  356. {
  357. if (NULL != zm->mq)
  358. {
  359. GNUNET_MQ_destroy (zm->mq);
  360. zm->mq = NULL;
  361. }
  362. GNUNET_free (zm);
  363. }
  364. /* end of namestore_api_monitor.c */