tighten formatting rules
[oweals/gnunet.git] / src / gns / plugin_rest_gns.c
index 22c908275b33f99424f66b3ac7bc2cc3068583fa..6ae753a0708e47b3ac5a01a1f6ae80fb7ed45aa2 100644 (file)
@@ -2,21 +2,21 @@
    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 <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
 /**
  * @author Philippe Buschmann
  * @file gns/plugin_rest_gns.c
 #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"
 #include <jansson.h>
 
+/**
+ * Rest API GNS Namespace
+ */
 #define GNUNET_REST_API_NS_GNS "/gns"
 
-#define GNUNET_REST_PARAMETER_GNS_NAME "name"
+/**
+ * Rest API GNS Parameter record_type
+ */
+#define GNUNET_REST_GNS_PARAM_RECORD_TYPE "record_type"
 
-#define GNUNET_REST_PARAMETER_GNS_RECORD_TYPE "record_type"
+/**
+ * Rest API GNS ERROR Unknown Error
+ */
+#define GNUNET_REST_GNS_ERROR_UNKNOWN "Unknown Error"
+
+/**
+ * Rest API GNS ERROR Record not found
+ */
+#define GNUNET_REST_GNS_NOT_FOUND "Record not found"
 
 /**
  * The configuration handle
@@ -45,7 +60,7 @@ const struct GNUNET_CONFIGURATION_Handle *cfg;
 /**
  * HTTP methods allows for this plugin
  */
-static charallow_methods;
+static char *allow_methods;
 
 /**
  * @brief struct returned by the initialization function of the plugin
@@ -55,11 +70,11 @@ struct Plugin
   const struct GNUNET_CONFIGURATION_Handle *cfg;
 };
 
-
-
+/**
+ * The request handle
+ */
 struct RequestHandle
 {
-
   /**
    * Connection to GNS
    */
@@ -84,7 +99,7 @@ struct RequestHandle
    * Rest connection
    */
   struct GNUNET_REST_RequestHandle *rest_handle;
-  
+
   /**
    * Desired timeout for the lookup (default is no timeout).
    */
@@ -116,10 +131,9 @@ struct RequestHandle
   char *emsg;
 
   /**
-   * Reponse code
+   * Response code
    */
   int response_code;
-
 };
 
 
@@ -128,10 +142,11 @@ struct RequestHandle
  * @param handle Handle to clean up
  */
 static void
-cleanup_handle (struct RequestHandle *handle)
+cleanup_handle (void *cls)
 {
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Cleaning up\n");
+  struct RequestHandle *handle = cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
 
   if (NULL != handle->gns_lookup)
   {
@@ -155,7 +170,7 @@ cleanup_handle (struct RequestHandle *handle)
     GNUNET_free (handle->name);
   if (NULL != handle->emsg)
     GNUNET_free (handle->emsg);
-  
+
   GNUNET_free (handle);
 }
 
@@ -170,20 +185,36 @@ 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->timeout_task)
+    GNUNET_SCHEDULER_cancel (handle->timeout_task);
+  handle->timeout_task = NULL;
   if (NULL == handle->emsg)
-    handle->emsg = GNUNET_strdup("Unknown Error");
+    handle->emsg = GNUNET_strdup (GNUNET_REST_GNS_ERROR_UNKNOWN);
 
-  GNUNET_asprintf (&json_error, "{\"error\": \"%s\"}", handle->emsg);
-  
-  if (0 == handle->response_code)
-    handle->response_code = MHD_HTTP_OK;
+  json_object_set_new (json_error, "error", json_string (handle->emsg));
 
-  resp = GNUNET_REST_create_response (json_error);
+  if (0 == handle->response_code)
+    handle->response_code = MHD_HTTP_INTERNAL_SERVER_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);
+}
+
+
+static void
+do_timeout (void *cls)
+{
+  struct RequestHandle *handle = cls;
+
+  handle->timeout_task = NULL;
+  handle->response_code = MHD_HTTP_REQUEST_TIMEOUT;
+  do_error (handle);
 }
 
 
