Ulfius
HTTP Framework for REST Applications in C
u_websocket.c File Reference
#include <u_private.h>
#include <ulfius.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <gnutls/crypto.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <zlib.h>
#include "yuarel.h"
Include dependency graph for u_websocket.c:

Macros

#define STR_HELPER(x)   #x
 
#define STR(x)   STR_HELPER(x)
 
#define U_WEBSOCKET_DEFAULT_MEMORY_LEVEL   4
 
#define U_WEBSOCKET_DEFAULT_WINDOWS_BITS   15
 
#define U_WEBSOCKET_SEC_KEY_LEN   16
 
#define U_WEBSOCKET_RESPONSE_BUFFER_LEN   4096
 

Functions

void ulfius_free_websocket_extension_pointer_list (void *extension)
 
void ulfius_free_websocket_extension (struct _websocket_extension *websocket_extension)
 
int ulfius_init_websocket_extension (struct _websocket_extension *websocket_extension)
 
void ulfius_start_websocket_cb (void *cls, struct MHD_Connection *connection, void *con_cls, const char *extra_in, size_t extra_in_size, MHD_socket sock, struct MHD_UpgradeResponseHandle *urh)
 
int ulfius_check_handshake_response (const char *key, const char *response)
 
int ulfius_generate_handshake_answer (const char *key, char *out_digest)
 
int ulfius_init_websocket_message_list (struct _websocket_message_list *message_list)
 
int ulfius_push_websocket_message (struct _websocket_message_list *message_list, struct _websocket_message *message)
 
int ulfius_check_list_match (const char *source, const char *match, const char *separator, char **result)
 
int ulfius_check_first_match (const char *source, const char *match, const char *separator, char **result)
 
int ulfius_close_websocket (struct _websocket *websocket)
 
int ulfius_instance_add_websocket_active (struct _u_instance *instance, struct _websocket *websocket)
 
int ulfius_instance_remove_websocket_active (struct _u_instance *instance, struct _websocket *websocket)
 
int ulfius_websocket_send_fragmented_message (struct _websocket_manager *websocket_manager, const uint8_t opcode, const uint64_t data_len, const char *data, const uint64_t fragment_len)
 
int ulfius_websocket_send_message (struct _websocket_manager *websocket_manager, const uint8_t opcode, const uint64_t data_len, const char *data)
 
int ulfius_websocket_send_json_message (struct _websocket_manager *websocket_manager, json_t *j_message)
 
json_t * ulfius_websocket_parse_json_message (const struct _websocket_message *message, json_error_t *json_error)
 
struct _websocket_message * ulfius_websocket_pop_first_message (struct _websocket_message_list *message_list)
 
void ulfius_clear_websocket_message (struct _websocket_message *message)
 
int ulfius_clear_websocket (struct _websocket *websocket)
 
void ulfius_clear_websocket_message_list (struct _websocket_message_list *message_list)
 
int ulfius_init_websocket (struct _websocket *websocket)
 
int ulfius_init_websocket_manager (struct _websocket_manager *websocket_manager)
 
void ulfius_clear_websocket_manager (struct _websocket_manager *websocket_manager)
 
int ulfius_set_websocket_response (struct _u_response *response, const char *websocket_protocol, const char *websocket_extensions, void(*websocket_manager_callback)(const struct _u_request *request, struct _websocket_manager *websocket_manager, void *websocket_manager_user_data), void *websocket_manager_user_data, void(*websocket_incoming_message_callback)(const struct _u_request *request, struct _websocket_manager *websocket_manager, const struct _websocket_message *message, void *websocket_incoming_user_data), void *websocket_incoming_user_data, void(*websocket_onclose_callback)(const struct _u_request *request, struct _websocket_manager *websocket_manager, void *websocket_onclose_user_data), void *websocket_onclose_user_data)
 
int ulfius_add_websocket_extension_message_perform (struct _u_response *response, const char *extension_server, uint8_t rsv, int(*websocket_extension_message_out_perform)(const uint8_t opcode, const uint64_t data_len_in, const char *data_in, uint64_t *data_len_out, char **data_out, const uint64_t fragment_len, void *user_data, void *context), void *websocket_extension_message_out_perform_user_data, int(*websocket_extension_message_in_perform)(const uint8_t opcode, const uint64_t data_len_in, const char *data_in, uint64_t *data_len_out, char **data_out, const uint64_t fragment_len, void *user_data, void *context), void *websocket_extension_message_in_perform_user_data, int(*websocket_extension_server_match)(const char *extension_client, const char **extension_client_list, char **extension_server, void *user_data, void **context), void *websocket_extension_server_match_user_data, void(*websocket_extension_free_context)(void *user_data, void *context), void *websocket_extension_free_context_user_data)
 
