gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r35370 - in gnunet: . src src/gns src/include src/rest


From: gnunet
Subject: [GNUnet-SVN] r35370 - in gnunet: . src src/gns src/include src/rest
Date: Wed, 11 Mar 2015 13:54:22 +0100

Author: schanzen
Date: 2015-03-11 13:54:22 +0100 (Wed, 11 Mar 2015)
New Revision: 35370

Added:
   gnunet/src/gns/plugin_rest_gns.c
   gnunet/src/include/gnunet_rest_plugin.h
   gnunet/src/rest/
   gnunet/src/rest/Makefile.am
   gnunet/src/rest/gnunet-rest-server.c
   gnunet/src/rest/rest.conf
Modified:
   gnunet/configure.ac
   gnunet/src/Makefile.am
   gnunet/src/gns/Makefile.am
Log:
REST Service

Modified: gnunet/configure.ac
===================================================================
--- gnunet/configure.ac 2015-03-10 12:20:31 UTC (rev 35369)
+++ gnunet/configure.ac 2015-03-11 12:54:22 UTC (rev 35370)
@@ -1216,6 +1216,15 @@
 AC_MSG_RESULT($enable_wachs)
 AM_CONDITIONAL([HAVE_WACHS], [test "x$enable_wachs" = "xyes"])
 
