GNUnet 0.22.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#include "namestore_plugin.h"
37
41#define GNUNET_REST_API_NS_NAMESTORE "/namestore"
42
46#define GNUNET_REST_API_NS_NAMESTORE_IMPORT "/namestore/import"
47
51#define ID_REST_STATE_INIT 0
52
56#define ID_REST_STATE_POST_INIT 1
61
65static char *allow_methods;
66
70static struct EgoEntry *ego_head;
71
75static struct EgoEntry *ego_tail;
76
80static int state;
81
86
91
95struct Plugin
96{
97 const struct GNUNET_CONFIGURATION_Handle *cfg;
98};
99
103struct EgoEntry
104{
108 struct EgoEntry *next;
109
113 struct EgoEntry *prev;
114
118 char *identifier;
119
123 char *keystring;
124
128 struct GNUNET_IDENTITY_Ego *ego;
129};
130
131
133{
137
141struct RequestHandle
142{
146 struct RequestHandle *next;
147
151 struct RequestHandle *prev;
152
157
161 uint32_t record_type;
162
167
172
176 unsigned int rd_count;
177
182
186 unsigned int rd_set_count;
187
191 unsigned int rd_set_pos;
192
197
202
206 json_t *resp_object;
207
208
213
218
223
228
233
238
243
248
252 void *proc_cls;
253
257 char *url;
258
262 enum GNUNET_ErrorCode ec;
263
264};
265
270
275
276
281static void
282cleanup_handle (void *cls)
283{
284 struct RequestHandle *handle = cls;
285
286 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
287 if (NULL != handle->timeout_task)
288 {
289 GNUNET_SCHEDULER_cancel (handle->timeout_task);
290 handle->timeout_task = NULL;
291 }
292 if (NULL != handle->record_name)
293 GNUNET_free (handle->record_name);
294 if (NULL != handle->url)
295 GNUNET_free (handle->url);
296 if (NULL != handle->rd)
297 {
298 for (int i = 0; i < handle->rd_count; i++)
299 {
300 if (NULL != handle->rd[i].data)
301 GNUNET_free_nz ((void *) handle->rd[i].data);
302 }
303 GNUNET_free (handle->rd);
304 }
305 if (NULL != handle->timeout_task)
306 GNUNET_SCHEDULER_cancel (handle->timeout_task);
307 if (NULL != handle->list_it)
309 if (NULL != handle->ns_qe)
311 if (NULL != handle->nc)
313 if (NULL != handle->resp_object)
314 {
315 json_decref (handle->resp_object);
316 }
319 handle);
321}
322
323
329static void
330do_error (void *cls)
331{
332 struct RequestHandle *handle = cls;
333 struct MHD_Response *resp;
334 json_t *json_error = json_object ();
335 char *response;
336 const char*emsg;
337 int response_code;
338
340 json_object_set_new (json_error, "error", json_string (emsg));
341 json_object_set_new (json_error, "error_code", json_integer (handle->ec));
342 response_code = GNUNET_ErrorCode_get_http_status (handle->ec);
343 if (0 == response_code)
344 response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
345 response = json_dumps (json_error, 0);
347 GNUNET_assert (MHD_YES ==
348 MHD_add_response_header (resp, "Content-Type",
349 "application/json"));
350 handle->proc (handle->proc_cls, resp, response_code);
351 json_decref (json_error);
354}
355
356
366static struct EgoEntry *
368{
369 struct EgoEntry *ego_entry;
370 char *copy = GNUNET_strdup (name);
371 char *tmp;
372
373 if (NULL == name)
374 return NULL;
375 tmp = strtok (copy, "/");
376 if (NULL == tmp)
377 return NULL;
378 for (ego_entry = ego_head; NULL != ego_entry;
379 ego_entry = ego_entry->next)
380 {
381 if (0 != strcasecmp (tmp, ego_entry->identifier))
382 continue;
383 GNUNET_free (copy);
384 return ego_entry;
385 }
386 GNUNET_free (copy);
387 return NULL;
388}
389
390
396static void
398{
399 struct RequestHandle *handle = cls;
400
403 return;
404}
405
406
407static void
409{
410 struct RequestHandle *handle = cls;
411 struct MHD_Response *resp;
412
413 handle->ns_qe = NULL;
414 handle->ec = ec;
415 if (GNUNET_EC_NONE != ec)
416 {
418 return;
419 }
420 resp = GNUNET_REST_create_response (NULL);
421 handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT);
423}
424
425
426static void
427del_finished (void *cls, enum GNUNET_ErrorCode ec)
428{
429 struct RequestHandle *handle = cls;
430
431 handle->ns_qe = NULL;
432 handle->ec = ec;
433 if (GNUNET_EC_NONE != ec)
434 {
436 return;
437 }
438 handle->proc (handle->proc_cls,
442}
443
444
451static void
453{
454 struct RequestHandle *handle = cls;
455 char *result_str;
456 struct MHD_Response *resp;
457
458 handle->list_it = NULL;
459
460 if (NULL == handle->resp_object)
461 {
464 return;
465 }
466 result_str = json_dumps (handle->resp_object, 0);
467 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
468 resp = GNUNET_REST_create_response (result_str);
469 GNUNET_assert (MHD_YES ==
470 MHD_add_response_header (resp, "Content-Type",
471 "application/json"));
472 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
473 GNUNET_free (result_str);
475}
476
477
483static void
485 const struct GNUNET_CRYPTO_PrivateKey *zone_key,
486 const char *rname,
487 unsigned int rd_len,
488 const struct GNUNET_GNSRECORD_Data *rd,
489 struct GNUNET_TIME_Absolute expiry)
490{
491 struct RequestHandle *handle = cls;
492 struct GNUNET_GNSRECORD_Data rd_filtered[rd_len];
493 json_t *record_obj;
494 int i = 0;
495 int j = 0;
496
497 if (rd_len == 0)
498 {
501 return;
502 }
503
504 for (i = 0; i < rd_len; i++)
505 {
506 if ((GNUNET_GNSRECORD_TYPE_ANY != handle->record_type) &&
507 (rd[i].record_type != handle->record_type))
508 continue; /* Apply filter */
509 rd_filtered[j] = rd[i];
510 rd_filtered[j].data = rd[i].data;
511 j++;
512 }
514 if (j > 0)
515 {
516 if (NULL == handle->resp_object)
517 handle->resp_object = json_array ();
518 record_obj = GNUNET_GNSRECORD_JSON_from_gnsrecord (rname,
519 rd_filtered,
520 j);
521 json_array_append_new (handle->resp_object, record_obj);
522 }
524}
525
526
532static void
534{
535 struct RequestHandle *handle = cls;
536
539}
540
541
542static void
544 const struct GNUNET_CRYPTO_PrivateKey *zone,
545 const char *label,
546 unsigned int rd_len,
547 const struct GNUNET_GNSRECORD_Data *rd)
548{
549 struct RequestHandle *handle = cls;
550 struct GNUNET_GNSRECORD_Data rd_filtered[rd_len];
551 int i = 0;
552 int j = 0;
553
554 handle->ns_qe = NULL;
555 for (i = 0; i < rd_len; i++)
556 {
557 if ((GNUNET_GNSRECORD_TYPE_ANY != handle->record_type) &&
558 (rd[i].record_type != handle->record_type))
559 continue; /* Apply filter */
560 rd_filtered[j] = rd[i];
561 rd_filtered[j].data = rd[i].data;
562 j++;
563 }
565 if (j == 0)
566 {
569 return;
570 }
571 handle->resp_object = GNUNET_GNSRECORD_JSON_from_gnsrecord (label,
572 rd_filtered,
573 j);
575}
576
577
585static void
587 const char *url,
588 void *cls)
589{
590 struct RequestHandle *handle = cls;
591 struct EgoEntry *ego_entry;
592 struct GNUNET_HashCode key;
593 enum GNUNET_GNSRECORD_Filter filter_flags;
594 char *egoname;
595 char *labelname;
596 char *typename;
597 char *boolstring;
598
599 egoname = NULL;
600 ego_entry = NULL;
601
602 // set zone to name if given
603 if (strlen (GNUNET_REST_API_NS_NAMESTORE) + 1 >= strlen (handle->url))
604 {
607 return;
608 }
609 egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE) + 1];
611 if (NULL == ego_entry)
612 {
615 return;
616 }
617 handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
618
619 GNUNET_CRYPTO_hash ("record_type", strlen ("record_type"), &key);
620 handle->record_type = GNUNET_GNSRECORD_TYPE_ANY;
621 if (GNUNET_YES ==
623 {
624 typename = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map,
625 &key);
626 if (NULL != typename)
627 handle->record_type = GNUNET_GNSRECORD_typename_to_number (typename);
628 }
629 GNUNET_CRYPTO_hash ("omit_private", strlen ("omit_private"), &key);
630 filter_flags = GNUNET_GNSRECORD_FILTER_NONE;
631 if (GNUNET_YES ==
633 {
634 boolstring = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map,
635 &key);
636 if ((0 == strcmp (boolstring, "1")) ||
637 (0 == strcmp (boolstring, "yes")) ||
638 (0 == strcmp (boolstring, "true")))
640 }
641 GNUNET_CRYPTO_hash ("include_maintenance", strlen ("include_maintenance"),
642 &key);
643 if (GNUNET_YES ==
645 {
646 boolstring = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map,
647 &key);
648 if ((0 == strcmp (boolstring, "1")) ||
649 (0 == strcmp (boolstring, "yes")) ||
650 (0 == strcmp (boolstring, "true")))
652 }
653 labelname = &egoname[strlen (ego_entry->identifier)];
654 if (1 >= strlen (labelname))
655 {
656 /* Iterate over all records */
657 handle->list_it =
659 handle->zone_pkey,
661 handle,
663 handle,
665 handle,
666 filter_flags);
667 if (NULL == handle->list_it)
668 {
671 return;
672 }
673 return;
674 }
675 handle->record_name = GNUNET_strdup (labelname + 1);
677 handle->zone_pkey,
678 handle->record_name,
680 handle,
682 handle,
683 filter_flags);
684 if (NULL == handle->ns_qe)
685 {
688 return;
689 }
690}
691
692
693static void
694ns_lookup_cb (void *cls,
695 const struct GNUNET_CRYPTO_PrivateKey *zone,
696 const char *label,
697 unsigned int rd_count,
698 const struct GNUNET_GNSRECORD_Data *rd)
699{
700 struct RequestHandle *handle = cls;
702 int i = 0;
703 int j = 0;
704
705 if (UPDATE_STRATEGY_APPEND == handle->update_strategy)
706 {
707 for (i = 0; i < rd_count; i++)
708 rd_new[i] = rd[i];
709 }
710 for (j = 0; j < handle->rd_count; j++)
711 rd_new[i + j] = handle->rd[j];
713 handle->zone_pkey,
714 handle->record_name,
715 i + j,
716 rd_new,
718 handle);
719 if (NULL == handle->ns_qe)
720 {
723 return;
724 }
725}
726
727
728static void
730{
731 struct RequestHandle *handle = cls;
732 unsigned int remaining;
733
735 "Import finished (%d)\n", ec);
736 handle->ns_qe = NULL;
737 handle->ec = ec;
738 if (GNUNET_EC_NONE != ec)
739 {
741 return;
742 }
743 remaining = handle->rd_set_count - handle->rd_set_pos;
744 if (0 == remaining)
745 {
746 struct MHD_Response *resp;
747
748 handle->ns_qe = NULL;
750 "Commit finished (%d)\n", ec);
751 handle->ec = ec;
752 if (GNUNET_EC_NONE != ec)
753 {
755 return;
756 }
757 resp = GNUNET_REST_create_response (NULL);
758 handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT);
760 return;
761 }
762 {
763 unsigned int sent_rds = 0;
764 // Find the smallest set of records we can send with our message size
765 // restriction of 16 bit
767 handle->zone_pkey,
768 remaining,
769 &handle->ri[handle->
770 rd_set_pos],
771 &sent_rds,
773 handle);
774 if ((NULL == handle->ns_qe) && (0 == sent_rds))
775 {
778 return;
779 }
780 handle->rd_set_pos += sent_rds;
781 }
782}
783
784
785static void
787{
788 json_t *data_js;
789 json_error_t err;
790 char term_data[handle->rest_handle->data_size + 1];
791
793 "Transaction started...\n");
794 if (0 >= handle->rest_handle->data_size)
795 {
798 return;
799 }
800 term_data[handle->rest_handle->data_size] = '\0';
801 GNUNET_memcpy (term_data,
802 handle->rest_handle->data,
803 handle->rest_handle->data_size);
804 data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
805 if (NULL == data_js)
806 {
809 "Error parsing data: %s", err.text);
811 return;
812 }
813 if (! json_is_array (data_js))
814 {
817 json_decref (data_js);
818 return;
819 }
820 handle->rd_set_count = json_array_size (data_js);
821 handle->ri = GNUNET_malloc (handle->rd_set_count
822 * sizeof (struct GNUNET_NAMESTORE_RecordInfo));
824 "Got record set of size %d\n", handle->rd_set_count);
825 {
826 char *albl;
827 size_t index;
828 json_t *value;
829 json_array_foreach (data_js, index, value) {
830 {
832 struct GNUNET_JSON_Specification gnsspec[] =
834 &handle->ri[index].a_rd_count,
835 &albl),
837 if (GNUNET_OK != GNUNET_JSON_parse (value, gnsspec, NULL, NULL))
838 {
841 json_decref (data_js);
842 return;
843 }
844 handle->ri[index].a_rd = rd;
845 handle->ri[index].a_label = albl;
847 "Parsed record set for name %s\n",
848 handle->ri[index].a_label);
849 }
850 }
851 }
852 // json_decref (data_js);
853 {
854 unsigned int sent_rds = 0;
855 // Find the smallest set of records we can send with our message size
856 // restriction of 16 bit
858 handle->zone_pkey,
859 handle->rd_set_count,
860 handle->ri,
861 &sent_rds,
863 handle);
864 if ((NULL == handle->ns_qe) && (0 == sent_rds))
865 {
868 return;
869 }
870 handle->rd_set_pos += sent_rds;
871 }
872}
873
874
882static void
884 const char *url,
885 void *cls)
886{
887 struct RequestHandle *handle = cls;
888 struct EgoEntry *ego_entry;
889 char *egoname;
890
891 // set zone to name if given
892 if (strlen (GNUNET_REST_API_NS_NAMESTORE_IMPORT) + 1 >= strlen (
893 handle->url))
894 {
897 return;
898 }
899 ego_entry = NULL;
900
903
904 if (NULL == ego_entry)
905 {
908 return;
909 }
910 handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
911
912 // We need a per-client connection for a transactional bulk import
914 if (NULL == handle->nc)
915 {
918 return;
919 }
921}
922
923
931static void
933 const char *url,
934 void *cls)
935{
936 struct RequestHandle *handle = cls;
937 struct EgoEntry *ego_entry;
938 char *egoname;
939 json_t *data_js;
940 json_error_t err;
941
942 char term_data[handle->rest_handle->data_size + 1];
943
944 if (0 >= handle->rest_handle->data_size)
945 {
948 return;
949 }
950 term_data[handle->rest_handle->data_size] = '\0';
951 GNUNET_memcpy (term_data,
952 handle->rest_handle->data,
953 handle->rest_handle->data_size);
954 data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
955 struct GNUNET_JSON_Specification gnsspec[] =
957 &handle->record_name),
959 if (GNUNET_OK != GNUNET_JSON_parse (data_js, gnsspec, NULL, NULL))
960 {
963 json_decref (data_js);
964 return;
965 }
966 GNUNET_JSON_parse_free (gnsspec);
967 if (0 >= strlen (handle->record_name))
968 {
971 json_decref (data_js);
972 return;
973 }
974 json_decref (data_js);
975
976 egoname = NULL;
977 ego_entry = NULL;
978
979 // set zone to name if given
980 if (strlen (GNUNET_REST_API_NS_NAMESTORE) + 1 >= strlen (handle->url))
981 {
984 return;
985 }
986 egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE) + 1];
988
989 if (NULL == ego_entry)
990 {
993 return;
994 }
995 handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
997 handle->zone_pkey,
998 handle->record_name,
1000 handle,
1001 &ns_lookup_cb,
1002 handle);
1003 if (NULL == handle->ns_qe)
1004 {
1007 return;
1008 }
1009}
1010
1011
1019static void
1021 const char *url,
1022 void *cls)
1023{
1024 struct RequestHandle *handle = cls;
1025 handle->update_strategy = UPDATE_STRATEGY_REPLACE;
1026 namestore_add_or_update (con_handle, url, cls);
1027}
1028
1029
1037static void
1039 const char *url,
1040 void *cls)
1041{
1042 struct RequestHandle *handle = cls;
1043 handle->update_strategy = UPDATE_STRATEGY_APPEND;
1044 namestore_add_or_update (con_handle, url, cls);
1045}
1046
1047
1055static void
1057 const char *url,
1058 void *cls)
1059{
1060 struct RequestHandle *handle = cls;
1061 struct EgoEntry *ego_entry;
1062 char *egoname;
1063 char *labelname;
1064
1065 egoname = NULL;
1066 ego_entry = NULL;
1067
1068 // set zone to name if given
1069 if (strlen (GNUNET_REST_API_NS_NAMESTORE) + 1 >= strlen (handle->url))
1070 {
1073 return;
1074 }
1075 egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE) + 1];
1076 ego_entry = get_egoentry_namestore (handle, egoname);
1077 if (NULL == ego_entry)
1078 {
1081 return;
1082 }
1083 handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1084 labelname = &egoname[strlen (ego_entry->identifier)];
1085 // set zone to name if given
1086 if (1 >= strlen (labelname))
1087 {
1088 /* label is only "/" */
1091 }
1092
1093 handle->record_name = GNUNET_strdup (labelname + 1);
1095 handle->zone_pkey,
1096 handle->record_name,
1097 0,
1098 NULL,
1099 &del_finished,
1100 handle);
1101 if (NULL == handle->ns_qe)
1102 {
1105 return;
1106 }
1107}
1108
1109
1117static void
1119 const char *url,
1120 void *cls)
1121{
1122 struct MHD_Response *resp;
1123 struct RequestHandle *handle = cls;
1124
1125 // independent of path return all options
1126 resp = GNUNET_REST_create_response (NULL);
1127 GNUNET_assert (MHD_YES ==
1128 MHD_add_response_header (resp,
1129 "Access-Control-Allow-Methods",
1130 allow_methods));
1131 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1133 return;
1134}
1135
1136
1137static void
1138list_ego (void *cls,
1139 struct GNUNET_IDENTITY_Ego *ego,
1140 void **ctx,
1141 const char *identifier)
1142{
1143 struct EgoEntry *ego_entry;
1145
1146 if ((NULL == ego) && (ID_REST_STATE_INIT == state))
1147 {
1149 return;
1150 }
1151 if (NULL == ego)
1152 {
1154 "Called with NULL ego\n");
1155 return;
1156 }
1158 {
1159 ego_entry = GNUNET_new (struct EgoEntry);
1162 ego_entry->ego = ego;
1163 ego_entry->identifier = GNUNET_strdup (identifier);
1165 ego_tail,
1166 ego_entry);
1167 }
1168 /* Ego renamed or added */
1169 if (identifier != NULL)
1170 {
1171 for (ego_entry = ego_head; NULL != ego_entry;
1172 ego_entry = ego_entry->next)
1173 {
1174 if (ego_entry->ego == ego)
1175 {
1176 /* Rename */
1177 GNUNET_free (ego_entry->identifier);
1178 ego_entry->identifier = GNUNET_strdup (identifier);
1179 break;
1180 }
1181 }
1182 if (NULL == ego_entry)
1183 {
1184 /* Add */
1185 ego_entry = GNUNET_new (struct EgoEntry);
1188 ego_entry->ego = ego;
1189 ego_entry->identifier = GNUNET_strdup (identifier);
1191 ego_tail,
1192 ego_entry);
1193 }
1194 }
1195 else
1196 {
1197 /* Delete */
1198 for (ego_entry = ego_head; NULL != ego_entry;
1199 ego_entry = ego_entry->next)
1200 {
1201 if (ego_entry->ego == ego)
1202 break;
1203 }
1204 if (NULL == ego_entry)
1205 return; /* Not found */
1206
1208 ego_tail,
1209 ego_entry);
1210 GNUNET_free (ego_entry->identifier);
1211 GNUNET_free (ego_entry->keystring);
1212 GNUNET_free (ego_entry);
1213 return;
1214 }
1215
1216}
1217
1218
1232 struct GNUNET_REST_RequestHandle *rest_handle,
1234 void *proc_cls)
1235{
1236 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1238 static const struct GNUNET_REST_RequestHandler handlers[] =
1239 { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE, &namestore_get },
1240 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE_IMPORT,
1242 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE, &namestore_add },
1243 { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_NAMESTORE, &namestore_update },
1244 { MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_NAMESTORE,
1246 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_NAMESTORE, &options_cont },
1248
1249 handle->ec = GNUNET_EC_NONE;
1251 handle->proc_cls = proc_cls;
1252 handle->proc = proc;
1253 handle->rest_handle = rest_handle;
1254 handle->zone_pkey = NULL;
1255 handle->timeout_task =
1257 handle->url = GNUNET_strdup (rest_handle->url);
1258 if (handle->url[strlen (handle->url) - 1] == '/')
1259 handle->url[strlen (handle->url) - 1] = '\0';
1262 handle);
1263 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
1264 if (GNUNET_NO ==
1265 GNUNET_REST_handle_request (handle->rest_handle, handlers, &err,
1266 handle))
1267 {
1269 return GNUNET_NO;
1270 }
1271
1272 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
1273 return GNUNET_YES;
1274}
1275
1276
1283void *
1285{
1286 static struct Plugin plugin;
1287 struct GNUNET_REST_Plugin *api;
1288
1289 ns_cfg = c;
1290 if (NULL != plugin.cfg)
1291 return NULL; /* can only initialize once! */
1292 memset (&plugin, 0, sizeof(struct Plugin));
1293 plugin.cfg = c;
1294 api = GNUNET_new (struct GNUNET_REST_Plugin);
1295 api->cls = &plugin;
1299 "%s, %s, %s, %s, %s",
1300 MHD_HTTP_METHOD_GET,
1301 MHD_HTTP_METHOD_POST,
1302 MHD_HTTP_METHOD_PUT,
1303 MHD_HTTP_METHOD_DELETE,
1304 MHD_HTTP_METHOD_OPTIONS);
1307
1309 "Namestore REST API initialized\n"));
1310 return api;
1311}
1312
1313
1320void
1322{
1323 struct Plugin *plugin = api->cls;
1324 struct RequestHandle *request;
1325 struct EgoEntry *ego_entry;
1326 struct EgoEntry *ego_tmp;
1327
1328 plugin->cfg = NULL;
1329 while (NULL != (request = requests_head))
1330 do_error (request);
1331 if (NULL != identity_handle)
1333 if (NULL != ns_handle)
1335
1336 for (ego_entry = ego_head; NULL != ego_entry;)
1337 {
1338 ego_tmp = ego_entry;
1339 ego_entry = ego_entry->next;
1340 GNUNET_free (ego_tmp->identifier);
1341 GNUNET_free (ego_tmp->keystring);
1342 GNUNET_free (ego_tmp);
1343 }
1344
1346 GNUNET_free (api);
1347 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Namestore REST plugin is finished\n");
1348}
1349
1350
1351/* end of plugin_rest_namestore.c */
struct GNUNET_MQ_MessageHandlers handlers[]
Definition: 003.c:1
static struct GNUNET_TESTING_PluginFunctions * plugin
Plugin to dynamically load a test case.
static struct MHD_Response * response
Our canonical response.
struct GNUNET_HashCode key
The key used in the DHT.
static char * egoname
Ego Attribute String.
Definition: gnunet-did.c:92
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:100
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:33
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:379
#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:979
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:1303
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:1276
#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.
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_get(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle namestore GET request.
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.
static void namestore_add(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle namestore POST request.
static 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,...
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)
static void namestore_import(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle namestore POST import.
static char * allow_methods
HTTP methods allows for this plugin.
static void namestore_delete(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle namestore DELETE request.
static void create_finished(void *cls, enum GNUNET_ErrorCode ec)
static void namestore_add_or_update(struct GNUNET_REST_RequestHandle *con_handle, const char *url, void *cls)
Handle namestore POST/PUT request.
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.
#define GNUNET_REST_API_NS_NAMESTORE_IMPORT
Namestore import API namespace.
static 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.
static void do_error(void *cls)
Task run on errors.
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
void * cls
The closure of the plugin.
const char * name
Plugin name.
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:135
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:47
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:56
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:71
struct GNUNET_GNSRECORD_Data * rd
Records to store.
GNUNET_REST_ResultProcessor proc
The plugin result processor.
Definition: config_plugin.c:66
unsigned int rd_set_pos
Position of record info.
struct RequestHandle * next
DLL.
Definition: config_plugin.c:51
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:61
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:81
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