#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 GetJsonStringListValue(cJSON* json, const std::string& key, bool* find = NULL) { std::vector 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 GetJsonIntListValue(cJSON* json, const std::string& key, bool* find = NULL) { std::vector 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 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; }