/*
This file is part of GNUnet.
- Copyright (C) 2012-2015 Christian Grothoff (and other contributing authors)
+ Copyright (C) 2012-2015 GNUnet e.V.
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
#include "gnunet_namestore_service.h"
#include "gnunet_identity_service.h"
#include "gnunet_rest_lib.h"
+#include "gnunet_jsonapi_lib.h"
+#include "gnunet_jsonapi_util.h"
#include "microhttpd.h"
#include <jansson.h>
* DLL
*/
struct RecordEntry *next;
-
+
/**
* DLL
*/
struct RecordEntry *prev;
-
+
};
struct RequestHandle
/**
* JSON response object
*/
- struct JsonApiObject *resp_object;
-
+ struct GNUNET_JSONAPI_Document *resp_object;
+
/**
* Rest connection
*/
- struct RestConnectionDataHandle *conndata_handle;
-
+ struct GNUNET_REST_RequestHandle *rest_handle;
+
/**
* Handle to GNS service.
*/
* Handle to NAMESTORE
*/
struct GNUNET_NAMESTORE_Handle *ns_handle;
-
+
/**
* Handle to NAMESTORE it
*/
struct GNUNET_NAMESTORE_ZoneIterator *list_it;
-
+
/**
* Private key for the zone
*/
/**
* ID of a task associated with the resolution process.
*/
- struct GNUNET_SCHEDULER_Task * timeout_task;
+ struct GNUNET_SCHEDULER_Task * timeout_task;
/**
* The plugin result processor
char *url;
/**
- * The data from the REST request
- */
- const char* data;
-
- /**
- * the length of the REST data
+ * Cfg
*/
- size_t data_size;
+ const struct GNUNET_CONFIGURATION_Handle *cfg;
/**
- * Cfg
+ * HTTP response code
*/
- const struct GNUNET_CONFIGURATION_Handle *cfg;
+ int response_code;
};
/**
* Cleanup lookup handle
+ *
* @param handle Handle to clean up
*/
static void
struct RecordEntry *record_entry;
struct RecordEntry *record_tmp;
int i;
+
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Cleaning up\n");
if (NULL != handle->resp_object)
- GNUNET_REST_jsonapi_object_delete (handle->resp_object);
+ GNUNET_JSONAPI_document_delete (handle->resp_object);
if (NULL != handle->name)
GNUNET_free (handle->name);
if (NULL != handle->timeout_task)
GNUNET_free (handle);
}
+
/**
* Create json representation of a GNSRECORD
*
/**
- * Task run on shutdown. Cleans up everything.
+ * Task run on error. Generates error response and cleans up.
*
- * @param cls unused
- * @param tc scheduler context
+ * @param cls the request to generate an error response for
*/
static void
-do_error (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
+do_error (void *cls)
{
struct RequestHandle *handle = cls;
- struct MHD_Response *resp = GNUNET_REST_create_json_response (NULL);
- handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
+ struct MHD_Response *resp = GNUNET_REST_create_response (NULL);
+
+ handle->proc (handle->proc_cls, resp, handle->response_code);
cleanup_handle (handle);
}
+
+/**
+ * Task run on timeout.
+ *
+ * @param cls the request to time out
+ */
+static void
+do_timeout (void *cls)
+{
+ struct RequestHandle *handle = cls;
+
+ handle->timeout_task = NULL;
+ do_error (handle);
+}
+
+
static void
-cleanup_handle_delayed (void *cls,
- const struct GNUNET_SCHEDULER_TaskContext *tc)
+cleanup_handle_delayed (void *cls)
{
cleanup_handle (cls);
}
+
/**
* Create a response with requested records
*
const struct GNUNET_GNSRECORD_Data *rd)
{
struct RequestHandle *handle = cls;
- struct JsonApiResource *json_resource;
+ struct GNUNET_JSONAPI_Resource *json_resource;
struct MHD_Response *resp;
json_t *result_array;
json_t *record_obj;
char *result;
if (NULL == handle->resp_object)
- handle->resp_object = GNUNET_REST_jsonapi_object_new ();
+ handle->resp_object = GNUNET_JSONAPI_document_new ();
if (NULL == rname)
{
handle->list_it = NULL;
//Handle response
- if (GNUNET_SYSERR == GNUNET_REST_jsonapi_data_serialize (handle->resp_object, &result))
+ if (GNUNET_SYSERR == GNUNET_JSONAPI_document_serialize (handle->resp_object, &result))
{
GNUNET_SCHEDULER_add_now (&do_error, handle);
return;
}
- resp = GNUNET_REST_create_json_response (result);
+ resp = GNUNET_REST_create_response (result);
handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
- GNUNET_free (result);
+ GNUNET_free_non_null (result);
GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
return;
}
if (0 < json_array_size(result_array))
{
- json_resource = GNUNET_REST_jsonapi_resource_new (GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO,
+ json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO,
rname);
- GNUNET_REST_jsonapi_resource_add_attr (json_resource,
+ GNUNET_JSONAPI_resource_add_attr (json_resource,
GNUNET_REST_JSONAPI_NAMESTORE_RECORD,
result_array);
- GNUNET_REST_jsonapi_object_resource_add (handle->resp_object, json_resource);
+ GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
}
json_decref (result_array);
GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
return;
}
- resp = GNUNET_REST_create_json_response (NULL);
+ resp = GNUNET_REST_create_response (NULL);
handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT);
GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
}
if (0 != rd_count)
{
handle->proc (handle->proc_cls,
- GNUNET_REST_create_json_response (NULL),
+ GNUNET_REST_create_response (NULL),
MHD_HTTP_CONFLICT);
GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
return;
return;
}
handle->proc (handle->proc_cls,
- GNUNET_REST_create_json_response (NULL),
+ GNUNET_REST_create_response (NULL),
MHD_HTTP_NO_CONTENT);
GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
}
}
static void
-namestore_delete_cont (struct RestConnectionDataHandle *con,
+namestore_delete_cont (struct GNUNET_REST_RequestHandle *con,
const char *url,
void *cls)
{
"Value property is no string\n");
return GNUNET_SYSERR;
}
- GNUNET_asprintf (&value, "%s", json_string_value (value_json));
+ value = GNUNET_strdup (json_string_value (value_json));
if (GNUNET_OK != GNUNET_GNSRECORD_string_to_value ((*rd)[i].record_type,
value,
&rdata,
{
(*rd)[i].expiration_time = etime_abs.abs_value_us;
}
- else
+ else
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Value `%s' invalid for record type `%s'\n"),
value, typestring);
}
static void
-namestore_create_cont (struct RestConnectionDataHandle *con,
+namestore_create_cont (struct GNUNET_REST_RequestHandle *con,
const char *url,
void *cls)
{
struct RequestHandle *handle = cls;
struct MHD_Response *resp;
- struct JsonApiObject *json_obj;
- struct JsonApiResource *json_res;
- json_t *name_json;
+ struct GNUNET_JSONAPI_Document *json_obj;
+ struct GNUNET_JSONAPI_Resource *json_res;
json_t *records_json;
- char term_data[handle->data_size+1];
-
+ json_t *data_js;
+ json_error_t err;
+ char term_data[handle->rest_handle->data_size+1];
+ struct GNUNET_JSON_Specification docspec[] = {
+ GNUNET_JSON_spec_jsonapi_document (&json_obj),
+ GNUNET_JSON_spec_end()
+ };
+
if (strlen (GNUNET_REST_API_NS_NAMESTORE) != strlen (handle->url))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
GNUNET_SCHEDULER_add_now (&do_error, handle);
return;
}
- if (0 >= handle->data_size)
+ if (0 >= handle->rest_handle->data_size)
{
GNUNET_SCHEDULER_add_now (&do_error, handle);
return;
}
- term_data[handle->data_size] = '\0';
- memcpy (term_data, handle->data, handle->data_size);
- json_obj = GNUNET_REST_jsonapi_object_parse (term_data);
+ term_data[handle->rest_handle->data_size] = '\0';
+ memcpy (term_data,
+ handle->rest_handle->data,
+ handle->rest_handle->data_size);
+ data_js = json_loads (term_data,
+ JSON_DECODE_ANY,
+ &err);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_JSON_parse (data_js, docspec,
+ NULL, NULL));
+ json_decref (data_js);
if (NULL == json_obj)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
GNUNET_SCHEDULER_add_now (&do_error, handle);
return;
}
- if (1 != GNUNET_REST_jsonapi_object_resource_count (json_obj))
+ if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Cannot create more than 1 resource! (Got %d)\n",
- GNUNET_REST_jsonapi_object_resource_count (json_obj));
- GNUNET_REST_jsonapi_object_delete (json_obj);
+ GNUNET_JSONAPI_document_resource_count (json_obj));
+ GNUNET_JSONAPI_document_delete (json_obj);
GNUNET_SCHEDULER_add_now (&do_error, handle);
return;
}
- json_res = GNUNET_REST_jsonapi_object_get_resource (json_obj, 0);
- if (GNUNET_NO == GNUNET_REST_jsonapi_resource_check_type (json_res,
- GNUNET_REST_JSONAPI_NAMESTORE_RECORD))
+ json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
+ if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
+ GNUNET_REST_JSONAPI_NAMESTORE_RECORD))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unsupported JSON data type\n");
- GNUNET_REST_jsonapi_object_delete (json_obj);
- resp = GNUNET_REST_create_json_response (NULL);
+ GNUNET_JSONAPI_document_delete (json_obj);
+ resp = GNUNET_REST_create_response (NULL);
handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
cleanup_handle (handle);
return;
}
- name_json = GNUNET_REST_jsonapi_resource_read_attr (json_res, GNUNET_REST_JSONAPI_KEY_ID);
- if (!json_is_string (name_json))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Name property is no string\n");
- GNUNET_REST_jsonapi_object_delete (json_obj);
- GNUNET_SCHEDULER_add_now (&do_error, handle);
- return;
- }
- GNUNET_asprintf (&handle->name, "%s", json_string_value (name_json));
- records_json = GNUNET_REST_jsonapi_resource_read_attr (json_res,
- GNUNET_REST_JSONAPI_NAMESTORE_RECORD);
+ handle->name = GNUNET_strdup (GNUNET_JSONAPI_resource_get_id (json_res));
+ records_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+ GNUNET_REST_JSONAPI_NAMESTORE_RECORD);
if (NULL == records_json)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"No records given\n");
- GNUNET_REST_jsonapi_object_delete (json_obj);
+ GNUNET_JSONAPI_document_delete (json_obj);
GNUNET_SCHEDULER_add_now (&do_error, handle);
return;
}
if (GNUNET_SYSERR == json_to_gnsrecord (records_json, &handle->rd, &handle->rd_count))
{
- GNUNET_REST_jsonapi_object_delete (json_obj);
+ GNUNET_JSONAPI_document_delete (json_obj);
GNUNET_SCHEDULER_add_now (&do_error, handle);
return;
}
- GNUNET_REST_jsonapi_object_delete (json_obj);
+ GNUNET_JSONAPI_document_delete (json_obj);
handle->add_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle,
&handle->zone_pkey,
{
struct RequestHandle *handle = cls;
struct MHD_Response *resp;
- struct JsonApiObject *json_obj;
- struct JsonApiResource *json_res;
+ struct GNUNET_JSONAPI_Document *json_obj;
+ struct GNUNET_JSONAPI_Resource *json_res;
json_t *name_json;
char* result;
handle->reverse_qe = NULL;
- json_obj = GNUNET_REST_jsonapi_object_new ();
+ json_obj = GNUNET_JSONAPI_document_new ();
if (NULL != label)
{
name_json = json_string (label);
- json_res = GNUNET_REST_jsonapi_resource_new (GNUNET_REST_JSONAPI_NAMESTORE_REVINFO,
- handle->zkey_str);
- GNUNET_REST_jsonapi_resource_add_attr (json_res,
- GNUNET_REST_JSONAPI_NAMESTORE_NAME,
- name_json);
- GNUNET_REST_jsonapi_object_resource_add (json_obj, json_res);
+ json_res = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_NAMESTORE_REVINFO,
+ handle->zkey_str);
+ GNUNET_JSONAPI_resource_add_attr (json_res,
+ GNUNET_REST_JSONAPI_NAMESTORE_NAME,
+ name_json);
+ GNUNET_JSONAPI_document_resource_add (json_obj, json_res);
json_decref (name_json);
}
//Handle response
- if (GNUNET_SYSERR == GNUNET_REST_jsonapi_data_serialize (json_obj, &result))
+ if (GNUNET_SYSERR == GNUNET_JSONAPI_document_serialize (json_obj, &result))
{
- GNUNET_REST_jsonapi_object_delete (json_obj);
+ GNUNET_JSONAPI_document_delete (json_obj);
GNUNET_SCHEDULER_add_now (&do_error, handle);
return;
}
- resp = GNUNET_REST_create_json_response (result);
+ resp = GNUNET_REST_create_response (result);
handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
- GNUNET_REST_jsonapi_object_delete (json_obj);
+ GNUNET_JSONAPI_document_delete (json_obj);
GNUNET_free (result);
GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
return;
}
static void
-namestore_zkey_cont (struct RestConnectionDataHandle *con,
+namestore_zkey_cont (struct GNUNET_REST_RequestHandle *con,
const char *url,
void *cls)
{
GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_NAMESTORE_ZKEY,
strlen (GNUNET_REST_JSONAPI_NAMESTORE_ZKEY),
&key);
- if ( GNUNET_NO ==
- GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
+ if ( GNUNET_NO ==
+ GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
&key) )
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
GNUNET_SCHEDULER_add_now (&do_error, handle);
return;
}
- handle->zkey_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
- &key);
+ handle->zkey_str = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
+ &key);
if (GNUNET_OK !=
GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->zkey_str,
strlen (handle->zkey_str),
}
static void
-namestore_info_cont (struct RestConnectionDataHandle *con,
+namestore_info_cont (struct GNUNET_REST_RequestHandle *con,
const char *url,
void *cls)
{
* @param cls the RequestHandle
*/
static void
-options_cont (struct RestConnectionDataHandle *con_handle,
+options_cont (struct GNUNET_REST_RequestHandle *con_handle,
const char* url,
void *cls)
{
struct RequestHandle *handle = cls;
//For now, independent of path return all options
- resp = GNUNET_REST_create_json_response (NULL);
+ resp = GNUNET_REST_create_response (NULL);
MHD_add_response_header (resp,
"Access-Control-Allow-Methods",
allow_methods);
int result)
{
struct RequestHandle *handle = cls;
- static const struct GNUNET_REST_RestConnectionHandler handlers[] = {
+ struct GNUNET_REST_RequestHandlerError err;
+ static const struct GNUNET_REST_RequestHandler handlers[] = {
{MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE_ZKEY, &namestore_zkey_cont}, //reverse
{MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE, &namestore_info_cont}, //list
{MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE, &namestore_create_cont}, //create
return;
}
- if (GNUNET_NO == GNUNET_REST_handle_request (handle->conndata_handle, handlers, handle))
+ if (GNUNET_OK != GNUNET_JSONAPI_handle_request (handle->rest_handle,
+ handlers,
+ &err,
+ handle))
+ {
+ handle->response_code = err.error_code;
GNUNET_SCHEDULER_add_now (&do_error, (void*) handle);
+ }
}
_("Ego `%s' not known to identity service\n"),
handle->ego_name);
}
- resp = GNUNET_REST_create_json_response (NULL);
+ resp = GNUNET_REST_create_response (NULL);
handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND);
cleanup_handle (handle);
return;
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
_("No default ego configured in identity service\n"));
- resp = GNUNET_REST_create_json_response (NULL);
+ resp = GNUNET_REST_create_response (NULL);
handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND);
cleanup_handle (handle);
return;
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
_("Identity service is not running\n"));
- resp = GNUNET_REST_create_json_response (NULL);
+ resp = GNUNET_REST_create_response (NULL);
handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND);
cleanup_handle (handle);
return;
GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_NAMESTORE_EGO,
strlen (GNUNET_REST_JSONAPI_NAMESTORE_EGO),
&key);
- if ( GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
+ if ( GNUNET_YES ==
+ GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
&key) )
{
- ego = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
+ ego = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
&key);
}
GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE,
strlen (GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE),
&key);
- if ( GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
+ if ( GNUNET_YES ==
+ GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
&key) )
{
- type = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
+ type = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
&key);
handle->type = GNUNET_GNSRECORD_typename_to_number (type);
}
name = get_name_from_url (handle->url);
if (NULL != ego)
- GNUNET_asprintf (&handle->ego_name, "%s", ego);
+ handle->ego_name = GNUNET_strdup (ego);
if (NULL != name)
- GNUNET_asprintf (&handle->name, "%s", name);
+ handle->name = GNUNET_strdup (name);
if (NULL == handle->ego_name)
{
handle->identity_handle = GNUNET_IDENTITY_connect (handle->cfg, &id_connect_cb, handle);
if (NULL == handle->identity_handle)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Cannot connect to identity service\n"));
- resp = GNUNET_REST_create_json_response (NULL);
+ resp = GNUNET_REST_create_response (NULL);
handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND);
cleanup_handle (handle);
}
* @return GNUNET_OK if request accepted
*/
static void
-rest_identity_process_request(struct RestConnectionDataHandle *conndata_handle,
+rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle,
GNUNET_REST_ResultProcessor proc,
void *proc_cls)
{
handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
handle->proc_cls = proc_cls;
handle->proc = proc;
- handle->conndata_handle = conndata_handle;
- handle->data = conndata_handle->data;
- handle->data_size = conndata_handle->data_size;
- GNUNET_asprintf (&handle->url, "%s", conndata_handle->url);
+ handle->rest_handle = rest_handle;
+ handle->url = GNUNET_strdup (rest_handle->url);
if (handle->url[strlen (handle->url)-1] == '/')
handle->url[strlen (handle->url)-1] = '\0';
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
&testservice_id_task,
handle);
handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
- &do_error,
+ &do_timeout,
handle);
-
-
}
/**