+# REST API
+AC_MSG_CHECKING(whether to compile REST API)
+AC_ARG_ENABLE([rest],
+   [AS_HELP_STRING([--enable-rest], [enable REST])],
+   [enable_rest=${enableval}],
+   [enable_rest=no])
+AC_MSG_RESULT($enable_rest)
+AM_CONDITIONAL([HAVE_REST], [test "x$enable_rest" = "xyes"])
+
 # should malicious code be compiled (should only be used for testing)?
 AC_MSG_CHECKING(whether to compile malicious code)
 AC_ARG_ENABLE([malicious],
@@ -1520,6 +1529,7 @@
 src/util/resolver.conf
 src/vpn/Makefile
 src/vpn/vpn.conf
+src/rest/Makefile
 pkgconfig/Makefile
 pkgconfig/gnunetarm.pc
 pkgconfig/gnunetats.pc

Modified: gnunet/src/Makefile.am
===================================================================
--- gnunet/src/Makefile.am      2015-03-10 12:20:31 UTC (rev 35369)
+++ gnunet/src/Makefile.am      2015-03-11 12:54:22 UTC (rev 35370)
@@ -48,6 +48,10 @@
  POSTGRES_DIR = postgres
 endif
 
+if HAVE_REST
+ REST_DIR = rest
+endif
+
 SUBDIRS = \
   include $(INTLEMU_SUBDIRS) \
   util \
@@ -60,6 +64,7 @@
   peerinfo \
   $(MYSQL_DIR) \
   $(POSTGRES_DIR) \
+  $(REST_DIR) \
   datacache \
   datastore \
   template \

Modified: gnunet/src/gns/Makefile.am
===================================================================
--- gnunet/src/gns/Makefile.am  2015-03-10 12:20:31 UTC (rev 35369)
+++ gnunet/src/gns/Makefile.am  2015-03-11 12:54:22 UTC (rev 35370)
@@ -85,12 +85,26 @@
 endif
 endif
 
+if HAVE_REST
+REST_PLUGIN = libgnunet_plugin_rest_gns.la
+endif
+
 bin_SCRIPTS = gnunet-gns-proxy-setup-ca
 
 plugin_LTLIBRARIES = \
   libgnunet_plugin_block_gns.la \
-  libgnunet_plugin_gnsrecord_gns.la
+  libgnunet_plugin_gnsrecord_gns.la \
+  $(REST_PLUGIN)
 
+libgnunet_plugin_rest_gns_la_SOURCES = \
+  plugin_rest_gns.c
+libgnunet_plugin_rest_gns_la_LIBADD = \
+  $(top_builddir)/src/gns/libgnunetgns.la \
+  $(top_builddir)/src/identity/libgnunetidentity.la \
+  $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
+  $(LTLIBINTL) -ljansson
+libgnunet_plugin_rest_gns_la_LDFLAGS = \
+ $(GN_PLUGIN_LDFLAGS)
 
 libgnunet_plugin_gnsrecord_gns_la_SOURCES = \
   plugin_gnsrecord_gns.c

Added: gnunet/src/gns/plugin_rest_gns.c
===================================================================
--- gnunet/src/gns/plugin_rest_gns.c                            (rev 0)
+++ gnunet/src/gns/plugin_rest_gns.c    2015-03-11 12:54:22 UTC (rev 35370)
@@ -0,0 +1,658 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2012-2015 Christian Grothoff (and other contributing 
authors)
+
+     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., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+/**
+ * @author Martin Schanzenbach
+ * @file gns/plugin_rest_gns.c
+ * @brief GNUnet GNS REST plugin
+ *
+ */
+
+#include "platform.h"
+#include "gnunet_rest_plugin.h"
+#include <gnunet_dnsparser_lib.h>
+#include <gnunet_identity_service.h>
+#include <gnunet_gnsrecord_lib.h>
+#include <gnunet_namestore_service.h>
+#include <gnunet_gns_service.h>
+#include <jansson.h>
+
+#define API_NAMESPACE "gns"
+
+/**
+ * @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;
+
+    /**
+     * 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;    
+    
+    json_t *json_root;
+
+    GNUNET_REST_ResultProcessor proc;
+
+    char *name;
+
+    const char *ego_str;
+
+    const char *pkey_str;
+
+    int type;
+
+    struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
+
+    struct GNUNET_CRYPTO_EcdsaPublicKey pkeym;
+    
+    enum GNUNET_GNS_LocalOptions options;
+    
+    struct GNUNET_CRYPTO_EcdsaPrivateKey shorten_key;
+    void *proc_cls;
+};
+
+void
+cleanup_handle (struct LookupHandle *handle)
+{
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                                    "Cleaning up\n");
+    if (NULL != handle->json_root)
+        json_decref (handle->json_root);
+
+    if (NULL != handle->name)
+       GNUNET_free (handle->name);
+    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,
+         const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct LookupHandle *handle = cls;
+  
+  cleanup_handle (handle);
+  handle->proc (handle->proc_cls, NULL, 0, GNUNET_SYSERR);
+}
+
+/**
+ * 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)
+{
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                                              "result \n");
+  struct LookupHandle *handle = cls;
+  uint32_t i;
+  const char *typename;
+  char *string_val;
+  char *result;
+  json_t *result_root;
+  json_t *result_name;
+  json_t *result_array;
+  json_t *record_obj;
+
+
+  result_root = json_object();
+  result_name = json_string (handle->name);
+  result_array = json_array();
+  json_object_set (result_root, "name", result_name);
+  json_decref (result_name);
+
+  handle->lookup_request = NULL;
+  
+  for (i=0; i<rd_count; i++)
+  {
+    if ( (rd[i].record_type != handle->type) &&
+     (GNUNET_GNSRECORD_TYPE_ANY != handle->type) )
+      continue;
+    typename = GNUNET_GNSRECORD_number_to_typename (rd[i].record_type);
+    string_val = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
+                           rd[i].data,
+                           rd[i].data_size);
+    if (NULL == string_val)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+           "Record %u of type %d malformed, skipping\n",
+           (unsigned int) i,
+           (int) rd[i].record_type);
+      continue;
+    }
+    else
+    {
+      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));
+      json_array_append (result_array, record_obj);
+      json_decref (record_obj);
+    }
+    GNUNET_free (string_val);
+  }
+  json_object_set (result_root, "query_result", result_array);
+  json_decref (result_array);
+  result = json_dumps (result_root, JSON_COMPACT);
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Result %s\n", result);
+  json_decref (result_root);
+  handle->proc (handle->proc_cls, result, strlen (result), GNUNET_OK);
+  GNUNET_free (result);
+  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
+ * @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)
+{
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                                              "Lookup w/ keys \n");
+  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,
+                    shorten_key,
+                    &process_lookup_result,
+                    handle);
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+         _("Please specify name to lookup!\n"));
+    handle->proc (handle->proc_cls, NULL, 0, GNUNET_SYSERR);
+    cleanup_handle (handle);
+    return;
+  }
+}
+
+/**
+ * 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)
+{
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                                              "shorten \n");
+  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)
+{
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                                  "Lookup w/ pkey \n");
+  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,
+ * 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->proc (handle->proc_cls, NULL, 0, GNUNET_SYSERR);
+    cleanup_handle (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;
+    
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                      "Master cb \n");
+  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->proc (handle->proc_cls, NULL, 0, GNUNET_SYSERR);
+    cleanup_handle (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);
+}
+
+int
+parse_url (const char *url, struct LookupHandle *handle)
+{
+    char *name;
+    char *type;
+    char tmp_url[strlen(url)+1];
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Parsing %s\n", url);
+    strcpy (tmp_url, url);
+
+    char *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_ERROR,
+            "Got name: %s\n", handle->name);
+
+    type = strtok (NULL, "/");
+
+    if (NULL == type)
+    {
+        handle->type = GNUNET_GNSRECORD_TYPE_ANY;
+        return GNUNET_OK;
+    }
+
+    handle->type = GNUNET_GNSRECORD_typename_to_number (type);
+ 
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+            "Got type: %s\n", type);   
+    return GNUNET_OK;
+}
+
+int
+parse_json (const char *data, size_t data_size, struct LookupHandle *handle)
+{
+    json_error_t error;
+    json_t *pkey_json;
+    json_t *ego_json;
+    json_t *options_json;
+
+    char term_data[data_size+1];
+    term_data[data_size] = '\0';
+
+    memcpy (term_data, data, data_size);
+
+    handle->json_root = json_loads (term_data, 0, &error);
+
+    if (NULL == handle->json_root)
+    {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR, error.text);
+        return GNUNET_SYSERR;
+    }
+
+    if(!json_is_object(handle->json_root))
+    {
+        return GNUNET_SYSERR;
+    }
+   
+    ego_json = json_object_get (handle->json_root, "ego");
+    
+    if(json_is_string(ego_json))
+    {
+        handle->ego_str = json_string_value (ego_json);
+    }
+
+    pkey_json = json_object_get (handle->json_root, "pkey");
+    if(json_is_string(pkey_json))
+    {
+        handle->pkey_str = json_string_value (pkey_json);
+    }
+
+    options_json = json_object_get (handle->json_root, "options");
+    if(json_is_integer (options_json))
+    {
+        handle->options = json_integer_value (options_json);
+    }
+    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
+ */
+void
+rest_gns_process_request(const char *method,
+                         const char *url,
+                         const char *data,
+                         size_t data_size,
+                         GNUNET_REST_ResultProcessor proc,
+                         void *proc_cls)
+{
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                        "In plugin\n");
+    struct LookupHandle *handle = GNUNET_new (struct LookupHandle);
+    
+    handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; //TODO read from json
+
+    //parse name and type from url
+    if (GNUNET_OK != parse_url (url, handle))
+    {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error parsing url...\n");
+        proc (proc_cls, NULL, 0, GNUNET_SYSERR);
+        cleanup_handle (handle);
+        return;
+    }
+ 
+    handle->proc_cls = proc_cls;
+    handle->proc = proc;
+ 
+    if (0 < data_size)
+    {
+        if (GNUNET_OK != parse_json (data, data_size, handle))
+        {
+            GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error parsing json...\n");
+            proc (proc_cls, NULL, 0, GNUNET_SYSERR);
+            cleanup_handle (handle);
+            return;
+        }
+    }
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                        "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_ERROR,
+                        "Connected\n");
+
+    if (NULL == handle->gns)
+    {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                                        "Connecting to GNS failed\n");
+        proc (proc_cls, NULL, 0, GNUNET_SYSERR);
+        cleanup_handle (handle);
+        return;
+    }
+
+    if (NULL != handle->pkey_str)
+    {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                                      "pkey_str\n");
+        if (GNUNET_OK !=
+        GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->pkey_str,
+                                                    strlen(handle->pkey_str),
+                                                    &(handle->pkey)))
+        {
+            proc (proc_cls, NULL, 0, GNUNET_SYSERR);
+            cleanup_handle (handle);
+            return;
+        }
+        lookup_with_public_key (handle);
+
+    }
+    if (NULL != handle->ego_str)
+    {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                                      "ego_str\n");
+        handle->el = GNUNET_IDENTITY_ego_lookup (cfg,
+                handle->ego_str,
+                &identity_zone_cb,
+                handle);
+        return;
+    }
+    if ( (NULL != handle->name) &&
+            (strlen (handle->name) > 4) &&
+            (0 == strcmp (".zkey",
+                          &handle->name[strlen (handle->name) - 4])) )
+    {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                                      "zkey\n");
+        /* no zone required, use 'anonymous' zone */
+        GNUNET_CRYPTO_ecdsa_key_get_public
+            (GNUNET_CRYPTO_ecdsa_key_get_anonymous (),
+             &(handle->pkey));
+        lookup_with_public_key (handle);
+    }
+    else
+    {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                                      "gns_master\n");
+        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);
+    }
+}
+
+/**
+ * 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 = API_NAMESPACE;
+  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_namestore_sqlite_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 */

