aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPhil <phil.buschmann@tum.de>2018-06-13 23:40:14 +0200
committerPhil <phil.buschmann@tum.de>2018-06-13 23:40:14 +0200
commita006f82603921d7b6775c7a7be60c7f388c6a927 (patch)
tree87855be9af215a86c3fe24904783de0193ea919a /src
parent09b6a814e0ddcca0497c5cbf37940c27e6a5d9de (diff)
downloadgnunet-a006f82603921d7b6775c7a7be60c7f388c6a927.tar.gz
gnunet-a006f82603921d7b6775c7a7be60c7f388c6a927.zip
-wip fix gns
Diffstat (limited to 'src')
-rw-r--r--src/gns/plugin_rest_gns.c685
-rw-r--r--src/gns/plugin_rest_gns2.c717
2 files changed, 939 insertions, 463 deletions
diff --git a/src/gns/plugin_rest_gns.c b/src/gns/plugin_rest_gns.c
index 82d62744c..57fdfc1d5 100644
--- a/src/gns/plugin_rest_gns.c
+++ b/src/gns/plugin_rest_gns.c
@@ -2,54 +2,52 @@
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2012-2015 GNUnet e.V. 3 Copyright (C) 2012-2015 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 5 GNUnet is free software; you can redistribute it and/or modify
6 under the terms of the GNU Affero General Public License as published 6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation, either version 3 of the License, 7 by the Free Software Foundation; either version 3, or (at your
8 or (at your option) any later version. 8 option) any later version.
9 9
10 GNUnet is distributed in the hope that it will be useful, but 10 GNUnet is distributed in the hope that it will be useful, but
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 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 General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. 16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
17 */ 19 */
18/** 20/**
19 * @author Martin Schanzenbach
20 * @author Philippe Buschmann 21 * @author Philippe Buschmann
21 * @file gns/plugin_rest_gns.c 22 * @file gns1/plugin_rest_gns1.c
22 * @brief GNUnet GNS REST plugin 23 * @brief GNUnet Gns1 REST plugin
23 *
24 */ 24 */
25 25
26#include "platform.h" 26#include "platform.h"
27#include "gnunet_rest_plugin.h" 27#include "gnunet_rest_plugin.h"
28#include <gnunet_dnsparser_lib.h> 28#include "gnunet_rest_lib.h"
29#include <gnunet_identity_service.h> 29#include "gnunet_gnsrecord_lib.h"
30#include <gnunet_gnsrecord_lib.h> 30#include "microhttpd.h"
31#include <gnunet_namestore_service.h>
32#include <gnunet_gns_service.h>
33#include <gnunet_rest_lib.h>
34#include <gnunet_jsonapi_lib.h>
35#include <gnunet_jsonapi_util.h>
36#include <jansson.h> 31#include <jansson.h>
37 32
38#define GNUNET_REST_API_NS_GNS "/gns" 33#define GNUNET_REST_API_NS_GNS "/gns"
39 34
40#define GNUNET_REST_JSONAPI_GNS_RECORD_TYPE "record_type" 35//TODO define other variables
41
42#define GNUNET_REST_PARAMETER_GNS_NAME "name" 36#define GNUNET_REST_PARAMETER_GNS_NAME "name"
43 37
44#define GNUNET_REST_JSONAPI_GNS_TYPEINFO "gns_name" 38#define GNUNET_REST_PARAMETER_GNS_RECORD_TYPE "record_type"
45 39
46#define GNUNET_REST_JSONAPI_GNS_RECORD "records" 40#define GNUNET_REST_PARAMETER_GNS_NAME "name"
47
48#define GNUNET_REST_JSONAPI_GNS_EGO "ego"
49 41
50#define GNUNET_REST_JSONAPI_GNS_PKEY "pkey" 42/**
43 * The configuration handle
44 */
45const struct GNUNET_CONFIGURATION_Handle *cfg;
51 46
52#define GNUNET_REST_JSONAPI_GNS_OPTIONS "options" 47/**
48 * HTTP methods allows for this plugin
49 */
50static char* allow_methods;
53 51
54/** 52/**
55 * @brief struct returned by the initialization function of the plugin 53 * @brief struct returned by the initialization function of the plugin
@@ -59,54 +57,48 @@ struct Plugin
59 const struct GNUNET_CONFIGURATION_Handle *cfg; 57 const struct GNUNET_CONFIGURATION_Handle *cfg;
60}; 58};
61 59
62const struct GNUNET_CONFIGURATION_Handle *cfg; 60//TODO add specific structs
63 61
64struct LookupHandle 62
63
64struct RequestHandle
65{ 65{
66 /** 66 //TODO add specific entries
67 * Handle to GNS service.
68 */
69 struct GNUNET_GNS_Handle *gns;
70 67
71 /** 68 /**
72 * Desired timeout for the lookup (default is no timeout). 69 * Connection to GNS
73 */ 70 */
74 struct GNUNET_TIME_Relative timeout; 71 struct GNUNET_GNS_Handle *gns;
75 72
76 /** 73 /**
77 * Handle to lookup request 74 * Active GNS lookup
78 */ 75 */
79 struct GNUNET_GNS_LookupRequest *lookup_request; 76 struct GNUNET_GNS_LookupWithTldRequest *gns_lookup;
80 77
81 /** 78 /**
82 * Handle to rest request 79 * Name to look up
83 */ 80 */
84 struct GNUNET_REST_RequestHandle *rest_handle; 81 char *name;
85 82
86 /** 83 /**
87 * Lookup an ego with the identity service. 84 * Record type to look up
88 */ 85 */
89 struct GNUNET_IDENTITY_EgoLookup *el; 86 int record_type;
90 87
91 /** 88 /**
92 * Handle for identity service. 89 * Rest connection
93 */ 90 */
94 struct GNUNET_IDENTITY_Handle *identity; 91 struct GNUNET_REST_RequestHandle *rest_handle;
95 92
96 /** 93 /**
97 * Active operation on identity service. 94 * Desired timeout for the lookup (default is no timeout).
98 */ 95 */
99 struct GNUNET_IDENTITY_Operation *id_op; 96 struct GNUNET_TIME_Relative timeout;
100 97
101 /** 98 /**
102 * ID of a task associated with the resolution process. 99 * ID of a task associated with the resolution process.
103 */ 100 */
104 struct GNUNET_SCHEDULER_Task * timeout_task; 101 struct GNUNET_SCHEDULER_Task *timeout_task;
105
106 /**
107 * The root of the received JSON or NULL
108 */
109 json_t *json_root;
110 102
111 /** 103 /**
112 * The plugin result processor 104 * The plugin result processor
@@ -119,96 +111,37 @@ struct LookupHandle
119 void *proc_cls; 111 void *proc_cls;
120 112
121 /** 113 /**
122 * The name to look up 114 * The url
123 */
124 char *name;
125
126 /**
127 * The ego to use
128 * In string representation from JSON
129 */
130 const char *ego_str;
131
132 /**
133 * The Pkey to use
134 * In string representation from JSON
135 */ 115 */
136 const char *pkey_str; 116 char *url;
137 117
138 /** 118 /**
139 * The record type 119 * Error response message
140 */ 120 */
141 int type; 121 char *emsg;
142 122
143 /** 123 /**
144 * The public key of to use for lookup 124 * Reponse code
145 */
146 struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
147
148 /**
149 * The public key to use for lookup
150 */
151 struct GNUNET_CRYPTO_EcdsaPublicKey pkeym;
152
153 /**
154 * The resolver options
155 */
156 enum GNUNET_GNS_LocalOptions options;
157
158 /**
159 * the shorten key
160 */
161 struct GNUNET_CRYPTO_EcdsaPrivateKey shorten_key;
162
163 /**
164 * HTTP response code
165 */ 125 */
166 int response_code; 126 int response_code;
167 127
168 /**
169 * HTTP response code
170 */
171 char* emsg;
172
173}; 128};
174 129
175 130
176/** 131/**
177 * Cleanup lookup handle. 132 * Cleanup lookup handle
178 *
179 * @param handle Handle to clean up 133 * @param handle Handle to clean up
180 */ 134 */
181static void 135static void
182cleanup_handle (struct LookupHandle *handle) 136cleanup_handle (struct RequestHandle *handle)
183{ 137{
184 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 138 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
185 "Cleaning up\n"); 139 "Cleaning up\n");
186 if (NULL != handle->json_root)
187 json_decref (handle->json_root);
188 140
189 if (NULL != handle->name) 141 if (NULL != handle->gns_lookup)
190 GNUNET_free (handle->name);
191 if (NULL != handle->emsg)
192 GNUNET_free (handle->emsg);
193 if (NULL != handle->el)
194 {
195 GNUNET_IDENTITY_ego_lookup_cancel (handle->el);
196 handle->el = NULL;
197 }
198 if (NULL != handle->id_op)
199 { 142 {
200 GNUNET_IDENTITY_cancel (handle->id_op); 143 GNUNET_GNS_lookup_with_tld_cancel (handle->gns_lookup);
201 handle->id_op = NULL; 144 handle->gns_lookup = NULL;
202 }
203 if (NULL != handle->lookup_request)
204 {
205 GNUNET_GNS_lookup_cancel (handle->lookup_request);
206 handle->lookup_request = NULL;
207 }
208 if (NULL != handle->identity)
209 {
210 GNUNET_IDENTITY_disconnect (handle->identity);
211 handle->identity = NULL;
212 } 145 }
213 if (NULL != handle->gns) 146 if (NULL != handle->gns)
214 { 147 {
@@ -219,21 +152,30 @@ cleanup_handle (struct LookupHandle *handle)
219 if (NULL != handle->timeout_task) 152 if (NULL != handle->timeout_task)
220 { 153 {
221 GNUNET_SCHEDULER_cancel (handle->timeout_task); 154 GNUNET_SCHEDULER_cancel (handle->timeout_task);
155 handle->timeout_task = NULL;
222 } 156 }
157 if (NULL != handle->url)
158 GNUNET_free (handle->url);
159 if (NULL != handle->name)
160 GNUNET_free (handle->name);
161 if (NULL != handle->emsg)
162 GNUNET_free (handle->emsg);
163
164 //TODO add specific cleanup
165
223 GNUNET_free (handle); 166 GNUNET_free (handle);
224} 167}
225 168
226 169
227/** 170/**
228 * Task run on shutdown. Cleans up everything. 171 * Task run on errors. Reports an error and cleans up everything.
229 * 172 *
230 * @param cls unused 173 * @param cls the `struct RequestHandle`
231 * @param tc scheduler context
232 */ 174 */
233static void 175static void
234do_error (void *cls) 176do_error (void *cls)
235{ 177{
236 struct LookupHandle *handle = cls; 178 struct RequestHandle *handle = cls;
237 struct MHD_Response *resp; 179 struct MHD_Response *resp;
238 char *json_error; 180 char *json_error;
239 181
@@ -241,7 +183,9 @@ do_error (void *cls)
241 handle->emsg = GNUNET_strdup("Unknown Error"); 183 handle->emsg = GNUNET_strdup("Unknown Error");
242 184
243 GNUNET_asprintf (&json_error, "{\"error\": \"%s\"}", handle->emsg); 185 GNUNET_asprintf (&json_error, "{\"error\": \"%s\"}", handle->emsg);
244 handle->response_code = MHD_HTTP_OK; 186
187 if (0 == handle->response_code)
188 handle->response_code = MHD_HTTP_OK;
245 189
246 resp = GNUNET_REST_create_response (json_error); 190 resp = GNUNET_REST_create_response (json_error);
247 handle->proc (handle->proc_cls, resp, handle->response_code); 191 handle->proc (handle->proc_cls, resp, handle->response_code);
@@ -251,83 +195,56 @@ do_error (void *cls)
251 195
252 196
253/** 197/**
254 * Create json representation of a GNSRECORD 198 * Iterator called on obtained result for a GNS lookup.
255 * 199 *
256 * @param rd the GNSRECORD_Data 200 * @param cls closure with the object
201 * @param was_gns #GNUNET_NO if name was not a GNS name
202 * @param rd_count number of records in @a rd
203 * @param rd the records in reply
257 */ 204 */
258static json_t * 205static void
259gnsrecord_to_json (const struct GNUNET_GNSRECORD_Data *rd) 206handle_gns_response (void *cls,
207 int was_gns,
208 uint32_t rd_count,
209 const struct GNUNET_GNSRECORD_Data *rd)
260{ 210{
261 const char *typename; 211 struct RequestHandle *handle = cls;
262 char *string_val; 212 struct MHD_Response *resp;
263 const char *exp_str; 213 json_t *result_array;
264 json_t *record_obj; 214 json_t *record_obj;
265 215
266 typename = GNUNET_GNSRECORD_number_to_typename (rd->record_type); 216 if (GNUNET_NO == was_gns)
267 string_val = GNUNET_GNSRECORD_value_to_string (rd->record_type,
268 rd->data,
269 rd->data_size);
270
271 if (NULL == string_val)
272 { 217 {
273 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 218 handle->emsg = GNUNET_strdup("Name not found in GNS");
274 "Record of type %d malformed, skipping\n", 219 GNUNET_SCHEDULER_add_now (&do_error, handle);
275 (int) rd->record_type); 220 return;
276 return NULL;
277 } 221 }
278 record_obj = json_object ();
279 json_object_set_new (record_obj, "type", json_string (typename));
280 json_object_set_new (record_obj, "value", json_string (string_val));
281 GNUNET_free (string_val);
282 222
283 if (GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION & rd->flags) 223 if (0 == rd_count)
284 { 224 {
285 struct GNUNET_TIME_Relative time_rel; 225 handle->emsg = GNUNET_strdup("No result found");
286 time_rel.rel_value_us = rd->expiration_time; 226 GNUNET_SCHEDULER_add_now (&do_error, handle);
287 exp_str = GNUNET_STRINGS_relative_time_to_string (time_rel, 1); 227 return;
288 }
289 else
290 {
291 struct GNUNET_TIME_Absolute time_abs;
292 time_abs.abs_value_us = rd->expiration_time;
293 exp_str = GNUNET_STRINGS_absolute_time_to_string (time_abs);
294 } 228 }
295 json_object_set_new (record_obj, "expiration_time", json_string (exp_str));
296
297 json_object_set_new (record_obj, "expired",
298 json_boolean (GNUNET_YES == GNUNET_GNSRECORD_is_expired (rd)));
299 return record_obj;
300}
301
302/**
303 * Function called with the result of a GNS lookup.
304 *
305 * @param cls the 'const char *' name that was resolved
306 * @param rd_count number of records returned
307 * @param rd array of @a rd_count records with the results
308 */
309static void
310process_lookup_result (void *cls, uint32_t rd_count,
311 const struct GNUNET_GNSRECORD_Data *rd)
312{
313 struct LookupHandle *handle = cls;
314 struct MHD_Response *resp;
315 uint32_t i;
316 char *result;
317 json_t *result_array;
318 json_t *record_obj;
319 229
320 result_array = json_array(); 230 result_array = json_array();
321 handle->lookup_request = NULL; 231 //TODO test break!
322 for (i=0; i<rd_count; i++) 232 GNUNET_break (NULL != handle->gns_lookup);
233 handle->gns_lookup = NULL;
234
235 for (uint32_t i=0;i<rd_count;i++)
323 { 236 {
324 if ( (rd[i].record_type != handle->type) && 237 if ((rd[i].record_type != handle->record_type) &&
325 (GNUNET_GNSRECORD_TYPE_ANY != handle->type) ) 238 (GNUNET_GNSRECORD_TYPE_ANY != handle->record_type) )
239 {
326 continue; 240 continue;
241 }
242
327 record_obj = gnsrecord_to_json (&(rd[i])); 243 record_obj = gnsrecord_to_json (&(rd[i]));
328 json_array_append (result_array, record_obj); 244 json_array_append (result_array, record_obj);
329 json_decref (record_obj); 245 json_decref (record_obj);
330 } 246 }
247
331 result = json_dumps(result_array, 0); 248 result = json_dumps(result_array, 0);
332 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result); 249 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result);
333 resp = GNUNET_REST_create_response (result); 250 resp = GNUNET_REST_create_response (result);
@@ -339,274 +256,70 @@ process_lookup_result (void *cls, uint32_t rd_count,
339 256
340 257
341/** 258/**
342 * Perform the actual resolution, starting with the zone 259 * Handle gns1 GET request
343 * identified by the given public key and the shorten zone.
344 *
345 * @param pkey public key to use for the zone, can be NULL
346 */
347static void
348lookup_with_public_key (struct LookupHandle *handle)
349{
350 if (UINT32_MAX == handle->type)
351 {
352 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
353 _("Invalid typename specified, assuming `ANY'\n"));
354 handle->type = GNUNET_GNSRECORD_TYPE_ANY;
355 }
356 if (NULL != handle->name)
357 {
358 handle->lookup_request = GNUNET_GNS_lookup (handle->gns,
359 handle->name,
360 &handle->pkey,
361 handle->type,
362 handle->options,
363 &process_lookup_result,
364 handle);
365 }
366 else
367 {
368 handle->emsg = GNUNET_strdup("Parameter name is missing");
369 GNUNET_SCHEDULER_add_now (&do_error, handle);
370 return;
371 }
372}
373
374
375/**
376 * Method called to with the ego we are to use for the lookup,
377 * when the ego is determined by a name.
378 *
379 * @param cls closure (NULL, unused)
380 * @param ego ego handle, NULL if not found
381 */
382static void
383identity_zone_cb (void *cls,
384 const struct GNUNET_IDENTITY_Ego *ego)
385{
386 struct LookupHandle *handle = cls;
387
388 handle->el = NULL;
389 if (NULL == ego)
390 {
391 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
392 _("Ego for not found, cannot perform lookup.\n"));
393 handle->emsg = GNUNET_strdup ("Ego for not found, cannot perform lookup.");
394 GNUNET_SCHEDULER_add_now (&do_error, handle);
395 return;
396 }
397 else
398 {
399 GNUNET_IDENTITY_ego_get_public_key (ego, &handle->pkey);
400 lookup_with_public_key (handle);
401 }
402 json_decref(handle->json_root);
403}
404
405
406/**
407 * Method called to with the ego we are to use for the lookup,
408 * when the ego is the one for the default master zone.
409 * 260 *
410 * @param cls closure (NULL, unused) 261 * @param con_handle the connection handle
411 * @param ego ego handle, NULL if not found 262 * @param url the url
412 * @param ctx context for application to store data for this ego 263 * @param cls the RequestHandle
413 * (during the lifetime of this process, initially NULL)
414 * @param name name assigned by the user for this ego,
415 * NULL if the user just deleted the ego and it
416 * must thus no longer be used
417 */ 264 */
418static void 265void
419identity_master_cb (void *cls, 266get_gns_cont (struct GNUNET_REST_RequestHandle *con_handle,
420 struct GNUNET_IDENTITY_Ego *ego, 267 const char* url,
421 void **ctx, 268 void *cls)
422 const char *name)
423{ 269{
424 const char *dot; 270 struct RequestHandle *handle = cls;
425 struct LookupHandle *handle = cls;
426
427 handle->id_op = NULL;
428 if (NULL == ego)
429 {
430 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
431 _("Ego for `gns-master' not found, cannot perform lookup. Did you run gnunet-gns-import.sh?\n"));
432 handle->emsg = GNUNET_strdup("Ego for `gns-master' not found, cannot perform lookup. Did you run gnunet-gns-import.sh?");
433 GNUNET_SCHEDULER_add_now (&do_error, handle);
434 return;
435 }
436 GNUNET_IDENTITY_ego_get_public_key (ego,
437 &handle->pkey);
438 /* main name is our own master zone, do no look for that in the DHT */
439 handle->options = GNUNET_GNS_LO_LOCAL_MASTER;
440 /* if the name is of the form 'label.gnu', never go to the DHT */
441 dot = NULL;
442 if (NULL != handle->name)
443 dot = strchr (handle->name, '.');
444 if ( (NULL != dot) &&
445 (0 == strcasecmp (dot, ".gnu")) )
446 handle->options = GNUNET_GNS_LO_NO_DHT;
447 lookup_with_public_key (handle);
448}
449
450/**
451 * Handle get request
452 *
453 * @param handle the lookup handle
454 */
455static void
456get_gns_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
457 const char* url,
458 void *cls)
459{
460 struct LookupHandle *handle = cls;
461 struct GNUNET_HashCode key; 271 struct GNUNET_HashCode key;
462 long int enum_test;
463 char *temp_val;
464
465 //check for /gns otherwise 404
466 if (strlen (GNUNET_REST_API_NS_GNS) > strlen (url))
467 {
468 handle->emsg = GNUNET_strdup("Wrong URL");
469 GNUNET_SCHEDULER_add_now (&do_error, handle);
470 return;
471 }
472 272
473 //connect to gns
474 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
475 handle->gns = GNUNET_GNS_connect (cfg);
476 handle->identity = GNUNET_IDENTITY_connect (cfg, NULL, NULL);
477 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
478 &do_error, handle);
479 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
480 if (NULL == handle->gns)
481 {
482 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Connecting to GNS failed\n");
483 handle->emsg = GNUNET_strdup("Connecting to GNS failed");
484 GNUNET_SCHEDULER_add_now (&do_error, handle);
485 return;
486 }
487
488 //check parameter name -> BAD_REQUEST
489 GNUNET_CRYPTO_hash (GNUNET_REST_PARAMETER_GNS_NAME, 273 GNUNET_CRYPTO_hash (GNUNET_REST_PARAMETER_GNS_NAME,
490 strlen (GNUNET_REST_PARAMETER_GNS_NAME), 274 strlen (GNUNET_REST_PARAMETER_GNS_NAME),
491 &key); 275 &key);
492 if ( GNUNET_NO 276 if ( GNUNET_NO
493 == GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, 277 == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map,
494 &key)) 278 &key))
495 { 279 {
496 handle->emsg = GNUNET_strdup("Parameter name is missing"); 280 handle->emsg = GNUNET_strdup("Parameter name is missing");
497 GNUNET_SCHEDULER_add_now (&do_error, handle); 281 GNUNET_SCHEDULER_add_now (&do_error, handle);
498 return; 282 return;
499 } 283 }
500 handle->name = GNUNET_strdup(GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, 284 handle->name = GNUNET_strdup(
501 &key)); 285 GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map,&key));
502
503 //check parameter record_type, optional
504 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_RECORD_TYPE,
505 strlen (GNUNET_REST_JSONAPI_GNS_RECORD_TYPE),
506 &key);
507 if ( GNUNET_YES ==
508 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
509 &key) )
510 {
511 handle->type = GNUNET_GNSRECORD_typename_to_number(
512 GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
513 &key));
514 }
515 else
516 {
517 handle->type = GNUNET_GNSRECORD_TYPE_ANY;
518 }
519 286
520 //check parameter options, optional 287 GNUNET_CRYPTO_hash (GNUNET_REST_PARAMETER_GNS_RECORD_TYPE,
521 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_OPTIONS, 288 strlen (GNUNET_REST_PARAMETER_GNS_RECORD_TYPE),
522 strlen (GNUNET_REST_JSONAPI_GNS_OPTIONS),
523 &key); 289 &key);
524 handle->options = GNUNET_GNS_LO_DEFAULT; 290 if ( GNUNET_NO
525 if ( GNUNET_YES 291 == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map,
526 == GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, 292 &key))
527 &key))
528 {
529 temp_val = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, &key);
530 if (1 < strlen(temp_val))
531 {
532 handle->options = GNUNET_GNS_LO_DEFAULT;
533 }
534 else
535 {
536 //atoi because no valid conversion is default local option
537 enum_test = atoi(temp_val);
538 if (2 < enum_test)
539 handle->options = GNUNET_GNS_LO_DEFAULT;
540 else
541 handle->options = enum_test;
542 }
543 }
544 else
545 handle->options = GNUNET_GNS_LO_DEFAULT;
546
547 //check parameter pkey, shortcut to lookup
548 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_PKEY,
549 strlen (GNUNET_REST_JSONAPI_GNS_PKEY),
550 &key);
551 if ( GNUNET_YES
552 == GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
553 &key))
554 { 293 {
555 handle->pkey_str = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, 294 handle->emsg = GNUNET_strdup("Parameter record_type is missing");
556 &key); 295 GNUNET_SCHEDULER_add_now (&do_error, handle);
557 GNUNET_assert(NULL != handle->pkey_str);
558 if (GNUNET_OK
559 != GNUNET_CRYPTO_ecdsa_public_key_from_string (
560 handle->pkey_str, strlen (handle->pkey_str), &(handle->pkey)))
561 {
562 handle->emsg = GNUNET_strdup("Parameter pkey has a wrong format");
563 GNUNET_SCHEDULER_add_now (&do_error, handle);
564 return;
565 }
566 lookup_with_public_key (handle);
567 return; 296 return;
568 } 297 }
569 298 handle->record_type = GNUNET_strdup(
570 //check parameter ego, lookup public key of ego 299 GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map,&key));
571 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_EGO, 300
572 strlen (GNUNET_REST_JSONAPI_GNS_EGO), 301 handle->gns_lookup = GNUNET_GNS_lookup_with_tld (handle->gns,
573 &key); 302 handle->name,
574 if ( GNUNET_YES == 303 handle->record_type,
575 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, 304 GNUNET_NO,
576 &key) ) 305 &handle_gns_response,
306 handle);
307 if (NULL == handle->gns_lookup)
577 { 308 {
578 handle->ego_str = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, 309 handle->emsg = GNUNET_strdup("GNS lookup failed");
579 &key); 310 GNUNET_SCHEDULER_add_now (&do_error, handle);
580 handle->el = GNUNET_IDENTITY_ego_lookup (cfg,
581 handle->ego_str,
582 &identity_zone_cb,
583 handle);
584 return; 311 return;
585 } 312 }
586
587 //if name ends with .zkey then get public key
588 if ( (NULL != handle->name) &&
589 (strlen (handle->name) > 4) &&
590 (0 == strcmp (".zkey",
591 &handle->name[strlen (handle->name) - 4])) )
592 {
593 GNUNET_CRYPTO_ecdsa_key_get_public( GNUNET_CRYPTO_ecdsa_key_get_anonymous (),
594 &(handle->pkey));
595 lookup_with_public_key (handle);
596 }
597 else //else use gns-master identity
598 {
599 handle->id_op = GNUNET_IDENTITY_get (handle->identity,
600 "gns-master",
601 &identity_master_cb,
602 handle);
603 }
604} 313}
605 314
315
316
606/** 317/**
607 * Handle rest request 318 * Respond to OPTIONS request
608 * 319 *
609 * @param handle the lookup handle 320 * @param con_handle the connection handle
321 * @param url the url
322 * @param cls the RequestHandle
610 */ 323 */
611static void 324static void
612options_cont (struct GNUNET_REST_RequestHandle *con_handle, 325options_cont (struct GNUNET_REST_RequestHandle *con_handle,
@@ -614,50 +327,35 @@ options_cont (struct GNUNET_REST_RequestHandle *con_handle,
614 void *cls) 327 void *cls)
615{ 328{
616 struct MHD_Response *resp; 329 struct MHD_Response *resp;
617 struct LookupHandle *handle = cls; 330 struct RequestHandle *handle = cls;
618 331
619 //For GNS, independent of path return all options 332 //independent of path return all options
620 resp = GNUNET_REST_create_response (NULL); 333 resp = GNUNET_REST_create_response (NULL);
621 MHD_add_response_header (resp, 334 MHD_add_response_header (resp,
622 "Access-Control-Allow-Methods", 335 "Access-Control-Allow-Methods",
623 MHD_HTTP_METHOD_GET); 336 allow_methods);
624 handle->proc (handle->proc_cls, 337 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
625 resp,
626 MHD_HTTP_OK);
627 cleanup_handle (handle); 338 cleanup_handle (handle);
339 return;
628} 340}
629 341
630 342
631/** 343/**
632 * Function processing the REST call 344 * Handle rest request
633 * 345 *
634 * @param method HTTP method 346 * @param handle the request handle
635 * @param url URL of the HTTP request
636 * @param data body of the HTTP request (optional)
637 * @param data_size length of the body
638 * @param proc callback function for the result
639 * @param proc_cls closure for @a proc
640 * @return #GNUNET_OK if request accepted
641 */ 347 */
642static void 348static void
643rest_gns_process_request (struct GNUNET_REST_RequestHandle *conndata_handle, 349init_cont (struct RequestHandle *handle)
644 GNUNET_REST_ResultProcessor proc,
645 void *proc_cls)
646{ 350{
351 struct GNUNET_REST_RequestHandlerError err;
647 static const struct GNUNET_REST_RequestHandler handlers[] = { 352 static const struct GNUNET_REST_RequestHandler handlers[] = {
648 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_GNS, &get_gns_cont}, 353 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_GNS, &get_gns_cont},
649 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_GNS, &options_cont}, 354 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_GNS, &options_cont},
650 GNUNET_REST_HANDLER_END 355 GNUNET_REST_HANDLER_END
651 }; 356 };
652 struct LookupHandle *handle = GNUNET_new (struct LookupHandle);
653 struct GNUNET_REST_RequestHandlerError err;
654 357
655 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; 358 if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle,
656 handle->proc_cls = proc_cls;
657 handle->proc = proc;
658 handle->rest_handle = conndata_handle;
659
660 if (GNUNET_NO == GNUNET_REST_handle_request (conndata_handle,
661 handlers, 359 handlers,
662 &err, 360 &err,
663 handle)) 361 handle))
@@ -669,18 +367,69 @@ rest_gns_process_request (struct GNUNET_REST_RequestHandle *conndata_handle,
669 367
670 368
671/** 369/**
370 * Function processing the REST call
371 *
372 * @param method HTTP method
373 * @param url URL of the HTTP request
374 * @param data body of the HTTP request (optional)
375 * @param data_size length of the body
376 * @param proc callback function for the result
377 * @param proc_cls closure for callback function
378 * @return GNUNET_OK if request accepted
379 */
380static void
381rest_process_request(struct GNUNET_REST_RequestHandle *rest_handle,
382 GNUNET_REST_ResultProcessor proc,
383 void *proc_cls)
384{
385 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
386
387 handle->response_code = 0;
388 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
389 handle->proc_cls = proc_cls;
390 handle->proc = proc;
391 handle->rest_handle = rest_handle;
392
393 handle->url = GNUNET_strdup (rest_handle->url);
394 if (handle->url[strlen (handle->url)-1] == '/')
395 handle->url[strlen (handle->url)-1] = '\0';
396 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
397
398
399 handle->gns = GNUNET_GNS_connect (cfg);
400 if (NULL == handle->gns)
401 {
402 handle->emsg = GNUNET_strdup ("GNS not available");
403 GNUNET_SCHEDULER_add_now (&do_error, handle);
404 return;
405 }
406
407 init_cont(handle);
408 //TODO connect to specific service
409 //connect ( cfg, [..., &callback_function, handle]);
410 //TODO callback then init_cont(handle)
411 handle->timeout_task =
412 GNUNET_SCHEDULER_add_delayed (handle->timeout,
413 &do_error,
414 handle);
415
416 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
417}
418
419
420/**
672 * Entry point for the plugin. 421 * Entry point for the plugin.
673 * 422 *
674 * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*" 423 * @param cls Config info
675 * @return NULL on error, otherwise the plugin context 424 * @return NULL on error, otherwise the plugin context
676 */ 425 */
677void * 426void *
678libgnunet_plugin_rest_gns_init (void *cls) 427libgnunet_plugin_rest_gns1_init (void *cls)
679{ 428{
680 static struct Plugin plugin; 429 static struct Plugin plugin;
681 cfg = cls;
682 struct GNUNET_REST_Plugin *api; 430 struct GNUNET_REST_Plugin *api;
683 431
432 cfg = cls;
684 if (NULL != plugin.cfg) 433 if (NULL != plugin.cfg)
685 return NULL; /* can only initialize once! */ 434 return NULL; /* can only initialize once! */
686 memset (&plugin, 0, sizeof (struct Plugin)); 435 memset (&plugin, 0, sizeof (struct Plugin));
@@ -688,9 +437,17 @@ libgnunet_plugin_rest_gns_init (void *cls)
688 api = GNUNET_new (struct GNUNET_REST_Plugin); 437 api = GNUNET_new (struct GNUNET_REST_Plugin);
689 api->cls = &plugin; 438 api->cls = &plugin;
690 api->name = GNUNET_REST_API_NS_GNS; 439 api->name = GNUNET_REST_API_NS_GNS;
691 api->process_request = &rest_gns_process_request; 440 api->process_request = &rest_process_request;
692 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 441 GNUNET_asprintf (&allow_methods,
693 _("GNS REST API initialized\n")); 442 "%s, %s, %s, %s, %s",
443 MHD_HTTP_METHOD_GET,
444 MHD_HTTP_METHOD_POST,
445 MHD_HTTP_METHOD_PUT,
446 MHD_HTTP_METHOD_DELETE,
447 MHD_HTTP_METHOD_OPTIONS);
448
449 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
450 _("Gns1 REST API initialized\n"));
694 return api; 451 return api;
695} 452}
696 453
@@ -702,16 +459,18 @@ libgnunet_plugin_rest_gns_init (void *cls)
702 * @return always NULL 459 * @return always NULL
703 */ 460 */
704void * 461void *
705libgnunet_plugin_rest_gns_done (void *cls) 462libgnunet_plugin_rest_gns1_done (void *cls)
706{ 463{
707 struct GNUNET_REST_Plugin *api = cls; 464 struct GNUNET_REST_Plugin *api = cls;
708 struct Plugin *plugin = api->cls; 465 struct Plugin *plugin = api->cls;
709
710 plugin->cfg = NULL; 466 plugin->cfg = NULL;
467
468 GNUNET_free_non_null (allow_methods);
711 GNUNET_free (api); 469 GNUNET_free (api);
712 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 470 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
713 "GNS REST plugin is finished\n"); 471 "Gns1 REST plugin is finished\n");
714 return NULL; 472 return NULL;
715} 473}
716 474
717/* end of plugin_rest_gns.c */ 475/* end of plugin_rest_gns1.c */
476
diff --git a/src/gns/plugin_rest_gns2.c b/src/gns/plugin_rest_gns2.c
new file mode 100644
index 000000000..82d62744c
--- /dev/null
+++ b/src/gns/plugin_rest_gns2.c
@@ -0,0 +1,717 @@
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 * @author Philippe Buschmann
21 * @file gns/plugin_rest_gns.c
22 * @brief GNUnet GNS REST plugin
23 *
24 */
25
26#include "platform.h"
27#include "gnunet_rest_plugin.h"
28#include <gnunet_dnsparser_lib.h>
29#include <gnunet_identity_service.h>
30#include <gnunet_gnsrecord_lib.h>
31#include <gnunet_namestore_service.h>
32#include <gnunet_gns_service.h>
33#include <gnunet_rest_lib.h>
34#include <gnunet_jsonapi_lib.h>
35#include <gnunet_jsonapi_util.h>
36#include <jansson.h>
37
38#define GNUNET_REST_API_NS_GNS "/gns"
39
40#define GNUNET_REST_JSONAPI_GNS_RECORD_TYPE "record_type"
41
42#define GNUNET_REST_PARAMETER_GNS_NAME "name"
43
44#define GNUNET_REST_JSONAPI_GNS_TYPEINFO "gns_name"
45
46#define GNUNET_REST_JSONAPI_GNS_RECORD "records"
47
48#define GNUNET_REST_JSONAPI_GNS_EGO "ego"
49
50#define GNUNET_REST_JSONAPI_GNS_PKEY "pkey"
51
52#define GNUNET_REST_JSONAPI_GNS_OPTIONS "options"
53
54/**
55 * @brief struct returned by the initialization function of the plugin
56 */
57struct Plugin
58{
59 const struct GNUNET_CONFIGURATION_Handle *cfg;
60};
61
62const struct GNUNET_CONFIGURATION_Handle *cfg;
63
64struct LookupHandle
65{
66 /**
67 * Handle to GNS service.
68 */
69 struct GNUNET_GNS_Handle *gns;
70
71 /**
72 * Desired timeout for the lookup (default is no timeout).
73 */
74 struct GNUNET_TIME_Relative timeout;
75
76 /**
77 * Handle to lookup request
78 */
79 struct GNUNET_GNS_LookupRequest *lookup_request;
80
81 /**
82 * Handle to rest request
83 */
84 struct GNUNET_REST_RequestHandle *rest_handle;
85
86 /**
87 * Lookup an ego with the identity service.
88 */
89 struct GNUNET_IDENTITY_EgoLookup *el;
90
91 /**
92 * Handle for identity service.
93 */
94 struct GNUNET_IDENTITY_Handle *identity;
95
96 /**
97 * Active operation on identity service.
98 */
99 struct GNUNET_IDENTITY_Operation *id_op;
100
101 /**
102 * ID of a task associated with the resolution process.
103 */
104 struct GNUNET_SCHEDULER_Task * timeout_task;
105
106 /**
107 * The root of the received JSON or NULL
108 */
109 json_t *json_root;
110
111 /**
112 * The plugin result processor
113 */
114 GNUNET_REST_ResultProcessor proc;
115
116 /**
117 * The closure of the result processor
118 */
119 void *proc_cls;
120
121 /**
122 * The name to look up
123 */
124 char *name;
125
126 /**
127 * The ego to use
128 * In string representation from JSON
129 */
130 const char *ego_str;
131
132 /**
133 * The Pkey to use
134 * In string representation from JSON
135 */
136 const char *pkey_str;
137
138 /**
139 * The record type
140 */
141 int type;
142
143 /**
144 * The public key of to use for lookup
145 */
146 struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
147
148 /**
149 * The public key to use for lookup
150 */
151 struct GNUNET_CRYPTO_EcdsaPublicKey pkeym;
152
153 /**
154 * The resolver options
155 */
156 enum GNUNET_GNS_LocalOptions options;
157
158 /**
159 * the shorten key
160 */
161 struct GNUNET_CRYPTO_EcdsaPrivateKey shorten_key;
162
163 /**
164 * HTTP response code
165 */
166 int response_code;
167
168 /**
169 * HTTP response code
170 */
171 char* emsg;
172
173};
174
175
176/**
177 * Cleanup lookup handle.
178 *
179 * @param handle Handle to clean up
180 */
181static void
182cleanup_handle (struct LookupHandle *handle)
183{
184 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
185 "Cleaning up\n");
186 if (NULL != handle->json_root)
187 json_decref (handle->json_root);
188
189 if (NULL != handle->name)
190 GNUNET_free (handle->name);
191 if (NULL != handle->emsg)
192 GNUNET_free (handle->emsg);
193 if (NULL != handle->el)
194 {
195 GNUNET_IDENTITY_ego_lookup_cancel (handle->el);
196 handle->el = NULL;
197 }
198 if (NULL != handle->id_op)
199 {
200 GNUNET_IDENTITY_cancel (handle->id_op);
201 handle->id_op = NULL;
202 }
203 if (NULL != handle->lookup_request)
204 {
205 GNUNET_GNS_lookup_cancel (handle->lookup_request);
206 handle->lookup_request = NULL;
207 }
208 if (NULL != handle->identity)
209 {
210 GNUNET_IDENTITY_disconnect (handle->identity);
211 handle->identity = NULL;
212 }
213 if (NULL != handle->gns)
214 {
215 GNUNET_GNS_disconnect (handle->gns);
216 handle->gns = NULL;
217 }
218
219 if (NULL != handle->timeout_task)
220 {
221 GNUNET_SCHEDULER_cancel (handle->timeout_task);
222 }
223 GNUNET_free (handle);
224}
225
226
227/**
228 * Task run on shutdown. Cleans up everything.
229 *
230 * @param cls unused
231 * @param tc scheduler context
232 */
233static void
234do_error (void *cls)
235{
236 struct LookupHandle *handle = cls;
237 struct MHD_Response *resp;
238 char *json_error;
239
240 if (NULL == handle->emsg)
241 handle->emsg = GNUNET_strdup("Unknown Error");
242
243 GNUNET_asprintf (&json_error, "{\"error\": \"%s\"}", handle->emsg);
244 handle->response_code = MHD_HTTP_OK;
245
246 resp = GNUNET_REST_create_response (json_error);
247 handle->proc (handle->proc_cls, resp, handle->response_code);
248 cleanup_handle (handle);
249 GNUNET_free(json_error);
250}
251
252
253/**
254 * Create json representation of a GNSRECORD
255 *
256 * @param rd the GNSRECORD_Data
257 */
258static json_t *
259gnsrecord_to_json (const struct GNUNET_GNSRECORD_Data *rd)
260{
261 const char *typename;
262 char *string_val;
263 const char *exp_str;
264 json_t *record_obj;
265
266 typename = GNUNET_GNSRECORD_number_to_typename (rd->record_type);
267 string_val = GNUNET_GNSRECORD_value_to_string (rd->record_type,
268 rd->data,
269 rd->data_size);
270
271 if (NULL == string_val)
272 {
273 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
274 "Record of type %d malformed, skipping\n",
275 (int) rd->record_type);
276 return NULL;
277 }
278 record_obj = json_object ();
279 json_object_set_new (record_obj, "type", json_string (typename));
280 json_object_set_new (record_obj, "value", json_string (string_val));
281 GNUNET_free (string_val);
282
283 if (GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION & rd->flags)
284 {
285 struct GNUNET_TIME_Relative time_rel;
286 time_rel.rel_value_us = rd->expiration_time;
287 exp_str = GNUNET_STRINGS_relative_time_to_string (time_rel, 1);
288 }
289 else
290 {
291 struct GNUNET_TIME_Absolute time_abs;
292 time_abs.abs_value_us = rd->expiration_time;
293 exp_str = GNUNET_STRINGS_absolute_time_to_string (time_abs);
294 }
295 json_object_set_new (record_obj, "expiration_time", json_string (exp_str));
296
297 json_object_set_new (record_obj, "expired",
298 json_boolean (GNUNET_YES == GNUNET_GNSRECORD_is_expired (rd)));
299 return record_obj;
300}
301
302/**
303 * Function called with the result of a GNS lookup.
304 *
305 * @param cls the 'const char *' name that was resolved
306 * @param rd_count number of records returned
307 * @param rd array of @a rd_count records with the results
308 */
309static void
310process_lookup_result (void *cls, uint32_t rd_count,
311 const struct GNUNET_GNSRECORD_Data *rd)
312{
313 struct LookupHandle *handle = cls;
314 struct MHD_Response *resp;
315 uint32_t i;
316 char *result;
317 json_t *result_array;
318 json_t *record_obj;
319
320 result_array = json_array();
321 handle->lookup_request = NULL;
322 for (i=0; i<rd_count; i++)
323 {
324 if ( (rd[i].record_type != handle->type) &&
325 (GNUNET_GNSRECORD_TYPE_ANY != handle->type) )
326 continue;
327 record_obj = gnsrecord_to_json (&(rd[i]));
328 json_array_append (result_array, record_obj);
329 json_decref (record_obj);
330 }
331 result = json_dumps(result_array, 0);
332 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result);
333 resp = GNUNET_REST_create_response (result);
334 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
335 GNUNET_free (result);
336 json_decref (result_array);
337 cleanup_handle (handle);
338}
339
340
341/**
342 * Perform the actual resolution, starting with the zone
343 * identified by the given public key and the shorten zone.
344 *
345 * @param pkey public key to use for the zone, can be NULL
346 */
347static void
348lookup_with_public_key (struct LookupHandle *handle)
349{
350 if (UINT32_MAX == handle->type)
351 {
352 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
353 _("Invalid typename specified, assuming `ANY'\n"));
354 handle->type = GNUNET_GNSRECORD_TYPE_ANY;
355 }
356 if (NULL != handle->name)
357 {
358 handle->lookup_request = GNUNET_GNS_lookup (handle->gns,
359 handle->name,
360 &handle->pkey,
361 handle->type,
362 handle->options,
363 &process_lookup_result,
364 handle);
365 }
366 else
367 {
368 handle->emsg = GNUNET_strdup("Parameter name is missing");
369 GNUNET_SCHEDULER_add_now (&do_error, handle);
370 return;
371 }
372}
373
374
375/**
376 * Method called to with the ego we are to use for the lookup,
377 * when the ego is determined by a name.
378 *
379 * @param cls closure (NULL, unused)
380 * @param ego ego handle, NULL if not found
381 */
382static void
383identity_zone_cb (void *cls,
384 const struct GNUNET_IDENTITY_Ego *ego)
385{
386 struct LookupHandle *handle = cls;
387
388 handle->el = NULL;
389 if (NULL == ego)
390 {
391 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
392 _("Ego for not found, cannot perform lookup.\n"));
393 handle->emsg = GNUNET_strdup ("Ego for not found, cannot perform lookup.");
394 GNUNET_SCHEDULER_add_now (&do_error, handle);
395 return;
396 }
397 else
398 {
399 GNUNET_IDENTITY_ego_get_public_key (ego, &handle->pkey);
400 lookup_with_public_key (handle);
401 }
402 json_decref(handle->json_root);
403}
404
405
406/**
407 * Method called to with the ego we are to use for the lookup,
408 * when the ego is the one for the default master zone.
409 *
410 * @param cls closure (NULL, unused)
411 * @param ego ego handle, NULL if not found
412 * @param ctx context for application to store data for this ego
413 * (during the lifetime of this process, initially NULL)
414 * @param name name assigned by the user for this ego,
415 * NULL if the user just deleted the ego and it
416 * must thus no longer be used
417 */
418static void
419identity_master_cb (void *cls,
420 struct GNUNET_IDENTITY_Ego *ego,
421 void **ctx,
422 const char *name)
423{
424 const char *dot;
425 struct LookupHandle *handle = cls;
426
427 handle->id_op = NULL;
428 if (NULL == ego)
429 {
430 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
431 _("Ego for `gns-master' not found, cannot perform lookup. Did you run gnunet-gns-import.sh?\n"));
432 handle->emsg = GNUNET_strdup("Ego for `gns-master' not found, cannot perform lookup. Did you run gnunet-gns-import.sh?");
433 GNUNET_SCHEDULER_add_now (&do_error, handle);
434 return;
435 }
436 GNUNET_IDENTITY_ego_get_public_key (ego,
437 &handle->pkey);
438 /* main name is our own master zone, do no look for that in the DHT */
439 handle->options = GNUNET_GNS_LO_LOCAL_MASTER;
440 /* if the name is of the form 'label.gnu', never go to the DHT */
441 dot = NULL;
442 if (NULL != handle->name)
443 dot = strchr (handle->name, '.');
444 if ( (NULL != dot) &&
445 (0 == strcasecmp (dot, ".gnu")) )
446 handle->options = GNUNET_GNS_LO_NO_DHT;
447 lookup_with_public_key (handle);
448}
449
450/**
451 * Handle get request
452 *
453 * @param handle the lookup handle
454 */
455static void
456get_gns_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
457 const char* url,
458 void *cls)
459{
460 struct LookupHandle *handle = cls;
461 struct GNUNET_HashCode key;
462 long int enum_test;
463 char *temp_val;
464
465 //check for /gns otherwise 404
466 if (strlen (GNUNET_REST_API_NS_GNS) > strlen (url))
467 {
468 handle->emsg = GNUNET_strdup("Wrong URL");
469 GNUNET_SCHEDULER_add_now (&do_error, handle);
470 return;
471 }
472
473 //connect to gns
474 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
475 handle->gns = GNUNET_GNS_connect (cfg);
476 handle->identity = GNUNET_IDENTITY_connect (cfg, NULL, NULL);
477 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
478 &do_error, handle);
479 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
480 if (NULL == handle->gns)
481 {
482 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Connecting to GNS failed\n");
483 handle->emsg = GNUNET_strdup("Connecting to GNS failed");
484 GNUNET_SCHEDULER_add_now (&do_error, handle);
485 return;
486 }
487
488 //check parameter name -> BAD_REQUEST
489 GNUNET_CRYPTO_hash (GNUNET_REST_PARAMETER_GNS_NAME,
490 strlen (GNUNET_REST_PARAMETER_GNS_NAME),
491 &key);
492 if ( GNUNET_NO
493 == GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
494 &key))
495 {
496 handle->emsg = GNUNET_strdup("Parameter name is missing");
497 GNUNET_SCHEDULER_add_now (&do_error, handle);
498 return;
499 }
500 handle->name = GNUNET_strdup(GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
501 &key));
502
503 //check parameter record_type, optional
504 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_RECORD_TYPE,
505 strlen (GNUNET_REST_JSONAPI_GNS_RECORD_TYPE),
506 &key);
507 if ( GNUNET_YES ==
508 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
509 &key) )
510 {
511 handle->type = GNUNET_GNSRECORD_typename_to_number(
512 GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
513 &key));
514 }
515 else
516 {
517 handle->type = GNUNET_GNSRECORD_TYPE_ANY;
518 }
519
520 //check parameter options, optional
521 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_OPTIONS,
522 strlen (GNUNET_REST_JSONAPI_GNS_OPTIONS),
523 &key);
524 handle->options = GNUNET_GNS_LO_DEFAULT;
525 if ( GNUNET_YES
526 == GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
527 &key))
528 {
529 temp_val = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, &key);
530 if (1 < strlen(temp_val))
531 {
532 handle->options = GNUNET_GNS_LO_DEFAULT;
533 }
534 else
535 {
536 //atoi because no valid conversion is default local option
537 enum_test = atoi(temp_val);
538 if (2 < enum_test)
539 handle->options = GNUNET_GNS_LO_DEFAULT;
540 else
541 handle->options = enum_test;
542 }
543 }
544 else
545 handle->options = GNUNET_GNS_LO_DEFAULT;
546
547 //check parameter pkey, shortcut to lookup
548 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_PKEY,
549 strlen (GNUNET_REST_JSONAPI_GNS_PKEY),
550 &key);
551 if ( GNUNET_YES
552 == GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
553 &key))
554 {
555 handle->pkey_str = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
556 &key);
557 GNUNET_assert(NULL != handle->pkey_str);
558 if (GNUNET_OK
559 != GNUNET_CRYPTO_ecdsa_public_key_from_string (
560 handle->pkey_str, strlen (handle->pkey_str), &(handle->pkey)))
561 {
562 handle->emsg = GNUNET_strdup("Parameter pkey has a wrong format");
563 GNUNET_SCHEDULER_add_now (&do_error, handle);
564 return;
565 }
566 lookup_with_public_key (handle);
567 return;
568 }
569
570 //check parameter ego, lookup public key of ego
571 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_EGO,
572 strlen (GNUNET_REST_JSONAPI_GNS_EGO),
573 &key);
574 if ( GNUNET_YES ==
575 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
576 &key) )
577 {
578 handle->ego_str = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
579 &key);
580 handle->el = GNUNET_IDENTITY_ego_lookup (cfg,
581 handle->ego_str,
582 &identity_zone_cb,
583 handle);
584 return;
585 }
586
587 //if name ends with .zkey then get public key
588 if ( (NULL != handle->name) &&
589 (strlen (handle->name) > 4) &&
590 (0 == strcmp (".zkey",
591 &handle->name[strlen (handle->name) - 4])) )
592 {
593 GNUNET_CRYPTO_ecdsa_key_get_public( GNUNET_CRYPTO_ecdsa_key_get_anonymous (),
594 &(handle->pkey));
595 lookup_with_public_key (handle);
596 }
597 else //else use gns-master identity
598 {
599 handle->id_op = GNUNET_IDENTITY_get (handle->identity,
600 "gns-master",
601 &identity_master_cb,
602 handle);
603 }
604}
605
606/**
607 * Handle rest request
608 *
609 * @param handle the lookup handle
610 */
611static void
612options_cont (struct GNUNET_REST_RequestHandle *con_handle,
613 const char* url,
614 void *cls)
615{
616 struct MHD_Response *resp;
617 struct LookupHandle *handle = cls;
618
619 //For GNS, independent of path return all options
620 resp = GNUNET_REST_create_response (NULL);
621 MHD_add_response_header (resp,
622 "Access-Control-Allow-Methods",
623 MHD_HTTP_METHOD_GET);
624 handle->proc (handle->proc_cls,
625 resp,
626 MHD_HTTP_OK);
627 cleanup_handle (handle);
628}
629
630
631/**
632 * Function processing the REST call
633 *
634 * @param method HTTP method
635 * @param url URL of the HTTP request
636 * @param data body of the HTTP request (optional)
637 * @param data_size length of the body
638 * @param proc callback function for the result
639 * @param proc_cls closure for @a proc
640 * @return #GNUNET_OK if request accepted
641 */
642static void
643rest_gns_process_request (struct GNUNET_REST_RequestHandle *conndata_handle,
644 GNUNET_REST_ResultProcessor proc,
645 void *proc_cls)
646{
647 static const struct GNUNET_REST_RequestHandler handlers[] = {
648 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_GNS, &get_gns_cont},
649 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_GNS, &options_cont},
650 GNUNET_REST_HANDLER_END
651 };
652 struct LookupHandle *handle = GNUNET_new (struct LookupHandle);
653 struct GNUNET_REST_RequestHandlerError err;
654
655 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
656 handle->proc_cls = proc_cls;
657 handle->proc = proc;
658 handle->rest_handle = conndata_handle;
659
660 if (GNUNET_NO == GNUNET_REST_handle_request (conndata_handle,
661 handlers,
662 &err,
663 handle))
664 {
665 handle->response_code = err.error_code;
666 GNUNET_SCHEDULER_add_now (&do_error, handle);
667 }
668}
669
670
671/**
672 * Entry point for the plugin.
673 *
674 * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
675 * @return NULL on error, otherwise the plugin context
676 */
677void *
678libgnunet_plugin_rest_gns_init (void *cls)
679{
680 static struct Plugin plugin;
681 cfg = cls;
682 struct GNUNET_REST_Plugin *api;
683
684 if (NULL != plugin.cfg)
685 return NULL; /* can only initialize once! */
686 memset (&plugin, 0, sizeof (struct Plugin));
687 plugin.cfg = cfg;
688 api = GNUNET_new (struct GNUNET_REST_Plugin);
689 api->cls = &plugin;
690 api->name = GNUNET_REST_API_NS_GNS;
691 api->process_request = &rest_gns_process_request;
692 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
693 _("GNS REST API initialized\n"));
694 return api;
695}
696
697
698/**
699 * Exit point from the plugin.
700 *
701 * @param cls the plugin context (as returned by "init")
702 * @return always NULL
703 */
704void *
705libgnunet_plugin_rest_gns_done (void *cls)
706{
707 struct GNUNET_REST_Plugin *api = cls;
708 struct Plugin *plugin = api->cls;
709
710 plugin->cfg = NULL;
711 GNUNET_free (api);
712 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
713 "GNS REST plugin is finished\n");
714 return NULL;
715}
716
717/* end of plugin_rest_gns.c */