code_app/sdk/webservice/WSUser.cpp

816 lines
19 KiB
C++
Raw Normal View History

#include "WSUser.h"
#include "WSServer.h"
#include "ManagerV2.h"
#include "base/HGInfo.h"
#include "cJSON.h"
#include "sha1.h"
#include "base64.h"
#include "HGString.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");
std::string iden = GetJsonStringValue(json, "iden");
if ("set_global_config" == func)
{
GlobalConfig cfg;
cfg.fileSavePath = Utf8ToStdString(GetJsonStringValue(json, "file_save_path"));
cfg.fileNamePrefix = Utf8ToStdString(GetJsonStringValue(json, "file_name_prefix"));
cfg.fileNameMode = GetJsonStringValue(json, "file_name_mode");
cfg.imageFormat = GetJsonStringValue(json, "image_format");
cfg.imageJpegQuality = GetJsonIntValue(json, "image_jpeg_quality");
cfg.imageTiffCompression = GetJsonStringValue(json, "image_tiff_compression");
cfg.imageTiffJpegQuality = GetJsonIntValue(json, "image_tiff_jpeg_quality");
cfg.uploadHttpHost = GetJsonStringValue(json, "upload_http_host");
cfg.uploadHttpPort = GetJsonIntValue(json, "upload_http_port");
cfg.uploadHttpPath = GetJsonStringValue(json, "upload_http_path");
cfg.uploadFtpUser = GetJsonStringValue(json, "upload_ftp_user");
cfg.uploadFtpPassword = GetJsonStringValue(json, "upload_ftp_password");
cfg.uploadFtpHost = GetJsonStringValue(json, "upload_ftp_host");
cfg.uploadFtpPort = GetJsonIntValue(json, "upload_ftp_port");
int ret = GetManager()->SetGlobalConfig(cfg);
std::string errInfo;
if (0 != ret)
errInfo = StdStringToUtf8("错误");
std::string fmt;
fmt += "{\"func\":\"%s\", ";
fmt += "\"iden\":\"%s\", ";
fmt += "\"ret\":%d, ";
fmt += "\"err_info\":\"%s\"}";
char resp[1024];
sprintf(resp, fmt.c_str(), func.c_str(), iden.c_str(), ret, errInfo.c_str());
SendResponse((const HGByte *)resp, (HGUInt)strlen(resp), HGTRUE);
}
else if ("get_global_config" == func)
{
GlobalConfig cfg;
int ret = GetManager()->GetGlobalConfig(cfg);
std::string errInfo;
if (0 != ret)
errInfo = StdStringToUtf8("错误");
std::string fmt;
fmt += "{\"func\":\"%s\", ";
fmt += "\"iden\":\"%s\", ";
fmt += "\"ret\":%d, ";
fmt += "\"err_info\":\"%s\", ";
fmt += "\"file_save_path\":\"%s\", ";
fmt += "\"file_name_prefix\":\"%s\", ";
fmt += "\"file_name_mode\":\"%s\", ";
fmt += "\"image_format\":\"%s\", ";
fmt += "\"image_jpeg_quality\":%d, ";
fmt += "\"image_tiff_compression\":\"%s\", ";
fmt += "\"image_tiff_jpeg_quality\":%d, ";
fmt += "\"upload_http_host\":\"%s\", ";
fmt += "\"upload_http_port\":%d, ";
fmt += "\"upload_http_path\":\"%s\", ";
fmt += "\"upload_ftp_user\":\"%s\", ";
fmt += "\"upload_ftp_password\":\"%s\", ";
fmt += "\"upload_ftp_host\":\"%s\", ";
fmt += "\"upload_ftp_port\":%d}";
char resp[1024];
sprintf(resp, fmt.c_str(), func.c_str(), iden.c_str(), ret, errInfo.c_str(), StdStringToUtf8(strToJson(cfg.fileSavePath)).c_str(),
StdStringToUtf8(strToJson(cfg.fileNamePrefix)).c_str(), cfg.fileNameMode.c_str(), cfg.imageFormat.c_str(), cfg.imageJpegQuality,
cfg.imageTiffCompression.c_str(), cfg.imageTiffJpegQuality, cfg.uploadHttpHost.c_str(), cfg.uploadHttpPort,
strToJson(cfg.uploadHttpPath).c_str(), cfg.uploadFtpUser.c_str(), cfg.uploadFtpPassword.c_str(), cfg.uploadFtpHost.c_str(),
cfg.uploadFtpPort);
SendResponse((const HGByte*)resp, (HGUInt)strlen(resp), HGTRUE);
}
else if ("load_local_image" == func)
{
}
else if ("init_device" == func)
{
int ret = GetManager()->InitDevice();
std::string errInfo;
if (0 != ret)
errInfo = StdStringToUtf8("错误");
std::string fmt;
fmt += "{\"func\":\"%s\", ";
fmt += "\"iden\":\"%s\", ";
fmt += "\"ret\":%d, ";
fmt += "\"err_info\":\"%s\"}";
char resp[1024];
sprintf(resp, fmt.c_str(), func.c_str(), iden.c_str(), ret, errInfo.c_str());
SendResponse((const HGByte*)resp, (HGUInt)strlen(resp), HGTRUE);
}
else if ("deinit_device" == func)
{
int ret = GetManager()->DeinitDevice();
std::string errInfo;
if (0 != ret)
errInfo = StdStringToUtf8("错误");
std::string fmt;
fmt += "{\"func\":\"%s\", ";
fmt += "\"iden\":\"%s\", ";
fmt += "\"ret\":%d, ";
fmt += "\"err_info\":\"%s\"}";
char resp[1024];
sprintf(resp, fmt.c_str(), func.c_str(), iden.c_str(), ret, errInfo.c_str());
SendResponse((const HGByte*)resp, (HGUInt)strlen(resp), HGTRUE);
}
else if ("get_device_name_list" == func)
{
std::vector<std::string> devNameList;
int ret = GetManager()->GetDeviceNameList(devNameList);
std::string errInfo;
if (0 != ret)
errInfo = StdStringToUtf8("错误");
std::string fmt;
fmt += "{\"func\":\"%s\", ";
fmt += "\"iden\":\"%s\", ";
fmt += "\"ret\":%d, ";
fmt += "\"err_info\":\"%s\", ";
fmt += "\"device_name_list\":%s}";
std::string nameList = "[";
for (int i = 0; i < (int)devNameList.size(); ++i)
{
nameList += "\"";
nameList += devNameList[i];
nameList += "\"";
if (i != (int)devNameList.size() - 1)
{
nameList += ", ";
}
}
nameList += "]";
char resp[1024];
sprintf(resp, fmt.c_str(), func.c_str(), iden.c_str(), ret, errInfo.c_str(), nameList.c_str());
SendResponse((const HGByte*)resp, (HGUInt)strlen(resp), HGTRUE);
}
else if ("open_device" == func)
{
std::string devName = GetJsonStringValue(json, "device_name");
int ret = GetManager()->OpenDevice(devName);
std::string errInfo;
if (0 != ret)
errInfo = StdStringToUtf8("错误");
std::string fmt;
fmt += "{\"func\":\"%s\", ";
fmt += "\"iden\":\"%s\", ";
fmt += "\"ret\":%d, ";
fmt += "\"err_info\":\"%s\"}";
char resp[1024];
sprintf(resp, fmt.c_str(), func.c_str(), iden.c_str(), ret, errInfo.c_str());
SendResponse((const HGByte*)resp, (HGUInt)strlen(resp), HGTRUE);
}
else if ("close_device" == func)
{
int ret = GetManager()->CloseDevice();
std::string errInfo;
if (0 != ret)
errInfo = StdStringToUtf8("错误");
std::string fmt;
fmt += "{\"func\":\"%s\", ";
fmt += "\"iden\":\"%s\", ";
fmt += "\"ret\":%d, ";
fmt += "\"err_info\":\"%s\"}";
char resp[1024];
sprintf(resp, fmt.c_str(), func.c_str(), iden.c_str(), ret, errInfo.c_str());
SendResponse((const HGByte*)resp, (HGUInt)strlen(resp), HGTRUE);
}
else if ("get_curr_device_name" == func)
{
std::string devName;
int ret = GetManager()->GetCurrDeviceName(devName);
std::string errInfo;
if (0 != ret)
errInfo = StdStringToUtf8("错误");
std::string fmt;
fmt += "{\"func\":\"%s\", ";
fmt += "\"iden\":\"%s\", ";
fmt += "\"ret\":%d, ";
fmt += "\"err_info\":\"%s\", ";
fmt += "\"device_name\":\"%s\"}";
char resp[1024];
sprintf(resp, fmt.c_str(), func.c_str(), iden.c_str(), ret, errInfo.c_str(), devName.c_str());
SendResponse((const HGByte*)resp, (HGUInt)strlen(resp), HGTRUE);
}
else if ("start_scan" == func)
{
int ret = GetManager()->StartScan();
std::string errInfo;
if (0 != ret)
errInfo = StdStringToUtf8("错误");
std::string fmt;
fmt += "{\"func\":\"%s\", ";
fmt += "\"iden\":\"%s\", ";
fmt += "\"ret\":%d, ";
fmt += "\"err_info\":\"%s\"}";
char resp[1024];
sprintf(resp, fmt.c_str(), func.c_str(), iden.c_str(), ret, errInfo.c_str());
SendResponse((const HGByte*)resp, (HGUInt)strlen(resp), HGTRUE);
}
else if ("stop_scan" == func)
{
int ret = GetManager()->StopScan();
std::string errInfo;
if (0 != ret)
errInfo = StdStringToUtf8("错误");
std::string fmt;
fmt += "{\"func\":\"%s\", ";
fmt += "\"iden\":\"%s\", ";
fmt += "\"ret\":%d, ";
fmt += "\"err_info\":\"%s\"}";
char resp[1024];
sprintf(resp, fmt.c_str(), func.c_str(), iden.c_str(), ret, errInfo.c_str());
SendResponse((const HGByte*)resp, (HGUInt)strlen(resp), HGTRUE);
}
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)
{
// 这里跳出可能是服务器关闭了socketConn或者客户端关闭了socket或者网络断开
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]) // 断开连接
{
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]) // 数据帧
{
if ((0x80 | 0x00) == headData[0] || (0x80 | 0x01) == headData[0] || (0x80 | 0x02) == headData[0])
{
// 分片结束
bHandle = true;
}
else
{
// 分片帧
bHandle = false;
}
}
else // 帧错误,断开连接
{
PostDisConnectMsg();
break;
}
}
else if (2 == nHeadDataLen)
{
if (0 == (headData[1] & 0x80)) // 必须经过掩码处理
{
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) // 这里一定会等于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], (HGUInt)vAllData.size());
bHandle = false;
vAllData.clear();
}
}
}
}
}
}
if (NULL != pData)
{
delete[] pData;
pData = NULL;
nDataSize = 0;
nMaskCount = 0;
}
}
std::string WSUser::strToJson(const std::string str)
{
std::string ret;
for (size_t i = 0; i < str.size(); i++)
{
char c = str[i];
switch (c)
{
case '\"':
ret.append("\\\"");
break;
case '\\':
ret.append("\\\\");
break;
case '/':
ret.append("\\/");
break;
case '\b':
ret.append("\\b");
break;
case '\f':
ret.append("\\f");
break;
case '\n':
ret.append("\\n");
break;
case '\r':
ret.append("\\r");
break;
case '\t':
ret.append("\\t");
break;
default:
ret.push_back(c);
}
}
return ret;
}
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;
}
}