int websocket_extension_message_out_deflate (const uint8_t opcode, const uint64_t data_len_in, const char *data_in, uint64_t *data_len_out, char **data_out, const uint64_t fragment_len, void *user_data, void *context)
 
int websocket_extension_message_in_inflate (const uint8_t opcode, const uint64_t data_len_in, const char *data_in, uint64_t *data_len_out, char **data_out, const uint64_t fragment_len, void *user_data, void *context)
 
int websocket_extension_server_match_deflate (const char *extension_client, const char **extension_client_list, char **extension_server, void *user_data, void **context)
 
void websocket_extension_deflate_free_context (void *user_data, void *context)
 
int ulfius_add_websocket_deflate_extension (struct _u_response *response)
 
int ulfius_websocket_send_close_signal (struct _websocket_manager *websocket_manager)
 
int ulfius_websocket_status (struct _websocket_manager *websocket_manager)
 
int ulfius_websocket_wait_close (struct _websocket_manager *websocket_manager, unsigned int timeout)
 
int ulfius_set_websocket_request (struct _u_request *request, const char *url, const char *websocket_protocol, const char *websocket_extensions)
 
int ulfius_add_websocket_client_extension_message_perform (struct _websocket_client_handler *websocket_client_handler, const char *extension, uint8_t rsv, int(*websocket_extension_message_out_perform)(const uint8_t opcode, const uint64_t data_len_in, const char *data_in, uint64_t *data_len_out, char **data_out, const uint64_t fragment_len, void *user_data, void *context), void *websocket_extension_message_out_perform_user_data, int(*websocket_extension_message_in_perform)(const uint8_t opcode, const uint64_t data_len_in, const char *data_in, uint64_t *data_len_out, char **data_out, const uint64_t fragment_len, void *user_data, void *context), void *websocket_extension_message_in_perform_user_data, int(*websocket_extension_client_match)(const char *extension_server, void *user_data, void **context), void *websocket_extension_client_match_user_data, void(*websocket_extension_free_context)(void *user_data, void *context), void *websocket_extension_free_context_user_data)
 
int ulfius_open_websocket_client_connection (struct _u_request *request, void(*websocket_manager_callback)(const struct _u_request *request, struct _websocket_manager *websocket_manager, void *websocket_manager_user_data), void *websocket_manager_user_data, void(*websocket_incoming_message_callback)(const struct _u_request *request, struct _websocket_manager *websocket_manager, const struct _websocket_message *message, void *websocket_incoming_user_data), void *websocket_incoming_user_data, void(*websocket_onclose_callback)(const struct _u_request *request, struct _websocket_manager *websocket_manager, void *websocket_onclose_user_data), void *websocket_onclose_user_data, struct _websocket_client_handler *websocket_client_handler, struct _u_response *response)
 
int websocket_extension_client_match_deflate (const char *extension_server, void *user_data, void **context)
 
int ulfius_add_websocket_client_deflate_extension (struct _websocket_client_handler *websocket_client_handler)
 
int ulfius_websocket_client_connection_send_close_signal (struct _websocket_client_handler *websocket_client_handler)
 
int ulfius_websocket_client_connection_close (struct _websocket_client_handler *websocket_client_handler)
 
int ulfius_websocket_client_connection_status (struct _websocket_client_handler *websocket_client_handler)
 
int ulfius_websocket_client_connection_wait_close (struct _websocket_client_handler *websocket_client_handler, unsigned int timeout)
 

Macro Definition Documentation

◆ STR_HELPER

#define STR_HELPER ( x)    #x

Ulfius Framework

REST framework library

u_websocket.c: websocket implementation

Copyright 2017-2022 Nicolas Mora mail@.nosp@m.babe.nosp@m.loues.nosp@m.t.or.nosp@m.g

This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; version 2.1 of the License.

This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU GENERAL PUBLIC LICENSE for more details.

You should have received a copy of the GNU General Public License along with this library. If not, see http://www.gnu.org/licenses/.

◆ STR

#define STR ( x)    STR_HELPER(x)

