/* ********************************************************************************************************* * uC/HTTP * Hypertext Transfer Protocol * * Copyright 2004-2020 Silicon Laboratories Inc. www.silabs.com * * SPDX-License-Identifier: APACHE-2.0 * * This software is subject to an open source license and is distributed by * Silicon Laboratories Inc. pursuant to the terms of the Apache License, * Version 2.0 available at www.apache.org/licenses/LICENSE-2.0. * ********************************************************************************************************* */ /* ********************************************************************************************************* * * HTTP CLIENT WEBSOCKET MODULE * * Filename : http-c_websock.h * Version : V3.01.00 ********************************************************************************************************* */ /* ********************************************************************************************************* ********************************************************************************************************* * INCLUDE FILES ********************************************************************************************************* ********************************************************************************************************* */ #include #include "include/lib_def.h" #include "include/lib_str.h" #include "include/lib_ascii.h" #include "http-c_cfg.h" #include "http.h" #include "http-c.h" #include "include/net.h" #include "include/net_base64.h" #include "include/net_sha1.h" /* ********************************************************************************************************* ********************************************************************************************************* * MODULE * * Note(s) : (1) This main network protocol suite header file is protected from multiple pre-processor * inclusion through use of the HTTPc module present pre-processor macro definition. * * (2) The following HTTPc-WebSocket-module configuration value MUST be pre-#define'd in * 'http-c.h' PRIOR to all other HTTPc modules that require the WebSocket Layer configuration: * * HTTPc_WEBSOCK_MODULE_EN ********************************************************************************************************* ********************************************************************************************************* */ #ifndef HTTPc_WEBSOCK_MODULE_PRESENT /* See Note #1. */ #define HTTPc_WEBSOCK_MODULE_PRESENT #ifdef HTTPc_WEBSOCK_MODULE_EN /* See Note #2. */ /* ********************************************************************************************************* ********************************************************************************************************* * DEFINES ********************************************************************************************************* ********************************************************************************************************* */ /* ********************************************************************************************************* * WEBSOCKET HANDSHAKE DEFINES ********************************************************************************************************* */ #define HTTPc_WEBSOCK_GUID_STRING "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" #define HTTPc_WEBSOCK_GUID_STRING_LEN sizeof(HTTPc_WEBSOCK_GUID_STRING) #define HTTPc_WEBSOCK_PROTOCOL_VERSION_13 13u #define HTTPc_WEBSOCK_PROTOCOL_VERSION_13_STR "13" #define HTTPc_WEBSOCK_PROTOCOL_VERSION_13_STR_LEN sizeof(HTTPc_WEBSOCK_PROTOCOL_VERSION_13_STR) - 1 #define HTTPc_WEBSOCK_KEY_LEN 16 #define HTTPc_WEBSOCK_KEY_ENCODED_LEN NET_BASE64_ENCODER_OUT_MAX_LEN(HTTPc_WEBSOCK_KEY_LEN) #define HTTPc_WEBSOCK_KEY_PRE_HASH_LEN (HTTPc_WEBSOCK_KEY_ENCODED_LEN - 1) + (HTTPc_WEBSOCK_GUID_STRING_LEN - 1) #define HTTPc_WEBSOCK_KEY_HASH_LEN NET_SHA1_HASH_SIZE #define HTTPc_WEBSOCK_KEY_HASH_ENCODED_LEN NET_BASE64_ENCODER_OUT_MAX_LEN(NET_SHA1_HASH_SIZE) /* ********************************************************************************************************* * WEBSOCKET FRAME LEN DEFINITION ********************************************************************************************************* */ #define HTTPc_WEBSOCK_SMALL_FRAME_MIN_LEN 0u #define HTTPc_WEBSOCK_SMALL_FRAME_MAX_LEN 125u #define HTTPc_WEBSOCK_NORMAL_FRAME_MIN_LEN 126u #define HTTPc_WEBSOCK_NORMAL_FRAME_MAX_LEN DEF_INT_16U_MAX_VAL #define HTTPc_WEBSOCK_NORMAL_FRAME_CODE 126u #define HTTPc_WEBSOCK_LONG_FRAME_MIN_LEN DEF_INT_16U_MAX_VAL + 1 #define HTTPc_WEBSOCK_LONG_FRAME_MAX_LEN DEF_INT_32U_MAX_VAL #define HTTPc_WEBSOCK_LONG_FRAME_CODE 127u #define HTTPc_WEBSOCK_MAX_CTRL_FRAME_LEN HTTPc_WEBSOCK_SMALL_FRAME_MAX_LEN #define HTTPc_WEBSOCK_CLOSE_CODE_LEN sizeof(CPU_INT16U) #define HTTPc_WEBSOCK_MAX_CLOSE_REASON_LEN HTTPc_WEBSOCK_MAX_CTRL_FRAME_LEN - HTTPc_WEBSOCK_CLOSE_CODE_LEN /* ********************************************************************************************************* * WEBSOCKET REQUEST FLAGS ********************************************************************************************************* */ #define HTTPc_FLAG_WEBSOCK_REQ_CONN_UPGRADE DEF_BIT_00 #define HTTPc_FLAG_WEBSOCK_REQ_UPGRADE_WEBSOCKET DEF_BIT_01 #define HTTPc_FLAG_WEBSOCK_REQ_ACCEPT_VALIDATED DEF_BIT_02 #define HTTPc_FLAG_WEBSOCK_REQ_VERSION_VALIDATED DEF_BIT_03 #define HTTPc_FLAG_WEBSOCK_REQ_IN_USE DEF_BIT_04 #define HTTPc_FLAG_WEBSOCK_ALL (HTTPc_FLAG_WEBSOCK_REQ_CONN_UPGRADE | \ HTTPc_FLAG_WEBSOCK_REQ_UPGRADE_WEBSOCKET | \ HTTPc_FLAG_WEBSOCK_REQ_ACCEPT_VALIDATED) /* ********************************************************************************************************* ********************************************************************************************************* * DATA TYPES ********************************************************************************************************* ********************************************************************************************************* */ /* ********************************************************************************************************* * WEBSOCKET CLOSE REASON STRUCTURE ********************************************************************************************************* */ typedef struct httpc_websock_close_reason { CPU_CHAR *DataPtr; CPU_INT08U Len; } HTTPc_WEBSOCK_CLOSE_REASON; /* ********************************************************************************************************* * WEBSOCKET FLAGS ********************************************************************************************************* */ typedef struct httpc_flag_websock_msg { CPU_INT08U IsUsed : 1; CPU_INT08U IsNoBlock : 1; CPU_INT08U IsFin : 1; CPU_INT08U IsMasked : 1; CPU_INT08U IsHdrSet : 1; CPU_INT08U IsCompleted : 1; } HTTPc_FLAG_WEBSOCK_MSG; typedef struct httpc_flag_websock { CPU_INT08U IsTxMsgCtrlUsed : 1; CPU_INT08U IsRxDataCached : 1; CPU_INT08U IsWebsockUsed : 1; CPU_INT08U IsCloseStarted : 1; CPU_INT08U IsPongStarted : 1; } HTTPc_FLAG_WEBSOCK; typedef struct httpc_flag_websock_rx { CPU_INT08U IsFin : 1; CPU_INT08U IsMasked : 1; } HTTPc_FLAG_WEBSOCK_RX; /* ********************************************************************************************************* * WEBSOCKET INTERNAL STATES ********************************************************************************************************* */ typedef enum { HTTPc_WEBSOCK_TX_STATE_MSG_INIT, HTTPc_WEBSOCK_TX_STATE_SET_BUF, HTTPc_WEBSOCK_TX_STATE_SEND_BUF, HTTPc_WEBSOCK_TX_STATE_COMPLETE, } HTTPc_WEBSOCK_TX_STATE; typedef enum { HTTPc_WEBSOCK_RX_STATE_WAIT, HTTPc_WEBSOCK_RX_STATE_HDR, HTTPc_WEBSOCK_RX_STATE_PREPARE, HTTPc_WEBSOCK_RX_STATE_PAYLOAD, HTTPc_WEBSOCK_RX_STATE_COMPLETE, } HTTPc_WEBSOCK_RX_STATE; /* ********************************************************************************************************* * HOOK & CALLBACK FUNCTIONS DATA TYPE ********************************************************************************************************* */ typedef void (*HTTPc_WEBSOCK_ON_OPEN)(HTTPc_CONN_OBJ *p_conn); typedef void (*HTTPc_WEBSOCK_ON_CLOSE)(HTTPc_CONN_OBJ *p_conn, HTTPc_WEBSOCK_CLOSE_CODE close_code, HTTPc_WEBSOCK_CLOSE_REASON *p_reason); typedef void (*HTTPc_WEBSOCK_ON_RX_INIT)(HTTPc_CONN_OBJ *p_conn, HTTPc_WEBSOCK_MSG_TYPE msg_type, CPU_INT32U msg_len, void **p_data); typedef CPU_INT32U(*HTTPc_WEBSOCK_ON_RX_DATA)(HTTPc_CONN_OBJ *p_conn, HTTPc_WEBSOCK_MSG_TYPE msg_type, void *p_data, CPU_INT16U data_len); typedef void (*HTTPc_WEBSOCK_ON_RX_COMPLETE)(HTTPc_CONN_OBJ *p_conn); typedef CPU_INT32U(*HTTPc_WEBSOCK_ON_TX_INIT)(HTTPc_CONN_OBJ *p_conn, HTTPc_WEBSOCK_MSG_OBJ *p_ws_msg); typedef CPU_INT32U(*HTTPc_WEBSOCK_ON_TX_DATA)(HTTPc_CONN_OBJ *p_conn, HTTPc_WEBSOCK_MSG_OBJ *p_websock_msg, CPU_CHAR *p_buf, CPU_INT32U buf_len); typedef void (*HTTPc_WEBSOCK_ON_TX_COMPLETE)(HTTPc_CONN_OBJ *p_conn, HTTPc_WEBSOCK_MSG_OBJ *p_websock_msg, CPU_BOOLEAN status); typedef void (*HTTPc_WEBSOCK_ON_ERR)(HTTPc_CONN_OBJ *p_conn, HTTPc_ERR err); typedef void (*HTTPc_WEBSOCK_ON_PONG)(HTTPc_CONN_OBJ *p_conn, CPU_CHAR *p_data, CPU_INT16U data_len); /* ********************************************************************************************************* * WEBSOCKET MSG TASK CALLBACK FIELDS MACRO ********************************************************************************************************* */ #define TASK_WEBSOCK_MSG_CALLBACK_FIELDS_DEF(prefix, suffix) FIELD_DEF(prefix, HTTPc_WEBSOCK_ON_TX_INIT, OnMsgTxInit, suffix) \ FIELD_DEF(prefix, HTTPc_WEBSOCK_ON_TX_DATA, OnMsgTxData, suffix) \ FIELD_DEF(prefix, HTTPc_WEBSOCK_ON_TX_COMPLETE, OnMsgTxComplete, suffix) /* ********************************************************************************************************* * WEBSOCKET TASK CALLBACK FIELDS MACRO ********************************************************************************************************* */ #define TASK_WEBSOCK_CALLBACK_FIELDS_DEF(prefix, suffix) FIELD_DEF(prefix, HTTPc_WEBSOCK_ON_OPEN, OnOpen, suffix) \ FIELD_DEF(prefix, HTTPc_WEBSOCK_ON_CLOSE, OnClose, suffix) \ FIELD_DEF(prefix, HTTPc_WEBSOCK_ON_ERR, OnErr, suffix) \ FIELD_DEF(prefix, HTTPc_WEBSOCK_ON_RX_INIT, OnMsgRxInit, suffix) \ FIELD_DEF(prefix, HTTPc_WEBSOCK_ON_RX_DATA, OnMsgRxData, suffix) \ FIELD_DEF(prefix, HTTPc_WEBSOCK_ON_RX_COMPLETE, OnMsgRxComplete, suffix) \ FIELD_DEF(prefix, HTTPc_WEBSOCK_ON_PONG, OnPong, suffix) /* ********************************************************************************************************* * WEBSOCKET REQUEST STRUCTURE ********************************************************************************************************* */ struct httpc_websock_req { CPU_CHAR Key[HTTPc_WEBSOCK_KEY_ENCODED_LEN]; CPU_CHAR Accept[HTTPc_WEBSOCK_KEY_HASH_ENCODED_LEN]; CPU_INT08U Flags; HTTPc_WEBSOCK *WebSockObjPtr; }; /* ********************************************************************************************************* * WEBSOCKET MESSAGE STRUCTURE MACRO ********************************************************************************************************* */ #define STRUCT_WS_MSG_INIT(prefix, suffix) \ FIELD_DEF(prefix, HTTPc_FLAG_WEBSOCK_MSG, Flags, suffix) \ FIELD_DEF(prefix, HTTPc_WEBSOCK_OPCODE, OpCode, suffix) \ FIELD_DEF(prefix, CPU_INT32U, Len, suffix) \ FIELD_DEF(prefix, CPU_INT32U, DataLen, suffix) \ FIELD_DEF(prefix, CPU_INT32U, LenSent, suffix) \ FIELD_DEF(prefix, CPU_INT32U, MskKey, suffix) \ FIELD_DEF(prefix, void, *DataPtr, suffix) \ FIELD_DEF(prefix, HTTPc_CONN, *ConnPtr, suffix) \ FIELD_DEF(prefix, HTTPc_WEBSOCK_MSG, *NextPtr, suffix) \ TASK_WEBSOCK_MSG_CALLBACK_FIELDS_DEF(prefix, suffix) \ USER_DATA_FIELD_DEF(,) struct httpc_websock_msg_obj { STRUCT_WS_MSG_INIT(const, _reserved) }; struct httpc_websock_msg { STRUCT_WS_MSG_INIT(,) }; /* ********************************************************************************************************* * WEBSOCKET STRUCTURE MACRO ********************************************************************************************************* */ #define STRUCT_WS_INIT(prefix, suffix) \ FIELD_DEF(prefix, HTTPc_FLAG_WEBSOCK, Flags, suffix) \ FIELD_DEF(prefix, HTTPc_WEBSOCK_MSG, *TxMsgListHeadPtr, suffix) \ FIELD_DEF(prefix, HTTPc_WEBSOCK_MSG, *TxMsgListEndPtr, suffix) \ FIELD_DEF(prefix, HTTPc_WEBSOCK_MSG, TxMsgCtrl, suffix) \ FIELD_DEF(prefix, HTTPc_WEBSOCK_OPCODE, RxMsgOpCode, suffix) \ FIELD_DEF(prefix, HTTPc_FLAG_WEBSOCK_RX, RxMsgFlags, suffix) \ FIELD_DEF(prefix, CPU_INT32U, RxMsgLen, suffix) \ FIELD_DEF(prefix, CPU_INT32U, RxMsgLenRead, suffix) \ FIELD_DEF(prefix, CPU_INT32U, RxMsgMskKey, suffix) \ FIELD_DEF(prefix, CPU_CHAR, *RxMsgDataPtr, suffix) \ FIELD_DEF(prefix, HTTPc_WEBSOCK_TX_STATE, TxState, suffix) \ FIELD_DEF(prefix, HTTPc_WEBSOCK_RX_STATE, RxState, suffix) \ FIELD_DEF(prefix, HTTPc_WEBSOCK_CLOSE_CODE, CloseCode, suffix) \ FIELD_DEF(prefix, HTTPc_WEBSOCK_CLOSE_REASON, CloseReason, suffix) \ FIELD_DEF(prefix, CPU_INT32U, TotalMsgLen, suffix) \ FIELD_DEF(prefix, HTTPc_WEBSOCK_OPCODE, OrigOpCode, suffix) \ TASK_WEBSOCK_CALLBACK_FIELDS_DEF(prefix, suffix) \ USER_DATA_FIELD_DEF(,) struct httpc_websock_obj { STRUCT_WS_INIT(const, _reserved) }; struct httpc_websock { STRUCT_WS_INIT(,) }; /* ********************************************************************************************************* ********************************************************************************************************* * FUNCTION PROTOTYPES ********************************************************************************************************* ********************************************************************************************************* */ void HTTPcWebSock_Process(HTTPc_CONN *p_conn); HTTPc_WEBSOCK_REQ *HTTPcWebSock_InitReqObj(HTTPc_ERR *p_err); void HTTPcWebSock_TxMsgAdd(HTTPc_WEBSOCK_MSG *p_msg, HTTPc_ERR *p_err); /* ********************************************************************************************************* ********************************************************************************************************* * MODULE END ********************************************************************************************************* ********************************************************************************************************* */ #endif /* HTTPc_WEBSOCK_MODULE_EN */ #endif /* HTTPc_WEBSOCK_MODULE_PRESENT */