add first sketch of gns benchmarking tool
[oweals/gnunet.git] / src / gns / plugin_rest_gns.c
index d7fc31d4c5d13b66d00e8d1373efd779008c7249..1d215b6a495bf81adef75d4d82ec4953e3b0083e 100644 (file)
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2012-2015 Christian Grothoff (and other contributing authors)
+   Copyright (C) 2012-2015 GNUnet e.V.
 
    GNUnet is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published
@@ -14,8 +14,8 @@
 
    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., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.
+   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
    */
 /**
  * @author Martin Schanzenbach
 #include <gnunet_namestore_service.h>
 #include <gnunet_gns_service.h>
 #include <gnunet_rest_lib.h>
+#include <gnunet_jsonapi_lib.h>
+#include <gnunet_jsonapi_util.h>
 #include <jansson.h>
 
-#define API_NAMESPACE "/resolver"
+#define GNUNET_REST_API_NS_GNS "/gns"
 
 #define GNUNET_REST_JSONAPI_GNS_RECORD_TYPE "record_type"
 
@@ -75,6 +77,11 @@ struct LookupHandle
    */
   struct GNUNET_GNS_LookupRequest *lookup_request;
 
+  /**
+   * Handle to rest request
+   */
+  struct GNUNET_REST_RequestHandle *rest_handle;
+
   /**
    * Lookup an ego with the identity service.
    */
@@ -152,6 +159,11 @@ struct LookupHandle
    */
   struct GNUNET_CRYPTO_EcdsaPrivateKey shorten_key;
 
+  /**
+   * HTTP response code
+   */
+  int response_code;
+
 };
 
 
@@ -211,12 +223,13 @@ cleanup_handle (struct LookupHandle *handle)
  * @param tc scheduler context
  */
 static void
-do_error (void *cls,
-          const struct GNUNET_SCHEDULER_TaskContext *tc)
+do_error (void *cls)
 {
   struct LookupHandle *handle = cls;
-  struct MHD_Response *resp = GNUNET_REST_create_json_response (NULL);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
+  struct MHD_Response *resp;
+
+  resp = GNUNET_REST_create_response (NULL);
+  handle->proc (handle->proc_cls, resp, handle->response_code);
   cleanup_handle (handle);
 }
 
@@ -246,7 +259,7 @@ gnsrecord_to_json (const struct GNUNET_GNSRECORD_Data *rd)
                 (int) rd->record_type);
     return NULL;
   }
