diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..1d39d132e0404b2c227990aea0d1cc0140b38013
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+/.vagrant
+*.swp
+*.o
+cryptops-api
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..e63d9364db0db570d9c1a7fded9c975427688399
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,38 @@
+TARGET=cryptops-api
+
+CFLAGS=-O0 -g -Wall -D_GNU_SOURCE -Iincludes -Isrc
+LFLAGS=-L./libraries -lcryptsetup -lc -lulfius -lyder -lorcania -ljansson
+CC=gcc
+LINKER=gcc
+
+SRCDIR   = src
+OBJDIR   = obj
+BINDIR   = bin
+
+SOURCES  := $(SRCDIR)/$(TARGET).c
+INCLUDES := $(wildcard $(SRCDIR)/*.h)
+OBJECTS  := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
+
+$(BINDIR)/$(TARGET): $(BINDIR)
+$(BINDIR):
+	mkdir -p $(BINDIR)
+$(BINDIR)/$(TARGET): $(OBJECTS)
+	@$(LINKER) $(OBJECTS) $(LFLAGS) -o $@
+	@echo "Linking complete."
+
+$(OBJECTS): | $(OBJDIR)
+$(OBJDIR):
+	mkdir -p $(OBJDIR)
+$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
+	@$(CC) $(CFLAGS) -c $< -o $@
+	@echo "Compiled "$<" successfully."
+
+.PHONY: clean
+clean:
+	@rm -f $(OBJECTS)
+	@echo "Cleanup complete."
+
+.PHONY: remove
+remove: clean
+	@rm -f $(BINDIR)/$(TARGET)
+	@echo "Executable removed."
diff --git a/Vagrantfile b/Vagrantfile
new file mode 100644
index 0000000000000000000000000000000000000000..678efd39c44c2238c9f729c4af26846c34bd562d
--- /dev/null
+++ b/Vagrantfile
@@ -0,0 +1,11 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+
+Vagrant.configure("2") do |config|
+  config.vm.box = "debian/jessie64"
+  config.vm.synced_folder ".", "/test", type: 'virtualbox'
+  config.vm.provision "shell", inline: <<-SHELL
+    apt-get update
+    apt-get install -y libmicrohttpd-dev libjansson-dev libcurl4-gnutls-dev libgnutls28-dev libgcrypt20-dev libcryptsetup-dev
+  SHELL
+end
diff --git a/includes/orcania.h b/includes/orcania.h
new file mode 100644
index 0000000000000000000000000000000000000000..c1f3599c082446a747f30e1c1cba0b256b6fea84
--- /dev/null
+++ b/includes/orcania.h
@@ -0,0 +1,215 @@
+/**
+ * 
+ * Orcania library
+ * 
+ * Different functions for different purposes but that can be shared between
+ * other projects
+ * 
+ */
+
+#ifndef __ORCANIA_H__
+#define __ORCANIA_H__
+
+#ifndef U_DISABLE_JANSSON
+#include <jansson.h>
+#endif
+
+#define ORCANIA_VERSION 1.1
+/**
+ * char * str_replace(const char * source, char * old, char * new)
+ * replace all occurences of old by new in the string source
+ * return a char * with the new value
+ * return NULL on error
+ * returned value must be free'd after use
+ */
+char * str_replace(const char * source, const char * str_old, const char * str_new);
+
+/**
+ * o_strdup
+ * a modified strdup function that don't crash when source is NULL, instead return NULL
+ * Returned value must be free'd after use
+ */
+char * o_strdup(const char * source);
+
+/**
+ * o_strndup
+ * a modified strndup function that don't crash when source is NULL, instead return NULL
+ * Returned value must be free'd after use
+ */
+char * o_strndup(const char * source, size_t len);
+
+/**
+ * o_strcmp
+ * a modified strcmp function that don't crash when p1 is NULL or p2 us NULL
+ */
+int o_strcmp(const char * p1, const char * p2);
+
+/**
+ * o_strncmp
+ * a modified strncmp function that don't crash when p1 is NULL or p2 us NULL
+ */
+int o_strncmp(const char * p1, const char * p2, size_t n);
+
+/**
+ * o_strcpy
+ * a modified strcpy function that don't crash when p1 is NULL or p2 us NULL
+ */
+char * o_strcpy(char * p1, const char * p2);
+
+/**
+ * o_strncpy
+ * a modified strncpy function that don't crash when p1 is NULL or p2 us NULL
+ */
+char * o_strncpy(char * p1, const char * p2, size_t n);
+
+/**
+ * o_strcasecmp
+ * a modified strcasecmp function that don't crash when p1 is NULL or p2 us NULL
+ */
+int o_strcasecmp(const char * p1, const char * p2);
+
+/**
+ * o_strncasecmp
+ * a modified strncasecmp function that don't crash when p1 is NULL or p2 us NULL
+ */
+int o_strncasecmp(const char * p1, const char * p2, size_t n);
+
+/**
+ * o_strstr
+ * a modified strstr function that don't crash when haystack is NULL or needle us NULL
+ */
+char * o_strstr(const char * haystack, const char * needle);
+
+/**
+ * o_strnstr
+ * a modified strnstr function that don't crash when haystack is NULL or needle us NULL
+ */
+char * o_strnstr(const char * haystack, const char * needle, size_t len);
+
+/**
+ * o_strcasestr
+ * a modified strcasestr function that don't crash when haystack is NULL or needle us NULL
+ */
+char * o_strcasestr(const char * haystack, const char * needle);
+
+/**
+ * o_strchr
+ * a modified strchr function that don't crash when haystack is NULL
+ */
+char * o_strchr(const char * haystack, int c);
+
+/**
+ * o_strrchr
+ * a modified strrchr function that don't crash when haystack is NULL
+ */
+char * o_strrchr(const char * haystack, int c);
+
+/**
+ * o_strlen
+ * a modified version of strlen that don't crash when s is NULL
+ */
+size_t o_strlen(const char * s);
+
+/**
+ * char * msprintf(const char * message, ...)
+ * Implementation of sprintf that return a malloc'd char * with the string construction
+ * because life is too short to use 3 lines instead of 1
+ * but don't forget to free the returned value after use!
+ */
+char * msprintf(const char * message, ...);
+
+/**
+ * Split a string into an array of strings using separator string
+ * return the number of elements to be returned, 0 on error
+ * if return_array is not NULL, set the returned array in it
+ * return_array is an array of char * ending with a NULL value
+ * return_array must be free'd after use
+ * you can use free_string_array to free return_array
+ */
+int split_string(const char * string, const char * separator, char *** return_array);
+
+/**
+ * Clean an array of strings
+ */
+void free_string_array(char ** array);
+
+/**
+ * Check if an array of string has a specified value
+ */
+int string_array_has_value(const char ** array, const char * needle);
+
+/**
+ * Check if an array of string has a specified trimmed value
+ */
+int string_array_has_trimmed_value(const char ** array, const char * needle);
+
+/**
+ * Remove string of beginning and ending whitespaces
+ */
+char * trimwhitespace(char * str);
+
+#ifndef U_DISABLE_JANSSON
+/**
+ * json_t * json_search(json_t * haystack, json_t * needle)
+ * jansson library addon
+ * This function could be removed if y pull request is accepted in jansson official repository:
+ * https://github.com/akheron/jansson/pull/265
+ * Look for an occurence of needle within haystack
+ * If needle is present in haystack, return the reference to the json_t * that is equal to needle
+ * If needle is not found, return NULL
+ */
+json_t * json_search(json_t * haystack, json_t * needle);
+
+/**
+ * Check if the result json object has a "result" element that is equal to value
+ */
+int check_result_value(json_t * result, const int value);
+#endif
+
+/**
+ * Memory functions
+ */
+/* C89 allows these to be macros */
+#undef malloc
+#undef realloc
+#undef free
+
+typedef void *(*o_malloc_t)(size_t);
+typedef void *(*o_realloc_t)(void *, size_t);
+typedef void (*o_free_t)(void *);
+
+void * o_malloc(size_t size);
+void * o_realloc(void * ptr, size_t size);
+void o_free(void * ptr);
+void o_set_alloc_funcs(o_malloc_t malloc_fn, o_realloc_t realloc_fn, o_free_t free_fn);
+void o_get_alloc_funcs(o_malloc_t * malloc_fn, o_realloc_t * realloc_fn, o_free_t * free_fn);
+
+/**
+ * Base64 encode and decode functions
+ */
+
+/**
+ * o_base64_encode - Base64 encode
+ * @src: Data to be encoded
+ * @len: Length of the data to be encoded
+ * @out: Pointer to output variable
+ * @out_len: Pointer to output length variable
+ * Returns: 1 on success, 0 on failure
+ *
+ * The nul terminator is not included in out_len.
+ */
+int o_base64_encode(const unsigned char * src, size_t len, unsigned char * out, size_t * out_len);
+
+/**
+ * o_base64_decode - Base64 decode
+ * @src: Data to be decoded
+ * @len: Length of the data to be decoded
+ * @out: Pointer to output variable
+ * @out_len: Pointer to output length variable
+ * Returns: 1 on success, 0 on failure
+ *
+ * The nul terminator is not included in out_len.
+ */
+int o_base64_decode(const unsigned char *src, size_t len, unsigned char * out, size_t * out_len);
+
+#endif
diff --git a/includes/ulfius.h b/includes/ulfius.h
new file mode 100644
index 0000000000000000000000000000000000000000..f7da3eb9c5a2874d83eec9e41de161e5e9b40df3
--- /dev/null
+++ b/includes/ulfius.h
@@ -0,0 +1,1224 @@
+/**
+ * 
+ * Ulfius Framework
+ * 
+ * REST framework library
+ * 
+ * ulfius.h: public structures and functions declarations
+ * 
+ * Copyright 2015-2017 Nicolas Mora <mail@babelouest.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library 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 this library.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ */
+
+#ifndef __ULFIUS_H__
+#define __ULFIUS_H__
+
+/** External dependencies **/
+#include <sys/poll.h>
+#include <microhttpd.h>
+
+#if (MHD_VERSION < 0x00095300) && !defined(U_DISABLE_WEBSOCKET)
+  #define U_DISABLE_WEBSOCKET
+#endif
+
+/** Angharad libraries **/
+#include <yder.h>
+#include <orcania.h>
+
+#ifndef U_DISABLE_JANSSON
+#include <jansson.h>
+#endif
+
+#define ULFIUS_STREAM_BLOCK_SIZE_DEFAULT 1024
+#define U_STREAM_END MHD_CONTENT_READER_END_OF_STREAM
+#define U_STREAM_ERROR MHD_CONTENT_READER_END_WITH_ERROR
+#define U_STREAM_SIZE_UNKOWN MHD_SIZE_UNKNOWN
+
+#define U_OK                 0 // No error
+#define U_ERROR              1 // Error
+#define U_ERROR_MEMORY       2 // Error in memory allocation
+#define U_ERROR_PARAMS       3 // Error in input parameters
+#define U_ERROR_LIBMHD       4 // Error in libmicrohttpd execution
+#define U_ERROR_LIBCURL      5 // Error in libcurl execution
+#define U_ERROR_NOT_FOUND    6 // Something was not found
+
+#define ULFIUS_VERSION 2.1
+
+#define U_CALLBACK_CONTINUE     0
+#define U_CALLBACK_COMPLETE     1
+#define U_CALLBACK_UNAUTHORIZED 2
+#define U_CALLBACK_ERROR        3
+
+/*************
+ * Structures
+ *************/
+
+/**
+ * struct _u_map
+ */
+struct _u_map {
+  int      nb_values;
+  char  ** keys;
+  char  ** values;
+  size_t * lengths;
+};
+
+/**
+ * struct _u_cookie
+ * the structure containing the response cookie parameters
+ */
+struct _u_cookie {
+  char * key;
+  char * value;
+  char * expires;
+  uint   max_age;
+  char * domain;
+  char * path;
+  int    secure;
+  int    http_only;
+};
+
+/**
+ * 
+ * Structure of request parameters
+ * 
+ * Contains request data
+ * http_protocol:             http protocol used (1.0 or 1.1)
+ * http_verb:                 http method (GET, POST, PUT, DELETE, etc.), use '*' to match all http methods
+ * http_url:                  url used to call this callback function or full url to call when used in a ulfius_send_http_request
+ * proxy:                     proxy address to use for outgoing connections, used by ulfius_send_http_request
+ * check_server_certificate:  do not check server certificate and hostname if false (default true), used by ulfius_send_http_request
+ * timeout                    connection timeout used by ulfius_send_http_request, default is 0
+ * client_address:            IP address of the client
+ * auth_basic_user:           basic authtication username
+ * auth_basic_password:       basic authtication password
+ * map_url:                   map containing the url variables, both from the route and the ?key=value variables
+ * map_header:                map containing the header variables
+ * map_cookie:                map containing the cookie variables
+ * map_post_body:             map containing the post body variables (if available)
+ * binary_body:               pointer to raw body
+ * binary_body_length:        length of raw body
+ * 
+ */
+struct _u_request {
+  char *               http_protocol;
+  char *               http_verb;
+  char *               http_url;
+	char *               proxy;
+  int                  check_server_certificate;
+  long                 timeout;
+  struct sockaddr *    client_address;
+  char *               auth_basic_user;
+  char *               auth_basic_password;
+  struct _u_map *      map_url;
+  struct _u_map *      map_header;
+  struct _u_map *      map_cookie;
+  struct _u_map *      map_post_body;
+  void *               binary_body;
+  size_t               binary_body_length;
+};
+
+/**
+ * 
+ * Structure of response parameters
+ * 
+ * Contains response data that must be set by the user
+ * status:                              HTTP status code (200, 404, 500, etc)
+ * protocol:                            HTTP Protocol sent
+ * map_header:                          map containing the header variables
+ * nb_cookies:                          number of cookies sent
+ * map_cookie:                          array of cookies sent
+ * auth_realm:                          realm to send to the client on authenticationb failed
+ * binary_body:                         a void * containing a raw binary content
+ * binary_body_length:                  the length of the binary_body
+ * stream_callback:                     callback function to stream data in response body
+ * stream_callback_free:                callback function to free data allocated for streaming
+ * stream_size:                         size of the streamed data (U_STREAM_SIZE_UNKOWN if unknown)
+ * stream_block_size:                   size of each block to be streamed, set according to your system
+ * stream_user_data:                    user defined data that will be available in your callback stream functions
+ * websocket_handle:                    handle for websocket extension
+ * shared_data:                         any data shared between callback functions, must be allocated and freed by the callback functions
+ * 
+ */
+struct _u_response {
+  long               status;
+  char             * protocol;
+  struct _u_map    * map_header;
+  unsigned int       nb_cookies;
+  struct _u_cookie * map_cookie;
+  char             * auth_realm;
+  void             * binary_body;
+  size_t             binary_body_length;
+  ssize_t         (* stream_callback) (void * stream_user_data, uint64_t offset, char * out_buf, size_t max);
+  void            (* stream_callback_free) (void * stream_user_data);
+  uint64_t           stream_size;
+  size_t             stream_block_size;
+  void             * stream_user_data;
+  void             * websocket_handle;
+  void *             shared_data;
+};
+
+/**
+ * 
+ * Structure of an endpoint
+ * 
+ * Contains all informations needed for an endpoint
+ * http_method:       http verb (GET, POST, PUT, etc.) in upper case
+ * url_prefix:        prefix for the url (optional)
+ * url_format:        string used to define the endpoint format
+ *                    separate words with /
+ *                    to define a variable in the url, prefix it with @ or :
+ *                    example: /test/resource/:name/elements
+ *                    on an url_format that ends with '*', the rest of the url will not be tested
+ * priority:          endpoint priority in descending order (0 is the higher priority)
+ * callback_function: a pointer to a function that will be executed each time the endpoint is called
+ *                    you must declare the function as described.
+ * user_data:         a pointer to a data or a structure that will be available in callback_function
+ * 
+ */
+struct _u_endpoint {
+  char * http_method;
+  char * url_prefix;
+  char * url_format;
+  uint   priority;
+  int (* callback_function)(const struct _u_request * request, // Input parameters (set by the framework)
+                            struct _u_response * response,     // Output parameters (set by the user)
+                            void * user_data);
+  void * user_data;
+};
+
+/**
+ * 
+ * Structure of an instance
+ * 
+ * Contains the needed data for an ulfius instance to work
+ * 
+ * mhd_daemon:            pointer to the libmicrohttpd daemon
+ * status:                status of the current instance, status are U_STATUS_STOP, U_STATUS_RUNNING or U_STATUS_ERROR
+ * port:                  port number to listen to
+ * bind_address:          ip address to listen to (optional)
+ * nb_endpoints:          Number of available endpoints
+ * default_auth_realm:    Default realm on authentication error
+ * endpoint_list:         List of available endpoints
+ * default_endpoint:      Default endpoint if no other endpoint match the current url
+ * default_headers:       Default headers that will be added to all response->map_header
+ * max_post_param_size:   maximum size for a post parameter, 0 means no limit, default 0
+ * max_post_body_size:    maximum size for the entire post body, 0 means no limit, default 0
+ * 
+ */
+struct _u_instance {
+  struct MHD_Daemon          *  mhd_daemon;
+  int                           status;
+  uint                          port;
+  struct sockaddr_in          * bind_address;
+  int                           nb_endpoints;
+  char                        * default_auth_realm;
+  struct _u_endpoint          * endpoint_list;
+  struct _u_endpoint          * default_endpoint;
+  struct _u_map               * default_headers;
+  size_t                        max_post_param_size;
+  size_t                        max_post_body_size;
+  void                        * websocket_handler;
+};
+
+/**
+ * Structures used to facilitate data manipulations (internal)
+ */
+struct connection_info_struct {
+  struct MHD_PostProcessor * post_processor;
+  int                        has_post_processor;
+  int                        callback_first_iteration;
+  struct _u_request *        request;
+  size_t                     max_post_param_size;
+  struct _u_map              map_url_initial;
+};
+
+/**********************************
+ * Instance functions declarations
+ **********************************/
+
+/**
+ * ulfius_init_instance
+ * 
+ * Initialize a struct _u_instance * with default values
+ * return U_OK on success
+ */
+int ulfius_init_instance(struct _u_instance * u_instance, uint port, struct sockaddr_in * bind_address, const char * default_auth_realm);
+
+/**
+ * ulfius_clean_instance
+ * 
+ * Clean memory allocated by a struct _u_instance *
+ */
+void ulfius_clean_instance(struct _u_instance * u_instance);
+
+/**
+ * ulfius_start_framework
+ * Initializes the framework and run the webservice based on the parameters given
+ * 
+ * u_instance:    pointer to a struct _u_instance that describe its port and bind address
+ * return U_OK on success
+ */
+int ulfius_start_framework(struct _u_instance * u_instance);
+
+/**
+ * ulfius_start_secure_framework
+ * Initializes the framework and run the webservice based on the parameters given using an HTTPS connection
+ * 
+ * u_instance:    pointer to a struct _u_instance that describe its port and bind address
+ * key_pem:       private key for the server
+ * cert_pem:      server certificate
+ * return U_OK on success
+ */
+int ulfius_start_secure_framework(struct _u_instance * u_instance, const char * key_pem, const char * cert_pem);
+
+/**
+ * ulfius_stop_framework
+ * 
+ * Stop the webservice
+ * u_instance:    pointer to a struct _u_instance that describe its port and bind address
+ * return U_OK on success
+ */
+int ulfius_stop_framework(struct _u_instance * u_instance);
+
+/***********************************
+ * Endpoints functions declarations
+ ***********************************/
+
+/**
+ * Add a struct _u_endpoint * to the specified u_instance
+ * Can be done during the execution of the webservice for injection
+ * u_instance: pointer to a struct _u_instance that describe its port and bind address
+ * u_endpoint: pointer to a struct _u_endpoint that will be copied in the u_instance endpoint_list
+ * return U_OK on success
+ */
+int ulfius_add_endpoint(struct _u_instance * u_instance, const struct _u_endpoint * u_endpoint);
+
+/**
+ * Add a struct _u_endpoint * to the specified u_instance with its values specified
+ * Can be done during the execution of the webservice for injection
+ * u_instance: pointer to a struct _u_instance that describe its port and bind address
+ * http_method:       http verb (GET, POST, PUT, etc.) in upper case
+ * url_prefix:        prefix for the url (optional)
+ * url_format:        string used to define the endpoint format
+ *                    separate words with /
+ *                    to define a variable in the url, prefix it with @ or :
+ *                    example: /test/resource/:name/elements
+ *                    on an url_format that ends with '*', the rest of the url will not be tested
+ * priority:          endpoint priority in descending order (0 is the higher priority)
+ * callback_function: a pointer to a function that will be executed each time the endpoint is called
+ *                    you must declare the function as described.
+ * user_data:         a pointer to a data or a structure that will be available in callback_function
+ * return U_OK on success
+ */
+int ulfius_add_endpoint_by_val(struct _u_instance * u_instance,
+                               const char * http_method,
+                               const char * url_prefix,
+                               const char * url_format,
+                               uint priority,
+                               int (* callback_function)(const struct _u_request * request, // Input parameters (set by the framework)
+                                                         struct _u_response * response,     // Output parameters (set by the user)
+                                                         void * user_data),
+                               void * user_data);
+
+/**
+ * Add a struct _u_endpoint * list to the specified u_instance
+ * Can be done during the execution of the webservice for injection
+ * u_instance: pointer to a struct _u_instance that describe its port and bind address
+ * u_endpoint_list: pointer to an array of struct _u_endpoint ending with a ulfius_empty_endpoint() that will be copied in the u_instance endpoint_list
+ * return U_OK on success
+ */
+int ulfius_add_endpoint_list(struct _u_instance * u_instance, const struct _u_endpoint ** u_endpoint_list);
+
+/**
+ * Remove a struct _u_endpoint * from the specified u_instance
+ * Can be done during the execution of the webservice for injection
+ * u_instance: pointer to a struct _u_instance that describe its port and bind address
+ * u_endpoint: pointer to a struct _u_endpoint that will be removed in the u_instance endpoint_list
+ * The parameters _u_endpoint.http_method, _u_endpoint.url_prefix and _u_endpoint.url_format are strictly compared for the match
+ * If no endpoint is found, return U_ERROR_NOT_FOUND
+ * return U_OK on success
+ */
+int ulfius_remove_endpoint(struct _u_instance * u_instance, const struct _u_endpoint * u_endpoint);
+
+/**
+ * ulfius_set_default_endpoint
+ * Set the default endpoint
+ * This endpoint will be called if no endpoint match the url called
+ * u_instance: pointer to a struct _u_instance that describe its port and bind address
+ * auth_function:     a pointer to a function that will be executed prior to the callback for authentication
+ *                    you must declare the function as described.
+ * auth_data:         a pointer to a data or a structure that will be available in auth_function
+ * auth_realm:        realm value for authentication
+ * callback_function: a pointer to a function that will be executed each time the endpoint is called
+ *                    you must declare the function as described.
+ * user_data:         a pointer to a data or a structure that will be available in callback_function
+ * to remove a default endpoint, call ulfius_set_default_endpoint with NULL parameter for callback_function
+ * return U_OK on success
+ */
+int ulfius_set_default_endpoint(struct _u_instance * u_instance,
+                                         int (* callback_function)(const struct _u_request * request, struct _u_response * response, void * user_data),
+                                         void * user_data);
+
+/**
+ * Remove a struct _u_endpoint * from the specified u_instance
+ * using the specified values used to identify an endpoint
+ * Can be done during the execution of the webservice for injection
+ * u_instance: pointer to a struct _u_instance that describe its port and bind address
+ * http_method: http_method used by the endpoint
+ * url_prefix: url_prefix used by the endpoint
+ * url_format: url_format used by the endpoint
+ * The parameters _u_endpoint.http_method, _u_endpoint.url_prefix and _u_endpoint.url_format are strictly compared for the match
+ * If no endpoint is found, return U_ERROR_NOT_FOUND
+ * return U_OK on success
+ */
+int ulfius_remove_endpoint_by_val(struct _u_instance * u_instance, const char * http_method, const char * url_prefix, const char * url_format);
+
+/**
+ * ulfius_empty_endpoint
+ * return an empty endpoint that goes at the end of an endpoint list
+ */
+const struct _u_endpoint * ulfius_empty_endpoint();
+
+/**
+ * ulfius_copy_endpoint
+ * return a copy of an endpoint with duplicate values
+ */
+int ulfius_copy_endpoint(struct _u_endpoint * dest, const struct _u_endpoint * source);
+
+/**
+ * u_copy_endpoint_list
+ * return a copy of an endpoint list with duplicate values
+ * returned value must be free'd after use
+ */
+struct _u_endpoint * ulfius_duplicate_endpoint_list(const struct _u_endpoint * endpoint_list);
+
+/**
+ * ulfius_clean_endpoint
+ * free allocated memory by an endpoint
+ */
+void ulfius_clean_endpoint(struct _u_endpoint * endpoint);
+
+/**
+ * ulfius_clean_endpoint_list
+ * free allocated memory by an endpoint list
+ */
+void ulfius_clean_endpoint_list(struct _u_endpoint * endpoint_list);
+
+/**
+ * ulfius_equals_endpoints
+ * Compare 2 endpoints and return true if their method, prefix and format are the same or if both are NULL
+ */
+int ulfius_equals_endpoints(const struct _u_endpoint * endpoint1, const struct _u_endpoint * endpoint2);
+
+#ifndef U_DISABLE_CURL
+/********************************************
+ * Requests/Responses functions declarations
+ ********************************************/
+
+/**
+ * ulfius_send_http_request
+ * Send a HTTP request and store the result into a _u_response
+ * return U_OK on success
+ */
+int ulfius_send_http_request(const struct _u_request * request, struct _u_response * response);
+
+/**
+ * ulfius_send_http_streaming_request
+ * Send a HTTP request and store the result into a _u_response
+ * Except for the body which will be available using write_body_function in the write_body_data
+ * return U_OK on success
+ */
+int ulfius_send_http_streaming_request(const struct _u_request * request, struct _u_response * response, size_t (* write_body_function)(void * contents, size_t size, size_t nmemb, void * user_data), void * write_body_data);
+
+/**
+ * ulfius_send_smtp_email
+ * Send an email using libcurl
+ * email is plain/text and UTF8 charset
+ * host: smtp server host name
+ * port: tcp port number (optional, 0 for default)
+ * use_tls: true if the connection is tls secured
+ * verify_certificate: true if you want to disable the certificate verification on a tls server
+ * user: connection user name (optional, NULL: no user name)
+ * password: connection password (optional, NULL: no password)
+ * from: from address (mandatory)
+ * to: to recipient address (mandatory)
+ * cc: cc recipient address (optional, NULL: no cc)
+ * bcc: bcc recipient address (optional, NULL: no bcc)
+ * subject: email subject (mandatory)
+ * mail_body: email body (mandatory)
+ * return U_OK on success
+ */
+int ulfius_send_smtp_email(const char * host, 
+                            const int port, 
+                            const int use_tls, 
+                            const int verify_certificate, 
+                            const char * user, 
+                            const char * password, 
+                            const char * from, 
+                            const char * to, 
+                            const char * cc, 
+                            const char * bcc, 
+                            const char * subject, 
+                            const char * mail_body);
+#endif
+
+/**
+ * ulfius_add_cookie_to_header
+ * add a cookie to the cookie map
+ * return U_OK on success
+ */
+int ulfius_add_cookie_to_response(struct _u_response * response, const char * key, const char * value, const char * expires, const uint max_age, 
+                      const char * domain, const char * path, const int secure, const int http_only);
+
+/**
+ * ulfius_add_header_to_response
+ * add a header to the response
+ * return U_OK on success
+ */
+int ulfius_add_header_to_response(struct _u_response * response, const char * key, const char * value);
+
+/**
+ * ulfius_set_string_body_response
+ * Add a string body to a response
+ * body must end with a '\0' character
+ * return U_OK on success
+ */
+int ulfius_set_string_body_response(struct _u_response * response, const uint status, const char * body);
+
+/**
+ * ulfius_set_binary_body_response
+ * Add a binary body to a response
+ * return U_OK on success
+ */
+int ulfius_set_binary_body_response(struct _u_response * response, const uint status, const char * body, const size_t length);
+
+/**
+ * ulfius_set_empty_body_response
+ * Set an empty response with only a status
+ * return U_OK on success
+ */
+int ulfius_set_empty_body_response(struct _u_response * response, const uint status);
+
+/**
+ * ulfius_set_stream_response
+ * Set an stream response with a status
+ * return U_OK on success
+ */
+int ulfius_set_stream_response(struct _u_response * response, 
+                                const uint status,
+                                ssize_t (* stream_callback) (void * stream_user_data, uint64_t offset, char * out_buf, size_t max),
+                                void (* stream_callback_free) (void * stream_user_data),
+                                uint64_t stream_size,
+                                size_t stream_block_size,
+                                void * stream_user_data);
+
+/**
+ * ulfius_init_request
+ * Initialize a request structure by allocating inner elements
+ * return U_OK on success
+ */
+int ulfius_init_request(struct _u_request * request);
+
+/**
+ * ulfius_clean_request
+ * clean the specified request's inner elements
+ * user must free the parent pointer if needed after clean
+ * or use ulfius_clean_request_full
+ * return U_OK on success
+ */
+int ulfius_clean_request(struct _u_request * request);
+
+/**
+ * ulfius_clean_request_full
+ * clean the specified request and all its elements
+ * return U_OK on success
+ */
+int ulfius_clean_request_full(struct _u_request * request);
+
+/**
+ * ulfius_init_response
+ * Initialize a response structure by allocating inner elements
+ * return U_OK on success
+ */
+int ulfius_init_response(struct _u_response * response);
+
+/**
+ * ulfius_clean_response
+ * clean the specified response's inner elements
+ * user must free the parent pointer if needed after clean
+ * or use ulfius_clean_response_full
+ * return U_OK on success
+ */
+int ulfius_clean_response(struct _u_response * response);
+
+/**
+ * ulfius_clean_response_full
+ * clean the specified response and all its elements
+ * return U_OK on success
+ */
+int ulfius_clean_response_full(struct _u_response * response);
+
+/**
+ * ulfius_copy_response
+ * Copy the source response elements into the des response
+ * return U_OK on success
+ */
+int ulfius_copy_response(struct _u_response * dest, const struct _u_response * source);
+
+/**
+ * ulfius_clean_cookie
+ * clean the cookie's elements
+ * return U_OK on success
+ */
+int ulfius_clean_cookie(struct _u_cookie * cookie);
+
+/**
+ * Copy the cookie source elements into dest elements
+ * return U_OK on success
+ */
+int ulfius_copy_cookie(struct _u_cookie * dest, const struct _u_cookie * source);
+
+/**
+ * create a new request based on the source elements
+ * returned value must be cleaned after use
+ */
+struct _u_request * ulfius_duplicate_request(const struct _u_request * request);
+
+/**
+ * create a new response based on the source elements
+ * return value must be cleaned after use
+ */
+struct _u_response * ulfius_duplicate_response(const struct _u_response * response);
+
+#ifndef U_DISABLE_JANSSON
+/**
+ * ulfius_get_json_body_request
+ * Get JSON structure from the request body if the request is valid
+ */
+json_t * ulfius_get_json_body_request(const struct _u_request * request, json_error_t * json_error);
+
+/**
+ * ulfius_set_json_body_request
+ * Add a json_t body to a request
+ * return U_OK on success
+ */
+int ulfius_set_json_body_request(struct _u_request * request, json_t * body);
+
+/**
+ * ulfius_set_json_body_response
+ * Add a json_t body to a response
+ * return U_OK on success
+ */
+int ulfius_set_json_body_response(struct _u_response * response, const uint status, const json_t * body);
+
+/**
+ * ulfius_get_json_body_response
+ * Get JSON structure from the response body if the request is valid
+ */
+json_t * ulfius_get_json_body_response(struct _u_response * response, json_error_t * json_error);
+#endif
+
+/************************************************************************
+ * _u_map declarations                                                  *  
+ * _u_map is a simple map structure that handles sets of key/value maps *
+ ************************************************************************/
+
+/**
+ * initialize a struct _u_map
+ * this function MUST be called after a declaration or allocation
+ * return U_OK on success
+ */
+int u_map_init(struct _u_map * map);
+
+/**
+ * free the struct _u_map's inner components
+ * return U_OK on success
+ */
+int u_map_clean(struct _u_map * u_map);
+
+/**
+ * free the struct _u_map and its components
+ * return U_OK on success
+ */
+int u_map_clean_full(struct _u_map * u_map);
+
+/**
+ * free an enum return by functions u_map_enum_keys or u_map_enum_values
+ * return U_OK on success
+ */
+int u_map_clean_enum(char ** array);
+
+/**
+ * returns an array containing all the keys in the struct _u_map
+ * return an array of char * ending with a NULL element
+ */
+const char ** u_map_enum_keys(const struct _u_map * u_map);
+
+/**
+ * returns an array containing all the values in the struct _u_map
+ * return an array of char * ending with a NULL element
+ */
+const char ** u_map_enum_values(const struct _u_map * u_map);
+
+/**
+ * return true if the sprcified u_map contains the specified key
+ * false otherwise
+ * search is case sensitive
+ */
+int u_map_has_key(const struct _u_map * u_map, const char * key);
+
+/**
+ * return true if the sprcified u_map contains the specified value
+ * false otherwise
+ * search is case sensitive
+ */
+int u_map_has_value(const struct _u_map * u_map, const char * value);
+
+/**
+ * return true if the sprcified u_map contains the specified value up until the specified length
+ * false otherwise
+ * search is case sensitive
+ */
+int u_map_has_value_binary(const struct _u_map * u_map, const char * value, size_t length);
+
+/**
+ * return true if the sprcified u_map contains the specified key
+ * false otherwise
+ * search is case insensitive
+ */
+int u_map_has_key_case(const struct _u_map * u_map, const char * key);
+
+/**
+ * return true if the sprcified u_map contains the specified value
+ * false otherwise
+ * search is case insensitive
+ */
+int u_map_has_value_case(const struct _u_map * u_map, const char * value);
+
+/**
+ * add the specified key/value pair into the specified u_map
+ * if the u_map already contains a pair with the same key, replace the value
+ * return U_OK on success
+ */
+int u_map_put(struct _u_map * u_map, const char * key, const char * value);
+
+/**
+ * add the specified key/binary value pair into the specified u_map
+ * if the u_map already contains a pair with the same key,
+ * replace the value at the specified offset with the specified length
+ * return U_OK on success
+ */
+int u_map_put_binary(struct _u_map * u_map, const char * key, const char * value, uint64_t offset, size_t length);
+
+/**
+ * get the value length corresponding to the specified key in the u_map
+ * return -1 if no match found
+ * search is case sensitive
+ */
+ssize_t u_map_get_length(const struct _u_map * u_map, const char * key);
+
+/**
+ * get the value length corresponding to the specified key in the u_map
+ * return -1 if no match found
+ * search is case insensitive
+ */
+ssize_t u_map_get_case_length(const struct _u_map * u_map, const char * key);
+
+/**
+ * get the value corresponding to the specified key in the u_map
+ * return NULL if no match found
+ * search is case sensitive
+ */
+const char * u_map_get(const struct _u_map * u_map, const char * key);
+
+/**
+ * get the value corresponding to the specified key in the u_map
+ * return NULL if no match found
+ * search is case insensitive
+ */
+const char * u_map_get_case(const struct _u_map * u_map, const char * key);
+
+/**
+ * remove an pair key/value that has the specified key
+ * return U_OK on success, U_NOT_FOUND if key was not found, error otherwise
+ */
+int u_map_remove_from_key(struct _u_map * u_map, const char * key);
+
+/**
+ * remove all pairs key/value that has the specified key (case insensitive search)
+ * return U_OK on success, U_NOT_FOUND if key was not found, error otherwise
+ */
+int u_map_remove_from_key_case(struct _u_map * u_map, const char * key);
+
+/**
+ * remove all pairs key/value that has the specified value
+ * return U_OK on success, U_NOT_FOUND if key was not found, error otherwise
+ */
+int u_map_remove_from_value(struct _u_map * u_map, const char * value);
+
+/**
+ * remove all pairs key/value that has the specified value (case insensitive search)
+ * return U_OK on success, U_NOT_FOUND if key was not found, error otherwise
+ */
+int u_map_remove_from_value_case(struct _u_map * u_map, const char * value);
+
+/**
+ * remove all pairs key/value that has the specified value up until the specified length
+ * return U_OK on success, U_NOT_FOUND if key was not found, error otherwise
+ */
+int u_map_remove_from_value_binary(struct _u_map * u_map, const char * key, size_t length);
+
+/**
+ * remove the pair key/value at the specified index
+ * return U_OK on success, U_NOT_FOUND if index is out of bound, error otherwise
+ */
+int u_map_remove_at(struct _u_map * u_map, const int index);
+
+/**
+ * Create an exact copy of the specified struct _u_map
+ * return a reference to the copy, NULL otherwise
+ * returned value must be free'd after use
+ */
+struct _u_map * u_map_copy(const struct _u_map * source);
+
+/**
+ * Copy all key/values pairs of source into dest
+ * If key is already present in dest, it's overwritten
+ * return U_OK on success, error otherwise
+ */
+int u_map_copy_into(struct _u_map * dest, const struct _u_map * source);
+
+/**
+ * Return the number of key/values pair in the specified struct _u_map
+ * Return -1 on error
+ */
+int u_map_count(const struct _u_map * source);
+
+/**
+ * Empty a struct u_map of all its elements
+ * return U_OK on success, error otherwise
+ */
+int u_map_empty(struct _u_map * u_map);
+
+#ifndef U_DISABLE_WEBSOCKET
+/**********************************
+ * Websocket functions declarations
+ **********************************/
+
+#define U_WEBSOCKET_MAGIC_STRING     "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
+#define U_WEBSOCKET_UPGRADE_VALUE    "websocket"
+#define U_WEBSOCKET_BAD_REQUEST_BODY "Error in websocket handshake, wrong parameters"
+#define U_WEBSOCKET_USEC_WAIT        50
+#define WEBSOCKET_MAX_CLOSE_TRY      10
+
+#define U_WEBSOCKET_BIT_FIN         0x80
+#define U_WEBSOCKET_HAS_MASK        0x80
+#define U_WEBSOCKET_LEN_MASK        0x7F
+#define U_WEBSOCKET_OPCODE_CONTINUE 0x00
+#define U_WEBSOCKET_OPCODE_TEXT     0x01
+#define U_WEBSOCKET_OPCODE_BINARY   0x01
+#define U_WEBSOCKET_OPCODE_CLOSE    0x08
+#define U_WEBSOCKET_OPCODE_PING     0x09
+#define U_WEBSOCKET_OPCODE_PONG     0x0A
+#define U_WEBSOCKET_OPCODE_CLOSED   0xFD
+#define U_WEBSOCKET_OPCODE_ERROR    0xFE
+#define U_WEBSOCKET_OPCODE_NONE     0xFF
+
+/**
+ * Websocket manager structure
+ * contains among other things the socket
+ * the status (open, closed), and the list of incoming and outcoming messages
+ * Used on public callback functions
+ */
+struct _websocket_manager {
+  struct _websocket_message_list * message_list_incoming;
+  struct _websocket_message_list * message_list_outcoming;
+  int connected;
+  int closing;
+  int manager_closed;
+  MHD_socket sock;
+  pthread_mutex_t read_lock;
+  pthread_mutex_t write_lock;
+  struct pollfd fds;
+};
+
+/**
+ * websocket message structure
+ * contains all the data of a websocket message
+ * and the timestamp of when it was sent of received
+ */
+struct _websocket_message {
+  time_t datestamp;
+  uint8_t opcode;
+  uint8_t has_mask;
+  uint8_t mask[4];
+  uint64_t data_len;
+  char * data;
+};
+
+struct _websocket_message_list {
+  struct _websocket_message ** list;
+  size_t len;
+};
+
+/**
+ * websocket structure
+ * contains all the data of the websocket
+ */
+struct _websocket {
+  struct _u_instance               * instance;
+  struct _u_request                * request;
+  char                             * websocket_protocol;
+  char                             * websocket_extensions;
+  void                             (* websocket_manager_callback) (const struct _u_request * request,
+                                                                  struct _websocket_manager * websocket_manager,
+                                                                  void * websocket_manager_user_data);
+  void                             * websocket_manager_user_data;
+  void                             (* websocket_incoming_message_callback) (const struct _u_request * request,
+                                                                           struct _websocket_manager * websocket_manager,
+                                                                           const struct _websocket_message * message,
+                                                                           void * websocket_incoming_user_data);
+  void                             * websocket_incoming_user_data;
+  void                             (* websocket_onclose_callback) (const struct _u_request * request,
+                                                                  struct _websocket_manager * websocket_manager,
+                                                                  void * websocket_onclose_user_data);
+  void                             * websocket_onclose_user_data;
+  int                                tls;
+  struct _websocket_manager        * websocket_manager;
+  struct MHD_UpgradeResponseHandle * urh;
+};
+
+/**
+ * Set a websocket in the response
+ * You must set at least websocket_manager_callback or websocket_incoming_message_callback
+ * @Parameters
+ * response: struct _u_response to send back the websocket initialization, mandatory
+ * websocket_protocol: list of protocols, separated by a comma, or NULL if all protocols are accepted
+ * websocket_extensions: list of extensions, separated by a comma, or NULL if all extensions are accepted
+ * websocket_manager_callback: callback function called right after the handshake acceptance, optional
+ * websocket_manager_user_data: any data that will be given to the websocket_manager_callback, optional
+ * websocket_incoming_message_callback: callback function called on each incoming complete message, optional
+ * websocket_incoming_user_data: any data that will be given to the websocket_incoming_message_callback, optional
+ * websocket_onclose_callback: callback function called right before closing the websocket, must be complete for the websocket to close
+ * websocket_onclose_user_data: any data that will be given to the websocket_onclose_callback, optional
+ * @Return value: U_OK on success
+ */
+int ulfius_set_websocket_response(struct _u_response * response,
+                                   const char * websocket_protocol,
+                                   const char * websocket_extensions, 
+                                   void (* websocket_manager_callback) (const struct _u_request * request,
+                                                                        struct _websocket_manager * websocket_manager,
+                                                                        void * websocket_manager_user_data),
+                                   void * websocket_manager_user_data,
+                                   void (* websocket_incoming_message_callback) (const struct _u_request * request,
+                                                                                 struct _websocket_manager * websocket_manager,
+                                                                                 const struct _websocket_message * message,
+                                                                                 void * websocket_incoming_user_data),
+                                   void * websocket_incoming_user_data,
+                                   void (* websocket_onclose_callback) (const struct _u_request * request,
+                                                                        struct _websocket_manager * websocket_manager,
+                                                                        void * websocket_onclose_user_data),
+                                   void * websocket_onclose_user_data);
+
+/**
+ * Send a message in the websocket
+ * Return U_OK on success
+ */
+int ulfius_websocket_send_message(struct _websocket_manager * websocket_manager,
+                                  const uint8_t opcode,
+                                  const uint64_t data_len,
+                                  const char * data);
+
+/**
+ * Return the first message of the message list
+ * Return NULL if message_list has no message
+ * Returned value must be cleared after use
+ */
+struct _websocket_message * ulfius_websocket_pop_first_message(struct _websocket_message_list * message_list);
+
+/**
+ * Clear data of a websocket message
+ */
+void ulfius_clear_websocket_message(struct _websocket_message * message);
+
+#endif
+
+/**
+ * free data allocated by ulfius functions
+ */
+void u_free(void * data);
+
+/**********************************
+ * Internal functions declarations
+ **********************************/
+
+/**
+ * ulfius_validate_instance
+ * return true if u_instance has valid parameters, false otherwise
+ */
+int ulfius_validate_instance(const struct _u_instance * u_instance);
+/**
+ * ulfius_is_valid_endpoint
+ * return true if the endpoind has valid parameters
+ */
+int ulfius_is_valid_endpoint(const struct _u_endpoint * endpoint, int to_delete);
+
+/**
+ * ulfius_validate_endpoint_list
+ * return true if endpoint_list has valid parameters, false otherwise
+ */
+int ulfius_validate_endpoint_list(const struct _u_endpoint * endpoint_list, int nb_endpoints);
+
+/**
+ * ulfius_webservice_dispatcher
+ * function executed by libmicrohttpd every time an HTTP call is made
+ * return MHD_NO on error
+ */
+int ulfius_webservice_dispatcher (void *cls, struct MHD_Connection *connection,
+                                  const char *url, const char *method,
+                                  const char *version, const char *upload_data,
+                                  size_t *upload_data_size, void **con_cls);
+/**
+ * mhd_iterate_post_data
+ * function used to iterate post parameters
+ * return MHD_NO on error
+ */
+int mhd_iterate_post_data (void *coninfo_cls, enum MHD_ValueKind kind, const char *key,
+                      const char *filename, const char *content_type,
+                      const char *transfer_encoding, const char *data, uint64_t off,
+                      size_t size);
+
+/**
+ * mhd_request_completed
+ * function used to clean data allocated after a web call is complete
+ */
+void mhd_request_completed (void *cls, struct MHD_Connection *connection,
+                        void **con_cls, enum MHD_RequestTerminationCode toe);
+
+/**
+ * ulfius_split_url
+ * return an array of char based on the url words
+ * returned value must be u_free'd after use
+ */
+char ** ulfius_split_url(const char * prefix, const char * url);
+
+/**
+ * Sort an array of struct _u_endpoint * using bubble sort algorithm
+ */
+void sort_endpoint_list (struct _u_endpoint ** endpoint_list, int length);
+
+/**
+ * ulfius_endpoint_match
+ * return the endpoint array matching the url called with the proper http method
+ * the returned array always has its last value to NULL
+ * return NULL on memory error
+ */
+struct _u_endpoint ** ulfius_endpoint_match(const char * method, const char * url, struct _u_endpoint * endpoint_list);
+
+/**
+ * ulfius_url_format_match
+ * return true if splitted_url matches splitted_url_format
+ * false otherwise
+ */
+int ulfius_url_format_match(const char ** splitted_url, const char ** splitted_url_format);
+
+/**
+ * ulfius_parse_url
+ * fills map with the keys/values defined in the url that are described in the endpoint format url
+ * return U_OK on success
+ */
+int ulfius_parse_url(const char * url, const struct _u_endpoint * endpoint, struct _u_map * map);
+
+/**
+ * ulfius_set_response_header
+ * adds headers defined in the response_map_header to the response
+ * return the number of added headers, -1 on error
+ */
+int ulfius_set_response_header(struct MHD_Response * response, const struct _u_map * response_map_header);
+
+/**
+ * ulfius_set_response_cookie
+ * adds cookies defined in the response_map_cookie
+ * return the number of added headers, -1 on error
+ */
+int ulfius_set_response_cookie(struct MHD_Response * mhd_response, const struct _u_response * response);
+
+/**
+ * Add a cookie in the cookie map as defined in the RFC 6265
+ * Returned value must be u_free'd after use
+ */
+char * ulfius_get_cookie_header(const struct _u_cookie * cookie);
+
+/** Macro values **/
+#define ULFIUS_URL_SEPARATOR       "/"
+#define ULFIUS_HTTP_ENCODING_JSON  "application/json"
+#define ULFIUS_HTTP_HEADER_CONTENT "Content-Type"
+#define ULFIUS_HTTP_NOT_FOUND_BODY "Resource not found"
+#define ULFIUS_HTTP_ERROR_BODY     "Server Error"
+
+#define ULFIUS_COOKIE_ATTRIBUTE_EXPIRES  "Expires"
+#define ULFIUS_COOKIE_ATTRIBUTE_MAX_AGE  "Max-Age"
+#define ULFIUS_COOKIE_ATTRIBUTE_DOMAIN   "Domain"
+#define ULFIUS_COOKIE_ATTRIBUTE_PATH     "Path"
+#define ULFIUS_COOKIE_ATTRIBUTE_SECURE   "Secure"
+#define ULFIUS_COOKIE_ATTRIBUTE_HTTPONLY "HttpOnly"
+
+#define ULFIUS_POSTBUFFERSIZE 1024
+
+#define U_STATUS_STOP     0
+#define U_STATUS_RUNNING  1
+#define U_STATUS_ERROR    2
+
+#ifndef U_DISABLE_WEBSOCKET
+
+/**
+ * websocket_manager_callback:          callback function for working with the websocket
+ * websocket_manager_user_data:         user-defined data that will be handled to websocket_manager_callback
+ * websocket_incoming_message_callback: callback function that will be called every time a message arrives from the client in the websocket
+ * websocket_incoming_user_data:        user-defined data that will be handled to websocket_incoming_message_callback
+ * websocket_onclose_callback:          callback function that will be called if the websocket is open while the program calls ulfius_stop_framework
+ * websocket_onclose_user_data:         user-defined data that will be handled to websocket_onclose_callback
+ */
+struct _websocket_handle {
+  char             * websocket_protocol;
+  char             * websocket_extensions;
+  void            (* websocket_manager_callback) (const struct _u_request * request,
+                                                  struct _websocket_manager * websocket_manager,
+                                                  void * websocket_manager_user_data);
+  void             * websocket_manager_user_data;
+  void            (* websocket_incoming_message_callback) (const struct _u_request * request,
+                                                           struct _websocket_manager * websocket_manager,
+                                                           const struct _websocket_message * message,
+                                                           void * websocket_incoming_user_data);
+  void             * websocket_incoming_user_data;
+  void            (* websocket_onclose_callback) (const struct _u_request * request,
+                                                  struct _websocket_manager * websocket_manager,
+                                                  void * websocket_onclose_user_data);
+  void             * websocket_onclose_user_data;
+};
+
+struct _websocket_handler {
+  size_t                        nb_websocket_active;
+  struct _websocket          ** websocket_active;
+  pthread_mutex_t               websocket_close_lock;
+  pthread_cond_t                websocket_close_cond;
+  int                           pthread_init;
+};
+
+/**
+ * Websocket callback function for MHD
+ * Starts the websocket manager if set,
+ * then sets a listening message loop
+ * Complete the callback when the websocket is closed
+ * The websocket can be closed by the client, the manager, the program, or on network disconnect
+ */
+void ulfius_start_websocket_cb (void *cls,
+            struct MHD_Connection *connection,
+            void *con_cls,
+            const char *extra_in,
+            size_t extra_in_size,
+            MHD_socket sock,
+            struct MHD_UpgradeResponseHandle *urh);
+
+/**
+ * Workaround to make sure a message, as long as it can be is complete sent
+ */
+void ulfius_websocket_send_all(MHD_socket sock, const uint8_t * data, size_t len);
+
+/**
+ * Centralise socket reading in this function
+ * so if options or check must be done, it's done here instead of each read call
+ */
+size_t ulfius_websocket_recv_all(MHD_socket sock, uint8_t * data, size_t len);
+
+/**
+ * Generates a handhshake answer from the key given in parameter
+ */
+int ulfius_generate_handshake_answer(const char * key, char * out_digest);
+
+/**
+ * Close the websocket
+ */
+int ulfius_close_websocket(struct _websocket * websocket);
+
+/**
+ * Return a match list between two list of items
+ * If match is NULL, then return source duplicate
+ * Returned value must be u_free'd after use
+ */
+char * ulfius_check_list_match(const char * source, const char * match);
+
+/**
+ * Initialize a websocket message list
+ * Return U_OK on success
+ */
+int ulfius_init_websocket_message_list(struct _websocket_message_list * message_list);
+
+/**
+ * Clear data of a websocket message list
+ */
+void ulfius_clear_websocket_message_list(struct _websocket_message_list * message_list);
+
+/**
+ * Append a message in a message list
+ * Return U_OK on success
+ */
+int ulfius_push_websocket_message(struct _websocket_message_list * message_list, struct _websocket_message * message);
+
+/**
+ * Clear data of a websocket
+ */
+int ulfius_clear_websocket(struct _websocket * websocket);
+
+/**
+ * Clear data of a websocket_manager
+ */
+void ulfius_clear_websocket_manager(struct _websocket_manager * websocket_manager);
+
+/**
+ * Read and parse a new message from the websocket
+ * Return the opcode of the new websocket, U_WEBSOCKET_OPCODE_NONE if no message arrived, or U_WEBSOCKET_OPCODE_ERROR on error
+ * Sets the new message in the message variable if available
+ */
+int ulfius_read_incoming_message(struct _websocket_manager * websocket_manager, struct _websocket_message ** message);
+
+/**
+ * Run the websocket manager in a separated detached thread
+ */
+void * ulfius_thread_websocket_manager_run(void * args);
+
+/**
+ * Send a message in the websocket without lock
+ * Return U_OK on success
+ */
+int ulfius_websocket_send_message_nolock(struct _websocket_manager * websocket_manager,
+                                  const uint8_t opcode,
+                                  const uint64_t data_len,
+                                  const char * data);
+
+ /**
+ * Add a websocket in the list of active websockets of the instance
+ */
+int ulfius_instance_add_websocket_active(struct _u_instance * instance, struct _websocket * websocket);
+
+/**
+ * Remove a websocket from the list of active websockets of the instance
+ */
+int ulfius_instance_remove_websocket_active(struct _u_instance * instance, struct _websocket * websocket); 
+#endif // U_DISABLE_WEBSOCKET
+
+#endif // __ULFIUS_H__
diff --git a/includes/yder.h b/includes/yder.h
new file mode 100644
index 0000000000000000000000000000000000000000..a2defa4660a0dd62637dfb14d2a72a9448d7600b
--- /dev/null
+++ b/includes/yder.h
@@ -0,0 +1,60 @@
+/**
+ * 
+ * Yder Framework
+ * 
+ * Logging framework library
+ * 
+ * yder.h: structures and functions declarations
+ * 
+ * Copyright 2015-2017 Nicolas Mora <mail@babelouest.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation;
+ * version 2.1 of the License.
+ *
+ * This library 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 this library.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ */
+
+#ifndef __YDER_H__
+#define __YDER_H__
+
+#define YDER_VERSION 2.0
+
+#define Y_LOG_MODE_NONE    0x0000
+#define Y_LOG_MODE_CONSOLE 0x00F0
+#define Y_LOG_MODE_SYSLOG  0x0F00
+#define Y_LOG_MODE_FILE    0xF000
+#define Y_LOG_MODE_CURRENT 0xFFFF
+
+#define Y_LOG_LEVEL_NONE    0x0000
+#define Y_LOG_LEVEL_ERROR   0x000F
+#define Y_LOG_LEVEL_WARNING 0x00F0
+#define Y_LOG_LEVEL_INFO    0x0F00
+#define Y_LOG_LEVEL_DEBUG   0xF000
+#define Y_LOG_LEVEL_CURRENT 0xFFFF
+
+/**
+ * Initialize logging with mode and level parameters, specify a log file if needed
+ * Return true on success, false on error
+ */
+int y_init_logs(const char * app, const unsigned long init_mode, const unsigned long init_level, const char * init_log_file, const char * message);
+
+/**
+ * Close the logs
+ */
+int y_close_logs();
+
+/**
+ * Log a message using current parameters
+ */
+void y_log_message(const unsigned long type, const char * message, ...);
+
+#endif // __YDER_H__
diff --git a/libraries/liborcania.so b/libraries/liborcania.so
new file mode 100755
index 0000000000000000000000000000000000000000..e41e68d5d809996e5df81680ac48cb89549f71f8
Binary files /dev/null and b/libraries/liborcania.so differ
diff --git a/libraries/liborcania.so.1.1 b/libraries/liborcania.so.1.1
new file mode 100755
index 0000000000000000000000000000000000000000..e41e68d5d809996e5df81680ac48cb89549f71f8
Binary files /dev/null and b/libraries/liborcania.so.1.1 differ
diff --git a/libraries/libulfius.so b/libraries/libulfius.so
new file mode 100755
index 0000000000000000000000000000000000000000..1f1731e0907d7bf1fbf51328565362fa510b4afc
Binary files /dev/null and b/libraries/libulfius.so differ
diff --git a/libraries/libulfius.so.2.1 b/libraries/libulfius.so.2.1
new file mode 100755
index 0000000000000000000000000000000000000000..1f1731e0907d7bf1fbf51328565362fa510b4afc
Binary files /dev/null and b/libraries/libulfius.so.2.1 differ
diff --git a/libraries/libyder.so b/libraries/libyder.so
new file mode 100755
index 0000000000000000000000000000000000000000..623103e1ab2ff20bb9b4a740847b3f5c5fc8f374
Binary files /dev/null and b/libraries/libyder.so differ
diff --git a/libraries/libyder.so.2.0 b/libraries/libyder.so.2.0
new file mode 100755
index 0000000000000000000000000000000000000000..623103e1ab2ff20bb9b4a740847b3f5c5fc8f374
Binary files /dev/null and b/libraries/libyder.so.2.0 differ
diff --git a/src/api/default.c b/src/api/default.c
new file mode 100644
index 0000000000000000000000000000000000000000..747d48f665e02b2e3083ed1cabffcd2cb1071ae3
--- /dev/null
+++ b/src/api/default.c
@@ -0,0 +1,13 @@
+/**
+ * Default callback function, returning a 404 response.
+ * @param[in]   request   incoming HTTP request
+ * @param[out]  response  HTTP response to the request
+ * @param[in]   user_data extra data to pass between main thread and callbacks
+ * @return                internal status code
+ */
+int callback_default(const struct _u_request * request,
+    struct _u_response * response, void * user_data)
+{
+    ulfius_set_string_body_response(response, 404, "Unknown endpoint");
+    return U_CALLBACK_CONTINUE;
+}
diff --git a/src/api/encryption_unlock.c b/src/api/encryption_unlock.c
new file mode 100644
index 0000000000000000000000000000000000000000..fbc7f790b229ae07c4c13877408bed34639a3025
--- /dev/null
+++ b/src/api/encryption_unlock.c
@@ -0,0 +1,43 @@
+/**
+ * Callback function that uses the password passed in the request to open the
+ * luks volume.
+ * @param[in]   request   incoming HTTP request
+ * @param[out]  response  HTTP response to the request
+ * @param[in]   user_data extra data to pass between main thread and callbacks
+ * @return                internal status code
+ */
+int callback_encryption_unlock(const struct _u_request * request,
+    struct _u_response * response, void * user_data)
+{
+    json_t * json_input = ulfius_get_json_body_request(request, NULL);
+    const char * password;
+    password = json_string_value(json_object_get(json_input, "password"));
+  
+    if (password == NULL)
+    {
+        return send_simple_response(response, 400, "error", "missing password");
+    }
+  
+    int unlock_status = encryption_unlock(CONTAINER_DEVICE, MAPPED_DEVICE_NAME,
+        password);
+  
+    if (unlock_status == -1)
+    {
+        // Experience learns that -1 is returned when the password is wrong.
+        return send_simple_response(response, 403, "error",
+           "incorrect password");
+    }
+  
+    if (unlock_status != 0)
+    {
+        // Something else went wrong with unlocking.
+        printf("encryption_unlock failed with status %d\n", unlock_status);
+        return send_simple_response(response, 500, "error",
+            "error during unlocking");
+    }
+  
+    // If we reach this point, apparently everything went well.
+    int r = send_simple_response(response, 200, "status", "ok");
+    stop_server();
+    return r;
+}
diff --git a/src/auxiliary.c b/src/auxiliary.c
new file mode 100644
index 0000000000000000000000000000000000000000..b025dddd734718554a07a9c363fdd7df5106a5ae
--- /dev/null
+++ b/src/auxiliary.c
@@ -0,0 +1,63 @@
+/**
+ * Use a fifo to signal that we want to stop the api server.
+ */
+void stop_server()
+{
+    printf("Stopping cryptops-api server...\n");
+    int fifo;
+    char fifo_path[] = FIFO_PATH;
+    fifo = open(fifo_path, O_WRONLY);
+    char * msg = "stop";
+    write(fifo, msg, strlen(msg) + 1);
+}
+
+/**
+ * Read a file completely into a string.
+ * @param  filename Path to the file to read.
+ * @return          Contents of the file.
+ */
+char * read_file(const char * filename)
+{
+    char * buffer = NULL;
+    long length;
+    FILE * file = fopen(filename, "rb");
+    if (filename != NULL)
+    {
+        if (file)
+        {
+            fseek(file, 0, SEEK_END);
+            length = ftell(file);
+            fseek(file, 0, SEEK_SET);
+            buffer = o_malloc(length + 1);
+            if (buffer)
+            {
+                fread(buffer, 1, length, file);
+            }
+            buffer[length] = '\0';
+            fclose (file);
+        }
+        return buffer;
+    }
+    else
+    {
+        return NULL;
+    }
+}
+
+/**
+ * Respond to the request with a simple json structure '{$field: $value}'.
+ * @param  response    response struct to use
+ * @param  http_status HTTP status code to return
+ * @param  field       name of the json field to return
+ * @param  value       json value to return
+ */
+int send_simple_response(struct _u_response * response, int http_status,
+    const char * field, const char * value)
+{
+    json_t * json_body = NULL;
+    json_body = json_object();
+    json_object_set_new(json_body, field, json_string(value));
+    ulfius_set_json_body_response(response, http_status, json_body);
+    json_decref(json_body);
+    return U_CALLBACK_CONTINUE;
+}
diff --git a/src/cryptops-api.c b/src/cryptops-api.c
new file mode 100644
index 0000000000000000000000000000000000000000..3ae3b6de924276b46f58954bdc81350f604281c5
--- /dev/null
+++ b/src/cryptops-api.c
@@ -0,0 +1,82 @@
+#include <includes/common-includes.h>
+#include <includes/settings.h>
+
+#define FIFO_PATH "/tmp/cryptops-api-stop"
+
+#include <auxiliary.c>
+#include <encryption_functions.c>
+#include <api/default.c>
+#include <api/encryption_unlock.c>
+
+int main(int argc, char ** argv)
+{
+    y_init_logs("cryptops-api", Y_LOG_MODE_CONSOLE, Y_LOG_LEVEL_DEBUG,
+        NULL, "Starting cryptops-api");
+
+    struct _u_instance instance;
+    if (ulfius_init_instance(&instance, PORT, NULL, NULL) != U_OK)
+    {
+        y_log_message(Y_LOG_LEVEL_ERROR, "Error ulfius_init_instance, abort");
+        return(1);
+    }
+
+    u_map_put(instance.default_headers, "Access-Control-Allow-Origin", "*");
+
+    // Maximum body size sent by the client is 1 Kb.
+    instance.max_post_body_size = 1024;
+
+    // Add api endpoints.
+    ulfius_add_endpoint_by_val(&instance, "POST", PREFIX, "/encryption/unlock",
+        0, &callback_encryption_unlock, NULL);
+
+    // Add default endpoint.
+    ulfius_set_default_endpoint(&instance, &callback_default, NULL);
+
+    // Start the framework.
+    int ret;
+    if (argc == 4 && strcmp("-secure", argv[1]) == 0)
+    {
+        // If command-line options are -secure <key_file> <cert_file>,
+        // then listen for https connections.
+        char * key_pem = read_file(argv[2]);
+        char * cert_pem = read_file(argv[3]);
+        ret = ulfius_start_secure_framework(&instance, key_pem, cert_pem);
+        o_free(key_pem);
+        o_free(cert_pem);
+    }
+    else
+    {
+        // Listen for http connections.
+        ret = ulfius_start_framework(&instance);
+    }
+
+    if (ret == U_OK)
+    {
+        y_log_message(Y_LOG_LEVEL_DEBUG, "Start %sframework on port %d",
+            ((argc == 4 && strcmp("-secure", argv[1]) == 0) ? "secure " : ""),
+            instance.port);
+        
+        // Wait for signal from fifo to quit.
+        y_init_logs("cryptops-api", Y_LOG_MODE_CONSOLE, Y_LOG_LEVEL_DEBUG,
+            NULL, "Waiting for fifo signal to quit");
+        int fifo = 0;
+        char buf[4];
+        char fifo_path[] = FIFO_PATH;
+        mkfifo(fifo_path, 0600);
+        fifo = open(fifo_path, O_RDONLY);
+        // This will block until the fifo is written to.
+        read(fifo, &buf, 4);
+    }
+    else
+    {
+        y_log_message(Y_LOG_LEVEL_DEBUG, "Error starting framework");
+    }
+    y_log_message(Y_LOG_LEVEL_DEBUG, "End framework");
+    
+    y_close_logs();
+    
+    ulfius_stop_framework(&instance);
+    ulfius_clean_instance(&instance);
+    
+    return 0;
+}
diff --git a/src/encryption_functions.c b/src/encryption_functions.c
new file mode 100644
index 0000000000000000000000000000000000000000..3f5502d9216c1b3356246ad71f8eea993ffd4473
--- /dev/null
+++ b/src/encryption_functions.c
@@ -0,0 +1,70 @@
+/**
+ * Use cryptsetup to initialise the luks container.
+ * It will not be opened (decrypted) yet, but it does check if the container
+ * seems usable.
+ * @param crypt_device struct to store crypt device context
+ * @param crypt_device path to the encrypted container
+ * @return             status code
+ */
+static int container_initialise(struct crypt_device **cd, const char *path)
+{
+    // Let LUKS initialise the encrypted device.
+    int r = crypt_init(cd, path);
+    if (r < 0)
+    {
+        printf("crypt_init() failed for %s.\n", path);
+        printf("status: %d.\n", r);
+        return r;
+    }
+
+    // Load the LUKS header from the block device into the crypt device context.
+    r = crypt_load(*cd, CRYPT_LUKS1, NULL);
+    if (r < 0)
+    {
+        printf("crypt_load() failed on device %s.\n",
+            crypt_get_device_name(*cd));
+    }
+
+    return r;
+}
+
+/**
+ * Use cryptsetup to unlock the luks container.
+ * This will create `/dev/mapper/$device_name`.
+ * @param path        path to the encrypted container
+ * @param device_name name of the mapping
+ * @param password    encryption password of the container
+ * @return            status code
+ */
+static int encryption_unlock(const char *path, const char *device_name,
+    const char *password)
+{
+    // Let LUKS initialise the encrypted device.
+    struct crypt_device *cd;
+    int r = container_initialise(&cd, path);
+    if (r < 0)
+    {
+        printf("crypt_load() failed on device %s.\n",
+            crypt_get_device_name(cd));
+        crypt_free(cd);
+        return r;
+    }
+
+    // Create device mapping with name device_name.
+    r = crypt_activate_by_passphrase(cd, device_name, CRYPT_ANY_SLOT,
+        password, strlen(password), 0);
+    if (r < 0)
+    {
+        printf("Device %s activation failed.\n", device_name);
+        crypt_free(cd);
+        return r;
+    }
+
+    printf("LUKS device %s/%s is active.\n", crypt_get_dir(), device_name);
+    printf("\tcipher used: %s\n", crypt_get_cipher(cd));
+    printf("\tcipher mode: %s\n", crypt_get_cipher_mode(cd));
+    printf("\tdevice UUID: %s\n", crypt_get_uuid(cd));
+
+    crypt_free(cd);
+    return 0;
+}
diff --git a/src/includes/common-includes.h b/src/includes/common-includes.h
new file mode 100644
index 0000000000000000000000000000000000000000..910cd619c913769648c973216a08fe6ca0fad744
--- /dev/null
+++ b/src/includes/common-includes.h
@@ -0,0 +1,9 @@
+#include <string.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#define U_DISABLE_CURL
+#define U_DISABLE_WEBSOCKET
+#include <ulfius.h>
+#include <jansson.h>
+#include <libcryptsetup.h>
diff --git a/src/includes/settings.h b/src/includes/settings.h
new file mode 100644
index 0000000000000000000000000000000000000000..10122d0d82a84dda308221ff02a8db4c2ef4e71f
--- /dev/null
+++ b/src/includes/settings.h
@@ -0,0 +1,4 @@
+#define PREFIX "/cryptops/v0"
+#define PORT 8000
+#define CONTAINER_DEVICE "/dev/xvda1"
+#define MAPPED_DEVICE_NAME "xvda1_crypt"