code_app/sdk/webservice/WSUser.cpp

549 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "WSUser.h"
#include "WSServer.h"
#include "ManagerV2.h"
#include "base/HGInfo.h"
#include "cJSON.h"
#include "sha1.h"
#include "base64.h"
namespace ver_2
{
static int GetJsonIntValue(cJSON* json, const std::string& key)
{
int ret = 0;
cJSON* p = json->child;
while (NULL != p)
{
if (0 == strcmp(p->string, key.c_str()))
{
if (p->type == cJSON_Number)
ret = p->valueint;
break;
}
p = p->next;
}
return ret;
}
static bool GetJsonBoolValue(cJSON* json, const std::string& key)
{
bool ret = false;
cJSON* p = json->child;
while (NULL != p)
{
if (0 == strcmp(p->string, key.c_str()))
{
if (p->type == cJSON_True)
ret = true;
break;
}
p = p->next;
}
return ret;
}
static std::string GetJsonStringValue(cJSON* json, const std::string& key)
{
std::string ret;
cJSON* p = json->child;
while (NULL != p)
{
if (0 == strcmp(p->string, key.c_str()))
{
if (p->type == cJSON_String)
ret = p->valuestring;
break;
}
p = p->next;
}
return ret;
}
#if defined(HG_CMP_MSC)
WSUser::WSUser(WebServer* server, HGUInt id, const std::string& ip, uint16_t port, SOCKET sockConn)
#else
WSUser::WSUser(WebServer* server, HGUInt id, const std::string& ip, uint16_t port, int sockConn)
#endif
: WebUser(server, id, ip, port, sockConn)
{
}
WSUser::~WSUser()
{
}
ManagerV2* WSUser::GetManager()
{
return ((WSServer*)m_server)->GetManger();
}
void WSUser::HandleCmd(const WSCmdParam* param)
{
assert(NULL != param && m_id == param->usrId);
std::string cmdData((const char*)param->data, param->size);
cJSON* json = cJSON_Parse(cmdData.c_str());
if (NULL != json)
{
std::string func = GetJsonStringValue(json, "func");
if ("set_global_config" == func)
{
}
else if ("get_global_config" == func)
{
}
else if ("load_local_image" == func)
{
}
cJSON_Delete(json);
}
}
void WSUser::HandleEvent(const WSEvtParam* param)
{
assert(NULL != param && m_id == param->usrId);
SendResponse(param->data, param->size, HGTRUE);
}
void WSUser::PostCmdMsg(const HGByte* data, HGUInt dataSize)
{
WSCmdParam* param = new WSCmdParam;
param->svr = (WSServer*)m_server;
param->usrId = m_id;
param->data = new HGByte[dataSize];
param->size = dataSize;
memcpy(param->data, data, dataSize);
HGMsg msg;
msg.id = MSGID_WS_COMMAND;
msg.data = param;
if (HGBASE_ERR_OK != HGBase_PostPumpMessage(m_server->GetMsgPump(), &msg))
{
delete[] param->data;
param->size = 0;
delete param;
}
}
void WSUser::PostEventMsg(const HGByte* data, HGUInt dataSize)
{
WSEvtParam* param = new WSEvtParam;
param->svr = (WSServer*)m_server;
param->usrId = m_id;
param->data = new HGByte[dataSize];
param->size = dataSize;
memcpy(param->data, data, dataSize);
HGMsg msg;
msg.id = MSGID_WS_EVENT;
msg.data = param;
if (HGBASE_ERR_OK != HGBase_PostPumpMessage(m_server->GetMsgPump(), &msg))
{
delete[] param->data;
param->size = 0;
delete param;
}
}
void WSUser::ThreadFunc()
{
HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "WSUser::ThreadFunc");
char chBuffer[2048];
const char* pBuffer = chBuffer;
int nBufferSize = 0;
bool bConnect = false;
unsigned char connectDataTail[4] = { '\r', '\n', '\r', '\n' };
unsigned int connectDataTailLen = 0;
std::string connectData;
uint8_t* pData = NULL;
int nDataSize = 0;
uint8_t* pDataEx = NULL;
int nRemainSize = 0;
uint8_t headData[20];
uint32_t nHeadDataLen = 0;
uint8_t vMask[4];
uint32_t nMaskCount = 0;
bool bHandle = false;
std::vector<uint8_t> vAllData;
while (1)
{
if (0 == nBufferSize)
{
int len = recv(m_sockConn, chBuffer, 2048, 0);
if (len <= 0)
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD><D8B1><EFBFBD>socketConn<6E><6E><EFBFBD><EFBFBD><EFBFBD>߿ͻ<DFBF><CDBB>˹ر<CBB9><D8B1><EFBFBD>socket<65><74><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͽ<EFBFBD>
PostDisConnectMsg();
break;
}
else
{
pBuffer = chBuffer;
nBufferSize = len;
}
}
assert(nBufferSize > 0);
if (!bConnect)
{
unsigned char b = *pBuffer;
++pBuffer;
--nBufferSize;
connectData.push_back(b);
if (b == connectDataTail[connectDataTailLen])
{
++connectDataTailLen;
}
else
{
connectDataTailLen = 0;
if (b == connectDataTail[connectDataTailLen])
{
++connectDataTailLen;
}
}
if (4 == connectDataTailLen)
{
connectDataTailLen = 0;
bool shakeRet = ShakeHand(connectData);
connectData.clear();
if (!shakeRet)
{
PostDisConnectMsg();
break;
}
bConnect = true;
}
}
else
{
if (NULL == pData)
{
assert(0 == nDataSize);
uint8_t b = *pBuffer;
++pBuffer;
--nBufferSize;
headData[nHeadDataLen] = b;
++nHeadDataLen;
if (1 == nHeadDataLen)
{
if ((0x80 | 0x08) == headData[0]) // <20>Ͽ<EFBFBD><CFBF><EFBFBD><EFBFBD><EFBFBD>
{
PostDisConnectMsg();
break;
}
else if ((0x80 | 0x09) == headData[0]) // PING֡
{
//
}
else if ((0x80 | 0x0A) == headData[0]) // PONG֡
{
//
}
else if ((0x00 | 0x01) == headData[0] || (0x00 | 0x02) == headData[0] || (0x00 | 0x00) == headData[0] || (0x80 | 0x00) == headData[0]
|| (0x80 | 0x01) == headData[0] || (0x80 | 0x02) == headData[0]) // <20><><EFBFBD><EFBFBD>֡
{
if ((0x80 | 0x00) == headData[0] || (0x80 | 0x01) == headData[0] || (0x80 | 0x02) == headData[0])
{
// <20><>Ƭ<EFBFBD><C6AC><EFBFBD><EFBFBD>
bHandle = true;
}
else
{
// <20><>Ƭ֡
bHandle = false;
}
}
else // ֡<><D6A1><EFBFBD>󣬶Ͽ<F3A3ACB6><CFBF><EFBFBD><EFBFBD><EFBFBD>
{
PostDisConnectMsg();
break;
}
}
else if (2 == nHeadDataLen)
{
if (0 == (headData[1] & 0x80)) // <20><><EFBFBD><EFBFBD><EBBEAD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EBB4A6>
{
PostDisConnectMsg();
break;
}
if ((0x80 | 0x09) == headData[0]) // PING֡
{
if (0x80 != headData[1])
{
PostDisConnectMsg();
break;
}
}
else if ((0x80 | 0x0A) == headData[0]) // PONG֡
{
if (0x80 != headData[1])
{
PostDisConnectMsg();
break;
}
}
else
{
if ((headData[1] & 0x7F) <= 125)
{
uint32_t nCmdSize = (headData[1] & 0x7F);
nHeadDataLen = 0;
if (0 == nCmdSize)
{
PostDisConnectMsg();
break;
}
nDataSize = nCmdSize;
nRemainSize = nCmdSize;
pData = new uint8_t[nDataSize];
pDataEx = pData;
}
}
}
else if (4 == nHeadDataLen)
{
if ((0x80 | 0x09) == headData[0]) // PING֡
{
//
}
else if ((0x80 | 0x0A) == headData[0]) // PONG֡
{
//
}
else
{
if ((headData[1] & 0x7F) == 126)
{
uint32_t nCmdSize = ntohs(*(uint16_t*)&headData[2]);
nHeadDataLen = 0;
if (0 == nCmdSize)
{
PostDisConnectMsg();
break;
}
nDataSize = nCmdSize;
nRemainSize = nCmdSize;
pData = new uint8_t[nDataSize];
pDataEx = pData;
}
}
}
else if (6 == nHeadDataLen)
{
if ((0x80 | 0x09) == headData[0]) // PING֡
{
nHeadDataLen = 0;
Pong();
}
else if ((0x80 | 0x0A) == headData[0]) // PONG֡
{
nHeadDataLen = 0;
}
}
else if (10 == nHeadDataLen)
{
if ((headData[1] & 0x7F) == 127) // <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>127
{
uint32_t nCmdSizeHigh = ntohl(*(uint32_t*)&headData[2]);
uint32_t nCmdSize = ntohl(*(uint32_t*)&headData[6]);
nHeadDataLen = 0;
if ((0 != nCmdSizeHigh) || (0 == nCmdSize))
{
PostDisConnectMsg();
break;
}
nDataSize = nCmdSize;
nRemainSize = nCmdSize;
pData = new uint8_t[nDataSize];
pDataEx = pData;
}
}
}
else
{
if (4 != nMaskCount)
{
uint8_t b = *pBuffer;
++pBuffer;
--nBufferSize;
vMask[nMaskCount] = b;
++nMaskCount;
}
else
{
int nWriteSize = HGMIN(nBufferSize, nRemainSize);
memcpy(pDataEx, pBuffer, nWriteSize);
pBuffer += nWriteSize;
nBufferSize -= nWriteSize;
pDataEx += nWriteSize;
nRemainSize -= nWriteSize;
if (0 == nRemainSize)
{
assert(pDataEx == pData + nDataSize);
for (int i = 0; i < nDataSize; ++i)
{
int j = i % 4;
pData[i] = pData[i] ^ vMask[j];
vAllData.push_back(pData[i]);
}
delete[] pData;
pData = NULL;
nDataSize = 0;
nMaskCount = 0;
if (bHandle)
{
PostCmdMsg(&vAllData[0], vAllData.size());
bHandle = false;
vAllData.clear();
}
}
}
}
}
}
if (NULL != pData)
{
delete[] pData;
pData = NULL;
nDataSize = 0;
nMaskCount = 0;
}
}
bool WSUser::ShakeHand(const std::string& head)
{
std::string requestMethod;
std::string requestURIPath;
HttpPairs requestURIQueryInfos;
std::string requestURIFragment;
std::string httpVersion;
HttpPairs headInfos;
HttpHead::AnalysisHead(head, requestMethod, requestURIPath, requestURIQueryInfos,
requestURIFragment, httpVersion, headInfos);
if ("Upgrade" != HttpHead::GetValue(headInfos, "Connection"))
return false;
if ("websocket" != HttpHead::GetValue(headInfos, "Upgrade"))
return false;
std::string key = HttpHead::GetValue(headInfos, "Sec-WebSocket-Key");
if (key.empty())
return false;
key += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
unsigned int message_digest[5];
SHA1 sha;
sha.Reset();
sha << key.c_str();
sha.Result(message_digest);
for (int i = 0; i < 5; ++i)
message_digest[i] = htonl(message_digest[i]);
std::string serverKey = base64_encode((const unsigned char*)message_digest, 20);
std::string handShakeResp = "HTTP/1.1 101 Switching Protocols\r\n";
handShakeResp += "Upgrade: websocket\r\n";
handShakeResp += "Connection: Upgrade\r\n";
handShakeResp += "Sec-WebSocket-Accept:";
handShakeResp += serverKey;
handShakeResp += "\r\n\r\n";
send(m_sockConn, handShakeResp.c_str(), (int)handShakeResp.length(), 0);
return true;
}
void WSUser::Pong()
{
uint8_t vHead[2];
vHead[0] = 0x80 | 0x0A;
vHead[1] = 0;
HGBase_EnterLock(m_cs);
send(m_sockConn, (const char*)vHead, 2, 0);
HGBase_LeaveLock(m_cs);
}
bool WSUser::SendResponse(const HGByte* data, HGUInt size, HGBool text)
{
if (NULL == data || 0 == size)
{
return false;
}
uint32_t nHeadLen = 0;
uint8_t vHead[20] = { 0 };
vHead[0] = text ? (0x80 | 0x01) : (0x80 | 0x02);
if (size <= 125)
{
vHead[1] = (uint8_t)size;
nHeadLen = 2;
}
else if (size <= 0xFFFF)
{
vHead[1] = 126;
uint16_t payloadLength16b = htons((uint16_t)size);
memcpy(&vHead[2], &payloadLength16b, 2);
nHeadLen = 4;
}
else
{
vHead[1] = 127;
vHead[2] = 0;
vHead[3] = 0;
vHead[4] = 0;
vHead[5] = 0;
uint32_t payloadLength32b = htonl(size);
memcpy(&vHead[6], &payloadLength32b, 4);
nHeadLen = 10;
}
HGBase_EnterLock(m_cs);
send(m_sockConn, (const char*)vHead, nHeadLen, 0);
send(m_sockConn, (const char*)data, size, 0);
HGBase_LeaveLock(m_cs);
return true;
}
}