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