code_app/sdk/webscan/WebUser.cpp

1416 lines
30 KiB
C++
Raw Permalink 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 "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;
m_dpi = 0;
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)
{
m_dpi = 0;
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)
{
m_dpi = 0;
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"));
cJSON_AddItemToObject(retJson, "code", cJSON_CreateString("0"));
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();
char str[10] = {0};
sprintf(str, "%d", i);
cJSON_AddItemToObject(js, "index", cJSON_CreateString(str));
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 = "错误";
int index = atoi(GetJsonStringValue(json, "arg").c_str());
HGBase_EnterLock(m_lockName);
if (index >= 0 && index < (int)m_devNameList.size())
{
if (m_devNameList[index] == m_devName)
{
code = 0;
result.clear();
}
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)
{
m_dpi = 0;
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();
}
}
}
HGBase_LeaveLock(m_lockName);
cJSON* retJson = cJSON_CreateObject();
if (NULL != retJson)
{
cJSON_AddItemToObject(retJson, "Func", cJSON_CreateString("SelectDevice"));
char str[10] = { 0 };
sprintf(str, "%d", code);
cJSON_AddItemToObject(retJson, "code", cJSON_CreateString(str));
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 = "错误";
int colorMode = atoi(GetJsonStringValue(json, "arg").c_str());
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"));
char str[10] = { 0 };
sprintf(str, "%d", code);
cJSON_AddItemToObject(retJson, "code", cJSON_CreateString(str));
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 = "错误";
int dpi = atoi(GetJsonStringValue(json, "arg").c_str());
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"));
char str[10] = { 0 };
sprintf(str, "%d", code);
cJSON_AddItemToObject(retJson, "code", cJSON_CreateString(str));
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 = "错误";
int duplexMode = atoi(GetJsonStringValue(json, "arg").c_str());
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"));
char str[10] = { 0 };
sprintf(str, "%d", code);
cJSON_AddItemToObject(retJson, "code", cJSON_CreateString(str));
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 = "错误";
int jpegQuality = atoi(GetJsonStringValue(json, "arg").c_str());
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"));
char str[10] = { 0 };
sprintf(str, "%d", code);
cJSON_AddItemToObject(retJson, "code", cJSON_CreateString(str));
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 = "错误";
int scanPage = atoi(GetJsonStringValue(json, "arg").c_str());
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"));
char str[10] = { 0 };
sprintf(str, "%d", code);
cJSON_AddItemToObject(retJson, "code", cJSON_CreateString(str));
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)
{
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"));
char str[10] = { 0 };
sprintf(str, "%d", code);
cJSON_AddItemToObject(retJson, "code", cJSON_CreateString(str));
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"));
char str[10] = { 0 };
sprintf(str, "%d", code);
cJSON_AddItemToObject(retJson, "code", cJSON_CreateString(str));
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))
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))
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))
ret = HGTRUE;
}
break;
}
}
return ret;
}
HGInt WebUser::GetDpi()
{
assert(NULL != m_devHandle);
HGInt dpi = 0;
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)
{
SANE_Int value = 0;
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;
}