GNUnet  0.19.4
plugin_rest_namestore.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"
30 #include "gnunet_gns_service.h"
33 #include "gnunet_rest_lib.h"
35 #include "microhttpd.h"
36 #include <jansson.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 
65 static char *allow_methods;
66 
70 static struct EgoEntry *ego_head;
71 
75 static struct EgoEntry *ego_tail;
76 
80 static int state;
81 
86 
91 
95 struct Plugin
96 {
97  const struct GNUNET_CONFIGURATION_Handle *cfg;
98 };
99 
103 struct 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 {
136 };
137 
141 struct RequestHandle
142 {
146  struct RequestHandle *next;
147 
151  struct RequestHandle *prev;
152 
156  char *record_name;
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 
281 static void
282 cleanup_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 
329 static void
330 do_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 
339  emsg = GNUNET_ErrorCode_get_hint (handle->ec);
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 
366 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 
396 static void
398 {
399  struct RequestHandle *handle = cls;
400 
403  return;
404 }
405 
406 
407 static 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 
426 static void
427 del_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 
451 static 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 
483 static void
485  const struct GNUNET_IDENTITY_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 
532 static void
534 {
535  struct RequestHandle *handle = cls;
536 
539 }
540 
541 
542 static void
543 ns_get_lookup_cb (void *cls,
544  const struct GNUNET_IDENTITY_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 
585 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];
610  ego_entry = get_egoentry_namestore (handle, egoname);
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 
693 static void
694 ns_lookup_cb (void *cls,
695  const struct GNUNET_IDENTITY_PrivateKey *zone,
696  const char *label,
697  unsigned int rd_count,
698  const struct GNUNET_GNSRECORD_Data *rd)
699 {
700  struct RequestHandle *handle = cls;
701  struct GNUNET_GNSRECORD_Data rd_new[rd_count + handle->rd_count];
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 
728 static void
730 {
731  struct RequestHandle *handle = cls;
732  struct MHD_Response *resp;
733 
734  handle->ns_qe = NULL;
736  "Commit finished (%d)\n", ec);
737  handle->ec = ec;
738  if (GNUNET_EC_NONE != ec)
739  {
741  return;
742  }
743  resp = GNUNET_REST_create_response (NULL);
744  handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT);
746 }
747 
748 
749 static void
750 import_next_cb (void *cls, enum GNUNET_ErrorCode ec)
751 {
752  struct RequestHandle *handle = cls;
753 
755  "Import finished (%d)\n", ec);
756  handle->ns_qe = NULL;
757  handle->ec = ec;
758  if (GNUNET_EC_NONE != ec)
759  {
761  return;
762  }
763  unsigned int remaining = handle->rd_set_count - handle->rd_set_pos;
764  if (0 == remaining)
765  {
768  handle);
769  return;
770  }
771  unsigned int sent_rds = 0;
772  // Find the smallest set of records we can send with our message size
773  // restriction of 16 bit
775  handle->zone_pkey,
776  remaining,
777  &handle->ri[handle->
778  rd_set_pos],
779  &sent_rds,
781  handle);
782  if ((NULL == handle->ns_qe) && (0 == sent_rds))
783  {
786  return;
787  }
788  handle->rd_set_pos += sent_rds;
789 }
790 
791 static void
793 {
794  struct RequestHandle *handle = cls;
795  json_t *data_js;
796  json_error_t err;
797 
799  "Transaction started...\n");
800  handle->ec = ec;
801  if (GNUNET_EC_NONE != ec)
802  {
804  return;
805  }
806  if (0 >= handle->rest_handle->data_size)
807  {
810  return;
811  }
812  char term_data[handle->rest_handle->data_size + 1];
813  term_data[handle->rest_handle->data_size] = '\0';
814  GNUNET_memcpy (term_data,
815  handle->rest_handle->data,
816  handle->rest_handle->data_size);
817  data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
818  if (NULL == data_js)
819  {
822  "Error parsing data: %s", err.text);
824  return;
825  }
826  if (! json_is_array (data_js))
827  {
830  json_decref (data_js);
831  return;
832  }
833  handle->rd_set_count = json_array_size (data_js);
834  handle->ri = GNUNET_malloc (handle->rd_set_count
835  * sizeof (struct GNUNET_NAMESTORE_RecordInfo));
837  "Got record set of size %d\n", handle->rd_set_count);
838  char *albl;
839  size_t index;
840  json_t *value;
841  json_array_foreach (data_js, index, value) {
842  {
843  struct GNUNET_GNSRECORD_Data *rd;
844  struct GNUNET_JSON_Specification gnsspec[] =
846  &handle->ri[index].a_rd_count,
847  &albl),
849  if (GNUNET_OK != GNUNET_JSON_parse (value, gnsspec, NULL, NULL))
850  {
853  json_decref (data_js);
854  return;
855  }
856  handle->ri[index].a_rd = rd;
857  handle->ri[index].a_label = albl;
859  "Parsed record set for name %s\n",
860  handle->ri[index].a_label);
861  }
862  }
863  // json_decref (data_js);
864 
865  unsigned int sent_rds = 0;
866  // Find the smallest set of records we can send with our message size
867  // restriction of 16 bit
869  handle->zone_pkey,
870  handle->rd_set_count,
871  handle->ri,
872  &sent_rds,
874  handle);
875  if ((NULL == handle->ns_qe) && (0 == sent_rds))
876  {
879  return;
880  }
881  handle->rd_set_pos += sent_rds;
882 }
883 
884 
892 void
894  const char *url,
895  void *cls)
896 {
897  struct RequestHandle *handle = cls;
898  struct EgoEntry *ego_entry;
899  char *egoname;
900 
901  // set zone to name if given
902  if (strlen (GNUNET_REST_API_NS_NAMESTORE_IMPORT) + 1 >= strlen (
903  handle->url))
904  {
907  return;
908  }
909  ego_entry = NULL;
910 
911  egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE_IMPORT) + 1];
912  ego_entry = get_egoentry_namestore (handle, egoname);
913 
914  if (NULL == ego_entry)
915  {
918  return;
919  }
920  handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
921 
922  // We need a per-client connection for a transactional bulk import
924  if (NULL == handle->nc)
925  {
928  return;
929  }
931  &bulk_tx_start,
932  handle);
933 }
934 
942 void
944  const char *url,
945  void *cls)
946 {
947  struct RequestHandle *handle = cls;
948  struct EgoEntry *ego_entry;
949  char *egoname;
950  json_t *data_js;
951  json_error_t err;
952 
953  char term_data[handle->rest_handle->data_size + 1];
954 
955  if (0 >= handle->rest_handle->data_size)
956  {
959  return;
960  }
961  term_data[handle->rest_handle->data_size] = '\0';
962  GNUNET_memcpy (term_data,
963  handle->rest_handle->data,
964  handle->rest_handle->data_size);
965  data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
966  struct GNUNET_JSON_Specification gnsspec[] =
968  &handle->record_name),
970  if (GNUNET_OK != GNUNET_JSON_parse (data_js, gnsspec, NULL, NULL))
971  {
974  json_decref (data_js);
975  return;
976  }
977  GNUNET_JSON_parse_free (gnsspec);
978  if (0 >= strlen (handle->record_name))
979  {
982  json_decref (data_js);
983  return;
984  }
985  json_decref (data_js);
986 
987  egoname = NULL;
988  ego_entry = NULL;
989 
990  // set zone to name if given
991  if (strlen (GNUNET_REST_API_NS_NAMESTORE) + 1 >= strlen (handle->url))
992  {
995  return;
996  }
997  egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE) + 1];
998  ego_entry = get_egoentry_namestore (handle, egoname);
999 
1000  if (NULL == ego_entry)
1001  {
1004  return;
1005  }
1006  handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1008  handle->zone_pkey,
1009  handle->record_name,
1011  handle,
1012  &ns_lookup_cb,
1013  handle);
1014  if (NULL == handle->ns_qe)
1015  {
1018  return;
1019  }
1020 }
1021 
1022 
1030 void
1032  const char *url,
1033  void *cls)
1034 {
1035  struct RequestHandle *handle = cls;
1036  handle->update_strategy = UPDATE_STRATEGY_REPLACE;
1037  namestore_add_or_update (con_handle, url, cls);
1038 }
1039 
1040 
1048 void
1050  const char *url,
1051  void *cls)
1052 {
1053  struct RequestHandle *handle = cls;
1054  handle->update_strategy = UPDATE_STRATEGY_APPEND;
1055  namestore_add_or_update (con_handle, url, cls);
1056 }
1057 
1058 
1066 void
1068  const char *url,
1069  void *cls)
1070 {
1071  struct RequestHandle *handle = cls;
1072  struct EgoEntry *ego_entry;
1073  char *egoname;
1074  char *labelname;
1075 
1076  egoname = NULL;
1077  ego_entry = NULL;
1078 
1079  // set zone to name if given
1080  if (strlen (GNUNET_REST_API_NS_NAMESTORE) + 1 >= strlen (handle->url))
1081  {
1084  return;
1085  }
1086  egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE) + 1];
1087  ego_entry = get_egoentry_namestore (handle, egoname);
1088  if (NULL == ego_entry)
1089  {
1092  return;
1093  }
1094  handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
1095  labelname = &egoname[strlen (ego_entry->identifier)];
1096  // set zone to name if given
1097  if (1 >= strlen (labelname))
1098  {
1099  /* label is only "/" */
1102  }
1103 
1104  handle->record_name = GNUNET_strdup (labelname + 1);
1106  handle->zone_pkey,
1107  handle->record_name,
1108  0,
1109  NULL,
1110  &del_finished,
1111  handle);
1112  if (NULL == handle->ns_qe)
1113  {
1116  return;
1117  }
1118 }
1119 
1120 
1128 static void
1130  const char *url,
1131  void *cls)
1132 {
1133  struct MHD_Response *resp;
1134  struct RequestHandle *handle = cls;
1135 
1136  // independent of path return all options
1137  resp = GNUNET_REST_create_response (NULL);
1138  GNUNET_assert (MHD_YES ==
1139  MHD_add_response_header (resp,
1140  "Access-Control-Allow-Methods",
1141  allow_methods));
1142  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
1144  return;
1145 }
1146 
1147 
1148 static void
1149 list_ego (void *cls,
1150  struct GNUNET_IDENTITY_Ego *ego,
1151  void **ctx,
1152  const char *identifier)
1153 {
1154  struct EgoEntry *ego_entry;
1156 
1157  if ((NULL == ego) && (ID_REST_STATE_INIT == state))
1158  {
1160  return;
1161  }
1162  if (NULL == ego)
1163  {
1165  "Called with NULL ego\n");
1166  return;
1167  }
1168  if (ID_REST_STATE_INIT == state)
1169  {
1170  ego_entry = GNUNET_new (struct EgoEntry);
1173  ego_entry->ego = ego;
1174  ego_entry->identifier = GNUNET_strdup (identifier);
1176  ego_tail,
1177  ego_entry);
1178  }
1179  /* Ego renamed or added */
1180  if (identifier != NULL)
1181  {
1182  for (ego_entry = ego_head; NULL != ego_entry;
1183  ego_entry = ego_entry->next)
1184  {
1185  if (ego_entry->ego == ego)
1186  {
1187  /* Rename */
1188  GNUNET_free (ego_entry->identifier);
1189  ego_entry->identifier = GNUNET_strdup (identifier);
1190  break;
1191  }
1192  }
1193  if (NULL == ego_entry)
1194  {
1195  /* Add */
1196  ego_entry = GNUNET_new (struct EgoEntry);
1199  ego_entry->ego = ego;
1200  ego_entry->identifier = GNUNET_strdup (identifier);
1202  ego_tail,
1203  ego_entry);
1204  }
1205  }
1206  else
1207  {
1208  /* Delete */
1209  for (ego_entry = ego_head; NULL != ego_entry;
1210  ego_entry = ego_entry->next)
1211  {
1212  if (ego_entry->ego == ego)
1213  break;
1214  }
1215  if (NULL == ego_entry)
1216  return; /* Not found */
1217 
1219  ego_tail,
1220  ego_entry);
1221  GNUNET_free (ego_entry->identifier);
1222  GNUNET_free (ego_entry->keystring);
1223  GNUNET_free (ego_entry);
1224  return;
1225  }
1226 
1227 }
1228 
1229 
1241 static enum GNUNET_GenericReturnValue
1242 rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
1244  void *proc_cls)
1245 {
1246  struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1248  static const struct GNUNET_REST_RequestHandler handlers[] =
1249  { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE, &namestore_get },
1250  { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE_IMPORT,
1251  &namestore_import },
1252  { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE, &namestore_add },
1253  { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_NAMESTORE, &namestore_update },
1254  { MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_NAMESTORE,
1255  &namestore_delete },
1256  { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_NAMESTORE, &options_cont },
1258 
1259  handle->ec = GNUNET_EC_NONE;
1261  handle->proc_cls = proc_cls;
1262  handle->proc = proc;
1263  handle->rest_handle = rest_handle;
1264  handle->zone_pkey = NULL;
1265  handle->timeout_task =
1267  handle->url = GNUNET_strdup (rest_handle->url);
1268  if (handle->url[strlen (handle->url) - 1] == '/')
1269  handle->url[strlen (handle->url) - 1] = '\0';
1271  requests_tail,
1272  handle);
1273  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
1274  if (GNUNET_NO ==
1275  GNUNET_REST_handle_request (handle->rest_handle, handlers, &err,
1276  handle))
1277  {
1279  return GNUNET_NO;
1280  }
1281 
1282  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
1283  return GNUNET_YES;
1284 }
1285 
1286 
1293 void *
1295 {
1296  static struct Plugin plugin;
1297  struct GNUNET_REST_Plugin *api;
1298 
1299  cfg = cls;
1300  if (NULL != plugin.cfg)
1301  return NULL; /* can only initialize once! */
1302  memset (&plugin, 0, sizeof(struct Plugin));
1303  plugin.cfg = cfg;
1304  api = GNUNET_new (struct GNUNET_REST_Plugin);
1305  api->cls = &plugin;
1310  "%s, %s, %s, %s, %s",
1311  MHD_HTTP_METHOD_GET,
1312  MHD_HTTP_METHOD_POST,
1313  MHD_HTTP_METHOD_PUT,
1314  MHD_HTTP_METHOD_DELETE,
1315  MHD_HTTP_METHOD_OPTIONS);
1318 
1320  "Namestore REST API initialized\n"));
1321  return api;
1322 }
1323 
1324 
1331 void *
1333 {
1334  struct GNUNET_REST_Plugin *api = cls;
1335  struct Plugin *plugin = api->cls;
1336  struct RequestHandle *request;
1337  struct EgoEntry *ego_entry;
1338  struct EgoEntry *ego_tmp;
1339 
1340  plugin->cfg = NULL;
1341  while (NULL != (request = requests_head))
1342  do_error (request);
1343  if (NULL != identity_handle)
1345  if (NULL != ns_handle)
1347 
1348  for (ego_entry = ego_head; NULL != ego_entry;)
1349  {
1350  ego_tmp = ego_entry;
1351  ego_entry = ego_entry->next;
1352  GNUNET_free (ego_tmp->identifier);
1353  GNUNET_free (ego_tmp->keystring);
1354  GNUNET_free (ego_tmp);
1355  }
1356 
1358  GNUNET_free (api);
1359  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Namestore REST plugin is finished\n");
1360  return NULL;
1361 }
1362 
1363 
1364 /* end of plugin_rest_namestore.c */
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_UNKNOWN
Unknown namestore error.
@ GNUNET_EC_NAMESTORE_ZONE_EMPTY
Zone does not contain any records.
@ GNUNET_EC_NAMESTORE_RECORD_DATA_INVALID
Record data invalid.
@ GNUNET_EC_NAMESTORE_ITERATION_FAILED
Zone iteration failed.
@ GNUNET_EC_NAMESTORE_NO_RECORDS_GIVEN
No records given.
@ GNUNET_EC_NAMESTORE_NO_LABEL_GIVEN
No label given.
@ GNUNET_EC_NAMESTORE_LOOKUP_ERROR
Failed to lookup record.
@ GNUNET_EC_NONE
No error (success).
@ GNUNET_EC_NAMESTORE_RECORD_NOT_FOUND
Record not found.
@ GNUNET_EC_NAMESTORE_ZONE_NOT_FOUND
Zone not found.
static struct GNUNET_CADET_MessageHandler handlers[]
Handlers, for diverse services.
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:96
static struct GNUNET_DNS_Handle * handle
Handle to transport service.
struct GNUNET_IDENTITY_PrivateKey pk
Private key from command line option, or NULL.
static char * zone
Name of the zone being managed.
static const struct GNUNET_IDENTITY_PrivateKey * zone_key
Private key of the zone.
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_DNSSTUB_Context * ctx
Context for DNS resolution.
API to the GNS service.
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.
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.
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.
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_IDENTITY_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:560
void GNUNET_IDENTITY_ego_get_public_key(struct GNUNET_IDENTITY_Ego *ego, struct GNUNET_IDENTITY_PublicKey *pk)
Get the identifier (public key) of an ego.
Definition: identity_api.c:573
char * GNUNET_IDENTITY_public_key_to_string(const struct GNUNET_IDENTITY_PublicKey *key)
Creates a (Base32) string representation of the public key.
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:531
void GNUNET_IDENTITY_disconnect(struct GNUNET_IDENTITY_Handle *h)
Disconnect from identity service.
Definition: identity_api.c:757
#define GNUNET_log(kind,...)
#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_lookup2(struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_IDENTITY_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_store2(struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_IDENTITY_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.
void GNUNET_NAMESTORE_disconnect(struct GNUNET_NAMESTORE_Handle *h)
Disconnect from the namestore service (and free associated resources).
struct GNUNET_NAMESTORE_QueueEntry * GNUNET_NAMESTORE_records_lookup(struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_IDENTITY_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_transaction_begin(struct GNUNET_NAMESTORE_Handle *h, GNUNET_NAMESTORE_ContinuationWithStatus cont, void *cont_cls)
New API draft.
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_ZoneIterator * GNUNET_NAMESTORE_zone_iteration_start2(struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_IDENTITY_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_store(struct GNUNET_NAMESTORE_Handle *h, const struct GNUNET_IDENTITY_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.
struct GNUNET_NAMESTORE_Handle * GNUNET_NAMESTORE_connect(const struct GNUNET_CONFIGURATION_Handle *cfg)
Connect to the namestore service.
struct GNUNET_NAMESTORE_QueueEntry * GNUNET_NAMESTORE_transaction_commit(struct GNUNET_NAMESTORE_Handle *h, GNUNET_NAMESTORE_ContinuationWithStatus cont, void *cont_cls)
Commit a namestore transaction.
void GNUNET_NAMESTORE_zone_iteration_stop(struct GNUNET_NAMESTORE_ZoneIterator *it)
Stops iteration and releases the namestore handle for further calls.
struct MHD_Response * GNUNET_REST_create_response(const char *data)
Create REST MHD response.
Definition: rest.c:44
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 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:1299
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:975
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:1272
#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].
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
const char * name
static struct EgoEntry * ego_tail
Ego list.
static void ns_lookup_cb(void *cls, const struct GNUNET_IDENTITY_PrivateKey *zone, const char *label, unsigned int rd_count, const struct GNUNET_GNSRECORD_Data *rd)
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,...
#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.
static void bulk_tx_commit_cb(void *cls, enum GNUNET_ErrorCode ec)
@ UPDATE_STRATEGY_REPLACE
@ UPDATE_STRATEGY_APPEND
static void import_next_cb(void *cls, enum GNUNET_ErrorCode ec)
void * libgnunet_plugin_rest_namestore_done(void *cls)
Exit point from the plugin.
static void del_finished(void *cls, enum GNUNET_ErrorCode ec)
static void bulk_tx_start(void *cls, enum GNUNET_ErrorCode ec)
static struct GNUNET_NAMESTORE_Handle * ns_handle
Handle to NAMESTORE.
const struct GNUNET_CONFIGURATION_Handle * cfg
The configuration handle.
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.
static void namestore_list_iteration(void *cls, const struct GNUNET_IDENTITY_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.
#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.
static enum GNUNET_GenericReturnValue rest_process_request(struct GNUNET_REST_RequestHandle *rest_handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
Function processing the REST call.
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)
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 struct RequestHandle * requests_tail
DLL.
static struct GNUNET_IDENTITY_Handle * identity_handle
Handle to Identity service.
static void ns_get_lookup_cb(void *cls, const struct GNUNET_IDENTITY_PrivateKey *zone, const char *label, unsigned int rd_len, const struct GNUNET_GNSRECORD_Data *rd)
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 * libgnunet_plugin_rest_namestore_init(void *cls)
Entry point for the plugin.
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.
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.
The ego list.
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.
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
A private key for an identity as per LSD0001.
An identity key as per LSD0001.
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:53
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.
enum GNUNET_GenericReturnValue(* process_request)(struct GNUNET_REST_RequestHandle *handle, GNUNET_REST_ResultProcessor proc, void *proc_cls)
Function to process a REST call.
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.
const struct GNUNET_IDENTITY_PrivateKey * zone_pkey
Private key for the zone.
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.
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.
struct GNUNET_REST_RequestHandle * rest_handle
Rest connection.
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).