[Debian-iot-packaging] [ulfius] 01/02: Import Upstream version 2.2.4

Thorsten Alteholz alteholz at moszumanska.debian.org
Sun Jan 28 18:20:14 UTC 2018


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

alteholz pushed a commit to branch master
in repository ulfius.

commit 3d88f28ae684c80b3112bc144c3cf8eb08d91775
Author: Thorsten Alteholz <debian at alteholz.de>
Date:   Sun Jan 28 19:15:45 2018 +0100

    Import Upstream version 2.2.4
---
 API.md                                             |  2 +-
 README.md                                          |  3 +-
 .../oauth2_bearer/glewlwyd_resource.c              | 63 ++++++++++-------
 .../oauth2_bearer/glewlwyd_resource.h              |  2 +-
 .../static_file/static_file_callback.c             | 82 ++++++++++++++--------
 .../static_file/static_file_callback.h             | 18 +++--
 example_programs/websocket_example/Makefile        |  4 +-
 .../websocket_example/websocket_example.c          | 29 ++++----
 src/Makefile                                       |  2 +-
 src/u_request.c                                    | 24 +++++--
 src/u_response.c                                   |  8 +--
 src/u_websocket.c                                  |  6 +-
 src/ulfius.c                                       | 74 +++++++++++--------
 src/ulfius.h                                       | 12 ++--
 14 files changed, 203 insertions(+), 126 deletions(-)

diff --git a/API.md b/API.md
index 3ec125b..72a85ca 100644
--- a/API.md
+++ b/API.md
@@ -59,7 +59,7 @@ If you already have programs that use Ulfius 1.x and want to update them to the
 
 #### Endpoints definitions
 
-Endpoints structure have change, `ulfius_add_endpoint_by_val` now requires only one callback function, but requires a priority number.
+Endpoints structure have changed, `ulfius_add_endpoint_by_val` now requires only one callback function, but requires a priority number.
 
 If you don't use authentication callback functions, you can simply remove the `NULL, NULL, NULL` parameters corresponding to the former authentication callback function pointer, the authentication callback user data, and the realm value. Then add any number as a priority, 0 for example.
 