◆ U_WEBSOCKET_DEFAULT_MEMORY_LEVEL

#define U_WEBSOCKET_DEFAULT_MEMORY_LEVEL   4

◆ U_WEBSOCKET_DEFAULT_WINDOWS_BITS

#define U_WEBSOCKET_DEFAULT_WINDOWS_BITS   15

◆ U_WEBSOCKET_SEC_KEY_LEN

#define U_WEBSOCKET_SEC_KEY_LEN   16

◆ U_WEBSOCKET_RESPONSE_BUFFER_LEN

#define U_WEBSOCKET_RESPONSE_BUFFER_LEN   4096

Function Documentation

◆ ulfius_free_websocket_extension_pointer_list()

void ulfius_free_websocket_extension_pointer_list ( void * extension)

Internal websocket functions

◆ ulfius_free_websocket_extension()

void ulfius_free_websocket_extension ( struct _websocket_extension * websocket_extension)

◆ ulfius_init_websocket_extension()

int ulfius_init_websocket_extension ( struct _websocket_extension * websocket_extension)

◆ ulfius_start_websocket_cb()

void ulfius_start_websocket_cb ( void * cls,
struct MHD_Connection * connection,
void * con_cls,
const char * extra_in,
size_t extra_in_size,
MHD_socket sock,
struct MHD_UpgradeResponseHandle * urh )

Websocket callback function for MHD Starts the websocket manager if set,

◆ ulfius_check_handshake_response()

int ulfius_check_handshake_response ( const char * key,
const char * response )

Check if the response corresponds to the transformation of the key with the magic string

◆ ulfius_generate_handshake_answer()

int ulfius_generate_handshake_answer ( const char * key,
char * out_digest )

Generates a handhshake answer from the key given in parameter

◆ ulfius_init_websocket_message_list()

int ulfius_init_websocket_message_list ( struct _websocket_message_list * message_list)

Initialize a websocket message list Return U_OK on success

◆ ulfius_push_websocket_message()

int ulfius_push_websocket_message ( struct _websocket_message_list * message_list,
struct _websocket_message * message )

Append a message in a message list Return U_OK on success

◆ ulfius_check_list_match()

int ulfius_check_list_match ( const char * source,
const char * match,
const char * separator,
char ** result )

Return a match list between two list of items If match is NULL, then result will be NULL and returned value will be U_OK *result value must be u_free'd after use

◆ ulfius_check_first_match()

int ulfius_check_first_match ( const char * source,
const char * match,
const char * separator,
char ** result )

Return the first match between two list of items If match is NULL, then return the first element of source Returned value must be u_free'd after use

◆ ulfius_close_websocket()

int ulfius_close_websocket ( struct _websocket * websocket)

Close the websocket

◆ ulfius_instance_add_websocket_active()

int ulfius_instance_add_websocket_active ( struct _u_instance * instance,
struct _websocket * websocket )

Add a websocket in the list of active websockets of the instance

◆ ulfius_instance_remove_websocket_active()

int ulfius_instance_remove_websocket_active ( struct _u_instance * instance,
struct _websocket * websocket )

Remove a websocket from the list of active websockets of the instance

◆ ulfius_websocket_send_fragmented_message()

int ulfius_websocket_send_fragmented_message ( struct _websocket_manager * websocket_manager,
const uint8_t opcode,
const uint64_t data_len,
const char * data,
const uint64_t fragment_len )

Common websocket functions Send a fragmented message in the websocket each fragment size will be at most fragment_len Return U_OK on success

◆ ulfius_websocket_send_message()

int ulfius_websocket_send_message ( struct _websocket_manager * websocket_manager,
const uint8_t opcode,
const uint64_t data_len,
const char * data )

Send a message in the websocket Return U_OK on success

◆ ulfius_websocket_send_json_message()

int ulfius_websocket_send_json_message ( struct _websocket_manager * websocket_manager,
json_t * j_message )

Send a JSON message in the websocket Return U_OK on success

◆ ulfius_websocket_parse_json_message()

json_t * ulfius_websocket_parse_json_message ( const struct _websocket_message * message,
json_error_t * json_error )

Parses a websocket message into a JSON object if possible

◆ ulfius_websocket_pop_first_message()

struct _websocket_message * ulfius_websocket_pop_first_message ( struct _websocket_message_list * message_list)

Return the first message of the message list Return NULL if message_list has no message Returned value must be cleared after use

