aboutsummaryrefslogtreecommitdiff
path: root/src/namestore
diff options
context:
space:
mode:
authorPhil <phil.buschmann@tum.de>2018-07-26 02:31:30 +0200
committerPhil <phil.buschmann@tum.de>2018-07-26 02:31:30 +0200
commitf7ca27a73e69a8c224d65768be3416ff1388c1d7 (patch)
tree7530a6def74a55885780285162b18b4c2b353380 /src/namestore
parentcc577a227d6a5ae8ef75e0fa91ef98ced2d2b743 (diff)
downloadgnunet-f7ca27a73e69a8c224d65768be3416ff1388c1d7.tar.gz
gnunet-f7ca27a73e69a8c224d65768be3416ff1388c1d7.zip
change namestore, json handling; fix identity, gns
Diffstat (limited to 'src/namestore')
-rw-r--r--src/namestore/plugin_rest_namestore.c225
-rw-r--r--src/namestore/plugin_rest_namestore2.c1229
2 files changed, 75 insertions, 1379 deletions
diff --git a/src/namestore/plugin_rest_namestore.c b/src/namestore/plugin_rest_namestore.c
index afe010b79..6924c53a4 100644
--- a/src/namestore/plugin_rest_namestore.c
+++ b/src/namestore/plugin_rest_namestore.c
@@ -36,11 +36,7 @@
36 36
37#define GNUNET_REST_SUBSYSTEM_NAMESTORE "namestore" 37#define GNUNET_REST_SUBSYSTEM_NAMESTORE "namestore"
38 38
39#define GNUNET_REST_JSON_NAMESTORE_RECORD_TYPE "record_type" 39#define GNUNET_REST_NAMESTORE_ERROR_UNKNOWN "Unknown Error"
40#define GNUNET_REST_JSON_NAMESTORE_VALUE "value"
41#define GNUNET_REST_JSON_NAMESTORE_EXPIRATION "expiration"
42#define GNUNET_REST_JSON_NAMESTORE_EXPIRED "expired"
43#define GNUNET_REST_ERROR_UNKNOWN "Unknown Error"
44 40
45#define GNUNET_REST_NAMESTORE_RD_COUNT 1 41#define GNUNET_REST_NAMESTORE_RD_COUNT 1
46 42
@@ -194,8 +190,6 @@ static void
194cleanup_handle (void *cls) 190cleanup_handle (void *cls)
195{ 191{
196 struct RequestHandle *handle = cls; 192 struct RequestHandle *handle = cls;
197 size_t index;
198 json_t *json_ego;
199 193
200 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 194 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
201 "Cleaning up\n"); 195 "Cleaning up\n");
@@ -239,10 +233,6 @@ cleanup_handle (void *cls)
239 233
240 if(NULL != handle->resp_object) 234 if(NULL != handle->resp_object)
241 { 235 {
242 json_array_foreach(handle->resp_object, index, json_ego )
243 {
244 json_decref (json_ego);
245 }
246 json_decref(handle->resp_object); 236 json_decref(handle->resp_object);
247 } 237 }
248 238
@@ -264,7 +254,7 @@ do_error (void *cls)
264 char *response; 254 char *response;
265 255
266 if (NULL == handle->emsg) 256 if (NULL == handle->emsg)
267 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_UNKNOWN); 257 handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_ERROR_UNKNOWN);
268 258
269 json_object_set_new(json_error,"error", json_string(handle->emsg)); 259 json_object_set_new(json_error,"error", json_string(handle->emsg));
270 260
@@ -286,66 +276,10 @@ namestore_iteration_error (void *cls)
286{ 276{
287 struct RequestHandle *handle = cls; 277 struct RequestHandle *handle = cls;
288 struct MHD_Response *resp = GNUNET_REST_create_response (NULL); 278 struct MHD_Response *resp = GNUNET_REST_create_response (NULL);
289 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; 279 handle->proc (handle->proc_cls, resp, MHD_HTTP_INTERNAL_SERVER_ERROR);
290 handle->proc (handle->proc_cls, resp, handle->response_code);
291 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); 280 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
292} 281}
293 282
294/**
295 * Create json representation of a GNSRECORD
296 *
297 * @param rd the GNSRECORD_Data
298 */
299static json_t *
300gnsrecord_to_json (const struct GNUNET_GNSRECORD_Data *rd)
301{
302 const char *typename;
303 char *string_val;
304 const char *exp_str;
305 json_t *record_obj;
306
307 typename = GNUNET_GNSRECORD_number_to_typename (rd->record_type);
308 string_val = GNUNET_GNSRECORD_value_to_string (rd->record_type,
309 rd->data,
310 rd->data_size);
311
312 if (NULL == string_val)
313 {
314 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
315 "Record of type %d malformed, skipping\n",
316 (int) rd->record_type);
317 return NULL;
318 }
319 record_obj = json_object();
320 json_object_set_new (record_obj,
321 GNUNET_REST_JSON_NAMESTORE_RECORD_TYPE,
322 json_string (typename));
323 json_object_set_new (record_obj,
324 GNUNET_REST_JSON_NAMESTORE_VALUE,
325 json_string (string_val));
326 //GNUNET_free (string_val);
327
328 if (GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION & rd->flags)
329 {
330 struct GNUNET_TIME_Relative time_rel;
331 time_rel.rel_value_us = rd->expiration_time;
332 exp_str = GNUNET_STRINGS_relative_time_to_string (time_rel, 1);
333 }
334 else
335 {
336 struct GNUNET_TIME_Absolute time_abs;
337 time_abs.abs_value_us = rd->expiration_time;
338 exp_str = GNUNET_STRINGS_absolute_time_to_string (time_abs);
339 }
340 json_object_set_new (record_obj,
341 GNUNET_REST_JSON_NAMESTORE_EXPIRATION,
342 json_string (exp_str));
343 json_object_set_new (record_obj, "expired",
344 json_boolean (GNUNET_YES == GNUNET_GNSRECORD_is_expired (rd)));
345 return record_obj;
346}
347
348
349static void 283static void
350create_finished (void *cls, int32_t success, const char *emsg) 284create_finished (void *cls, int32_t success, const char *emsg)
351{ 285{
@@ -364,6 +298,29 @@ create_finished (void *cls, int32_t success, const char *emsg)
364 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); 298 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
365} 299}
366 300
301static void
302del_finished (void *cls, int32_t success, const char *emsg)
303{
304 struct RequestHandle *handle = cls;
305
306 handle->add_qe = NULL;
307 if (GNUNET_NO == success)
308 {
309 handle->emsg = GNUNET_strdup("Deleting record failed. Record does not exist");
310 GNUNET_SCHEDULER_add_now (&do_error, handle);
311 return;
312 }
313 if (GNUNET_SYSERR == success)
314 {
315 handle->emsg = GNUNET_strdup("Deleting record failed");
316 GNUNET_SCHEDULER_add_now (&do_error, handle);
317 return;
318 }
319 handle->proc (handle->proc_cls,
320 GNUNET_REST_create_response (NULL),
321 MHD_HTTP_NO_CONTENT);
322 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
323}
367/** 324/**
368 * Iteration over all results finished, build final 325 * Iteration over all results finished, build final
369 * response. 326 * response.
@@ -379,10 +336,8 @@ namestore_list_finished (void *cls)
379 336
380 handle->list_it = NULL; 337 handle->list_it = NULL;
381 338
382 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "HEY\n");
383 if (NULL == handle->resp_object) 339 if (NULL == handle->resp_object)
384 { 340 {
385 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "OH\n");
386 GNUNET_SCHEDULER_add_now (&do_error, handle); 341 GNUNET_SCHEDULER_add_now (&do_error, handle);
387 return; 342 return;
388 } 343 }
@@ -415,9 +370,6 @@ namestore_list_iteration (void *cls,
415 if (NULL == handle->resp_object) 370 if (NULL == handle->resp_object)
416 handle->resp_object = json_array(); 371 handle->resp_object = json_array();
417 372
418 char *result_str = json_dumps (handle->resp_object, 0);
419 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "%s\n", result_str);
420 GNUNET_free(result_str);
421 /*if ( (NULL != handle->ego_entry->identifier) && 373 /*if ( (NULL != handle->ego_entry->identifier) &&
422 (0 != strcmp (handle->ego_entry->identifier, 374 (0 != strcmp (handle->ego_entry->identifier,
423 rname)) ) 375 rname)) )
@@ -435,13 +387,12 @@ namestore_list_iteration (void *cls,
435 (0 != strcmp (rname, GNUNET_GNS_EMPTY_LABEL_AT)) ) 387 (0 != strcmp (rname, GNUNET_GNS_EMPTY_LABEL_AT)) )
436 continue; 388 continue;
437 389
438 record_obj = gnsrecord_to_json (&rd[i]); 390 record_obj = GNUNET_JSON_from_gns_record(rname,rd);
439 391
440 if(NULL == record_obj) 392 if(NULL == record_obj)
441 continue; 393 continue;
442 394
443 json_array_append (handle->resp_object, 395 json_array_append (handle->resp_object, record_obj);
444 record_obj);
445 json_decref (record_obj); 396 json_decref (record_obj);
446 } 397 }
447 398
@@ -477,73 +428,7 @@ namestore_get (struct GNUNET_REST_RequestHandle *con_handle,
477 &namestore_list_finished, 428 &namestore_list_finished,
478 handle); 429 handle);
479} 430}
480/*
481 431
482//TODO filter input
483static int
484json_to_gnsrecord (struct RequestHandle *handle)
485{
486 struct GNUNET_TIME_Relative etime_rel;
487 struct GNUNET_TIME_Absolute etime_abs;
488 void *rdata;
489 size_t rdata_size;
490
491 handle->rd = GNUNET_new_array(GNUNET_REST_NAMESTORE_RD_COUNT,
492 struct GNUNET_GNSRECORD_Data);
493 memset (handle->rd, 0, sizeof(struct GNUNET_GNSRECORD_Data));
494 handle->rd->record_type = GNUNET_GNSRECORD_typename_to_number (
495 handle->json_data->type);
496 if (UINT32_MAX == (*handle->rd).record_type)
497 {
498 handle->emsg = GNUNET_strdup("Unsupported type");
499 return GNUNET_SYSERR;
500 }
501 if (GNUNET_OK
502 != GNUNET_GNSRECORD_string_to_value ((*handle->rd).record_type,
503 handle->json_data->value, &rdata,
504 &rdata_size))
505 {
506 handle->emsg = GNUNET_strdup("Value invalid for record type");
507 return GNUNET_SYSERR;
508 }
509 (*handle->rd).data = rdata;
510 (*handle->rd).data_size = rdata_size;
511 //TODO other flags
512 if (0 == handle->json_data->is_public)
513 {
514 handle->rd->flags |= GNUNET_GNSRECORD_RF_PRIVATE;
515 }
516 /**TODO
517 * if (1 == handle->is_shadow)
518 rde->flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD;
519 if (1 != handle->is_public)
520 rde->flags |= GNUNET_GNSRECORD_RF_PRIVATE;
521 *
522 if (0 == strcmp (handle->json_data->expiration_time, "never"))
523 {
524 (*handle->rd).expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
525 }
526 else if (GNUNET_OK
527 == GNUNET_STRINGS_fancy_time_to_relative (
528 handle->json_data->expiration_time, &etime_rel))
529 {
530 (*handle->rd).expiration_time = etime_rel.rel_value_us;
531 (*handle->rd).flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
532 }
533 else if (GNUNET_OK
534 == GNUNET_STRINGS_fancy_time_to_absolute (
535 handle->json_data->expiration_time, &etime_abs))
536 {
537 (*handle->rd).expiration_time = etime_abs.abs_value_us;
538 }
539 else
540 {
541 handle->emsg = GNUNET_strdup("Value invalid for record type");
542 return GNUNET_SYSERR;
543 }
544 return GNUNET_OK;
545}
546*/
547 432
548/** 433/**
549 * We're storing a new record; this requires 434 * We're storing a new record; this requires
@@ -564,12 +449,11 @@ create_new_record_cont (void *cls,
564{ 449{
565 struct RequestHandle *handle = cls; 450 struct RequestHandle *handle = cls;
566 451
567
568 handle->add_qe = NULL; 452 handle->add_qe = NULL;
569 if (0 != strcmp (rec_name, handle->label_name)) 453 if (0 != strcmp (rec_name, handle->label_name))
570 { 454 {
571 GNUNET_break (0); 455 GNUNET_break (0);
572 do_error (handle); 456 GNUNET_SCHEDULER_add_now (&do_error, handle);
573 return; 457 return;
574 } 458 }
575 459
@@ -656,6 +540,31 @@ namestore_add (struct GNUNET_REST_RequestHandle *con_handle,
656} 540}
657 541
658 542
543static void
544del_cont (void *cls,
545 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
546 const char *label,
547 unsigned int rd_count,
548 const struct GNUNET_GNSRECORD_Data *rd)
549{
550 struct RequestHandle *handle = cls;
551
552 handle->add_qe = NULL;
553 if (0 == rd_count)
554 {
555 handle->emsg = GNUNET_strdup("Record not found");
556 GNUNET_SCHEDULER_add_now (&do_error, handle);
557 return;
558 }
559
560 handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle,
561 &handle->zone_pkey,
562 handle->label_name,
563 0, NULL,
564 &del_finished,
565 handle);
566}
567
659/** 568/**
660 * Handle namestore DELETE request 569 * Handle namestore DELETE request
661 * 570 *
@@ -669,12 +578,28 @@ namestore_delete (struct GNUNET_REST_RequestHandle *con_handle,
669 void *cls) 578 void *cls)
670{ 579{
671 struct RequestHandle *handle = cls; 580 struct RequestHandle *handle = cls;
581 struct GNUNET_HashCode key;
582
583 GNUNET_CRYPTO_hash ("label", strlen ("label"), &key);
584 if ( GNUNET_NO
585 == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map,
586 &key))
587 {
588 handle->emsg = GNUNET_strdup("Missing name");
589 GNUNET_SCHEDULER_add_now (&do_error, handle);
590 return;
591 }
592 handle->label_name = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map,
593 &key);
672 594
673 //TODO add behaviour and response 595 handle->add_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle,
674 596 &handle->zone_pkey,
675 handle->emsg = GNUNET_strdup ("Not implemented yet"); 597 handle->label_name,
676 GNUNET_SCHEDULER_add_now (&do_error, handle); 598 &do_error,
677 return; 599 handle,
600 &del_cont,
601 handle);
602
678} 603}
679 604
680 605
diff --git a/src/namestore/plugin_rest_namestore2.c b/src/namestore/plugin_rest_namestore2.c
deleted file mode 100644
index ec44046e0..000000000
--- a/src/namestore/plugin_rest_namestore2.c
+++ /dev/null
@@ -1,1229 +0,0 @@
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/**
19 * @author Martin Schanzenbach
20 * @file namestore/plugin_rest_namestore.c
21 * @brief GNUnet Namestore REST plugin
22 *
23 */
24
25#include "platform.h"
26#include "gnunet_rest_plugin.h"
27#include "gnunet_gns_service.h"
28#include "gnunet_namestore_service.h"
29#include "gnunet_identity_service.h"
30#include "gnunet_rest_lib.h"
31#include "gnunet_jsonapi_lib.h"
32#include "gnunet_jsonapi_util.h"
33#include "microhttpd.h"
34#include <jansson.h>
35
36#define GNUNET_REST_API_NS_NAMESTORE "/names"
37
38#define GNUNET_REST_API_NS_NAMESTORE_ZKEY "/names/zkey"
39
40#define GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO "record"
41
42#define GNUNET_REST_JSONAPI_NAMESTORE_NAME "name"
43
44#define GNUNET_REST_JSONAPI_NAMESTORE_REVINFO "revinfo"
45
46#define GNUNET_REST_JSONAPI_NAMESTORE_RECORD GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO
47
48#define GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE "record_type"
49
50#define GNUNET_REST_JSONAPI_NAMESTORE_VALUE "value"
51
52#define GNUNET_REST_JSONAPI_NAMESTORE_PUBLIC "public"
53
54#define GNUNET_REST_JSONAPI_NAMESTORE_SHADOW "shadow"
55
56#define GNUNET_REST_JSONAPI_NAMESTORE_PKEY "pkey"
57
58#define GNUNET_REST_JSONAPI_NAMESTORE_ZKEY "zkey"
59
60#define GNUNET_REST_JSONAPI_NAMESTORE_EXPIRATION "expiration"
61
62#define GNUNET_REST_JSONAPI_NAMESTORE_EGO "ego"
63
64/**
65 * @brief struct returned by the initialization function of the plugin
66 */
67struct Plugin
68{
69 const struct GNUNET_CONFIGURATION_Handle *cfg;
70};
71
72
73/**
74 * HTTP methods allows for this plugin
75 */
76static char* allow_methods;
77
78const struct GNUNET_CONFIGURATION_Handle *cfg;
79
80struct RecordEntry
81{
82 /**
83 * DLL
84 */
85 struct RecordEntry *next;
86
87 /**
88 * DLL
89 */
90 struct RecordEntry *prev;
91
92};
93
94struct RequestHandle
95{
96 /**
97 * Ego list
98 */
99 struct RecordEntry *record_head;
100
101 /**
102 * Ego list
103 */
104 struct record_entry *record_tail;
105
106 /**
107 * JSON response object
108 */
109 struct GNUNET_JSONAPI_Document *resp_object;
110
111 /**
112 * Rest connection
113 */
114 struct GNUNET_REST_RequestHandle *rest_handle;
115
116 /**
117 * Handle to GNS service.
118 */
119 struct GNUNET_IDENTITY_Handle *identity_handle;
120
121 /**
122 * Handle to NAMESTORE
123 */
124 struct GNUNET_NAMESTORE_Handle *ns_handle;
125
126 /**
127 * Handle to NAMESTORE it
128 */
129 struct GNUNET_NAMESTORE_ZoneIterator *list_it;
130
131 /**
132 * Private key for the zone
133 */
134 struct GNUNET_CRYPTO_EcdsaPrivateKey zone_pkey;
135
136 /**
137 * Handle to identity lookup
138 */
139 struct GNUNET_IDENTITY_EgoLookup *ego_lookup;
140
141 /**
142 * Default Ego operation
143 */
144 struct GNUNET_IDENTITY_Operation *get_default;
145
146 /**
147 * Name of the ego
148 */
149 char *ego_name;
150
151 /**
152 * Record is public
153 */
154 int is_public;
155
156 /**
157 * Shadow record
158 */
159 int is_shadow;
160
161 /**
162 * Name of the record to modify
163 */
164 char *name;
165
166 /**
167 * Value of the record
168 */
169 char *value;
170
171 /**
172 * Zkey string
173 */
174 const char* zkey_str;
175
176 /**
177 * record type
178 */
179 uint32_t type;
180
181 /**
182 * Records to store
183 */
184 struct GNUNET_GNSRECORD_Data *rd;
185
186 /**
187 * record count
188 */
189 unsigned int rd_count;
190
191 /**
192 * NAMESTORE Operation
193 */
194 struct GNUNET_NAMESTORE_QueueEntry *add_qe;
195
196 /**
197 * NAMESTORE Operation
198 */
199 struct GNUNET_NAMESTORE_QueueEntry *reverse_qe;
200
201 /**
202 * Desired timeout for the lookup (default is no timeout).
203 */
204 struct GNUNET_TIME_Relative timeout;
205
206 /**
207 * ID of a task associated with the resolution process.
208 */
209 struct GNUNET_SCHEDULER_Task * timeout_task;
210
211 /**
212 * The plugin result processor
213 */
214 GNUNET_REST_ResultProcessor proc;
215
216 /**
217 * The closure of the result processor
218 */
219 void *proc_cls;
220
221 /**
222 * The url
223 */
224 char *url;
225
226 /**
227 * Cfg
228 */
229 const struct GNUNET_CONFIGURATION_Handle *cfg;
230
231 /**
232 * HTTP response code
233 */
234 int response_code;
235
236};
237
238
239/**
240 * Cleanup lookup handle
241 *
242 * @param handle Handle to clean up
243 */
244static void
245cleanup_handle (struct RequestHandle *handle)
246{
247 struct RecordEntry *record_entry;
248 struct RecordEntry *record_tmp;
249
250 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
251 "Cleaning up\n");
252 if (NULL != handle->resp_object)
253 GNUNET_JSONAPI_document_delete (handle->resp_object);
254 if (NULL != handle->name)
255 GNUNET_free (handle->name);
256 if (NULL != handle->timeout_task)
257 GNUNET_SCHEDULER_cancel (handle->timeout_task);
258 if (NULL != handle->ego_lookup)
259 GNUNET_IDENTITY_ego_lookup_cancel (handle->ego_lookup);
260 if (NULL != handle->get_default)
261 GNUNET_IDENTITY_cancel (handle->get_default);
262 if (NULL != handle->list_it)
263 GNUNET_NAMESTORE_zone_iteration_stop (handle->list_it);
264 if (NULL != handle->add_qe)
265 GNUNET_NAMESTORE_cancel (handle->add_qe);
266 if (NULL != handle->identity_handle)
267 GNUNET_IDENTITY_disconnect (handle->identity_handle);
268 if (NULL != handle->ns_handle)
269 GNUNET_NAMESTORE_disconnect (handle->ns_handle);
270 if (NULL != handle->url)
271 GNUNET_free (handle->url);
272 if (NULL != handle->value)
273 GNUNET_free (handle->value);
274 if (NULL != handle->rd)
275 {
276 for (unsigned int i = 0; i < handle->rd_count; i++)
277 {
278 if (NULL != handle->rd[i].data)
279 GNUNET_free ((void*)handle->rd[i].data);
280 }
281 GNUNET_free (handle->rd);
282 }
283 if (NULL != handle->ego_name)
284 GNUNET_free (handle->ego_name);
285 for (record_entry = handle->record_head;
286 NULL != record_entry;)
287 {
288 record_tmp = record_entry;
289 record_entry = record_entry->next;
290 GNUNET_free (record_tmp);
291 }
292 GNUNET_free (handle);
293}
294
295
296/**
297 * Create json representation of a GNSRECORD
298 *
299 * @param rd the GNSRECORD_Data
300 */
301static json_t *
302gnsrecord_to_json (const struct GNUNET_GNSRECORD_Data *rd)
303{
304 const char *typename;
305 char *string_val;
306 const char *exp_str;
307 json_t *record_obj;
308
309 typename = GNUNET_GNSRECORD_number_to_typename (rd->record_type);
310 string_val = GNUNET_GNSRECORD_value_to_string (rd->record_type,
311 rd->data,
312 rd->data_size);
313
314 if (NULL == string_val)
315 {
316 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
317 "Record of type %d malformed, skipping\n",
318 (int) rd->record_type);
319 return NULL;
320 }
321 record_obj = json_object();
322 json_object_set_new (record_obj,
323 GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE,
324 json_string (typename));
325 json_object_set_new (record_obj,
326 GNUNET_REST_JSONAPI_NAMESTORE_VALUE,
327 json_string (string_val));
328 GNUNET_free (string_val);
329
330 if (GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION & rd->flags)
331 {
332 struct GNUNET_TIME_Relative time_rel;
333 time_rel.rel_value_us = rd->expiration_time;
334 exp_str = GNUNET_STRINGS_relative_time_to_string (time_rel, 1);
335 }
336 else
337 {
338 struct GNUNET_TIME_Absolute time_abs;
339 time_abs.abs_value_us = rd->expiration_time;
340 exp_str = GNUNET_STRINGS_absolute_time_to_string (time_abs);
341 }
342 json_object_set_new (record_obj, GNUNET_REST_JSONAPI_NAMESTORE_EXPIRATION, json_string (exp_str));
343
344 json_object_set_new (record_obj, "expired",
345 json_boolean (GNUNET_YES == GNUNET_GNSRECORD_is_expired (rd)));
346 return record_obj;
347}
348
349
350/**
351 * Task run on error. Generates error response and cleans up.
352 *
353 * @param cls the request to generate an error response for
354 */
355static void
356do_error (void *cls)
357{
358 struct RequestHandle *handle = cls;
359 struct MHD_Response *resp = GNUNET_REST_create_response (NULL);
360
361 handle->proc (handle->proc_cls, resp, handle->response_code);
362 cleanup_handle (handle);
363}
364
365
366/**
367 * Task run on timeout.
368 *
369 * @param cls the request to time out
370 */
371static void
372do_timeout (void *cls)
373{
374 struct RequestHandle *handle = cls;
375
376 handle->timeout_task = NULL;
377 do_error (handle);
378}
379
380
381static void
382cleanup_handle_delayed (void *cls)
383{
384 cleanup_handle (cls);
385}
386
387
388/**
389 * Iteration over all results finished, build final
390 * response.
391 *
392 * @param cls the `struct RequestHandle`
393 */
394static void
395namestore_list_finished (void *cls)
396{
397 struct RequestHandle *handle = cls;
398 char *result;
399 struct MHD_Response *resp;
400
401 handle->list_it = NULL;
402 if (NULL == handle->resp_object)
403 handle->resp_object = GNUNET_JSONAPI_document_new ();
404
405 if (GNUNET_SYSERR ==
406 GNUNET_JSONAPI_document_serialize (handle->resp_object,
407 &result))
408 {
409 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
410 GNUNET_SCHEDULER_add_now (&do_error,
411 handle);
412 return;
413 }
414 resp = GNUNET_REST_create_response (result);
415 handle->proc (handle->proc_cls,
416 resp,
417 MHD_HTTP_OK);
418 GNUNET_free_non_null (result);
419 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed,
420 handle);
421}
422
423
424
425/**
426 * Create a response with requested records
427 *
428 * @param handle the RequestHandle
429 */
430static void
431namestore_list_response (void *cls,
432 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
433 const char *rname,
434 unsigned int rd_len,
435 const struct GNUNET_GNSRECORD_Data *rd)
436{
437 struct RequestHandle *handle = cls;
438 struct GNUNET_JSONAPI_Resource *json_resource;
439 json_t *result_array;
440 json_t *record_obj;
441
442 if (NULL == handle->resp_object)
443 handle->resp_object = GNUNET_JSONAPI_document_new ();
444
445 if ( (NULL != handle->name) &&
446 (0 != strcmp (handle->name,
447 rname)) )
448 {
449 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
450 "%s does not match %s\n",
451 rname,
452 handle->name);
453 GNUNET_NAMESTORE_zone_iterator_next (handle->list_it,
454 1);
455 return;
456 }
457
458 result_array = json_array ();
459 for (unsigned int i=0; i<rd_len; i++)
460 {
461 if ( (GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type) &&
462 (0 != strcmp (rname, GNUNET_GNS_EMPTY_LABEL_AT)) )
463 continue;
464
465 if ( (rd[i].record_type != handle->type) &&
466 (GNUNET_GNSRECORD_TYPE_ANY != handle->type) )
467 continue;
468 record_obj = gnsrecord_to_json (&rd[i]);
469 json_array_append (result_array,
470 record_obj);
471 json_decref (record_obj);
472 }
473
474 if (0 < json_array_size(result_array))
475 {
476 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO,
477 rname);
478 GNUNET_JSONAPI_resource_add_attr (json_resource,
479 GNUNET_REST_JSONAPI_NAMESTORE_RECORD,
480 result_array);
481 GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
482 }
483
484 json_decref (result_array);
485 GNUNET_NAMESTORE_zone_iterator_next (handle->list_it,
486 1);
487}
488
489
490static void
491create_finished (void *cls, int32_t success, const char *emsg)
492{
493 struct RequestHandle *handle = cls;
494 struct MHD_Response *resp;
495
496 handle->add_qe = NULL;
497 if (GNUNET_YES != success)
498 {
499 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
500 "Error storing records%s%s\n",
501 (NULL == emsg) ? "" : ": ",
502 (NULL == emsg) ? "" : emsg);
503 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
504 return;
505 }
506 resp = GNUNET_REST_create_response (NULL);
507 handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT);
508 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
509}
510
511
512/**
513 * We're storing a new record; this requires
514 * that no record already exists
515 *
516 * @param cls closure, unused
517 * @param zone_key private key of the zone
518 * @param rec_name name that is being mapped (at most 255 characters long)
519 * @param rd_count number of entries in @a rd array
520 * @param rd array of records with data to store
521 */
522static void
523create_new_record_cont (void *cls,
524 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key,
525 const char *rec_name,
526 unsigned int rd_count,
527 const struct GNUNET_GNSRECORD_Data *rd)
528{
529 struct RequestHandle *handle = cls;
530
531 handle->add_qe = NULL;
532 if (0 != strcmp (rec_name, handle->name))
533 {
534 GNUNET_break (0);
535 do_error (handle);
536 return;
537 }
538
539 if (0 != rd_count)
540 {
541 handle->proc (handle->proc_cls,
542 GNUNET_REST_create_response (NULL),
543 MHD_HTTP_CONFLICT);
544 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
545 return;
546 }
547
548 GNUNET_assert (NULL != handle->name);
549 handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle,
550 &handle->zone_pkey,
551 handle->name,
552 handle->rd_count,
553 handle->rd,
554 &create_finished,
555 handle);
556}
557
558
559static void
560del_finished (void *cls,
561 int32_t success,
562 const char *emsg)
563{
564 struct RequestHandle *handle = cls;
565
566 handle->add_qe = NULL;
567 if (GNUNET_NO == success)
568 {
569 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
570 _("Deleting record failed, record does not exist%s%s\n"),
571 (NULL != emsg) ? ": " : "",
572 (NULL != emsg) ? emsg : "");
573 GNUNET_SCHEDULER_add_now (&do_error, handle); //do_not_found TODO
574 return;
575 }
576 if (GNUNET_SYSERR == success)
577 {
578 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
579 _("Deleting record failed%s%s\n"),
580 (NULL != emsg) ? ": " : "",
581 (NULL != emsg) ? emsg : "");
582 GNUNET_SCHEDULER_add_now (&do_error, handle);
583 return;
584 }
585 handle->proc (handle->proc_cls,
586 GNUNET_REST_create_response (NULL),
587 MHD_HTTP_NO_CONTENT);
588 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
589}
590
591
592static void
593del_cont (void *cls,
594 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
595 const char *label,
596 unsigned int rd_count,
597 const struct GNUNET_GNSRECORD_Data *rd)
598{
599 struct RequestHandle *handle = cls;
600
601 handle->add_qe = NULL;
602 if (0 == rd_count)
603 {
604 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
605 _("There are no records under label `%s' that could be deleted.\n"),
606 label);
607 do_error (handle);
608 return;
609 }
610
611 handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle,
612 &handle->zone_pkey,
613 handle->name,
614 0, NULL,
615 &del_finished,
616 handle);
617}
618
619
620static void
621namestore_delete_cont (struct GNUNET_REST_RequestHandle *con,
622 const char *url,
623 void *cls)
624{
625 struct RequestHandle *handle = cls;
626
627 if (NULL == handle->name)
628 {
629 GNUNET_SCHEDULER_add_now (&do_error, handle);
630 return;
631 }
632
633 handle->add_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle,
634 &handle->zone_pkey,
635 handle->name,
636 &do_error,
637 handle,
638 &del_cont,
639 handle);
640}
641
642
643static int
644json_to_gnsrecord (const json_t *records_json,
645 struct GNUNET_GNSRECORD_Data **rd,
646 unsigned int *rd_count)
647{
648 struct GNUNET_TIME_Relative etime_rel;
649 struct GNUNET_TIME_Absolute etime_abs;
650 char *value;
651 void *rdata;
652 size_t rdata_size;
653 const char *typestring;
654 const char *expirationstring;
655 json_t *type_json;
656 json_t *value_json;
657 json_t *record_json;
658 json_t *exp_json;
659
660 *rd_count = json_array_size (records_json);
661 *rd = GNUNET_new_array (*rd_count,
662 struct GNUNET_GNSRECORD_Data);
663 for (unsigned int i = 0; i < *rd_count; i++)
664 {
665 memset (&(*rd)[i],
666 0,
667 sizeof (struct GNUNET_GNSRECORD_Data));
668 record_json = json_array_get (records_json,
669 i);
670 type_json = json_object_get (record_json,
671 GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE);
672 if (! json_is_string (type_json))
673 {
674 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
675 "Type property is no string\n");
676 return GNUNET_SYSERR;
677 }
678 typestring = json_string_value (type_json);
679 (*rd)[i].record_type = GNUNET_GNSRECORD_typename_to_number (typestring);
680 if (UINT32_MAX == (*rd)[i].record_type)
681 {
682 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unsupported type `%s'\n"),
683 json_string_value (type_json));
684 return GNUNET_SYSERR;
685 }
686 value_json = json_object_get (record_json,
687 GNUNET_REST_JSONAPI_NAMESTORE_VALUE);
688 if (! json_is_string (value_json))
689 {
690 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
691 "Value property is no string\n");
692 return GNUNET_SYSERR;
693 }
694 value = GNUNET_strdup (json_string_value (value_json));
695 if (GNUNET_OK !=
696 GNUNET_GNSRECORD_string_to_value ((*rd)[i].record_type,
697 value,
698 &rdata,
699 &rdata_size))
700 {
701 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
702 _("Value `%s' invalid for record type `%s'\n"),
703 value,
704 typestring);
705 return GNUNET_SYSERR;
706 }
707 (*rd)[i].data = rdata;
708 (*rd)[i].data_size = rdata_size;
709 /**TODO
710 * if (1 == handle->is_shadow)
711 rde->flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD;
712 if (1 != handle->is_public)
713 rde->flags |= GNUNET_GNSRECORD_RF_PRIVATE;
714 */
715 exp_json = json_object_get (record_json,
716 GNUNET_REST_JSONAPI_NAMESTORE_EXPIRATION);
717 if (! json_is_string (exp_json))
718 {
719 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
720 "Expiration property is no string\n");
721 return GNUNET_SYSERR;
722 }
723 expirationstring = json_string_value (exp_json);
724 if (0 == strcmp (expirationstring, "never"))
725 {
726 (*rd)[i].expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
727 }
728 else if (GNUNET_OK ==
729 GNUNET_STRINGS_fancy_time_to_relative (expirationstring,
730 &etime_rel))
731 {
732 (*rd)[i].expiration_time = etime_rel.rel_value_us;
733 (*rd)[i].flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
734 }
735 else if (GNUNET_OK ==
736 GNUNET_STRINGS_fancy_time_to_absolute (expirationstring,
737 &etime_abs))
738 {
739 (*rd)[i].expiration_time = etime_abs.abs_value_us;
740 }
741 else
742 {
743 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
744 _("Value `%s' invalid for record type `%s'\n"),
745 value,
746 typestring);
747 return GNUNET_SYSERR;
748 }
749 }
750 return GNUNET_OK;
751}
752
753
754static void
755namestore_create_cont (struct GNUNET_REST_RequestHandle *con,
756 const char *url,
757 void *cls)
758{
759 struct RequestHandle *handle = cls;
760 struct MHD_Response *resp;
761 struct GNUNET_JSONAPI_Document *json_obj;
762 struct GNUNET_JSONAPI_Resource *json_res;
763 json_t *records_json;
764 json_t *data_js;
765 json_error_t err;
766 char term_data[handle->rest_handle->data_size+1];
767 struct GNUNET_JSON_Specification docspec[] = {
768 GNUNET_JSON_spec_jsonapi_document (&json_obj),
769 GNUNET_JSON_spec_end()
770 };
771
772 if (strlen (GNUNET_REST_API_NS_NAMESTORE) != strlen (handle->url))
773 {
774 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
775 "Cannot create under %s\n", handle->url);
776 GNUNET_SCHEDULER_add_now (&do_error, handle);
777 return;
778 }
779 if (0 >= handle->rest_handle->data_size)
780 {
781 GNUNET_SCHEDULER_add_now (&do_error, handle);
782 return;
783 }
784 term_data[handle->rest_handle->data_size] = '\0';
785 GNUNET_memcpy (term_data,
786 handle->rest_handle->data,
787 handle->rest_handle->data_size);
788 data_js = json_loads (term_data,
789 JSON_DECODE_ANY,
790 &err);
791 GNUNET_assert (GNUNET_OK ==
792 GNUNET_JSON_parse (data_js, docspec,
793 NULL, NULL));
794 json_decref (data_js);
795 if (NULL == json_obj)
796 {
797 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
798 "Unable to parse JSONAPI Object from %s\n",
799 term_data);
800 GNUNET_SCHEDULER_add_now (&do_error, handle);
801 return;
802 }
803 if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
804 {
805 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
806 "Cannot create more than 1 resource! (Got %d)\n",
807 GNUNET_JSONAPI_document_resource_count (json_obj));
808 GNUNET_JSONAPI_document_delete (json_obj);
809 GNUNET_SCHEDULER_add_now (&do_error, handle);
810 return;
811 }
812 json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
813 if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
814 GNUNET_REST_JSONAPI_NAMESTORE_RECORD))
815 {
816 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
817 "Unsupported JSON data type\n");
818 GNUNET_JSONAPI_document_delete (json_obj);
819 resp = GNUNET_REST_create_response (NULL);
820 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
821 cleanup_handle (handle);
822 return;
823 }
824 handle->name = GNUNET_strdup (GNUNET_JSONAPI_resource_get_id (json_res));
825 records_json = GNUNET_JSONAPI_resource_read_attr (json_res,
826 GNUNET_REST_JSONAPI_NAMESTORE_RECORD);
827 if (NULL == records_json)
828 {
829 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
830 "No records given\n");
831 GNUNET_JSONAPI_document_delete (json_obj);
832 GNUNET_SCHEDULER_add_now (&do_error, handle);
833 return;
834 }
835 if (GNUNET_SYSERR == json_to_gnsrecord (records_json, &handle->rd, &handle->rd_count))
836 {
837 GNUNET_JSONAPI_document_delete (json_obj);
838 GNUNET_SCHEDULER_add_now (&do_error, handle);
839 return;
840 }
841 GNUNET_JSONAPI_document_delete (json_obj);
842
843 handle->add_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle,
844 &handle->zone_pkey,
845 handle->name,
846 &do_error,
847 handle,
848 &create_new_record_cont,
849 handle);
850}
851
852
853static void
854namestore_zkey_response (void *cls,
855 const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
856 const char *label,
857 unsigned int rd_count,
858 const struct GNUNET_GNSRECORD_Data *rd)
859{
860 struct RequestHandle *handle = cls;
861 struct MHD_Response *resp;
862 struct GNUNET_JSONAPI_Document *json_obj;
863 struct GNUNET_JSONAPI_Resource *json_res;
864 json_t *name_json;
865 char* result;
866
867 handle->reverse_qe = NULL;
868 json_obj = GNUNET_JSONAPI_document_new ();
869 if (NULL != label)
870 {
871 name_json = json_string (label);
872 json_res = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_NAMESTORE_REVINFO,
873 handle->zkey_str);
874 GNUNET_JSONAPI_resource_add_attr (json_res,
875 GNUNET_REST_JSONAPI_NAMESTORE_NAME,
876 name_json);
877 GNUNET_JSONAPI_document_resource_add (json_obj, json_res);
878 json_decref (name_json);
879 }
880 //Handle response
881 if (GNUNET_SYSERR == GNUNET_JSONAPI_document_serialize (json_obj, &result))
882 {
883 GNUNET_JSONAPI_document_delete (json_obj);
884 GNUNET_SCHEDULER_add_now (&do_error, handle);
885 return;
886 }
887 resp = GNUNET_REST_create_response (result);
888 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
889 GNUNET_JSONAPI_document_delete (json_obj);
890 GNUNET_free (result);
891 GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
892}
893
894
895static void
896namestore_zkey_cont (struct GNUNET_REST_RequestHandle *con,
897 const char *url,
898 void *cls)
899{
900 struct RequestHandle *handle = cls;
901 struct GNUNET_HashCode key;
902 struct GNUNET_CRYPTO_EcdsaPublicKey pubkey;
903
904 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_NAMESTORE_ZKEY,
905 strlen (GNUNET_REST_JSONAPI_NAMESTORE_ZKEY),
906 &key);
907 if ( GNUNET_NO ==
908 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
909 &key) )
910 {
911 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
912 "No zkey given %s\n", handle->url);
913 GNUNET_SCHEDULER_add_now (&do_error, handle);
914 return;
915 }
916 handle->zkey_str = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
917 &key);
918 if ((NULL == handle->zkey_str) ||
919 (GNUNET_OK !=
920 GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->zkey_str,
921 strlen (handle->zkey_str),
922 &pubkey)))
923 {
924 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
925 "Zkey invalid %s\n", handle->zkey_str);
926 GNUNET_SCHEDULER_add_now (&do_error, handle);
927 return;
928 }
929 handle->reverse_qe = GNUNET_NAMESTORE_zone_to_name (handle->ns_handle,
930 &handle->zone_pkey,
931 &pubkey,
932 &do_error,
933 handle,
934 &namestore_zkey_response,
935 handle);
936}
937
938
939static void
940namestore_info_cont (struct GNUNET_REST_RequestHandle *con,
941 const char *url,
942 void *cls)
943{
944 struct RequestHandle *handle = cls;
945
946 handle->list_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle,
947 &handle->zone_pkey,
948 &do_error,
949 handle,
950 &namestore_list_response,
951 handle,
952 &namestore_list_finished,
953 handle);
954}
955
956
957static char*
958get_name_from_url (const char* url)
959{
960 if (strlen (url) <= strlen (GNUNET_REST_API_NS_NAMESTORE))
961 return NULL;
962 return (char*)url + strlen (GNUNET_REST_API_NS_NAMESTORE) + 1;
963}
964
965/**
966 * Respond to OPTIONS request
967 *
968 * @param con_handle the connection handle
969 * @param url the url
970 * @param cls the RequestHandle
971 */
972static void
973options_cont (struct GNUNET_REST_RequestHandle *con_handle,
974 const char* url,
975 void *cls)
976{
977 struct MHD_Response *resp;
978 struct RequestHandle *handle = cls;
979
980 //For now, independent of path return all options
981 resp = GNUNET_REST_create_response (NULL);
982 MHD_add_response_header (resp,
983 "Access-Control-Allow-Methods",
984 allow_methods);
985 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
986 cleanup_handle (handle);
987}
988
989
990/**
991 * Callback invoked from identity service with ego information.
992 * An @a ego of NULL means the ego was not found.
993 *
994 * @param cls closure with the configuration
995 * @param ego an ego known to identity service, or NULL
996 */
997static void
998identity_cb (void *cls,
999 const struct GNUNET_IDENTITY_Ego *ego)
1000{
1001 struct RequestHandle *handle = cls;
1002 struct MHD_Response *resp;
1003 struct GNUNET_REST_RequestHandlerError err;
1004 static const struct GNUNET_REST_RequestHandler handlers[] = {
1005 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE_ZKEY, &namestore_zkey_cont}, //reverse
1006 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE, &namestore_info_cont}, //list
1007 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE, &namestore_create_cont}, //create
1008 // {MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_NAMESTORE, &namestore_edit_cont}, //update. TODO this shoul be PATCH
1009 {MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_NAMESTORE, &namestore_delete_cont}, //delete
1010 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_NAMESTORE, &options_cont},
1011 GNUNET_REST_HANDLER_END
1012 };
1013
1014 handle->ego_lookup = NULL;
1015 if (NULL == ego)
1016 {
1017 if (NULL != handle->ego_name)
1018 {
1019 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1020 _("Ego `%s' not known to identity service\n"),
1021 handle->ego_name);
1022 }
1023 resp = GNUNET_REST_create_response (NULL);
1024 handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND);
1025 cleanup_handle (handle);
1026 return;
1027 }
1028 handle->zone_pkey = *GNUNET_IDENTITY_ego_get_private_key (ego);
1029 handle->ns_handle = GNUNET_NAMESTORE_connect (cfg);
1030 if (NULL == handle->ns_handle)
1031 {
1032 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1033 _("Failed to connect to namestore\n"));
1034 GNUNET_SCHEDULER_add_now (&do_error, handle);
1035 return;
1036 }
1037
1038 if (GNUNET_OK !=
1039 GNUNET_JSONAPI_handle_request (handle->rest_handle,
1040 handlers,
1041 &err,
1042 handle))
1043 {
1044 handle->response_code = err.error_code;
1045 GNUNET_SCHEDULER_add_now (&do_error,
1046 (void *) handle);
1047 }
1048}
1049
1050
1051static void
1052default_ego_cb (void *cls,
1053 struct GNUNET_IDENTITY_Ego *ego,
1054 void **ctx,
1055 const char *name)
1056{
1057 struct RequestHandle *handle = cls;
1058 struct MHD_Response *resp;
1059 handle->get_default = NULL;
1060 if (NULL == ego)
1061 {
1062 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1063 _("No default ego configured in identity service\n"));
1064 resp = GNUNET_REST_create_response (NULL);
1065 handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND);
1066 cleanup_handle (handle);
1067 return;
1068 }
1069 else
1070 {
1071 identity_cb (cls, ego);
1072 }
1073}
1074
1075static void
1076id_connect_cb (void *cls,
1077 struct GNUNET_IDENTITY_Ego *ego,
1078 void **ctx,
1079 const char *name)
1080{
1081 struct RequestHandle *handle = cls;
1082 if (NULL == ego)
1083 {
1084 handle->get_default = GNUNET_IDENTITY_get (handle->identity_handle,
1085 "namestore",
1086 &default_ego_cb, handle);
1087 }
1088}
1089
1090
1091/**
1092 * Function processing the REST call
1093 *
1094 * @param method HTTP method
1095 * @param url URL of the HTTP request
1096 * @param data body of the HTTP request (optional)
1097 * @param data_size length of the body
1098 * @param proc callback function for the result
1099 * @param proc_cls closure for callback function
1100 * @return #GNUNET_OK if request accepted
1101 */
1102static void
1103rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle,
1104 GNUNET_REST_ResultProcessor proc,
1105 void *proc_cls)
1106{
1107 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1108 struct MHD_Response *resp;
1109 struct GNUNET_HashCode key;
1110 char *ego;
1111 char *name;
1112 char *type;
1113
1114 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1115 handle->proc_cls = proc_cls;
1116 handle->proc = proc;
1117 handle->rest_handle = rest_handle;
1118 handle->url = GNUNET_strdup (rest_handle->url);
1119 if (handle->url[strlen (handle->url)-1] == '/')
1120 handle->url[strlen (handle->url)-1] = '\0';
1121 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1122 "Connecting...\n");
1123 handle->cfg = cfg;
1124 ego = NULL;
1125 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_NAMESTORE_EGO,
1126 strlen (GNUNET_REST_JSONAPI_NAMESTORE_EGO),
1127 &key);
1128 if ( GNUNET_YES ==
1129 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
1130 &key) )
1131 {
1132 ego = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
1133 &key);
1134 }
1135
1136 handle->type = GNUNET_GNSRECORD_TYPE_ANY;
1137 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE,
1138 strlen (GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE),
1139 &key);
1140 if ( GNUNET_YES ==
1141 GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
1142 &key) )
1143 {
1144 type = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
1145 &key);
1146 if (NULL != type)
1147 handle->type = GNUNET_GNSRECORD_typename_to_number (type);
1148 }
1149 name = get_name_from_url (handle->url);
1150 if (NULL != ego)
1151 handle->ego_name = GNUNET_strdup (ego);
1152 if (NULL != name)
1153 handle->name = GNUNET_strdup (name);
1154 if (NULL == handle->ego_name)
1155 {
1156 handle->identity_handle = GNUNET_IDENTITY_connect (handle->cfg, &id_connect_cb, handle);
1157 if (NULL == handle->identity_handle)
1158 {
1159 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Cannot connect to identity service\n"));
1160 resp = GNUNET_REST_create_response (NULL);
1161 handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND);
1162 cleanup_handle (handle);
1163 }
1164 return;
1165 }
1166 handle->ego_lookup = GNUNET_IDENTITY_ego_lookup (cfg,
1167 handle->ego_name,
1168 &identity_cb,
1169 handle);
1170 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
1171 &do_timeout,
1172 handle);
1173}
1174
1175/**
1176 * Entry point for the plugin.
1177 *
1178 * @param cls Config info
1179 * @return NULL on error, otherwise the plugin context
1180 */
1181void *
1182libgnunet_plugin_rest_namestore_init (void *cls)
1183{
1184 static struct Plugin plugin;
1185 cfg = cls;
1186 struct GNUNET_REST_Plugin *api;
1187
1188 if (NULL != plugin.cfg)
1189 return NULL; /* can only initialize once! */
1190 memset (&plugin, 0, sizeof (struct Plugin));
1191 plugin.cfg = cfg;
1192 api = GNUNET_new (struct GNUNET_REST_Plugin);
1193 api->cls = &plugin;
1194 api->name = GNUNET_REST_API_NS_NAMESTORE;
1195 api->process_request = &rest_identity_process_request;
1196 GNUNET_asprintf (&allow_methods,
1197 "%s, %s, %s, %s, %s",
1198 MHD_HTTP_METHOD_GET,
1199 MHD_HTTP_METHOD_POST,
1200 MHD_HTTP_METHOD_PUT,
1201 MHD_HTTP_METHOD_DELETE,
1202 MHD_HTTP_METHOD_OPTIONS);
1203 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1204 _("Namestore REST API initialized\n"));
1205 return api;
1206}
1207
1208
1209/**
1210 * Exit point from the plugin.
1211 *
1212 * @param cls the plugin context (as returned by "init")
1213 * @return always NULL
1214 */
1215void *
1216libgnunet_plugin_rest_namestore_done (void *cls)
1217{
1218 struct GNUNET_REST_Plugin *api = cls;
1219 struct Plugin *plugin = api->cls;
1220
1221 plugin->cfg = NULL;
1222 GNUNET_free (api);
1223 GNUNET_free_non_null (allow_methods);
1224 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1225 "Namestore REST plugin is finished\n");
1226 return NULL;
1227}
1228
1229/* end of plugin_rest_namestore.c */