@@ -197,56 +228,34 @@ 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)
 {
   struct RequestHandle *handle = cls;
   struct MHD_Response *resp;
-  json_t *result_array;
-  json_t *record_obj;
-  char *record_value;
+  json_t *result_obj;
   char *result;
 
   handle->gns_lookup = NULL;
 
   if (GNUNET_NO == was_gns)
   {
-    handle->emsg = GNUNET_strdup("Name not found in GNS");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  if (0 == rd_count)
-  {
-    handle->emsg = GNUNET_strdup("No result found");
+    handle->response_code = MHD_HTTP_NOT_FOUND;
+    handle->emsg = GNUNET_strdup (GNUNET_REST_GNS_NOT_FOUND);
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
 
-  result_array = json_array();
-  for (uint32_t i=0;i<rd_count;i++)
-  {
-    if ((rd[i].record_type != handle->record_type) &&
-       (GNUNET_GNSRECORD_TYPE_ANY != handle->record_type) )
-    {
-      continue;
-    }
-
-    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);
-  }
+  result_obj = GNUNET_JSON_from_gnsrecord (handle->name, rd, rd_count);
 
-  result = json_dumps(result_array, 0);
+  result = json_dumps (result_obj, 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);
+  json_decref (result_obj);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
 }
 
 
@@ -259,72 +268,63 @@ 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;
-  int conversion_state;
-
-  GNUNET_CRYPTO_hash (GNUNET_REST_PARAMETER_GNS_NAME,
-                     strlen (GNUNET_REST_PARAMETER_GNS_NAME),
-                     &key);
-  if ( GNUNET_NO
-        == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map,
-                                                &key))
+  char *record_type;
+  char *name;
+
+  name = NULL;
+  handle->name = NULL;
+  if (strlen (GNUNET_REST_API_NS_GNS) < strlen (handle->url))
   {
-    handle->emsg = GNUNET_strdup("Parameter name is missing");
+    name = &handle->url[strlen (GNUNET_REST_API_NS_GNS) + 1];
+  }
+
+  if (NULL == name)
+  {
+    handle->response_code = MHD_HTTP_NOT_FOUND;
+    handle->emsg = GNUNET_strdup (GNUNET_REST_GNS_NOT_FOUND);
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
-  handle->name = GNUNET_strdup(
-      GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map,&key));
-
-  GNUNET_CRYPTO_hash (GNUNET_REST_PARAMETER_GNS_RECORD_TYPE,
-                     strlen (GNUNET_REST_PARAMETER_GNS_RECORD_TYPE),
-                     &key);
-  if ( GNUNET_NO
-        == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map,
-                                                &key))
+  if (0 >= strlen (name))
   {
-    handle->emsg = GNUNET_strdup("Parameter record_type is missing");
+    handle->response_code = MHD_HTTP_NOT_FOUND;
+    handle->emsg = GNUNET_strdup (GNUNET_REST_GNS_NOT_FOUND);
     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))
+  handle->name = GNUNET_strdup (name);
+
+  handle->record_type = UINT32_MAX;
+  GNUNET_CRYPTO_hash (GNUNET_REST_GNS_PARAM_RECORD_TYPE,
+                      strlen (GNUNET_REST_GNS_PARAM_RECORD_TYPE),
+                      &key);
+  if (GNUNET_YES ==
+      GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, &key))
   {
-    handle->record_type = GNUNET_GNSRECORD_TYPE_ANY;
+    record_type =
+      GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, &key);
+    handle->record_type = GNUNET_GNSRECORD_typename_to_number (record_type);
   }
 
-  handle->gns = GNUNET_GNS_connect (cfg);
-  if (NULL == handle->gns)
+  if (UINT32_MAX == handle->record_type)
   {
-    handle->emsg = GNUNET_strdup ("GNS not available");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
+    handle->record_type = GNUNET_GNSRECORD_TYPE_ANY;
   }
 
   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->emsg = GNUNET_strdup("GNS lookup failed");
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
+                                                   handle->name,
+                                                   handle->record_type,
+                                                   GNUNET_NO,
+                                                   &handle_gns_response,
+                                                   handle);
 }
 
 
-
 /**
  * Respond to OPTIONS request
  *
@@ -334,19 +334,17 @@ get_gns_cont (struct GNUNET_REST_RequestHandle *con_handle,
  */
 static void
 options_cont (struct GNUNET_REST_RequestHandle *con_handle,
-              const charurl,
+              const char *url,
               void *cls)
 {
   struct MHD_Response *resp;
   struct RequestHandle *handle = cls;
 
-  //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);
+  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;
 }
 
@@ -360,16 +358,13 @@ static void
 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
-  };
-
-  if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle,
-                                               handlers,
-                                               &err,
-                                               handle))
+  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 };
+
+  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);
@@ -389,30 +384,29 @@ init_cont (struct RequestHandle *handle)
  * @return GNUNET_OK if request accepted
  */
 static void
-rest_process_request(struct GNUNET_REST_RequestHandle *rest_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);
-  
+
   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;
-  
+
   handle->url = GNUNET_strdup (rest_handle->url);
-  if (handle->url[strlen (handle->url)-1] == '/')
-    handle->url[strlen (handle->url)-1] = '\0';
+  if (handle->url[strlen (handle->url) - 1] == '/')
+    handle->url[strlen (handle->url) - 1] = '\0';
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
-
-  init_cont(handle);
+  handle->gns = GNUNET_GNS_connect (cfg);
+  init_cont (handle);
 
   handle->timeout_task =
-    GNUNET_SCHEDULER_add_delayed (handle->timeout,
-                                  &do_error,
-                                  handle);
-  
+    GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_timeout, handle);
+
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
 }
 
@@ -431,8 +425,8 @@ libgnunet_plugin_rest_gns_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->cls = &plugin;
@@ -446,8 +440,7 @@ libgnunet_plugin_rest_gns_init (void *cls)
                    MHD_HTTP_METHOD_DELETE,
                    MHD_HTTP_METHOD_OPTIONS);
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              _("Gns REST API initialized\n"));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Gns REST API initialized\n"));
   return api;
 }
 
@@ -463,14 +456,14 @@ libgnunet_plugin_rest_gns_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");
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Gns REST plugin is finished\n");
   return NULL;
 }
 
-/* end of plugin_rest_gns.c */
 
+/* end of plugin_rest_gns.c */