◆ ulfius_clear_websocket_message()

void ulfius_clear_websocket_message ( struct _websocket_message * message)

Clear data of a websocket message

◆ ulfius_clear_websocket()

int ulfius_clear_websocket ( struct _websocket * websocket)

Init/clear websocket functions Clear all data related to the websocket

◆ ulfius_clear_websocket_message_list()

void ulfius_clear_websocket_message_list ( struct _websocket_message_list * message_list)

Clear data of a websocket message list

◆ ulfius_init_websocket()

int ulfius_init_websocket ( struct _websocket * websocket)

Initialize a struct _websocket return U_OK on success

◆ ulfius_init_websocket_manager()

int ulfius_init_websocket_manager ( struct _websocket_manager * websocket_manager)

Initialize a struct _websocket_manager return U_OK on success

◆ ulfius_clear_websocket_manager()

void ulfius_clear_websocket_manager ( struct _websocket_manager * websocket_manager)

Clear data of a websocket_manager

◆ ulfius_set_websocket_response()

int ulfius_set_websocket_response ( struct _u_response * response,
const char * websocket_protocol,
const char * websocket_extensions,
void(* websocket_manager_callback )(const struct _u_request *request, struct _websocket_manager *websocket_manager, void *websocket_manager_user_data),
void * websocket_manager_user_data,
void(* websocket_incoming_message_callback )(const struct _u_request *request, struct _websocket_manager *websocket_manager, const struct _websocket_message *message, void *websocket_incoming_user_data),
void * websocket_incoming_user_data,
void(* websocket_onclose_callback )(const struct _u_request *request, struct _websocket_manager *websocket_manager, void *websocket_onclose_user_data),
void * websocket_onclose_user_data )

Server websocket functions

◆ ulfius_add_websocket_extension_message_perform()

int ulfius_add_websocket_extension_message_perform ( struct _u_response * response,
const char * extension_server,
uint8_t rsv,
int(* websocket_extension_message_out_perform )(const uint8_t opcode, const uint64_t data_len_in, const char *data_in, uint64_t *data_len_out, char **data_out, const uint64_t fragment_len, void *user_data, void *context),
void * websocket_extension_message_out_perform_user_data,
int(* websocket_extension_message_in_perform )(const uint8_t opcode, const uint64_t data_len_in, const char *data_in, uint64_t *data_len_out, char **data_out, const uint64_t fragment_len, void *user_data, void *context),
void * websocket_extension_message_in_perform_user_data,
int(* websocket_extension_server_match )(const char *extension_client, const char **extension_client_list, char **extension_server, void *user_data, void **context),
void * websocket_extension_server_match_user_data,
void(* websocket_extension_free_context )(void *user_data, void *context),
void * websocket_extension_free_context_user_data )

◆ websocket_extension_message_out_deflate()

int websocket_extension_message_out_deflate ( const uint8_t opcode,
const uint64_t data_len_in,
const char * data_in,
uint64_t * data_len_out,
char ** data_out,
const uint64_t fragment_len,
void * user_data,
void * context )

◆ websocket_extension_message_in_inflate()

int websocket_extension_message_in_inflate ( const uint8_t opcode,
const uint64_t data_len_in,
const char * data_in,
uint64_t * data_len_out,
char ** data_out,
const uint64_t fragment_len,
void * user_data,
void * context )

◆ websocket_extension_server_match_deflate()

int websocket_extension_server_match_deflate ( const char * extension_client,
const char ** extension_client_list,
char ** extension_server,
void * user_data,
void ** context )

◆ websocket_extension_deflate_free_context()

void websocket_extension_deflate_free_context ( void * user_data,
void * context )

◆ ulfius_add_websocket_deflate_extension()

int ulfius_add_websocket_deflate_extension ( struct _u_response * response)

◆ ulfius_websocket_send_close_signal()

int ulfius_websocket_send_close_signal ( struct _websocket_manager * websocket_manager)

Sets the websocket in closing mode The websocket will not necessarily be closed at the return of this function, it will process through the end of the websocket_manager_callback and the websocket_onclose_callback calls first. return U_OK on success or U_ERROR on error

◆ ulfius_websocket_status()

int ulfius_websocket_status ( struct _websocket_manager * websocket_manager)

Returns the status of the websocket connection Returned values can be U_WEBSOCKET_STATUS_OPEN or U_WEBSOCKET_STATUS_CLOSE wether the websocket is open or closed, or U_WEBSOCKET_STATUS_ERROR on error

