GNUnet 0.21.1
namestore_plugin.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2015 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
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 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
27#include "platform.h"
28#include "gnunet_error_codes.h"
29#include "gnunet_rest_plugin.h"
32#include "gnunet_rest_lib.h"
34#include "microhttpd.h"
35#include <jansson.h>
36
40#define GNUNET_REST_API_NS_NAMESTORE "/namestore"
41
45#define GNUNET_REST_API_NS_NAMESTORE_IMPORT "/namestore/import"
46
50#define ID_REST_STATE_INIT 0
51
55#define ID_REST_STATE_POST_INIT 1
60
64static char *allow_methods;
65
69static struct EgoEntry *ego_head;
70
74static struct EgoEntry *ego_tail;
75
79static int state;
80
85
90
94struct Plugin
95{
96 const struct GNUNET_CONFIGURATION_Handle *cfg;
97};
98
102struct EgoEntry
103{
107 struct EgoEntry *next;
108
112 struct EgoEntry *prev;
113
117 char *identifier;
118
122 char *keystring;
123
127 struct GNUNET_IDENTITY_Ego *ego;
128};
129
130
132{
136
140struct RequestHandle
141{
145 struct RequestHandle *next;
146
150 struct RequestHandle *prev;
151
156
160 uint32_t record_type;
161
166
171
175 unsigned int rd_count;
176
181
185 unsigned int rd_set_count;
186
190 unsigned int rd_set_pos;
191
196
201
205 json_t *resp_object;
206
207
212
217
222
227
232
237
242
247
251 void *proc_cls;
252
256 char *url;
257
261 enum GNUNET_ErrorCode ec;
262
263};
264
269
274
275
280static void
281cleanup_handle (void *cls)
282{
283 struct RequestHandle *handle = cls;
284
285 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
286 if (NULL != handle->timeout_task)
287 {
288 GNUNET_SCHEDULER_cancel (handle->timeout_task);
289 handle->timeout_task = NULL;
290 }
291 if (NULL != handle->record_name)
292 GNUNET_free (handle->record_name);
293 if (NULL != handle->url)
294 GNUNET_free (handle->url);
295 if (NULL != handle->rd)
296 {
297 for (int i = 0; i < handle->rd_count; i++)
298 {
299 if (NULL != handle->rd[i].data)
300 GNUNET_free_nz ((void *) handle->rd[i].data);
301 }
302 GNUNET_free (handle->rd);
303 }
304 if (NULL != handle->timeout_task)
305 GNUNET_SCHEDULER_cancel (handle->timeout_task);
306 if (NULL != handle->list_it)
308 if (NULL != handle->ns_qe)
310 if (NULL != handle->nc)
312 if (NULL != handle->resp_object)
313 {
314 json_decref (handle->resp_object);
315 }
318 handle);
320}
321
322
328static void
329do_error (void *cls)
330{
331 struct RequestHandle *handle = cls;
332 struct MHD_Response *resp;
333 json_t *json_error = json_object ();
334 char *response;
335 const char*emsg;
336 int response_code;
337
339 json_object_set_new (json_error, "error", json_string (emsg));
340 json_object_set_new (json_error, "error_code", json_integer (handle->ec));
341 response_code = GNUNET_ErrorCode_get_http_status (handle->ec);
342 if (0 == response_code)
343 response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
344 response = json_dumps (json_error, 0);
346 GNUNET_assert (MHD_YES ==
347 MHD_add_response_header (resp, "Content-Type",
348 "application/json"));
349 handle->proc (handle->proc_cls, resp, response_code);
350 json_decref (json_error);
353}
354
355
365struct EgoEntry *
367{
368 struct EgoEntry *ego_entry;
369 char *copy = GNUNET_strdup (name);
370 char *tmp;
371
372 if (NULL == name)
373 return NULL;
374 tmp = strtok (copy, "/");
375 if (NULL == tmp)
376 return NULL;
377 for (ego_entry = ego_head; NULL != ego_entry;
378 ego_entry = ego_entry->next)
379 {
380 if (0 != strcasecmp (tmp, ego_entry->identifier))
381 continue;
382 GNUNET_free (copy);
383 return ego_entry;
384 }
385 GNUNET_free (copy);
386 return NULL;
387}
388
389
395static void
397{
398 struct RequestHandle *handle = cls;
399
402 return;
403}
404
405
406static void
408{
409 struct RequestHandle *handle = cls;
410 struct MHD_Response *resp;
411
412 handle->ns_qe = NULL;
413 handle->ec = ec;
414 if (GNUNET_EC_NONE != ec)
415 {
417 return;
418 }
419 resp = GNUNET_REST_create_response (NULL);
420 handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT);
422}
423
424
425static void
426del_finished (void *cls, enum GNUNET_ErrorCode ec)
427{
428 struct RequestHandle *handle = cls;
429
430 handle->ns_qe = NULL;
431 handle->ec = ec;
432 if (GNUNET_EC_NONE != ec)
433 {
435 return;
436 }
437 handle->proc (handle->proc_cls,
441}
442
443
450static void
452{
453 struct RequestHandle *handle = cls;
454 char *result_str;
455 struct MHD_Response *resp;
456
457 handle->list_it = NULL;
458
459 if (NULL == handle->resp_object)
460 {
463 return;
464 }
465 result_str = json_dumps (handle->resp_object, 0);
466 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
467 resp = GNUNET_REST_create_response (result_str);
468 GNUNET_assert (MHD_YES ==
469 MHD_add_response_header (resp, "Content-Type",
470 "application/json"));
471 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
472 GNUNET_free (result_str);
474}
475
476
482static void
484 const struct GNUNET_CRYPTO_PrivateKey *zone_key,
485 const char *rname,
486 unsigned int rd_len,
487 const struct GNUNET_GNSRECORD_Data *rd,
488 struct GNUNET_TIME_Absolute expiry)
489{
490 struct RequestHandle *handle = cls;
491 struct GNUNET_GNSRECORD_Data rd_filtered[rd_len];
492 json_t *record_obj;
493 int i = 0;
494 int j = 0;
495
496 if (rd_len == 0)
497 {
500 return;
501 }
502
503 for (i = 0; i < rd_len; i++)
504 {
505 if ((GNUNET_GNSRECORD_TYPE_ANY != handle->record_type) &&
506 (rd[i].record_type != handle->record_type))
507 continue; /* Apply filter */
508 rd_filtered[j] = rd[i];
509 rd_filtered[j].data = rd[i].data;
510 j++;
511 }
513 if (j > 0)
514 {
515 if (NULL == handle->resp_object)
516 handle->resp_object = json_array ();
517 record_obj = GNUNET_GNSRECORD_JSON_from_gnsrecord (rname,
518 rd_filtered,
519 j);
520 json_array_append_new (handle->resp_object, record_obj);
521 }
523}
524
525
531static void
533{
534 struct RequestHandle *handle = cls;
535
538}
539
540
541static void
543 const struct GNUNET_CRYPTO_PrivateKey *zone,
544 const char *label,
545 unsigned int rd_len,
546 const struct GNUNET_GNSRECORD_Data *rd)
547{
548 struct RequestHandle *handle = cls;
549 struct GNUNET_GNSRECORD_Data rd_filtered[rd_len];
550 int i = 0;
551 int j = 0;
552
553 handle->ns_qe = NULL;
554 for (i = 0; i < rd_len; i++)
555 {
556 if ((GNUNET_GNSRECORD_TYPE_ANY != handle->record_type) &&
557 (rd[i].record_type != handle->record_type))
558 continue; /* Apply filter */
559 rd_filtered[j] = rd[i];
560 rd_filtered[j].data = rd[i].data;
561 j++;
562 }
564 if (j == 0)
565 {
568 return;
569 }
570 handle->resp_object = GNUNET_GNSRECORD_JSON_from_gnsrecord (label,
571 rd_filtered,
572 j);
574}
575
576
584void
586 const char *url,
587 void *cls)
588{
589 struct RequestHandle *handle = cls;
590 struct EgoEntry *ego_entry;
591 struct GNUNET_HashCode key;
592 enum GNUNET_GNSRECORD_Filter filter_flags;
593 char *egoname;
594 char *labelname;
595 char *typename;
596 char *boolstring;
597
598 egoname = NULL;
599 ego_entry = NULL;
600
601 // set zone to name if given
602 if (strlen (GNUNET_REST_API_NS_NAMESTORE) + 1 >= strlen (handle->url))
603 {
606 return;
607 }
608 egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE) + 1];
610 if (NULL == ego_entry)
611 {
614 return;
615 }
616 handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
617
618 GNUNET_CRYPTO_hash ("record_type", strlen ("record_type"), &key);
619 handle->record_type = GNUNET_GNSRECORD_TYPE_ANY;
620 if (GNUNET_YES ==
622 {
623 typename = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map,
624 &key);
625 if (NULL != typename)
626 handle->record_type = GNUNET_GNSRECORD_typename_to_number (typename);
627 }
628 GNUNET_CRYPTO_hash ("omit_private", strlen ("omit_private"), &key);
629 filter_flags = GNUNET_GNSRECORD_FILTER_NONE;
630 if (GNUNET_YES ==
632 {
633 boolstring = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map,
634 &key);
635 if ((0 == strcmp (boolstring, "1")) ||
636 (0 == strcmp (boolstring, "yes")) ||
637 (0 == strcmp (boolstring, "true")))
639 }
640 GNUNET_CRYPTO_hash ("include_maintenance", strlen ("include_maintenance"),
641 &key);
642 if (GNUNET_YES ==
644 {
645 boolstring = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map,
646 &key);
647 if ((0 == strcmp (boolstring, "1")) ||
648 (0 == strcmp (boolstring, "yes")) ||
649 (0 == strcmp (boolstring, "true")))
651 }
652 labelname = &egoname[strlen (ego_entry->identifier)];
653 if (1 >= strlen (labelname))
654 {
655 /* Iterate over all records */
656 handle->list_it =
658 handle->zone_pkey,
660 handle,
662 handle,
664 handle,
665 filter_flags);
666 if (NULL == handle->list_it)
667 {
670 return;
671 }
672 return;
673 }
674 handle->record_name = GNUNET_strdup (labelname + 1);
676 handle->zone_pkey,
677 handle->record_name,
679 handle,
681 handle,
682 filter_flags);
683 if (NULL == handle->ns_qe)
684 {
687 return;
688 }
689}
690
691
692static void
693ns_lookup_cb (void *cls,
694 const struct GNUNET_CRYPTO_PrivateKey *zone,
695 const char *label,
696 unsigned int rd_count,
697 const struct GNUNET_GNSRECORD_Data *rd)
698{
699 struct RequestHandle *handle = cls;
701 int i = 0;
702 int j = 0;
703
704 if (UPDATE_STRATEGY_APPEND == handle->update_strategy)
705 {
706 for (i = 0; i < rd_count; i++)
707 rd_new[i] = rd[i];
708 }
709 for (j = 0; j < handle->rd_count; j++)
710 rd_new[i + j] = handle->rd[j];
712 handle->zone_pkey,
713 handle->record_name,
714 i + j,
715 rd_new,
717 handle);
718 if (NULL == handle->ns_qe)
719 {
722 return;
723 }
724}
725
726
727static void
729{
730 struct RequestHandle *handle = cls;
731
733 "Import finished (%d)\n", ec);
734 handle->ns_qe = NULL;
735 handle->ec = ec;
736 if (GNUNET_EC_NONE != ec)
737 {
739 return;
740 }
741 unsigned int remaining = handle->rd_set_count - handle->rd_set_pos;
742 if (0 == remaining)
743 {
744 struct MHD_Response *resp;
745
746 handle->ns_qe = NULL;
748 "Commit finished (%d)\n", ec);
749 handle->ec = ec;
750 if (GNUNET_EC_NONE != ec)
751 {
753 return;
754 }
755 resp = GNUNET_REST_create_response (NULL);
756 handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT);
758 return;
759 }
760 unsigned int sent_rds = 0;
761 // Find the smallest set of records we can send with our message size
762 // restriction of 16 bit
764 handle->zone_pkey,
765 remaining,
766 &handle->ri[handle->
767 rd_set_pos],
768 &sent_rds,
770 handle);
771 if ((NULL == handle->ns_qe) && (0 == sent_rds))
772 {
775 return;
776 }
777 handle->rd_set_pos += sent_rds;
778}
779
780
781static void
783{
784 json_t *data_js;
785 json_error_t err;
786
788 "Transaction started...\n");
789 if (0 >= handle->rest_handle->data_size)
790 {
793 return;
794 }
795 char term_data[handle->rest_handle->data_size + 1];
796 term_data[handle->rest_handle->data_size] = '\0';
797 GNUNET_memcpy (term_data,
798 handle->rest_handle->data,
799 handle->rest_handle->data_size);
800 data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
801 if (NULL == data_js)
802 {
805 "Error parsing data: %s", err.text);
807 return;
808 }
809 if (! json_is_array (data_js))
810 {
813 json_decref (data_js);
814 return;
815 }
816 handle->rd_set_count = json_array_size (data_js);
817 handle->ri = GNUNET_malloc (handle->rd_set_count
818 * sizeof (struct GNUNET_NAMESTORE_RecordInfo));
820 "Got record set of size %d\n", handle->rd_set_count);
821 char *albl;
822 size_t index;
823 json_t *value;
824 json_array_foreach (data_js, index, value) {
825 {
827 struct GNUNET_JSON_Specification gnsspec[] =
829 &handle->ri[index].a_rd_count,
830 &albl),
832 if (GNUNET_OK != GNUNET_JSON_parse (value, gnsspec, NULL, NULL))
833 {
836 json_decref (data_js);
837 return;
838 }
839 handle->ri[index].a_rd = rd;
840 handle->ri[index].a_label = albl;
842 "Parsed record set for name %s\n",
843 handle->ri[index].a_label);
844 }
845 }
846 // json_decref (data_js);
847
848 unsigned int sent_rds = 0;
849 // Find the smallest set of records we can send with our message size
850 // restriction of 16 bit
852 handle->zone_pkey,
853 handle->rd_set_count,
854 handle->ri,
855 &sent_rds,
857 handle);
858 if ((NULL == handle->ns_qe) && (0 == sent_rds))
859 {
862 return;
863 }
864 handle->rd_set_pos += sent_rds;
865}
866
867
875void
877 const char *url,
878 void *cls)
879{
880 struct RequestHandle *handle = cls;
881 struct EgoEntry *ego_entry;
882 char *egoname;
883
884 // set zone to name if given
885 if (strlen (GNUNET_REST_API_NS_NAMESTORE_IMPORT) + 1 >= strlen (
886 handle->url))
887 {
890 return;
891 }
892 ego_entry = NULL;
893
896
897 if (NULL == ego_entry)
898 {
901 return;
902 }
903 handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
904
905 // We need a per-client connection for a transactional bulk import
907 if (NULL == handle->nc)
908 {
911 return;
912 }
914}
915
916
924void
926 const char *url,
927 void *cls)
928{
929 struct RequestHandle *handle = cls;
930 struct EgoEntry *ego_entry;
931 char *egoname;
932 json_t *data_js;
933 json_error_t err;
934
935 char term_data[handle->rest_handle->data_size + 1];
936
937 if (0 >= handle->rest_handle->data_size)
938 {
941 return;
942 }
943 term_data[handle->rest_handle->data_size] = '\0';
944 GNUNET_memcpy (term_data,
945 handle->rest_handle->data,
946 handle->rest_handle->data_size);
947 data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
948 struct GNUNET_JSON_Specification gnsspec[] =
950 &handle->record_name),
952 if (GNUNET_OK != GNUNET_JSON_parse (data_js, gnsspec, NULL, NULL))
953 {
956 json_decref (data_js);
957 return;
958 }
959 GNUNET_JSON_parse_free (gnsspec);
960 if (0 >= strlen (handle->record_name))
961 {
964 json_decref (data_js);
965 return;
966 }
967 json_decref (data_js);
968
969 egoname = NULL;
970 ego_entry = NULL;
971
972 // set zone to name if given
973 if (strlen (GNUNET_REST_API_NS_NAMESTORE) + 1 >= strlen (handle->url))
974 {
977 return;
978 }
979 egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE) + 1];
981
982 if (NULL == ego_entry)
983 {
986 return;
987 }
988 handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
990 handle->zone_pkey,
991 handle->record_name,
993 handle,
995 handle);
996 if (NULL == handle->ns_qe)
997 {
1000 return;
1001 }
1002}
1003
1004
1012void
1014 const char *url,
1015 void *cls)
1016{
1017 struct RequestHandle *handle = cls;
1018 handle->update_strategy = UPDATE_STRATEGY_REPLACE;
1019 namestore_add_or_update (con_handle, url, cls);
1020}
1021
1022
1030void
1032 const char *url,
1033 void *cls)
1034{
1035 struct RequestHandle *handle = cls;
1036 handle->update_strategy = UPDATE_STRATEGY_APPEND;
1037 namestore_add_or_update (con_handle, url, cls);
1038}
1039
1040
1048void
1050 const char *url,
1051 void *cls)
1052{
1053 struct RequestHandle *handle = cls;
1054 struct EgoEntry *ego_entry;
1055 char *egoname;
1056 char *labelname;
1057
1058 egoname = NULL;
1059 ego_entry = NULL;
1060
1061 // set zone to name if given
1062 if (strlen (GNUNET_REST_API_NS_NAMESTORE) + 1 >= strlen (handle->url))
1063 {
1066 return;
1067 }
1068 egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE) + 1];
1069 ego_entry = get_egoentry_namestore (handle, egoname);
1070 if (NULL == ego_entry)
1071 {
1074 return;
1075 }
1076 handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1077 labelname = &egoname[strlen (ego_entry->identifier)];
1078 // set zone to name if given
1079 if (1 >= strlen (labelname))
1080 {
1081 /* label is only "/" */
1084 }
1085
1086 handle->record_name = GNUNET_strdup (labelname + 1);
1088 handle->zone_pkey,
1089 handle->record_name,
1090 0,
1091 NULL,
1092 &del_finished,
1093 handle);
1094 if (NULL == handle->ns_qe)
1095 {
1098 return;
1099 }
1100}
1101
1102
1110static void
1112 const char *url,
1113 void *cls)
1114{
1115 struct MHD_Response *resp;
1116 struct RequestHandle *handle = cls;
1117
1118 // independent of path return all options
1119 resp = GNUNET_REST_create_response (NULL);
1120 GNUNET_assert (MHD_YES ==
1121 MHD_add_response_header (resp,
1122 "Access-Control-Allow-Methods",
1123 allow_methods));
1124 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1126 return;
1127}
1128
1129
1130static void
1131list_ego (void *cls,
1132 struct GNUNET_IDENTITY_Ego *ego,
1133 void **ctx,
1134 const char *identifier)
1135{
1136 struct EgoEntry *ego_entry;
1138
1139 if ((NULL == ego) && (ID_REST_STATE_INIT == state))
1140 {
1142 return;
1143 }
1144 if (NULL == ego)
1145 {
1147 "Called with NULL ego\n");
1148 return;
1149 }
1151 {
1152 ego_entry = GNUNET_new (struct EgoEntry);
1155 ego_entry->ego = ego;
1156 ego_entry->identifier = GNUNET_strdup (identifier);
1158 ego_tail,
1159 ego_entry);
1160 }
1161 /* Ego renamed or added */
1162 if (identifier != NULL)
1163 {
1164 for (ego_entry = ego_head; NULL != ego_entry;
1165 ego_entry = ego_entry->next)
1166 {
1167 if (ego_entry->ego == ego)
1168 {
1169 /* Rename */
1170 GNUNET_free (ego_entry->identifier);
1171 ego_entry->identifier = GNUNET_strdup (identifier);
1172 break;
1173 }
1174 }
1175 if (NULL == ego_entry)
1176 {
1177 /* Add */
1178 ego_entry = GNUNET_new (struct EgoEntry);
1181 ego_entry->ego = ego;
1182 ego_entry->identifier = GNUNET_strdup (identifier);
1184 ego_tail,
1185 ego_entry);
1186 }
1187 }
1188 else
1189 {
1190 /* Delete */
1191 for (ego_entry = ego_head; NULL != ego_entry;
1192 ego_entry = ego_entry->next)
1193 {
1194 if (ego_entry->ego == ego)
1195 break;
1196 }
1197 if (NULL == ego_entry)
1198 return; /* Not found */
1199
1201 ego_tail,
1202 ego_entry);
1203 GNUNET_free (ego_entry->identifier);
1204 GNUNET_free (ego_entry->keystring);
1205 GNUNET_free (ego_entry);
1206 return;
1207 }
1208
1209}
1210
1211
1225 struct GNUNET_REST_RequestHandle *rest_handle,
1227 void *proc_cls)
1228{
1229 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1231 static const struct GNUNET_REST_RequestHandler handlers[] =
1232 { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE, &namestore_get },
1233 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE_IMPORT,
1235 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE, &namestore_add },
1236 { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_NAMESTORE, &namestore_update },
1237 { MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_NAMESTORE,
1239 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_NAMESTORE, &options_cont },
1241
1242 handle->ec = GNUNET_EC_NONE;
1244 handle->proc_cls = proc_cls;
1245 handle->proc = proc;
1246 handle->rest_handle = rest_handle;
1247 handle->zone_pkey = NULL;
1248 handle->timeout_task =
1250 handle->url = GNUNET_strdup (rest_handle->url);
1251 if (handle->url[strlen (handle->url) - 1] == '/')
1252 handle->url[strlen (handle->url) - 1] = '\0';
1255 handle);
1256 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
1257 if (GNUNET_NO ==
1258 GNUNET_REST_handle_request (handle->rest_handle, handlers, &err,
1259 handle))
1260 {
1262 return GNUNET_NO;
1263 }
1264
1265 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
1266 return GNUNET_YES;
1267}
1268
1269
1276void *
1278{
1279 static struct Plugin plugin;
1280 struct GNUNET_REST_Plugin *api;
1281
1282 ns_cfg = c;
1283 if (NULL != plugin.cfg)
1284 return NULL; /* can only initialize once! */
1285 memset (&plugin, 0, sizeof(struct Plugin));
1286 plugin.cfg = c;
1287 api = GNUNET_new (struct GNUNET_REST_Plugin);
1288 api->cls = &plugin;
1292 "%s, %s, %s, %s, %s",
1293 MHD_HTTP_METHOD_GET,
1294 MHD_HTTP_METHOD_POST,
1295 MHD_HTTP_METHOD_PUT,
1296 MHD_HTTP_METHOD_DELETE,
1297 MHD_HTTP_METHOD_OPTIONS);
1300
1302 "Namestore REST API initialized\n"));
1303 return api;
1304}
1305
1306
1313void
1315{
1316 struct Plugin *plugin = api->cls;
1317 struct RequestHandle *request;
1318 struct EgoEntry *ego_entry;
1319 struct EgoEntry *ego_tmp;
1320
1321 plugin->cfg = NULL;
1322 while (NULL != (request = requests_head))
1323 do_error (request);
1324 if (NULL != identity_handle)
1326 if (NULL != ns_handle)
1328
1329 for (ego_entry = ego_head; NULL != ego_entry;)
1330 {
1331 ego_tmp = ego_entry;
1332 ego_entry = ego_entry->next;
1333 GNUNET_free (ego_tmp->identifier);
1334 GNUNET_free (ego_tmp->keystring);
1335 GNUNET_free (ego_tmp);
1336 }
1337
1339 GNUNET_free (api);
1340 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Namestore REST plugin is finished\n");
1341}
1342
1343
1344/* end of plugin_rest_namestore.c */
struct GNUNET_MQ_MessageHandlers handlers[]
Definition: 003.c:1
struct TestcasePlugin * plugin
The process handle to the testbed service.
static struct MHD_Response * response
Our canonical response.
struct GNUNET_HashCode key
The key used in the DHT.
static char * egoname
Ego Attribut String.
Definition: gnunet-did.c:93
static struct GNUNET_FS_Handle * ctx
struct GNUNET_CRYPTO_PrivateKey pk
Private key from command line option, or NULL.
static char * name
Name (label) of the records to list.
static unsigned int rd_count
Number of records for currently parsed set.
static struct GNUNET_GNSRECORD_Data rd[50]
The record data under a single label.
static char * value
Value of the record to add/remove.
static struct GNUNET_VPN_RedirectionRequest * request
Opaque redirection request handle.
Definition: gnunet-vpn.c:40
static struct GNUNET_VPN_Handle * handle
Handle to vpn service.
Definition: gnunet-vpn.c:35
API that can be used to manipulate JSON GNS record data.
Identity service; implements identity management for GNUnet.
void GNUNET_JSON_parse_free(struct GNUNET_JSON_Specification *spec)
Frees all elements allocated during a GNUNET_JSON_parse() operation.
Definition: json.c:94
enum GNUNET_GenericReturnValue GNUNET_JSON_parse(const json_t *root, struct GNUNET_JSON_Specification *spec, const char **error_json_name, unsigned int *error_line)
Navigate and parse data in a JSON tree.
Definition: json.c:32
struct GNUNET_JSON_Specification GNUNET_JSON_spec_end(void)
End of a parser specification.
Definition: json_helper.c:32
API that can be used to store naming information on a GNUnet node;.
API for helper library to parse/create REST.
GNUnet service REST plugin header.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
json_t * GNUNET_GNSRECORD_JSON_from_gnsrecord(const char *rname, const struct GNUNET_GNSRECORD_Data *rd, unsigned int rd_count)
Convert GNS record to JSON.
uint32_t GNUNET_GNSRECORD_typename_to_number(const char *dns_typename)
Convert a type name (e.g.
Definition: gnsrecord.c:200
struct GNUNET_JSON_Specification GNUNET_GNSRECORD_JSON_spec_gnsrecord(struct GNUNET_GNSRECORD_Data **rd, unsigned int *rd_count, char **name)
JSON Specification for GNS Records.
GNUNET_GNSRECORD_Filter
Filter for GNUNET_GNSRECORD_normalize_record_set().
#define GNUNET_GNSRECORD_TYPE_ANY
Record type indicating any record/'*'.
@ GNUNET_GNSRECORD_FILTER_NONE
No filter flags set.
@ GNUNET_GNSRECORD_FILTER_INCLUDE_MAINTENANCE
Include maintenance records (TOMBSTONE etc).
@ GNUNET_GNSRECORD_FILTER_OMIT_PRIVATE
Filter private records.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:41
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_contains(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Check if the map contains any value under the given key (including values that are NULL).
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
const struct GNUNET_CRYPTO_PrivateKey * GNUNET_IDENTITY_ego_get_private_key(const struct GNUNET_IDENTITY_Ego *ego)
Obtain the ECC key associated with a ego.
Definition: identity_api.c:517
struct GNUNET_IDENTITY_Handle * GNUNET_IDENTITY_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_IDENTITY_Callback cb, void *cb_cls)
Connect to the identity service.
Definition: identity_api.c:487
void GNUNET_IDENTITY_disconnect(struct GNUNET_IDENTITY_Handle *h)
Disconnect from identity service.
Definition: identity_api.c:732
void GNUNET_IDENTITY_ego_get_public_key(struct GNUNET_IDENTITY_Ego *ego, struct GNUNET_CRYPTO_PublicKey *pk)
Get the identifier (public key) of an ego.
Definition: identity_api.c:529
#define GNUNET_log(kind,...)
char * GNUNET_CRYPTO_public_key_to_string(const struct GNUNET_CRYPTO_PublicKey *key)
Creates a (Base32) string representation of the public key.
Definition: crypto_pkey.c:551
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
#define GNUNET_free_nz(ptr)
Wrapper around free.
struct GNUNET_NAMESTORE_ZoneIterator * GNUNET_NAMESTORE_zone_iteration_start2(struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_PrivateKey *zone, GNUNET_SCHEDULER_TaskCallback error_cb, void *error_cb_cls, GNUNET_NAMESTORE_RecordSetMonitor proc, void *proc_cls, GNUNET_SCHEDULER_TaskCallback finish_cb, void *finish_cb_cls, enum GNUNET_GNSRECORD_Filter filter)
Starts a new zone iteration (used to periodically PUT all of our records into our DHT).
struct GNUNET_NAMESTORE_QueueEntry * GNUNET_NAMESTORE_records_lookup(struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_PrivateKey *pkey, const char *label, GNUNET_SCHEDULER_TaskCallback error_cb, void *error_cb_cls, GNUNET_NAMESTORE_RecordMonitor rm, void *rm_cls)
Lookup an item in the namestore.
struct GNUNET_NAMESTORE_QueueEntry * GNUNET_NAMESTORE_record_set_store(struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_PrivateKey *pkey, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd, GNUNET_NAMESTORE_ContinuationWithStatus cont, void *cont_cls)
Store an item in the namestore.
void GNUNET_NAMESTORE_disconnect(struct GNUNET_NAMESTORE_Handle *h)
Disconnect from the namestore service (and free associated resources).
void GNUNET_NAMESTORE_zone_iterator_next(struct GNUNET_NAMESTORE_ZoneIterator *it, uint64_t limit)
Calls the record processor specified in GNUNET_NAMESTORE_zone_iteration_start for the next record.
void GNUNET_NAMESTORE_cancel(struct GNUNET_NAMESTORE_QueueEntry *qe)
Cancel a namestore operation.
struct GNUNET_NAMESTORE_QueueEntry * GNUNET_NAMESTORE_records_lookup2(struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_PrivateKey *pkey, const char *label, GNUNET_SCHEDULER_TaskCallback error_cb, void *error_cb_cls, GNUNET_NAMESTORE_RecordMonitor rm, void *rm_cls, enum GNUNET_GNSRECORD_Filter filter)
Lookup an item in the namestore with GNSRECORD filter.
struct GNUNET_NAMESTORE_QueueEntry * GNUNET_NAMESTORE_records_store(struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_PrivateKey *pkey, unsigned int rd_set_count, const struct GNUNET_NAMESTORE_RecordInfo *record_info, unsigned int *rds_sent, GNUNET_NAMESTORE_ContinuationWithStatus cont, void *cont_cls)
Store one or more record sets in the namestore.
struct GNUNET_NAMESTORE_Handle * GNUNET_NAMESTORE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the namestore service.
void GNUNET_NAMESTORE_zone_iteration_stop(struct GNUNET_NAMESTORE_ZoneIterator *it)
Stops iteration and releases the namestore handle for further calls.
int GNUNET_REST_handle_request(struct GNUNET_REST_RequestHandle *conn, const struct GNUNET_REST_RequestHandler *handlers, struct GNUNET_REST_RequestHandlerError *err, void *cls)
Definition: rest.c:64
void(* GNUNET_REST_ResultProcessor)(void *cls, struct MHD_Response *resp, int status)
Iterator called on obtained result for a REST result.
#define GNUNET_REST_HANDLER_END
struct MHD_Response * GNUNET_REST_create_response(const char *data)
Create REST MHD response.
Definition: rest.c:44
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:981
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1305
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1278
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
@ MHD_HTTP_OK
OK [RFC7231, Section 6.3.1].
@ MHD_HTTP_NO_CONTENT
No Content [RFC7231, Section 6.3.5].
@ MHD_HTTP_INTERNAL_SERVER_ERROR
Internal Server Error [RFC7231, Section 6.6.1].
static struct EgoEntry * ego_tail
Ego list.
#define GNUNET_REST_API_NS_NAMESTORE
Namestore namespace.
void namestore_import(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle namestore POST import.
UpdateStrategy
@ UPDATE_STRATEGY_REPLACE
@ UPDATE_STRATEGY_APPEND
static void ns_get_lookup_cb(void *cls, const struct GNUNET_CRYPTO_PrivateKey *zone, const char *label, unsigned int rd_len, const struct GNUNET_GNSRECORD_Data *rd)
static void import_next_cb(void *cls, enum GNUNET_ErrorCode ec)
static void del_finished(void *cls, enum GNUNET_ErrorCode ec)
static void ns_lookup_cb(void *cls, const struct GNUNET_CRYPTO_PrivateKey *zone, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
static struct GNUNET_NAMESTORE_Handle * ns_handle
Handle to NAMESTORE.
static void namestore_iteration_error(void *cls)
Does internal server error when iteration failed.
static void namestore_list_finished(void *cls)
Iteration over all results finished, build final response.
#define ID_REST_STATE_INIT
State while collecting all egos.
static struct RequestHandle * requests_head
DLL.
static void options_cont(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Respond to OPTIONS request.
void REST_namestore_done(struct GNUNET_REST_Plugin *api)
Exit point from the plugin.
void * REST_namestore_init(const struct GNUNET_CONFIGURATION_Handle *c)
Entry point for the plugin.
static int state
The processing state.
static void namestore_list_iteration(void *cls, const struct GNUNET_CRYPTO_PrivateKey *zone_key, const char *rname, unsigned int rd_len, const struct GNUNET_GNSRECORD_Data *rd, struct GNUNET_TIME_Absolute expiry)
Create a response with requested records.
static struct EgoEntry * ego_head
Ego list.
static void list_ego(void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *identifier)
void namestore_delete(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle namestore DELETE request.
static char * allow_methods
HTTP methods allows for this plugin.
void namestore_add(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle namestore POST request.
static void create_finished(void *cls, enum GNUNET_ErrorCode ec)
static void bulk_tx_start(struct RequestHandle *handle)
static struct RequestHandle * requests_tail
DLL.
enum GNUNET_GenericReturnValue REST_namestore_process_request(void *plugin, struct GNUNET_REST_RequestHandle *rest_handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
Function processing the REST call.
static struct GNUNET_IDENTITY_Handle * identity_handle
Handle to Identity service.
const struct GNUNET_CONFIGURATION_Handle * ns_cfg
The configuration handle.
static void ns_lookup_error_cb(void *cls)
Handle lookup error.
void namestore_add_or_update(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle namestore POST/PUT request.
#define GNUNET_REST_API_NS_NAMESTORE_IMPORT
Namestore import API namespace.
void namestore_update(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle namestore PUT request.
#define ID_REST_STATE_POST_INIT
Done collecting egos.
struct EgoEntry * get_egoentry_namestore(struct RequestHandle *handle, char *name)
Get EgoEntry from list with either a public key or a name If public key and name are not NULL,...
static void do_error(void *cls)
Task run on errors.
void namestore_get(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle namestore GET request.
static void cleanup_handle(void *cls)
Cleanup lookup handle.
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
const char * GNUNET_ErrorCode_get_hint(enum GNUNET_ErrorCode ec)
Returns a hint for a given error code.
unsigned int GNUNET_ErrorCode_get_http_status(enum GNUNET_ErrorCode ec)
Return HTTP status for a given error code.
GNUNET_ErrorCode
Taler error codes.
@ GNUNET_EC_NAMESTORE_LOOKUP_ERROR
Failed to lookup record.
@ GNUNET_EC_NAMESTORE_ITERATION_FAILED
Zone iteration failed.
@ GNUNET_EC_NAMESTORE_ZONE_EMPTY
Zone does not contain any records.
@ GNUNET_EC_NAMESTORE_NO_LABEL_GIVEN
No label given.
@ GNUNET_EC_NAMESTORE_RECORD_DATA_INVALID
Record data invalid.
@ GNUNET_EC_NAMESTORE_NO_RECORDS_GIVEN
No records given.
@ GNUNET_EC_NAMESTORE_ZONE_NOT_FOUND
Zone not found.
@ GNUNET_EC_NONE
No error (success).
@ GNUNET_EC_NAMESTORE_UNKNOWN
Unknown namestore error.
@ GNUNET_EC_NAMESTORE_RECORD_NOT_FOUND
Record not found.
The default namestore ego.
char * identifier
Ego Identifier.
struct EgoEntry * prev
DLL.
char * keystring
Public key string.
struct EgoEntry * next
DLL.
struct GNUNET_IDENTITY_Ego * ego
The Ego.
void * cls
Closure for all of the callbacks.
A private key for an identity as per LSD0001.
An identity key as per LSD0001.
uint32_t record_type
Type of the GNS/DNS record.
const void * data
Binary value stored in the DNS record.
A 512-bit hashcode.
Handle for an ego.
Definition: identity.h:37
Handle for the service.
Definition: identity_api.c:97
Handle for an operation with the identity service.
Definition: identity_api.c:41
Entry in parser specification for GNUNET_JSON_parse().
void * cls
Closure for parser and cleaner.
Connection to the NAMESTORE service.
An QueueEntry used to store information for a pending NAMESTORE record operation.
Definition: namestore_api.c:49
A struct for record bulk import.
Handle for a zone iterator operation.
struct returned by the initialization function of the plugin
char * name
Plugin name.
void * cls
The closure of the plugin.
const char * url
The url as string.
struct GNUNET_CONTAINER_MultiHashMap * url_param_map
Map of url parameters.
void(* proc)(struct GNUNET_REST_RequestHandle *handle, const char *url, void *cls)
Namespace to handle.
Entry in list of pending tasks.
Definition: scheduler.c:136
Time for absolute times used by GNUnet, in microseconds.
Time for relative time used by GNUnet, in microseconds.
Handle for a plugin.
Definition: block.c:38
struct GNUNET_BLOCK_PluginFunctions * api
Plugin API.
Definition: block.c:47
const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
The request handle.
Definition: config_plugin.c:46
char * record_name
Records to store.
unsigned int rd_count
Number of records in rd.
enum GNUNET_ErrorCode ec
Error code.
struct GNUNET_IDENTITY_Operation * op
IDENTITY Operation.
struct RequestHandle * prev
DLL.
Definition: config_plugin.c:55
const struct GNUNET_CRYPTO_PrivateKey * zone_pkey
Private key for the zone.
struct GNUNET_NAMESTORE_RecordInfo * ri
RecordInfo array.
struct EgoEntry * ego_entry
IDENTITY Operation.
struct GNUNET_SCHEDULER_Task * timeout_task
ID of a task associated with the resolution process.
Definition: gns_plugin.c:122
void * proc_cls
The closure of the result processor.
Definition: config_plugin.c:70
struct GNUNET_GNSRECORD_Data * rd
Records to store.
GNUNET_REST_ResultProcessor proc
The plugin result processor.
Definition: config_plugin.c:65
unsigned int rd_set_pos
Position of record info.
struct RequestHandle * next
DLL.
Definition: config_plugin.c:50
enum UpdateStrategy update_strategy
How to update the record set.
uint32_t record_type
Record type filter.
json_t * resp_object
Response object.
struct GNUNET_REST_RequestHandle * rest_handle
Handle to rest request.
Definition: config_plugin.c:60
struct GNUNET_NAMESTORE_ZoneIterator * list_it
Handle to NAMESTORE it.
struct GNUNET_NAMESTORE_Handle * nc
For bulk import, we need a dedicated Namestore handle.
char * url
The URL.
Definition: config_plugin.c:80
struct GNUNET_NAMESTORE_QueueEntry * ns_qe
NAMESTORE Operation.
unsigned int rd_set_count
Size of record info.
struct GNUNET_TIME_Relative timeout
Desired timeout for the lookup (default is no timeout).
Definition: gns_plugin.c:117