#include "stdafx.h" #include "IOCPServer.h" #include "ServerSocketItem.h" #include "WebServerDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #endif #define PACKET_SIZE 4096 #define BUFFER_OVERFLOW 8192 #define REQUEST_METHOD_POST 0 #define REQUEST_METHOD_GET 1 CServerSocketItem::CServerSocketItem(WORD id, WORD socket, DWORD dwClientAddr, CIOCPServer* pIOCPServer, IClientSocket* pClientSocket) : CTCPSocket(id, socket, dwClientAddr, pIOCPServer) { m_pClientSocket = pClientSocket; } CServerSocketItem::~CServerSocketItem() { } bool CServerSocketItem::Close() { m_pIOCPServer->Disconnect(getID()); return true; } bool CServerSocketItem::processRecvData(void* data, DWORD len) { // [Trace] log raw incoming data if (data != NULL && len > 0 && len != (DWORD)SOCKET_ERROR) { int nTraceLen = (len > 200) ? 200 : (int)len; CString strRaw((LPCSTR)data, nTraceLen); strRaw.Replace(_T("\r"), _T("")); strRaw.Replace(_T("\n"), _T(" | ")); CString strLog; strLog.Format(_T("[WebGate] Recv len=%d, head=[%s]"), len, strRaw); CTraceService::TraceString(strLog, TraceLevel_Normal); } switch (len) { case 0: SendResult(_T("{\"result\":%d}"), 1); break; case SOCKET_ERROR: if (GetLastError() != WSAEWOULDBLOCK) { TCHAR szError[256]; _tprintf_s(szError, sizeof(szError), _T("ERROR in OnReceive(): %d"), GetLastError()); SaveLog(_T("%s"), szError, TraceLevel_Exception); } break; default: if (len != SOCKET_ERROR && len != 0) { try { // Filter non-HTTP data (TLS handshake / binary protocol) BYTE cbFirstByte = ((LPBYTE)data)[0]; if (cbFirstByte == 0x16 || cbFirstByte == 0x15 || cbFirstByte == 0x00) { CString strLog; strLog.Format(_T("[WebGate] Non-HTTP data (first=0x%02X, len=%d), rejected"), cbFirstByte, len); CTraceService::TraceString(strLog, TraceLevel_Warning); SendResult(_T("{\"result\":%d}"), 1); break; } if ( false==m_ParseData.ParseRequests((LPBYTE)data, len) ) { CString strLog; strLog.Format(_T("[WebGate] ParseRequests failed, len=%d"), len); CTraceService::TraceString(strLog, TraceLevel_Exception); SendResult(_T("{\"result\":%d}"), 1); break; } m_ParseData.ProcessRequests(); CString strUrl; m_ParseData.GetServerVariable(_T("script_name"), strUrl); // [Trace] log parsed request info { CString strLog; strLog.Format(_T("[WebGate] Parsed: method=%d, url=[%s], query=[%s], form=[%s]"), m_ParseData.GetRequestMethod(), strUrl, m_ParseData.m_QueryParams, m_ParseData.m_FormVars); CTraceService::TraceString(strLog, TraceLevel_Normal); } if ( strUrl.Compare(_T("/active.do"))==0 ) { bool bRet = ExecuteRequest(); if ( bRet ) break; // [Trace] ExecuteRequest returned false { CString strLog; strLog.Format(_T("[WebGate] ExecuteRequest failed, url=[%s], query=[%s], form=[%s]"), strUrl, m_ParseData.m_QueryParams, m_ParseData.m_FormVars); CTraceService::TraceString(strLog, TraceLevel_Exception); } } else { // [Trace] URL does not match /active.do { CString strLog; strLog.Format(_T("[WebGate] URL mismatch: got=[%s] (len=%d), expected=[/active.do]"), strUrl, strUrl.GetLength()); CTraceService::TraceString(strLog, TraceLevel_Exception); } SendResult(_T("{\"result\":%d}"), 1); if ( strUrl == _T("/favicon.ico") ) break; } CTraceService::TraceString(_T("Request URL error: ") + strUrl, TraceLevel_Exception); } catch(...) { SendResult(_T("{\"result\":%d}"), 1); throw ; } } break; } return true; } bool CServerSocketItem::ExecuteRequest() { int nRequestMethod = m_ParseData.GetRequestMethod(); if (REQUEST_METHOD_POST == nRequestMethod) { m_ParseData.ParseQueryString(m_ParseData.m_FormVars); SaveLog(_T("%s"), m_ParseData.m_FormVars); } else { m_ParseData.ParseQueryString(m_ParseData.m_QueryParams); SaveLog(_T("%s"), m_ParseData.m_QueryParams); } CString strWay; m_ParseData.GetQueryString(_T("way"), strWay); int nWay = _ttoi(strWay.GetBuffer()); // [Trace] log way parameter { CString strLog; strLog.Format(_T("[WebGate] ExecuteRequest: way=%d (raw=[%s]), method=%d"), nWay, strWay, nRequestMethod); CTraceService::TraceString(strLog, TraceLevel_Normal); } switch(nWay) { case eWebNull: case eWebCardLib: { CTraceService::TraceString(_T("[WebGate] -> WebSetCardLibRequest"), TraceLevel_Normal); WebSetCardLibRequest(); break; } case eWebCheatUser: { CTraceService::TraceString(_T("[WebGate] -> WebSetCheatUserRequest"), TraceLevel_Normal); WebSetCheatUserRequest(); break; } case eWebCardLibGlobalCfg: { CTraceService::TraceString(_T("[WebGate] -> WebCardLibGlobalCfgRequest"), TraceLevel_Normal); WebCardLibGlobalCfgRequest(); break; } default: { CString strLog; strLog.Format(_T("[WebGate] Unknown way=%d, returning false"), nWay); CTraceService::TraceString(strLog, TraceLevel_Exception); return false; } } return true; } // Set card library bool CServerSocketItem::WebSetCardLibRequest() { CString strLibID, strSet, strLibKindID, strLibCustomID, strLibCardData, strSign; m_ParseData.GetQueryString(_T("id"), strLibID); m_ParseData.GetQueryString(_T("set"), strSet); m_ParseData.GetQueryString(_T("kid"), strLibKindID); m_ParseData.GetQueryString(_T("cid"), strLibCustomID); m_ParseData.GetQueryString(_T("data"), strLibCardData); m_ParseData.GetQueryString(_T("sign"), strSign); CString strData; strData.Format(_T("way=%d&id=%s&set=%s&kid=%s&cid=%s&data=%s&%s"), eWebCardLib, strLibID, strSet, strLibKindID, strLibCustomID, strLibCardData, CWebServerDlg::g_strVerifyKey); TCHAR szMD5Result[33]; CWHEncrypt::MD5Encrypt(strData, szMD5Result); // [Trace] log sign verification for CardLib { CString strLog; strLog.Format(_T("[WebGate] CardLib sign check: recv=[%s], calc=[%s], id=[%s], set=[%s], kid=[%s], cid=[%s]"), strSign, szMD5Result, strLibID, strSet, strLibKindID, strLibCustomID); CTraceService::TraceString(strLog, TraceLevel_Normal); } if (strSign.CompareNoCase(szMD5Result) == 0) { CMD_CS_SetCardLib mCardLib; ZeroMemory(&mCardLib, sizeof(CMD_CS_SetCardLib)); mCardLib.dwID = atoi(strLibID.GetBuffer()); mCardLib.dwCustomID = atoi(strLibCustomID.GetBuffer()); mCardLib.cbFlag = atoi(strSet.GetBuffer()); mCardLib.wKindID = atoi(strLibKindID.GetBuffer()); CString strSub; int nCount = 0; while (AfxExtractSubString(strSub, strLibCardData, nCount, ',')) { ASSERT(nCount <= LEN_CARD_LIB); if (nCount > LEN_CARD_LIB) { break; } TCHAR* lpStrEnd = NULL; mCardLib.cbData[nCount] = (BYTE)_tcstol(strSub.GetBuffer(), &lpStrEnd, 16); nCount++; mCardLib.cbCount++; } m_pClientSocket->SendData(MDM_CS_WEB_SERVICE, SUB_CS_C_SET_CARD_LIB, &mCardLib, sizeof(CMD_CS_SetCardLib)); SendResult(_T("{\"result\":%d}"), OPER_SUCCESSED); } else { SendResult(_T("{\"result\":%d}"), OPER_VERIFY_ERROR); SaveLog(_T("%s"), "Sign verify failed!"); } return true; } // Set cheat user bool CServerSocketItem::WebSetCheatUserRequest() { CString strUserID, strSet, strLibIndex, strLibStartTime, strLibStopTime, strSign; m_ParseData.GetQueryString(_T("uid"), strUserID); m_ParseData.GetQueryString(_T("set"), strSet); m_ParseData.GetQueryString(_T("sign"), strSign); m_ParseData.GetQueryString(_T("index"), strLibIndex); m_ParseData.GetQueryString(_T("stime"), strLibStartTime); m_ParseData.GetQueryString(_T("etime"), strLibStopTime); CString strData; strData.Format(_T("way=%d&uid=%s&set=%s&index=%s&stime=%s&etime=%s&%s"), eWebCheatUser, strUserID, strSet, strLibIndex, strLibStartTime, strLibStopTime, CWebServerDlg::g_strVerifyKey); TCHAR szMD5Result[33]; CWHEncrypt::MD5Encrypt(strData, szMD5Result); // [Trace] log sign verification for CheatUser { CString strLog; strLog.Format(_T("[WebGate] CheatUser sign check: recv=[%s], calc=[%s], uid=[%s], set=[%s]"), strSign, szMD5Result, strUserID, strSet); CTraceService::TraceString(strLog, TraceLevel_Normal); } if ( strSign.CompareNoCase(szMD5Result) == 0 ) { CMD_CS_SetCheatUser mCheatUser; ZeroMemory(&mCheatUser, sizeof(CMD_CS_SetCheatUser)); mCheatUser.dwUserID = atoi(strUserID.GetBuffer()); mCheatUser.cbFlag = atoi(strSet.GetBuffer()); if (strLibStartTime.GetLength()>0 && strLibStopTime.GetLength()>0) { try { CTime cTime = CTime::GetCurrentTime(); CString strDateTime; strDateTime.Format(_T("%s %s"), cTime.Format("%Y-%m-%d"), strLibStartTime); mCheatUser.dwStartLibTime = CWHService::ConvertDateTimeToDWORD(strDateTime); strDateTime.Format(_T("%s %s"), cTime.Format("%Y-%m-%d"), strLibStopTime); mCheatUser.dwStopLibTime = CWHService::ConvertDateTimeToDWORD(strDateTime); } catch (...) { mCheatUser.dwStartLibTime = 0; mCheatUser.dwStopLibTime = 0; mCheatUser.cbFlag = 0; } } else { mCheatUser.cbFlag = 0; } m_pClientSocket->SendData(MDM_CS_WEB_SERVICE, SUB_CS_C_SET_CHEAT_USER, &mCheatUser, sizeof(CMD_CS_SetCheatUser)); SendResult(_T("{\"result\":%d}"), OPER_SUCCESSED); } else { SendResult(_T("{\"result\":%d}"), OPER_VERIFY_ERROR); SaveLog(_T("%s"), "Sign verify failed!"); } return true; } // Card library global config bool CServerSocketItem::WebCardLibGlobalCfgRequest() { CString strSet, strLibKindID, strCardLibCount, strLibStartTime, strLibStopTime, strSign; m_ParseData.GetQueryString(_T("set"), strSet); m_ParseData.GetQueryString(_T("kid"), strLibKindID); m_ParseData.GetQueryString(_T("libcount"), strCardLibCount); m_ParseData.GetQueryString(_T("stime"), strLibStartTime); m_ParseData.GetQueryString(_T("etime"), strLibStopTime); m_ParseData.GetQueryString(_T("sign"), strSign); CString strData; strData.Format(_T("way=%d&set=%s&kid=%s&libcount=%s&stime=%s&etime=%s&%s"), eWebCardLibGlobalCfg, strSet, strLibKindID, strCardLibCount, strLibStartTime, strLibStopTime, CWebServerDlg::g_strVerifyKey); TCHAR szMD5Result[33]; CWHEncrypt::MD5Encrypt(strData, szMD5Result); // [Trace] log sign verification for GlobalCfg { CString strLog; strLog.Format(_T("[WebGate] GlobalCfg sign check: recv=[%s], calc=[%s], set=[%s], kid=[%s], libcount=[%s]"), strSign, szMD5Result, strSet, strLibKindID, strCardLibCount); CTraceService::TraceString(strLog, TraceLevel_Normal); } if (strSign.CompareNoCase(szMD5Result) == 0) { CMD_CS_CardLibGlobalCfg mGlobalCfg; ZeroMemory(&mGlobalCfg, sizeof(CMD_CS_CardLibGlobalCfg)); mGlobalCfg.cbFlag = atoi(strSet.GetBuffer()); mGlobalCfg.wKindID = atoi(strLibKindID.GetBuffer()); mGlobalCfg.dwLibCount = atoi(strCardLibCount.GetBuffer()); if (strLibStartTime.GetLength() > 0 && strLibStopTime.GetLength() > 0) { try { mGlobalCfg.dwStartLibTime = CWHService::ConvertDateTimeToDWORD(strLibStartTime); mGlobalCfg.dwStopLibTime = CWHService::ConvertDateTimeToDWORD(strLibStopTime); } catch (...) { mGlobalCfg.dwStartLibTime = 0; mGlobalCfg.dwStopLibTime = 0; mGlobalCfg.cbFlag = 0; } } else { mGlobalCfg.cbFlag = 0; } m_pClientSocket->SendData(MDM_CS_WEB_SERVICE, SUB_CS_C_CARD_LIB_GLOBAL_CFG, &mGlobalCfg, sizeof(CMD_CS_CardLibGlobalCfg)); SendResult(_T("{\"result\":%d}"), OPER_SUCCESSED); } else { SendResult(_T("{\"result\":%d}"), OPER_VERIFY_ERROR); SaveLog(_T("%s"), "Sign verify failed!"); } return true; } bool CServerSocketItem::HttpResponse(LPCTSTR lpszMessage) { CString strHeader; CString strResult = lpszMessage; // HTTP version strHeader = _T("HTTP/1.0 "); // status strHeader += _T("200 OK\r\n"); // servername strHeader += _T("Server: Web Server\r\n"); // content type strHeader += _T("Content-Type: text/html\r\n"); // file length CString strLength; strLength.Format(_T("Content-Length: %d\r\n"), strResult.GetLength()); strHeader += strLength; SYSTEMTIME systemTime; GetSystemTime(&systemTime); // get internet time TCHAR buff[INTERNET_RFC1123_BUFSIZE] = {0}; InternetTimeFromSystemTime(&systemTime, INTERNET_RFC1123_FORMAT, buff, INTERNET_RFC1123_BUFSIZE); // modified strHeader += _T("Last-Modified: "); strHeader += CString(buff); // In HTTP1.1, client and server support keep-alive by default. // If client does not want keep-alive, set Connection: close in header. // If server does not support keep-alive, response should also say Connection: close. // connection strHeader += _T("Connection: close"); strHeader += _T("\r\n\r\n"); strHeader += lpszMessage; m_pIOCPServer->SendData(getID(), strHeader.GetBuffer(), strHeader.GetLength()); //Close(); return true; } // Send result bool CServerSocketItem::SendResult(LPCTSTR pstrFormat, ...) { try { CString strResult; // format and write the data we were given va_list args; va_start(args, pstrFormat); strResult.FormatV(pstrFormat, args); va_end(args); HttpResponse(strResult); } catch(CMemoryException *e) { e->Delete(); return false; } catch(...) { return false; } return true; }