Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers web_socket.h Source File

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