wsServer main routines. More...
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
#include <utf8.h>
#include <ws.h>
Classes | |
struct | ws_cli_conn_t |
Client socks. More... | |
struct | ws_frame_data |
WebSocket frame data. More... | |
struct | frame_state_data |
Frame state data. More... | |
struct | ws_accept_params |
Accept parameters. More... | |
Macros | |
#define | _POSIX_C_SOURCE 200809L |
#define | MSG_NOSIGNAL 0 |
#define | CLIENT_VALID(cli) |
Client validity macro. More... | |
#define | panic(s) |
Issues an error message and aborts the program. More... | |
Functions | |
void * | ws_get_server_context (ws_cli_conn_t *cli) |
Get server context. More... | |
void | ws_set_connection_context (ws_cli_conn_t *cli, void *ptr) |
Set connection context. More... | |
void * | ws_get_connection_context (ws_cli_conn_t *cli) |
Get connection context. More... | |
static void | close_socket (int fd) |
Shutdown and close a given socket. More... | |
static int | get_client_state (ws_cli_conn_t *client) |
Returns the current client state for a given client client . More... | |
static int | set_client_state (ws_cli_conn_t *client, int state) |
Set a state state to the client index client . More... | |
static ssize_t | send_all (ws_cli_conn_t *client, const void *buf, size_t len, int flags) |
Send a given message buf on a socket sockfd . More... | |
static void | close_client (ws_cli_conn_t *client, int lock) |
Close client connection (no close handshake, this should be done earlier), set appropriate state and destroy mutexes. More... | |
static void * | close_timeout (void *p) |
Close time-out thread. More... | |
static int | start_close_timeout (ws_cli_conn_t *client) |
For a valid client index client , starts the timeout thread and set the current state to 'CLOSING'. More... | |
static void | set_client_address (ws_cli_conn_t *client) |
Sets the IP address relative to a client connection opened by the server and save inside the client structure. More... | |
char * | ws_getaddress (ws_cli_conn_t *client) |
Gets the IP address relative to a client connection opened by the server. More... | |
char * | ws_getport (ws_cli_conn_t *client) |
Gets the IP port relative to a client connection opened by the server. More... | |
static int | ws_sendframe_internal (ws_cli_conn_t *client, const char *msg, uint64_t size, int type, uint16_t port) |
Creates and send an WebSocket frame with some payload data. More... | |
int | ws_sendframe (ws_cli_conn_t *client, const char *msg, uint64_t size, int type) |
Send an WebSocket frame with some payload data. More... | |
int | ws_sendframe_bcast (uint16_t port, const char *msg, uint64_t size, int type) |
Send an WebSocket frame with some payload data to all clients connected into the same port. More... | |
static int32_t | pong_msg_to_int32 (uint8_t *msg) |
Given a PONG message, decodes the content as a int32_t number that corresponds to our PONG id. More... | |
static void | int32_to_ping_msg (int32_t ping_id, uint8_t *msg) |
Given a PING id, encodes the content to be sent as payload of a PING frame. More... | |
static void | send_ping_close (ws_cli_conn_t *cli, int threshold, int lock) |
Send a ping message and close if the client surpasses the threshold imposed. More... | |
void | ws_ping (ws_cli_conn_t *cli, int threshold) |
Sends a PING frame to the client cli with threshold threshold . More... | |
int | ws_sendframe_txt (ws_cli_conn_t *client, const char *msg) |
Sends a WebSocket text frame. More... | |
int | ws_sendframe_txt_bcast (uint16_t port, const char *msg) |
Sends a broadcast WebSocket text frame. More... | |
int | ws_sendframe_bin (ws_cli_conn_t *client, const char *msg, uint64_t size) |
Sends a WebSocket binary frame. More... | |
int | ws_sendframe_bin_bcast (uint16_t port, const char *msg, uint64_t size) |
Sends a broadcast WebSocket binary frame. More... | |
int | ws_get_state (ws_cli_conn_t *client) |
For a given client , gets the current state for the connection, or -1 if invalid. More... | |
int | ws_close_client (ws_cli_conn_t *client) |
Close the client connection for the given client with normal close code (1000) and no reason string. More... | |
static int | is_control_frame (int frame) |
Checks is a given opcode frame belongs to a control frame or not. More... | |
static int | is_valid_frame (int opcode) |
Checks is a given opcode opcode is valid or not. More... | |
static int | do_handshake (struct ws_frame_data *wfd) |
Do the handshake process. More... | |
static int | do_close (struct ws_frame_data *wfd, int close_code) |
Sends a close frame, accordingly with the close_code or the message inside wfd . More... | |
static int | do_pong (struct ws_frame_data *wfd, uint64_t frame_size) |
Send a pong frame in response to a ping frame. More... | |
static int | next_byte (struct ws_frame_data *wfd) |
Read a chunk of bytes and return the next byte belonging to the frame. More... | |
static int | skip_frame (struct ws_frame_data *wfd, uint64_t frame_size) |
Skips frame_size bytes of the current frame. More... | |
static int | validate_utf8_txt (struct ws_frame_data *wfd, struct frame_state_data *fsd) |
Validates TXT frames if UTF8 validation is enabled. More... | |
static int | handle_pong_frame (struct ws_frame_data *wfd, struct frame_state_data *fsd) |
Handle PONG frames in response to our PING (or not, unsolicited is possible too). More... | |
static int | handle_ping_frame (struct ws_frame_data *wfd, struct frame_state_data *fsd) |
Handle PING frames sending a PONG response. More... | |
static int | handle_close_frame (struct ws_frame_data *wfd, struct frame_state_data *fsd) |
Handle close frames while checking for UTF8 in the close reason. More... | |
static int | read_single_frame (struct ws_frame_data *wfd, struct frame_state_data *fsd) |
Reads the current frame isolating data from control frames. More... | |
static int | next_complete_frame (struct ws_frame_data *wfd) |
Reads the next frame, whether if a TXT/BIN/CLOSE of arbitrary size. More... | |
static void * | ws_establishconnection (void *vclient) |
Establishes to connection with the client and trigger events when occurs one. More... | |
static void * | ws_accept (void *data) |
Main loop that keeps accepting new connections. More... | |
static int | do_bind_socket (struct ws_server *ws_srv) |
By using the server parameters provided in ws_srv , create a socket and bind it accordingly with the server configurations. More... | |
int | ws_socket (struct ws_server *ws_srv) |
Main loop for the server. More... | |
Variables | |
static struct ws_connection | client_socks [MAX_CLIENTS] |
Clients list. More... | |
static uint32_t | timeout |
Timeout to a single send(). More... | |
static pthread_mutex_t | mutex = PTHREAD_MUTEX_INITIALIZER |
Global mutex. More... | |
wsServer main routines.
#define _POSIX_C_SOURCE 200809L |
#define CLIENT_VALID | ( | cli | ) |
Client validity macro.
#define MSG_NOSIGNAL 0 |
#define panic | ( | s | ) |
Issues an error message and aborts the program.
s | Error message. |
|
static |
Close client connection (no close handshake, this should be done earlier), set appropriate state and destroy mutexes.
client | Client connection. |
lock | Should lock the global mutex?. |
|
static |
Shutdown and close a given socket.
fd | Socket file descriptor to be closed. |
|
static |
Close time-out thread.
For a given client, this routine sleeps until TIMEOUT_MS and closes the connection or returns sooner if already closed connection.
p | ws_connection/ws_cli_conn_t Structure Pointer. |
|
static |
By using the server parameters provided in ws_srv
, create a socket and bind it accordingly with the server configurations.
ws_srv | Web Socket configurations. |
|
static |
Sends a close frame, accordingly with the close_code
or the message inside wfd
.
wfd | Websocket Frame Data. |
close_code | Websocket close code. |
|
static |
Do the handshake process.
wfd | Websocket Frame Data. |
|
static |
Send a pong frame in response to a ping frame.
Accordingly to the RFC, a pong frame must have the same data payload as the ping frame, so we just send a ordinary frame with PONG opcode.
wfd | Websocket frame data. |
frame_size | Pong frame size. |
|
static |
Returns the current client state for a given client client
.
client | Client structure. |
|
static |
Handle close frames while checking for UTF8 in the close reason.
wfd | WebSocket frame data. |
fsd | Frame state data. |
|
static |
Handle PING frames sending a PONG response.
wfd | WebSocket frame data. |
fsd | Frame state data. |
|
static |
Handle PONG frames in response to our PING (or not, unsolicited is possible too).
wfd | WebSocket frame data. |
fsd | Frame state data. |
|
inlinestatic |
Given a PING id, encodes the content to be sent as payload of a PING frame.
ping_id | PING id to be encoded. |
msg | Target buffer. |
|
inlinestatic |
Checks is a given opcode frame
belongs to a control frame or not.
frame | Frame opcode to be checked. |
|
inlinestatic |
Checks is a given opcode opcode
is valid or not.
opcode | Frame opcode to be checked. |
|
inlinestatic |
Read a chunk of bytes and return the next byte belonging to the frame.
wfd | Websocket Frame Data. |
|
static |
Reads the next frame, whether if a TXT/BIN/CLOSE of arbitrary size.
wfd | Websocket Frame Data. |
|
inlinestatic |
Given a PONG message, decodes the content as a int32_t number that corresponds to our PONG id.
msg | Content to be decoded. |
|
static |
Reads the current frame isolating data from control frames.
The parameters are changed in order to reflect the current state.
wfd | Websocket Frame Data. |
fsd | Frame state data. |
|
static |
Send a given message buf
on a socket sockfd
.
client | Target client. |
buf | Message to be sent. |
len | Message length. |
flags | Send flags. |
|
static |
Send a ping message and close if the client surpasses the threshold imposed.
cli | Client to be sent. |
threshold | How many pings can miss?. |
lock | Should lock global mutex or not?. |
|
static |
Sets the IP address relative to a client connection opened by the server and save inside the client structure.
client | Client connection. |
|
static |
Set a state state
to the client index client
.
client | Client structure. |
state | State to be set. |
|
static |
Skips frame_size
bytes of the current frame.
wfd | Websocket Frame Data. |
frame_size | Amount of bytes to be skipped. |
|
static |
For a valid client index client
, starts the timeout thread and set the current state to 'CLOSING'.
client | Client connection. |
|
static |
Validates TXT frames if UTF8 validation is enabled.
If the content is not valid, the connection is aborted.
wfd | WebSocket frame data. |
fsd | Frame state data. |
|
static |
Main loop that keeps accepting new connections.
data | Server socket. |
data
.int ws_close_client | ( | ws_cli_conn_t * | client | ) |
Close the client connection for the given client
with normal close code (1000) and no reason string.
client | Client connection. |
|
static |
Establishes to connection with the client and trigger events when occurs one.
vclient | Client connection. |
vclient
.void* ws_get_connection_context | ( | ws_cli_conn_t * | cli | ) |
Get connection context.
void* ws_get_server_context | ( | ws_cli_conn_t * | cli | ) |
Get server context.
Assumed to be set once, when initializing .context
in struct ws_server
.
int ws_get_state | ( | ws_cli_conn_t * | client | ) |
For a given client
, gets the current state for the connection, or -1 if invalid.
client | Client connection. |
client
.char* ws_getaddress | ( | ws_cli_conn_t * | client | ) |
Gets the IP address relative to a client connection opened by the server.
client | Client connection. |
char* ws_getport | ( | ws_cli_conn_t * | client | ) |
Gets the IP port relative to a client connection opened by the server.
client | Client connection. |
void ws_ping | ( | ws_cli_conn_t * | cli, |
int | threshold | ||
) |
Sends a PING frame to the client cli
with threshold threshold
.
This routine sends a PING to a single client pointed to by cli
or a broadcast PING if cli
is NULL. If the specified client does not respond up to threshold
PINGs, the connection is aborted.
ws_ping() is not automatic: the user who wants to send keep-alive PINGs must call this routine in a timely manner, whether on a different thread or inside an event.
See examples/ping/ping.c for a minimal example usage.
cli | Client to be sent, if NULL, broadcast. |
threshold | How many ignored PINGs should tolerate? (should be positive and greater than 0). |
It is also important to note that for devices with unstable connections (such as a weak WiFi signal or 3/4/5G from a cell phone), a threshold greater than 1 is advisable.
int ws_sendframe | ( | ws_cli_conn_t * | client, |
const char * | msg, | ||
uint64_t | size, | ||
int | type | ||
) |
Send an WebSocket frame with some payload data.
client | Target to be send. If NULL, broadcast the message. |
msg | Message to be send. |
size | Binary message size. |
type | Frame type. |
size
is -1, it is assumed that a text frame is being sent, otherwise, a binary frame. In the later case, the size
is used. int ws_sendframe_bcast | ( | uint16_t | port, |
const char * | msg, | ||
uint64_t | size, | ||
int | type | ||
) |
Send an WebSocket frame with some payload data to all clients connected into the same port.
port | Server listen port to broadcast message. |
msg | Message to be send. |
size | Binary message size. |
type | Frame type. |
size
is -1, it is assumed that a text frame is being sent, otherwise, a binary frame. In the later case, the size
is used. int ws_sendframe_bin | ( | ws_cli_conn_t * | client, |
const char * | msg, | ||
uint64_t | size | ||
) |
Sends a WebSocket binary frame.
client | Target to be send. |
msg | Message to be send. |
size | Binary message size. |
int ws_sendframe_bin_bcast | ( | uint16_t | port, |
const char * | msg, | ||
uint64_t | size | ||
) |
Sends a broadcast WebSocket binary frame.
port | Server listen port to broadcast message. |
msg | Message to be send. |
size | Binary message size. |
|
static |
Creates and send an WebSocket frame with some payload data.
This routine is intended to be used to create a websocket frame for a given type e sending to the client. For higher level routines, please check ws_sendframe_txt and ws_sendframe_bin.
client | Target to be send. If NULL, broadcast the message. |
msg | Message to be send. |
size | Binary message size. |
type | Frame type. |
port | Server listen port to broadcast message (if any). |
size
is -1, it is assumed that a text frame is being sent, otherwise, a binary frame. In the later case, the size
is used.int ws_sendframe_txt | ( | ws_cli_conn_t * | client, |
const char * | msg | ||
) |
Sends a WebSocket text frame.
client | Target to be send. |
msg | Message to be send, null terminated. |
int ws_sendframe_txt_bcast | ( | uint16_t | port, |
const char * | msg | ||
) |
Sends a broadcast WebSocket text frame.
port | Server listen port to broadcast message. |
msg | Message to be send, null terminated. |
void ws_set_connection_context | ( | ws_cli_conn_t * | cli, |
void * | ptr | ||
) |
Set connection context.
int ws_socket | ( | struct ws_server * | ws_srv | ) |
Main loop for the server.
ws_srv | Web Socket server parameters. |
thread_loop
!= 0, returns 0. Otherwise, never returns.
|
static |
Clients list.
|
static |
Global mutex.
|
static |
Timeout to a single send().