Added: gnunet/src/include/gnunet_rest_plugin.h
===================================================================
--- gnunet/src/include/gnunet_rest_plugin.h                             (rev 0)
+++ gnunet/src/include/gnunet_rest_plugin.h     2015-03-11 12:54:22 UTC (rev 
35370)
@@ -0,0 +1,100 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2012-2015 Christian Grothoff (and other contributing 
authors)
+
+     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., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+/**
+ * @author Martin Schanzenbach
+ * @file include/gnunet_rest_plugin.h
+ * @brief GNUnet service REST plugin header
+ *
+ */
+#ifndef GNUNET_REST_PLUGIN_H
+#define GNUNET_REST_PLUGIN_H
+
+#include "gnunet_util_lib.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#if 0                           /* keep Emacsens' auto-indent happy */
+}
+#endif
+#endif
+
+/**
+ * Iterator called on obtained result for a REST result.
+ *
+ * @param cls closure
+ * @param data REST result
+ * @param data_len length of result
+ * @param status status code (HTTP)
+ */
+typedef void (*GNUNET_REST_ResultProcessor) (void *cls,
+                          const char *data,
+                          size_t data_len,
+                          int status);
+
+/**
+ * @brief struct returned by the initialization function of the plugin
+ */
+struct GNUNET_REST_Plugin
+{
+
+  /**
+   *
+   * The closure of the plugin
+   *
+   */
+  void *cls;
+  
+  /**
+   * Plugin name. Used as the namespace for the API.
+   * e.g. http://hostname:port/<name>
+   */
+  char *name;
+
+  /**
+   * Function to process a REST call
+   * 
+   * @param method the HTTP method called
+   * @param url the relative url accessed
+   * @param data the REST data (can be NULL)
+   * @param data_size the length of the data
+   * @param proc the callback for result
+   * @param proc_cls closure for callback
+   */
+  void (*process_request) (const char *method,
+                          const char *url,
+                          const char *data,
+                          size_t data_size,
+                          GNUNET_REST_ResultProcessor proc,
+                          void *proc_cls);
+
+};
+
+
+#if 0                           /* keep Emacsens' auto-indent happy */
+{
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/* end of gnunet_rest_plugin.h */
+#endif
+

Added: gnunet/src/rest/Makefile.am
===================================================================
--- gnunet/src/rest/Makefile.am                         (rev 0)
+++ gnunet/src/rest/Makefile.am 2015-03-11 12:54:22 UTC (rev 35370)
@@ -0,0 +1,31 @@
+# This Makefile.am is in the public domain
+AM_CPPFLAGS = -I$(top_srcdir)/src/include
+
+plugindir = $(libdir)/gnunet
+
+pkgcfgdir= $(pkgdatadir)/config.d/
+
+libexecdir= $(pkglibdir)/libexec/
+
+pkgcfg_DATA = \
+   rest.conf
+
+
+if MINGW
+  WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
+endif
+
+if USE_COVERAGE
+  AM_CFLAGS = --coverage -O0
+  XLIBS = -lgcov
+endif
+
+libexec_PROGRAMS = \
+ gnunet-rest-server
+
+gnunet_rest_server_SOURCES = \
+ gnunet-rest-server.c
+
+gnunet_rest_server_LDADD = \
+  $(top_builddir)/src/util/libgnunetutil.la \
+  $(GN_LIBINTL) -lmicrohttpd

Added: gnunet/src/rest/gnunet-rest-server.c
===================================================================
--- gnunet/src/rest/gnunet-rest-server.c                                (rev 0)
+++ gnunet/src/rest/gnunet-rest-server.c        2015-03-11 12:54:22 UTC (rev 
35370)
@@ -0,0 +1,746 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2012-2015 Christian Grothoff (and other contributing 
authors)
+
+     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., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+/**
+ * @author Martin Schanzenbach
+ * @file src/rest/gnunet-rest-server.c
+ * @brief REST service for GNUnet services
+ *
+ */
+#include "platform.h"
+#include <microhttpd.h>
+#include "gnunet_util_lib.h"
+#include "gnunet_rest_plugin.h"
+
+
+/**
+ * Default Socks5 listen port.
+ */
+#define GNUNET_REST_SERVICE_PORT 7776
+
+/**
+ * Maximum supported length for a URI.
+ * Should die. @deprecated
+ */
+#define MAX_HTTP_URI_LENGTH 2048
+
+/**
+ * Port for plaintext HTTP.
+ */
+#define HTTP_PORT 80
+
+/**
+ * Port for HTTPS.
+ */
+#define HTTPS_PORT 443
+
+/**
+ * After how long do we clean up unused MHD SSL/TLS instances?
+ */
+#define MHD_CACHE_TIMEOUT GNUNET_TIME_relative_multiply 
(GNUNET_TIME_UNIT_MINUTES, 5)
+
+#define GN_REST_STATE_INIT 0
+#define GN_REST_STATE_UPLOAD 1
+#define GN_REST_STATE_RECV 2
+
+/**
+ * The task ID
+ */
+struct GNUNET_SCHEDULER_Task * httpd_task;
+
+/**
+ * is this an ssl daemon? //TODO
+ */
+int is_ssl;
+
+/**
+ * The port the service is running on (default 7776)
+ */
+static unsigned long port = GNUNET_REST_SERVICE_PORT;
+
+/**
+ * The listen socket of the service for IPv4
+ */
+static struct GNUNET_NETWORK_Handle *lsock4;
+
+/**
+ * The listen socket of the service for IPv6
+ */
+static struct GNUNET_NETWORK_Handle *lsock6;
+
+/**
+ * The listen task ID for IPv4
+ */
+static struct GNUNET_SCHEDULER_Task * ltask4;
+
+/**
+ * The listen task ID for IPv6
+ */
+static struct GNUNET_SCHEDULER_Task * ltask6;
+
+/**
+ * Daemon for HTTP
+ */
+static struct MHD_Daemon *httpd;
+
+/**
+ * Response we return on failures.
+ */
+static struct MHD_Response *failure_response;
+
+/**
+ * Our configuration.
+ */
+static const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * Map of loaded plugins.
+ */
+struct GNUNET_CONTAINER_MultiHashMap *plugin_map;
+
+/**
+ * MHD Connection handle 
+ */
+struct MhdConnectionHandle
+{
+    struct MHD_Connection *con;
+    
+    struct MHD_Response *response;
+
+    struct GNUNET_REST_Plugin *plugin;
+
+    int status;
+
+    int state;
+};
+
+/* ************************* Global helpers ********************* */
+
+
+/**
+ * Task run whenever HTTP server operations are pending.
+ *
+ * @param cls NULL
+ * @param tc sched context
+ */
+static void
+do_httpd (void *cls,
+          const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+
+/**
+ * Run MHD now, we have extra data ready for the callback.
+ *
+ * @param hd the daemon to run now.
+ */
+static void
+run_mhd_now ()
+{
+  if (NULL !=
+      httpd_task)
+    GNUNET_SCHEDULER_cancel (httpd_task);
+  httpd_task = GNUNET_SCHEDULER_add_now (&do_httpd,
+                         NULL);
+}
+
+/**
+ * Plugin result callback
+ *
+ * @param cls closure (MHD connection handle)
+ * @param data the data to return to the caller
+ * @param len length of the data
+ * @param status GNUNET_OK if successful
+ */
+void
+plugin_callback (void *cls,
+                 const char *data,
+                 size_t len,
+                 int status)
+{
+    struct MhdConnectionHandle *handle = cls;
+    struct MHD_Response *resp = MHD_create_response_from_buffer (len,
+                                                                (void*)data,
+                                                                
MHD_RESPMEM_MUST_COPY);
+    (void) MHD_add_response_header 
(resp,MHD_HTTP_HEADER_CONTENT_TYPE,"application/json");
+    handle->status = status;
+    handle->response = resp;
+    run_mhd_now(); 
+}
+
+/* ********************************* MHD response generation 
******************* */
+
+/**
+ * Main MHD callback for handling requests.
+ *
+ * @param cls unused
+ * @param con MHD connection handle
+ * @param url the url in the request
+ * @param meth the HTTP method used ("GET", "PUT", etc.)
+ * @param ver the HTTP version string (i.e. "HTTP/1.1")
+ * @param upload_data the data being uploaded (excluding HEADERS,
+ *        for a POST that fits into memory and that is encoded
+ *        with a supported encoding, the POST data will NOT be
+ *        given in upload_data and is instead available as
+ *        part of MHD_get_connection_values; very large POST
+ *        data *will* be made available incrementally in
+ *        upload_data)
+ * @param upload_data_size set initially to the size of the
+ *        @a upload_data provided; the method must update this
+ *        value to the number of bytes NOT processed;
+ * @param con_cls pointer to location where we store the 'struct Request'
+ * @return MHD_YES if the connection was handled successfully,
+ *         MHD_NO if the socket must be closed due to a serious
+ *         error while handling the request
+ */
+static int
+create_response (void *cls,
+                 struct MHD_Connection *con,
+                 const char *url,
+                 const char *meth,
+                 const char *ver,
+                 const char *upload_data,
+                 size_t *upload_data_size,
+                 void **con_cls)
+{
+    char *plugin_name;
+    struct GNUNET_HashCode key;
+    struct MhdConnectionHandle *con_handle;
+       
+    con_handle = *con_cls;
+     
+    if (NULL == *con_cls)
+    {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                              "New connection %s\n", url);
+        char tmp_url[strlen(url)+1];
+        strcpy (tmp_url, url);
+        con_handle = GNUNET_new (struct MhdConnectionHandle);
+        con_handle->con = con;
+        con_handle->state = GN_REST_STATE_INIT;
+        *con_cls = con_handle;
+        
+        plugin_name = strtok(tmp_url, "/");
+
+        if (NULL != plugin_name)
+        {
+            GNUNET_CRYPTO_hash (plugin_name, strlen (plugin_name), &key);
+
+            con_handle->plugin = GNUNET_CONTAINER_multihashmap_get (plugin_map,
+                                                    &key);
+        }
+        else
+            con_handle->plugin = NULL;
+    
+        if (NULL == con_handle->plugin)
+        {
+            GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Queueing response with MHD\n");
+            GNUNET_free (con_handle);
+            MHD_queue_response (con,
+                              MHD_HTTP_INTERNAL_SERVER_ERROR,
+                              failure_response);
+        }
+        return MHD_YES;
+    }
+                GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    "Size %d\n", *upload_data_size);
+    if (GN_REST_STATE_INIT == con_handle->state)
+    {
+        if (0 != *upload_data_size)
+        {
+            con_handle->state = GN_REST_STATE_UPLOAD;
+
+            con_handle->plugin->process_request (meth,
+                                     url,
+                                     upload_data,
+                                     *upload_data_size,
+                                     &plugin_callback,
+                                     con_handle);
+            *upload_data_size = 0;
+   
+        }
+        else 
+        {
+            con_handle->state = GN_REST_STATE_RECV;
+            con_handle->plugin->process_request (meth,
+                                     url,
+                                     NULL,
+                                     0,
+                                     &plugin_callback,
+                                     con_handle);
+        }
+    }
+    if (NULL != con_handle->response)
+    {
+
+GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    "Queueing response from plugin with MHD\n");
+        if (GNUNET_OK == con_handle->status) {
+            return MHD_queue_response (con,
+                            MHD_HTTP_OK,
+                            con_handle->response);
+        } else {
+            return MHD_queue_response (con,
+                    MHD_HTTP_BAD_REQUEST,
+                    con_handle->response);
+        }
+    }
+    return MHD_YES;
+}
+
+/* ******************** MHD HTTP setup and event loop ******************** */
+
+/**
+ * Function called when MHD decides that we are done with a connection.
+ *
+ * @param cls NULL
+ * @param connection connection handle
+ * @param con_cls value as set by the last call to
+ *        the MHD_AccessHandlerCallback, should be our handle
+ * @param toe reason for request termination (ignored)
+ */
+static void
+mhd_completed_cb (void *cls,
+                  struct MHD_Connection *connection,
+                  void **con_cls,
+                  enum MHD_RequestTerminationCode toe)
+{
+
+  if (MHD_REQUEST_TERMINATED_COMPLETED_OK != toe)
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "MHD encountered error handling request: %d\n",
+                toe);
+  *con_cls = NULL;
+}
+
+/**
+ * Kill the MHD daemon.
+ */
+static void
+kill_httpd ()
+{
+  MHD_stop_daemon (httpd);
+  if (NULL != httpd_task)
+  { 
+    GNUNET_SCHEDULER_cancel (httpd_task);
+    httpd_task = NULL;
+  }
+}
+
+/**
+ * Task run whenever HTTP server is idle for too long. Kill it.
+ *
+ * @param cls NULL
+ * @param tc sched context
+ */
+static void
+kill_httpd_task (void *cls,
+                 const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  httpd_task = NULL;
+  kill_httpd ();
+}
+/**
+ * Schedule MHD.  This function should be called initially when an
+ * MHD is first getting its client socket, and will then automatically
+ * always be called later whenever there is work to be done.
+ *
+ * @param hd the daemon to schedule
+ */
+static void
+schedule_httpd ()
+{
+  fd_set rs;
+  fd_set ws;
+  fd_set es;
+  struct GNUNET_NETWORK_FDSet *wrs;
+  struct GNUNET_NETWORK_FDSet *wws;
+  int max;
+  int haveto;
+  MHD_UNSIGNED_LONG_LONG timeout;
+  struct GNUNET_TIME_Relative tv;
+
+  FD_ZERO (&rs);
+  FD_ZERO (&ws);
+  FD_ZERO (&es);
+  max = -1;
+  if (MHD_YES != MHD_get_fdset (httpd, &rs, &ws, &es, &max))
+  {
+    kill_httpd ();
+    return;
+  }
+  haveto = MHD_get_timeout (httpd, &timeout);
+  if (MHD_YES == haveto)
+    tv.rel_value_us = (uint64_t) timeout * 1000LL;
+  else
+    tv = GNUNET_TIME_UNIT_FOREVER_REL;
+  if (-1 != max)
+  {
+    wrs = GNUNET_NETWORK_fdset_create ();
+    wws = GNUNET_NETWORK_fdset_create ();
+    GNUNET_NETWORK_fdset_copy_native (wrs, &rs, max + 1);
+    GNUNET_NETWORK_fdset_copy_native (wws, &ws, max + 1);
+  }
+  else
+  {
+    wrs = NULL;
+    wws = NULL;
+  }
+  if (NULL != httpd_task)
+    GNUNET_SCHEDULER_cancel (httpd_task);
+  if ( (MHD_YES != haveto) &&
+    (-1 == max))
+  {
+    /* daemon is idle, kill after timeout */
+    httpd_task = GNUNET_SCHEDULER_add_delayed (MHD_CACHE_TIMEOUT,
+                           &kill_httpd_task,
+                           NULL);
+  }
+  else
+  {
+    httpd_task =
+      GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
+                   tv, wrs, wws,
+                   &do_httpd, NULL);
+  }
+  if (NULL != wrs)
+    GNUNET_NETWORK_fdset_destroy (wrs);
+  if (NULL != wws)
+    GNUNET_NETWORK_fdset_destroy (wws);
+}
+
+/**
+ * Task run whenever HTTP server operations are pending.
+ *
+ * @param cls NULL
+ * @param tc scheduler context
+ */
+static void
+do_httpd (void *cls,
+          const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  httpd_task = NULL;
+  MHD_run (httpd);
+  schedule_httpd ();
+}
+
+/**
+ * Accept new incoming connections
+ *
+ * @param cls the closure with the lsock4 or lsock6
+ * @param tc the scheduler context
+ */
+static void
+do_accept (void *cls,
+           const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_NETWORK_Handle *lsock = cls;
+  struct GNUNET_NETWORK_Handle *s;
+  int fd;
+  const struct sockaddr *addr;
+  socklen_t len;
+
+  if (lsock == lsock4)
+    ltask4 = NULL;
+  else
+    ltask6 = NULL;
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+    return; 
+  if (lsock == lsock4)
+    ltask4 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                            lsock,
+                                            &do_accept, lsock);
+  else
+    ltask6 = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                            lsock,
+                                            &do_accept, lsock);
+  s = GNUNET_NETWORK_socket_accept (lsock, NULL, NULL);
+  if (NULL == s)
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "accept");
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Got an inbound connection, waiting for data\n");
+  fd = GNUNET_NETWORK_get_fd (s);
+  addr = GNUNET_NETWORK_get_addr (s);
+  len = GNUNET_NETWORK_get_addrlen (s);
+  if (MHD_YES != MHD_add_connection (httpd, fd, addr, len))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+        _("Failed to pass client to MHD\n"));
+    return;
+  }
+  
+  schedule_httpd ();
+}
+
+/**
+ * Task run on shutdown
+ *
+ * @param cls closure
+ * @param tc task context
+ */
+static void
+do_shutdown (void *cls,
+             const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Shutting down...\n");
+  kill_httpd ();
+}
+
+/**
+ * Create an IPv4 listen socket bound to our port.
+ *
+ * @return NULL on error
+ */
+static struct GNUNET_NETWORK_Handle *
+bind_v4 ()
+{
+  struct GNUNET_NETWORK_Handle *ls;
+  struct sockaddr_in sa4;
+  int eno;
+
+  memset (&sa4, 0, sizeof (sa4));
+  sa4.sin_family = AF_INET;
+  sa4.sin_port = htons (port);
+#if HAVE_SOCKADDR_IN_SIN_LEN
+  sa4.sin_len = sizeof (sa4);
+#endif 
+  ls = GNUNET_NETWORK_socket_create (AF_INET,
+                                     SOCK_STREAM,
+                                     0);
+  if (NULL == ls)
+    return NULL;
+  if (GNUNET_OK !=
+      GNUNET_NETWORK_socket_bind (ls, (const struct sockaddr *) &sa4,
+                                  sizeof (sa4)))
+  {
+    eno = errno;
+    GNUNET_NETWORK_socket_close (ls);
+    errno = eno;
+    return NULL;
+  }
+  return ls;
+}
+
+/**
+ * Create an IPv6 listen socket bound to our port.
+ *
+ * @return NULL on error
+ */
+static struct GNUNET_NETWORK_Handle *
+bind_v6 ()
+{
+  struct GNUNET_NETWORK_Handle *ls;
+  struct sockaddr_in6 sa6;
+  int eno;
+
+  memset (&sa6, 0, sizeof (sa6));
+  sa6.sin6_family = AF_INET6;
+  sa6.sin6_port = htons (port);
+#if HAVE_SOCKADDR_IN_SIN_LEN
+  sa6.sin6_len = sizeof (sa6);
+#endif 
+  ls = GNUNET_NETWORK_socket_create (AF_INET6,
+                                     SOCK_STREAM,
+                                     0);
+  if (NULL == ls)
+    return NULL;
+  if (GNUNET_OK !=
+      GNUNET_NETWORK_socket_bind (ls, (const struct sockaddr *) &sa6,
+                                  sizeof (sa6)))
+  {
+    eno = errno;
+    GNUNET_NETWORK_socket_close (ls);
+    errno = eno;
+    return NULL;
+  }
+  return ls;
+}
+
+/**
+ * Callback for plugin load
+ *
+ * @param cls NULL
+ * @param libname the name of the library loaded
+ * @param lib_ret the object returned by the plugin initializer
+ */
+void
+load_plugin (void *cls,
+             const char *libname,
+             void *lib_ret)
+{
+    struct GNUNET_REST_Plugin *plugin = lib_ret;
+    struct GNUNET_HashCode key;
+    if (NULL == lib_ret)
+    {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    "Could not load plugin `%s'\n",
+                    libname);
+        return;
+    }
+    
+    GNUNET_CRYPTO_hash (plugin->name, strlen (plugin->name), &key);
+
+    if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (plugin_map,
+                                       &key,
+                                       plugin,
+                                       
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
+    {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Could not load add plugin `%s'\n",
+                libname);
+        return;
+    }
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Loaded plugin `%s'\n",
+                libname);
+}
+
+/**
+ * Main function that will be run
+ *
+ * @param cls closure
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be NULL)
+ * @param c configuration
+ */
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *c)
+{
+    cfg = c;
+    
+    plugin_map = GNUNET_CONTAINER_multihashmap_create (10, GNUNET_NO);
+
+    /* Load plugins */
+    GNUNET_PLUGIN_load_all ("libgnunet_plugin_rest",
+                                     (void *) cfg,
+                                     &load_plugin,
+                                     NULL);
+    
+
+    /* Open listen socket proxy */
+    lsock6 = bind_v6 ();
+    if (NULL == lsock6)
+        GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
+    else
+    {
+        if (GNUNET_OK != GNUNET_NETWORK_socket_listen (lsock6, 5))
+        {
+            GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "listen");
+            GNUNET_NETWORK_socket_close (lsock6);
+            lsock6 = NULL;
+        }
+        else
+        {
+            ltask6 = GNUNET_SCHEDULER_add_read_net 
(GNUNET_TIME_UNIT_FOREVER_REL,
+                                                      lsock6, &do_accept, 
lsock6);
+        }
+    }
+    lsock4 = bind_v4 ();
+    if (NULL == lsock4)
+        GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
+    else
+    {
+        if (GNUNET_OK != GNUNET_NETWORK_socket_listen (lsock4, 5))
+        {
+            GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "listen");
+            GNUNET_NETWORK_socket_close (lsock4);
+            lsock4 = NULL;
+        }
+        else
+        {
+            ltask4 = GNUNET_SCHEDULER_add_read_net 
(GNUNET_TIME_UNIT_FOREVER_REL,
+                                                      lsock4, &do_accept, 
lsock4);
+        }
+    }
+    if ( (NULL == lsock4) &&
+         (NULL == lsock6) )
+    {
+        GNUNET_SCHEDULER_shutdown ();
+        return;
+    } 
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Service listens on port %u\n",
+              port);
+    httpd = MHD_start_daemon (MHD_USE_DEBUG | MHD_USE_NO_LISTEN_SOCKET,
+                                   0,
+                                   NULL, NULL,
+                                   &create_response, NULL,
+                                   MHD_OPTION_CONNECTION_TIMEOUT, (unsigned 
int) 16,
+                                   MHD_OPTION_NOTIFY_COMPLETED, 
&mhd_completed_cb, NULL,
+                                   MHD_OPTION_END);
+    if (NULL == httpd)
+    {
+        GNUNET_SCHEDULER_shutdown ();
+        return;
+    }
+    
+    
+
+    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
+                                            &do_shutdown, NULL);
+}
+
+/**
+ *
+ * The main function for gnunet-rest-service
+ *
+ * @param argc number of arguments from the cli
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ *
+ */
+int
+main (int argc, char *const *argv)
+{
+    static const struct GNUNET_GETOPT_CommandLineOption options[] = {
+        {'p', "port", NULL,
+            gettext_noop ("listen on specified port (default: 7776)"), 1,
+            &GNUNET_GETOPT_set_ulong, &port},
+        GNUNET_GETOPT_OPTION_END
+    };
+    static const char* err_page =
+        "<html><head><title>gnunet-rest-service</title>"
+        "</head><body>ERROR</body></html>";
+    int ret;
+
+    if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
+        return 2;
+    GNUNET_log_setup ("gnunet-rest-service", "WARNING", NULL);
+    failure_response = MHD_create_response_from_buffer (strlen(err_page),
+                                                        (void*)err_page,
+                                                        
MHD_RESPMEM_PERSISTENT);
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                          "Start\n");
+    ret =
+        (GNUNET_OK ==
+         GNUNET_PROGRAM_run (argc, argv, "gnunet-rest-service",
+                             _("GNUnet REST service"),
+                             options,
+                             &run, NULL)) ? 0: 1;
+    MHD_destroy_response (failure_response);
+    GNUNET_free_non_null ((char *) argv);
+    return ret;
+}
+
+/* end of gnunet-rest-service.c */

Added: gnunet/src/rest/rest.conf
===================================================================



reply via email to

[Prev in Thread] Current Thread [Next in Thread]