3165 lines
106 KiB
C
3165 lines
106 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
|
|
*
|
|
* Filename : http-c.c
|
|
* Version : V3.01.00
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
* INCLUDE FILES
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
#define MICRIUM_SOURCE
|
|
#define HTTPc_MODULE
|
|
|
|
#include <net_ascii.h>
|
|
#include <net_util.h>
|
|
#include "http-c.h"
|
|
#include "http-c_type.h"
|
|
#include "http-c_sock.h"
|
|
#include "http-c_conn.h"
|
|
#include "http-c_req.h"
|
|
#include "http-c_resp.h"
|
|
#include "http-c_mem.h"
|
|
#ifdef HTTPc_TASK_MODULE_EN
|
|
#include "http-c_task.h"
|
|
#endif
|
|
#ifdef HTTPc_WEBSOCK_MODULE_EN
|
|
#include "http-c_websock.h"
|
|
#endif
|
|
|
|
#define ASCII_CHAR_SPACE 0x20 /* ' ' */
|
|
#define ASCII_CHAR_COLON 0x3A /* ':' */
|
|
#define ASCII_CHAR_QUESTION_MARK 0x3F /* '\?' */
|
|
#define ASCII_CHAR_EQUALS_SIGN 0x3D /* '=' */
|
|
#define ASCII_CHAR_AMPERSAND 0x26 /* '&' */
|
|
#define ASCII_CHAR_QUESTION_MARK 0x3F /* '\?' */
|
|
#define ASCII_CHAR_SEMICOLON 0x3B /* ';' */
|
|
#define ASCII_CHAR_EQUALS_SIGN 0x3D /* '=' */
|
|
#define ASCII_CHAR_QUOTATION_MARK 0x22 /* '\"' */
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
* LOCAL DEFINES
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
#define HTTPc_BUF_LEN_MIN 256u
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
* LOCAL GLOBAL VARIABLES
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static CPU_BOOLEAN HTTPc_InitDone = DEF_NO;
|
|
|
|
static const HTTPc_CFG *HTTPc_CfgPtr;
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
* LOCAL FUNCTION PROTOTYPES
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
#if ((HTTPc_CFG_PERSISTENT_EN == DEF_ENABLED) || \
|
|
defined(HTTPc_SIGNAL_TASK_MODULE_EN) )
|
|
static void HTTPc_ConnCloseHandler(HTTPc_CONN *p_conn,
|
|
HTTPc_FLAGS flags,
|
|
HTTPc_ERR *p_err);
|
|
#endif
|
|
|
|
/*uchttp只能初始化一次*/
|
|
CPU_BOOLEAN HTTPc_Is_InitDone(void)
|
|
{
|
|
return HTTPc_InitDone;
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPc_Init()
|
|
*
|
|
* Description : (1) Initialize HTTP Client Suite :
|
|
* (a) Validate Configuration.
|
|
* (c) Create HTTP Client Task if necessary.
|
|
*
|
|
*
|
|
* Argument(s) : p_cfg Pointer to HTTP Client Instance Configuration Object.
|
|
*
|
|
* p_task_cfg Pointer to HTTP Client task configuration object.
|
|
*
|
|
* p_mem_seg For future usage: Set to DEF_NULL.
|
|
*
|
|
* p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* HTTPc_ERR_NONE HTTPc Initialization successful.
|
|
* HTTPc_ERR_NULL_PTR function passed a null pointer as argument(s).
|
|
* HTTPc_ERR_CFG_CONN_INACTIVITY_TIMEOUT_INVALID Invalid inactivity timeout value.
|
|
* HTTPc_ERR_CFG_CONN_Q_SIZE_INVALID Invalid Conn Q size value.
|
|
* HTTPc_ERR_CFG_REQ_Q_SIZE_INVALID Invalid Request Q size value.
|
|
* HTTPc_ERR_CFG_TASK_PTR_NULL Null Task configuration's pointer.
|
|
* HTTPc_ERR_INIT HTTPc Initialization failed.
|
|
**
|
|
* ----------- RETURNED BY HTTPcTask_Init() : ------------
|
|
* See HTTPcTask_Init() for additional return error codes.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Caller(s) : Application.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
void HTTPc_Init(const HTTPc_CFG *p_cfg,
|
|
const HTTP_TASK_CFG *p_task_cfg,
|
|
MEM_SEG *p_mem_seg,
|
|
HTTPc_ERR *p_err)
|
|
{
|
|
CPU_SR_ALLOC();
|
|
|
|
|
|
CPU_CRITICAL_ENTER();
|
|
if (HTTPc_InitDone == DEF_NO) {
|
|
CPU_CRITICAL_EXIT();
|
|
|
|
#if (HTTPc_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
|
|
|
|
if (p_err == DEF_NULL) { /* Validate p_err ptr. */
|
|
CPU_SW_EXCEPTION();
|
|
}
|
|
|
|
if (p_cfg == DEF_NULL) { /* Validate cfg ptr. */
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
|
|
if (p_cfg->MsgQ_Size <= 0) {
|
|
*p_err = HTTPc_ERR_CFG_MSG_Q_SIZE_INVALID;
|
|
goto exit;
|
|
}
|
|
|
|
#ifdef HTTPc_TASK_MODULE_EN
|
|
/* Validate HTTPc Task parameters. */
|
|
if (p_task_cfg == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_CFG_TASK_PTR_NULL;
|
|
goto exit;
|
|
}
|
|
|
|
HTTPcTask_SetDly(p_cfg->TaskDly_ms, p_err);
|
|
if (*p_err != HTTPc_ERR_NONE) {
|
|
goto exit;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
HTTPc_CfgPtr = p_cfg; /* Set global Cfg pointer variable. */
|
|
|
|
|
|
#ifdef HTTPc_TASK_MODULE_EN
|
|
HTTPc_Mem_TaskMsgPoolInit(p_cfg, p_mem_seg, p_err);
|
|
if (*p_err != HTTPc_ERR_NONE) {
|
|
goto exit;
|
|
}
|
|
#ifdef HTTPc_WEBSOCK_MODULE_EN
|
|
HTTPc_Mem_WebSockReqPoolInit(p_cfg, p_mem_seg, p_err);
|
|
if (*p_err != HTTPc_ERR_NONE) {
|
|
goto exit;
|
|
}
|
|
#endif
|
|
HTTPcTask_Init(p_cfg, /* HTTPc Task creation. */
|
|
p_task_cfg,
|
|
p_err);
|
|
if (*p_err != HTTPc_ERR_NONE) {
|
|
goto exit;
|
|
}
|
|
#endif
|
|
|
|
} else {
|
|
CPU_CRITICAL_EXIT();
|
|
*p_err = HTTPc_ERR_INIT;
|
|
goto exit;
|
|
}
|
|
|
|
CPU_CRITICAL_ENTER();
|
|
HTTPc_InitDone = DEF_YES;
|
|
CPU_CRITICAL_EXIT();
|
|
|
|
(void)p_mem_seg;
|
|
|
|
*p_err = HTTPc_ERR_NONE;
|
|
|
|
|
|
exit:
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPc_ConnClr()
|
|
*
|
|
* Description : Clear an HTTPc Connection before the first usage.
|
|
*
|
|
* Argument(s) : p_conn_obj Pointer to the current HTTPc Connection.
|
|
*
|
|
* p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* HTTPc_ERR_NONE Connection object clear successfully.
|
|
* HTTPc_ERR_INIT_NOT_COMPLETED HTTPc Initialization is not completed.
|
|
* HTTPc_ERR_NULL_PTR Function passed Null pointer as argument(s).
|
|
* HTTPc_ERR_CONN_IS_USED Connection is already used.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Caller(s) : Application.
|
|
*
|
|
* Note(s) : (1) This function MUST be called before the HTTPc_CONN object is used for the first time.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
void HTTPc_ConnClr(HTTPc_CONN_OBJ *p_conn_obj,
|
|
HTTPc_ERR *p_err)
|
|
{
|
|
const HTTPc_CFG *p_cfg;
|
|
HTTPc_CONN *p_conn;
|
|
CPU_BOOLEAN in_use;
|
|
CPU_SR_ALLOC();
|
|
|
|
|
|
/* --------------- ARGUMENTS VALIDATION --------------- */
|
|
#if (HTTPc_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
|
|
if (p_err == DEF_NULL) {
|
|
CPU_SW_EXCEPTION(;);
|
|
}
|
|
|
|
if (HTTPc_InitDone != DEF_YES) {
|
|
*p_err = HTTPc_ERR_INIT_NOT_COMPLETED;
|
|
goto exit;
|
|
}
|
|
|
|
if (p_conn_obj == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
#endif
|
|
|
|
p_cfg = HTTPc_CfgPtr;
|
|
p_conn = (HTTPc_CONN *)p_conn_obj;
|
|
|
|
/* ------ VALIDATE THAT CONN IS NOT USED ALREADY ------ */
|
|
CPU_CRITICAL_ENTER();
|
|
in_use = DEF_BIT_IS_SET(p_conn->Flags, HTTPc_FLAG_CONN_IN_USE);
|
|
CPU_CRITICAL_EXIT();
|
|
if (in_use == DEF_YES) {
|
|
*p_err = HTTPc_ERR_CONN_IS_USED;
|
|
goto exit;
|
|
}
|
|
|
|
/* ------------ INIT CONNECTION PARAMETERS ------------ */
|
|
Mem_Clr(&p_conn->ServerSockAddr, sizeof(NET_SOCK_ADDR));
|
|
p_conn->SockID = NET_SOCK_ID_NONE;
|
|
p_conn->SockFlags = DEF_BIT_NONE;
|
|
p_conn->ConnectTimeout_ms = p_cfg->ConnConnectTimeout_ms;
|
|
p_conn->InactivityTimeout_s = p_cfg->ConnInactivityTimeout_s;
|
|
p_conn->ServerPort = HTTP_DFLT_PORT_NBR;
|
|
#ifdef NET_SECURE_MODULE_EN
|
|
p_conn->SockSecureCfg.CommonName = DEF_NULL;
|
|
p_conn->SockSecureCfg.TrustCallback = DEF_NULL;
|
|
#endif
|
|
p_conn->HostNamePtr = DEF_NULL;
|
|
p_conn->HostNameLen = 0;
|
|
p_conn->State = HTTPc_CONN_STATE_NONE;
|
|
p_conn->Flags = DEF_BIT_NONE;
|
|
p_conn->ErrCode = HTTPc_ERR_NONE;
|
|
p_conn->CloseStatus = HTTPc_CONN_CLOSE_STATUS_NONE;
|
|
#ifdef HTTPc_TASK_MODULE_EN
|
|
p_conn->OnConnect = DEF_NULL;
|
|
p_conn->OnClose = DEF_NULL;
|
|
#endif
|
|
p_conn->IsKeepAlive = p_cfg->ConnIsKeepAlive;
|
|
|
|
/* ------------- INIT REQUEST PARAMETERS -------------- */
|
|
p_conn->ReqListHeadPtr = DEF_NULL;
|
|
p_conn->ReqListEndPtr = DEF_NULL;
|
|
p_conn->ReqFlags = 0u;
|
|
#if (HTTPc_CFG_QUERY_STR_EN == DEF_ENABLED)
|
|
p_conn->ReqQueryStrTxIx = 0u;
|
|
p_conn->ReqQueryStrTempPtr = DEF_NULL;
|
|
#endif
|
|
#if (HTTPc_CFG_HDR_TX_EN == DEF_ENABLED)
|
|
p_conn->ReqHdrTxIx = 0u;
|
|
p_conn->ReqHdrTempPtr = DEF_NULL;
|
|
#endif
|
|
#if (HTTPc_CFG_FORM_EN == DEF_ENABLED)
|
|
p_conn->ReqFormDataTxIx = 0u;
|
|
#endif
|
|
p_conn->ReqDataOffset = 0u;
|
|
|
|
/* ------------- INIT RESPONSE PARAMETERS ------------- */
|
|
p_conn->RespFlags = 0u;
|
|
|
|
|
|
/* --------- INIT CONNECTION BUFFER PARAMETERS -------- */
|
|
p_conn->RxBufPtr = p_conn->BufPtr;
|
|
p_conn->RxDataLenRem = 0u;
|
|
p_conn->RxDataLen = 0u;
|
|
p_conn->TxBufPtr = p_conn->BufPtr;
|
|
p_conn->TxDataLen = 0u;
|
|
p_conn->TxDataPtr = DEF_NULL;
|
|
p_conn->BufPtr = DEF_NULL;
|
|
p_conn->BufLen = 0;
|
|
p_conn->NextPtr = DEF_NULL;
|
|
|
|
*p_err = HTTPc_ERR_NONE;
|
|
|
|
|
|
exit:
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPc_ConnSetParam()
|
|
*
|
|
* Description : Set parameters related to the HTTP Client Connection.
|
|
*
|
|
* Argument(s) : p_conn Pointer to the current HTTPc Connection.
|
|
*
|
|
* type Parameter type :
|
|
*
|
|
* HTTPc_PARAM_TYPE_SERVER_PORT
|
|
* HTTPc_PARAM_TYPE_PERSISTENT
|
|
* HTTPc_PARAM_TYPE_CONNECT_TIMEOUT
|
|
* HTTPc_PARAM_TYPE_INACTIVITY_TIMEOUT
|
|
* HTTPc_PARAM_TYPE_SECURE_COMMON_NAME
|
|
* HTTPc_PARAM_TYPE_SECURE_TRUST_CALLBACK
|
|
* HTTPc_PARAM_TYPE_CONN_CONNECT_CALLBACK
|
|
* HTTPc_PARAM_TYPE_CONN_CLOSE_CALLBACK
|
|
*
|
|
* p_param Pointer to parameter
|
|
*
|
|
* p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* HTTPc_ERR_NONE Parameter set successfully.
|
|
* HTTPc_ERR_INIT_NOT_COMPLETED HTTP Client Initialization not completed.
|
|
* HTTPc_ERR_NULL_PTR Function passed Null argument(s).
|
|
* HTTPc_ERR_CONN_IS_USED HTTPc Connection currently used.
|
|
* HTTPc_ERR_PARAM_INVALID Invalid parameter passed.
|
|
* HTTPc_ERR_FEATURE_DIS Parameter is related with a disabled feature.
|
|
*
|
|
* Return(s) : None
|
|
*
|
|
* Caller(s) : Application.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
void HTTPc_ConnSetParam(HTTPc_CONN_OBJ *p_conn_obj,
|
|
HTTPc_PARAM_TYPE type,
|
|
void *p_param,
|
|
HTTPc_ERR *p_err)
|
|
{
|
|
HTTPc_CONN *p_conn;
|
|
CPU_BOOLEAN in_use;
|
|
#if (HTTPc_CFG_PERSISTENT_EN == DEF_ENABLED)
|
|
CPU_BOOLEAN persistent;
|
|
#endif
|
|
CPU_SR_ALLOC();
|
|
|
|
|
|
/* --------------- ARGUMENTS VALIDATION --------------- */
|
|
#if (HTTPc_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
|
|
if (p_err == DEF_NULL) {
|
|
CPU_SW_EXCEPTION(;);
|
|
}
|
|
|
|
if (HTTPc_InitDone != DEF_YES) {
|
|
*p_err = HTTPc_ERR_INIT_NOT_COMPLETED;
|
|
goto exit;
|
|
}
|
|
|
|
if (p_conn_obj == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
|
|
if (p_param == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
#endif
|
|
|
|
p_conn = (HTTPc_CONN *)p_conn_obj;
|
|
|
|
/* ------ VALIDATE THAT CONN IS NOT USED ALREADY ------ */
|
|
CPU_CRITICAL_ENTER();
|
|
in_use = DEF_BIT_IS_SET(p_conn->Flags, HTTPc_FLAG_CONN_IN_USE);
|
|
CPU_CRITICAL_EXIT();
|
|
if (in_use == DEF_YES) {
|
|
*p_err = HTTPc_ERR_CONN_IS_USED;
|
|
goto exit;
|
|
}
|
|
|
|
switch (type) {
|
|
case HTTPc_PARAM_TYPE_SERVER_PORT:
|
|
p_conn->ServerPort = *(NET_PORT_NBR *)p_param;
|
|
break;
|
|
|
|
|
|
case HTTPc_PARAM_TYPE_PERSISTENT:
|
|
#if (HTTPc_CFG_PERSISTENT_EN == DEF_ENABLED)
|
|
persistent = *(CPU_BOOLEAN *)p_param;
|
|
if (persistent == DEF_YES) {
|
|
DEF_BIT_SET(p_conn->Flags, HTTPc_FLAG_CONN_PERSISTENT);
|
|
}
|
|
break;
|
|
#else
|
|
*p_err = HTTPc_ERR_FEATURE_DIS;
|
|
goto exit;
|
|
#endif
|
|
|
|
|
|
case HTTPc_PARAM_TYPE_CONNECT_TIMEOUT:
|
|
p_conn->ConnectTimeout_ms = *(CPU_INT16U *)p_param;
|
|
break;
|
|
|
|
|
|
case HTTPc_PARAM_TYPE_INACTIVITY_TIMEOUT:
|
|
p_conn->InactivityTimeout_s = *(CPU_INT16U *)p_param;
|
|
break;
|
|
|
|
|
|
case HTTPc_PARAM_TYPE_SECURE_COMMON_NAME:
|
|
#ifdef NET_SECURE_MODULE_EN
|
|
p_conn->SockSecureCfg.CommonName = (CPU_CHAR *)p_param;
|
|
break;
|
|
#else
|
|
*p_err = HTTPc_ERR_FEATURE_DIS;
|
|
goto exit;
|
|
#endif
|
|
|
|
|
|
case HTTPc_PARAM_TYPE_SECURE_TRUST_CALLBACK:
|
|
#ifdef NET_SECURE_MODULE_EN
|
|
p_conn->SockSecureCfg.TrustCallback = (NET_SOCK_SECURE_TRUST_FNCT)p_param;
|
|
break;
|
|
#else
|
|
*p_err = HTTPc_ERR_FEATURE_DIS;
|
|
goto exit;
|
|
#endif
|
|
|
|
|
|
case HTTPc_PARAM_TYPE_CONN_CONNECT_CALLBACK:
|
|
#ifdef HTTPc_TASK_MODULE_EN
|
|
p_conn->OnConnect = (HTTPc_CONNECT_CALLBACK)p_param;
|
|
break;
|
|
#else
|
|
*p_err = HTTPc_ERR_FEATURE_DIS;
|
|
goto exit;
|
|
#endif
|
|
|
|
|
|
case HTTPc_PARAM_TYPE_CONN_CLOSE_CALLBACK:
|
|
#ifdef HTTPc_TASK_MODULE_EN
|
|
p_conn->OnClose = (HTTPc_CONN_CLOSE_CALLBACK)p_param;
|
|
break;
|
|
#else
|
|
*p_err = HTTPc_ERR_FEATURE_DIS;
|
|
goto exit;
|
|
#endif
|
|
|
|
case HTTPc_PARAM_TYPE_USER_SECURE_DATA: //增加
|
|
p_conn->UserData = (void *)p_param;
|
|
break;
|
|
|
|
case HTTPc_PARAM_TYPE_SECURE_MUTUAL: //增加,ssl_tsl安全连接参数设置
|
|
#ifdef NET_SECURE_MODULE_EN
|
|
p_conn->SockSecureCfg.MutualAuthPtr = (void *)p_param;
|
|
break;
|
|
#else
|
|
*p_err = HTTPc_ERR_FEATURE_DIS;
|
|
goto exit;
|
|
#endif
|
|
|
|
default:
|
|
*p_err = HTTPc_ERR_PARAM_INVALID;
|
|
goto exit;
|
|
}
|
|
|
|
*p_err = HTTPc_ERR_NONE;
|
|
|
|
|
|
exit:
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPc_ConnOpen()
|
|
*
|
|
* Description : Open a new HTTP connection.
|
|
*
|
|
* Argument(s) : p_conn_obj Pointer to HTTPc Connection object to open.
|
|
*
|
|
* p_buf Pointer to the HTTP buffer that will be used to Tx and Rx data.
|
|
*
|
|
* buf_len Length of the HTTP buffer.
|
|
*
|
|
* p_hostname_str Pointer to the hostname string.
|
|
*
|
|
* hostname_str_len Length of the hostname string.
|
|
*
|
|
* flags Configuration flags :
|
|
*
|
|
* HTTPc_FLAG_CONN_NO_BLOCK
|
|
*
|
|
* p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* HTTPc_ERR_NONE Connection Open successfully started.
|
|
* HTTPc_ERR_INIT_NOT_COMPLETED HTTPc Initialization is not completed.
|
|
* HTTPc_ERR_NULL_PTR Function passed null pointer as argument(s).
|
|
* HTTPc_ERR_CFG_INVALID_BUF_LEN Buffer Length is to small.
|
|
* HTTPc_ERR_CONN_PARAM_HOSTNAME_INVALID Hostname Pointer is null.
|
|
* HTTPc_ERR_CONN_IS_USED Connection is already used.
|
|
*
|
|
* Return(s) : DEF_OK, if Connection opening successfully completed.
|
|
* DEF_FAIL, otherwise.
|
|
*
|
|
* Caller(s) : Application.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
CPU_BOOLEAN HTTPc_ConnOpen(HTTPc_CONN_OBJ *p_conn_obj,
|
|
CPU_CHAR *p_buf,
|
|
CPU_INT16U buf_len,
|
|
CPU_CHAR *p_hostname_str,
|
|
CPU_INT16U hostname_str_len,
|
|
HTTPc_FLAGS flags,
|
|
HTTPc_ERR *p_err)
|
|
{
|
|
HTTPc_CONN *p_conn;
|
|
CPU_BOOLEAN result;
|
|
CPU_BOOLEAN in_use;
|
|
CPU_BOOLEAN no_block;
|
|
#ifdef HTTPc_TASK_MODULE_EN
|
|
HTTPc_ERR err;
|
|
#endif
|
|
CPU_SR_ALLOC();
|
|
|
|
|
|
result = DEF_FAIL;
|
|
|
|
/* --------------- ARGUMENTS VALIDATION --------------- */
|
|
#if (HTTPc_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
|
|
if (p_err == DEF_NULL) {
|
|
CPU_SW_EXCEPTION(DEF_FAIL);
|
|
}
|
|
|
|
if (HTTPc_InitDone != DEF_YES) {
|
|
*p_err = HTTPc_ERR_INIT_NOT_COMPLETED;
|
|
goto exit;
|
|
}
|
|
|
|
if (p_conn_obj == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
|
|
if (p_buf == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
|
|
if (buf_len < HTTPc_BUF_LEN_MIN) {
|
|
*p_err = HTTPc_ERR_CFG_INVALID_BUF_LEN;
|
|
goto exit;
|
|
}
|
|
|
|
if (p_hostname_str == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_CONN_PARAM_HOSTNAME_INVALID;
|
|
goto exit;
|
|
}
|
|
|
|
if (hostname_str_len <= 0) {
|
|
*p_err = HTTPc_ERR_CONN_PARAM_HOSTNAME_INVALID;
|
|
goto exit;
|
|
}
|
|
#endif
|
|
|
|
p_conn = (HTTPc_CONN *)p_conn_obj;
|
|
/* ------ VALIDATE THAT CONN IS NOT USED ALREADY ------ */
|
|
CPU_CRITICAL_ENTER();
|
|
in_use = DEF_BIT_IS_SET(p_conn->Flags, HTTPc_FLAG_CONN_IN_USE);
|
|
CPU_CRITICAL_EXIT();
|
|
if (in_use == DEF_YES) {
|
|
*p_err = HTTPc_ERR_CONN_IS_USED;
|
|
goto exit;
|
|
}
|
|
|
|
/* -------------- SET BUFFER PARAMETERS --------------- */
|
|
p_conn->BufPtr = p_buf;
|
|
p_conn->TxBufPtr = p_buf;
|
|
p_conn->RxBufPtr = p_buf;
|
|
p_conn->BufLen = buf_len;
|
|
p_conn->NextPtr = DEF_NULL;
|
|
|
|
/* ------------- SET HOSTNAME PARAMETERS -------------- */
|
|
p_conn->HostNamePtr = p_hostname_str;
|
|
p_conn->HostNameLen = hostname_str_len;
|
|
|
|
/* ---------------- SET BLOCKING MODE ----------------- */
|
|
no_block = DEF_BIT_IS_SET(flags, HTTPc_FLAG_CONN_NO_BLOCK);
|
|
if (no_block == DEF_YES) {
|
|
DEF_BIT_SET(p_conn->Flags, HTTPc_FLAG_CONN_NO_BLOCK);
|
|
} else {
|
|
DEF_BIT_CLR(p_conn->Flags, HTTPc_FLAG_CONN_NO_BLOCK);
|
|
}
|
|
|
|
#ifdef HTTPc_TASK_MODULE_EN
|
|
|
|
if (no_block == DEF_NO) {
|
|
#ifdef HTTPc_SIGNAL_TASK_MODULE_EN
|
|
HTTPcTask_ConnConnectSignalCreate(p_conn, p_err);
|
|
if (*p_err != HTTPc_ERR_NONE) {
|
|
goto exit;
|
|
}
|
|
#else
|
|
*p_err = HTTPc_ERR_FEATURE_DIS;
|
|
goto exit;
|
|
#endif
|
|
}
|
|
|
|
HTTPcTask_MsgQueue(HTTPc_MSG_TYPE_CONN_OPEN,
|
|
(void *) p_conn,
|
|
p_err);
|
|
if (*p_err != HTTPc_ERR_NONE) {
|
|
goto exit;
|
|
}
|
|
|
|
HTTPcTask_Wake(p_conn, &err);
|
|
if (*p_err != HTTPc_ERR_NONE) {
|
|
CPU_SW_EXCEPTION(DEF_FAIL);
|
|
}
|
|
|
|
|
|
if (no_block == DEF_NO) {
|
|
#ifdef HTTPc_SIGNAL_TASK_MODULE_EN
|
|
HTTPcTask_ConnConnectSignalWait(p_conn, p_err);
|
|
if (*p_err != HTTPc_ERR_NONE) {
|
|
HTTPc_ConnCloseHandler(p_conn, HTTPc_FLAG_NONE, &err);
|
|
goto exit;
|
|
}
|
|
|
|
HTTPcTask_ConnConnectSignalDel(p_conn, p_err);
|
|
if (*p_err != HTTPc_ERR_NONE) {
|
|
HTTPc_ConnCloseHandler(p_conn, HTTPc_FLAG_NONE, &err);
|
|
goto exit;
|
|
}
|
|
|
|
CPU_CRITICAL_ENTER();
|
|
result = DEF_BIT_IS_SET(p_conn->Flags, HTTPc_FLAG_CONN_CONNECT);
|
|
CPU_CRITICAL_EXIT();
|
|
if (result == DEF_FAIL) {
|
|
*p_err = p_conn->ErrCode;
|
|
goto exit;
|
|
}
|
|
|
|
#else
|
|
*p_err = HTTPc_ERR_FEATURE_DIS;
|
|
goto exit;
|
|
#endif
|
|
}
|
|
|
|
#else
|
|
|
|
if (no_block == DEF_YES) {
|
|
*p_err = HTTPc_ERR_FEATURE_DIS;
|
|
goto exit;
|
|
}
|
|
|
|
HTTPcConn_Add(p_conn);
|
|
|
|
while ((p_conn->State != HTTPc_CONN_STATE_PARAM_VALIDATE) &&
|
|
(p_conn->State != HTTPc_CONN_STATE_NONE)) {
|
|
HTTPcConn_Process(p_conn);
|
|
}
|
|
|
|
*p_err = p_conn->ErrCode;
|
|
if (*p_err != HTTPc_ERR_NONE) {
|
|
goto exit;
|
|
}
|
|
|
|
result = DEF_OK;
|
|
|
|
#endif
|
|
|
|
*p_err = HTTPc_ERR_NONE;
|
|
exit:
|
|
return (result);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPc_ConnClose()
|
|
*
|
|
* Description : Close a persistent HTTPc Connection.
|
|
*
|
|
* Argument(s) : p_conn_obj Pointer to HTTPc Connection to close.
|
|
*
|
|
* flags Configuration flags :
|
|
*
|
|
* HTTPc_FLAG_CONN_NO_BLOCK
|
|
*
|
|
* p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* HTTPc_ERR_NONE Connection closing successfully started.
|
|
* HTTPc_ERR_INIT_NOT_COMPLETED HTTPc Initialization is not completed.
|
|
* HTTPc_ERR_NULL_PTR Function passed a null pointer as argument.
|
|
* HTTPc_ERR_FEATURE_DIS Connection Close function is unavailable.
|
|
*
|
|
* ------------ RETURNED BY HTTPc_ConnCloseHandler() ------------
|
|
* See HTTPc_ConnCloseHandler() for additional return error codes.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Caller(s) : Application.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
void HTTPc_ConnClose(HTTPc_CONN_OBJ *p_conn_obj,
|
|
HTTPc_FLAGS flags,
|
|
HTTPc_ERR *p_err)
|
|
{
|
|
HTTPc_CONN *p_conn;
|
|
|
|
|
|
#if (HTTPc_CFG_PERSISTENT_EN == DEF_ENABLED)
|
|
/* --------------- ARGUMENTS VALIDATION --------------- */
|
|
#if (HTTPc_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
|
|
if (p_err == DEF_NULL) {
|
|
CPU_SW_EXCEPTION(;);
|
|
}
|
|
|
|
if (HTTPc_InitDone != DEF_YES) {
|
|
*p_err = HTTPc_ERR_INIT_NOT_COMPLETED;
|
|
goto exit;
|
|
}
|
|
|
|
if (p_conn_obj == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
#endif
|
|
|
|
p_conn = (HTTPc_CONN *)p_conn_obj;
|
|
|
|
HTTPc_ConnCloseHandler(p_conn, flags, p_err);
|
|
if (*p_err != HTTPc_ERR_NONE) {
|
|
goto exit;
|
|
}
|
|
|
|
*p_err = HTTPc_ERR_NONE;
|
|
|
|
goto exit;
|
|
|
|
#else
|
|
(void)p_conn;
|
|
|
|
*p_err = HTTPc_ERR_FEATURE_DIS;
|
|
|
|
goto exit;
|
|
#endif
|
|
|
|
exit:
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPc_ReqClr()
|
|
*
|
|
* Description : Clear Request object members.
|
|
*
|
|
* Argument(s) : p_req_obj Pointer to request object to clear.
|
|
*
|
|
* p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* HTTPc_ERR_NONE Request cleared successfully.
|
|
* HTTPc_ERR_INIT_NOT_COMPLETED HTTP Client Initialization not completed.
|
|
* HTTPc_ERR_NULL_PTR Function passed a Null arguments.
|
|
* HTTPc_ERR_REQ_IS_USED Request object already in usage.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Caller(s) : Application.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
void HTTPc_ReqClr(HTTPc_REQ_OBJ *p_req_obj,
|
|
HTTPc_ERR *p_err)
|
|
{
|
|
HTTPc_REQ *p_req;
|
|
CPU_BOOLEAN in_use;
|
|
CPU_SR_ALLOC();
|
|
|
|
|
|
/* --------------- ARGUMENTS VALIDATION --------------- */
|
|
#if (HTTPc_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
|
|
if (p_err == DEF_NULL) {
|
|
CPU_SW_EXCEPTION(;);
|
|
}
|
|
|
|
if (HTTPc_InitDone != DEF_YES) {
|
|
printf(">>>>>>>>>>>---------------------------------->>>>>>>>>>>>>%s, %d", __FUNCTION__, __LINE__);
|
|
*p_err = HTTPc_ERR_INIT_NOT_COMPLETED;
|
|
goto exit;
|
|
}
|
|
|
|
if (p_req_obj == DEF_NULL) {
|
|
printf(">>>>>>>>>>>---------------------------------->>>>>>>>>>>>>%s, %d", __FUNCTION__, __LINE__);
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
#endif
|
|
|
|
p_req = (HTTPc_REQ *)p_req_obj;
|
|
|
|
/* ------ VALIDATE THAT REQ IS NOT USED ALREADY ------- */
|
|
CPU_CRITICAL_ENTER();
|
|
in_use = DEF_BIT_IS_SET(p_req->Flags, HTTPc_FLAG_REQ_IN_USE);
|
|
CPU_CRITICAL_EXIT();
|
|
if (in_use == DEF_YES) {
|
|
printf(">>>>>>>>>>>---------------------------------->>>>>>>>>>>>>%s, %d", __FUNCTION__, __LINE__);
|
|
*p_err = HTTPc_ERR_REQ_IS_USED;
|
|
goto exit;
|
|
}
|
|
|
|
p_req->Flags = DEF_BIT_NONE;
|
|
p_req->HdrFlags = DEF_BIT_NONE;
|
|
p_req->Method = HTTP_METHOD_UNKNOWN;
|
|
p_req->ResourcePathPtr = DEF_NULL;
|
|
p_req->ResourcePathLen = 0;
|
|
p_req->ContentType = HTTP_CONTENT_TYPE_UNKNOWN;
|
|
p_req->ContentLen = 0u;
|
|
#if (HTTPc_CFG_QUERY_STR_EN == DEF_ENABLED)
|
|
p_req->QueryStrTbl = DEF_NULL;
|
|
p_req->QueryStrNbr = 0u;
|
|
p_req->OnQueryStrTx = DEF_NULL;
|
|
#endif
|
|
#if (HTTPc_CFG_HDR_TX_EN == DEF_ENABLED)
|
|
p_req->HdrTbl = DEF_NULL;
|
|
p_req->HdrNbr = 0;
|
|
p_req->OnHdrTx = DEF_NULL;
|
|
#endif
|
|
#if (HTTPc_CFG_FORM_EN == DEF_ENABLED)
|
|
p_req->FormFieldTbl = DEF_NULL;
|
|
p_req->FormFieldNbr = 0;
|
|
#endif
|
|
p_req->DataPtr = DEF_NULL;
|
|
#if (HTTPc_CFG_CHUNK_TX_EN == DEF_ENABLED)
|
|
p_req->OnBodyTx = DEF_NULL;
|
|
#endif
|
|
|
|
#if (HTTPc_CFG_HDR_RX_EN == DEF_ENABLED)
|
|
p_req->OnHdrRx = DEF_NULL;
|
|
#endif
|
|
p_req->OnBodyRx = DEF_NULL;
|
|
|
|
#ifdef HTTPc_TASK_MODULE_EN
|
|
p_req->OnTransComplete = DEF_NULL;
|
|
p_req->OnErr = DEF_NULL;
|
|
#endif
|
|
|
|
p_req->ConnPtr = DEF_NULL;
|
|
p_req->RespPtr = DEF_NULL;
|
|
|
|
p_req->NextPtr = DEF_NULL;
|
|
|
|
*p_err = HTTPc_ERR_NONE;
|
|
|
|
goto exit;
|
|
|
|
|
|
exit:
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPc_ReqSetParam()
|
|
*
|
|
* Description : Set a parameter related to a given HTTP Request.
|
|
*
|
|
* Argument(s) : p_req_obj Pointer to request object.
|
|
*
|
|
* type Parameter type :
|
|
*
|
|
* HTTPc_PARAM_TYPE_REQ_QUERY_STR_TBL
|
|
* HTTPc_PARAM_TYPE_REQ_QUERY_STR_HOOK
|
|
* HTTPc_PARAM_TYPE_REQ_HDR_TBL
|
|
* HTTPc_PARAM_TYPE_REQ_HDR_HOOK
|
|
* HTTPc_PARAM_TYPE_REQ_FORM_TBL
|
|
* HTTPc_PARAM_TYPE_REQ_BODY_CONTENT_TYPE
|
|
* HTTPc_PARAM_TYPE_REQ_BODY_CONTENT_LEN
|
|
* HTTPc_PARAM_TYPE_REQ_BODY_CHUNK
|
|
* HTTPc_PARAM_TYPE_REQ_BODY_HOOK
|
|
* HTTPc_PARAM_TYPE_RESP_HDR_HOOK
|
|
* HTTPc_PARAM_TYPE_RESP_BODY_HOOK
|
|
* HTTPc_PARAM_TYPE_TRANS_COMPLETE_CALLBACK
|
|
* HTTPc_PARAM_TYPE_TRANS_ERR_CALLBACK
|
|
*
|
|
* p_param Pointer to parameter.
|
|
*
|
|
* p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* HTTPc_ERR_NONE Parameter set successfully.
|
|
* HTTPc_ERR_INIT_NOT_COMPLETED HTTP Client Initialization not completed.
|
|
* HTTPc_ERR_NULL_PTR Function passed a null argument(s).
|
|
* HTTPc_ERR_REQ_IS_USED Request object already in usage.
|
|
* HTTPc_ERR_FEATURE_DIS Parameter is related to a feature disabled.
|
|
* HTTPc_ERR_PARAM_INVALID Invalid request parameter.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Caller(s) : Application.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
void HTTPc_ReqSetParam(HTTPc_REQ_OBJ *p_req_obj,
|
|
HTTPc_PARAM_TYPE type,
|
|
void *p_param,
|
|
HTTPc_ERR *p_err)
|
|
{
|
|
HTTPc_REQ *p_req;
|
|
HTTPc_PARAM_TBL *p_tbl_obj;
|
|
CPU_BOOLEAN in_use;
|
|
CPU_BOOLEAN chunk_en;
|
|
CPU_SR_ALLOC();
|
|
|
|
|
|
/* --------------- ARGUMENTS VALIDATION --------------- */
|
|
#if (HTTPc_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
|
|
if (p_err == DEF_NULL) {
|
|
CPU_SW_EXCEPTION(;);
|
|
}
|
|
|
|
if (HTTPc_InitDone != DEF_YES) {
|
|
*p_err = HTTPc_ERR_INIT_NOT_COMPLETED;
|
|
goto exit;
|
|
}
|
|
|
|
if (p_req_obj == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
|
|
if (p_param == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
#endif
|
|
|
|
p_req = (HTTPc_REQ *)p_req_obj;
|
|
|
|
/* ------ VALIDATE THAT REQ IS NOT USED ALREADY ------- */
|
|
CPU_CRITICAL_ENTER();
|
|
in_use = DEF_BIT_IS_SET(p_req->Flags, HTTPc_FLAG_REQ_IN_USE);
|
|
CPU_CRITICAL_EXIT();
|
|
if (in_use == DEF_YES) {
|
|
*p_err = HTTPc_ERR_REQ_IS_USED;
|
|
goto exit;
|
|
}
|
|
|
|
/* ------------- REQUEST PARAMETER SETUP -------------- */
|
|
switch (type) {
|
|
case HTTPc_PARAM_TYPE_REQ_QUERY_STR_TBL:
|
|
p_tbl_obj = (HTTPc_PARAM_TBL *)p_param;
|
|
#if (HTTPc_CFG_QUERY_STR_EN == DEF_ENABLED)
|
|
p_req->QueryStrTbl = (HTTPc_KEY_VAL *)p_tbl_obj->TblPtr;
|
|
p_req->QueryStrNbr = p_tbl_obj->EntryNbr;
|
|
p_req->OnQueryStrTx = DEF_NULL;
|
|
break;
|
|
#else
|
|
*p_err = HTTPc_ERR_FEATURE_DIS;
|
|
goto exit;
|
|
#endif
|
|
|
|
|
|
case HTTPc_PARAM_TYPE_REQ_QUERY_STR_HOOK:
|
|
#if (HTTPc_CFG_QUERY_STR_EN == DEF_ENABLED)
|
|
p_req->OnQueryStrTx = (HTTPc_REQ_QUERY_STR_HOOK)p_param;
|
|
p_req->QueryStrTbl = DEF_NULL;
|
|
p_req->QueryStrNbr = 0;
|
|
break;
|
|
#else
|
|
*p_err = HTTPc_ERR_FEATURE_DIS;
|
|
goto exit;
|
|
#endif
|
|
|
|
|
|
case HTTPc_PARAM_TYPE_REQ_HDR_TBL:
|
|
p_tbl_obj = (HTTPc_PARAM_TBL *)p_param;
|
|
#if (HTTPc_CFG_HDR_TX_EN == DEF_ENABLED)
|
|
p_req->HdrNbr = p_tbl_obj->EntryNbr;
|
|
p_req->HdrTbl = (HTTPc_HDR *)p_tbl_obj->TblPtr;
|
|
p_req->OnHdrTx = DEF_NULL;
|
|
break;
|
|
#else
|
|
*p_err = HTTPc_ERR_FEATURE_DIS;
|
|
goto exit;
|
|
#endif
|
|
|
|
|
|
case HTTPc_PARAM_TYPE_REQ_HDR_HOOK:
|
|
#if (HTTPc_CFG_HDR_TX_EN == DEF_ENABLED)
|
|
p_req->OnHdrTx = (HTTPc_REQ_HDR_HOOK)p_param;
|
|
p_req->HdrNbr = 0;
|
|
p_req->HdrTbl = DEF_NULL;
|
|
break;
|
|
#else
|
|
*p_err = HTTPc_ERR_FEATURE_DIS;
|
|
goto exit;
|
|
#endif
|
|
|
|
|
|
case HTTPc_PARAM_TYPE_REQ_FORM_TBL:
|
|
p_tbl_obj = (HTTPc_PARAM_TBL *)p_param;
|
|
#if (HTTPc_CFG_FORM_EN == DEF_ENABLED)
|
|
DEF_BIT_SET(p_req->Flags, HTTPc_FLAG_REQ_BODY_PRESENT);
|
|
DEF_BIT_SET(p_req->Flags, HTTPc_FLAG_REQ_FORM_PRESENT);
|
|
p_req->FormFieldNbr = p_tbl_obj->EntryNbr;
|
|
p_req->FormFieldTbl = p_tbl_obj->TblPtr;
|
|
break;
|
|
#else
|
|
*p_err = HTTPc_ERR_FEATURE_DIS;
|
|
goto exit;
|
|
#endif
|
|
|
|
|
|
case HTTPc_PARAM_TYPE_REQ_BODY_CONTENT_TYPE:
|
|
DEF_BIT_SET(p_req->Flags, HTTPc_FLAG_REQ_BODY_PRESENT);
|
|
p_req->ContentType = *(HTTP_CONTENT_TYPE *)p_param;
|
|
break;
|
|
|
|
|
|
case HTTPc_PARAM_TYPE_REQ_BODY_CONTENT_LEN:
|
|
DEF_BIT_SET(p_req->Flags, HTTPc_FLAG_REQ_BODY_PRESENT);
|
|
p_req->ContentLen = *(CPU_INT32U *)p_param;
|
|
break;
|
|
|
|
|
|
case HTTPc_PARAM_TYPE_REQ_BODY_CHUNK:
|
|
#if (HTTPc_CFG_CHUNK_TX_EN == DEF_ENABLED)
|
|
chunk_en = *(CPU_BOOLEAN *)p_param;
|
|
if (chunk_en == DEF_YES) {
|
|
DEF_BIT_SET(p_req->Flags, HTTPc_FLAG_REQ_BODY_CHUNK_TRANSFER);
|
|
}
|
|
DEF_BIT_SET(p_req->Flags, HTTPc_FLAG_REQ_BODY_PRESENT);
|
|
break;
|
|
#else
|
|
(void)chunk_en;
|
|
*p_err = HTTPc_ERR_FEATURE_DIS;
|
|
goto exit;
|
|
#endif
|
|
|
|
|
|
case HTTPc_PARAM_TYPE_REQ_BODY_HOOK:
|
|
p_req->OnBodyTx = (HTTPc_REQ_BODY_HOOK)p_param;
|
|
break;
|
|
|
|
|
|
case HTTPc_PARAM_TYPE_RESP_HDR_HOOK:
|
|
#if (HTTPc_CFG_HDR_RX_EN == DEF_ENABLED)
|
|
p_req->OnHdrRx = (HTTPc_RESP_HDR_HOOK)p_param;
|
|
break;
|
|
#else
|
|
*p_err = HTTPc_ERR_FEATURE_DIS;
|
|
goto exit;
|
|
#endif
|
|
|
|
|
|
case HTTPc_PARAM_TYPE_RESP_BODY_HOOK:
|
|
p_req->OnBodyRx = (HTTPc_RESP_BODY_HOOK)p_param;
|
|
break;
|
|
|
|
|
|
case HTTPc_PARAM_TYPE_TRANS_COMPLETE_CALLBACK:
|
|
#ifdef HTTPc_TASK_MODULE_EN
|
|
p_req->OnTransComplete = (HTTPc_COMPLETE_CALLBACK)p_param;
|
|
break;
|
|
#else
|
|
*p_err = HTTPc_ERR_FEATURE_DIS;
|
|
goto exit;
|
|
#endif
|
|
|
|
|
|
case HTTPc_PARAM_TYPE_TRANS_ERR_CALLBACK:
|
|
#ifdef HTTPc_TASK_MODULE_EN
|
|
p_req->OnErr = (HTTPc_TRANS_ERR_CALLBACK)p_param;
|
|
break;
|
|
#else
|
|
*p_err = HTTPc_ERR_FEATURE_DIS;
|
|
goto exit;
|
|
#endif
|
|
|
|
case HTTPc_PARAM_TYPE_REQ_UPGRADE_WEBSOCKET:
|
|
#ifdef HTTPc_WEBSOCK_MODULE_EN
|
|
DEF_BIT_SET(p_req->Flags, HTTPc_FLAG_REQ_UPGRADE_WEBSOCKET);
|
|
break;
|
|
#else
|
|
*p_err = HTTPc_ERR_FEATURE_DIS;
|
|
goto exit;
|
|
#endif
|
|
default:
|
|
*p_err = HTTPc_ERR_PARAM_INVALID;
|
|
goto exit;
|
|
}
|
|
|
|
(void)p_tbl_obj;
|
|
|
|
*p_err = HTTPc_ERR_NONE;
|
|
|
|
|
|
exit:
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPc_ReqSend()
|
|
*
|
|
* Description : Send a HTTP request.
|
|
*
|
|
* Argument(s) : p_conn_obj Pointer to valid HTTPc Connection on which request will occurred.
|
|
*
|
|
* p_req_obj Pointer to request to send.
|
|
*
|
|
* p_resp_obj Pointer to response object that will be filled with the received response.
|
|
*
|
|
* method HTTP method of the request.
|
|
*
|
|
* p_resource_path Pointer to complete URI (or only resource path) of the request.
|
|
*
|
|
* resource_path_len Resource path length.
|
|
*
|
|
* flags Configuration flags :
|
|
*
|
|
* HTTPc_FLAG_REQ_NO_BLOCK
|
|
*
|
|
* p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* HTTPc_ERR_NONE Request Sending successfully started.
|
|
* HTTPc_ERR_INIT_NOT_COMPLETED HTTPc Initialization is not completed.
|
|
* HTTPc_ERR_NULL_PTR Null pointer(s) was passed as argument(s).
|
|
* HTTPc_ERR_CONN_IS_RELEASED Connection is not active.
|
|
* HTTPc_ERR_REQ_IS_USED Request is already in usage.
|
|
* HTTPc_ERR_REQ_PARAM_METHOD_INVALID Invalid HTTP Method.
|
|
* HTTPc_ERR_REQ_PARAM_RESOURCE_PATH_INVALID Resource path is null.
|
|
* HTTPc_ERR_FEATURE_DIS A needed feature is disabled.
|
|
*
|
|
*
|
|
* ------------ RETURNED BY HTTPcTask_TransDoneSignalCreate() ------------
|
|
* See HTTPcTask_TransDoneSignalCreate() for additional return error codes.
|
|
*
|
|
* ------------ RETURNED BY HTTPcTask_TransDoneSignalWait() ------------
|
|
* See HTTPcTask_TransDoneSignalWait() for additional return error codes.
|
|
*
|
|
* ------------ RETURNED BY HTTPcTask_TransDoneSignalDel() ------------
|
|
* See HTTPcTask_TransDoneSignalDel() for additional return error codes.
|
|
*
|
|
* ------------ RETURNED BY HTTPcReq_Prepare() ------------
|
|
* See HTTPcReq_Prepare() for additional return error codes.
|
|
*
|
|
* ------------ RETURNED BY HTTPcSock_Sel() ------------
|
|
* See HTTPcSock_Sel() for additional return error codes.
|
|
*
|
|
* ------------ RETURNED BY HTTPcReq() ------------
|
|
* See HTTPcReq() for additional return error codes.
|
|
*
|
|
* ------------ RETURNED BY HTTPcResp() ------------
|
|
* See HTTPcResp() for additional return error codes.
|
|
*
|
|
* Return(s) : DEF_YES, if HTTP Response received successfully.
|
|
* DEF_NO, otherwise.
|
|
*
|
|
* Caller(s) : Application.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
CPU_BOOLEAN HTTPc_ReqSend(HTTPc_CONN_OBJ *p_conn_obj,
|
|
HTTPc_REQ_OBJ *p_req_obj,
|
|
HTTPc_RESP_OBJ *p_resp_obj,
|
|
HTTP_METHOD method,
|
|
CPU_CHAR *p_resource_path,
|
|
CPU_INT16U resource_path_len,
|
|
HTTPc_FLAGS flags,
|
|
HTTPc_ERR *p_err)
|
|
{
|
|
HTTPc_CONN *p_conn;
|
|
HTTPc_REQ *p_req;
|
|
CPU_BOOLEAN result;
|
|
CPU_BOOLEAN in_use;
|
|
CPU_BOOLEAN no_block;
|
|
#ifdef HTTPc_TASK_MODULE_EN
|
|
HTTPc_ERR err;
|
|
#endif
|
|
CPU_SR_ALLOC();
|
|
|
|
|
|
result = DEF_FAIL;
|
|
|
|
/* --------------- ARGUMENTS VALIDATION --------------- */
|
|
#if (HTTPc_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
|
|
if (p_err == DEF_NULL) {
|
|
CPU_SW_EXCEPTION(DEF_FAIL);
|
|
}
|
|
|
|
if (HTTPc_InitDone != DEF_YES) {
|
|
*p_err = HTTPc_ERR_INIT_NOT_COMPLETED;
|
|
goto exit;
|
|
}
|
|
|
|
if (p_conn_obj == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
|
|
if (p_req_obj == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
|
|
if (p_resp_obj == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
#endif
|
|
|
|
p_conn = (HTTPc_CONN *)p_conn_obj;
|
|
p_req = (HTTPc_REQ *)p_req_obj;
|
|
|
|
/* ------ VALIDATE THAT REQ IS NOT USED ALREADY ------- */
|
|
CPU_CRITICAL_ENTER();
|
|
in_use = DEF_BIT_IS_SET(p_req->Flags, HTTPc_FLAG_REQ_IN_USE);
|
|
if (in_use != DEF_YES) {
|
|
DEF_BIT_SET(p_req->Flags, HTTPc_FLAG_REQ_IN_USE);
|
|
CPU_CRITICAL_EXIT();
|
|
} else {
|
|
CPU_CRITICAL_EXIT();
|
|
*p_err = HTTPc_ERR_REQ_IS_USED;
|
|
goto exit;
|
|
}
|
|
|
|
p_req->ConnPtr = p_conn;
|
|
p_req->RespPtr = p_resp_obj;
|
|
/* ----------------- SET HTTP METHOD ------------------ */
|
|
switch (method) {
|
|
case HTTP_METHOD_GET:
|
|
case HTTP_METHOD_POST:
|
|
case HTTP_METHOD_HEAD:
|
|
case HTTP_METHOD_PUT:
|
|
case HTTP_METHOD_DELETE:
|
|
case HTTP_METHOD_TRACE:
|
|
case HTTP_METHOD_CONNECT:
|
|
case HTTP_METHOD_OPTIONS:
|
|
p_req->Method = method;
|
|
break;
|
|
|
|
case HTTP_METHOD_UNKNOWN:
|
|
default:
|
|
*p_err = HTTPc_ERR_REQ_PARAM_METHOD_INVALID;
|
|
goto exit;
|
|
}
|
|
/* ---------------- SET RESOURCE PATH ----------------- */
|
|
if (p_resource_path == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_REQ_PARAM_RESOURCE_PATH_INVALID;
|
|
goto exit;
|
|
}
|
|
|
|
p_req->ResourcePathPtr = p_resource_path;
|
|
p_req->ResourcePathLen = resource_path_len;
|
|
/* ---------------- SET BLOCKING MODE ----------------- */
|
|
no_block = DEF_BIT_IS_SET(flags, HTTPc_FLAG_REQ_NO_BLOCK);
|
|
if (no_block == DEF_YES) {
|
|
DEF_BIT_SET(p_req->Flags, HTTPc_FLAG_REQ_NO_BLOCK);
|
|
} else {
|
|
DEF_BIT_CLR(p_req->Flags, HTTPc_FLAG_REQ_NO_BLOCK);
|
|
}
|
|
|
|
#ifdef HTTPc_TASK_MODULE_EN
|
|
if (no_block == DEF_NO) {
|
|
#ifdef HTTPc_SIGNAL_TASK_MODULE_EN
|
|
HTTPcTask_TransDoneSignalCreate(p_conn, p_err);
|
|
if (*p_err != HTTPc_ERR_NONE) {
|
|
goto exit_conn_close;
|
|
}
|
|
#else
|
|
*p_err = HTTPc_ERR_FEATURE_DIS;
|
|
goto exit;
|
|
#endif
|
|
}
|
|
|
|
HTTPcTask_MsgQueue(HTTPc_MSG_TYPE_REQ,
|
|
(void *) p_req,
|
|
p_err);
|
|
if (*p_err != HTTPc_ERR_NONE) {
|
|
goto exit;
|
|
}
|
|
|
|
|
|
HTTPcTask_Wake(p_conn, &err);
|
|
if (*p_err != HTTPc_ERR_NONE) {
|
|
goto exit;
|
|
}
|
|
|
|
if (no_block == DEF_NO) {
|
|
#ifdef HTTPc_SIGNAL_TASK_MODULE_EN
|
|
/* -------- WAIT FOR RESPONSE IN BLOCKING MODE -------- */
|
|
HTTPcTask_TransDoneSignalWait(p_conn, p_err);
|
|
if (*p_err != HTTPc_ERR_NONE) {
|
|
goto exit_conn_close;
|
|
}
|
|
|
|
CPU_CRITICAL_ENTER();
|
|
result = DEF_BIT_IS_SET(p_conn->RespFlags, HTTPc_FLAG_RESP_COMPLETE_OK);
|
|
CPU_CRITICAL_EXIT();
|
|
if (result == DEF_FAIL) {
|
|
*p_err = p_conn->ErrCode;
|
|
goto exit;
|
|
}
|
|
|
|
HTTPcTask_TransDoneSignalDel(p_conn, p_err);
|
|
if (*p_err != HTTPc_ERR_NONE) {
|
|
goto exit_conn_close;
|
|
}
|
|
|
|
#else
|
|
*p_err = HTTPc_ERR_FEATURE_DIS;
|
|
goto exit;
|
|
#endif
|
|
}
|
|
|
|
*p_err = HTTPc_ERR_NONE;
|
|
|
|
goto exit;
|
|
#else
|
|
|
|
if (no_block == DEF_YES) {
|
|
*p_err = HTTPc_ERR_FEATURE_DIS;
|
|
goto exit;
|
|
}
|
|
|
|
HTTPcConn_ReqAdd(p_req, p_err); /* Add Request to Connection. */
|
|
if (*p_err != HTTPc_ERR_NONE) {
|
|
goto exit;
|
|
}
|
|
|
|
/********************************修改***************************************/
|
|
do {
|
|
/*接收与发送处理*/
|
|
HTTPcConn_TransProcess(p_conn);
|
|
} while ((p_conn->State != HTTPc_CONN_STATE_PARAM_VALIDATE) &&
|
|
(p_conn->State != HTTPc_CONN_STATE_NONE));
|
|
/********************************修改***************************************/
|
|
|
|
result = DEF_BIT_IS_SET(p_conn->RespFlags, HTTPc_FLAG_RESP_COMPLETE_OK);
|
|
|
|
*p_err = p_conn->ErrCode;
|
|
|
|
goto exit;
|
|
|
|
#endif
|
|
|
|
#ifdef HTTPc_SIGNAL_TASK_MODULE_EN
|
|
exit_conn_close:
|
|
HTTPc_ConnCloseHandler(p_conn, HTTPc_FLAG_NONE, &err);
|
|
#endif
|
|
|
|
exit:
|
|
return (result);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPc_FormAppFmt()
|
|
*
|
|
* Description : Format an application type form from a form field's table.
|
|
*
|
|
* Argument(s) : p_buf Pointer to buffer where the form will be written.
|
|
*
|
|
* buf_len Buffer length.
|
|
*
|
|
* p_form_tbl Pointer to form field's table.
|
|
*
|
|
* form_tbl_size Table size.
|
|
*
|
|
* p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* HTTPc_ERR_NONE Form successfully created.
|
|
* HTTPc_ERR_NULL_PTR Null pointer argument(s) passed.
|
|
* HTTPc_ERR_FORM_TYPE_INVALID Invalid form field type.
|
|
* HTTPc_ERR_FORM_BUF_LEN_INVALID buffer size to small for form.
|
|
* HTTPc_ERR_FORM_CREATE Form creation faulted.
|
|
*
|
|
* Return(s) : Length of the formatted form, if no errors.
|
|
*
|
|
* 0 , otherwise.
|
|
*
|
|
* Caller(s) : Application.
|
|
*
|
|
* Note(s) : (1) Only standard Key-Value Pair object are supported in the table to be able to format
|
|
* the form.
|
|
*********************************************************************************************************
|
|
*/
|
|
#if (HTTPc_CFG_FORM_EN == DEF_ENABLED)
|
|
CPU_INT32U HTTPc_FormAppFmt(CPU_CHAR *p_buf,
|
|
CPU_INT16U buf_len,
|
|
HTTPc_FORM_TBL_FIELD *p_form_tbl,
|
|
CPU_INT16U form_tbl_size,
|
|
HTTPc_ERR *p_err)
|
|
{
|
|
CPU_CHAR *p_buf_wr;
|
|
HTTPc_FORM_TBL_FIELD *p_tbl_field;
|
|
HTTPc_KEY_VAL *p_form_field;
|
|
CPU_INT16U key_char_encode_nbr;
|
|
CPU_INT16U val_char_encode_nbr;
|
|
CPU_SIZE_T str_len_key;
|
|
CPU_SIZE_T str_len_val;
|
|
CPU_SIZE_T data_size;
|
|
CPU_BOOLEAN url_encode;
|
|
CPU_INT16U i;
|
|
|
|
|
|
data_size = 0;
|
|
|
|
/* --------------- ARGUMENTS VALIDATION --------------- */
|
|
#if (HTTPc_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
|
|
if (p_err == DEF_NULL) {
|
|
CPU_SW_EXCEPTION(0);
|
|
}
|
|
|
|
if (p_buf == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
|
|
if (p_form_tbl == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
#endif
|
|
|
|
p_buf_wr = p_buf;
|
|
|
|
/* ----------------- PARSE FORM TABLE ----------------- */
|
|
for (i = 0u; i < form_tbl_size; i++) {
|
|
|
|
p_tbl_field = &p_form_tbl[i];
|
|
|
|
switch (p_tbl_field->Type) {
|
|
case HTTPc_FORM_FIELD_TYPE_KEY_VAL:
|
|
break;
|
|
|
|
case HTTPc_FORM_FIELD_TYPE_KEY_VAL_EXT:
|
|
case HTTPc_FORM_FIELD_TYPE_FILE:
|
|
default:
|
|
data_size = 0;
|
|
*p_err = HTTPc_ERR_FORM_TYPE_INVALID;
|
|
goto exit;
|
|
}
|
|
|
|
p_form_field = p_tbl_field->FieldObjPtr;
|
|
|
|
/* Calculate length of key and value without encoding. */
|
|
str_len_key = p_form_field->KeyLen;
|
|
str_len_val = p_form_field->ValLen;
|
|
|
|
/* Found number of character needing URL encoding. */
|
|
key_char_encode_nbr = HTTP_URL_CharEncodeNbr(p_form_field->KeyPtr, str_len_key);
|
|
val_char_encode_nbr = HTTP_URL_CharEncodeNbr(p_form_field->ValPtr, str_len_val);
|
|
|
|
/* Calculate total size needed for key & value encoded. */
|
|
data_size += str_len_key +
|
|
str_len_val +
|
|
HTTP_URL_ENCODING_JUMP * key_char_encode_nbr +
|
|
HTTP_URL_ENCODING_JUMP * val_char_encode_nbr +
|
|
1; /* + 1 for the "=" between key & value. */
|
|
|
|
if (i < (form_tbl_size - 1)) {
|
|
data_size++; /* + 1 for the "&" between each key&value pair. */
|
|
}
|
|
|
|
|
|
if (data_size > buf_len) { /* Return if no more space in buf. */
|
|
data_size = 0;
|
|
*p_err = HTTPc_ERR_FORM_BUF_LEN_INVALID;
|
|
goto exit;
|
|
}
|
|
|
|
url_encode = HTTP_URL_EncodeStr(p_form_field->KeyPtr, /* Encode and Write to buffer the Key. */
|
|
p_buf_wr,
|
|
&str_len_key,
|
|
buf_len);
|
|
if (url_encode == DEF_FAIL) {
|
|
data_size = 0;
|
|
*p_err = HTTPc_ERR_FORM_CREATE;
|
|
goto exit;
|
|
}
|
|
|
|
p_buf_wr += str_len_key;
|
|
buf_len -= str_len_key;
|
|
|
|
*p_buf_wr = ASCII_CHAR_EQUALS_SIGN; /* Write the "=" sign. */
|
|
p_buf_wr++;
|
|
buf_len--;
|
|
|
|
url_encode = HTTP_URL_EncodeStr(p_form_field->ValPtr, /* Encode and Write to buffer the Value. */
|
|
p_buf_wr,
|
|
&str_len_val,
|
|
buf_len);
|
|
if (url_encode == DEF_FAIL) {
|
|
data_size = 0;
|
|
*p_err = HTTPc_ERR_FORM_CREATE;
|
|
goto exit;
|
|
}
|
|
|
|
p_buf_wr += str_len_val;
|
|
buf_len -= str_len_val;
|
|
|
|
if (i < (form_tbl_size - 1)) {
|
|
*p_buf_wr = ASCII_CHAR_AMPERSAND; /* Write the "&" sign between pairs. */
|
|
p_buf_wr++;
|
|
buf_len--;
|
|
}
|
|
|
|
p_form_field++;
|
|
}
|
|
|
|
*p_err = HTTPc_ERR_NONE;
|
|
|
|
|
|
exit:
|
|
return (data_size);
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPc_FormMultipartFmt()
|
|
*
|
|
* Description : Format an multipart type form from a form field's table.
|
|
*
|
|
* Argument(s) : p_buf Pointer to buffer where the form will be written.
|
|
*
|
|
* buf_len Buffer length.
|
|
*
|
|
* p_form_tbl Pointer to form field's table.
|
|
*
|
|
* form_tbl_size Table size.
|
|
*
|
|
* p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* HTTPc_ERR_NONE Form successfully created.
|
|
* HTTPc_ERR_NULL_PTR Null pointer argument(s) passed.
|
|
* HTTPc_ERR_FORM_TYPE_INVALID Invalid form field type.
|
|
* HTTPc_ERR_FORM_BUF_LEN_INVALID buffer size to small for form.
|
|
* HTTPc_ERR_FORM_CREATE Form creation faulted.
|
|
*
|
|
* Return(s) : Length of the formatted form, if no errors.
|
|
*
|
|
* 0 , otherwise.
|
|
*
|
|
* Caller(s) : Application.
|
|
*
|
|
* Note(s) : (1) Only standard Key-Value Pair object are supported in the table to be able to format
|
|
* the form.
|
|
*********************************************************************************************************
|
|
*/
|
|
#if (HTTPc_CFG_FORM_EN == DEF_ENABLED)
|
|
CPU_INT32U HTTPc_FormMultipartFmt(CPU_CHAR *p_buf,
|
|
CPU_INT16U buf_len,
|
|
HTTPc_FORM_TBL_FIELD *p_form_tbl,
|
|
CPU_INT16U form_tbl_size,
|
|
HTTPc_ERR *p_err)
|
|
{
|
|
CPU_CHAR *p_buf_wr;
|
|
CPU_CHAR *p_str;
|
|
HTTPc_FORM_TBL_FIELD *p_tbl_field;
|
|
HTTPc_KEY_VAL *p_form_field;
|
|
CPU_SIZE_T data_size = 0;
|
|
CPU_SIZE_T name_field_len;
|
|
CPU_INT08U name_char_encode_nbr;
|
|
CPU_INT16U tot_buf_len;
|
|
CPU_INT16U i;
|
|
CPU_BOOLEAN url_encode;
|
|
|
|
|
|
/* --------------- ARGUMENTS VALIDATION --------------- */
|
|
#if (HTTPc_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
|
|
if (p_err == DEF_NULL) {
|
|
CPU_SW_EXCEPTION(0);
|
|
}
|
|
|
|
if (p_buf == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
|
|
if (p_form_tbl == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
#endif
|
|
|
|
tot_buf_len = buf_len;
|
|
p_buf_wr = p_buf;
|
|
|
|
/* ----------------- PARSE FORM TABLE ----------------- */
|
|
for (i = 0u; i < form_tbl_size; i++) {
|
|
|
|
p_tbl_field = &p_form_tbl[i];
|
|
|
|
switch (p_tbl_field->Type) {
|
|
case HTTPc_FORM_FIELD_TYPE_KEY_VAL:
|
|
break;
|
|
|
|
case HTTPc_FORM_FIELD_TYPE_KEY_VAL_EXT:
|
|
case HTTPc_FORM_FIELD_TYPE_FILE:
|
|
default:
|
|
data_size = 0;
|
|
*p_err = HTTPc_ERR_FORM_TYPE_INVALID;
|
|
goto exit;
|
|
}
|
|
|
|
p_form_field = p_tbl_field->FieldObjPtr;
|
|
|
|
|
|
data_size += HTTPc_STR_BOUNDARY_START_LEN + STR_CR_LF_LEN;
|
|
|
|
/* Find nbr of chars to encode in name. */
|
|
name_field_len = p_form_field->KeyLen;
|
|
name_char_encode_nbr = HTTP_URL_CharEncodeNbr(p_form_field->KeyPtr, name_field_len);
|
|
|
|
data_size += HTTP_STR_HDR_FIELD_CONTENT_DISPOSITION_LEN + /* "Content-Disposition" */
|
|
2 + /* ": " */
|
|
HTTP_STR_CONTENT_DISPOSITION_FORM_DATA_LEN + /* "form-data" */
|
|
2 + /* "; " */
|
|
HTTP_STR_MULTIPART_FIELD_NAME_LEN + /* "name" */
|
|
3 + /* "=\"\"" */
|
|
name_field_len + /* "name_rx_in_form" */
|
|
HTTP_URL_ENCODING_JUMP * name_char_encode_nbr + /* nbr of char to encode. */
|
|
STR_CR_LF_LEN; /* "\r\n" */
|
|
|
|
data_size += 2 * STR_CR_LF_LEN +
|
|
p_form_field->ValLen;
|
|
|
|
|
|
if (i == (form_tbl_size - 1)) {
|
|
data_size += (HTTPc_STR_BOUNDARY_END_LEN + STR_CR_LF_LEN);
|
|
}
|
|
|
|
if (data_size > buf_len) { /* Return if no more space in buf. */
|
|
data_size = 0;
|
|
*p_err = HTTPc_ERR_FORM_BUF_LEN_INVALID;
|
|
goto exit;
|
|
}
|
|
|
|
|
|
/* Write start of boundary. */
|
|
p_str = Str_Copy_N(p_buf_wr, HTTPc_STR_BOUNDARY_START, data_size);
|
|
if (p_str == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_FORM_CREATE;
|
|
goto exit;
|
|
}
|
|
|
|
p_str += HTTPc_STR_BOUNDARY_START_LEN;
|
|
|
|
/* Write CRLF after boundary. */
|
|
p_str = Str_Copy_N(p_str, STR_CR_LF, STR_CR_LF_LEN);
|
|
if (p_str == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_FORM_CREATE;
|
|
goto exit;
|
|
}
|
|
|
|
p_str += STR_CR_LF_LEN;
|
|
buf_len -= (p_str - p_buf_wr);
|
|
p_buf_wr = p_str;
|
|
|
|
/* Write Content-Disposition header. */
|
|
p_str = HTTPcReq_HdrCopyToBuf(p_buf_wr,
|
|
tot_buf_len,
|
|
buf_len,
|
|
HTTP_HDR_FIELD_CONTENT_DISPOSITION,
|
|
HTTP_STR_CONTENT_DISPOSITION_FORM_DATA,
|
|
HTTP_STR_CONTENT_DISPOSITION_FORM_DATA_LEN,
|
|
DEF_NO,
|
|
p_err);
|
|
if (p_str == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_FORM_CREATE;
|
|
goto exit;
|
|
}
|
|
|
|
*p_str = ASCII_CHAR_SEMICOLON;
|
|
p_str++;
|
|
*p_str = ASCII_CHAR_SPACE;
|
|
p_str++;
|
|
|
|
/* Write string "name". */
|
|
p_str = Str_Copy_N(p_str, HTTP_STR_MULTIPART_FIELD_NAME, HTTP_STR_MULTIPART_FIELD_NAME_LEN);
|
|
if (p_str == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_FORM_CREATE;
|
|
goto exit;
|
|
}
|
|
|
|
p_str += HTTP_STR_MULTIPART_FIELD_NAME_LEN;
|
|
*p_str = ASCII_CHAR_EQUALS_SIGN;
|
|
p_str++;
|
|
*p_str = ASCII_CHAR_QUOTATION_MARK;
|
|
p_str++;
|
|
|
|
/* Write name's value. */
|
|
url_encode = HTTP_URL_EncodeStr(p_form_field->KeyPtr,
|
|
p_str,
|
|
&name_field_len,
|
|
buf_len);
|
|
if (url_encode == DEF_FAIL) {
|
|
*p_err = HTTPc_ERR_FORM_CREATE;
|
|
goto exit;
|
|
}
|
|
|
|
p_str += name_field_len;
|
|
*p_str = ASCII_CHAR_QUOTATION_MARK;
|
|
p_str++;
|
|
|
|
/* Write 2 CRLF. */
|
|
p_str = Str_Copy_N(p_str, STR_CR_LF, STR_CR_LF_LEN);
|
|
if (p_str == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_REQ_FORM_CREATE;
|
|
goto exit;
|
|
}
|
|
|
|
p_str += STR_CR_LF_LEN;
|
|
|
|
buf_len -= (p_str - p_buf_wr);
|
|
p_buf_wr = p_str;
|
|
|
|
p_str = Str_Copy_N(p_str, STR_CR_LF, STR_CR_LF_LEN);
|
|
if (p_str == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_REQ_FORM_CREATE;
|
|
goto exit;
|
|
}
|
|
|
|
p_str += STR_CR_LF_LEN;
|
|
buf_len -= (p_str - p_buf_wr);
|
|
p_buf_wr = p_str;
|
|
|
|
/* Write Data. */
|
|
Mem_Copy(p_buf_wr, p_form_field->ValPtr, p_form_field->ValLen);
|
|
|
|
p_str += p_form_field->ValLen;
|
|
buf_len -= (p_str - p_buf_wr);
|
|
p_buf_wr = p_str;
|
|
|
|
/* Write CRLF. */
|
|
p_str = Str_Copy_N(p_buf_wr, STR_CR_LF, STR_CR_LF_LEN);
|
|
if (p_str == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_REQ_FORM_CREATE;
|
|
goto exit;
|
|
}
|
|
|
|
p_str += STR_CR_LF_LEN;
|
|
buf_len -= (p_str - p_buf_wr);
|
|
p_buf_wr = p_str;
|
|
|
|
if (i == (form_tbl_size - 1)) {
|
|
/* Write end of boundary. */
|
|
p_str = Str_Copy_N(p_buf_wr, HTTPc_STR_BOUNDARY_END, HTTPc_STR_BOUNDARY_END_LEN);
|
|
if (p_str == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_REQ_FORM_CREATE;
|
|
goto exit;
|
|
}
|
|
|
|
p_str += HTTPc_STR_BOUNDARY_END_LEN;
|
|
/* Write CRLF after last boundary. */
|
|
p_str = Str_Copy_N(p_str, STR_CR_LF, STR_CR_LF_LEN);
|
|
if (p_str == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_REQ_FORM_CREATE;
|
|
goto exit;
|
|
}
|
|
|
|
p_str += STR_CR_LF_LEN;
|
|
buf_len -= (p_str - p_buf_wr);
|
|
p_buf_wr = p_str;
|
|
}
|
|
}
|
|
|
|
*p_err = HTTPc_ERR_NONE;
|
|
|
|
|
|
exit:
|
|
return (data_size);
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPc_FormAddKeyVal()
|
|
*
|
|
* Description : Add a Key-Value Pair object to the form table.
|
|
*
|
|
* Argument(s) : p_form_tbl Pointer to the form table.
|
|
*
|
|
* p_kvp Pointer to Key-Value Pair object to put in table.
|
|
*
|
|
* p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* HTTPc_ERR_NONE Object successfully added to Form table.
|
|
* HTTPc_ERR_NULL_PTR Null argument(s) passed.
|
|
* HTTPc_ERR_FORM_FIELD_INVALID Invalid form object.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Caller(s) : Application.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
#if (HTTPc_CFG_FORM_EN == DEF_ENABLED)
|
|
void HTTPc_FormAddKeyVal(HTTPc_FORM_TBL_FIELD *p_form_tbl,
|
|
HTTPc_KEY_VAL *p_key_val,
|
|
HTTPc_ERR *p_err)
|
|
{
|
|
/* --------------- ARGUMENTS VALIDATION --------------- */
|
|
#if (HTTPc_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
|
|
if (p_err == DEF_NULL) {
|
|
CPU_SW_EXCEPTION(;);
|
|
}
|
|
|
|
if (p_form_tbl == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
|
|
if (p_key_val == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
#endif
|
|
|
|
/* --------------- VALIDATE KVP OBJECT ---------------- */
|
|
if (p_key_val->KeyPtr == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_FORM_FIELD_INVALID;
|
|
goto exit;
|
|
|
|
}
|
|
|
|
if (p_key_val->ValPtr == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_FORM_FIELD_INVALID;
|
|
goto exit;
|
|
}
|
|
|
|
/* ----------------- SET TABLE FIELD ------------------ */
|
|
p_form_tbl->Type = HTTPc_FORM_FIELD_TYPE_KEY_VAL;
|
|
p_form_tbl->FieldObjPtr = (void *)p_key_val;
|
|
|
|
*p_err = HTTPc_ERR_NONE;
|
|
|
|
|
|
exit:
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPc_FormAddKeyValExt()
|
|
*
|
|
* Description : Add an Extended Key-Value Pair object to the form table.
|
|
*
|
|
* Argument(s) : p_form_tbl p_key_val_ext
|
|
*
|
|
* p_key_val_ext Pointer to the Extended Key-Value Pair object to put in table.
|
|
*
|
|
* p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* HTTPc_ERR_NONE Object successfully added to Form table.
|
|
* HTTPc_ERR_NULL_PTR Null argument(s) passed.
|
|
* HTTPc_ERR_FORM_FIELD_INVALID Invalid form object.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Caller(s) : Application.
|
|
*
|
|
* Note(s) : (1) HTTPc_KVP_BIG type object allows you to setup a Hook function that will be called when
|
|
* the form is sent to let the Application write the value directly into the buffer.
|
|
*********************************************************************************************************
|
|
*/
|
|
#if (HTTPc_CFG_FORM_EN == DEF_ENABLED)
|
|
void HTTPc_FormAddKeyValExt(HTTPc_FORM_TBL_FIELD *p_form_tbl,
|
|
HTTPc_KEY_VAL_EXT *p_key_val_ext,
|
|
HTTPc_ERR *p_err)
|
|
{
|
|
/* --------------- ARGUMENTS VALIDATION --------------- */
|
|
#if (HTTPc_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
|
|
if (p_err == DEF_NULL) {
|
|
CPU_SW_EXCEPTION(;);
|
|
}
|
|
|
|
if (p_form_tbl == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
|
|
if (p_key_val_ext == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
#endif
|
|
|
|
/* --------------- VALIDATE KVP OBJECT ---------------- */
|
|
if (p_key_val_ext->KeyPtr == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_FORM_FIELD_INVALID;
|
|
goto exit;
|
|
|
|
}
|
|
|
|
if (p_key_val_ext->OnValTx == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_FORM_FIELD_INVALID;
|
|
goto exit;
|
|
}
|
|
|
|
/* ----------------- SET TABLE FIELD ------------------ */
|
|
p_form_tbl->Type = HTTPc_FORM_FIELD_TYPE_KEY_VAL_EXT;
|
|
p_form_tbl->FieldObjPtr = (void *)p_key_val_ext;
|
|
|
|
*p_err = HTTPc_ERR_NONE;
|
|
|
|
|
|
exit:
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPc_FormAddFile()
|
|
*
|
|
* Description : Add a multipart file object to the form table.
|
|
*
|
|
* Argument(s) : p_form_tbl Pointer to the form table.
|
|
*
|
|
* p_file_obj Pointer to the multipart file object to put in table.
|
|
*
|
|
* p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* HTTPc_ERR_NONE Object successfully added to Form table.
|
|
* HTTPc_ERR_NULL_PTR Null argument(s) passed.
|
|
* HTTPc_ERR_FORM_FIELD_INVALID Invalid form object.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Caller(s) : Application.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
#if (HTTPc_CFG_FORM_EN == DEF_ENABLED)
|
|
void HTTPc_FormAddFile(HTTPc_FORM_TBL_FIELD *p_form_tbl,
|
|
HTTPc_MULTIPART_FILE *p_file_obj,
|
|
HTTPc_ERR *p_err)
|
|
{
|
|
/* --------------- ARGUMENTS VALIDATION --------------- */
|
|
#if (HTTPc_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
|
|
if (p_err == DEF_NULL) {
|
|
CPU_SW_EXCEPTION(;);
|
|
}
|
|
|
|
if (p_form_tbl == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
|
|
if (p_file_obj == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
#endif
|
|
|
|
/* ---------- VALIDATE MULTIPART FILE OBJECT ---------- */
|
|
if (p_file_obj->NamePtr == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_FORM_FIELD_INVALID;
|
|
goto exit;
|
|
|
|
}
|
|
|
|
if (p_file_obj->FileNamePtr == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_FORM_FIELD_INVALID;
|
|
goto exit;
|
|
}
|
|
|
|
if (p_file_obj->OnFileTx == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_FORM_FIELD_INVALID;
|
|
goto exit;
|
|
}
|
|
|
|
/* ----------------- SET TABLE FIELD ------------------ */
|
|
p_form_tbl->Type = HTTPc_FORM_FIELD_TYPE_FILE;
|
|
p_form_tbl->FieldObjPtr = (void *)p_file_obj;
|
|
|
|
*p_err = HTTPc_ERR_NONE;
|
|
|
|
|
|
exit:
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPc_WebSockSetParam()
|
|
*
|
|
* Description : Set a parameter related to a given WebSocket Obj.
|
|
*
|
|
* Argument(s) : p_ws_obj Pointer to the WebSocket Obj.
|
|
*
|
|
* type Parameter type :
|
|
*
|
|
* HTTPc_PARAM_TYPE_WEBSOCK_ON_OPEN
|
|
* HTTPc_PARAM_TYPE_WEBSOCK_ON_CLOSE
|
|
* HTTPc_PARAM_TYPE_WEBSOCK_ON_MSG_RX_INIT
|
|
* HTTPc_PARAM_TYPE_WEBSOCK_ON_MSG_RX_DATA
|
|
* HTTPc_PARAM_TYPE_WEBSOCK_ON_MSG_RX_COMPLETE
|
|
* HTTPc_PARAM_TYPE_WEBSOCK_ON_ERR
|
|
* HTTPc_PARAM_TYPE_WEBSOCK_ON_PONG
|
|
*
|
|
* p_param Pointer to parameter.
|
|
*
|
|
* p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* HTTPc_ERR_NONE Parameter set successfully.
|
|
* HTTPc_ERR_INIT_NOT_COMPLETED HTTPc Initialization is not completed.
|
|
* HTTPc_ERR_NULL_PTR Null argument(s) passed.
|
|
* HTTPc_ERR_WEBSOCK_IS_USED WebSocket Obj is already in use.
|
|
* HTTPc_ERR_PARAM_INVALID Invalid request parameter.
|
|
*
|
|
* Return(s) : none.
|
|
*
|
|
* Caller(s) : Application.
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
#ifdef HTTPc_WEBSOCK_MODULE_EN
|
|
void HTTPc_WebSockSetParam(HTTPc_WEBSOCK_OBJ *p_ws_obj,
|
|
HTTPc_PARAM_TYPE type,
|
|
void *p_param,
|
|
HTTPc_ERR *p_err)
|
|
{
|
|
HTTPc_WEBSOCK *p_ws;
|
|
CPU_BOOLEAN in_use;
|
|
CPU_SR_ALLOC();
|
|
|
|
/* --------------- ARGUMENTS VALIDATION --------------- */
|
|
#if (HTTPc_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
|
|
if (p_err == DEF_NULL) {
|
|
CPU_SW_EXCEPTION(;);
|
|
}
|
|
|
|
if (HTTPc_InitDone != DEF_YES) {
|
|
*p_err = HTTPc_ERR_INIT_NOT_COMPLETED;
|
|
goto exit;
|
|
}
|
|
|
|
if (p_ws_obj == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
|
|
if (p_param == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
#endif
|
|
|
|
p_ws = (HTTPc_WEBSOCK *)p_ws_obj;
|
|
/* ------ VALIDATE THAT REQ IS NOT USED ALREADY ------- */
|
|
CPU_CRITICAL_ENTER();
|
|
in_use = p_ws->Flags.IsWebsockUsed;
|
|
CPU_CRITICAL_EXIT();
|
|
if (in_use == DEF_YES) {
|
|
*p_err = HTTPc_ERR_WEBSOCK_IS_USED;
|
|
goto exit;
|
|
}
|
|
|
|
/* ------------- WEBSOCK PARAMETER SETUP -------------- */
|
|
switch (type) {
|
|
|
|
case HTTPc_PARAM_TYPE_WEBSOCK_ON_OPEN:
|
|
p_ws->OnOpen = (HTTPc_WEBSOCK_ON_OPEN)p_param;
|
|
break;
|
|
|
|
case HTTPc_PARAM_TYPE_WEBSOCK_ON_CLOSE:
|
|
p_ws->OnClose = (HTTPc_WEBSOCK_ON_CLOSE)p_param;
|
|
break;
|
|
|
|
case HTTPc_PARAM_TYPE_WEBSOCK_ON_MSG_RX_INIT:
|
|
p_ws->OnMsgRxInit = (HTTPc_WEBSOCK_ON_RX_INIT)p_param;
|
|
break;
|
|
|
|
case HTTPc_PARAM_TYPE_WEBSOCK_ON_MSG_RX_DATA:
|
|
p_ws->OnMsgRxData = (HTTPc_WEBSOCK_ON_RX_DATA)p_param;
|
|
break;
|
|
|
|
case HTTPc_PARAM_TYPE_WEBSOCK_ON_MSG_RX_COMPLETE:
|
|
p_ws->OnMsgRxComplete = (HTTPc_WEBSOCK_ON_RX_COMPLETE)p_param;
|
|
break;
|
|
|
|
case HTTPc_PARAM_TYPE_WEBSOCK_ON_ERR:
|
|
p_ws->OnErr = (HTTPc_WEBSOCK_ON_ERR)p_param;
|
|
break;
|
|
|
|
case HTTPc_PARAM_TYPE_WEBSOCK_ON_PONG:
|
|
p_ws->OnPong = (HTTPc_WEBSOCK_ON_PONG)p_param;
|
|
break;
|
|
|
|
default:
|
|
*p_err = HTTPc_ERR_PARAM_INVALID;
|
|
goto exit;
|
|
}
|
|
|
|
*p_err = HTTPc_ERR_NONE;
|
|
exit:
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPc_WebSockMsgSetParam()
|
|
*
|
|
* Description : Set a parameter related to a given WebSocket Msg Obj.
|
|
*
|
|
* Argument(s) : p_msg_obj Pointer to the WebSocket Msg Obj.
|
|
*
|
|
* type Parameter type :
|
|
*
|
|
* HTTPc_PARAM_TYPE_WEBSOCK_MSG_USER_DATA
|
|
* HTTPc_PARAM_TYPE_WEBSOCK_MSG_ON_TX_INIT
|
|
* HTTPc_PARAM_TYPE_WEBSOCK_MSG_ON_TX_DATA
|
|
* HTTPc_PARAM_TYPE_WEBSOCK_MSG_ON_TX_COMPLETE
|
|
*
|
|
* p_param Pointer to parameter.
|
|
*
|
|
* p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* HTTPc_ERR_NONE Parameter set successfully.
|
|
* HTTPc_ERR_INIT_NOT_COMPLETED HTTPc Initialization is not completed.
|
|
* HTTPc_ERR_NULL_PTR Null argument(s) passed.
|
|
* HTTPc_ERR_WEBSOCK_MSG_IS_USED WebSocket Obj is already in use.
|
|
* HTTPc_ERR_PARAM_INVALID Invalid request parameter.
|
|
*
|
|
* Return(s) : none.
|
|
*
|
|
* Caller(s) : Application.
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
#ifdef HTTPc_WEBSOCK_MODULE_EN
|
|
void HTTPc_WebSockMsgSetParam(HTTPc_WEBSOCK_MSG_OBJ *p_msg_obj,
|
|
HTTPc_PARAM_TYPE type,
|
|
void *p_param,
|
|
HTTPc_ERR *p_err)
|
|
{
|
|
HTTPc_WEBSOCK_MSG *p_msg;
|
|
CPU_BOOLEAN in_use;
|
|
CPU_SR_ALLOC();
|
|
|
|
/* --------------- ARGUMENTS VALIDATION --------------- */
|
|
#if (HTTPc_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
|
|
if (p_err == DEF_NULL) {
|
|
CPU_SW_EXCEPTION(;);
|
|
}
|
|
|
|
if (HTTPc_InitDone != DEF_YES) {
|
|
*p_err = HTTPc_ERR_INIT_NOT_COMPLETED;
|
|
goto exit;
|
|
}
|
|
|
|
if (p_msg_obj == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
|
|
if (p_param == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
#endif
|
|
|
|
p_msg = (HTTPc_WEBSOCK_MSG *)p_msg_obj;
|
|
/* ------ VALIDATE THAT REQ IS NOT USED ALREADY ------- */
|
|
CPU_CRITICAL_ENTER();
|
|
in_use = p_msg->Flags.IsUsed;
|
|
CPU_CRITICAL_EXIT();
|
|
if (in_use == DEF_YES) {
|
|
*p_err = HTTPc_ERR_WEBSOCK_MSG_IS_USED;
|
|
goto exit;
|
|
}
|
|
/* ------------- WEBSOCK PARAMETER SETUP -------------- */
|
|
switch (type) {
|
|
|
|
case HTTPc_PARAM_TYPE_WEBSOCK_MSG_USER_DATA:
|
|
p_msg->UserDataPtr = p_param;
|
|
break;
|
|
|
|
case HTTPc_PARAM_TYPE_WEBSOCK_MSG_ON_TX_INIT:
|
|
p_msg->OnMsgTxInit = (HTTPc_WEBSOCK_ON_TX_INIT)p_param;
|
|
break;
|
|
|
|
case HTTPc_PARAM_TYPE_WEBSOCK_MSG_ON_TX_DATA:
|
|
p_msg->OnMsgTxData = (HTTPc_WEBSOCK_ON_TX_DATA)p_param;
|
|
break;
|
|
|
|
case HTTPc_PARAM_TYPE_WEBSOCK_MSG_ON_TX_COMPLETE:
|
|
p_msg->OnMsgTxComplete = (HTTPc_WEBSOCK_ON_TX_COMPLETE)p_param;
|
|
break;
|
|
|
|
default:
|
|
*p_err = HTTPc_ERR_PARAM_INVALID;
|
|
goto exit;
|
|
}
|
|
|
|
*p_err = HTTPc_ERR_NONE;
|
|
exit:
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPcWebSock_Upgrade()
|
|
*
|
|
* Description : Upgrade a HTTP client connection to a WebSocket.
|
|
*
|
|
* Argument(s) : p_conn_obj Pointer to valid HTTPc Connection on which request will occurred.
|
|
*
|
|
* p_req_obj Pointer to request to send.
|
|
*
|
|
* p_resp_obj Pointer to response object that will be filled with the received response.
|
|
*
|
|
* p_ws_obj Pointer to WebSocket object.
|
|
*
|
|
* p_resource_path Pointer to complete URI (or only resource path) of the request.
|
|
*
|
|
* resource_path_len Resource path length.
|
|
*
|
|
* flags Configuration flags :
|
|
*
|
|
* HTTPc_FLAG_WEBSOCK_NO_BLOCK
|
|
*
|
|
* p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* HTTPc_ERR_NONE Request Sending successfully started.
|
|
* HTTPc_ERR_WEBSOCK_CONN_ALREADY_WEBSOCKET The connection is already a websocket.
|
|
* HTTPc_ERR_INIT_NOT_COMPLETED HTTPc Initialization is not completed.
|
|
* HTTPc_ERR_NULL_PTR Null pointer(s) was passed as argument(s).
|
|
* HTTPc_ERR_CONN_IS_RELEASED Connection is not active.
|
|
* HTTPc_ERR_REQ_IS_USED Request is already in usage.
|
|
* HTTPc_ERR_REQ_PARAM_METHOD_INVALID Invalid HTTP Method.
|
|
* HTTPc_ERR_REQ_PARAM_RESOURCE_PATH_INVALID Resource path is null.
|
|
* HTTPc_ERR_FEATURE_DIS A needed feature is disabled.
|
|
* HTTPc_ERR_PARAM_INVALID Invalid request parameter.
|
|
* HTTPc_ERR_MSG_Q_FULL Error Queue full.
|
|
* HTTPc_ERR_MSG_Q_SIGNAL_FAULT Signal Post faulted.
|
|
* HTTPc_ERR_CONN_SIGNAL_CREATE Signal creation faulted.
|
|
* HTTPc_ERR_CONN_SIGNAL_TIMEOUT Signal pending timed out.
|
|
* HTTPc_ERR_CONN_SIGNAL_FAULT Error occurred during signal pending.
|
|
* HTTPc_ERR_CONN_SIGNAL_DEL Signal deletion faulted.
|
|
* HTTPc_ERR_WEBSOCK_REQ_MEM_ERR WebSock Req Obj allocation failed.
|
|
* HTTPc_ERR_WEBSOCK_SHA1_ENCODE_FAIL SHA1 encoding failed.
|
|
* HTTPc_ERR_WEBSOCK_BASE64_ENCODE_FAIL Base64 encoding failed.
|
|
*.-
|
|
* Return(s) : DEF_OK, if the operation is successful.
|
|
* DEF_FAIL, if the operation has failed.
|
|
*
|
|
* Caller(s) : Application.
|
|
*
|
|
* Note(s) : (1) Connection Object:
|
|
*
|
|
* (a) Since the WebSocket Upgrade handshake is based on a HTTP request, the connection object
|
|
* p_conn_obj MUST have already established a connection to the desired host server.
|
|
*
|
|
* (2) Request and Response Object.
|
|
*
|
|
* (a) Any HTTP request/response features available can be used during the WebSocket Upgrade Request.
|
|
*
|
|
* (3) WebSocket Upgrade related Header field
|
|
*
|
|
* (a) During a WebSocket Upgrade handshake, the following mandatory header fields are managed by the
|
|
* WebSocket module and MUST NOT be set by the Application:
|
|
* Connection
|
|
* Upgrade
|
|
* Sec-WebSocket-Key
|
|
* Sec-WebSocket-Accept
|
|
* Sec-WebSocket-Version
|
|
*
|
|
* (b) During a WebSocket Upgrade Handshake, the following optional header fields MAY be managed by
|
|
* the Application using the standard HTTPc Request/Response API:
|
|
* Sec-WebSocket-Protocol
|
|
* Sec-WebSocket-Extensions
|
|
*
|
|
* (4) If the WebSocket Upgrade Handshake is successful, Status Code in the response obj should be '101'.
|
|
* This means that the Host server has switched to the WebSocket protocol. Otherwise, the response
|
|
* object will TYPICALLY described the reason of the failure.
|
|
*
|
|
* (5) When the WebSocket Upgrade is completed, any HTTP request is no more allowed and it is not posssible
|
|
* to switch the connection protocol to HTTP. However, if a HTTP request is required to be sent by the
|
|
* Application, it SHOULD do one of the following procedure:
|
|
*
|
|
* (1) Close the current WebSocket Connection by sending a Close Frame and open again the HTTP
|
|
* connection.
|
|
*
|
|
* (2) Open a different HTTP connection with the Host Server.
|
|
*********************************************************************************************************
|
|
*/
|
|
#ifdef HTTPc_WEBSOCK_MODULE_EN
|
|
CPU_BOOLEAN HTTPc_WebSockUpgrade(HTTPc_CONN_OBJ *p_conn_obj,
|
|
HTTPc_REQ_OBJ *p_req_obj,
|
|
HTTPc_RESP_OBJ *p_resp_obj,
|
|
HTTPc_WEBSOCK_OBJ *p_ws_obj,
|
|
CPU_CHAR *p_resource_path,
|
|
CPU_INT16U resource_path_len,
|
|
HTTPc_FLAGS flags,
|
|
HTTPc_ERR *p_err)
|
|
{
|
|
HTTPc_REQ *p_req;
|
|
HTTPc_WEBSOCK *p_ws;
|
|
HTTPc_WEBSOCK_REQ *p_ws_req;
|
|
HTTPc_CONN *p_conn;
|
|
CPU_BOOLEAN is_websocket;
|
|
CPU_BOOLEAN is_connected;
|
|
CPU_BOOLEAN no_block;
|
|
CPU_BOOLEAN result;
|
|
CPU_SR_ALLOC();
|
|
|
|
|
|
p_req = (HTTPc_REQ *)p_req_obj;
|
|
p_ws = (HTTPc_WEBSOCK *)p_ws_obj;
|
|
p_conn = (HTTPc_CONN *)p_conn_obj;
|
|
/* -------------------- VALIDATION -------------------- */
|
|
/* Validate if the conn is eligible to upgrade. */
|
|
/* Check if the conn is already upgraded to Websock. */
|
|
CPU_CRITICAL_ENTER();
|
|
is_websocket = DEF_BIT_IS_SET(p_conn->Flags, HTTPc_FLAG_CONN_WEBSOCKET);
|
|
CPU_CRITICAL_EXIT();
|
|
if (is_websocket == DEF_YES) {
|
|
*p_err = HTTPc_ERR_WEBSOCK_CONN_ALREADY_WEBSOCKET;
|
|
result = DEF_NO;
|
|
goto exit;
|
|
}
|
|
/* Check if the connn is still open. */
|
|
CPU_CRITICAL_ENTER();
|
|
is_connected = DEF_BIT_IS_SET(p_conn->Flags, HTTPc_FLAG_CONN_CONNECT);
|
|
CPU_CRITICAL_EXIT();
|
|
if (is_connected == DEF_NO) {
|
|
*p_err = HTTPc_ERR_WEBSOCK_CONN_IS_NOT_CONNECTED;
|
|
result = DEF_NO;
|
|
goto exit;
|
|
}
|
|
/* If no blocking mode, validate callbacks. */
|
|
no_block = DEF_BIT_IS_SET(flags, HTTPc_FLAG_WEBSOCK_NO_BLOCK);
|
|
if (no_block == DEF_YES) {
|
|
if (p_ws->OnOpen == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_REQ_PARAM_WEBSOCK_ON_OPEN_CALLBACK_INVALID;
|
|
result = DEF_NO;
|
|
goto exit;
|
|
}
|
|
}
|
|
/* -------------- REQUEST INTIALIZATION --------------- */
|
|
/* Set as a Upgrade Request to WebSocket. */
|
|
is_websocket = DEF_YES;
|
|
HTTPc_ReqSetParam(p_req_obj,
|
|
HTTPc_PARAM_TYPE_REQ_UPGRADE_WEBSOCKET,
|
|
&is_websocket,
|
|
p_err);
|
|
if (*p_err != HTTPc_ERR_NONE) {
|
|
result = DEF_FAIL;
|
|
goto exit;
|
|
}
|
|
/* Initialize the WebSocket Request object. */
|
|
p_ws_req = HTTPcWebSock_InitReqObj(p_err);
|
|
if (*p_err != HTTPc_ERR_NONE) {
|
|
result = DEF_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
p_ws_req->WebSockObjPtr = p_ws;
|
|
p_req->WebSockPtr = p_ws_req;
|
|
/* ---------------- SEND HTTP REQUEST ----------------- */
|
|
result = HTTPc_ReqSend(p_conn_obj,
|
|
p_req_obj,
|
|
p_resp_obj,
|
|
HTTP_METHOD_GET,
|
|
p_resource_path,
|
|
resource_path_len,
|
|
flags,
|
|
p_err);
|
|
if (*p_err != HTTPc_ERR_NONE) {
|
|
result = DEF_FAIL;
|
|
}
|
|
|
|
exit:
|
|
return (result);
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPc_WebSockSend()
|
|
*
|
|
* Description : Send a WebSocket message.
|
|
*
|
|
* Argument(s) : p_conn_obj Pointer to valid HTTPc Connection upgraded to WebSocket.
|
|
*
|
|
* p_msg_obj Pointer to a valid WebSocket message object.
|
|
*
|
|
* msg_type Type of message to send.
|
|
*
|
|
* p_data Pointer to the payload to send.
|
|
*
|
|
* data_len Length of the payload to send.
|
|
*
|
|
* p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* HTTPc_ERR_NONE Request Sending successfully started.
|
|
* HTTPc_ERR_INIT_NOT_COMPLETED HTTPc Initialization is not completed.
|
|
* HTTPc_ERR_NULL_PTR Null pointer(s) was passed as argument(s).
|
|
* HTTPc_ERR_FEATURE_DIS A needed feature is disabled.
|
|
* HTTPc_ERR_WEBSOCK_INVALID_CONN The connection is not upgraded to websocket.
|
|
* HTTPc_ERR_WEBSOCK_INVALID_TX_PARAM Tx msg params is invalid.
|
|
* HTTPc_ERR_WEBSOCK_MSG_IS_USED The WebSock msg object is currently used.
|
|
* HTTPc_ERR_MSG_Q_FULL Error Queue full.
|
|
* HTTPc_ERR_MSG_Q_SIGNAL_FAULT Signal Post faulted.
|
|
* HTTPc_ERR_CONN_SIGNAL_CREATE Signal creation faulted.
|
|
* HTTPc_ERR_CONN_SIGNAL_TIMEOUT Signal pending timed out.
|
|
* HTTPc_ERR_CONN_SIGNAL_FAULT Error occurred during signal pending.
|
|
* HTTPc_ERR_CONN_SIGNAL_DEL Signal deletion faulted.
|
|
*
|
|
* Return(s) : DEF_OK, the operation is successful.
|
|
* DEF_FAIL, the operation has failed.
|
|
*
|
|
* Caller(s) : Application.
|
|
*
|
|
* Note(s) : (1) The connection object p_conn MUST has been previouslyupgraded to WebSocket to use this
|
|
* function. Refer to the HTTPc_WebSockUpgrade() function.
|
|
*
|
|
* (2) The available Message Types are :
|
|
*
|
|
* HTTPc_WEBSOCK_MSG_TYPE_TXT_FRAME (Data msg)
|
|
* HTTPc_WEBSOCK_MSG_TYPE_BIN_FRAME (Data msg)
|
|
* HTTPc_WEBSOCK_MSG_TYPE_CLOSE (Ctrl msg)
|
|
* HTTPc_WEBSOCK_MSG_TYPE_PING (Ctrl msg)
|
|
* HTTPc_WEBSOCK_MSG_TYPE_PONG (Ctrl msg)
|
|
*
|
|
* (3) Payload Content:
|
|
*
|
|
* (a) The "Payload data" (argument p_data) is defined as "Extension data" concatenated
|
|
* with "Application data".
|
|
*
|
|
* (b) Extension data length is 0 Bytes unless an extension has been negotiated during
|
|
* the handshake.
|
|
*
|
|
* (c) "Extension data" content and length are defines by the extension negotiated.
|
|
*
|
|
* (d) If negotiated, the "Extension data" must be handled by the Application.
|
|
*
|
|
* (4) Data message Restrictions:
|
|
*
|
|
* (b) Even if the RFC6455 allow to sent message payload up to 2^64 bytes, Only 2^32 bytes is
|
|
* allowed in the current implementation.
|
|
*
|
|
* (5) Control message Restrictions:
|
|
*
|
|
* (a) According to the RFC 6455 section 5.5:
|
|
*
|
|
* "All control frames MUST have a payload length of 125 bytes or less
|
|
* and MUST NOT be fragmented."
|
|
*
|
|
* (b) Close frame have a specific payload format. Refer to the HTTPc_WebSockFmtCloseMsg()
|
|
* function for more information.
|
|
*
|
|
* (6) Client-to-Server Masking
|
|
*
|
|
* (a) According to the RFC 6455 section 5.2:
|
|
*
|
|
* "All frames sent from the client to the server are masked by a 32-bit value that is
|
|
* contained within the frame."
|
|
*
|
|
* (b) The Application DO NOT need to mask the payload since it's handled by the WebSocket
|
|
* module.
|
|
*********************************************************************************************************
|
|
*/
|
|
#ifdef HTTPc_WEBSOCK_MODULE_EN
|
|
CPU_BOOLEAN HTTPc_WebSockSend(HTTPc_CONN_OBJ *p_conn_obj,
|
|
HTTPc_WEBSOCK_MSG_OBJ *p_msg_obj,
|
|
HTTPc_WEBSOCK_MSG_TYPE msg_type,
|
|
CPU_CHAR *p_data,
|
|
CPU_INT32U payload_len,
|
|
HTTPc_FLAGS flags,
|
|
HTTPc_ERR *p_err)
|
|
{
|
|
CPU_BOOLEAN result;
|
|
CPU_BOOLEAN is_websocket;
|
|
CPU_BOOLEAN no_block;
|
|
HTTPc_CONN *p_conn;
|
|
HTTPc_WEBSOCK_MSG *p_msg;
|
|
CPU_BOOLEAN in_use;
|
|
HTTPc_ERR err;
|
|
CPU_SR_ALLOC();
|
|
|
|
|
|
result = DEF_NO;
|
|
/* --------------- ARGUMENTS VALIDATION --------------- */
|
|
#if (HTTPc_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
|
|
if (p_err == DEF_NULL) {
|
|
CPU_SW_EXCEPTION(DEF_FAIL);
|
|
}
|
|
|
|
if (HTTPc_InitDone != DEF_YES) {
|
|
*p_err = HTTPc_ERR_INIT_NOT_COMPLETED;
|
|
goto exit;
|
|
}
|
|
|
|
if (p_conn_obj == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
|
|
if (p_msg_obj == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
#endif
|
|
|
|
p_conn = (HTTPc_CONN *)p_conn_obj;
|
|
p_msg = (HTTPc_WEBSOCK_MSG *)p_msg_obj;
|
|
/* Validate the connection state. */
|
|
CPU_CRITICAL_ENTER();
|
|
is_websocket = DEF_BIT_IS_SET(p_conn->Flags, HTTPc_FLAG_CONN_WEBSOCKET);
|
|
CPU_CRITICAL_EXIT();
|
|
if (is_websocket == DEF_NO) {
|
|
*p_err = HTTPc_ERR_WEBSOCK_INVALID_CONN;
|
|
result = DEF_NO;
|
|
goto exit;
|
|
}
|
|
/* Check if the Websock msg obj is already used. */
|
|
CPU_CRITICAL_ENTER();
|
|
in_use = p_msg->Flags.IsUsed;
|
|
CPU_CRITICAL_EXIT();
|
|
if (in_use == DEF_YES) {
|
|
*p_err = HTTPc_ERR_WEBSOCK_MSG_IS_USED;
|
|
goto exit;
|
|
}
|
|
/* Validate callback if no blocking mode. */
|
|
no_block = DEF_BIT_IS_SET(flags, HTTPc_FLAG_WEBSOCK_NO_BLOCK);
|
|
if (no_block == DEF_YES) {
|
|
if (p_msg->OnMsgTxComplete == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_WEBSOCK_PARAM_ON_TX_COMPLETE_CALLBACK_INVALID;
|
|
result = DEF_NO;
|
|
goto exit;
|
|
}
|
|
}
|
|
/* Check if the message will be set on callback. */
|
|
if (p_data == DEF_NULL) {
|
|
if (p_msg->OnMsgTxData == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_WEBSOCK_PARAM_ON_TX_CALLBACK_INVALID;
|
|
result = DEF_NO;
|
|
goto exit;
|
|
}
|
|
}
|
|
/* Validate the opcode. */
|
|
switch (msg_type) {
|
|
case HTTPc_WEBSOCK_MSG_TYPE_TXT_FRAME:
|
|
case HTTPc_WEBSOCK_MSG_TYPE_BIN_FRAME:
|
|
break;
|
|
|
|
case HTTPc_WEBSOCK_MSG_TYPE_CLOSE:
|
|
case HTTPc_WEBSOCK_MSG_TYPE_PING:
|
|
case HTTPc_WEBSOCK_MSG_TYPE_PONG:
|
|
/* Control msg can't be longer than 125 bytes. */
|
|
if (payload_len > HTTPc_WEBSOCK_MAX_CTRL_FRAME_LEN) {
|
|
*p_err = HTTPc_ERR_WEBSOCK_INVALID_TX_PARAM;
|
|
result = DEF_NO;
|
|
goto exit;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
*p_err = HTTPc_ERR_WEBSOCK_INVALID_TX_PARAM;
|
|
result = DEF_NO;
|
|
goto exit;
|
|
}
|
|
|
|
/* --------------- SET WEBSOCK MESSAGE ---------------- */
|
|
p_msg->DataPtr = p_data;
|
|
p_msg->Len = payload_len;
|
|
p_msg->LenSent = 0u;
|
|
p_msg->OpCode = (HTTPc_WEBSOCK_MSG_TYPE) msg_type;
|
|
p_msg->ConnPtr = p_conn;
|
|
|
|
p_msg->Flags.IsFin = DEF_YES;
|
|
p_msg->Flags.IsMasked = DEF_YES;
|
|
p_msg->Flags.IsHdrSet = DEF_NO;
|
|
p_msg->Flags.IsCompleted = DEF_NO;
|
|
|
|
/* ---------------- SET BLOCKING MODE ----------------- */
|
|
no_block = DEF_BIT_IS_SET(flags, HTTPc_FLAG_WEBSOCK_NO_BLOCK);
|
|
if (no_block == DEF_NO) {
|
|
#ifdef HTTPc_SIGNAL_TASK_MODULE_EN
|
|
HTTPcTask_TransDoneSignalCreate(p_conn, p_err);
|
|
if (*p_err != HTTPc_ERR_NONE) {
|
|
goto exit_conn_close;
|
|
}
|
|
#else
|
|
*p_err = HTTPc_ERR_FEATURE_DIS;
|
|
goto exit;
|
|
#endif
|
|
}
|
|
HTTPcTask_MsgQueue(HTTPc_MSG_TYPE_WEBSOCK_MSG,
|
|
(void *) p_msg,
|
|
p_err);
|
|
if (*p_err != HTTPc_ERR_NONE) {
|
|
goto exit;
|
|
}
|
|
|
|
HTTPcTask_Wake(p_conn, &err);
|
|
if (*p_err != HTTPc_ERR_NONE) {
|
|
goto exit;
|
|
}
|
|
|
|
if (no_block == DEF_NO) {
|
|
#ifdef HTTPc_SIGNAL_TASK_MODULE_EN
|
|
/* -------- WAIT FOR RESPONSE IN BLOCKING MODE -------- */
|
|
HTTPcTask_TransDoneSignalWait(p_conn, p_err);
|
|
if (*p_err != HTTPc_ERR_NONE) {
|
|
goto exit_conn_close;
|
|
}
|
|
CPU_CRITICAL_ENTER();
|
|
result = p_msg->Flags.IsCompleted;
|
|
CPU_CRITICAL_EXIT();
|
|
if (result == DEF_FAIL) {
|
|
if (p_conn->ErrCode == HTTPc_ERR_NONE) {
|
|
*p_err = HTTPc_ERR_WEBSOCK_SEND_ERROR;
|
|
} else {
|
|
*p_err = p_conn->ErrCode ;
|
|
}
|
|
goto exit;
|
|
}
|
|
HTTPcTask_TransDoneSignalDel(p_conn, p_err);
|
|
if (*p_err != HTTPc_ERR_NONE) {
|
|
goto exit_conn_close;
|
|
}
|
|
#else
|
|
*p_err = HTTPc_ERR_FEATURE_DIS;
|
|
goto exit;
|
|
#endif
|
|
}
|
|
result = DEF_OK;
|
|
*p_err = HTTPc_ERR_NONE;
|
|
|
|
exit:
|
|
return (result);
|
|
|
|
#ifdef HTTPc_SIGNAL_TASK_MODULE_EN
|
|
exit_conn_close:
|
|
HTTPc_ConnCloseHandler(p_conn, HTTPc_FLAG_NONE, p_err);
|
|
return (result);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPc_WebSockClr()
|
|
*
|
|
* Description : Clear an HTTPc WebSock object before the first usage.
|
|
*
|
|
* Argument(s) : p_ws_obj Pointer to the current HTTPc Websock Object.
|
|
*
|
|
* p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* HTTPc_ERR_NONE WebSock object clear successfully.
|
|
* HTTPc_ERR_INIT_NOT_COMPLETED HTTPc Initialization is not completed.
|
|
* HTTPc_ERR_NULL_PTR Function passed Null pointer as argument(s).
|
|
*
|
|
* Return(s) : none.
|
|
*
|
|
* Caller(s) : Application.
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
#ifdef HTTPc_WEBSOCK_MODULE_EN
|
|
void HTTPc_WebSockClr(HTTPc_WEBSOCK_OBJ *p_ws_obj,
|
|
HTTPc_ERR *p_err)
|
|
{
|
|
HTTPc_WEBSOCK *p_ws;
|
|
|
|
/* --------------- ARGUMENTS VALIDATION --------------- */
|
|
#if (HTTPc_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
|
|
if (p_err == DEF_NULL) {
|
|
CPU_SW_EXCEPTION(;);
|
|
}
|
|
|
|
if (HTTPc_InitDone != DEF_YES) {
|
|
*p_err = HTTPc_ERR_INIT_NOT_COMPLETED;
|
|
goto exit;
|
|
}
|
|
|
|
if (p_ws_obj == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
#endif
|
|
|
|
p_ws = (HTTPc_WEBSOCK *)p_ws_obj;
|
|
|
|
/* -------------- WEBSOCK INITIALIZATION -------------- */
|
|
p_ws->CloseCode = HTTPc_WEBSOCK_CLOSE_CODE_NONE;
|
|
p_ws->CloseReason.DataPtr = DEF_NULL;
|
|
p_ws->CloseReason.Len = 0u;
|
|
p_ws->Flags.IsCloseStarted = DEF_NO;
|
|
p_ws->Flags.IsPongStarted = DEF_NO;
|
|
p_ws->Flags.IsRxDataCached = DEF_NO;
|
|
p_ws->Flags.IsTxMsgCtrlUsed = DEF_NO;
|
|
p_ws->Flags.IsWebsockUsed = DEF_NO;
|
|
p_ws->OnClose = DEF_NULL;
|
|
p_ws->OnMsgRxInit = DEF_NULL;
|
|
p_ws->OnMsgRxData = DEF_NULL;
|
|
p_ws->OnMsgRxComplete = DEF_NULL;
|
|
p_ws->OnOpen = DEF_NULL;
|
|
p_ws->OnErr = DEF_NULL;
|
|
p_ws->OnPong = DEF_NULL;
|
|
p_ws->RxMsgLen = 0u;
|
|
p_ws->RxMsgLenRead = 0u;
|
|
p_ws->RxMsgOpCode = HTTPc_WEBSOCK_OPCODE_NONE;
|
|
p_ws->RxState = HTTPc_WEBSOCK_RX_STATE_WAIT;
|
|
p_ws->TxMsgListEndPtr = DEF_NULL;
|
|
p_ws->TxMsgListHeadPtr = DEF_NULL;
|
|
p_ws->TxState = HTTPc_WEBSOCK_TX_STATE_MSG_INIT;
|
|
p_ws->TotalMsgLen = 0u;
|
|
p_ws->OrigOpCode = HTTPc_WEBSOCK_OPCODE_NONE;
|
|
|
|
Mem_Clr(&p_ws->TxMsgCtrl, sizeof(HTTPc_WEBSOCK_MSG));
|
|
|
|
*p_err = HTTPc_ERR_NONE;
|
|
|
|
exit:
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPc_WebSockMsgClr()
|
|
*
|
|
* Description : Clear an HTTPc WebSock Msg object before the first usage.
|
|
*
|
|
* Argument(s) : p_msg_obj Pointer to the WebSock Msg obj to clear.
|
|
*
|
|
* p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* HTTPc_ERR_NONE WebSock object clear successfully.
|
|
* HTTPc_ERR_INIT_NOT_COMPLETED HTTPc Initialization is not completed.
|
|
* HTTPc_ERR_NULL_PTR Function passed Null pointer as argument(s).
|
|
*
|
|
* Return(s) : none.
|
|
*
|
|
* Caller(s) : Application.
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
#ifdef HTTPc_WEBSOCK_MODULE_EN
|
|
void HTTPc_WebSockMsgClr(HTTPc_WEBSOCK_MSG_OBJ *p_msg_obj,
|
|
HTTPc_ERR *p_err)
|
|
{
|
|
HTTPc_WEBSOCK_MSG *p_msg;
|
|
|
|
/* --------------- ARGUMENTS VALIDATION --------------- */
|
|
#if (HTTPc_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
|
|
if (p_err == DEF_NULL) {
|
|
CPU_SW_EXCEPTION(;);
|
|
}
|
|
|
|
if (HTTPc_InitDone != DEF_YES) {
|
|
*p_err = HTTPc_ERR_INIT_NOT_COMPLETED;
|
|
goto exit;
|
|
}
|
|
|
|
if (p_msg_obj == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
#endif
|
|
|
|
p_msg = (HTTPc_WEBSOCK_MSG *)p_msg_obj;
|
|
/* ------------ WEBSOCK REQ INITIALIZATION ------------ */
|
|
p_msg->ConnPtr = DEF_NULL;
|
|
p_msg->DataPtr = DEF_NULL;
|
|
p_msg->Len = 0u;
|
|
p_msg->Flags.IsFin = DEF_NO;
|
|
p_msg->Flags.IsMasked = DEF_NO;
|
|
p_msg->Flags.IsUsed = DEF_NO;
|
|
p_msg->Flags.IsNoBlock = DEF_NO;
|
|
p_msg->Flags.IsHdrSet = DEF_NO;
|
|
p_msg->LenSent = 0u;
|
|
p_msg->MskKey = 0u;
|
|
p_msg->NextPtr = DEF_NULL;
|
|
p_msg->OpCode = HTTPc_WEBSOCK_OPCODE_NONE;
|
|
p_msg->UserDataPtr = DEF_NULL;
|
|
p_msg->DataLen = 0u;
|
|
p_msg->OnMsgTxInit = DEF_NULL;
|
|
p_msg->OnMsgTxData = DEF_NULL;
|
|
p_msg->OnMsgTxComplete = DEF_NULL;
|
|
|
|
*p_err = HTTPc_ERR_NONE;
|
|
|
|
exit:
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPc_WebSockFmtCloseMsg()
|
|
*
|
|
* Description : Format a Close Frame.
|
|
*
|
|
* Argument(s) : close_code Value that defines the origin of connection closure.
|
|
*
|
|
* p_reason Pointer to a string that contains a reason of the connection closure.
|
|
*
|
|
* p_buf Pointer to the destination buffer
|
|
*
|
|
* buf_len Length of the destination buffer'
|
|
*
|
|
* p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* HTTPc_ERR_NONE WebSock object clear successfully.
|
|
* HTTPc_ERR_NULL_PTR Function passed Null pointer as argument(s).
|
|
* HTTPc_ERR_WEBSOCK_INVALID_CLOSE_CODE Close code argument is an unknown value.
|
|
* HTTPc_ERR_WEBSOCK_INVALID_CTRL_FRAME_LEN Total frame is passed are invalid.
|
|
*
|
|
* Return(s) : Payload length, If operation is successful.
|
|
*
|
|
* 0u, If operation has failed.
|
|
*
|
|
* Caller(s) : Application.
|
|
*
|
|
* Note(s) : (1) Close Frame have a specific format. According to the RFC 6455 section :
|
|
*
|
|
* "If there is a body, the first two bytes of the body MUST be a 2-byte unsigned
|
|
* integer (in network byte order) representing a status code with value /code/
|
|
* defined in Section 7.4. Following the 2-byte integer,the body MAY contain
|
|
* UTF-8-encoded data with value /reason/, the interpretation of which is not
|
|
* defined by this specification."
|
|
*
|
|
* (2) Close Codes available:
|
|
*
|
|
* HTTPc_WEBSOCK_CLOSE_CODE_NORMAL
|
|
* HTTPc_WEBSOCK_CLOSE_CODE_GOING_AWAY
|
|
* HTTPc_WEBSOCK_CLOSE_CODE_PROTOCOL_ERR
|
|
* HTTPc_WEBSOCK_CLOSE_CODE_DATA_TYPE_NOT_ALLOWED
|
|
* HTTPc_WEBSOCK_CLOSE_CODE_DATA_TYPE_ERR
|
|
* HTTPc_WEBSOCK_CLOSE_CODE_POLICY_VIOLATION
|
|
* HTTPc_WEBSOCK_CLOSE_CODE_MSG_TOO_BIG
|
|
* HTTPc_WEBSOCK_CLOSE_CODE_INVALID_EXT
|
|
* HTTPc_WEBSOCK_CLOSE_CODE_UNEXPECTED_CONDITION
|
|
*
|
|
* (3) Close Reason:
|
|
*
|
|
* (a) Except for its length, the reason string has no restriction and it is user-definable.
|
|
* This should be used for debug purpose.
|
|
*
|
|
* (b) This field can be empty.
|
|
*********************************************************************************************************
|
|
*/
|
|
#if (HTTPc_CFG_WEBSOCKET_EN == DEF_ENABLED)
|
|
CPU_INT16U HTTPc_WebSockFmtCloseMsg(HTTPc_WEBSOCK_CLOSE_CODE close_code,
|
|
CPU_CHAR *p_reason,
|
|
CPU_CHAR *p_buf,
|
|
CPU_INT16U buf_len,
|
|
HTTPc_ERR *p_err)
|
|
{
|
|
CPU_INT16U str_len;
|
|
CPU_INT16U msg_len;
|
|
|
|
|
|
msg_len = 0u;
|
|
|
|
#if (HTTPc_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
|
|
if (p_err == DEF_NULL) {
|
|
CPU_SW_EXCEPTION(0);
|
|
}
|
|
|
|
if (HTTPc_InitDone != DEF_YES) {
|
|
*p_err = HTTPc_ERR_INIT_NOT_COMPLETED;
|
|
goto exit;
|
|
}
|
|
|
|
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:
|
|
break;
|
|
|
|
default:
|
|
*p_err = HTTPc_ERR_WEBSOCK_INVALID_CLOSE_CODE;
|
|
goto exit;
|
|
}
|
|
if (p_buf == DEF_NULL) {
|
|
*p_err = HTTPc_ERR_NULL_PTR;
|
|
goto exit;
|
|
}
|
|
#endif
|
|
|
|
str_len = Str_Len(p_reason);
|
|
if (str_len > HTTPc_WEBSOCK_MAX_CLOSE_REASON_LEN) {
|
|
*p_err = HTTPc_ERR_WEBSOCK_INVALID_CTRL_FRAME_LEN;
|
|
goto exit;
|
|
}
|
|
|
|
close_code = MEM_VAL_GET_INT16U_BIG(&close_code);
|
|
Mem_Copy(p_buf, (CPU_CHAR *)&close_code, sizeof(CPU_INT16U));
|
|
|
|
p_buf += sizeof(CPU_INT16U);
|
|
buf_len -= HTTPc_WEBSOCK_CLOSE_CODE_LEN;
|
|
|
|
if (buf_len < str_len) {
|
|
*p_err = HTTPc_ERR_WEBSOCK_INVALID_CTRL_FRAME_LEN;
|
|
goto exit;
|
|
}
|
|
|
|
Str_Copy_N(p_buf, p_reason, str_len);
|
|
msg_len = str_len + sizeof(CPU_INT16U);
|
|
|
|
exit:
|
|
return (msg_len);
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
* LOCAL FUNCTIONS
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* HTTPc_ConnCloseHandler()
|
|
*
|
|
* Description : Close an HTTPc Connection.
|
|
*
|
|
* Argument(s) : p_conn Pointer to Connection to close.
|
|
*
|
|
* flags Configuration flags :
|
|
*
|
|
* HTTPc_FLAG_CONN_NO_BLOCK
|
|
*
|
|
* p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* HTTPc_ERR_NONE Connection closing successfully started.
|
|
* HTTPc_ERR_CONN_IS_RELEASED Connection is not used.
|
|
* HTTPc_ERR_FEATURE_DIS A needed feature is disabled.
|
|
*
|
|
* ------------ RETURNED BY HTTPcTask_MsgQueue() ------------
|
|
* See HTTPcTask_MsgQueue() for additional return error codes.
|
|
*
|
|
* ------------ RETURNED BY HTTPcTask_ConnCloseSignalCreate() ------------
|
|
* See HTTPcTask_ConnCloseSignalCreate() for additional return error codes.
|
|
*
|
|
* ------------ RETURNED BY HTTPcTask_ConnCloseSignalWait() ------------
|
|
* See HTTPcTask_ConnCloseSignalWait() for additional return error codes.
|
|
*
|
|
* ------------ RETURNED BY HTTPcTask_ConnCloseSignalDel() ------------
|
|
* See HTTPcTask_ConnCloseSignalDel() for additional return error codes.
|
|
*
|
|
* ------------ RETURNED BY HTTPcConn_Close() ------------
|
|
* See HTTPcConn_Close() for additional return error codes.
|
|
* Return(s) : None.
|
|
*
|
|
* Caller(s) : HTTPc_ConnClose(),
|
|
* HTTPc_ConnOpen(),
|
|
* HTTPc_ReqSend().
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
#if ((HTTPc_CFG_PERSISTENT_EN == DEF_ENABLED) || \
|
|
defined(HTTPc_SIGNAL_TASK_MODULE_EN) )
|
|
static void HTTPc_ConnCloseHandler(HTTPc_CONN *p_conn,
|
|
HTTPc_FLAGS flags,
|
|
HTTPc_ERR *p_err)
|
|
{
|
|
CPU_BOOLEAN in_use;
|
|
CPU_BOOLEAN no_block;
|
|
#ifdef HTTPc_TASK_MODULE_EN
|
|
HTTPc_ERR err;
|
|
#endif
|
|
CPU_SR_ALLOC();
|
|
|
|
|
|
/* ------------ VALIDATE THAT CONN IS USED ------------ */
|
|
CPU_CRITICAL_ENTER();
|
|
in_use = DEF_BIT_IS_SET(p_conn->Flags, HTTPc_FLAG_CONN_IN_USE);
|
|
CPU_CRITICAL_EXIT();
|
|
if (in_use == DEF_NO) {
|
|
*p_err = HTTPc_ERR_CONN_IS_RELEASED;
|
|
goto exit;
|
|
}
|
|
|
|
/* ---------------- SET BLOCKING MODE ----------------- */
|
|
no_block = DEF_BIT_IS_SET(flags, HTTPc_FLAG_CONN_NO_BLOCK);
|
|
if (no_block == DEF_YES) {
|
|
DEF_BIT_SET(p_conn->Flags, HTTPc_FLAG_CONN_NO_BLOCK);
|
|
} else {
|
|
DEF_BIT_CLR(p_conn->Flags, HTTPc_FLAG_CONN_NO_BLOCK);
|
|
}
|
|
|
|
#ifdef HTTPc_TASK_MODULE_EN
|
|
if (no_block == DEF_NO) {
|
|
#ifdef HTTPc_SIGNAL_TASK_MODULE_EN
|
|
|
|
HTTPcTask_ConnCloseSignalCreate(p_conn, &err);
|
|
if (err != HTTPc_ERR_NONE) {
|
|
CPU_SW_EXCEPTION(;);
|
|
}
|
|
#else
|
|
*p_err = HTTPc_ERR_FEATURE_DIS;
|
|
goto exit;
|
|
#endif
|
|
}
|
|
|
|
HTTPcTask_MsgQueue(HTTPc_MSG_TYPE_CONN_CLOSE,
|
|
(void *) p_conn,
|
|
p_err);
|
|
if (*p_err != HTTPc_ERR_NONE) {
|
|
goto exit;
|
|
}
|
|
|
|
HTTPcTask_Wake(p_conn, &err);
|
|
if (err != HTTPc_ERR_NONE) {
|
|
goto exit;
|
|
}
|
|
|
|
if (no_block == DEF_NO) {
|
|
#ifdef HTTPc_SIGNAL_TASK_MODULE_EN
|
|
HTTPcTask_ConnCloseSignalWait(p_conn, &err);
|
|
if (err != HTTPc_ERR_NONE) {
|
|
CPU_SW_EXCEPTION(;);
|
|
}
|
|
|
|
HTTPcTask_ConnCloseSignalDel(p_conn, &err);
|
|
if (err != HTTPc_ERR_NONE) {
|
|
CPU_SW_EXCEPTION(;);
|
|
}
|
|
|
|
#else
|
|
*p_err = HTTPc_ERR_FEATURE_DIS;
|
|
goto exit;
|
|
#endif
|
|
}
|
|
|
|
#else
|
|
|
|
HTTPcConn_Close(p_conn, p_err);
|
|
if (*p_err != HTTPc_ERR_NONE) {
|
|
goto exit;
|
|
}
|
|
|
|
HTTPcConn_Remove(p_conn);
|
|
|
|
#endif
|
|
*p_err = HTTPc_ERR_NONE;
|
|
|
|
|
|
exit:
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
|