1 /**
2  *
3  * @file ulfius.h
4  * @brief Ulfius framework
5  *
6  * REST framework library
7  *
8  * ulfius.h: public structures and functions declarations
9  *
10  * Copyright 2015-2020 Nicolas Mora <mail@babelouest.org>
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public License
14  * as published by the Free Software Foundation;
15  * version 2.1 of the License.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU GENERAL PUBLIC LICENSE for more details.
21  *
22  * You should have received a copy of the GNU General Public
23  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
24  *
25  */
26 
27 #ifndef __ULFIUS_H__
28 #define __ULFIUS_H__
29 
30 #ifdef __cplusplus
31 extern "C"
32 {
33 #endif
34 
35 #include "ulfius-cfg.h"
36 
37 /** External dependencies **/
38 
39 #ifndef U_DISABLE_GNUTLS
40   #ifndef _GNU_SOURCE
41     #define _GNU_SOURCE
42   #endif
43   #include <gnutls/gnutls.h>
44   #include <gnutls/x509.h>
45 #endif
46 
47 #ifndef U_DISABLE_WEBSOCKET
48   #include <poll.h>
49   #include <zlib.h>
50   #ifndef POLLRDHUP
51     #define POLLRDHUP 0x2000
52   #endif
53 #endif
54 
55 #include <pthread.h>
56 #include <microhttpd.h>
57 
58 #if defined(_WIN32) && !defined(U_DISABLE_WEBSOCKET)
59   #define U_DISABLE_WEBSOCKET
60 #endif
61 
62 #if (MHD_VERSION < 0x00095300) && !defined(U_DISABLE_WEBSOCKET)
63   #define U_DISABLE_WEBSOCKET
64 #endif
65 
66 /** Angharad libraries **/
67 #include <orcania.h>
68 
69 /** To disable all yder log messages, this flag must be enabled **/
70 #ifndef U_DISABLE_YDER
71   #include <yder.h>
72 #else
73 
74 #define Y_LOG_MODE_NONE     0
75 #define Y_LOG_MODE_CONSOLE  0
76 #define Y_LOG_MODE_SYSLOG   0
77 #define Y_LOG_MODE_FILE     0
78 #define Y_LOG_MODE_JOURNALD 0
79 #define Y_LOG_MODE_CALLBACK 0
80 #define Y_LOG_MODE_CURRENT  0
81 
82 #define Y_LOG_LEVEL_NONE    0
83 #define Y_LOG_LEVEL_DEBUG   0
84 #define Y_LOG_LEVEL_INFO    0
85 #define Y_LOG_LEVEL_WARNING 0
86 #define Y_LOG_LEVEL_ERROR   0
87 #define Y_LOG_LEVEL_CURRENT 0
88 
89 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);
90 int y_set_logs_callback(void (* y_callback_log_message) (void * cls, const char * app_name, const time_t date, const unsigned long level, const char * message), void * cls, const char * message);
91 void y_log_message(const unsigned long type, const char * message, ...);
92 int y_close_logs();
93 #endif
94 
95 #ifndef U_DISABLE_JANSSON
96 #include <jansson.h>
97 #endif
98 
99 /**
100  * @defgroup const Constants
101  * @{
102  */
103 
104 #define ULFIUS_STREAM_BLOCK_SIZE_DEFAULT 1024
105 #define U_STREAM_END MHD_CONTENT_READER_END_OF_STREAM
106 #define U_STREAM_ERROR MHD_CONTENT_READER_END_WITH_ERROR
107 #define U_STREAM_SIZE_UNKNOWN MHD_SIZE_UNKNOWN
108 #define U_STREAM_SIZE_UNKOWN U_STREAM_SIZE_UNKNOWN // Backward compatibility
109 
110 #define U_OK                 0 ///< No error
111 #define U_ERROR              1 ///< Error
112 #define U_ERROR_MEMORY       2 ///< Error in memory allocation
113 #define U_ERROR_PARAMS       3 ///< Error in input parameters
114 #define U_ERROR_LIBMHD       4 ///< Error in libmicrohttpd execution
115 #define U_ERROR_LIBCURL      5 ///< Error in libcurl execution
116 #define U_ERROR_NOT_FOUND    6 ///< Something was not found
117 #define U_ERROR_DISCONNECTED 7 ///< Connection closed
118 
119 #define U_CALLBACK_CONTINUE     0 ///< Callback exited with success, continue to next callback
120 #define U_CALLBACK_IGNORE       1 ///< Callback decided to be ignored, request.callback_position will not be incremented, continue to next callback
121 #define U_CALLBACK_COMPLETE     2 ///< Callback exited with success, exit callback list
122 #define U_CALLBACK_UNAUTHORIZED 3 ///< Request is unauthorized, exit callback list and return status 401
123 #define U_CALLBACK_ERROR        4 ///< Error during request process, exit callback list and return status 500
124 
125 #define U_COOKIE_SAME_SITE_NONE   0 ///< Set same_site cookie property to 0
126 #define U_COOKIE_SAME_SITE_STRICT 1 ///< Set same_site cookie property to strict
127 #define U_COOKIE_SAME_SITE_LAX    2 ///< Set same_site cookie property to lax
128 
129 #define U_USE_IPV4 0x0001 ///< Use instance in IPV4 mode only
130 #define U_USE_IPV6 0x0010 ///< Use instance in IPV6 mode only
131 #define U_USE_ALL (U_USE_IPV4|U_USE_IPV6) ///< Use instance in both IPV4 and IPV6 mode
132 
133 #define U_SSL_VERIFY_PEER     0x0001 ///< Verify TLS session with peers
134 #define U_SSL_VERIFY_HOSTNAME 0x0010 ///< Verify TLS session with hostname
135 
136 /**
137  * Options available to set or get properties using
138  * ulfius_set_request_properties or ulfius_set_request_properties
139  */
140 typedef enum {
141   U_OPT_NONE                          = 0, ///< Empty option to complete a ulfius_set_request_properties or ulfius_set_request_properties
142   U_OPT_HTTP_VERB                     = 1, ///< http method (GET, POST, PUT, DELETE, etc.), expected option value type: const char *
143   U_OPT_HTTP_URL                      = 2, ///< full url used to call this callback function or full url to call when used in a ulfius_send_http_request, expected option value type: const char *
144   U_OPT_HTTP_PROXY                    = 3, ///< proxy address to use for outgoing connections, used by ulfius_send_http_request, expected option value type: const char *
145 #if MHD_VERSION >= 0x00095208
146   U_OPT_NETWORK_TYPE                  = 4, ///< Force connect to ipv4, ipv6 addresses or both, values available are U_USE_ALL, U_USE_IPV4 or U_USE_IPV6, expected option value type: unsigned short
147 #endif
148   U_OPT_CHECK_SERVER_CERTIFICATE      = 5, ///< check server certificate and hostname, default true, used by ulfius_send_http_request, expected option value type: int
149   U_OPT_CHECK_SERVER_CERTIFICATE_FLAG = 6, ///< check certificate peer and or server hostname if check_server_certificate is enabled, values available are U_SSL_VERIFY_PEER, U_SSL_VERIFY_HOSTNAME or both, default value is both (U_SSL_VERIFY_PEER|U_SSL_VERIFY_HOSTNAME), used by ulfius_send_http_request, expected option value type: int
150   U_OPT_CHECK_PROXY_CERTIFICATE       = 7, ///< check proxy certificate and hostname, default true, used by ulfius_send_http_request, requires libcurl >= 7.52, expected option value type: int
151   U_OPT_CHECK_PROXY_CERTIFICATE_FLAG  = 8, ///< check certificate peer and or proxy hostname if check_proxy_certificate is enabled, values available are U_SSL_VERIFY_PEER, U_SSL_VERIFY_HOSTNAME or both, default value is both (U_SSL_VERIFY_PEER|U_SSL_VERIFY_HOSTNAME), used by ulfius_send_http_request, requires libcurl >= 7.52, expected option value type: int
152   U_OPT_FOLLOW_REDIRECT               = 9, ///< follow url redirections, used by ulfius_send_http_request, expected option value type: int
153   U_OPT_CA_PATH                       = 10, ///< specify a path to CA certificates instead of system path, used by ulfius_send_http_request, expected option value type: const char *
154   U_OPT_TIMEOUT                       = 11, ///< connection timeout used by ulfius_send_http_request, default is 0 _or_ Timeout in seconds to close the connection because of inactivity between the client and the server, expected option value type: unsigned long
155   U_OPT_AUTH_BASIC_USER               = 12, ///< basic authentication username, expected option value type: const char *
156   U_OPT_AUTH_BASIC_PASSWORD           = 13, ///< basic authentication password, expected option value type: const char *
157   U_OPT_URL_PARAMETER                 = 14, ///< Add to the map containing the url variables, both from the route and the ?key=value variables, expected option value type: const char *, const char *
158   U_OPT_HEADER_PARAMETER              = 15, ///< Add to the map containing the header variables, expected option value type: const char *, const char *
159   U_OPT_COOKIE_PARAMETER              = 16, ///< Add to the map containing the cookie variables, expected option value type: const char *, const char *
160   U_OPT_POST_BODY_PARAMETER           = 17, ///< Add to the map containing the post body variables (if available), expected option value type: const char *, const char *
161   U_OPT_URL_PARAMETER_REMOVE          = 18, ///< Remove from the map containing the url variables, both from the route and the ?key=value variables, expected option value type: const char *
162   U_OPT_HEADER_PARAMETER_REMOVE       = 19, ///< Remove from map containing the header variables, expected option value type: const char *
163   U_OPT_COOKIE_PARAMETER_REMOVE       = 20, ///< Remove from map containing the cookie variables, expected option value type: const char *
164   U_OPT_POST_BODY_PARAMETER_REMOVE    = 21, ///< Remove from map containing the post body variables (if available), expected option value type: const char *
165   U_OPT_BINARY_BODY                   = 22, ///< Set a raw body to the request or the reponse, expected option value type: const char *, size_t
166   U_OPT_STRING_BODY                   = 23, ///< Set a char * body to the request or the reponse, expected option value type: const char *
167 #ifndef U_DISABLE_JANSSON
168   U_OPT_JSON_BODY                     = 24, ///< Set a stringified json_t * body to the request or the reponse, expected option value type: json_t *
169 #endif
170 #ifndef U_DISABLE_GNUTLS
171   U_OPT_CLIENT_CERT_FILE              = 25, ///< path to client certificate file for sending http requests with certificate authentication, available only if GnuTLS support is enabled, expected option value type: const char *
172   U_OPT_CLIENT_KEY_FILE               = 26, ///< path to client key file for sending http requests with certificate authentication, available only if GnuTLS support is enabled, expected option value type: const char *
173   U_OPT_CLIENT_KEY_PASSWORD           = 27, ///< password to unlock client key file, available only if GnuTLS support is enabled, expected option value type: const char *
174 #endif
175   U_OPT_STATUS                        = 28, ///< HTTP response status code (200, 404, 500, etc), expected option value type: long
176   U_OPT_AUTH_REALM                    = 29, ///< realm to send to the client response on authenticationb failed, expected option value type: const char *
177   U_OPT_SHARED_DATA                   = 30, ///< any data shared between callback functions, must be allocated and freed by the callback functions, expected option value type: void *
178   U_OPT_HTTP_URL_APPEND               = 31  ///< append char * value to the current url, expected option value type: const char *
179 } u_option;
180 
181 /**
182  * @}
183  */
184 
185 /*************
186  * Structures
187  *************/
188 
189 /**
190  * @defgroup struct Structures
191  * structures definitions
192  * @{
193  */
194 
195 /**
196  * struct _u_map
197  */
198 struct _u_map {
199   int      nb_values; /* !< Values count */
200   char  ** keys; /* !< Array of keys */
201   char  ** values; /* !< Array of values */
202   size_t * lengths; /* !< Lengths of each values */
203 };
204 
205 /**
206  * struct _u_cookie
207  * the structure containing the response cookie parameters
208  */
209 struct _u_cookie {
210   char * key; /* !< key if the cookie */
211   char * value; /* !< value of the cookie */
212   char * expires; /* !< expiration date of the cookie */
213   unsigned int   max_age; /* !< duration of the cookie in seconds */
214   char * domain; /* !< domain for the cookie */
215   char * path; /* !< url path for the cookie */
216   int    secure; /* !< flag to set cookie secure or not */
217   int    http_only; /* !< flag to set cookie for HTTP connections only or not */
218   int    same_site; /* !< flag to set same_site option to the cookie */
219 };
220 
221 /**
222  *
223  * @struct _u_request
224  * @brief definition of the parameters available in a struct _u_request
225  *
226  */
227 struct _u_request {
228   char *               http_protocol; /* !< http protocol used (1.0 or 1.1) */
229   char *               http_verb; /* !< http method (GET, POST, PUT, DELETE, etc.) */
230   char *               http_url; /* !< full url used to call this callback function or full url to call when used in a ulfius_send_http_request */
231   char *               url_path; /* !< url path only used to call this callback function (ex, if http_url is /path/?param=1, url_path is /path/) */
232   char *               proxy; /* !<proxy address to use for outgoing connections, used by ulfius_send_http_request  */
233 #if MHD_VERSION >= 0x00095208
234   unsigned short       network_type; /* !< Force connect to ipv4, ipv6 addresses or both, values available are U_USE_ALL, U_USE_IPV4 or U_USE_IPV6 */
235 #endif
236   int                  check_server_certificate; /* !< check server certificate and hostname, default true, used by ulfius_send_http_request */
237   int                  check_server_certificate_flag; /* !< check certificate peer and or server hostname if check_server_certificate is enabled, values available are U_SSL_VERIFY_PEER, U_SSL_VERIFY_HOSTNAME or both, default value is both (U_SSL_VERIFY_PEER|U_SSL_VERIFY_HOSTNAME), used by ulfius_send_http_request */
238   int                  check_proxy_certificate; /* !< check proxy certificate and hostname, default true, used by ulfius_send_http_request, requires libcurl >= 7.52 */
239   int                  check_proxy_certificate_flag; /* !< check certificate peer and or proxy hostname if check_proxy_certificate is enabled, values available are U_SSL_VERIFY_PEER, U_SSL_VERIFY_HOSTNAME or both, default value is both (U_SSL_VERIFY_PEER|U_SSL_VERIFY_HOSTNAME), used by ulfius_send_http_request, requires libcurl >= 7.52 */
240   int                  follow_redirect; /* !< follow url redirections, used by ulfius_send_http_request */
241   char *               ca_path; /* !< specify a path to CA certificates instead of system path, used by ulfius_send_http_request */
242   unsigned long        timeout; /* !< connection timeout used by ulfius_send_http_request, default is 0 */
243   struct sockaddr *    client_address; /* !< IP address of the client */
244   char *               auth_basic_user; /* !< basic authentication username */
245   char *               auth_basic_password; /* !< basic authentication password */
246   struct _u_map *      map_url; /* !< map containing the url variables, both from the route and the ?key=value variables */
247   struct _u_map *      map_header; /* !< map containing the header variables */
248   struct _u_map *      map_cookie; /* !< map containing the cookie variables */
249   struct _u_map *      map_post_body; /* !< map containing the post body variables (if available) */
250   void *               binary_body; /* !< raw body */
251   size_t               binary_body_length; /* !< length of raw body */
252   unsigned int         callback_position; /* !< position of the current callback function in the callback list, starts at 0 */
253 #ifndef U_DISABLE_GNUTLS
254   gnutls_x509_crt_t    client_cert; /* !< x509 certificate of the client if the instance uses client certificate authentication and the client is authenticated, available only if GnuTLS support is enabled */
255   char *               client_cert_file; /* !< path to client certificate file for sending http requests with certificate authentication, available only if GnuTLS support is enabled */
256   char *               client_key_file; /* !< path to client key file for sending http requests with certificate authentication, available only if GnuTLS support is enabled */
257   char *               client_key_password; /* !< password to unlock client key file, available only if GnuTLS support is enabled */
258 #endif
259 };
260 
261 /**
262  *
263  * @struct _u_response
264  * @brief definition of the parameters available in a struct _u_response
265  *
266  */
267 struct _u_response {
268   long               status; /* !< HTTP status code (200, 404, 500, etc) */
269   char             * protocol; /* !< HTTP Protocol sent */
270   struct _u_map    * map_header; /* !< map containing the header variables */
271   unsigned int       nb_cookies; /* !< number of cookies sent */
272   struct _u_cookie * map_cookie; /* !< array of cookies sent */
273   char             * auth_realm; /* !< realm to send to the client on authenticationb failed */
274   void             * binary_body; /* !< raw binary content */
275   size_t             binary_body_length; /* !< length of the binary_body */
276   ssize_t         (* stream_callback) (void * stream_user_data, uint64_t offset, char * out_buf, size_t max); /* !< callback function to stream data in response body */
277   void            (* stream_callback_free) (void * stream_user_data); /* !< callback function to free data allocated for streaming */
278   uint64_t           stream_size; /* !< size of the streamed data (U_STREAM_SIZE_UNKNOWN if unknown) */
279   size_t             stream_block_size; /* !< size of each block to be streamed, set according to your system */
280   void             * stream_user_data; /* !< user defined data that will be available in your callback stream functions */
281   void             * websocket_handle; /* !< handle for websocket extension */
282   void *             shared_data; /* !< any data shared between callback functions, must be allocated and freed by the callback functions */
283   void            (* free_shared_data)(void * shared_data); /* !< pointer to a function that will free shared_data */
284   unsigned int       timeout; /* !< Timeout in seconds to close the connection because of inactivity between the client and the server */
285 };
286 
287 /**
288  *
289  * @struct _u_endpoint
290  * @brief Contains all informations needed for an endpoint
291  *
292  */
293 struct _u_endpoint {
294   char       * http_method; /* !< http verb (GET, POST, PUT, etc.) in upper case */
295   char       * url_prefix; /* !< prefix for the url (optional) */
296   char       * 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 */
297   unsigned int priority; /* !< endpoint priority in descending order (0 is the higher priority) */
298   int       (* callback_function)(const struct _u_request * request, /* !< pointer to a function that will be executed each time the endpoint is called, you must declare the function as described. */
299                                   struct _u_response * response,
300                                   void * user_data);
301   void       * user_data; /* !< pointer to a data or a structure that will be available in callback_function */
302 };
303 
304 /**
305  *
306  * @struct _u_instance
307  * @brief Contains the needed data for an ulfius instance to work
308  *
309  */
310 struct _u_instance {
311   struct MHD_Daemon          *  mhd_daemon; /* !< pointer to the libmicrohttpd daemon */
312   int                           status; /* !< status of the current instance, status are U_STATUS_STOP, U_STATUS_RUNNING or U_STATUS_ERROR */
313   unsigned int                  port; /* !< port number to listen to */
314 #if MHD_VERSION >= 0x00095208
315   unsigned short                network_type; /* !< Listen to ipv4 and or ipv6 connections, values available are U_USE_ALL, U_USE_IPV4 or U_USE_IPV6 */
316 #endif
317   struct sockaddr_in          * bind_address; /* !< ipv4 address to listen to (optional) */
318   struct sockaddr_in6         * bind_address6; /* !< ipv6 address to listen to (optional) */
319   unsigned int                  timeout; /* !< Timeout to close the connection because of inactivity between the client and the server */
320   int                           nb_endpoints; /* !< Number of available endpoints */
321   char                        * default_auth_realm; /* !< Default realm on authentication error */
322   struct _u_endpoint          * endpoint_list; /* !< List of available endpoints */
323   struct _u_endpoint          * default_endpoint; /* !< Default endpoint if no other endpoint match the current url */
324   struct _u_map               * default_headers; /* !< Default headers that will be added to all response->map_header */
325   size_t                        max_post_param_size; /* !< maximum size for a post parameter, 0 means no limit, default 0 */
326   size_t                        max_post_body_size; /* !< maximum size for the entire post body, 0 means no limit, default 0 */
327   void                        * websocket_handler; /* !< handler for the websocket structure */
328   int                        (* file_upload_callback) (const struct _u_request * request,  /* !< callback function to manage file upload by blocks */
329                                                        const char * key,
330                                                        const char * filename,
331                                                        const char * content_type,
332                                                        const char * transfer_encoding,
333                                                        const char * data,
334                                                        uint64_t off,
335                                                        size_t size,
336                                                        void * cls);
337   void                        * file_upload_cls; /* !< any pointer to pass to the file_upload_callback function */
338   int                           mhd_response_copy_data; /* !< to choose between MHD_RESPMEM_MUST_COPY and MHD_RESPMEM_MUST_FREE, only if you use MHD < 0.9.61, otherwise this option is skipped because it's useless */
339   int                           check_utf8; /* !< check that all parameters values in the request (url, header and post_body), are valid utf8 strings, if a parameter value has non utf8 character, the value, will be ignored, default 1 */
340 #ifndef U_DISABLE_GNUTLS
341   int                           use_client_cert_auth; /* !< Internal variable use to indicate if the instance uses client certificate authentication, Do not change this value, available only if websocket support is enabled */
342 #endif
343 };
344 
345 /**
346  * @}
347  */
348 
349 /**
350  * Structures used to facilitate data manipulations (internal)
351  */
352 struct connection_info_struct {
353   struct _u_instance       * u_instance;
354   struct MHD_PostProcessor * post_processor;
355   int                        has_post_processor;
356   int                        callback_first_iteration;
357   struct _u_request        * request;
358   size_t                     max_post_param_size;
359   struct _u_map              map_url_initial;
360 };
361 
362 /**********************************
363  * Instance functions declarations
364  **********************************/
365 
366 /**
367  * @defgroup mem memory
368  * memory management function
369  * @{
370  */
371 
372 /**
373  * free data allocated by ulfius functions
374  * @param data data to free
375  */
376 void u_free(void * data);
377 
378 /**
379  * Initialize global parameters
380  * This function isn't thread-safe so it must be called once before any call to
381  * ulfius_send_http_request, ulfius_send_http_streaming_request, ulfius_send_smtp_email or ulfius_send_smtp_rich_email
382  * The function ulfius_send_request_close must be called when ulfius send request functions are no longer needed
383  * @return U_OK on success
384  */
385 int ulfius_global_init();
386 
387 /**
388  * Close global parameters
389  */
390 void ulfius_global_close();
391 
392 /**
393  * @}
394  */
395 
396 /**
397  * @defgroup instance struct _u_instance
398  * struct _u_instance management functions
399  * @{
400  */
401 
402 /**
403  * ulfius_init_instance
404  *
405  * Initialize a struct _u_instance * with default values
406  * Binds to IPV4 addresses only
407  * @param u_instance the ulfius instance to initialize
408  * @param port tcp port to bind to, must be between 1 and 65535
409  * @param bind_address IPv4 address to listen to, optional, the reference is borrowed, the structure isn't copied
410  * @param default_auth_realm default realm to send to the client on authentication error
411  * @return U_OK on success
412  */
413 int ulfius_init_instance(struct _u_instance * u_instance, unsigned int port, struct sockaddr_in * bind_address, const char * default_auth_realm);
414 
415 #if MHD_VERSION >= 0x00095208
416 /**
417  * ulfius_init_instance_ipv6
418  *
419  * Initialize a struct _u_instance * with default values
420  * Binds to IPV6 and IPV4 addresses or IPV6 addresses only
421  * @param port tcp port to bind to, must be between 1 and 65535
422  * @param bind_address IPv6 address to listen to, optional, the reference is borrowed, the structure isn't copied
423  * @param network_type Type of network to listen to, values available are U_USE_IPV6 or U_USE_ALL
424  * @param default_auth_realm default realm to send to the client on authentication error
425  * @return U_OK on success
426  */
427 int ulfius_init_instance_ipv6(struct _u_instance * u_instance, unsigned int port, struct sockaddr_in6 * bind_address, unsigned short network_type, const char * default_auth_realm);
428 #endif
429 
430 /**
431  * ulfius_clean_instance
432  *
433  * Clean memory allocated by a struct _u_instance *
434  * @param u_instance an Ulfius instance
435  */
436 void ulfius_clean_instance(struct _u_instance * u_instance);
437 
438 /**
439  * ulfius_start_framework
440  * Initializes the framework and run the webservice based on the parameters given
441  *
442  * @param u_instance pointer to a struct _u_instance that describe its port and bind address
443  * @return U_OK on success
444  */
445 int ulfius_start_framework(struct _u_instance * u_instance);
446 
447 /**
448  * ulfius_start_secure_framework
449  * Initializes the framework and run the webservice based on the parameters given using an HTTPS connection
450  *
451  * @param u_instance pointer to a struct _u_instance that describe its port and bind address
452  * @param key_pem private key for the server
453  * @param cert_pem server certificate
454  * @return U_OK on success
455  */
456 int ulfius_start_secure_framework(struct _u_instance * u_instance, const char * key_pem, const char * cert_pem);
457 
458 #ifndef U_DISABLE_GNUTLS
459 /**
460  * ulfius_start_secure_ca_trust_framework
461  * Initializes the framework and run the webservice based on the parameters given using an HTTPS connection
462  * And using a root server to authenticate client connections
463  *
464  * @param u_instance pointer to a struct _u_instance that describe its port and bind address
465  * @param key_pem private key for the server
466  * @param cert_pem server certificate
467  * @param root_ca_pem client root CA you're willing to trust for this instance
468  * @return U_OK on success
469  */
470 int ulfius_start_secure_ca_trust_framework(struct _u_instance * u_instance, const char * key_pem, const char * cert_pem, const char * root_ca_pem);
471 #endif
472 
473 /**
474  * ulfius_start_framework_with_mhd_options
475  * Initializes the framework and run the webservice based on the specified MHD options table given in parameter
476  * Read https://www.gnu.org/software/libmicrohttpd/tutorial.html for more information
477  * This is for user who know what they do, Ulfius' options used in other `ulfius_start_framework_*`
478  * are good for most use cases where you need a multi-threaded HTTP webservice
479  * Some struct MHD_OptionItem may cause unexpected problems with Ulfius API
480  * If you find an unresolved issue with this function you can open an issue in GitHub
481  * But some issues may not be solvable if fixing them would break Ulfius API or philosophy
482  * i.e.: you're on your own
483  * @param u_instance pointer to a struct _u_instance that describe its port and bind address
484  * @param mhd_flags OR-ed combination of MHD_FLAG values
485  * @param mhd_ops struct MHD_OptionItem * options table,
486  * - MUST contain an option with the fllowing value: {.option = MHD_OPTION_NOTIFY_COMPLETED; .value = (intptr_t)mhd_request_completed; .ptr_value = NULL;}
487  * - MUST contain an option with the fllowing value: {.option = MHD_OPTION_URI_LOG_CALLBACK; .value = (intptr_t)ulfius_uri_logger; .ptr_value = NULL;}
488  * - MUST end with a terminal struct MHD_OptionItem: {.option = MHD_OPTION_END; .value = 0; .ptr_value = NULL;}
489  * @return U_OK on success
490  */
491 int ulfius_start_framework_with_mhd_options(struct _u_instance * u_instance, unsigned int mhd_flags, struct MHD_OptionItem * options);
492 
493 /**
494  * Internal functions externalized to use ulfius_start_framework_with_mhd_options
495  */
496 void mhd_request_completed (void *cls, struct MHD_Connection *connection, void **con_cls, enum MHD_RequestTerminationCode toe);
497 void * ulfius_uri_logger (void * cls, const char * uri);
498 
499 /**
500  * ulfius_stop_framework
501  *
502  * Stop the webservice
503  * @param u_instance pointer to a struct _u_instance that describe its port and bind address
504  * @return U_OK on success
505  */
506 int ulfius_stop_framework(struct _u_instance * u_instance);
507 
508 /**
509  * ulfius_set_upload_file_callback_function
510  *
511  * Set the callback function to handle file upload
512  * Used to facilitate large files upload management
513  * The callback function file_upload_callback will be called
514  * multiple times, with the uploaded file in striped in parts
515  *
516  * Warning: If this function is used, all the uploaded files
517  * for the instance will be managed via this function, and they
518  * will no longer be available in the struct _u_request in the
519  * ulfius callback function afterwards.
520  *
521  * Thanks to Thad Phetteplace for the help on this feature
522  *
523  * @param u_instance pointer to a struct _u_instance that describe its port and bind address
524  * @param file_upload_callback Pointer to a callback function that will handle all file uploads
525  * @param cls a pointer that will be passed to file_upload_callback each tim it's called
526  * @return U_OK on success
527  */
528 int ulfius_set_upload_file_callback_function(struct _u_instance * u_instance,
529                                              int (* file_upload_callback) (const struct _u_request * request,
530                                                                            const char * key,
531                                                                            const char * filename,
532                                                                            const char * content_type,
533                                                                            const char * transfer_encoding,
534                                                                            const char * data,
535                                                                            uint64_t off,
536                                                                            size_t size,
537                                                                            void * cls),
538                                              void * cls);
539 
540 /**
541  * @}
542  */
543 
544 /**
545  * @defgroup endpoints struct _u_endpoint
546  * struct _u_endpoint management functions
547  * @{
548  */
549 
550 /***********************************
551  * Endpoints functions declarations
552  ***********************************/
553 
554 /**
555  * Add a struct _u_endpoint * to the specified u_instance
556  * Can be done during the execution of the webservice for injection
557  * @param u_instance pointer to a struct _u_instance that describe its port and bind address
558  * @param u_endpoint pointer to a struct _u_endpoint that will be copied in the u_instance endpoint_list
559  * @return U_OK on success
560  */
561 int ulfius_add_endpoint(struct _u_instance * u_instance, const struct _u_endpoint * u_endpoint);
562 
563 /**
564  * Add a struct _u_endpoint * to the specified u_instance with its values specified
565  * Can be done during the execution of the webservice for injection
566  * @param u_instance pointer to a struct _u_instance that describe its port and bind address
567  * @param http_method http verb (GET, POST, PUT, etc.) in upper case
568  * @param url_prefix prefix for the url (optional)
569  * @param url_format string used to define the endpoint format
570  *                    separate words with /
571  *                    to define a variable in the url, prefix it with @ or :
572  *                    example: /test/resource/:name/elements
573  *                    on an url_format that ends with '*', the rest of the url will not be tested
574  * @param priority endpoint priority in descending order (0 is the higher priority)
575  * @param callback_function a pointer to a function that will be executed each time the endpoint is called
576  * you must declare the function as described.
577  * @param user_data a pointer to a data or a structure that will be available in callback_function
578  * @return U_OK on success
579  */
580 int ulfius_add_endpoint_by_val(struct _u_instance * u_instance,
581                                const char * http_method,
582                                const char * url_prefix,
583                                const char * url_format,
584                                unsigned int priority,
585                                int (* callback_function)(const struct _u_request * request, // Input parameters (set by the framework)
586                                                          struct _u_response * response,     // Output parameters (set by the user)
587                                                          void * user_data),
588                                void * user_data);
589 
590 /**
591  * Add a struct _u_endpoint * list to the specified u_instance
592  * Can be done during the execution of the webservice for injection
593  * @param u_instance pointer to a struct _u_instance that describe its port and bind address
594  * @param 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
595  * @return U_OK on success
596  */
597 int ulfius_add_endpoint_list(struct _u_instance * u_instance, const struct _u_endpoint ** u_endpoint_list);
598 
599 /**
600  * Remove a struct _u_endpoint * from the specified u_instance
601  * Can be done during the execution of the webservice for injection
602  * @param u_instance pointer to a struct _u_instance that describe its port and bind address
603  * @param u_endpoint pointer to a struct _u_endpoint that will be removed in the u_instance endpoint_list
604  * The parameters _u_endpoint.http_method, _u_endpoint.url_prefix and _u_endpoint.url_format are strictly compared for the match
605  * If no endpoint is found, return U_ERROR_NOT_FOUND
606  * @return U_OK on success
607  */
608 int ulfius_remove_endpoint(struct _u_instance * u_instance, const struct _u_endpoint * u_endpoint);
609 
610 /**
611  * ulfius_set_default_endpoint
612  * Set the default endpoint
613  * This endpoint will be called if no endpoint match the url called
614  * @param u_instance pointer to a struct _u_instance that describe its port and bind address
615  * @param callback_function a pointer to a function that will be executed each time the endpoint is called
616  * you must declare the function as described.
617  * @param user_data a pointer to a data or a structure that will be available in callback_function
618  * to remove a default endpoint, call ulfius_set_default_endpoint with NULL parameter for callback_function
619  * @return U_OK on success
620  */
621 int ulfius_set_default_endpoint(struct _u_instance * u_instance,
622                                          int (* callback_function)(const struct _u_request * request, struct _u_response * response, void * user_data),
623                                          void * user_data);
624 
625 /**
626  * Remove a struct _u_endpoint * from the specified u_instance
627  * using the specified values used to identify an endpoint
628  * Can be done during the execution of the webservice for injection
629  * The parameters _u_endpoint.http_method, _u_endpoint.url_prefix and _u_endpoint.url_format are strictly compared for the match
630  * If no endpoint is found, return U_ERROR_NOT_FOUND
631  * @param u_instance pointer to a struct _u_instance that describe its port and bind address
632  * @param http_method http_method used by the endpoint
633  * @param url_prefix url_prefix used by the endpoint
634  * @param url_format url_format used by the endpoint
635  * @return U_OK on success
636  */
637 int ulfius_remove_endpoint_by_val(struct _u_instance * u_instance, const char * http_method, const char * url_prefix, const char * url_format);
638 
639 /**
640  * ulfius_empty_endpoint
641  * @return empty endpoint that goes at the end of an endpoint list
642  */
643 const struct _u_endpoint * ulfius_empty_endpoint();
644 
645 /**
646  * ulfius_copy_endpoint
647  * makes a copy of an endpoint with duplicate values
648  * @param dest the endpoint destination
649  * @param source the endpoint source
650  * @return U_OK on success
651  */
652 int ulfius_copy_endpoint(struct _u_endpoint * dest, const struct _u_endpoint * source);
653 
654 /**
655  * u_copy_endpoint_list
656  * makes a copy of an endpoint list with duplicate values
657  * @param endpoint_list an array of struct _u_endpoint * finishing with a ulfius_empty_endpoint()
658  * @return a list with duplicate values
659  * returned value must be free'd after use
660  */
661 struct _u_endpoint * ulfius_duplicate_endpoint_list(const struct _u_endpoint * endpoint_list);
662 
663 /**
664  * ulfius_clean_endpoint
665  * free allocated memory by an endpoint
666  * @param endpoint the endpoint to cleanup
667  */
668 void ulfius_clean_endpoint(struct _u_endpoint * endpoint);
669 
670 /**
671  * ulfius_clean_endpoint_list
672  * free allocated memory by an endpoint list
673  * @param endpoint_list the list of endpoints to cleanup, finishing with a ulfius_empty_endpoint()
674  */
675 void ulfius_clean_endpoint_list(struct _u_endpoint * endpoint_list);
676 
677 /**
678  * ulfius_equals_endpoints
679  * Compare 2 endpoints
680  * @param endpoint1 the first endpoint to compare
681  * @param endpoint2 the second endpoint to compare
682  * @return true if their method, prefix and format are the same or if both are NULL, false otherwise
683  */
684 int ulfius_equals_endpoints(const struct _u_endpoint * endpoint1, const struct _u_endpoint * endpoint2);
685 
686 /**
687  * @}
688  */
689 
690 /**
691  * @defgroup http_smtp_client Client HTTP and SMTP
692  * client HTTP and SMTP requests management functions
693  * @{
694  */
695 
696 #ifndef U_DISABLE_CURL
697 /********************************************
698  * Requests/Responses functions declarations
699  ********************************************/
700 
701 /**
702  * ulfius_send_http_request
703  * Send a HTTP request and store the result into a _u_response
704  * @param request the struct _u_request that contains all the input parameters to perform the HTTP request
705  * @param response the struct _u_response that will be filled with all response parameter values, optional, may be NULL
706  * @return U_OK on success
707  */
708 int ulfius_send_http_request(const struct _u_request * request, struct _u_response * response);
709 
710 /**
711  * ulfius_send_http_streaming_request
712  * Send a HTTP request and store the result into a _u_response
713  * Except for the body which will be available using write_body_function in the write_body_data
714  * @param request the struct _u_request that contains all the input parameters to perform the HTTP request
715  * @param response the struct _u_response that will be filled with all response parameter values, optional, may be NULL
716  * @param write_body_function a pointer to a function that will be used to receive response body in chunks
717  * @param write_body_data a user-defined poitner that will be passed in parameter to write_body_function
718  * @return U_OK on success
719  */
720 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);
721 
722 /**
723  * ulfius_send_smtp_email
724  * Send an email using libcurl
725  * email is plain/text and UTF8 charset
726  * @param host smtp server host name
727  * @param port tcp port number (optional, 0 for default)
728  * @param use_tls true if the connection is tls secured
729  * @param verify_certificate true if you want to disable the certificate verification on a tls server
730  * @param user connection user name (optional, NULL: no user name)
731  * @param password connection password (optional, NULL: no password)
732  * @param from from address (mandatory)
733  * @param to to recipient address (mandatory)
734  * @param cc cc recipient address (optional, NULL: no cc)
735  * @param bcc bcc recipient address (optional, NULL: no bcc)
736  * @param subject email subject (mandatory)
737  * @param mail_body email body (mandatory)
738  * @return U_OK on success
739  */
740 int ulfius_send_smtp_email(const char * host,
741                             const int port,
742                             const int use_tls,
743                             const int verify_certificate,
744                             const char * user,
745                             const char * password,
746                             const char * from,
747                             const char * to,
748                             const char * cc,
749                             const char * bcc,
750                             const char * subject,
751                             const char * mail_body);
752 
753 /**
754  * Send an email using libcurl
755  * email has the content-type specified in parameter
756  * @param host smtp server host name
757  * @param port tcp port number (optional, 0 for default)
758  * @param use_tls true if the connection is tls secured
759  * @param verify_certificate true if you want to disable the certificate verification on a tls server
760  * @param user connection user name (optional, NULL: no user name)
761  * @param password connection password (optional, NULL: no password)
762  * @param from from address (mandatory)
763  * @param to to recipient address (mandatory)
764  * @param cc cc recipient address (optional, NULL: no cc)
765  * @param bcc bcc recipient address (optional, NULL: no bcc)
766  * @param content_type: content-type to add to the e-mail body
767  * @param subject email subject (mandatory)
768  * @param mail_body email body (mandatory)
769  * @return U_OK on success
770  */
771 
772 int ulfius_send_smtp_rich_email(const char * host,
773                                 const int port,
774                                 const int use_tls,
775                                 const int verify_certificate,
776                                 const char * user,
777                                 const char * password,
778                                 const char * from,
779                                 const char * to,
780                                 const char * cc,
781                                 const char * bcc,
782                                 const char * content_type,
783                                 const char * subject,
784                                 const char * mail_body);
785 #endif
786 
787 /**
788  * @}
789  */
790 
791 /**
792  * @defgroup cookie Cookies
793  * Cookies management functions
794  * @{
795  */
796 
797 /**
798  * ulfius_add_cookie_to_response
799  * add a cookie to the cookie map
800  * @param response the response to add the cookie to
801  * @param key the cookie key
802  * @param value the cookie value
803  * @param expires the expiration date of the ccokie in ISO format (optional)
804  * @param max_age the maximum age of the cookie in seconds (optional)
805  * @param domain the domain of the cookie (optional)
806  * @param path the path of the cookie (optional)
807  * @param secure wether the cookie must be secure or not (optional)
808  * @param http_only wether the cookie must be used only for http requests or not (optional)
809  * @return U_OK on success
810  */
811 int ulfius_add_cookie_to_response(struct _u_response * response, const char * key, const char * value, const char * expires, const unsigned int max_age,
812                                   const char * domain, const char * path, const int secure, const int http_only);
813 
814 /**
815  * ulfius_add_same_site_cookie_to_response
816  * add a cookie to the cookie map with a SameSite attribute
817  * @param response the response to add the cookie to
818  * @param key the cookie key
819  * @param value the cookie value
820  * @param expires the expiration date of the ccokie in ISO format (optional)
821  * @param max_age the maximum age of the cookie in seconds (optional)
822  * @param domain the domain of the cookie (optional)
823  * @param path the path of the cookie (optional)
824  * @param secure wether the cookie must be secure or not (optional)
825  * @param http_only wether the cookie must be used only for http requests or not (optional)
826  * @param same_site parameter must have one of the following values:
827  * - U_COOKIE_SAME_SITE_NONE   - No SameSite attribute
828  * - U_COOKIE_SAME_SITE_STRICT - SameSite attribute set to 'Strict'
829  * - U_COOKIE_SAME_SITE_LAX    - SameSite attribute set to 'Lax'
830  * @return U_OK on success
831  */
832 int ulfius_add_same_site_cookie_to_response(struct _u_response * response, const char * key, const char * value, const char * expires, const unsigned int max_age,
833                                             const char * domain, const char * path, const int secure, const int http_only, const int same_site);
834 
835 /**
836  * @}
837  */
838 
839 /**
840  * @defgroup parameters URL, POST and Header parameters
841  * URL, POST and Header management functions
842  * @{
843  */
844 
845 /**
846  * ulfius_add_header_to_response
847  * add a header to the response
848  * @param response the response to be updated
849  * @param key the key of the header
850  * @param value the value of the header
851  * @return U_OK on success
852  */
853 int ulfius_add_header_to_response(struct _u_response * response, const char * key, const char * value);
854 
855 /**
856  * ulfius_set_string_body_request
857  * Set a string string_body to a request, replace any existing body in the request
858  * @param request the request to be updated
859  * @param string_body string to set to the body response must end with a '\0' character
860  * @return U_OK on success
861  */
862 int ulfius_set_string_body_request(struct _u_request * request, const char * string_body);
863 
864 /**
865  * ulfius_set_binary_body_request
866  * Set a binary binary_body to a request, replace any existing body in the request
867  * @param request the request to be updated
868  * @param binary_body an array of char to set to the body response
869  * @param length the length of binary_body to set to the request body
870  * return U_OK on success
871  */
872 int ulfius_set_binary_body_request(struct _u_request * request, const char * binary_body, const size_t length);
873 
874 /**
875  * ulfius_set_empty_body_request
876  * Set an empty request body
877  * @param request the request to be updated
878  * @return U_OK on success
879  */
880 int ulfius_set_empty_body_request(struct _u_request * request);
881 
882 /**
883  * ulfius_set_string_body_response
884  * Add a string body to a response, replace any existing body in the response
885  * @param response the response to be updated
886  * @param status the http status code to set to the response
887  * @param body the string body to set, must end with a '\0' character
888  * @return U_OK on success
889  */
890 int ulfius_set_string_body_response(struct _u_response * response, const unsigned int status, const char * body);
891 
892 /**
893  * ulfius_set_binary_body_response
894  * Add a binary body to a response, replace any existing body in the response
895  * @param response the response to be updated
896  * @param status the http status code to set to the response
897  * @param body the array of char to set
898  * @param length the length of body to set to the request body
899  * @return U_OK on success
900  */
901 int ulfius_set_binary_body_response(struct _u_response * response, const unsigned int status, const char * body, const size_t length);
902 
903 /**
904  * ulfius_set_empty_body_response
905  * Set an empty response with only a status
906  * @param response the response to be updated
907  * @param status the http status code to set to the response
908  * @return U_OK on success
909  */
910 int ulfius_set_empty_body_response(struct _u_response * response, const unsigned int status);
911 
912 /**
913  * @}
914  */
915 
916 /**
917  * @defgroup stream Response streaming
918  * Response streaming function
919  * @{
920  */
921 
922 /**
923  * ulfius_set_stream_response
924  * Set an stream response with a status
925  * @param response the response to be updated
926  * @param status the http status code to set to the response
927  * @param stream_callback a pointer to a function that will handle the response stream
928  * @param stream_callback_free a pointer to a function that will free its allocated resoures during stream_callback
929  * @param stream_size size of the streamed data (U_STREAM_SIZE_UNKNOWN if unknown)
930  * @param stream_block_size preferred size of each stream chunk, may be overwritten by the system if necessary
931  * @param stream_user_data a user-defined pointer that will be available in stream_callback and stream_callback_free
932  * @return U_OK on success
933  */
934 int ulfius_set_stream_response(struct _u_response * response,
935                                 const unsigned int status,
936                                 ssize_t (* stream_callback) (void * stream_user_data, uint64_t offset, char * out_buf, size_t max),
937                                 void (* stream_callback_free) (void * stream_user_data),
938                                 uint64_t stream_size,
939                                 size_t stream_block_size,
940                                 void * stream_user_data);
941 
942 /**
943  * @}
944  */
945 
946 /**
947  * @defgroup request_response_cookie struct _u_request, struct _u_response and struct _u_cookie
948  * struct _u_request, struct _u_response and struct _u_cookie management functions
949  * @{
950  */
951 
952 /**
953  * ulfius_init_request
954  * Initialize a request structure by allocating inner elements
955  * @param request the request to initialize
956  * @return U_OK on success
957  */
958 int ulfius_init_request(struct _u_request * request);
959 
960 /**
961  * ulfius_clean_request
962  * clean the specified request's inner elements
963  * user must free the parent pointer if needed after clean
964  * or use ulfius_clean_request_full
965  * @param request the request to cleanup
966  * @return U_OK on success
967  */
968 int ulfius_clean_request(struct _u_request * request);
969 
970 /**
971  * ulfius_clean_request_full
972  * clean the specified request and all its elements
973  * @param request the request to cleanup
974  * @return U_OK on success
975  */
976 int ulfius_clean_request_full(struct _u_request * request);
977 
978 /**
979  * ulfius_copy_request
980  * Copy the source request elements into the dest request
981  * @param dest the request to receive the copied data
982  * @param source the source request to copy
983  * @return U_OK on success
984  */
985 int ulfius_copy_request(struct _u_request * dest, const struct _u_request * source);
986 
987 /**
988  * ulfius_set_request_properties
989  * Set a list of properties to a request
990  * return U_OK on success
991  */
992 int ulfius_set_request_properties(struct _u_request * request, ...);
993 
994 /**
995  * Initialize a response structure by allocating inner elements
996  * @param response the response to initialize
997  * @return U_OK on success
998  */
999 int ulfius_init_response(struct _u_response * response);
1000 
1001 /**
1002  * ulfius_clean_response
1003  * clean the specified response's inner elements
1004  * user must free the parent pointer if needed after clean
1005  * or use ulfius_clean_response_full
1006  * @param response the response to cleanup
1007  * @return U_OK on success
1008  */
1009 int ulfius_clean_response(struct _u_response * response);
1010 
1011 /**
1012  * clean the specified response and all its elements
1013  * @param response the response to cleanup
1014  * @return U_OK on success
1015  */
1016 int ulfius_clean_response_full(struct _u_response * response);
1017 
1018 /**
1019  * Copy the source response elements into the dest response
1020  * @param dest the response to receive the copied data
1021  * @param source the source response to copy
1022  * @return U_OK on success
1023  */
1024 int ulfius_copy_response(struct _u_response * dest, const struct _u_response * source);
1025 
1026 /**
1027  * ulfius_clean_cookie
1028  * clean the cookie's elements
1029  * @param cookie the cookie structure to cleanup
1030  * @return U_OK on success
1031  */
1032 int ulfius_clean_cookie(struct _u_cookie * cookie);
1033 
1034 /**
1035  * Copy the cookie source elements into dest elements
1036  * @param dest the cookie to receive the copied data
1037  * @param source the cookie response to copy
1038  * @return U_OK on success
1039  */
1040 int ulfius_copy_cookie(struct _u_cookie * dest, const struct _u_cookie * source);
1041 
1042 /**
1043  * create a new request based on the source elements
1044  * returned value must be cleaned after use
1045  * @param request the request to duplicate
1046  * @return a heap-allocated request
1047  */
1048 struct _u_request * ulfius_duplicate_request(const struct _u_request * request);
1049 
1050 /**
1051  * create a new response based on the source elements
1052  * return value must be cleaned after use
1053  * @param response the response to duplicate
1054  * @return a heap-allocated response
1055  */
1056 struct _u_response * ulfius_duplicate_response(const struct _u_response * response);
1057 
1058 /**
1059  * Set a list of properties to a response
1060  * @param response the response to set values to
1061  * @return U_OK on success
1062  */
1063 int ulfius_set_response_properties(struct _u_response * response, ...);
1064 
1065 /**
1066  * Adds a shared_data pointer to the response
1067  * and the function to free the shared_data at the end of the callback list
1068  * @param response the response to set values to
1069  * @param shared_data a pointer that will be transmitted to every callback
1070  * @param free_shared_data a pointer to a function that will free shared_data at the end of the callback list
1071  * @return U_OK on success
1072  */
1073 int ulfius_set_response_shared_data(struct _u_response * response, void * shared_data, void (* free_shared_data) (void * shared_data));
1074 
1075 /**
1076  * @}
1077  */
1078 
1079 /**
1080  * @defgroup url_encode URL Encode
1081  * URL Encode functions
1082  * @{
1083  */
1084 
1085 /**
1086  * Returns a url-decoded version of str
1087  * returned value must be cleaned after use
1088  * Thanks Geek Hideout!
1089  * http://www.geekhideout.com/urlcode.shtml
1090  * @param str the string to decode
1091  * @return a heap-allocated string
1092  */
1093 char * ulfius_url_decode(const char * str);
1094 
1095 /**
1096  * Returns a url-encoded version of str
1097  * returned value must be cleaned after use
1098  * Thanks Geek Hideout!
1099  * http://www.geekhideout.com/urlcode.shtml
1100  * @param str the string to encode
1101  * @return a heap-allocated string
1102  */
1103 char * ulfius_url_encode(const char * str);
1104 
1105 /**
1106  * @}
1107  */
1108 
1109 /**
1110  * @defgroup request_response_cookie struct _u_request, struct _u_response and struct _u_cookie
1111  * struct _u_request, struct _u_response and struct _u_cookie management functions
1112  * @{
1113  */
1114 
1115 #ifndef U_DISABLE_JANSSON
1116 /**
1117  * ulfius_get_json_body_request
1118  * Get JSON structure from the request body if the request is valid
1119  * In case of an error in getting or parsing JSON data in the request,
1120  * the structure json_error_t * json_error will be filled with an error
1121  * message if json_error is not NULL
1122  * @param request the request to retrieve the JSON data
1123  * @param json_error a json_error_t reference that will contain decoding errors if any, may be NULL
1124  * @return a json_t * containing the JSON decoded, NULL on error
1125  */
1126 json_t * ulfius_get_json_body_request(const struct _u_request * request, json_error_t * json_error);
1127 
1128 /**
1129  * ulfius_set_json_body_request
1130  * Add a json_t j_body to a request
1131  * @param request the request to retrieve the JSON data
1132  * @param j_body a json_t to stringify in the body
1133  * @return U_OK on success
1134  */
1135 int ulfius_set_json_body_request(struct _u_request * request, json_t * j_body);
1136 
1137 /**
1138  * ulfius_get_json_body_response
1139  * Get JSON structure from the response body if the response is valid
1140  * In case of an error in getting or parsing JSON data in the response,
1141  * the structure json_error_t * json_error will be filled with an error
1142  * message if json_error is not NULL
1143  * @param response the response to retrieve the JSON data
1144  * @param json_error a json_error_t reference that will contain decoding errors if any, may be NULL
1145  * @return a json_t * containing the JSON decoded, NULL on error
1146  */
1147 json_t * ulfius_get_json_body_response(struct _u_response * response, json_error_t * json_error);
1148 
1149 /**
1150  * ulfius_set_json_body_response
1151  * Add a json_t j_body to a response
1152  * @param response the response to retrieve the JSON data
1153  * @param status the HTTP status for the response
1154  * @param j_body a json_t to stringify in the body
1155  * @return U_OK on success
1156  */
1157 int ulfius_set_json_body_response(struct _u_response * response, const unsigned int status, const json_t * j_body);
1158 #endif
1159 
1160 /**
1161  * @}
1162  */
1163 
1164 /**
1165  * @defgroup u_map struct _u_map
1166  * struct _u_map management functions
1167  * @{
1168  */
1169 
1170 /************************************************************************
1171  * _u_map declarations                                                  *
1172  * _u_map is a simple map structure that handles sets of key/value maps *
1173  ************************************************************************/
1174 
1175 /**
1176  * initialize a struct _u_map
1177  * this function MUST be called after a declaration or allocation
1178  * @param u_map the _u_map to initialize
1179  * @return U_OK on success
1180  */
1181 int u_map_init(struct _u_map * u_map);
1182 
1183 /**
1184  * free the struct _u_map's inner components
1185  * @param u_map the _u_map to cleanup
1186  * @return U_OK on success
1187  */
1188 int u_map_clean(struct _u_map * u_map);
1189 
1190 /**
1191  * free the struct _u_map and its components
1192  * @param u_map the _u_map to cleanup
1193  * @return U_OK on success
1194  */
1195 int u_map_clean_full(struct _u_map * u_map);
1196 
1197 /**
1198  * free an enum return by functions u_map_enum_keys or u_map_enum_values
1199  * @param array the string array to cleanup
1200  * @return U_OK on success
1201  */
1202 int u_map_clean_enum(char ** array);
1203 
1204 /**
1205  * returns an array containing all the keys in the struct _u_map
1206  * @param u_map the _u_map to retreive the keys from
1207  * @return an array of char * ending with a NULL element
1208  */
1209 const char ** u_map_enum_keys(const struct _u_map * u_map);
1210 
1211 /**
1212  * returns an array containing all the values in the struct _u_map
1213  * @param u_map the _u_map to retreive the values from
1214  * @return an array of char * ending with a NULL element
1215  */
1216 const char ** u_map_enum_values(const struct _u_map * u_map);
1217 
1218 /**
1219  * Detects if the key exists in the _u_map
1220  * search is case sensitive
1221  * @param u_map the _u_map to analyze
1222  * @param key the key to look for
1223  * @return true if the sprcified u_map contains the specified key
1224  * false otherwise
1225  */
1226 int u_map_has_key(const struct _u_map * u_map, const char * key);
1227 
1228 /**
1229  * Detects if the value exists in the _u_map, value must be a char * string
1230  * search is case sensitive
1231  * @param u_map the _u_map to analyze
1232  * @param value the value to look for
1233  * @return true if the sprcified u_map contains the specified value
1234  * false otherwise
1235  */
1236 int u_map_has_value(const struct _u_map * u_map, const char * value);
1237 
1238 /**
1239  * Detects if the value exists in the _u_map, value may be any byte array
1240  * search is case sensitive
1241  * @param u_map the _u_map to analyze
1242  * @param value the value to look for
1243  * @param length the length of the value to look for
1244  * @return true if the sprcified u_map contains the specified value up until the specified length
1245  * false otherwise
1246  */
1247 int u_map_has_value_binary(const struct _u_map * u_map, const char * value, size_t length);
1248 
1249 /**
1250  * Detects if the key exists in the _u_map
1251  * search is case insensitive
1252  * @param u_map the _u_map to analyze
1253  * @param key the key to look for
1254  * @return true if the sprcified u_map contains the specified key
1255  * false otherwise
1256  */
1257 int u_map_has_key_case(const struct _u_map * u_map, const char * key);
1258 
1259 /**
1260  * Detects if the key exists in the _u_map
1261  * search is case insensitive
1262  * @param u_map the _u_map to analyze
1263  * @param value the value to look for
1264  * @return true if the sprcified u_map contains the specified value
1265  * false otherwise
1266  */
1267 int u_map_has_value_case(const struct _u_map * u_map, const char * value);
1268 
1269 /**
1270  * add the specified key/value pair into the specified u_map
1271  * if the u_map already contains a pair with the same key, replace the value
1272  * @param u_map the _u_map to update
1273  * @param key the key string
1274  * @param value the value string
1275  * @return U_OK on success
1276  */
1277 int u_map_put(struct _u_map * u_map, const char * key, const char * value);
1278 
1279 /**
1280  * add the specified key/binary value pair into the specified u_map
1281  * if the u_map already contains a pair with the same key,
1282  * replace the value at the specified offset with the specified length
1283  * @param u_map the _u_map to update
1284  * @param key the key string
1285  * @param value the value binary
1286  * @param offset the start offset to set value in u_map value
1287  * @param length the length of value to set
1288  * @return U_OK on success
1289  */
1290 int u_map_put_binary(struct _u_map * u_map, const char * key, const char * value, uint64_t offset, size_t length);
1291 
1292 /**
1293  * get the value length corresponding to the specified key in the u_map
1294  * search is case sensitive
1295  * @param u_map the _u_map to analyze
1296  * @param key the key look for
1297  * @return the value length if found, -1 if no match found
1298  */
1299 ssize_t u_map_get_length(const struct _u_map * u_map, const char * key);
1300 
1301 /**
1302  * get the value length corresponding to the specified key in the u_map
1303  * search is case insensitive
1304  * @param u_map the _u_map to analyze
1305  * @param key the key look for
1306  * @return the value length if found, -1 if no match found
1307  */
1308 ssize_t u_map_get_case_length(const struct _u_map * u_map, const char * key);
1309 
1310 /**
1311  * get the value corresponding to the specified key in the u_map
1312  * search is case sensitive
1313  * @param u_map the _u_map to analyze
1314  * @param key the key to look for
1315  * @return the value if key exists NULL if no match found
1316  */
1317 const char * u_map_get(const struct _u_map * u_map, const char * key);
1318 
1319 /**
1320  * get the value corresponding to the specified key in the u_map
1321  * search is case insensitive
1322  * @param u_map the _u_map to analyze
1323  * @param key the key to look for
1324  * @return the value if key exists NULL if no match found
1325  */
1326 const char * u_map_get_case(const struct _u_map * u_map, const char * key);
1327 
1328 /**
1329  * remove an pair key/value that has the specified key
1330  * search is case sensitive
1331  * @param u_map the _u_map to analyze
1332  * @param key the key to look for
1333  * @return U_OK on success, U_NOT_FOUND if key was not found, error otherwise
1334  */
1335 int u_map_remove_from_key(struct _u_map * u_map, const char * key);
1336 
1337 /**
1338  * remove all pairs key/value that has the specified key (case insensitive search)
1339  * search is case insensitive
1340  * @param u_map the _u_map to analyze
1341  * @param key the key to look for
1342  * @return U_OK on success, U_NOT_FOUND if key was not found, error otherwise
1343  */
1344 int u_map_remove_from_key_case(struct _u_map * u_map, const char * key);
1345 
1346 /**
1347  * remove all pairs key/value that has the specified value
1348  * search is case sensitive
1349  * @param u_map the _u_map to analyze
1350  * @param value the value to look for
1351  * @return U_OK on success, U_NOT_FOUND if key was not found, error otherwise
1352  */
1353 int u_map_remove_from_value(struct _u_map * u_map, const char * value);
1354 
1355 /**
1356  * remove all pairs key/value that has the specified value
1357  * search is case insensitive
1358  * @param u_map the _u_map to analyze
1359  * @param value the value to look for
1360  * @return U_OK on success, U_NOT_FOUND if key was not found, error otherwise
1361  */
1362 int u_map_remove_from_value_case(struct _u_map * u_map, const char * value);
1363 
1364 /**
1365  * remove all pairs key/value that has the specified value up until the specified length
1366  * @param u_map the _u_map to analyze
1367  * @param key the key to look for
1368  * @param length the length of key
1369  * @return U_OK on success, U_NOT_FOUND if key was not found, error otherwise
1370  */
1371 int u_map_remove_from_value_binary(struct _u_map * u_map, const char * key, size_t length);
1372 
1373 /**
1374  * remove the pair key/value at the specified index
1375  * @param u_map the _u_map to analyze
1376  * @param index the position of the tuple to remove
1377  * @return U_OK on success, U_NOT_FOUND if index is out of bound, error otherwise
1378  */
1379 int u_map_remove_at(struct _u_map * u_map, const int index);
1380 
1381 /**
1382  * Create an exact copy of the specified struct _u_map
1383  * @param source the _u_map to copy
1384  * @return a reference to the copy, NULL otherwise
1385  * returned value must be free'd after use
1386  */
1387 struct _u_map * u_map_copy(const struct _u_map * source);
1388 
1389 /**
1390  * Copy all key/values pairs of source into dest
1391  * If a key is already present in dest, value is overwritten
1392  * @param dest the _u_map to update
1393  * @param source the _u_map to copy
1394  * @return U_OK on success, error otherwise
1395  */
1396 int u_map_copy_into(struct _u_map * dest, const struct _u_map * source);
1397 
1398 /**
1399  * Count the number of elements in the _u_map
1400  * @param source the _u_map to analyze
1401  * @return the number of key/values pair in the specified struct _u_map
1402  * Return -1 on error
1403  */
1404 int u_map_count(const struct _u_map * source);
1405 
1406 /**
1407  * Empty a struct u_map of all its elements
1408  * @param u_map the _u_map to empty
1409  * @return U_OK on success, error otherwise
1410  */
1411 int u_map_empty(struct _u_map * u_map);
1412 
1413 /**
1414  * @}
1415  */
1416 
1417 /**
1418  * @defgroup websocket Websockets
1419  * Websocket management functions
1420  * @{
1421  */
1422 
1423 #ifndef U_DISABLE_WEBSOCKET
1424 
1425 /**********************************
1426  * Websocket functions declarations
1427  **********************************/
1428 
1429 #define U_WEBSOCKET_USER_AGENT "Ulfius Websocket Client Framework"
1430 
1431 #define U_WEBSOCKET_MAGIC_STRING     "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
1432 #define U_WEBSOCKET_UPGRADE_VALUE    "websocket"
1433 #define U_WEBSOCKET_BAD_REQUEST_BODY "Error in websocket handshake, wrong parameters"
1434 #define U_WEBSOCKET_USEC_WAIT        50
1435 #define WEBSOCKET_MAX_CLOSE_TRY      10
1436 
1437 #define U_WEBSOCKET_BIT_FIN         0x80
1438 #define U_WEBSOCKET_MASK            0x80
1439 #define U_WEBSOCKET_LEN_MASK        0x7F
1440 #define U_WEBSOCKET_OPCODE_CONTINUE 0x00
1441 #define U_WEBSOCKET_OPCODE_TEXT     0x01
1442 #define U_WEBSOCKET_OPCODE_BINARY   0x02
1443 #define U_WEBSOCKET_OPCODE_CLOSE    0x08
1444 #define U_WEBSOCKET_OPCODE_PING     0x09
1445 #define U_WEBSOCKET_OPCODE_PONG     0x0A
1446 #define U_WEBSOCKET_OPCODE_CLOSED   0xFD
1447 #define U_WEBSOCKET_OPCODE_ERROR    0xFE
1448 #define U_WEBSOCKET_OPCODE_NONE     0xFF
1449 
1450 #define U_WEBSOCKET_NONE   0
1451 #define U_WEBSOCKET_SERVER 1
1452 #define U_WEBSOCKET_CLIENT 2
1453 
1454 #define U_WEBSOCKET_STATUS_OPEN  0
1455 #define U_WEBSOCKET_STATUS_CLOSE 1
1456 #define U_WEBSOCKET_STATUS_ERROR 2
1457 
1458 #define U_WEBSOCKET_RSV1 0x40
1459 #define U_WEBSOCKET_RSV2 0x20
1460 #define U_WEBSOCKET_RSV3 0x10
1461 
1462 #define WEBSOCKET_RESPONSE_HTTP       0x0001
1463 #define WEBSOCKET_RESPONSE_UPGRADE    0x0002
1464 #define WEBSOCKET_RESPONSE_CONNECTION 0x0004
1465 #define WEBSOCKET_RESPONSE_ACCEPT     0x0008
1466 #define WEBSOCKET_RESPONSE_PROTCOL    0x0010
1467 #define WEBSOCKET_RESPONSE_EXTENSION  0x0020
1468 
1469 #define WEBSOCKET_DEFLATE_CHUNK_SIZE 32768
1470 #define WEBSOCKET_DEFLATE_WINDOWS_BITS 15
1471 
1472 #define U_WEBSOCKET_KEEP_NONE      0x00
1473 #define U_WEBSOCKET_KEEP_INCOMING  0x01
1474 #define U_WEBSOCKET_KEEP_OUTCOMING 0x10
1475 
1476 /**
1477  * @struct _websocket_deflate_context websocket extension permessage-deflate context
1478  */
1479 struct _websocket_deflate_context {
1480   z_stream infstream;
1481   z_stream defstream;
1482   int deflate_mask;
1483   int inflate_mask;
1484   uint server_no_context_takeover;
1485   uint client_no_context_takeover;
1486   uint server_max_window_bits;
1487   uint client_max_window_bits;
1488 };
1489 
1490 /**
1491  * @struct _websocket_extension Websocket extension structure
1492  * contains callback functions and context to handle websocket extensions
1493  */
1494 struct _websocket_extension {
1495   char  * extension_server;
1496   char  * extension_client;
1497   uint8_t rsv;
1498   int  (* websocket_extension_message_out_perform)(const uint8_t opcode,
1499                                                    const uint64_t data_len_in,
1500                                                    const char * data_in,
1501                                                    uint64_t * data_len_out,
1502                                                    char ** data_out,
1503                                                    const uint64_t fragment_len,
1504                                                    void * user_data,
1505                                                    void * context);
1506   void  * websocket_extension_message_out_perform_user_data;
1507   int  (* websocket_extension_message_in_perform)(const uint8_t opcode,
1508                                                   const uint64_t data_len_in,
1509                                                   const char * data_in,
1510                                                   uint64_t * data_len_out,
1511                                                   char ** data_out,
1512                                                   const uint64_t fragment_len,
1513                                                   void * user_data,
1514                                                   void * context);
1515   void  * websocket_extension_message_in_perform_user_data;
1516   int  (* websocket_extension_server_match)(const char * extension_client,
1517                                             const char ** extension_client_list,
1518                                             char ** extension_server,
1519                                             void * user_data,
1520                                             void ** context);
1521   void  * websocket_extension_server_match_user_data;
1522   int  (* websocket_extension_client_match)(const char * extension_server,
1523                                             void * user_data,
1524                                             void ** context);
1525   void  * websocket_extension_client_match_user_data;
1526   void (* websocket_extension_free_context)(void * user_data,
1527                                             void * context);
1528   void  * websocket_extension_free_context_user_data;
1529   int     enabled;
1530   void  * context;
1531 };
1532 
1533 /**
1534  * @struct _websocket_manager Websocket manager structure
1535  * contains among other things the socket
1536  * the status (open, closed), and the list of incoming and outcoming messages
1537  * Used on public callback functions
1538  */
1539 struct _websocket_manager {
1540   struct _websocket_message_list * message_list_incoming; /* !< list of incoming messages */
1541   struct _websocket_message_list * message_list_outcoming; /* !< list of outcoming messages */
1542   int                              keep_messages; /* !< keep incoming and/or outcoming messages, flags available are U_WEBSOCKET_KEEP_INCOMING, U_WEBSOCKET_KEEP_OUTCOMING, U_WEBSOCKET_KEEP_NONE, default is U_WEBSOCKET_KEEP_INCOMING|U_WEBSOCKET_KEEP_OUTCOMING */
1543   int                              connected; /* !< flag to know if the websocket is connected or not */
1544   int                              ping_sent; /* !< flag to know if the websocket has sent a ping frame or not, before receiving a pong */
1545   int                              close_flag; /* !< flag to set before closing a websocket */
1546   MHD_socket                       mhd_sock; /* !< reference to libmicrohttpd's socket for websocket server */
1547   int                              tcp_sock; /* !< tcp socket for websocket client */
1548   int                              tls; /* !< set to 1 if the websocket is in a TLS socket */
1549   gnutls_session_t                 gnutls_session; /* !< GnuTLS session for websocket client */
1550   gnutls_certificate_credentials_t xcred; /* !< certificate credential used by GnuTLS */
1551   char                           * protocol; /* !< websocket protocol */
1552   char                           * extensions; /* !< websocket extension */
1553   pthread_mutex_t                  read_lock; /* !< mutex to read data in the socket */
1554   pthread_mutex_t                  write_lock; /* !< mutex to write data in the socket */
1555   pthread_mutex_t                  status_lock; /* !< mutex to broadcast new status */
1556   pthread_cond_t                   status_cond; /* !< condition to broadcast new status */
1557   struct pollfd                    fds_in;
1558   struct pollfd                    fds_out;
1559   int                              type;
1560   int                              rsv_expected;
1561   struct _pointer_list           * websocket_extension_list;
1562 };
1563 
1564 /**
1565  * @struct _websocket_message websocket message structure
1566  * contains all the data of a websocket message
1567  * and the timestamp of when it was sent of received
1568  */
1569 struct _websocket_message {
1570   time_t  datestamp; /* !< date stamp of the message */
1571   uint8_t rsv; /* !< flags RSV1-3 of the message */
1572   uint8_t opcode; /* !< opcode for the message (string or binary) */
1573   uint8_t has_mask; /* !< does the message contain a mask? */
1574   uint8_t mask[4]; /* !< mask used if any */
1575   size_t  data_len; /* !< length of the data */
1576   char *  data; /* !< message data */
1577   size_t  fragment_len; /* !< length of the fragment, 0 if not fragmented */
1578   uint8_t fin;  /* !< flag fin (end of fragmented message) */
1579 };
1580 
1581 /**
1582  * @struct _websocket_message_list List of websocket messages
1583  */
1584 struct _websocket_message_list {
1585   struct _websocket_message ** list; /* !< messages list */
1586   size_t len; /* !< message list length */
1587 };
1588 
1589 /**
1590  * @struct _websocket websocket structure
1591  * contains all the data of the websocket
1592  */
1593 struct _websocket {
1594   struct _u_instance               * instance; /* !< reference to the ulfius instance if any */
1595   struct _u_request                * request; /* !< refrence to the ulfius request of any */
1596   void                             (* websocket_manager_callback) (const struct _u_request * request, /* !< reference to a function called after the websocket handshake */
1597                                                                    struct _websocket_manager * websocket_manager,
1598                                                                    void * websocket_manager_user_data);
1599   void                             * websocket_manager_user_data; /* !< a user-defined reference that will be available in websocket_manager_callback */
1600   void                             (* websocket_incoming_message_callback) (const struct _u_request * request, /* !< reference to a function called each time a message arrives */
1601                                                                             struct _websocket_manager * websocket_manager,
1602                                                                             const struct _websocket_message * message,
1603                                                                             void * websocket_incoming_user_data);
1604   void                             * websocket_incoming_user_data; /* !< a user-defined reference that will be available in websocket_incoming_message_callback */
1605   void                             (* websocket_onclose_callback) (const struct _u_request * request, /* !< reference to a function called after the websocket connection ends */
1606                                                                    struct _websocket_manager * websocket_manager,
1607                                                                    void * websocket_onclose_user_data);
1608   void                             * websocket_onclose_user_data; /* !< a user-defined reference that will be available in websocket_onclose_callback */
1609   struct _websocket_manager        * websocket_manager; /* !< refrence to the websocket manager if any */
1610   struct MHD_UpgradeResponseHandle * urh; /* !< reference used by libmicrohttpd to upgrade the connection */
1611 };
1612 
1613 /**
1614  * @struct _websocket_client_handler Handler for the websocket client, to allow the program to know the status of a websocket client
1615  */
1616 struct _websocket_client_handler {
1617   struct _websocket * websocket; /* !< the websocket to use */
1618   struct _u_response * response; /* !< the response attached to the websocket */
1619 };
1620 
1621 /********************************/
1622 /** Common websocket functions **/
1623 /********************************/
1624 
1625 /**
1626  * Sends a message in the websocket
1627  * @param websocket_manager the websocket manager to use for sending the message
1628  * @param opcode the opcode to use
1629  * values available are U_WEBSOCKET_OPCODE_TEXT, U_WEBSOCKET_OPCODE_BINARY, U_WEBSOCKET_OPCODE_PING, U_WEBSOCKET_OPCODE_PONG, U_WEBSOCKET_OPCODE_CLOSE
1630  * @param data_len the length of the data to send
1631  * @param data the data to send
1632  * @return U_OK on success
1633  */
1634 int ulfius_websocket_send_message(struct _websocket_manager * websocket_manager,
1635                                   const uint8_t opcode,
1636                                   const uint64_t data_len,
1637                                   const char * data);
1638 
1639 /**
1640  * Send a fragmented message in the websocket
1641  * each fragment size will be at most fragment_len
1642  * @param websocket_manager the websocket manager to use for sending the message
1643  * @param opcode the opcode to use
1644  * values available are U_WEBSOCKET_OPCODE_TEXT, U_WEBSOCKET_OPCODE_BINARY, U_WEBSOCKET_OPCODE_PING, U_WEBSOCKET_OPCODE_PONG, U_WEBSOCKET_OPCODE_CLOSE
1645  * @param data_len the length of the data to send
1646  * @param data the data to send
1647  * @param fragment_len the maximum length of each fragment
1648  * @return U_OK on success
1649  */
1650 int ulfius_websocket_send_fragmented_message(struct _websocket_manager * websocket_manager,
1651                                              const uint8_t opcode,
1652                                              const uint64_t data_len,
1653                                              const char * data,
1654                                              const uint64_t fragment_len);
1655 
1656 /**
1657  * Sends a JSON message in the websocket
1658  * @param websocket_manager the websocket manager to use for sending the message
1659  * @param message the message to send
1660  * @return U_OK on success
1661  */
1662 #ifndef U_DISABLE_JANSSON
1663 int ulfius_websocket_send_json_message(struct _websocket_manager * websocket_manager,
1664                                        json_t * message);
1665 #endif
1666 
1667 /**
1668  * Return the first message of the message list
1669  * Return NULL if message_list has no message
1670  * Use it with struct _websocket_manager->message_list_incoming
1671  * or struct _websocket_manager->message_list_outcoming
1672  * @param message_list the list to pop the first message
1673  * @return a _websocket_message reference
1674  * Returned value must be cleared after use
1675  */
1676 struct _websocket_message * ulfius_websocket_pop_first_message(struct _websocket_message_list * message_list);
1677 
1678 /**
1679  * Clear data of a websocket message
1680  * @param message the message to cleanup
1681  */
1682 void ulfius_clear_websocket_message(struct _websocket_message * message);
1683 
1684 /********************************/
1685 /** Server websocket functions **/
1686 /********************************/
1687 
1688 /**
1689  * Set a websocket in the response
1690  * You must set at least websocket_manager_callback or websocket_incoming_message_callback
1691  * @param response struct _u_response to send back the websocket initialization, mandatory
1692  * @param websocket_protocol list of protocols, separated by a comma, or NULL if no protocols are accepted
1693  * @param websocket_extensions list of extensions, separated by a comma, or NULL if no extensions are accepted
1694  * @param websocket_manager_callback callback function called right after the handshake acceptance, optional
1695  * @param websocket_manager_user_data any data that will be given to the websocket_manager_callback, optional
1696  * @param websocket_incoming_message_callback callback function called on each incoming complete message, optional
1697  * @param websocket_incoming_user_data any data that will be given to the websocket_incoming_message_callback, optional
1698  * @param websocket_onclose_callback callback function called right before closing the websocket, must be complete for the websocket to close
1699  * @param websocket_onclose_user_data any data that will be given to the websocket_onclose_callback, optional
1700  * @return U_OK on success
1701  */
1702 int ulfius_set_websocket_response(struct _u_response * response,
1703                                    const char * websocket_protocol,
1704                                    const char * websocket_extensions,
1705                                    void (* websocket_manager_callback) (const struct _u_request * request,
1706                                                                         struct _websocket_manager * websocket_manager,
1707                                                                         void * websocket_manager_user_data),
1708                                    void * websocket_manager_user_data,
1709                                    void (* websocket_incoming_message_callback) (const struct _u_request * request,
1710                                                                                  struct _websocket_manager * websocket_manager,
1711                                                                                  const struct _websocket_message * message,
1712                                                                                  void * websocket_incoming_user_data),
1713                                    void * websocket_incoming_user_data,
1714                                    void (* websocket_onclose_callback) (const struct _u_request * request,
1715                                                                         struct _websocket_manager * websocket_manager,
1716                                                                         void * websocket_onclose_user_data),
1717                                    void * websocket_onclose_user_data);
1718 
1719 /**
1720  * Adds a set of callback functions to perform a message transformation via an extension
1721  * @param response struct _u_response to send back the websocket initialization, mandatory
1722  * @param extension_server the expected extension value
1723  * @param rsv the expected rsv flag attached to this extension
1724  * @param websocket_extension_message_out_perform a callback function called before a message is sent to the server
1725  * @param websocket_extension_message_out_perform_user_data a user-defined pointer passed to websocket_extension_message_out_perform
1726  * @param websocket_extension_message_in_perform a callback function called after a message is received from the server
1727  * @param websocket_extension_message_in_perform_user_data a user-defined pointer passed to websocket_extension_message_in_perform
1728  * @param websocket_extension_server_match a callback function called on handshake response to match an extensions value with the given callback message perform extensions
1729  *        if NULL, then extension_client and the extension sent by the server will be compared for an exact match to enable this extension
1730  * @param websocket_extension_server_match_user_data a user-defined pointer passed to websocket_extension_server_match
1731  * @param websocket_extension_free_context a callback function called during the websocket close to free the context created in websocket_extension_server_match
1732  * @param websocket_extension_free_context_user_data a user-defined pointer passed to websocket_extension_free_context
1733  * @return U_OK on success
1734  */
1735 int ulfius_add_websocket_extension_message_perform(struct _u_response * response,
1736                                                    const char * extension_server,
1737                                                    uint8_t rsv,
1738                                                    int (* websocket_extension_message_out_perform)(const uint8_t opcode,
1739                                                                                                    const uint64_t data_len_in,
1740                                                                                                    const char * data_in,
1741                                                                                                    uint64_t * data_len_out,
1742                                                                                                    char ** data_out,
1743                                                                                                    const uint64_t fragment_len,
1744                                                                                                    void * user_data,
1745                                                                                                    void * context),
1746                                                    void * websocket_extension_message_out_perform_user_data,
1747                                                    int (* websocket_extension_message_in_perform)(const uint8_t opcode,
1748                                                                                                   const uint64_t data_len_in,
1749                                                                                                   const char * data_in,
1750                                                                                                   uint64_t * data_len_out,
1751                                                                                                   char ** data_out,
1752                                                                                                   const uint64_t fragment_len,
1753                                                                                                   void * user_data,
1754                                                                                                   void * context),
1755                                                    void * websocket_extension_message_in_perform_user_data,
1756                                                    int (* websocket_extension_server_match)(const char * extension_client,
1757                                                                                             const char ** extension_client_list,
1758                                                                                             char ** extension_server,
1759                                                                                             void * user_data,
1760                                                                                             void ** context),
1761                                                    void * websocket_extension_server_match_user_data,
1762                                                    void (* websocket_extension_free_context)(void * user_data,
1763                                                                                              void * context),
1764                                                    void  * websocket_extension_free_context_user_data);
1765 
1766 /**
1767  * websocket_extension_message_out_perform used in
1768  * ulfius_add_websocket_deflate_extension and ulfius_add_websocket_client_deflate_extension
1769  * will compress the message in data_in and set the result in *data_out
1770  * @param opcode the opcode of the message to send
1771  * @param data_len_in length of data_in
1772  * @param data_in payload data to transform
1773  * @param data_len_out length of *data_out to be set by the function
1774  * @param data_out result of the transformed data_in
1775  * @param fragment_len fragmentation length of the message
1776  * @param user_data user-defined data
1777  * @param context context of the extension
1778  * @return U_OK on success
1779  */
1780 int websocket_extension_message_out_deflate(const uint8_t opcode,
1781                                             const uint64_t data_len_in,
1782                                             const char * data_in,
1783                                             uint64_t * data_len_out,
1784                                             char ** data_out,
1785                                             const uint64_t fragment_len,
1786                                             void * user_data,
1787                                             void * context);
1788 
1789 /**
1790  * websocket_extension_message_in_perform used in
1791  * ulfius_add_websocket_deflate_extension and ulfius_add_websocket_client_deflate_extension
1792  * @param opcode the opcode of the message to send
1793  * @param data_len_in length of data_in
1794  * @param data_in payload data to transform
1795  * @param data_len_out length of *data_out to be set by the function
1796  * @param data_out result of the transformed data_in
1797  * @param fragment_len fragmentation length of the message
1798  * @param user_data user-defined data
1799  * @param context context of the extension
1800  * @return U_OK on success
1801  */
1802 int websocket_extension_message_in_inflate(const uint8_t opcode,
1803                                            const uint64_t data_len_in,
1804                                            const char * data_in,
1805                                            uint64_t * data_len_out,
1806                                            char ** data_out,
1807                                            const uint64_t fragment_len,
1808                                            void * user_data,
1809                                            void * context);
1810 
1811 /**
1812  * Free deflate extension context
1813  * @param user_data user-defined data
1814  * @param context context of the extension
1815  * @return U_OK on success
1816  */
1817 void websocket_extension_deflate_free_context(void * user_data, void * context);
1818 
1819 /**
1820  * websocket_extension_server_match used in ulfius_add_websocket_deflate_extension
1821  * @param extension_client the extension value to check
1822  * @param extension_client_list the list of all extension_client to match
1823  * @param extension_server the extension value to return to the client
1824  * @param user_data user-defined data
1825  * @param context context to allocate
1826  * @return U_OK on success
1827  */
1828 int websocket_extension_server_match_deflate(const char * extension_client, const char ** extension_client_list, char ** extension_server, void * user_data, void ** context);
1829 
1830 /**
1831  * Adds the required extension message perform to implement message compression according to
1832  * RFC 7692: Compression Extensions for WebSocket
1833  * https://tools.ietf.org/html/rfc7692
1834  * Due to limited implementation, will force response parameters to server_no_context_takeover; client_no_context_takeover
1835  * @param response struct _u_response to send back the websocket initialization, mandatory
1836  * @return U_OK on success
1837  */
1838 int ulfius_add_websocket_deflate_extension(struct _u_response * response);
1839 
1840 /**
1841  * Sets the websocket in closing mode
1842  * The websocket will not necessarily be closed at the return of this function,
1843  * it will process through the end of the `websocket_manager_callback`
1844  * and the `websocket_onclose_callback` calls first.
1845  * This function has no effect if the websocket isn't connected
1846  * @param websocket_manager the _websocket_manager to send close signal to
1847  * @return U_OK on success, U_ERROR on error
1848  */
1849 int ulfius_websocket_send_close_signal(struct _websocket_manager * websocket_manager);
1850 
1851 /**
1852  * Get the websocket status
1853  * @param websocket_manager the _websocket_manager to analyze
1854  * @return the status of the websocket connection
1855  * Returned values can be U_WEBSOCKET_STATUS_OPEN or U_WEBSOCKET_STATUS_CLOSE
1856  * wether the websocket is open or closed, or U_WEBSOCKET_STATUS_ERROR on error
1857  */
1858 int ulfius_websocket_status(struct _websocket_manager * websocket_manager);
1859 
1860 /**
1861  * Wait until the websocket connection is closed or the timeout in milliseconds is reached
1862  * if timeout is 0, no timeout is set
1863  * @param websocket_manager the _websocket_manager to analyze
1864  * @param timeout timeout in milliseconds
1865  * @return U_WEBSOCKET_STATUS_OPEN or U_WEBSOCKET_STATUS_CLOSE
1866  * wether the websocket is open or closed, or U_WEBSOCKET_STATUS_ERROR on error
1867  */
1868 int ulfius_websocket_wait_close(struct _websocket_manager * websocket_manager, unsigned int timeout);
1869 
1870 /********************************/
1871 /** Client websocket functions **/
1872 /********************************/
1873 
1874 /**
1875  * Open a websocket client connection
1876  * @param request the request to use to open the websocket connection
1877  * @param websocket_manager_callback a reference to a function called after the handshake, may be NULL
1878  * @param websocket_manager_user_data a user-defined pointer passed to websocket_manager_callback
1879  * @param websocket_incoming_message_callback a reference to a function called each time a message arrives in the websocket, may be NULL
1880  * @param websocket_incoming_user_data a user-defined pointer passed to websocket_incoming_message_callback
1881  * @param websocket_onclose_callback a reference to a function called after the websocket connection is closed, may be NULL
1882  * @param websocket_onclose_user_data a user-defined pointer passed to websocket_onclose_callback
1883  * @param websocket_client_handler the handler of the websocket
1884  * @param response the response attached with the websocket
1885  * @return U_OK on success
1886  */
1887 int ulfius_open_websocket_client_connection(struct _u_request * request,
1888                                             void (* websocket_manager_callback) (const struct _u_request * request,
1889                                                                                  struct _websocket_manager * websocket_manager,
1890                                                                                  void * websocket_manager_user_data),
1891                                             void * websocket_manager_user_data,
1892                                             void (* websocket_incoming_message_callback) (const struct _u_request * request,
1893                                                                                           struct _websocket_manager * websocket_manager,
1894                                                                                           const struct _websocket_message * message,
1895                                                                                           void * websocket_incoming_user_data),
1896                                             void * websocket_incoming_user_data,
1897                                             void (* websocket_onclose_callback) (const struct _u_request * request,
1898                                                                                  struct _websocket_manager * websocket_manager,
1899                                                                                  void * websocket_onclose_user_data),
1900                                             void * websocket_onclose_user_data,
1901                                             struct _websocket_client_handler * websocket_client_handler,
1902                                             struct _u_response * response);
1903 
1904 /**
1905  * Adds a set of callback functions to perform a message transformation via an extension
1906  * @param websocket_client_handler the handler of the websocket
1907  * @param extension the expected extension value
1908  * @param websocket_extension_message_out_perform a callback function called before a message is sent to the client
1909  * @param websocket_extension_message_out_perform_user_data a user-defined pointer passed to websocket_extension_message_out_perform
1910  * @param websocket_extension_message_in_perform a callback function called after a message is received from the client
1911  * @param websocket_extension_message_in_perform_user_data a user-defined pointer passed to websocket_extension_message_in_perform
1912  * @param websocket_extension_client_match a callback function called on handshake response to match an extensions value with the given callback message perform extensions
1913  * if NULL, then extension and the extension sent by the client will be compared for an exact match to enable this extension
1914  * @param websocket_extension_client_match_user_data a user-defined pointer passed to websocket_extension_client_match
1915  * @param websocket_extension_free_context a callback function called during the websocket close to free the context created in websocket_extension_server_match
1916  * @param websocket_extension_free_context_user_data a user-defined pointer passed to websocket_extension_free_context
1917  * @return U_OK on success
1918  */
1919 int ulfius_add_websocket_client_extension_message_perform(struct _websocket_client_handler * websocket_client_handler,
1920                                                           const char * extension,
1921                                                           uint8_t rsv,
1922                                                           int (* websocket_extension_message_out_perform)(const uint8_t opcode,
1923                                                                                                           const uint64_t data_len_in,
1924                                                                                                           const char * data_in,
1925                                                                                                           uint64_t * data_len_out,
1926                                                                                                           char ** data_out,
1927                                                                                                           const uint64_t fragment_len,
1928                                                                                                           void * user_data,
1929                                                                                                           void * context),
1930                                                           void * websocket_extension_message_out_perform_user_data,
1931                                                           int (* websocket_extension_message_in_perform)(const uint8_t opcode,
1932                                                                                                          const uint64_t data_len_in,
1933                                                                                                          const char * data_in,
1934                                                                                                          uint64_t * data_len_out,
1935                                                                                                          char ** data_out,
1936                                                                                                          const uint64_t fragment_len,
1937                                                                                                          void * user_data,
1938                                                                                                          void * context),
1939                                                           void * websocket_extension_message_in_perform_user_data,
1940                                                           int (* websocket_extension_client_match)(const char * extension_server,
1941                                                                                                    void * user_data,
1942                                                                                                    void ** context),
1943                                                           void * websocket_extension_client_match_user_data,
1944                                                           void (* websocket_extension_free_context)(void * user_data,
1945                                                                                                     void * context),
1946                                                           void  * websocket_extension_free_context_user_data);
1947 
1948 /**
1949  * websocket_extension_client_match used in ulfius_add_websocket_deflate_extension
1950  * @param extension_server the extension value to check
1951  * @param user_data user-defined data
1952  * @param context context to allocate
1953  * @return U_OK on success
1954  */
1955 int websocket_extension_client_match_deflate(const char * extension_server, void * user_data, void ** context);
1956 
1957 /**
1958  * Adds the required extension message perform to implement message compression according to
1959  * RFC 7692: Compression Extensions for WebSocket
1960  * https://tools.ietf.org/html/rfc7692
1961  * @param websocket_client_handler the handler of the websocket
1962  * @return U_OK on success
1963  */
1964 int ulfius_add_websocket_client_deflate_extension(struct _websocket_client_handler * websocket_client_handler);
1965 
1966 /**
1967  * Send a close signal to the websocket
1968  * @param websocket_client_handler the handler to the websocket connection
1969  * @return U_OK when the signal is sent, U_ERROR on error
1970  */
1971 int ulfius_websocket_client_connection_send_close_signal(struct _websocket_client_handler * websocket_client_handler);
1972 
1973 /**
1974  * Closes a websocket client connection
1975  * @param websocket_client_handler the handler to the websocket connection
1976  * @return U_OK when the websocket is closed, U_ERROR on error
1977  */
1978 int ulfius_websocket_client_connection_close(struct _websocket_client_handler * websocket_client_handler);
1979 
1980 /**
1981  * Returns the status of the websocket client connection
1982  * @param websocket_client_handler the handler to the websocket connection
1983  * @return U_WEBSOCKET_STATUS_OPEN or U_WEBSOCKET_STATUS_CLOSE
1984  * wether the websocket is open or closed, or U_WEBSOCKET_STATUS_ERROR on error
1985  */
1986 int ulfius_websocket_client_connection_status(struct _websocket_client_handler * websocket_client_handler);
1987 
1988 /**
1989  * Wait until the websocket client connection is closed or the timeout in milliseconds is reached
1990  * if timeout is 0, no timeout is set
1991  * @param websocket_client_handler the handler to the websocket connection
1992  * @param timeout timeout in milliseconds
1993  * @return U_WEBSOCKET_STATUS_OPEN or U_WEBSOCKET_STATUS_CLOSE
1994  * wether the websocket is open or closed, or U_WEBSOCKET_STATUS_ERROR on error
1995  */
1996 int ulfius_websocket_client_connection_wait_close(struct _websocket_client_handler * websocket_client_handler, unsigned int timeout);
1997 
1998 /**
1999  * Set values for a struct _u_request to open a websocket
2000  * request must be previously initialized
2001  * @param request the request to use to open the websocket
2002  * @param url the url of the websocket service
2003  * @param websocket_protocol the protocol for the websocket, may be NULL
2004  * @param websocket_extensions the extension for the websocket, may be NULL
2005  * @return U_OK on success
2006  */
2007 int ulfius_set_websocket_request(struct _u_request * request,
2008                                  const char * url,
2009                                  const char * websocket_protocol,
2010                                  const char * websocket_extensions);
2011 
2012 #endif
2013 
2014 /** Macro values **/
2015 #define ULFIUS_URL_SEPARATOR       "/"
2016 #define ULFIUS_HTTP_ENCODING_JSON  "application/json"
2017 #define ULFIUS_HTTP_HEADER_CONTENT "Content-Type"
2018 #define ULFIUS_HTTP_NOT_FOUND_BODY "Resource not found"
2019 #define ULFIUS_HTTP_ERROR_BODY     "Server Error"
2020 
2021 #define ULFIUS_COOKIE_ATTRIBUTE_EXPIRES  "Expires"
2022 #define ULFIUS_COOKIE_ATTRIBUTE_MAX_AGE  "Max-Age"
2023 #define ULFIUS_COOKIE_ATTRIBUTE_DOMAIN   "Domain"
2024 #define ULFIUS_COOKIE_ATTRIBUTE_PATH     "Path"
2025 #define ULFIUS_COOKIE_ATTRIBUTE_SECURE   "Secure"
2026 #define ULFIUS_COOKIE_ATTRIBUTE_HTTPONLY "HttpOnly"
2027 
2028 #define ULFIUS_POSTBUFFERSIZE 65536
2029 
2030 #define U_STATUS_STOP     0
2031 #define U_STATUS_RUNNING  1
2032 #define U_STATUS_ERROR    2
2033 
2034 #ifndef U_DISABLE_WEBSOCKET
2035 
2036 /**
2037  * @struct _websocket_handle handle for a websocket
2038  */
2039 struct _websocket_handle {
2040   char                 * websocket_protocol; /* !< protocol for the websocket */
2041   char                 * websocket_extensions; /* !< extensions for the websocket */
2042   void                (* websocket_manager_callback) (const struct _u_request * request, /* !< callback function for working with the websocket */
2043                                                       struct _websocket_manager * websocket_manager,
2044                                                       void * websocket_manager_user_data);
2045   void                 * websocket_manager_user_data; /* !< user-defined data that will be handled to websocket_manager_callback */
2046   void                (* websocket_incoming_message_callback) (const struct _u_request * request, /* !< callback function that will be called every time a message arrives from the client in the websocket */
2047                                                                struct _websocket_manager * websocket_manager,
2048                                                                const struct _websocket_message * message,
2049                                                                void * websocket_incoming_user_data);
2050   void                 * websocket_incoming_user_data; /* !< user-defined data that will be handled to websocket_incoming_message_callback */
2051   void                (* websocket_onclose_callback) (const struct _u_request * request, /* !< callback function that will be called if the websocket is open while the program calls ulfius_stop_framework */
2052                                                       struct _websocket_manager * websocket_manager,
2053                                                       void * websocket_onclose_user_data);
2054   void                 * websocket_onclose_user_data; /* !< user-defined data that will be handled to websocket_onclose_callback */
2055   int                    rsv_expected;
2056   struct _pointer_list * websocket_extension_list;
2057 };
2058 
2059 /**
2060  * @struct _websocket_handler handler for the websockets list
2061  */
2062 struct _websocket_handler {
2063   pthread_mutex_t               websocket_active_lock; /* !< mutex to change nb_websocket_active value */
2064   size_t                        nb_websocket_active; /* !< number of active websocket */
2065   struct _websocket          ** websocket_active; /* !< array of active websocket */
2066   pthread_mutex_t               websocket_close_lock; /* !< mutex to broadcast close signal */
2067   pthread_cond_t                websocket_close_cond; /* !< condition to broadcast close signal */
2068   int                           pthread_init;
2069 };
2070 
2071 #endif // U_DISABLE_WEBSOCKET
2072 
2073 /**
2074  * @}
2075  */
2076 
2077 /**
2078  * @defgroup cert TLS client certificate
2079  * TLS client certificate management functions
2080  * @{
2081  */
2082 
2083 #ifndef U_DISABLE_GNUTLS
2084 /*
2085  * ulfius_export_client_certificate_pem
2086  * Exports the client certificate using PEM format
2087  * @param request struct _u_request used
2088  * @return the certificate in PEM format
2089  * returned value must be u_free'd after use
2090  */
2091 char * ulfius_export_client_certificate_pem(const struct _u_request * request);
2092 
2093 /*
2094  * ulfius_import_client_certificate_pem
2095  * Imports the client certificate using PEM format
2096  * @param request struct _u_request used
2097  * @param str_cert client certificate in PEM format
2098  * @return U_OK on success
2099  */
2100 int ulfius_import_client_certificate_pem(struct _u_request * request, const char * str_cert);
2101 
2102 #endif // U_DISABLE_GNUTLS
2103 
2104 /**
2105  * @}
2106  */
2107 
2108 #ifdef __cplusplus
2109 }
2110 #endif
2111 
2112 #endif // __ULFIUS_H__
2113