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