plugin_rest_namestore.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2012-2015 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. * @author Martin Schanzenbach
  18. * @author Philippe Buschmann
  19. * @file namestore/plugin_rest_namestore.c
  20. * @brief GNUnet Namestore REST plugin
  21. */
  22. #include "platform.h"
  23. #include "gnunet_rest_plugin.h"
  24. #include "gnunet_gns_service.h"
  25. #include "gnunet_namestore_service.h"
  26. #include "gnunet_identity_service.h"
  27. #include "gnunet_rest_lib.h"
  28. #include "gnunet_json_lib.h"
  29. #include "microhttpd.h"
  30. #include <jansson.h>
  31. /**
  32. * Namestore Namespace
  33. */
  34. #define GNUNET_REST_API_NS_NAMESTORE "/namestore"
  35. /**
  36. * Error message Unknown Error
  37. */
  38. #define GNUNET_REST_NAMESTORE_ERROR_UNKNOWN "Unknown Error"
  39. /**
  40. * Error message No identity found
  41. */
  42. #define GNUNET_REST_IDENTITY_NOT_FOUND "No identity found"
  43. /**
  44. * Error message Failed request
  45. */
  46. #define GNUNET_REST_NAMESTORE_FAILED "Namestore action failed"
  47. /**
  48. * Error message invalid data
  49. */
  50. #define GNUNET_REST_NAMESTORE_INVALID_DATA "Data invalid"
  51. /**
  52. * Error message No data
  53. */
  54. #define GNUNET_REST_NAMESTORE_NO_DATA "No data"
  55. /**
  56. * State while collecting all egos
  57. */
  58. #define ID_REST_STATE_INIT 0
  59. /**
  60. * Done collecting egos
  61. */
  62. #define ID_REST_STATE_POST_INIT 1
  63. /**
  64. * The configuration handle
  65. */
  66. const struct GNUNET_CONFIGURATION_Handle *cfg;
  67. /**
  68. * HTTP methods allows for this plugin
  69. */
  70. static char *allow_methods;
  71. /**
  72. * @brief struct returned by the initialization function of the plugin
  73. */
  74. struct Plugin
  75. {
  76. const struct GNUNET_CONFIGURATION_Handle *cfg;
  77. };
  78. /**
  79. * The default namestore ego
  80. */
  81. struct EgoEntry
  82. {
  83. /**
  84. * DLL
  85. */
  86. struct EgoEntry *next;
  87. /**
  88. * DLL
  89. */
  90. struct EgoEntry *prev;
  91. /**
  92. * Ego Identifier
  93. */
  94. char *identifier;
  95. /**
  96. * Public key string
  97. */
  98. char *keystring;
  99. /**
  100. * The Ego
  101. */
  102. struct GNUNET_IDENTITY_Ego *ego;
  103. };
  104. /**
  105. * The request handle
  106. */
  107. struct RequestHandle
  108. {
  109. /**
  110. * Records to store
  111. */
  112. char *record_name;
  113. /**
  114. * Records to store
  115. */
  116. struct GNUNET_GNSRECORD_Data *rd;
  117. /**
  118. * Number of records in rd
  119. */
  120. unsigned int rd_count;
  121. /**
  122. * NAMESTORE Operation
  123. */
  124. struct GNUNET_NAMESTORE_QueueEntry *add_qe;
  125. /**
  126. * Response object
  127. */
  128. json_t *resp_object;
  129. /**
  130. * The processing state
  131. */
  132. int state;
  133. /**
  134. * Handle to NAMESTORE
  135. */
  136. struct GNUNET_NAMESTORE_Handle *ns_handle;
  137. /**
  138. * Handle to NAMESTORE it
  139. */
  140. struct GNUNET_NAMESTORE_ZoneIterator *list_it;
  141. /**
  142. * Private key for the zone
  143. */
  144. const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_pkey;
  145. /**
  146. * IDENTITY Operation
  147. */
  148. struct EgoEntry *ego_entry;
  149. /**
  150. * Ego list
  151. */
  152. struct EgoEntry *ego_head;
  153. /**
  154. * Ego list
  155. */
  156. struct EgoEntry *ego_tail;
  157. /**
  158. * IDENTITY Operation
  159. */
  160. struct GNUNET_IDENTITY_Operation *op;
  161. /**
  162. * Handle to Identity service.
  163. */
  164. struct GNUNET_IDENTITY_Handle *identity_handle;
  165. /**
  166. * Rest connection
  167. */
  168. struct GNUNET_REST_RequestHandle *rest_handle;
  169. /**
  170. * Desired timeout for the lookup (default is no timeout).
  171. */
  172. struct GNUNET_TIME_Relative timeout;
  173. /**
  174. * ID of a task associated with the resolution process.
  175. */
  176. struct GNUNET_SCHEDULER_Task *timeout_task;
  177. /**
  178. * The plugin result processor
  179. */
  180. GNUNET_REST_ResultProcessor proc;
  181. /**
  182. * The closure of the result processor
  183. */
  184. void *proc_cls;
  185. /**
  186. * The url
  187. */
  188. char *url;
  189. /**
  190. * Error response message
  191. */
  192. char *emsg;
  193. /**
  194. * Response code
  195. */
  196. int response_code;
  197. };
  198. /**
  199. * Cleanup lookup handle
  200. * @param handle Handle to clean up
  201. */
  202. static void
  203. cleanup_handle (void *cls)
  204. {
  205. struct RequestHandle *handle = cls;
  206. struct EgoEntry *ego_entry;
  207. struct EgoEntry *ego_tmp;
  208. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
  209. if (NULL != handle->timeout_task)
  210. {
  211. GNUNET_SCHEDULER_cancel (handle->timeout_task);
  212. handle->timeout_task = NULL;
  213. }
  214. if (NULL != handle->record_name)
  215. GNUNET_free (handle->record_name);
  216. if (NULL != handle->url)
  217. GNUNET_free (handle->url);
  218. if (NULL != handle->emsg)
  219. GNUNET_free (handle->emsg);
  220. if (NULL != handle->rd)
  221. {
  222. for (int i = 0; i < handle->rd_count; i++)
  223. {
  224. if (NULL != handle->rd[i].data)
  225. GNUNET_free ((void *) handle->rd[i].data);
  226. }
  227. GNUNET_free (handle->rd);
  228. }
  229. if (NULL != handle->timeout_task)
  230. GNUNET_SCHEDULER_cancel (handle->timeout_task);
  231. if (NULL != handle->list_it)
  232. GNUNET_NAMESTORE_zone_iteration_stop (handle->list_it);
  233. if (NULL != handle->add_qe)
  234. GNUNET_NAMESTORE_cancel (handle->add_qe);
  235. if (NULL != handle->identity_handle)
  236. GNUNET_IDENTITY_disconnect (handle->identity_handle);
  237. if (NULL != handle->ns_handle)
  238. {
  239. GNUNET_NAMESTORE_disconnect (handle->ns_handle);
  240. }
  241. for (ego_entry = handle->ego_head; NULL != ego_entry;)
  242. {
  243. ego_tmp = ego_entry;
  244. ego_entry = ego_entry->next;
  245. GNUNET_free (ego_tmp->identifier);
  246. GNUNET_free (ego_tmp->keystring);
  247. GNUNET_free (ego_tmp);
  248. }
  249. if (NULL != handle->resp_object)
  250. {
  251. json_decref (handle->resp_object);
  252. }
  253. GNUNET_free (handle);
  254. }
  255. /**
  256. * Task run on errors. Reports an error and cleans up everything.
  257. *
  258. * @param cls the `struct RequestHandle`
  259. */
  260. static void
  261. do_error (void *cls)
  262. {
  263. struct RequestHandle *handle = cls;
  264. struct MHD_Response *resp;
  265. json_t *json_error = json_object ();
  266. char *response;
  267. if (NULL == handle->emsg)
  268. handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_ERROR_UNKNOWN);
  269. json_object_set_new (json_error, "error", json_string (handle->emsg));
  270. if (0 == handle->response_code)
  271. handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
  272. response = json_dumps (json_error, 0);
  273. resp = GNUNET_REST_create_response (response);
  274. handle->proc (handle->proc_cls, resp, handle->response_code);
  275. json_decref (json_error);
  276. GNUNET_free (response);
  277. GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
  278. }
  279. /**
  280. * Get EgoEntry from list with either a public key or a name
  281. * If public key and name are not NULL, it returns the public key result first
  282. *
  283. * @param handle the RequestHandle
  284. * @param pubkey the public key of an identity (only one can be NULL)
  285. * @param name the name of an identity (only one can be NULL)
  286. * @return EgoEntry or NULL if not found
  287. */
  288. struct EgoEntry *
  289. get_egoentry_namestore (struct RequestHandle *handle, char *name)
  290. {
  291. struct EgoEntry *ego_entry;
  292. if (NULL != name)
  293. {
  294. for (ego_entry = handle->ego_head; NULL != ego_entry;
  295. ego_entry = ego_entry->next)
  296. {
  297. if (0 != strcasecmp (name, ego_entry->identifier))
  298. continue;
  299. return ego_entry;
  300. }
  301. }
  302. return NULL;
  303. }
  304. /**
  305. * Does internal server error when iteration failed.
  306. *
  307. * @param cls the `struct RequestHandle`
  308. */
  309. static void
  310. namestore_iteration_error (void *cls)
  311. {
  312. struct RequestHandle *handle = cls;
  313. handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED);
  314. GNUNET_SCHEDULER_add_now (&do_error, handle);
  315. return;
  316. }
  317. /**
  318. * Create finished callback
  319. *
  320. * @param cls the `struct RequestHandle`
  321. * @param success the success indicating integer, GNUNET_OK on success
  322. * @param emsg the error message (can be NULL)
  323. */
  324. static void
  325. create_finished (void *cls, int32_t success, const char *emsg)
  326. {
  327. struct RequestHandle *handle = cls;
  328. struct MHD_Response *resp;
  329. handle->add_qe = NULL;
  330. if (GNUNET_YES != success)
  331. {
  332. if (NULL != emsg)
  333. {
  334. handle->emsg = GNUNET_strdup (emsg);
  335. GNUNET_SCHEDULER_add_now (&do_error, handle);
  336. return;
  337. }
  338. handle->emsg = GNUNET_strdup ("Error storing records");
  339. GNUNET_SCHEDULER_add_now (&do_error, handle);
  340. return;
  341. }
  342. resp = GNUNET_REST_create_response (NULL);
  343. handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT);
  344. GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
  345. }
  346. /**
  347. * Delete finished callback
  348. *
  349. * @param cls the `struct RequestHandle`
  350. * @param success the success indicating integer, GNUNET_OK on success
  351. * @param emsg the error message (can be NULL)
  352. */
  353. static void
  354. del_finished (void *cls, int32_t success, const char *emsg)
  355. {
  356. struct RequestHandle *handle = cls;
  357. handle->add_qe = NULL;
  358. if (GNUNET_NO == success)
  359. {
  360. handle->response_code = MHD_HTTP_NOT_FOUND;
  361. handle->emsg = GNUNET_strdup ("No record found");
  362. GNUNET_SCHEDULER_add_now (&do_error, handle);
  363. return;
  364. }
  365. if (GNUNET_SYSERR == success)
  366. {
  367. if (NULL != emsg)
  368. {
  369. handle->emsg = GNUNET_strdup (emsg);
  370. GNUNET_SCHEDULER_add_now (&do_error, handle);
  371. return;
  372. }
  373. handle->emsg = GNUNET_strdup ("Deleting record failed");
  374. GNUNET_SCHEDULER_add_now (&do_error, handle);
  375. return;
  376. }
  377. handle->proc (handle->proc_cls,
  378. GNUNET_REST_create_response (NULL),
  379. MHD_HTTP_NO_CONTENT);
  380. GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
  381. }
  382. /**
  383. * Iteration over all results finished, build final
  384. * response.
  385. *
  386. * @param cls the `struct RequestHandle`
  387. */
  388. static void
  389. namestore_list_finished (void *cls)
  390. {
  391. struct RequestHandle *handle = cls;
  392. char *result_str;
  393. struct MHD_Response *resp;
  394. handle->list_it = NULL;
  395. if (NULL == handle->resp_object)
  396. handle->resp_object = json_array ();
  397. result_str = json_dumps (handle->resp_object, 0);
  398. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
  399. resp = GNUNET_REST_create_response (result_str);
  400. handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
  401. GNUNET_free_non_null (result_str);
  402. GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
  403. }
  404. /**
  405. * Create a response with requested records
  406. *
  407. * @param handle the RequestHandle
  408. */
  409. static void
  410. namestore_list_iteration (void *cls,
  411. const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
  412. const char *rname,
  413. unsigned int rd_len,
  414. const struct GNUNET_GNSRECORD_Data *rd)
  415. {
  416. struct RequestHandle *handle = cls;
  417. json_t *record_obj;
  418. if (NULL == handle->resp_object)
  419. handle->resp_object = json_array ();
  420. record_obj = GNUNET_JSON_from_gnsrecord (rname,
  421. rd,
  422. rd_len);
  423. json_array_append_new (handle->resp_object, record_obj);
  424. GNUNET_NAMESTORE_zone_iterator_next (handle->list_it, 1);
  425. }
  426. /**
  427. * Handle namestore GET request
  428. *
  429. * @param con_handle the connection handle
  430. * @param url the url
  431. * @param cls the RequestHandle
  432. */
  433. void
  434. namestore_get (struct GNUNET_REST_RequestHandle *con_handle,
  435. const char *url,
  436. void *cls)
  437. {
  438. struct RequestHandle *handle = cls;
  439. struct EgoEntry *ego_entry;
  440. char *egoname;
  441. egoname = NULL;
  442. ego_entry = NULL;
  443. // set zone to name if given
  444. if (strlen (GNUNET_REST_API_NS_NAMESTORE) < strlen (handle->url))
  445. {
  446. egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE) + 1];
  447. ego_entry = get_egoentry_namestore (handle, egoname);
  448. if (NULL == ego_entry)
  449. {
  450. handle->response_code = MHD_HTTP_NOT_FOUND;
  451. handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
  452. GNUNET_SCHEDULER_add_now (&do_error, handle);
  453. return;
  454. }
  455. }
  456. if (NULL != ego_entry)
  457. handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
  458. handle->list_it =
  459. GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle,
  460. handle->zone_pkey,
  461. &namestore_iteration_error,
  462. handle,
  463. &namestore_list_iteration,
  464. handle,
  465. &namestore_list_finished,
  466. handle);
  467. if (NULL == handle->list_it)
  468. {
  469. handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED);
  470. GNUNET_SCHEDULER_add_now (&do_error, handle);
  471. return;
  472. }
  473. }
  474. static void
  475. ns_lookup_error_cb (void *cls)
  476. {
  477. struct RequestHandle *handle = cls;
  478. handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED);
  479. GNUNET_SCHEDULER_add_now (&do_error, handle);
  480. }
  481. static void
  482. ns_lookup_cb (void *cls,
  483. const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
  484. const char *label,
  485. unsigned int rd_count,
  486. const struct GNUNET_GNSRECORD_Data *rd)
  487. {
  488. struct RequestHandle *handle = cls;
  489. struct GNUNET_GNSRECORD_Data rd_new[rd_count + handle->rd_count];
  490. for (int i = 0; i < rd_count; i++)
  491. rd_new[i] = rd[i];
  492. for (int j = 0; j < handle->rd_count; j++)
  493. rd_new[rd_count + j] = handle->rd[j];
  494. handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle,
  495. handle->zone_pkey,
  496. handle->record_name,
  497. rd_count + handle->rd_count,
  498. rd_new,
  499. &create_finished,
  500. handle);
  501. if (NULL == handle->add_qe)
  502. {
  503. handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED);
  504. GNUNET_SCHEDULER_add_now (&do_error, handle);
  505. return;
  506. }
  507. }
  508. /**
  509. * Handle namestore POST request
  510. *
  511. * @param con_handle the connection handle
  512. * @param url the url
  513. * @param cls the RequestHandle
  514. */
  515. void
  516. namestore_add (struct GNUNET_REST_RequestHandle *con_handle,
  517. const char *url,
  518. void *cls)
  519. {
  520. struct RequestHandle *handle = cls;
  521. struct EgoEntry *ego_entry;
  522. char *egoname;
  523. json_t *data_js;
  524. json_error_t err;
  525. char term_data[handle->rest_handle->data_size + 1];
  526. if (0 >= handle->rest_handle->data_size)
  527. {
  528. handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_NO_DATA);
  529. GNUNET_SCHEDULER_add_now (&do_error, handle);
  530. return;
  531. }
  532. term_data[handle->rest_handle->data_size] = '\0';
  533. GNUNET_memcpy (term_data,
  534. handle->rest_handle->data,
  535. handle->rest_handle->data_size);
  536. data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
  537. struct GNUNET_JSON_Specification gnsspec[] =
  538. {GNUNET_JSON_spec_gnsrecord (&handle->rd, &handle->rd_count, &handle->record_name), GNUNET_JSON_spec_end ()};
  539. if (GNUNET_OK != GNUNET_JSON_parse (data_js, gnsspec, NULL, NULL))
  540. {
  541. handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_INVALID_DATA);
  542. GNUNET_SCHEDULER_add_now (&do_error, handle);
  543. json_decref (data_js);
  544. return;
  545. }
  546. GNUNET_JSON_parse_free (gnsspec);
  547. if (0 >= strlen (handle->record_name))
  548. {
  549. handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_INVALID_DATA);
  550. GNUNET_SCHEDULER_add_now (&do_error, handle);
  551. json_decref (data_js);
  552. return;
  553. }
  554. json_decref (data_js);
  555. egoname = NULL;
  556. ego_entry = NULL;
  557. // set zone to name if given
  558. if (strlen (GNUNET_REST_API_NS_NAMESTORE) < strlen (handle->url))
  559. {
  560. egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE) + 1];
  561. ego_entry = get_egoentry_namestore (handle, egoname);
  562. if (NULL == ego_entry)
  563. {
  564. handle->response_code = MHD_HTTP_NOT_FOUND;
  565. handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
  566. GNUNET_SCHEDULER_add_now (&do_error, handle);
  567. return;
  568. }
  569. }
  570. if (NULL != ego_entry)
  571. handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
  572. handle->add_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle,
  573. handle->zone_pkey,
  574. handle->record_name,
  575. &ns_lookup_error_cb,
  576. handle,
  577. &ns_lookup_cb,
  578. handle);
  579. if (NULL == handle->add_qe)
  580. {
  581. handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED);
  582. GNUNET_SCHEDULER_add_now (&do_error, handle);
  583. return;
  584. }
  585. }
  586. /**
  587. * Handle namestore DELETE request
  588. *
  589. * @param con_handle the connection handle
  590. * @param url the url
  591. * @param cls the RequestHandle
  592. */
  593. void
  594. namestore_delete (struct GNUNET_REST_RequestHandle *con_handle,
  595. const char *url,
  596. void *cls)
  597. {
  598. struct RequestHandle *handle = cls;
  599. struct GNUNET_HashCode key;
  600. struct EgoEntry *ego_entry;
  601. char *egoname;
  602. egoname = NULL;
  603. ego_entry = NULL;
  604. // set zone to name if given
  605. if (strlen (GNUNET_REST_API_NS_NAMESTORE) < strlen (handle->url))
  606. {
  607. egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE) + 1];
  608. ego_entry = get_egoentry_namestore (handle, egoname);
  609. if (NULL == ego_entry)
  610. {
  611. handle->response_code = MHD_HTTP_NOT_FOUND;
  612. handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
  613. GNUNET_SCHEDULER_add_now (&do_error, handle);
  614. return;
  615. }
  616. }
  617. if (NULL != ego_entry)
  618. handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
  619. GNUNET_CRYPTO_hash ("record_name", strlen ("record_name"), &key);
  620. if (GNUNET_NO ==
  621. GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, &key))
  622. {
  623. handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_INVALID_DATA);
  624. GNUNET_SCHEDULER_add_now (&do_error, handle);
  625. return;
  626. }
  627. handle->record_name = GNUNET_strdup (
  628. GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, &key));
  629. handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle,
  630. handle->zone_pkey,
  631. handle->record_name,
  632. 0,
  633. NULL,
  634. &del_finished,
  635. handle);
  636. if (NULL == handle->add_qe)
  637. {
  638. handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED);
  639. GNUNET_SCHEDULER_add_now (&do_error, handle);
  640. return;
  641. }
  642. }
  643. /**
  644. * Respond to OPTIONS request
  645. *
  646. * @param con_handle the connection handle
  647. * @param url the url
  648. * @param cls the RequestHandle
  649. */
  650. static void
  651. options_cont (struct GNUNET_REST_RequestHandle *con_handle,
  652. const char *url,
  653. void *cls)
  654. {
  655. struct MHD_Response *resp;
  656. struct RequestHandle *handle = cls;
  657. // independent of path return all options
  658. resp = GNUNET_REST_create_response (NULL);
  659. MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
  660. handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
  661. GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
  662. return;
  663. }
  664. /**
  665. * Handle rest request
  666. *
  667. * @param handle the request handle
  668. */
  669. static void
  670. init_cont (struct RequestHandle *handle)
  671. {
  672. struct GNUNET_REST_RequestHandlerError err;
  673. static const struct GNUNET_REST_RequestHandler handlers[] =
  674. {{MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE, &namestore_get},
  675. {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE, &namestore_add},
  676. {MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_NAMESTORE, &namestore_delete},
  677. {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_NAMESTORE, &options_cont},
  678. GNUNET_REST_HANDLER_END};
  679. if (GNUNET_NO ==
  680. GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
  681. {
  682. handle->response_code = err.error_code;
  683. GNUNET_SCHEDULER_add_now (&do_error, handle);
  684. }
  685. }
  686. /**
  687. * This function is initially called for all egos and then again
  688. * whenever a ego's identifier changes or if it is deleted. At the
  689. * end of the initial pass over all egos, the function is once called
  690. * with 'NULL' for 'ego'. That does NOT mean that the callback won't
  691. * be invoked in the future or that there was an error.
  692. *
  693. * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get',
  694. * this function is only called ONCE, and 'NULL' being passed in
  695. * 'ego' does indicate an error (i.e. name is taken or no default
  696. * value is known). If 'ego' is non-NULL and if '*ctx'
  697. * is set in those callbacks, the value WILL be passed to a subsequent
  698. * call to the identity callback of 'GNUNET_IDENTITY_connect' (if
  699. * that one was not NULL).
  700. *
  701. * When an identity is renamed, this function is called with the
  702. * (known) ego but the NEW identifier.
  703. *
  704. * When an identity is deleted, this function is called with the
  705. * (known) ego and "NULL" for the 'identifier'. In this case,
  706. * the 'ego' is henceforth invalid (and the 'ctx' should also be
  707. * cleaned up).
  708. *
  709. * @param cls closure
  710. * @param ego ego handle
  711. * @param ctx context for application to store data for this ego
  712. * (during the lifetime of this process, initially NULL)
  713. * @param name identifier assigned by the user for this ego,
  714. * NULL if the user just deleted the ego and it
  715. * must thus no longer be used
  716. */
  717. static void
  718. id_connect_cb (void *cls,
  719. struct GNUNET_IDENTITY_Ego *ego,
  720. void **ctx,
  721. const char *name)
  722. {
  723. struct RequestHandle *handle = cls;
  724. struct EgoEntry *ego_entry;
  725. struct GNUNET_CRYPTO_EcdsaPublicKey pk;
  726. if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state))
  727. {
  728. handle->state = ID_REST_STATE_POST_INIT;
  729. init_cont (handle);
  730. return;
  731. }
  732. if (ID_REST_STATE_INIT == handle->state)
  733. {
  734. ego_entry = GNUNET_new (struct EgoEntry);
  735. GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
  736. ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
  737. ego_entry->ego = ego;
  738. GNUNET_asprintf (&ego_entry->identifier, "%s", name);
  739. GNUNET_CONTAINER_DLL_insert_tail (handle->ego_head,
  740. handle->ego_tail,
  741. ego_entry);
  742. }
  743. }
  744. /**
  745. * Function processing the REST call
  746. *
  747. * @param method HTTP method
  748. * @param url URL of the HTTP request
  749. * @param data body of the HTTP request (optional)
  750. * @param data_size length of the body
  751. * @param proc callback function for the result
  752. * @param proc_cls closure for callback function
  753. * @return GNUNET_OK if request accepted
  754. */
  755. static void
  756. rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
  757. GNUNET_REST_ResultProcessor proc,
  758. void *proc_cls)
  759. {
  760. struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
  761. handle->response_code = 0;
  762. handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
  763. handle->proc_cls = proc_cls;
  764. handle->proc = proc;
  765. handle->rest_handle = rest_handle;
  766. handle->zone_pkey = NULL;
  767. handle->url = GNUNET_strdup (rest_handle->url);
  768. if (handle->url[strlen (handle->url) - 1] == '/')
  769. handle->url[strlen (handle->url) - 1] = '\0';
  770. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
  771. handle->ns_handle = GNUNET_NAMESTORE_connect (cfg);
  772. handle->identity_handle =
  773. GNUNET_IDENTITY_connect (cfg, &id_connect_cb, handle);
  774. handle->timeout_task =
  775. GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_error, handle);
  776. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
  777. }
  778. /**
  779. * Entry point for the plugin.
  780. *
  781. * @param cls Config info
  782. * @return NULL on error, otherwise the plugin context
  783. */
  784. void *
  785. libgnunet_plugin_rest_namestore_init (void *cls)
  786. {
  787. static struct Plugin plugin;
  788. struct GNUNET_REST_Plugin *api;
  789. cfg = cls;
  790. if (NULL != plugin.cfg)
  791. return NULL; /* can only initialize once! */
  792. memset (&plugin, 0, sizeof (struct Plugin));
  793. plugin.cfg = cfg;
  794. api = GNUNET_new (struct GNUNET_REST_Plugin);
  795. api->cls = &plugin;
  796. api->name = GNUNET_REST_API_NS_NAMESTORE;
  797. api->process_request = &rest_process_request;
  798. GNUNET_asprintf (&allow_methods,
  799. "%s, %s, %s, %s, %s",
  800. MHD_HTTP_METHOD_GET,
  801. MHD_HTTP_METHOD_POST,
  802. MHD_HTTP_METHOD_PUT,
  803. MHD_HTTP_METHOD_DELETE,
  804. MHD_HTTP_METHOD_OPTIONS);
  805. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Namestore REST API initialized\n"));
  806. return api;
  807. }
  808. /**
  809. * Exit point from the plugin.
  810. *
  811. * @param cls the plugin context (as returned by "init")
  812. * @return always NULL
  813. */
  814. void *
  815. libgnunet_plugin_rest_namestore_done (void *cls)
  816. {
  817. struct GNUNET_REST_Plugin *api = cls;
  818. struct Plugin *plugin = api->cls;
  819. plugin->cfg = NULL;
  820. GNUNET_free_non_null (allow_methods);
  821. GNUNET_free (api);
  822. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Namestore REST plugin is finished\n");
  823. return NULL;
  824. }
  825. /* end of plugin_rest_namestore.c */