GNUnet 0.25.2-11-g84e94e98c
 
Loading...
Searching...
No Matches
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
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
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,
440 MHD_HTTP_NO_CONTENT);
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
486 zone_key,
487 const char *rname,
488 unsigned int rd_len,
489 const struct GNUNET_GNSRECORD_Data *rd,
490 struct GNUNET_TIME_Absolute expiry)
491{
492 struct RequestHandle *handle = cls;
493 struct GNUNET_GNSRECORD_Data rd_filtered[rd_len];
494 json_t *record_obj;
495 int i = 0;
496 int j = 0;
497
498 if (rd_len == 0)
499 {
502 return;
503 }
504
505 for (i = 0; i < rd_len; i++)
506 {
507 if ((GNUNET_GNSRECORD_TYPE_ANY != handle->record_type) &&
508 (rd[i].record_type != handle->record_type))
509 continue; /* Apply filter */
510 rd_filtered[j] = rd[i];
511 rd_filtered[j].data = rd[i].data;
512 j++;
513 }
515 if (j > 0)
516 {
517 if (NULL == handle->resp_object)
518 handle->resp_object = json_array ();
519 record_obj = GNUNET_GNSRECORD_JSON_from_gnsrecord (rname,
520 rd_filtered,
521 j);
522 json_array_append_new (handle->resp_object, record_obj);
523 }
525}
526
527
533static void
541
542
543static void
545 const struct GNUNET_CRYPTO_BlindablePrivateKey *zone,
546 const char *label,
547 unsigned int rd_len,
548 const struct GNUNET_GNSRECORD_Data *rd)
549{
550 struct RequestHandle *handle = cls;
551 struct GNUNET_GNSRECORD_Data rd_filtered[rd_len];
552 int i = 0;
553 int j = 0;
554
555 handle->ns_qe = NULL;
556 for (i = 0; i < rd_len; i++)
557 {
558 if ((GNUNET_GNSRECORD_TYPE_ANY != handle->record_type) &&
559 (rd[i].record_type != handle->record_type))
560 continue; /* Apply filter */
561 rd_filtered[j] = rd[i];
562 rd_filtered[j].data = rd[i].data;
563 j++;
564 }
566 if (j == 0)
567 {
570 return;
571 }
572 handle->resp_object = GNUNET_GNSRECORD_JSON_from_gnsrecord (label,
573 rd_filtered,
574 j);
576}
577
578
586static void
588 const char *url,
589 void *cls)
590{
591 struct RequestHandle *handle = cls;
592 struct EgoEntry *ego_entry;
593 struct GNUNET_HashCode key;
594 enum GNUNET_GNSRECORD_Filter filter_flags;
595 char *egoname;
596 char *labelname;
597 char *typename;
598 char *boolstring;
599
600 egoname = NULL;
601 ego_entry = NULL;
602
603 // set zone to name if given
604 if (strlen (GNUNET_REST_API_NS_NAMESTORE) + 1 >= strlen (handle->url))
605 {
608 return;
609 }
610 egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE) + 1];
612 if (NULL == ego_entry)
613 {
616 return;
617 }
618 handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
619
620 GNUNET_CRYPTO_hash ("record_type", strlen ("record_type"), &key);
621 handle->record_type = GNUNET_GNSRECORD_TYPE_ANY;
622 if (GNUNET_YES ==
624 {
625 typename = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map,
626 &key);
627 if (NULL != typename)
628 handle->record_type = GNUNET_GNSRECORD_typename_to_number (typename);
629 }
630 GNUNET_CRYPTO_hash ("omit_private", strlen ("omit_private"), &key);
631 filter_flags = GNUNET_GNSRECORD_FILTER_NONE;
632 if (GNUNET_YES ==
634 {
635 boolstring = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map,
636 &key);
637 if ((0 == strcmp (boolstring, "1")) ||
638 (0 == strcmp (boolstring, "yes")) ||
639 (0 == strcmp (boolstring, "true")))
641 }
642 GNUNET_CRYPTO_hash ("include_maintenance", strlen ("include_maintenance"),
643 &key);
644 if (GNUNET_YES ==
646 {
647 boolstring = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map,
648 &key);
649 if ((0 == strcmp (boolstring, "1")) ||
650 (0 == strcmp (boolstring, "yes")) ||
651 (0 == strcmp (boolstring, "true")))
653 }
654 labelname = &egoname[strlen (ego_entry->identifier)];
655 if (1 >= strlen (labelname))
656 {
657 /* Iterate over all records */
658 handle->list_it =
660 handle->zone_pkey,
662 handle,
664 handle,
666 handle,
667 filter_flags);
668 if (NULL == handle->list_it)
669 {
672 return;
673 }
674 return;
675 }
676 handle->record_name = GNUNET_strdup (labelname + 1);
678 handle->zone_pkey,
679 handle->record_name,
681 handle,
683 handle,
684 filter_flags);
685 if (NULL == handle->ns_qe)
686 {
689 return;
690 }
691}
692
693
694static void
695ns_lookup_cb (void *cls,
696 const struct GNUNET_CRYPTO_BlindablePrivateKey *zone,
697 const char *label,
698 unsigned int rd_count,
699 const struct GNUNET_GNSRECORD_Data *rd)
700{
701 struct RequestHandle *handle = cls;
703 int i = 0;
704 int j = 0;
705
706 if (UPDATE_STRATEGY_APPEND == handle->update_strategy)
707 {
708 for (i = 0; i < rd_count; i++)
709 rd_new[i] = rd[i];
710 }
711 for (j = 0; j < handle->rd_count; j++)
712 rd_new[i + j] = handle->rd[j];
714 handle->zone_pkey,
715 handle->record_name,
716 i + j,
717 rd_new,
719 handle);
720 if (NULL == handle->ns_qe)
721 {
724 return;
725 }
726}
727
728
729static void
731{
732 struct RequestHandle *handle = cls;
733 unsigned int remaining;
734
736 "Import finished (%d)\n", ec);
737 handle->ns_qe = NULL;
738 handle->ec = ec;
739 if (GNUNET_EC_NONE != ec)
740 {
742 return;
743 }
744 remaining = handle->rd_set_count - handle->rd_set_pos;
745 if (0 == remaining)
746 {
747 struct MHD_Response *resp;
748
749 handle->ns_qe = NULL;
751 "Commit finished (%d)\n", ec);
752 handle->ec = ec;
753 if (GNUNET_EC_NONE != ec)
754 {
756 return;
757 }
758 resp = GNUNET_REST_create_response (NULL);
759 handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT);
761 return;
762 }
763 {
764 unsigned int sent_rds = 0;
765 // Find the smallest set of records we can send with our message size
766 // restriction of 16 bit
768 handle->zone_pkey,
769 remaining,
770 &handle->ri[handle->
771 rd_set_pos],
772 &sent_rds,
774 handle);
775 if ((NULL == handle->ns_qe) && (0 == sent_rds))
776 {
779 return;
780 }
781 handle->rd_set_pos += sent_rds;
782 }
783}
784
785
786static void
788{
789 json_t *data_js;
790 json_error_t err;
791 char term_data[handle->rest_handle->data_size + 1];
792
794 "Transaction started...\n");
795 if (0 >= handle->rest_handle->data_size)
796 {
799 return;
800 }
801 term_data[handle->rest_handle->data_size] = '\0';
802 GNUNET_memcpy (term_data,
803 handle->rest_handle->data,
804 handle->rest_handle->data_size);
805 data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
806 if (NULL == data_js)
807 {
810 "Error parsing data: %s", err.text);
812 return;
813 }
814 if (! json_is_array (data_js))
815 {
818 json_decref (data_js);
819 return;
820 }
821 handle->rd_set_count = json_array_size (data_js);
822 handle->ri = GNUNET_malloc (handle->rd_set_count
823 * sizeof (struct GNUNET_NAMESTORE_RecordInfo));
825 "Got record set of size %d\n", handle->rd_set_count);
826 {
827 char *albl;
828 size_t index;
829 json_t *value;
830 json_array_foreach (data_js, index, value) {
831 {
833 struct GNUNET_JSON_Specification gnsspec[] =
835 &handle->ri[index].a_rd_count,
836 &albl),
838 if (GNUNET_OK != GNUNET_JSON_parse (value, gnsspec, NULL, NULL))
839 {
842 json_decref (data_js);
843 return;
844 }
845 handle->ri[index].a_rd = rd;
846 handle->ri[index].a_label = albl;
848 "Parsed record set for name %s\n",
849 handle->ri[index].a_label);
850 }
851 }
852 }
853 // json_decref (data_js);
854 {
855 unsigned int sent_rds = 0;
856 // Find the smallest set of records we can send with our message size
857 // restriction of 16 bit
859 handle->zone_pkey,
860 handle->rd_set_count,
861 handle->ri,
862 &sent_rds,
864 handle);
865 if ((NULL == handle->ns_qe) && (0 == sent_rds))
866 {
869 return;
870 }
871 handle->rd_set_pos += sent_rds;
872 }
873}
874
875
883static void
885 const char *url,
886 void *cls)
887{
888 struct RequestHandle *handle = cls;
889 struct EgoEntry *ego_entry;
890 char *egoname;
891
892 // set zone to name if given
893 if (strlen (GNUNET_REST_API_NS_NAMESTORE_IMPORT) + 1 >= strlen (
894 handle->url))
895 {
898 return;
899 }
900 ego_entry = NULL;
901
904
905 if (NULL == ego_entry)
906 {
909 return;
910 }
911 handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
912
913 // We need a per-client connection for a transactional bulk import
915 if (NULL == handle->nc)
916 {
919 return;
920 }
922}
923
924
932static void
934 const char *url,
935 void *cls)
936{
937 struct RequestHandle *handle = cls;
938 struct EgoEntry *ego_entry;
939 char *egoname;
940 json_t *data_js;
941 json_error_t err;
942
943 char term_data[handle->rest_handle->data_size + 1];
944
945 if (0 >= handle->rest_handle->data_size)
946 {
949 return;
950 }
951 term_data[handle->rest_handle->data_size] = '\0';
952 GNUNET_memcpy (term_data,
953 handle->rest_handle->data,
954 handle->rest_handle->data_size);
955 data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
956 struct GNUNET_JSON_Specification gnsspec[] =
958 &handle->record_name),
960 if (GNUNET_OK != GNUNET_JSON_parse (data_js, gnsspec, NULL, NULL))
961 {
964 json_decref (data_js);
965 return;
966 }
967 GNUNET_JSON_parse_free (gnsspec);
968 if (0 >= strlen (handle->record_name))
969 {
972 json_decref (data_js);
973 return;
974 }
975 json_decref (data_js);
976
977 egoname = NULL;
978 ego_entry = NULL;
979
980 // set zone to name if given
981 if (strlen (GNUNET_REST_API_NS_NAMESTORE) + 1 >= strlen (handle->url))
982 {
985 return;
986 }
987 egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE) + 1];
989
990 if (NULL == ego_entry)
991 {
994 return;
995 }
996 handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
998 handle->zone_pkey,
999 handle->record_name,
1001 handle,
1002 &ns_lookup_cb,
1003 handle);
1004 if (NULL == handle->ns_qe)
1005 {
1008 return;
1009 }
1010}
1011
1012
1020static void
1022 const char *url,
1023 void *cls)
1024{
1025 struct RequestHandle *handle = cls;
1026 handle->update_strategy = UPDATE_STRATEGY_REPLACE;
1027 namestore_add_or_update (con_handle, url, cls);
1028}
1029
1030
1038static void
1040 const char *url,
1041 void *cls)
1042{
1043 struct RequestHandle *handle = cls;
1044 handle->update_strategy = UPDATE_STRATEGY_APPEND;
1045 namestore_add_or_update (con_handle, url, cls);
1046}
1047
1048
1056static void
1058 const char *url,
1059 void *cls)
1060{
1061 struct RequestHandle *handle = cls;
1062 struct EgoEntry *ego_entry;
1063 char *egoname;
1064 char *labelname;
1065
1066 egoname = NULL;
1067 ego_entry = NULL;
1068
1069 // set zone to name if given
1070 if (strlen (GNUNET_REST_API_NS_NAMESTORE) + 1 >= strlen (handle->url))
1071 {
1074 return;
1075 }
1076 egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE) + 1];
1077 ego_entry = get_egoentry_namestore (handle, egoname);
1078 if (NULL == ego_entry)
1079 {
1082 return;
1083 }
1084 handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1085 labelname = &egoname[strlen (ego_entry->identifier)];
1086 // set zone to name if given
1087 if (1 >= strlen (labelname))
1088 {
1089 /* label is only "/" */
1092 }
1093
1094 handle->record_name = GNUNET_strdup (labelname + 1);
1096 handle->zone_pkey,
1097 handle->record_name,
1098 0,
1099 NULL,
1100 &del_finished,
1101 handle);
1102 if (NULL == handle->ns_qe)
1103 {
1106 return;
1107 }
1108}
1109
1110
1118static void
1120 const char *url,
1121 void *cls)
1122{
1123 struct MHD_Response *resp;
1124 struct RequestHandle *handle = cls;
1125
1126 // independent of path return all options
1127 resp = GNUNET_REST_create_response (NULL);
1128 GNUNET_assert (MHD_YES ==
1129 MHD_add_response_header (resp,
1130 "Access-Control-Allow-Methods",
1131 allow_methods));
1132 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1134 return;
1135}
1136
1137
1138static void
1139list_ego (void *cls,
1140 struct GNUNET_IDENTITY_Ego *ego,
1141 void **ctx,
1142 const char *identifier)
1143{
1144 struct EgoEntry *ego_entry;
1146
1147 if ((NULL == ego) && (ID_REST_STATE_INIT == state))
1148 {
1150 return;
1151 }
1152 if (NULL == ego)
1153 {
1155 "Called with NULL ego\n");
1156 return;
1157 }
1159 {
1160 ego_entry = GNUNET_new (struct EgoEntry);
1163 ego_entry->ego = ego;
1164 ego_entry->identifier = GNUNET_strdup (identifier);
1166 ego_tail,
1167 ego_entry);
1168 }
1169 /* Ego renamed or added */
1170 if (identifier != NULL)
1171 {
1172 for (ego_entry = ego_head; NULL != ego_entry;
1173 ego_entry = ego_entry->next)
1174 {
1175 if (ego_entry->ego == ego)
1176 {
1177 /* Rename */
1178 GNUNET_free (ego_entry->identifier);
1179 ego_entry->identifier = GNUNET_strdup (identifier);
1180 break;
1181 }
1182 }
1183 if (NULL == ego_entry)
1184 {
1185 /* Add */
1186 ego_entry = GNUNET_new (struct EgoEntry);
1189 ego_entry->ego = ego;
1190 ego_entry->identifier = GNUNET_strdup (identifier);
1192 ego_tail,
1193 ego_entry);
1194 }
1195 }
1196 else
1197 {
1198 /* Delete */
1199 for (ego_entry = ego_head; NULL != ego_entry;
1200 ego_entry = ego_entry->next)
1201 {
1202 if (ego_entry->ego == ego)
1203 break;
1204 }
1205 if (NULL == ego_entry)
1206 return; /* Not found */
1207
1209 ego_tail,
1210 ego_entry);
1211 GNUNET_free (ego_entry->identifier);
1212 GNUNET_free (ego_entry->keystring);
1213 GNUNET_free (ego_entry);
1214 return;
1215 }
1216
1217}
1218
1219
1233 struct GNUNET_REST_RequestHandle *rest_handle,
1235 void *proc_cls)
1236{
1237 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1239 static const struct GNUNET_REST_RequestHandler handlers[] =
1240 { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE, &namestore_get },
1241 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE_IMPORT,
1243 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE, &namestore_add },
1244 { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_NAMESTORE, &namestore_update },
1245 { MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_NAMESTORE,
1247 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_NAMESTORE, &options_cont },
1249
1250 handle->ec = GNUNET_EC_NONE;
1252 handle->proc_cls = proc_cls;
1253 handle->proc = proc;
1254 handle->rest_handle = rest_handle;
1255 handle->zone_pkey = NULL;
1256 handle->timeout_task =
1258 handle->url = GNUNET_strdup (rest_handle->url);
1259 if (handle->url[strlen (handle->url) - 1] == '/')
1260 handle->url[strlen (handle->url) - 1] = '\0';
1263 handle);
1264 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
1265 if (GNUNET_NO ==
1266 GNUNET_REST_handle_request (handle->rest_handle, handlers, &err,
1267 handle))
1268 {
1270 return GNUNET_NO;
1271 }
1272
1273 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
1274 return GNUNET_YES;
1275}
1276
1277
1284void *
1286{
1287 static struct Plugin plugin;
1288 struct GNUNET_REST_Plugin *api;
1289
1290 ns_cfg = c;
1291 if (NULL != plugin.cfg)
1292 return NULL; /* can only initialize once! */
1293 memset (&plugin, 0, sizeof(struct Plugin));
1294 plugin.cfg = c;
1295 api = GNUNET_new (struct GNUNET_REST_Plugin);
1296 api->cls = &plugin;
1300 "%s, %s, %s, %s, %s",
1301 MHD_HTTP_METHOD_GET,
1302 MHD_HTTP_METHOD_POST,
1303 MHD_HTTP_METHOD_PUT,
1304 MHD_HTTP_METHOD_DELETE,
1305 MHD_HTTP_METHOD_OPTIONS);
1308
1310 "Namestore REST API initialized\n"));
1311 return api;
1312}
1313
1314
1321void
1323{
1324 struct Plugin *plugin = api->cls;
1325 struct RequestHandle *request;
1326 struct EgoEntry *ego_entry;
1327 struct EgoEntry *ego_tmp;
1328
1329 plugin->cfg = NULL;
1330 while (NULL != (request = requests_head))
1331 do_error (request);
1332 if (NULL != identity_handle)
1334 if (NULL != ns_handle)
1336
1337 for (ego_entry = ego_head; NULL != ego_entry;)
1338 {
1339 ego_tmp = ego_entry;
1340 ego_entry = ego_entry->next;
1341 GNUNET_free (ego_tmp->identifier);
1342 GNUNET_free (ego_tmp->keystring);
1343 GNUNET_free (ego_tmp);
1344 }
1345
1347 GNUNET_free (api);
1348 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Namestore REST plugin is finished\n");
1349}
1350
1351
1352/* 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:93
static struct GNUNET_FS_Handle * ctx
struct GNUNET_CRYPTO_BlindablePrivateKey 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
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.
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:34
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:192
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.
void GNUNET_IDENTITY_ego_get_public_key(struct GNUNET_IDENTITY_Ego *ego, struct GNUNET_CRYPTO_BlindablePublicKey *pk)
Get the identifier (public key) of an ego.
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.
void GNUNET_IDENTITY_disconnect(struct GNUNET_IDENTITY_Handle *h)
Disconnect from identity service.
const struct GNUNET_CRYPTO_BlindablePrivateKey * GNUNET_IDENTITY_ego_get_private_key(const struct GNUNET_IDENTITY_Ego *ego)
Obtain the ECC key associated with a ego.
#define GNUNET_log(kind,...)
char * GNUNET_CRYPTO_blindable_public_key_to_string(const struct GNUNET_CRYPTO_BlindablePublicKey *key)
Creates a (Base32) string representation of the public key.
#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_QueueEntry * GNUNET_NAMESTORE_records_store(struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_BlindablePrivateKey *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_QueueEntry * GNUNET_NAMESTORE_record_set_store(struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_BlindablePrivateKey *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.
struct GNUNET_NAMESTORE_QueueEntry * GNUNET_NAMESTORE_records_lookup2(struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_BlindablePrivateKey *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.
void GNUNET_NAMESTORE_cancel(struct GNUNET_NAMESTORE_QueueEntry *qe)
Cancel a namestore operation.
struct GNUNET_NAMESTORE_ZoneIterator * GNUNET_NAMESTORE_zone_iteration_start2(struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_CRYPTO_BlindablePrivateKey *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_BlindablePrivateKey *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_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:980
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:1304
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:1277
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
static struct EgoEntry * ego_tail
Ego list.
#define GNUNET_REST_API_NS_NAMESTORE
Namestore namespace.
UpdateStrategy
@ UPDATE_STRATEGY_REPLACE
@ UPDATE_STRATEGY_APPEND
static void import_next_cb(void *cls, enum GNUNET_ErrorCode ec)
static void del_finished(void *cls, enum GNUNET_ErrorCode ec)
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 struct EgoEntry * ego_head
Ego list.
static void list_ego(void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *identifier)
static void ns_get_lookup_cb(void *cls, const struct GNUNET_CRYPTO_BlindablePrivateKey *zone, const char *label, unsigned int rd_len, const struct GNUNET_GNSRECORD_Data *rd)
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.
static void ns_lookup_cb(void *cls, const struct GNUNET_CRYPTO_BlindablePrivateKey *zone, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
const struct GNUNET_CONFIGURATION_Handle * ns_cfg
The configuration handle.
static void namestore_list_iteration(void *cls, const struct GNUNET_CRYPTO_BlindablePrivateKey *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 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:179
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.
Handle for an operation with the identity service.
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.
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: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.
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.
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.
struct GNUNET_GNSRECORD_Data * rd
Records to store.
GNUNET_REST_ResultProcessor proc
The plugin result processor.
unsigned int rd_set_pos
Position of record info.
struct RequestHandle * next
DLL.
enum UpdateStrategy update_strategy
How to update the record set.
uint32_t record_type
Record type filter.
json_t * resp_object
Response object.
const struct GNUNET_CRYPTO_BlindablePrivateKey * zone_pkey
Private key for the zone.
struct GNUNET_REST_RequestHandle * rest_handle
Handle to rest request.
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.
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