code_app/sdk/webscan/WebUser.cpp

1416 lines
30 KiB
C++
Raw Normal View History

2022-09-06 08:27:58 +00:00
#include "WebUser.h"
#include "WebServer.h"
#include "base/HGInfo.h"
#include "base/HGBase64.h"
#include "base/HGImage.h"
#include "imgfmt/HGJpeg.h"
#include "sha1.h"
#include "base64.h"
#include "HGString.h"
static int GetJsonIntValue(cJSON* json, const std::string& key, bool* find = NULL)
{
int ret = 0;
if (NULL != find)
*find = false;
cJSON* p = json->child;
while (NULL != p)
{
if (0 == strcmp(p->string, key.c_str()))
{
if (p->type == cJSON_Number)
{
ret = p->valueint;
if (NULL != find)
*find = true;
}
break;
}
p = p->next;
}
return ret;
}
static double GetJsonDoubleValue(cJSON* json, const std::string& key, bool* find = NULL)
{
double ret = 0.0;
if (NULL != find)
*find = false;
cJSON* p = json->child;
while (NULL != p)
{
if (0 == strcmp(p->string, key.c_str()))
{
if (p->type == cJSON_Number)
{
ret = p->valuedouble;
if (NULL != find)
*find = true;
}
break;
}
p = p->next;
}
return ret;
}
static bool GetJsonBoolValue(cJSON* json, const std::string& key, bool* find = NULL)
{
bool ret = false;
if (NULL != find)
*find = false;
cJSON* p = json->child;
while (NULL != p)
{
if (0 == strcmp(p->string, key.c_str()))
{
if (p->type == cJSON_True || p->type == cJSON_False)
{
ret = (p->type == cJSON_True) ? true : false;
if (NULL != find)
*find = true;
}
break;
}
p = p->next;
}
return ret;
}
static std::string GetJsonStringValue(cJSON* json, const std::string& key, bool* find = NULL)
{
std::string ret;
if (NULL != find)
*find = false;
cJSON* p = json->child;
while (NULL != p)
{
if (0 == strcmp(p->string, key.c_str()))
{
if (p->type == cJSON_String)
{
ret = p->valuestring;
if (NULL != find)
*find = true;
}
break;
}
p = p->next;
}
return ret;
}
static std::vector<std::string> GetJsonStringListValue(cJSON* json, const std::string& key, bool* find = NULL)
{
std::vector<std::string> ret;
if (NULL != find)
*find = false;
cJSON* p = json->child;
while (NULL != p)
{
if (0 == strcmp(p->string, key.c_str()))
{
if (p->type == cJSON_Array)
{
cJSON* pEx = p->child;
while (NULL != pEx)
{
if (pEx->type == cJSON_String)
ret.push_back(pEx->valuestring);
pEx = pEx->next;
}
if (NULL != find)
*find = true;
}
break;
}
p = p->next;
}
return ret;
}
static std::vector<int> GetJsonIntListValue(cJSON* json, const std::string& key, bool* find = NULL)
{
std::vector<int> ret;
if (NULL != find)
*find = false;
cJSON* p = json->child;
while (NULL != p)
{
if (0 == strcmp(p->string, key.c_str()))
{
if (p->type == cJSON_Array)
{
cJSON* pEx = p->child;
while (NULL != pEx)
{
if (pEx->type == cJSON_Number)
ret.push_back(pEx->valueint);
pEx = pEx->next;
}
if (NULL != find)
*find = true;
}
break;
}
p = p->next;
}
return ret;
}
#if defined(HG_CMP_MSC)
WebUser::WebUser(WebServer* server, HGUInt id, HGMsgPump msgPump, const std::string& ip, uint16_t port, SOCKET sockConn)
#else
WebUser::WebUser(WebServer* server, HGUInt id, HGMsgPump msgPump, const std::string& ip, uint16_t port, int sockConn)
#endif
{
m_lock = NULL;
HGBase_CreateLock(&m_lock);
m_lockName = NULL;
HGBase_CreateLock(&m_lockName);
m_server = server;
m_id = id;
m_msgPump = msgPump;
m_ip = ip;
m_port = port;
m_sockConn = sockConn;
m_thread = NULL;
HGBase_OpenThread(ThreadFunc, this, &m_thread);
assert(NULL != m_thread);
m_jpgQuality = 80;
m_devNameList.clear();
m_devName.clear();
m_devHandle = NULL;
2023-02-27 07:05:40 +00:00
m_dpi = 0;
2022-09-06 08:27:58 +00:00
m_scanEvent = NULL;
SANE_Int version_code = 0;
sane_init_ex(&version_code, sane_ex_callback, this);
}
WebUser::~WebUser()
{
if (NULL != m_scanEvent)
{
assert(NULL != m_devHandle);
sane_cancel(m_devHandle);
HGBase_WaitEvent(m_scanEvent);
HGBase_DestroyEvent(m_scanEvent);
m_scanEvent = NULL;
}
if (NULL != m_devHandle)
{
2023-02-27 07:05:40 +00:00
m_dpi = 0;
2022-09-06 08:27:58 +00:00
sane_close(m_devHandle);
m_devHandle = NULL;
m_devName.clear();
}
sane_exit();
#if defined(HG_CMP_MSC)
closesocket(m_sockConn);
m_sockConn = INVALID_SOCKET;
#else
close(m_sockConn);
m_sockConn = -1;
#endif
HGBase_CloseThread(m_thread);
m_thread = NULL;
m_port = 0;
m_ip.clear();
m_msgPump = NULL;
m_id = 0;
m_server = NULL;
HGBase_DestroyLock(m_lockName);
m_lockName = NULL;
HGBase_DestroyLock(m_lock);
m_lock = NULL;
}
HGUInt WebUser::GetId()
{
return m_id;
}
void WebUser::CloseDev(const CloseDevParam* param)
{
assert(NULL != param && m_id == param->usrId);
if (m_devName == param->devName)
{
if (NULL != m_scanEvent)
{
assert(NULL != m_devHandle);
sane_cancel(m_devHandle);
HGBase_WaitEvent(m_scanEvent);
HGBase_DestroyEvent(m_scanEvent);
m_scanEvent = NULL;
}
if (NULL != m_devHandle)
{
2023-02-27 07:05:40 +00:00
m_dpi = 0;
2022-09-06 08:27:58 +00:00
sane_close(m_devHandle);
m_devHandle = NULL;
m_devName.clear();
}
}
}
void WebUser::ScanFinish(const ScanFinishParam* param)
{
assert(NULL != param && m_id == param->usrId);
if (NULL != m_scanEvent)
{
assert(NULL != m_devHandle);
sane_cancel(m_devHandle);
HGBase_WaitEvent(m_scanEvent);
HGBase_DestroyEvent(m_scanEvent);
m_scanEvent = NULL;
}
}
void WebUser::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 ("GetDeviceList" == func)
{
GetDeviceList(json);
}
else if ("SelectDevice" == func)
{
SelectDevice(json);
}
else if ("SetScanColorType" == func)
{
SetScanColorType(json);
}
else if ("SetDPI" == func)
{
SetDPI(json);
}
else if ("SetDuplex" == func)
{
SetDuplex(json);
}
else if ("SetScanJPGQuality" == func)
{
SetScanJPGQuality(json);
}
else if ("StartScan" == func)
{
StartScan(json);
}
cJSON_Delete(json);
}
}
void WebUser::HandleEvent(const WSEvtParam* param)
{
assert(NULL != param && m_id == param->usrId);
SendResponse(param->data, param->size, HGTRUE);
}
void WebUser::GetDeviceList(cJSON* json)
{
assert(NULL != json);
cJSON* retJson = cJSON_CreateObject();
if (NULL != retJson)
{
cJSON_AddItemToObject(retJson, "Func", cJSON_CreateString("GetDeviceList"));
2022-09-07 05:57:28 +00:00
cJSON_AddItemToObject(retJson, "code", cJSON_CreateString("0"));
2022-09-06 08:27:58 +00:00
cJSON* array = cJSON_CreateArray();
cJSON_AddItemToObject(retJson, "result", array);
HGBase_EnterLock(m_lockName);
for (int i = 0; i < (int)m_devNameList.size(); ++i)
{
cJSON* js = cJSON_CreateObject();
2022-09-07 05:57:28 +00:00
char str[10] = {0};
sprintf(str, "%d", i);
cJSON_AddItemToObject(js, "index", cJSON_CreateString(str));
2022-09-06 08:27:58 +00:00
cJSON_AddItemToObject(js, "name", cJSON_CreateString(m_devNameList[i].c_str()));
cJSON_AddItemToArray(array, js);
}
HGBase_LeaveLock(m_lockName);
char* resp = cJSON_Print(retJson);
if (NULL != resp)
{
SendResponse((const HGByte*)resp, (HGUInt)strlen(resp), HGTRUE);
free(resp);
}
cJSON_Delete(retJson);
}
}
void WebUser::SelectDevice(cJSON* json)
{
assert(NULL != json);
int code = -1;
std::string result = "错误";
2022-09-07 05:57:28 +00:00
int index = atoi(GetJsonStringValue(json, "arg").c_str());
2022-09-06 08:27:58 +00:00
HGBase_EnterLock(m_lockName);
if (index >= 0 && index < (int)m_devNameList.size())
{
2022-09-07 02:51:14 +00:00
if (m_devNameList[index] == m_devName)
2022-09-06 08:27:58 +00:00
{
code = 0;
result.clear();
}
2022-09-07 02:51:14 +00:00
else
{
if (NULL != m_scanEvent)
{
assert(NULL != m_devHandle);
sane_cancel(m_devHandle);
HGBase_WaitEvent(m_scanEvent);
HGBase_DestroyEvent(m_scanEvent);
m_scanEvent = NULL;
}
if (NULL != m_devHandle)
{
2023-02-27 07:05:40 +00:00
m_dpi = 0;
2022-09-07 02:51:14 +00:00
sane_close(m_devHandle);
m_devHandle = NULL;
m_devName.clear();
}
SANE_Handle dev = NULL;
SANE_Status status = sane_open(m_devNameList[index].c_str(), &dev);
if (SANE_STATUS_GOOD == status)
{
m_devName = m_devNameList[index];
m_devHandle = dev;
m_dpi = GetDpi();
code = 0;
result.clear();
}
}
2022-09-06 08:27:58 +00:00
}
HGBase_LeaveLock(m_lockName);
cJSON* retJson = cJSON_CreateObject();
if (NULL != retJson)
{
cJSON_AddItemToObject(retJson, "Func", cJSON_CreateString("SelectDevice"));
2022-09-07 05:57:28 +00:00
char str[10] = { 0 };
sprintf(str, "%d", code);
cJSON_AddItemToObject(retJson, "code", cJSON_CreateString(str));
2022-09-06 08:27:58 +00:00
cJSON_AddItemToObject(retJson, "result", cJSON_CreateString(StdStringToUtf8(result).c_str()));
char* resp = cJSON_Print(retJson);
if (NULL != resp)
{
SendResponse((const HGByte*)resp, (HGUInt)strlen(resp), HGTRUE);
free(resp);
}
cJSON_Delete(retJson);
}
}
void WebUser::SetScanColorType(cJSON* json)
{
assert(NULL != json);
int code = -1;
std::string result = "错误";
2022-09-07 05:57:28 +00:00
int colorMode = atoi(GetJsonStringValue(json, "arg").c_str());
2022-09-06 08:27:58 +00:00
if (NULL != m_devHandle && NULL == m_scanEvent && colorMode >= 1 && colorMode <= 3)
{
const char* colorModeStr = OPTION_VALUE_YSMS_24WCS;
if (2 == colorMode)
colorModeStr = OPTION_VALUE_YSMS_256JHD;
else if (3 == colorMode)
colorModeStr = OPTION_VALUE_YSMS_HB;
if (SetParam(OPTION_TITLE_YSMS, colorModeStr))
{
code = 0;
result.clear();
}
}
cJSON* retJson = cJSON_CreateObject();
if (NULL != retJson)
{
cJSON_AddItemToObject(retJson, "Func", cJSON_CreateString("SetScanColorType"));
2022-09-07 05:57:28 +00:00
char str[10] = { 0 };
sprintf(str, "%d", code);
cJSON_AddItemToObject(retJson, "code", cJSON_CreateString(str));
2022-09-06 08:27:58 +00:00
cJSON_AddItemToObject(retJson, "result", cJSON_CreateString(StdStringToUtf8(result).c_str()));
char* resp = cJSON_Print(retJson);
if (NULL != resp)
{
SendResponse((const HGByte*)resp, (HGUInt)strlen(resp), HGTRUE);
free(resp);
}
cJSON_Delete(retJson);
}
}
void WebUser::SetDPI(cJSON* json)
{
assert(NULL != json);
int code = -1;
std::string result = "错误";
2022-09-07 05:57:28 +00:00
int dpi = atoi(GetJsonStringValue(json, "arg").c_str());
2022-09-06 08:27:58 +00:00
if (NULL != m_devHandle && NULL == m_scanEvent && dpi > 0)
{
if (SetParam(OPTION_TITLE_FBL, &dpi))
{
m_dpi = dpi;
code = 0;
result.clear();
}
}
cJSON* retJson = cJSON_CreateObject();
if (NULL != retJson)
{
cJSON_AddItemToObject(retJson, "Func", cJSON_CreateString("SetDPI"));
2022-09-07 05:57:28 +00:00
char str[10] = { 0 };
sprintf(str, "%d", code);
cJSON_AddItemToObject(retJson, "code", cJSON_CreateString(str));
2022-09-06 08:27:58 +00:00
cJSON_AddItemToObject(retJson, "result", cJSON_CreateString(StdStringToUtf8(result).c_str()));
char* resp = cJSON_Print(retJson);
if (NULL != resp)
{
SendResponse((const HGByte*)resp, (HGUInt)strlen(resp), HGTRUE);
free(resp);
}
cJSON_Delete(retJson);
}
}
void WebUser::SetDuplex(cJSON* json)
{
assert(NULL != json);
int code = -1;
std::string result = "错误";
2022-09-07 05:57:28 +00:00
int duplexMode = atoi(GetJsonStringValue(json, "arg").c_str());
2022-09-06 08:27:58 +00:00
if (NULL != m_devHandle && NULL == m_scanEvent && duplexMode >= 0 && duplexMode <= 1)
{
const char* duplexModeStr = OPTION_VALUE_SMYM_DM;
if (1 == duplexMode)
duplexModeStr = OPTION_VALUE_SMYM_SM;
if (SetParam(OPTION_TITLE_SMYM, duplexModeStr))
{
code = 0;
result.clear();
}
}
cJSON* retJson = cJSON_CreateObject();
if (NULL != retJson)
{
cJSON_AddItemToObject(retJson, "Func", cJSON_CreateString("SetDuplex"));
2022-09-07 05:57:28 +00:00
char str[10] = { 0 };
sprintf(str, "%d", code);
cJSON_AddItemToObject(retJson, "code", cJSON_CreateString(str));
2022-09-06 08:27:58 +00:00
cJSON_AddItemToObject(retJson, "result", cJSON_CreateString(StdStringToUtf8(result).c_str()));
char* resp = cJSON_Print(retJson);
if (NULL != resp)
{
SendResponse((const HGByte*)resp, (HGUInt)strlen(resp), HGTRUE);
free(resp);
}
cJSON_Delete(retJson);
}
}
void WebUser::SetScanJPGQuality(cJSON* json)
{
assert(NULL != json);
int code = -1;
std::string result = "错误";
2022-09-07 05:57:28 +00:00
int jpegQuality = atoi(GetJsonStringValue(json, "arg").c_str());
2022-09-06 08:27:58 +00:00
if (NULL == m_scanEvent && jpegQuality >= 0 && jpegQuality <= 100)
{
m_jpgQuality = jpegQuality;
code = 0;
result.clear();
}
cJSON* retJson = cJSON_CreateObject();
if (NULL != retJson)
{
cJSON_AddItemToObject(retJson, "Func", cJSON_CreateString("SetScanJPGQuality"));
2022-09-07 05:57:28 +00:00
char str[10] = { 0 };
sprintf(str, "%d", code);
cJSON_AddItemToObject(retJson, "code", cJSON_CreateString(str));
2022-09-06 08:27:58 +00:00
cJSON_AddItemToObject(retJson, "result", cJSON_CreateString(StdStringToUtf8(result).c_str()));
char* resp = cJSON_Print(retJson);
if (NULL != resp)
{
SendResponse((const HGByte*)resp, (HGUInt)strlen(resp), HGTRUE);
free(resp);
}
cJSON_Delete(retJson);
}
}
void WebUser::StartScan(cJSON* json)
{
assert(NULL != json);
int code = -1;
std::string result = "错误";
2022-09-07 05:57:28 +00:00
int scanPage = atoi(GetJsonStringValue(json, "arg").c_str());
2022-09-06 08:27:58 +00:00
if (NULL != m_devHandle && NULL == m_scanEvent && scanPage >= 0)
{
if (0 == scanPage)
{
SetParam(OPTION_TITLE_SMZS, OPTION_VALUE_SMZS_LXSM);
}
else
{
SetParam(OPTION_TITLE_SMZS, OPTION_VALUE_SMZS_SMZDZS);
SetParam(OPTION_TITLE_SMSL, &scanPage);
}
HGBase_CreateEvent(HGFALSE, HGFALSE, &m_scanEvent);
assert(NULL != m_scanEvent);
SANE_Status status = sane_start(m_devHandle);
if (SANE_STATUS_GOOD == status)
{
code = 0;
result.clear();
}
else
{
HGBase_DestroyEvent(m_scanEvent);
m_scanEvent = NULL;
}
}
cJSON* retJson = cJSON_CreateObject();
if (NULL != retJson)
{
cJSON_AddItemToObject(retJson, "Func", cJSON_CreateString("StartScan"));
2022-09-07 05:57:28 +00:00
char str[10] = { 0 };
sprintf(str, "%d", code);
cJSON_AddItemToObject(retJson, "code", cJSON_CreateString(str));
2022-09-06 08:27:58 +00:00
cJSON_AddItemToObject(retJson, "result", cJSON_CreateString(StdStringToUtf8(result).c_str()));
char* resp = cJSON_Print(retJson);
if (NULL != resp)
{
SendResponse((const HGByte*)resp, (HGUInt)strlen(resp), HGTRUE);
free(resp);
}
cJSON_Delete(retJson);
}
}
void WebUser::PostDisConnectMsg()
{
DisConnectParam* param = new DisConnectParam;
param->svr = m_server;
param->usrId = m_id;
HGMsg msg;
msg.id = MSGID_DISCONNECT;
msg.data = param;
if (HGBASE_ERR_OK != HGBase_PostPumpMessage(m_msgPump, &msg))
{
delete param;
}
}
void WebUser::PostCmdMsg(const HGByte* data, HGUInt dataSize)
{
WSCmdParam* param = new WSCmdParam;
param->svr = 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_msgPump, &msg))
{
delete[] param->data;
param->size = 0;
delete param;
}
}
void WebUser::PostEventMsg(const HGByte* data, HGUInt dataSize)
{
WSEvtParam* param = new WSEvtParam;
param->svr = 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_msgPump, &msg))
{
delete[] param->data;
param->size = 0;
delete param;
}
}
void HGAPI WebUser::ThreadFunc(HGThread thread, HGPointer param)
2022-09-06 08:27:58 +00:00
{
WebUser* p = (WebUser*)param;
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(p->m_sockConn, chBuffer, 2048, 0);
if (len <= 0)
{
// 这里跳出可能是服务器关闭了socketConn或者客户端关闭了socket或者网络断开
p->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 = p->ShakeHand(connectData);
connectData.clear();
if (!shakeRet)
{
p->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]) // 断开连接
{
p->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 // 帧错误,断开连接
{
p->PostDisConnectMsg();
break;
}
}
else if (2 == nHeadDataLen)
{
if (0 == (headData[1] & 0x80)) // 必须经过掩码处理
{
p->PostDisConnectMsg();
break;
}
if ((0x80 | 0x09) == headData[0]) // PING帧
{
if (0x80 != headData[1])
{
p->PostDisConnectMsg();
break;
}
}
else if ((0x80 | 0x0A) == headData[0]) // PONG帧
{
if (0x80 != headData[1])
{
p->PostDisConnectMsg();
break;
}
}
else
{
if ((headData[1] & 0x7F) <= 125)
{
uint32_t nCmdSize = (headData[1] & 0x7F);
nHeadDataLen = 0;
if (0 == nCmdSize)
{
p->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)
{
p->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;
p->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))
{
p->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)
{
p->PostCmdMsg(&vAllData[0], (HGUInt)vAllData.size());
bHandle = false;
vAllData.clear();
}
}
}
}
}
}
if (NULL != pData)
{
delete[] pData;
pData = NULL;
nDataSize = 0;
nMaskCount = 0;
}
}
int WebUser::sane_ex_callback(SANE_Handle hdev, int code, void* data, unsigned int* len, void* param)
{
(void)hdev;
(void)len;
WebUser* p = (WebUser*)param;
switch (code)
{
case SANE_EVENT_DEVICE_ARRIVED:
{
SANE_Device* sane_dev = (SANE_Device*)data;
HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "SANE_EVENT_DEVICE_ARRIVED, name=%s", Utf8ToStdString(sane_dev->name).c_str());
HGBase_EnterLock(p->m_lockName);
p->m_devNameList.push_back(sane_dev->name);
HGBase_LeaveLock(p->m_lockName);
}
break;
case SANE_EVENT_DEVICE_LEFT:
{
SANE_Device* sane_dev = (SANE_Device*)data;
HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "SANE_EVENT_DEVICE_LEFT, name=%s", Utf8ToStdString(sane_dev->name).c_str());
CloseDevParam* closeDevParam = new CloseDevParam;
closeDevParam->svr = p->m_server;
closeDevParam->usrId = p->m_id;
closeDevParam->devName = sane_dev->name;
HGMsg msg;
msg.id = MSGID_CLOSE_DEVICE;
msg.data = closeDevParam;
if (HGBASE_ERR_OK != HGBase_PostPumpMessage(p->m_msgPump, &msg))
{
delete closeDevParam;
}
HGBase_EnterLock(p->m_lockName);
for (int i = 0; i < (int)p->m_devNameList.size(); ++i)
{
if (0 == strcmp(sane_dev->name, p->m_devNameList[i].c_str()))
{
p->m_devNameList.erase(p->m_devNameList.begin() + i);
break;
}
}
HGBase_LeaveLock(p->m_lockName);
}
break;
case SANE_EVENT_WORKING:
{
HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "SANE_EVENT_WORKING, msg=%s", Utf8ToStdString((char*)data).c_str());
}
break;
case SANE_EVENT_SCAN_FINISHED:
{
HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "SANE_EVENT_SCAN_FINISHED, msg=%s", Utf8ToStdString((char*)data).c_str());
HGBase_SetEvent(p->m_scanEvent);
ScanFinishParam* scanFinishParam = new ScanFinishParam;
scanFinishParam->svr = p->m_server;
scanFinishParam->usrId = p->m_id;
HGMsg msg;
msg.id = MSGID_SCAN_FINISH;
msg.data = scanFinishParam;
if (HGBASE_ERR_OK != HGBase_PostPumpMessage(p->m_msgPump, &msg))
{
delete scanFinishParam;
}
int code = 0;
std::string result = "";
cJSON* retJson = cJSON_CreateObject();
if (NULL != retJson)
{
cJSON_AddItemToObject(retJson, "Func", cJSON_CreateString("ScanComplete"));
2022-09-07 05:57:28 +00:00
char str[10] = { 0 };
sprintf(str, "%d", code);
cJSON_AddItemToObject(retJson, "code", cJSON_CreateString(str));
2022-09-06 08:27:58 +00:00
cJSON_AddItemToObject(retJson, "result", cJSON_CreateString(StdStringToUtf8(result).c_str()));
char* resp = cJSON_Print(retJson);
if (NULL != resp)
{
p->PostEventMsg((const HGByte*)resp, (HGUInt)strlen(resp));
free(resp);
}
cJSON_Delete(retJson);
}
}
break;
case SANE_EVENT_STATUS:
{
HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "SANE_EVENT_STATUS, msg=%s", Utf8ToStdString((char*)data).c_str());
}
break;
case SANE_EVENT_ERROR:
{
HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "SANE_EVENT_ERROR, msg=%s", Utf8ToStdString((char*)data).c_str());
}
break;
case SANE_EVENT_IMAGE_OK:
{
HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "SANE_EVENT_IMAGE_OK");
SANE_Image* sane_img = (SANE_Image*)data;
HGUInt imgType = 0;
if (sane_img->header.format == SANE_FRAME_GRAY)
{
if (1 == sane_img->header.depth)
imgType = HGBASE_IMGTYPE_BINARY;
else if (8 == sane_img->header.depth)
imgType = HGBASE_IMGTYPE_GRAY;
}
else if (sane_img->header.format == SANE_FRAME_RGB)
imgType = HGBASE_IMGTYPE_RGB;
HGByte* data = sane_img->data;
HGImageInfo imgInfo = { (HGUInt)sane_img->header.pixels_per_line, (HGUInt)sane_img->header.lines,
imgType, (HGUInt)sane_img->header.bytes_per_line, HGBASE_IMGORIGIN_TOP };
HGImage img = NULL;
HGBase_CreateImageFromData(data, &imgInfo, NULL, 0, HGBASE_IMGORIGIN_TOP, &img);
if (NULL != img)
{
HGBase_SetImageDpi(img, p->m_dpi, p->m_dpi);
int code = 0;
std::string result = p->GetBase64(img);
cJSON* retJson = cJSON_CreateObject();
if (NULL != retJson)
{
cJSON_AddItemToObject(retJson, "Func", cJSON_CreateString("ImageSaveDone"));
2022-09-07 05:57:28 +00:00
char str[10] = { 0 };
sprintf(str, "%d", code);
cJSON_AddItemToObject(retJson, "code", cJSON_CreateString(str));
2022-09-06 08:27:58 +00:00
cJSON_AddItemToObject(retJson, "result", cJSON_CreateString(StdStringToUtf8(result).c_str()));
char* resp = cJSON_Print(retJson);
if (NULL != resp)
{
p->PostEventMsg((const HGByte*)resp, (HGUInt)strlen(resp));
free(resp);
}
cJSON_Delete(retJson);
}
HGBase_DestroyImage(img);
}
}
break;
}
return 0;
}
std::string WebUser::GetBase64(HGImage image)
{
std::string ret;
if (NULL != image)
{
HGUInt xDpi, yDpi;
HGBase_GetImageDpi(image, &xDpi, &yDpi);
HGBuffer buffer = NULL;
HGJpegSaveInfo saveInfo;
saveInfo.densityUnit = HGIMGFMT_JPEGDENUNIT_INCH;
saveInfo.xDensity = xDpi;
saveInfo.yDensity = yDpi;
saveInfo.quality = m_jpgQuality;
HGImgFmt_SaveJpegImageToBuffer(image, &saveInfo, &buffer);
if (NULL != buffer)
{
HGByte* data = NULL;
HGBase_GetBufferData(buffer, &data);
HGUSize size = 0;
HGBase_GetBufferSize(buffer, &size);
HGSize base64Size = 0;
HGBase_Base64Encode(data, size, NULL, &base64Size);
HGByte* base64 = new HGByte[base64Size + 1];
HGBase_Base64Encode(data, size, base64, &base64Size);
base64[base64Size] = 0;
ret = (const char *)base64;
delete[] base64;
HGBase_DestroyBuffer(buffer);
}
}
return ret;
}
HGBool WebUser::SetParam(const char* optionName, const HGVoid* data)
{
assert(NULL != m_devHandle);
if (NULL == data || NULL == optionName)
return HGFALSE;
HGBool ret = HGFALSE;
SANE_Int num_dev_options = 0;
sane_control_option(m_devHandle, 0, SANE_ACTION_GET_VALUE, &num_dev_options, NULL);
for (int i = 1; i < num_dev_options; ++i)
{
const SANE_Option_Descriptor* desp = sane_get_option_descriptor(m_devHandle, i);
if (NULL == desp)
continue;
const char* name = desp->title;
while (' ' == *name)
++name;
if (0 == strcmp(optionName, name))
{
if (SANE_TYPE_STRING == desp->type)
{
SANE_Char* value = (SANE_Char*)((HGChar*)data);
if (NULL != value)
{
if (SANE_STATUS_GOOD == sane_control_option(m_devHandle, i, SANE_ACTION_SET_VALUE, value, NULL))
ret = HGTRUE;
}
}
else if (SANE_TYPE_INT == desp->type)
{
SANE_Int value = (SANE_Int)(*(HGInt*)data);
if (SANE_STATUS_GOOD == sane_control_option(m_devHandle, i, SANE_ACTION_SET_VALUE, &value, NULL))
2022-09-06 08:27:58 +00:00
ret = HGTRUE;
}
else if (SANE_TYPE_FIXED == desp->type)
{
SANE_Fixed value = SANE_FIX(*(HGDouble*)data);
if (SANE_STATUS_GOOD == sane_control_option(m_devHandle, i, SANE_ACTION_SET_VALUE, &value, NULL))
2022-09-06 08:27:58 +00:00
ret = HGTRUE;
}
else if (SANE_TYPE_BOOL == desp->type)
{
SANE_Bool value = (SANE_Bool)(*(HGBool*)data);
if (SANE_STATUS_GOOD == sane_control_option(m_devHandle, i, SANE_ACTION_SET_VALUE, &value, NULL))
2022-09-06 08:27:58 +00:00
ret = HGTRUE;
}
break;
}
}
return ret;
}
HGInt WebUser::GetDpi()
{
assert(NULL != m_devHandle);
2023-02-27 07:05:40 +00:00
HGInt dpi = 0;
2022-09-06 08:27:58 +00:00
SANE_Int num_dev_options = 0;
sane_control_option(m_devHandle, 0, SANE_ACTION_GET_VALUE, &num_dev_options, NULL);
for (int i = 1; i < num_dev_options; ++i)
{
const SANE_Option_Descriptor* desp = sane_get_option_descriptor(m_devHandle, i);
if (NULL == desp)
continue;
const char* name = desp->title;
while (' ' == *name)
++name;
if (0 == strcmp(OPTION_TITLE_FBL, name))
{
if (SANE_TYPE_INT == desp->type)
{
2023-02-27 07:05:40 +00:00
SANE_Int value = 0;
2022-09-06 08:27:58 +00:00
sane_control_option(m_devHandle, i, SANE_ACTION_GET_VALUE, &value, NULL);
dpi = value;
}
break;
}
}
return dpi;
}
bool WebUser::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);
HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, head.c_str());
//if (std::string::npos == HttpHead::GetValue(headInfos, "Connection").find("Upgrade"))
// 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 WebUser::Pong()
{
uint8_t vHead[2];
vHead[0] = 0x80 | 0x0A;
vHead[1] = 0;
HGBase_EnterLock(m_lock);
send(m_sockConn, (const char*)vHead, 2, 0);
HGBase_LeaveLock(m_lock);
}
bool WebUser::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_lock);
send(m_sockConn, (const char*)vHead, nHeadLen, 0);
send(m_sockConn, (const char*)data, size, 0);
HGBase_LeaveLock(m_lock);
return true;
}