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