Robotran C Documentation
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ws.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2016-2022 Davidson Francis <davidsondfgl@gmail.com>
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>
16  */
17 
25 #ifndef WS_H
26 #define WS_H
27 
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31 
32  #include <stdbool.h>
33  #include <stdint.h>
34  #include <inttypes.h>
35 
43 #ifndef MAX_CLIENTS
44  #define MAX_CLIENTS 8
45 #endif
46 
54  #define MESSAGE_LENGTH 2048
55 
58  #define MAX_FRAME_LENGTH (16*1024*1024)
59 
62  #define WS_KEY_LEN 24
63 
66  #define WS_MS_LEN 36
67 
70  #define WS_KEYMS_LEN (WS_KEY_LEN + WS_MS_LEN)
71 
74  #define MAGIC_STRING "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
75 
84  #define WS_HS_REQ "Sec-WebSocket-Key"
85 
89  #define WS_HS_ACCLEN 130
90 
94  #define WS_HS_ACCEPT \
95  "HTTP/1.1 101 Switching Protocols\r\n" \
96  "Upgrade: websocket\r\n" \
97  "Connection: Upgrade\r\n" \
98  "Sec-WebSocket-Accept: "
99 
108  #define WS_FIN 128
109 
113  #define WS_FIN_SHIFT 7
114 
118  #define WS_FR_OP_CONT 0
119 
123  #define WS_FR_OP_TXT 1
124 
128  #define WS_FR_OP_BIN 2
129 
133  #define WS_FR_OP_CLSE 8
134 
138  #define WS_FR_OP_PING 0x9
139 
143  #define WS_FR_OP_PONG 0xA
144 
148  #define WS_FR_OP_UNSUPPORTED 0xF
149 
158  #define WS_CLSE_NORMAL 1000
159 
162  #define WS_CLSE_PROTERR 1002
163 
167  #define WS_CLSE_INVUTF8 1007
168 
176  #define WS_STATE_CONNECTING 0
177 
180  #define WS_STATE_OPEN 1
181 
184  #define WS_STATE_CLOSING 2
185 
188  #define WS_STATE_CLOSED 3
189 
198  #define MS_TO_NS(x) ((x)*1000000)
199 
202  #define TIMEOUT_MS (500)
203 
212  #ifdef VERBOSE_MODE
213  #define DEBUG(...) fprintf(stderr, __VA_ARGS__)
214  #else
215  #define DEBUG(...)
216  #endif
217 
219  #ifndef AFL_FUZZ
220  #define SEND(client,buf,len) send_all((client), (buf), (len), MSG_NOSIGNAL)
221  #define RECV(fd,buf,len) recv((fd)->client_sock, (buf), (len), 0)
222  #else
223  #define SEND(client,buf,len) write(fileno(stdout), (buf), (len))
224  #define RECV(fd,buf,len) read((fd)->client_sock, (buf), (len))
225  #endif
226 
227  /* Opaque client connection type. */
228  typedef struct ws_connection ws_cli_conn_t;
229 
230  /* Opaque server instance type. */
231  typedef struct ws_server ws_server_t;
232 
237  void *ws_get_server_context(ws_cli_conn_t *cli);
238 
242  void ws_set_connection_context(ws_cli_conn_t *cli, void *ptr);
243 
247  void *ws_get_connection_context(ws_cli_conn_t *cli);
248 
252  struct ws_events
253  {
257  void (*onopen)(ws_cli_conn_t *client);
261  void (*onclose)(ws_cli_conn_t *client);
266  void (*onmessage)(ws_cli_conn_t *client,
267  const unsigned char *msg, uint64_t msg_size, int type);
268  };
269 
273  struct ws_server
274  {
278  const char *host;
282  uint16_t port;
291  uint32_t timeout_ms;
295  struct ws_events evs;
300  void* context;
301  };
302 
303  /* Forward declarations. */
304 
305  /* Internal usage. */
306  extern int get_handshake_accept(char *wsKey, unsigned char **dest);
307  extern int get_handshake_response(char *hsrequest, char **hsresponse);
308 
309  /* External usage. */
310  extern char *ws_getaddress(ws_cli_conn_t *client);
311  extern char *ws_getport(ws_cli_conn_t *client);
312  extern int ws_sendframe(
313  ws_cli_conn_t *cli, const char *msg, uint64_t size, int type);
314  extern int ws_sendframe_bcast(
315  uint16_t port, const char *msg, uint64_t size, int type);
316  extern int ws_sendframe_txt(ws_cli_conn_t *cli, const char *msg);
317  extern int ws_sendframe_txt_bcast(uint16_t port, const char *msg);
318  extern int ws_sendframe_bin(ws_cli_conn_t *cli, const char *msg,
319  uint64_t size);
320  extern int ws_sendframe_bin_bcast(uint16_t port, const char *msg,
321  uint64_t size);
322  extern int ws_get_state(ws_cli_conn_t *cli);
323  extern int ws_close_client(ws_cli_conn_t *cli);
324  extern int ws_socket(struct ws_server *ws_srv);
325 
326  /* Ping routines. */
327  extern void ws_ping(ws_cli_conn_t *cli, int threshold);
328 
329 #ifdef AFL_FUZZ
330  extern int ws_file(struct ws_events *evs, const char *file);
331 #endif
332 
333 #ifdef __cplusplus
334 }
335 #endif
336 
337 #endif /* WS_H */
ws_sendframe_bcast
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.
Definition: ws.c:682
ws_set_connection_context
void ws_set_connection_context(ws_cli_conn_t *cli, void *ptr)
Set connection context.
Definition: ws.c:112
ws_socket
int ws_socket(struct ws_server *ws_srv)
Main loop for the server.
Definition: ws.c:1940
get_handshake_response
int get_handshake_response(char *hsrequest, char **hsresponse)
Gets the complete response to accomplish a succesfully handshake.
Definition: handshake.c:87
ws_events::onmessage
void(* onmessage)(ws_cli_conn_t *client, const unsigned char *msg, uint64_t msg_size, int type)
On message event, called when a client sends a text or binary message.
Definition: ws.h:266
client
static ws_cli_conn_t * client
Definition: visu_websocket.cc:49
ws_sendframe_txt_bcast
int ws_sendframe_txt_bcast(uint16_t port, const char *msg)
Sends a broadcast WebSocket text frame.
Definition: ws.c:828
ws_get_connection_context
void * ws_get_connection_context(ws_cli_conn_t *cli)
Get connection context.
Definition: ws.c:120
ws_server::thread_loop
int thread_loop
Whether if the ws_socket() should create a new thread and be non-blocking (1) or not (0).
Definition: ws.h:287
ws_close_client
int ws_close_client(ws_cli_conn_t *cli)
Close the client connection for the given client with normal close code (1000) and no reason string.
Definition: ws.c:893
ws_sendframe
int ws_sendframe(ws_cli_conn_t *cli, const char *msg, uint64_t size, int type)
Send an WebSocket frame with some payload data.
Definition: ws.c:663
ws_server::port
uint16_t port
Listening port.
Definition: ws.h:282
ws_server::context
void * context
Server context.
Definition: ws.h:300
ws_get_state
int ws_get_state(ws_cli_conn_t *cli)
For a given client, gets the current state for the connection, or -1 if invalid.
Definition: ws.c:875
ws_connection
Client socks.
Definition: ws.c:70
ws_ping
void ws_ping(ws_cli_conn_t *cli, int threshold)
Sends a PING frame to the client cli with threshold threshold.
Definition: ws.c:783
ws_events::onclose
void(* onclose)(ws_cli_conn_t *client)
On close event, called when a client disconnects.
Definition: ws.h:261
ws_server::evs
struct ws_events evs
Server events.
Definition: ws.h:295
ws_getport
char * ws_getport(ws_cli_conn_t *client)
Gets the IP port relative to a client connection opened by the server.
Definition: ws.c:493
ws_server::timeout_ms
uint32_t timeout_ms
Ping timeout in milliseconds.
Definition: ws.h:291
ws_events::onopen
void(* onopen)(ws_cli_conn_t *client)
On open event, called when a new client connects.
Definition: ws.h:257
get_handshake_accept
int get_handshake_accept(char *wsKey, unsigned char **dest)
Gets the field Sec-WebSocket-Accept on response, by an previously informed key.
Definition: handshake.c:47
ws_events
events Web Socket events types.
Definition: ws.h:252
ws_get_server_context
void * ws_get_server_context(ws_cli_conn_t *cli)
Get server context.
Definition: ws.c:104
ws_sendframe_bin
int ws_sendframe_bin(ws_cli_conn_t *cli, const char *msg, uint64_t size)
Sends a WebSocket binary frame.
Definition: ws.c:842
ws_sendframe_txt
int ws_sendframe_txt(ws_cli_conn_t *cli, const char *msg)
Sends a WebSocket text frame.
Definition: ws.c:815
ws_sendframe_bin_bcast
int ws_sendframe_bin_bcast(uint16_t port, const char *msg, uint64_t size)
Sends a broadcast WebSocket binary frame.
Definition: ws.c:856
ws_getaddress
char * ws_getaddress(ws_cli_conn_t *client)
Gets the IP address relative to a client connection opened by the server.
Definition: ws.c:475
ws_server
server Web Socket server parameters
Definition: ws.h:273
ws_server::host
const char * host
Required hostname that the wsServer will bind to.
Definition: ws.h:278