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