1622 lines
60 KiB
C
1622 lines
60 KiB
C
/*
|
|
*********************************************************************************************************
|
|
* 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.c
|
|
* Version : V3.01.00
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
* INCLUDE FILES
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
#define MICRIUM_SOURCE
|
|
#define HTTPc_WEBSOCK_MODULE
|
|
|
|
#include <net_ascii.h>
|
|
#include <net_util.h>
|
|
#include <lib_def.h>
|
|
#include <lib_math.h>
|
|
|
|
#include <net.h>
|
|
#include <net_cfg_net.h>
|
|
#include <net_app.h>
|
|
#include <net_sock.h>
|
|
#include <net_util.h>
|
|
|
|
|
|
#include "http-c_websock.h"
|
|
#include "http-c_conn.h"
|
|
#include "http-c_sock.h"
|
|
#include "http-c_req.h"
|
|
#include "http-c_resp.h"
|
|
#ifdef HTTPc_TASK_MODULE_EN
|
|
#include "http-c_task.h"
|
|
#endif
|
|
|
|
//添加宏定义
|
|
#undef HTTPc_WEBSOCK_MODULE_EN
|
|
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
* MODULE
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
#ifdef HTTPc_WEBSOCK_MODULE_EN
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
* LOCAL DEFINES
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
#define HTTPc_WEBSOCK_TX_REQ_Q_NAME "WebSocket Tx Req Q name"
|
|
|
|
#define HTTPc_WEBSOCK_PROTOCOL_ERR_MSG "\x03\xEAProtocolError"
|
|
|
|
#define HTTPc_WEBSOCK_MIN_HEADER_LEN 2u
|
|
#define HTTPc_WEBSOCK_MAX_HEADER_LEN 14u
|
|
|
|
#define HTTPc_WEBSOCK_FIN_BIT DEF_BIT_07
|
|
#define HTTPc_WEBSOCK_MASK_BIT DEF_BIT_07
|
|
#define HTTPc_WEBSOCK_OPCODE_MASK DEF_NIBBLE_MASK
|
|
#define HTTPc_WEBSOCK_PAYLOAD_MASK 0x7F
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
* LOCAL MACRO'S
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
#define HTTPc_WEBSOCK_GET_TX_BUF_SIZE(p_conn) (p_conn->BufLen - p_conn->TxDataLen - (p_conn->TxBufPtr - p_conn->BufPtr))
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
* LOCAL FUNCTION PROTOTYPES
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void HTTPcWebSock_TX(HTTPc_CONN *p_conn);
|
|
|
|
static void HTTPcWebSock_RX(HTTPc_CONN *p_conn);
|
|
|
|
static CPU_INT32U HTTPcWebSock_GetMsgHdr(HTTPc_CONN *p_conn,
|
|
HTTPc_ERR *p_err);
|
|
|
|
static void HTTPcWebSock_GetPayload(HTTPc_CONN *p_conn);
|
|
|
|
static void HTTPcWebSock_SetTxBuf(HTTPc_WEBSOCK_MSG *p_msg,
|
|
CPU_CHAR *p_dst_buf,
|
|
CPU_CHAR *p_src_buf,
|
|
CPU_INT32U len);
|
|
|
|
|
|
static void HTTPcWebSock_SetTxBufHdr(HTTPc_CONN *p_conn,
|
|
HTTPc_WEBSOCK_MSG *p_tx_msg,
|
|
CPU_CHAR *p_tx_buf);
|
|
|
|
|
|
static void HTTPcWebSock_SetCtrlResponse(HTTPc_CONN *p_conn,
|
|
HTTPc_WEBSOCK_OPCODE opcode,
|
|
CPU_CHAR *p_data,
|
|
CPU_INT32U msg_len);
|
|
|
|
static void HTTPcWebSock_TxMsgRemove(HTTPc_CONN *p_conn);
|
|
|
|
static void HTTPcWebSock_TxMsgCleanList(HTTPc_CONN *p_conn);
|
|
|
|
static CPU_INT16U HTTPcWebSock_ComputeHdrLen(HTTPc_WEBSOCK_MSG *p_msg);
|
|
|
|
static CPU_BOOLEAN HTTPcWebSock_IsProtocolError(HTTPc_ERR err);
|
|
|
|
static CPU_BOOLEAN HTTPcWebSock_IsStandardCloseCode(HTTPc_WEBSOCK_CLOSE_CODE close_code);
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPcWebSock_Process()
|
|
*
|
|
* Description : Process all the states for a HTTP connection that has been upgraded to a WebSocket.
|
|
*
|
|
* Argument(s) : p_conn Pointer to current HTTPc Connection (WebSocket Upgraded).
|
|
*
|
|
* Return(s) : none.
|
|
*
|
|
* Caller(s) : HTTPcTask_Handler().
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
void HTTPcWebSock_Process(HTTPc_CONN *p_conn)
|
|
{
|
|
HTTPc_CONN_OBJ *p_conn_const;
|
|
HTTPc_WEBSOCK *p_ws;
|
|
CPU_BOOLEAN is_protocol_err;
|
|
|
|
|
|
p_conn_const = (HTTPc_CONN_OBJ *)p_conn;
|
|
p_ws = p_conn->WebSockPtr;
|
|
|
|
switch (p_conn->State) {
|
|
|
|
case HTTPc_CONN_STATE_WEBSOCK_INIT:
|
|
/* WebSocket OnOpen Hook. */
|
|
if (p_ws->OnOpen != DEF_NULL) {
|
|
p_ws->OnOpen(p_conn_const);
|
|
}
|
|
/* Set the WebSocket initial state. */
|
|
p_ws->TxState = HTTPc_WEBSOCK_TX_STATE_MSG_INIT;
|
|
p_ws->RxState = HTTPc_WEBSOCK_RX_STATE_WAIT;
|
|
p_conn->State = HTTPc_CONN_STATE_WEBSOCK_RXTX;
|
|
break;
|
|
|
|
|
|
case HTTPc_CONN_STATE_WEBSOCK_RXTX:
|
|
|
|
HTTPcWebSock_TX(p_conn); /* Process Tx states of the WebSocket. */
|
|
HTTPcWebSock_RX(p_conn); /* Process Rx states of the WebSocket. */
|
|
break;
|
|
|
|
|
|
case HTTPc_CONN_STATE_WEBSOCK_ERR:
|
|
/* WebSocket OnErr hook. */
|
|
if (p_ws->OnErr != DEF_NULL) {
|
|
p_ws->OnErr(p_conn_const, p_conn->ErrCode);
|
|
}
|
|
|
|
is_protocol_err = HTTPcWebSock_IsProtocolError(p_conn->ErrCode);
|
|
if (is_protocol_err == DEF_YES) { /* Send a Close Frame if the Err Code a Protocol Error. */
|
|
p_ws->CloseCode = HTTPc_WEBSOCK_CLOSE_CODE_PROTOCOL_ERR;
|
|
|
|
if (p_ws->Flags.IsTxMsgCtrlUsed == DEF_NO) {
|
|
HTTPcWebSock_SetCtrlResponse(p_conn,
|
|
HTTPc_WEBSOCK_OPCODE_CLOSE,
|
|
HTTPc_WEBSOCK_PROTOCOL_ERR_MSG,
|
|
sizeof(HTTPc_WEBSOCK_PROTOCOL_ERR_MSG));
|
|
|
|
p_ws->Flags.IsCloseStarted = DEF_YES;
|
|
p_ws->RxState = HTTPc_WEBSOCK_RX_STATE_WAIT;
|
|
p_conn->State = HTTPc_CONN_STATE_WEBSOCK_RXTX;
|
|
|
|
} else { /* If the ctrl msg is already used, close the conn. */
|
|
p_conn->State = HTTPc_CONN_STATE_WEBSOCK_CLOSE;
|
|
}
|
|
} else {
|
|
p_conn->State = HTTPc_CONN_STATE_WEBSOCK_CLOSE;
|
|
}
|
|
break;
|
|
|
|
|
|
case HTTPc_CONN_STATE_WEBSOCK_CLOSE:
|
|
/* WebSocket OnClose hook. */
|
|
if (p_ws->OnClose != DEF_NULL) {
|
|
p_ws->OnClose(p_conn_const, p_ws->CloseCode, &p_ws->CloseReason);
|
|
}
|
|
|
|
HTTPcWebSock_TxMsgCleanList(p_conn); /* Empty the Tx Msg request pending list. */
|
|
/* Change state to remove and close the conn. */
|
|
p_conn->State = HTTPc_CONN_STATE_CLOSE;
|
|
break;
|
|
|
|
|
|
default:
|
|
CPU_SW_EXCEPTION(;);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPcWebSock_InitReqObj()
|
|
*
|
|
* Description : Initialize the WebSocket Request object.
|
|
*
|
|
* Argument(s) : p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* HTTPc_ERR_NONE
|
|
* HTTPc_ERR_WEBSOCK_BASE64_ENCODE_FAIL
|
|
* HTTPc_ERR_WEBSOCK_SHA1_ENCODE_FAIL
|
|
* HTTPc_ERR_WEBSOCK_REQ_MEM_ERR
|
|
*
|
|
* Return(s) : If the operation is successful, pointer to the WebSocket Request object to initialize.
|
|
* If the operation has failed, DEF_NULL;
|
|
*
|
|
* Caller(s) : HTTPcWebSock_Upgrade().
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
HTTPc_WEBSOCK_REQ *HTTPcWebSock_InitReqObj(HTTPc_ERR *p_err)
|
|
{
|
|
CPU_INT32U val;
|
|
CPU_CHAR tmp_buf[HTTPc_WEBSOCK_KEY_PRE_HASH_LEN];
|
|
CPU_INT08U i;
|
|
NET_ERR net_err;
|
|
NET_SHA1_ERR sha1_err;
|
|
NET_SHA1_CTX sha1_ctx;
|
|
HTTPc_WEBSOCK_REQ *p_ws_req;
|
|
|
|
/* ------------- CREATE RAMDOM 16 BYTES --------------- */
|
|
/* Reset the WebSocket handshake obj. */
|
|
p_ws_req = HTTPc_Mem_WebSockReqGet();
|
|
if (p_ws_req == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_WEBSOCK_REQ_MEM_ERR;
|
|
goto exit;
|
|
}
|
|
/* Generate a Random Seed. */
|
|
|
|
val = NetUtil_RandomRangeGet(1u, DEF_INT_32U_MAX_VAL);
|
|
/* Create the 16-byte random-key. */
|
|
for (i = 0; i < HTTPc_WEBSOCK_KEY_LEN; i += sizeof(CPU_INT32U)) {
|
|
val = Math_RandSeed(val);
|
|
Mem_Copy(&tmp_buf[i], &val, sizeof(CPU_INT32U));
|
|
}
|
|
|
|
/* --------- PROCESS SEC-WEBSOCKET-KEY VALUE ---------- */
|
|
NetBase64_Encode(tmp_buf,
|
|
HTTPc_WEBSOCK_KEY_LEN,
|
|
p_ws_req->Key,
|
|
HTTPc_WEBSOCK_KEY_ENCODED_LEN,
|
|
&net_err);
|
|
if (net_err != NET_ERR_NONE) {
|
|
*p_err = HTTPc_ERR_WEBSOCK_BASE64_ENCODE_FAIL;
|
|
goto exit_release;
|
|
}
|
|
/* -------- PROCESS SEC-WEBSOCKET-ACCEPT VALUE -------- */
|
|
Str_Copy(tmp_buf, p_ws_req->Key);
|
|
Str_Cat(tmp_buf, HTTPc_WEBSOCK_GUID_STRING);
|
|
|
|
NetSHA1_Reset(&sha1_ctx,
|
|
&sha1_err);
|
|
if (sha1_err != NET_SHA1_ERR_NONE) {
|
|
*p_err = HTTPc_ERR_WEBSOCK_SHA1_ENCODE_FAIL;
|
|
goto exit_release;
|
|
}
|
|
|
|
NetSHA1_Input(&sha1_ctx,
|
|
tmp_buf,
|
|
HTTPc_WEBSOCK_KEY_PRE_HASH_LEN,
|
|
&sha1_err);
|
|
if (sha1_err != NET_SHA1_ERR_NONE) {
|
|
*p_err = HTTPc_ERR_WEBSOCK_SHA1_ENCODE_FAIL;
|
|
goto exit_release;
|
|
}
|
|
|
|
NetSHA1_Result(&sha1_ctx,
|
|
tmp_buf,
|
|
&sha1_err);
|
|
if (sha1_err != NET_SHA1_ERR_NONE) {
|
|
*p_err = HTTPc_ERR_WEBSOCK_SHA1_ENCODE_FAIL;
|
|
goto exit_release;
|
|
}
|
|
|
|
NetBase64_Encode(tmp_buf,
|
|
HTTPc_WEBSOCK_KEY_HASH_LEN,
|
|
p_ws_req->Accept,
|
|
HTTPc_WEBSOCK_KEY_HASH_ENCODED_LEN,
|
|
&net_err);
|
|
if (net_err != NET_ERR_NONE) {
|
|
*p_err = HTTPc_ERR_WEBSOCK_BASE64_ENCODE_FAIL;
|
|
goto exit_release;
|
|
}
|
|
|
|
exit:
|
|
return p_ws_req;
|
|
|
|
exit_release:
|
|
HTTPc_Mem_WebSockReqRelease(p_ws_req);
|
|
return DEF_NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPcWebSock_TxMsgAdd()
|
|
*
|
|
* Description : Add a message in the TX message queue.
|
|
*
|
|
* Argument(s) : p_msg Pointer to the message to queue
|
|
*
|
|
* p_err Pointer to variable that will receive the return error code from this function.
|
|
*
|
|
* Return(s) : none.
|
|
*
|
|
* Caller(s) : HTTPcTask().
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
void HTTPcWebSock_TxMsgAdd(HTTPc_WEBSOCK_MSG *p_msg,
|
|
HTTPc_ERR *p_err)
|
|
{
|
|
HTTPc_CONN *p_conn;
|
|
HTTPc_WEBSOCK *p_ws;
|
|
HTTPc_WEBSOCK_MSG *p_msg_item;
|
|
CPU_BOOLEAN in_use;
|
|
|
|
|
|
p_conn = p_msg->ConnPtr;
|
|
p_ws = p_conn->WebSockPtr;
|
|
|
|
in_use = DEF_BIT_IS_SET(p_conn->Flags, HTTPc_FLAG_CONN_IN_USE);
|
|
|
|
if (in_use == DEF_YES) {
|
|
|
|
if (p_ws->TxMsgListHeadPtr == DEF_NULL) {
|
|
p_ws->TxMsgListHeadPtr = p_msg;
|
|
p_ws->TxMsgListEndPtr = p_msg;
|
|
p_msg->NextPtr = 0;
|
|
} else {
|
|
p_msg_item = p_ws->TxMsgListEndPtr;
|
|
p_msg_item->NextPtr = p_msg;
|
|
p_ws->TxMsgListEndPtr = p_msg;
|
|
p_msg->NextPtr = 0;
|
|
}
|
|
|
|
p_msg->Flags.IsUsed = DEF_YES;
|
|
|
|
*p_err = HTTPc_ERR_NONE;
|
|
|
|
} else {
|
|
*p_err = HTTPc_ERR_CONN_IS_RELEASED;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
* LOCAL FUNCTIONS
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPcWebSock_TX()
|
|
*
|
|
* Description : Process the WebSocket states TX.
|
|
*
|
|
* Argument(s) : p_conn Pointer to current HTTPc Connection (WebSocket Upgraded).
|
|
*
|
|
* Return(s) : none.
|
|
*
|
|
* Caller(s) : HTTPcConn_WebSocketProcess().
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void HTTPcWebSock_TX(HTTPc_CONN *p_conn)
|
|
{
|
|
HTTPc_ERR err;
|
|
HTTPc_WEBSOCK *p_ws;
|
|
HTTPc_WEBSOCK_MSG *p_msg;
|
|
CPU_BOOLEAN done;
|
|
HTTPc_CONN_OBJ *p_conn_const;
|
|
HTTPc_WEBSOCK_MSG_OBJ *p_msg_const;
|
|
CPU_INT16U hdr_len;
|
|
CPU_INT16U buf_size;
|
|
CPU_INT32U len;
|
|
CPU_INT32U len_rem;
|
|
CPU_CHAR *p_src_buf;
|
|
CPU_BOOLEAN sock_rdy_wr;
|
|
CPU_BOOLEAN sock_rdy_err;
|
|
CPU_CHAR *p_tx_buf;
|
|
HTTPc_WEBSOCK_CLOSE_CODE *p_close_code;
|
|
|
|
/* ------------------ INITIALIZAITON ------------------ */
|
|
p_ws = p_conn->WebSockPtr;
|
|
p_msg = p_ws->TxMsgListHeadPtr;
|
|
|
|
if (p_conn->State != HTTPc_CONN_STATE_WEBSOCK_RXTX) {
|
|
return;
|
|
}
|
|
|
|
if (p_msg != DEF_NULL) {
|
|
do {
|
|
done = DEF_YES; /* Always set to avoid unhandled state. */
|
|
switch (p_ws->TxState) {
|
|
|
|
case HTTPc_WEBSOCK_TX_STATE_MSG_INIT:
|
|
/* On Msg Tx Initialization Hook. */
|
|
if (p_msg->OnMsgTxInit != DEF_NULL) {
|
|
p_conn_const = (HTTPc_CONN_OBJ *)p_conn;
|
|
p_msg_const = (HTTPc_WEBSOCK_MSG_OBJ *)p_msg;
|
|
p_msg->Len = p_msg->OnMsgTxInit(p_conn_const, p_msg_const);
|
|
}
|
|
done = DEF_NO;
|
|
p_ws->TxState = HTTPc_WEBSOCK_TX_STATE_SET_BUF;
|
|
break;
|
|
|
|
|
|
case HTTPc_WEBSOCK_TX_STATE_SET_BUF:
|
|
/* Get hdr space needed. */
|
|
if (p_msg->Flags.IsHdrSet == DEF_NO) {
|
|
hdr_len = HTTPcWebSock_ComputeHdrLen(p_msg);
|
|
p_msg->MskKey = NetUtil_RandomRangeGet(1u, DEF_INT_32U_MAX_VAL);
|
|
} else {
|
|
hdr_len = 0;
|
|
}
|
|
/* Compute buffer space available. */
|
|
buf_size = HTTPc_WEBSOCK_GET_TX_BUF_SIZE(p_conn);
|
|
if (buf_size > hdr_len) {
|
|
buf_size -= hdr_len;
|
|
} else {
|
|
done = DEF_YES;
|
|
break;
|
|
}
|
|
/* Check if sock rdy to wr to avoid using the conn... */
|
|
/* ...buf unnecessarily. */
|
|
sock_rdy_wr = DEF_BIT_IS_SET(p_conn->SockFlags, HTTPc_FLAG_SOCK_RDY_WR);
|
|
if (sock_rdy_wr == DEF_NO) {
|
|
done = DEF_YES;
|
|
break;
|
|
}
|
|
/* Check if On Msg Tx Data Hook is initialized. */
|
|
if (p_msg->OnMsgTxData != DEF_NULL) {
|
|
p_conn_const = (HTTPc_CONN_OBJ *)p_conn;
|
|
p_msg_const = (HTTPc_WEBSOCK_MSG_OBJ *)p_msg;
|
|
p_msg->DataLen = p_msg->OnMsgTxData(p_conn_const,
|
|
p_msg_const,
|
|
p_conn->TxBufPtr,
|
|
buf_size);
|
|
|
|
if (p_msg->Len == HTTPc_WEBSOCK_TX_MSG_LEN_NOT_DEFINED) {
|
|
if (p_msg->DataLen == 0) {
|
|
p_msg->Flags.IsFin = DEF_YES;
|
|
} else {
|
|
p_msg->Flags.IsFin = DEF_NO;
|
|
}
|
|
p_msg->Len = p_msg->DataLen;
|
|
}
|
|
p_src_buf = p_conn->TxBufPtr;
|
|
|
|
} else {
|
|
/* Otherwise, use DataPtr. */
|
|
p_src_buf = (CPU_CHAR *)p_msg->DataPtr + p_msg->LenSent;
|
|
}
|
|
/* Compute chunk len and TxDataPtr. */
|
|
len_rem = p_msg->Len - p_msg->LenSent;
|
|
len = DEF_MIN(len_rem, buf_size);
|
|
p_conn->TxDataPtr = p_conn->BufPtr + p_conn->BufLen - len;
|
|
|
|
/* Mask data and set Tx Buffer */
|
|
HTTPcWebSock_SetTxBuf(p_msg, p_conn->TxDataPtr, p_src_buf, len);
|
|
|
|
/* Set the Hdr if needed. */
|
|
if (p_msg->Flags.IsHdrSet == DEF_NO) {
|
|
hdr_len = HTTPcWebSock_ComputeHdrLen(p_msg);
|
|
p_tx_buf = (CPU_CHAR *)p_conn->TxDataPtr;
|
|
p_tx_buf -= hdr_len;
|
|
HTTPcWebSock_SetTxBufHdr(p_conn,
|
|
p_msg,
|
|
p_tx_buf);
|
|
p_conn->TxDataPtr = (void *)p_tx_buf;
|
|
p_msg->Flags.IsHdrSet = DEF_YES;
|
|
}
|
|
|
|
p_msg->LenSent += len;
|
|
p_conn->TxDataLen = len + hdr_len;
|
|
p_ws->TxState = HTTPc_WEBSOCK_TX_STATE_SEND_BUF;
|
|
done = DEF_NO;
|
|
break;
|
|
|
|
|
|
case HTTPc_WEBSOCK_TX_STATE_SEND_BUF:
|
|
/* Send Data available in the buffer. */
|
|
sock_rdy_wr = DEF_BIT_IS_SET(p_conn->SockFlags, HTTPc_FLAG_SOCK_RDY_WR);
|
|
sock_rdy_err = DEF_BIT_IS_SET(p_conn->SockFlags, HTTPc_FLAG_SOCK_RDY_ERR);
|
|
if ((sock_rdy_wr == DEF_YES) ||
|
|
(sock_rdy_err == DEF_YES)) {
|
|
(void)HTTPcSock_ConnDataTx(p_conn, &err);
|
|
switch (err) {
|
|
case HTTPc_ERR_NONE:
|
|
case HTTPc_ERR_CONN_SOCK_TX:
|
|
break;
|
|
|
|
default:
|
|
goto exit_err;
|
|
}
|
|
}
|
|
|
|
if (p_conn->TxDataLen == 0u) { /* If all the data available in the buf has been sent. */
|
|
|
|
if (p_msg->LenSent < p_msg->Len) { /* Rtn to prev state if the frame is not completed. */
|
|
|
|
p_ws->TxState = HTTPc_WEBSOCK_TX_STATE_SET_BUF;
|
|
|
|
} else if (p_msg->LenSent == p_msg->Len) {
|
|
/* Validate if it was the last frame of the message. */
|
|
if (p_msg->Flags.IsFin == DEF_YES) {
|
|
p_ws->TxState = HTTPc_WEBSOCK_TX_STATE_COMPLETE;
|
|
done = DEF_NO;
|
|
} else {
|
|
p_msg->OpCode = HTTPc_WEBSOCK_OPCODE_CONTINUATION_FRAME;
|
|
p_msg->Flags.IsHdrSet = DEF_NO;
|
|
p_msg->Len = HTTPc_WEBSOCK_TX_MSG_LEN_NOT_DEFINED;
|
|
p_msg->LenSent = 0;
|
|
p_ws->TxState = HTTPc_WEBSOCK_TX_STATE_SET_BUF;
|
|
}
|
|
} else {
|
|
err = HTTPc_ERR_WEBSOCK_FAULT;
|
|
goto exit_err;
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
case HTTPc_WEBSOCK_TX_STATE_COMPLETE:
|
|
|
|
p_ws->TxState = HTTPc_WEBSOCK_TX_STATE_MSG_INIT;
|
|
p_msg->Flags.IsCompleted = DEF_YES;
|
|
|
|
switch (p_msg->OpCode) { /* Refresh WebSock states according to the msg types. */
|
|
|
|
case HTTPc_WEBSOCK_OPCODE_CONTINUATION_FRAME:
|
|
case HTTPc_WEBSOCK_OPCODE_TXT_FRAME:
|
|
case HTTPc_WEBSOCK_OPCODE_BIN_FRAME:
|
|
case HTTPc_WEBSOCK_OPCODE_PING:
|
|
break;
|
|
|
|
case HTTPc_WEBSOCK_OPCODE_CLOSE:
|
|
/* Check if it was initiated by the server. */
|
|
if (p_ws->Flags.IsCloseStarted == DEF_YES) {
|
|
/* Set Close information. */
|
|
if (p_msg->Len >= sizeof(CPU_INT16U)) {
|
|
p_close_code = (CPU_INT16U *)p_msg->DataPtr;
|
|
p_ws->CloseCode = MEM_VAL_GET_INT16U_BIG(p_close_code);
|
|
p_ws->CloseReason.DataPtr = ((CPU_CHAR *)p_msg->DataPtr) + sizeof(CPU_INT16U);
|
|
p_ws->CloseReason.Len = p_msg->Len - HTTPc_WEBSOCK_CLOSE_CODE_LEN;
|
|
} else {
|
|
p_ws->CloseCode = HTTPc_WEBSOCK_CLOSE_CODE_NONE;
|
|
p_ws->CloseReason.DataPtr = DEF_NULL;
|
|
p_ws->CloseReason.Len = 0u;
|
|
}
|
|
/* Restore the Rx msg cached space. */
|
|
if (p_ws->Flags.IsRxDataCached == DEF_YES) {
|
|
p_conn->TxBufPtr = p_conn->BufPtr;
|
|
p_ws->Flags.IsRxDataCached = DEF_NO;
|
|
}
|
|
/* Closing Handshake is completed. */
|
|
p_conn->State = HTTPc_CONN_STATE_WEBSOCK_CLOSE;
|
|
p_ws->Flags.IsCloseStarted = DEF_NO;
|
|
} else { /* Otherwise, wait for the close response from server. */
|
|
p_ws->Flags.IsCloseStarted = DEF_YES;
|
|
}
|
|
break;
|
|
|
|
case HTTPc_WEBSOCK_OPCODE_PONG:
|
|
/* Check if the Pong msg was initiated by the server. */
|
|
if (p_ws->Flags.IsPongStarted == DEF_YES) {
|
|
/* Restore the Rx msg cached space. */
|
|
if (p_ws->Flags.IsRxDataCached == DEF_YES) {
|
|
p_conn->TxBufPtr = p_conn->BufPtr;
|
|
p_ws->Flags.IsRxDataCached = DEF_NO;
|
|
}
|
|
p_ws->Flags.IsPongStarted = DEF_NO;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
err = HTTPc_ERR_WEBSOCK_INVALID_OPCODE;
|
|
goto exit_err;
|
|
}
|
|
|
|
if (p_msg == &p_ws->TxMsgCtrl) { /* Check If Tx Msg object is the internal obj for ctrl. */
|
|
p_ws->Flags.IsTxMsgCtrlUsed = DEF_NO;
|
|
HTTPcWebSock_TxMsgRemove(p_conn); /* Remove the Tx Msg obj in the list. */
|
|
} else {
|
|
/* On Msg Tx Complete Hook. */
|
|
if (p_msg->OnMsgTxComplete != DEF_NULL) {
|
|
p_conn_const = (HTTPc_CONN_OBJ *)p_conn;
|
|
p_msg_const = (HTTPc_WEBSOCK_MSG_OBJ *)p_msg;
|
|
p_msg->OnMsgTxComplete(p_conn_const, p_msg_const, DEF_OK);
|
|
}
|
|
|
|
HTTPcWebSock_TxMsgRemove(p_conn); /* Remove the Tx Msg obj in the list. */
|
|
|
|
#ifdef HTTPc_SIGNAL_TASK_MODULE_EN
|
|
/* Signal that TX transaction is done. */
|
|
if (p_conn->TransDoneSignal.SemObjPtr != DEF_NULL) {
|
|
HTTPcTask_TransDoneSignal(p_conn, &err);
|
|
if (err != HTTPc_ERR_NONE) {
|
|
CPU_SW_EXCEPTION(;);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
break;
|
|
|
|
|
|
default:
|
|
err = HTTPc_ERR_WEBSOCK_INVALID_TX_STATE;
|
|
goto exit_err;
|
|
}
|
|
} while (done == DEF_NO);
|
|
}
|
|
return;
|
|
|
|
exit_err:
|
|
p_conn->ErrCode = err;
|
|
p_conn->State = HTTPc_CONN_STATE_WEBSOCK_ERR;
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPcWebSock_RX()
|
|
*
|
|
* Description : Process the WebSocket states for RX.
|
|
*
|
|
* Argument(s) : p_conn Pointer to current HTTPc Connection (WebSocket Upgraded).
|
|
*
|
|
* Return(s) : none.
|
|
*
|
|
* Caller(s) : HTTPcConn_WebSocketProcess().
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void HTTPcWebSock_RX(HTTPc_CONN *p_conn)
|
|
{
|
|
HTTPc_ERR err;
|
|
HTTPc_WEBSOCK *p_ws;
|
|
CPU_BOOLEAN sock_rdy_rd;
|
|
CPU_BOOLEAN sock_rdy_err;
|
|
CPU_BOOLEAN done;
|
|
CPU_BOOLEAN result;
|
|
CPU_INT32U rem_rx_len;
|
|
CPU_INT32U rx_len;
|
|
HTTPc_CONN_OBJ *p_conn_const;
|
|
CPU_INT32U msg_len;
|
|
CPU_BOOLEAN is_std;
|
|
CPU_INT16U *p_close_code;
|
|
|
|
/* ------------------ INITIALIZAITON ------------------ */
|
|
p_ws = p_conn->WebSockPtr;
|
|
|
|
if (p_conn->State != HTTPc_CONN_STATE_WEBSOCK_RXTX) {
|
|
return;
|
|
}
|
|
|
|
do {
|
|
done = DEF_YES; /* Always set to avoid unhandled state. */
|
|
rem_rx_len = 0u;
|
|
/* --------------- RX STATES PROCESSING --------------- */
|
|
switch (p_ws->RxState) {
|
|
|
|
case HTTPc_WEBSOCK_RX_STATE_WAIT:
|
|
|
|
if (p_conn->RxDataLenRem != 0) { /* If there's data to process... */
|
|
p_ws->RxState = HTTPc_WEBSOCK_RX_STATE_HDR;
|
|
p_ws->RxMsgLenRead = 0u;
|
|
p_conn->RxDataLen = 0u;
|
|
done = DEF_NO;
|
|
DEF_BIT_CLR(p_conn->RespFlags, HTTPc_FLAG_RESP_RX_MORE_DATA);
|
|
} else { /* Otherwise, try to rx WebSocket header. */
|
|
DEF_BIT_SET(p_conn->RespFlags, HTTPc_FLAG_RESP_RX_MORE_DATA);
|
|
rem_rx_len = HTTPc_WEBSOCK_MAX_HEADER_LEN;
|
|
}
|
|
break;
|
|
|
|
|
|
case HTTPc_WEBSOCK_RX_STATE_HDR: /* Process the msg header. */
|
|
|
|
rem_rx_len = HTTPcWebSock_GetMsgHdr(p_conn, &err);
|
|
if (err != HTTPc_ERR_NONE) {
|
|
goto exit_err;
|
|
}
|
|
|
|
if (rem_rx_len == 0u) { /* Proceed to the next step if successful. */
|
|
p_ws->RxState = HTTPc_WEBSOCK_RX_STATE_PREPARE;
|
|
done = DEF_NO;
|
|
DEF_BIT_CLR(p_conn->RespFlags, HTTPc_FLAG_RESP_RX_MORE_DATA);
|
|
/* On Msg Rx Initialization Hook. */
|
|
if (p_ws->OnMsgRxInit != DEF_NULL) {
|
|
|
|
if ((p_ws->RxMsgOpCode == HTTPc_WEBSOCK_OPCODE_TXT_FRAME) ||
|
|
(p_ws->RxMsgOpCode == HTTPc_WEBSOCK_OPCODE_BIN_FRAME)) {
|
|
/* Check if the msg is fragmented. */
|
|
if (p_ws->RxMsgFlags.IsFin == DEF_NO) {
|
|
msg_len = HTTPc_WEBSOCK_TX_MSG_LEN_NOT_DEFINED;
|
|
} else {
|
|
msg_len = p_ws->RxMsgLen;
|
|
}
|
|
p_conn_const = (HTTPc_CONN_OBJ *)p_conn;
|
|
p_ws->RxMsgDataPtr = DEF_NULL;
|
|
p_ws->OnMsgRxInit(p_conn_const, (HTTPc_WEBSOCK_MSG_TYPE)p_ws->RxMsgOpCode, msg_len, (void **) & (p_ws->RxMsgDataPtr));
|
|
}
|
|
}
|
|
} else { /* If there is no enough data rx to process the hdr. */
|
|
DEF_BIT_SET(p_conn->RespFlags, HTTPc_FLAG_RESP_RX_MORE_DATA);
|
|
}
|
|
break;
|
|
|
|
|
|
case HTTPc_WEBSOCK_RX_STATE_PREPARE:
|
|
|
|
rx_len = p_ws->RxMsgLenRead + p_conn->RxDataLenRem;
|
|
|
|
if (rx_len < p_ws->RxMsgLen) { /* Compute to nb of bytes to rx if needed. */
|
|
rem_rx_len = p_ws->RxMsgLen - rx_len;
|
|
DEF_BIT_SET(p_conn->RespFlags, HTTPc_FLAG_RESP_RX_MORE_DATA);
|
|
} else { /* If the msg is already all rxd, process the payload. */
|
|
done = DEF_NO;
|
|
DEF_BIT_CLR(p_conn->RespFlags, HTTPc_FLAG_RESP_RX_MORE_DATA);
|
|
}
|
|
p_ws->RxState = HTTPc_WEBSOCK_RX_STATE_PAYLOAD;
|
|
break;
|
|
|
|
|
|
case HTTPc_WEBSOCK_RX_STATE_PAYLOAD: /* Process the rxd payload data. */
|
|
|
|
HTTPcWebSock_GetPayload(p_conn);
|
|
|
|
DEF_BIT_CLR(p_conn->RespFlags, HTTPc_FLAG_RESP_RX_MORE_DATA);
|
|
if (p_ws->RxMsgLenRead < p_ws->RxMsgLen) { /* If the msg is not rxed completely. */
|
|
|
|
p_ws->RxState = HTTPc_WEBSOCK_RX_STATE_PREPARE;
|
|
/* Continue to process if Ctrl msg. */
|
|
if ((p_ws->RxMsgOpCode == HTTPc_WEBSOCK_OPCODE_CLOSE) ||
|
|
(p_ws->RxMsgOpCode == HTTPc_WEBSOCK_OPCODE_PING) ||
|
|
(p_ws->RxMsgOpCode == HTTPc_WEBSOCK_OPCODE_PONG)) {
|
|
done = DEF_NO;
|
|
} else { /* Otherwise, save the remaining rx data and exit. */
|
|
p_conn->TxBufPtr = p_conn->RxBufPtr + p_conn->RxDataLenRem;
|
|
done = DEF_YES;
|
|
}
|
|
/* If the msg is rxed completely. */
|
|
} else if (p_ws->RxMsgLenRead == p_ws->RxMsgLen) {
|
|
|
|
if (p_ws->Flags.IsRxDataCached == DEF_NO) {
|
|
p_conn->TxBufPtr = p_conn->BufPtr; /* Reset TxBufPtr. */
|
|
}
|
|
p_ws->RxState = HTTPc_WEBSOCK_RX_STATE_COMPLETE;
|
|
done = DEF_NO;
|
|
} else {
|
|
err = HTTPc_ERR_WEBSOCK_FAULT;
|
|
goto exit_err;
|
|
}
|
|
break;
|
|
|
|
|
|
case HTTPc_WEBSOCK_RX_STATE_COMPLETE:
|
|
|
|
switch (p_ws->RxMsgOpCode) {
|
|
|
|
case HTTPc_WEBSOCK_OPCODE_CONTINUATION_FRAME:
|
|
case HTTPc_WEBSOCK_OPCODE_TXT_FRAME:
|
|
case HTTPc_WEBSOCK_OPCODE_BIN_FRAME:
|
|
|
|
if (p_ws->RxMsgFlags.IsFin == DEF_YES) {
|
|
p_ws->OrigOpCode = HTTPc_WEBSOCK_OPCODE_NONE;
|
|
p_ws->TotalMsgLen = 0u;
|
|
/* On Msg Rx Complete Hook. */
|
|
if (p_ws->OnMsgRxComplete != DEF_NULL) {
|
|
p_conn_const = (HTTPc_CONN_OBJ *)p_conn;
|
|
p_ws->OnMsgRxComplete(p_conn_const);
|
|
}
|
|
}
|
|
p_ws->RxState = HTTPc_WEBSOCK_RX_STATE_WAIT;
|
|
break;
|
|
|
|
case HTTPc_WEBSOCK_OPCODE_PING: /* Send a Pong Msg. */
|
|
|
|
if (p_ws->Flags.IsTxMsgCtrlUsed == DEF_NO) {
|
|
HTTPcWebSock_SetCtrlResponse(p_conn, HTTPc_WEBSOCK_OPCODE_PONG, p_conn->RxBufPtr, p_ws->RxMsgLen);
|
|
p_conn->RxBufPtr += p_ws->RxMsgLen;
|
|
p_ws->Flags.IsPongStarted = DEF_YES;
|
|
p_ws->RxState = HTTPc_WEBSOCK_RX_STATE_WAIT;
|
|
}
|
|
break;
|
|
|
|
case HTTPc_WEBSOCK_OPCODE_CLOSE: /* Process the closing handshake */
|
|
|
|
if (p_ws->RxMsgLen >= sizeof(CPU_INT16U)) {
|
|
p_close_code = (CPU_INT16U *)p_conn->RxBufPtr;
|
|
p_ws->CloseCode = MEM_VAL_GET_INT16U_BIG(p_close_code);
|
|
p_ws->CloseReason.DataPtr = p_conn->RxBufPtr + HTTPc_WEBSOCK_CLOSE_CODE_LEN;
|
|
p_ws->CloseReason.Len = p_ws->RxMsgLen - HTTPc_WEBSOCK_CLOSE_CODE_LEN;
|
|
} else {
|
|
p_ws->CloseCode = HTTPc_WEBSOCK_CLOSE_CODE_NORMAL;
|
|
p_ws->CloseReason.DataPtr = DEF_NULL;
|
|
p_ws->CloseReason.Len = 0u;
|
|
}
|
|
/* Check if initiated by the application. */
|
|
if (p_ws->Flags.IsCloseStarted == DEF_YES) {
|
|
|
|
p_conn->State = HTTPc_CONN_STATE_WEBSOCK_CLOSE;
|
|
p_ws->RxState = HTTPc_WEBSOCK_RX_STATE_WAIT;
|
|
p_ws->Flags.IsCloseStarted = DEF_NO;
|
|
|
|
} else {
|
|
/* Otherwise, initiated by the server. */
|
|
if (p_ws->Flags.IsTxMsgCtrlUsed == DEF_NO) {
|
|
/* Send a close response. */
|
|
is_std = HTTPcWebSock_IsStandardCloseCode(p_ws->CloseCode);
|
|
if (is_std == DEF_YES) {
|
|
HTTPcWebSock_SetCtrlResponse(p_conn, HTTPc_WEBSOCK_OPCODE_CLOSE, p_conn->RxBufPtr, p_ws->RxMsgLen);
|
|
p_ws->Flags.IsCloseStarted = DEF_YES;
|
|
} else {
|
|
err = HTTPc_ERR_WEBSOCK_RX_CLOSE_CODE_INVALID;
|
|
goto exit_err;
|
|
}
|
|
}
|
|
p_conn->RxBufPtr += p_ws->RxMsgLen;
|
|
p_ws->RxState = HTTPc_WEBSOCK_RX_STATE_WAIT;
|
|
}
|
|
break;
|
|
|
|
case HTTPc_WEBSOCK_OPCODE_PONG:
|
|
|
|
/* On Pong Hook. */
|
|
if (p_ws->OnPong != DEF_NULL) {
|
|
p_conn_const = (HTTPc_CONN_OBJ *)p_conn;
|
|
p_ws->OnPong(p_conn_const, p_conn->RxBufPtr, p_ws->RxMsgLen);
|
|
}
|
|
|
|
p_conn->RxBufPtr += p_ws->RxMsgLen;
|
|
p_ws->RxState = HTTPc_WEBSOCK_RX_STATE_WAIT;
|
|
break;
|
|
|
|
default:
|
|
err = HTTPc_ERR_WEBSOCK_INVALID_OPCODE;
|
|
goto exit_err;
|
|
}
|
|
|
|
if ((p_conn->RxDataLenRem == 0u) ||
|
|
(p_ws->Flags.IsTxMsgCtrlUsed == DEF_YES)) {
|
|
done = DEF_YES;
|
|
} else {
|
|
done = DEF_NO;
|
|
}
|
|
break;
|
|
|
|
|
|
default:
|
|
err = HTTPc_ERR_WEBSOCK_INVALID_RX_STATE;
|
|
goto exit_err;
|
|
}
|
|
/* --------------------- RX DATA ---------------------- */
|
|
result = DEF_BIT_IS_SET(p_conn->RespFlags, HTTPc_FLAG_RESP_RX_MORE_DATA);
|
|
|
|
if (result == DEF_YES) { /* If more data is needed... */
|
|
|
|
if (p_ws->Flags.IsRxDataCached == DEF_NO) { /* ...and If there is no rx data cached for ctrl msg... */
|
|
|
|
sock_rdy_rd = DEF_BIT_IS_SET(p_conn->SockFlags, HTTPc_FLAG_SOCK_RDY_RD);
|
|
sock_rdy_err = DEF_BIT_IS_SET(p_conn->SockFlags, HTTPc_FLAG_SOCK_RDY_ERR);
|
|
|
|
if ((sock_rdy_rd == DEF_YES) || /* ...and if the sock is ready.... */
|
|
(sock_rdy_err == DEF_YES)) {
|
|
/* ...then Rx data. */
|
|
result = HTTPcSock_ConnDataRx(p_conn, rem_rx_len, &err);
|
|
switch (err) {
|
|
case HTTPc_ERR_NONE:
|
|
case HTTPc_ERR_CONN_SOCK_RX:
|
|
break;
|
|
|
|
case HTTPc_ERR_CONN_SOCK_CLOSED:
|
|
p_conn->ErrCode = HTTPc_ERR_NONE;
|
|
p_conn->CloseStatus = HTTPc_CONN_CLOSE_STATUS_SERVER;
|
|
p_conn->State = HTTPc_CONN_STATE_WEBSOCK_CLOSE;
|
|
break;
|
|
|
|
default:
|
|
goto exit_err;
|
|
}
|
|
|
|
if (result == DEF_OK) {
|
|
if (p_conn->RxDataLenRem == 0u) {
|
|
done = DEF_YES;
|
|
} else {
|
|
done = DEF_NO;
|
|
}
|
|
} else {
|
|
if (p_conn->RxDataLenRem == 0u) {
|
|
done = DEF_YES;
|
|
}
|
|
}
|
|
} else {
|
|
done = DEF_YES;
|
|
}
|
|
}
|
|
}
|
|
} while (done == DEF_NO);
|
|
|
|
return;
|
|
|
|
exit_err:
|
|
p_conn->ErrCode = err;
|
|
p_conn->State = HTTPc_CONN_STATE_WEBSOCK_ERR;
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPcWebSock_GetMsgHdr()
|
|
*
|
|
* Description : Process the header of a WebSocket message.
|
|
*
|
|
* Argument(s) : p_conn Pointer to current HTTPc Connection (WebSocket Upgraded).
|
|
*
|
|
* p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* HTTPc_ERR_NONE
|
|
* HTTPc_ERR_WEBSOCK_INVALID_RX_LEN
|
|
*
|
|
* Return(s) : Remaining number of bytes to parse the hdr.
|
|
*
|
|
* Caller(s) : HTTPcWebSock_ProcessRXTX().
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static CPU_INT32U HTTPcWebSock_GetMsgHdr(HTTPc_CONN *p_conn,
|
|
HTTPc_ERR *p_err)
|
|
{
|
|
CPU_SIZE_T len;
|
|
CPU_INT08U hdr_1;
|
|
CPU_INT08U hdr_2;
|
|
CPU_CHAR *p_data;
|
|
CPU_INT64U payload;
|
|
CPU_INT64U rem_hdr;
|
|
HTTPc_WEBSOCK *p_ws;
|
|
CPU_BOOLEAN rsvd_bit;
|
|
|
|
|
|
/* ------------------ INITIALIZATION ------------------ */
|
|
*p_err = HTTPc_ERR_NONE;
|
|
rem_hdr = 0u;
|
|
|
|
len = p_conn->RxDataLenRem;
|
|
p_data = p_conn->RxBufPtr;
|
|
p_ws = p_conn->WebSockPtr;
|
|
/* ----------------- PROCESS HDR BYTES ---------------- */
|
|
if (len < HTTPc_WEBSOCK_MIN_HEADER_LEN) { /* Check if enough data to compute the first parts of...*/
|
|
rem_hdr = HTTPc_WEBSOCK_MIN_HEADER_LEN; /* ...the message hdr. */
|
|
goto exit;
|
|
}
|
|
/* Get the 2 first bytes. */
|
|
hdr_1 = p_data[0];
|
|
hdr_2 = p_data[1];
|
|
p_data += 2;
|
|
len -= 2;
|
|
/* Process msg OPCODE field. */
|
|
p_ws->RxMsgOpCode = hdr_1 & HTTPc_WEBSOCK_OPCODE_MASK;
|
|
/* Process FIN bit. */
|
|
p_ws->RxMsgFlags.IsFin = DEF_BIT_IS_SET(hdr_1, HTTPc_WEBSOCK_FIN_BIT);
|
|
|
|
/* Process RSVD bits. */
|
|
rsvd_bit = DEF_BIT_IS_SET(hdr_1, DEF_BIT_06);
|
|
if (rsvd_bit == DEF_YES) {
|
|
*p_err = HTTPc_ERR_WEBSOCK_RX_RSVD_BIT_1_SET;
|
|
goto exit;
|
|
}
|
|
|
|
rsvd_bit = DEF_BIT_IS_SET(hdr_1, DEF_BIT_05);
|
|
if (rsvd_bit == DEF_YES) {
|
|
*p_err = HTTPc_ERR_WEBSOCK_RX_RSVD_BIT_2_SET;
|
|
goto exit;
|
|
}
|
|
|
|
rsvd_bit = DEF_BIT_IS_SET(hdr_1, DEF_BIT_04);
|
|
if (rsvd_bit == DEF_YES) {
|
|
*p_err = HTTPc_ERR_WEBSOCK_RX_RSVD_BIT_3_SET;
|
|
goto exit;
|
|
}
|
|
/* Process MASK bit. */
|
|
p_ws->RxMsgFlags.IsMasked = DEF_BIT_IS_SET(hdr_2, HTTPc_WEBSOCK_MASK_BIT);
|
|
|
|
/* ----------------- PROCESS PAYLOAD ------------------ */
|
|
payload = hdr_2 & HTTPc_WEBSOCK_PAYLOAD_MASK;
|
|
rem_hdr = 0u;
|
|
/* According for the 2 first bytes, check the rem... */
|
|
/* ...size of the hdr. */
|
|
if (p_ws->RxMsgFlags.IsMasked == DEF_YES) {
|
|
rem_hdr += sizeof(CPU_INT32U);
|
|
}
|
|
|
|
if (payload == HTTPc_WEBSOCK_NORMAL_FRAME_CODE) {
|
|
rem_hdr += sizeof(CPU_INT16U);
|
|
} else if (payload == HTTPc_WEBSOCK_LONG_FRAME_CODE) {
|
|
rem_hdr += sizeof(CPU_INT64U);
|
|
}
|
|
/* Check if enough data rxd data. */
|
|
if (len < rem_hdr) {
|
|
goto exit;
|
|
}
|
|
/* Get the msg PAYLOAD length. */
|
|
if (payload <= HTTPc_WEBSOCK_SMALL_FRAME_MAX_LEN) {
|
|
/* Payload length is <= 125 . */
|
|
p_ws->RxMsgLen = payload;
|
|
|
|
} else if (payload == HTTPc_WEBSOCK_NORMAL_FRAME_CODE) {
|
|
/* Payload length is > 125 and <= 65535. */
|
|
p_ws->RxMsgLen = MEM_VAL_GET_INT16U_BIG(p_data);
|
|
p_data += sizeof(CPU_INT16U);
|
|
|
|
} else if (payload == HTTPc_WEBSOCK_LONG_FRAME_CODE) {
|
|
/* Payload length is > 65535. */
|
|
payload = MEM_VAL_GET_INT32U_BIG(p_data);
|
|
if (payload != 0u) {
|
|
*p_err = HTTPc_ERR_WEBSOCK_INVALID_RX_LEN;
|
|
goto exit;
|
|
}
|
|
p_data += sizeof(CPU_INT32U);
|
|
payload = MEM_VAL_GET_INT32U_BIG(p_data);
|
|
Mem_Copy(&p_ws->RxMsgLen, &payload, sizeof(CPU_INT64U));
|
|
p_data += sizeof(CPU_INT32U);
|
|
}
|
|
/* ------------------ MSG VALIDATION ------------------ */
|
|
switch (p_ws->RxMsgOpCode) {
|
|
|
|
case HTTPc_WEBSOCK_OPCODE_TXT_FRAME:
|
|
case HTTPc_WEBSOCK_OPCODE_BIN_FRAME:
|
|
/* If not the first frame of a frag msg, must be cont. */
|
|
if (p_ws->TotalMsgLen != 0u) {
|
|
*p_err = HTTPc_ERR_WEBSOCK_RX_FRAG_FRAME_SEQUENCE_INVALID;
|
|
goto exit;
|
|
}
|
|
p_ws->OrigOpCode = p_ws->RxMsgOpCode;
|
|
p_ws->TotalMsgLen = p_ws->RxMsgLen;
|
|
break;
|
|
|
|
case HTTPc_WEBSOCK_OPCODE_CONTINUATION_FRAME:
|
|
|
|
if (p_ws->TotalMsgLen == 0u) {
|
|
*p_err = HTTPc_ERR_WEBSOCK_RX_FRAG_FRAME_SEQUENCE_INVALID;
|
|
goto exit;
|
|
}
|
|
|
|
p_ws->TotalMsgLen += p_ws->RxMsgLen;
|
|
break;
|
|
|
|
case HTTPc_WEBSOCK_OPCODE_CLOSE:
|
|
case HTTPc_WEBSOCK_OPCODE_PING:
|
|
case HTTPc_WEBSOCK_OPCODE_PONG:
|
|
/* Control message cannot be longer than 125 bytes. */
|
|
if (p_ws->RxMsgLen > HTTPc_WEBSOCK_MAX_CTRL_FRAME_LEN) {
|
|
*p_err = HTTPc_ERR_WEBSOCK_RX_CTRL_FRAME_TOO_LONG;
|
|
}
|
|
/* Control message cannot be fragmented. */
|
|
if (p_ws->RxMsgFlags.IsFin == DEF_NO) {
|
|
*p_err = HTTPc_ERR_WEBSOCK_RX_CTRL_FRAME_FRAGMENTED;;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
*p_err = HTTPc_ERR_WEBSOCK_RX_INVALID_OPCODE;
|
|
}
|
|
/* --------------- PROCESS MASKING KEY ---------------- */
|
|
if (p_ws->RxMsgFlags.IsMasked == DEF_YES) {
|
|
Mem_Copy(&p_ws->RxMsgMskKey, p_data, sizeof(CPU_INT32U));
|
|
p_data += sizeof(CPU_INT32U);
|
|
}
|
|
/* -------------- UPDATE CONN RX PARAMS --------------- */
|
|
p_conn->RxDataLenRem -= (p_data - p_conn->RxBufPtr);
|
|
p_conn->RxBufPtr = p_data;
|
|
|
|
rem_hdr = 0u;
|
|
|
|
exit:
|
|
return rem_hdr;
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPcWebSock_GetPayload()
|
|
*
|
|
* Description : Get the payload of a WebSocket message.
|
|
*
|
|
* Argument(s) : p_conn Pointer to current HTTPc Connection (WebSocket Upgraded).
|
|
*
|
|
* Return(s) : none.
|
|
*
|
|
* Caller(s) : HTTPcWebSock_ProcessRX().
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void HTTPcWebSock_GetPayload(HTTPc_CONN *p_conn)
|
|
{
|
|
CPU_CHAR *p_buf;
|
|
HTTPc_CONN_OBJ *p_conn_const;
|
|
HTTPc_WEBSOCK *p_ws;
|
|
CPU_INT32U content_len;
|
|
CPU_INT32U msg_len_rem;
|
|
CPU_INT32U chunk_len;
|
|
HTTPc_WEBSOCK_MSG_TYPE msg_type;
|
|
CPU_INT32U data_len_read;
|
|
|
|
/* ------------------ INTIALIZATION ------------------- */
|
|
p_ws = p_conn->WebSockPtr;
|
|
p_conn_const = (HTTPc_CONN_OBJ *)p_conn;
|
|
p_buf = p_conn->RxBufPtr;
|
|
content_len = p_ws->RxMsgLen;
|
|
|
|
msg_len_rem = p_ws->RxMsgLen - p_conn->RxDataLen;
|
|
|
|
switch (p_ws->RxMsgOpCode) {
|
|
/* -------------------- DATA FRAME -------------------- */
|
|
case HTTPc_WEBSOCK_OPCODE_CONTINUATION_FRAME:
|
|
case HTTPc_WEBSOCK_OPCODE_TXT_FRAME:
|
|
case HTTPc_WEBSOCK_OPCODE_BIN_FRAME:
|
|
|
|
if (msg_len_rem > p_conn->RxDataLenRem) {
|
|
chunk_len = p_conn->RxDataLenRem;
|
|
} else {
|
|
chunk_len = msg_len_rem;
|
|
}
|
|
if (p_conn->RxDataLen > content_len) {
|
|
return;
|
|
}
|
|
|
|
if (p_ws->RxMsgOpCode == HTTPc_WEBSOCK_OPCODE_CONTINUATION_FRAME) {
|
|
msg_type = (HTTPc_WEBSOCK_MSG_TYPE)p_ws->OrigOpCode;
|
|
} else {
|
|
msg_type = (HTTPc_WEBSOCK_MSG_TYPE)p_ws->RxMsgOpCode;
|
|
}
|
|
if (p_ws->RxMsgDataPtr != DEF_NULL) {
|
|
Mem_Copy(&((p_ws->RxMsgDataPtr)[p_ws->RxMsgLenRead]), p_buf, chunk_len);
|
|
data_len_read = chunk_len;
|
|
|
|
} else if (p_ws->OnMsgRxData != DEF_NULL) {
|
|
data_len_read = p_ws->OnMsgRxData(p_conn_const,
|
|
msg_type,
|
|
p_buf,
|
|
chunk_len);
|
|
} else {
|
|
data_len_read = chunk_len;
|
|
}
|
|
|
|
|
|
p_conn->RxDataLen += data_len_read;
|
|
p_ws->RxMsgLenRead += data_len_read;
|
|
p_conn->RxBufPtr += data_len_read;
|
|
p_conn->RxDataLenRem -= data_len_read;
|
|
break;
|
|
/* -------------------- CTRL FRAME -------------------- */
|
|
case HTTPc_WEBSOCK_OPCODE_PONG:
|
|
case HTTPc_WEBSOCK_OPCODE_CLOSE:
|
|
case HTTPc_WEBSOCK_OPCODE_PING:
|
|
if (p_ws->RxMsgLen <= p_conn->RxDataLenRem) {
|
|
p_conn->TxBufPtr = p_conn->RxBufPtr + p_conn->RxDataLenRem;
|
|
p_conn->RxDataLenRem -= p_ws->RxMsgLen;
|
|
p_ws->Flags.IsRxDataCached = DEF_YES;
|
|
p_ws->RxMsgLenRead += p_ws->RxMsgLen;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPcWebSock_SetTxBuf()
|
|
*
|
|
* Description : Mask and copy a message into a buffer.
|
|
*
|
|
* Argument(s) : p_msg Pointer to the WebSocket message object.
|
|
*
|
|
* p_dst_buf Pointer to the destination buffer.
|
|
*
|
|
* p_src_buf Pointer to the source buffer.
|
|
*
|
|
* len Length of the data to copy.
|
|
*
|
|
* Return(s) : none.
|
|
*
|
|
* Caller(s) : HTTPcWebSock_ProcessTX().
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void HTTPcWebSock_SetTxBuf(HTTPc_WEBSOCK_MSG *p_msg,
|
|
CPU_CHAR *p_dst_buf,
|
|
CPU_CHAR *p_src_buf,
|
|
CPU_INT32U len)
|
|
{
|
|
CPU_INT32U msk_idx;
|
|
CPU_INT32U msg_idx;
|
|
CPU_CHAR msk_byte[4];
|
|
|
|
|
|
if (len == 0u) {
|
|
return;
|
|
}
|
|
|
|
msk_byte[3] = (CPU_CHAR)(p_msg->MskKey & 0x000000FF);
|
|
msk_byte[2] = (CPU_CHAR)((p_msg->MskKey & 0x0000FF00) >> 8);
|
|
msk_byte[1] = (CPU_CHAR)((p_msg->MskKey & 0x00FF0000) >> 16);
|
|
msk_byte[0] = (CPU_CHAR)((p_msg->MskKey & 0xFF000000) >> 24);
|
|
|
|
p_dst_buf += len;
|
|
p_src_buf += len;
|
|
msg_idx = p_msg->LenSent + len ;
|
|
|
|
while (p_msg->LenSent < msg_idx) {
|
|
msg_idx--;
|
|
p_src_buf--;
|
|
p_dst_buf--;
|
|
msk_idx = msg_idx % sizeof(CPU_INT32U);
|
|
*p_dst_buf = *p_src_buf ^ msk_byte[msk_idx];
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPc_WebSock_PrepareTxBufHdr()
|
|
*
|
|
* Description : Set the message header into the TX buffer..
|
|
*
|
|
* Argument(s) : p_conn Pointer to current HTTPc Connection (WebSocket Upgraded).
|
|
*
|
|
* p_tx_msg Pointer to the WebSocket message object to send.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Caller(s) : HTTPcWebSock_ProcessRXTX().
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void HTTPcWebSock_SetTxBufHdr(HTTPc_CONN *p_conn,
|
|
HTTPc_WEBSOCK_MSG *p_tx_msg,
|
|
CPU_CHAR *p_tx_buf)
|
|
{
|
|
CPU_CHAR *p_hdr;
|
|
CPU_INT32U tmp_len;
|
|
CPU_INT32U tmp_mask;
|
|
CPU_BOOLEAN fin;
|
|
|
|
/* ------------------ INITIALIZATION ------------------ */
|
|
p_hdr = p_tx_buf;
|
|
/* Set the first to Byte of the WebSocket hdr. */
|
|
fin = p_tx_msg->Flags.IsFin;
|
|
*p_hdr = p_tx_msg->OpCode + ((fin == DEF_YES) ? HTTPc_WEBSOCK_FIN_BIT : 0u);
|
|
p_hdr++;
|
|
/* Set the Masking Key. */
|
|
*p_hdr = HTTPc_WEBSOCK_MASK_BIT ;
|
|
/* ----------------- SET PAYLOAD LEN ------------------ */
|
|
if (p_tx_msg->Len >= HTTPc_WEBSOCK_LONG_FRAME_MIN_LEN) { /* Use the extended 64-bits payload len. */
|
|
|
|
*p_hdr += HTTPc_WEBSOCK_LONG_FRAME_CODE;
|
|
p_hdr++;
|
|
|
|
Mem_Clr(p_hdr, sizeof(CPU_INT32U)); /* Maximum msg lenght is 32-bit. */
|
|
p_hdr += sizeof(CPU_INT32U);
|
|
|
|
tmp_len = MEM_VAL_GET_INT32U_BIG(&p_tx_msg->Len);
|
|
Mem_Copy(p_hdr, &tmp_len, sizeof(CPU_INT32U));
|
|
p_hdr += sizeof(CPU_INT32U);
|
|
/* Use the extended 16-bits payload len. */
|
|
} else if (p_tx_msg->Len >= HTTPc_WEBSOCK_NORMAL_FRAME_MIN_LEN) {
|
|
|
|
*p_hdr += HTTPc_WEBSOCK_NORMAL_FRAME_CODE;
|
|
p_hdr++;
|
|
|
|
tmp_len = MEM_VAL_GET_INT16U_BIG(&p_tx_msg->Len);
|
|
Mem_Copy(p_hdr, &tmp_len, sizeof(CPU_INT16U));
|
|
p_hdr += sizeof(CPU_INT16U);
|
|
} else { /* Use the 7-bits payload len. */
|
|
*p_hdr += p_tx_msg->Len;
|
|
p_hdr++;
|
|
}
|
|
/* ----------------- SET MASKING KEY ------------------ */
|
|
tmp_mask = MEM_VAL_GET_INT32U_BIG(&p_tx_msg->MskKey);
|
|
Mem_Copy(p_hdr, &tmp_mask, sizeof(CPU_INT32U));
|
|
}
|
|
|
|
|
|
/*
|
|
*************************************************************************************************
|
|
* HTTPcWebSock_SetCtrlResponse()
|
|
*
|
|
* Description : Set an internal Control message response using cached Rx Data.
|
|
*
|
|
* Argument(s) : p_conn Pointer to current HTTPc Connection (WebSocket Upgraded).
|
|
*
|
|
* opcode Type of control frame to send.
|
|
*
|
|
* Return(s) : none.
|
|
*
|
|
* Caller(s) : HTTPcWebSock_ProcessRX().
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void HTTPcWebSock_SetCtrlResponse(HTTPc_CONN *p_conn,
|
|
HTTPc_WEBSOCK_OPCODE opcode,
|
|
CPU_CHAR *p_data,
|
|
CPU_INT32U msg_len)
|
|
{
|
|
HTTPc_WEBSOCK *p_ws;
|
|
HTTPc_WEBSOCK_MSG *p_msg_tx;
|
|
HTTPc_ERR err;
|
|
|
|
/* ------------------- GET MSG PTR -------------------- */
|
|
p_ws = p_conn->WebSockPtr;
|
|
p_msg_tx = &p_ws->TxMsgCtrl;
|
|
|
|
/* --------------- SET TX CTRL MSG OBJ ---------------- */
|
|
p_msg_tx->Len = msg_len;
|
|
p_msg_tx->LenSent = 0u;
|
|
p_msg_tx->DataPtr = p_data;
|
|
p_msg_tx->OpCode = opcode;
|
|
p_msg_tx->ConnPtr = p_conn;
|
|
p_msg_tx->Flags.IsFin = DEF_YES;
|
|
p_msg_tx->Flags.IsMasked = DEF_YES;
|
|
p_msg_tx->Flags.IsHdrSet = DEF_NO;
|
|
|
|
p_ws->Flags.IsTxMsgCtrlUsed = DEF_YES;
|
|
|
|
HTTPcWebSock_TxMsgAdd(p_msg_tx, &err);
|
|
|
|
(void)err;
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPcWebSock_TxMsgRemove()
|
|
*
|
|
* Description : Remove the first message in the TX message queue.
|
|
*
|
|
* Argument(s) : p_conn Pointer to current HTTPc Connection (WebSocket Upgraded).
|
|
*
|
|
* Return(s) : none.
|
|
*
|
|
* Caller(s) : HTTPcWebSock_TX(),
|
|
* HTTPcWebSock_TxMsgCleanList().
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void HTTPcWebSock_TxMsgRemove(HTTPc_CONN *p_conn)
|
|
{
|
|
HTTPc_WEBSOCK *p_ws;
|
|
HTTPc_WEBSOCK_MSG *p_msg_item;
|
|
|
|
|
|
p_ws = p_conn->WebSockPtr;
|
|
p_msg_item = p_ws->TxMsgListHeadPtr;
|
|
|
|
if (p_msg_item == DEF_NULL) {
|
|
p_ws->TxMsgListEndPtr = DEF_NULL;
|
|
} else if (p_msg_item->NextPtr == DEF_NULL) {
|
|
p_ws->TxMsgListHeadPtr = DEF_NULL;
|
|
p_ws->TxMsgListEndPtr = DEF_NULL;
|
|
p_msg_item->NextPtr = 0;
|
|
} else {
|
|
p_ws->TxMsgListHeadPtr = p_msg_item->NextPtr;
|
|
}
|
|
if (p_msg_item != DEF_NULL) {
|
|
p_msg_item->Flags.IsUsed = DEF_NO;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPcWebSock_TxMsgCleanList()
|
|
*
|
|
* Description : Remove all the pending WebSocket message.
|
|
*
|
|
* Argument(s) : p_conn Pointer to current HTTPc Connection (WebSocket Upgraded).
|
|
*
|
|
* Return(s) : none.
|
|
*
|
|
* Caller(s) : HTTPcConn_WebSocketProcess().
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void HTTPcWebSock_TxMsgCleanList(HTTPc_CONN *p_conn)
|
|
{
|
|
|
|
HTTPc_WEBSOCK *p_ws;
|
|
HTTPc_CONN_OBJ *p_conn_const;
|
|
HTTPc_WEBSOCK_MSG *p_msg;
|
|
HTTPc_WEBSOCK_MSG_OBJ *p_msg_const;
|
|
|
|
|
|
p_ws = p_conn->WebSockPtr;
|
|
|
|
while (p_ws->TxMsgListHeadPtr != DEF_NULL) {
|
|
p_msg = (HTTPc_WEBSOCK_MSG *)p_ws->TxMsgListHeadPtr;
|
|
/* Call On Msg Tx Complete Callback if set. */
|
|
if (p_msg->OnMsgTxComplete != DEF_NULL) {
|
|
p_conn_const = (HTTPc_CONN_OBJ *)p_conn;
|
|
p_msg_const = (HTTPc_WEBSOCK_MSG_OBJ *)p_ws->TxMsgListHeadPtr;
|
|
p_msg->OnMsgTxComplete(p_conn_const, p_msg_const, DEF_FAIL);
|
|
}
|
|
HTTPcWebSock_TxMsgRemove(p_conn);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPcWebSock_ComputeHdrLen()
|
|
*
|
|
* Description : Compute the header length of a WebSocket Msg.
|
|
*
|
|
* Argument(s) : p_msg Pointer to a WebSocket Msg obj.
|
|
*
|
|
* Return(s) : Length of the header.
|
|
*
|
|
* Caller(s) : HTTPcWebSock_TX().
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static CPU_INT16U HTTPcWebSock_ComputeHdrLen(HTTPc_WEBSOCK_MSG *p_msg)
|
|
{
|
|
CPU_INT16U hdr_len ;
|
|
|
|
|
|
hdr_len = 2; /* Minimum Header Len. */
|
|
|
|
if (p_msg->Len >= HTTPc_WEBSOCK_LONG_FRAME_MIN_LEN) {
|
|
/* Use the extended 64-bits payload len. */
|
|
hdr_len += sizeof(CPU_INT64U);
|
|
|
|
} else if (p_msg->Len >= HTTPc_WEBSOCK_NORMAL_FRAME_MIN_LEN) {
|
|
/* Use the extended 16-bits payload len. */
|
|
hdr_len += sizeof(CPU_INT16U);
|
|
}
|
|
|
|
if (p_msg->Flags.IsMasked == DEF_YES) {
|
|
hdr_len += sizeof(CPU_INT32U);
|
|
}
|
|
|
|
return (hdr_len);
|
|
}
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPcWebSock_IsProtocolError()
|
|
*
|
|
* Description : Check if the error code is related to a WebSocket protocol error.
|
|
*
|
|
* Argument(s) : err Error code to check.
|
|
*
|
|
* Return(s) : DEF_YES, if the error code is a protocol error.
|
|
* DEF_NO, if the error code is NOT a protocol error.
|
|
*
|
|
* Caller(s) : HTTPcWebSock_Process().
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static CPU_BOOLEAN HTTPcWebSock_IsProtocolError(HTTPc_ERR err)
|
|
{
|
|
|
|
|
|
switch (err) {
|
|
case HTTPc_ERR_WEBSOCK_RX_RSVD_BIT_1_SET:
|
|
case HTTPc_ERR_WEBSOCK_RX_RSVD_BIT_2_SET:
|
|
case HTTPc_ERR_WEBSOCK_RX_RSVD_BIT_3_SET:
|
|
case HTTPc_ERR_WEBSOCK_RX_CTRL_FRAME_TOO_LONG:
|
|
case HTTPc_ERR_WEBSOCK_RX_CTRL_FRAME_FRAGMENTED:
|
|
case HTTPc_ERR_WEBSOCK_RX_INVALID_OPCODE:
|
|
case HTTPc_ERR_WEBSOCK_RX_FRAG_FRAME_SEQUENCE_INVALID:
|
|
case HTTPc_ERR_WEBSOCK_RX_CLOSE_CODE_INVALID:
|
|
return DEF_YES;
|
|
|
|
default:
|
|
return DEF_NO;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPcWebSock_IsStandardCloseCode()
|
|
*
|
|
* Description : Check if the Close code value is known and standarized.
|
|
*
|
|
* Argument(s) : close_code Close code value to check.
|
|
*
|
|
* Return(s) : DEF_YES, if the close code is standard.
|
|
* DEF_NO, if the close code is NOT standard.
|
|
*
|
|
* Caller(s) : HTTPcWebSock_RX().
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static CPU_BOOLEAN HTTPcWebSock_IsStandardCloseCode(HTTPc_WEBSOCK_CLOSE_CODE close_code)
|
|
{
|
|
|
|
|
|
switch (close_code) {
|
|
case HTTPc_WEBSOCK_CLOSE_CODE_NORMAL:
|
|
case HTTPc_WEBSOCK_CLOSE_CODE_GOING_AWAY:
|
|
case HTTPc_WEBSOCK_CLOSE_CODE_PROTOCOL_ERR:
|
|
case HTTPc_WEBSOCK_CLOSE_CODE_DATA_TYPE_NOT_ALLOWED:
|
|
case HTTPc_WEBSOCK_CLOSE_CODE_DATA_TYPE_ERR:
|
|
case HTTPc_WEBSOCK_CLOSE_CODE_POLICY_VIOLATION:
|
|
case HTTPc_WEBSOCK_CLOSE_CODE_MSG_TOO_BIG:
|
|
case HTTPc_WEBSOCK_CLOSE_CODE_INVALID_EXT:
|
|
case HTTPc_WEBSOCK_CLOSE_CODE_UNEXPECTED_CONDITION:
|
|
return DEF_YES;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
if ((close_code >= 3000) && (close_code <= 4999)) {
|
|
return DEF_YES;
|
|
}
|
|
return DEF_NO;
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
* MODULE END
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
#endif /* HTTPc_WEBSOCK_MODULE_EN */
|