Ulfius: src/u_websocket.c File Reference

Ulfius HTTP Framework for REST Applications in C

Loading...
Searching...
No Matches
Macros | Functions
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"`

## 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

## 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

#define STR | ( |  | x | ) | STR_HELPER(x)

## ◆ 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/.

## ◆ U_WEBSOCKET_DEFAULT_MEMORY_LEVEL

#define U_WEBSOCKET_DEFAULT_MEMORY_LEVEL 4

## ◆ U_WEBSOCKET_DEFAULT_WINDOWS_BITS

#define U_WEBSOCKET_DEFAULT_WINDOWS_BITS 15

## Function Documentation

## ◆ ulfius_add_websocket_client_deflate_extension()

int ulfius_add_websocket_client_deflate_extension | ( | struct _websocket_client_handler * | websocket_client_handler | ) |

## ◆ 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(*)(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_out_perform,
|  | void * | websocket_extension_message_out_perform_user_data,
|  | int(*)(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_perform,
|  | void * | websocket_extension_message_in_perform_user_data,
|  | int(*)(const char *extension_server, void *user_data, void **context) | websocket_extension_client_match,
|  | void * | websocket_extension_client_match_user_data,
|  | void(*)(void *user_data, void *context) | websocket_extension_free_context,
|  | void * | websocket_extension_free_context_user_data
| ) |  |

## ◆ ulfius_add_websocket_deflate_extension()

int ulfius_add_websocket_deflate_extension | ( | struct _u_response * | response | ) |

## ◆ 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(*)(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_out_perform,
|  | void * | websocket_extension_message_out_perform_user_data,
|  | int(*)(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_perform,
|  | void * | websocket_extension_message_in_perform_user_data,
|  | int(*)(const char *extension_client, const char **extension_client_list, char **extension_server, void *user_data, void **context) | websocket_extension_server_match,
|  | void * | websocket_extension_server_match_user_data,
|  | void(*)(void *user_data, void *context) | websocket_extension_free_context,
|  | void * | websocket_extension_free_context_user_data
| ) |  |

## ◆ 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_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_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_clear_websocket()

int ulfius_clear_websocket | ( | struct _websocket * | websocket | ) |

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

## ◆ ulfius_clear_websocket_manager()

void ulfius_clear_websocket_manager | ( | struct _websocket_manager * | websocket_manager | ) |

Clear data of a websocket_manager

## ◆ ulfius_clear_websocket_message()

void ulfius_clear_websocket_message | ( | struct _websocket_message * | message | ) |

Clear data of a websocket message

## ◆ 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_close_websocket()

int ulfius_close_websocket | ( | struct _websocket * | websocket | ) |

Close the websocket

## ◆ ulfius_free_websocket_extension()

void ulfius_free_websocket_extension | ( | struct _websocket_extension * | websocket_extension | ) |

## ◆ ulfius_free_websocket_extension_pointer_list()

void ulfius_free_websocket_extension_pointer_list | ( | void * | extension | ) |

Internal websocket functions

## ◆ 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()

int ulfius_init_websocket | ( | struct _websocket * | websocket | ) |

Initialize a struct _websocket return U_OK on success

## ◆ ulfius_init_websocket_extension()

int ulfius_init_websocket_extension | ( | struct _websocket_extension * | websocket_extension | ) |

## ◆ 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_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_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_open_websocket_client_connection()

int ulfius_open_websocket_client_connection | ( | struct _u_request * | request,
|  | void(*)(const struct _u_request *request, struct _websocket_manager *websocket_manager, void *websocket_manager_user_data) | websocket_manager_callback,
|  | void * | websocket_manager_user_data,
|  | void(*)(const struct _u_request *request, struct _websocket_manager *websocket_manager, const struct _websocket_message *message, void *websocket_incoming_user_data) | websocket_incoming_message_callback,
|  | void * | websocket_incoming_user_data,
|  | void(*)(const struct _u_request *request, struct _websocket_manager *websocket_manager, void *websocket_onclose_user_data) | websocket_onclose_callback,
|  | 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

## ◆ 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_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_set_websocket_response()

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

Server websocket functions

## ◆ 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_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_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_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

## ◆ 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_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_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_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_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_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

## ◆ websocket_extension_client_match_deflate()

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

## ◆ websocket_extension_deflate_free_context()

void websocket_extension_deflate_free_context | ( | 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_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_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
| ) |  |