-  record_obj = json_object();
+  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);
@@ -283,16 +296,16 @@ process_lookup_result (void *cls, uint32_t rd_count,
 {
   struct LookupHandle *handle = cls;
   struct MHD_Response *resp;
-  struct JsonApiObject *json_object;
-  struct JsonApiResource *json_resource;
+  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_object = GNUNET_REST_jsonapi_object_new ();
-  json_resource = GNUNET_REST_jsonapi_resource_new (GNUNET_REST_JSONAPI_GNS_TYPEINFO, handle->name);
+  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; i<rd_count; i++)
   {
@@ -303,15 +316,15 @@ process_lookup_result (void *cls, uint32_t rd_count,
     json_array_append (result_array, record_obj);
     json_decref (record_obj);
   }
-  GNUNET_REST_jsonapi_resource_add_attr (json_resource,
+  GNUNET_JSONAPI_resource_add_attr (json_resource,
                                          GNUNET_REST_JSONAPI_GNS_RECORD,
                                          result_array);
-  GNUNET_REST_jsonapi_object_resource_add (json_object, json_resource);
-  GNUNET_REST_jsonapi_data_serialize (json_object, &result);
+  GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
+  GNUNET_JSONAPI_document_serialize (json_document, &result);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result);
   json_decref (result_array);
-  GNUNET_REST_jsonapi_object_delete (json_object);
-  resp = GNUNET_REST_create_json_response (result);
+  GNUNET_JSONAPI_document_delete (json_document);
+  resp = GNUNET_REST_create_response (result);
   handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
   GNUNET_free (result);
   cleanup_handle (handle);
@@ -323,10 +336,9 @@ process_lookup_result (void *cls, uint32_t rd_count,
  * identified by the given public key and the shorten zone.
  *
  * @param pkey public key to use for the zone, can be NULL
- * @param shorten_key private key used for shortening, can be NULL
  */
 static void
-lookup_with_keys (struct LookupHandle *handle, const struct GNUNET_CRYPTO_EcdsaPrivateKey *shorten_key)
+lookup_with_public_key (struct LookupHandle *handle)
 {
   if (UINT32_MAX == handle->type)
   {
@@ -341,7 +353,6 @@ lookup_with_keys (struct LookupHandle *handle, const struct GNUNET_CRYPTO_EcdsaP
                                                 &handle->pkey,
                                                 handle->type,
                                                 handle->options,
-                                                shorten_key,
                                                 &process_lookup_result,
                                                 handle);
   }
@@ -352,55 +363,6 @@ lookup_with_keys (struct LookupHandle *handle, const struct GNUNET_CRYPTO_EcdsaP
   }
 }
 
-/**
- * Method called to with the ego we are to use for shortening
- * during the lookup.
- *
- * @param cls closure contains the public key to use
- * @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_shorten_cb (void *cls,
-                     struct GNUNET_IDENTITY_Ego *ego,
-                     void **ctx,
-                     const char *name)
-{
-  struct LookupHandle *handle = cls;
-
-  handle->id_op = NULL;
-  if (NULL == ego)
-    lookup_with_keys (handle, NULL);
-  else
-    lookup_with_keys (handle,
-                      GNUNET_IDENTITY_ego_get_private_key (ego));
-}
-
-/**
- * Perform the actual resolution, starting with the zone
- * identified by the given public key.
- *
- * @param pkey public key to use for the zone
- */
-static void
-lookup_with_public_key (struct LookupHandle *handle)
-{
-  handle->pkeym = handle->pkey;
-  GNUNET_break (NULL == handle->id_op);
-  handle->id_op = GNUNET_IDENTITY_get (handle->identity,
-                                       "gns-short",
-                                       &identity_shorten_cb,
-                                       handle);
-  if (NULL == handle->id_op)
-  {
-    GNUNET_break (0);
-    lookup_with_keys (handle, NULL);
-  }
-}
 
 /**
  * Method called to with the ego we are to use for the lookup,
@@ -431,6 +393,7 @@ identity_zone_cb (void *cls,
   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.
@@ -460,7 +423,8 @@ identity_master_cb (void *cls,
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
-  GNUNET_IDENTITY_ego_get_public_key (ego, &handle->pkey);
+  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 */
@@ -502,30 +466,17 @@ parse_url (const char *url, struct LookupHandle *handle)
   return GNUNET_OK;
 }
 
-/**
- * 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_gns_process_request(struct RestConnectionDataHandle *conndata_handle,
-                         GNUNET_REST_ResultProcessor proc,
-                         void *proc_cls)
+get_gns_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
+              const char* url,
+              void *cls)
 {
-  struct LookupHandle *handle = GNUNET_new (struct LookupHandle);
+  struct LookupHandle *handle = cls;
   struct GNUNET_HashCode key;
 
-  handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
-  handle->proc_cls = proc_cls;
-  handle->proc = proc;
   //parse name and type from url
-  if (GNUNET_OK != parse_url (conndata_handle->url, handle))
+  if (GNUNET_OK != parse_url (url, handle))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error parsing url...\n");
     GNUNET_SCHEDULER_add_now (&do_error, handle);
@@ -555,7 +506,7 @@ rest_gns_process_request(struct RestConnectionDataHandle *conndata_handle,
                                                &key) )
   {
     handle->options = GNUNET_GNS_LO_DEFAULT;//TODO(char*) GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
-                                                         //&key);
+    //&key);
   }
   GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_RECORD_TYPE,
                       strlen (GNUNET_REST_JSONAPI_GNS_RECORD_TYPE),
@@ -564,9 +515,9 @@ rest_gns_process_request(struct RestConnectionDataHandle *conndata_handle,
        GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
                                                &key) )
   {
-    handle->type = GNUNET_GNSRECORD_typename_to_number 
+    handle->type = GNUNET_GNSRECORD_typename_to_number
       (GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
-      &key));
+                                          &key));
   }
   else
     handle->type = GNUNET_GNSRECORD_TYPE_ANY;
@@ -580,6 +531,7 @@ rest_gns_process_request(struct RestConnectionDataHandle *conndata_handle,
   {
     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),
@@ -627,6 +579,71 @@ rest_gns_process_request(struct RestConnectionDataHandle *conndata_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_JSONAPI_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.
  *
@@ -646,7 +663,7 @@ libgnunet_plugin_rest_gns_init (void *cls)
   plugin.cfg = cfg;
   api = GNUNET_new (struct GNUNET_REST_Plugin);
   api->cls = &plugin;
-  api->name = API_NAMESPACE;
+  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"));