gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [taler-exchange] branch master updated: implement #4982


From: gnunet
Subject: [GNUnet-SVN] [taler-exchange] branch master updated: implement #4982
Date: Mon, 17 Apr 2017 01:29:52 +0200

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new 5a32162  implement #4982
5a32162 is described below

commit 5a321621f40d09b4f38bdd6dd43ee6580915fba2
Author: Christian Grothoff <address@hidden>
AuthorDate: Mon Apr 17 01:29:36 2017 +0200

    implement #4982
---
 ChangeLog                                     |   3 +
 src/exchange/Makefile.am                      |   1 +
 src/exchange/taler-exchange-httpd_keystate.c  |  51 ++++++++++++-
 src/exchange/taler-exchange-httpd_responses.c | 104 +++++++++++++++++++++++++-
 src/exchange/taler-exchange-httpd_responses.h |  23 ++++++
 5 files changed, 176 insertions(+), 6 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 93d03f4..ee0cae8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,6 @@
+Mon Apr 17 01:29:07 CEST 2017
+       Add support for HTTP body compression (#4982). -CG
+
 Mon Mar 20 04:37:46 CET 2017
        Implemented first working version of taler-auditor. -CG
 
diff --git a/src/exchange/Makefile.am b/src/exchange/Makefile.am
index ecb774b..f936c3a 100644
--- a/src/exchange/Makefile.am
+++ b/src/exchange/Makefile.am
@@ -55,6 +55,7 @@ taler_exchange_httpd_LDADD = \
   -lgnunetutil \
   -lgnunetjson \
   -ljansson \
+  -lz \
   -lpthread
 
 if HAVE_DEVELOPER
diff --git a/src/exchange/taler-exchange-httpd_keystate.c 
b/src/exchange/taler-exchange-httpd_keystate.c
index 95ddd04..057f89c 100644
--- a/src/exchange/taler-exchange-httpd_keystate.c
+++ b/src/exchange/taler-exchange-httpd_keystate.c
@@ -72,6 +72,16 @@ struct TEH_KS_StateHandle
   char *keys_json;
 
   /**
+   * deflate-compressed version of @e keys_json, or NULL if not available.
+   */
+  void *keys_jsonz;
+
+  /**
+   * Number of bytes in @e keys_jsonz.
+   */
+  size_t keys_jsonz_size;
+
+  /**
    * Mapping from denomination keys to denomination key issue struct.
    * Used to lookup the key by hash.
    */
@@ -709,6 +719,7 @@ ks_release_ (struct TEH_KS_StateHandle *key_state)
       key_state->revoked_map = NULL;
     }
     GNUNET_free_non_null (key_state->keys_json);
+    GNUNET_free_non_null (key_state->keys_jsonz);
     GNUNET_free (key_state);
   }
 }
@@ -851,6 +862,17 @@ TEH_KS_acquire_ (const char *location)
                                        JSON_INDENT (2));
     GNUNET_assert (NULL != key_state->keys_json);
     json_decref (keys);
+    /* also compute compressed version of /keys */
+    key_state->keys_jsonz = GNUNET_strdup (key_state->keys_json);
+    key_state->keys_jsonz_size = strlen (key_state->keys_json);
+    if (MHD_YES !=
+       TEH_RESPONSE_body_compress (&key_state->keys_jsonz,
+                                   &key_state->keys_jsonz_size))
+    {
+      GNUNET_free (key_state->keys_jsonz);
+      key_state->keys_jsonz = NULL;
+      key_state->keys_jsonz_size = 0;
+    }
     internal_key_state = key_state;
   }
   key_state = internal_key_state;
