From 2c2e76228330e4024062a5e8b4ef75f7f04cabbd Mon Sep 17 00:00:00 2001 From: Phil Date: Sat, 2 Jun 2018 00:34:58 +0200 Subject: -wip remove jsonapi from identity --- src/identity/plugin_rest_identity.c | 45 +++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/identity/plugin_rest_identity.c b/src/identity/plugin_rest_identity.c index 6044d0641..97f50ff03 100644 --- a/src/identity/plugin_rest_identity.c +++ b/src/identity/plugin_rest_identity.c @@ -349,6 +349,7 @@ get_ego_for_subsys (void *cls, cleanup_handle (handle); } +//TODO clean up, fix memleaks /** * Create a response with requested ego(s) * @@ -369,9 +370,12 @@ ego_info_response (struct GNUNET_REST_RequestHandle *con, struct EgoEntry *ego_entry; struct GNUNET_HashCode key; struct MHD_Response *resp; - struct GNUNET_JSONAPI_Document *json_document; - struct GNUNET_JSONAPI_Resource *json_resource; + //struct GNUNET_JSONAPI_Document *json_document; + //struct GNUNET_JSONAPI_Resource *json_resource; + json_t *json_root; + json_t *json_ego; json_t *name_str; + struct GNUNET_JSON_Specification test; if (GNUNET_NO == GNUNET_REST_namespace_match (handle->url, GNUNET_REST_API_NS_IDENTITY)) { @@ -419,7 +423,8 @@ ego_info_response (struct GNUNET_REST_RequestHandle *con, } } - json_document = GNUNET_JSONAPI_document_new (); + json_root = json_array(); + //json_document = GNUNET_JSONAPI_document_new (); //Return all egos for (ego_entry = handle->ego_head; @@ -428,27 +433,39 @@ ego_info_response (struct GNUNET_REST_RequestHandle *con, { if ( (NULL != egoname) && (0 != strcmp (egoname, ego_entry->identifier)) ) continue; - json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_EGO, - ego_entry->keystring); + + //json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_EGO, + // ego_entry->keystring); + json_ego = json_object(); + json_object_set_new( json_ego, "id", json_string (ego_entry->keystring)); + json_object_set_new( json_ego, "type", json_string (GNUNET_REST_JSONAPI_IDENTITY_EGO)); name_str = json_string (ego_entry->identifier); - GNUNET_JSONAPI_resource_add_attr ( - json_resource, - GNUNET_REST_JSONAPI_IDENTITY_NAME, - name_str); + json_object_set_new( json_ego, "name", name_str); + json_array_append( json_root, json_ego ); + //GNUNET_JSONAPI_resource_add_attr ( + // json_resource, + // GNUNET_REST_JSONAPI_IDENTITY_NAME, + // name_str); json_decref (name_str); - GNUNET_JSONAPI_document_resource_add (json_document, json_resource); + //GNUNET_JSONAPI_document_resource_add (json_document, json_resource); } - if (0 == GNUNET_JSONAPI_document_resource_count (json_document)) + //if (0 == GNUNET_JSONAPI_document_resource_count (json_document)) + if (0 == json_array_size(json_root)) { - GNUNET_JSONAPI_document_delete (json_document); + //GNUNET_JSONAPI_document_delete (json_document); + json_decref (json_root); handle->emsg = GNUNET_strdup ("No identities found!"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - GNUNET_JSONAPI_document_serialize (json_document, &result_str); + //TODO here parse + //GNUNET_JSONAPI_document_serialize (json_document, &result_str); + //GNUNET_JSON_parse(); + result_str = json_dumps(json_root, 0); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); resp = GNUNET_REST_create_response (result_str); - GNUNET_JSONAPI_document_delete (json_document); + //GNUNET_JSONAPI_document_delete (json_document); + json_decref (json_root); handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); GNUNET_free (result_str); cleanup_handle (handle); -- cgit v1.2.3 From 320c62a4f5b7dac08394cd6f6b82666df4d499e9 Mon Sep 17 00:00:00 2001 From: Phil Date: Sat, 2 Jun 2018 22:15:59 +0200 Subject: removed jsonapi structures --- src/identity/plugin_rest_identity.c | 244 ++++++++++++++++++++++-------------- 1 file changed, 149 insertions(+), 95 deletions(-) (limited to 'src') diff --git a/src/identity/plugin_rest_identity.c b/src/identity/plugin_rest_identity.c index 97f50ff03..3fe749a52 100644 --- a/src/identity/plugin_rest_identity.c +++ b/src/identity/plugin_rest_identity.c @@ -19,6 +19,7 @@ */ /** * @author Martin Schanzenbach + * @author Philippe Buschmann * @file identity/plugin_rest_identity.c * @brief GNUnet Namestore REST plugin * @@ -76,6 +77,7 @@ */ #define GNUNET_REST_ERROR_RESOURCE_INVALID "Resource location invalid" #define GNUNET_REST_ERROR_NO_DATA "No data" +#define GNUNET_REST_ERROR_DATA_INVALID "Data invalid" /** * GNUid token lifetime @@ -279,9 +281,9 @@ do_error (void *cls) char *json_error; GNUNET_asprintf (&json_error, - "{Error while processing request: %s}", - &handle->emsg); - + "{\"error\": \"%s\"}", + handle->emsg); + handle->response_code = MHD_HTTP_OK; resp = GNUNET_REST_create_response (json_error); handle->proc (handle->proc_cls, resp, @@ -306,14 +308,15 @@ get_ego_for_subsys (void *cls, const char *name) { struct RequestHandle *handle = cls; - struct GNUNET_JSONAPI_Document *json_document; - struct GNUNET_JSONAPI_Resource *json_resource; struct EgoEntry *ego_entry; struct MHD_Response *resp; + json_t *json_root; + json_t *json_ego; json_t *name_json; char *result_str; + size_t index; - json_document = GNUNET_JSONAPI_document_new (); + json_root = json_array(); for (ego_entry = handle->ego_head; NULL != ego_entry; @@ -323,33 +326,38 @@ get_ego_for_subsys (void *cls, continue; if (NULL == name) continue; - json_resource = GNUNET_JSONAPI_resource_new - (GNUNET_REST_JSONAPI_IDENTITY_EGO, ego_entry->keystring); + + json_ego = json_object(); name_json = json_string (ego_entry->identifier); - GNUNET_JSONAPI_resource_add_attr (json_resource, - GNUNET_REST_JSONAPI_IDENTITY_NAME, - name_json); - json_decref (name_json); - GNUNET_JSONAPI_document_resource_add (json_document, json_resource); + json_object_set_new(json_ego, GNUNET_REST_JSONAPI_IDENTITY_EGO, name_json); + json_array_append(json_root, json_ego); + break; } - if (0 == GNUNET_JSONAPI_document_resource_count (json_document)) + + if (0 == json_array_size(json_root)) { - GNUNET_JSONAPI_document_delete (json_document); + json_decref(json_root); handle->emsg = GNUNET_strdup("No identity matches results!"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - GNUNET_JSONAPI_document_serialize (json_document, &result_str); + + result_str = json_dumps(json_root, 0); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); resp = GNUNET_REST_create_response (result_str); - GNUNET_JSONAPI_document_delete (json_document); + + json_array_foreach(json_root, index, json_ego ) + { + json_decref(json_ego); + } + json_decref (json_root); handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); GNUNET_free (result_str); cleanup_handle (handle); } -//TODO clean up, fix memleaks + /** * Create a response with requested ego(s) * @@ -370,12 +378,10 @@ ego_info_response (struct GNUNET_REST_RequestHandle *con, struct EgoEntry *ego_entry; struct GNUNET_HashCode key; struct MHD_Response *resp; - //struct GNUNET_JSONAPI_Document *json_document; - //struct GNUNET_JSONAPI_Resource *json_resource; json_t *json_root; json_t *json_ego; json_t *name_str; - struct GNUNET_JSON_Specification test; + size_t index; if (GNUNET_NO == GNUNET_REST_namespace_match (handle->url, GNUNET_REST_API_NS_IDENTITY)) { @@ -424,7 +430,6 @@ ego_info_response (struct GNUNET_REST_RequestHandle *con, } json_root = json_array(); - //json_document = GNUNET_JSONAPI_document_new (); //Return all egos for (ego_entry = handle->ego_head; @@ -434,37 +439,33 @@ ego_info_response (struct GNUNET_REST_RequestHandle *con, if ( (NULL != egoname) && (0 != strcmp (egoname, ego_entry->identifier)) ) continue; - //json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_EGO, - // ego_entry->keystring); json_ego = json_object(); + json_object_set_new( json_ego, "id", json_string (ego_entry->keystring)); json_object_set_new( json_ego, "type", json_string (GNUNET_REST_JSONAPI_IDENTITY_EGO)); name_str = json_string (ego_entry->identifier); json_object_set_new( json_ego, "name", name_str); + json_array_append( json_root, json_ego ); - //GNUNET_JSONAPI_resource_add_attr ( - // json_resource, - // GNUNET_REST_JSONAPI_IDENTITY_NAME, - // name_str); - json_decref (name_str); - //GNUNET_JSONAPI_document_resource_add (json_document, json_resource); - } - //if (0 == GNUNET_JSONAPI_document_resource_count (json_document)) - if (0 == json_array_size(json_root)) + } + + if ((size_t)0 == json_array_size(json_root)) { - //GNUNET_JSONAPI_document_delete (json_document); - json_decref (json_root); + json_decref (json_root); handle->emsg = GNUNET_strdup ("No identities found!"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - //TODO here parse - //GNUNET_JSONAPI_document_serialize (json_document, &result_str); - //GNUNET_JSON_parse(); + result_str = json_dumps(json_root, 0); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); resp = GNUNET_REST_create_response (result_str); - //GNUNET_JSONAPI_document_delete (json_document); + + //delete json_objects in json_array with macro + json_array_foreach(json_root, index, json_ego ) + { + json_decref(json_ego); + } json_decref (json_root); handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); GNUNET_free (result_str); @@ -491,10 +492,80 @@ do_finished (void *cls, const char *emsg) return; } resp = GNUNET_REST_create_response (NULL); - handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT); + handle->proc (handle->proc_cls, resp, MHD_HTTP_CREATED); cleanup_handle (handle); } +// +// +///** +// * Parse given JSON object to jsonapi document. +// * +// * @param cls closure, NULL +// * @param root the json object representing data +// * @param[out] spec where to write the data +// * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error +// */ +//static int +//parse_jsonapiobject (void *cls, json_t *root, +// struct GNUNET_JSON_Specification *spec) +//{ +// if (NULL == root) +// { +// return GNUNET_SYSERR; +// } +// if (1 == json_is_object(root)) +// { +// if (1 == json_is_string(json_object_get (root, GNUNET_REST_JSONAPI_IDENTITY_NAME))) +// { +// return GNUNET_OK; +// } +// } +// return GNUNET_SYSERR; +//} +// +///** +// * Cleanup data left from parsing RSA public key. +// * +// * @param cls closure, NULL +// * @param[out] spec where to free the data +// */ +//static void +//clean_jsonapiobject (void *cls, +// struct GNUNET_JSON_Specification *spec) +//{ +// json_t **jsonapi_obj = (json_t **) spec->ptr; +// if (NULL != *jsonapi_obj) +// { +// json_decref (*jsonapi_obj); +// *jsonapi_obj = NULL; +// } +//} +// +///** +// * JSON object. +// * +// * @param name name of the JSON field +// * @param[out] jsonp where to store the JSON found under @a name +// */ +//struct GNUNET_JSON_Specification +//GNUNET_JSON_spec_json_create_identity (json_t **jsonapi_object) +//{ +// struct GNUNET_JSON_Specification ret = { +// .parser = &parse_jsonapiobject, +// .cleaner = &clean_jsonapiobject, +// .cls = NULL, +// .field = NULL, +// .ptr = jsonapi_object, +// .ptr_size = 0, +// .size_ptr = NULL +// }; +// *jsonapi_object = NULL; +// return ret; +//} + + + /** * Create a new ego * @@ -510,23 +581,19 @@ ego_create_cont (struct GNUNET_REST_RequestHandle *con, struct RequestHandle *handle = cls; struct EgoEntry *ego_entry; struct MHD_Response *resp; - struct GNUNET_JSONAPI_Document *json_obj; - struct GNUNET_JSONAPI_Resource *json_res; json_t *egoname_json; json_t *data_js; json_error_t err; const char* egoname; char term_data[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_IDENTITY) != strlen (handle->url)) { handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_RESOURCE_INVALID); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } + if (0 >= handle->data_size) { handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA); @@ -538,38 +605,34 @@ ego_create_cont (struct GNUNET_REST_RequestHandle *con, data_js = json_loads (term_data, JSON_DECODE_ANY, &err); - GNUNET_assert (NULL != data_js); - GNUNET_assert (GNUNET_OK == - GNUNET_JSON_parse (data_js, docspec, - NULL, NULL)); - json_decref (data_js); - if (NULL == json_obj) + if (NULL == data_js) { + handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_DATA_INVALID); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - if (1 != GNUNET_JSONAPI_document_resource_count (json_obj)) + //instead of parse + if (!json_is_object(data_js)) { - GNUNET_JSONAPI_document_delete (json_obj); - handle->emsg = GNUNET_strdup ("Provided resource count invalid"); + handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_DATA_INVALID); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0); - if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res, GNUNET_REST_JSONAPI_IDENTITY_EGO)) + + if (1 != json_object_size(data_js)) { - GNUNET_JSONAPI_document_delete (json_obj); - resp = GNUNET_REST_create_response (NULL); - handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); - cleanup_handle (handle); + json_decref (data_js); + handle->emsg = GNUNET_strdup ("Provided resource count invalid"); + GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - egoname_json = GNUNET_JSONAPI_resource_read_attr (json_res, GNUNET_REST_JSONAPI_IDENTITY_NAME); + + egoname_json = json_object_get (data_js, GNUNET_REST_JSONAPI_IDENTITY_NAME); if (!json_is_string (egoname_json)) { - GNUNET_JSONAPI_document_delete (json_obj); + json_decref (data_js); handle->emsg = GNUNET_strdup ("No name provided"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; @@ -581,7 +644,7 @@ ego_create_cont (struct GNUNET_REST_RequestHandle *con, { if (0 == strcasecmp (egoname, ego_entry->identifier)) { - GNUNET_JSONAPI_document_delete (json_obj); + json_decref (data_js); resp = GNUNET_REST_create_response (NULL); handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); cleanup_handle (handle); @@ -589,7 +652,7 @@ ego_create_cont (struct GNUNET_REST_RequestHandle *con, } } GNUNET_asprintf (&handle->name, "%s", egoname); - GNUNET_JSONAPI_document_delete (json_obj); + json_decref (data_js); handle->op = GNUNET_IDENTITY_create (handle->identity_handle, handle->name, &do_finished, @@ -609,8 +672,6 @@ ego_edit_cont (struct GNUNET_REST_RequestHandle *con, const char *url, void *cls) { - struct GNUNET_JSONAPI_Document *json_obj; - struct GNUNET_JSONAPI_Resource *json_res; struct RequestHandle *handle = cls; struct EgoEntry *ego_entry; struct EgoEntry *ego_entry_tmp; @@ -624,10 +685,6 @@ ego_edit_cont (struct GNUNET_REST_RequestHandle *con, const char *newname; char term_data[handle->data_size+1]; int ego_exists = GNUNET_NO; - struct GNUNET_JSON_Specification docspec[] = { - GNUNET_JSON_spec_jsonapi_document (&json_obj), - GNUNET_JSON_spec_end() - }; if (strlen (GNUNET_REST_API_NS_IDENTITY) > strlen (handle->url)) { @@ -668,40 +725,30 @@ ego_edit_cont (struct GNUNET_REST_RequestHandle *con, data_js = json_loads (term_data, JSON_DECODE_ANY, &err); - GNUNET_assert (NULL != data_js); - GNUNET_assert (GNUNET_OK == - GNUNET_JSON_parse (data_js, docspec, - NULL, NULL)); - - json_decref (data_js); - - if (NULL == json_obj) + if (NULL == data_js) { - handle->emsg = GNUNET_strdup ("Data invalid"); + handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - - if (1 != GNUNET_JSONAPI_document_resource_count (json_obj)) + if (!json_is_object(data_js)) { - GNUNET_JSONAPI_document_delete (json_obj); - handle->emsg = GNUNET_strdup ("Resource amount invalid"); + json_decref (data_js); + handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_DATA_INVALID); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0); - if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res, GNUNET_REST_JSONAPI_IDENTITY_EGO)) + if (1 != json_object_size(data_js)) { - GNUNET_JSONAPI_document_delete (json_obj); - handle->emsg = GNUNET_strdup ("Resource type invalid"); + json_decref (data_js); + handle->emsg = GNUNET_strdup ("Resource amount invalid"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } //This is a rename - name_json = GNUNET_JSONAPI_resource_read_attr (json_res, - GNUNET_REST_JSONAPI_IDENTITY_NEWNAME); + name_json = json_object_get (data_js, GNUNET_REST_JSONAPI_IDENTITY_NEWNAME); if ((NULL != name_json) && json_is_string (name_json)) { newname = json_string_value (name_json); @@ -713,7 +760,7 @@ ego_edit_cont (struct GNUNET_REST_RequestHandle *con, 0 != strcasecmp (keystring, ego_entry_tmp->keystring)) { //Ego with same name not allowed - GNUNET_JSONAPI_document_delete (json_obj); + json_decref (data_js); resp = GNUNET_REST_create_response (NULL); handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); cleanup_handle (handle); @@ -725,17 +772,17 @@ ego_edit_cont (struct GNUNET_REST_RequestHandle *con, newname, &do_finished, handle); - GNUNET_JSONAPI_document_delete (json_obj); + json_decref (data_js); return; } //Set subsystem - subsys_json = GNUNET_JSONAPI_resource_read_attr (json_res, GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM); + subsys_json = json_object_get (data_js, GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM); if ( (NULL != subsys_json) && json_is_string (subsys_json)) { subsys = json_string_value (subsys_json); GNUNET_asprintf (&handle->subsys, "%s", subsys); - GNUNET_JSONAPI_document_delete (json_obj); + json_decref (data_js); handle->op = GNUNET_IDENTITY_set (handle->identity_handle, handle->subsys, ego_entry->ego, @@ -743,11 +790,18 @@ ego_edit_cont (struct GNUNET_REST_RequestHandle *con, handle); return; } - GNUNET_JSONAPI_document_delete (json_obj); + json_decref (data_js); handle->emsg = GNUNET_strdup ("Subsystem not provided"); GNUNET_SCHEDULER_add_now (&do_error, handle); } +/** + * Handle ego delete request + * + * @param con_handle the connection handle + * @param url the url + * @param cls the RequestHandle + */ void ego_delete_cont (struct GNUNET_REST_RequestHandle *con_handle, const char* url, -- cgit v1.2.3 From 4ab30f893f22c75d1aafcc9584cd7eac6c4d82a0 Mon Sep 17 00:00:00 2001 From: Phil Date: Mon, 4 Jun 2018 23:50:00 +0200 Subject: identity rest api - finished and added test_script --- src/identity/plugin_rest_identity.c | 34 +++- src/identity/test_plugin_identity_rest.sh | 252 ++++++++++++++++++++++++++++++ 2 files changed, 282 insertions(+), 4 deletions(-) create mode 100755 src/identity/test_plugin_identity_rest.sh (limited to 'src') diff --git a/src/identity/plugin_rest_identity.c b/src/identity/plugin_rest_identity.c index 3fe749a52..49d7b58af 100644 --- a/src/identity/plugin_rest_identity.c +++ b/src/identity/plugin_rest_identity.c @@ -492,7 +492,7 @@ do_finished (void *cls, const char *emsg) return; } resp = GNUNET_REST_create_response (NULL); - handle->proc (handle->proc_cls, resp, MHD_HTTP_CREATED); + handle->proc (handle->proc_cls, resp, handle->response_code); cleanup_handle (handle); } @@ -616,15 +616,16 @@ ego_create_cont (struct GNUNET_REST_RequestHandle *con, //instead of parse if (!json_is_object(data_js)) { + json_decref(data_js); handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_DATA_INVALID); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - if (1 != json_object_size(data_js)) + if (1 != json_object_size (data_js)) { json_decref (data_js); - handle->emsg = GNUNET_strdup ("Provided resource count invalid"); + handle->emsg = GNUNET_strdup("Provided resource count invalid"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } @@ -638,6 +639,13 @@ ego_create_cont (struct GNUNET_REST_RequestHandle *con, return; } egoname = json_string_value (egoname_json); + if(0 >= strlen(egoname)) + { + json_decref (data_js); + handle->emsg = GNUNET_strdup ("No name provided"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = ego_entry->next) @@ -653,6 +661,7 @@ ego_create_cont (struct GNUNET_REST_RequestHandle *con, } GNUNET_asprintf (&handle->name, "%s", egoname); json_decref (data_js); + handle->response_code = MHD_HTTP_CREATED; handle->op = GNUNET_IDENTITY_create (handle->identity_handle, handle->name, &do_finished, @@ -752,6 +761,13 @@ ego_edit_cont (struct GNUNET_REST_RequestHandle *con, if ((NULL != name_json) && json_is_string (name_json)) { newname = json_string_value (name_json); + if(0 >= strlen(newname)) + { + json_decref (data_js); + handle->emsg = GNUNET_strdup ("No name provided"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } for (ego_entry_tmp = handle->ego_head; NULL != ego_entry_tmp; ego_entry_tmp = ego_entry_tmp->next) @@ -767,6 +783,7 @@ ego_edit_cont (struct GNUNET_REST_RequestHandle *con, return; } } + handle->response_code = MHD_HTTP_NO_CONTENT; handle->op = GNUNET_IDENTITY_rename (handle->identity_handle, ego_entry->identifier, newname, @@ -781,8 +798,16 @@ ego_edit_cont (struct GNUNET_REST_RequestHandle *con, if ( (NULL != subsys_json) && json_is_string (subsys_json)) { subsys = json_string_value (subsys_json); + if(0 >= strlen(subsys)) + { + json_decref (data_js); + handle->emsg = GNUNET_strdup ("No name provided"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } GNUNET_asprintf (&handle->subsys, "%s", subsys); json_decref (data_js); + handle->response_code = MHD_HTTP_NO_CONTENT; handle->op = GNUNET_IDENTITY_set (handle->identity_handle, handle->subsys, ego_entry->ego, @@ -837,6 +862,7 @@ ego_delete_cont (struct GNUNET_REST_RequestHandle *con_handle, cleanup_handle (handle); return; } + handle->response_code = MHD_HTTP_NO_CONTENT; handle->op = GNUNET_IDENTITY_delete (handle->identity_handle, ego_entry->identifier, &do_finished, @@ -980,7 +1006,7 @@ rest_identity_process_request(struct GNUNET_REST_RequestHandle *conndata_handle, handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; - + handle->response_code = MHD_HTTP_OK; handle->proc_cls = proc_cls; handle->proc = proc; handle->state = ID_REST_STATE_INIT; diff --git a/src/identity/test_plugin_identity_rest.sh b/src/identity/test_plugin_identity_rest.sh new file mode 100755 index 000000000..d43f4206b --- /dev/null +++ b/src/identity/test_plugin_identity_rest.sh @@ -0,0 +1,252 @@ +#!/usr/bin/bash + +#First, start gnunet-arm and the rest-service. Make sure, no identity exists + +link_to_api="http://localhost:7776/identity" +wrong_link="http://localhost:7776/idenmmmy" + +#Test GET (multiple identities) for error when no identity exists + +echo "No test for subsystem available" +echo "The next test case can be ignored if you have already added identities" +cache="$(curl --silent "$link_to_api" | grep "error")" +if [ "" == "$cache" ] +then + echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for GET request when missing identity\n" +else + echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for GET request when missing identity\n" +fi + +#Test POST success code, error response code and error json +echo "The next test case can be ignored if you have already added an identity with the name Test" +cache="$(curl -v -X "POST" "$link_to_api" --data "{\"name\":\"Test\"}" 2>&1 | grep "HTTP/1.1 201")" +if [ "" == "$cache" ] +then + echo -n -e "[\033[0;31m FAILURE\033[0m ] Error for good POST request\n" +else + echo -n -e "[\033[0;32m SUCCESS\033[0m ] Success for good POST request\n" +fi + +cache="$(curl -v -X "POST" "$link_to_api" --data "{\"name\":\"Test\"}" 2>&1 | grep "HTTP/1.1 409")" +if [ "" == "$cache" ] +then + echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for duplicate name POST request\n" +else + echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for duplicate name POST request\n" +fi + +cache="$(curl -v -X "POST" "$link_to_api" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for no data POST request\n" +else + echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for no data POST request\n" +fi + +cache="$(curl -v -X "POST" "$link_to_api" --data "wrong" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong data POST request\n" +else + echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong data POST request\n" +fi + +cache="$(curl -v -X "POST" "$link_to_api" --data "[{}]" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for json array input POST request\n" +else + echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for json array input POST request\n" +fi + +cache="$(curl -v -X "POST" "$link_to_api" --data "{\"name\":\"Test\",\"other\":\"Test\"}" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for multi element json POST request\n" +else + echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for multi element json POST request\n" +fi + +cache="$(curl -v -X "POST" "$link_to_api" --data "{\"nam\":\"Test\"}" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong json POST request\n" +else + echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong json POST request\n" +fi + +cache="$(curl -v -X "POST" "$link_to_api" --data "{\"name\":123}" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong json type POST request\n" +else + echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong json type POST request\n" +fi + +cache="$(curl -v -X "POST" "$link_to_api" --data "{\"name\":""}" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for no name POST request\n" +else + echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for no name POST request\n" +fi + + +#Test GET (multiple identities) for success and error json +cache="$(curl --silent "$link_to_api" | grep "error")" +if [ "" == "$cache" ] +then + echo -n -e "[\033[0;32m SUCCESS\033[0m ] Success for good GET request (multiple identities)\n" +else + echo -n -e "[\033[0;31m FAILURE\033[0m ] Error for good GET request (multiple identities)\n" +fi + + +id="$(gnunet-identity -d | grep "Test - " | sed "s/Test - //g")" +#Test GET (one identity) for success and error json +cache="$(curl --silent "${link_to_api}/$id" | grep "error")" +if [ "" == "$cache" ] +then + echo -n -e "[\033[0;32m SUCCESS\033[0m ] Success for good GET request (one identity)\n" +else + echo -n -e "[\033[0;31m FAILURE\033[0m ] Error for good GET request (one identity)\n" +fi + + +#Test DELETE success code, error response code and error json +echo "Next tests for DELETE will probably fail when POST fails" +cache="$(curl -v -X "DELETE" "${link_to_api}/$id" 2>&1 | grep "HTTP/1.1 404")" +if [ "" == "$cache" ] +then + echo -n -e "[\033[0;32m SUCCESS\033[0m ] Success for good DELETE request\n" +else + echo -n -e "[\033[0;31m FAILURE\033[0m ] Error for good DELETE request\n" +fi + +curl --silent -X "POST" "$link_to_api" --data "{\"name\":\"Test\"}" +id="$(gnunet-identity -d | grep "Test - " | sed "s/Test - //g")" + +cache="$(curl -v -X "DELETE" "${link_to_api}/df1" 2>&1 | grep "HTTP/1.1 404")" +if [ "" == "$cache" ] +then + echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong DELETE request\n" +else + echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong DELETE request\n" +fi + +#Test PUT success code, error response codes and error json +cache="$(curl -v -X "PUT" "${link_to_api}/$id" --data "{\"newname\":\"NewTest\"}" 2>&1 | grep "HTTP/1.1 204")" +if [ "" == "$cache" ] +then + echo -n -e "[\033[0;31m FAILURE\033[0m ] Error for good PUT request\n" +else + echo -n -e "[\033[0;32m SUCCESS\033[0m ] Success for good PUT request\n" +fi + +cache="$(curl -v -X "PUT" "${link_to_api}/${id}1" --data "{\"newname\":\"NewNewTest\"}" 2>&1 | grep "HTTP/1.1 404")" +if [ "" == "$cache" ] +then + echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong identity PUT request\n" +else + echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong identity PUT request\n" +fi + +cache="$(curl -v -X "PUT" "$link_to_api/$id" --data "{\"newname\":\"NewTest\"}" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for duplicate name PUT request\n" +else + echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for duplicate name PUT request\n" +fi + +cache="$(curl -v -X "PUT" "$link_to_api/$id" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for no data PUT request\n" +else + echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for no data PUT request\n" +fi + +cache="$(curl -v -X "PUT" "$link_to_api/$id" --data "wrong" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong data PUT request\n" +else + echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong data PUT request\n" +fi + +cache="$(curl -v -X "PUT" "$link_to_api/$id" --data "[{}]" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for json array input PUT request\n" +else + echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for json array input PUT request\n" +fi + +cache="$(curl -v -X "PUT" "$link_to_api/$id" --data "{\"newname\":\"Test\",\"other\":\"Test\"}" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for multi element json PUT request\n" +else + echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for multi element json PUT request\n" +fi + +cache="$(curl -v -X "PUT" "$link_to_api/$id" --data "{\"newnam\":\"Test\"}" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong json PUT request\n" +else + echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong json PUT request\n" +fi + +cache="$(curl -v -X "PUT" "$link_to_api/$id" --data "{\"newname\":123}" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong json type PUT request\n" +else + echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong json type PUT request\n" +fi + +cache="$(curl -v -X "PUT" "$link_to_api/$id" --data "{\"newname\":""}" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for no name PUT request\n" +else + echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for no name PUT request\n" +fi +#TODO Missing subsystem test + +#Missing OPTIONS success - nothing can really go wrong here + +#Test wrong url +cache="$(curl -v "$wrong_link" 2>&1 | grep "HTTP/1.1 404")" +if [ "" == "$cache" ] +then + echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong url GET request \n" +else + echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong url GET request \n" +fi + +cache="$(curl -X "PUT" -v "$wrong_link/$id" --data "{\"newname\":\"Testing\"}" 2>&1 | grep "HTTP/1.1 404")" +if [ "" == "$cache" ] +then + echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong url GET request \n" +else + echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong url GET request \n" +fi + +cache="$(curl -X "POST" -v "$wrong_link/$id" --data "{\"name\":\"Test\"}" 2>&1 | grep "HTTP/1.1 404")" +if [ "" == "$cache" ] +then + echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong url POST request \n" +else + echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong url POST request \n" +fi + +cache="$(curl -X "DELETE" -v "${wrong_link}/$id" 2>&1 | grep "HTTP/1.1 404")" +if [ "" == "$cache" ] +then + echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong url DELETE request \n" +else + echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong url DELETE request \n" +fi -- cgit v1.2.3 From f5aae6fb1455b197c54073d0be807b460268da6d Mon Sep 17 00:00:00 2001 From: Phil Date: Tue, 5 Jun 2018 00:33:30 +0200 Subject: cleanup identity rest api, removed jsonapi includes --- src/identity/plugin_rest_identity.c | 96 +++++-------------------------------- 1 file changed, 12 insertions(+), 84 deletions(-) (limited to 'src') diff --git a/src/identity/plugin_rest_identity.c b/src/identity/plugin_rest_identity.c index 49d7b58af..957a200b5 100644 --- a/src/identity/plugin_rest_identity.c +++ b/src/identity/plugin_rest_identity.c @@ -29,8 +29,6 @@ #include "gnunet_rest_plugin.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 #include "gnunet_signatures.h" @@ -53,23 +51,23 @@ /** * Resource type */ -#define GNUNET_REST_JSONAPI_IDENTITY_EGO "ego" +#define GNUNET_REST_JSON_IDENTITY_EGO "ego" /** * Name attribute */ -#define GNUNET_REST_JSONAPI_IDENTITY_NAME "name" +#define GNUNET_REST_JSON_IDENTITY_NAME "name" /** * Attribute to rename "name" TODO we changed id to the pubkey * so this can be unified with "name" */ -#define GNUNET_REST_JSONAPI_IDENTITY_NEWNAME "newname" +#define GNUNET_REST_JSON_IDENTITY_NEWNAME "newname" /** * URL parameter to change the subsytem for ego */ -#define GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM "subsystem" +#define GNUNET_REST_JSON_IDENTITY_SUBSYSTEM "subsystem" /** @@ -329,7 +327,7 @@ get_ego_for_subsys (void *cls, json_ego = json_object(); name_json = json_string (ego_entry->identifier); - json_object_set_new(json_ego, GNUNET_REST_JSONAPI_IDENTITY_EGO, name_json); + json_object_set_new(json_ego, GNUNET_REST_JSON_IDENTITY_EGO, name_json); json_array_append(json_root, json_ego); break; @@ -407,8 +405,8 @@ ego_info_response (struct GNUNET_REST_RequestHandle *con, } if ( NULL == egoname ) { - GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM, - strlen (GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM), + GNUNET_CRYPTO_hash (GNUNET_REST_JSON_IDENTITY_SUBSYSTEM, + strlen (GNUNET_REST_JSON_IDENTITY_SUBSYSTEM), &key); if ( GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, @@ -442,7 +440,7 @@ ego_info_response (struct GNUNET_REST_RequestHandle *con, json_ego = json_object(); json_object_set_new( json_ego, "id", json_string (ego_entry->keystring)); - json_object_set_new( json_ego, "type", json_string (GNUNET_REST_JSONAPI_IDENTITY_EGO)); + json_object_set_new( json_ego, "type", json_string (GNUNET_REST_JSON_IDENTITY_EGO)); name_str = json_string (ego_entry->identifier); json_object_set_new( json_ego, "name", name_str); @@ -496,76 +494,6 @@ do_finished (void *cls, const char *emsg) cleanup_handle (handle); } -// -// -///** -// * Parse given JSON object to jsonapi document. -// * -// * @param cls closure, NULL -// * @param root the json object representing data -// * @param[out] spec where to write the data -// * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error -// */ -//static int -//parse_jsonapiobject (void *cls, json_t *root, -// struct GNUNET_JSON_Specification *spec) -//{ -// if (NULL == root) -// { -// return GNUNET_SYSERR; -// } -// if (1 == json_is_object(root)) -// { -// if (1 == json_is_string(json_object_get (root, GNUNET_REST_JSONAPI_IDENTITY_NAME))) -// { -// return GNUNET_OK; -// } -// } -// return GNUNET_SYSERR; -//} -// -///** -// * Cleanup data left from parsing RSA public key. -// * -// * @param cls closure, NULL -// * @param[out] spec where to free the data -// */ -//static void -//clean_jsonapiobject (void *cls, -// struct GNUNET_JSON_Specification *spec) -//{ -// json_t **jsonapi_obj = (json_t **) spec->ptr; -// if (NULL != *jsonapi_obj) -// { -// json_decref (*jsonapi_obj); -// *jsonapi_obj = NULL; -// } -//} -// -///** -// * JSON object. -// * -// * @param name name of the JSON field -// * @param[out] jsonp where to store the JSON found under @a name -// */ -//struct GNUNET_JSON_Specification -//GNUNET_JSON_spec_json_create_identity (json_t **jsonapi_object) -//{ -// struct GNUNET_JSON_Specification ret = { -// .parser = &parse_jsonapiobject, -// .cleaner = &clean_jsonapiobject, -// .cls = NULL, -// .field = NULL, -// .ptr = jsonapi_object, -// .ptr_size = 0, -// .size_ptr = NULL -// }; -// *jsonapi_object = NULL; -// return ret; -//} - - - /** * Create a new ego * @@ -630,7 +558,7 @@ ego_create_cont (struct GNUNET_REST_RequestHandle *con, return; } - egoname_json = json_object_get (data_js, GNUNET_REST_JSONAPI_IDENTITY_NAME); + egoname_json = json_object_get (data_js, GNUNET_REST_JSON_IDENTITY_NAME); if (!json_is_string (egoname_json)) { json_decref (data_js); @@ -757,7 +685,7 @@ ego_edit_cont (struct GNUNET_REST_RequestHandle *con, } //This is a rename - name_json = json_object_get (data_js, GNUNET_REST_JSONAPI_IDENTITY_NEWNAME); + name_json = json_object_get (data_js, GNUNET_REST_JSON_IDENTITY_NEWNAME); if ((NULL != name_json) && json_is_string (name_json)) { newname = json_string_value (name_json); @@ -794,7 +722,7 @@ ego_edit_cont (struct GNUNET_REST_RequestHandle *con, } //Set subsystem - subsys_json = json_object_get (data_js, GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM); + subsys_json = json_object_get (data_js, GNUNET_REST_JSON_IDENTITY_SUBSYSTEM); if ( (NULL != subsys_json) && json_is_string (subsys_json)) { subsys = json_string_value (subsys_json); @@ -914,7 +842,7 @@ init_cont (struct RequestHandle *handle) GNUNET_REST_HANDLER_END }; - if (GNUNET_NO == GNUNET_JSONAPI_handle_request (handle->conndata_handle, + if (GNUNET_NO == GNUNET_REST_handle_request (handle->conndata_handle, handlers, &err, handle)) -- cgit v1.2.3 From c1062075eddca49cfeaac8f7fd8c84e73198c2aa Mon Sep 17 00:00:00 2001 From: Phil Date: Sun, 10 Jun 2018 19:02:07 +0200 Subject: -wip error gns --- src/gns/plugin_rest_gns.c | 188 ++++++++++++++++++++---------------- src/identity/plugin_rest_identity.c | 18 ++-- 2 files changed, 116 insertions(+), 90 deletions(-) (limited to 'src') diff --git a/src/gns/plugin_rest_gns.c b/src/gns/plugin_rest_gns.c index 1d215b6a4..eeb74887e 100644 --- a/src/gns/plugin_rest_gns.c +++ b/src/gns/plugin_rest_gns.c @@ -19,6 +19,7 @@ */ /** * @author Martin Schanzenbach + * @author Philippe Buschmann * @file gns/plugin_rest_gns.c * @brief GNUnet GNS REST plugin * @@ -40,6 +41,8 @@ #define GNUNET_REST_JSONAPI_GNS_RECORD_TYPE "record_type" +#define GNUNET_REST_PARAMETER_GNS_NAME "name" + #define GNUNET_REST_JSONAPI_GNS_TYPEINFO "gns_name" #define GNUNET_REST_JSONAPI_GNS_RECORD "records" @@ -164,6 +167,11 @@ struct LookupHandle */ int response_code; + /** + * HTTP response code + */ + char* emsg; + }; @@ -182,6 +190,8 @@ cleanup_handle (struct LookupHandle *handle) if (NULL != handle->name) GNUNET_free (handle->name); + if (NULL != handle->emsg) + GNUNET_free (handle->emsg); if (NULL != handle->el) { GNUNET_IDENTITY_ego_lookup_cancel (handle->el); @@ -227,10 +237,18 @@ do_error (void *cls) { struct LookupHandle *handle = cls; struct MHD_Response *resp; + char *json_error; - resp = GNUNET_REST_create_response (NULL); + if (NULL == handle->emsg) + handle->emsg = GNUNET_strdup("Unknown Error"); + + GNUNET_asprintf (&json_error, "{\"error\": \"%s\"}", handle->emsg); + handle->response_code = MHD_HTTP_OK; + + resp = GNUNET_REST_create_response (json_error); handle->proc (handle->proc_cls, resp, handle->response_code); cleanup_handle (handle); + GNUNET_free(json_error); } @@ -296,16 +314,12 @@ process_lookup_result (void *cls, uint32_t rd_count, { struct LookupHandle *handle = cls; struct MHD_Response *resp; - struct GNUNET_JSONAPI_Document *json_document; - struct GNUNET_JSONAPI_Resource *json_resource; uint32_t i; char *result; json_t *result_array; json_t *record_obj; result_array = json_array(); - json_document = GNUNET_JSONAPI_document_new (); - json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_GNS_TYPEINFO, handle->name); handle->lookup_request = NULL; for (i=0; iproc (handle->proc_cls, resp, MHD_HTTP_OK); GNUNET_free (result); + json_decref (result_array); cleanup_handle (handle); } @@ -358,6 +367,7 @@ lookup_with_public_key (struct LookupHandle *handle) } else { + handle->emsg = GNUNET_strdup("Parameter name is missing"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } @@ -382,6 +392,7 @@ identity_zone_cb (void *cls, { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Ego for not found, cannot perform lookup.\n")); + handle->emsg = GNUNET_strdup ("Ego for not found, cannot perform lookup."); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } @@ -420,6 +431,7 @@ identity_master_cb (void *cls, { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Ego for `gns-master' not found, cannot perform lookup. Did you run gnunet-gns-import.sh?\n")); + handle->emsg = GNUNET_strdup("Ego for `gns-master' not found, cannot perform lookup. Did you run gnunet-gns-import.sh?"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } @@ -438,35 +450,10 @@ identity_master_cb (void *cls, } /** - * Parse REST uri for name and record type + * Handle get request * - * @param url Url to parse - * @param handle lookup handle to populate - * @return GNUNET_SYSERR on error + * @param handle the lookup handle */ -static int -parse_url (const char *url, struct LookupHandle *handle) -{ - char *name; - char tmp_url[strlen(url)+1]; - char *tok; - - strcpy (tmp_url, url); - tok = strtok ((char*)tmp_url, "/"); - if (NULL == tok) - return GNUNET_SYSERR; - name = strtok (NULL, "/"); - if (NULL == name) - return GNUNET_SYSERR; - GNUNET_asprintf (&handle->name, - "%s", - name); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Got name: %s\n", handle->name); - return GNUNET_OK; -} - - static void get_gns_cont (struct GNUNET_REST_RequestHandle *conndata_handle, const char* url, @@ -474,40 +461,48 @@ get_gns_cont (struct GNUNET_REST_RequestHandle *conndata_handle, { struct LookupHandle *handle = cls; struct GNUNET_HashCode key; + long int enum_test; + char *temp_val; - //parse name and type from url - if (GNUNET_OK != parse_url (url, handle)) + //check for /gns otherwise 404 + if (strlen (GNUNET_REST_API_NS_GNS) > strlen (url)) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error parsing url...\n"); + handle->emsg = GNUNET_strdup("Wrong URL"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Connecting...\n"); + + //connect to gns + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n"); handle->gns = GNUNET_GNS_connect (cfg); handle->identity = GNUNET_IDENTITY_connect (cfg, NULL, NULL); handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout, - &do_error, handle); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Connected\n"); + &do_error, handle); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connected\n"); if (NULL == handle->gns) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Connecting to GNS failed\n"); + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Connecting to GNS failed\n"); + handle->emsg = GNUNET_strdup("Connecting to GNS failed"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_OPTIONS, - strlen (GNUNET_REST_JSONAPI_GNS_OPTIONS), - &key); - handle->options = GNUNET_GNS_LO_DEFAULT; - if ( GNUNET_YES == - GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, - &key) ) + + //check parameter name -> BAD_REQUEST + GNUNET_CRYPTO_hash (GNUNET_REST_PARAMETER_GNS_NAME, + strlen (GNUNET_REST_PARAMETER_GNS_NAME), + &key); + if ( GNUNET_NO + == GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, + &key)) { - handle->options = GNUNET_GNS_LO_DEFAULT;//TODO(char*) GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, - //&key); + handle->emsg = GNUNET_strdup("Parameter name is missing"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; } + handle->name = GNUNET_strdup(GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, + &key)); + + //check parameter record_type, optional GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_RECORD_TYPE, strlen (GNUNET_REST_JSONAPI_GNS_RECORD_TYPE), &key); @@ -515,34 +510,66 @@ get_gns_cont (struct GNUNET_REST_RequestHandle *conndata_handle, GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, &key) ) { - handle->type = GNUNET_GNSRECORD_typename_to_number - (GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, + handle->type = GNUNET_GNSRECORD_typename_to_number( + GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, &key)); } else + { handle->type = GNUNET_GNSRECORD_TYPE_ANY; + } + //check parameter options, optional + GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_OPTIONS, + strlen (GNUNET_REST_JSONAPI_GNS_OPTIONS), + &key); + handle->options = GNUNET_GNS_LO_DEFAULT; + if ( GNUNET_YES + == GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, + &key)) + { + temp_val = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, &key); + if (1 < strlen(temp_val)) + { + handle->options = GNUNET_GNS_LO_DEFAULT; + } + else + { + //atoi because no valid conversion is default local option + enum_test = atoi(temp_val); + if (2 < enum_test) + handle->options = GNUNET_GNS_LO_DEFAULT; + else + handle->options = enum_test; + } + } + else + handle->options = GNUNET_GNS_LO_DEFAULT; + + //check parameter pkey, shortcut to lookup GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_PKEY, - strlen (GNUNET_REST_JSONAPI_GNS_PKEY), - &key); - if ( GNUNET_YES == - GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, - &key) ) + strlen (GNUNET_REST_JSONAPI_GNS_PKEY), + &key); + if ( GNUNET_YES + == GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, + &key)) { handle->pkey_str = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, - &key); - GNUNET_assert (NULL != handle->pkey_str); - if (GNUNET_OK != - GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->pkey_str, - strlen(handle->pkey_str), - &(handle->pkey))) + &key); + GNUNET_assert(NULL != handle->pkey_str); + if (GNUNET_OK + != GNUNET_CRYPTO_ecdsa_public_key_from_string ( + handle->pkey_str, strlen (handle->pkey_str), &(handle->pkey))) { + handle->emsg = GNUNET_strdup("Parameter pkey has a wrong format"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } lookup_with_public_key (handle); return; } + + //check parameter ego, lookup public key of ego GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_EGO, strlen (GNUNET_REST_JSONAPI_GNS_EGO), &key); @@ -558,24 +585,23 @@ get_gns_cont (struct GNUNET_REST_RequestHandle *conndata_handle, handle); return; } + + //if name ends with .zkey then get public key if ( (NULL != handle->name) && (strlen (handle->name) > 4) && (0 == strcmp (".zkey", &handle->name[strlen (handle->name) - 4])) ) { - GNUNET_CRYPTO_ecdsa_key_get_public - (GNUNET_CRYPTO_ecdsa_key_get_anonymous (), - &(handle->pkey)); + GNUNET_CRYPTO_ecdsa_key_get_public( GNUNET_CRYPTO_ecdsa_key_get_anonymous (), + &(handle->pkey)); lookup_with_public_key (handle); } - else + else //else use gns-master identity { - GNUNET_break (NULL == handle->id_op); handle->id_op = GNUNET_IDENTITY_get (handle->identity, "gns-master", &identity_master_cb, handle); - GNUNET_assert (NULL != handle->id_op); } } @@ -633,10 +659,10 @@ rest_gns_process_request (struct GNUNET_REST_RequestHandle *conndata_handle, handle->proc = proc; handle->rest_handle = conndata_handle; - if (GNUNET_NO == GNUNET_JSONAPI_handle_request (conndata_handle, - handlers, - &err, - handle)) + if (GNUNET_NO == GNUNET_REST_handle_request (conndata_handle, + handlers, + &err, + handle)) { handle->response_code = err.error_code; GNUNET_SCHEDULER_add_now (&do_error, handle); diff --git a/src/identity/plugin_rest_identity.c b/src/identity/plugin_rest_identity.c index 957a200b5..00835be7a 100644 --- a/src/identity/plugin_rest_identity.c +++ b/src/identity/plugin_rest_identity.c @@ -278,16 +278,16 @@ do_error (void *cls) struct MHD_Response *resp; char *json_error; - GNUNET_asprintf (&json_error, - "{\"error\": \"%s\"}", - handle->emsg); + if (NULL == handle->emsg) + handle->emsg = GNUNET_strdup("Unknown Error"); + + GNUNET_asprintf (&json_error, "{\"error\": \"%s\"}", handle->emsg); handle->response_code = MHD_HTTP_OK; + resp = GNUNET_REST_create_response (json_error); - handle->proc (handle->proc_cls, - resp, - handle->response_code); + handle->proc (handle->proc_cls, resp, handle->response_code); cleanup_handle (handle); - GNUNET_free (json_error); + GNUNET_free(json_error); } @@ -335,7 +335,7 @@ get_ego_for_subsys (void *cls, if (0 == json_array_size(json_root)) { - json_decref(json_root); + json_decref(json_root); handle->emsg = GNUNET_strdup("No identity matches results!"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; @@ -347,7 +347,7 @@ get_ego_for_subsys (void *cls, json_array_foreach(json_root, index, json_ego ) { - json_decref(json_ego); + json_decref(json_ego); } json_decref (json_root); handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); -- cgit v1.2.3 From a006f82603921d7b6775c7a7be60c7f388c6a927 Mon Sep 17 00:00:00 2001 From: Phil Date: Wed, 13 Jun 2018 23:40:14 +0200 Subject: -wip fix gns --- src/gns/plugin_rest_gns.c | 685 ++++++++++++++----------------------------- src/gns/plugin_rest_gns2.c | 717 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 939 insertions(+), 463 deletions(-) create mode 100644 src/gns/plugin_rest_gns2.c (limited to 'src') 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 @@ This file is part of GNUnet. 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 Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - or (at your option) any later version. + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ /** - * @author Martin Schanzenbach * @author Philippe Buschmann - * @file gns/plugin_rest_gns.c - * @brief GNUnet GNS REST plugin - * + * @file gns1/plugin_rest_gns1.c + * @brief GNUnet Gns1 REST plugin */ #include "platform.h" #include "gnunet_rest_plugin.h" -#include -#include -#include -#include -#include -#include -#include -#include +#include "gnunet_rest_lib.h" +#include "gnunet_gnsrecord_lib.h" +#include "microhttpd.h" #include #define GNUNET_REST_API_NS_GNS "/gns" -#define GNUNET_REST_JSONAPI_GNS_RECORD_TYPE "record_type" - +//TODO define other variables #define GNUNET_REST_PARAMETER_GNS_NAME "name" -#define GNUNET_REST_JSONAPI_GNS_TYPEINFO "gns_name" +#define GNUNET_REST_PARAMETER_GNS_RECORD_TYPE "record_type" -#define GNUNET_REST_JSONAPI_GNS_RECORD "records" - -#define GNUNET_REST_JSONAPI_GNS_EGO "ego" +#define GNUNET_REST_PARAMETER_GNS_NAME "name" -#define GNUNET_REST_JSONAPI_GNS_PKEY "pkey" +/** + * The configuration handle + */ +const struct GNUNET_CONFIGURATION_Handle *cfg; -#define GNUNET_REST_JSONAPI_GNS_OPTIONS "options" +/** + * HTTP methods allows for this plugin + */ +static char* allow_methods; /** * @brief struct returned by the initialization function of the plugin @@ -59,54 +57,48 @@ struct Plugin const struct GNUNET_CONFIGURATION_Handle *cfg; }; -const struct GNUNET_CONFIGURATION_Handle *cfg; +//TODO add specific structs -struct LookupHandle + + +struct RequestHandle { - /** - * Handle to GNS service. - */ - struct GNUNET_GNS_Handle *gns; + //TODO add specific entries /** - * Desired timeout for the lookup (default is no timeout). + * Connection to GNS */ - struct GNUNET_TIME_Relative timeout; + struct GNUNET_GNS_Handle *gns; /** - * Handle to lookup request + * Active GNS lookup */ - struct GNUNET_GNS_LookupRequest *lookup_request; + struct GNUNET_GNS_LookupWithTldRequest *gns_lookup; /** - * Handle to rest request + * Name to look up */ - struct GNUNET_REST_RequestHandle *rest_handle; + char *name; /** - * Lookup an ego with the identity service. + * Record type to look up */ - struct GNUNET_IDENTITY_EgoLookup *el; + int record_type; /** - * Handle for identity service. + * Rest connection */ - struct GNUNET_IDENTITY_Handle *identity; - + struct GNUNET_REST_RequestHandle *rest_handle; + /** - * Active operation on identity service. + * Desired timeout for the lookup (default is no timeout). */ - struct GNUNET_IDENTITY_Operation *id_op; + struct GNUNET_TIME_Relative timeout; /** * ID of a task associated with the resolution process. */ - struct GNUNET_SCHEDULER_Task * timeout_task; - - /** - * The root of the received JSON or NULL - */ - json_t *json_root; + struct GNUNET_SCHEDULER_Task *timeout_task; /** * The plugin result processor @@ -119,96 +111,37 @@ struct LookupHandle void *proc_cls; /** - * The name to look up - */ - char *name; - - /** - * The ego to use - * In string representation from JSON - */ - const char *ego_str; - - /** - * The Pkey to use - * In string representation from JSON + * The url */ - const char *pkey_str; + char *url; /** - * The record type + * Error response message */ - int type; + char *emsg; /** - * The public key of to use for lookup - */ - struct GNUNET_CRYPTO_EcdsaPublicKey pkey; - - /** - * The public key to use for lookup - */ - struct GNUNET_CRYPTO_EcdsaPublicKey pkeym; - - /** - * The resolver options - */ - enum GNUNET_GNS_LocalOptions options; - - /** - * the shorten key - */ - struct GNUNET_CRYPTO_EcdsaPrivateKey shorten_key; - - /** - * HTTP response code + * Reponse code */ int response_code; - /** - * HTTP response code - */ - char* emsg; - }; /** - * Cleanup lookup handle. - * + * Cleanup lookup handle * @param handle Handle to clean up */ static void -cleanup_handle (struct LookupHandle *handle) +cleanup_handle (struct RequestHandle *handle) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n"); - if (NULL != handle->json_root) - json_decref (handle->json_root); - if (NULL != handle->name) - GNUNET_free (handle->name); - if (NULL != handle->emsg) - GNUNET_free (handle->emsg); - if (NULL != handle->el) - { - GNUNET_IDENTITY_ego_lookup_cancel (handle->el); - handle->el = NULL; - } - if (NULL != handle->id_op) + if (NULL != handle->gns_lookup) { - GNUNET_IDENTITY_cancel (handle->id_op); - handle->id_op = NULL; - } - if (NULL != handle->lookup_request) - { - GNUNET_GNS_lookup_cancel (handle->lookup_request); - handle->lookup_request = NULL; - } - if (NULL != handle->identity) - { - GNUNET_IDENTITY_disconnect (handle->identity); - handle->identity = NULL; + GNUNET_GNS_lookup_with_tld_cancel (handle->gns_lookup); + handle->gns_lookup = NULL; } if (NULL != handle->gns) { @@ -219,21 +152,30 @@ cleanup_handle (struct LookupHandle *handle) if (NULL != handle->timeout_task) { GNUNET_SCHEDULER_cancel (handle->timeout_task); + handle->timeout_task = NULL; } + if (NULL != handle->url) + GNUNET_free (handle->url); + if (NULL != handle->name) + GNUNET_free (handle->name); + if (NULL != handle->emsg) + GNUNET_free (handle->emsg); + + //TODO add specific cleanup + GNUNET_free (handle); } /** - * Task run on shutdown. Cleans up everything. + * Task run on errors. Reports an error and cleans up everything. * - * @param cls unused - * @param tc scheduler context + * @param cls the `struct RequestHandle` */ static void do_error (void *cls) { - struct LookupHandle *handle = cls; + struct RequestHandle *handle = cls; struct MHD_Response *resp; char *json_error; @@ -241,7 +183,9 @@ do_error (void *cls) handle->emsg = GNUNET_strdup("Unknown Error"); GNUNET_asprintf (&json_error, "{\"error\": \"%s\"}", handle->emsg); - handle->response_code = MHD_HTTP_OK; + + if (0 == handle->response_code) + handle->response_code = MHD_HTTP_OK; resp = GNUNET_REST_create_response (json_error); handle->proc (handle->proc_cls, resp, handle->response_code); @@ -251,83 +195,56 @@ do_error (void *cls) /** - * Create json representation of a GNSRECORD + * Iterator called on obtained result for a GNS lookup. * - * @param rd the GNSRECORD_Data + * @param cls closure with the object + * @param was_gns #GNUNET_NO if name was not a GNS name + * @param rd_count number of records in @a rd + * @param rd the records in reply */ -static json_t * -gnsrecord_to_json (const struct GNUNET_GNSRECORD_Data *rd) +static void +handle_gns_response (void *cls, + int was_gns, + uint32_t rd_count, + const struct GNUNET_GNSRECORD_Data *rd) { - const char *typename; - char *string_val; - const char *exp_str; + struct RequestHandle *handle = cls; + struct MHD_Response *resp; + json_t *result_array; json_t *record_obj; - typename = GNUNET_GNSRECORD_number_to_typename (rd->record_type); - string_val = GNUNET_GNSRECORD_value_to_string (rd->record_type, - rd->data, - rd->data_size); - - if (NULL == string_val) + if (GNUNET_NO == was_gns) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Record of type %d malformed, skipping\n", - (int) rd->record_type); - return NULL; + handle->emsg = GNUNET_strdup("Name not found in GNS"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; } - record_obj = json_object (); - json_object_set_new (record_obj, "type", json_string (typename)); - json_object_set_new (record_obj, "value", json_string (string_val)); - GNUNET_free (string_val); - if (GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION & rd->flags) + if (0 == rd_count) { - struct GNUNET_TIME_Relative time_rel; - time_rel.rel_value_us = rd->expiration_time; - exp_str = GNUNET_STRINGS_relative_time_to_string (time_rel, 1); - } - else - { - struct GNUNET_TIME_Absolute time_abs; - time_abs.abs_value_us = rd->expiration_time; - exp_str = GNUNET_STRINGS_absolute_time_to_string (time_abs); + handle->emsg = GNUNET_strdup("No result found"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; } - json_object_set_new (record_obj, "expiration_time", json_string (exp_str)); - - json_object_set_new (record_obj, "expired", - json_boolean (GNUNET_YES == GNUNET_GNSRECORD_is_expired (rd))); - return record_obj; -} - -/** - * Function called with the result of a GNS lookup. - * - * @param cls the 'const char *' name that was resolved - * @param rd_count number of records returned - * @param rd array of @a rd_count records with the results - */ -static void -process_lookup_result (void *cls, uint32_t rd_count, - const struct GNUNET_GNSRECORD_Data *rd) -{ - struct LookupHandle *handle = cls; - struct MHD_Response *resp; - uint32_t i; - char *result; - json_t *result_array; - json_t *record_obj; result_array = json_array(); - handle->lookup_request = NULL; - for (i=0; igns_lookup); + handle->gns_lookup = NULL; + + for (uint32_t i=0;itype) && - (GNUNET_GNSRECORD_TYPE_ANY != handle->type) ) + if ((rd[i].record_type != handle->record_type) && + (GNUNET_GNSRECORD_TYPE_ANY != handle->record_type) ) + { continue; + } + record_obj = gnsrecord_to_json (&(rd[i])); json_array_append (result_array, record_obj); json_decref (record_obj); } + result = json_dumps(result_array, 0); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result); resp = GNUNET_REST_create_response (result); @@ -339,274 +256,70 @@ process_lookup_result (void *cls, uint32_t rd_count, /** - * Perform the actual resolution, starting with the zone - * identified by the given public key and the shorten zone. - * - * @param pkey public key to use for the zone, can be NULL - */ -static void -lookup_with_public_key (struct LookupHandle *handle) -{ - if (UINT32_MAX == handle->type) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Invalid typename specified, assuming `ANY'\n")); - handle->type = GNUNET_GNSRECORD_TYPE_ANY; - } - if (NULL != handle->name) - { - handle->lookup_request = GNUNET_GNS_lookup (handle->gns, - handle->name, - &handle->pkey, - handle->type, - handle->options, - &process_lookup_result, - handle); - } - else - { - handle->emsg = GNUNET_strdup("Parameter name is missing"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } -} - - -/** - * Method called to with the ego we are to use for the lookup, - * when the ego is determined by a name. - * - * @param cls closure (NULL, unused) - * @param ego ego handle, NULL if not found - */ -static void -identity_zone_cb (void *cls, - const struct GNUNET_IDENTITY_Ego *ego) -{ - struct LookupHandle *handle = cls; - - handle->el = NULL; - if (NULL == ego) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Ego for not found, cannot perform lookup.\n")); - handle->emsg = GNUNET_strdup ("Ego for not found, cannot perform lookup."); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - else - { - GNUNET_IDENTITY_ego_get_public_key (ego, &handle->pkey); - lookup_with_public_key (handle); - } - json_decref(handle->json_root); -} - - -/** - * Method called to with the ego we are to use for the lookup, - * when the ego is the one for the default master zone. + * Handle gns1 GET request * - * @param cls closure (NULL, unused) - * @param ego ego handle, NULL if not found - * @param ctx context for application to store data for this ego - * (during the lifetime of this process, initially NULL) - * @param name name assigned by the user for this ego, - * NULL if the user just deleted the ego and it - * must thus no longer be used + * @param con_handle the connection handle + * @param url the url + * @param cls the RequestHandle */ -static void -identity_master_cb (void *cls, - struct GNUNET_IDENTITY_Ego *ego, - void **ctx, - const char *name) +void +get_gns_cont (struct GNUNET_REST_RequestHandle *con_handle, + const char* url, + void *cls) { - const char *dot; - struct LookupHandle *handle = cls; - - handle->id_op = NULL; - if (NULL == ego) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Ego for `gns-master' not found, cannot perform lookup. Did you run gnunet-gns-import.sh?\n")); - handle->emsg = GNUNET_strdup("Ego for `gns-master' not found, cannot perform lookup. Did you run gnunet-gns-import.sh?"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - GNUNET_IDENTITY_ego_get_public_key (ego, - &handle->pkey); - /* main name is our own master zone, do no look for that in the DHT */ - handle->options = GNUNET_GNS_LO_LOCAL_MASTER; - /* if the name is of the form 'label.gnu', never go to the DHT */ - dot = NULL; - if (NULL != handle->name) - dot = strchr (handle->name, '.'); - if ( (NULL != dot) && - (0 == strcasecmp (dot, ".gnu")) ) - handle->options = GNUNET_GNS_LO_NO_DHT; - lookup_with_public_key (handle); -} - -/** - * Handle get request - * - * @param handle the lookup handle - */ -static void -get_gns_cont (struct GNUNET_REST_RequestHandle *conndata_handle, - const char* url, - void *cls) -{ - struct LookupHandle *handle = cls; + struct RequestHandle *handle = cls; struct GNUNET_HashCode key; - long int enum_test; - char *temp_val; - - //check for /gns otherwise 404 - if (strlen (GNUNET_REST_API_NS_GNS) > strlen (url)) - { - handle->emsg = GNUNET_strdup("Wrong URL"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - //connect to gns - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n"); - handle->gns = GNUNET_GNS_connect (cfg); - handle->identity = GNUNET_IDENTITY_connect (cfg, NULL, NULL); - handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout, - &do_error, handle); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connected\n"); - if (NULL == handle->gns) - { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Connecting to GNS failed\n"); - handle->emsg = GNUNET_strdup("Connecting to GNS failed"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - - //check parameter name -> BAD_REQUEST GNUNET_CRYPTO_hash (GNUNET_REST_PARAMETER_GNS_NAME, strlen (GNUNET_REST_PARAMETER_GNS_NAME), &key); if ( GNUNET_NO - == GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, - &key)) + == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, + &key)) { handle->emsg = GNUNET_strdup("Parameter name is missing"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - handle->name = GNUNET_strdup(GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, - &key)); - - //check parameter record_type, optional - GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_RECORD_TYPE, - strlen (GNUNET_REST_JSONAPI_GNS_RECORD_TYPE), - &key); - if ( GNUNET_YES == - GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, - &key) ) - { - handle->type = GNUNET_GNSRECORD_typename_to_number( - GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, - &key)); - } - else - { - handle->type = GNUNET_GNSRECORD_TYPE_ANY; - } + handle->name = GNUNET_strdup( + GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map,&key)); - //check parameter options, optional - GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_OPTIONS, - strlen (GNUNET_REST_JSONAPI_GNS_OPTIONS), + GNUNET_CRYPTO_hash (GNUNET_REST_PARAMETER_GNS_RECORD_TYPE, + strlen (GNUNET_REST_PARAMETER_GNS_RECORD_TYPE), &key); - handle->options = GNUNET_GNS_LO_DEFAULT; - if ( GNUNET_YES - == GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, - &key)) - { - temp_val = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, &key); - if (1 < strlen(temp_val)) - { - handle->options = GNUNET_GNS_LO_DEFAULT; - } - else - { - //atoi because no valid conversion is default local option - enum_test = atoi(temp_val); - if (2 < enum_test) - handle->options = GNUNET_GNS_LO_DEFAULT; - else - handle->options = enum_test; - } - } - else - handle->options = GNUNET_GNS_LO_DEFAULT; - - //check parameter pkey, shortcut to lookup - GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_PKEY, - strlen (GNUNET_REST_JSONAPI_GNS_PKEY), - &key); - if ( GNUNET_YES - == GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, - &key)) + if ( GNUNET_NO + == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, + &key)) { - handle->pkey_str = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, - &key); - GNUNET_assert(NULL != handle->pkey_str); - if (GNUNET_OK - != GNUNET_CRYPTO_ecdsa_public_key_from_string ( - handle->pkey_str, strlen (handle->pkey_str), &(handle->pkey))) - { - handle->emsg = GNUNET_strdup("Parameter pkey has a wrong format"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - lookup_with_public_key (handle); + handle->emsg = GNUNET_strdup("Parameter record_type is missing"); + GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - - //check parameter ego, lookup public key of ego - GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_EGO, - strlen (GNUNET_REST_JSONAPI_GNS_EGO), - &key); - if ( GNUNET_YES == - GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, - &key) ) + handle->record_type = GNUNET_strdup( + GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map,&key)); + + handle->gns_lookup = GNUNET_GNS_lookup_with_tld (handle->gns, + handle->name, + handle->record_type, + GNUNET_NO, + &handle_gns_response, + handle); + if (NULL == handle->gns_lookup) { - handle->ego_str = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, - &key); - handle->el = GNUNET_IDENTITY_ego_lookup (cfg, - handle->ego_str, - &identity_zone_cb, - handle); + handle->emsg = GNUNET_strdup("GNS lookup failed"); + GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - - //if name ends with .zkey then get public key - if ( (NULL != handle->name) && - (strlen (handle->name) > 4) && - (0 == strcmp (".zkey", - &handle->name[strlen (handle->name) - 4])) ) - { - GNUNET_CRYPTO_ecdsa_key_get_public( GNUNET_CRYPTO_ecdsa_key_get_anonymous (), - &(handle->pkey)); - lookup_with_public_key (handle); - } - else //else use gns-master identity - { - handle->id_op = GNUNET_IDENTITY_get (handle->identity, - "gns-master", - &identity_master_cb, - handle); - } } + + /** - * Handle rest request + * Respond to OPTIONS request * - * @param handle the lookup handle + * @param con_handle the connection handle + * @param url the url + * @param cls the RequestHandle */ static void options_cont (struct GNUNET_REST_RequestHandle *con_handle, @@ -614,50 +327,35 @@ options_cont (struct GNUNET_REST_RequestHandle *con_handle, void *cls) { struct MHD_Response *resp; - struct LookupHandle *handle = cls; + struct RequestHandle *handle = cls; - //For GNS, independent of path return all options + //independent of path return all options resp = GNUNET_REST_create_response (NULL); MHD_add_response_header (resp, "Access-Control-Allow-Methods", - MHD_HTTP_METHOD_GET); - handle->proc (handle->proc_cls, - resp, - MHD_HTTP_OK); + allow_methods); + handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); cleanup_handle (handle); + return; } /** - * Function processing the REST call + * Handle rest request * - * @param method HTTP method - * @param url URL of the HTTP request - * @param data body of the HTTP request (optional) - * @param data_size length of the body - * @param proc callback function for the result - * @param proc_cls closure for @a proc - * @return #GNUNET_OK if request accepted + * @param handle the request handle */ static void -rest_gns_process_request (struct GNUNET_REST_RequestHandle *conndata_handle, - GNUNET_REST_ResultProcessor proc, - void *proc_cls) +init_cont (struct RequestHandle *handle) { + struct GNUNET_REST_RequestHandlerError err; static const struct GNUNET_REST_RequestHandler handlers[] = { {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_GNS, &get_gns_cont}, {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_GNS, &options_cont}, GNUNET_REST_HANDLER_END }; - struct LookupHandle *handle = GNUNET_new (struct LookupHandle); - struct GNUNET_REST_RequestHandlerError err; - handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; - handle->proc_cls = proc_cls; - handle->proc = proc; - handle->rest_handle = conndata_handle; - - if (GNUNET_NO == GNUNET_REST_handle_request (conndata_handle, + if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle)) @@ -668,19 +366,70 @@ rest_gns_process_request (struct GNUNET_REST_RequestHandle *conndata_handle, } +/** + * Function processing the REST call + * + * @param method HTTP method + * @param url URL of the HTTP request + * @param data body of the HTTP request (optional) + * @param data_size length of the body + * @param proc callback function for the result + * @param proc_cls closure for callback function + * @return GNUNET_OK if request accepted + */ +static void +rest_process_request(struct GNUNET_REST_RequestHandle *rest_handle, + GNUNET_REST_ResultProcessor proc, + void *proc_cls) +{ + struct RequestHandle *handle = GNUNET_new (struct RequestHandle); + + handle->response_code = 0; + handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; + handle->proc_cls = proc_cls; + handle->proc = proc; + 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, "Connecting...\n"); + + + handle->gns = GNUNET_GNS_connect (cfg); + if (NULL == handle->gns) + { + handle->emsg = GNUNET_strdup ("GNS not available"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + + init_cont(handle); + //TODO connect to specific service + //connect ( cfg, [..., &callback_function, handle]); + //TODO callback then init_cont(handle) + handle->timeout_task = + GNUNET_SCHEDULER_add_delayed (handle->timeout, + &do_error, + handle); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n"); +} + + /** * Entry point for the plugin. * - * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*" + * @param cls Config info * @return NULL on error, otherwise the plugin context */ void * -libgnunet_plugin_rest_gns_init (void *cls) +libgnunet_plugin_rest_gns1_init (void *cls) { static struct Plugin plugin; - cfg = cls; struct GNUNET_REST_Plugin *api; + cfg = cls; if (NULL != plugin.cfg) return NULL; /* can only initialize once! */ memset (&plugin, 0, sizeof (struct Plugin)); @@ -688,9 +437,17 @@ libgnunet_plugin_rest_gns_init (void *cls) api = GNUNET_new (struct GNUNET_REST_Plugin); api->cls = &plugin; api->name = GNUNET_REST_API_NS_GNS; - api->process_request = &rest_gns_process_request; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("GNS REST API initialized\n")); + api->process_request = &rest_process_request; + GNUNET_asprintf (&allow_methods, + "%s, %s, %s, %s, %s", + MHD_HTTP_METHOD_GET, + MHD_HTTP_METHOD_POST, + MHD_HTTP_METHOD_PUT, + MHD_HTTP_METHOD_DELETE, + MHD_HTTP_METHOD_OPTIONS); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + _("Gns1 REST API initialized\n")); return api; } @@ -702,16 +459,18 @@ libgnunet_plugin_rest_gns_init (void *cls) * @return always NULL */ void * -libgnunet_plugin_rest_gns_done (void *cls) +libgnunet_plugin_rest_gns1_done (void *cls) { struct GNUNET_REST_Plugin *api = cls; struct Plugin *plugin = api->cls; - plugin->cfg = NULL; + + GNUNET_free_non_null (allow_methods); GNUNET_free (api); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "GNS REST plugin is finished\n"); + "Gns1 REST plugin is finished\n"); return NULL; } -/* end of plugin_rest_gns.c */ +/* end of plugin_rest_gns1.c */ + 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 @@ +/* + This file is part of GNUnet. + 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 Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + */ +/** + * @author Martin Schanzenbach + * @author Philippe Buschmann + * @file gns/plugin_rest_gns.c + * @brief GNUnet GNS REST plugin + * + */ + +#include "platform.h" +#include "gnunet_rest_plugin.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GNUNET_REST_API_NS_GNS "/gns" + +#define GNUNET_REST_JSONAPI_GNS_RECORD_TYPE "record_type" + +#define GNUNET_REST_PARAMETER_GNS_NAME "name" + +#define GNUNET_REST_JSONAPI_GNS_TYPEINFO "gns_name" + +#define GNUNET_REST_JSONAPI_GNS_RECORD "records" + +#define GNUNET_REST_JSONAPI_GNS_EGO "ego" + +#define GNUNET_REST_JSONAPI_GNS_PKEY "pkey" + +#define GNUNET_REST_JSONAPI_GNS_OPTIONS "options" + +/** + * @brief struct returned by the initialization function of the plugin + */ +struct Plugin +{ + const struct GNUNET_CONFIGURATION_Handle *cfg; +}; + +const struct GNUNET_CONFIGURATION_Handle *cfg; + +struct LookupHandle +{ + /** + * Handle to GNS service. + */ + struct GNUNET_GNS_Handle *gns; + + /** + * Desired timeout for the lookup (default is no timeout). + */ + struct GNUNET_TIME_Relative timeout; + + /** + * Handle to lookup request + */ + struct GNUNET_GNS_LookupRequest *lookup_request; + + /** + * Handle to rest request + */ + struct GNUNET_REST_RequestHandle *rest_handle; + + /** + * Lookup an ego with the identity service. + */ + struct GNUNET_IDENTITY_EgoLookup *el; + + /** + * Handle for identity service. + */ + struct GNUNET_IDENTITY_Handle *identity; + + /** + * Active operation on identity service. + */ + struct GNUNET_IDENTITY_Operation *id_op; + + /** + * ID of a task associated with the resolution process. + */ + struct GNUNET_SCHEDULER_Task * timeout_task; + + /** + * The root of the received JSON or NULL + */ + json_t *json_root; + + /** + * The plugin result processor + */ + GNUNET_REST_ResultProcessor proc; + + /** + * The closure of the result processor + */ + void *proc_cls; + + /** + * The name to look up + */ + char *name; + + /** + * The ego to use + * In string representation from JSON + */ + const char *ego_str; + + /** + * The Pkey to use + * In string representation from JSON + */ + const char *pkey_str; + + /** + * The record type + */ + int type; + + /** + * The public key of to use for lookup + */ + struct GNUNET_CRYPTO_EcdsaPublicKey pkey; + + /** + * The public key to use for lookup + */ + struct GNUNET_CRYPTO_EcdsaPublicKey pkeym; + + /** + * The resolver options + */ + enum GNUNET_GNS_LocalOptions options; + + /** + * the shorten key + */ + struct GNUNET_CRYPTO_EcdsaPrivateKey shorten_key; + + /** + * HTTP response code + */ + int response_code; + + /** + * HTTP response code + */ + char* emsg; + +}; + + +/** + * Cleanup lookup handle. + * + * @param handle Handle to clean up + */ +static void +cleanup_handle (struct LookupHandle *handle) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Cleaning up\n"); + if (NULL != handle->json_root) + json_decref (handle->json_root); + + if (NULL != handle->name) + GNUNET_free (handle->name); + if (NULL != handle->emsg) + GNUNET_free (handle->emsg); + if (NULL != handle->el) + { + GNUNET_IDENTITY_ego_lookup_cancel (handle->el); + handle->el = NULL; + } + if (NULL != handle->id_op) + { + GNUNET_IDENTITY_cancel (handle->id_op); + handle->id_op = NULL; + } + if (NULL != handle->lookup_request) + { + GNUNET_GNS_lookup_cancel (handle->lookup_request); + handle->lookup_request = NULL; + } + if (NULL != handle->identity) + { + GNUNET_IDENTITY_disconnect (handle->identity); + handle->identity = NULL; + } + if (NULL != handle->gns) + { + GNUNET_GNS_disconnect (handle->gns); + handle->gns = NULL; + } + + if (NULL != handle->timeout_task) + { + GNUNET_SCHEDULER_cancel (handle->timeout_task); + } + GNUNET_free (handle); +} + + +/** + * Task run on shutdown. Cleans up everything. + * + * @param cls unused + * @param tc scheduler context + */ +static void +do_error (void *cls) +{ + struct LookupHandle *handle = cls; + struct MHD_Response *resp; + char *json_error; + + if (NULL == handle->emsg) + handle->emsg = GNUNET_strdup("Unknown Error"); + + GNUNET_asprintf (&json_error, "{\"error\": \"%s\"}", handle->emsg); + handle->response_code = MHD_HTTP_OK; + + resp = GNUNET_REST_create_response (json_error); + handle->proc (handle->proc_cls, resp, handle->response_code); + cleanup_handle (handle); + GNUNET_free(json_error); +} + + +/** + * Create json representation of a GNSRECORD + * + * @param rd the GNSRECORD_Data + */ +static json_t * +gnsrecord_to_json (const struct GNUNET_GNSRECORD_Data *rd) +{ + const char *typename; + char *string_val; + const char *exp_str; + json_t *record_obj; + + typename = GNUNET_GNSRECORD_number_to_typename (rd->record_type); + string_val = GNUNET_GNSRECORD_value_to_string (rd->record_type, + rd->data, + rd->data_size); + + if (NULL == string_val) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Record of type %d malformed, skipping\n", + (int) rd->record_type); + return NULL; + } + record_obj = json_object (); + json_object_set_new (record_obj, "type", json_string (typename)); + json_object_set_new (record_obj, "value", json_string (string_val)); + GNUNET_free (string_val); + + if (GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION & rd->flags) + { + struct GNUNET_TIME_Relative time_rel; + time_rel.rel_value_us = rd->expiration_time; + exp_str = GNUNET_STRINGS_relative_time_to_string (time_rel, 1); + } + else + { + struct GNUNET_TIME_Absolute time_abs; + time_abs.abs_value_us = rd->expiration_time; + exp_str = GNUNET_STRINGS_absolute_time_to_string (time_abs); + } + json_object_set_new (record_obj, "expiration_time", json_string (exp_str)); + + json_object_set_new (record_obj, "expired", + json_boolean (GNUNET_YES == GNUNET_GNSRECORD_is_expired (rd))); + return record_obj; +} + +/** + * Function called with the result of a GNS lookup. + * + * @param cls the 'const char *' name that was resolved + * @param rd_count number of records returned + * @param rd array of @a rd_count records with the results + */ +static void +process_lookup_result (void *cls, uint32_t rd_count, + const struct GNUNET_GNSRECORD_Data *rd) +{ + struct LookupHandle *handle = cls; + struct MHD_Response *resp; + uint32_t i; + char *result; + json_t *result_array; + json_t *record_obj; + + result_array = json_array(); + handle->lookup_request = NULL; + for (i=0; itype) && + (GNUNET_GNSRECORD_TYPE_ANY != handle->type) ) + continue; + record_obj = gnsrecord_to_json (&(rd[i])); + json_array_append (result_array, record_obj); + json_decref (record_obj); + } + result = json_dumps(result_array, 0); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result); + resp = GNUNET_REST_create_response (result); + handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); + GNUNET_free (result); + json_decref (result_array); + cleanup_handle (handle); +} + + +/** + * Perform the actual resolution, starting with the zone + * identified by the given public key and the shorten zone. + * + * @param pkey public key to use for the zone, can be NULL + */ +static void +lookup_with_public_key (struct LookupHandle *handle) +{ + if (UINT32_MAX == handle->type) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Invalid typename specified, assuming `ANY'\n")); + handle->type = GNUNET_GNSRECORD_TYPE_ANY; + } + if (NULL != handle->name) + { + handle->lookup_request = GNUNET_GNS_lookup (handle->gns, + handle->name, + &handle->pkey, + handle->type, + handle->options, + &process_lookup_result, + handle); + } + else + { + handle->emsg = GNUNET_strdup("Parameter name is missing"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } +} + + +/** + * Method called to with the ego we are to use for the lookup, + * when the ego is determined by a name. + * + * @param cls closure (NULL, unused) + * @param ego ego handle, NULL if not found + */ +static void +identity_zone_cb (void *cls, + const struct GNUNET_IDENTITY_Ego *ego) +{ + struct LookupHandle *handle = cls; + + handle->el = NULL; + if (NULL == ego) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Ego for not found, cannot perform lookup.\n")); + handle->emsg = GNUNET_strdup ("Ego for not found, cannot perform lookup."); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + else + { + GNUNET_IDENTITY_ego_get_public_key (ego, &handle->pkey); + lookup_with_public_key (handle); + } + json_decref(handle->json_root); +} + + +/** + * Method called to with the ego we are to use for the lookup, + * when the ego is the one for the default master zone. + * + * @param cls closure (NULL, unused) + * @param ego ego handle, NULL if not found + * @param ctx context for application to store data for this ego + * (during the lifetime of this process, initially NULL) + * @param name name assigned by the user for this ego, + * NULL if the user just deleted the ego and it + * must thus no longer be used + */ +static void +identity_master_cb (void *cls, + struct GNUNET_IDENTITY_Ego *ego, + void **ctx, + const char *name) +{ + const char *dot; + struct LookupHandle *handle = cls; + + handle->id_op = NULL; + if (NULL == ego) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Ego for `gns-master' not found, cannot perform lookup. Did you run gnunet-gns-import.sh?\n")); + handle->emsg = GNUNET_strdup("Ego for `gns-master' not found, cannot perform lookup. Did you run gnunet-gns-import.sh?"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + GNUNET_IDENTITY_ego_get_public_key (ego, + &handle->pkey); + /* main name is our own master zone, do no look for that in the DHT */ + handle->options = GNUNET_GNS_LO_LOCAL_MASTER; + /* if the name is of the form 'label.gnu', never go to the DHT */ + dot = NULL; + if (NULL != handle->name) + dot = strchr (handle->name, '.'); + if ( (NULL != dot) && + (0 == strcasecmp (dot, ".gnu")) ) + handle->options = GNUNET_GNS_LO_NO_DHT; + lookup_with_public_key (handle); +} + +/** + * Handle get request + * + * @param handle the lookup handle + */ +static void +get_gns_cont (struct GNUNET_REST_RequestHandle *conndata_handle, + const char* url, + void *cls) +{ + struct LookupHandle *handle = cls; + struct GNUNET_HashCode key; + long int enum_test; + char *temp_val; + + //check for /gns otherwise 404 + if (strlen (GNUNET_REST_API_NS_GNS) > strlen (url)) + { + handle->emsg = GNUNET_strdup("Wrong URL"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + + //connect to gns + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n"); + handle->gns = GNUNET_GNS_connect (cfg); + handle->identity = GNUNET_IDENTITY_connect (cfg, NULL, NULL); + handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout, + &do_error, handle); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connected\n"); + if (NULL == handle->gns) + { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Connecting to GNS failed\n"); + handle->emsg = GNUNET_strdup("Connecting to GNS failed"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + + //check parameter name -> BAD_REQUEST + GNUNET_CRYPTO_hash (GNUNET_REST_PARAMETER_GNS_NAME, + strlen (GNUNET_REST_PARAMETER_GNS_NAME), + &key); + if ( GNUNET_NO + == GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, + &key)) + { + handle->emsg = GNUNET_strdup("Parameter name is missing"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + handle->name = GNUNET_strdup(GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, + &key)); + + //check parameter record_type, optional + GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_RECORD_TYPE, + strlen (GNUNET_REST_JSONAPI_GNS_RECORD_TYPE), + &key); + if ( GNUNET_YES == + GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, + &key) ) + { + handle->type = GNUNET_GNSRECORD_typename_to_number( + GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, + &key)); + } + else + { + handle->type = GNUNET_GNSRECORD_TYPE_ANY; + } + + //check parameter options, optional + GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_OPTIONS, + strlen (GNUNET_REST_JSONAPI_GNS_OPTIONS), + &key); + handle->options = GNUNET_GNS_LO_DEFAULT; + if ( GNUNET_YES + == GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, + &key)) + { + temp_val = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, &key); + if (1 < strlen(temp_val)) + { + handle->options = GNUNET_GNS_LO_DEFAULT; + } + else + { + //atoi because no valid conversion is default local option + enum_test = atoi(temp_val); + if (2 < enum_test) + handle->options = GNUNET_GNS_LO_DEFAULT; + else + handle->options = enum_test; + } + } + else + handle->options = GNUNET_GNS_LO_DEFAULT; + + //check parameter pkey, shortcut to lookup + GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_PKEY, + strlen (GNUNET_REST_JSONAPI_GNS_PKEY), + &key); + if ( GNUNET_YES + == GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, + &key)) + { + handle->pkey_str = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, + &key); + GNUNET_assert(NULL != handle->pkey_str); + if (GNUNET_OK + != GNUNET_CRYPTO_ecdsa_public_key_from_string ( + handle->pkey_str, strlen (handle->pkey_str), &(handle->pkey))) + { + handle->emsg = GNUNET_strdup("Parameter pkey has a wrong format"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + lookup_with_public_key (handle); + return; + } + + //check parameter ego, lookup public key of ego + GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_EGO, + strlen (GNUNET_REST_JSONAPI_GNS_EGO), + &key); + if ( GNUNET_YES == + GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, + &key) ) + { + handle->ego_str = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, + &key); + handle->el = GNUNET_IDENTITY_ego_lookup (cfg, + handle->ego_str, + &identity_zone_cb, + handle); + return; + } + + //if name ends with .zkey then get public key + if ( (NULL != handle->name) && + (strlen (handle->name) > 4) && + (0 == strcmp (".zkey", + &handle->name[strlen (handle->name) - 4])) ) + { + GNUNET_CRYPTO_ecdsa_key_get_public( GNUNET_CRYPTO_ecdsa_key_get_anonymous (), + &(handle->pkey)); + lookup_with_public_key (handle); + } + else //else use gns-master identity + { + handle->id_op = GNUNET_IDENTITY_get (handle->identity, + "gns-master", + &identity_master_cb, + handle); + } +} + +/** + * Handle rest request + * + * @param handle the lookup handle + */ +static void +options_cont (struct GNUNET_REST_RequestHandle *con_handle, + const char* url, + void *cls) +{ + struct MHD_Response *resp; + struct LookupHandle *handle = cls; + + //For GNS, independent of path return all options + resp = GNUNET_REST_create_response (NULL); + MHD_add_response_header (resp, + "Access-Control-Allow-Methods", + MHD_HTTP_METHOD_GET); + handle->proc (handle->proc_cls, + resp, + MHD_HTTP_OK); + cleanup_handle (handle); +} + + +/** + * Function processing the REST call + * + * @param method HTTP method + * @param url URL of the HTTP request + * @param data body of the HTTP request (optional) + * @param data_size length of the body + * @param proc callback function for the result + * @param proc_cls closure for @a proc + * @return #GNUNET_OK if request accepted + */ +static void +rest_gns_process_request (struct GNUNET_REST_RequestHandle *conndata_handle, + GNUNET_REST_ResultProcessor proc, + void *proc_cls) +{ + static const struct GNUNET_REST_RequestHandler handlers[] = { + {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_GNS, &get_gns_cont}, + {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_GNS, &options_cont}, + GNUNET_REST_HANDLER_END + }; + struct LookupHandle *handle = GNUNET_new (struct LookupHandle); + struct GNUNET_REST_RequestHandlerError err; + + handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; + handle->proc_cls = proc_cls; + handle->proc = proc; + handle->rest_handle = conndata_handle; + + if (GNUNET_NO == GNUNET_REST_handle_request (conndata_handle, + handlers, + &err, + handle)) + { + handle->response_code = err.error_code; + GNUNET_SCHEDULER_add_now (&do_error, handle); + } +} + + +/** + * Entry point for the plugin. + * + * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*" + * @return NULL on error, otherwise the plugin context + */ +void * +libgnunet_plugin_rest_gns_init (void *cls) +{ + static struct Plugin plugin; + cfg = cls; + struct GNUNET_REST_Plugin *api; + + if (NULL != plugin.cfg) + return NULL; /* can only initialize once! */ + memset (&plugin, 0, sizeof (struct Plugin)); + plugin.cfg = cfg; + api = GNUNET_new (struct GNUNET_REST_Plugin); + api->cls = &plugin; + api->name = GNUNET_REST_API_NS_GNS; + api->process_request = &rest_gns_process_request; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _("GNS REST API initialized\n")); + return api; +} + + +/** + * Exit point from the plugin. + * + * @param cls the plugin context (as returned by "init") + * @return always NULL + */ +void * +libgnunet_plugin_rest_gns_done (void *cls) +{ + struct GNUNET_REST_Plugin *api = cls; + struct Plugin *plugin = api->cls; + + plugin->cfg = NULL; + GNUNET_free (api); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "GNS REST plugin is finished\n"); + return NULL; +} + +/* end of plugin_rest_gns.c */ -- cgit v1.2.3 From 4e6cb01843318385cfad41aec4cde5791f51cde2 Mon Sep 17 00:00:00 2001 From: Phil Date: Mon, 25 Jun 2018 00:17:06 +0200 Subject: Identity+GNS Rest changed and fixed --- src/gns/plugin_rest_gns.c | 72 +-- src/identity/plugin_rest_identity.c | 837 ++++++++++++++---------------- src/identity/test_plugin_rest_identity.sh | 216 ++++++++ 3 files changed, 634 insertions(+), 491 deletions(-) create mode 100755 src/identity/test_plugin_rest_identity.sh (limited to 'src') diff --git a/src/gns/plugin_rest_gns.c b/src/gns/plugin_rest_gns.c index 57fdfc1d5..22c908275 100644 --- a/src/gns/plugin_rest_gns.c +++ b/src/gns/plugin_rest_gns.c @@ -19,26 +19,24 @@ */ /** * @author Philippe Buschmann - * @file gns1/plugin_rest_gns1.c - * @brief GNUnet Gns1 REST plugin + * @file gns/plugin_rest_gns.c + * @brief GNUnet Gns REST plugin */ #include "platform.h" #include "gnunet_rest_plugin.h" #include "gnunet_rest_lib.h" #include "gnunet_gnsrecord_lib.h" +#include "gnunet_gns_service.h" #include "microhttpd.h" #include #define GNUNET_REST_API_NS_GNS "/gns" -//TODO define other variables #define GNUNET_REST_PARAMETER_GNS_NAME "name" #define GNUNET_REST_PARAMETER_GNS_RECORD_TYPE "record_type" -#define GNUNET_REST_PARAMETER_GNS_NAME "name" - /** * The configuration handle */ @@ -57,13 +55,10 @@ struct Plugin const struct GNUNET_CONFIGURATION_Handle *cfg; }; -//TODO add specific structs - struct RequestHandle { - //TODO add specific entries /** * Connection to GNS @@ -160,8 +155,6 @@ cleanup_handle (struct RequestHandle *handle) GNUNET_free (handle->name); if (NULL != handle->emsg) GNUNET_free (handle->emsg); - - //TODO add specific cleanup GNUNET_free (handle); } @@ -212,6 +205,10 @@ handle_gns_response (void *cls, struct MHD_Response *resp; json_t *result_array; json_t *record_obj; + char *record_value; + char *result; + + handle->gns_lookup = NULL; if (GNUNET_NO == was_gns) { @@ -219,7 +216,6 @@ handle_gns_response (void *cls, GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - if (0 == rd_count) { handle->emsg = GNUNET_strdup("No result found"); @@ -228,10 +224,6 @@ handle_gns_response (void *cls, } result_array = json_array(); - //TODO test break! - GNUNET_break (NULL != handle->gns_lookup); - handle->gns_lookup = NULL; - for (uint32_t i=0;irecord_type) && @@ -240,7 +232,10 @@ handle_gns_response (void *cls, continue; } - record_obj = gnsrecord_to_json (&(rd[i])); + record_value = GNUNET_GNSRECORD_value_to_string (rd->record_type, + rd->data, + rd->data_size); + record_obj = json_string(record_value); json_array_append (result_array, record_obj); json_decref (record_obj); } @@ -256,7 +251,7 @@ handle_gns_response (void *cls, /** - * Handle gns1 GET request + * Handle gns GET request * * @param con_handle the connection handle * @param url the url @@ -269,6 +264,7 @@ get_gns_cont (struct GNUNET_REST_RequestHandle *con_handle, { struct RequestHandle *handle = cls; struct GNUNET_HashCode key; + int conversion_state; GNUNET_CRYPTO_hash (GNUNET_REST_PARAMETER_GNS_NAME, strlen (GNUNET_REST_PARAMETER_GNS_NAME), @@ -295,8 +291,22 @@ get_gns_cont (struct GNUNET_REST_RequestHandle *con_handle, GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - handle->record_type = GNUNET_strdup( - GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map,&key)); + conversion_state = sscanf ( + GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, &key),"%u", + &(handle->record_type)); + + if((EOF == conversion_state) || (0 == conversion_state)) + { + handle->record_type = GNUNET_GNSRECORD_TYPE_ANY; + } + + handle->gns = GNUNET_GNS_connect (cfg); + if (NULL == handle->gns) + { + handle->emsg = GNUNET_strdup ("GNS not available"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } handle->gns_lookup = GNUNET_GNS_lookup_with_tld (handle->gns, handle->name, @@ -304,6 +314,7 @@ get_gns_cont (struct GNUNET_REST_RequestHandle *con_handle, GNUNET_NO, &handle_gns_response, handle); + if (NULL == handle->gns_lookup) { handle->emsg = GNUNET_strdup("GNS lookup failed"); @@ -395,19 +406,8 @@ rest_process_request(struct GNUNET_REST_RequestHandle *rest_handle, handle->url[strlen (handle->url)-1] = '\0'; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n"); - - handle->gns = GNUNET_GNS_connect (cfg); - if (NULL == handle->gns) - { - handle->emsg = GNUNET_strdup ("GNS not available"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - init_cont(handle); - //TODO connect to specific service - //connect ( cfg, [..., &callback_function, handle]); - //TODO callback then init_cont(handle) + handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_error, @@ -424,7 +424,7 @@ rest_process_request(struct GNUNET_REST_RequestHandle *rest_handle, * @return NULL on error, otherwise the plugin context */ void * -libgnunet_plugin_rest_gns1_init (void *cls) +libgnunet_plugin_rest_gns_init (void *cls) { static struct Plugin plugin; struct GNUNET_REST_Plugin *api; @@ -447,7 +447,7 @@ libgnunet_plugin_rest_gns1_init (void *cls) MHD_HTTP_METHOD_OPTIONS); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - _("Gns1 REST API initialized\n")); + _("Gns REST API initialized\n")); return api; } @@ -459,7 +459,7 @@ libgnunet_plugin_rest_gns1_init (void *cls) * @return always NULL */ void * -libgnunet_plugin_rest_gns1_done (void *cls) +libgnunet_plugin_rest_gns_done (void *cls) { struct GNUNET_REST_Plugin *api = cls; struct Plugin *plugin = api->cls; @@ -468,9 +468,9 @@ libgnunet_plugin_rest_gns1_done (void *cls) GNUNET_free_non_null (allow_methods); GNUNET_free (api); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Gns1 REST plugin is finished\n"); + "Gns REST plugin is finished\n"); return NULL; } -/* end of plugin_rest_gns1.c */ +/* end of plugin_rest_gns.c */ diff --git a/src/identity/plugin_rest_identity.c b/src/identity/plugin_rest_identity.c index fd6562f1d..8d525b950 100644 --- a/src/identity/plugin_rest_identity.c +++ b/src/identity/plugin_rest_identity.c @@ -1,26 +1,27 @@ /* - This file is part of GNUnet. - 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 Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - or (at your option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ + This file is part of GNUnet. + 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 + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ /** * @author Martin Schanzenbach * @author Philippe Buschmann * @file identity/plugin_rest_identity.c - * @brief GNUnet Namestore REST plugin - * + * @brief GNUnet Identity REST plugin */ #include "platform.h" @@ -29,56 +30,34 @@ #include "gnunet_rest_lib.h" #include "microhttpd.h" #include -#include "gnunet_signatures.h" -/** - * REST root namespace - */ #define GNUNET_REST_API_NS_IDENTITY "/identity" /** - * State while collecting all egos - */ -#define ID_REST_STATE_INIT 0 - -/** - * Done collecting egos - */ -#define ID_REST_STATE_POST_INIT 1 - -/** - * Resource type - */ -#define GNUNET_REST_JSON_IDENTITY_EGO "ego" - -/** - * Name attribute - */ -#define GNUNET_REST_JSON_IDENTITY_NAME "name" - -/** - * Attribute to rename "name" TODO we changed id to the pubkey - * so this can be unified with "name" + * Parameter names */ -#define GNUNET_REST_JSON_IDENTITY_NEWNAME "newname" - -/** - * URL parameter to change the subsytem for ego - */ -#define GNUNET_REST_JSON_IDENTITY_SUBSYSTEM "subsystem" - +#define GNUNET_REST_PARAM_PUBKEY "pubkey" +#define GNUNET_REST_PARAM_SUBSYSTEM "subsystem" +#define GNUNET_REST_PARAM_NAME "name" +#define GNUNET_REST_PARAM_NEWNAME "newname" /** * Error messages */ +#define GNUNET_REST_ERROR_UNKNOWN "Unknown Error" #define GNUNET_REST_ERROR_RESOURCE_INVALID "Resource location invalid" #define GNUNET_REST_ERROR_NO_DATA "No data" #define GNUNET_REST_ERROR_DATA_INVALID "Data invalid" /** - * GNUid token lifetime + * State while collecting all egos + */ +#define ID_REST_STATE_INIT 0 + +/** + * Done collecting egos */ -#define GNUNET_GNUID_TOKEN_EXPIRATION_MICROSECONDS 300000000 +#define ID_REST_STATE_POST_INIT 1 /** * The configuration handle @@ -129,28 +108,37 @@ struct EgoEntry struct GNUNET_IDENTITY_Ego *ego; }; - struct RequestHandle { /** - * Ego list + * The data from the REST request */ - struct EgoEntry *ego_head; + const char* data; /** - * Ego list + * The name to look up */ - struct EgoEntry *ego_tail; + char *name; /** - * Handle to the rest connection + * the length of the REST data */ - struct GNUNET_REST_RequestHandle *conndata_handle; + size_t data_size; /** - * response code + * Requested Subsystem */ - int response_code; + char *subsystem; + + /** + * Ego list + */ + struct EgoEntry *ego_head; + + /** + * Ego list + */ + struct EgoEntry *ego_tail; /** * The processing state @@ -158,7 +146,7 @@ struct RequestHandle int state; /** - * Handle to GNS service. + * Handle to Identity service. */ struct GNUNET_IDENTITY_Handle *identity_handle; @@ -167,6 +155,11 @@ struct RequestHandle */ struct GNUNET_IDENTITY_Operation *op; + /** + * Rest connection + */ + struct GNUNET_REST_RequestHandle *rest_handle; + /** * Desired timeout for the lookup (default is no timeout). */ @@ -175,7 +168,7 @@ struct RequestHandle /** * 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 @@ -187,44 +180,23 @@ struct RequestHandle */ void *proc_cls; - /** - * The name to look up - */ - char *name; - - /** - * The subsystem set from REST - */ - char *subsys; - /** * The url */ char *url; /** - * The data from the REST request - */ - const char* data; - - /** - * the length of the REST data - */ - size_t data_size; - - /** - * HTTP method + * Error response message */ - const char* method; + char *emsg; /** - * Error response message + * Reponse code */ - char *emsg; + int response_code; }; - /** * Cleanup lookup handle * @param handle Handle to clean up @@ -234,35 +206,37 @@ cleanup_handle (struct RequestHandle *handle) { struct EgoEntry *ego_entry; struct EgoEntry *ego_tmp; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Cleaning up\n"); - if (NULL != handle->name) - GNUNET_free (handle->name); + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n"); if (NULL != handle->timeout_task) { GNUNET_SCHEDULER_cancel (handle->timeout_task); handle->timeout_task = NULL; } - if (NULL != handle->identity_handle) - GNUNET_IDENTITY_disconnect (handle->identity_handle); - if (NULL != handle->subsys) - GNUNET_free (handle->subsys); + + if (NULL != handle->subsystem) + GNUNET_free(handle->subsystem); if (NULL != handle->url) - GNUNET_free (handle->url); + GNUNET_free(handle->url); if (NULL != handle->emsg) - GNUNET_free (handle->emsg); + GNUNET_free(handle->emsg); + if (NULL != handle->name) + GNUNET_free (handle->name); + if (NULL != handle->identity_handle) + GNUNET_IDENTITY_disconnect (handle->identity_handle); + for (ego_entry = handle->ego_head; - NULL != ego_entry;) + NULL != ego_entry;) { ego_tmp = ego_entry; ego_entry = ego_entry->next; - GNUNET_free (ego_tmp->identifier); - GNUNET_free (ego_tmp->keystring); - GNUNET_free (ego_tmp); + GNUNET_free(ego_tmp->identifier); + GNUNET_free(ego_tmp->keystring); + GNUNET_free(ego_tmp); } - GNUNET_free (handle); -} + GNUNET_free(handle); +} /** * Task run on errors. Reports an error and cleans up everything. @@ -277,10 +251,12 @@ do_error (void *cls) char *json_error; if (NULL == handle->emsg) - handle->emsg = GNUNET_strdup("Unknown Error"); + handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_UNKNOWN); GNUNET_asprintf (&json_error, "{\"error\": \"%s\"}", handle->emsg); - handle->response_code = MHD_HTTP_OK; + + if (0 == handle->response_code) + handle->response_code = MHD_HTTP_OK; resp = GNUNET_REST_create_response (json_error); handle->proc (handle->proc_cls, resp, handle->response_code); @@ -288,9 +264,8 @@ do_error (void *cls) GNUNET_free(json_error); } - /** - * Callback for IDENTITY_get() + * Callback for GET Request with subsystem * * @param cls the RequestHandle * @param ego the Ego found @@ -298,173 +273,153 @@ do_error (void *cls) * @param name the id of the ego */ static void -get_ego_for_subsys (void *cls, - struct GNUNET_IDENTITY_Ego *ego, - void **ctx, - const char *name) +ego_get_for_subsystem (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, + const char *name) { struct RequestHandle *handle = cls; - struct EgoEntry *ego_entry; struct MHD_Response *resp; + struct GNUNET_CRYPTO_EcdsaPublicKey public_key; json_t *json_root; - json_t *json_ego; - json_t *name_json; char *result_str; - size_t index; - - json_root = json_array(); + char *public_key_string; - for (ego_entry = handle->ego_head; - NULL != ego_entry; - ego_entry = ego_entry->next) + if(NULL == ego) { - if ( (NULL != name) && (0 != strcmp (name, ego_entry->identifier)) ) - continue; - if (NULL == name) - continue; - - json_ego = json_object(); - name_json = json_string (ego_entry->identifier); - json_object_set_new(json_ego, GNUNET_REST_JSON_IDENTITY_EGO, name_json); - json_array_append(json_root, json_ego); - - break; - } - - if (0 == json_array_size(json_root)) - { - json_decref(json_root); - handle->emsg = GNUNET_strdup("No identity matches results!"); + handle->emsg = GNUNET_strdup("No identity found for subsystem"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - result_str = json_dumps(json_root, 0); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); + GNUNET_IDENTITY_ego_get_public_key(ego,&public_key); + public_key_string = GNUNET_CRYPTO_ecdsa_public_key_to_string(&public_key); + + // create json with subsystem identity + json_root = json_object (); + json_object_set_new (json_root, GNUNET_REST_PARAM_PUBKEY, json_string(public_key_string)); + json_object_set_new (json_root, GNUNET_REST_PARAM_NAME, json_string(name)); + + result_str = json_dumps (json_root, 0); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); resp = GNUNET_REST_create_response (result_str); - json_array_foreach(json_root, index, json_ego ) - { - json_decref(json_ego); - } json_decref (json_root); handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); - GNUNET_free (result_str); + GNUNET_free(result_str); + GNUNET_free(public_key_string); cleanup_handle (handle); } - /** - * Create a response with requested ego(s) + * Handle identity GET request * - * @param con the Rest handle - * @param url the requested url - * @param cls the request handle + * @param con_handle the connection handle + * @param url the url + * @param cls the RequestHandle */ -static void -ego_info_response (struct GNUNET_REST_RequestHandle *con, - const char *url, - void *cls) +void +ego_get (struct GNUNET_REST_RequestHandle *con_handle, const char* url, + void *cls) { - const char *egoname; - char *result_str; - char *subsys_val; - char *keystring; struct RequestHandle *handle = cls; struct EgoEntry *ego_entry; struct GNUNET_HashCode key; struct MHD_Response *resp; + char *keystring; + const char *egoname; json_t *json_root; json_t *json_ego; - json_t *name_str; + char *result_str; size_t index; - if (GNUNET_NO == GNUNET_REST_namespace_match (handle->url, GNUNET_REST_API_NS_IDENTITY)) - { - resp = GNUNET_REST_create_response (NULL); - handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST); - cleanup_handle (handle); + //if subsystem + GNUNET_CRYPTO_hash (GNUNET_REST_PARAM_SUBSYSTEM, + strlen (GNUNET_REST_PARAM_SUBSYSTEM), &key); + if ( GNUNET_YES + == GNUNET_CONTAINER_multihashmap_contains ( + handle->rest_handle->url_param_map, &key)) + { + handle->subsystem = GNUNET_strdup( + GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, + &key)); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Looking for %s's ego\n", + handle->subsystem); + + handle->op = GNUNET_IDENTITY_get (handle->identity_handle, + handle->subsystem, &ego_get_for_subsystem, + handle); + if (NULL == handle->op) + { + handle->emsg = GNUNET_strdup("No identity found for subsystem"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } return; } egoname = NULL; keystring = NULL; - if (strlen (GNUNET_REST_API_NS_IDENTITY) < strlen (handle->url)) + + //if only one identity requested + GNUNET_CRYPTO_hash (GNUNET_REST_PARAM_PUBKEY, + strlen (GNUNET_REST_PARAM_PUBKEY), &key); + if ( GNUNET_YES + == GNUNET_CONTAINER_multihashmap_contains ( + handle->rest_handle->url_param_map, &key)) { - keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY)+1]; - //Return all egos + keystring = GNUNET_CONTAINER_multihashmap_get ( + handle->rest_handle->url_param_map, &key); + for (ego_entry = handle->ego_head; - NULL != ego_entry; - ego_entry = ego_entry->next) + NULL != ego_entry; ego_entry = ego_entry->next) { - if ( (NULL != keystring) && (0 != strcmp (keystring, ego_entry->keystring)) ) - continue; + if ((NULL != keystring) + && (0 != strcmp (keystring, ego_entry->keystring))) + continue; egoname = ego_entry->identifier; } } - if ( NULL == egoname ) { - GNUNET_CRYPTO_hash (GNUNET_REST_JSON_IDENTITY_SUBSYSTEM, - strlen (GNUNET_REST_JSON_IDENTITY_SUBSYSTEM), - &key); - if ( GNUNET_YES == - GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, - &key) ) - { - subsys_val = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, - &key); - if (NULL != subsys_val) - { - GNUNET_asprintf (&handle->subsys, "%s", subsys_val); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for %s's ego\n", subsys_val); - handle->op = GNUNET_IDENTITY_get (handle->identity_handle, - handle->subsys, - &get_ego_for_subsys, - handle); - return; - } - } - } - - json_root = json_array(); - - //Return all egos + json_root = json_array (); + //Return ego/egos for (ego_entry = handle->ego_head; - NULL != ego_entry; - ego_entry = ego_entry->next) + NULL != ego_entry; ego_entry = ego_entry->next) { - if ( (NULL != egoname) && (0 != strcmp (egoname, ego_entry->identifier)) ) - continue; - - json_ego = json_object(); - - json_object_set_new( json_ego, "id", json_string (ego_entry->keystring)); - json_object_set_new( json_ego, "type", json_string (GNUNET_REST_JSON_IDENTITY_EGO)); - name_str = json_string (ego_entry->identifier); - json_object_set_new( json_ego, "name", name_str); + //if only one ego requested + if ((NULL != egoname)){ + if(0 != strcmp (egoname, ego_entry->identifier)){ + continue; + } + } - json_array_append( json_root, json_ego ); + json_ego = json_object (); + json_object_set_new (json_ego, + GNUNET_REST_PARAM_PUBKEY, + json_string (ego_entry->keystring)); + json_object_set_new (json_ego, + GNUNET_REST_PARAM_NAME, + json_string (ego_entry->identifier)); + json_array_append (json_root, json_ego); } - if ((size_t)0 == json_array_size(json_root)) + if ((size_t) 0 == json_array_size (json_root)) { json_decref (json_root); - handle->emsg = GNUNET_strdup ("No identities found!"); + handle->emsg = GNUNET_strdup("No identities found!"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - result_str = json_dumps(json_root, 0); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); + result_str = json_dumps (json_root, 0); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); resp = GNUNET_REST_create_response (result_str); //delete json_objects in json_array with macro json_array_foreach(json_root, index, json_ego ) { - json_decref(json_ego); + json_decref (json_ego); } json_decref (json_root); handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); - GNUNET_free (result_str); + GNUNET_free(result_str); cleanup_handle (handle); } @@ -483,7 +438,7 @@ do_finished (void *cls, const char *emsg) handle->op = NULL; if (NULL != emsg) { - handle->emsg = GNUNET_strdup (emsg); + handle->emsg = GNUNET_strdup(emsg); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } @@ -493,288 +448,280 @@ do_finished (void *cls, const char *emsg) } /** - * Create a new ego + * Handle identity PUT request * - * @param con rest handle - * @param url url - * @param cls request handle + * @param con_handle the connection handle + * @param url the url + * @param cls the RequestHandle */ -static void -ego_create_cont (struct GNUNET_REST_RequestHandle *con, - const char *url, - void *cls) +void +ego_edit (struct GNUNET_REST_RequestHandle *con_handle, const char* url, + void *cls) { struct RequestHandle *handle = cls; struct EgoEntry *ego_entry; + struct EgoEntry *ego_entry_tmp; struct MHD_Response *resp; - json_t *egoname_json; + json_t *subsys_json; + json_t *name_json; + json_t *key_json; json_t *data_js; json_error_t err; - const char* egoname; - char term_data[handle->data_size+1]; - - if (strlen (GNUNET_REST_API_NS_IDENTITY) != strlen (handle->url)) - { - handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_RESOURCE_INVALID); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } + const char *keystring; + const char *subsys; + const char *newname; + char term_data[handle->data_size + 1]; + int ego_exists = GNUNET_NO; + //if no data if (0 >= handle->data_size) { - handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA); + handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } + //if not json term_data[handle->data_size] = '\0'; - GNUNET_memcpy (term_data, handle->data, handle->data_size); - data_js = json_loads (term_data, - JSON_DECODE_ANY, - &err); - - + GNUNET_memcpy(term_data, handle->data, handle->data_size); + data_js = json_loads (term_data,JSON_DECODE_ANY,&err); if (NULL == data_js) { - handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_DATA_INVALID); + handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - //instead of parse if (!json_is_object(data_js)) { - json_decref(data_js); - handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_DATA_INVALID); + json_decref (data_js); + handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - - if (1 != json_object_size (data_js)) + //json must contain pubkey and (subsystem or name) + if (2 != json_object_size (data_js)) { json_decref (data_js); - handle->emsg = GNUNET_strdup("Provided resource count invalid"); + handle->emsg = GNUNET_strdup("Resource amount invalid"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - egoname_json = json_object_get (data_js, GNUNET_REST_JSON_IDENTITY_NAME); - if (!json_is_string (egoname_json)) + key_json = json_object_get (data_js, GNUNET_REST_PARAM_PUBKEY); + if ((NULL == key_json) || !json_is_string(key_json)) { json_decref (data_js); - handle->emsg = GNUNET_strdup ("No name provided"); + handle->emsg = GNUNET_strdup("Missing element pubkey"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - egoname = json_string_value (egoname_json); - if(0 >= strlen(egoname)) + keystring = json_string_value (key_json); + + for (ego_entry = handle->ego_head; + NULL != ego_entry; ego_entry = ego_entry->next) + { + if (0 != strcasecmp (keystring, ego_entry->keystring)) + continue; + ego_exists = GNUNET_YES; + break; + } + + if (GNUNET_NO == ego_exists) { json_decref (data_js); - handle->emsg = GNUNET_strdup ("No name provided"); - GNUNET_SCHEDULER_add_now (&do_error, handle); + resp = GNUNET_REST_create_response (NULL); + handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND); + cleanup_handle (handle); return; } - for (ego_entry = handle->ego_head; - NULL != ego_entry; - ego_entry = ego_entry->next) + //This is a rename + name_json = json_object_get (data_js, GNUNET_REST_PARAM_NEWNAME); + if ((NULL != name_json) && json_is_string(name_json)) { - if (0 == strcasecmp (egoname, ego_entry->identifier)) + newname = json_string_value (name_json); + if (0 >= strlen (newname)) { json_decref (data_js); - resp = GNUNET_REST_create_response (NULL); - handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); - cleanup_handle (handle); + handle->emsg = GNUNET_strdup("No name provided"); + GNUNET_SCHEDULER_add_now (&do_error, handle); return; } + for (ego_entry_tmp = handle->ego_head; + NULL != ego_entry_tmp; ego_entry_tmp = ego_entry_tmp->next) + { + if (0 == strcasecmp (newname, ego_entry_tmp->identifier) + && 0 != strcasecmp (keystring, ego_entry_tmp->keystring)) + { + //Ego with same name not allowed + json_decref (data_js); + resp = GNUNET_REST_create_response (NULL); + handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); + cleanup_handle (handle); + return; + } + } + handle->response_code = MHD_HTTP_NO_CONTENT; + handle->op = GNUNET_IDENTITY_rename (handle->identity_handle, + ego_entry->identifier, newname, + &do_finished, handle); + json_decref (data_js); + return; + } + + //Set subsystem + subsys_json = json_object_get (data_js, GNUNET_REST_PARAM_SUBSYSTEM); + if ((NULL != subsys_json) && json_is_string(subsys_json)) + { + subsys = json_string_value (subsys_json); + if (0 >= strlen (subsys)) + { + json_decref (data_js); + handle->emsg = GNUNET_strdup("Invalid subsystem name"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + GNUNET_asprintf (&handle->subsystem, "%s", subsys); + json_decref (data_js); + handle->response_code = MHD_HTTP_NO_CONTENT; + handle->op = GNUNET_IDENTITY_set (handle->identity_handle, handle->subsystem, + ego_entry->ego, &do_finished, handle); + return; } - GNUNET_asprintf (&handle->name, "%s", egoname); json_decref (data_js); - handle->response_code = MHD_HTTP_CREATED; - handle->op = GNUNET_IDENTITY_create (handle->identity_handle, - handle->name, - &do_finished, - handle); + handle->emsg = GNUNET_strdup("Subsystem not provided"); + GNUNET_SCHEDULER_add_now (&do_error, handle); } - /** - * Handle ego edit request + * Handle identity POST request * - * @param con rest connection handle - * @param url the url that is requested + * @param con_handle the connection handle + * @param url the url * @param cls the RequestHandle */ -static void -ego_edit_cont (struct GNUNET_REST_RequestHandle *con, - const char *url, - void *cls) +void +ego_create (struct GNUNET_REST_RequestHandle *con_handle, const char* url, + void *cls) { struct RequestHandle *handle = cls; struct EgoEntry *ego_entry; - struct EgoEntry *ego_entry_tmp; struct MHD_Response *resp; - json_t *subsys_json; - json_t *name_json; + json_t *egoname_json; json_t *data_js; json_error_t err; - const char *keystring; - const char *subsys; - const char *newname; - char term_data[handle->data_size+1]; - int ego_exists = GNUNET_NO; + const char* egoname; + char term_data[handle->data_size + 1]; - if (strlen (GNUNET_REST_API_NS_IDENTITY) > strlen (handle->url)) + if (strlen (GNUNET_REST_API_NS_IDENTITY) != strlen (handle->url)) { - handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_RESOURCE_INVALID); + handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_RESOURCE_INVALID); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - keystring = &handle->url[strlen(GNUNET_REST_API_NS_IDENTITY)+1]; - - for (ego_entry = handle->ego_head; - NULL != ego_entry; - ego_entry = ego_entry->next) - { - if (0 != strcasecmp (keystring, ego_entry->keystring)) - continue; - ego_exists = GNUNET_YES; - break; - } - - if (GNUNET_NO == ego_exists) - { - resp = GNUNET_REST_create_response (NULL); - handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND); - cleanup_handle (handle); - return; - } - if (0 >= handle->data_size) { - handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA); + handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - term_data[handle->data_size] = '\0'; - GNUNET_memcpy (term_data, handle->data, handle->data_size); + GNUNET_memcpy(term_data, handle->data, handle->data_size); data_js = json_loads (term_data, - JSON_DECODE_ANY, - &err); + JSON_DECODE_ANY, + &err); + if (NULL == data_js) { - handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA); + handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } + //instead of parse if (!json_is_object(data_js)) { json_decref (data_js); - handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_DATA_INVALID); + handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - if (1 != json_object_size(data_js)) + if (1 != json_object_size (data_js)) { json_decref (data_js); - handle->emsg = GNUNET_strdup ("Resource amount invalid"); + handle->emsg = GNUNET_strdup("Provided resource count invalid"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - //This is a rename - name_json = json_object_get (data_js, GNUNET_REST_JSON_IDENTITY_NEWNAME); - if ((NULL != name_json) && json_is_string (name_json)) + egoname_json = json_object_get (data_js, GNUNET_REST_PARAM_NAME); + if (!json_is_string(egoname_json)) { - newname = json_string_value (name_json); - if(0 >= strlen(newname)) - { - json_decref (data_js); - handle->emsg = GNUNET_strdup ("No name provided"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - for (ego_entry_tmp = handle->ego_head; - NULL != ego_entry_tmp; - ego_entry_tmp = ego_entry_tmp->next) - { - if (0 == strcasecmp (newname, ego_entry_tmp->identifier) && - 0 != strcasecmp (keystring, ego_entry_tmp->keystring)) - { - //Ego with same name not allowed - json_decref (data_js); - resp = GNUNET_REST_create_response (NULL); - handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); - cleanup_handle (handle); - return; - } - } - handle->response_code = MHD_HTTP_NO_CONTENT; - handle->op = GNUNET_IDENTITY_rename (handle->identity_handle, - ego_entry->identifier, - newname, - &do_finished, - handle); json_decref (data_js); + handle->emsg = GNUNET_strdup("No name provided"); + GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - - //Set subsystem - subsys_json = json_object_get (data_js, GNUNET_REST_JSON_IDENTITY_SUBSYSTEM); - if ( (NULL != subsys_json) && json_is_string (subsys_json)) + egoname = json_string_value (egoname_json); + if (0 >= strlen (egoname)) { - subsys = json_string_value (subsys_json); - if(0 >= strlen(subsys)) + json_decref (data_js); + handle->emsg = GNUNET_strdup("No name provided"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + for (ego_entry = handle->ego_head; + NULL != ego_entry; ego_entry = ego_entry->next) + { + if (0 == strcasecmp (egoname, ego_entry->identifier)) { json_decref (data_js); - handle->emsg = GNUNET_strdup ("No name provided"); - GNUNET_SCHEDULER_add_now (&do_error, handle); + resp = GNUNET_REST_create_response (NULL); + handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); + cleanup_handle (handle); return; } - GNUNET_asprintf (&handle->subsys, "%s", subsys); - json_decref (data_js); - handle->response_code = MHD_HTTP_NO_CONTENT; - handle->op = GNUNET_IDENTITY_set (handle->identity_handle, - handle->subsys, - ego_entry->ego, - &do_finished, - handle); - return; } + GNUNET_asprintf (&handle->name, "%s", egoname); json_decref (data_js); - handle->emsg = GNUNET_strdup ("Subsystem not provided"); - GNUNET_SCHEDULER_add_now (&do_error, handle); + handle->response_code = MHD_HTTP_CREATED; + handle->op = GNUNET_IDENTITY_create (handle->identity_handle, handle->name, + &do_finished, handle); } /** - * Handle ego delete request + * Handle identity DELETE request * * @param con_handle the connection handle * @param url the url * @param cls the RequestHandle */ void -ego_delete_cont (struct GNUNET_REST_RequestHandle *con_handle, - const char* url, - void *cls) +ego_delete (struct GNUNET_REST_RequestHandle *con_handle, const char* url, + void *cls) { const char *keystring; struct EgoEntry *ego_entry; + struct GNUNET_HashCode key; struct MHD_Response *resp; struct RequestHandle *handle = cls; int ego_exists = GNUNET_NO; - if (strlen (GNUNET_REST_API_NS_IDENTITY) >= strlen (handle->url)) + //if only one identity requested + GNUNET_CRYPTO_hash (GNUNET_REST_PARAM_PUBKEY, + strlen (GNUNET_REST_PARAM_PUBKEY), &key); + if ( GNUNET_NO + == GNUNET_CONTAINER_multihashmap_contains ( + handle->rest_handle->url_param_map, &key)) { - handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_RESOURCE_INVALID); + handle->emsg = GNUNET_strdup("Missing parameter pubkey"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - keystring = &handle->url[strlen(GNUNET_REST_API_NS_IDENTITY)+1]; + keystring = GNUNET_CONTAINER_multihashmap_get ( + handle->rest_handle->url_param_map,&key); for (ego_entry = handle->ego_head; - NULL != ego_entry; - ego_entry = ego_entry->next) + NULL != ego_entry; ego_entry = ego_entry->next) { if (0 != strcasecmp (keystring, ego_entry->keystring)) continue; @@ -790,13 +737,11 @@ ego_delete_cont (struct GNUNET_REST_RequestHandle *con_handle, } handle->response_code = MHD_HTTP_NO_CONTENT; handle->op = GNUNET_IDENTITY_delete (handle->identity_handle, - ego_entry->identifier, - &do_finished, - handle); + ego_entry->identifier, &do_finished, + handle); } - /** * Respond to OPTIONS request * @@ -805,18 +750,15 @@ ego_delete_cont (struct GNUNET_REST_RequestHandle *con_handle, * @param cls the RequestHandle */ static void -options_cont (struct GNUNET_REST_RequestHandle *con_handle, - const char* url, - void *cls) +options_cont (struct GNUNET_REST_RequestHandle *con_handle, const char* url, + void *cls) { struct MHD_Response *resp; struct RequestHandle *handle = cls; //For now, independent of path return all options resp = GNUNET_REST_create_response (NULL); - MHD_add_response_header (resp, - "Access-Control-Allow-Methods", - allow_methods); + MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods); handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); cleanup_handle (handle); return; @@ -832,18 +774,17 @@ init_cont (struct RequestHandle *handle) { struct GNUNET_REST_RequestHandlerError err; static const struct GNUNET_REST_RequestHandler handlers[] = { - {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY, &ego_info_response}, - {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY, &ego_create_cont}, - {MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY, &ego_edit_cont}, - {MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_IDENTITY, &ego_delete_cont}, - {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY, &options_cont}, - GNUNET_REST_HANDLER_END + { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY, &ego_get }, + { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY, &ego_edit }, + { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY, &ego_create }, + { MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_IDENTITY, &ego_delete }, + { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY, &options_cont }, + GNUNET_REST_HANDLER_END }; - if (GNUNET_NO == GNUNET_REST_handle_request (handle->conndata_handle, - handlers, - &err, - handle)) + if (GNUNET_NO + == GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, + handle)) { handle->response_code = err.error_code; GNUNET_SCHEDULER_add_now (&do_error, handle); @@ -884,10 +825,8 @@ init_cont (struct RequestHandle *handle) * must thus no longer be used */ static void -list_ego (void *cls, - struct GNUNET_IDENTITY_Ego *ego, - void **ctx, - const char *identifier) +init_egos (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, + const char *identifier) { struct RequestHandle *handle = cls; struct EgoEntry *ego_entry; @@ -899,16 +838,16 @@ list_ego (void *cls, init_cont (handle); return; } - if (ID_REST_STATE_INIT == handle->state) { - ego_entry = GNUNET_new (struct EgoEntry); + if (ID_REST_STATE_INIT == handle->state) + { + ego_entry = GNUNET_new(struct EgoEntry); GNUNET_IDENTITY_ego_get_public_key (ego, &pk); - ego_entry->keystring = - GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); + ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); ego_entry->ego = ego; GNUNET_asprintf (&ego_entry->identifier, "%s", identifier); - GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry); + GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head, handle->ego_tail, + ego_entry); } - } /** @@ -923,39 +862,30 @@ list_ego (void *cls, * @return GNUNET_OK if request accepted */ static void -rest_identity_process_request(struct GNUNET_REST_RequestHandle *conndata_handle, - GNUNET_REST_ResultProcessor proc, - void *proc_cls) +rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle, + GNUNET_REST_ResultProcessor proc, void *proc_cls) { - struct RequestHandle *handle = GNUNET_new (struct RequestHandle); - - + struct RequestHandle *handle = GNUNET_new(struct RequestHandle); + handle->response_code = 0; handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; - handle->response_code = MHD_HTTP_OK; handle->proc_cls = proc_cls; handle->proc = proc; - handle->state = ID_REST_STATE_INIT; - handle->conndata_handle = conndata_handle; - handle->data = conndata_handle->data; - handle->data_size = conndata_handle->data_size; - handle->method = conndata_handle->method; - GNUNET_asprintf (&handle->url, "%s", conndata_handle->url); - if (handle->url[strlen (handle->url)-1] == '/') - handle->url[strlen (handle->url)-1] = '\0'; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Connecting...\n"); - handle->identity_handle = GNUNET_IDENTITY_connect (cfg, - &list_ego, - handle); - handle->timeout_task = - GNUNET_SCHEDULER_add_delayed (handle->timeout, - &do_error, - handle); - - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Connected\n"); + handle->rest_handle = rest_handle; + handle->data = rest_handle->data; + handle->data_size = rest_handle->data_size; + + 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, "Connecting...\n"); + + handle->identity_handle = GNUNET_IDENTITY_connect (cfg, &init_egos, handle); + + handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout, + &do_error, handle); + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connected\n"); } /** @@ -972,27 +902,24 @@ libgnunet_plugin_rest_identity_init (void *cls) cfg = cls; if (NULL != plugin.cfg) - return NULL; /* can only initialize once! */ - memset (&plugin, 0, sizeof (struct Plugin)); + return NULL; /* can only initialize once! */ + memset (&plugin, 0, sizeof(struct Plugin)); plugin.cfg = cfg; - api = GNUNET_new (struct GNUNET_REST_Plugin); + api = GNUNET_new(struct GNUNET_REST_Plugin); api->cls = &plugin; api->name = GNUNET_REST_API_NS_IDENTITY; - api->process_request = &rest_identity_process_request; - GNUNET_asprintf (&allow_methods, - "%s, %s, %s, %s, %s", - MHD_HTTP_METHOD_GET, - MHD_HTTP_METHOD_POST, - MHD_HTTP_METHOD_PUT, - MHD_HTTP_METHOD_DELETE, - MHD_HTTP_METHOD_OPTIONS); - - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("Identity REST API initialized\n")); + api->process_request = &rest_process_request; + GNUNET_asprintf (&allow_methods, "%s, %s, %s, %s, %s", + MHD_HTTP_METHOD_GET, + MHD_HTTP_METHOD_POST, + MHD_HTTP_METHOD_PUT, + MHD_HTTP_METHOD_DELETE, + MHD_HTTP_METHOD_OPTIONS); + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, _("Identity REST API initialized\n")); return api; } - /** * Exit point from the plugin. * @@ -1004,13 +931,13 @@ libgnunet_plugin_rest_identity_done (void *cls) { struct GNUNET_REST_Plugin *api = cls; struct Plugin *plugin = api->cls; - plugin->cfg = NULL; - GNUNET_free_non_null (allow_methods); - GNUNET_free (api); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Identity REST plugin is finished\n"); + + GNUNET_free_non_null(allow_methods); + GNUNET_free(api); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Identity REST plugin is finished\n"); return NULL; } -/* end of plugin_rest_gns.c */ +/* end of plugin_rest_identity.c */ + diff --git a/src/identity/test_plugin_rest_identity.sh b/src/identity/test_plugin_rest_identity.sh new file mode 100755 index 000000000..b48becc45 --- /dev/null +++ b/src/identity/test_plugin_rest_identity.sh @@ -0,0 +1,216 @@ +#!/usr/bin/bash + +#First, start gnunet-arm and the rest-service. Make sure, no identity exists +#Exit 0 means success, exit 1 means failed test + +#No test for subsystem available + +link_to_api="http://localhost:7776/identity" +wrong_link="http://localhost:7776/idenmmmy" +wrong_link2="http://localhost:7776/identityandmore" + +#Test GET (multiple identities) for error when no identity exists +#The next test case can be ignored if you have already added identities +cache="$(curl --silent "$link_to_api" | grep "error")" +if [ "" == "$cache" ] +then + exit 1 +fi + +#Test POST success code, error response code and error json +#The next test case can be ignored if you have already added an identity with the name Test +cache="$(curl -v -X "POST" "$link_to_api" --data "{\"name\":\"Test\"}" 2>&1 | grep "HTTP/1.1 201")" +if [ "" == "$cache" ] +then + exit 1 +fi + +cache="$(curl -v -X "POST" "$link_to_api" --data "{\"name\":\"Test\"}" 2>&1 | grep "HTTP/1.1 409")" +if [ "" == "$cache" ] +then + exit 1 +fi + +cache="$(curl -v -X "POST" "$link_to_api" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + exit 1 +fi + +cache="$(curl -v -X "POST" "$link_to_api" --data "wrong" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + exit 1 +fi + +cache="$(curl -v -X "POST" "$link_to_api" --data "[{}]" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + exit 1 +fi + +cache="$(curl -v -X "POST" "$link_to_api" --data "{\"name\":\"Test\",\"other\":\"Test\"}" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + exit 1 +fi + +cache="$(curl -v -X "POST" "$link_to_api" --data "{\"nam\":\"Test\"}" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + exit 1 +fi + +cache="$(curl -v -X "POST" "$link_to_api" --data "{\"name\":123}" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + exit 1 +fi + +cache="$(curl -v -X "POST" "$link_to_api" --data "{\"name\":""}" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + exit 1 +fi + + +#Test GET (multiple identities) for success and error json +cache="$(curl --silent "$link_to_api" | grep "error")" +if [ "" != "$cache" ] +then + exit 1 +fi + + +id="$(gnunet-identity -d | grep "Test - " | sed "s/Test - //g")" +#Test GET (one identity) for success and error json +cache="$(curl --silent "${link_to_api}?pubkey=$id" | grep "error")" +if [ "" != "$cache" ] +then + exit 1 +fi + + +#Test DELETE success code, error response code and error json +#echo "Next tests for DELETE will probably fail when POST fails" +cache="$(curl -v -X "DELETE" "${link_to_api}?pubkey=$id" 2>&1 | grep "HTTP/1.1 404")" +if [ "" != "$cache" ] +then + exit 1 +fi + +curl --silent -X "POST" "$link_to_api" --data "{\"name\":\"Test\"}" +id="$(gnunet-identity -d | grep "Test - " | sed "s/Test - //g")" + +cache="$(curl -v -X "DELETE" "${link_to_api}?pubkey=df1" 2>&1 | grep "HTTP/1.1 404")" +if [ "" == "$cache" ] +then + exit 1 +fi + +cache="$(curl -v -X "DELETE" "${link_to_api}?pubke=$id" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + exit 1 +fi + +#Test PUT success code, error response codes and error json +cache="$(curl -v -X "PUT" "${link_to_api}" --data "{\"newname\":\"NewTest\",\"pubkey\":\"${id}\"}" 2>&1 | grep "HTTP/1.1 204")" +if [ "" == "$cache" ] +then + exit 1 +fi + +cache="$(curl -v -X "PUT" "${link_to_api}" --data "{\"newname\":\"NewNewTest\",\"pubkey\":\"${id}1\"}" 2>&1 | grep "HTTP/1.1 404")" +if [ "" == "$cache" ] +then + exit 1 +fi + +# feature: you can rename your identity with its own name. +# cache="$(curl -v -X "PUT" "$link_to_api" --data "{\"newname\":\"NewTest\",\"pubkey\":\"${id}\"}" 2>&1 | grep "error")" +# if [ "" == "$cache" ] +# then +# exit 1 +# fi + + +cache="$(curl -v -X "PUT" "$link_to_api" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + exit 1 +fi + +cache="$(curl -v -X "PUT" "$link_to_api" --data "wrong" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + exit 1 +fi + +cache="$(curl -v -X "PUT" "$link_to_api" --data "[{}]" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + exit 1 +fi + +cache="$(curl -v -X "PUT" "$link_to_api" --data "{\"newname\":\"Test\",\"other\":\"Test\",\"pubkey\":\"${id}\"}" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + exit 1 +fi + +cache="$(curl -v -X "PUT" "$link_to_api" --data "{\"newnam\":\"Test\",\"pubkey\":\"${id}\"}" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + exit 1 +fi + +cache="$(curl -v -X "PUT" "$link_to_api" --data "{\"newname\":\"Test\",\"pubke\":\"${id}\"}" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + exit 1 +fi + +cache="$(curl -v -X "PUT" "$link_to_api" --data "{\"newname\":123,\"pubkey\":\"${id}\"}" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + exit 1 +fi + +cache="$(curl -v -X "PUT" "$link_to_api" --data "{\"newname\":"",\"pubkey\":\"${id}\"}" 2>&1 | grep "error")" +if [ "" == "$cache" ] +then + exit 1 +fi +#TODO Missing subsystem test + +#Missing OPTIONS success - nothing can really go wrong here + +#Test wrong url +cache="$(curl -v "$wrong_link" 2>&1 | grep "HTTP/1.1 404")" +if [ "" == "$cache" ] +then + exit 1 +fi + +cache="$(curl -X "PUT" -v "$wrong_link" --data "{\"newname\":\"Testing\",\"pubkey\":\"${id}\"}" 2>&1 | grep "HTTP/1.1 404")" +if [ "" == "$cache" ] +then + exit 1 +fi + +cache="$(curl -X "POST" -v "$wrong_link?pubkey=$id" --data "{\"name\":\"Test\"}" 2>&1 | grep "HTTP/1.1 404")" +if [ "" == "$cache" ] +then + exit 1 +fi + +cache="$(curl -X "DELETE" -v "${wrong_link}?pubkey=$id" 2>&1 | grep "HTTP/1.1 404")" +if [ "" == "$cache" ] +then + exit 1 +fi + +gnunet-identity -D NewTest + +exit 0 -- cgit v1.2.3 From 6efdf409484a0b694bb3d6bcf95b1891f70886fb Mon Sep 17 00:00:00 2001 From: Phil Date: Tue, 3 Jul 2018 10:47:40 +0200 Subject: -wip namestore --- src/include/gnunet_json_lib.h | 64 ++ src/json/Makefile.am | 3 +- src/json/json_parser.c | 169 +++++ src/namestore/plugin_rest_namestore.c | 1163 +++++++++++------------------- src/namestore/plugin_rest_namestore2.c | 1229 ++++++++++++++++++++++++++++++++ 5 files changed, 1882 insertions(+), 746 deletions(-) create mode 100644 src/json/json_parser.c create mode 100644 src/namestore/plugin_rest_namestore2.c (limited to 'src') diff --git a/src/include/gnunet_json_lib.h b/src/include/gnunet_json_lib.h index 06749590c..6340d1f41 100644 --- a/src/include/gnunet_json_lib.h +++ b/src/include/gnunet_json_lib.h @@ -479,6 +479,70 @@ GNUNET_JSON_getopt (char shortName, const char *description, json_t **json); +/* ****************** GETOPT JSON parser ******************* */ + +struct GNUNET_REST_JSON_Data +{ + /** + * Public key of an identity + */ + char *pubkey; + + /** + * Name + */ + char *name; + + /** + * Nickname + */ + char *nickname; + + /** + * New name + */ + char *new_name; + + /** + * Name of subsystem + */ + char *subsystem; + + /** + * Should data be handled as public (GNUNET_YES or GNUNET_NO) + */ + int is_public; + + /** + * Expiration date of data + */ + char *expiration_time; + + /** + * Type of data + */ + char *type; + + /** + * Value of data + */ + char *value; + + /** + * Zone + */ + char *zone; +}; +/* + * Test + */ +int +GNUNET_REST_JSON_parse (struct GNUNET_REST_JSON_Data** rest_json_data, + json_t *json_data); + +int +GNUNET_REST_JSON_free (struct GNUNET_REST_JSON_Data* rest_json_data); + #endif diff --git a/src/json/Makefile.am b/src/json/Makefile.am index da19e7955..5aac23654 100644 --- a/src/json/Makefile.am +++ b/src/json/Makefile.am @@ -16,7 +16,8 @@ libgnunetjson_la_SOURCES = \ json.c \ json_mhd.c \ json_generator.c \ - json_helper.c + json_helper.c \ + json_parser.c libgnunetjson_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ -ljansson \ diff --git a/src/json/json_parser.c b/src/json/json_parser.c new file mode 100644 index 000000000..cfe553b34 --- /dev/null +++ b/src/json/json_parser.c @@ -0,0 +1,169 @@ +/* + This file is part of GNUnet + Copyright (C) 2014, 2015, 2016 GNUnet e.V. + + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ +/** + * @file json/json_helper.c + * @brief functions for REST JSON parsing + * @author Philippe Buschmann + */ + +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_json_lib.h" + +#define GNUNET_REST_JSON_PUBKEY_ENTRY "pubkey" +#define GNUNET_REST_JSON_NAME_ENTRY "name" +#define GNUNET_REST_JSON_NICKNAME_ENTRY "nickname" +#define GNUNET_REST_JSON_NEWNAME_ENTRY "newname" +#define GNUNET_REST_JSON_SUBSYSTEM_ENTRY "subsystem" +#define GNUNET_REST_JSON_IS_PUBLIC_ENTRY "is_public" +#define GNUNET_REST_JSON_EXPIRATION_DATE_ENTRY "expiration_time" +#define GNUNET_REST_JSON_TYPE_ENTRY "type" +#define GNUNET_REST_JSON_VALUE_ENTRY "value" +#define GNUNET_REST_JSON_ZONE_ENTRY "zone" + + +int +GNUNET_REST_JSON_parse (struct GNUNET_REST_JSON_Data** output_data ,json_t *json_data) +{ + struct GNUNET_REST_JSON_Data *rest_json_data; + json_t *cache; + + rest_json_data = GNUNET_malloc(sizeof(struct GNUNET_REST_JSON_Data)); + + cache = json_object_get (json_data, GNUNET_REST_JSON_EXPIRATION_DATE_ENTRY); + rest_json_data->expiration_time = NULL; + if (NULL != cache) + { + if (json_is_string(cache)) + { + rest_json_data->expiration_time = GNUNET_strdup(json_string_value(cache)); + } + } + cache = json_object_get (json_data, GNUNET_REST_JSON_NAME_ENTRY); + rest_json_data->name = NULL; + if (NULL != cache) + { + if (json_is_string(cache)) + { + rest_json_data->name = GNUNET_strdup(json_string_value(cache)); + } + } + cache = json_object_get (json_data, GNUNET_REST_JSON_NEWNAME_ENTRY); + rest_json_data->new_name = NULL; + if (NULL != cache) + { + if (json_is_string(cache)) + { + rest_json_data->new_name = GNUNET_strdup(json_string_value(cache)); + } + } + cache = json_object_get (json_data, GNUNET_REST_JSON_NICKNAME_ENTRY); + rest_json_data->nickname = NULL; + if (NULL != cache) + { + if (json_is_string(cache)) + { + rest_json_data->nickname = GNUNET_strdup(json_string_value(cache)); + } + } + cache = json_object_get (json_data, GNUNET_REST_JSON_PUBKEY_ENTRY); + rest_json_data->pubkey = NULL; + if (NULL != cache) + { + if (json_is_string(cache)) + { + rest_json_data->pubkey = GNUNET_strdup(json_string_value(cache)); + } + } + cache = json_object_get (json_data, GNUNET_REST_JSON_SUBSYSTEM_ENTRY); + rest_json_data->subsystem = NULL; + if (NULL != cache) + { + if (json_is_string(cache)) + { + rest_json_data->subsystem = GNUNET_strdup(json_string_value(cache)); + } + } + cache = json_object_get (json_data, GNUNET_REST_JSON_TYPE_ENTRY); + rest_json_data->type = NULL; + if (NULL != cache) + { + if (json_is_string(cache)) + { + rest_json_data->type = GNUNET_strdup(json_string_value(cache)); + } + } + cache = json_object_get (json_data, GNUNET_REST_JSON_VALUE_ENTRY); + rest_json_data->value = NULL; + if (NULL != cache) + { + if (json_is_string(cache)) + { + rest_json_data->value = GNUNET_strdup(json_string_value(cache)); + } + } + cache = json_object_get (json_data, GNUNET_REST_JSON_ZONE_ENTRY); + rest_json_data->zone = NULL; + if (NULL != cache) + { + if (json_is_string(cache)) + { + rest_json_data->zone = GNUNET_strdup(json_string_value(cache)); + } + } + cache = json_object_get (json_data, GNUNET_REST_JSON_IS_PUBLIC_ENTRY); + if (NULL != cache) + { + if (json_is_integer(cache)) + { + rest_json_data->is_public = json_integer_value(cache); + } + } + *output_data = rest_json_data; + return GNUNET_OK; +} + + + +int +GNUNET_REST_JSON_free (struct GNUNET_REST_JSON_Data* rest_json_data) +{ + if (rest_json_data != NULL) + { + GNUNET_free_non_null(rest_json_data->expiration_time); + GNUNET_free_non_null(rest_json_data->name); + GNUNET_free_non_null(rest_json_data->new_name); + GNUNET_free_non_null(rest_json_data->nickname); + GNUNET_free_non_null(rest_json_data->pubkey); + GNUNET_free_non_null(rest_json_data->subsystem); + GNUNET_free_non_null(rest_json_data->type); + GNUNET_free_non_null(rest_json_data->value); + GNUNET_free_non_null(rest_json_data->zone); + } + GNUNET_free_non_null(rest_json_data); + return GNUNET_OK; +} + + + + + + + + + diff --git a/src/namestore/plugin_rest_namestore.c b/src/namestore/plugin_rest_namestore.c index ec44046e0..ab490c04f 100644 --- a/src/namestore/plugin_rest_namestore.c +++ b/src/namestore/plugin_rest_namestore.c @@ -2,24 +2,26 @@ This file is part of GNUnet. 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 Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - or (at your option) any later version. + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ /** * @author Martin Schanzenbach + * @author Philippe Buschmann * @file namestore/plugin_rest_namestore.c * @brief GNUnet Namestore REST plugin - * */ #include "platform.h" @@ -28,38 +30,32 @@ #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 "gnunet_json_lib.h" #include "microhttpd.h" #include -#define GNUNET_REST_API_NS_NAMESTORE "/names" - -#define GNUNET_REST_API_NS_NAMESTORE_ZKEY "/names/zkey" - -#define GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO "record" - -#define GNUNET_REST_JSONAPI_NAMESTORE_NAME "name" - -#define GNUNET_REST_JSONAPI_NAMESTORE_REVINFO "revinfo" +#define GNUNET_REST_API_NS_NAMESTORE "/namestore" -#define GNUNET_REST_JSONAPI_NAMESTORE_RECORD GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO +#define GNUNET_REST_SUBSYSTEM_NAMESTORE "namestore" -#define GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE "record_type" +#define GNUNET_REST_JSON_NAMESTORE_RECORD_TYPE "record_type" +#define GNUNET_REST_JSON_NAMESTORE_VALUE "value" +#define GNUNET_REST_JSON_NAMESTORE_EXPIRATION "expiration" +#define GNUNET_REST_JSON_NAMESTORE_EXPIRED "expired" -#define GNUNET_REST_JSONAPI_NAMESTORE_VALUE "value" +#define GNUNET_REST_NAMESTORE_RD_COUNT 1 -#define GNUNET_REST_JSONAPI_NAMESTORE_PUBLIC "public" +//TODO define other variables -#define GNUNET_REST_JSONAPI_NAMESTORE_SHADOW "shadow" - -#define GNUNET_REST_JSONAPI_NAMESTORE_PKEY "pkey" - -#define GNUNET_REST_JSONAPI_NAMESTORE_ZKEY "zkey" - -#define GNUNET_REST_JSONAPI_NAMESTORE_EXPIRATION "expiration" +/** + * The configuration handle + */ +const struct GNUNET_CONFIGURATION_Handle *cfg; -#define GNUNET_REST_JSONAPI_NAMESTORE_EGO "ego" +/** + * HTTP methods allows for this plugin + */ +static char* allow_methods; /** * @brief struct returned by the initialization function of the plugin @@ -69,54 +65,53 @@ struct Plugin const struct GNUNET_CONFIGURATION_Handle *cfg; }; +//TODO add specific structs /** - * HTTP methods allows for this plugin + * The default namestore ego */ -static char* allow_methods; - -const struct GNUNET_CONFIGURATION_Handle *cfg; - -struct RecordEntry +struct EgoEntry { /** - * DLL + * Ego Identifier */ - struct RecordEntry *next; + const char *identifier; /** - * DLL + * Public key string */ - struct RecordEntry *prev; + char *keystring; + /** + * The Ego + */ + struct GNUNET_IDENTITY_Ego *ego; }; + struct RequestHandle { - /** - * Ego list - */ - struct RecordEntry *record_head; + //TODO add specific entries /** - * Ego list + * Records to store */ - struct record_entry *record_tail; + struct GNUNET_GNSRECORD_Data *rd; /** - * JSON response object + * NAMESTORE Operation */ - struct GNUNET_JSONAPI_Document *resp_object; + struct GNUNET_NAMESTORE_QueueEntry *add_qe; /** - * Rest connection + * JSON data parser */ - struct GNUNET_REST_RequestHandle *rest_handle; + struct GNUNET_REST_JSON_Data *json_data; /** - * Handle to GNS service. + * Response object */ - struct GNUNET_IDENTITY_Handle *identity_handle; + json_t *resp_object; /** * Handle to NAMESTORE @@ -134,70 +129,25 @@ struct RequestHandle struct GNUNET_CRYPTO_EcdsaPrivateKey zone_pkey; /** - * Handle to identity lookup - */ - struct GNUNET_IDENTITY_EgoLookup *ego_lookup; - - /** - * Default Ego operation - */ - struct GNUNET_IDENTITY_Operation *get_default; - - /** - * Name of the ego - */ - char *ego_name; - - /** - * Record is public - */ - int is_public; - - /** - * Shadow record - */ - int is_shadow; - - /** - * Name of the record to modify - */ - char *name; - - /** - * Value of the record - */ - char *value; - - /** - * Zkey string - */ - const char* zkey_str; - - /** - * record type + * IDENTITY Operation */ - uint32_t type; - - /** - * Records to store - */ - struct GNUNET_GNSRECORD_Data *rd; + struct EgoEntry *ego_entry; /** - * record count + * IDENTITY Operation */ - unsigned int rd_count; + struct GNUNET_IDENTITY_Operation *op; /** - * NAMESTORE Operation + * Handle to Identity service. */ - struct GNUNET_NAMESTORE_QueueEntry *add_qe; + struct GNUNET_IDENTITY_Handle *identity_handle; /** - * NAMESTORE Operation + * Rest connection */ - struct GNUNET_NAMESTORE_QueueEntry *reverse_qe; - + struct GNUNET_REST_RequestHandle *rest_handle; + /** * Desired timeout for the lookup (default is no timeout). */ @@ -206,7 +156,7 @@ struct RequestHandle /** * 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 @@ -224,75 +174,122 @@ struct RequestHandle char *url; /** - * Cfg + * Error response message */ - const struct GNUNET_CONFIGURATION_Handle *cfg; + char *emsg; /** - * HTTP response code + * Reponse code */ int response_code; }; +//TODO add specific cleanup /** * Cleanup lookup handle - * * @param handle Handle to clean up */ static void cleanup_handle (struct RequestHandle *handle) { - struct RecordEntry *record_entry; - struct RecordEntry *record_tmp; + size_t index; + json_t *json_ego; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n"); - if (NULL != handle->resp_object) - GNUNET_JSONAPI_document_delete (handle->resp_object); - if (NULL != handle->name) - GNUNET_free (handle->name); if (NULL != handle->timeout_task) + { GNUNET_SCHEDULER_cancel (handle->timeout_task); - if (NULL != handle->ego_lookup) - GNUNET_IDENTITY_ego_lookup_cancel (handle->ego_lookup); - if (NULL != handle->get_default) - GNUNET_IDENTITY_cancel (handle->get_default); + handle->timeout_task = NULL; + } + if (NULL != handle->url) + GNUNET_free(handle->url); + if (NULL != handle->emsg) + GNUNET_free(handle->emsg); + if (NULL != handle->rd) + { + if (NULL != handle->rd->data) + GNUNET_free((void*)handle->rd->data); + GNUNET_free(handle->rd); + } + if (NULL != handle->timeout_task) + GNUNET_SCHEDULER_cancel(handle->timeout_task); if (NULL != handle->list_it) - GNUNET_NAMESTORE_zone_iteration_stop (handle->list_it); + GNUNET_NAMESTORE_zone_iteration_stop(handle->list_it); if (NULL != handle->add_qe) - GNUNET_NAMESTORE_cancel (handle->add_qe); + GNUNET_NAMESTORE_cancel(handle->add_qe); if (NULL != handle->identity_handle) - GNUNET_IDENTITY_disconnect (handle->identity_handle); + GNUNET_IDENTITY_disconnect(handle->identity_handle); if (NULL != handle->ns_handle) - GNUNET_NAMESTORE_disconnect (handle->ns_handle); - if (NULL != handle->url) - GNUNET_free (handle->url); - if (NULL != handle->value) - GNUNET_free (handle->value); - if (NULL != handle->rd) { - for (unsigned int i = 0; i < handle->rd_count; i++) - { - if (NULL != handle->rd[i].data) - GNUNET_free ((void*)handle->rd[i].data); - } - GNUNET_free (handle->rd); + GNUNET_NAMESTORE_disconnect(handle->ns_handle); } - if (NULL != handle->ego_name) - GNUNET_free (handle->ego_name); - for (record_entry = handle->record_head; - NULL != record_entry;) + + if (NULL != handle->ego_entry) { - record_tmp = record_entry; - record_entry = record_entry->next; - GNUNET_free (record_tmp); + if (NULL != handle->ego_entry->keystring) + GNUNET_free(handle->ego_entry->keystring); + + GNUNET_free(handle->ego_entry); + } + + if(NULL != handle->resp_object) + { + json_array_foreach(handle->resp_object, index, json_ego ) + { + json_decref (json_ego); + } + json_decref(handle->resp_object); } + + if (NULL != handle->json_data) + GNUNET_REST_JSON_free(handle->json_data); + GNUNET_free (handle); } +/** + * Task run on errors. Reports an error and cleans up everything. + * + * @param cls the `struct RequestHandle` + */ +static void +do_error (void *cls) +{ + struct RequestHandle *handle = cls; + struct MHD_Response *resp; + char *json_error; + + if (NULL == handle->emsg) + handle->emsg = GNUNET_strdup("Unknown Error"); + + GNUNET_asprintf (&json_error, "{\"error\": \"%s\"}", handle->emsg); + + if (0 == handle->response_code) + handle->response_code = MHD_HTTP_OK; + + resp = GNUNET_REST_create_response (json_error); + handle->proc (handle->proc_cls, resp, handle->response_code); + cleanup_handle (handle); + GNUNET_free(json_error); +} + +/** + * Does internal server error when iteration failed. + */ +static void +namestore_iteration_error (void *cls) +{ + struct RequestHandle *handle = cls; + struct MHD_Response *resp = GNUNET_REST_create_response (NULL); + handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; + handle->proc (handle->proc_cls, resp, handle->response_code); + cleanup_handle (handle); +} + /** * Create json representation of a GNSRECORD * @@ -313,19 +310,19 @@ gnsrecord_to_json (const struct GNUNET_GNSRECORD_Data *rd) if (NULL == string_val) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Record of type %d malformed, skipping\n", (int) rd->record_type); return NULL; } record_obj = json_object(); json_object_set_new (record_obj, - GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE, + GNUNET_REST_JSON_NAMESTORE_RECORD_TYPE, json_string (typename)); json_object_set_new (record_obj, - GNUNET_REST_JSONAPI_NAMESTORE_VALUE, + GNUNET_REST_JSON_NAMESTORE_VALUE, json_string (string_val)); - GNUNET_free (string_val); + //GNUNET_free (string_val); if (GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION & rd->flags) { @@ -339,52 +336,33 @@ gnsrecord_to_json (const struct GNUNET_GNSRECORD_Data *rd) time_abs.abs_value_us = rd->expiration_time; exp_str = GNUNET_STRINGS_absolute_time_to_string (time_abs); } - json_object_set_new (record_obj, GNUNET_REST_JSONAPI_NAMESTORE_EXPIRATION, json_string (exp_str)); - + json_object_set_new (record_obj, + GNUNET_REST_JSON_NAMESTORE_EXPIRATION, + json_string (exp_str)); json_object_set_new (record_obj, "expired", json_boolean (GNUNET_YES == GNUNET_GNSRECORD_is_expired (rd))); return record_obj; } -/** - * Task run on error. Generates error response and cleans up. - * - * @param cls the request to generate an error response for - */ -static void -do_error (void *cls) -{ - struct RequestHandle *handle = cls; - 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) +create_finished (void *cls, int32_t success, const char *emsg) { struct RequestHandle *handle = cls; + struct MHD_Response *resp; - handle->timeout_task = NULL; - do_error (handle); -} - - -static void -cleanup_handle_delayed (void *cls) -{ - cleanup_handle (cls); + handle->add_qe = NULL; + if (GNUNET_YES != success) + { + handle->emsg = GNUNET_strdup("Error storing records"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + resp = GNUNET_REST_create_response (NULL); + handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT); + cleanup_handle(handle); } - /** * Iteration over all results finished, build final * response. @@ -395,29 +373,25 @@ static void namestore_list_finished (void *cls) { struct RequestHandle *handle = cls; - char *result; + char *result_str; struct MHD_Response *resp; handle->list_it = NULL; - if (NULL == handle->resp_object) - handle->resp_object = GNUNET_JSONAPI_document_new (); - if (GNUNET_SYSERR == - GNUNET_JSONAPI_document_serialize (handle->resp_object, - &result)) + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "HEY\n"); + if (NULL == handle->resp_object) { - handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; - GNUNET_SCHEDULER_add_now (&do_error, - handle); + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "OH\n"); + GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - resp = GNUNET_REST_create_response (result); - handle->proc (handle->proc_cls, - resp, - MHD_HTTP_OK); - GNUNET_free_non_null (result); - GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, - handle); + + result_str = json_dumps (handle->resp_object, 0); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); + resp = GNUNET_REST_create_response (result_str); + handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); + GNUNET_free_non_null (result_str); + cleanup_handle(handle); } @@ -428,84 +402,172 @@ namestore_list_finished (void *cls) * @param handle the RequestHandle */ static void -namestore_list_response (void *cls, +namestore_list_iteration (void *cls, const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, const char *rname, unsigned int rd_len, const struct GNUNET_GNSRECORD_Data *rd) { struct RequestHandle *handle = cls; - struct GNUNET_JSONAPI_Resource *json_resource; - json_t *result_array; json_t *record_obj; if (NULL == handle->resp_object) - handle->resp_object = GNUNET_JSONAPI_document_new (); + handle->resp_object = json_array(); - if ( (NULL != handle->name) && - (0 != strcmp (handle->name, + char *result_str = json_dumps (handle->resp_object, 0); + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "%s\n", result_str); + GNUNET_free(result_str); + /*if ( (NULL != handle->ego_entry->identifier) && + (0 != strcmp (handle->ego_entry->identifier, rname)) ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "%s does not match %s\n", - rname, - handle->name); - GNUNET_NAMESTORE_zone_iterator_next (handle->list_it, - 1); + "%s does not match %s\n", rname, + handle->ego_entry->identifier); + GNUNET_NAMESTORE_zone_iterator_next (handle->list_it, 1); return; - } + }*/ - result_array = json_array (); - for (unsigned int i=0; itype) && - (GNUNET_GNSRECORD_TYPE_ANY != handle->type) ) - continue; record_obj = gnsrecord_to_json (&rd[i]); - json_array_append (result_array, + + if(NULL == record_obj) + continue; + + json_array_append (handle->resp_object, record_obj); json_decref (record_obj); } - if (0 < json_array_size(result_array)) + GNUNET_NAMESTORE_zone_iterator_next (handle->list_it, 1); +} + + +/** + * Handle namestore GET request + * + * @param con_handle the connection handle + * @param url the url + * @param cls the RequestHandle + */ +void +namestore_get (struct GNUNET_REST_RequestHandle *con_handle, + const char* url, + void *cls) +{ + struct RequestHandle *handle = cls; + if (strlen (GNUNET_REST_API_NS_NAMESTORE) != strlen (handle->url)) { - json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO, - rname); - GNUNET_JSONAPI_resource_add_attr (json_resource, - GNUNET_REST_JSONAPI_NAMESTORE_RECORD, - result_array); - GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource); + handle->emsg = GNUNET_strdup("Wrong URL"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; } - - json_decref (result_array); - GNUNET_NAMESTORE_zone_iterator_next (handle->list_it, - 1); + handle->list_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle, + &handle->zone_pkey, + &namestore_iteration_error, + handle, + &namestore_list_iteration, + handle, + &namestore_list_finished, + handle); } +int +check_needed_data(struct RequestHandle *handle){ + if(NULL == handle->json_data->name) + { + handle->emsg = GNUNET_strdup("Missing JSON parameter: name"); + return GNUNET_SYSERR; + } + + if(NULL == handle->json_data->type) + { + handle->emsg = GNUNET_strdup("Missing JSON parameter: type"); + return GNUNET_SYSERR; + } -static void -create_finished (void *cls, int32_t success, const char *emsg) + if(NULL == handle->json_data->value) + { + handle->emsg = GNUNET_strdup("Missing JSON parameter: value"); + return GNUNET_SYSERR; + } + + if(NULL == handle->json_data->expiration_time) + { + handle->emsg = GNUNET_strdup("Missing JSON parameter: expiration time"); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + +//TODO filter input +static int +json_to_gnsrecord (struct RequestHandle *handle) { - struct RequestHandle *handle = cls; - struct MHD_Response *resp; + struct GNUNET_TIME_Relative etime_rel; + struct GNUNET_TIME_Absolute etime_abs; + void *rdata; + size_t rdata_size; - handle->add_qe = NULL; - if (GNUNET_YES != success) + handle->rd = GNUNET_new_array(GNUNET_REST_NAMESTORE_RD_COUNT, + struct GNUNET_GNSRECORD_Data); + memset (handle->rd, 0, sizeof(struct GNUNET_GNSRECORD_Data)); + handle->rd->record_type = GNUNET_GNSRECORD_typename_to_number ( + handle->json_data->type); + if (UINT32_MAX == (*handle->rd).record_type) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Error storing records%s%s\n", - (NULL == emsg) ? "" : ": ", - (NULL == emsg) ? "" : emsg); - GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); - return; + handle->emsg = GNUNET_strdup("Unsupported type"); + return GNUNET_SYSERR; } - 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 (GNUNET_OK + != GNUNET_GNSRECORD_string_to_value ((*handle->rd).record_type, + handle->json_data->value, &rdata, + &rdata_size)) + { + handle->emsg = GNUNET_strdup("Value invalid for record type"); + return GNUNET_SYSERR; + } + (*handle->rd).data = rdata; + (*handle->rd).data_size = rdata_size; + //TODO other flags + if (0 == handle->json_data->is_public) + { + handle->rd->flags |= GNUNET_GNSRECORD_RF_PRIVATE; + } + /**TODO + * if (1 == handle->is_shadow) + rde->flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD; + if (1 != handle->is_public) + rde->flags |= GNUNET_GNSRECORD_RF_PRIVATE; + */ + if (0 == strcmp (handle->json_data->expiration_time, "never")) + { + (*handle->rd).expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; + } + else if (GNUNET_OK + == GNUNET_STRINGS_fancy_time_to_relative ( + handle->json_data->expiration_time, &etime_rel)) + { + (*handle->rd).expiration_time = etime_rel.rel_value_us; + (*handle->rd).flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; + } + else if (GNUNET_OK + == GNUNET_STRINGS_fancy_time_to_absolute ( + handle->json_data->expiration_time, &etime_abs)) + { + (*handle->rd).expiration_time = etime_abs.abs_value_us; + } + else + { + handle->emsg = GNUNET_strdup("Value invalid for record type"); + return GNUNET_SYSERR; + } + return GNUNET_OK; } @@ -529,7 +591,7 @@ create_new_record_cont (void *cls, struct RequestHandle *handle = cls; handle->add_qe = NULL; - if (0 != strcmp (rec_name, handle->name)) + if (0 != strcmp (rec_name, handle->json_data->name)) { GNUNET_break (0); do_error (handle); @@ -541,426 +603,99 @@ create_new_record_cont (void *cls, handle->proc (handle->proc_cls, GNUNET_REST_create_response (NULL), MHD_HTTP_CONFLICT); - GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); + cleanup_handle(handle); return; } - - GNUNET_assert (NULL != handle->name); handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle, &handle->zone_pkey, - handle->name, - handle->rd_count, + handle->json_data->name, + GNUNET_REST_NAMESTORE_RD_COUNT, handle->rd, &create_finished, handle); } -static void -del_finished (void *cls, - int32_t success, - const char *emsg) -{ - struct RequestHandle *handle = cls; - - handle->add_qe = NULL; - if (GNUNET_NO == success) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Deleting record failed, record does not exist%s%s\n"), - (NULL != emsg) ? ": " : "", - (NULL != emsg) ? emsg : ""); - GNUNET_SCHEDULER_add_now (&do_error, handle); //do_not_found TODO - return; - } - if (GNUNET_SYSERR == success) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Deleting record failed%s%s\n"), - (NULL != emsg) ? ": " : "", - (NULL != emsg) ? emsg : ""); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - handle->proc (handle->proc_cls, - GNUNET_REST_create_response (NULL), - MHD_HTTP_NO_CONTENT); - GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); -} - - -static void -del_cont (void *cls, - const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, - const char *label, - unsigned int rd_count, - const struct GNUNET_GNSRECORD_Data *rd) -{ - struct RequestHandle *handle = cls; - - handle->add_qe = NULL; - if (0 == rd_count) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("There are no records under label `%s' that could be deleted.\n"), - label); - do_error (handle); - return; - } - - handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle, - &handle->zone_pkey, - handle->name, - 0, NULL, - &del_finished, - handle); -} - - -static void -namestore_delete_cont (struct GNUNET_REST_RequestHandle *con, - const char *url, - void *cls) -{ - struct RequestHandle *handle = cls; - - if (NULL == handle->name) - { - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - - handle->add_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle, - &handle->zone_pkey, - handle->name, - &do_error, - handle, - &del_cont, - handle); -} - - -static int -json_to_gnsrecord (const json_t *records_json, - struct GNUNET_GNSRECORD_Data **rd, - unsigned int *rd_count) -{ - struct GNUNET_TIME_Relative etime_rel; - struct GNUNET_TIME_Absolute etime_abs; - char *value; - void *rdata; - size_t rdata_size; - const char *typestring; - const char *expirationstring; - json_t *type_json; - json_t *value_json; - json_t *record_json; - json_t *exp_json; - - *rd_count = json_array_size (records_json); - *rd = GNUNET_new_array (*rd_count, - struct GNUNET_GNSRECORD_Data); - for (unsigned int i = 0; i < *rd_count; i++) - { - memset (&(*rd)[i], - 0, - sizeof (struct GNUNET_GNSRECORD_Data)); - record_json = json_array_get (records_json, - i); - type_json = json_object_get (record_json, - GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE); - if (! json_is_string (type_json)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Type property is no string\n"); - return GNUNET_SYSERR; - } - typestring = json_string_value (type_json); - (*rd)[i].record_type = GNUNET_GNSRECORD_typename_to_number (typestring); - if (UINT32_MAX == (*rd)[i].record_type) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unsupported type `%s'\n"), - json_string_value (type_json)); - return GNUNET_SYSERR; - } - value_json = json_object_get (record_json, - GNUNET_REST_JSONAPI_NAMESTORE_VALUE); - if (! json_is_string (value_json)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Value property is no string\n"); - return GNUNET_SYSERR; - } - value = GNUNET_strdup (json_string_value (value_json)); - if (GNUNET_OK != - GNUNET_GNSRECORD_string_to_value ((*rd)[i].record_type, - value, - &rdata, - &rdata_size)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Value `%s' invalid for record type `%s'\n"), - value, - typestring); - return GNUNET_SYSERR; - } - (*rd)[i].data = rdata; - (*rd)[i].data_size = rdata_size; - /**TODO - * if (1 == handle->is_shadow) - rde->flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD; - if (1 != handle->is_public) - rde->flags |= GNUNET_GNSRECORD_RF_PRIVATE; - */ - exp_json = json_object_get (record_json, - GNUNET_REST_JSONAPI_NAMESTORE_EXPIRATION); - if (! json_is_string (exp_json)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Expiration property is no string\n"); - return GNUNET_SYSERR; - } - expirationstring = json_string_value (exp_json); - if (0 == strcmp (expirationstring, "never")) - { - (*rd)[i].expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; - } - else if (GNUNET_OK == - GNUNET_STRINGS_fancy_time_to_relative (expirationstring, - &etime_rel)) - { - (*rd)[i].expiration_time = etime_rel.rel_value_us; - (*rd)[i].flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; - } - else if (GNUNET_OK == - GNUNET_STRINGS_fancy_time_to_absolute (expirationstring, - &etime_abs)) - { - (*rd)[i].expiration_time = etime_abs.abs_value_us; - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Value `%s' invalid for record type `%s'\n"), - value, - typestring); - return GNUNET_SYSERR; - } - } - return GNUNET_OK; -} - - -static void -namestore_create_cont (struct GNUNET_REST_RequestHandle *con, - const char *url, - void *cls) +/** + * Handle namestore POST request + * + * @param con_handle the connection handle + * @param url the url + * @param cls the RequestHandle + */ +void +namestore_add (struct GNUNET_REST_RequestHandle *con_handle, + const char* url, + void *cls) { struct RequestHandle *handle = cls; - struct MHD_Response *resp; - struct GNUNET_JSONAPI_Document *json_obj; - struct GNUNET_JSONAPI_Resource *json_res; - json_t *records_json; 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() - }; + char term_data[handle->rest_handle->data_size + 1]; if (strlen (GNUNET_REST_API_NS_NAMESTORE) != strlen (handle->url)) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Cannot create under %s\n", handle->url); + handle->emsg = GNUNET_strdup("Wrong URL"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } if (0 >= handle->rest_handle->data_size) { + handle->emsg = GNUNET_strdup("No data"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } term_data[handle->rest_handle->data_size] = '\0'; - GNUNET_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, - "Unable to parse JSONAPI Object from %s\n", - term_data); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - 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_JSONAPI_document_resource_count (json_obj)); - GNUNET_JSONAPI_document_delete (json_obj); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - 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_memcpy(term_data, handle->rest_handle->data, + handle->rest_handle->data_size); + data_js = json_loads (term_data, JSON_DECODE_ANY, &err); + GNUNET_REST_JSON_parse(&handle->json_data, data_js); + if(NULL == handle->json_data) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unsupported JSON data type\n"); - 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; - } - 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_JSONAPI_document_delete (json_obj); + handle->emsg = GNUNET_strdup("Wrong data"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - if (GNUNET_SYSERR == json_to_gnsrecord (records_json, &handle->rd, &handle->rd_count)) + if(GNUNET_SYSERR == check_needed_data(handle)) { - GNUNET_JSONAPI_document_delete (json_obj); + json_decref (data_js); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - GNUNET_JSONAPI_document_delete (json_obj); - + json_decref (data_js); + json_to_gnsrecord (handle); handle->add_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle, - &handle->zone_pkey, - handle->name, - &do_error, - handle, - &create_new_record_cont, - handle); -} - - -static void -namestore_zkey_response (void *cls, - const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, - const char *label, - unsigned int rd_count, - const struct GNUNET_GNSRECORD_Data *rd) -{ - struct RequestHandle *handle = cls; - struct MHD_Response *resp; - 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_JSONAPI_document_new (); - if (NULL != label) - { - name_json = json_string (label); - 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_JSONAPI_document_serialize (json_obj, &result)) - { - GNUNET_JSONAPI_document_delete (json_obj); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - resp = GNUNET_REST_create_response (result); - handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); - GNUNET_JSONAPI_document_delete (json_obj); - GNUNET_free (result); - GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); -} - - -static void -namestore_zkey_cont (struct GNUNET_REST_RequestHandle *con, - const char *url, - void *cls) -{ - struct RequestHandle *handle = cls; - struct GNUNET_HashCode key; - struct GNUNET_CRYPTO_EcdsaPublicKey pubkey; - - GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_NAMESTORE_ZKEY, - strlen (GNUNET_REST_JSONAPI_NAMESTORE_ZKEY), - &key); - if ( GNUNET_NO == - GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, - &key) ) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "No zkey given %s\n", handle->url); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - handle->zkey_str = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, - &key); - if ((NULL == handle->zkey_str) || - (GNUNET_OK != - GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->zkey_str, - strlen (handle->zkey_str), - &pubkey))) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Zkey invalid %s\n", handle->zkey_str); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - handle->reverse_qe = GNUNET_NAMESTORE_zone_to_name (handle->ns_handle, - &handle->zone_pkey, - &pubkey, - &do_error, - handle, - &namestore_zkey_response, - handle); + &handle->zone_pkey, + handle->json_data->name, + &do_error, + handle, + &create_new_record_cont, + handle); } -static void -namestore_info_cont (struct GNUNET_REST_RequestHandle *con, - const char *url, - void *cls) +/** + * Handle namestore DELETE request + * + * @param con_handle the connection handle + * @param url the url + * @param cls the RequestHandle + */ +void +namestore_delete (struct GNUNET_REST_RequestHandle *con_handle, + const char* url, + void *cls) { struct RequestHandle *handle = cls; - - handle->list_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle, - &handle->zone_pkey, - &do_error, - handle, - &namestore_list_response, - handle, - &namestore_list_finished, - handle); + + //TODO add behaviour and response + + handle->emsg = GNUNET_strdup ("Not implemented yet"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; } -static char* -get_name_from_url (const char* url) -{ - if (strlen (url) <= strlen (GNUNET_REST_API_NS_NAMESTORE)) - return NULL; - return (char*)url + strlen (GNUNET_REST_API_NS_NAMESTORE) + 1; -} /** * Respond to OPTIONS request @@ -977,77 +712,48 @@ options_cont (struct GNUNET_REST_RequestHandle *con_handle, struct MHD_Response *resp; struct RequestHandle *handle = cls; - //For now, independent of path return all options + //independent of path return all options resp = GNUNET_REST_create_response (NULL); MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods); handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); cleanup_handle (handle); + return; } /** - * Callback invoked from identity service with ego information. - * An @a ego of NULL means the ego was not found. + * Handle rest request * - * @param cls closure with the configuration - * @param ego an ego known to identity service, or NULL + * @param handle the request handle */ static void -identity_cb (void *cls, - const struct GNUNET_IDENTITY_Ego *ego) +init_cont (struct RequestHandle *handle) { - struct RequestHandle *handle = cls; - struct MHD_Response *resp; + //TODO specify parameter of init_cont if necessary 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 - // {MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_NAMESTORE, &namestore_edit_cont}, //update. TODO this shoul be PATCH - {MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_NAMESTORE, &namestore_delete_cont}, //delete + {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE, &namestore_get}, + {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE, &namestore_add}, + {MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_NAMESTORE, &namestore_delete}, {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_NAMESTORE, &options_cont}, GNUNET_REST_HANDLER_END }; - handle->ego_lookup = NULL; - if (NULL == ego) - { - if (NULL != handle->ego_name) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Ego `%s' not known to identity service\n"), - handle->ego_name); - } - resp = GNUNET_REST_create_response (NULL); - handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND); - cleanup_handle (handle); - return; - } - handle->zone_pkey = *GNUNET_IDENTITY_ego_get_private_key (ego); - handle->ns_handle = GNUNET_NAMESTORE_connect (cfg); - if (NULL == handle->ns_handle) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Failed to connect to namestore\n")); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - - if (GNUNET_OK != - GNUNET_JSONAPI_handle_request (handle->rest_handle, - handlers, - &err, - handle)) + if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle, + handlers, + &err, + handle)) { handle->response_code = err.error_code; - GNUNET_SCHEDULER_add_now (&do_error, - (void *) handle); + GNUNET_SCHEDULER_add_now (&do_error, handle); } } - +/** + * + */ static void default_ego_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego, @@ -1055,23 +761,31 @@ default_ego_cb (void *cls, const char *name) { struct RequestHandle *handle = cls; - struct MHD_Response *resp; - handle->get_default = NULL; + struct EgoEntry *ego_entry; + struct GNUNET_CRYPTO_EcdsaPublicKey pk; + + handle->op = NULL; + if (NULL == ego) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("No default ego configured in identity service\n")); - resp = GNUNET_REST_create_response (NULL); - handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND); - cleanup_handle (handle); + handle->emsg = GNUNET_strdup ("No default ego configured in identity service"); + GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - else - { - identity_cb (cls, ego); - } + ego_entry = GNUNET_new(struct EgoEntry); + GNUNET_IDENTITY_ego_get_public_key (ego, &pk); + ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); + ego_entry->identifier = name; + ego_entry->ego = ego; + handle->ego_entry = ego_entry; + handle->zone_pkey = *GNUNET_IDENTITY_ego_get_private_key (ego); + init_cont (handle); } + +/** + * Connect to identity callback + */ static void id_connect_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego, @@ -1081,9 +795,10 @@ id_connect_cb (void *cls, struct RequestHandle *handle = cls; if (NULL == ego) { - handle->get_default = GNUNET_IDENTITY_get (handle->identity_handle, - "namestore", - &default_ego_cb, handle); + handle->op = GNUNET_IDENTITY_get (handle->identity_handle, + GNUNET_REST_SUBSYSTEM_NAMESTORE, + &default_ego_cb, + handle); } } @@ -1097,81 +812,37 @@ id_connect_cb (void *cls, * @param data_size length of the body * @param proc callback function for the result * @param proc_cls closure for callback function - * @return #GNUNET_OK if request accepted + * @return GNUNET_OK if request accepted */ static void -rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle, +rest_process_request(struct GNUNET_REST_RequestHandle *rest_handle, GNUNET_REST_ResultProcessor proc, void *proc_cls) { struct RequestHandle *handle = GNUNET_new (struct RequestHandle); - struct MHD_Response *resp; - struct GNUNET_HashCode key; - char *ego; - char *name; - char *type; - + + handle->response_code = 0; handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; handle->proc_cls = proc_cls; handle->proc = proc; 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, - "Connecting...\n"); - handle->cfg = cfg; - ego = NULL; - GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_NAMESTORE_EGO, - strlen (GNUNET_REST_JSONAPI_NAMESTORE_EGO), - &key); - if ( GNUNET_YES == - GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, - &key) ) - { - ego = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, - &key); - } + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n"); - handle->type = GNUNET_GNSRECORD_TYPE_ANY; - 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->rest_handle->url_param_map, - &key) ) - { - type = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, - &key); - if (NULL != type) - handle->type = GNUNET_GNSRECORD_typename_to_number (type); - } - name = get_name_from_url (handle->url); - if (NULL != ego) - handle->ego_name = GNUNET_strdup (ego); - if (NULL != 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_response (NULL); - handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND); - cleanup_handle (handle); - } - return; - } - handle->ego_lookup = GNUNET_IDENTITY_ego_lookup (cfg, - handle->ego_name, - &identity_cb, - handle); - handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout, - &do_timeout, - handle); + handle->identity_handle = GNUNET_IDENTITY_connect (cfg, &id_connect_cb, handle); + handle->ns_handle = GNUNET_NAMESTORE_connect (cfg); + handle->timeout_task = + GNUNET_SCHEDULER_add_delayed (handle->timeout, + &do_error, + handle); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n"); } + /** * Entry point for the plugin. * @@ -1182,9 +853,9 @@ void * libgnunet_plugin_rest_namestore_init (void *cls) { static struct Plugin plugin; - cfg = cls; struct GNUNET_REST_Plugin *api; + cfg = cls; if (NULL != plugin.cfg) return NULL; /* can only initialize once! */ memset (&plugin, 0, sizeof (struct Plugin)); @@ -1192,7 +863,7 @@ libgnunet_plugin_rest_namestore_init (void *cls) api = GNUNET_new (struct GNUNET_REST_Plugin); api->cls = &plugin; api->name = GNUNET_REST_API_NS_NAMESTORE; - api->process_request = &rest_identity_process_request; + api->process_request = &rest_process_request; GNUNET_asprintf (&allow_methods, "%s, %s, %s, %s, %s", MHD_HTTP_METHOD_GET, @@ -1200,7 +871,8 @@ libgnunet_plugin_rest_namestore_init (void *cls) MHD_HTTP_METHOD_PUT, MHD_HTTP_METHOD_DELETE, MHD_HTTP_METHOD_OPTIONS); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Namestore REST API initialized\n")); return api; } @@ -1217,13 +889,14 @@ libgnunet_plugin_rest_namestore_done (void *cls) { struct GNUNET_REST_Plugin *api = cls; struct Plugin *plugin = api->cls; - plugin->cfg = NULL; - GNUNET_free (api); + GNUNET_free_non_null (allow_methods); + GNUNET_free (api); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Namestore REST plugin is finished\n"); return NULL; } /* end of plugin_rest_namestore.c */ + diff --git a/src/namestore/plugin_rest_namestore2.c b/src/namestore/plugin_rest_namestore2.c new file mode 100644 index 000000000..ec44046e0 --- /dev/null +++ b/src/namestore/plugin_rest_namestore2.c @@ -0,0 +1,1229 @@ +/* + This file is part of GNUnet. + 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 Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + */ +/** + * @author Martin Schanzenbach + * @file namestore/plugin_rest_namestore.c + * @brief GNUnet Namestore REST plugin + * + */ + +#include "platform.h" +#include "gnunet_rest_plugin.h" +#include "gnunet_gns_service.h" +#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 + +#define GNUNET_REST_API_NS_NAMESTORE "/names" + +#define GNUNET_REST_API_NS_NAMESTORE_ZKEY "/names/zkey" + +#define GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO "record" + +#define GNUNET_REST_JSONAPI_NAMESTORE_NAME "name" + +#define GNUNET_REST_JSONAPI_NAMESTORE_REVINFO "revinfo" + +#define GNUNET_REST_JSONAPI_NAMESTORE_RECORD GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO + +#define GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE "record_type" + +#define GNUNET_REST_JSONAPI_NAMESTORE_VALUE "value" + +#define GNUNET_REST_JSONAPI_NAMESTORE_PUBLIC "public" + +#define GNUNET_REST_JSONAPI_NAMESTORE_SHADOW "shadow" + +#define GNUNET_REST_JSONAPI_NAMESTORE_PKEY "pkey" + +#define GNUNET_REST_JSONAPI_NAMESTORE_ZKEY "zkey" + +#define GNUNET_REST_JSONAPI_NAMESTORE_EXPIRATION "expiration" + +#define GNUNET_REST_JSONAPI_NAMESTORE_EGO "ego" + +/** + * @brief struct returned by the initialization function of the plugin + */ +struct Plugin +{ + const struct GNUNET_CONFIGURATION_Handle *cfg; +}; + + +/** + * HTTP methods allows for this plugin + */ +static char* allow_methods; + +const struct GNUNET_CONFIGURATION_Handle *cfg; + +struct RecordEntry +{ + /** + * DLL + */ + struct RecordEntry *next; + + /** + * DLL + */ + struct RecordEntry *prev; + +}; + +struct RequestHandle +{ + /** + * Ego list + */ + struct RecordEntry *record_head; + + /** + * Ego list + */ + struct record_entry *record_tail; + + /** + * JSON response object + */ + struct GNUNET_JSONAPI_Document *resp_object; + + /** + * Rest connection + */ + struct GNUNET_REST_RequestHandle *rest_handle; + + /** + * Handle to GNS service. + */ + struct GNUNET_IDENTITY_Handle *identity_handle; + + /** + * Handle to NAMESTORE + */ + struct GNUNET_NAMESTORE_Handle *ns_handle; + + /** + * Handle to NAMESTORE it + */ + struct GNUNET_NAMESTORE_ZoneIterator *list_it; + + /** + * Private key for the zone + */ + struct GNUNET_CRYPTO_EcdsaPrivateKey zone_pkey; + + /** + * Handle to identity lookup + */ + struct GNUNET_IDENTITY_EgoLookup *ego_lookup; + + /** + * Default Ego operation + */ + struct GNUNET_IDENTITY_Operation *get_default; + + /** + * Name of the ego + */ + char *ego_name; + + /** + * Record is public + */ + int is_public; + + /** + * Shadow record + */ + int is_shadow; + + /** + * Name of the record to modify + */ + char *name; + + /** + * Value of the record + */ + char *value; + + /** + * Zkey string + */ + const char* zkey_str; + + /** + * record type + */ + uint32_t type; + + /** + * Records to store + */ + struct GNUNET_GNSRECORD_Data *rd; + + /** + * record count + */ + unsigned int rd_count; + + /** + * NAMESTORE Operation + */ + struct GNUNET_NAMESTORE_QueueEntry *add_qe; + + /** + * NAMESTORE Operation + */ + struct GNUNET_NAMESTORE_QueueEntry *reverse_qe; + + /** + * Desired timeout for the lookup (default is no timeout). + */ + struct GNUNET_TIME_Relative timeout; + + /** + * ID of a task associated with the resolution process. + */ + struct GNUNET_SCHEDULER_Task * timeout_task; + + /** + * The plugin result processor + */ + GNUNET_REST_ResultProcessor proc; + + /** + * The closure of the result processor + */ + void *proc_cls; + + /** + * The url + */ + char *url; + + /** + * Cfg + */ + const struct GNUNET_CONFIGURATION_Handle *cfg; + + /** + * HTTP response code + */ + int response_code; + +}; + + +/** + * Cleanup lookup handle + * + * @param handle Handle to clean up + */ +static void +cleanup_handle (struct RequestHandle *handle) +{ + struct RecordEntry *record_entry; + struct RecordEntry *record_tmp; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Cleaning up\n"); + if (NULL != handle->resp_object) + GNUNET_JSONAPI_document_delete (handle->resp_object); + if (NULL != handle->name) + GNUNET_free (handle->name); + if (NULL != handle->timeout_task) + GNUNET_SCHEDULER_cancel (handle->timeout_task); + if (NULL != handle->ego_lookup) + GNUNET_IDENTITY_ego_lookup_cancel (handle->ego_lookup); + if (NULL != handle->get_default) + GNUNET_IDENTITY_cancel (handle->get_default); + if (NULL != handle->list_it) + GNUNET_NAMESTORE_zone_iteration_stop (handle->list_it); + if (NULL != handle->add_qe) + GNUNET_NAMESTORE_cancel (handle->add_qe); + if (NULL != handle->identity_handle) + GNUNET_IDENTITY_disconnect (handle->identity_handle); + if (NULL != handle->ns_handle) + GNUNET_NAMESTORE_disconnect (handle->ns_handle); + if (NULL != handle->url) + GNUNET_free (handle->url); + if (NULL != handle->value) + GNUNET_free (handle->value); + if (NULL != handle->rd) + { + for (unsigned int i = 0; i < handle->rd_count; i++) + { + if (NULL != handle->rd[i].data) + GNUNET_free ((void*)handle->rd[i].data); + } + GNUNET_free (handle->rd); + } + if (NULL != handle->ego_name) + GNUNET_free (handle->ego_name); + for (record_entry = handle->record_head; + NULL != record_entry;) + { + record_tmp = record_entry; + record_entry = record_entry->next; + GNUNET_free (record_tmp); + } + GNUNET_free (handle); +} + + +/** + * Create json representation of a GNSRECORD + * + * @param rd the GNSRECORD_Data + */ +static json_t * +gnsrecord_to_json (const struct GNUNET_GNSRECORD_Data *rd) +{ + const char *typename; + char *string_val; + const char *exp_str; + json_t *record_obj; + + typename = GNUNET_GNSRECORD_number_to_typename (rd->record_type); + string_val = GNUNET_GNSRECORD_value_to_string (rd->record_type, + rd->data, + rd->data_size); + + if (NULL == string_val) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Record of type %d malformed, skipping\n", + (int) rd->record_type); + return NULL; + } + record_obj = json_object(); + json_object_set_new (record_obj, + GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE, + json_string (typename)); + json_object_set_new (record_obj, + GNUNET_REST_JSONAPI_NAMESTORE_VALUE, + json_string (string_val)); + GNUNET_free (string_val); + + if (GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION & rd->flags) + { + struct GNUNET_TIME_Relative time_rel; + time_rel.rel_value_us = rd->expiration_time; + exp_str = GNUNET_STRINGS_relative_time_to_string (time_rel, 1); + } + else + { + struct GNUNET_TIME_Absolute time_abs; + time_abs.abs_value_us = rd->expiration_time; + exp_str = GNUNET_STRINGS_absolute_time_to_string (time_abs); + } + json_object_set_new (record_obj, GNUNET_REST_JSONAPI_NAMESTORE_EXPIRATION, json_string (exp_str)); + + json_object_set_new (record_obj, "expired", + json_boolean (GNUNET_YES == GNUNET_GNSRECORD_is_expired (rd))); + return record_obj; +} + + +/** + * Task run on error. Generates error response and cleans up. + * + * @param cls the request to generate an error response for + */ +static void +do_error (void *cls) +{ + struct RequestHandle *handle = cls; + 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) +{ + cleanup_handle (cls); +} + + +/** + * Iteration over all results finished, build final + * response. + * + * @param cls the `struct RequestHandle` + */ +static void +namestore_list_finished (void *cls) +{ + struct RequestHandle *handle = cls; + char *result; + struct MHD_Response *resp; + + handle->list_it = NULL; + if (NULL == handle->resp_object) + handle->resp_object = GNUNET_JSONAPI_document_new (); + + if (GNUNET_SYSERR == + GNUNET_JSONAPI_document_serialize (handle->resp_object, + &result)) + { + handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; + GNUNET_SCHEDULER_add_now (&do_error, + handle); + return; + } + resp = GNUNET_REST_create_response (result); + handle->proc (handle->proc_cls, + resp, + MHD_HTTP_OK); + GNUNET_free_non_null (result); + GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, + handle); +} + + + +/** + * Create a response with requested records + * + * @param handle the RequestHandle + */ +static void +namestore_list_response (void *cls, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, + const char *rname, + unsigned int rd_len, + const struct GNUNET_GNSRECORD_Data *rd) +{ + struct RequestHandle *handle = cls; + struct GNUNET_JSONAPI_Resource *json_resource; + json_t *result_array; + json_t *record_obj; + + if (NULL == handle->resp_object) + handle->resp_object = GNUNET_JSONAPI_document_new (); + + if ( (NULL != handle->name) && + (0 != strcmp (handle->name, + rname)) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "%s does not match %s\n", + rname, + handle->name); + GNUNET_NAMESTORE_zone_iterator_next (handle->list_it, + 1); + return; + } + + result_array = json_array (); + for (unsigned int i=0; itype) && + (GNUNET_GNSRECORD_TYPE_ANY != handle->type) ) + continue; + record_obj = gnsrecord_to_json (&rd[i]); + json_array_append (result_array, + record_obj); + json_decref (record_obj); + } + + if (0 < json_array_size(result_array)) + { + json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO, + rname); + GNUNET_JSONAPI_resource_add_attr (json_resource, + GNUNET_REST_JSONAPI_NAMESTORE_RECORD, + result_array); + GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource); + } + + json_decref (result_array); + GNUNET_NAMESTORE_zone_iterator_next (handle->list_it, + 1); +} + + +static void +create_finished (void *cls, int32_t success, const char *emsg) +{ + struct RequestHandle *handle = cls; + struct MHD_Response *resp; + + handle->add_qe = NULL; + if (GNUNET_YES != success) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Error storing records%s%s\n", + (NULL == emsg) ? "" : ": ", + (NULL == emsg) ? "" : emsg); + GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); + return; + } + resp = GNUNET_REST_create_response (NULL); + handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT); + GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); +} + + +/** + * We're storing a new record; this requires + * that no record already exists + * + * @param cls closure, unused + * @param zone_key private key of the zone + * @param rec_name name that is being mapped (at most 255 characters long) + * @param rd_count number of entries in @a rd array + * @param rd array of records with data to store + */ +static void +create_new_record_cont (void *cls, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, + const char *rec_name, + unsigned int rd_count, + const struct GNUNET_GNSRECORD_Data *rd) +{ + struct RequestHandle *handle = cls; + + handle->add_qe = NULL; + if (0 != strcmp (rec_name, handle->name)) + { + GNUNET_break (0); + do_error (handle); + return; + } + + if (0 != rd_count) + { + handle->proc (handle->proc_cls, + GNUNET_REST_create_response (NULL), + MHD_HTTP_CONFLICT); + GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); + return; + } + + GNUNET_assert (NULL != handle->name); + handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle, + &handle->zone_pkey, + handle->name, + handle->rd_count, + handle->rd, + &create_finished, + handle); +} + + +static void +del_finished (void *cls, + int32_t success, + const char *emsg) +{ + struct RequestHandle *handle = cls; + + handle->add_qe = NULL; + if (GNUNET_NO == success) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Deleting record failed, record does not exist%s%s\n"), + (NULL != emsg) ? ": " : "", + (NULL != emsg) ? emsg : ""); + GNUNET_SCHEDULER_add_now (&do_error, handle); //do_not_found TODO + return; + } + if (GNUNET_SYSERR == success) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Deleting record failed%s%s\n"), + (NULL != emsg) ? ": " : "", + (NULL != emsg) ? emsg : ""); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + handle->proc (handle->proc_cls, + GNUNET_REST_create_response (NULL), + MHD_HTTP_NO_CONTENT); + GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); +} + + +static void +del_cont (void *cls, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, + const char *label, + unsigned int rd_count, + const struct GNUNET_GNSRECORD_Data *rd) +{ + struct RequestHandle *handle = cls; + + handle->add_qe = NULL; + if (0 == rd_count) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("There are no records under label `%s' that could be deleted.\n"), + label); + do_error (handle); + return; + } + + handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle, + &handle->zone_pkey, + handle->name, + 0, NULL, + &del_finished, + handle); +} + + +static void +namestore_delete_cont (struct GNUNET_REST_RequestHandle *con, + const char *url, + void *cls) +{ + struct RequestHandle *handle = cls; + + if (NULL == handle->name) + { + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + + handle->add_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle, + &handle->zone_pkey, + handle->name, + &do_error, + handle, + &del_cont, + handle); +} + + +static int +json_to_gnsrecord (const json_t *records_json, + struct GNUNET_GNSRECORD_Data **rd, + unsigned int *rd_count) +{ + struct GNUNET_TIME_Relative etime_rel; + struct GNUNET_TIME_Absolute etime_abs; + char *value; + void *rdata; + size_t rdata_size; + const char *typestring; + const char *expirationstring; + json_t *type_json; + json_t *value_json; + json_t *record_json; + json_t *exp_json; + + *rd_count = json_array_size (records_json); + *rd = GNUNET_new_array (*rd_count, + struct GNUNET_GNSRECORD_Data); + for (unsigned int i = 0; i < *rd_count; i++) + { + memset (&(*rd)[i], + 0, + sizeof (struct GNUNET_GNSRECORD_Data)); + record_json = json_array_get (records_json, + i); + type_json = json_object_get (record_json, + GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE); + if (! json_is_string (type_json)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Type property is no string\n"); + return GNUNET_SYSERR; + } + typestring = json_string_value (type_json); + (*rd)[i].record_type = GNUNET_GNSRECORD_typename_to_number (typestring); + if (UINT32_MAX == (*rd)[i].record_type) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unsupported type `%s'\n"), + json_string_value (type_json)); + return GNUNET_SYSERR; + } + value_json = json_object_get (record_json, + GNUNET_REST_JSONAPI_NAMESTORE_VALUE); + if (! json_is_string (value_json)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Value property is no string\n"); + return GNUNET_SYSERR; + } + value = GNUNET_strdup (json_string_value (value_json)); + if (GNUNET_OK != + GNUNET_GNSRECORD_string_to_value ((*rd)[i].record_type, + value, + &rdata, + &rdata_size)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Value `%s' invalid for record type `%s'\n"), + value, + typestring); + return GNUNET_SYSERR; + } + (*rd)[i].data = rdata; + (*rd)[i].data_size = rdata_size; + /**TODO + * if (1 == handle->is_shadow) + rde->flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD; + if (1 != handle->is_public) + rde->flags |= GNUNET_GNSRECORD_RF_PRIVATE; + */ + exp_json = json_object_get (record_json, + GNUNET_REST_JSONAPI_NAMESTORE_EXPIRATION); + if (! json_is_string (exp_json)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Expiration property is no string\n"); + return GNUNET_SYSERR; + } + expirationstring = json_string_value (exp_json); + if (0 == strcmp (expirationstring, "never")) + { + (*rd)[i].expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; + } + else if (GNUNET_OK == + GNUNET_STRINGS_fancy_time_to_relative (expirationstring, + &etime_rel)) + { + (*rd)[i].expiration_time = etime_rel.rel_value_us; + (*rd)[i].flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; + } + else if (GNUNET_OK == + GNUNET_STRINGS_fancy_time_to_absolute (expirationstring, + &etime_abs)) + { + (*rd)[i].expiration_time = etime_abs.abs_value_us; + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Value `%s' invalid for record type `%s'\n"), + value, + typestring); + return GNUNET_SYSERR; + } + } + return GNUNET_OK; +} + + +static void +namestore_create_cont (struct GNUNET_REST_RequestHandle *con, + const char *url, + void *cls) +{ + struct RequestHandle *handle = cls; + struct MHD_Response *resp; + struct GNUNET_JSONAPI_Document *json_obj; + struct GNUNET_JSONAPI_Resource *json_res; + json_t *records_json; + 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, + "Cannot create under %s\n", handle->url); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + if (0 >= handle->rest_handle->data_size) + { + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + term_data[handle->rest_handle->data_size] = '\0'; + GNUNET_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, + "Unable to parse JSONAPI Object from %s\n", + term_data); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + 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_JSONAPI_document_resource_count (json_obj)); + GNUNET_JSONAPI_document_delete (json_obj); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + 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_JSONAPI_document_delete (json_obj); + resp = GNUNET_REST_create_response (NULL); + handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); + cleanup_handle (handle); + return; + } + 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_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_JSONAPI_document_delete (json_obj); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + GNUNET_JSONAPI_document_delete (json_obj); + + handle->add_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle, + &handle->zone_pkey, + handle->name, + &do_error, + handle, + &create_new_record_cont, + handle); +} + + +static void +namestore_zkey_response (void *cls, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, + const char *label, + unsigned int rd_count, + const struct GNUNET_GNSRECORD_Data *rd) +{ + struct RequestHandle *handle = cls; + struct MHD_Response *resp; + 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_JSONAPI_document_new (); + if (NULL != label) + { + name_json = json_string (label); + 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_JSONAPI_document_serialize (json_obj, &result)) + { + GNUNET_JSONAPI_document_delete (json_obj); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + resp = GNUNET_REST_create_response (result); + handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); + GNUNET_JSONAPI_document_delete (json_obj); + GNUNET_free (result); + GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); +} + + +static void +namestore_zkey_cont (struct GNUNET_REST_RequestHandle *con, + const char *url, + void *cls) +{ + struct RequestHandle *handle = cls; + struct GNUNET_HashCode key; + struct GNUNET_CRYPTO_EcdsaPublicKey pubkey; + + GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_NAMESTORE_ZKEY, + strlen (GNUNET_REST_JSONAPI_NAMESTORE_ZKEY), + &key); + if ( GNUNET_NO == + GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, + &key) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "No zkey given %s\n", handle->url); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + handle->zkey_str = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, + &key); + if ((NULL == handle->zkey_str) || + (GNUNET_OK != + GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->zkey_str, + strlen (handle->zkey_str), + &pubkey))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Zkey invalid %s\n", handle->zkey_str); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + handle->reverse_qe = GNUNET_NAMESTORE_zone_to_name (handle->ns_handle, + &handle->zone_pkey, + &pubkey, + &do_error, + handle, + &namestore_zkey_response, + handle); +} + + +static void +namestore_info_cont (struct GNUNET_REST_RequestHandle *con, + const char *url, + void *cls) +{ + struct RequestHandle *handle = cls; + + handle->list_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle, + &handle->zone_pkey, + &do_error, + handle, + &namestore_list_response, + handle, + &namestore_list_finished, + handle); +} + + +static char* +get_name_from_url (const char* url) +{ + if (strlen (url) <= strlen (GNUNET_REST_API_NS_NAMESTORE)) + return NULL; + return (char*)url + strlen (GNUNET_REST_API_NS_NAMESTORE) + 1; +} + +/** + * Respond to OPTIONS request + * + * @param con_handle the connection handle + * @param url the url + * @param cls the RequestHandle + */ +static void +options_cont (struct GNUNET_REST_RequestHandle *con_handle, + const char* url, + void *cls) +{ + struct MHD_Response *resp; + struct RequestHandle *handle = cls; + + //For now, independent of path return all options + resp = GNUNET_REST_create_response (NULL); + MHD_add_response_header (resp, + "Access-Control-Allow-Methods", + allow_methods); + handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); + cleanup_handle (handle); +} + + +/** + * Callback invoked from identity service with ego information. + * An @a ego of NULL means the ego was not found. + * + * @param cls closure with the configuration + * @param ego an ego known to identity service, or NULL + */ +static void +identity_cb (void *cls, + const struct GNUNET_IDENTITY_Ego *ego) +{ + struct RequestHandle *handle = cls; + struct MHD_Response *resp; + 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 + // {MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_NAMESTORE, &namestore_edit_cont}, //update. TODO this shoul be PATCH + {MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_NAMESTORE, &namestore_delete_cont}, //delete + {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_NAMESTORE, &options_cont}, + GNUNET_REST_HANDLER_END + }; + + handle->ego_lookup = NULL; + if (NULL == ego) + { + if (NULL != handle->ego_name) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Ego `%s' not known to identity service\n"), + handle->ego_name); + } + resp = GNUNET_REST_create_response (NULL); + handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND); + cleanup_handle (handle); + return; + } + handle->zone_pkey = *GNUNET_IDENTITY_ego_get_private_key (ego); + handle->ns_handle = GNUNET_NAMESTORE_connect (cfg); + if (NULL == handle->ns_handle) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Failed to connect to namestore\n")); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + + 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); + } +} + + +static void +default_ego_cb (void *cls, + struct GNUNET_IDENTITY_Ego *ego, + void **ctx, + const char *name) +{ + struct RequestHandle *handle = cls; + struct MHD_Response *resp; + handle->get_default = NULL; + if (NULL == ego) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("No default ego configured in identity service\n")); + resp = GNUNET_REST_create_response (NULL); + handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND); + cleanup_handle (handle); + return; + } + else + { + identity_cb (cls, ego); + } +} + +static void +id_connect_cb (void *cls, + struct GNUNET_IDENTITY_Ego *ego, + void **ctx, + const char *name) +{ + struct RequestHandle *handle = cls; + if (NULL == ego) + { + handle->get_default = GNUNET_IDENTITY_get (handle->identity_handle, + "namestore", + &default_ego_cb, handle); + } +} + + +/** + * Function processing the REST call + * + * @param method HTTP method + * @param url URL of the HTTP request + * @param data body of the HTTP request (optional) + * @param data_size length of the body + * @param proc callback function for the result + * @param proc_cls closure for callback function + * @return #GNUNET_OK if request accepted + */ +static void +rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle, + GNUNET_REST_ResultProcessor proc, + void *proc_cls) +{ + struct RequestHandle *handle = GNUNET_new (struct RequestHandle); + struct MHD_Response *resp; + struct GNUNET_HashCode key; + char *ego; + char *name; + char *type; + + handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; + handle->proc_cls = proc_cls; + handle->proc = proc; + 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, + "Connecting...\n"); + handle->cfg = cfg; + ego = NULL; + GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_NAMESTORE_EGO, + strlen (GNUNET_REST_JSONAPI_NAMESTORE_EGO), + &key); + if ( GNUNET_YES == + GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, + &key) ) + { + ego = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, + &key); + } + + handle->type = GNUNET_GNSRECORD_TYPE_ANY; + 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->rest_handle->url_param_map, + &key) ) + { + type = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, + &key); + if (NULL != type) + handle->type = GNUNET_GNSRECORD_typename_to_number (type); + } + name = get_name_from_url (handle->url); + if (NULL != ego) + handle->ego_name = GNUNET_strdup (ego); + if (NULL != 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_response (NULL); + handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND); + cleanup_handle (handle); + } + return; + } + handle->ego_lookup = GNUNET_IDENTITY_ego_lookup (cfg, + handle->ego_name, + &identity_cb, + handle); + handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout, + &do_timeout, + handle); +} + +/** + * Entry point for the plugin. + * + * @param cls Config info + * @return NULL on error, otherwise the plugin context + */ +void * +libgnunet_plugin_rest_namestore_init (void *cls) +{ + static struct Plugin plugin; + cfg = cls; + struct GNUNET_REST_Plugin *api; + + if (NULL != plugin.cfg) + return NULL; /* can only initialize once! */ + memset (&plugin, 0, sizeof (struct Plugin)); + plugin.cfg = cfg; + api = GNUNET_new (struct GNUNET_REST_Plugin); + api->cls = &plugin; + api->name = GNUNET_REST_API_NS_NAMESTORE; + api->process_request = &rest_identity_process_request; + GNUNET_asprintf (&allow_methods, + "%s, %s, %s, %s, %s", + MHD_HTTP_METHOD_GET, + MHD_HTTP_METHOD_POST, + MHD_HTTP_METHOD_PUT, + MHD_HTTP_METHOD_DELETE, + MHD_HTTP_METHOD_OPTIONS); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _("Namestore REST API initialized\n")); + return api; +} + + +/** + * Exit point from the plugin. + * + * @param cls the plugin context (as returned by "init") + * @return always NULL + */ +void * +libgnunet_plugin_rest_namestore_done (void *cls) +{ + struct GNUNET_REST_Plugin *api = cls; + struct Plugin *plugin = api->cls; + + plugin->cfg = NULL; + GNUNET_free (api); + GNUNET_free_non_null (allow_methods); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Namestore REST plugin is finished\n"); + return NULL; +} + +/* end of plugin_rest_namestore.c */ -- cgit v1.2.3 From 9009fb0aa496cd72ff6f1ea3d20ac4a547055e1b Mon Sep 17 00:00:00 2001 From: Phil Date: Wed, 25 Jul 2018 16:59:08 +0200 Subject: -fix identity file --- src/identity/plugin_rest_identity.c | 59 +++---- src/identity/test_plugin_identity_rest.sh | 252 ------------------------------ 2 files changed, 30 insertions(+), 281 deletions(-) delete mode 100755 src/identity/test_plugin_identity_rest.sh (limited to 'src') diff --git a/src/identity/plugin_rest_identity.c b/src/identity/plugin_rest_identity.c index 8d525b950..f1d33b0f3 100644 --- a/src/identity/plugin_rest_identity.c +++ b/src/identity/plugin_rest_identity.c @@ -2,20 +2,18 @@ This file is part of GNUnet. 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 - by the Free Software Foundation; either version 3, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ /** * @author Martin Schanzenbach @@ -202,8 +200,9 @@ struct RequestHandle * @param handle Handle to clean up */ static void -cleanup_handle (struct RequestHandle *handle) +cleanup_handle (void *cls) { + struct RequestHandle *handle = cls; struct EgoEntry *ego_entry; struct EgoEntry *ego_tmp; @@ -248,20 +247,22 @@ do_error (void *cls) { struct RequestHandle *handle = cls; struct MHD_Response *resp; - char *json_error; + json_t *json_error = json_object(); + char *response; if (NULL == handle->emsg) handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_UNKNOWN); - GNUNET_asprintf (&json_error, "{\"error\": \"%s\"}", handle->emsg); + json_object_set_new(json_error,"error", json_string(handle->emsg)); if (0 == handle->response_code) handle->response_code = MHD_HTTP_OK; - - resp = GNUNET_REST_create_response (json_error); + response = json_dumps (json_error, 0); + resp = GNUNET_REST_create_response (response); handle->proc (handle->proc_cls, resp, handle->response_code); - cleanup_handle (handle); - GNUNET_free(json_error); + json_decref(json_error); + GNUNET_free(response); + GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); } /** @@ -306,7 +307,7 @@ ego_get_for_subsystem (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); GNUNET_free(result_str); GNUNET_free(public_key_string); - cleanup_handle (handle); + GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); } /** @@ -420,7 +421,7 @@ ego_get (struct GNUNET_REST_RequestHandle *con_handle, const char* url, json_decref (json_root); handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); GNUNET_free(result_str); - cleanup_handle (handle); + GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); } /** @@ -444,7 +445,7 @@ do_finished (void *cls, const char *emsg) } resp = GNUNET_REST_create_response (NULL); handle->proc (handle->proc_cls, resp, handle->response_code); - cleanup_handle (handle); + GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); } /** @@ -530,7 +531,7 @@ ego_edit (struct GNUNET_REST_RequestHandle *con_handle, const char* url, json_decref (data_js); resp = GNUNET_REST_create_response (NULL); handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND); - cleanup_handle (handle); + GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); return; } //This is a rename @@ -555,7 +556,7 @@ ego_edit (struct GNUNET_REST_RequestHandle *con_handle, const char* url, json_decref (data_js); resp = GNUNET_REST_create_response (NULL); handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); - cleanup_handle (handle); + GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); return; } } @@ -677,7 +678,7 @@ ego_create (struct GNUNET_REST_RequestHandle *con_handle, const char* url, json_decref (data_js); resp = GNUNET_REST_create_response (NULL); handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); - cleanup_handle (handle); + GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); return; } } @@ -732,7 +733,7 @@ ego_delete (struct GNUNET_REST_RequestHandle *con_handle, const char* url, { resp = GNUNET_REST_create_response (NULL); handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND); - cleanup_handle (handle); + GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); return; } handle->response_code = MHD_HTTP_NO_CONTENT; @@ -760,7 +761,7 @@ options_cont (struct GNUNET_REST_RequestHandle *con_handle, const char* url, resp = GNUNET_REST_create_response (NULL); MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods); handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); - cleanup_handle (handle); + GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); return; } diff --git a/src/identity/test_plugin_identity_rest.sh b/src/identity/test_plugin_identity_rest.sh deleted file mode 100755 index d43f4206b..000000000 --- a/src/identity/test_plugin_identity_rest.sh +++ /dev/null @@ -1,252 +0,0 @@ -#!/usr/bin/bash - -#First, start gnunet-arm and the rest-service. Make sure, no identity exists - -link_to_api="http://localhost:7776/identity" -wrong_link="http://localhost:7776/idenmmmy" - -#Test GET (multiple identities) for error when no identity exists - -echo "No test for subsystem available" -echo "The next test case can be ignored if you have already added identities" -cache="$(curl --silent "$link_to_api" | grep "error")" -if [ "" == "$cache" ] -then - echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for GET request when missing identity\n" -else - echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for GET request when missing identity\n" -fi - -#Test POST success code, error response code and error json -echo "The next test case can be ignored if you have already added an identity with the name Test" -cache="$(curl -v -X "POST" "$link_to_api" --data "{\"name\":\"Test\"}" 2>&1 | grep "HTTP/1.1 201")" -if [ "" == "$cache" ] -then - echo -n -e "[\033[0;31m FAILURE\033[0m ] Error for good POST request\n" -else - echo -n -e "[\033[0;32m SUCCESS\033[0m ] Success for good POST request\n" -fi - -cache="$(curl -v -X "POST" "$link_to_api" --data "{\"name\":\"Test\"}" 2>&1 | grep "HTTP/1.1 409")" -if [ "" == "$cache" ] -then - echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for duplicate name POST request\n" -else - echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for duplicate name POST request\n" -fi - -cache="$(curl -v -X "POST" "$link_to_api" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for no data POST request\n" -else - echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for no data POST request\n" -fi - -cache="$(curl -v -X "POST" "$link_to_api" --data "wrong" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong data POST request\n" -else - echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong data POST request\n" -fi - -cache="$(curl -v -X "POST" "$link_to_api" --data "[{}]" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for json array input POST request\n" -else - echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for json array input POST request\n" -fi - -cache="$(curl -v -X "POST" "$link_to_api" --data "{\"name\":\"Test\",\"other\":\"Test\"}" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for multi element json POST request\n" -else - echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for multi element json POST request\n" -fi - -cache="$(curl -v -X "POST" "$link_to_api" --data "{\"nam\":\"Test\"}" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong json POST request\n" -else - echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong json POST request\n" -fi - -cache="$(curl -v -X "POST" "$link_to_api" --data "{\"name\":123}" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong json type POST request\n" -else - echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong json type POST request\n" -fi - -cache="$(curl -v -X "POST" "$link_to_api" --data "{\"name\":""}" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for no name POST request\n" -else - echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for no name POST request\n" -fi - - -#Test GET (multiple identities) for success and error json -cache="$(curl --silent "$link_to_api" | grep "error")" -if [ "" == "$cache" ] -then - echo -n -e "[\033[0;32m SUCCESS\033[0m ] Success for good GET request (multiple identities)\n" -else - echo -n -e "[\033[0;31m FAILURE\033[0m ] Error for good GET request (multiple identities)\n" -fi - - -id="$(gnunet-identity -d | grep "Test - " | sed "s/Test - //g")" -#Test GET (one identity) for success and error json -cache="$(curl --silent "${link_to_api}/$id" | grep "error")" -if [ "" == "$cache" ] -then - echo -n -e "[\033[0;32m SUCCESS\033[0m ] Success for good GET request (one identity)\n" -else - echo -n -e "[\033[0;31m FAILURE\033[0m ] Error for good GET request (one identity)\n" -fi - - -#Test DELETE success code, error response code and error json -echo "Next tests for DELETE will probably fail when POST fails" -cache="$(curl -v -X "DELETE" "${link_to_api}/$id" 2>&1 | grep "HTTP/1.1 404")" -if [ "" == "$cache" ] -then - echo -n -e "[\033[0;32m SUCCESS\033[0m ] Success for good DELETE request\n" -else - echo -n -e "[\033[0;31m FAILURE\033[0m ] Error for good DELETE request\n" -fi - -curl --silent -X "POST" "$link_to_api" --data "{\"name\":\"Test\"}" -id="$(gnunet-identity -d | grep "Test - " | sed "s/Test - //g")" - -cache="$(curl -v -X "DELETE" "${link_to_api}/df1" 2>&1 | grep "HTTP/1.1 404")" -if [ "" == "$cache" ] -then - echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong DELETE request\n" -else - echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong DELETE request\n" -fi - -#Test PUT success code, error response codes and error json -cache="$(curl -v -X "PUT" "${link_to_api}/$id" --data "{\"newname\":\"NewTest\"}" 2>&1 | grep "HTTP/1.1 204")" -if [ "" == "$cache" ] -then - echo -n -e "[\033[0;31m FAILURE\033[0m ] Error for good PUT request\n" -else - echo -n -e "[\033[0;32m SUCCESS\033[0m ] Success for good PUT request\n" -fi - -cache="$(curl -v -X "PUT" "${link_to_api}/${id}1" --data "{\"newname\":\"NewNewTest\"}" 2>&1 | grep "HTTP/1.1 404")" -if [ "" == "$cache" ] -then - echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong identity PUT request\n" -else - echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong identity PUT request\n" -fi - -cache="$(curl -v -X "PUT" "$link_to_api/$id" --data "{\"newname\":\"NewTest\"}" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for duplicate name PUT request\n" -else - echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for duplicate name PUT request\n" -fi - -cache="$(curl -v -X "PUT" "$link_to_api/$id" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for no data PUT request\n" -else - echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for no data PUT request\n" -fi - -cache="$(curl -v -X "PUT" "$link_to_api/$id" --data "wrong" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong data PUT request\n" -else - echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong data PUT request\n" -fi - -cache="$(curl -v -X "PUT" "$link_to_api/$id" --data "[{}]" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for json array input PUT request\n" -else - echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for json array input PUT request\n" -fi - -cache="$(curl -v -X "PUT" "$link_to_api/$id" --data "{\"newname\":\"Test\",\"other\":\"Test\"}" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for multi element json PUT request\n" -else - echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for multi element json PUT request\n" -fi - -cache="$(curl -v -X "PUT" "$link_to_api/$id" --data "{\"newnam\":\"Test\"}" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong json PUT request\n" -else - echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong json PUT request\n" -fi - -cache="$(curl -v -X "PUT" "$link_to_api/$id" --data "{\"newname\":123}" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong json type PUT request\n" -else - echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong json type PUT request\n" -fi - -cache="$(curl -v -X "PUT" "$link_to_api/$id" --data "{\"newname\":""}" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for no name PUT request\n" -else - echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for no name PUT request\n" -fi -#TODO Missing subsystem test - -#Missing OPTIONS success - nothing can really go wrong here - -#Test wrong url -cache="$(curl -v "$wrong_link" 2>&1 | grep "HTTP/1.1 404")" -if [ "" == "$cache" ] -then - echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong url GET request \n" -else - echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong url GET request \n" -fi - -cache="$(curl -X "PUT" -v "$wrong_link/$id" --data "{\"newname\":\"Testing\"}" 2>&1 | grep "HTTP/1.1 404")" -if [ "" == "$cache" ] -then - echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong url GET request \n" -else - echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong url GET request \n" -fi - -cache="$(curl -X "POST" -v "$wrong_link/$id" --data "{\"name\":\"Test\"}" 2>&1 | grep "HTTP/1.1 404")" -if [ "" == "$cache" ] -then - echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong url POST request \n" -else - echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong url POST request \n" -fi - -cache="$(curl -X "DELETE" -v "${wrong_link}/$id" 2>&1 | grep "HTTP/1.1 404")" -if [ "" == "$cache" ] -then - echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong url DELETE request \n" -else - echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong url DELETE request \n" -fi -- cgit v1.2.3 From 4992eacc10bedaa0edfa03b401253408c6267798 Mon Sep 17 00:00:00 2001 From: Phil Date: Wed, 25 Jul 2018 17:43:37 +0200 Subject: added name search --- src/identity/plugin_rest_identity.c | 23 ++++++++++++++++++++--- src/identity/test_plugin_rest_identity.sh | 6 ++++++ 2 files changed, 26 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/identity/plugin_rest_identity.c b/src/identity/plugin_rest_identity.c index f1d33b0f3..59dad66c7 100644 --- a/src/identity/plugin_rest_identity.c +++ b/src/identity/plugin_rest_identity.c @@ -346,7 +346,8 @@ ego_get (struct GNUNET_REST_RequestHandle *con_handle, const char* url, handle->subsystem); handle->op = GNUNET_IDENTITY_get (handle->identity_handle, - handle->subsystem, &ego_get_for_subsystem, + handle->subsystem, + &ego_get_for_subsystem, handle); if (NULL == handle->op) { @@ -359,9 +360,10 @@ ego_get (struct GNUNET_REST_RequestHandle *con_handle, const char* url, egoname = NULL; keystring = NULL; - //if only one identity requested + //if only one identity requested with key GNUNET_CRYPTO_hash (GNUNET_REST_PARAM_PUBKEY, - strlen (GNUNET_REST_PARAM_PUBKEY), &key); + strlen (GNUNET_REST_PARAM_PUBKEY), + &key); if ( GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains ( handle->rest_handle->url_param_map, &key)) @@ -379,6 +381,21 @@ ego_get (struct GNUNET_REST_RequestHandle *con_handle, const char* url, } } + //if only one identity requested with name + if (NULL == egoname) + { + GNUNET_CRYPTO_hash (GNUNET_REST_PARAM_NAME, + strlen (GNUNET_REST_PARAM_NAME), + &key); + if ( GNUNET_YES + == GNUNET_CONTAINER_multihashmap_contains ( + handle->rest_handle->url_param_map, &key)) + { + egoname = GNUNET_CONTAINER_multihashmap_get ( + handle->rest_handle->url_param_map, &key); + } + } + json_root = json_array (); //Return ego/egos for (ego_entry = handle->ego_head; diff --git a/src/identity/test_plugin_rest_identity.sh b/src/identity/test_plugin_rest_identity.sh index b48becc45..170f3e928 100755 --- a/src/identity/test_plugin_rest_identity.sh +++ b/src/identity/test_plugin_rest_identity.sh @@ -84,6 +84,12 @@ fi id="$(gnunet-identity -d | grep "Test - " | sed "s/Test - //g")" #Test GET (one identity) for success and error json +cache="$(curl --silent "${link_to_api}?name=Test" | grep "error")" +if [ "" != "$cache" ] +then + exit 1 +fi +#Test GET (one identity) for success and error json cache="$(curl --silent "${link_to_api}?pubkey=$id" | grep "error")" if [ "" != "$cache" ] then -- cgit v1.2.3 From cc577a227d6a5ae8ef75e0fa91ef98ced2d2b743 Mon Sep 17 00:00:00 2001 From: Phil Date: Wed, 25 Jul 2018 21:57:49 +0200 Subject: -wip namestore api, changed adding gnsrecord --- src/gnsrecord/Makefile.am | 1 + src/gnsrecord/gnsrecord.c | 127 +++++++++++++++++++++++++ src/include/gnunet_gnsrecord_lib.h | 8 ++ src/include/gnunet_json_lib.h | 65 ------------- src/json/Makefile.am | 3 +- src/json/json_parser.c | 169 ---------------------------------- src/namestore/plugin_rest_namestore.c | 124 +++++++++++-------------- 7 files changed, 190 insertions(+), 307 deletions(-) delete mode 100644 src/json/json_parser.c (limited to 'src') diff --git a/src/gnsrecord/Makefile.am b/src/gnsrecord/Makefile.am index f840a31a4..47d83169f 100644 --- a/src/gnsrecord/Makefile.am +++ b/src/gnsrecord/Makefile.am @@ -39,6 +39,7 @@ libgnunetgnsrecord_la_SOURCES = \ gnsrecord_misc.c libgnunetgnsrecord_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ + -ljansson \ $(GN_LIBINTL) libgnunetgnsrecord_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ diff --git a/src/gnsrecord/gnsrecord.c b/src/gnsrecord/gnsrecord.c index da34846e7..30a0ffa83 100644 --- a/src/gnsrecord/gnsrecord.c +++ b/src/gnsrecord/gnsrecord.c @@ -28,7 +28,9 @@ #include "gnunet_constants.h" #include "gnunet_gnsrecord_lib.h" #include "gnunet_gnsrecord_plugin.h" +#include "gnunet_json_lib.h" #include "gnunet_tun_lib.h" +#include #define LOG(kind,...) GNUNET_log_from (kind, "gnsrecord",__VA_ARGS__) @@ -245,5 +247,130 @@ GNUNET_GNSRECORD_number_to_typename (uint32_t type) return NULL; } +/** + * Parse given JSON object to gns record + * + * @param cls closure, NULL + * @param root the json object representing data + * @param spec where to write the data + * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error + */ +static int +parse_gnsrecordobject (void *cls, + json_t *root, + struct GNUNET_JSON_Specification *spec) +{ + struct GNUNET_GNSRECORD_Data *gnsrecord_object; + struct GNUNET_TIME_Absolute abs_expiration_time; + int unpack_state=0; + const char *data; + const char *expiration_date; + const char *record_type; + const char *dummy_value; + int flag; + void *rdata; + size_t rdata_size; + + if(!json_is_object(root)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Error json is not array nor object!\n"); + return GNUNET_SYSERR; + } + //interpret single gns record + unpack_state = json_unpack(root, + "{s:s, s:s, s:s, s?:i, s:s!}", + "value", &data, + "type", &record_type, + "expiration_time", &expiration_date, + "flag", &flag, + "label", &dummy_value); + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, + "{value:%s, type:%s, expire:%s, flag:%i}", + data, + record_type, + expiration_date, + flag); + if (GNUNET_SYSERR == unpack_state) + { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, + "Error json object has a wrong format!\n"); + return GNUNET_SYSERR; + } + //TODO test + gnsrecord_object = GNUNET_new (struct GNUNET_GNSRECORD_Data); + gnsrecord_object->record_type = GNUNET_GNSRECORD_typename_to_number(record_type); + if (GNUNET_OK + != GNUNET_GNSRECORD_string_to_value (gnsrecord_object->record_type, + data, &rdata, + &rdata_size)) + { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR,"Value invalid for record type"); + return GNUNET_SYSERR; + } + gnsrecord_object->data = rdata; + gnsrecord_object->data_size = rdata_size; + + if (0 == strcmp (expiration_date, "never")) + { + gnsrecord_object->expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; + } + else if (GNUNET_OK + == GNUNET_STRINGS_fancy_time_to_absolute (expiration_date, + &abs_expiration_time)) + { + gnsrecord_object->expiration_time = abs_expiration_time.abs_value_us; + } + else + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Value invalid for record type"); + return GNUNET_SYSERR; + } + gnsrecord_object->flags = (enum GNUNET_GNSRECORD_Flags)flag; + *(struct GNUNET_GNSRECORD_Data **) spec->ptr = gnsrecord_object; + return GNUNET_OK; +} + +/** + * Cleanup data left from parsing RSA public key. + * + * @param cls closure, NULL + * @param[out] spec where to free the data + */ +static void +clean_gnsrecordobject (void *cls, struct GNUNET_JSON_Specification *spec) +{ + struct GNUNET_GNSRECORD_Data **gnsrecord_object; + gnsrecord_object = (struct GNUNET_GNSRECORD_Data **) spec->ptr; + if (NULL != *gnsrecord_object) + { + if (NULL != (*gnsrecord_object)->data) + GNUNET_free((char*)(*gnsrecord_object)->data); + GNUNET_free(*gnsrecord_object); + *gnsrecord_object = NULL; + } +} + +/** + * JSON Specification for GNS Records. + * + * @param gnsrecord_object struct of GNUNET_GNSRECORD_Data to fill + * @return JSON Specification + */ +struct GNUNET_JSON_Specification +GNUNET_JSON_spec_gnsrecord_data (struct GNUNET_GNSRECORD_Data **gnsrecord_object) +{ + struct GNUNET_JSON_Specification ret = { + .parser = &parse_gnsrecordobject, + .cleaner = &clean_gnsrecordobject, + .cls = NULL, + .field = NULL, + .ptr = gnsrecord_object, + .ptr_size = 0, + .size_ptr = NULL + }; + *gnsrecord_object = NULL; + return ret; +} /* end of gnsrecord.c */ diff --git a/src/include/gnunet_gnsrecord_lib.h b/src/include/gnunet_gnsrecord_lib.h index 20846238b..2eaa304de 100644 --- a/src/include/gnunet_gnsrecord_lib.h +++ b/src/include/gnunet_gnsrecord_lib.h @@ -447,6 +447,14 @@ GNUNET_GNSRECORD_records_deserialize (size_t len, unsigned int rd_count, struct GNUNET_GNSRECORD_Data *dest); +/** + * JSON Specification for GNS Records. + * + * @param gnsrecord_object struct of GNUNET_GNSRECORD_Data to fill + * @return JSON Specification + */ +struct GNUNET_JSON_Specification +GNUNET_JSON_spec_gnsrecord_data (struct GNUNET_GNSRECORD_Data **gnsrecord_object); /* ******* general APIs relating to blocks, records and labels ******** */ diff --git a/src/include/gnunet_json_lib.h b/src/include/gnunet_json_lib.h index 6340d1f41..4855f21b4 100644 --- a/src/include/gnunet_json_lib.h +++ b/src/include/gnunet_json_lib.h @@ -479,71 +479,6 @@ GNUNET_JSON_getopt (char shortName, const char *description, json_t **json); -/* ****************** GETOPT JSON parser ******************* */ - -struct GNUNET_REST_JSON_Data -{ - /** - * Public key of an identity - */ - char *pubkey; - - /** - * Name - */ - char *name; - - /** - * Nickname - */ - char *nickname; - - /** - * New name - */ - char *new_name; - - /** - * Name of subsystem - */ - char *subsystem; - - /** - * Should data be handled as public (GNUNET_YES or GNUNET_NO) - */ - int is_public; - - /** - * Expiration date of data - */ - char *expiration_time; - - /** - * Type of data - */ - char *type; - - /** - * Value of data - */ - char *value; - - /** - * Zone - */ - char *zone; -}; -/* - * Test - */ -int -GNUNET_REST_JSON_parse (struct GNUNET_REST_JSON_Data** rest_json_data, - json_t *json_data); - -int -GNUNET_REST_JSON_free (struct GNUNET_REST_JSON_Data* rest_json_data); - - #endif /* end of gnunet_json_lib.h */ diff --git a/src/json/Makefile.am b/src/json/Makefile.am index 5aac23654..16c0450d9 100644 --- a/src/json/Makefile.am +++ b/src/json/Makefile.am @@ -16,8 +16,7 @@ libgnunetjson_la_SOURCES = \ json.c \ json_mhd.c \ json_generator.c \ - json_helper.c \ - json_parser.c + json_helper.c libgnunetjson_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ -ljansson \ diff --git a/src/json/json_parser.c b/src/json/json_parser.c deleted file mode 100644 index cfe553b34..000000000 --- a/src/json/json_parser.c +++ /dev/null @@ -1,169 +0,0 @@ -/* - This file is part of GNUnet - Copyright (C) 2014, 2015, 2016 GNUnet e.V. - - GNUnet is free software: you can redistribute it and/or modify it - under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - or (at your option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ -/** - * @file json/json_helper.c - * @brief functions for REST JSON parsing - * @author Philippe Buschmann - */ - -#include "platform.h" -#include "gnunet_util_lib.h" -#include "gnunet_json_lib.h" - -#define GNUNET_REST_JSON_PUBKEY_ENTRY "pubkey" -#define GNUNET_REST_JSON_NAME_ENTRY "name" -#define GNUNET_REST_JSON_NICKNAME_ENTRY "nickname" -#define GNUNET_REST_JSON_NEWNAME_ENTRY "newname" -#define GNUNET_REST_JSON_SUBSYSTEM_ENTRY "subsystem" -#define GNUNET_REST_JSON_IS_PUBLIC_ENTRY "is_public" -#define GNUNET_REST_JSON_EXPIRATION_DATE_ENTRY "expiration_time" -#define GNUNET_REST_JSON_TYPE_ENTRY "type" -#define GNUNET_REST_JSON_VALUE_ENTRY "value" -#define GNUNET_REST_JSON_ZONE_ENTRY "zone" - - -int -GNUNET_REST_JSON_parse (struct GNUNET_REST_JSON_Data** output_data ,json_t *json_data) -{ - struct GNUNET_REST_JSON_Data *rest_json_data; - json_t *cache; - - rest_json_data = GNUNET_malloc(sizeof(struct GNUNET_REST_JSON_Data)); - - cache = json_object_get (json_data, GNUNET_REST_JSON_EXPIRATION_DATE_ENTRY); - rest_json_data->expiration_time = NULL; - if (NULL != cache) - { - if (json_is_string(cache)) - { - rest_json_data->expiration_time = GNUNET_strdup(json_string_value(cache)); - } - } - cache = json_object_get (json_data, GNUNET_REST_JSON_NAME_ENTRY); - rest_json_data->name = NULL; - if (NULL != cache) - { - if (json_is_string(cache)) - { - rest_json_data->name = GNUNET_strdup(json_string_value(cache)); - } - } - cache = json_object_get (json_data, GNUNET_REST_JSON_NEWNAME_ENTRY); - rest_json_data->new_name = NULL; - if (NULL != cache) - { - if (json_is_string(cache)) - { - rest_json_data->new_name = GNUNET_strdup(json_string_value(cache)); - } - } - cache = json_object_get (json_data, GNUNET_REST_JSON_NICKNAME_ENTRY); - rest_json_data->nickname = NULL; - if (NULL != cache) - { - if (json_is_string(cache)) - { - rest_json_data->nickname = GNUNET_strdup(json_string_value(cache)); - } - } - cache = json_object_get (json_data, GNUNET_REST_JSON_PUBKEY_ENTRY); - rest_json_data->pubkey = NULL; - if (NULL != cache) - { - if (json_is_string(cache)) - { - rest_json_data->pubkey = GNUNET_strdup(json_string_value(cache)); - } - } - cache = json_object_get (json_data, GNUNET_REST_JSON_SUBSYSTEM_ENTRY); - rest_json_data->subsystem = NULL; - if (NULL != cache) - { - if (json_is_string(cache)) - { - rest_json_data->subsystem = GNUNET_strdup(json_string_value(cache)); - } - } - cache = json_object_get (json_data, GNUNET_REST_JSON_TYPE_ENTRY); - rest_json_data->type = NULL; - if (NULL != cache) - { - if (json_is_string(cache)) - { - rest_json_data->type = GNUNET_strdup(json_string_value(cache)); - } - } - cache = json_object_get (json_data, GNUNET_REST_JSON_VALUE_ENTRY); - rest_json_data->value = NULL; - if (NULL != cache) - { - if (json_is_string(cache)) - { - rest_json_data->value = GNUNET_strdup(json_string_value(cache)); - } - } - cache = json_object_get (json_data, GNUNET_REST_JSON_ZONE_ENTRY); - rest_json_data->zone = NULL; - if (NULL != cache) - { - if (json_is_string(cache)) - { - rest_json_data->zone = GNUNET_strdup(json_string_value(cache)); - } - } - cache = json_object_get (json_data, GNUNET_REST_JSON_IS_PUBLIC_ENTRY); - if (NULL != cache) - { - if (json_is_integer(cache)) - { - rest_json_data->is_public = json_integer_value(cache); - } - } - *output_data = rest_json_data; - return GNUNET_OK; -} - - - -int -GNUNET_REST_JSON_free (struct GNUNET_REST_JSON_Data* rest_json_data) -{ - if (rest_json_data != NULL) - { - GNUNET_free_non_null(rest_json_data->expiration_time); - GNUNET_free_non_null(rest_json_data->name); - GNUNET_free_non_null(rest_json_data->new_name); - GNUNET_free_non_null(rest_json_data->nickname); - GNUNET_free_non_null(rest_json_data->pubkey); - GNUNET_free_non_null(rest_json_data->subsystem); - GNUNET_free_non_null(rest_json_data->type); - GNUNET_free_non_null(rest_json_data->value); - GNUNET_free_non_null(rest_json_data->zone); - } - GNUNET_free_non_null(rest_json_data); - return GNUNET_OK; -} - - - - - - - - - diff --git a/src/namestore/plugin_rest_namestore.c b/src/namestore/plugin_rest_namestore.c index ab490c04f..afe010b79 100644 --- a/src/namestore/plugin_rest_namestore.c +++ b/src/namestore/plugin_rest_namestore.c @@ -2,20 +2,18 @@ This file is part of GNUnet. 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 - by the Free Software Foundation; either version 3, or (at your - option) any later version. + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Affero General Public License for more details. - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ /** * @author Martin Schanzenbach @@ -42,6 +40,7 @@ #define GNUNET_REST_JSON_NAMESTORE_VALUE "value" #define GNUNET_REST_JSON_NAMESTORE_EXPIRATION "expiration" #define GNUNET_REST_JSON_NAMESTORE_EXPIRED "expired" +#define GNUNET_REST_ERROR_UNKNOWN "Unknown Error" #define GNUNET_REST_NAMESTORE_RD_COUNT 1 @@ -96,17 +95,17 @@ struct RequestHandle /** * Records to store */ - struct GNUNET_GNSRECORD_Data *rd; + char *label_name; /** - * NAMESTORE Operation + * Records to store */ - struct GNUNET_NAMESTORE_QueueEntry *add_qe; + struct GNUNET_GNSRECORD_Data *rd; /** - * JSON data parser + * NAMESTORE Operation */ - struct GNUNET_REST_JSON_Data *json_data; + struct GNUNET_NAMESTORE_QueueEntry *add_qe; /** * Response object @@ -192,8 +191,9 @@ struct RequestHandle * @param handle Handle to clean up */ static void -cleanup_handle (struct RequestHandle *handle) +cleanup_handle (void *cls) { + struct RequestHandle *handle = cls; size_t index; json_t *json_ego; @@ -204,6 +204,8 @@ cleanup_handle (struct RequestHandle *handle) GNUNET_SCHEDULER_cancel (handle->timeout_task); handle->timeout_task = NULL; } + if (NULL != handle->label_name) + GNUNET_free(handle->label_name); if (NULL != handle->url) GNUNET_free(handle->url); if (NULL != handle->emsg) @@ -243,9 +245,6 @@ cleanup_handle (struct RequestHandle *handle) } json_decref(handle->resp_object); } - - if (NULL != handle->json_data) - GNUNET_REST_JSON_free(handle->json_data); GNUNET_free (handle); } @@ -261,20 +260,22 @@ do_error (void *cls) { struct RequestHandle *handle = cls; struct MHD_Response *resp; - char *json_error; + json_t *json_error = json_object(); + char *response; if (NULL == handle->emsg) - handle->emsg = GNUNET_strdup("Unknown Error"); + handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_UNKNOWN); + + json_object_set_new(json_error,"error", json_string(handle->emsg)); - GNUNET_asprintf (&json_error, "{\"error\": \"%s\"}", handle->emsg); - if (0 == handle->response_code) handle->response_code = MHD_HTTP_OK; - - resp = GNUNET_REST_create_response (json_error); + response = json_dumps (json_error, 0); + resp = GNUNET_REST_create_response (response); handle->proc (handle->proc_cls, resp, handle->response_code); - cleanup_handle (handle); - GNUNET_free(json_error); + json_decref(json_error); + GNUNET_free(response); + GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); } /** @@ -287,7 +288,7 @@ namestore_iteration_error (void *cls) struct MHD_Response *resp = GNUNET_REST_create_response (NULL); handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; handle->proc (handle->proc_cls, resp, handle->response_code); - cleanup_handle (handle); + GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); } /** @@ -360,7 +361,7 @@ create_finished (void *cls, int32_t success, const char *emsg) } resp = GNUNET_REST_create_response (NULL); handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT); - cleanup_handle(handle); + GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); } /** @@ -391,7 +392,7 @@ namestore_list_finished (void *cls) resp = GNUNET_REST_create_response (result_str); handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); GNUNET_free_non_null (result_str); - cleanup_handle(handle); + GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); } @@ -476,34 +477,7 @@ namestore_get (struct GNUNET_REST_RequestHandle *con_handle, &namestore_list_finished, handle); } - -int -check_needed_data(struct RequestHandle *handle){ - if(NULL == handle->json_data->name) - { - handle->emsg = GNUNET_strdup("Missing JSON parameter: name"); - return GNUNET_SYSERR; - } - - if(NULL == handle->json_data->type) - { - handle->emsg = GNUNET_strdup("Missing JSON parameter: type"); - return GNUNET_SYSERR; - } - - if(NULL == handle->json_data->value) - { - handle->emsg = GNUNET_strdup("Missing JSON parameter: value"); - return GNUNET_SYSERR; - } - - if(NULL == handle->json_data->expiration_time) - { - handle->emsg = GNUNET_strdup("Missing JSON parameter: expiration time"); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} +/* //TODO filter input static int @@ -544,7 +518,7 @@ json_to_gnsrecord (struct RequestHandle *handle) rde->flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD; if (1 != handle->is_public) rde->flags |= GNUNET_GNSRECORD_RF_PRIVATE; - */ + * if (0 == strcmp (handle->json_data->expiration_time, "never")) { (*handle->rd).expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; @@ -569,7 +543,7 @@ json_to_gnsrecord (struct RequestHandle *handle) } return GNUNET_OK; } - +*/ /** * We're storing a new record; this requires @@ -590,8 +564,9 @@ create_new_record_cont (void *cls, { struct RequestHandle *handle = cls; + handle->add_qe = NULL; - if (0 != strcmp (rec_name, handle->json_data->name)) + if (0 != strcmp (rec_name, handle->label_name)) { GNUNET_break (0); do_error (handle); @@ -603,19 +578,18 @@ create_new_record_cont (void *cls, handle->proc (handle->proc_cls, GNUNET_REST_create_response (NULL), MHD_HTTP_CONFLICT); - cleanup_handle(handle); + GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); return; } handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle, &handle->zone_pkey, - handle->json_data->name, + handle->label_name, GNUNET_REST_NAMESTORE_RD_COUNT, handle->rd, &create_finished, handle); } - /** * Handle namestore POST request * @@ -629,9 +603,15 @@ namestore_add (struct GNUNET_REST_RequestHandle *con_handle, void *cls) { struct RequestHandle *handle = cls; + struct GNUNET_GNSRECORD_Data *gns_record; json_t *data_js; + json_t *name_json; json_error_t err; char term_data[handle->rest_handle->data_size + 1]; + struct GNUNET_JSON_Specification gnsspec[] = { + GNUNET_JSON_spec_gnsrecord_data(&gns_record), + GNUNET_JSON_spec_end () + }; if (strlen (GNUNET_REST_API_NS_NAMESTORE) != strlen (handle->url)) { @@ -649,24 +629,26 @@ namestore_add (struct GNUNET_REST_RequestHandle *con_handle, GNUNET_memcpy(term_data, handle->rest_handle->data, handle->rest_handle->data_size); data_js = json_loads (term_data, JSON_DECODE_ANY, &err); - GNUNET_REST_JSON_parse(&handle->json_data, data_js); - if(NULL == handle->json_data) + GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (data_js, gnsspec, NULL, NULL)); + name_json = json_object_get(data_js, "label"); + if (!json_is_string(name_json)) { - handle->emsg = GNUNET_strdup("Wrong data"); + handle->emsg = GNUNET_strdup("Missing name"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - if(GNUNET_SYSERR == check_needed_data(handle)) + handle->label_name = GNUNET_strdup(json_string_value(name_json)); + if(NULL == handle->label_name) { - json_decref (data_js); + handle->emsg = GNUNET_strdup("Missing name"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } json_decref (data_js); - json_to_gnsrecord (handle); + handle->rd = gns_record; handle->add_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle, &handle->zone_pkey, - handle->json_data->name, + handle->label_name, &do_error, handle, &create_new_record_cont, @@ -718,7 +700,7 @@ options_cont (struct GNUNET_REST_RequestHandle *con_handle, "Access-Control-Allow-Methods", allow_methods); handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); - cleanup_handle (handle); + GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); return; } -- cgit v1.2.3 From f7ca27a73e69a8c224d65768be3416ff1388c1d7 Mon Sep 17 00:00:00 2001 From: Phil Date: Thu, 26 Jul 2018 02:31:30 +0200 Subject: change namestore, json handling; fix identity, gns --- src/gns/plugin_rest_gns.c | 81 +-- src/gns/plugin_rest_gns2.c | 717 ------------------- src/gnsrecord/Makefile.am | 1 - src/gnsrecord/gnsrecord.c | 126 ---- src/identity/plugin_rest_identity.c | 4 +- src/include/gnunet_gnsrecord_lib.h | 8 - src/include/gnunet_json_lib.h | 22 + src/json/Makefile.am | 3 +- src/json/json_generator.c | 35 + src/json/json_gnsrecord.c | 163 +++++ src/namestore/plugin_rest_namestore.c | 225 ++---- src/namestore/plugin_rest_namestore2.c | 1229 -------------------------------- 12 files changed, 340 insertions(+), 2274 deletions(-) delete mode 100644 src/gns/plugin_rest_gns2.c create mode 100644 src/json/json_gnsrecord.c delete mode 100644 src/namestore/plugin_rest_namestore2.c (limited to 'src') diff --git a/src/gns/plugin_rest_gns.c b/src/gns/plugin_rest_gns.c index 22c908275..aae14153d 100644 --- a/src/gns/plugin_rest_gns.c +++ b/src/gns/plugin_rest_gns.c @@ -2,20 +2,18 @@ This file is part of GNUnet. 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 - by the Free Software Foundation; either version 3, or (at your - option) any later version. + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Affero General Public License for more details. - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - Boston, MA 02110-1301, USA. + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ /** * @author Philippe Buschmann @@ -36,6 +34,7 @@ #define GNUNET_REST_PARAMETER_GNS_NAME "name" #define GNUNET_REST_PARAMETER_GNS_RECORD_TYPE "record_type" +#define GNUNET_REST_GNS_ERROR_UNKNOWN "Unknown Error" /** * The configuration handle @@ -128,8 +127,9 @@ struct RequestHandle * @param handle Handle to clean up */ static void -cleanup_handle (struct RequestHandle *handle) +cleanup_handle (void *cls) { + struct RequestHandle *handle = cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n"); @@ -170,20 +170,22 @@ do_error (void *cls) { struct RequestHandle *handle = cls; struct MHD_Response *resp; - char *json_error; + json_t *json_error = json_object(); + char *response; if (NULL == handle->emsg) - handle->emsg = GNUNET_strdup("Unknown Error"); + handle->emsg = GNUNET_strdup(GNUNET_REST_GNS_ERROR_UNKNOWN); + + json_object_set_new(json_error,"error", json_string(handle->emsg)); - GNUNET_asprintf (&json_error, "{\"error\": \"%s\"}", handle->emsg); - if (0 == handle->response_code) handle->response_code = MHD_HTTP_OK; - - resp = GNUNET_REST_create_response (json_error); + response = json_dumps (json_error, 0); + resp = GNUNET_REST_create_response (response); handle->proc (handle->proc_cls, resp, handle->response_code); - cleanup_handle (handle); - GNUNET_free(json_error); + json_decref(json_error); + GNUNET_free(response); + GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); } @@ -201,6 +203,7 @@ handle_gns_response (void *cls, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd) { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "TEST4\n"); struct RequestHandle *handle = cls; struct MHD_Response *resp; json_t *result_array; @@ -216,12 +219,6 @@ handle_gns_response (void *cls, GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - if (0 == rd_count) - { - handle->emsg = GNUNET_strdup("No result found"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } result_array = json_array(); for (uint32_t i=0;iproc (handle->proc_cls, resp, MHD_HTTP_OK); GNUNET_free (result); json_decref (result_array); - cleanup_handle (handle); + GNUNET_SCHEDULER_add_now(&cleanup_handle, handle); } @@ -264,7 +261,8 @@ get_gns_cont (struct GNUNET_REST_RequestHandle *con_handle, { struct RequestHandle *handle = cls; struct GNUNET_HashCode key; - int conversion_state; + char *record_type; + char *name; GNUNET_CRYPTO_hash (GNUNET_REST_PARAMETER_GNS_NAME, strlen (GNUNET_REST_PARAMETER_GNS_NAME), @@ -277,8 +275,14 @@ get_gns_cont (struct GNUNET_REST_RequestHandle *con_handle, GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - handle->name = GNUNET_strdup( - GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map,&key)); + name = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map,&key); + if(0 >= strlen (name)) + { + handle->emsg = GNUNET_strdup("Length of parameter name is zero"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + handle->name = GNUNET_strdup(name); GNUNET_CRYPTO_hash (GNUNET_REST_PARAMETER_GNS_RECORD_TYPE, strlen (GNUNET_REST_PARAMETER_GNS_RECORD_TYPE), @@ -291,11 +295,13 @@ get_gns_cont (struct GNUNET_REST_RequestHandle *con_handle, GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - conversion_state = sscanf ( - GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, &key),"%u", - &(handle->record_type)); - if((EOF == conversion_state) || (0 == conversion_state)) + + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "TEST1\n"); + + record_type = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, &key); + handle->record_type = GNUNET_GNSRECORD_typename_to_number(record_type); + if(UINT32_MAX == handle->record_type) { handle->record_type = GNUNET_GNSRECORD_TYPE_ANY; } @@ -307,6 +313,7 @@ get_gns_cont (struct GNUNET_REST_RequestHandle *con_handle, GNUNET_SCHEDULER_add_now (&do_error, handle); return; } + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "TEST2\n"); handle->gns_lookup = GNUNET_GNS_lookup_with_tld (handle->gns, handle->name, @@ -314,13 +321,7 @@ get_gns_cont (struct GNUNET_REST_RequestHandle *con_handle, GNUNET_NO, &handle_gns_response, handle); - - if (NULL == handle->gns_lookup) - { - handle->emsg = GNUNET_strdup("GNS lookup failed"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } + return; } @@ -346,7 +347,7 @@ options_cont (struct GNUNET_REST_RequestHandle *con_handle, "Access-Control-Allow-Methods", allow_methods); handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); - cleanup_handle (handle); + GNUNET_SCHEDULER_add_now(&cleanup_handle, handle); return; } diff --git a/src/gns/plugin_rest_gns2.c b/src/gns/plugin_rest_gns2.c deleted file mode 100644 index 82d62744c..000000000 --- a/src/gns/plugin_rest_gns2.c +++ /dev/null @@ -1,717 +0,0 @@ -/* - This file is part of GNUnet. - 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 Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - or (at your option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ -/** - * @author Martin Schanzenbach - * @author Philippe Buschmann - * @file gns/plugin_rest_gns.c - * @brief GNUnet GNS REST plugin - * - */ - -#include "platform.h" -#include "gnunet_rest_plugin.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define GNUNET_REST_API_NS_GNS "/gns" - -#define GNUNET_REST_JSONAPI_GNS_RECORD_TYPE "record_type" - -#define GNUNET_REST_PARAMETER_GNS_NAME "name" - -#define GNUNET_REST_JSONAPI_GNS_TYPEINFO "gns_name" - -#define GNUNET_REST_JSONAPI_GNS_RECORD "records" - -#define GNUNET_REST_JSONAPI_GNS_EGO "ego" - -#define GNUNET_REST_JSONAPI_GNS_PKEY "pkey" - -#define GNUNET_REST_JSONAPI_GNS_OPTIONS "options" - -/** - * @brief struct returned by the initialization function of the plugin - */ -struct Plugin -{ - const struct GNUNET_CONFIGURATION_Handle *cfg; -}; - -const struct GNUNET_CONFIGURATION_Handle *cfg; - -struct LookupHandle -{ - /** - * Handle to GNS service. - */ - struct GNUNET_GNS_Handle *gns; - - /** - * Desired timeout for the lookup (default is no timeout). - */ - struct GNUNET_TIME_Relative timeout; - - /** - * Handle to lookup request - */ - struct GNUNET_GNS_LookupRequest *lookup_request; - - /** - * Handle to rest request - */ - struct GNUNET_REST_RequestHandle *rest_handle; - - /** - * Lookup an ego with the identity service. - */ - struct GNUNET_IDENTITY_EgoLookup *el; - - /** - * Handle for identity service. - */ - struct GNUNET_IDENTITY_Handle *identity; - - /** - * Active operation on identity service. - */ - struct GNUNET_IDENTITY_Operation *id_op; - - /** - * ID of a task associated with the resolution process. - */ - struct GNUNET_SCHEDULER_Task * timeout_task; - - /** - * The root of the received JSON or NULL - */ - json_t *json_root; - - /** - * The plugin result processor - */ - GNUNET_REST_ResultProcessor proc; - - /** - * The closure of the result processor - */ - void *proc_cls; - - /** - * The name to look up - */ - char *name; - - /** - * The ego to use - * In string representation from JSON - */ - const char *ego_str; - - /** - * The Pkey to use - * In string representation from JSON - */ - const char *pkey_str; - - /** - * The record type - */ - int type; - - /** - * The public key of to use for lookup - */ - struct GNUNET_CRYPTO_EcdsaPublicKey pkey; - - /** - * The public key to use for lookup - */ - struct GNUNET_CRYPTO_EcdsaPublicKey pkeym; - - /** - * The resolver options - */ - enum GNUNET_GNS_LocalOptions options; - - /** - * the shorten key - */ - struct GNUNET_CRYPTO_EcdsaPrivateKey shorten_key; - - /** - * HTTP response code - */ - int response_code; - - /** - * HTTP response code - */ - char* emsg; - -}; - - -/** - * Cleanup lookup handle. - * - * @param handle Handle to clean up - */ -static void -cleanup_handle (struct LookupHandle *handle) -{ - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Cleaning up\n"); - if (NULL != handle->json_root) - json_decref (handle->json_root); - - if (NULL != handle->name) - GNUNET_free (handle->name); - if (NULL != handle->emsg) - GNUNET_free (handle->emsg); - if (NULL != handle->el) - { - GNUNET_IDENTITY_ego_lookup_cancel (handle->el); - handle->el = NULL; - } - if (NULL != handle->id_op) - { - GNUNET_IDENTITY_cancel (handle->id_op); - handle->id_op = NULL; - } - if (NULL != handle->lookup_request) - { - GNUNET_GNS_lookup_cancel (handle->lookup_request); - handle->lookup_request = NULL; - } - if (NULL != handle->identity) - { - GNUNET_IDENTITY_disconnect (handle->identity); - handle->identity = NULL; - } - if (NULL != handle->gns) - { - GNUNET_GNS_disconnect (handle->gns); - handle->gns = NULL; - } - - if (NULL != handle->timeout_task) - { - GNUNET_SCHEDULER_cancel (handle->timeout_task); - } - GNUNET_free (handle); -} - - -/** - * Task run on shutdown. Cleans up everything. - * - * @param cls unused - * @param tc scheduler context - */ -static void -do_error (void *cls) -{ - struct LookupHandle *handle = cls; - struct MHD_Response *resp; - char *json_error; - - if (NULL == handle->emsg) - handle->emsg = GNUNET_strdup("Unknown Error"); - - GNUNET_asprintf (&json_error, "{\"error\": \"%s\"}", handle->emsg); - handle->response_code = MHD_HTTP_OK; - - resp = GNUNET_REST_create_response (json_error); - handle->proc (handle->proc_cls, resp, handle->response_code); - cleanup_handle (handle); - GNUNET_free(json_error); -} - - -/** - * Create json representation of a GNSRECORD - * - * @param rd the GNSRECORD_Data - */ -static json_t * -gnsrecord_to_json (const struct GNUNET_GNSRECORD_Data *rd) -{ - const char *typename; - char *string_val; - const char *exp_str; - json_t *record_obj; - - typename = GNUNET_GNSRECORD_number_to_typename (rd->record_type); - string_val = GNUNET_GNSRECORD_value_to_string (rd->record_type, - rd->data, - rd->data_size); - - if (NULL == string_val) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Record of type %d malformed, skipping\n", - (int) rd->record_type); - return NULL; - } - record_obj = json_object (); - json_object_set_new (record_obj, "type", json_string (typename)); - json_object_set_new (record_obj, "value", json_string (string_val)); - GNUNET_free (string_val); - - if (GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION & rd->flags) - { - struct GNUNET_TIME_Relative time_rel; - time_rel.rel_value_us = rd->expiration_time; - exp_str = GNUNET_STRINGS_relative_time_to_string (time_rel, 1); - } - else - { - struct GNUNET_TIME_Absolute time_abs; - time_abs.abs_value_us = rd->expiration_time; - exp_str = GNUNET_STRINGS_absolute_time_to_string (time_abs); - } - json_object_set_new (record_obj, "expiration_time", json_string (exp_str)); - - json_object_set_new (record_obj, "expired", - json_boolean (GNUNET_YES == GNUNET_GNSRECORD_is_expired (rd))); - return record_obj; -} - -/** - * Function called with the result of a GNS lookup. - * - * @param cls the 'const char *' name that was resolved - * @param rd_count number of records returned - * @param rd array of @a rd_count records with the results - */ -static void -process_lookup_result (void *cls, uint32_t rd_count, - const struct GNUNET_GNSRECORD_Data *rd) -{ - struct LookupHandle *handle = cls; - struct MHD_Response *resp; - uint32_t i; - char *result; - json_t *result_array; - json_t *record_obj; - - result_array = json_array(); - handle->lookup_request = NULL; - for (i=0; itype) && - (GNUNET_GNSRECORD_TYPE_ANY != handle->type) ) - continue; - record_obj = gnsrecord_to_json (&(rd[i])); - json_array_append (result_array, record_obj); - json_decref (record_obj); - } - result = json_dumps(result_array, 0); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result); - resp = GNUNET_REST_create_response (result); - handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); - GNUNET_free (result); - json_decref (result_array); - cleanup_handle (handle); -} - - -/** - * Perform the actual resolution, starting with the zone - * identified by the given public key and the shorten zone. - * - * @param pkey public key to use for the zone, can be NULL - */ -static void -lookup_with_public_key (struct LookupHandle *handle) -{ - if (UINT32_MAX == handle->type) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Invalid typename specified, assuming `ANY'\n")); - handle->type = GNUNET_GNSRECORD_TYPE_ANY; - } - if (NULL != handle->name) - { - handle->lookup_request = GNUNET_GNS_lookup (handle->gns, - handle->name, - &handle->pkey, - handle->type, - handle->options, - &process_lookup_result, - handle); - } - else - { - handle->emsg = GNUNET_strdup("Parameter name is missing"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } -} - - -/** - * Method called to with the ego we are to use for the lookup, - * when the ego is determined by a name. - * - * @param cls closure (NULL, unused) - * @param ego ego handle, NULL if not found - */ -static void -identity_zone_cb (void *cls, - const struct GNUNET_IDENTITY_Ego *ego) -{ - struct LookupHandle *handle = cls; - - handle->el = NULL; - if (NULL == ego) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Ego for not found, cannot perform lookup.\n")); - handle->emsg = GNUNET_strdup ("Ego for not found, cannot perform lookup."); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - else - { - GNUNET_IDENTITY_ego_get_public_key (ego, &handle->pkey); - lookup_with_public_key (handle); - } - json_decref(handle->json_root); -} - - -/** - * Method called to with the ego we are to use for the lookup, - * when the ego is the one for the default master zone. - * - * @param cls closure (NULL, unused) - * @param ego ego handle, NULL if not found - * @param ctx context for application to store data for this ego - * (during the lifetime of this process, initially NULL) - * @param name name assigned by the user for this ego, - * NULL if the user just deleted the ego and it - * must thus no longer be used - */ -static void -identity_master_cb (void *cls, - struct GNUNET_IDENTITY_Ego *ego, - void **ctx, - const char *name) -{ - const char *dot; - struct LookupHandle *handle = cls; - - handle->id_op = NULL; - if (NULL == ego) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Ego for `gns-master' not found, cannot perform lookup. Did you run gnunet-gns-import.sh?\n")); - handle->emsg = GNUNET_strdup("Ego for `gns-master' not found, cannot perform lookup. Did you run gnunet-gns-import.sh?"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - GNUNET_IDENTITY_ego_get_public_key (ego, - &handle->pkey); - /* main name is our own master zone, do no look for that in the DHT */ - handle->options = GNUNET_GNS_LO_LOCAL_MASTER; - /* if the name is of the form 'label.gnu', never go to the DHT */ - dot = NULL; - if (NULL != handle->name) - dot = strchr (handle->name, '.'); - if ( (NULL != dot) && - (0 == strcasecmp (dot, ".gnu")) ) - handle->options = GNUNET_GNS_LO_NO_DHT; - lookup_with_public_key (handle); -} - -/** - * Handle get request - * - * @param handle the lookup handle - */ -static void -get_gns_cont (struct GNUNET_REST_RequestHandle *conndata_handle, - const char* url, - void *cls) -{ - struct LookupHandle *handle = cls; - struct GNUNET_HashCode key; - long int enum_test; - char *temp_val; - - //check for /gns otherwise 404 - if (strlen (GNUNET_REST_API_NS_GNS) > strlen (url)) - { - handle->emsg = GNUNET_strdup("Wrong URL"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - - //connect to gns - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n"); - handle->gns = GNUNET_GNS_connect (cfg); - handle->identity = GNUNET_IDENTITY_connect (cfg, NULL, NULL); - handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout, - &do_error, handle); - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connected\n"); - if (NULL == handle->gns) - { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Connecting to GNS failed\n"); - handle->emsg = GNUNET_strdup("Connecting to GNS failed"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - - //check parameter name -> BAD_REQUEST - GNUNET_CRYPTO_hash (GNUNET_REST_PARAMETER_GNS_NAME, - strlen (GNUNET_REST_PARAMETER_GNS_NAME), - &key); - if ( GNUNET_NO - == GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, - &key)) - { - handle->emsg = GNUNET_strdup("Parameter name is missing"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - handle->name = GNUNET_strdup(GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, - &key)); - - //check parameter record_type, optional - GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_RECORD_TYPE, - strlen (GNUNET_REST_JSONAPI_GNS_RECORD_TYPE), - &key); - if ( GNUNET_YES == - GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, - &key) ) - { - handle->type = GNUNET_GNSRECORD_typename_to_number( - GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, - &key)); - } - else - { - handle->type = GNUNET_GNSRECORD_TYPE_ANY; - } - - //check parameter options, optional - GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_OPTIONS, - strlen (GNUNET_REST_JSONAPI_GNS_OPTIONS), - &key); - handle->options = GNUNET_GNS_LO_DEFAULT; - if ( GNUNET_YES - == GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, - &key)) - { - temp_val = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, &key); - if (1 < strlen(temp_val)) - { - handle->options = GNUNET_GNS_LO_DEFAULT; - } - else - { - //atoi because no valid conversion is default local option - enum_test = atoi(temp_val); - if (2 < enum_test) - handle->options = GNUNET_GNS_LO_DEFAULT; - else - handle->options = enum_test; - } - } - else - handle->options = GNUNET_GNS_LO_DEFAULT; - - //check parameter pkey, shortcut to lookup - GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_PKEY, - strlen (GNUNET_REST_JSONAPI_GNS_PKEY), - &key); - if ( GNUNET_YES - == GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, - &key)) - { - handle->pkey_str = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, - &key); - GNUNET_assert(NULL != handle->pkey_str); - if (GNUNET_OK - != GNUNET_CRYPTO_ecdsa_public_key_from_string ( - handle->pkey_str, strlen (handle->pkey_str), &(handle->pkey))) - { - handle->emsg = GNUNET_strdup("Parameter pkey has a wrong format"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - lookup_with_public_key (handle); - return; - } - - //check parameter ego, lookup public key of ego - GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_EGO, - strlen (GNUNET_REST_JSONAPI_GNS_EGO), - &key); - if ( GNUNET_YES == - GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, - &key) ) - { - handle->ego_str = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, - &key); - handle->el = GNUNET_IDENTITY_ego_lookup (cfg, - handle->ego_str, - &identity_zone_cb, - handle); - return; - } - - //if name ends with .zkey then get public key - if ( (NULL != handle->name) && - (strlen (handle->name) > 4) && - (0 == strcmp (".zkey", - &handle->name[strlen (handle->name) - 4])) ) - { - GNUNET_CRYPTO_ecdsa_key_get_public( GNUNET_CRYPTO_ecdsa_key_get_anonymous (), - &(handle->pkey)); - lookup_with_public_key (handle); - } - else //else use gns-master identity - { - handle->id_op = GNUNET_IDENTITY_get (handle->identity, - "gns-master", - &identity_master_cb, - handle); - } -} - -/** - * Handle rest request - * - * @param handle the lookup handle - */ -static void -options_cont (struct GNUNET_REST_RequestHandle *con_handle, - const char* url, - void *cls) -{ - struct MHD_Response *resp; - struct LookupHandle *handle = cls; - - //For GNS, independent of path return all options - resp = GNUNET_REST_create_response (NULL); - MHD_add_response_header (resp, - "Access-Control-Allow-Methods", - MHD_HTTP_METHOD_GET); - handle->proc (handle->proc_cls, - resp, - MHD_HTTP_OK); - cleanup_handle (handle); -} - - -/** - * Function processing the REST call - * - * @param method HTTP method - * @param url URL of the HTTP request - * @param data body of the HTTP request (optional) - * @param data_size length of the body - * @param proc callback function for the result - * @param proc_cls closure for @a proc - * @return #GNUNET_OK if request accepted - */ -static void -rest_gns_process_request (struct GNUNET_REST_RequestHandle *conndata_handle, - GNUNET_REST_ResultProcessor proc, - void *proc_cls) -{ - static const struct GNUNET_REST_RequestHandler handlers[] = { - {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_GNS, &get_gns_cont}, - {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_GNS, &options_cont}, - GNUNET_REST_HANDLER_END - }; - struct LookupHandle *handle = GNUNET_new (struct LookupHandle); - struct GNUNET_REST_RequestHandlerError err; - - handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; - handle->proc_cls = proc_cls; - handle->proc = proc; - handle->rest_handle = conndata_handle; - - if (GNUNET_NO == GNUNET_REST_handle_request (conndata_handle, - handlers, - &err, - handle)) - { - handle->response_code = err.error_code; - GNUNET_SCHEDULER_add_now (&do_error, handle); - } -} - - -/** - * Entry point for the plugin. - * - * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*" - * @return NULL on error, otherwise the plugin context - */ -void * -libgnunet_plugin_rest_gns_init (void *cls) -{ - static struct Plugin plugin; - cfg = cls; - struct GNUNET_REST_Plugin *api; - - if (NULL != plugin.cfg) - return NULL; /* can only initialize once! */ - memset (&plugin, 0, sizeof (struct Plugin)); - plugin.cfg = cfg; - api = GNUNET_new (struct GNUNET_REST_Plugin); - api->cls = &plugin; - api->name = GNUNET_REST_API_NS_GNS; - api->process_request = &rest_gns_process_request; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("GNS REST API initialized\n")); - return api; -} - - -/** - * Exit point from the plugin. - * - * @param cls the plugin context (as returned by "init") - * @return always NULL - */ -void * -libgnunet_plugin_rest_gns_done (void *cls) -{ - struct GNUNET_REST_Plugin *api = cls; - struct Plugin *plugin = api->cls; - - plugin->cfg = NULL; - GNUNET_free (api); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "GNS REST plugin is finished\n"); - return NULL; -} - -/* end of plugin_rest_gns.c */ diff --git a/src/gnsrecord/Makefile.am b/src/gnsrecord/Makefile.am index 47d83169f..f840a31a4 100644 --- a/src/gnsrecord/Makefile.am +++ b/src/gnsrecord/Makefile.am @@ -39,7 +39,6 @@ libgnunetgnsrecord_la_SOURCES = \ gnsrecord_misc.c libgnunetgnsrecord_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ - -ljansson \ $(GN_LIBINTL) libgnunetgnsrecord_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) $(WINFLAGS) \ diff --git a/src/gnsrecord/gnsrecord.c b/src/gnsrecord/gnsrecord.c index 30a0ffa83..b80d86073 100644 --- a/src/gnsrecord/gnsrecord.c +++ b/src/gnsrecord/gnsrecord.c @@ -247,130 +247,4 @@ GNUNET_GNSRECORD_number_to_typename (uint32_t type) return NULL; } -/** - * Parse given JSON object to gns record - * - * @param cls closure, NULL - * @param root the json object representing data - * @param spec where to write the data - * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error - */ -static int -parse_gnsrecordobject (void *cls, - json_t *root, - struct GNUNET_JSON_Specification *spec) -{ - struct GNUNET_GNSRECORD_Data *gnsrecord_object; - struct GNUNET_TIME_Absolute abs_expiration_time; - int unpack_state=0; - const char *data; - const char *expiration_date; - const char *record_type; - const char *dummy_value; - int flag; - void *rdata; - size_t rdata_size; - - if(!json_is_object(root)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Error json is not array nor object!\n"); - return GNUNET_SYSERR; - } - //interpret single gns record - unpack_state = json_unpack(root, - "{s:s, s:s, s:s, s?:i, s:s!}", - "value", &data, - "type", &record_type, - "expiration_time", &expiration_date, - "flag", &flag, - "label", &dummy_value); - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, - "{value:%s, type:%s, expire:%s, flag:%i}", - data, - record_type, - expiration_date, - flag); - if (GNUNET_SYSERR == unpack_state) - { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, - "Error json object has a wrong format!\n"); - return GNUNET_SYSERR; - } - //TODO test - gnsrecord_object = GNUNET_new (struct GNUNET_GNSRECORD_Data); - gnsrecord_object->record_type = GNUNET_GNSRECORD_typename_to_number(record_type); - if (GNUNET_OK - != GNUNET_GNSRECORD_string_to_value (gnsrecord_object->record_type, - data, &rdata, - &rdata_size)) - { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR,"Value invalid for record type"); - return GNUNET_SYSERR; - } - gnsrecord_object->data = rdata; - gnsrecord_object->data_size = rdata_size; - - if (0 == strcmp (expiration_date, "never")) - { - gnsrecord_object->expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; - } - else if (GNUNET_OK - == GNUNET_STRINGS_fancy_time_to_absolute (expiration_date, - &abs_expiration_time)) - { - gnsrecord_object->expiration_time = abs_expiration_time.abs_value_us; - } - else - { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Value invalid for record type"); - return GNUNET_SYSERR; - } - gnsrecord_object->flags = (enum GNUNET_GNSRECORD_Flags)flag; - *(struct GNUNET_GNSRECORD_Data **) spec->ptr = gnsrecord_object; - return GNUNET_OK; -} - -/** - * Cleanup data left from parsing RSA public key. - * - * @param cls closure, NULL - * @param[out] spec where to free the data - */ -static void -clean_gnsrecordobject (void *cls, struct GNUNET_JSON_Specification *spec) -{ - struct GNUNET_GNSRECORD_Data **gnsrecord_object; - gnsrecord_object = (struct GNUNET_GNSRECORD_Data **) spec->ptr; - if (NULL != *gnsrecord_object) - { - if (NULL != (*gnsrecord_object)->data) - GNUNET_free((char*)(*gnsrecord_object)->data); - GNUNET_free(*gnsrecord_object); - *gnsrecord_object = NULL; - } -} - -/** - * JSON Specification for GNS Records. - * - * @param gnsrecord_object struct of GNUNET_GNSRECORD_Data to fill - * @return JSON Specification - */ -struct GNUNET_JSON_Specification -GNUNET_JSON_spec_gnsrecord_data (struct GNUNET_GNSRECORD_Data **gnsrecord_object) -{ - struct GNUNET_JSON_Specification ret = { - .parser = &parse_gnsrecordobject, - .cleaner = &clean_gnsrecordobject, - .cls = NULL, - .field = NULL, - .ptr = gnsrecord_object, - .ptr_size = 0, - .size_ptr = NULL - }; - *gnsrecord_object = NULL; - return ret; -} - /* end of gnsrecord.c */ diff --git a/src/identity/plugin_rest_identity.c b/src/identity/plugin_rest_identity.c index 59dad66c7..49fa9f0fb 100644 --- a/src/identity/plugin_rest_identity.c +++ b/src/identity/plugin_rest_identity.c @@ -42,7 +42,7 @@ /** * Error messages */ -#define GNUNET_REST_ERROR_UNKNOWN "Unknown Error" +#define GNUNET_REST_IDENTITY_ERROR_UNKNOWN "Unknown Error" #define GNUNET_REST_ERROR_RESOURCE_INVALID "Resource location invalid" #define GNUNET_REST_ERROR_NO_DATA "No data" #define GNUNET_REST_ERROR_DATA_INVALID "Data invalid" @@ -251,7 +251,7 @@ do_error (void *cls) char *response; if (NULL == handle->emsg) - handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_UNKNOWN); + handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_ERROR_UNKNOWN); json_object_set_new(json_error,"error", json_string(handle->emsg)); diff --git a/src/include/gnunet_gnsrecord_lib.h b/src/include/gnunet_gnsrecord_lib.h index 2eaa304de..20846238b 100644 --- a/src/include/gnunet_gnsrecord_lib.h +++ b/src/include/gnunet_gnsrecord_lib.h @@ -447,14 +447,6 @@ GNUNET_GNSRECORD_records_deserialize (size_t len, unsigned int rd_count, struct GNUNET_GNSRECORD_Data *dest); -/** - * JSON Specification for GNS Records. - * - * @param gnsrecord_object struct of GNUNET_GNSRECORD_Data to fill - * @return JSON Specification - */ -struct GNUNET_JSON_Specification -GNUNET_JSON_spec_gnsrecord_data (struct GNUNET_GNSRECORD_Data **gnsrecord_object); /* ******* general APIs relating to blocks, records and labels ******** */ diff --git a/src/include/gnunet_json_lib.h b/src/include/gnunet_json_lib.h index 4855f21b4..781d5698b 100644 --- a/src/include/gnunet_json_lib.h +++ b/src/include/gnunet_json_lib.h @@ -26,6 +26,7 @@ #define GNUNET_JSON_LIB_H #include "gnunet_util_lib.h" +#include "gnunet_gnsrecord_lib.h" #include @@ -318,6 +319,17 @@ GNUNET_JSON_spec_rsa_signature (const char *name, struct GNUNET_CRYPTO_RsaSignature **sig); + +/** + * JSON Specification for GNS Records. + * + * @param gnsrecord_object struct of GNUNET_GNSRECORD_Data to fill + * @return JSON Specification + */ +struct GNUNET_JSON_Specification +GNUNET_JSON_spec_gnsrecord_data (struct GNUNET_GNSRECORD_Data **gnsrecord_object); + + /* ****************** Generic generator interface ******************* */ @@ -393,6 +405,16 @@ GNUNET_JSON_from_rsa_public_key (const struct GNUNET_CRYPTO_RsaPublicKey *pk); json_t * GNUNET_JSON_from_rsa_signature (const struct GNUNET_CRYPTO_RsaSignature *sig); +/** + * Convert Gns record to JSON. + * + * @param rname name of record + * @param rd record data + * @return corresponding JSON encoding + */ +json_t * +GNUNET_JSON_from_gns_record (const char* rname, + const struct GNUNET_GNSRECORD_Data *rd); /* ******************* Helpers for MHD upload handling ******************* */ diff --git a/src/json/Makefile.am b/src/json/Makefile.am index 16c0450d9..04f27fec7 100644 --- a/src/json/Makefile.am +++ b/src/json/Makefile.am @@ -16,7 +16,8 @@ libgnunetjson_la_SOURCES = \ json.c \ json_mhd.c \ json_generator.c \ - json_helper.c + json_helper.c \ + json_gnsrecord.c libgnunetjson_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ -ljansson \ diff --git a/src/json/json_generator.c b/src/json/json_generator.c index dd6df4f74..7b24a3c12 100644 --- a/src/json/json_generator.c +++ b/src/json/json_generator.c @@ -157,5 +157,40 @@ GNUNET_JSON_from_rsa_signature (const struct GNUNET_CRYPTO_RsaSignature *sig) return ret; } +/** + * Convert Gns record to JSON. + * + * @param rname name of record + * @param rd record data + * @return corresponding JSON encoding + */ +json_t * +GNUNET_JSON_from_gns_record (const char* rname, + const struct GNUNET_GNSRECORD_Data *rd) +{ + struct GNUNET_TIME_Absolute expiration_time; + const char *expiration_time_str; + const char *record_type_str; + char *value_str; + json_t *ret; + int flags; + + value_str = GNUNET_GNSRECORD_value_to_string(rd->record_type,rd->data,rd->data_size); + expiration_time = GNUNET_GNSRECORD_record_get_expiration_time(1, rd); + expiration_time_str = GNUNET_STRINGS_absolute_time_to_string(expiration_time); + flags = (int)rd->flags; //maybe necessary + record_type_str = GNUNET_GNSRECORD_number_to_typename(rd->record_type); + + // ? for possible NULL values + ret = json_pack("{s:s?,s:s?,s:s?,s:i,s:s?}", + "value", value_str, + "type", record_type_str, + "expiration_time", expiration_time_str, + "flag", flags, + "label", rname); + GNUNET_free_non_null(value_str); + return ret; +} + /* End of json/json_generator.c */ diff --git a/src/json/json_gnsrecord.c b/src/json/json_gnsrecord.c new file mode 100644 index 000000000..48b78f38b --- /dev/null +++ b/src/json/json_gnsrecord.c @@ -0,0 +1,163 @@ +/* + This file is part of GNUnet. + Copyright (C) 2009-2013 GNUnet e.V. + + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +/** + * @file json/json_gnsrecord.c + * @brief JSON handling of GNS record data + * @author Philippe Buschmann + */ +#include "platform.h" +#include "gnunet_util_lib.h" +#include "gnunet_gnsrecord_lib.h" +#include "gnunet_json_lib.h" + +#define GNUNET_JSON_GNSRECORD_VALUE "value" +#define GNUNET_JSON_GNSRECORD_TYPE "type" +#define GNUNET_JSON_GNSRECORD_EXPIRATION_TIME "expiration_time" +#define GNUNET_JSON_GNSRECORD_FLAG "flag" +#define GNUNET_JSON_GNSRECORD_LABEL "label" +#define GNUNET_JSON_GNSRECORD_NEVER "never" + + +/** + * Parse given JSON object to gns record + * + * @param cls closure, NULL + * @param root the json object representing data + * @param spec where to write the data + * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error + */ +static int +parse_gnsrecordobject (void *cls, + json_t *root, + struct GNUNET_JSON_Specification *spec) +{ + struct GNUNET_GNSRECORD_Data *gnsrecord_object; + struct GNUNET_TIME_Absolute abs_expiration_time; + int unpack_state=0; + const char *value; + const char *expiration_time; + const char *record_type; + const char *label; + int flag; + void *rdata; + size_t rdata_size; + + GNUNET_assert(NULL != root); + if(!json_is_object(root)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Error json is not array nor object!\n"); + return GNUNET_SYSERR; + } + //interpret single gns record + unpack_state = json_unpack(root, + "{s:s, s:s, s:s, s?:i, s:s!}", + GNUNET_JSON_GNSRECORD_VALUE, &value, + GNUNET_JSON_GNSRECORD_TYPE, &record_type, + GNUNET_JSON_GNSRECORD_EXPIRATION_TIME, &expiration_time, + GNUNET_JSON_GNSRECORD_FLAG, &flag, + GNUNET_JSON_GNSRECORD_LABEL, &label); + if (GNUNET_SYSERR == unpack_state) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, + "Error json object has a wrong format!\n"); + return GNUNET_SYSERR; + } + gnsrecord_object = GNUNET_new (struct GNUNET_GNSRECORD_Data); + gnsrecord_object->record_type = GNUNET_GNSRECORD_typename_to_number(record_type); + if (UINT32_MAX == gnsrecord_object->record_type) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,"Unsupported type"); + return GNUNET_SYSERR; + } + if (GNUNET_OK + != GNUNET_GNSRECORD_string_to_value (gnsrecord_object->record_type, + value, + &rdata, + &rdata_size)) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,"Value invalid for record type"); + return GNUNET_SYSERR; + } + + gnsrecord_object->data = rdata; + gnsrecord_object->data_size = rdata_size; + + if (0 == strcmp (expiration_time, GNUNET_JSON_GNSRECORD_NEVER)) + { + gnsrecord_object->expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; + } + else if (GNUNET_OK + == GNUNET_STRINGS_fancy_time_to_absolute (expiration_time, + &abs_expiration_time)) + { + gnsrecord_object->expiration_time = abs_expiration_time.abs_value_us; + } + else + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Value invalid for expiration time"); + return GNUNET_SYSERR; + } + gnsrecord_object->flags = (enum GNUNET_GNSRECORD_Flags)flag; + *(struct GNUNET_GNSRECORD_Data **) spec->ptr = gnsrecord_object; + return GNUNET_OK; +} + +/** + * Cleanup data left from parsing RSA public key. + * + * @param cls closure, NULL + * @param[out] spec where to free the data + */ +static void +clean_gnsrecordobject (void *cls, struct GNUNET_JSON_Specification *spec) +{ + struct GNUNET_GNSRECORD_Data **gnsrecord_object; + gnsrecord_object = (struct GNUNET_GNSRECORD_Data **) spec->ptr; + if (NULL != *gnsrecord_object) + { + if (NULL != (*gnsrecord_object)->data) + GNUNET_free((char*)(*gnsrecord_object)->data); + + GNUNET_free(*gnsrecord_object); + *gnsrecord_object = NULL; + } +} + +/** + * JSON Specification for GNS Records. + * + * @param gnsrecord_object struct of GNUNET_GNSRECORD_Data to fill + * @return JSON Specification + */ +struct GNUNET_JSON_Specification +GNUNET_JSON_spec_gnsrecord_data (struct GNUNET_GNSRECORD_Data **gnsrecord_object) +{ + struct GNUNET_JSON_Specification ret = { + .parser = &parse_gnsrecordobject, + .cleaner = &clean_gnsrecordobject, + .cls = NULL, + .field = NULL, + .ptr = gnsrecord_object, + .ptr_size = 0, + .size_ptr = NULL + }; + *gnsrecord_object = NULL; + return ret; +} diff --git a/src/namestore/plugin_rest_namestore.c b/src/namestore/plugin_rest_namestore.c index afe010b79..6924c53a4 100644 --- a/src/namestore/plugin_rest_namestore.c +++ b/src/namestore/plugin_rest_namestore.c @@ -36,11 +36,7 @@ #define GNUNET_REST_SUBSYSTEM_NAMESTORE "namestore" -#define GNUNET_REST_JSON_NAMESTORE_RECORD_TYPE "record_type" -#define GNUNET_REST_JSON_NAMESTORE_VALUE "value" -#define GNUNET_REST_JSON_NAMESTORE_EXPIRATION "expiration" -#define GNUNET_REST_JSON_NAMESTORE_EXPIRED "expired" -#define GNUNET_REST_ERROR_UNKNOWN "Unknown Error" +#define GNUNET_REST_NAMESTORE_ERROR_UNKNOWN "Unknown Error" #define GNUNET_REST_NAMESTORE_RD_COUNT 1 @@ -194,8 +190,6 @@ static void cleanup_handle (void *cls) { struct RequestHandle *handle = cls; - size_t index; - json_t *json_ego; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n"); @@ -239,10 +233,6 @@ cleanup_handle (void *cls) if(NULL != handle->resp_object) { - json_array_foreach(handle->resp_object, index, json_ego ) - { - json_decref (json_ego); - } json_decref(handle->resp_object); } @@ -264,7 +254,7 @@ do_error (void *cls) char *response; if (NULL == handle->emsg) - handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_UNKNOWN); + handle->emsg = GNUNET_strdup(GNUNET_REST_NAMESTORE_ERROR_UNKNOWN); json_object_set_new(json_error,"error", json_string(handle->emsg)); @@ -286,66 +276,10 @@ namestore_iteration_error (void *cls) { struct RequestHandle *handle = cls; struct MHD_Response *resp = GNUNET_REST_create_response (NULL); - handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; - handle->proc (handle->proc_cls, resp, handle->response_code); + handle->proc (handle->proc_cls, resp, MHD_HTTP_INTERNAL_SERVER_ERROR); GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); } -/** - * Create json representation of a GNSRECORD - * - * @param rd the GNSRECORD_Data - */ -static json_t * -gnsrecord_to_json (const struct GNUNET_GNSRECORD_Data *rd) -{ - const char *typename; - char *string_val; - const char *exp_str; - json_t *record_obj; - - typename = GNUNET_GNSRECORD_number_to_typename (rd->record_type); - string_val = GNUNET_GNSRECORD_value_to_string (rd->record_type, - rd->data, - rd->data_size); - - if (NULL == string_val) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Record of type %d malformed, skipping\n", - (int) rd->record_type); - return NULL; - } - record_obj = json_object(); - json_object_set_new (record_obj, - GNUNET_REST_JSON_NAMESTORE_RECORD_TYPE, - json_string (typename)); - json_object_set_new (record_obj, - GNUNET_REST_JSON_NAMESTORE_VALUE, - json_string (string_val)); - //GNUNET_free (string_val); - - if (GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION & rd->flags) - { - struct GNUNET_TIME_Relative time_rel; - time_rel.rel_value_us = rd->expiration_time; - exp_str = GNUNET_STRINGS_relative_time_to_string (time_rel, 1); - } - else - { - struct GNUNET_TIME_Absolute time_abs; - time_abs.abs_value_us = rd->expiration_time; - exp_str = GNUNET_STRINGS_absolute_time_to_string (time_abs); - } - json_object_set_new (record_obj, - GNUNET_REST_JSON_NAMESTORE_EXPIRATION, - json_string (exp_str)); - json_object_set_new (record_obj, "expired", - json_boolean (GNUNET_YES == GNUNET_GNSRECORD_is_expired (rd))); - return record_obj; -} - - static void create_finished (void *cls, int32_t success, const char *emsg) { @@ -364,6 +298,29 @@ create_finished (void *cls, int32_t success, const char *emsg) GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); } +static void +del_finished (void *cls, int32_t success, const char *emsg) +{ + struct RequestHandle *handle = cls; + + handle->add_qe = NULL; + if (GNUNET_NO == success) + { + handle->emsg = GNUNET_strdup("Deleting record failed. Record does not exist"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + if (GNUNET_SYSERR == success) + { + handle->emsg = GNUNET_strdup("Deleting record failed"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + handle->proc (handle->proc_cls, + GNUNET_REST_create_response (NULL), + MHD_HTTP_NO_CONTENT); + GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); +} /** * Iteration over all results finished, build final * response. @@ -379,10 +336,8 @@ namestore_list_finished (void *cls) handle->list_it = NULL; - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "HEY\n"); if (NULL == handle->resp_object) { - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "OH\n"); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } @@ -415,9 +370,6 @@ namestore_list_iteration (void *cls, if (NULL == handle->resp_object) handle->resp_object = json_array(); - char *result_str = json_dumps (handle->resp_object, 0); - GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "%s\n", result_str); - GNUNET_free(result_str); /*if ( (NULL != handle->ego_entry->identifier) && (0 != strcmp (handle->ego_entry->identifier, rname)) ) @@ -435,13 +387,12 @@ namestore_list_iteration (void *cls, (0 != strcmp (rname, GNUNET_GNS_EMPTY_LABEL_AT)) ) continue; - record_obj = gnsrecord_to_json (&rd[i]); + record_obj = GNUNET_JSON_from_gns_record(rname,rd); if(NULL == record_obj) continue; - json_array_append (handle->resp_object, - record_obj); + json_array_append (handle->resp_object, record_obj); json_decref (record_obj); } @@ -477,73 +428,7 @@ namestore_get (struct GNUNET_REST_RequestHandle *con_handle, &namestore_list_finished, handle); } -/* -//TODO filter input -static int -json_to_gnsrecord (struct RequestHandle *handle) -{ - struct GNUNET_TIME_Relative etime_rel; - struct GNUNET_TIME_Absolute etime_abs; - void *rdata; - size_t rdata_size; - - handle->rd = GNUNET_new_array(GNUNET_REST_NAMESTORE_RD_COUNT, - struct GNUNET_GNSRECORD_Data); - memset (handle->rd, 0, sizeof(struct GNUNET_GNSRECORD_Data)); - handle->rd->record_type = GNUNET_GNSRECORD_typename_to_number ( - handle->json_data->type); - if (UINT32_MAX == (*handle->rd).record_type) - { - handle->emsg = GNUNET_strdup("Unsupported type"); - return GNUNET_SYSERR; - } - if (GNUNET_OK - != GNUNET_GNSRECORD_string_to_value ((*handle->rd).record_type, - handle->json_data->value, &rdata, - &rdata_size)) - { - handle->emsg = GNUNET_strdup("Value invalid for record type"); - return GNUNET_SYSERR; - } - (*handle->rd).data = rdata; - (*handle->rd).data_size = rdata_size; - //TODO other flags - if (0 == handle->json_data->is_public) - { - handle->rd->flags |= GNUNET_GNSRECORD_RF_PRIVATE; - } - /**TODO - * if (1 == handle->is_shadow) - rde->flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD; - if (1 != handle->is_public) - rde->flags |= GNUNET_GNSRECORD_RF_PRIVATE; - * - if (0 == strcmp (handle->json_data->expiration_time, "never")) - { - (*handle->rd).expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; - } - else if (GNUNET_OK - == GNUNET_STRINGS_fancy_time_to_relative ( - handle->json_data->expiration_time, &etime_rel)) - { - (*handle->rd).expiration_time = etime_rel.rel_value_us; - (*handle->rd).flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; - } - else if (GNUNET_OK - == GNUNET_STRINGS_fancy_time_to_absolute ( - handle->json_data->expiration_time, &etime_abs)) - { - (*handle->rd).expiration_time = etime_abs.abs_value_us; - } - else - { - handle->emsg = GNUNET_strdup("Value invalid for record type"); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} -*/ /** * We're storing a new record; this requires @@ -564,12 +449,11 @@ create_new_record_cont (void *cls, { struct RequestHandle *handle = cls; - handle->add_qe = NULL; if (0 != strcmp (rec_name, handle->label_name)) { GNUNET_break (0); - do_error (handle); + GNUNET_SCHEDULER_add_now (&do_error, handle); return; } @@ -656,6 +540,31 @@ namestore_add (struct GNUNET_REST_RequestHandle *con_handle, } +static void +del_cont (void *cls, + const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, + const char *label, + unsigned int rd_count, + const struct GNUNET_GNSRECORD_Data *rd) +{ + struct RequestHandle *handle = cls; + + handle->add_qe = NULL; + if (0 == rd_count) + { + handle->emsg = GNUNET_strdup("Record not found"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + + handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle, + &handle->zone_pkey, + handle->label_name, + 0, NULL, + &del_finished, + handle); +} + /** * Handle namestore DELETE request * @@ -669,12 +578,28 @@ namestore_delete (struct GNUNET_REST_RequestHandle *con_handle, void *cls) { struct RequestHandle *handle = cls; + struct GNUNET_HashCode key; + + GNUNET_CRYPTO_hash ("label", strlen ("label"), &key); + if ( GNUNET_NO + == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, + &key)) + { + handle->emsg = GNUNET_strdup("Missing name"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + handle->label_name = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, + &key); - //TODO add behaviour and response - - handle->emsg = GNUNET_strdup ("Not implemented yet"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; + handle->add_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle, + &handle->zone_pkey, + handle->label_name, + &do_error, + handle, + &del_cont, + handle); + } diff --git a/src/namestore/plugin_rest_namestore2.c b/src/namestore/plugin_rest_namestore2.c deleted file mode 100644 index ec44046e0..000000000 --- a/src/namestore/plugin_rest_namestore2.c +++ /dev/null @@ -1,1229 +0,0 @@ -/* - This file is part of GNUnet. - 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 Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, - or (at your option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - */ -/** - * @author Martin Schanzenbach - * @file namestore/plugin_rest_namestore.c - * @brief GNUnet Namestore REST plugin - * - */ - -#include "platform.h" -#include "gnunet_rest_plugin.h" -#include "gnunet_gns_service.h" -#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 - -#define GNUNET_REST_API_NS_NAMESTORE "/names" - -#define GNUNET_REST_API_NS_NAMESTORE_ZKEY "/names/zkey" - -#define GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO "record" - -#define GNUNET_REST_JSONAPI_NAMESTORE_NAME "name" - -#define GNUNET_REST_JSONAPI_NAMESTORE_REVINFO "revinfo" - -#define GNUNET_REST_JSONAPI_NAMESTORE_RECORD GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO - -#define GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE "record_type" - -#define GNUNET_REST_JSONAPI_NAMESTORE_VALUE "value" - -#define GNUNET_REST_JSONAPI_NAMESTORE_PUBLIC "public" - -#define GNUNET_REST_JSONAPI_NAMESTORE_SHADOW "shadow" - -#define GNUNET_REST_JSONAPI_NAMESTORE_PKEY "pkey" - -#define GNUNET_REST_JSONAPI_NAMESTORE_ZKEY "zkey" - -#define GNUNET_REST_JSONAPI_NAMESTORE_EXPIRATION "expiration" - -#define GNUNET_REST_JSONAPI_NAMESTORE_EGO "ego" - -/** - * @brief struct returned by the initialization function of the plugin - */ -struct Plugin -{ - const struct GNUNET_CONFIGURATION_Handle *cfg; -}; - - -/** - * HTTP methods allows for this plugin - */ -static char* allow_methods; - -const struct GNUNET_CONFIGURATION_Handle *cfg; - -struct RecordEntry -{ - /** - * DLL - */ - struct RecordEntry *next; - - /** - * DLL - */ - struct RecordEntry *prev; - -}; - -struct RequestHandle -{ - /** - * Ego list - */ - struct RecordEntry *record_head; - - /** - * Ego list - */ - struct record_entry *record_tail; - - /** - * JSON response object - */ - struct GNUNET_JSONAPI_Document *resp_object; - - /** - * Rest connection - */ - struct GNUNET_REST_RequestHandle *rest_handle; - - /** - * Handle to GNS service. - */ - struct GNUNET_IDENTITY_Handle *identity_handle; - - /** - * Handle to NAMESTORE - */ - struct GNUNET_NAMESTORE_Handle *ns_handle; - - /** - * Handle to NAMESTORE it - */ - struct GNUNET_NAMESTORE_ZoneIterator *list_it; - - /** - * Private key for the zone - */ - struct GNUNET_CRYPTO_EcdsaPrivateKey zone_pkey; - - /** - * Handle to identity lookup - */ - struct GNUNET_IDENTITY_EgoLookup *ego_lookup; - - /** - * Default Ego operation - */ - struct GNUNET_IDENTITY_Operation *get_default; - - /** - * Name of the ego - */ - char *ego_name; - - /** - * Record is public - */ - int is_public; - - /** - * Shadow record - */ - int is_shadow; - - /** - * Name of the record to modify - */ - char *name; - - /** - * Value of the record - */ - char *value; - - /** - * Zkey string - */ - const char* zkey_str; - - /** - * record type - */ - uint32_t type; - - /** - * Records to store - */ - struct GNUNET_GNSRECORD_Data *rd; - - /** - * record count - */ - unsigned int rd_count; - - /** - * NAMESTORE Operation - */ - struct GNUNET_NAMESTORE_QueueEntry *add_qe; - - /** - * NAMESTORE Operation - */ - struct GNUNET_NAMESTORE_QueueEntry *reverse_qe; - - /** - * Desired timeout for the lookup (default is no timeout). - */ - struct GNUNET_TIME_Relative timeout; - - /** - * ID of a task associated with the resolution process. - */ - struct GNUNET_SCHEDULER_Task * timeout_task; - - /** - * The plugin result processor - */ - GNUNET_REST_ResultProcessor proc; - - /** - * The closure of the result processor - */ - void *proc_cls; - - /** - * The url - */ - char *url; - - /** - * Cfg - */ - const struct GNUNET_CONFIGURATION_Handle *cfg; - - /** - * HTTP response code - */ - int response_code; - -}; - - -/** - * Cleanup lookup handle - * - * @param handle Handle to clean up - */ -static void -cleanup_handle (struct RequestHandle *handle) -{ - struct RecordEntry *record_entry; - struct RecordEntry *record_tmp; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Cleaning up\n"); - if (NULL != handle->resp_object) - GNUNET_JSONAPI_document_delete (handle->resp_object); - if (NULL != handle->name) - GNUNET_free (handle->name); - if (NULL != handle->timeout_task) - GNUNET_SCHEDULER_cancel (handle->timeout_task); - if (NULL != handle->ego_lookup) - GNUNET_IDENTITY_ego_lookup_cancel (handle->ego_lookup); - if (NULL != handle->get_default) - GNUNET_IDENTITY_cancel (handle->get_default); - if (NULL != handle->list_it) - GNUNET_NAMESTORE_zone_iteration_stop (handle->list_it); - if (NULL != handle->add_qe) - GNUNET_NAMESTORE_cancel (handle->add_qe); - if (NULL != handle->identity_handle) - GNUNET_IDENTITY_disconnect (handle->identity_handle); - if (NULL != handle->ns_handle) - GNUNET_NAMESTORE_disconnect (handle->ns_handle); - if (NULL != handle->url) - GNUNET_free (handle->url); - if (NULL != handle->value) - GNUNET_free (handle->value); - if (NULL != handle->rd) - { - for (unsigned int i = 0; i < handle->rd_count; i++) - { - if (NULL != handle->rd[i].data) - GNUNET_free ((void*)handle->rd[i].data); - } - GNUNET_free (handle->rd); - } - if (NULL != handle->ego_name) - GNUNET_free (handle->ego_name); - for (record_entry = handle->record_head; - NULL != record_entry;) - { - record_tmp = record_entry; - record_entry = record_entry->next; - GNUNET_free (record_tmp); - } - GNUNET_free (handle); -} - - -/** - * Create json representation of a GNSRECORD - * - * @param rd the GNSRECORD_Data - */ -static json_t * -gnsrecord_to_json (const struct GNUNET_GNSRECORD_Data *rd) -{ - const char *typename; - char *string_val; - const char *exp_str; - json_t *record_obj; - - typename = GNUNET_GNSRECORD_number_to_typename (rd->record_type); - string_val = GNUNET_GNSRECORD_value_to_string (rd->record_type, - rd->data, - rd->data_size); - - if (NULL == string_val) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Record of type %d malformed, skipping\n", - (int) rd->record_type); - return NULL; - } - record_obj = json_object(); - json_object_set_new (record_obj, - GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE, - json_string (typename)); - json_object_set_new (record_obj, - GNUNET_REST_JSONAPI_NAMESTORE_VALUE, - json_string (string_val)); - GNUNET_free (string_val); - - if (GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION & rd->flags) - { - struct GNUNET_TIME_Relative time_rel; - time_rel.rel_value_us = rd->expiration_time; - exp_str = GNUNET_STRINGS_relative_time_to_string (time_rel, 1); - } - else - { - struct GNUNET_TIME_Absolute time_abs; - time_abs.abs_value_us = rd->expiration_time; - exp_str = GNUNET_STRINGS_absolute_time_to_string (time_abs); - } - json_object_set_new (record_obj, GNUNET_REST_JSONAPI_NAMESTORE_EXPIRATION, json_string (exp_str)); - - json_object_set_new (record_obj, "expired", - json_boolean (GNUNET_YES == GNUNET_GNSRECORD_is_expired (rd))); - return record_obj; -} - - -/** - * Task run on error. Generates error response and cleans up. - * - * @param cls the request to generate an error response for - */ -static void -do_error (void *cls) -{ - struct RequestHandle *handle = cls; - 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) -{ - cleanup_handle (cls); -} - - -/** - * Iteration over all results finished, build final - * response. - * - * @param cls the `struct RequestHandle` - */ -static void -namestore_list_finished (void *cls) -{ - struct RequestHandle *handle = cls; - char *result; - struct MHD_Response *resp; - - handle->list_it = NULL; - if (NULL == handle->resp_object) - handle->resp_object = GNUNET_JSONAPI_document_new (); - - if (GNUNET_SYSERR == - GNUNET_JSONAPI_document_serialize (handle->resp_object, - &result)) - { - handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; - GNUNET_SCHEDULER_add_now (&do_error, - handle); - return; - } - resp = GNUNET_REST_create_response (result); - handle->proc (handle->proc_cls, - resp, - MHD_HTTP_OK); - GNUNET_free_non_null (result); - GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, - handle); -} - - - -/** - * Create a response with requested records - * - * @param handle the RequestHandle - */ -static void -namestore_list_response (void *cls, - const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, - const char *rname, - unsigned int rd_len, - const struct GNUNET_GNSRECORD_Data *rd) -{ - struct RequestHandle *handle = cls; - struct GNUNET_JSONAPI_Resource *json_resource; - json_t *result_array; - json_t *record_obj; - - if (NULL == handle->resp_object) - handle->resp_object = GNUNET_JSONAPI_document_new (); - - if ( (NULL != handle->name) && - (0 != strcmp (handle->name, - rname)) ) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "%s does not match %s\n", - rname, - handle->name); - GNUNET_NAMESTORE_zone_iterator_next (handle->list_it, - 1); - return; - } - - result_array = json_array (); - for (unsigned int i=0; itype) && - (GNUNET_GNSRECORD_TYPE_ANY != handle->type) ) - continue; - record_obj = gnsrecord_to_json (&rd[i]); - json_array_append (result_array, - record_obj); - json_decref (record_obj); - } - - if (0 < json_array_size(result_array)) - { - json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO, - rname); - GNUNET_JSONAPI_resource_add_attr (json_resource, - GNUNET_REST_JSONAPI_NAMESTORE_RECORD, - result_array); - GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource); - } - - json_decref (result_array); - GNUNET_NAMESTORE_zone_iterator_next (handle->list_it, - 1); -} - - -static void -create_finished (void *cls, int32_t success, const char *emsg) -{ - struct RequestHandle *handle = cls; - struct MHD_Response *resp; - - handle->add_qe = NULL; - if (GNUNET_YES != success) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Error storing records%s%s\n", - (NULL == emsg) ? "" : ": ", - (NULL == emsg) ? "" : emsg); - GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); - return; - } - resp = GNUNET_REST_create_response (NULL); - handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT); - GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); -} - - -/** - * We're storing a new record; this requires - * that no record already exists - * - * @param cls closure, unused - * @param zone_key private key of the zone - * @param rec_name name that is being mapped (at most 255 characters long) - * @param rd_count number of entries in @a rd array - * @param rd array of records with data to store - */ -static void -create_new_record_cont (void *cls, - const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, - const char *rec_name, - unsigned int rd_count, - const struct GNUNET_GNSRECORD_Data *rd) -{ - struct RequestHandle *handle = cls; - - handle->add_qe = NULL; - if (0 != strcmp (rec_name, handle->name)) - { - GNUNET_break (0); - do_error (handle); - return; - } - - if (0 != rd_count) - { - handle->proc (handle->proc_cls, - GNUNET_REST_create_response (NULL), - MHD_HTTP_CONFLICT); - GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); - return; - } - - GNUNET_assert (NULL != handle->name); - handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle, - &handle->zone_pkey, - handle->name, - handle->rd_count, - handle->rd, - &create_finished, - handle); -} - - -static void -del_finished (void *cls, - int32_t success, - const char *emsg) -{ - struct RequestHandle *handle = cls; - - handle->add_qe = NULL; - if (GNUNET_NO == success) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Deleting record failed, record does not exist%s%s\n"), - (NULL != emsg) ? ": " : "", - (NULL != emsg) ? emsg : ""); - GNUNET_SCHEDULER_add_now (&do_error, handle); //do_not_found TODO - return; - } - if (GNUNET_SYSERR == success) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Deleting record failed%s%s\n"), - (NULL != emsg) ? ": " : "", - (NULL != emsg) ? emsg : ""); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - handle->proc (handle->proc_cls, - GNUNET_REST_create_response (NULL), - MHD_HTTP_NO_CONTENT); - GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); -} - - -static void -del_cont (void *cls, - const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, - const char *label, - unsigned int rd_count, - const struct GNUNET_GNSRECORD_Data *rd) -{ - struct RequestHandle *handle = cls; - - handle->add_qe = NULL; - if (0 == rd_count) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("There are no records under label `%s' that could be deleted.\n"), - label); - do_error (handle); - return; - } - - handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle, - &handle->zone_pkey, - handle->name, - 0, NULL, - &del_finished, - handle); -} - - -static void -namestore_delete_cont (struct GNUNET_REST_RequestHandle *con, - const char *url, - void *cls) -{ - struct RequestHandle *handle = cls; - - if (NULL == handle->name) - { - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - - handle->add_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle, - &handle->zone_pkey, - handle->name, - &do_error, - handle, - &del_cont, - handle); -} - - -static int -json_to_gnsrecord (const json_t *records_json, - struct GNUNET_GNSRECORD_Data **rd, - unsigned int *rd_count) -{ - struct GNUNET_TIME_Relative etime_rel; - struct GNUNET_TIME_Absolute etime_abs; - char *value; - void *rdata; - size_t rdata_size; - const char *typestring; - const char *expirationstring; - json_t *type_json; - json_t *value_json; - json_t *record_json; - json_t *exp_json; - - *rd_count = json_array_size (records_json); - *rd = GNUNET_new_array (*rd_count, - struct GNUNET_GNSRECORD_Data); - for (unsigned int i = 0; i < *rd_count; i++) - { - memset (&(*rd)[i], - 0, - sizeof (struct GNUNET_GNSRECORD_Data)); - record_json = json_array_get (records_json, - i); - type_json = json_object_get (record_json, - GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE); - if (! json_is_string (type_json)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Type property is no string\n"); - return GNUNET_SYSERR; - } - typestring = json_string_value (type_json); - (*rd)[i].record_type = GNUNET_GNSRECORD_typename_to_number (typestring); - if (UINT32_MAX == (*rd)[i].record_type) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unsupported type `%s'\n"), - json_string_value (type_json)); - return GNUNET_SYSERR; - } - value_json = json_object_get (record_json, - GNUNET_REST_JSONAPI_NAMESTORE_VALUE); - if (! json_is_string (value_json)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Value property is no string\n"); - return GNUNET_SYSERR; - } - value = GNUNET_strdup (json_string_value (value_json)); - if (GNUNET_OK != - GNUNET_GNSRECORD_string_to_value ((*rd)[i].record_type, - value, - &rdata, - &rdata_size)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Value `%s' invalid for record type `%s'\n"), - value, - typestring); - return GNUNET_SYSERR; - } - (*rd)[i].data = rdata; - (*rd)[i].data_size = rdata_size; - /**TODO - * if (1 == handle->is_shadow) - rde->flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD; - if (1 != handle->is_public) - rde->flags |= GNUNET_GNSRECORD_RF_PRIVATE; - */ - exp_json = json_object_get (record_json, - GNUNET_REST_JSONAPI_NAMESTORE_EXPIRATION); - if (! json_is_string (exp_json)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Expiration property is no string\n"); - return GNUNET_SYSERR; - } - expirationstring = json_string_value (exp_json); - if (0 == strcmp (expirationstring, "never")) - { - (*rd)[i].expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us; - } - else if (GNUNET_OK == - GNUNET_STRINGS_fancy_time_to_relative (expirationstring, - &etime_rel)) - { - (*rd)[i].expiration_time = etime_rel.rel_value_us; - (*rd)[i].flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION; - } - else if (GNUNET_OK == - GNUNET_STRINGS_fancy_time_to_absolute (expirationstring, - &etime_abs)) - { - (*rd)[i].expiration_time = etime_abs.abs_value_us; - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Value `%s' invalid for record type `%s'\n"), - value, - typestring); - return GNUNET_SYSERR; - } - } - return GNUNET_OK; -} - - -static void -namestore_create_cont (struct GNUNET_REST_RequestHandle *con, - const char *url, - void *cls) -{ - struct RequestHandle *handle = cls; - struct MHD_Response *resp; - struct GNUNET_JSONAPI_Document *json_obj; - struct GNUNET_JSONAPI_Resource *json_res; - json_t *records_json; - 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, - "Cannot create under %s\n", handle->url); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - if (0 >= handle->rest_handle->data_size) - { - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - term_data[handle->rest_handle->data_size] = '\0'; - GNUNET_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, - "Unable to parse JSONAPI Object from %s\n", - term_data); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - 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_JSONAPI_document_resource_count (json_obj)); - GNUNET_JSONAPI_document_delete (json_obj); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - 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_JSONAPI_document_delete (json_obj); - resp = GNUNET_REST_create_response (NULL); - handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); - cleanup_handle (handle); - return; - } - 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_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_JSONAPI_document_delete (json_obj); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - GNUNET_JSONAPI_document_delete (json_obj); - - handle->add_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle, - &handle->zone_pkey, - handle->name, - &do_error, - handle, - &create_new_record_cont, - handle); -} - - -static void -namestore_zkey_response (void *cls, - const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, - const char *label, - unsigned int rd_count, - const struct GNUNET_GNSRECORD_Data *rd) -{ - struct RequestHandle *handle = cls; - struct MHD_Response *resp; - 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_JSONAPI_document_new (); - if (NULL != label) - { - name_json = json_string (label); - 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_JSONAPI_document_serialize (json_obj, &result)) - { - GNUNET_JSONAPI_document_delete (json_obj); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - resp = GNUNET_REST_create_response (result); - handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); - GNUNET_JSONAPI_document_delete (json_obj); - GNUNET_free (result); - GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle); -} - - -static void -namestore_zkey_cont (struct GNUNET_REST_RequestHandle *con, - const char *url, - void *cls) -{ - struct RequestHandle *handle = cls; - struct GNUNET_HashCode key; - struct GNUNET_CRYPTO_EcdsaPublicKey pubkey; - - GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_NAMESTORE_ZKEY, - strlen (GNUNET_REST_JSONAPI_NAMESTORE_ZKEY), - &key); - if ( GNUNET_NO == - GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, - &key) ) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "No zkey given %s\n", handle->url); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - handle->zkey_str = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, - &key); - if ((NULL == handle->zkey_str) || - (GNUNET_OK != - GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->zkey_str, - strlen (handle->zkey_str), - &pubkey))) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Zkey invalid %s\n", handle->zkey_str); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - handle->reverse_qe = GNUNET_NAMESTORE_zone_to_name (handle->ns_handle, - &handle->zone_pkey, - &pubkey, - &do_error, - handle, - &namestore_zkey_response, - handle); -} - - -static void -namestore_info_cont (struct GNUNET_REST_RequestHandle *con, - const char *url, - void *cls) -{ - struct RequestHandle *handle = cls; - - handle->list_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle, - &handle->zone_pkey, - &do_error, - handle, - &namestore_list_response, - handle, - &namestore_list_finished, - handle); -} - - -static char* -get_name_from_url (const char* url) -{ - if (strlen (url) <= strlen (GNUNET_REST_API_NS_NAMESTORE)) - return NULL; - return (char*)url + strlen (GNUNET_REST_API_NS_NAMESTORE) + 1; -} - -/** - * Respond to OPTIONS request - * - * @param con_handle the connection handle - * @param url the url - * @param cls the RequestHandle - */ -static void -options_cont (struct GNUNET_REST_RequestHandle *con_handle, - const char* url, - void *cls) -{ - struct MHD_Response *resp; - struct RequestHandle *handle = cls; - - //For now, independent of path return all options - resp = GNUNET_REST_create_response (NULL); - MHD_add_response_header (resp, - "Access-Control-Allow-Methods", - allow_methods); - handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); - cleanup_handle (handle); -} - - -/** - * Callback invoked from identity service with ego information. - * An @a ego of NULL means the ego was not found. - * - * @param cls closure with the configuration - * @param ego an ego known to identity service, or NULL - */ -static void -identity_cb (void *cls, - const struct GNUNET_IDENTITY_Ego *ego) -{ - struct RequestHandle *handle = cls; - struct MHD_Response *resp; - 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 - // {MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_NAMESTORE, &namestore_edit_cont}, //update. TODO this shoul be PATCH - {MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_NAMESTORE, &namestore_delete_cont}, //delete - {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_NAMESTORE, &options_cont}, - GNUNET_REST_HANDLER_END - }; - - handle->ego_lookup = NULL; - if (NULL == ego) - { - if (NULL != handle->ego_name) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Ego `%s' not known to identity service\n"), - handle->ego_name); - } - resp = GNUNET_REST_create_response (NULL); - handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND); - cleanup_handle (handle); - return; - } - handle->zone_pkey = *GNUNET_IDENTITY_ego_get_private_key (ego); - handle->ns_handle = GNUNET_NAMESTORE_connect (cfg); - if (NULL == handle->ns_handle) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Failed to connect to namestore\n")); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - - 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); - } -} - - -static void -default_ego_cb (void *cls, - struct GNUNET_IDENTITY_Ego *ego, - void **ctx, - const char *name) -{ - struct RequestHandle *handle = cls; - struct MHD_Response *resp; - handle->get_default = NULL; - if (NULL == ego) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("No default ego configured in identity service\n")); - resp = GNUNET_REST_create_response (NULL); - handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND); - cleanup_handle (handle); - return; - } - else - { - identity_cb (cls, ego); - } -} - -static void -id_connect_cb (void *cls, - struct GNUNET_IDENTITY_Ego *ego, - void **ctx, - const char *name) -{ - struct RequestHandle *handle = cls; - if (NULL == ego) - { - handle->get_default = GNUNET_IDENTITY_get (handle->identity_handle, - "namestore", - &default_ego_cb, handle); - } -} - - -/** - * Function processing the REST call - * - * @param method HTTP method - * @param url URL of the HTTP request - * @param data body of the HTTP request (optional) - * @param data_size length of the body - * @param proc callback function for the result - * @param proc_cls closure for callback function - * @return #GNUNET_OK if request accepted - */ -static void -rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle, - GNUNET_REST_ResultProcessor proc, - void *proc_cls) -{ - struct RequestHandle *handle = GNUNET_new (struct RequestHandle); - struct MHD_Response *resp; - struct GNUNET_HashCode key; - char *ego; - char *name; - char *type; - - handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; - handle->proc_cls = proc_cls; - handle->proc = proc; - 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, - "Connecting...\n"); - handle->cfg = cfg; - ego = NULL; - GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_NAMESTORE_EGO, - strlen (GNUNET_REST_JSONAPI_NAMESTORE_EGO), - &key); - if ( GNUNET_YES == - GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map, - &key) ) - { - ego = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, - &key); - } - - handle->type = GNUNET_GNSRECORD_TYPE_ANY; - 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->rest_handle->url_param_map, - &key) ) - { - type = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map, - &key); - if (NULL != type) - handle->type = GNUNET_GNSRECORD_typename_to_number (type); - } - name = get_name_from_url (handle->url); - if (NULL != ego) - handle->ego_name = GNUNET_strdup (ego); - if (NULL != 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_response (NULL); - handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND); - cleanup_handle (handle); - } - return; - } - handle->ego_lookup = GNUNET_IDENTITY_ego_lookup (cfg, - handle->ego_name, - &identity_cb, - handle); - handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout, - &do_timeout, - handle); -} - -/** - * Entry point for the plugin. - * - * @param cls Config info - * @return NULL on error, otherwise the plugin context - */ -void * -libgnunet_plugin_rest_namestore_init (void *cls) -{ - static struct Plugin plugin; - cfg = cls; - struct GNUNET_REST_Plugin *api; - - if (NULL != plugin.cfg) - return NULL; /* can only initialize once! */ - memset (&plugin, 0, sizeof (struct Plugin)); - plugin.cfg = cfg; - api = GNUNET_new (struct GNUNET_REST_Plugin); - api->cls = &plugin; - api->name = GNUNET_REST_API_NS_NAMESTORE; - api->process_request = &rest_identity_process_request; - GNUNET_asprintf (&allow_methods, - "%s, %s, %s, %s, %s", - MHD_HTTP_METHOD_GET, - MHD_HTTP_METHOD_POST, - MHD_HTTP_METHOD_PUT, - MHD_HTTP_METHOD_DELETE, - MHD_HTTP_METHOD_OPTIONS); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - _("Namestore REST API initialized\n")); - return api; -} - - -/** - * Exit point from the plugin. - * - * @param cls the plugin context (as returned by "init") - * @return always NULL - */ -void * -libgnunet_plugin_rest_namestore_done (void *cls) -{ - struct GNUNET_REST_Plugin *api = cls; - struct Plugin *plugin = api->cls; - - plugin->cfg = NULL; - GNUNET_free (api); - GNUNET_free_non_null (allow_methods); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Namestore REST plugin is finished\n"); - return NULL; -} - -/* end of plugin_rest_namestore.c */ -- cgit v1.2.3 From 7d1449573337751de58055d89c954e0c4ebbe6f4 Mon Sep 17 00:00:00 2001 From: Phil Date: Wed, 1 Aug 2018 03:25:18 +0200 Subject: fix makefiles --- src/identity/Makefile.am | 2 -- src/json/Makefile.am | 1 + src/namestore/Makefile.am | 4 ++-- 3 files changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/identity/Makefile.am b/src/identity/Makefile.am index b8e70fffb..e7104f0c3 100644 --- a/src/identity/Makefile.am +++ b/src/identity/Makefile.am @@ -60,8 +60,6 @@ libgnunet_plugin_rest_identity_la_SOURCES = \ libgnunet_plugin_rest_identity_la_LIBADD = \ libgnunetidentity.la \ $(top_builddir)/src/rest/libgnunetrest.la \ - $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \ - $(top_builddir)/src/jsonapi/libgnunetjsonapiutils.la \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ $(LTLIBINTL) -ljansson -lmicrohttpd libgnunet_plugin_rest_identity_la_LDFLAGS = \ diff --git a/src/json/Makefile.am b/src/json/Makefile.am index 04f27fec7..f3fa28d69 100644 --- a/src/json/Makefile.am +++ b/src/json/Makefile.am @@ -20,6 +20,7 @@ libgnunetjson_la_SOURCES = \ json_gnsrecord.c libgnunetjson_la_LIBADD = \ $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ -ljansson \ $(XLIB) diff --git a/src/namestore/Makefile.am b/src/namestore/Makefile.am index 777e722c2..7f44c2a71 100644 --- a/src/namestore/Makefile.am +++ b/src/namestore/Makefile.am @@ -230,8 +230,8 @@ libgnunet_plugin_rest_namestore_la_LIBADD = \ libgnunetnamestore.la \ $(top_builddir)/src/rest/libgnunetrest.la \ $(top_builddir)/src/identity/libgnunetidentity.la \ - $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \ - $(top_builddir)/src/jsonapi/libgnunetjsonapiutils.la \ + $(top_builddir)/src/json/libgnunetjson.la \ + $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ $(LTLIBINTL) -ljansson -lmicrohttpd libgnunet_plugin_rest_namestore_la_LDFLAGS = \ -- cgit v1.2.3 From 83095b7bbf49263d66ab1d89d0535e8fee2a9d01 Mon Sep 17 00:00:00 2001 From: Phil Date: Wed, 1 Aug 2018 03:26:50 +0200 Subject: -fix json and namestore --- src/json/json_generator.c | 2 +- src/json/json_gnsrecord.c | 12 ++++++++++-- src/namestore/plugin_rest_namestore.c | 10 +--------- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/json/json_generator.c b/src/json/json_generator.c index 7b24a3c12..d8c82bc86 100644 --- a/src/json/json_generator.c +++ b/src/json/json_generator.c @@ -166,7 +166,7 @@ GNUNET_JSON_from_rsa_signature (const struct GNUNET_CRYPTO_RsaSignature *sig) */ json_t * GNUNET_JSON_from_gns_record (const char* rname, - const struct GNUNET_GNSRECORD_Data *rd) + const struct GNUNET_GNSRECORD_Data *rd) { struct GNUNET_TIME_Absolute expiration_time; const char *expiration_time_str; diff --git a/src/json/json_gnsrecord.c b/src/json/json_gnsrecord.c index 48b78f38b..4f6d30748 100644 --- a/src/json/json_gnsrecord.c +++ b/src/json/json_gnsrecord.c @@ -23,7 +23,6 @@ */ #include "platform.h" #include "gnunet_util_lib.h" -#include "gnunet_gnsrecord_lib.h" #include "gnunet_json_lib.h" #define GNUNET_JSON_GNSRECORD_VALUE "value" @@ -111,7 +110,16 @@ parse_gnsrecordobject (void *cls, } else { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Value invalid for expiration time"); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Expiration time invalid"); + return GNUNET_SYSERR; + } + // check if flag is a valid enum value + if ((GNUNET_GNSRECORD_RF_NONE != flag) + && (GNUNET_GNSRECORD_RF_PRIVATE != flag) + && (GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION != flag) + && (GNUNET_GNSRECORD_RF_SHADOW_RECORD) != flag) + { + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Flag invalid"); return GNUNET_SYSERR; } gnsrecord_object->flags = (enum GNUNET_GNSRECORD_Flags)flag; diff --git a/src/namestore/plugin_rest_namestore.c b/src/namestore/plugin_rest_namestore.c index 6924c53a4..90928165e 100644 --- a/src/namestore/plugin_rest_namestore.c +++ b/src/namestore/plugin_rest_namestore.c @@ -32,6 +32,7 @@ #include "microhttpd.h" #include + #define GNUNET_REST_API_NS_NAMESTORE "/namestore" #define GNUNET_REST_SUBSYSTEM_NAMESTORE "namestore" @@ -40,8 +41,6 @@ #define GNUNET_REST_NAMESTORE_RD_COUNT 1 -//TODO define other variables - /** * The configuration handle */ @@ -60,8 +59,6 @@ struct Plugin const struct GNUNET_CONFIGURATION_Handle *cfg; }; -//TODO add specific structs - /** * The default namestore ego */ @@ -86,8 +83,6 @@ struct EgoEntry struct RequestHandle { - //TODO add specific entries - /** * Records to store */ @@ -180,8 +175,6 @@ struct RequestHandle }; - -//TODO add specific cleanup /** * Cleanup lookup handle * @param handle Handle to clean up @@ -638,7 +631,6 @@ options_cont (struct GNUNET_REST_RequestHandle *con_handle, static void init_cont (struct RequestHandle *handle) { - //TODO specify parameter of init_cont if necessary struct GNUNET_REST_RequestHandlerError err; static const struct GNUNET_REST_RequestHandler handlers[] = { {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE, &namestore_get}, -- cgit v1.2.3 From 791192b0de6bae796b9eecb7f6e26517559a02a1 Mon Sep 17 00:00:00 2001 From: Phil Date: Wed, 1 Aug 2018 03:27:43 +0200 Subject: -wip peerinfo, async call work in progress --- src/peerinfo/Makefile.am | 22 ++ src/peerinfo/plugin_rest_peerinfo.c | 641 ++++++++++++++++++++++++++++++++++++ 2 files changed, 663 insertions(+) create mode 100644 src/peerinfo/plugin_rest_peerinfo.c (limited to 'src') diff --git a/src/peerinfo/Makefile.am b/src/peerinfo/Makefile.am index eeb5ee54e..5e96250b1 100644 --- a/src/peerinfo/Makefile.am +++ b/src/peerinfo/Makefile.am @@ -5,6 +5,8 @@ pkgcfgdir= $(pkgdatadir)/config.d/ libexecdir= $(pkglibdir)/libexec/ +plugindir = $(libdir)/gnunet + pkgcfg_DATA = \ peerinfo.conf @@ -25,6 +27,8 @@ libgnunetpeerinfo_la_SOURCES = \ libgnunetpeerinfo_la_LIBADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/util/libgnunetutil.la \ + $(top_builddir)/src/json/libgnunetjson.la \ + $(top_builddir)/src/transport/libgnunettransport.la \ $(XLIB) \ $(LTLIBINTL) libgnunetpeerinfo_la_LDFLAGS = \ @@ -35,12 +39,30 @@ libgnunetpeerinfo_la_LDFLAGS = \ libexec_PROGRAMS = \ gnunet-service-peerinfo +if HAVE_MHD +if HAVE_JSON +plugin_LTLIBRARIES = \ + libgnunet_plugin_rest_peerinfo.la +endif +endif + gnunet_service_peerinfo_SOURCES = \ gnunet-service-peerinfo.c gnunet_service_peerinfo_LDADD = \ $(top_builddir)/src/hello/libgnunethello.la \ $(top_builddir)/src/statistics/libgnunetstatistics.la \ $(top_builddir)/src/util/libgnunetutil.la + + +libgnunet_plugin_rest_peerinfo_la_SOURCES = \ + plugin_rest_peerinfo.c +libgnunet_plugin_rest_peerinfo_la_LIBADD = \ + libgnunetpeerinfo.la \ + $(top_builddir)/src/rest/libgnunetrest.la \ + $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ + $(LTLIBINTL) -ljansson -lmicrohttpd +libgnunet_plugin_rest_peerinfo_la_LDFLAGS = \ + $(GN_PLUGIN_LDFLAGS) if HAVE_BENCHMARKS PEERINFO_BENCHMARKS = \ diff --git a/src/peerinfo/plugin_rest_peerinfo.c b/src/peerinfo/plugin_rest_peerinfo.c new file mode 100644 index 000000000..408f9a6f7 --- /dev/null +++ b/src/peerinfo/plugin_rest_peerinfo.c @@ -0,0 +1,641 @@ +/* + This file is part of GNUnet. + 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 Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + */ +/** + * @author Martin Schanzenbach + * @author Philippe Buschmann + * @file peerinfo/plugin_rest_peerinfo.c + * @brief GNUnet Peerinfo REST plugin + */ + +#include "platform.h" +#include "gnunet_rest_plugin.h" +#include "gnunet_peerinfo_service.h" +#include "gnunet_transport_service.h" +#include "gnunet_rest_lib.h" +#include "gnunet_json_lib.h" +#include "microhttpd.h" +#include + +#define GNUNET_REST_API_NS_PEERINFO "/peerinfo" +#define GNUNET_REST_API_PEERINFO_PEER "peer" +#define GNUNET_REST_API_PEERINFO_FRIEND "friend" + +//TODO define other variables +#define GNUNET_REST_ERROR_UNKNOWN "Unkown Error" + +/** + * The configuration handle + */ +const struct GNUNET_CONFIGURATION_Handle *cfg; + +/** + * HTTP methods allows for this plugin + */ +static char* allow_methods; + +/** + * @brief struct returned by the initialization function of the plugin + */ +struct Plugin +{ + const struct GNUNET_CONFIGURATION_Handle *cfg; +}; + +//TODO add specific structs + + + +struct RequestHandle +{ + //TODO add specific entries + json_t *temp_array; + char *expiration_str; + const char *address; + + /** + * Iteration peer public key + */ + char *pubkey; + + /** + * JSON array response + */ + json_t *response; + + /** + * Handle to PEERINFO it + */ + struct GNUNET_PEERINFO_IteratorContext *list_it; + + /** + * Handle to PEERINFO + */ + struct GNUNET_PEERINFO_Handle *peerinfo_handle; + + /** + * Rest connection + */ + struct GNUNET_REST_RequestHandle *rest_handle; + + /** + * Desired timeout for the lookup (default is no timeout). + */ + struct GNUNET_TIME_Relative timeout; + + /** + * ID of a task associated with the resolution process. + */ + struct GNUNET_SCHEDULER_Task *timeout_task; + + /** + * The plugin result processor + */ + GNUNET_REST_ResultProcessor proc; + + /** + * The closure of the result processor + */ + void *proc_cls; + + /** + * The url + */ + char *url; + + /** + * Error response message + */ + char *emsg; + + /** + * Reponse code + */ + int response_code; + +}; + + +/** + * Cleanup lookup handle + * @param handle Handle to clean up + */ +static void +cleanup_handle (void *cls) +{ + struct RequestHandle *handle = cls; + + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Test: %i\n", NULL == handle); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Cleaning up\n"); + if (NULL != handle->timeout_task) + { + GNUNET_SCHEDULER_cancel (handle->timeout_task); + handle->timeout_task = NULL; + } + if (NULL != handle->url) + GNUNET_free (handle->url); + if (NULL != handle->emsg) + GNUNET_free (handle->emsg); + + if (NULL != handle->response) + { + json_decref(handle->response); + handle->response = NULL; + } + + if (NULL != handle->list_it) + { + GNUNET_PEERINFO_iterate_cancel(handle->list_it); + handle->list_it = NULL; + } + + if (NULL != handle->peerinfo_handle) + { + GNUNET_PEERINFO_disconnect(handle->peerinfo_handle); + handle->peerinfo_handle = NULL; + } + + //TODO add specific cleanup + + GNUNET_free (handle); +} + + +/** + * Task run on errors. Reports an error and cleans up everything. + * + * @param cls the `struct RequestHandle` + */ +static void +do_error (void *cls) +{ + struct RequestHandle *handle = cls; + struct MHD_Response *resp; + json_t *json_error = json_object(); + char *response; + + if (NULL == handle->emsg) + handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_UNKNOWN); + + json_object_set_new(json_error,"error", json_string(handle->emsg)); + + if (0 == handle->response_code) + handle->response_code = MHD_HTTP_OK; + response = json_dumps (json_error, 0); + resp = GNUNET_REST_create_response (response); + handle->proc (handle->proc_cls, resp, handle->response_code); + json_decref(json_error); + GNUNET_free(response); + GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); +} + + +/** + * Function that assembles our response. + */ +static void +peerinfo_list_finished (void *cls) +{ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "6\n"); + struct RequestHandle *handle = cls; + char *result_str; + struct MHD_Response *resp; + + if (NULL == handle->response) + { + handle->emsg = GNUNET_strdup ("No peers found"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + + result_str = json_dumps (handle->response, 0); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); + resp = GNUNET_REST_create_response (result_str); + handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); + GNUNET_free_non_null (result_str); + GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); +} + + +/** + * Set @a cls to #GNUNET_YES (we have an address!). + * + * @param cls closure, an `int *` + * @param address the address (ignored) + * @param expiration expiration time (call is ignored if this is in the past) + * @return #GNUNET_SYSERR to stop iterating (unless expiration has occured) + */ +static int +check_has_addr (void *cls, + const struct GNUNET_HELLO_Address *address, + struct GNUNET_TIME_Absolute expiration) +{ + int *arg = cls; + if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us) + { + return GNUNET_YES; /* ignore this address */ + } + *arg = GNUNET_YES; + return GNUNET_SYSERR; +} + +static void +create_array(void *cls) +{ + struct RequestHandle *handle = cls; +// json_t *object; +// object = json_object(); +// +// json_object_set(object,"address",json_string(handle->address)); +// json_object_set(object,"expires",json_string(handle->expiration_str)); +// +// if(NULL == handle->temp_array) +// { +// handle->temp_array = json_array(); +// } +// +// json_array_append(handle->temp_array,object); +// +// json_decref(object); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "5\n"); + json_object_set(handle->response, handle->pubkey, handle->temp_array); + json_decref (handle->temp_array); +} + +static void +create_tmp_array (void *cls) +{ + struct RequestHandle *handle = cls; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "4\n"); + json_t *object; + json_t *address_json = json_string (handle->address); + json_t *expires_json = json_string (handle->expiration_str); + object = json_object (); + + json_object_set (object, "address", address_json); + json_decref(address_json); + json_object_set (object, "expires", expires_json); + json_decref(expires_json); + GNUNET_free(handle->expiration_str); + + if (NULL == handle->temp_array) + { + handle->temp_array = json_array (); + } + + json_array_append (handle->temp_array, object); + + json_decref (object); +} + +static void +addr_to_str_cb (void *cls, + const char *address, + int res) +{ + struct RequestHandle *handle = cls; + if (NULL == address) + { + return; + } + if (GNUNET_OK != res) + { + return; + } + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "3\n"); + handle->address = GNUNET_strdup(address); + GNUNET_assert(false); +} + +/** + * Set @a cls to #GNUNET_YES (we have an address!). + * + * @param cls closure + * @param address the address (ignored) + * @param expiration expiration time (call is ignored if this is in the past) + * @return #GNUNET_SYSERR to stop iterating (unless expiration has occured) + */ +static int +address_iteration (void *cls, + const struct GNUNET_HELLO_Address *address, + struct GNUNET_TIME_Absolute expiration) +{ + struct RequestHandle *handle = cls; + char *expiration_tmp; + + if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us) + { + return GNUNET_YES; /* ignore this address */ + } + expiration_tmp = GNUNET_STRINGS_absolute_time_to_string(expiration); + handle->expiration_str = GNUNET_strdup(expiration_tmp); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "2\n"); + GNUNET_TRANSPORT_address_to_string(cfg, + address, + GNUNET_NO, + GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10), + &addr_to_str_cb, + handle); + + GNUNET_SCHEDULER_add_now(&create_tmp_array,handle); + +// GNUNET_SCHEDULER_add_delayed ( +// GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 11), +// &create_array, +// handle); + return GNUNET_YES; +} + + +/** + * Callback that processes each of the known HELLOs for the + * iteration response construction. + * + * @param cls closure, NULL + * @param peer id of the peer, NULL for last call + * @param hello hello message for the peer (can be NULL) + * @param err_msg message + */ +void +peerinfo_list_iteration(void *cls, + const struct GNUNET_PeerIdentity *peer, + const struct GNUNET_HELLO_Message *hello, + const char *err_msg) +{ + struct RequestHandle *handle = cls; + int has_addr; + + if (NULL == handle->response) + { + handle->response = json_object(); + } + + if (NULL != err_msg) + { + GNUNET_assert (NULL == peer); + handle->list_it = NULL; + handle->emsg = GNUNET_strdup ("Error in communication with peerinfo"); + handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + if (NULL == peer) + { + handle->list_it = NULL; + GNUNET_SCHEDULER_add_now (&peerinfo_list_finished, handle); + return; + } + if (NULL == hello) + return; + has_addr = GNUNET_NO; + GNUNET_HELLO_iterate_addresses (hello, + GNUNET_NO, + &check_has_addr, + &has_addr); + if (GNUNET_NO == has_addr) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "HELLO for peer `%4s' has no address, not suitable for hostlist!\n", + GNUNET_i2s (peer)); + return; + } + + if (NULL != handle->pubkey) + GNUNET_free (handle->pubkey); + handle->pubkey = GNUNET_CRYPTO_eddsa_public_key_to_string(&peer->public_key); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "1\n"); + GNUNET_HELLO_iterate_addresses (hello, + GNUNET_NO, + &address_iteration, + handle); + GNUNET_SCHEDULER_add_now(&create_array,handle); +} + +/** + * Handle peerinfo GET request + * + * @param con_handle the connection handle + * @param url the url + * @param cls the RequestHandle + */ +void +peerinfo_get (struct GNUNET_REST_RequestHandle *con_handle, + const char* url, + void *cls) +{ + struct RequestHandle *handle = cls; + struct GNUNET_HashCode key; + const struct GNUNET_PeerIdentity *specific_peer; + GNUNET_PEER_Id peer_id; + int include_friend_only; + + include_friend_only = GNUNET_NO; + GNUNET_CRYPTO_hash (GNUNET_REST_API_PEERINFO_FRIEND, + strlen (GNUNET_REST_API_PEERINFO_FRIEND), + &key); + if ( GNUNET_YES + == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, + &key)) + { + include_friend_only = *(int*)GNUNET_CONTAINER_multihashmap_get ( + con_handle->url_param_map, &key); + } + if(GNUNET_YES != include_friend_only) + { + include_friend_only = GNUNET_NO; + } + + specific_peer = NULL; + GNUNET_CRYPTO_hash (GNUNET_REST_API_PEERINFO_PEER, + strlen (GNUNET_REST_API_PEERINFO_PEER), + &key); + if ( GNUNET_YES + == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, + &key)) + { + peer_id = *(unsigned int*)GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, &key); + specific_peer = GNUNET_PEER_resolve2(peer_id); + } + + + //TODO friend_only and special peer + + //TODO add behaviour and response + //TODO maybe notify better than iteration + + handle->list_it = GNUNET_PEERINFO_iterate(handle->peerinfo_handle, + include_friend_only, + specific_peer, + &peerinfo_list_iteration, + handle); +} + + + +/** + * Respond to OPTIONS request + * + * @param con_handle the connection handle + * @param url the url + * @param cls the RequestHandle + */ +static void +options_cont (struct GNUNET_REST_RequestHandle *con_handle, + const char* url, + void *cls) +{ + struct MHD_Response *resp; + struct RequestHandle *handle = cls; + + //independent of path return all options + resp = GNUNET_REST_create_response (NULL); + MHD_add_response_header (resp, + "Access-Control-Allow-Methods", + allow_methods); + handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); + GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); + return; +} + + +/** + * Handle rest request + * + * @param handle the request handle + */ +static void +init_cont (struct RequestHandle *handle) +{ + //TODO specify parameter of init_cont if necessary + struct GNUNET_REST_RequestHandlerError err; + static const struct GNUNET_REST_RequestHandler handlers[] = { + {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_PEERINFO, &peerinfo_get}, + {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_PEERINFO, &options_cont}, + GNUNET_REST_HANDLER_END + }; + + if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle, + handlers, + &err, + handle)) + { + handle->response_code = err.error_code; + GNUNET_SCHEDULER_add_now (&do_error, handle); + } +} + + +/** + * Function processing the REST call + * + * @param method HTTP method + * @param url URL of the HTTP request + * @param data body of the HTTP request (optional) + * @param data_size length of the body + * @param proc callback function for the result + * @param proc_cls closure for callback function + * @return GNUNET_OK if request accepted + */ +static void +rest_process_request(struct GNUNET_REST_RequestHandle *rest_handle, + GNUNET_REST_ResultProcessor proc, + void *proc_cls) +{ + struct RequestHandle *handle = GNUNET_new (struct RequestHandle); + + handle->response_code = 0; + handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; + handle->proc_cls = proc_cls; + handle->proc = proc; + 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, "Connecting...\n"); + //TODO connect to specific service + //connect ( cfg, [..., &callback_function, handle]); + handle->peerinfo_handle = GNUNET_PEERINFO_connect(cfg); + init_cont(handle); + handle->timeout_task = + GNUNET_SCHEDULER_add_delayed (handle->timeout, + &do_error, + handle); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n"); +} + + +/** + * Entry point for the plugin. + * + * @param cls Config info + * @return NULL on error, otherwise the plugin context + */ +void * +libgnunet_plugin_rest_peerinfo_init (void *cls) +{ + static struct Plugin plugin; + struct GNUNET_REST_Plugin *api; + + cfg = cls; + if (NULL != plugin.cfg) + return NULL; /* can only initialize once! */ + memset (&plugin, 0, sizeof (struct Plugin)); + plugin.cfg = cfg; + api = GNUNET_new (struct GNUNET_REST_Plugin); + api->cls = &plugin; + api->name = GNUNET_REST_API_NS_PEERINFO; + api->process_request = &rest_process_request; + GNUNET_asprintf (&allow_methods, + "%s, %s, %s, %s, %s", + MHD_HTTP_METHOD_GET, + MHD_HTTP_METHOD_POST, + MHD_HTTP_METHOD_PUT, + MHD_HTTP_METHOD_DELETE, + MHD_HTTP_METHOD_OPTIONS); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + _("Peerinfo REST API initialized\n")); + return api; +} + + +/** + * Exit point from the plugin. + * + * @param cls the plugin context (as returned by "init") + * @return always NULL + */ +void * +libgnunet_plugin_rest_peerinfo_done (void *cls) +{ + struct GNUNET_REST_Plugin *api = cls; + struct Plugin *plugin = api->cls; + plugin->cfg = NULL; + + GNUNET_free_non_null (allow_methods); + GNUNET_free (api); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Peerinfo REST plugin is finished\n"); + return NULL; +} + +/* end of plugin_rest_peerinfo.c */ + -- cgit v1.2.3 From 894aaa280790c55e6ffb10aa189a5cadc5bad8f7 Mon Sep 17 00:00:00 2001 From: Phil Date: Thu, 2 Aug 2018 03:08:36 +0200 Subject: fix lowercase identities --- src/identity/plugin_rest_identity.c | 80 ++++++++++++++++++++++--------- src/identity/test_plugin_rest_identity.sh | 4 +- 2 files changed, 60 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/identity/plugin_rest_identity.c b/src/identity/plugin_rest_identity.c index 49fa9f0fb..83bf4075d 100644 --- a/src/identity/plugin_rest_identity.c +++ b/src/identity/plugin_rest_identity.c @@ -326,13 +326,13 @@ ego_get (struct GNUNET_REST_RequestHandle *con_handle, const char* url, struct GNUNET_HashCode key; struct MHD_Response *resp; char *keystring; - const char *egoname; + char *egoname; json_t *json_root; json_t *json_ego; char *result_str; size_t index; - //if subsystem + //requested default identity of subsystem GNUNET_CRYPTO_hash (GNUNET_REST_PARAM_SUBSYSTEM, strlen (GNUNET_REST_PARAM_SUBSYSTEM), &key); if ( GNUNET_YES @@ -360,7 +360,7 @@ ego_get (struct GNUNET_REST_RequestHandle *con_handle, const char* url, egoname = NULL; keystring = NULL; - //if only one identity requested with key + //one identity requested with key GNUNET_CRYPTO_hash (GNUNET_REST_PARAM_PUBKEY, strlen (GNUNET_REST_PARAM_PUBKEY), &key); @@ -381,7 +381,7 @@ ego_get (struct GNUNET_REST_RequestHandle *con_handle, const char* url, } } - //if only one identity requested with name + //one identity requested with name if (NULL == egoname) { GNUNET_CRYPTO_hash (GNUNET_REST_PARAM_NAME, @@ -393,6 +393,8 @@ ego_get (struct GNUNET_REST_RequestHandle *con_handle, const char* url, { egoname = GNUNET_CONTAINER_multihashmap_get ( handle->rest_handle->url_param_map, &key); + //LOWERCASE ego names? + GNUNET_STRINGS_utf8_tolower(egoname, egoname); } } @@ -410,10 +412,10 @@ ego_get (struct GNUNET_REST_RequestHandle *con_handle, const char* url, json_ego = json_object (); json_object_set_new (json_ego, - GNUNET_REST_PARAM_PUBKEY, + GNUNET_REST_PARAM_PUBKEY, json_string (ego_entry->keystring)); json_object_set_new (json_ego, - GNUNET_REST_PARAM_NAME, + GNUNET_REST_PARAM_NAME, json_string (ego_entry->identifier)); json_array_append (json_root, json_ego); } @@ -645,7 +647,7 @@ ego_create (struct GNUNET_REST_RequestHandle *con_handle, const char* url, term_data[handle->data_size] = '\0'; GNUNET_memcpy(term_data, handle->data, handle->data_size); data_js = json_loads (term_data, - JSON_DECODE_ANY, + JSON_DECODE_ANY, &err); if (NULL == data_js) @@ -717,35 +719,69 @@ void ego_delete (struct GNUNET_REST_RequestHandle *con_handle, const char* url, void *cls) { - const char *keystring; + struct RequestHandle *handle = cls; struct EgoEntry *ego_entry; struct GNUNET_HashCode key; struct MHD_Response *resp; - struct RequestHandle *handle = cls; + const char *keystring; + char *egoname; int ego_exists = GNUNET_NO; - //if only one identity requested + keystring = NULL; + egoname = NULL; + + //delete with pubkey GNUNET_CRYPTO_hash (GNUNET_REST_PARAM_PUBKEY, strlen (GNUNET_REST_PARAM_PUBKEY), &key); - if ( GNUNET_NO + if ( GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains ( handle->rest_handle->url_param_map, &key)) { - handle->emsg = GNUNET_strdup("Missing parameter pubkey"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; + keystring = GNUNET_CONTAINER_multihashmap_get ( + handle->rest_handle->url_param_map,&key); } - keystring = GNUNET_CONTAINER_multihashmap_get ( - handle->rest_handle->url_param_map,&key); - for (ego_entry = handle->ego_head; - NULL != ego_entry; ego_entry = ego_entry->next) + GNUNET_CRYPTO_hash (GNUNET_REST_PARAM_NAME, + strlen (GNUNET_REST_PARAM_NAME), &key); + if ( GNUNET_YES + == GNUNET_CONTAINER_multihashmap_contains ( + handle->rest_handle->url_param_map, &key)) { - if (0 != strcasecmp (keystring, ego_entry->keystring)) - continue; - ego_exists = GNUNET_YES; - break; + egoname = GNUNET_CONTAINER_multihashmap_get ( + handle->rest_handle->url_param_map, &key); + //LOWERCASE ego names? + GNUNET_STRINGS_utf8_tolower(egoname, egoname); + } + + if (NULL != keystring) + { + for (ego_entry = handle->ego_head; + NULL != ego_entry; ego_entry = ego_entry->next) + { + if (0 != strcasecmp (keystring, ego_entry->keystring)) + continue; + ego_exists = GNUNET_YES; + break; + } } + else if (NULL != egoname) + { + for (ego_entry = handle->ego_head; + NULL != ego_entry; ego_entry = ego_entry->next) + { + if (0 != strcasecmp (egoname, ego_entry->identifier)) + continue; + ego_exists = GNUNET_YES; + break; + } + } + else + { + handle->emsg = GNUNET_strdup("Missing parameter pubkey or name"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + if (GNUNET_NO == ego_exists) { resp = GNUNET_REST_create_response (NULL); diff --git a/src/identity/test_plugin_rest_identity.sh b/src/identity/test_plugin_rest_identity.sh index 170f3e928..f391f827f 100755 --- a/src/identity/test_plugin_rest_identity.sh +++ b/src/identity/test_plugin_rest_identity.sh @@ -84,8 +84,9 @@ fi id="$(gnunet-identity -d | grep "Test - " | sed "s/Test - //g")" #Test GET (one identity) for success and error json +#Only lowercase cache="$(curl --silent "${link_to_api}?name=Test" | grep "error")" -if [ "" != "$cache" ] +if [ "" == "$cache" ] then exit 1 fi @@ -96,7 +97,6 @@ then exit 1 fi - #Test DELETE success code, error response code and error json #echo "Next tests for DELETE will probably fail when POST fails" cache="$(curl -v -X "DELETE" "${link_to_api}?pubkey=$id" 2>&1 | grep "HTTP/1.1 404")" -- cgit v1.2.3 From 36a899058d6863eee242a026b282e6150b4855fa Mon Sep 17 00:00:00 2001 From: Phil Date: Thu, 2 Aug 2018 03:09:22 +0200 Subject: add peerinfo rest api --- src/peerinfo/plugin_rest_peerinfo.c | 398 ++++++++++++++++++++++++------------ 1 file changed, 267 insertions(+), 131 deletions(-) (limited to 'src') diff --git a/src/peerinfo/plugin_rest_peerinfo.c b/src/peerinfo/plugin_rest_peerinfo.c index 408f9a6f7..a65089b32 100644 --- a/src/peerinfo/plugin_rest_peerinfo.c +++ b/src/peerinfo/plugin_rest_peerinfo.c @@ -38,6 +38,10 @@ //TODO define other variables #define GNUNET_REST_ERROR_UNKNOWN "Unkown Error" +/** + * How long until we time out during address lookup? + */ +#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5) /** * The configuration handle */ @@ -59,6 +63,95 @@ struct Plugin //TODO add specific structs +/** + * Record we keep for each printable address. + */ +struct AddressRecord +{ + /** + * Current address-to-string context (if active, otherwise NULL). + */ + struct GNUNET_TRANSPORT_AddressToStringContext *atsc; + + /** + * Address expiration time + */ + struct GNUNET_TIME_Absolute expiration; + + /** + * Printable address. + */ + char *result; + + /** + * Print context this address record belongs to. + */ + struct PrintContext *pc; +}; + + +/** + * Structure we use to collect printable address information. + */ +struct PrintContext +{ + + /** + * Kept in DLL. + */ + struct PrintContext *next; + + /** + * Kept in DLL. + */ + struct PrintContext *prev; + + /** + * Identity of the peer. + */ + struct GNUNET_PeerIdentity peer; + + /** + * List of printable addresses. + */ + struct AddressRecord *address_list; + + /** + * Number of completed addresses in @e address_list. + */ + unsigned int num_addresses; + + /** + * Number of addresses allocated in @e address_list. + */ + unsigned int address_list_size; + + /** + * Current offset in @e address_list (counted down). + */ + unsigned int off; + + /** + * Hello was friend only, #GNUNET_YES or #GNUNET_NO + */ + int friend_only; + + /** + * RequestHandle + */ + struct RequestHandle *handle; + +}; + +/** + * Head of list of print contexts. + */ +static struct PrintContext *pc_head; + +/** + * Tail of list of print contexts. + */ +static struct PrintContext *pc_tail; struct RequestHandle { @@ -139,8 +232,6 @@ cleanup_handle (void *cls) { struct RequestHandle *handle = cls; - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Test: %i\n", NULL == handle); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n"); if (NULL != handle->timeout_task) @@ -212,7 +303,6 @@ do_error (void *cls) static void peerinfo_list_finished (void *cls) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "6\n"); struct RequestHandle *handle = cls; char *result_str; struct MHD_Response *resp; @@ -234,132 +324,177 @@ peerinfo_list_finished (void *cls) /** - * Set @a cls to #GNUNET_YES (we have an address!). + * Iterator callback to go over all addresses and count them. * - * @param cls closure, an `int *` - * @param address the address (ignored) - * @param expiration expiration time (call is ignored if this is in the past) - * @return #GNUNET_SYSERR to stop iterating (unless expiration has occured) + * @param cls `struct PrintContext *` with `off` to increment + * @param address the address + * @param expiration expiration time + * @return #GNUNET_OK to keep the address and continue */ static int -check_has_addr (void *cls, - const struct GNUNET_HELLO_Address *address, - struct GNUNET_TIME_Absolute expiration) +count_address (void *cls, + const struct GNUNET_HELLO_Address *address, + struct GNUNET_TIME_Absolute expiration) { - int *arg = cls; + struct PrintContext *pc = cls; + if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us) { - return GNUNET_YES; /* ignore this address */ + return GNUNET_OK; /* ignore expired address */ } - *arg = GNUNET_YES; - return GNUNET_SYSERR; -} -static void -create_array(void *cls) -{ - struct RequestHandle *handle = cls; -// json_t *object; -// object = json_object(); -// -// json_object_set(object,"address",json_string(handle->address)); -// json_object_set(object,"expires",json_string(handle->expiration_str)); -// -// if(NULL == handle->temp_array) -// { -// handle->temp_array = json_array(); -// } -// -// json_array_append(handle->temp_array,object); -// -// json_decref(object); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "5\n"); - json_object_set(handle->response, handle->pubkey, handle->temp_array); - json_decref (handle->temp_array); + pc->off++; + return GNUNET_OK; } + +/** + * Print the collected address information to the console and free @a pc. + * + * @param pc printing context + */ static void -create_tmp_array (void *cls) +dump_pc (struct PrintContext *pc) { - struct RequestHandle *handle = cls; - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "4\n"); + struct RequestHandle *handle; + unsigned int i; + json_t *temp_array; json_t *object; - json_t *address_json = json_string (handle->address); - json_t *expires_json = json_string (handle->expiration_str); - object = json_object (); + json_t *address; + json_t *expires; + char *friend_and_peer; - json_object_set (object, "address", address_json); - json_decref(address_json); - json_object_set (object, "expires", expires_json); - json_decref(expires_json); - GNUNET_free(handle->expiration_str); + temp_array = json_array(); - if (NULL == handle->temp_array) +// printf (_("%sPeer `%s'\n"), +// (GNUNET_YES == pc->friend_only) ? "F2F: " : "", +// GNUNET_i2s_full (&pc->peer)); + for (i = 0; i < pc->num_addresses; i++) { - handle->temp_array = json_array (); + if (NULL != pc->address_list[i].result) + { + object = json_object (); + address = json_string(pc->address_list[i].result); + expires = json_string( + GNUNET_STRINGS_absolute_time_to_string (pc->address_list[i].expiration)); + json_object_set (object, "address", address); + json_object_set (object, "expires", expires); + + json_decref(address); + json_decref(expires); + + json_array_append(temp_array, object); + json_decref(object); + GNUNET_free (pc->address_list[i].result); + } } - json_array_append (handle->temp_array, object); + if (0 < json_array_size(temp_array)) + { + GNUNET_asprintf(&friend_and_peer, + "%s%s", + (GNUNET_YES == pc->friend_only) ? "F2F:" : "", + GNUNET_i2s_full (&pc->peer)); + json_object_set(pc->handle->response, + friend_and_peer, + temp_array); + GNUNET_free(friend_and_peer); + } + + json_decref (temp_array); + + GNUNET_free_non_null (pc->address_list); + GNUNET_CONTAINER_DLL_remove (pc_head, + pc_tail, + pc); + handle = pc->handle; + GNUNET_free (pc); + + if ( (NULL == pc_head) && + (NULL == handle->list_it) ) + { + GNUNET_SCHEDULER_add_now (&peerinfo_list_finished, handle); + } - json_decref (object); } + +/** + * Function to call with a human-readable format of an address + * + * @param cls closure + * @param address NULL on error, otherwise 0-terminated printable UTF-8 string + * @param res result of the address to string conversion: + * if #GNUNET_OK: address was valid (conversion to + * string might still have failed) + * if #GNUNET_SYSERR: address is invalid + */ static void -addr_to_str_cb (void *cls, - const char *address, - int res) +process_resolved_address (void *cls, + const char *address, + int res) { - struct RequestHandle *handle = cls; - if (NULL == address) - { - return; - } - if (GNUNET_OK != res) + struct AddressRecord *ar = cls; + struct PrintContext *pc = ar->pc; + + if (NULL != address) { + if (0 != strlen (address)) + { + if (NULL != ar->result) + GNUNET_free (ar->result); + ar->result = GNUNET_strdup (address); + } return; } - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "3\n"); - handle->address = GNUNET_strdup(address); - GNUNET_assert(false); + ar->atsc = NULL; + if (GNUNET_SYSERR == res) + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + _("Failure: Cannot convert address to string for peer `%s'\n"), + GNUNET_i2s (&ar->pc->peer)); + pc->num_addresses++; + if (pc->num_addresses == pc->address_list_size) + dump_pc (ar->pc); } + /** - * Set @a cls to #GNUNET_YES (we have an address!). + * Iterator callback to go over all addresses. * * @param cls closure - * @param address the address (ignored) - * @param expiration expiration time (call is ignored if this is in the past) - * @return #GNUNET_SYSERR to stop iterating (unless expiration has occured) + * @param address the address + * @param expiration expiration time + * @return #GNUNET_OK to keep the address and continue */ static int -address_iteration (void *cls, - const struct GNUNET_HELLO_Address *address, - struct GNUNET_TIME_Absolute expiration) +print_address (void *cls, + const struct GNUNET_HELLO_Address *address, + struct GNUNET_TIME_Absolute expiration) { - struct RequestHandle *handle = cls; - char *expiration_tmp; + struct PrintContext *pc = cls; + struct AddressRecord *ar; if (0 == GNUNET_TIME_absolute_get_remaining (expiration).rel_value_us) { - return GNUNET_YES; /* ignore this address */ + return GNUNET_OK; /* ignore expired address */ } - expiration_tmp = GNUNET_STRINGS_absolute_time_to_string(expiration); - handle->expiration_str = GNUNET_strdup(expiration_tmp); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "2\n"); - GNUNET_TRANSPORT_address_to_string(cfg, - address, - GNUNET_NO, - GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10), - &addr_to_str_cb, - handle); - - GNUNET_SCHEDULER_add_now(&create_tmp_array,handle); - -// GNUNET_SCHEDULER_add_delayed ( -// GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 11), -// &create_array, -// handle); - return GNUNET_YES; + + GNUNET_assert (0 < pc->off); + ar = &pc->address_list[--pc->off]; + ar->pc = pc; + ar->expiration = expiration; + GNUNET_asprintf (&ar->result, + "%s:%u:%u", + address->transport_name, + address->address_length, + address->local_info); + ar->atsc = GNUNET_TRANSPORT_address_to_string (cfg, + address, + GNUNET_NO, + TIMEOUT, + &process_resolved_address, + ar); + return GNUNET_OK; } @@ -379,52 +514,58 @@ peerinfo_list_iteration(void *cls, const char *err_msg) { struct RequestHandle *handle = cls; - int has_addr; + struct PrintContext *pc; + int friend_only; if (NULL == handle->response) { handle->response = json_object(); } - if (NULL != err_msg) - { - GNUNET_assert (NULL == peer); - handle->list_it = NULL; - handle->emsg = GNUNET_strdup ("Error in communication with peerinfo"); - handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } if (NULL == peer) { handle->list_it = NULL; - GNUNET_SCHEDULER_add_now (&peerinfo_list_finished, handle); + handle->emsg = GNUNET_strdup ("Error in communication with peerinfo"); + if (NULL != err_msg) + { + GNUNET_free(handle->emsg); + handle->emsg = GNUNET_strdup (err_msg); + handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR; + } + if (NULL == pc_head) + GNUNET_SCHEDULER_add_now (&do_error, handle); return; } if (NULL == hello) return; - has_addr = GNUNET_NO; + + friend_only = GNUNET_NO; + if (NULL != hello) + friend_only = GNUNET_HELLO_is_friend_only (hello); + + pc = GNUNET_new(struct PrintContext); + GNUNET_CONTAINER_DLL_insert (pc_head, + pc_tail, + pc); + pc->peer = *peer; + pc->friend_only = friend_only; + pc->handle = handle; GNUNET_HELLO_iterate_addresses (hello, - GNUNET_NO, - &check_has_addr, - &has_addr); - if (GNUNET_NO == has_addr) + GNUNET_NO, + &count_address, + pc); + if (0 == pc->off) { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "HELLO for peer `%4s' has no address, not suitable for hostlist!\n", - GNUNET_i2s (peer)); + dump_pc (pc); return; } - - if (NULL != handle->pubkey) - GNUNET_free (handle->pubkey); - handle->pubkey = GNUNET_CRYPTO_eddsa_public_key_to_string(&peer->public_key); - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "1\n"); + pc->address_list_size = pc->off; + pc->address_list = GNUNET_malloc( + sizeof(struct AddressRecord) * pc->off); GNUNET_HELLO_iterate_addresses (hello, - GNUNET_NO, - &address_iteration, - handle); - GNUNET_SCHEDULER_add_now(&create_array,handle); + GNUNET_NO, + &print_address, + pc); } /** @@ -444,6 +585,7 @@ peerinfo_get (struct GNUNET_REST_RequestHandle *con_handle, const struct GNUNET_PeerIdentity *specific_peer; GNUNET_PEER_Id peer_id; int include_friend_only; + char* include_friend_only_str; include_friend_only = GNUNET_NO; GNUNET_CRYPTO_hash (GNUNET_REST_API_PEERINFO_FRIEND, @@ -453,12 +595,12 @@ peerinfo_get (struct GNUNET_REST_RequestHandle *con_handle, == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, &key)) { - include_friend_only = *(int*)GNUNET_CONTAINER_multihashmap_get ( + include_friend_only_str = GNUNET_CONTAINER_multihashmap_get ( con_handle->url_param_map, &key); - } - if(GNUNET_YES != include_friend_only) - { - include_friend_only = GNUNET_NO; + if (0 == strcmp(include_friend_only_str, "yes")) + { + include_friend_only = GNUNET_YES; + } } specific_peer = NULL; @@ -473,12 +615,6 @@ peerinfo_get (struct GNUNET_REST_RequestHandle *con_handle, specific_peer = GNUNET_PEER_resolve2(peer_id); } - - //TODO friend_only and special peer - - //TODO add behaviour and response - //TODO maybe notify better than iteration - handle->list_it = GNUNET_PEERINFO_iterate(handle->peerinfo_handle, include_friend_only, specific_peer, @@ -560,7 +696,7 @@ rest_process_request(struct GNUNET_REST_RequestHandle *rest_handle, struct RequestHandle *handle = GNUNET_new (struct RequestHandle); handle->response_code = 0; - handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; + handle->timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60); handle->proc_cls = proc_cls; handle->proc = proc; handle->rest_handle = rest_handle; -- cgit v1.2.3 From dc1c69e3109ccd7311a6d1f07ecc9dce0ee4c186 Mon Sep 17 00:00:00 2001 From: Phil Date: Sun, 5 Aug 2018 22:43:35 +0200 Subject: Identity REST API finished --- src/identity/plugin_rest_identity.c | 286 ++++++++++++++--------- src/identity/test_plugin_rest_identity.sh | 371 +++++++++++++----------------- 2 files changed, 329 insertions(+), 328 deletions(-) (limited to 'src') diff --git a/src/identity/plugin_rest_identity.c b/src/identity/plugin_rest_identity.c index 83bf4075d..a518a74cc 100644 --- a/src/identity/plugin_rest_identity.c +++ b/src/identity/plugin_rest_identity.c @@ -265,6 +265,47 @@ do_error (void *cls) GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); } + + +/** + * Get EgoEntry from list with either a public key or a name + * If public key and name are not NULL, it returns the public key result first + * + * @param handle the RequestHandle + * @param pubkey the public key of an identity (only one can be NULL) + * @param name the name of an identity (only one can be NULL) + * @return EgoEntry or NULL if not found + */ +struct EgoEntry* +get_egoentry(struct RequestHandle *handle, char* pubkey, char *name) +{ + struct EgoEntry *ego_entry; + if (NULL != pubkey) + { + for (ego_entry = handle->ego_head; + NULL != ego_entry; + ego_entry = ego_entry->next) + { + if (0 != strcasecmp (pubkey, ego_entry->keystring)) + continue; + return ego_entry; + } + } + if (NULL != name) + { + for (ego_entry = handle->ego_head; + NULL != ego_entry; + ego_entry = ego_entry->next) + { + if (0 != strcasecmp (name, ego_entry->identifier)) + continue; + return ego_entry; + } + } + return NULL; +} + + /** * Callback for GET Request with subsystem * @@ -330,7 +371,6 @@ ego_get (struct GNUNET_REST_RequestHandle *con_handle, const char* url, json_t *json_root; json_t *json_ego; char *result_str; - size_t index; //requested default identity of subsystem GNUNET_CRYPTO_hash (GNUNET_REST_PARAM_SUBSYSTEM, @@ -371,14 +411,14 @@ ego_get (struct GNUNET_REST_RequestHandle *con_handle, const char* url, keystring = GNUNET_CONTAINER_multihashmap_get ( handle->rest_handle->url_param_map, &key); - for (ego_entry = handle->ego_head; - NULL != ego_entry; ego_entry = ego_entry->next) + ego_entry = get_egoentry(handle, keystring, NULL); + if (NULL == ego_entry) { - if ((NULL != keystring) - && (0 != strcmp (keystring, ego_entry->keystring))) - continue; - egoname = ego_entry->identifier; + handle->emsg = GNUNET_strdup("No identity found for public key"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; } + egoname = ego_entry->identifier; } //one identity requested with name @@ -393,6 +433,12 @@ ego_get (struct GNUNET_REST_RequestHandle *con_handle, const char* url, { egoname = GNUNET_CONTAINER_multihashmap_get ( handle->rest_handle->url_param_map, &key); + if (0 >= strlen(egoname)) + { + handle->emsg = GNUNET_strdup("No identity found for name"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } //LOWERCASE ego names? GNUNET_STRINGS_utf8_tolower(egoname, egoname); } @@ -418,6 +464,7 @@ ego_get (struct GNUNET_REST_RequestHandle *con_handle, const char* url, GNUNET_REST_PARAM_NAME, json_string (ego_entry->identifier)); json_array_append (json_root, json_ego); + json_decref (json_ego); } if ((size_t) 0 == json_array_size (json_root)) @@ -432,17 +479,13 @@ ego_get (struct GNUNET_REST_RequestHandle *con_handle, const char* url, GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); resp = GNUNET_REST_create_response (result_str); - //delete json_objects in json_array with macro - json_array_foreach(json_root, index, json_ego ) - { - json_decref (json_ego); - } json_decref (json_root); handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); GNUNET_free(result_str); GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); } + /** * Processing finished * @@ -467,6 +510,7 @@ do_finished (void *cls, const char *emsg) GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); } + /** * Handle identity PUT request * @@ -475,23 +519,22 @@ do_finished (void *cls, const char *emsg) * @param cls the RequestHandle */ void -ego_edit (struct GNUNET_REST_RequestHandle *con_handle, const char* url, - void *cls) +ego_edit (struct GNUNET_REST_RequestHandle *con_handle, + const char* url, + void *cls) { struct RequestHandle *handle = cls; struct EgoEntry *ego_entry; struct EgoEntry *ego_entry_tmp; struct MHD_Response *resp; - json_t *subsys_json; - json_t *name_json; - json_t *key_json; + int json_state; json_t *data_js; json_error_t err; - const char *keystring; - const char *subsys; - const char *newname; + char *pubkey; + char *name; + char *newsubsys; + char *newname; char term_data[handle->data_size + 1]; - int ego_exists = GNUNET_NO; //if no data if (0 >= handle->data_size) @@ -504,111 +547,135 @@ ego_edit (struct GNUNET_REST_RequestHandle *con_handle, const char* url, term_data[handle->data_size] = '\0'; GNUNET_memcpy(term_data, handle->data, handle->data_size); data_js = json_loads (term_data,JSON_DECODE_ANY,&err); + if (NULL == data_js) { handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA); GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - if (!json_is_object(data_js)) - { - json_decref (data_js); - handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - //json must contain pubkey and (subsystem or name) - if (2 != json_object_size (data_js)) - { - json_decref (data_js); - handle->emsg = GNUNET_strdup("Resource amount invalid"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - key_json = json_object_get (data_js, GNUNET_REST_PARAM_PUBKEY); - if ((NULL == key_json) || !json_is_string(key_json)) + ego_entry = NULL; + pubkey = NULL; + name = NULL; + newname = NULL; + //NEW NAME + json_state = 0; + json_state = json_unpack(data_js, + "{s:s,s?:s,s?:s}", + GNUNET_REST_PARAM_NEWNAME, + &newname, + GNUNET_REST_PARAM_PUBKEY, + &pubkey, + GNUNET_REST_PARAM_NAME, + &name); + //Change name with pubkey or name identifier + if (0 == json_state) { - json_decref (data_js); - handle->emsg = GNUNET_strdup("Missing element pubkey"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - keystring = json_string_value (key_json); + if (NULL == newname) + { + handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); + GNUNET_SCHEDULER_add_now (&do_error, handle); + json_decref (data_js); + return; + } - for (ego_entry = handle->ego_head; - NULL != ego_entry; ego_entry = ego_entry->next) - { - if (0 != strcasecmp (keystring, ego_entry->keystring)) - continue; - ego_exists = GNUNET_YES; - break; - } + if (0 >= strlen(newname)) + { + handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); + GNUNET_SCHEDULER_add_now (&do_error, handle); + json_decref (data_js); + return; + } + //lower case name + GNUNET_STRINGS_utf8_tolower(newname,newname); - if (GNUNET_NO == ego_exists) - { - json_decref (data_js); - resp = GNUNET_REST_create_response (NULL); - handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND); - GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); - return; - } - //This is a rename - name_json = json_object_get (data_js, GNUNET_REST_PARAM_NEWNAME); - if ((NULL != name_json) && json_is_string(name_json)) - { - newname = json_string_value (name_json); - if (0 >= strlen (newname)) + ego_entry = get_egoentry(handle,pubkey,name); + + if (NULL == ego_entry) { + resp = GNUNET_REST_create_response (NULL); + handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND); + GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); json_decref (data_js); - handle->emsg = GNUNET_strdup("No name provided"); - GNUNET_SCHEDULER_add_now (&do_error, handle); return; } + for (ego_entry_tmp = handle->ego_head; NULL != ego_entry_tmp; ego_entry_tmp = ego_entry_tmp->next) { - if (0 == strcasecmp (newname, ego_entry_tmp->identifier) - && 0 != strcasecmp (keystring, ego_entry_tmp->keystring)) + if (0 == strcasecmp (newname, ego_entry_tmp->identifier)) { - //Ego with same name not allowed - json_decref (data_js); - resp = GNUNET_REST_create_response (NULL); - handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); - GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); - return; + //Ego with same name not allowed + resp = GNUNET_REST_create_response (NULL); + handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); + GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); + json_decref (data_js); + return; } } handle->response_code = MHD_HTTP_NO_CONTENT; handle->op = GNUNET_IDENTITY_rename (handle->identity_handle, - ego_entry->identifier, newname, - &do_finished, handle); + ego_entry->identifier, newname, + &do_finished, handle); json_decref (data_js); return; } - //Set subsystem - subsys_json = json_object_get (data_js, GNUNET_REST_PARAM_SUBSYSTEM); - if ((NULL != subsys_json) && json_is_string(subsys_json)) + newsubsys = NULL; + //SUBSYSTEM + json_state = 0; + json_state = json_unpack(data_js, + "{s:s,s?:s,s?:s}", + GNUNET_REST_PARAM_SUBSYSTEM, + &newsubsys, + GNUNET_REST_PARAM_PUBKEY, + &pubkey, + GNUNET_REST_PARAM_NAME, + &name); + //Change subsystem with pubkey or name identifier + if (0 == json_state) { - subsys = json_string_value (subsys_json); - if (0 >= strlen (subsys)) + if (NULL == newsubsys || (NULL == pubkey && NULL == name)) + { + handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); + GNUNET_SCHEDULER_add_now (&do_error, handle); + json_decref (data_js); + return; + } + + if (0 >= strlen(newsubsys)) { + handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); + GNUNET_SCHEDULER_add_now (&do_error, handle); json_decref (data_js); - handle->emsg = GNUNET_strdup("Invalid subsystem name"); + return; + } + + ego_entry = get_egoentry(handle, pubkey, name); + + if (NULL == ego_entry) + { + handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); GNUNET_SCHEDULER_add_now (&do_error, handle); + json_decref (data_js); return; } - GNUNET_asprintf (&handle->subsystem, "%s", subsys); - json_decref (data_js); + handle->response_code = MHD_HTTP_NO_CONTENT; - handle->op = GNUNET_IDENTITY_set (handle->identity_handle, handle->subsystem, - ego_entry->ego, &do_finished, handle); + handle->op = GNUNET_IDENTITY_set (handle->identity_handle, + newsubsys, + ego_entry->ego, + &do_finished, + handle); + json_decref (data_js); return; } - json_decref (data_js); - handle->emsg = GNUNET_strdup("Subsystem not provided"); + + handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); GNUNET_SCHEDULER_add_now (&do_error, handle); + json_decref (data_js); + return; } /** @@ -625,10 +692,10 @@ ego_create (struct GNUNET_REST_RequestHandle *con_handle, const char* url, struct RequestHandle *handle = cls; struct EgoEntry *ego_entry; struct MHD_Response *resp; - json_t *egoname_json; json_t *data_js; json_error_t err; - const char* egoname; + char* egoname; + int json_unpack_state; char term_data[handle->data_size + 1]; if (strlen (GNUNET_REST_API_NS_IDENTITY) != strlen (handle->url)) @@ -649,39 +716,33 @@ ego_create (struct GNUNET_REST_RequestHandle *con_handle, const char* url, data_js = json_loads (term_data, JSON_DECODE_ANY, &err); - if (NULL == data_js) { - handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); + handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA); GNUNET_SCHEDULER_add_now (&do_error, handle); + json_decref (data_js); return; } - //instead of parse - if (!json_is_object(data_js)) + json_unpack_state = 0; + json_unpack_state = json_unpack(data_js, + "{s:s!}", + GNUNET_REST_PARAM_NAME, + &egoname); + if (0 != json_unpack_state) { - json_decref (data_js); handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); GNUNET_SCHEDULER_add_now (&do_error, handle); - return; - } - - if (1 != json_object_size (data_js)) - { json_decref (data_js); - handle->emsg = GNUNET_strdup("Provided resource count invalid"); - GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - egoname_json = json_object_get (data_js, GNUNET_REST_PARAM_NAME); - if (!json_is_string(egoname_json)) + if (NULL == egoname) { - json_decref (data_js); handle->emsg = GNUNET_strdup("No name provided"); GNUNET_SCHEDULER_add_now (&do_error, handle); + json_decref (data_js); return; } - egoname = json_string_value (egoname_json); if (0 >= strlen (egoname)) { json_decref (data_js); @@ -689,19 +750,20 @@ ego_create (struct GNUNET_REST_RequestHandle *con_handle, const char* url, GNUNET_SCHEDULER_add_now (&do_error, handle); return; } + GNUNET_STRINGS_utf8_tolower(egoname, egoname); for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = ego_entry->next) { if (0 == strcasecmp (egoname, ego_entry->identifier)) { - json_decref (data_js); resp = GNUNET_REST_create_response (NULL); handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); + json_decref (data_js); return; } } - GNUNET_asprintf (&handle->name, "%s", egoname); + handle->name = GNUNET_strdup(egoname); json_decref (data_js); handle->response_code = MHD_HTTP_CREATED; handle->op = GNUNET_IDENTITY_create (handle->identity_handle, handle->name, @@ -750,7 +812,7 @@ ego_delete (struct GNUNET_REST_RequestHandle *con_handle, const char* url, egoname = GNUNET_CONTAINER_multihashmap_get ( handle->rest_handle->url_param_map, &key); //LOWERCASE ego names? - GNUNET_STRINGS_utf8_tolower(egoname, egoname); + //GNUNET_STRINGS_utf8_tolower(egoname, egoname); } if (NULL != keystring) @@ -769,7 +831,7 @@ ego_delete (struct GNUNET_REST_RequestHandle *con_handle, const char* url, for (ego_entry = handle->ego_head; NULL != ego_entry; ego_entry = ego_entry->next) { - if (0 != strcasecmp (egoname, ego_entry->identifier)) + if (0 != strcmp (egoname, ego_entry->identifier)) continue; ego_exists = GNUNET_YES; break; diff --git a/src/identity/test_plugin_rest_identity.sh b/src/identity/test_plugin_rest_identity.sh index f391f827f..22a7a53c6 100755 --- a/src/identity/test_plugin_rest_identity.sh +++ b/src/identity/test_plugin_rest_identity.sh @@ -1,222 +1,161 @@ #!/usr/bin/bash -#First, start gnunet-arm and the rest-service. Make sure, no identity exists +#First, start gnunet-arm and the rest-service. #Exit 0 means success, exit 1 means failed test #No test for subsystem available -link_to_api="http://localhost:7776/identity" -wrong_link="http://localhost:7776/idenmmmy" -wrong_link2="http://localhost:7776/identityandmore" - -#Test GET (multiple identities) for error when no identity exists -#The next test case can be ignored if you have already added identities -cache="$(curl --silent "$link_to_api" | grep "error")" -if [ "" == "$cache" ] -then - exit 1 -fi - -#Test POST success code, error response code and error json -#The next test case can be ignored if you have already added an identity with the name Test -cache="$(curl -v -X "POST" "$link_to_api" --data "{\"name\":\"Test\"}" 2>&1 | grep "HTTP/1.1 201")" -if [ "" == "$cache" ] -then - exit 1 -fi - -cache="$(curl -v -X "POST" "$link_to_api" --data "{\"name\":\"Test\"}" 2>&1 | grep "HTTP/1.1 409")" -if [ "" == "$cache" ] -then - exit 1 -fi - -cache="$(curl -v -X "POST" "$link_to_api" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - exit 1 -fi - -cache="$(curl -v -X "POST" "$link_to_api" --data "wrong" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - exit 1 -fi - -cache="$(curl -v -X "POST" "$link_to_api" --data "[{}]" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - exit 1 -fi - -cache="$(curl -v -X "POST" "$link_to_api" --data "{\"name\":\"Test\",\"other\":\"Test\"}" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - exit 1 -fi - -cache="$(curl -v -X "POST" "$link_to_api" --data "{\"nam\":\"Test\"}" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - exit 1 -fi - -cache="$(curl -v -X "POST" "$link_to_api" --data "{\"name\":123}" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - exit 1 -fi - -cache="$(curl -v -X "POST" "$link_to_api" --data "{\"name\":""}" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - exit 1 -fi - - -#Test GET (multiple identities) for success and error json -cache="$(curl --silent "$link_to_api" | grep "error")" -if [ "" != "$cache" ] -then - exit 1 -fi - - -id="$(gnunet-identity -d | grep "Test - " | sed "s/Test - //g")" -#Test GET (one identity) for success and error json -#Only lowercase -cache="$(curl --silent "${link_to_api}?name=Test" | grep "error")" -if [ "" == "$cache" ] -then - exit 1 -fi -#Test GET (one identity) for success and error json -cache="$(curl --silent "${link_to_api}?pubkey=$id" | grep "error")" -if [ "" != "$cache" ] -then - exit 1 -fi - -#Test DELETE success code, error response code and error json -#echo "Next tests for DELETE will probably fail when POST fails" -cache="$(curl -v -X "DELETE" "${link_to_api}?pubkey=$id" 2>&1 | grep "HTTP/1.1 404")" -if [ "" != "$cache" ] -then - exit 1 -fi - -curl --silent -X "POST" "$link_to_api" --data "{\"name\":\"Test\"}" -id="$(gnunet-identity -d | grep "Test - " | sed "s/Test - //g")" - -cache="$(curl -v -X "DELETE" "${link_to_api}?pubkey=df1" 2>&1 | grep "HTTP/1.1 404")" -if [ "" == "$cache" ] -then - exit 1 -fi - -cache="$(curl -v -X "DELETE" "${link_to_api}?pubke=$id" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - exit 1 -fi - -#Test PUT success code, error response codes and error json -cache="$(curl -v -X "PUT" "${link_to_api}" --data "{\"newname\":\"NewTest\",\"pubkey\":\"${id}\"}" 2>&1 | grep "HTTP/1.1 204")" -if [ "" == "$cache" ] -then - exit 1 -fi - -cache="$(curl -v -X "PUT" "${link_to_api}" --data "{\"newname\":\"NewNewTest\",\"pubkey\":\"${id}1\"}" 2>&1 | grep "HTTP/1.1 404")" -if [ "" == "$cache" ] -then - exit 1 -fi - -# feature: you can rename your identity with its own name. -# cache="$(curl -v -X "PUT" "$link_to_api" --data "{\"newname\":\"NewTest\",\"pubkey\":\"${id}\"}" 2>&1 | grep "error")" -# if [ "" == "$cache" ] -# then -# exit 1 -# fi - - -cache="$(curl -v -X "PUT" "$link_to_api" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - exit 1 -fi - -cache="$(curl -v -X "PUT" "$link_to_api" --data "wrong" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - exit 1 -fi - -cache="$(curl -v -X "PUT" "$link_to_api" --data "[{}]" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - exit 1 -fi - -cache="$(curl -v -X "PUT" "$link_to_api" --data "{\"newname\":\"Test\",\"other\":\"Test\",\"pubkey\":\"${id}\"}" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - exit 1 -fi - -cache="$(curl -v -X "PUT" "$link_to_api" --data "{\"newnam\":\"Test\",\"pubkey\":\"${id}\"}" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - exit 1 -fi - -cache="$(curl -v -X "PUT" "$link_to_api" --data "{\"newname\":\"Test\",\"pubke\":\"${id}\"}" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - exit 1 -fi - -cache="$(curl -v -X "PUT" "$link_to_api" --data "{\"newname\":123,\"pubkey\":\"${id}\"}" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - exit 1 -fi - -cache="$(curl -v -X "PUT" "$link_to_api" --data "{\"newname\":"",\"pubkey\":\"${id}\"}" 2>&1 | grep "error")" -if [ "" == "$cache" ] -then - exit 1 -fi -#TODO Missing subsystem test - -#Missing OPTIONS success - nothing can really go wrong here - -#Test wrong url -cache="$(curl -v "$wrong_link" 2>&1 | grep "HTTP/1.1 404")" -if [ "" == "$cache" ] -then - exit 1 -fi - -cache="$(curl -X "PUT" -v "$wrong_link" --data "{\"newname\":\"Testing\",\"pubkey\":\"${id}\"}" 2>&1 | grep "HTTP/1.1 404")" -if [ "" == "$cache" ] -then - exit 1 -fi - -cache="$(curl -X "POST" -v "$wrong_link?pubkey=$id" --data "{\"name\":\"Test\"}" 2>&1 | grep "HTTP/1.1 404")" -if [ "" == "$cache" ] -then - exit 1 -fi - -cache="$(curl -X "DELETE" -v "${wrong_link}?pubkey=$id" 2>&1 | grep "HTTP/1.1 404")" -if [ "" == "$cache" ] -then - exit 1 -fi - -gnunet-identity -D NewTest - -exit 0 +identity_link="http://localhost:7776/identity" +wrong_link="http://localhost:7776/identityandmore" + + +curl_get () { + #$1 is link + #$2 is grep + cache="$(curl -v "$1" 2>&1 | grep "$2")" + #echo $cache + if [ "" == "$cache" ] + then + exit 1 + fi +} + +curl_post () { + #$1 is link + #$2 is data + #$3 is grep + cache="$(curl -v -X "POST" "$1" --data "$2" 2>&1 | grep "$3")" + #echo $cache + if [ "" == "$cache" ] + then + exit 1 + fi +} + +curl_delete () { + #$1 is link + #$2 is grep + cache="$(curl -v -X "DELETE" "$1" 2>&1 | grep "$2")" + #echo $cache + if [ "" == "$cache" ] + then + exit 1 + fi +} + +curl_put () { + #$1 is link + #$2 is data + #$3 is grep + cache="$(curl -v -X "PUT" "$1" --data "$2" 2>&1 | grep "$3")" + #echo $cache + if [ "" == "$cache" ] + then + exit 1 + fi +} + +#Test GET +test="$(gnunet-identity -d)" +#if no identity exists +if [ "" == "$test" ] +then + curl_get "$identity_link" "error" + gnunet-identity -C "test_plugin_rest_identity" + name="$(gnunet-identity -d | awk 'NR==1{print $1}')" + public="$(gnunet-identity -d | awk 'NR==1{print $3}')" + + curl_get "${identity_link}?name=$name" "$public" + curl_get "${identity_link}?name=" "error" + curl_get "${identity_link}?name=$public" "error" + + curl_get "${identity_link}?pubkey=$public" "$name" + curl_get "${identity_link}?pubkey=$name" "error" + curl_get "${identity_link}?pubkey=" "error" + + gnunet-identity -D "test_plugin_rest_identity" +else + name="$(gnunet-identity -d | awk 'NR==1{print $1}')" + public="$(gnunet-identity -d | awk 'NR==1{print $3}')" + + curl_get "${identity_link}?name=$name" "$public" + curl_get "${identity_link}?name=" "error" + curl_get "${identity_link}?name=$public" "error" + + curl_get "${identity_link}?pubkey=$public" "$name" + curl_get "${identity_link}?pubkey=$name" "error" + curl_get "${identity_link}?pubkey=" "error" +fi + +#Test POST +gnunet-identity -D "test_plugin_rest_identity" > /dev/null 2>&1 +gnunet-identity -D "test_plugin_rest_identity1" > /dev/null 2>&1 + +curl_post "${identity_link}" '{"name":"test_plugin_rest_identity"}' "HTTP/1.1 201 Created" +curl_post "${identity_link}" '{"name":"test_plugin_rest_identity"}' "HTTP/1.1 409" +curl_post "${identity_link}" '{"name":"Test_plugin_rest_identity"}' "HTTP/1.1 409" +curl_post "${identity_link}" '{}' "error" +curl_post "${identity_link}" '' "error" +curl_post "${identity_link}" '{"name":""}' "error" +curl_post "${identity_link}" '{"name":123}' "error" +curl_post "${identity_link}" '{"name":[]}' "error" +curl_post "${identity_link}" '{"name1":"test_plugin_rest_identity"}' "error" +curl_post "${identity_link}" '{"other":""}' "error" +curl_post "${identity_link}" '{"name":"test_plugin_rest_identity1", "other":"test_plugin_rest_identity2"}' "error" + +#Test PUT +name="$(gnunet-identity -d | grep "test_plugin_rest_identity" | awk 'NR==1{print $1}')" +public="$(gnunet-identity -d | grep "test_plugin_rest_identity" | awk 'NR==1{print $3}')" + +curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity1","pubkey":"'$public'"}' "HTTP/1.1 204" +curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity1","pubkey":"'$public'"}' "HTTP/1.1 409" +curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity1","pubkey":"'$public'xx"}' "HTTP/1.1 404" +curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity1","pubkey":""}' "HTTP/1.1 404" +curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity1","pubke":""}' "HTTP/1.1 404" +curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity1","pubke":"","other":"sdfdsf"}' "HTTP/1.1 404" +curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity1","pubke":"","name":"sdfdsf"}' "HTTP/1.1 404" +curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity","pubke":"","name":"test_plugin_rest_identity1"}' "HTTP/1.1 204" +curl_put "${identity_link}" '{"newnam":"test_plugin_rest_identity","pubkey":"'$public'"}' "error" +curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity1","name":"test_plugin_rest_identity"}' "HTTP/1.1 204" +curl_put "${identity_link}" '{"newname":"TEST_plugin_rest_identity1","name":"test_plugin_rest_identity1"}' "HTTP/1.1 409" +curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity1","name":"test_plugin_rest_identity1"}' "HTTP/1.1 409" +curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity","name":"test_plugin_rest_identityxxx"}' "HTTP/1.1 404" +curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity","name":"test_plugin_rest_identity1"}' "HTTP/1.1 204" +curl_put "${identity_link}" '{"newnam":"test_plugin_rest_identityfail","name":"test_plugin_rest_identity"}' "error" + + +#Test subsystem +curl_put "${identity_link}" '{"subsystem":"namestore","name":"test_plugin_rest_identity"}' "HTTP/1.1 204" +curl_put "${identity_link}" '{"subsystem":"namestore","name":"test_plugin_rest_identity"}' "HTTP/1.1 204" +curl_get "${identity_link}?subsystem=namestore" "test_plugin_rest_identity" +curl_post "${identity_link}" '{"name":"test_plugin_rest_identity1"}' "HTTP/1.1 201 Created" +public="$(gnunet-identity -d | grep "test_plugin_rest_identity" | awk 'NR==1{print $3}')" +curl_put "${identity_link}" '{"subsystem":"namestore","pubkey":"'"$public"'"}' "HTTP/1.1 204" +curl_get "${identity_link}?subsystem=namestore" "test_plugin_rest_identity1" +curl_get "${identity_link}?subsystem=test_plugin_rest_identity_no_subsystem" "error" +curl_put "${identity_link}" '{"subsystem":"test_plugin_rest_identity_no_subsystem","name":"test_plugin_rest_identity1"}' "HTTP/1.1 204" +curl_get "${identity_link}?subsystem=test_plugin_rest_identity_no_subsystem" "test_plugin_rest_identity1" + +curl_put "${identity_link}" '{"subsyste":"test_plugin_rest_identity_no_subsystem","name":"test_plugin_rest_identity1"}' "error" +curl_put "${identity_link}" '{"subsystem":"test_plugin_rest_identity_no_subsystem","name":"Test_plugin_rest_identity1"}' "HTTP/1.1 204" + +#Test DELETE +curl_delete "${identity_link}?name=test_plugin_rest_identity" "HTTP/1.1 204" +curl_get "${identity_link}?name=test_plugin_rest_identity" "error" +curl_delete "${identity_link}?name=TEST_plugin_rest_identity1" "HTTP/1.1 404" +curl_delete "${identity_link}?name=test_plugin_rest_identity1" "HTTP/1.1 204" +curl_get "${identity_link}?name=test_plugin_rest_identity1" "error" +curl_delete "${identity_link}?name=test_plugin_rest_identity_not_found" "HTTP/1.1 404" +curl_post "${identity_link}" '{"name":"test_plugin_rest_identity1"}' "HTTP/1.1 201 Created" +public="$(gnunet-identity -d | grep "test_plugin_rest_identity1" | awk 'NR==1{print $3}')" +curl_delete "${identity_link}?pubkey=$public" "HTTP/1.1 204" +curl_delete "${identity_link}?pubke=$public" "error" +curl_delete "${identity_link}?pubkey=$public&other=232" "HTTP/1.1 404" + +#Test wrong_link +curl_get "$wrong_link" "HTTP/1.1 404" +curl_post "$wrong_link" '{"name":"test_plugin_rest_identity"}' "HTTP/1.1 404" +curl_put "$wrong_link" '{"newname":"test_plugin_rest_identity1","name":"test_plugin_rest_identity"}' "HTTP/1.1 404" +curl_delete "$wrong_link?name=test_plugin_rest_identity1" "HTTP/1.1 404" + +exit 0; -- cgit v1.2.3 From 741916af1dee72af1ba24a1c9e4fb40f63b2a0a1 Mon Sep 17 00:00:00 2001 From: Phil Date: Mon, 6 Aug 2018 02:09:57 +0200 Subject: GNS REST API finished --- src/gns/plugin_rest_gns.c | 34 +++++++++++----------------- src/gns/test_plugin_rest_gns.sh | 50 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 21 deletions(-) create mode 100755 src/gns/test_plugin_rest_gns.sh (limited to 'src') diff --git a/src/gns/plugin_rest_gns.c b/src/gns/plugin_rest_gns.c index aae14153d..4be583f73 100644 --- a/src/gns/plugin_rest_gns.c +++ b/src/gns/plugin_rest_gns.c @@ -24,6 +24,7 @@ #include "platform.h" #include "gnunet_rest_plugin.h" #include "gnunet_rest_lib.h" +#include "gnunet_json_lib.h" #include "gnunet_gnsrecord_lib.h" #include "gnunet_gns_service.h" #include "microhttpd.h" @@ -31,9 +32,9 @@ #define GNUNET_REST_API_NS_GNS "/gns" -#define GNUNET_REST_PARAMETER_GNS_NAME "name" +#define GNUNET_REST_GNS_PARAM_NAME "name" -#define GNUNET_REST_PARAMETER_GNS_RECORD_TYPE "record_type" +#define GNUNET_REST_GNS_PARAM_RECORD_TYPE "record_type" #define GNUNET_REST_GNS_ERROR_UNKNOWN "Unknown Error" /** @@ -203,7 +204,6 @@ handle_gns_response (void *cls, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "TEST4\n"); struct RequestHandle *handle = cls; struct MHD_Response *resp; json_t *result_array; @@ -229,10 +229,7 @@ handle_gns_response (void *cls, continue; } - record_value = GNUNET_GNSRECORD_value_to_string (rd->record_type, - rd->data, - rd->data_size); - record_obj = json_string(record_value); + record_obj = GNUNET_JSON_from_gns_record(NULL,&rd[i]); json_array_append (result_array, record_obj); json_decref (record_obj); } @@ -264,8 +261,8 @@ get_gns_cont (struct GNUNET_REST_RequestHandle *con_handle, char *record_type; char *name; - GNUNET_CRYPTO_hash (GNUNET_REST_PARAMETER_GNS_NAME, - strlen (GNUNET_REST_PARAMETER_GNS_NAME), + GNUNET_CRYPTO_hash (GNUNET_REST_GNS_PARAM_NAME, + strlen (GNUNET_REST_GNS_PARAM_NAME), &key); if ( GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, @@ -284,23 +281,19 @@ get_gns_cont (struct GNUNET_REST_RequestHandle *con_handle, } handle->name = GNUNET_strdup(name); - GNUNET_CRYPTO_hash (GNUNET_REST_PARAMETER_GNS_RECORD_TYPE, - strlen (GNUNET_REST_PARAMETER_GNS_RECORD_TYPE), + handle->record_type = UINT32_MAX; + GNUNET_CRYPTO_hash (GNUNET_REST_GNS_PARAM_RECORD_TYPE, + strlen (GNUNET_REST_GNS_PARAM_RECORD_TYPE), &key); - if ( GNUNET_NO - == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, + if ( GNUNET_YES + == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, &key)) { - handle->emsg = GNUNET_strdup("Parameter record_type is missing"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; + record_type = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, &key); + handle->record_type = GNUNET_GNSRECORD_typename_to_number(record_type); } - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "TEST1\n"); - - record_type = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, &key); - handle->record_type = GNUNET_GNSRECORD_typename_to_number(record_type); if(UINT32_MAX == handle->record_type) { handle->record_type = GNUNET_GNSRECORD_TYPE_ANY; @@ -313,7 +306,6 @@ get_gns_cont (struct GNUNET_REST_RequestHandle *con_handle, GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "TEST2\n"); handle->gns_lookup = GNUNET_GNS_lookup_with_tld (handle->gns, handle->name, diff --git a/src/gns/test_plugin_rest_gns.sh b/src/gns/test_plugin_rest_gns.sh new file mode 100755 index 000000000..fca35ee2d --- /dev/null +++ b/src/gns/test_plugin_rest_gns.sh @@ -0,0 +1,50 @@ +#!/usr/bin/bash + +#First, start gnunet-arm and the rest-service. +#Exit 0 means success, exit 1 means failed test + +gns_link="http://localhost:7776/gns" +wrong_link="http://localhost:7776/gnsandmore" + +curl_get () { + #$1 is link + #$2 is grep + cache="$(curl -v "$1" 2>&1 | grep "$2")" + echo $cache + if [ "" == "$cache" ] + then + exit 1 + fi +} + +gnunet-identity -D "test_plugin_rest_gns" > /dev/null 2>&1 + +curl_get "$gns_link?name=www.test_plugin_rest_gns" "error" + +gnunet-identity -C "test_plugin_rest_gns" + +curl_get "$gns_link?name=www.test_plugin_rest_gns" "\[\]" + +gnunet-namestore -z "test_plugin_rest_gns" -p -a -n www -e 1d -V 1.1.1.1 -t A + +curl_get "$gns_link?name=www.test_plugin_rest_gns" "1.1.1.1" + +gnunet-namestore -z "test_plugin_rest_gns" -p -a -n www -e 1d -V 1::1 -t AAAA + +curl_get "$gns_link?name=www.test_plugin_rest_gns" "1::1.*1.1.1.1" + +gnunet-namestore -z "test_plugin_rest_gns" -p -a -n www -e 1d -V 1.1.1.2 -t A + +curl_get "$gns_link?name=www.test_plugin_rest_gns" "1.1.1.2.*1::1.*1.1.1.1" +curl_get "$gns_link?name=www.test_plugin_rest_gns&record_type=A" "1.1.1.2.*1.1.1.1" +curl_get "$gns_link?name=www.test_plugin_rest_gns&record_type=AAAA" "1::1" +curl_get "$gns_link?name=www.test_plugin_rest_gns&record_type=WRONG_TYPE" "1.1.1.2.*1::1.*1.1.1.1" + +gnunet-namestore -z "test_plugin_rest_gns" -p -a -n www1 -e 1d -V 1.1.1.1 -t A +curl_get "$gns_link?name=www1.test_plugin_rest_gns" "1.1.1.1" + +gnunet-identity -D "test_plugin_rest_gns" + +curl_get "$gns_link?name=www1.test_plugin_rest_gns" "error" + +exit 0 -- cgit v1.2.3 From 65f9785e7752b6d73e2ad8c6ff2735336ad5baa6 Mon Sep 17 00:00:00 2001 From: Phil Date: Mon, 6 Aug 2018 02:26:04 +0200 Subject: fix gns and identity test script --- src/gns/plugin_rest_gns.c | 3 +-- src/gns/test_plugin_rest_gns.sh | 2 +- src/identity/test_plugin_rest_identity.sh | 2 -- 3 files changed, 2 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/gns/plugin_rest_gns.c b/src/gns/plugin_rest_gns.c index 4be583f73..495d01504 100644 --- a/src/gns/plugin_rest_gns.c +++ b/src/gns/plugin_rest_gns.c @@ -32,6 +32,7 @@ #define GNUNET_REST_API_NS_GNS "/gns" + #define GNUNET_REST_GNS_PARAM_NAME "name" #define GNUNET_REST_GNS_PARAM_RECORD_TYPE "record_type" @@ -56,7 +57,6 @@ struct Plugin }; - struct RequestHandle { @@ -208,7 +208,6 @@ handle_gns_response (void *cls, struct MHD_Response *resp; json_t *result_array; json_t *record_obj; - char *record_value; char *result; handle->gns_lookup = NULL; diff --git a/src/gns/test_plugin_rest_gns.sh b/src/gns/test_plugin_rest_gns.sh index fca35ee2d..7ede44501 100755 --- a/src/gns/test_plugin_rest_gns.sh +++ b/src/gns/test_plugin_rest_gns.sh @@ -10,7 +10,7 @@ curl_get () { #$1 is link #$2 is grep cache="$(curl -v "$1" 2>&1 | grep "$2")" - echo $cache + #echo $cache if [ "" == "$cache" ] then exit 1 diff --git a/src/identity/test_plugin_rest_identity.sh b/src/identity/test_plugin_rest_identity.sh index 22a7a53c6..d9377500e 100755 --- a/src/identity/test_plugin_rest_identity.sh +++ b/src/identity/test_plugin_rest_identity.sh @@ -3,8 +3,6 @@ #First, start gnunet-arm and the rest-service. #Exit 0 means success, exit 1 means failed test -#No test for subsystem available - identity_link="http://localhost:7776/identity" wrong_link="http://localhost:7776/identityandmore" -- cgit v1.2.3 From 9eb2df3407246f984f0d85af338bff872d5e6fba Mon Sep 17 00:00:00 2001 From: Phil Date: Wed, 8 Aug 2018 03:59:08 +0200 Subject: -wip namestore --- src/namestore/plugin_rest_namestore.c | 322 ++++++++++++++++++++++++---- src/namestore/test_plugin_rest_namestore.sh | 270 +++++++++++++++++++++++ 2 files changed, 552 insertions(+), 40 deletions(-) create mode 100755 src/namestore/test_plugin_rest_namestore.sh (limited to 'src') diff --git a/src/namestore/plugin_rest_namestore.c b/src/namestore/plugin_rest_namestore.c index 90928165e..3801431b2 100644 --- a/src/namestore/plugin_rest_namestore.c +++ b/src/namestore/plugin_rest_namestore.c @@ -34,13 +34,30 @@ #define GNUNET_REST_API_NS_NAMESTORE "/namestore" - #define GNUNET_REST_SUBSYSTEM_NAMESTORE "namestore" +/** + * Parameter names + */ +#define GNUNET_REST_API_PARAM_PUBKEY "pubkey" +#define GNUNET_REST_API_PARAM_NAME "name" + +/** + * Error messages + */ #define GNUNET_REST_NAMESTORE_ERROR_UNKNOWN "Unknown Error" #define GNUNET_REST_NAMESTORE_RD_COUNT 1 +/** + * State while collecting all egos + */ +#define ID_REST_STATE_INIT 0 + +/** + * Done collecting egos + */ +#define ID_REST_STATE_POST_INIT 1 /** * The configuration handle */ @@ -64,10 +81,20 @@ struct Plugin */ struct EgoEntry { + /** + * DLL + */ + struct EgoEntry *next; + + /** + * DLL + */ + struct EgoEntry *prev; + /** * Ego Identifier */ - const char *identifier; + char *identifier; /** * Public key string @@ -103,6 +130,11 @@ struct RequestHandle */ json_t *resp_object; + /** + * The processing state + */ + int state; + /** * Handle to NAMESTORE */ @@ -116,13 +148,23 @@ struct RequestHandle /** * Private key for the zone */ - struct GNUNET_CRYPTO_EcdsaPrivateKey zone_pkey; + const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_pkey; /** * IDENTITY Operation */ struct EgoEntry *ego_entry; + /** + * Ego list + */ + struct EgoEntry *ego_head; + + /** + * Ego list + */ + struct EgoEntry *ego_tail; + /** * IDENTITY Operation */ @@ -183,6 +225,8 @@ static void cleanup_handle (void *cls) { struct RequestHandle *handle = cls; + struct EgoEntry *ego_entry; + struct EgoEntry *ego_tmp; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n"); @@ -216,12 +260,14 @@ cleanup_handle (void *cls) GNUNET_NAMESTORE_disconnect(handle->ns_handle); } - if (NULL != handle->ego_entry) + for (ego_entry = handle->ego_head; + NULL != ego_entry;) { - if (NULL != handle->ego_entry->keystring) - GNUNET_free(handle->ego_entry->keystring); - - GNUNET_free(handle->ego_entry); + ego_tmp = ego_entry; + ego_entry = ego_entry->next; + GNUNET_free(ego_tmp->identifier); + GNUNET_free(ego_tmp->keystring); + GNUNET_free(ego_tmp); } if(NULL != handle->resp_object) @@ -261,6 +307,46 @@ do_error (void *cls) GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); } + +/** + * Get EgoEntry from list with either a public key or a name + * If public key and name are not NULL, it returns the public key result first + * + * @param handle the RequestHandle + * @param pubkey the public key of an identity (only one can be NULL) + * @param name the name of an identity (only one can be NULL) + * @return EgoEntry or NULL if not found + */ +struct EgoEntry* +get_egoentry(struct RequestHandle *handle, char* pubkey, char *name) +{ + struct EgoEntry *ego_entry; + if (NULL != pubkey) + { + for (ego_entry = handle->ego_head; + NULL != ego_entry; + ego_entry = ego_entry->next) + { + if (0 != strcasecmp (pubkey, ego_entry->keystring)) + continue; + return ego_entry; + } + } + if (NULL != name) + { + for (ego_entry = handle->ego_head; + NULL != ego_entry; + ego_entry = ego_entry->next) + { + if (0 != strcasecmp (name, ego_entry->identifier)) + continue; + return ego_entry; + } + } + return NULL; +} + + /** * Does internal server error when iteration failed. */ @@ -273,6 +359,7 @@ namestore_iteration_error (void *cls) GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); } + static void create_finished (void *cls, int32_t success, const char *emsg) { @@ -291,6 +378,7 @@ create_finished (void *cls, int32_t success, const char *emsg) GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); } + static void del_finished (void *cls, int32_t success, const char *emsg) { @@ -314,6 +402,8 @@ del_finished (void *cls, int32_t success, const char *emsg) MHD_HTTP_NO_CONTENT); GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); } + + /** * Iteration over all results finished, build final * response. @@ -344,7 +434,6 @@ namestore_list_finished (void *cls) } - /** * Create a response with requested records * @@ -406,14 +495,50 @@ namestore_get (struct GNUNET_REST_RequestHandle *con_handle, void *cls) { struct RequestHandle *handle = cls; - if (strlen (GNUNET_REST_API_NS_NAMESTORE) != strlen (handle->url)) + struct EgoEntry *ego_entry = NULL; + struct GNUNET_HashCode key; + char *pubkey = NULL; + char *name = NULL; + + //change zone if pubkey or name specified + GNUNET_CRYPTO_hash (GNUNET_REST_API_PARAM_PUBKEY, + strlen (GNUNET_REST_API_PARAM_PUBKEY), + &key); + if ( GNUNET_YES + == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, + &key)) { - handle->emsg = GNUNET_strdup("Wrong URL"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; + pubkey = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, + &key); + } + GNUNET_CRYPTO_hash (GNUNET_REST_API_PARAM_NAME, + strlen (GNUNET_REST_API_PARAM_NAME), + &key); + if ( GNUNET_YES + == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, + &key)) + { + name = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, + &key); + } + + ego_entry = get_egoentry(handle,pubkey,name); + if (NULL == ego_entry) + { + if (NULL != pubkey || NULL != name) + { + handle->emsg = GNUNET_strdup("Invalid identity"); + handle->response_code = MHD_HTTP_NOT_FOUND; + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + } + if ( NULL != ego_entry ) + { + handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key(ego_entry->ego); } handle->list_it = GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle, - &handle->zone_pkey, + handle->zone_pkey, &namestore_iteration_error, handle, &namestore_list_iteration, @@ -459,7 +584,7 @@ create_new_record_cont (void *cls, return; } handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle, - &handle->zone_pkey, + handle->zone_pkey, handle->label_name, GNUNET_REST_NAMESTORE_RD_COUNT, handle->rd, @@ -484,6 +609,12 @@ namestore_add (struct GNUNET_REST_RequestHandle *con_handle, json_t *data_js; json_t *name_json; json_error_t err; + + struct EgoEntry *ego_entry = NULL; + struct GNUNET_HashCode key; + char *pubkey = NULL; + char *name = NULL; + char term_data[handle->rest_handle->data_size + 1]; struct GNUNET_JSON_Specification gnsspec[] = { GNUNET_JSON_spec_gnsrecord_data(&gns_record), @@ -506,12 +637,21 @@ namestore_add (struct GNUNET_REST_RequestHandle *con_handle, GNUNET_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, gnsspec, NULL, NULL)); + if (GNUNET_OK != GNUNET_JSON_parse (data_js, gnsspec, NULL, NULL)) + { + handle->emsg = GNUNET_strdup("Invalid data"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + GNUNET_free_non_null(gns_record); + json_decref (data_js); + return; + } name_json = json_object_get(data_js, "label"); if (!json_is_string(name_json)) { handle->emsg = GNUNET_strdup("Missing name"); GNUNET_SCHEDULER_add_now (&do_error, handle); + GNUNET_free_non_null(gns_record); + json_decref (data_js); return; } handle->label_name = GNUNET_strdup(json_string_value(name_json)); @@ -519,12 +659,60 @@ namestore_add (struct GNUNET_REST_RequestHandle *con_handle, { handle->emsg = GNUNET_strdup("Missing name"); GNUNET_SCHEDULER_add_now (&do_error, handle); + GNUNET_free_non_null(gns_record); + json_decref (data_js); + return; + } + if (0 >= strlen(handle->label_name)) + { + handle->emsg = GNUNET_strdup("Missing name"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + GNUNET_free_non_null(gns_record); + json_decref (data_js); return; } json_decref (data_js); handle->rd = gns_record; + + //change zone if pubkey or name specified + GNUNET_CRYPTO_hash (GNUNET_REST_API_PARAM_PUBKEY, + strlen (GNUNET_REST_API_PARAM_PUBKEY), + &key); + if ( GNUNET_YES + == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, + &key)) + { + pubkey = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, + &key); + } + GNUNET_CRYPTO_hash (GNUNET_REST_API_PARAM_NAME, + strlen (GNUNET_REST_API_PARAM_NAME), + &key); + if ( GNUNET_YES + == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, + &key)) + { + name = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, + &key); + } + + ego_entry = get_egoentry(handle,pubkey,name); + if (NULL == ego_entry) + { + if (NULL != pubkey || NULL != name) + { + handle->emsg = GNUNET_strdup("Invalid identity"); + handle->response_code = MHD_HTTP_NOT_FOUND; + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + } + if ( NULL != ego_entry ) + { + handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key(ego_entry->ego); + } handle->add_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle, - &handle->zone_pkey, + handle->zone_pkey, handle->label_name, &do_error, handle, @@ -551,7 +739,7 @@ del_cont (void *cls, } handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle, - &handle->zone_pkey, + handle->zone_pkey, handle->label_name, 0, NULL, &del_finished, @@ -572,6 +760,47 @@ namestore_delete (struct GNUNET_REST_RequestHandle *con_handle, { struct RequestHandle *handle = cls; struct GNUNET_HashCode key; + struct EgoEntry *ego_entry = NULL; + char *pubkey = NULL; + char *name = NULL; + + //change zone if pubkey or name specified + GNUNET_CRYPTO_hash (GNUNET_REST_API_PARAM_PUBKEY, + strlen (GNUNET_REST_API_PARAM_PUBKEY), + &key); + if ( GNUNET_YES + == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, + &key)) + { + pubkey = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, + &key); + } + GNUNET_CRYPTO_hash (GNUNET_REST_API_PARAM_NAME, + strlen (GNUNET_REST_API_PARAM_NAME), + &key); + if ( GNUNET_YES + == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, + &key)) + { + name = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, + &key); + } + + ego_entry = get_egoentry(handle,pubkey,name); + if (NULL == ego_entry) + { + if (NULL != pubkey || NULL != name) + { + handle->emsg = GNUNET_strdup("Invalid identity"); + handle->response_code = MHD_HTTP_NOT_FOUND; + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + } + if ( NULL != ego_entry ) + { + handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key(ego_entry->ego); + } GNUNET_CRYPTO_hash ("label", strlen ("label"), &key); if ( GNUNET_NO @@ -582,11 +811,10 @@ namestore_delete (struct GNUNET_REST_RequestHandle *con_handle, GNUNET_SCHEDULER_add_now (&do_error, handle); return; } - handle->label_name = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, - &key); - + handle->label_name = GNUNET_strdup( + GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, &key)); handle->add_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle, - &handle->zone_pkey, + handle->zone_pkey, handle->label_name, &do_error, handle, @@ -651,34 +879,27 @@ init_cont (struct RequestHandle *handle) } /** - * + * @param cls closure + * @param ego ego handle + * @param ctx context for application to store data for this ego + * (during the lifetime of this process, initially NULL) + * @param identifier identifier assigned by the user for this ego, + * NULL if the user just deleted the ego and it + * must thus no longer be used */ static void default_ego_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, - const char *name) + const char *identifier) { struct RequestHandle *handle = cls; - struct EgoEntry *ego_entry; - struct GNUNET_CRYPTO_EcdsaPublicKey pk; - handle->op = NULL; - if (NULL == ego) + if (ego != NULL) { - handle->emsg = GNUNET_strdup ("No default ego configured in identity service"); - GNUNET_SCHEDULER_add_now (&do_error, handle); - return; + handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego); } - ego_entry = GNUNET_new(struct EgoEntry); - GNUNET_IDENTITY_ego_get_public_key (ego, &pk); - ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); - ego_entry->identifier = name; - ego_entry->ego = ego; - handle->ego_entry = ego_entry; - handle->zone_pkey = *GNUNET_IDENTITY_ego_get_private_key (ego); - init_cont (handle); } @@ -692,13 +913,33 @@ id_connect_cb (void *cls, const char *name) { struct RequestHandle *handle = cls; - if (NULL == ego) + struct EgoEntry *ego_entry; + struct GNUNET_CRYPTO_EcdsaPublicKey pk; + + if ((NULL == ego) && (NULL == handle->zone_pkey)) { handle->op = GNUNET_IDENTITY_get (handle->identity_handle, GNUNET_REST_SUBSYSTEM_NAMESTORE, &default_ego_cb, handle); } + if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state)) + { + handle->state = ID_REST_STATE_POST_INIT; + init_cont (handle); + return; + } + if (ID_REST_STATE_INIT == handle->state) + { + ego_entry = GNUNET_new(struct EgoEntry); + GNUNET_IDENTITY_ego_get_public_key (ego, &pk); + ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); + ego_entry->ego = ego; + GNUNET_asprintf (&ego_entry->identifier, "%s", name); + GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head, handle->ego_tail, + ego_entry); + } + } @@ -725,6 +966,7 @@ rest_process_request(struct GNUNET_REST_RequestHandle *rest_handle, handle->proc_cls = proc_cls; handle->proc = proc; handle->rest_handle = rest_handle; + handle->zone_pkey = NULL; handle->url = GNUNET_strdup (rest_handle->url); if (handle->url[strlen (handle->url)-1] == '/') diff --git a/src/namestore/test_plugin_rest_namestore.sh b/src/namestore/test_plugin_rest_namestore.sh new file mode 100755 index 000000000..7c1e97397 --- /dev/null +++ b/src/namestore/test_plugin_rest_namestore.sh @@ -0,0 +1,270 @@ +#!/usr/bin/bash + +#First, start gnunet-arm and the rest-service. +#Exit 0 means success, exit 1 means failed test + +namestore_link="http://localhost:7776/namestore" +wrong_link="http://localhost:7776/namestoreandmore" + + +curl_get () { + #$1 is link + #$2 is grep + cache="$(curl -v "$1" 2>&1 | grep "$2")" + echo $cache + if [ "" == "$cache" ] + then + exit 1 + fi +} + +curl_post () { + #$1 is link + #$2 is data + #$3 is grep + cache="$(curl -v -X "POST" "$1" --data "$2" 2>&1 | grep "$3")" + echo $cache + if [ "" == "$cache" ] + then + exit 1 + fi +} + +curl_delete () { + #$1 is link + #$2 is grep + cache="$(curl -v -X "DELETE" "$1" 2>&1 | grep "$2")" + echo $cache + if [ "" == "$cache" ] + then + exit 1 + fi +} + +# curl_put () { +# #$1 is link +# #$2 is data +# #$3 is grep +# cache="$(curl -v -X "PUT" "$1" --data "$2" 2>&1 | grep "$3")" +# #echo $cache +# if [ "" == "$cache" ] +# then +# exit 1 +# fi +# } + +#Test subsystem default identity + +#Test GET +gnunet-identity -D "test_plugin_rest_namestore" +gnunet-identity -C "test_plugin_rest_namestore" +test="$(gnunet-namestore -D -z "test_plugin_rest_namestore")" +name="test_plugin_rest_namestore" +public="$(gnunet-identity -d | grep "test_plugin_rest_namestore" | awk 'NR==1{print $3}')" +if [ "" == "$test" ] +then + #if no entries for test_plugin_rest_namestore + curl_get "${namestore_link}?name=$name" "error" + curl_get "${namestore_link}?name=" "error" + curl_get "${namestore_link}?name=$public" "error" + + curl_get "${namestore_link}?pubkey=$public" "error" + curl_get "${namestore_link}?pubkey=$name" "error" + curl_get "${namestore_link}?pubkey=" "error" +else + #if entries exists (that should not be possible) + curl_get "${namestore_link}" "HTTP/1.1 200 OK" + curl_get "${namestore_link}?name=$name" "HTTP/1.1 200 OK" + curl_get "${namestore_link}?name=" "error" + curl_get "${namestore_link}?name=$public" "error" + + curl_get "${namestore_link}?pubkey=$public" "HTTP/1.1 200 OK" + curl_get "${namestore_link}?pubkey=$name" "error" + curl_get "${namestore_link}?pubkey=" "error" +fi +gnunet-namestore -z $name -p -a -n "test_entry" -e "1d" -V "HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG" -t "PKEY" +curl_get "${namestore_link}" "HTTP/1.1 200 OK" +curl_get "${namestore_link}?name=$name" "HTTP/1.1 200 OK" +curl_get "${namestore_link}?name=" "error" +curl_get "${namestore_link}?name=$public" "error" +curl_get "${namestore_link}?pubkey=$public" "HTTP/1.1 200 OK" +curl_get "${namestore_link}?pubkey=$name" "error" +curl_get "${namestore_link}?pubkey=" "error" +gnunet-namestore -z $name -d -n "test_entry" + +#Test POST with NAME +curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "HTTP/1.1 204 No Content" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +#value +curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRGxxx", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "error" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?name=$name" '{"value":"", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "error" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?name=$name" '{"value_missing":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRGxxx", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "error" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +#time +curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"0d","flag":0,"label":"test_entry"}' "HTTP/1.1 204" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"10000d","flag":0,"label":"test_entry"}' "HTTP/1.1 204" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"now","flag":0,"label":"test_entry"}' "error" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"","flag":0,"label":"test_entry"}' "error" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time_missing":"1d","flag":0,"label":"test_entry"}' "error" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +#flag +curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "HTTP/1.1 204 No Content" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":2,"label":"test_entry"}' "HTTP/1.1 204 No Content" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":8,"label":"test_entry"}' "HTTP/1.1 204 No Content" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":16,"label":"test_entry"}' "HTTP/1.1 204 No Content" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":-1,"label":"test_entry"}' "error" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":"Test","label":"test_entry"}' "error" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":,"label":"test_entry"}' "error" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag_missing":0,"label":"test_entry"}' "error" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +#label +curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "HTTP/1.1 204 No Content" +curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "HTTP/1.1 409" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":0,"label":""}' "error" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?name=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":0,"label_missing":"test_entry"}' "error" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 + +#Test POST with PUBKEY +curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "HTTP/1.1 204 No Content" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +#value +curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRGxxx", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "error" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?pubkey=$public" '{"value":"", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "error" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?pubkey=$public" '{"value_missing":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRGxxx", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "error" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +#time +curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"0d","flag":0,"label":"test_entry"}' "HTTP/1.1 204" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"10000d","flag":0,"label":"test_entry"}' "HTTP/1.1 204" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"now","flag":0,"label":"test_entry"}' "error" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"","flag":0,"label":"test_entry"}' "error" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time_missing":"1d","flag":0,"label":"test_entry"}' "error" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +#flag +curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "HTTP/1.1 204 No Content" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":2,"label":"test_entry"}' "HTTP/1.1 204 No Content" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":8,"label":"test_entry"}' "HTTP/1.1 204 No Content" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":16,"label":"test_entry"}' "HTTP/1.1 204 No Content" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":-1,"label":"test_entry"}' "error" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":"Test","label":"test_entry"}' "error" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":,"label":"test_entry"}' "error" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag_missing":0,"label":"test_entry"}' "error" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +#label +curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "HTTP/1.1 204 No Content" +curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "HTTP/1.1 409" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":0,"label":""}' "error" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?pubkey=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":0,"label_missing":"test_entry"}' "error" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 + +#wrong zone +curl_post "${namestore_link}?name=$public" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "error" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 +curl_post "${namestore_link}?pubkey=$name" '{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG", "type":"PKEY", "expiration_time":"1d","flag":0,"label":"test_entry"}' "error" +gnunet-namestore -z $name -d -n "test_entry" > /dev/null 2>&1 + +#Test DELETE +gnunet-namestore -z $name -p -a -n "test_entry" -e "1d" -V "HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG" -t "PKEY" +curl_delete "${namestore_link}?label=test_entry&name=$name" "HTTP/1.1 204" +gnunet-namestore -z $name -p -a -n "test_entry" -e "1d" -V "HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG" -t "PKEY" +curl_delete "${namestore_link}?label=test_entry&pubkey=$public" "HTTP/1.1 204" + +exit 0; + + + +#pubkey zone +#name zone +curl_post "${namestore_link}" '{"name":"test_plugin_rest_identity"}' "HTTP/1.1 201 Created" +curl_post "${namestore_link}" '{"name":"test_plugin_rest_identity"}' "HTTP/1.1 409" +curl_post "${namestore_link}" '{"name":"Test_plugin_rest_identity"}' "HTTP/1.1 409" +curl_post "${namestore_link}" '{}' "error" +curl_post "${namestore_link}" '' "error" +curl_post "${namestore_link}" '{"name":""}' "error" +curl_post "${namestore_link}" '{"name":123}' "error" +curl_post "${namestore_link}" '{"name":[]}' "error" +curl_post "${namestore_link}" '{"name1":"test_plugin_rest_identity"}' "error" +curl_post "${namestore_link}" '{"other":""}' "error" +curl_post "${namestore_link}" '{"name":"test_plugin_rest_identity1", "other":"test_plugin_rest_identity2"}' "error" + +#Test PUT +name="$(gnunet-identity -d | grep "test_plugin_rest_identity" | awk 'NR==1{print $1}')" +public="$(gnunet-identity -d | grep "test_plugin_rest_identity" | awk 'NR==1{print $3}')" + +curl_put "${namestore_link}" '{"newname":"test_plugin_rest_identity1","pubkey":"'$public'"}' "HTTP/1.1 204" +curl_put "${namestore_link}" '{"newname":"test_plugin_rest_identity1","pubkey":"'$public'"}' "HTTP/1.1 409" +curl_put "${namestore_link}" '{"newname":"test_plugin_rest_identity1","pubkey":"'$public'xx"}' "HTTP/1.1 404" +curl_put "${namestore_link}" '{"newname":"test_plugin_rest_identity1","pubkey":""}' "HTTP/1.1 404" +curl_put "${namestore_link}" '{"newname":"test_plugin_rest_identity1","pubke":""}' "HTTP/1.1 404" +curl_put "${namestore_link}" '{"newname":"test_plugin_rest_identity1","pubke":"","other":"sdfdsf"}' "HTTP/1.1 404" +curl_put "${namestore_link}" '{"newname":"test_plugin_rest_identity1","pubke":"","name":"sdfdsf"}' "HTTP/1.1 404" +curl_put "${namestore_link}" '{"newname":"test_plugin_rest_identity","pubke":"","name":"test_plugin_rest_identity1"}' "HTTP/1.1 204" +curl_put "${namestore_link}" '{"newnam":"test_plugin_rest_identity","pubkey":"'$public'"}' "error" +curl_put "${namestore_link}" '{"newname":"test_plugin_rest_identity1","name":"test_plugin_rest_identity"}' "HTTP/1.1 204" +curl_put "${namestore_link}" '{"newname":"TEST_plugin_rest_identity1","name":"test_plugin_rest_identity1"}' "HTTP/1.1 409" +curl_put "${namestore_link}" '{"newname":"test_plugin_rest_identity1","name":"test_plugin_rest_identity1"}' "HTTP/1.1 409" +curl_put "${namestore_link}" '{"newname":"test_plugin_rest_identity","name":"test_plugin_rest_identityxxx"}' "HTTP/1.1 404" +curl_put "${namestore_link}" '{"newname":"test_plugin_rest_identity","name":"test_plugin_rest_identity1"}' "HTTP/1.1 204" +curl_put "${namestore_link}" '{"newnam":"test_plugin_rest_identityfail","name":"test_plugin_rest_identity"}' "error" + + +#Test subsystem +curl_put "${identity_link}" '{"subsystem":"namestore","name":"test_plugin_rest_identity"}' "HTTP/1.1 204" +curl_put "${identity_link}" '{"subsystem":"namestore","name":"test_plugin_rest_identity"}' "HTTP/1.1 204" +curl_get "${identity_link}?subsystem=namestore" "test_plugin_rest_identity" +curl_post "${identity_link}" '{"name":"test_plugin_rest_identity1"}' "HTTP/1.1 201 Created" +public="$(gnunet-identity -d | grep "test_plugin_rest_identity" | awk 'NR==1{print $3}')" +curl_put "${identity_link}" '{"subsystem":"namestore","pubkey":"'"$public"'"}' "HTTP/1.1 204" +curl_get "${identity_link}?subsystem=namestore" "test_plugin_rest_identity1" +curl_get "${identity_link}?subsystem=test_plugin_rest_identity_no_subsystem" "error" +curl_put "${identity_link}" '{"subsystem":"test_plugin_rest_identity_no_subsystem","name":"test_plugin_rest_identity1"}' "HTTP/1.1 204" +curl_get "${identity_link}?subsystem=test_plugin_rest_identity_no_subsystem" "test_plugin_rest_identity1" + +curl_put "${identity_link}" '{"subsyste":"test_plugin_rest_identity_no_subsystem","name":"test_plugin_rest_identity1"}' "error" +curl_put "${identity_link}" '{"subsystem":"test_plugin_rest_identity_no_subsystem","name":"Test_plugin_rest_identity1"}' "HTTP/1.1 204" + +#Test DELETE +curl_delete "${identity_link}?name=test_plugin_rest_identity" "HTTP/1.1 204" +curl_get "${identity_link}?name=test_plugin_rest_identity" "error" +curl_delete "${identity_link}?name=TEST_plugin_rest_identity1" "HTTP/1.1 404" +curl_delete "${identity_link}?name=test_plugin_rest_identity1" "HTTP/1.1 204" +curl_get "${identity_link}?name=test_plugin_rest_identity1" "error" +curl_delete "${identity_link}?name=test_plugin_rest_identity_not_found" "HTTP/1.1 404" +curl_post "${identity_link}" '{"name":"test_plugin_rest_identity1"}' "HTTP/1.1 201 Created" +public="$(gnunet-identity -d | grep "test_plugin_rest_identity1" | awk 'NR==1{print $3}')" +curl_delete "${identity_link}?pubkey=$public" "HTTP/1.1 204" +curl_delete "${identity_link}?pubke=$public" "error" +curl_delete "${identity_link}?pubkey=$public&other=232" "HTTP/1.1 404" + +#test default subsystem + +exit 0; -- cgit v1.2.3 From 0d239903075f518edef85277f13d1b5d303443bf Mon Sep 17 00:00:00 2001 From: Phil Date: Wed, 8 Aug 2018 23:24:10 +0200 Subject: Namestore Rest API finished --- src/json/json_gnsrecord.c | 18 ++++--- src/namestore/plugin_rest_namestore.c | 22 ++++++-- src/namestore/test_plugin_rest_namestore.sh | 78 +++-------------------------- 3 files changed, 37 insertions(+), 81 deletions(-) (limited to 'src') diff --git a/src/json/json_gnsrecord.c b/src/json/json_gnsrecord.c index 4f6d30748..7bdf97f06 100644 --- a/src/json/json_gnsrecord.c +++ b/src/json/json_gnsrecord.c @@ -54,7 +54,7 @@ parse_gnsrecordobject (void *cls, const char *record_type; const char *label; int flag; - void *rdata; + void *rdata = NULL; size_t rdata_size; GNUNET_assert(NULL != root); @@ -72,7 +72,7 @@ parse_gnsrecordobject (void *cls, GNUNET_JSON_GNSRECORD_EXPIRATION_TIME, &expiration_time, GNUNET_JSON_GNSRECORD_FLAG, &flag, GNUNET_JSON_GNSRECORD_LABEL, &label); - if (GNUNET_SYSERR == unpack_state) + if (0 != unpack_state) { GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Error json object has a wrong format!\n"); @@ -82,7 +82,8 @@ parse_gnsrecordobject (void *cls, gnsrecord_object->record_type = GNUNET_GNSRECORD_typename_to_number(record_type); if (UINT32_MAX == gnsrecord_object->record_type) { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,"Unsupported type"); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,"Unsupported type\n"); + GNUNET_free(gnsrecord_object); return GNUNET_SYSERR; } if (GNUNET_OK @@ -91,7 +92,8 @@ parse_gnsrecordobject (void *cls, &rdata, &rdata_size)) { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,"Value invalid for record type"); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,"Value invalid for record type\n"); + GNUNET_free(gnsrecord_object); return GNUNET_SYSERR; } @@ -110,7 +112,9 @@ parse_gnsrecordobject (void *cls, } else { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Expiration time invalid"); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Expiration time invalid\n"); + GNUNET_free_non_null(rdata); + GNUNET_free(gnsrecord_object); return GNUNET_SYSERR; } // check if flag is a valid enum value @@ -119,7 +123,9 @@ parse_gnsrecordobject (void *cls, && (GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION != flag) && (GNUNET_GNSRECORD_RF_SHADOW_RECORD) != flag) { - GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Flag invalid"); + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Flag invalid\n"); + GNUNET_free_non_null(rdata); + GNUNET_free(gnsrecord_object); return GNUNET_SYSERR; } gnsrecord_object->flags = (enum GNUNET_GNSRECORD_Flags)flag; diff --git a/src/namestore/plugin_rest_namestore.c b/src/namestore/plugin_rest_namestore.c index 3801431b2..f14707cce 100644 --- a/src/namestore/plugin_rest_namestore.c +++ b/src/namestore/plugin_rest_namestore.c @@ -641,16 +641,17 @@ namestore_add (struct GNUNET_REST_RequestHandle *con_handle, { handle->emsg = GNUNET_strdup("Invalid data"); GNUNET_SCHEDULER_add_now (&do_error, handle); - GNUNET_free_non_null(gns_record); + GNUNET_JSON_parse_free(gnsspec); json_decref (data_js); return; } + handle->rd = gns_record; + name_json = json_object_get(data_js, "label"); if (!json_is_string(name_json)) { handle->emsg = GNUNET_strdup("Missing name"); GNUNET_SCHEDULER_add_now (&do_error, handle); - GNUNET_free_non_null(gns_record); json_decref (data_js); return; } @@ -659,7 +660,6 @@ namestore_add (struct GNUNET_REST_RequestHandle *con_handle, { handle->emsg = GNUNET_strdup("Missing name"); GNUNET_SCHEDULER_add_now (&do_error, handle); - GNUNET_free_non_null(gns_record); json_decref (data_js); return; } @@ -667,12 +667,10 @@ namestore_add (struct GNUNET_REST_RequestHandle *con_handle, { handle->emsg = GNUNET_strdup("Missing name"); GNUNET_SCHEDULER_add_now (&do_error, handle); - GNUNET_free_non_null(gns_record); json_decref (data_js); return; } json_decref (data_js); - handle->rd = gns_record; //change zone if pubkey or name specified GNUNET_CRYPTO_hash (GNUNET_REST_API_PARAM_PUBKEY, @@ -711,6 +709,12 @@ namestore_add (struct GNUNET_REST_RequestHandle *con_handle, { handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key(ego_entry->ego); } + if (NULL == handle->zone_pkey) + { + handle->emsg = GNUNET_strdup("No default identity for namestore"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } handle->add_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle, handle->zone_pkey, handle->label_name, @@ -813,6 +817,14 @@ namestore_delete (struct GNUNET_REST_RequestHandle *con_handle, } handle->label_name = GNUNET_strdup( GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, &key)); + + if (NULL == handle->zone_pkey) + { + handle->emsg = GNUNET_strdup("No default identity for namestore"); + GNUNET_SCHEDULER_add_now (&do_error, handle); + return; + } + handle->add_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle, handle->zone_pkey, handle->label_name, diff --git a/src/namestore/test_plugin_rest_namestore.sh b/src/namestore/test_plugin_rest_namestore.sh index 7c1e97397..de02dfafc 100755 --- a/src/namestore/test_plugin_rest_namestore.sh +++ b/src/namestore/test_plugin_rest_namestore.sh @@ -11,7 +11,7 @@ curl_get () { #$1 is link #$2 is grep cache="$(curl -v "$1" 2>&1 | grep "$2")" - echo $cache + #echo $cache if [ "" == "$cache" ] then exit 1 @@ -23,7 +23,7 @@ curl_post () { #$2 is data #$3 is grep cache="$(curl -v -X "POST" "$1" --data "$2" 2>&1 | grep "$3")" - echo $cache + #echo $cache if [ "" == "$cache" ] then exit 1 @@ -34,7 +34,7 @@ curl_delete () { #$1 is link #$2 is grep cache="$(curl -v -X "DELETE" "$1" 2>&1 | grep "$2")" - echo $cache + #echo $cache if [ "" == "$cache" ] then exit 1 @@ -197,74 +197,12 @@ gnunet-namestore -z $name -p -a -n "test_entry" -e "1d" -V "HVX38H2CB7WJM0WCPWT9 curl_delete "${namestore_link}?label=test_entry&name=$name" "HTTP/1.1 204" gnunet-namestore -z $name -p -a -n "test_entry" -e "1d" -V "HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG" -t "PKEY" curl_delete "${namestore_link}?label=test_entry&pubkey=$public" "HTTP/1.1 204" +gnunet-namestore -z $name -p -a -n "test_entry" -e "1d" -V "HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRG" -t "PKEY" +curl_delete "${namestore_link}?label=test_entry&pubkey=$name" "HTTP/1.1 404" -exit 0; - - - -#pubkey zone -#name zone -curl_post "${namestore_link}" '{"name":"test_plugin_rest_identity"}' "HTTP/1.1 201 Created" -curl_post "${namestore_link}" '{"name":"test_plugin_rest_identity"}' "HTTP/1.1 409" -curl_post "${namestore_link}" '{"name":"Test_plugin_rest_identity"}' "HTTP/1.1 409" -curl_post "${namestore_link}" '{}' "error" -curl_post "${namestore_link}" '' "error" -curl_post "${namestore_link}" '{"name":""}' "error" -curl_post "${namestore_link}" '{"name":123}' "error" -curl_post "${namestore_link}" '{"name":[]}' "error" -curl_post "${namestore_link}" '{"name1":"test_plugin_rest_identity"}' "error" -curl_post "${namestore_link}" '{"other":""}' "error" -curl_post "${namestore_link}" '{"name":"test_plugin_rest_identity1", "other":"test_plugin_rest_identity2"}' "error" - -#Test PUT -name="$(gnunet-identity -d | grep "test_plugin_rest_identity" | awk 'NR==1{print $1}')" -public="$(gnunet-identity -d | grep "test_plugin_rest_identity" | awk 'NR==1{print $3}')" - -curl_put "${namestore_link}" '{"newname":"test_plugin_rest_identity1","pubkey":"'$public'"}' "HTTP/1.1 204" -curl_put "${namestore_link}" '{"newname":"test_plugin_rest_identity1","pubkey":"'$public'"}' "HTTP/1.1 409" -curl_put "${namestore_link}" '{"newname":"test_plugin_rest_identity1","pubkey":"'$public'xx"}' "HTTP/1.1 404" -curl_put "${namestore_link}" '{"newname":"test_plugin_rest_identity1","pubkey":""}' "HTTP/1.1 404" -curl_put "${namestore_link}" '{"newname":"test_plugin_rest_identity1","pubke":""}' "HTTP/1.1 404" -curl_put "${namestore_link}" '{"newname":"test_plugin_rest_identity1","pubke":"","other":"sdfdsf"}' "HTTP/1.1 404" -curl_put "${namestore_link}" '{"newname":"test_plugin_rest_identity1","pubke":"","name":"sdfdsf"}' "HTTP/1.1 404" -curl_put "${namestore_link}" '{"newname":"test_plugin_rest_identity","pubke":"","name":"test_plugin_rest_identity1"}' "HTTP/1.1 204" -curl_put "${namestore_link}" '{"newnam":"test_plugin_rest_identity","pubkey":"'$public'"}' "error" -curl_put "${namestore_link}" '{"newname":"test_plugin_rest_identity1","name":"test_plugin_rest_identity"}' "HTTP/1.1 204" -curl_put "${namestore_link}" '{"newname":"TEST_plugin_rest_identity1","name":"test_plugin_rest_identity1"}' "HTTP/1.1 409" -curl_put "${namestore_link}" '{"newname":"test_plugin_rest_identity1","name":"test_plugin_rest_identity1"}' "HTTP/1.1 409" -curl_put "${namestore_link}" '{"newname":"test_plugin_rest_identity","name":"test_plugin_rest_identityxxx"}' "HTTP/1.1 404" -curl_put "${namestore_link}" '{"newname":"test_plugin_rest_identity","name":"test_plugin_rest_identity1"}' "HTTP/1.1 204" -curl_put "${namestore_link}" '{"newnam":"test_plugin_rest_identityfail","name":"test_plugin_rest_identity"}' "error" - - -#Test subsystem -curl_put "${identity_link}" '{"subsystem":"namestore","name":"test_plugin_rest_identity"}' "HTTP/1.1 204" -curl_put "${identity_link}" '{"subsystem":"namestore","name":"test_plugin_rest_identity"}' "HTTP/1.1 204" -curl_get "${identity_link}?subsystem=namestore" "test_plugin_rest_identity" -curl_post "${identity_link}" '{"name":"test_plugin_rest_identity1"}' "HTTP/1.1 201 Created" -public="$(gnunet-identity -d | grep "test_plugin_rest_identity" | awk 'NR==1{print $3}')" -curl_put "${identity_link}" '{"subsystem":"namestore","pubkey":"'"$public"'"}' "HTTP/1.1 204" -curl_get "${identity_link}?subsystem=namestore" "test_plugin_rest_identity1" -curl_get "${identity_link}?subsystem=test_plugin_rest_identity_no_subsystem" "error" -curl_put "${identity_link}" '{"subsystem":"test_plugin_rest_identity_no_subsystem","name":"test_plugin_rest_identity1"}' "HTTP/1.1 204" -curl_get "${identity_link}?subsystem=test_plugin_rest_identity_no_subsystem" "test_plugin_rest_identity1" - -curl_put "${identity_link}" '{"subsyste":"test_plugin_rest_identity_no_subsystem","name":"test_plugin_rest_identity1"}' "error" -curl_put "${identity_link}" '{"subsystem":"test_plugin_rest_identity_no_subsystem","name":"Test_plugin_rest_identity1"}' "HTTP/1.1 204" - -#Test DELETE -curl_delete "${identity_link}?name=test_plugin_rest_identity" "HTTP/1.1 204" -curl_get "${identity_link}?name=test_plugin_rest_identity" "error" -curl_delete "${identity_link}?name=TEST_plugin_rest_identity1" "HTTP/1.1 404" -curl_delete "${identity_link}?name=test_plugin_rest_identity1" "HTTP/1.1 204" -curl_get "${identity_link}?name=test_plugin_rest_identity1" "error" -curl_delete "${identity_link}?name=test_plugin_rest_identity_not_found" "HTTP/1.1 404" -curl_post "${identity_link}" '{"name":"test_plugin_rest_identity1"}' "HTTP/1.1 201 Created" -public="$(gnunet-identity -d | grep "test_plugin_rest_identity1" | awk 'NR==1{print $3}')" -curl_delete "${identity_link}?pubkey=$public" "HTTP/1.1 204" -curl_delete "${identity_link}?pubke=$public" "error" -curl_delete "${identity_link}?pubkey=$public&other=232" "HTTP/1.1 404" -#test default subsystem +#Test default identity +#not possible without defining exit 0; + -- cgit v1.2.3 From 995c8c9ce229d3ad25eeda53a0fbeda5cafa4f05 Mon Sep 17 00:00:00 2001 From: Phil Date: Wed, 8 Aug 2018 23:25:44 +0200 Subject: -fix added timeout for gns Rest plugin --- src/gns/plugin_rest_gns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/gns/plugin_rest_gns.c b/src/gns/plugin_rest_gns.c index 495d01504..41b855743 100644 --- a/src/gns/plugin_rest_gns.c +++ b/src/gns/plugin_rest_gns.c @@ -388,7 +388,7 @@ rest_process_request(struct GNUNET_REST_RequestHandle *rest_handle, struct RequestHandle *handle = GNUNET_new (struct RequestHandle); handle->response_code = 0; - handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; + handle->timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60); handle->proc_cls = proc_cls; handle->proc = proc; handle->rest_handle = rest_handle; -- cgit v1.2.3 From cffad0ad30400dda7c7c4ef77ed7625013193dbe Mon Sep 17 00:00:00 2001 From: Phil Date: Wed, 8 Aug 2018 23:26:11 +0200 Subject: Peerinfo Rest API finished --- src/peerinfo/plugin_rest_peerinfo.c | 54 ++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/peerinfo/plugin_rest_peerinfo.c b/src/peerinfo/plugin_rest_peerinfo.c index a65089b32..97c473e36 100644 --- a/src/peerinfo/plugin_rest_peerinfo.c +++ b/src/peerinfo/plugin_rest_peerinfo.c @@ -32,10 +32,11 @@ #include #define GNUNET_REST_API_NS_PEERINFO "/peerinfo" + #define GNUNET_REST_API_PEERINFO_PEER "peer" #define GNUNET_REST_API_PEERINFO_FRIEND "friend" +#define GNUNET_REST_API_PEERINFO_ARRAY "array" -//TODO define other variables #define GNUNET_REST_ERROR_UNKNOWN "Unkown Error" /** @@ -60,8 +61,6 @@ struct Plugin const struct GNUNET_CONFIGURATION_Handle *cfg; }; -//TODO add specific structs - /** * Record we keep for each printable address. @@ -155,9 +154,19 @@ static struct PrintContext *pc_tail; struct RequestHandle { - //TODO add specific entries + /** + * JSON temporary array + */ json_t *temp_array; + + /** + * Expiration time string + */ char *expiration_str; + + /** + * Address string + */ const char *address; /** @@ -166,7 +175,7 @@ struct RequestHandle char *pubkey; /** - * JSON array response + * JSON response */ json_t *response; @@ -243,7 +252,18 @@ cleanup_handle (void *cls) GNUNET_free (handle->url); if (NULL != handle->emsg) GNUNET_free (handle->emsg); - + if (NULL != handle->address) + GNUNET_free ((char*)handle->address); + if (NULL != handle->expiration_str) + GNUNET_free (handle->expiration_str); + if (NULL != handle->pubkey) + GNUNET_free (handle->pubkey); + + if (NULL != handle->temp_array) + { + json_decref(handle->temp_array); + handle->temp_array = NULL; + } if (NULL != handle->response) { json_decref(handle->response); @@ -255,14 +275,11 @@ cleanup_handle (void *cls) GNUNET_PEERINFO_iterate_cancel(handle->list_it); handle->list_it = NULL; } - if (NULL != handle->peerinfo_handle) { GNUNET_PEERINFO_disconnect(handle->peerinfo_handle); handle->peerinfo_handle = NULL; } - - //TODO add specific cleanup GNUNET_free (handle); } @@ -358,13 +375,16 @@ dump_pc (struct PrintContext *pc) { struct RequestHandle *handle; unsigned int i; + json_t *response_entry; json_t *temp_array; json_t *object; json_t *address; json_t *expires; + json_t *friend_and_peer_json; char *friend_and_peer; temp_array = json_array(); + response_entry = json_object(); // printf (_("%sPeer `%s'\n"), // (GNUNET_YES == pc->friend_only) ? "F2F: " : "", @@ -395,13 +415,20 @@ dump_pc (struct PrintContext *pc) "%s%s", (GNUNET_YES == pc->friend_only) ? "F2F:" : "", GNUNET_i2s_full (&pc->peer)); - json_object_set(pc->handle->response, - friend_and_peer, + friend_and_peer_json = json_string(friend_and_peer); + json_object_set(response_entry, + GNUNET_REST_API_PEERINFO_PEER, + friend_and_peer_json); + json_object_set(response_entry, + GNUNET_REST_API_PEERINFO_ARRAY, temp_array); + json_array_append(pc->handle->response, response_entry); + json_decref(friend_and_peer_json); GNUNET_free(friend_and_peer); } json_decref (temp_array); + json_decref(response_entry); GNUNET_free_non_null (pc->address_list); GNUNET_CONTAINER_DLL_remove (pc_head, @@ -519,7 +546,7 @@ peerinfo_list_iteration(void *cls, if (NULL == handle->response) { - handle->response = json_object(); + handle->response = json_array(); } if (NULL == peer) @@ -658,7 +685,6 @@ options_cont (struct GNUNET_REST_RequestHandle *con_handle, static void init_cont (struct RequestHandle *handle) { - //TODO specify parameter of init_cont if necessary struct GNUNET_REST_RequestHandlerError err; static const struct GNUNET_REST_RequestHandler handlers[] = { {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_PEERINFO, &peerinfo_get}, @@ -705,8 +731,6 @@ rest_process_request(struct GNUNET_REST_RequestHandle *rest_handle, if (handle->url[strlen (handle->url)-1] == '/') handle->url[strlen (handle->url)-1] = '\0'; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n"); - //TODO connect to specific service - //connect ( cfg, [..., &callback_function, handle]); handle->peerinfo_handle = GNUNET_PEERINFO_connect(cfg); init_cont(handle); handle->timeout_task = -- cgit v1.2.3 From 1ad7b69834fffc95e05354983009e435030c0861 Mon Sep 17 00:00:00 2001 From: "Schanzenbach, Martin" Date: Thu, 9 Aug 2018 23:51:46 +0200 Subject: style --- src/gns/plugin_rest_gns.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/gns/plugin_rest_gns.c b/src/gns/plugin_rest_gns.c index 41b855743..fd2469577 100644 --- a/src/gns/plugin_rest_gns.c +++ b/src/gns/plugin_rest_gns.c @@ -200,7 +200,7 @@ do_error (void *cls) */ static void handle_gns_response (void *cls, - int was_gns, + int was_gns, uint32_t rd_count, const struct GNUNET_GNSRECORD_Data *rd) { @@ -223,7 +223,7 @@ handle_gns_response (void *cls, for (uint32_t i=0;irecord_type) && - (GNUNET_GNSRECORD_TYPE_ANY != handle->record_type) ) + (GNUNET_GNSRECORD_TYPE_ANY != handle->record_type) ) { continue; } @@ -252,8 +252,8 @@ handle_gns_response (void *cls, */ void get_gns_cont (struct GNUNET_REST_RequestHandle *con_handle, - const char* url, - void *cls) + const char* url, + void *cls) { struct RequestHandle *handle = cls; struct GNUNET_HashCode key; @@ -261,11 +261,11 @@ get_gns_cont (struct GNUNET_REST_RequestHandle *con_handle, char *name; GNUNET_CRYPTO_hash (GNUNET_REST_GNS_PARAM_NAME, - strlen (GNUNET_REST_GNS_PARAM_NAME), - &key); + strlen (GNUNET_REST_GNS_PARAM_NAME), + &key); if ( GNUNET_NO - == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, - &key)) + == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, + &key)) { handle->emsg = GNUNET_strdup("Parameter name is missing"); GNUNET_SCHEDULER_add_now (&do_error, handle); @@ -282,11 +282,11 @@ get_gns_cont (struct GNUNET_REST_RequestHandle *con_handle, handle->record_type = UINT32_MAX; GNUNET_CRYPTO_hash (GNUNET_REST_GNS_PARAM_RECORD_TYPE, - strlen (GNUNET_REST_GNS_PARAM_RECORD_TYPE), - &key); + strlen (GNUNET_REST_GNS_PARAM_RECORD_TYPE), + &key); if ( GNUNET_YES - == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, - &key)) + == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, + &key)) { record_type = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, &key); handle->record_type = GNUNET_GNSRECORD_typename_to_number(record_type); @@ -307,11 +307,11 @@ get_gns_cont (struct GNUNET_REST_RequestHandle *con_handle, } handle->gns_lookup = GNUNET_GNS_lookup_with_tld (handle->gns, - handle->name, - handle->record_type, - GNUNET_NO, - &handle_gns_response, - handle); + handle->name, + handle->record_type, + GNUNET_NO, + &handle_gns_response, + handle); return; } @@ -382,17 +382,17 @@ init_cont (struct RequestHandle *handle) */ static void rest_process_request(struct GNUNET_REST_RequestHandle *rest_handle, - GNUNET_REST_ResultProcessor proc, - void *proc_cls) + GNUNET_REST_ResultProcessor proc, + void *proc_cls) { struct RequestHandle *handle = GNUNET_new (struct RequestHandle); - + handle->response_code = 0; handle->timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60); handle->proc_cls = proc_cls; handle->proc = proc; 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'; @@ -404,7 +404,7 @@ rest_process_request(struct GNUNET_REST_RequestHandle *rest_handle, GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_error, handle); - + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n"); } -- cgit v1.2.3