Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
web_socket.h
Go to the documentation of this file.
00001 /** 00002 * @file web_socket.h 00003 * @brief WebSocket API (client and server) 00004 * 00005 * @section License 00006 * 00007 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. 00008 * 00009 * This file is part of CycloneTCP Open. 00010 * 00011 * This program is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU General Public License 00013 * as published by the Free Software Foundation; either version 2 00014 * of the License, or (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License 00022 * along with this program; if not, write to the Free Software Foundation, 00023 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00024 * 00025 * @author Oryx Embedded SARL (www.oryx-embedded.com) 00026 * @version 1.7.6 00027 **/ 00028 00029 #ifndef _WEB_SOCKET_H 00030 #define _WEB_SOCKET_H 00031 00032 //Dependencies 00033 #include "core/net.h" 00034 #include "core/socket.h" 00035 00036 //WebSocket support 00037 #ifndef WEB_SOCKET_SUPPORT 00038 #define WEB_SOCKET_SUPPORT DISABLED 00039 #elif (WEB_SOCKET_SUPPORT != ENABLED && WEB_SOCKET_SUPPORT != DISABLED) 00040 #error WEB_SOCKET_SUPPORT parameter is not valid 00041 #endif 00042 00043 //Number of WebSockets that can be opened simultaneously 00044 #ifndef WEB_SOCKET_MAX_COUNT 00045 #define WEB_SOCKET_MAX_COUNT 4 00046 #elif (WEB_SOCKET_MAX_COUNT < 1) 00047 #error WEB_SOCKET_MAX_COUNT parameter is not valid 00048 #endif 00049 00050 //Support for WebSocket connections over SSL/TLS 00051 #ifndef WEB_SOCKET_TLS_SUPPORT 00052 #define WEB_SOCKET_TLS_SUPPORT DISABLED 00053 #elif (WEB_SOCKET_TLS_SUPPORT != ENABLED && WEB_SOCKET_TLS_SUPPORT != DISABLED) 00054 #error WEB_SOCKET_TLS_SUPPORT parameter is not valid 00055 #endif 00056 00057 //Basic access authentication support 00058 #ifndef WEB_SOCKET_BASIC_AUTH_SUPPORT 00059 #define WEB_SOCKET_BASIC_AUTH_SUPPORT DISABLED 00060 #elif (WEB_SOCKET_BASIC_AUTH_SUPPORT != ENABLED && WEB_SOCKET_BASIC_AUTH_SUPPORT != DISABLED) 00061 #error WEB_SOCKET_BASIC_AUTH_SUPPORT parameter is not valid 00062 #endif 00063 00064 //Digest access authentication support 00065 #ifndef WEB_SOCKET_DIGEST_AUTH_SUPPORT 00066 #define WEB_SOCKET_DIGEST_AUTH_SUPPORT DISABLED 00067 #elif (WEB_SOCKET_DIGEST_AUTH_SUPPORT != ENABLED && WEB_SOCKET_DIGEST_AUTH_SUPPORT != DISABLED) 00068 #error WEB_SOCKET_DIGEST_AUTH_SUPPORT parameter is not valid 00069 #endif 00070 00071 //Maximum number of connection attempts 00072 #ifndef WEB_SOCKET_MAX_CONN_RETRIES 00073 #define WEB_SOCKET_MAX_CONN_RETRIES 3 00074 #elif (WEB_SOCKET_MAX_CONN_RETRIES < 1) 00075 #error WEB_SOCKET_MAX_CONN_RETRIES parameter is not valid 00076 #endif 00077 00078 //Size of the WebSocket buffer 00079 #ifndef WEB_SOCKET_BUFFER_SIZE 00080 #define WEB_SOCKET_BUFFER_SIZE 1024 00081 #elif (WEB_SOCKET_BUFFER_SIZE < 128) 00082 #error WEB_SOCKET_BUFFER_SIZE parameter is not valid 00083 #endif 00084 00085 //Maximum length of the hostname 00086 #ifndef WEB_SOCKET_HOST_MAX_LEN 00087 #define WEB_SOCKET_HOST_MAX_LEN 32 00088 #elif (WEB_SOCKET_HOST_MAX_LEN < 1) 00089 #error WEB_SOCKET_HOST_MAX_LEN parameter is not valid 00090 #endif 00091 00092 //Maximum length of the origin header field 00093 #ifndef WEB_SOCKET_ORIGIN_MAX_LEN 00094 #define WEB_SOCKET_ORIGIN_MAX_LEN 16 00095 #elif (WEB_SOCKET_ORIGIN_MAX_LEN < 1) 00096 #error WEB_SOCKET_ORIGIN_MAX_LEN parameter is not valid 00097 #endif 00098 00099 //Maximum length of the sub-protocol 00100 #ifndef WEB_SOCKET_SUB_PROTOCOL_MAX_LEN 00101 #define WEB_SOCKET_SUB_PROTOCOL_MAX_LEN 8 00102 #elif (WEB_SOCKET_SUB_PROTOCOL_MAX_LEN < 1) 00103 #error WEB_SOCKET_SUB_PROTOCOL_MAX_LEN parameter is not valid 00104 #endif 00105 00106 //Maximum length of the URI 00107 #ifndef WEB_SOCKET_URI_MAX_LEN 00108 #define WEB_SOCKET_URI_MAX_LEN 32 00109 #elif (WEB_SOCKET_URI_MAX_LEN < 1) 00110 #error WEB_SOCKET_URI_MAX_LEN parameter is not valid 00111 #endif 00112 00113 //Maximum length of the query string 00114 #ifndef WEB_SOCKET_QUERY_STRING_MAX_LEN 00115 #define WEB_SOCKET_QUERY_STRING_MAX_LEN 32 00116 #elif (WEB_SOCKET_QUERY_STRING_MAX_LEN < 1) 00117 #error WEB_SOCKET_QUERY_STRING_MAX_LEN parameter is not valid 00118 #endif 00119 00120 //Maximum length of the realm 00121 #ifndef WEB_SOCKET_REALM_MAX_LEN 00122 #define WEB_SOCKET_REALM_MAX_LEN 32 00123 #elif (WEB_SOCKET_REALM_MAX_LEN < 1) 00124 #error WEB_SOCKET_REALM_MAX_LEN parameter is not valid 00125 #endif 00126 00127 //Maximum length of the user name 00128 #ifndef WEB_SOCKET_USERNAME_MAX_LEN 00129 #define WEB_SOCKET_USERNAME_MAX_LEN 16 00130 #elif (WEB_SOCKET_USERNAME_MAX_LEN < 1) 00131 #error WEB_SOCKET_USERNAME_MAX_LEN parameter is not valid 00132 #endif 00133 00134 //Maximum length of the password 00135 #ifndef WEB_SOCKET_PASSWORD_MAX_LEN 00136 #define WEB_SOCKET_PASSWORD_MAX_LEN 16 00137 #elif (WEB_SOCKET_PASSWORD_MAX_LEN < 1) 00138 #error WEB_SOCKET_PASSWORD_MAX_LEN parameter is not valid 00139 #endif 00140 00141 //Maximum length of the nonce 00142 #ifndef WEB_SOCKET_NONCE_MAX_LEN 00143 #define WEB_SOCKET_NONCE_MAX_LEN 32 00144 #elif (WEB_SOCKET_NONCE_MAX_LEN < 1) 00145 #error WEB_SOCKET_NONCE_MAX_LEN parameter is not valid 00146 #endif 00147 00148 //Maximum length of the opaque parameter 00149 #ifndef WEB_SOCKET_OPAQUE_MAX_LEN 00150 #define WEB_SOCKET_OPAQUE_MAX_LEN 32 00151 #elif (WEB_SOCKET_OPAQUE_MAX_LEN < 1) 00152 #error WEB_SOCKET_OPAQUE_MAX_LEN parameter is not valid 00153 #endif 00154 00155 //Cnonce size 00156 #ifndef WEB_SOCKET_CNONCE_SIZE 00157 #define WEB_SOCKET_CNONCE_SIZE 16 00158 #elif (WEB_SOCKET_CNONCE_SIZE < 1) 00159 #error WEB_SOCKET_CNONCE_SIZE parameter is not valid 00160 #endif 00161 00162 //TLS supported? 00163 #if (WEB_SOCKET_TLS_SUPPORT == ENABLED) 00164 #include "crypto.h" 00165 #include "tls.h" 00166 #endif 00167 00168 //Client key size 00169 #define WEB_SOCKET_CLIENT_KEY_SIZE 24 00170 //Server key size 00171 #define WEB_SOCKET_SERVER_KEY_SIZE 28 00172 00173 //Forward declaration of WebSocket structure 00174 struct _WebSocket; 00175 #define WebSocket struct _WebSocket 00176 00177 00178 /** 00179 * @brief WebSocket endpoint types 00180 **/ 00181 00182 typedef enum 00183 { 00184 WS_ENDPOINT_CLIENT = 0, 00185 WS_ENDPOINT_SERVER = 1 00186 } WebSocketEndpoint; 00187 00188 00189 /** 00190 * @brief HTTP version numbers 00191 **/ 00192 00193 typedef enum 00194 { 00195 WS_HTTP_VERSION_0_9 = 0x0009, 00196 WS_HTTP_VERSION_1_0 = 0x0100, 00197 WS_HTTP_VERSION_1_1 = 0x0101 00198 } WebSocketHttpVersion; 00199 00200 00201 /** 00202 * @brief Authentication schemes 00203 **/ 00204 00205 typedef enum 00206 { 00207 WS_AUTH_MODE_NONE = 0x00, 00208 WS_AUTH_MODE_BASIC = 0x01, 00209 WS_AUTH_MODE_DIGEST = 0x02 00210 } WebSocketAuthMode; 00211 00212 00213 /** 00214 * @brief WebSocket states 00215 **/ 00216 00217 typedef enum 00218 { 00219 WS_STATE_UNUSED = 0, 00220 WS_STATE_CLOSED = 1, 00221 WS_STATE_INIT = 2, 00222 WS_STATE_CONNECTING = 3, 00223 WS_STATE_CLIENT_HANDSHAKE = 4, 00224 WS_STATE_SERVER_HANDSHAKE = 5, 00225 WS_STATE_SERVER_RESP_BODY = 6, 00226 WS_STATE_OPEN = 7, 00227 WS_STATE_CLOSING_TX = 8, 00228 WS_STATE_CLOSING_RX = 9, 00229 WS_STATE_SHUTDOWN = 10, 00230 } WebSocketState; 00231 00232 00233 /** 00234 * @brief WebSocket sub-states 00235 **/ 00236 00237 typedef enum 00238 { 00239 WS_SUB_STATE_INIT = 0, 00240 //Handshake decoding 00241 WS_SUB_STATE_HANDSHAKE_LEADING_LINE = 1, 00242 WS_SUB_STATE_HANDSHAKE_HEADER_FIELD = 2, 00243 WS_SUB_STATE_HANDSHAKE_LWSP = 3, 00244 //WebSocket frame decoding 00245 WS_SUB_STATE_FRAME_HEADER = 4, 00246 WS_SUB_STATE_FRAME_EXT_HEADER = 5, 00247 WS_SUB_STATE_FRAME_PAYLOAD = 6 00248 } WebSocketSubState; 00249 00250 00251 /** 00252 * @brief WebSocket frame types 00253 **/ 00254 00255 typedef enum 00256 { 00257 WS_FRAME_TYPE_CONTINUATION = 0x00, 00258 WS_FRAME_TYPE_TEXT = 0x01, 00259 WS_FRAME_TYPE_BINARY = 0x02, 00260 WS_FRAME_TYPE_CLOSE = 0x08, 00261 WS_FRAME_TYPE_PING = 0x09, 00262 WS_FRAME_TYPE_PONG = 0x0A 00263 } WebSocketFrameType; 00264 00265 00266 /** 00267 * @brief WebSocket status codes 00268 **/ 00269 00270 typedef enum 00271 { 00272 WS_STATUS_CODE_NORMAL_CLOSURE = 1000, 00273 WS_STATUS_CODE_GOING_AWAY = 1001, 00274 WS_STATUS_CODE_PROTOCOL_ERROR = 1002, 00275 WS_STATUS_CODE_UNSUPPORTED_DATA = 1003, 00276 WS_STATUS_CODE_NO_STATUS_RCVD = 1005, 00277 WS_STATUS_CODE_ABNORMAL_CLOSURE = 1006, 00278 WS_STATUS_CODE_INVALID_PAYLOAD_DATA = 1007, 00279 WS_STATUS_CODE_POLICY_VIOLATION = 1008, 00280 WS_STATUS_CODE_MESSAGE_TOO_BIG = 1009, 00281 WS_STATUS_CODE_MANDATORY_EXT = 1010, 00282 WS_STATUS_CODE_INTERNAL_ERROR = 1011, 00283 WS_STATUS_CODE_TLS_HANDSHAKE = 1015 00284 } WebSocketStatusCode; 00285 00286 00287 //CodeWarrior or Win32 compiler? 00288 #if defined(__CWCC__) || defined(_WIN32) 00289 #pragma pack(push, 1) 00290 #endif 00291 00292 00293 /** 00294 * @brief WebSocket frame 00295 **/ 00296 00297 typedef __start_packed struct 00298 { 00299 #ifdef _CPU_BIG_ENDIAN 00300 uint8_t fin : 1; //0 00301 uint8_t reserved : 3; 00302 uint8_t opcode : 4; 00303 uint8_t mask : 1; //1 00304 uint8_t payloadLen: 7; 00305 #else 00306 uint8_t opcode : 4; //0 00307 uint8_t reserved : 3; 00308 uint8_t fin : 1; 00309 uint8_t payloadLen: 7; //1 00310 uint8_t mask : 1; 00311 #endif 00312 uint8_t extPayloadLen[]; //2 00313 } __end_packed WebSocketFrame; 00314 00315 00316 //CodeWarrior or Win32 compiler? 00317 #if defined(__CWCC__) || defined(_WIN32) 00318 #pragma pack(pop) 00319 #endif 00320 00321 00322 /** 00323 * @brief Random data generation callback function 00324 **/ 00325 00326 typedef error_t (*WebSocketRandCallback)(uint8_t *data, size_t length); 00327 00328 00329 //WebSocket connections over SSL/TLS supported? 00330 #if (WEB_SOCKET_TLS_SUPPORT == ENABLED) 00331 00332 /** 00333 * @brief SSL/TLS initialization callback function 00334 **/ 00335 00336 typedef error_t (*WebSocketTlsInitCallback)(WebSocket *webSocket, 00337 TlsContext *tlsContext); 00338 00339 #endif 00340 00341 00342 /** 00343 * @brief Authentication context 00344 **/ 00345 00346 typedef struct 00347 { 00348 uint_t allowedAuthModes; 00349 WebSocketAuthMode requiredAuthMode; 00350 WebSocketAuthMode selectedAuthMode; 00351 char_t username[WEB_SOCKET_USERNAME_MAX_LEN + 1]; 00352 char_t password[WEB_SOCKET_PASSWORD_MAX_LEN + 1]; 00353 char_t realm[WEB_SOCKET_REALM_MAX_LEN + 1]; 00354 #if (WEB_SOCKET_DIGEST_AUTH_SUPPORT == ENABLED) 00355 uint32_t nc; 00356 char_t nonce[WEB_SOCKET_NONCE_MAX_LEN + 1]; 00357 char_t cnonce[WEB_SOCKET_CNONCE_SIZE * 2 + 1]; 00358 char_t opaque[WEB_SOCKET_OPAQUE_MAX_LEN + 1]; 00359 bool_t stale; 00360 #endif 00361 } WebSocketAuthContext; 00362 00363 00364 /** 00365 * @brief Handshake context 00366 **/ 00367 00368 typedef struct 00369 { 00370 uint_t version; 00371 uint_t statusCode; 00372 bool_t upgradeWebSocket; 00373 bool_t connectionUpgrade; 00374 bool_t connectionClose; 00375 size_t contentLength; 00376 char_t clientKey[WEB_SOCKET_CLIENT_KEY_SIZE + 1]; 00377 char_t serverKey[WEB_SOCKET_SERVER_KEY_SIZE + 1]; 00378 bool_t closingFrameSent; 00379 bool_t closingFrameReceived; 00380 } WebSocketHandshakeContext; 00381 00382 00383 /** 00384 * @brief Frame encoding/decoding context 00385 **/ 00386 00387 typedef struct 00388 { 00389 WebSocketSubState state; ///FSM state 00390 WebSocketFrameType dataFrameType; ///<Data frame type 00391 WebSocketFrameType controlFrameType; ///<Control frame type 00392 bool_t fin; ///<Final fragment in a message 00393 bool_t mask; ///<Defines whether the payload data is masked 00394 uint8_t maskingKey[4]; ///<Masking key 00395 size_t payloadLen; ///<Payload length 00396 size_t payloadPos; ///<Current position 00397 uint8_t buffer[WEB_SOCKET_BUFFER_SIZE]; ///<Data buffer 00398 size_t bufferLen; ///<Length of the data buffer 00399 size_t bufferPos; ///<Current position 00400 } WebSocketFrameContext; 00401 00402 00403 /** 00404 * @brief UTF-8 decoding context 00405 **/ 00406 00407 typedef struct 00408 { 00409 uint_t utf8CharSize; 00410 uint_t utf8CharIndex; 00411 uint32_t utf8CodePoint; 00412 } WebSocketUtf8Context; 00413 00414 00415 /** 00416 * @brief Structure describing a WebSocket 00417 **/ 00418 00419 struct _WebSocket 00420 { 00421 WebSocketEndpoint endpoint; ///<Endpoint type (client or server) 00422 WebSocketState state; ///<WebSocket connection state 00423 uint16_t statusCode; 00424 systime_t timestamp; 00425 uint_t retryCount; 00426 char_t host[WEB_SOCKET_HOST_MAX_LEN + 1]; 00427 char_t origin[WEB_SOCKET_ORIGIN_MAX_LEN + 1]; 00428 char_t subProtocol[WEB_SOCKET_SUB_PROTOCOL_MAX_LEN + 1]; 00429 char_t uri[WEB_SOCKET_URI_MAX_LEN + 1]; 00430 char_t queryString[WEB_SOCKET_QUERY_STRING_MAX_LEN + 1]; 00431 systime_t timeout; ///<timeout value for blocking operations 00432 NetInterface *interface; ///<Underlying network interface 00433 Socket *socket; ///<Underlying TCP socket 00434 #if (WEB_SOCKET_TLS_SUPPORT == ENABLED) 00435 TlsContext *tlsContext; ///<SSL/TLS context 00436 TlsSession tlsSession; ///<SSL/TLS session 00437 WebSocketTlsInitCallback tlsInitCallback; ///<SSL/TLS initialization callback function 00438 #endif 00439 #if (WEB_SOCKET_BASIC_AUTH_SUPPORT == ENABLED || WEB_SOCKET_DIGEST_AUTH_SUPPORT == ENABLED) 00440 WebSocketAuthContext authContext; 00441 #endif 00442 WebSocketHandshakeContext handshakeContext; 00443 WebSocketFrameContext txContext; 00444 WebSocketFrameContext rxContext; 00445 WebSocketUtf8Context utf8Context; 00446 }; 00447 00448 00449 //Random data generation callback function 00450 extern WebSocketRandCallback webSockRandCallback; 00451 00452 //WebSocket related functions 00453 error_t webSocketInit(void); 00454 00455 error_t webSocketRegisterRandCallback(WebSocketRandCallback callback); 00456 00457 WebSocket *webSocketOpen(void); 00458 WebSocket *webSocketUpgradeSocket(Socket *socket); 00459 00460 #if (WEB_SOCKET_TLS_SUPPORT == ENABLED) 00461 00462 WebSocket *webSocketUpgradeSecureSocket(Socket *socket, TlsContext *tlsContext); 00463 00464 error_t webSocketRegisterTlsInitCallback(WebSocket *webSocket, 00465 WebSocketTlsInitCallback callback); 00466 00467 #endif 00468 00469 error_t webSocketSetTimeout(WebSocket *webSocket, systime_t timeout); 00470 00471 error_t webSocketSetHost(WebSocket *webSocket, const char_t *host); 00472 error_t webSocketSetOrigin(WebSocket *webSocket, const char_t *origin); 00473 error_t webSocketSetSubProtocol(WebSocket *webSocket, const char_t *subProtocol); 00474 00475 error_t webSocketSetAuthInfo(WebSocket *webSocket, const char_t *username, 00476 const char_t *password, uint_t allowedAuthModes); 00477 00478 error_t webSocketBindToInterface(WebSocket *webSocket, NetInterface *interface); 00479 00480 error_t webSocketConnect(WebSocket *webSocket, const IpAddr *serverIpAddr, 00481 uint16_t serverPort, const char_t *uri); 00482 00483 error_t webSocketSetClientKey(WebSocket *webSocket, const char_t *clientKey); 00484 error_t webSocketParseClientHandshake(WebSocket *webSocket); 00485 error_t webSocketSendServerHandshake(WebSocket *webSocket); 00486 00487 error_t webSocketSendErrorResponse(WebSocket *webSocket, 00488 uint_t statusCode, const char_t *message); 00489 00490 error_t webSocketSend(WebSocket *webSocket, const void *data, 00491 size_t length, WebSocketFrameType type, size_t *written); 00492 00493 error_t webSocketSendEx(WebSocket *webSocket, const void *data, size_t length, 00494 WebSocketFrameType type, size_t *written, bool_t firstFrag, bool_t lastFrag); 00495 00496 error_t webSocketReceive(WebSocket *webSocket, void *data, 00497 size_t size, WebSocketFrameType *type, size_t *received); 00498 00499 error_t webSocketReceiveEx(WebSocket *webSocket, void *data, size_t size, 00500 WebSocketFrameType *type, size_t *received, bool_t *firstFrag, bool_t *lastFrag); 00501 00502 bool_t webSocketIsRxReady(WebSocket *webSocket); 00503 error_t webSocketShutdown(WebSocket *webSocket); 00504 void webSocketClose(WebSocket *webSocket); 00505 00506 #endif 00507
Generated on Tue Jul 12 2022 17:10:17 by
