A lightweight WebSocket Server library in C, written from the ground up to implement RFC6455, using BSD sockets API. This library can handle multiple clients in a single thread using I/O Multiplexing.
Compatible with ESP32 (primary development target), Linux, Mac, and Windows.
You may want to limit the number of concurrent clients in an embedded device due to memory constraints.
Here's a basic Echo Server using WebSockets.
#include"ws_server.h"#include<stdio.h>#include<signal.h>#definePORT 8081
staticintexitServer=0;
voidsig_handler(intsigno) {
if (signo==SIGINT) {
exitServer=1;
}
}
staticvoidonConnect(Endpoint_t*client) {
// A new client is connectedif(client) {
printf("WS Client connected: %p\n", client);
// Send a ping to the clientif(ws_server_SendPing((WsEndpoint_t*) client, NULL, 0) !=LWS_ERR_OK) {
printf("Could not send ping\n");
}
}
}
staticvoidonMessage(Endpoint_t*client, void*payload, size_tsize) {
(void) size;
// A new message has been received from a client.WsMessage_t*message= (WsMessage_t*) payload;
if(message->opcode==OP_TEXT) {
printf("Echoing Text Message: %.*s\n", (int) message->length, message->buffer);
} else {
printf("Echoing Binary Message: ");
for(size_ti=0; i<message->length; i++) {
printf("%02X ", message->buffer[i]);
}
printf("\n");
}
// Echo the message back to the client.ws_server_SendMessage((WsEndpoint_t*) client, message->opcode, message->buffer, message->length);
}
staticvoidonDisconnect(Endpoint_t*client) {
// A client has been disconnected from the peer end.if(client) {
printf("WS Client disconnected: %p\n", client);
}
}
staticvoidonServerError(Server_t*server, constunsigned char*payload, size_tsize) {
(void) server;
// Encountered an error in WS Serverfprintf(stderr, "WS SERVER ERROR: %.*s\n", (int) size, payload);
}
staticvoidonEndpointError(Endpoint_t*client, constunsigned char*payload, size_tsize) {
(void) client;
// Encountered an error in WS Clientfprintf(stderr, "WS CLIENT ERROR: %.*s\n", (int) size, payload);
}
intmain() {
if (signal(SIGINT, sig_handler) ==SIG_ERR)
fprintf(stderr, "===\ncan't catch SIGINT\n===\n");
WsServerConfig_tserver_config= { 0 };
server_config.onConnect=onConnect;
server_config.onDisconnect=onDisconnect;
server_config.onMessage=onMessage;
server_config.onServerError=onServerError;
server_config.onEndpointError=onEndpointError;
WsServer_t*server=ws_server_Init(&server_config, NULL);
if(!server) {
fprintf(stderr, "Exited WS Server!\n");
return1;
}
ws_server_Bind(server, PORT);
printf("Websocket Server listening on Port: %d\n", PORT);
while(1) {
if(ws_server_Tick(server) !=LWS_ERR_OK||exitServer) {
break;
}
}
ws_server_DeInit(server);
fprintf(stderr, "Exited WS Server!\n");
return0;
}Other examples to create TCP, TLS, WS, WSS libraries can be found in the examples directory.
typedef void (*ConnectCallback)(Endpoint_t*);typedef void (*DisconnectCallback)(Endpoint_t*);typedef void (*MessageCallback)(Endpoint_t*, void* message, size_t size);typedef void (*ServerErrorCallback)(Server_t*, const unsigned char* message, size_t size);typedef void (*EndpointErrorCallback)(Endpoint_t*, const unsigned char* message, size_t size);
structWsServerConfig_t {
ConnectCallbackonConnect; // Handler for a new WebSocket endpoint connectionDisconnectCallbackonDisconnect; // Handler for a WebSocket endpoint disconnectionMessageCallbackonMessage; // Handler for a WebSocket endpoint messageServerErrorCallbackonServerError; // Handler for a WebSocket server errorEndpointErrorCallbackonEndpointError; // Handler for a WebSocket endpoint error
};WsServer_t*ws_server_Init(WsServerConfig_t*config, CertificateData*certs);Initialize the WebSocket server and allocate resources.
- param config: Instance of WsServerConfig_t with event handlers.
- param certs: Certificate data for WSS server. Pass NULL for WS server.
- returns an instance of WsServer_t on success, or NULL otherwise.
Err_tws_server_DeInit(WsServer_t*server);Deinitialize the WebSocket server and free up resources.
- param server: Pointer to WsServer_t instance.
- returns WS_OK on success.
Err_tws_server_Bind(WsServer_t*server, intport);Bind the WebSocket server to the given port.
- param server: WsServer_t instance.
- param port: Port number to bind to.
- returns WS_OK on success.
Err_tws_server_SendTextMessage(WsEndpoint_t*endpoint, unsigned char*buffer, size_tlength);Send a text message to a WebSocket endpoint.
- param endpoint: Recipient WsEndpoint_t.
- param buffer: Buffer to send.
- param length: Length of buffer.
- returns WS_OK on success.
Err_tws_server_BroadcastTextMessage(WsServer_t*server, unsigned char*buffer, size_tlength);Broadcast a text message to all WebSocket endpoints connected to the server.
- param server: WebSocket server.
- param buffer: Buffer to send.
- param length: Length of buffer.
- returns WS_OK on success.
Err_tws_server_SendBinaryMessage(WsEndpoint_t*endpoint, unsigned char*buffer, size_tlength);Send a binary message to a WebSocket endpoint.
- param endpoint: Recipient WsEndpoint_t.
- param buffer: Buffer to send.
- param length: Length of buffer.
- returns WS_OK on success.
Err_tws_server_BroadcastBinaryMessage(WsServer_t*server, unsigned char*buffer, size_tlength);Broadcast a binary message to all WebSocket clients connected to the server.
- param server: WebSocket server.
- param buffer: Buffer to send.
- param length: Length of buffer.
- returns WS_OK on success.
Err_tws_server_SendCloseMessage(WsEndpoint_t*endpoint, WsCloseReason_treason);Send a close message to a WebSocket endpoint.
- param endpoint: Recipient WsEndpoint_t.
- param reason: Reason for closing the connection.
- returns WS_OK on success.
Err_tws_server_Tick(WsServer_t*server);Tick function for the WebSocket server. Call this function repeatedly for the server to process its events.
- param server: WsServer_t instance.
- returns WS_OK on success.
Err_tws_server_CloseConnection(WsEndpoint_t*endpoint);Close the connection to a WebSocket endpoint.
- param endpoint: WsEndpoint_t instance.
- returns LWS_ERR_OK on success.
char*string_ltrim(char*s);Trim whitespace from the beginning of the string
- param s Pointer to string with whitespace
- returns Pointer to trimmed string, NULL if s is NULL
char*string_rtrim(char*s);Trim whitespace from the end of the string
- param s Pointer to string with whitespace
- returns Pointer to trimmed string, NULL if s is NULL
char*string_trim(char*s);Trim whitespace from the both ends of the string
- param s Pointer to string with whitespace
- returns Pointer to trimmed string, NULL if s is NULL