1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** NetX WebSocket Component                                              */
16 /**                                                                       */
17 /**   WebSocket Protocol                                                  */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 
23 /**************************************************************************/
24 /*                                                                        */
25 /*  APPLICATION INTERFACE DEFINITION                       RELEASE        */
26 /*                                                                        */
27 /*    nx_websocket_client.h                               PORTABLE C      */
28 /*                                                           6.2.0        */
29 /*  AUTHOR                                                                */
30 /*                                                                        */
31 /*                                                                        */
32 /*                                                                        */
33 /*  DESCRIPTION                                                           */
34 /*                                                                        */
35 /*    This file defines the NetX WebSocket Protocol component, including  */
36 /*    all data types and external references.                             */
37 /*                                                                        */
38 /*  RELEASE HISTORY                                                       */
39 /*                                                                        */
40 /*    DATE              NAME                      DESCRIPTION             */
41 /*                                                                        */
42 /*  10-31-2022     Bo Chen                  Initial Version 6.2.0         */
43 /*                                                                        */
44 /**************************************************************************/
45 
46 #ifndef NX_WEBSOCKET_CLIENT_H
47 #define NX_WEBSOCKET_CLIENT_H
48 
49 /* Determine if a C++ compiler is being used.  If so, ensure that standard
50    C is used to process the API information.  */
51 
52 
53 #ifdef   __cplusplus
54 
55 /* Yes, C++ compiler is present.  Use standard C.  */
56 extern   "C" {
57 
58 #endif
59 
60 #include "nx_api.h"
61 #include "nx_sha1.h"
62 
63 #ifdef NX_SECURE_ENABLE
64 #include "nx_secure_tls_api.h"
65 #endif /* NX_SECURE_ENABLE */
66 
67 #ifdef NX_DISABLE_PACKET_CHAIN
68 #error "NX_DISABLE_PACKET_CHAIN must not be defined"
69 #endif /* NX_DISABLE_PACKET_CHAIN */
70 
71 /* Define the WebSocket ID.  */
72 #define NX_WEBSOCKET_CLIENT_ID                  0x57454253UL
73 
74 /* Define the GUID size.  */
75 #define NX_WEBSOCKET_CLIENT_GUID_SIZE           16
76 
77 /* Define the WebSocket Key size.  */
78 #define NX_WEBSOCKET_CLIENT_KEY_SIZE            26
79 
80 /* WebSocket Header Format:
81      0                   1                   2                   3
82      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
83     +-+-+-+-+-------+-+-------------+-------------------------------+
84     |F|R|R|R| opcode|M| Payload len |    Extended payload length    |
85     |I|S|S|S|  (4)  |A|     (7)     |             (16)              |
86     |N|V|V|V|       |S|             |                               |
87     | |1|2|3|       |K|             |                               |
88     +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
89     | Masking-key , if MASK set to 1                                |
90     +-------------------------------- - - - - - - - - - - - - - - - +
91     | Payload Data...                                               |
92     +-------------------------------- - - - - - - - - - - - - - - - +
93 */
94 
95 /* First two bytes are required.  */
96 
97 /* Define FIN.  */
98 #define NX_WEBSOCKET_FIN                            0x80
99 #define NX_WEBSOCKET_FIN_MASK                       0x80
100 
101 /* Define the opcode.  */
102 #define NX_WEBSOCKET_OPCODE_CONTINUATION_FRAME      0x00
103 #define NX_WEBSOCKET_OPCODE_TEXT_FRAME              0x01
104 #define NX_WEBSOCKET_OPCODE_BINARY_FRAME            0x02
105 #define NX_WEBSOCKET_OPCODE_CONNECTION_CLOSE        0x08
106 #define NX_WEBSOCKET_OPCODE_PING                    0x09
107 #define NX_WEBSOCKET_OPCODE_PONG                    0x0A
108 #define NX_WEBSOCKET_OPCODE_MASK                    0x0F
109 
110 /* Define the mask bit.  */
111 #define NX_WEBSOCKET_MASK                           0x80
112 #define NX_WEBSOCKET_MASK_MASK                      0x80
113 
114 /* Define the payload length, always using 7bits + 16bits for payload length.  */
115 #define NX_WEBSOCKET_PAYLOAD_LEN_MASK               0x7F
116 #define NX_WEBSOCKET_PAYLOAD_LEN_16BITS             0x7E /* Payload length: 126, the following 2 bytes interpreted as a 16-bits unsigned integer are the payload length.  */
117 #define NX_WEBSOCKET_PAYLOAD_LEN_64BITS             0x7F /* Payload length: 127, the following 4 bytes interpreted as a 64-bits unsigned integer are the payload length.  */
118 #define NX_WEBSOCKET_EXTENDED_PAYLOAD_16BITS_SIZE   2
119 #define NX_WEBSOCKET_EXTENDED_PAYLOAD_64BITS_SIZE   8
120 
121 /* Define the masking key size.  */
122 #define NX_WEBSOCKET_MASKING_KEY_SIZE               4
123 
124 /* Define the basic header size (2 bytes normal header  + 4 bytes masking key)*/
125 #define NX_WEBSOCKET_HEADER_NORMAL_SIZE             6
126 
127 /* Define the header size (2 bytes normal header  + 2 bytes extended payload length + 4 bytes masking key). 8 bytes extended payload length is not supported yet.  */
128 #define NX_WEBSOCKET_HEADER_SIZE                    8
129 
130 /* Define the state.  */
131 #define NX_WEBSOCKET_CLIENT_STATE_INITIALIZE           0
132 #define NX_WEBSOCKET_CLIENT_STATE_IDLE                 1
133 #define NX_WEBSOCKET_CLIENT_STATE_CONNECTING           2
134 #define NX_WEBSOCKET_CLIENT_STATE_CONNECTED            3
135 #define NX_WEBSOCKET_CLIENT_STATE_DISCONNECT_SENT      4
136 #define NX_WEBSOCKET_CLIENT_STATE_DISCONNECT_RECEIVED  5
137 
138 /* Define the return value.  */
139 #define NX_WEBSOCKET_SUCCESS                        0x0
140 #define NX_WEBSOCKET_ERROR                          0x30001
141 #define NX_WEBSOCKET_CONNECTING                     0x30002
142 #define NX_WEBSOCKET_ALREADY_CONNECTED              0x30003
143 #define NX_WEBSOCKET_NOT_CONNECTED                  0x30004
144 #define NX_WEBSOCKET_DATA_APPEND_FAILURE            0x30005
145 #define NX_WEBSOCKET_INVALID_STATE                  0x30006
146 #define NX_WEBSOCKET_INVALID_PACKET                 0x30007
147 #define NX_WEBSOCKET_INVALID_STATUS_CODE            0x30008
148 #define NX_WEBSOCKET_DISCONNECTED                   0x30009
149 
150 /* Define the websocket Client data structure.  */
151 typedef struct NX_WEBSOCKET_CLIENT_STRUCT
152 {
153 
154     /* WebSocket Client ID.  */
155     ULONG                       nx_websocket_client_id;
156 
157     /* Name of this WebSocket Client.  */
158     UCHAR                      *nx_websocket_client_name;
159 
160     /* Pointer to associated IP structure.  */
161     NX_IP                      *nx_websocket_client_ip_ptr;
162 
163     /* Pointer to WebSocket Client packet pool.  */
164     NX_PACKET_POOL             *nx_websocket_client_packet_pool_ptr;
165 
166     /* State.  */
167     UINT                        nx_websocket_client_state;
168 
169     /* Pointer to WebSocket Client TCP socket.  */
170     NX_TCP_SOCKET              *nx_websocket_client_socket_ptr;
171 
172 #ifdef NX_SECURE_ENABLE
173     UINT                        nx_websocket_client_use_tls;
174     NX_SECURE_TLS_SESSION      *nx_websocket_client_tls_session_ptr;
175 #endif
176 
177     /* Pointer to the received packet to be processed. This packet may be composited by more than one tcp/tls packet. */
178     NX_PACKET                  *nx_websocket_client_processing_packet;
179 
180     /* Globally Unique Identifier.  */
181     UCHAR                       nx_websocket_client_guid[NX_WEBSOCKET_CLIENT_GUID_SIZE];
182 
183     /* Protocol Name and length */
184     UCHAR                      *nx_websocket_client_subprotocol;
185     UINT                        nx_websocket_client_subprotocol_length;
186 
187     /* WebSocket-Key.  */
188     UINT                        nx_websocket_client_key_size;
189     UCHAR                       nx_websocket_client_key[NX_WEBSOCKET_CLIENT_KEY_SIZE];
190 
191     /* Websocket frame header parse context */
192     UCHAR                       nx_websocket_client_frame_header_found;
193     UCHAR                       nx_websocket_client_frame_fragmented;
194     UCHAR                       nx_websocket_client_frame_opcode;
195     UCHAR                       nx_websocket_client_frame_masked;
196     UCHAR                       nx_websocket_client_frame_masking_key[4];
197     ULONG                       nx_websocket_client_frame_data_length;
198     ULONG                       nx_websocket_client_frame_data_received;
199 
200     /* SHA1 in connect response calculation for Sec-Protocol-Accept field */
201     NX_SHA1                     nx_websocket_client_sha1;
202 
203     /* Connection status callback function.  */
204     VOID                        (*nx_websocket_client_connection_status_callback)(struct NX_WEBSOCKET_CLIENT_STRUCT *, VOID *, UINT);
205 
206     /* Pointer to an argument passed to connection status callback.  */
207     VOID                       *nx_websocket_client_connection_context;
208 
209     /* Define the websocket protect purpose mutex */
210     TX_MUTEX                    nx_websocket_client_mutex;
211 
212 } NX_WEBSOCKET_CLIENT;
213 
214 
215 
216 #ifndef NX_WEBSOCKET_CLIENT_SOURCE_CODE
217 
218 /* Application caller is present, perform API mapping.  */
219 
220 /* Determine if error checking is desired.  If so, map API functions
221    to the appropriate error checking front-ends.  Otherwise, map API
222    functions to the core functions that actually perform the work.
223    Note: error checking is enabled by default.  */
224 
225 #ifdef NX_DISABLE_ERROR_CHECKING
226 
227 /* Services without error checking.  */
228 
229 #define nx_websocket_client_create                          _nx_websocket_client_create
230 #define nx_websocket_client_delete                          _nx_websocket_client_delete
231 #define nx_websocket_client_connect                         _nx_websocket_client_connect
232 #ifdef NX_SECURE_ENABLE
233 #define nx_websocket_client_secure_connect                  _nx_websocket_client_secure_connect
234 #endif /* NX_SECURE_ENABLE */
235 #define nx_websocket_client_disconnect                      _nx_websocket_client_disconnect
236 #define nx_websocket_client_packet_allocate                 _nx_websocket_client_packet_allocate
237 #define nx_websocket_client_send                            _nx_websocket_client_send
238 #define nx_websocket_client_receive                         _nx_websocket_client_receive
239 #define nx_websocket_client_connection_status_callback_set  _nx_websocket_client_connection_status_callback_set
240 
241 #else
242 
243 /* Services with error checking.  */
244 
245 #define nx_websocket_client_create                          _nxe_websocket_client_create
246 #define nx_websocket_client_delete                          _nxe_websocket_client_delete
247 #define nx_websocket_client_connect                         _nxe_websocket_client_connect
248 #ifdef NX_SECURE_ENABLE
249 #define nx_websocket_client_secure_connect                  _nxe_websocket_client_secure_connect
250 #endif /* NX_SECURE_ENABLE */
251 #define nx_websocket_client_disconnect                      _nxe_websocket_client_disconnect
252 #define nx_websocket_client_packet_allocate                 _nxe_websocket_client_packet_allocate
253 #define nx_websocket_client_send                            _nxe_websocket_client_send
254 #define nx_websocket_client_receive                         _nxe_websocket_client_receive
255 #define nx_websocket_client_connection_status_callback_set  _nxe_websocket_client_connection_status_callback_set
256 
257 #endif  /* NX_DISABLE_ERROR_CHECKING */
258 
259 /* Define the prototypes accessible to the application software.  */
260 
261 UINT  nx_websocket_client_create(NX_WEBSOCKET_CLIENT *client_ptr, UCHAR *client_name, NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr);
262 UINT  nx_websocket_client_delete(NX_WEBSOCKET_CLIENT *client_ptr);
263 UINT  nx_websocket_client_packet_allocate(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET **packet_ptr, ULONG wait_option);
264 UINT  nx_websocket_client_connect(NX_WEBSOCKET_CLIENT *client_ptr, NX_TCP_SOCKET *socket_ptr,
265                                   UCHAR *host, UINT host_length,
266                                   UCHAR *uri_path, UINT uri_path_length,
267                                   UCHAR *protocol, UINT protocol_length,UINT wait_option);
268 #ifdef NX_SECURE_ENABLE
269 UINT  nx_websocket_client_secure_connect(NX_WEBSOCKET_CLIENT *client_ptr, NX_SECURE_TLS_SESSION *tls_session,
270                                          UCHAR *host, UINT host_length,
271                                          UCHAR *uri_path, UINT uri_path_length,
272                                          UCHAR *protocol, UINT protocol_length,UINT wait_option);
273 #endif /* NX_SECURE_ENABLE */
274 UINT  nx_websocket_client_disconnect(NX_WEBSOCKET_CLIENT *client_ptr, UINT wait_option);
275 UINT  nx_websocket_client_send(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET *packet_ptr, UINT code, UINT is_final, UINT wait_option);
276 UINT  nx_websocket_client_receive(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET **packet_ptr, UINT *code, UINT wait_option);
277 UINT  nx_websocket_client_connection_status_callback_set(NX_WEBSOCKET_CLIENT *client_ptr, VOID *context,
278                                                          VOID (*connection_status_callback)(NX_WEBSOCKET_CLIENT *, VOID *, UINT));
279 
280 #else
281 
282 /* Websocket source code is being compiled, do not perform any API mapping.  */
283 
284 UINT  _nxe_websocket_client_create(NX_WEBSOCKET_CLIENT *client_ptr, UCHAR *client_name, NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr);
285 UINT  _nx_websocket_client_create(NX_WEBSOCKET_CLIENT *client_ptr, UCHAR *client_name, NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr);
286 UINT  _nxe_websocket_client_delete(NX_WEBSOCKET_CLIENT *client_ptr);
287 UINT  _nx_websocket_client_delete(NX_WEBSOCKET_CLIENT *client_ptr);
288 UINT  _nxe_websocket_client_packet_allocate(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET **packet_ptr, ULONG wait_option);
289 UINT  _nx_websocket_client_packet_allocate(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET **packet_ptr, ULONG wait_option);
290 UINT  _nxe_websocket_client_connect(NX_WEBSOCKET_CLIENT *client_ptr, NX_TCP_SOCKET *socket_ptr,
291                                     UCHAR *host, UINT host_length,
292                                     UCHAR *uri_path, UINT uri_path_length,
293                                     UCHAR *protocol, UINT protocol_length,UINT wait_option);
294 UINT  _nx_websocket_client_connect(NX_WEBSOCKET_CLIENT *client_ptr, NX_TCP_SOCKET *socket_ptr,
295                                    UCHAR *host, UINT host_length,
296                                    UCHAR *uri_path, UINT uri_path_length,
297                                    UCHAR *protocol, UINT protocol_length,UINT wait_option);
298 #ifdef NX_SECURE_ENABLE
299 UINT  _nxe_websocket_client_secure_connect(NX_WEBSOCKET_CLIENT *client_ptr, NX_SECURE_TLS_SESSION *tls_session,
300                                            UCHAR *host, UINT host_length,
301                                            UCHAR *uri_path, UINT uri_path_length,
302                                            UCHAR *protocol, UINT protocol_length,UINT wait_option);
303 UINT  _nx_websocket_client_secure_connect(NX_WEBSOCKET_CLIENT *client_ptr, NX_SECURE_TLS_SESSION *tls_session,
304                                           UCHAR *host, UINT host_length,
305                                           UCHAR *uri_path, UINT uri_path_length,
306                                           UCHAR *protocol, UINT protocol_length,UINT wait_option);
307 #endif /* NX_SECURE_ENABLE */
308 UINT  _nxe_websocket_client_disconnect(NX_WEBSOCKET_CLIENT *client_ptr, UINT wait_option);
309 UINT  _nx_websocket_client_disconnect(NX_WEBSOCKET_CLIENT *client_ptr, UINT wait_option);
310 UINT  _nxe_websocket_client_send(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET *packet_ptr, UINT code, UINT is_final, UINT wait_option);
311 UINT  _nx_websocket_client_send(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET *packet_ptr, UINT code, UINT is_final, UINT wait_option);
312 UINT  _nxe_websocket_client_receive(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET **packet_ptr, UINT *code, UINT wait_option);
313 UINT  _nx_websocket_client_receive(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET **packet_ptr, UINT *code, UINT wait_option);
314 UINT  _nxe_websocket_client_connection_status_callback_set(NX_WEBSOCKET_CLIENT *client_ptr, VOID * context,
315                                                            VOID (*connection_status_callback)(NX_WEBSOCKET_CLIENT *, VOID *, UINT));
316 UINT  _nx_websocket_client_connection_status_callback_set(NX_WEBSOCKET_CLIENT *client_ptr, VOID * context,
317                                                           VOID (*connection_status_callback)(NX_WEBSOCKET_CLIENT *, VOID *, UINT));
318 
319 #endif  /* NX_WEBSOCKET_CLIENT_SOURCE_CODE */
320 
321 /* Define internal websocket functions.  */
322 UINT  _nx_websocket_client_connect_internal(NX_WEBSOCKET_CLIENT *client_ptr,
323                                             UCHAR *host, UINT host_length,
324                                             UCHAR *uri_path, UINT uri_path_length,
325                                             UCHAR *protocol, UINT protocol_length,UINT wait_option);
326 UINT  _nx_websocket_client_name_compare(UCHAR *src, ULONG src_length, UCHAR *dest, ULONG dest_length);
327 UINT  _nx_websocket_client_connect_response_process(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET *packet_ptr);
328 UINT  _nx_websocket_client_packet_trim(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET **packet_ptr, ULONG trim_size);
329 UINT  _nx_websocket_client_packet_send(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET *packet_ptr, ULONG wait_option);
330 UINT  _nx_websocket_client_packet_receive(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET **packet_ptr, ULONG wait_option);
331 UINT  _nx_websocket_client_data_process(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET **packet_ptr, UINT *code);
332 UINT  _nx_websocket_client_connect_response_check(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET *packet_ptr, UINT wait_option);
333 void  _nx_websocket_client_cleanup(NX_WEBSOCKET_CLIENT *client_ptr);
334 
335 /* Determine if a C++ compiler is being used.  If so, complete the standard
336    C conditional started above.  */
337 #ifdef   __cplusplus
338         }
339 #endif
340 
341 #endif  /* NX_WEBSOCKET_CLIENT_H */
342