diff --git a/README.md b/README.md
index 8f332d9..87507d9 100644
--- a/README.md
+++ b/README.md
@@ -87,7 +87,8 @@ Example callback functions are available in the folder [example_callbacks](https
 
 - [Angharad](https://github.com/babelouest/angharad), House automation system for ZWave and other types of devices
 - [Glewlwyd](https://github.com/babelouest/glewlwyd), a lightweight OAuth2 authentication server that provides [JSON Web Tokens](https://jwt.io/)
-- [Hutch](https://github.com/babelouest/hutch), a safe locker for passwords and other secrets, using encryption on the client side only
+- [Hutch](https://github.com/babelouest/hutch), a safe locker for passwords and other secrets, using client side encryption only
+- [Taliesin](https://github.com/babelouest/taliesin), a lightweight audio streaming server
 - [Taulas Raspberry Pi Serial interface](https://github.com/babelouest/taulas/tree/master/taulas_raspberrypi_serial), an interface for Arduino devices that implent [Taulas](https://github.com/babelouest/taulas/) protocol, a house automation protocol
 
 ## What's new in Ulfius 2.2?
diff --git a/example_callbacks/oauth2_bearer/glewlwyd_resource.c b/example_callbacks/oauth2_bearer/glewlwyd_resource.c
index b063686..8866eca 100644
--- a/example_callbacks/oauth2_bearer/glewlwyd_resource.c
+++ b/example_callbacks/oauth2_bearer/glewlwyd_resource.c
@@ -28,12 +28,12 @@
 #include "glewlwyd_resource.h"
 
 /**
- * check if bearer token has the specified scope
+ * check if bearer token has some of the specified scope
  */
 int callback_check_glewlwyd_access_token (const struct _u_request * request, struct _u_response * response, void * user_data) {
   struct _glewlwyd_resource_config * config = (struct _glewlwyd_resource_config *)user_data;
-  json_t * j_access_token = NULL;
-  int res = U_CALLBACK_UNAUTHORIZED, res_scope, res_validity;
+  json_t * j_access_token = NULL, * j_res_scope;
+  int res = U_CALLBACK_UNAUTHORIZED, res_validity;
   const char * token_value = NULL;
   char * response_value = NULL;
   
@@ -42,7 +42,7 @@ int callback_check_glewlwyd_access_token (const struct _u_request * request, str
       case G_METHOD_HEADER:
         if (u_map_get(request->map_header, HEADER_AUTHORIZATION) != NULL) {
           if (o_strstr(u_map_get(request->map_header, HEADER_AUTHORIZATION), HEADER_PREFIX_BEARER) == u_map_get(request->map_header, HEADER_AUTHORIZATION)) {
-            token_value = u_map_get(request->map_header, HEADER_AUTHORIZATION) + strlen(HEADER_PREFIX_BEARER);
+            token_value = u_map_get(request->map_header, HEADER_AUTHORIZATION) + o_strlen(HEADER_PREFIX_BEARER);
           }
         }
         break;
@@ -60,18 +60,23 @@ int callback_check_glewlwyd_access_token (const struct _u_request * request, str
       if (check_result_value(j_access_token, G_OK)) {
         res_validity = access_token_check_validity(config, json_object_get(j_access_token, "grants"));
         if (res_validity == G_OK) {
-          res_scope = access_token_check_scope(config, json_object_get(j_access_token, "grants"));
-          if (res_scope == G_ERROR_INSUFFICIENT_SCOPE) {
+          j_res_scope = access_token_check_scope(config, json_object_get(j_access_token, "grants"));
+          if (check_result_value(j_res_scope, G_ERROR_INSUFFICIENT_SCOPE)) {
             response_value = msprintf(HEADER_PREFIX_BEARER "%s%s%serror=\"insufficient_scope\",error_description=\"The scope is invalid\"", (config->realm!=NULL?"realm=":""), (config->realm!=NULL?config->realm:""), (config->realm!=NULL?",":""));
             u_map_put(response->map_header, HEADER_RESPONSE, response_value);
             o_free(response_value);
-          } else if (res_scope != G_OK) {
+          } else if (!check_result_value(j_res_scope, G_OK)) {
             response_value = msprintf(HEADER_PREFIX_BEARER "%s%s%serror=\"invalid_request\",error_description=\"Internal server error\"", (config->realm!=NULL?"realm=":""), (config->realm!=NULL?config->realm:""), (config->realm!=NULL?",":""));
             u_map_put(response->map_header, HEADER_RESPONSE, response_value);
             o_free(response_value);
           } else {
             res = U_CALLBACK_CONTINUE;
+            response->shared_data = (void*)json_pack("{ssso}", "username", json_string_value(json_object_get(json_object_get(j_access_token, "grants"), "username")), "scope", json_copy(json_object_get(j_res_scope, "scope")));
+            if (response->shared_data == NULL) {
+              res = U_CALLBACK_ERROR;
+            }
           }
+          json_decref(j_res_scope);
         } else if (res_validity == G_ERROR_INVALID_TOKEN) {
           response_value = msprintf(HEADER_PREFIX_BEARER "%s%s%serror=\"invalid_request\",error_description=\"The access token is invalid\"", (config->realm!=NULL?"realm=":""), (config->realm!=NULL?config->realm:""), (config->realm!=NULL?",":""));
           u_map_put(response->map_header, HEADER_RESPONSE, response_value);
@@ -98,31 +103,41 @@ int callback_check_glewlwyd_access_token (const struct _u_request * request, str
 
 /**
  * Validates if an access_token grants has a valid scope
+ * return the final scope list on success
  */
-int access_token_check_scope(struct _glewlwyd_resource_config * config, json_t * j_access_token) {
-  int res, i, scope_count_token, scope_count_expected, count;
+json_t * access_token_check_scope(struct _glewlwyd_resource_config * config, json_t * j_access_token) {
+  int i, scope_count_token, scope_count_expected;
   char ** scope_list_token, ** scope_list_expected;
+  json_t * j_res = NULL, * j_scope_final_list = json_array();
   
-  if (j_access_token != NULL) {
-    scope_count_token = split_string(json_string_value(json_object_get(j_access_token, "scope")), " ", &scope_list_token);
-    scope_count_expected = split_string(config->oauth_scope, " ", &scope_list_expected);
-    count = 0;
-    if (scope_count_token > 0 && scope_count_expected > 0) {
-      for (i=0; scope_count_expected > 0 && scope_list_expected[i] != NULL; i++) {
-        if (string_array_has_value((const char **)scope_list_token, scope_list_expected[i])) {
-          count++;
+  if (j_scope_final_list != NULL) {
+    if (j_access_token != NULL) {
+      scope_count_token = split_string(json_string_value(json_object_get(j_access_token, "scope")), " ", &scope_list_token);
+      scope_count_expected = split_string(config->oauth_scope, " ", &scope_list_expected);
+      if (scope_count_token > 0 && scope_count_expected > 0) {
+        for (i=0; scope_count_expected > 0 && scope_list_expected[i] != NULL; i++) {
+          if (string_array_has_value((const char **)scope_list_token, scope_list_expected[i])) {
+            json_array_append_new(j_scope_final_list, json_string(scope_list_expected[i]));
+          }
+        }
+        if (json_array_size(j_scope_final_list) > 0) {
+          j_res = json_pack("{siso}", "result", G_OK, "scope", json_copy(j_scope_final_list));
+        } else {
+          j_res = json_pack("{si}", "result", G_ERROR_INSUFFICIENT_SCOPE);
         }
+      } else {
+        j_res = json_pack("{si}", "result", G_ERROR_INTERNAL);
       }
-      res = (count==scope_count_expected?G_OK:G_ERROR_INSUFFICIENT_SCOPE);
+      free_string_array(scope_list_token);
+      free_string_array(scope_list_expected);
     } else {
-      res = G_ERROR_INVALID_TOKEN;
+      j_res = json_pack("{si}", "result", G_ERROR_INVALID_TOKEN);
     }
-    free_string_array(scope_list_token);
-    free_string_array(scope_list_expected);
   } else {
-    res = G_ERROR_INVALID_TOKEN;
+    j_res = json_pack("{si}", "result", G_ERROR_INTERNAL);
   }
-  return res;
+  json_decref(j_scope_final_list);
+  return j_res;
 }
 
 /**
@@ -166,7 +181,7 @@ json_t * access_token_check_signature(struct _glewlwyd_resource_config * config,
   char  * grants;
   
   if (token_value != NULL) {
-    if (!jwt_decode(&jwt, token_value, (const unsigned char *)config->jwt_decode_key, strlen(config->jwt_decode_key)) && jwt_get_alg(jwt) == config->jwt_alg) {
+    if (!jwt_decode(&jwt, token_value, (const unsigned char *)config->jwt_decode_key, o_strlen(config->jwt_decode_key)) && jwt_get_alg(jwt) == config->jwt_alg) {
       grants = jwt_get_grants_json(jwt, NULL);
       j_grants = json_loads(grants, JSON_DECODE_ANY, NULL);
       if (j_grants != NULL) {
diff --git a/example_callbacks/oauth2_bearer/glewlwyd_resource.h b/example_callbacks/oauth2_bearer/glewlwyd_resource.h
index e363cbd..e00a994 100644
--- a/example_callbacks/oauth2_bearer/glewlwyd_resource.h
+++ b/example_callbacks/oauth2_bearer/glewlwyd_resource.h
@@ -48,4 +48,4 @@ int callback_check_glewlwyd_access_token (const struct _u_request * request, str
 json_t * access_token_check_signature(struct _glewlwyd_resource_config * config, const char * token_value);
 json_t * access_token_get_payload(const char * token_value);
 int access_token_check_validity(struct _glewlwyd_resource_config * config, json_t * j_access_token);
-int access_token_check_scope(struct _glewlwyd_resource_config * config, json_t * j_access_token);
+json_t * access_token_check_scope(struct _glewlwyd_resource_config * config, json_t * j_access_token);
diff --git a/example_callbacks/static_file/static_file_callback.c b/example_callbacks/static_file/static_file_callback.c
index e606285..5197be5 100644
--- a/example_callbacks/static_file/static_file_callback.c
+++ b/example_callbacks/static_file/static_file_callback.c
@@ -39,18 +39,52 @@ const char * get_filename_ext(const char *path) {
 }
 
 /**
+ * Streaming callback function to ease sending large files
+ */
+static ssize_t callback_static_file_stream(void * cls, uint64_t pos, char * buf, size_t max) {
+  if (cls != NULL) {
+    return fread (buf, 1, max, (FILE *)cls);
+  } else {
+    return U_STREAM_END;
+  }
+}
+
+/**
+ * Cleanup FILE* structure when streaming is complete
+ */
+static void callback_static_file_stream_free(void * cls) {
+  if (cls != NULL) {
+    fclose((FILE *)cls);
+  }
+}
+
+/**
  * static file callback endpoint
  */
 int callback_static_file (const struct _u_request * request, struct _u_response * response, void * user_data) {
-  void * buffer = NULL;
-  size_t length, res;
+  size_t length;
   FILE * f;
-  char * file_requested;
-  char * file_path;
+  char * file_requested, * file_path, * url_dup_save;
   const char * content_type;
 
-  if (user_data != NULL && ((struct static_file_config *)user_data)->files_path != NULL) {
-    file_requested = o_strdup((request->http_url + (((struct static_file_config *)user_data)->url_prefix!=NULL?strlen(((struct static_file_config *)user_data)->url_prefix):0)));
+  /*
+   * Comment this if statement if you put static files url not in root, like /app
+   */
+  if (response->shared_data != NULL) {
+    return U_CALLBACK_CONTINUE;
+  }
+  
+  if (user_data != NULL && ((struct _static_file_config *)user_data)->files_path != NULL) {
+    file_requested = o_strdup(request->http_url);
+    url_dup_save = file_requested;
+    
+    while (file_requested[0] == '/') {
+      file_requested++;
+    }
+    file_requested += o_strlen(((struct _static_file_config *)user_data)->url_prefix);
+    while (file_requested[0] == '/') {
+      file_requested++;
+    }
     
     if (strchr(file_requested, '#') != NULL) {
       *strchr(file_requested, '#') = '\0';
@@ -60,12 +94,12 @@ int callback_static_file (const struct _u_request * request, struct _u_response
       *strchr(file_requested, '?') = '\0';
     }
     
-    if (file_requested == NULL || strlen(file_requested) == 0 || 0 == o_strcmp("/", file_requested)) {
-      o_free(file_requested);
-      file_requested = o_strdup("index.html");
+    if (file_requested == NULL || o_strlen(file_requested) == 0 || 0 == o_strcmp("/", file_requested)) {
+      o_free(url_dup_save);
+      url_dup_save = file_requested = o_strdup("index.html");
     }
     
-    file_path = msprintf("%s/%s", ((struct static_file_config *)user_data)->files_path, file_requested);
+    file_path = msprintf("%s/%s", ((struct _static_file_config *)user_data)->files_path, file_requested);
 
     if (access(file_path, F_OK) != -1) {
       f = fopen (file_path, "rb");
@@ -73,34 +107,24 @@ int callback_static_file (const struct _u_request * request, struct _u_response
         fseek (f, 0, SEEK_END);
         length = ftell (f);
         fseek (f, 0, SEEK_SET);
-        buffer = o_malloc(length*sizeof(void));
-        if (buffer) {
-          res = fread (buffer, 1, length, f);
-          if (res != length) {
-            y_log_message(Y_LOG_LEVEL_WARNING, "callback_angharad_static_file - fread warning, reading %ld while expecting %ld", res, length);
-          }
-        }
-        fclose (f);
-      }
-
-      if (buffer) {
-        content_type = u_map_get_case(&((struct static_file_config *)user_data)->mime_types, get_filename_ext(file_requested));
+        
+        content_type = u_map_get_case(((struct _static_file_config *)user_data)->mime_types, get_filename_ext(file_requested));
         if (content_type == NULL) {
-          content_type = u_map_get(&((struct static_file_config *)user_data)->mime_types, "*");
+          content_type = u_map_get(((struct _static_file_config *)user_data)->mime_types, "*");
           y_log_message(Y_LOG_LEVEL_WARNING, "Static File Server - Unknown mime type for extension %s", get_filename_ext(file_requested));
         }
-        response->binary_body = buffer;
-        response->binary_body_length = length;
         u_map_put(response->map_header, "Content-Type", content_type);
-      } else {
-        ulfius_set_string_body_response(response, 500, "Error processing static file");
-        y_log_message(Y_LOG_LEVEL_ERROR, "Static File Server - Internal error in %s", request->http_url);
+        u_map_put(response->map_header, "Cache-Control", "public, max-age=31536000");
+        
+        if (ulfius_set_stream_response(response, 200, callback_static_file_stream, callback_static_file_stream_free, length, STATIC_FILE_CHUNK, f) != U_OK) {
+          y_log_message(Y_LOG_LEVEL_ERROR, "callback_static_file - Error ulfius_set_stream_response");
+        }
       }
     } else {
       ulfius_set_string_body_response(response, 404, "File not found");
     }
     o_free(file_path);
-    o_free(file_requested);
+    o_free(url_dup_save);
     return U_CALLBACK_CONTINUE;
   } else {
     y_log_message(Y_LOG_LEVEL_ERROR, "Static File Server - Error, user_data is NULL or inconsistent");
diff --git a/example_callbacks/static_file/static_file_callback.h b/example_callbacks/static_file/static_file_callback.h
index c44c453..a57c72c 100644
--- a/example_callbacks/static_file/static_file_callback.h
+++ b/example_callbacks/static_file/static_file_callback.h
@@ -1,4 +1,3 @@
-
 /**
  * struct static_file_config must be initialized with proper values
  * files_path: path (relative or absolute) to the DocumentRoot folder
@@ -52,10 +51,19 @@
  * }
  * 
  */
-struct static_file_config {
-  char *        files_path;
-  char *        url_prefix;
-  struct _u_map mime_types;
+
+#ifndef _STATIC_FILE
+#define _STATIC_FILE
+
+#define STATIC_FILE_CHUNK 256
+
+struct _static_file_config {
+  char          * files_path;
+  char          * url_prefix;
+  struct _u_map * mime_types;
 };
 
 int callback_static_file (const struct _u_request * request, struct _u_response * response, void * user_data);
+const char * get_filename_ext(const char *path);
+
+#endif
\ No newline at end of file
diff --git a/example_programs/websocket_example/Makefile b/example_programs/websocket_example/Makefile
index d6cd1bb..b0187ce 100644
--- a/example_programs/websocket_example/Makefile
+++ b/example_programs/websocket_example/Makefile
@@ -31,10 +31,10 @@ libulfius.so:
 	cd $(ULFIUS_LOCATION) && $(MAKE) debug JANSSONFLAG=-DU_DISABLE_JANSSON CURLFLAG=-DU_DISABLE_CURL
 
 static_file_callback.o: $(STATIC_FILE_LOCATION)/static_file_callback.c
-	$(CC) $(CFLAGS) $(STATIC_FILE_LOCATION)/static_file_callback.c -DDEBUG -g -O0
+	$(CC) $(CFLAGS) $(STATIC_FILE_LOCATION)/static_file_callback.c
 
 websocket_example.o: websocket_example.c
-	$(CC) $(CFLAGS) websocket_example.c -DDEBUG -g -O0
+	$(CC) $(CFLAGS) websocket_example.c
 
 websocket_example: libulfius.so static_file_callback.o websocket_example.o
 	$(CC) -o websocket_example websocket_example.o static_file_callback.o $(LIBS)
diff --git a/example_programs/websocket_example/websocket_example.c b/example_programs/websocket_example/websocket_example.c
index e87d08e..13da001 100644
--- a/example_programs/websocket_example/websocket_example.c
+++ b/example_programs/websocket_example/websocket_example.c
@@ -93,23 +93,24 @@ char * read_file(const char * filename) {
 int main(int argc, char ** argv) {
   int ret;
   struct _u_instance instance;
-  struct static_file_config file_config;
+  struct _static_file_config file_config;
   char * cert_file = NULL, * key_file = NULL;
   
   y_init_logs("websocket_example", Y_LOG_MODE_CONSOLE, Y_LOG_LEVEL_DEBUG, NULL, "Starting websocket_example");
   
-  u_map_init(&file_config.mime_types);
-  u_map_put(&file_config.mime_types, ".html", "text/html");
-  u_map_put(&file_config.mime_types, ".css", "text/css");
-  u_map_put(&file_config.mime_types, ".js", "application/javascript");
-  u_map_put(&file_config.mime_types, ".png", "image/png");
-  u_map_put(&file_config.mime_types, ".jpg", "image/jpeg");
-  u_map_put(&file_config.mime_types, ".jpeg", "image/jpeg");
-  u_map_put(&file_config.mime_types, ".ttf", "font/ttf");
-  u_map_put(&file_config.mime_types, ".woff", "font/woff");
-  u_map_put(&file_config.mime_types, ".woff2", "font/woff2");
-  u_map_put(&file_config.mime_types, ".map", "application/octet-stream");
-  u_map_put(&file_config.mime_types, "*", "application/octet-stream");
+  file_config.mime_types = o_malloc(sizeof(struct _u_map));
+  u_map_init(file_config.mime_types);
+  u_map_put(file_config.mime_types, ".html", "text/html");
+  u_map_put(file_config.mime_types, ".css", "text/css");
+  u_map_put(file_config.mime_types, ".js", "application/javascript");
+  u_map_put(file_config.mime_types, ".png", "image/png");
+  u_map_put(file_config.mime_types, ".jpg", "image/jpeg");
+  u_map_put(file_config.mime_types, ".jpeg", "image/jpeg");
+  u_map_put(file_config.mime_types, ".ttf", "font/ttf");
+  u_map_put(file_config.mime_types, ".woff", "font/woff");
+  u_map_put(file_config.mime_types, ".woff2", "font/woff2");
+  u_map_put(file_config.mime_types, ".map", "application/octet-stream");
+  u_map_put(file_config.mime_types, "*", "application/octet-stream");
   file_config.files_path = "static";
   file_config.url_prefix = PREFIX_STATIC;
   
@@ -152,7 +153,7 @@ int main(int argc, char ** argv) {
   
   ulfius_stop_framework(&instance);
   ulfius_clean_instance(&instance);
-  u_map_clean(&file_config.mime_types);
+  u_map_clean_full(file_config.mime_types);
   y_close_logs();
   
   return 0;
diff --git a/src/Makefile b/src/Makefile
index c50cfbe..f921c22 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -26,7 +26,7 @@ CC=gcc
 CFLAGS=-c -pedantic -std=gnu99 -fPIC -Wall -D_REENTRANT -I$(PREFIX)/include -I$(LIBORCANIA_LOCATION) -I$(LIBYDER_LOCATION) $(ADDITIONALFLAGS) $(JANSSONFLAG) $(CURLFLAG) $(WEBSOCKETFLAG)
 LIBS=-L$(PREFIX)/lib -L$(LIBORCANIA_LOCATION) -L$(LIBYDER_LOCATION) -lc -lmicrohttpd -lyder -lorcania -lpthread
 OUTPUT=libulfius.so
-VERSION=2.2
+VERSION=2.2.4
 
 ifndef JANSSONFLAG
 LJANSSON=-ljansson
diff --git a/src/u_request.c b/src/u_request.c
index dac1fe1..5e9421a 100644
--- a/src/u_request.c
+++ b/src/u_request.c
@@ -402,17 +402,17 @@ struct _u_request * ulfius_duplicate_request(const struct _u_request * request)
 #ifndef U_DISABLE_JANSSON
 /**
  * ulfius_set_json_body_request
- * Add a json_t binary_body to a response
+ * Add a json_t j_body to a response
  * return U_OK on success
  */
-int ulfius_set_json_body_request(struct _u_request * request, json_t * body) {
-  if (request != NULL && body != NULL) {
+int ulfius_set_json_body_request(struct _u_request * request, json_t * j_body) {
+  if (request != NULL && j_body != NULL && (json_is_array(j_body) || json_is_object(j_body))) {
     // Free all the bodies available
     o_free(request->binary_body);
     request->binary_body = NULL;
     request->binary_body_length = 0;
 
-    request->binary_body = (void*) json_dumps(body, JSON_COMPACT);
+    request->binary_body = (void*) json_dumps(j_body, JSON_COMPACT);
     if (request->binary_body == NULL) {
       y_log_message(Y_LOG_LEVEL_ERROR, "Ulfius - Error allocating memory for request->binary_body");
       return U_ERROR_MEMORY;
@@ -430,10 +430,24 @@ int ulfius_set_json_body_request(struct _u_request * request, json_t * body) {
  * Get JSON structure from the request body if the request is valid
  * request: struct _u_request used
  * json_error: structure to store json_error_t if specified
- */
+ */  
 json_t * ulfius_get_json_body_request(const struct _u_request * request, json_error_t * json_error) {
   if (request != NULL && request->map_header != NULL && NULL != o_strstr(u_map_get_case(request->map_header, ULFIUS_HTTP_HEADER_CONTENT), ULFIUS_HTTP_ENCODING_JSON)) {
     return json_loadb(request->binary_body, request->binary_body_length, JSON_DECODE_ANY, json_error);
+  } else if (json_error != NULL) {
+    json_error->line     = 1;
+    json_error->position = 1;
+    snprintf(json_error->source, (JSON_ERROR_SOURCE_LENGTH - 1), "ulfius_get_json_body_request");
+    if (NULL == request) {
+      json_error->column = 7;
+      snprintf(json_error->text, (JSON_ERROR_TEXT_LENGTH - 1), "Request not set.");
+    } else if (NULL == request->map_header) {
+      json_error->column = 26;
+      snprintf(json_error->text, (JSON_ERROR_TEXT_LENGTH - 1), "Request header not set.");
+    } else if (NULL == o_strstr(u_map_get_case(request->map_header, ULFIUS_HTTP_HEADER_CONTENT), ULFIUS_HTTP_ENCODING_JSON)) {
+      json_error->column = 57;
+      snprintf(json_error->text, (JSON_ERROR_TEXT_LENGTH - 1), "HEADER content not valid. Expected containging '%s' in header - received '%s'.", ULFIUS_HTTP_ENCODING_JSON, u_map_get_case(request->map_header, ULFIUS_HTTP_HEADER_CONTENT));
+    }
   }
   return NULL;
 }
diff --git a/src/u_response.c b/src/u_response.c
index bc98bb4..0b9e6e9 100644
--- a/src/u_response.c
+++ b/src/u_response.c
@@ -664,17 +664,17 @@ int ulfius_set_stream_response(struct _u_response * response,
 #ifndef U_DISABLE_JANSSON
 /**
  * ulfius_set_json_body_response
- * Add a json_t binary_body to a response
+ * Add a json_t j_body to a response
  * return U_OK on success
  */
-int ulfius_set_json_body_response(struct _u_response * response, const unsigned int status, const json_t * binary_body) {
-  if (response != NULL && binary_body != NULL) {
+int ulfius_set_json_body_response(struct _u_response * response, const unsigned int status, const json_t * j_body) {
+  if (response != NULL && j_body != NULL && (json_is_array(j_body) || json_is_object(j_body))) {
     // Free all the bodies available
     o_free(response->binary_body);
     response->binary_body = NULL;
     response->binary_body_length = 0;
 
-    response->binary_body = (void*) json_dumps(binary_body, JSON_COMPACT);
+    response->binary_body = (void*) json_dumps(j_body, JSON_COMPACT);
     if (response->binary_body == NULL) {
       y_log_message(Y_LOG_LEVEL_ERROR, "Ulfius - Error allocating memory for response->binary_body");
       return U_ERROR_MEMORY;
diff --git a/src/u_websocket.c b/src/u_websocket.c
index 1b0cefd..bda627d 100644
--- a/src/u_websocket.c
+++ b/src/u_websocket.c
@@ -32,7 +32,6 @@
 #include <fcntl.h>
 #include <pthread.h>
 #include <unistd.h>
-#include <sys/poll.h>
 #include <gnutls/gnutls.h>
 
 /**
@@ -112,7 +111,7 @@ void * ulfius_thread_websocket(void * data) {
   
   if (websocket != NULL && websocket->websocket_manager != NULL) {
     pthread_mutexattr_init ( &mutexattr );
-    pthread_mutexattr_settype( &mutexattr, PTHREAD_MUTEX_RECURSIVE_NP );
+    pthread_mutexattr_settype( &mutexattr, PTHREAD_MUTEX_RECURSIVE );
     if (pthread_mutex_init(&(websocket->websocket_manager->read_lock), &mutexattr) != 0 || pthread_mutex_init(&(websocket->websocket_manager->write_lock), &mutexattr) != 0) {
       y_log_message(Y_LOG_LEVEL_ERROR, "Impossible to initialize Mutex Lock for websocket");
       websocket->websocket_manager->connected = 0;
@@ -344,6 +343,7 @@ int ulfius_clear_websocket(struct _websocket * websocket) {
     }
     ulfius_instance_remove_websocket_active(websocket->instance, websocket);
     ulfius_clear_websocket_manager(websocket->websocket_manager);
+		ulfius_clean_request_full(websocket->request);
     o_free(websocket->websocket_manager);
     websocket->websocket_manager = NULL;
     o_free(websocket);
@@ -735,7 +735,7 @@ int ulfius_instance_remove_websocket_active(struct _u_instance * instance, struc
         }
         ((struct _websocket_handler *)instance->websocket_handler)->nb_websocket_active--;
         pthread_mutex_lock(&((struct _websocket_handler *)instance->websocket_handler)->websocket_close_lock);
-        pthread_cond_signal(&((struct _websocket_handler *)instance->websocket_handler)->websocket_close_cond);
+        pthread_cond_broadcast(&((struct _websocket_handler *)instance->websocket_handler)->websocket_close_cond);
         pthread_mutex_unlock(&((struct _websocket_handler *)instance->websocket_handler)->websocket_close_lock);
         return U_OK;
       }
diff --git a/src/ulfius.c b/src/ulfius.c
index 37a2cdf..2dc56b9 100644
--- a/src/ulfius.c
+++ b/src/ulfius.c
@@ -431,36 +431,50 @@ static int ulfius_webservice_dispatcher (void * cls, struct MHD_Connection * con
                 if (ulfius_generate_handshake_answer(u_map_get(con_info->request->map_header, "Sec-WebSocket-Key"), websocket_accept)) {
                   struct _websocket * websocket = o_malloc(sizeof(struct _websocket));
                   if (websocket != NULL) {
-                    websocket->instance = (struct _u_instance *)cls;
-                    websocket->request = con_info->request;
-                    websocket->websocket_protocol = ((struct _websocket_handle *)response->websocket_handle)->websocket_protocol;
-                    websocket->websocket_extensions = ((struct _websocket_handle *)response->websocket_handle)->websocket_extensions;
-                    websocket->websocket_manager_callback = ((struct _websocket_handle *)response->websocket_handle)->websocket_manager_callback;
-                    websocket->websocket_manager_user_data = ((struct _websocket_handle *)response->websocket_handle)->websocket_manager_user_data;
-                    websocket->websocket_incoming_message_callback = ((struct _websocket_handle *)response->websocket_handle)->websocket_incoming_message_callback;
-                    websocket->websocket_incoming_user_data = ((struct _websocket_handle *)response->websocket_handle)->websocket_incoming_user_data;
-                    websocket->websocket_onclose_callback = ((struct _websocket_handle *)response->websocket_handle)->websocket_onclose_callback;
-                    websocket->websocket_onclose_user_data = ((struct _websocket_handle *)response->websocket_handle)->websocket_onclose_user_data;
-                    websocket->tls = 0;
-                    mhd_response = MHD_create_response_for_upgrade(ulfius_start_websocket_cb, websocket);
-                    if (mhd_response == NULL) {
-                      y_log_message(Y_LOG_LEVEL_ERROR, "Ulfius - Error MHD_create_response_for_upgrade");
-                      mhd_ret = MHD_NO;
-                    } else {
-                      MHD_add_response_header (mhd_response,
-                                               MHD_HTTP_HEADER_UPGRADE,
-                                               U_WEBSOCKET_UPGRADE_VALUE);
-                      MHD_add_response_header (mhd_response,
-                                               "Sec-WebSocket-Accept",
-                                               websocket_accept);
-                      if (ulfius_set_response_header(mhd_response, response->map_header) == -1 || ulfius_set_response_cookie(mhd_response, response) == -1) {
-                        y_log_message(Y_LOG_LEVEL_ERROR, "Ulfius - Error setting headers or cookies");
-                        mhd_ret = MHD_NO;
-                      } else {
-                        ulfius_instance_add_websocket_active((struct _u_instance *)cls, websocket);
-                        upgrade_protocol = 1;
-                      }
-                    }
+                    websocket->request = ulfius_duplicate_request(con_info->request);
+										if (websocket->request != NULL) {
+											websocket->instance = (struct _u_instance *)cls;
+											websocket->websocket_protocol = ((struct _websocket_handle *)response->websocket_handle)->websocket_protocol;
+											websocket->websocket_extensions = ((struct _websocket_handle *)response->websocket_handle)->websocket_extensions;
+											websocket->websocket_manager_callback = ((struct _websocket_handle *)response->websocket_handle)->websocket_manager_callback;
+											websocket->websocket_manager_user_data = ((struct _websocket_handle *)response->websocket_handle)->websocket_manager_user_data;
+											websocket->websocket_incoming_message_callback = ((struct _websocket_handle *)response->websocket_handle)->websocket_incoming_message_callback;
+											websocket->websocket_incoming_user_data = ((struct _websocket_handle *)response->websocket_handle)->websocket_incoming_user_data;
+											websocket->websocket_onclose_callback = ((struct _websocket_handle *)response->websocket_handle)->websocket_onclose_callback;
+											websocket->websocket_onclose_user_data = ((struct _websocket_handle *)response->websocket_handle)->websocket_onclose_user_data;
+											websocket->tls = 0;
+											mhd_response = MHD_create_response_for_upgrade(ulfius_start_websocket_cb, websocket);
+											if (mhd_response == NULL) {
+												y_log_message(Y_LOG_LEVEL_ERROR, "Ulfius - Error MHD_create_response_for_upgrade");
+												mhd_ret = MHD_NO;
+											} else {
+												MHD_add_response_header (mhd_response,
+																								 MHD_HTTP_HEADER_UPGRADE,
+																								 U_WEBSOCKET_UPGRADE_VALUE);
+												MHD_add_response_header (mhd_response,
+																								 "Sec-WebSocket-Accept",
+																								 websocket_accept);
+												if (ulfius_set_response_header(mhd_response, response->map_header) == -1 || ulfius_set_response_cookie(mhd_response, response) == -1) {
+													y_log_message(Y_LOG_LEVEL_ERROR, "Ulfius - Error setting headers or cookies");
+													mhd_ret = MHD_NO;
+												} else {
+													ulfius_instance_add_websocket_active((struct _u_instance *)cls, websocket);
+													upgrade_protocol = 1;
+												}
+											}
+										} else {
+											o_free(websocket);
+											// Error building struct _websocket, sending error 500
+											response->status = MHD_HTTP_INTERNAL_SERVER_ERROR;
+											response_buffer = o_strdup(ULFIUS_HTTP_ERROR_BODY);
+											if (response_buffer == NULL) {
+												y_log_message(Y_LOG_LEVEL_ERROR, "Ulfius - Error allocating memory for websocket->request");
+												mhd_ret = MHD_NO;
+											} else {
+												response_buffer_len = strlen(ULFIUS_HTTP_ERROR_BODY);
+												mhd_response = MHD_create_response_from_buffer (response_buffer_len, response_buffer, MHD_RESPMEM_MUST_FREE );
+											}
+										}
                   } else {
                     // Error building struct _websocket, sending error 500
                     response->status = MHD_HTTP_INTERNAL_SERVER_ERROR;
diff --git a/src/ulfius.h b/src/ulfius.h
index 7f32a66..f94ccba 100644
--- a/src/ulfius.h
+++ b/src/ulfius.h
@@ -27,7 +27,7 @@
 #define __ULFIUS_H__
 
 /** External dependencies **/
-#include <sys/poll.h>
+#include <poll.h>
 #include <pthread.h>
 #include <microhttpd.h>
 
@@ -56,7 +56,7 @@
 #define U_ERROR_LIBCURL      5 // Error in libcurl execution
 #define U_ERROR_NOT_FOUND    6 // Something was not found
 
-#define ULFIUS_VERSION 2.2
+#define ULFIUS_VERSION 2.2.4
 
 #define U_CALLBACK_CONTINUE     0
 #define U_CALLBACK_COMPLETE     1
@@ -661,17 +661,17 @@ json_t * ulfius_get_json_body_request(const struct _u_request * request, json_er
 
 /**
  * ulfius_set_json_body_request
- * Add a json_t body to a request
+ * Add a json_t j_body to a request
  * return U_OK on success
  */
-int ulfius_set_json_body_request(struct _u_request * request, json_t * body);
+int ulfius_set_json_body_request(struct _u_request * request, json_t * j_body);
 
 /**
  * ulfius_set_json_body_response
- * Add a json_t body to a response
+ * Add a json_t j_body to a response
  * return U_OK on success
  */
-int ulfius_set_json_body_response(struct _u_response * response, const unsigned int status, const json_t * body);
+int ulfius_set_json_body_response(struct _u_response * response, const unsigned int status, const json_t * j_body);
 
 /**
  * ulfius_get_json_body_response

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-iot/ulfius.git



More information about the Debian-iot-packaging mailing list