namecache_api.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2010-2013, 2016 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 namecache/namecache_api.c
  18. * @brief API to access the NAMECACHE service
  19. * @author Martin Schanzenbach
  20. * @author Matthias Wachs
  21. * @author Christian Grothoff
  22. */
  23. #include "platform.h"
  24. #include "gnunet_util_lib.h"
  25. #include "gnunet_crypto_lib.h"
  26. #include "gnunet_constants.h"
  27. #include "gnunet_dnsparser_lib.h"
  28. #include "gnunet_gnsrecord_lib.h"
  29. #include "gnunet_signatures.h"
  30. #include "gnunet_namecache_service.h"
  31. #include "namecache.h"
  32. #define LOG(kind,...) GNUNET_log_from (kind, "namecache-api",__VA_ARGS__)
  33. /**
  34. * An QueueEntry used to store information for a pending
  35. * NAMECACHE record operation
  36. */
  37. struct GNUNET_NAMECACHE_QueueEntry
  38. {
  39. /**
  40. * Kept in a DLL.
  41. */
  42. struct GNUNET_NAMECACHE_QueueEntry *next;
  43. /**
  44. * Kept in a DLL.
  45. */
  46. struct GNUNET_NAMECACHE_QueueEntry *prev;
  47. /**
  48. * Main handle to access the namecache.
  49. */
  50. struct GNUNET_NAMECACHE_Handle *nsh;
  51. /**
  52. * Continuation to call
  53. */
  54. GNUNET_NAMECACHE_ContinuationWithStatus cont;
  55. /**
  56. * Closure for @e cont.
  57. */
  58. void *cont_cls;
  59. /**
  60. * Function to call with the blocks we get back; or NULL.
  61. */
  62. GNUNET_NAMECACHE_BlockProcessor block_proc;
  63. /**
  64. * Closure for @e block_proc.
  65. */
  66. void *block_proc_cls;
  67. /**
  68. * The operation id this zone iteration operation has
  69. */
  70. uint32_t op_id;
  71. };
  72. /**
  73. * Connection to the NAMECACHE service.
  74. */
  75. struct GNUNET_NAMECACHE_Handle
  76. {
  77. /**
  78. * Configuration to use.
  79. */
  80. const struct GNUNET_CONFIGURATION_Handle *cfg;
  81. /**
  82. * Message queue to service.
  83. */
  84. struct GNUNET_MQ_Handle *mq;
  85. /**
  86. * Currently pending transmission request (or NULL).
  87. */
  88. struct GNUNET_CLIENT_TransmitHandle *th;
  89. /**
  90. * Head of pending namecache queue entries
  91. */
  92. struct GNUNET_NAMECACHE_QueueEntry *op_head;
  93. /**
  94. * Tail of pending namecache queue entries
  95. */
  96. struct GNUNET_NAMECACHE_QueueEntry *op_tail;
  97. /**
  98. * Reconnect task
  99. */
  100. struct GNUNET_SCHEDULER_Task *reconnect_task;
  101. /**
  102. * Delay introduced before we reconnect.
  103. */
  104. struct GNUNET_TIME_Relative reconnect_delay;
  105. /**
  106. * Should we reconnect to service due to some serious error?
  107. */
  108. int reconnect;
  109. /**
  110. * The last operation id used for a NAMECACHE operation
  111. */
  112. uint32_t last_op_id_used;
  113. };
  114. /**
  115. * Disconnect from service and then reconnect.
  116. *
  117. * @param h our handle
  118. */
  119. static void
  120. force_reconnect (struct GNUNET_NAMECACHE_Handle *h);
  121. /**
  122. * Find queue entry for the given @a rid.
  123. *
  124. * @param h handle to search
  125. * @param rid request ID to look for
  126. * @return NULL if not found, otherwise the queue entry (removed from the queue)
  127. */
  128. static struct GNUNET_NAMECACHE_QueueEntry *
  129. find_qe (struct GNUNET_NAMECACHE_Handle *h,
  130. uint32_t rid)
  131. {
  132. struct GNUNET_NAMECACHE_QueueEntry *qe;
  133. for (qe = h->op_head; qe != NULL; qe = qe->next)
  134. {
  135. if (qe->op_id == rid)
  136. {
  137. GNUNET_CONTAINER_DLL_remove (h->op_head,
  138. h->op_tail,
  139. qe);
  140. return qe;
  141. }
  142. }
  143. return NULL;
  144. }
  145. /**
  146. * Handle an incoming message of type
  147. * #GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK_RESPONSE.
  148. *
  149. * @param cls the `struct GNUNET_NAMECACHE_Handle`
  150. * @param msg the message we received
  151. */
  152. static int
  153. check_lookup_block_response (void *cls,
  154. const struct LookupBlockResponseMessage *msg)
  155. {
  156. /* any length will do, format validation is in handler */
  157. return GNUNET_OK;
  158. }
  159. /**
  160. * Handle an incoming message of type
  161. * #GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK_RESPONSE.
  162. *
  163. * @param cls the `struct GNUNET_NAMECACHE_Handle`
  164. * @param msg the message we received
  165. */
  166. static void
  167. handle_lookup_block_response (void *cls,
  168. const struct LookupBlockResponseMessage *msg)
  169. {
  170. struct GNUNET_NAMECACHE_Handle *h = cls;
  171. size_t size;
  172. struct GNUNET_NAMECACHE_QueueEntry *qe;
  173. LOG (GNUNET_ERROR_TYPE_DEBUG,
  174. "Received LOOKUP_BLOCK_RESPONSE\n");
  175. qe = find_qe (h,
  176. ntohl (msg->gns_header.r_id));
  177. if (NULL == qe)
  178. return;
  179. if (0 == GNUNET_TIME_absolute_ntoh (msg->expire).abs_value_us)
  180. {
  181. /* no match found */
  182. if (NULL != qe->block_proc)
  183. qe->block_proc (qe->block_proc_cls,
  184. NULL);
  185. GNUNET_free (qe);
  186. return;
  187. }
  188. size = ntohs (msg->gns_header.header.size)
  189. - sizeof (struct LookupBlockResponseMessage);
  190. {
  191. char buf[size + sizeof (struct GNUNET_GNSRECORD_Block)] GNUNET_ALIGN;
  192. struct GNUNET_GNSRECORD_Block *block;
  193. block = (struct GNUNET_GNSRECORD_Block *) buf;
  194. block->signature = msg->signature;
  195. block->derived_key = msg->derived_key;
  196. block->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_GNS_RECORD_SIGN);
  197. block->purpose.size = htonl (size +
  198. sizeof (struct GNUNET_TIME_AbsoluteNBO) +
  199. sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose));
  200. block->expiration_time = msg->expire;
  201. GNUNET_memcpy (&block[1],
  202. &msg[1],
  203. size);
  204. if (GNUNET_OK !=
  205. GNUNET_GNSRECORD_block_verify (block))
  206. {
  207. GNUNET_break (0);
  208. if (NULL != qe->block_proc)
  209. qe->block_proc (qe->block_proc_cls,
  210. NULL);
  211. force_reconnect (h);
  212. }
  213. else
  214. {
  215. if (NULL != qe->block_proc)
  216. qe->block_proc (qe->block_proc_cls,
  217. block);
  218. }
  219. }
  220. GNUNET_free (qe);
  221. }
  222. /**
  223. * Handle an incoming message of type
  224. * #GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE_RESPONSE
  225. *
  226. * @param cls the `struct GNUNET_NAMECACHE_Handle`
  227. * @param msg the message we received
  228. * @param size the message size
  229. * @return #GNUNET_OK on success, #GNUNET_SYSERR on error and we did NOT notify the client
  230. */
  231. static void
  232. handle_block_cache_response (void *cls,
  233. const struct BlockCacheResponseMessage *msg)
  234. {
  235. struct GNUNET_NAMECACHE_Handle *h = cls;
  236. struct GNUNET_NAMECACHE_QueueEntry *qe;
  237. int res;
  238. LOG (GNUNET_ERROR_TYPE_DEBUG,
  239. "Received BLOCK_CACHE_RESPONSE\n");
  240. qe = find_qe (h,
  241. ntohl (msg->gns_header.r_id));
  242. if (NULL == qe)
  243. return;
  244. res = ntohl (msg->op_result);
  245. /* TODO: add actual error message from namecache to response... */
  246. if (NULL != qe->cont)
  247. qe->cont (qe->cont_cls,
  248. res,
  249. (GNUNET_OK == res)
  250. ? NULL
  251. : _("Namecache failed to cache block"));
  252. GNUNET_free (qe);
  253. }
  254. /**
  255. * Generic error handler, called with the appropriate error code and
  256. * the same closure specified at the creation of the message queue.
  257. * Not every message queue implementation supports an error handler.
  258. *
  259. * @param cls closure with the `struct GNUNET_NAMECACHE_Handle *`
  260. * @param error error code
  261. */
  262. static void
  263. mq_error_handler (void *cls,
  264. enum GNUNET_MQ_Error error)
  265. {
  266. struct GNUNET_NAMECACHE_Handle *h = cls;
  267. force_reconnect (h);
  268. }
  269. /**
  270. * Reconnect to namecache service.
  271. *
  272. * @param h the handle to the NAMECACHE service
  273. */
  274. static void
  275. reconnect (struct GNUNET_NAMECACHE_Handle *h)
  276. {
  277. struct GNUNET_MQ_MessageHandler handlers[] = {
  278. GNUNET_MQ_hd_var_size (lookup_block_response,
  279. GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK_RESPONSE,
  280. struct LookupBlockResponseMessage,
  281. h),
  282. GNUNET_MQ_hd_fixed_size (block_cache_response,
  283. GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE_RESPONSE,
  284. struct BlockCacheResponseMessage,
  285. h),
  286. GNUNET_MQ_handler_end ()
  287. };
  288. GNUNET_assert (NULL == h->mq);
  289. h->mq = GNUNET_CLIENT_connect (h->cfg,
  290. "namecache",
  291. handlers,
  292. &mq_error_handler,
  293. h);
  294. }
  295. /**
  296. * Re-establish the connection to the service.
  297. *
  298. * @param cls handle to use to re-connect.
  299. */
  300. static void
  301. reconnect_task (void *cls)
  302. {
  303. struct GNUNET_NAMECACHE_Handle *h = cls;
  304. h->reconnect_task = NULL;
  305. reconnect (h);
  306. }
  307. /**
  308. * Disconnect from service and then reconnect.
  309. *
  310. * @param h our handle
  311. */
  312. static void
  313. force_reconnect (struct GNUNET_NAMECACHE_Handle *h)
  314. {
  315. struct GNUNET_NAMECACHE_QueueEntry *qe;
  316. h->reconnect = GNUNET_NO;
  317. GNUNET_MQ_destroy (h->mq);
  318. h->mq = NULL;
  319. while (NULL != (qe = h->op_head))
  320. {
  321. GNUNET_CONTAINER_DLL_remove (h->op_head,
  322. h->op_tail,
  323. qe);
  324. if (NULL != qe->cont)
  325. qe->cont (qe->cont_cls,
  326. GNUNET_SYSERR,
  327. _("Error communicating with namecache service"));
  328. GNUNET_free (qe);
  329. }
  330. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  331. "Reconnecting to namecache\n");
  332. h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay);
  333. h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_delay,
  334. &reconnect_task,
  335. h);
  336. }
  337. /**
  338. * Get a fresh operation id to distinguish between namecache requests
  339. *
  340. * @param h the namecache handle
  341. * @return next operation id to use
  342. */
  343. static uint32_t
  344. get_op_id (struct GNUNET_NAMECACHE_Handle *h)
  345. {
  346. return h->last_op_id_used++;
  347. }
  348. /**
  349. * Initialize the connection with the NAMECACHE service.
  350. *
  351. * @param cfg configuration to use
  352. * @return handle to the GNS service, or NULL on error
  353. */
  354. struct GNUNET_NAMECACHE_Handle *
  355. GNUNET_NAMECACHE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
  356. {
  357. struct GNUNET_NAMECACHE_Handle *h;
  358. h = GNUNET_new (struct GNUNET_NAMECACHE_Handle);
  359. h->cfg = cfg;
  360. reconnect (h);
  361. if (NULL == h->mq)
  362. {
  363. GNUNET_free (h);
  364. return NULL;
  365. }
  366. return h;
  367. }
  368. /**
  369. * Disconnect from the namecache service (and free associated
  370. * resources).
  371. *
  372. * @param h handle to the namecache
  373. */
  374. void
  375. GNUNET_NAMECACHE_disconnect (struct GNUNET_NAMECACHE_Handle *h)
  376. {
  377. struct GNUNET_NAMECACHE_QueueEntry *q;
  378. GNUNET_break (NULL == h->op_head);
  379. while (NULL != (q = h->op_head))
  380. {
  381. GNUNET_CONTAINER_DLL_remove (h->op_head,
  382. h->op_tail,
  383. q);
  384. GNUNET_free (q);
  385. }
  386. if (NULL != h->mq)
  387. {
  388. GNUNET_MQ_destroy (h->mq);
  389. h->mq = NULL;
  390. }
  391. if (NULL != h->reconnect_task)
  392. {
  393. GNUNET_SCHEDULER_cancel (h->reconnect_task);
  394. h->reconnect_task = NULL;
  395. }
  396. GNUNET_free (h);
  397. }
  398. /**
  399. * Store an item in the namecache. If the item is already present,
  400. * it is replaced with the new record.
  401. *
  402. * @param h handle to the namecache
  403. * @param block block to store
  404. * @param cont continuation to call when done
  405. * @param cont_cls closure for @a cont
  406. * @return handle to abort the request, NULL on error
  407. */
  408. struct GNUNET_NAMECACHE_QueueEntry *
  409. GNUNET_NAMECACHE_block_cache (struct GNUNET_NAMECACHE_Handle *h,
  410. const struct GNUNET_GNSRECORD_Block *block,
  411. GNUNET_NAMECACHE_ContinuationWithStatus cont,
  412. void *cont_cls)
  413. {
  414. struct GNUNET_NAMECACHE_QueueEntry *qe;
  415. struct BlockCacheMessage *msg;
  416. struct GNUNET_MQ_Envelope *env;
  417. uint32_t rid;
  418. size_t blen;
  419. if (NULL == h->mq)
  420. return NULL;
  421. blen = ntohl (block->purpose.size);
  422. GNUNET_assert (blen > (sizeof (struct GNUNET_TIME_AbsoluteNBO) +
  423. sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose)));
  424. blen -= (sizeof (struct GNUNET_TIME_AbsoluteNBO) +
  425. sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose));
  426. rid = get_op_id (h);
  427. qe = GNUNET_new (struct GNUNET_NAMECACHE_QueueEntry);
  428. qe->nsh = h;
  429. qe->cont = cont;
  430. qe->cont_cls = cont_cls;
  431. qe->op_id = rid;
  432. GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
  433. h->op_tail,
  434. qe);
  435. /* send msg */
  436. env = GNUNET_MQ_msg_extra (msg,
  437. blen,
  438. GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE);
  439. msg->gns_header.r_id = htonl (rid);
  440. msg->expire = block->expiration_time;
  441. msg->signature = block->signature;
  442. msg->derived_key = block->derived_key;
  443. GNUNET_memcpy (&msg[1],
  444. &block[1],
  445. blen);
  446. GNUNET_MQ_send (h->mq,
  447. env);
  448. return qe;
  449. }
  450. /**
  451. * Get a result for a particular key from the namecache. The processor
  452. * will only be called once.
  453. *
  454. * @param h handle to the namecache
  455. * @param derived_hash hash of zone key combined with name to lookup
  456. * @param proc function to call on the matching block, or with
  457. * NULL if there is no matching block
  458. * @param proc_cls closure for @a proc
  459. * @return a handle that can be used to cancel, NULL on error
  460. */
  461. struct GNUNET_NAMECACHE_QueueEntry *
  462. GNUNET_NAMECACHE_lookup_block (struct GNUNET_NAMECACHE_Handle *h,
  463. const struct GNUNET_HashCode *derived_hash,
  464. GNUNET_NAMECACHE_BlockProcessor proc,
  465. void *proc_cls)
  466. {
  467. struct GNUNET_NAMECACHE_QueueEntry *qe;
  468. struct LookupBlockMessage *msg;
  469. struct GNUNET_MQ_Envelope *env;
  470. uint32_t rid;
  471. if (NULL == h->mq)
  472. return NULL;
  473. LOG (GNUNET_ERROR_TYPE_DEBUG,
  474. "Looking for block under %s\n",
  475. GNUNET_h2s (derived_hash));
  476. rid = get_op_id (h);
  477. qe = GNUNET_new (struct GNUNET_NAMECACHE_QueueEntry);
  478. qe->nsh = h;
  479. qe->block_proc = proc;
  480. qe->block_proc_cls = proc_cls;
  481. qe->op_id = rid;
  482. GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
  483. h->op_tail,
  484. qe);
  485. env = GNUNET_MQ_msg (msg,
  486. GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK);
  487. msg->gns_header.r_id = htonl (rid);
  488. msg->query = *derived_hash;
  489. GNUNET_MQ_send (h->mq,
  490. env);
  491. return qe;
  492. }
  493. /**
  494. * Cancel a namecache operation. The final callback from the
  495. * operation must not have been done yet.
  496. *
  497. * @param qe operation to cancel
  498. */
  499. void
  500. GNUNET_NAMECACHE_cancel (struct GNUNET_NAMECACHE_QueueEntry *qe)
  501. {
  502. struct GNUNET_NAMECACHE_Handle *h = qe->nsh;
  503. GNUNET_CONTAINER_DLL_remove (h->op_head,
  504. h->op_tail,
  505. qe);
  506. GNUNET_free(qe);
  507. }
  508. /* end of namecache_api.c */