@@ -1225,10 +1247,26 @@ TEH_KS_handler_keys (struct TEH_RequestHandler *rh,
   struct MHD_Response *response;
   int ret;
   char dat[128];
+  char *json;
+  size_t json_len;
+  int comp;
 
   key_state = TEH_KS_acquire ();
-  response = MHD_create_response_from_buffer (strlen (key_state->keys_json),
-                                              key_state->keys_json,
+  comp = MHD_NO;
+  if (NULL != key_state->keys_jsonz)
+    comp = TEH_RESPONSE_can_compress (connection);
+  if (MHD_YES == comp)
+  {
+    json = key_state->keys_jsonz;
+    json_len = key_state->keys_jsonz_size;
+  }
+  else
+  {
+    json = key_state->keys_json;
+    json_len = strlen (key_state->keys_json);
+  }
+  response = MHD_create_response_from_buffer (json_len,
+                                              json,
                                               MHD_RESPMEM_MUST_COPY);
   TEH_KS_release (key_state);
   if (NULL == response)
@@ -1241,6 +1279,15 @@ TEH_KS_handler_keys (struct TEH_RequestHandler *rh,
                 MHD_add_response_header (response,
                                          MHD_HTTP_HEADER_CONTENT_TYPE,
                                          rh->mime_type));
+  if (MHD_YES !=
+      MHD_add_response_header (response,
+                              MHD_HTTP_HEADER_CONTENT_ENCODING,
+                              "deflate"))
+  {
+    GNUNET_break (0);
+    MHD_destroy_response (response);
+    return MHD_NO;
+  }
   get_date_string (key_state->reload_time,
                    dat);
   GNUNET_break (MHD_YES ==
diff --git a/src/exchange/taler-exchange-httpd_responses.c 
b/src/exchange/taler-exchange-httpd_responses.c
index eea5341..c67c885 100644
--- a/src/exchange/taler-exchange-httpd_responses.c
+++ b/src/exchange/taler-exchange-httpd_responses.c
@@ -23,6 +23,7 @@
  * @author Christian Grothoff
  */
 #include "platform.h"
+#include <zlib.h>
 #include "taler-exchange-httpd_responses.h"
 #include "taler_util.h"
 #include "taler_json_lib.h"
@@ -47,6 +48,74 @@ TEH_RESPONSE_add_global_headers (struct MHD_Response 
*response)
 }
 
 
+/** 
+ * Is HTTP body deflate compression supported by the client?
+ *
+ * @param connection connection to check
+ * @return #MHD_YES if 'deflate' compression is allowed
+ */
+int
+TEH_RESPONSE_can_compress (struct MHD_Connection *connection)
+{
+  const char *ae;
+  const char *de;
+
+  ae = MHD_lookup_connection_value (connection,
+                                   MHD_HEADER_KIND,
+                                   MHD_HTTP_HEADER_ACCEPT_ENCODING);
+  if (NULL == ae)
+    return MHD_NO;
+  de = strstr (ae,
+              "deflate");
+  if (NULL == de)
+    return MHD_NO;
+  if ( ( (de == ae) ||
+        ( de[-1] == ',') ||
+        (de[-1] == ' ') ) &&
+       ( (de[strlen ("deflate")] == '\0') ||
+        (de[strlen ("deflate")] == ',') ) )
+    return MHD_YES;
+  return MHD_NO;  
+}
+
+
+/**
+ * Try to compress a response body.  Updates @a buf and @buf_size.
+ *
+ * @param[in,out] buf pointer to body to compress
+ * @param[in,out] buf_size pointer to initial size of @a buf
+ * @return #MHD_TES if @a buf was compressed
+ */
+int
+TEH_RESPONSE_body_compress (void **buf,
+                           size_t *buf_size)
+{
+  Bytef *cbuf;
+  uLongf cbuf_size;
+  int ret;
+
+  cbuf_size = compressBound (*buf_size);
+  cbuf = malloc (cbuf_size);
+  if (NULL == cbuf)
+    return MHD_NO;
+  ret = compress (cbuf,
+                 &cbuf_size,
+                 (const Bytef *) *buf,
+                 *buf_size);
+  if ( (Z_OK != ret) ||
+       (cbuf_size >= *buf_size) )
+  {
+    /* compression failed */
+    free (cbuf);
+    return MHD_NO;
+  }
+  free (*buf);
+  *buf = (void *) cbuf;
+  *buf_size = (size_t) cbuf_size;
+  return MHD_YES;
+}
+
+
 /**
  * Send JSON object as response.
  *
@@ -61,12 +130,26 @@ TEH_RESPONSE_reply_json (struct MHD_Connection *connection,
                          unsigned int response_code)
 {
   struct MHD_Response *resp;
-  char *json_str;
+  void *json_str;
+  size_t json_len;
   int ret;
+  int comp;
 
-  json_str = json_dumps (json, JSON_INDENT(2));
-  GNUNET_assert (NULL != json_str);
-  resp = MHD_create_response_from_buffer (strlen (json_str),
+  json_str = json_dumps (json,
+                        JSON_INDENT(2));
+  if (NULL == json_str)
+  {
+    GNUNET_break (0);
+    return MHD_NO;
+  }
+  json_len = strlen (json_str);
+  /* try to compress the body */
+  comp = MHD_NO;
+  if (MHD_YES ==
+      TEH_RESPONSE_can_compress (connection))
+    comp = TEH_RESPONSE_body_compress (&json_str,
+                                      &json_len);
+  resp = MHD_create_response_from_buffer (json_len,
                                           json_str,
                                           MHD_RESPMEM_MUST_FREE);
   if (NULL == resp)
@@ -79,6 +162,19 @@ TEH_RESPONSE_reply_json (struct MHD_Connection *connection,
   (void) MHD_add_response_header (resp,
                                   MHD_HTTP_HEADER_CONTENT_TYPE,
                                   "application/json");
+  if (MHD_YES == comp)
+  {
+    /* Need to indicate to client that body is compressed */
+    if (MHD_NO ==
+       MHD_add_response_header (resp,
+                                MHD_HTTP_HEADER_CONTENT_ENCODING,
+                                "deflate"))
+    {
+      GNUNET_break (0);
+      MHD_destroy_response (resp);
+      return MHD_NO;
+    }
+  }
   ret = MHD_queue_response (connection,
                             response_code,
                             resp);
diff --git a/src/exchange/taler-exchange-httpd_responses.h 
b/src/exchange/taler-exchange-httpd_responses.h
index 83dafdc..091d438 100644
--- a/src/exchange/taler-exchange-httpd_responses.h
+++ b/src/exchange/taler-exchange-httpd_responses.h
@@ -33,6 +33,7 @@
 #include "taler-exchange-httpd.h"
 #include "taler-exchange-httpd_db.h"
 
+
 /**
  * Add headers we want to return in every response.
  * Useful for testing, like if we want to always close
@@ -45,6 +46,28 @@ TEH_RESPONSE_add_global_headers (struct MHD_Response 
*response);
 
 
 /**
+ * Try to compress a response body.  Updates @a buf and @buf_size.
+ *
+ * @param[in,out] buf pointer to body to compress
+ * @param[in,out] buf_size pointer to initial size of @a buf
+ * @return #MHD_TES if @a buf was compressed
+ */
+int
+TEH_RESPONSE_body_compress (void **buf,
+                           size_t *buf_size);
+
+
+/** 
+ * Is HTTP body deflate compression supported by the client?
+ *
+ * @param connection connection to check
+ * @return #MHD_YES if 'deflate' compression is allowed
+ */
+int
+TEH_RESPONSE_can_compress (struct MHD_Connection *connection);
+
+
+/**
  * Send JSON object as response.
  *
  * @param connection the MHD connection

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

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