/******************************************************************************* * File Name : HTTP.c * Description : * Created on : 2020��7��1�� * Author : �ż� *******************************************************************************/ /******************************************************************************* * Include Files * *******************************************************************************/ #include "HTTPClient.h" #include "string.h" #include "HIDO_Util.h" #include "HIDO_Debug.h" #include "HIDO_ArraryQueue.h" #include "HIDO_Timer.h" #include "Socket.h" #include "Internet.h" /******************************************************************************* * Macro * *******************************************************************************/ #define HTTP_RECV_BUFF_SIZE (1024 * 32) /******************************************************************************* * Type Definition * *******************************************************************************/ typedef enum { HTTP_CLIENT_STATE_IDLE, HTTP_CLIENT_STATE_CONNECTING, HTTP_CLIENT_STATE_CONNECTED, } E_HTTPClientState; typedef enum { HTTP_RECV_STATE_HEAD, HTTP_RECV_STATE_BODY, } E_HTTPRecvState; typedef enum { HTTP_METHOD_GET, HTTP_METHOD_POST, HTTP_METHOD_GET_FILE, HTTP_METHOD_POST_FILE, } E_HTTPMethod; /******************************************************************************* * Local Variable * *******************************************************************************/ static E_HTTPClientState l_eHTTPClientState = HTTP_CLIENT_STATE_IDLE; static E_HTTPRecvState l_eHTTPRecvState = HTTP_RECV_STATE_HEAD; static E_HTTPMethod l_eHTTPMethod; static HIDO_INT32 l_i32HTTPClientSockID = 0; static HIDO_UINT32 l_u32HTTPClientTimerID = 0; static HIDO_CHAR l_acHTTPUrl[128]; static FN_HTTPResponseCallback l_fnHTTPResponseCallback; static FN_HTTPGetFileCallback l_fnHTTPGetFileCallback; static FN_HTTPPostDataCallback l_fnHTTPostDataCallback; static HIDO_VOID *l_pHTTPArg = HIDO_NULL; static HIDO_UINT32 l_u32HTTPTryCnt = 0; static HIDO_UINT32 l_u32HTTPPort = 80; static HIDO_CHAR l_acHTTPPath[128]; // Increased from 64 to 128 for longer file paths static HIDO_CHAR l_acHTTPHost[64]; static HIDO_UINT32 l_u32HTTPPostLen = 0; static HIDO_CHAR l_acHTTPSendBuff[1024]; static HIDO_UINT32 l_u32HTTPSendBuffLen; static HIDO_CHAR l_acHTTPRecvBuff[HTTP_RECV_BUFF_SIZE + 1]; static HIDO_UINT32 l_u32HTTPRecvBuffLen = 0; static HIDO_UINT32 l_u32HTTPRecvTotalLen = 0; static HIDO_UINT32 l_u32HTTPRespCode = 0; static HIDO_UINT32 l_u32HTTPContentLength = 0; static HIDO_UINT8 *l_pu8HTTPRespBody = HIDO_NULL; static HIDO_UINT8 l_au8HTTPPostBuff[1024]; //static ST_HTTPGetFileOpt l_stHTTPGetFileOpt; static ST_HTTPGetFileResponse l_stHTTPGetFileResponse; /******************************************************************************* * Local Function Declaration * *******************************************************************************/ /******************************************************************************* * Local Function * *******************************************************************************/ /******************************************************************************* * Function Name : HTTPClient_Response * Description : * Input : * Output : * Return : * Author : �ż� * Modified Date: : 2020��7��1�� *******************************************************************************/ static HIDO_INT32 HTTPClient_Response(HIDO_UINT32 _u32RespCode, HIDO_UINT8 *_pu8Data, HIDO_UINT32 _u32Len) { if(HTTP_METHOD_GET_FILE == l_eHTTPMethod) { if(l_fnHTTPGetFileCallback != HIDO_NULL) { l_fnHTTPGetFileCallback(_u32RespCode, &l_stHTTPGetFileResponse, _pu8Data, _u32Len, l_pHTTPArg); } } else { HIDO_DebugString((HIDO_CHAR *)_pu8Data, _u32Len); if(l_fnHTTPResponseCallback != HIDO_NULL) { l_fnHTTPResponseCallback(_u32RespCode, _pu8Data, _u32Len, l_pHTTPArg); } } return HIDO_OK; } /******************************************************************************* * Function Name : HTTPClient_TimerCallback * Description : * Input : * Output : * Return : * Author : �ż� * Modified Date: : 2020��7��1�� *******************************************************************************/ static HIDO_VOID HTTPClient_TimerCallback(HIDO_VOID *_pArg) { if(l_eHTTPClientState != HTTP_CLIENT_STATE_IDLE) { Socket_Close(l_i32HTTPClientSockID); } } /******************************************************************************* * Function Name : HTTPClient_SocketEventProc * Description : * Input : * Output : * Return : * Author : �ż� * Modified Date: : 2020��11��14�� *******************************************************************************/ static void HTTPClient_SocketEventProc(HIDO_INT32 _i32SockID, E_SocketEvent _eEvent, HIDO_VOID *_pArg) { switch (_eEvent) { case SOCKET_EVENT_CONNECT_FAILED: { if(HTTP_CLIENT_STATE_CONNECTING == l_eHTTPClientState) { if(l_u32HTTPTryCnt < 3) { l_u32HTTPTryCnt++; Socket_Connect(l_i32HTTPClientSockID, l_acHTTPHost, l_u32HTTPPort); } else { l_eHTTPClientState = HTTP_CLIENT_STATE_IDLE; HTTPClient_Response(408, HIDO_NULL, 0); } } break; } case SOCKET_EVENT_CONNECTED: { if(HTTP_CLIENT_STATE_CONNECTING == l_eHTTPClientState) { l_eHTTPClientState = HTTP_CLIENT_STATE_CONNECTED; l_eHTTPRecvState = HTTP_RECV_STATE_HEAD; l_u32HTTPRecvBuffLen = 0; if(l_eHTTPMethod != HTTP_METHOD_POST_FILE) { Socket_Send(l_i32HTTPClientSockID, (HIDO_UINT8 *)l_acHTTPSendBuff, l_u32HTTPSendBuffLen); } } break; } case SOCKET_EVENT_CLOSED: { if(l_eHTTPClientState != HTTP_CLIENT_STATE_IDLE) { HIDO_TimerCancel(l_u32HTTPClientTimerID); l_eHTTPClientState = HTTP_CLIENT_STATE_IDLE; // 对于GET_FILE方法,发送NULL表示下载完成 if(HTTP_METHOD_GET_FILE == l_eHTTPMethod) { HTTPClient_Response(l_u32HTTPRespCode, HIDO_NULL, 0); } else { HTTPClient_Response(l_u32HTTPRespCode, l_pu8HTTPRespBody, l_u32HTTPContentLength); } } else { HIDO_TimerCancel(l_u32HTTPClientTimerID); } break; } case SOCKET_EVENT_RECV_DATA: { HIDO_INT32 i32Ret = 0; HIDO_UINT32 u32RecvLen = 0; do { if (l_u32HTTPRecvBuffLen >= HTTP_RECV_BUFF_SIZE) { Socket_Close(l_i32HTTPClientSockID); break; } i32Ret = Socket_Recv(l_i32HTTPClientSockID, (HIDO_UINT8 *)(l_acHTTPRecvBuff + l_u32HTTPRecvBuffLen), HTTP_RECV_BUFF_SIZE - l_u32HTTPRecvBuffLen, &u32RecvLen); if ((i32Ret != HIDO_OK) || (0 == u32RecvLen)) { break; } l_u32HTTPRecvBuffLen += u32RecvLen; if (HTTP_RECV_STATE_HEAD == l_eHTTPRecvState) { /* �յ�"\r\n\r\n */ l_pu8HTTPRespBody = (HIDO_UINT8 *)HIDO_UtilStrnstr(l_acHTTPRecvBuff, "\r\n\r\n", u32RecvLen); if (l_pu8HTTPRespBody != HIDO_NULL) { HIDO_CHAR *pcKeyName = HIDO_NULL; HIDO_UINT32 u32Range0 = 0; HIDO_UINT32 u32Range1 = 0; HIDO_UINT32 u32RangeAll = 0; l_pu8HTTPRespBody += 4; if (HIDO_UtilParseFormat((HIDO_UINT8 *) l_acHTTPRecvBuff, u32RecvLen, "HTTP/1.1 %d %*\r\n", &l_u32HTTPRespCode) != 2) { Socket_Close(l_i32HTTPClientSockID); break; } pcKeyName = HIDO_UtilStrnstr(l_acHTTPRecvBuff, "Content-Length: ", u32RecvLen); if (pcKeyName != HIDO_NULL) { if (HIDO_UtilParseFormat((HIDO_UINT8 *) pcKeyName, u32RecvLen - (pcKeyName - l_acHTTPRecvBuff), "Content-Length: %d\r\n", &l_u32HTTPContentLength) != 1) { Socket_Close(l_i32HTTPClientSockID); break; } } else { Socket_Close(l_i32HTTPClientSockID); break; } /* ��ȡ�ļ���Ƭ��Ϣ */ if(HTTP_METHOD_GET_FILE == l_eHTTPMethod) { HIDO_DataStruct stETag; memset(&l_stHTTPGetFileResponse, 0, sizeof(l_stHTTPGetFileResponse)); // 检查是否有Content-Range头(206 Partial Content响应) pcKeyName = HIDO_UtilStrnstr(l_acHTTPRecvBuff, "Content-Range: ", u32RecvLen); if (pcKeyName != HIDO_NULL) { // 有Range,解析Range信息 if (HIDO_UtilParseFormat((HIDO_UINT8 *) pcKeyName, u32RecvLen - (pcKeyName - l_acHTTPRecvBuff), "Content-Range: bytes %d-%d/%d\r\n", &u32Range0, &u32Range1, &u32RangeAll) != 3) { Socket_Close(l_i32HTTPClientSockID); break; } l_stHTTPGetFileResponse.m_u32RangeBegin = u32Range0; l_stHTTPGetFileResponse.m_u32RangeEnd = u32Range1; l_stHTTPGetFileResponse.m_u32RangeTotal = u32RangeAll; } else { // 无Range头,使用Content-Length作为总大小(200 OK响应) l_stHTTPGetFileResponse.m_u32RangeBegin = 0; l_stHTTPGetFileResponse.m_u32RangeEnd = l_u32HTTPContentLength - 1; l_stHTTPGetFileResponse.m_u32RangeTotal = l_u32HTTPContentLength; } // ETag是可选的 pcKeyName = HIDO_UtilStrnstr(l_acHTTPRecvBuff, "ETag: ", u32RecvLen); if (pcKeyName != HIDO_NULL) { if (HIDO_UtilParseFormat((HIDO_UINT8 *) pcKeyName, u32RecvLen - (pcKeyName - l_acHTTPRecvBuff), "ETag: %p\r\n", &stETag) == 1) { if((stETag.m_u32Len + 1) < sizeof(l_stHTTPGetFileResponse.m_acETag)) { memcpy(l_stHTTPGetFileResponse.m_acETag, stETag.m_pData, stETag.m_u32Len); } } } } l_u32HTTPRecvTotalLen = l_pu8HTTPRespBody - (HIDO_UINT8 *)l_acHTTPRecvBuff + l_u32HTTPContentLength; l_eHTTPRecvState = HTTP_RECV_STATE_BODY; // 对于GET_FILE方法,立即回调传递头部信息(DataLen=0表示首次回调) if(HTTP_METHOD_GET_FILE == l_eHTTPMethod) { HIDO_UINT32 u32BodyLen = l_u32HTTPRecvBuffLen - (l_pu8HTTPRespBody - (HIDO_UINT8 *)l_acHTTPRecvBuff); if(u32BodyLen > 0) { // 头部接收时已经包含部分Body数据,立即回调 HTTPClient_Response(l_u32HTTPRespCode, l_pu8HTTPRespBody, u32BodyLen); // 重置缓冲区,准备接收后续数据 l_u32HTTPRecvBuffLen = 0; l_u32HTTPRecvTotalLen = l_u32HTTPContentLength - u32BodyLen; } else { // 头部刚接收完,Body数据还未到,先回调头部信息 HTTPClient_Response(l_u32HTTPRespCode, HIDO_NULL, 0); l_u32HTTPRecvBuffLen = 0; l_u32HTTPRecvTotalLen = l_u32HTTPContentLength; } } else { // 非GET_FILE方法,保持原有逻辑 if (l_u32HTTPRecvBuffLen >= l_u32HTTPRecvTotalLen) { Socket_Close(l_i32HTTPClientSockID); } } } } else if(HTTP_RECV_STATE_BODY == l_eHTTPRecvState) { // BODY接收状态 if(HTTP_METHOD_GET_FILE == l_eHTTPMethod) { // GET_FILE方法:分块回调,接收满缓冲区就回调 if(l_u32HTTPRecvBuffLen >= HTTP_RECV_BUFF_SIZE - 1024 || l_u32HTTPRecvBuffLen >= l_u32HTTPRecvTotalLen) { HTTPClient_Response(l_u32HTTPRespCode, (HIDO_UINT8 *)l_acHTTPRecvBuff, l_u32HTTPRecvBuffLen); l_u32HTTPRecvTotalLen -= l_u32HTTPRecvBuffLen; l_u32HTTPRecvBuffLen = 0; // 所有数据接收完成 if(l_u32HTTPRecvTotalLen == 0) { Socket_Close(l_i32HTTPClientSockID); } } } else { // 非GET_FILE方法:等待完整接收 if (l_u32HTTPRecvBuffLen >= l_u32HTTPRecvTotalLen) { HTTPClient_Response(l_u32HTTPRespCode, l_pu8HTTPRespBody, l_u32HTTPContentLength); Socket_Close(l_i32HTTPClientSockID); } } } } while(HIDO_TRUE); break; } default: { break; } } } /******************************************************************************* * Function Name : HTTPClient_ParseUrl * Description : ����Url * Input : * Output : * Return : * Author : �ż� * Modified Date: : 2020��7��1�� *******************************************************************************/ HIDO_INT32 HTTPClient_ParseUrl(HIDO_CHAR *_pcUrl, HIDO_CHAR *_pcHost, HIDO_UINT32 _u32HostSize, HIDO_CHAR *_pcPath, HIDO_UINT32 _u32PathSize, HIDO_UINT32 *_pu32Port) { HIDO_DataStruct stHost; HIDO_DataStruct stPath; HIDO_UINT32 u32Port = 0; if(HIDO_NULL == _pcUrl) { return HIDO_ERR; } if(HIDO_UtilParseFormat((HIDO_UINT8 *)_pcUrl, strlen(_pcUrl), "http://%p:%d/%p", &stHost, &u32Port, &stPath) != 3) { u32Port = 80; if (HIDO_UtilParseFormat((HIDO_UINT8 *) _pcUrl, strlen(_pcUrl), "http://%p/%p", &stHost, &stPath) != 2) { return HIDO_ERR; } } /* HOST */ if((stHost.m_u32Len + 1) < _u32HostSize) { memcpy(_pcHost, stHost.m_pData, stHost.m_u32Len); _pcHost[stHost.m_u32Len] = '\0'; } else { return HIDO_ERR; } /* Path */ if(stPath.m_u32Len > 0) { if((stPath.m_u32Len + 1) < _u32PathSize) { memcpy(_pcPath, stPath.m_pData, stPath.m_u32Len); _pcPath[stPath.m_u32Len] = '\0'; } else { return HIDO_ERR; } } else { _pcPath[0] = '\0'; } *_pu32Port = u32Port; return HIDO_OK; } /******************************************************************************* * Function Name : HTTP_GetPostData * Description : * Input : * Output : * Return : * Author : �ż� * Modified Date: : 2021��5��3�� *******************************************************************************/ HIDO_INT32 HTTPClient_GetPostFileData(HIDO_UINT32 _u32Offset, HIDO_VOID *_pBuff, HIDO_UINT32 _u32BuffSize, HIDO_UINT32 *_pu32Len) { if(l_fnHTTPostDataCallback != HIDO_NULL) { return l_fnHTTPostDataCallback(_u32Offset, _pBuff, _u32BuffSize, _pu32Len, l_pHTTPArg); } return HIDO_ERR; } /******************************************************************************* * Global Function * *******************************************************************************/ /******************************************************************************* * Function Name : HTTPClient_Post * Description : * Input : * Output : * Return : * Author : �ż� * Modified Date: : 2020��7��1�� *******************************************************************************/ HIDO_INT32 HTTPClient_Post(HIDO_CHAR *_pcUrl, HIDO_CHAR *_pcBody, HIDO_UINT32 _u32BodyLen, FN_HTTPResponseCallback _fnResponseCallback, HIDO_VOID *_pArg) { if(l_eHTTPClientState != HTTP_CLIENT_STATE_IDLE) { return HIDO_ERR; } if(Internet_IsIPReady() != HIDO_TRUE) { return HIDO_ERR; } /* ����Url */ if(HTTPClient_ParseUrl(_pcUrl, l_acHTTPHost, sizeof(l_acHTTPHost), l_acHTTPPath, sizeof(l_acHTTPPath), &l_u32HTTPPort) != HIDO_OK) { return HIDO_ERR; } /* URL */ HIDO_UtilSnprintf(l_acHTTPUrl, sizeof(l_acHTTPUrl), _pcUrl); l_u32HTTPSendBuffLen = HIDO_UtilSnprintf(l_acHTTPSendBuff, sizeof(l_acHTTPSendBuff), "POST /%s HTTP/1.1\r\n" "Host: %s\r\n" "User-Agent: QUECTEL_MODULE\r\n" "Connection: Keep-Alive\r\n" "Content-Type: application/json\r\n" "Accept: */*\r\n" "Content-Length: %u\r\n" "\r\n" "%s" , l_acHTTPPath, l_acHTTPHost, _u32BodyLen, _pcBody); l_fnHTTPResponseCallback = _fnResponseCallback; l_pHTTPArg = _pArg; l_u32HTTPRespCode = 0; l_u32HTTPContentLength = 0; l_eHTTPClientState = HTTP_CLIENT_STATE_CONNECTING; l_eHTTPMethod = HTTP_METHOD_POST; l_u32HTTPTryCnt = 1; Socket_Connect(l_i32HTTPClientSockID, l_acHTTPHost, l_u32HTTPPort); HIDO_TimerStart(l_u32HTTPClientTimerID, HIDO_TIMER_TYPE_ONCE, HIDO_TIMER_TICK_S(15), HTTPClient_TimerCallback, HIDO_NULL); return HIDO_OK; } /******************************************************************************* * Function Name : HTTPClient_Get * Description : * Input : * Output : * Return : * Author : �ż� * Modified Date: : 2020��7��1�� *******************************************************************************/ HIDO_INT32 HTTPClient_Get(HIDO_CHAR *_pcUrl, FN_HTTPResponseCallback _fnResponseCallback, HIDO_VOID *_pArg) { if(l_eHTTPClientState != HTTP_CLIENT_STATE_IDLE) { return HIDO_ERR; } if(Internet_IsIPReady() != HIDO_TRUE) { return HIDO_ERR; } /* ����Url */ if(HTTPClient_ParseUrl(_pcUrl, l_acHTTPHost, sizeof(l_acHTTPHost), l_acHTTPPath, sizeof(l_acHTTPPath), &l_u32HTTPPort) != HIDO_OK) { return HIDO_ERR; } /* URL */ HIDO_UtilSnprintf(l_acHTTPUrl, sizeof(l_acHTTPUrl), _pcUrl); l_u32HTTPSendBuffLen = HIDO_UtilSnprintf(l_acHTTPSendBuff, sizeof(l_acHTTPSendBuff), "GET /%s HTTP/1.1\r\n" "Host: %s\r\n" "User-Agent: QUECTEL_MODULE\r\n" "Connection: Keep-Alive\r\n" "Accept: */*\r\n" "\r\n" , l_acHTTPPath, l_acHTTPHost); l_fnHTTPResponseCallback = _fnResponseCallback; l_pHTTPArg = _pArg; l_u32HTTPRespCode = 0; l_u32HTTPContentLength = 0; l_eHTTPClientState = HTTP_CLIENT_STATE_CONNECTING; l_eHTTPMethod = HTTP_METHOD_GET; l_u32HTTPTryCnt = 1; Socket_Connect(l_i32HTTPClientSockID, l_acHTTPHost, l_u32HTTPPort); HIDO_TimerStart(l_u32HTTPClientTimerID, HIDO_TIMER_TYPE_ONCE, HIDO_TIMER_TICK_S(15), HTTPClient_TimerCallback, HIDO_NULL); return HIDO_OK; } /******************************************************************************* * Function Name : HTTPClient_GetFile * Description : HTTP �����ļ� * Input : _pcUrl �ļ����� * : _fnGetFileCallback �ļ������¼��ص� * : _pstOpt ���ز��� * �� _pArg �û�����,�ص�ʹ�� * Output : None * Return : HIDO_OK �ɹ�,HIDO_ERR ʧ�� * Author : �ż� * Modified Date: : 2020��7��1�� *******************************************************************************/ HIDO_INT32 HTTPClient_GetFile(HIDO_CHAR *_pcUrl, FN_HTTPGetFileCallback _fnGetFileCallback, ST_HTTPGetFileOpt *_pstOpt, HIDO_VOID *_pArg) { HIDO_INT32 ret; if(l_eHTTPClientState != HTTP_CLIENT_STATE_IDLE) { return HIDO_ERR; } if((HIDO_NULL == _pcUrl) || (HIDO_NULL == _pstOpt)) { return HIDO_ERR; } if(Internet_IsIPReady() != HIDO_TRUE) { return HIDO_ERR; } /* ����Url */ ret = HTTPClient_ParseUrl(_pcUrl, l_acHTTPHost, sizeof(l_acHTTPHost), l_acHTTPPath, sizeof(l_acHTTPPath), &l_u32HTTPPort); if(ret != HIDO_OK) { return HIDO_ERR; } /* URL */ HIDO_UtilSnprintf(l_acHTTPUrl, sizeof(l_acHTTPUrl), _pcUrl); // 构建基础HTTP请求头 l_u32HTTPSendBuffLen = HIDO_UtilSnprintf(l_acHTTPSendBuff, sizeof(l_acHTTPSendBuff), "GET /%s HTTP/1.1\r\n" "Host: %s\r\n" "User-Agent: QUECTEL_MODULE\r\n" "Connection: Keep-Alive\r\n" "Accept: */*\r\n", l_acHTTPPath, l_acHTTPHost); // 只有当RangeEnd > RangeBegin且不为0时才添加Range头 if(_pstOpt->m_u32RangeEnd > 0 && _pstOpt->m_u32RangeEnd != 0xFFFFFFFF) { l_u32HTTPSendBuffLen += HIDO_UtilSnprintf(l_acHTTPSendBuff + l_u32HTTPSendBuffLen, sizeof(l_acHTTPSendBuff) - l_u32HTTPSendBuffLen, "Range: bytes=%u-%u\r\n", _pstOpt->m_u32RangeBegin, _pstOpt->m_u32RangeEnd); } if(strlen(_pstOpt->m_acIfRange) != 0) { l_u32HTTPSendBuffLen += HIDO_UtilSnprintf(l_acHTTPSendBuff + l_u32HTTPSendBuffLen, sizeof(l_acHTTPSendBuff) - l_u32HTTPSendBuffLen, "If-Range: \"%s\"\r\n" "\r\n" , _pstOpt->m_acIfRange); } else { l_u32HTTPSendBuffLen += HIDO_UtilSnprintf(l_acHTTPSendBuff + l_u32HTTPSendBuffLen, sizeof(l_acHTTPSendBuff) - l_u32HTTPSendBuffLen, "\r\n"); } l_fnHTTPGetFileCallback = _fnGetFileCallback; l_pHTTPArg = _pArg; l_u32HTTPRespCode = 0; l_u32HTTPContentLength = 0; l_eHTTPClientState = HTTP_CLIENT_STATE_CONNECTING; l_eHTTPMethod = HTTP_METHOD_GET_FILE; l_u32HTTPTryCnt = 1; Socket_Connect(l_i32HTTPClientSockID, l_acHTTPHost, l_u32HTTPPort); HIDO_TimerStart(l_u32HTTPClientTimerID, HIDO_TIMER_TYPE_ONCE, HIDO_TIMER_TICK_S(30), HTTPClient_TimerCallback, HIDO_NULL); return HIDO_OK; } /******************************************************************************* * Function Name : HTTPClient_PostFile * Description : HTTP �ϴ��ļ� * Input : _pcUrl HTTP·�� * : _pcFileName �ļ����� * : _fnResponseCallback HTTP��Ӧ�ص����� * : _pArg ���� * Output : Mone * Return : HIDO_OK �ɹ�,HIDO_ERR ʧ�� * Author : �ż� * Modified Date: : 2021��5��3�� *******************************************************************************/ HIDO_INT32 HTTPClient_PostFile(HIDO_CHAR *_pcUrl, FN_HTTPPostDataCallback _fnPostDataCallback, FN_HTTPResponseCallback _fnResponseCallback, HIDO_VOID *_pArg) { if(l_eHTTPClientState != HTTP_CLIENT_STATE_IDLE) { return HIDO_ERR; } if(HIDO_NULL == _pcUrl) { return HIDO_ERR; } if(HIDO_NULL == _fnPostDataCallback) { return HIDO_ERR; } if(HIDO_NULL == _fnResponseCallback) { return HIDO_ERR; } if(Internet_IsIPReady() != HIDO_TRUE) { return HIDO_ERR; } /* ����Url */ if(HTTPClient_ParseUrl(_pcUrl, l_acHTTPHost, sizeof(l_acHTTPHost), l_acHTTPPath, sizeof(l_acHTTPPath), &l_u32HTTPPort) != HIDO_OK) { return HIDO_ERR; } l_fnHTTPResponseCallback = _fnResponseCallback; l_fnHTTPostDataCallback = _fnPostDataCallback; l_pHTTPArg = _pArg; l_u32HTTPPostLen = 0; l_eHTTPMethod = HTTP_METHOD_POST_FILE; l_eHTTPClientState = HTTP_CLIENT_STATE_CONNECTING; Socket_Connect(l_i32HTTPClientSockID, l_acHTTPHost, l_u32HTTPPort); return HIDO_OK; } /******************************************************************************* * Function Name : HTTPClient_Poll * Description : HTTP�ͻ�����ѯ���� * Input : None * Output : None * Return : HIDO_OK �ɹ�,HIDO_ERR ʧ�� * Author : �ż� * Modified Date: : 2020��7��1�� *******************************************************************************/ HIDO_INT32 HTTPClient_Poll(HIDO_VOID) { if(HTTP_CLIENT_STATE_CONNECTED == l_eHTTPClientState) { if(HTTP_METHOD_POST_FILE == l_eHTTPMethod) { if(Socket_IsSendQueueEmpty(l_i32HTTPClientSockID) == HIDO_TRUE) { HIDO_UINT32 u32PostLen = 0; HIDO_INT32 i32Result = 0; i32Result = HTTPClient_GetPostFileData(l_u32HTTPPostLen, l_au8HTTPPostBuff, sizeof(l_au8HTTPPostBuff), &u32PostLen); if((HIDO_OK == i32Result) && (u32PostLen != 0)) { Socket_Send(l_i32HTTPClientSockID, l_au8HTTPPostBuff, u32PostLen); } } } } return HIDO_OK; } /******************************************************************************* * Function Name : HTTPClient_Init * Description : HTTP�ͻ��˳�ʼ�� * Input : None * Output : None * Return : HIDO_OK �ɹ�,HIDO_ERR ʧ�� * Author : �ż� * Modified Date: : 2020��7��1�� *******************************************************************************/ HIDO_INT32 HTTPClient_Init(HIDO_VOID) { l_eHTTPClientState = HTTP_CLIENT_STATE_IDLE; if(Socket_Create(&l_i32HTTPClientSockID, SOCKET_TYPE_TCP, HTTPClient_SocketEventProc, HIDO_NULL) != HIDO_OK) { return HIDO_ERR; } if(HIDO_TimerCreate(&l_u32HTTPClientTimerID) != HIDO_OK) { return HIDO_ERR; } return HIDO_OK; } /******************************************************************************* * Function Name : HTTPClient_GetState * Description : 获取HTTPClient当前状态(用于调试) * Return : 0=IDLE, 1=CONNECTING, 2=CONNECTED *******************************************************************************/ HIDO_INT32 HTTPClient_GetState(HIDO_VOID) { return (HIDO_INT32)l_eHTTPClientState; } /******************************************************************************* * Function Name : HTTPClient_Reset * Description : 强制重置HTTPClient状态到IDLE(用于错误恢复) *******************************************************************************/ HIDO_VOID HTTPClient_Reset(HIDO_VOID) { l_eHTTPClientState = HTTP_CLIENT_STATE_IDLE; HIDO_TimerCancel(l_u32HTTPClientTimerID); }