◆ ulfius_websocket_wait_close()

int ulfius_websocket_wait_close ( struct _websocket_manager * websocket_manager,
unsigned int timeout )

Wait until the websocket connection is closed or the timeout in milliseconds is reached if timeout is 0, no timeout is set Returned values can be U_WEBSOCKET_STATUS_OPEN or U_WEBSOCKET_STATUS_CLOSE wether the websocket is open or closed, or U_WEBSOCKET_STATUS_ERROR on error

◆ ulfius_set_websocket_request()

int ulfius_set_websocket_request ( struct _u_request * request,
const char * url,
const char * websocket_protocol,
const char * websocket_extensions )

Set values for a struct _u_request to open a websocket request must be previously initialized Return U_OK on success

◆ ulfius_add_websocket_client_extension_message_perform()

int ulfius_add_websocket_client_extension_message_perform ( struct _websocket_client_handler * websocket_client_handler,
const char * extension,
uint8_t rsv,
int(* websocket_extension_message_out_perform )(const uint8_t opcode, const uint64_t data_len_in, const char *data_in, uint64_t *data_len_out, char **data_out, const uint64_t fragment_len, void *user_data, void *context),
void * websocket_extension_message_out_perform_user_data,
int(* websocket_extension_message_in_perform )(const uint8_t opcode, const uint64_t data_len_in, const char *data_in, uint64_t *data_len_out, char **data_out, const uint64_t fragment_len, void *user_data, void *context),
void * websocket_extension_message_in_perform_user_data,
int(* websocket_extension_client_match )(const char *extension_server, void *user_data, void **context),
void * websocket_extension_client_match_user_data,
void(* websocket_extension_free_context )(void *user_data, void *context),
void * websocket_extension_free_context_user_data )

◆ ulfius_open_websocket_client_connection()

int ulfius_open_websocket_client_connection ( struct _u_request * request,
void(* websocket_manager_callback )(const struct _u_request *request, struct _websocket_manager *websocket_manager, void *websocket_manager_user_data),
void * websocket_manager_user_data,
void(* websocket_incoming_message_callback )(const struct _u_request *request, struct _websocket_manager *websocket_manager, const struct _websocket_message *message, void *websocket_incoming_user_data),
void * websocket_incoming_user_data,
void(* websocket_onclose_callback )(const struct _u_request *request, struct _websocket_manager *websocket_manager, void *websocket_onclose_user_data),
void * websocket_onclose_user_data,
struct _websocket_client_handler * websocket_client_handler,
struct _u_response * response )

Open a websocket client connection Return U_OK on success

◆ websocket_extension_client_match_deflate()

int websocket_extension_client_match_deflate ( const char * extension_server,
void * user_data,
void ** context )

◆ ulfius_add_websocket_client_deflate_extension()

int ulfius_add_websocket_client_deflate_extension ( struct _websocket_client_handler * websocket_client_handler)

◆ ulfius_websocket_client_connection_send_close_signal()

int ulfius_websocket_client_connection_send_close_signal ( struct _websocket_client_handler * websocket_client_handler)

Send a close signal to the websocket return U_OK when the signal is sent or U_ERROR on error

◆ ulfius_websocket_client_connection_close()

int ulfius_websocket_client_connection_close ( struct _websocket_client_handler * websocket_client_handler)

Closes a websocket client connection return U_OK when the websocket is closed or U_ERROR on error

◆ ulfius_websocket_client_connection_status()

int ulfius_websocket_client_connection_status ( struct _websocket_client_handler * websocket_client_handler)

Returns the status of the websocket client connection Returned values can be U_WEBSOCKET_STATUS_OPEN or U_WEBSOCKET_STATUS_CLOSE wether the websocket is open or closed, or U_WEBSOCKET_STATUS_ERROR on error

◆ ulfius_websocket_client_connection_wait_close()

int ulfius_websocket_client_connection_wait_close ( struct _websocket_client_handler * websocket_client_handler,
unsigned int timeout )

Wait until the websocket client connection is closed or the timeout in milliseconds is reached if timeout is 0, no timeout is set Returned values can be U_WEBSOCKET_STATUS_OPEN or U_WEBSOCKET_STATUS_CLOSE wether the websocket is open or closed, or U_WEBSOCKET_STATUS_ERROR on error