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