// guardian.cpp : Defines the entry point for the console application. // //#include "stdafx.h" #ifdef linux #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include int epfd; struct epoll_event ev; #define MAXLINE 128 #define OPEN_MAX 100 #define LISTENQ 20 #define INFTIM 1000 #else #undef UNICODE #pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" ) #define WIN32_LEAN_AND_MEAN #include #include #include #include #include #include #endif //linux #include #include #include #include "GuardianBase.h" #include "guardian.h" using namespace std; #define NET_TYPE_WIRELESS 1 #define NET_TYPE_ETHERNET 2 #define NET_TYPE_3G 3 #define NET_TYPE_4G 4 #define NET_TYPE_BLUETOOTH 5 #define DLL_PATH "C:\\RVC\\SystemInit\\CmbPadDll.dll" typedef DWORD(*pWlanConnect)(BOOL bConnect, int nType); typedef DWORD (*pDisableBluetooth)(BOOL bDisable); #ifdef linux int g_sListen; pthread_mutex_t g_cs, g_cs_event, g_cs_log; #define EnterCriticalSectionRVC(xType) pthread_mutex_lock(&xType) #define LeaveCriticalSectionRVC(xType) pthread_mutex_unlock(&xType) #else SOCKET g_sListen = INVALID_SOCKET; #pragma comment (lib, "Ws2_32.lib") unsigned int __stdcall DoNetControl(void *pData); CRITICAL_SECTION g_cs,g_cs_event,g_cs_log; #define EnterCriticalSectionRVC(xType) EnterCriticalSection(&xType) #define LeaveCriticalSectionRVC(xType) LeaveCriticalSection(&xType) #endif //linux //unsigned int __stdcall DoLog(void *pData); const int DEFAULT_BUFLEN = 512; const int SHAKEHAND_BUFZIE = 32; #define DEFAULT_PORT "30005" const int default_port = 30005; int g_needToRollBack = 0; bool g_bFrameQuit = false,g_bFrameOnline = false,g_bLogFileOpen = false,g_bAuthSuc = false,g_bInUpgrade = false; ULONGLONG g_dwTimeBegin = 0; ULONGLONG g_dwUpgradeRestartTimeBegin = 0; int cnt = 0; ofstream logFile; char currDirBuf[256]; char chDisk[2]; void NetControl(); const int MAX_WAIT_TIME_TO_RESTART = 600000; const int MAX_WAIT_TIME_TO_RESTART_UPGRADE = 110000; int g_startDay = 0; //HANDLE g_logHandle; char g_allMsg[1024]; #ifdef linux extern "C" { void* DoWorkLinux(void* arg); void* DoNetControlLinux(void* arg); } #define FUNCTION_STDCALL typedef unsigned short WORD; typedef struct _SYSTEMTIME { WORD wYear; WORD wMonth; WORD wDayOfWeek; WORD wDay; WORD wHour; WORD wMinute; WORD wSecond; WORD wMilliseconds; } SYSTEMTIME; #else typedef struct { OVERLAPPED Overlapped; WSABUF DataBuf; CHAR Buffer[DATA_BUFSIZE]; } PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA; typedef struct { SOCKET Socket; } PER_HANDLE_DATA, * LPPER_HANDLE_DATA; unsigned int __stdcall DoWork(void* pData); #define FUNCTION_STDCALL __stdcall #endif unsigned long long GetTickCountRVC() { #ifdef linux struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return (ts.tv_sec * 1000 + ts.tv_nsec / 1000000); #else return GetTickCount64(); #endif //RVC_OS_WIN } void GetLocalTimeRVC(SYSTEMTIME& stTime) { #ifdef linux struct tm* pst = NULL; time_t t = time(NULL); pst = localtime(&t); stTime.wYear = pst->tm_year + 1900; stTime.wMonth = pst->tm_mon + 1;//because the range of tm_mon is:0-11 stTime.wDay = pst->tm_mday; stTime.wHour = pst->tm_hour; stTime.wMinute = pst->tm_min; stTime.wDayOfWeek = pst->tm_wday; stTime.wSecond = pst->tm_sec; stTime.wMilliseconds = 0; //("oiltest,time:%d,%d,%d,%d", stTime.wYear, stTime.wHour, stTime.wMinute, stTime.wDayOfWeek); #else GetLocalTime(stTime); #endif } int BeginThreadRVC(void* (*pFuncLinux)(void*), unsigned int(FUNCTION_STDCALL* pFuncWin)(void*)) { #ifdef linux pthread_t tidp; if ((pthread_create(&tidp, NULL, pFuncLinux, NULL) == -1)) { //printf("create error!\n"); return 1; } cout << "after pthread_create of linux thread" << endl; return 0; #else _beginthreadex(NULL, 0, pFuncWin, NULL, 0, NULL); return 0; #endif //linux } void EndThreadRVC() { #ifdef linux cout << "thread to exit" << endl; pthread_exit(0); cout << "return of EndThreadRVC" << endl; #else _endthreadex(0); #endif //linux } void StartDoNetControlRVC() { #ifdef linux BeginThreadRVC(DoNetControlLinux, NULL); cout << "after DoNetControlLinux thread created." << endl; #else BeginThreadRVC(NULL, DoNetControl); #endif //linux } void StartDoWorkRVC() { #ifdef linux BeginThreadRVC(DoWorkLinux, NULL); #else BeginThreadRVC(NULL, DoWork); #endif //linux } void ServerReportEvent(const char* szFunction,const char* szName="guardian") { #ifdef linux return;//oiltest cout << "oiltest(SPE):" << szFunction << endl; openlog("guardian", LOG_CONS | LOG_PID, LOG_LOCAL0); syslog(LOG_ERR, szFunction); closelog(); #else //LogToFile(false,false,false,szFunction); HANDLE hEventSource; LPCTSTR lpszStrings[2]; int len = sizeof(szFunction); //char *Buffer = new char[len]; char Buffer[1024] = {0}; hEventSource = RegisterEventSource(NULL, szName); if( NULL != hEventSource ) { //StringCchPrintf(Buffer, 80, TEXT("%s failed with %d"), szFunction, GetLastError()); strcpy_s(Buffer,1024,szFunction); lpszStrings[0] = szName; lpszStrings[1] = Buffer; ReportEvent(hEventSource, // event log handle EVENTLOG_ERROR_TYPE, // event type 0, // event category 0xe0000001, // event identifier NULL, // no security identifier 2, // size of lpszStrings array 0, // no binary data lpszStrings, // array of strings NULL); // no binary data DeregisterEventSource(hEventSource); } #endif //linux } bool VersionRollback() { const int VersionLenMax = 64; fstream verFile,verBak;//to confirm string strActiveTxtPath, strVersionDatPath; #ifdef linux //todo oiltestlinux strActiveTxtPath = "/opt/run/version/active.txt"; strVersionDatPath = "/opt/run/runinfo/runcfg/version.dat"; #else string strDisk(chDisk); strActiveTxtPath = strDisk + ":\\Run\\version\\active.txt"; strVersionDatPath = strDisk + ":\\Run\\runinfo\\runcfg\\version.dat"; #endif //linux verFile.open(strActiveTxtPath,std::fstream::in|std::fstream::out|std::fstream::binary); verBak.open(strVersionDatPath,std::fstream::in|std::fstream::out|std::fstream::binary); if (!verFile.is_open() || !verBak.is_open()) return false; char *pVerBak,*pNULL,*pCurrVer; pVerBak = new char[VersionLenMax]; pNULL = new char[VersionLenMax]; pCurrVer = new char[VersionLenMax]; memset(pVerBak,0,VersionLenMax); memset(pNULL,0,VersionLenMax); memset(pCurrVer,0,VersionLenMax); verBak.seekg(0,verBak.end); int lenBak = verBak.tellg(); verBak.seekg(0,verBak.beg); verBak.read(pVerBak,lenBak); //need to consider atomic op? oilyang verFile.seekg(0,verFile.end); int len = verFile.tellg(); verFile.seekg(0,verFile.beg); verFile.read(pCurrVer,len); LogSingleMsg(pVerBak); LogSingleMsg(pCurrVer); LogSingleMsg(pNULL); if (strcmp(pVerBak,pCurrVer) == 0) { ServerReportEvent(pVerBak); verFile.close(); verBak.close(); delete []pVerBak; delete []pNULL; return false; } //verBak.write(pNULL,len); //verFile.write(pNULL,len); //how foolish? verFile.close(); verFile.open(strActiveTxtPath,std::fstream::in|std::fstream::out|std::fstream::binary|std::fstream::trunc); verFile.seekg(0,verFile.beg); verFile.write(pVerBak,lenBak); LogSingleMsg("version will rollback to "); LogSingleMsg(pVerBak); verFile.close(); verBak.close(); delete []pVerBak; delete []pNULL; return true; } int FrameworkShutdown(bool bUpgrade=false,bool bRestart = true) { cout << "in FrameworkShutdown,bUpgrade:" << bUpgrade << ",bRestart:" << bRestart << endl; if (!bUpgrade) g_dwTimeBegin = GetTickCountRVC(); NetControl(); #ifdef linux //todo oiltestlinux LogSingleMsg("to kill spshell"); ServerReportEvent("FrameworkShutdown linux"); system("killall -9 spshell"); system("killall -9 sphost"); sleep(2); system("/opt/run/version/spexplorer.sh"); LogSingleMsg("after kill spshell"); return 0; #else STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); ZeroMemory( &pi, sizeof(pi) ); // Start the child process. CSimpleStringA csRestart,csVerPath,csAll,csSep("\""),csBlank(" "),csScript("wscript.exe"),csReFlag("r"); csRestart = "sprestart.exe "; csVerPath = chDisk; csVerPath += ":\\Run\\version"; csVerPath +="\\spexplorerfast.vbs"; if (!bRestart) csReFlag = "n"; csAll = csSep + csRestart + csSep + csBlank + csSep + csScript+csBlank + csVerPath + csSep + csBlank + csSep + csReFlag + csSep; LPTSTR szCmdline = _strdup(csAll); LogSingleMsg(szCmdline); //MessageBoxA(0,0,0,0); if( !CreateProcess( NULL,szCmdline,NULL,NULL,FALSE,CREATE_NEW_CONSOLE,NULL,NULL,&si,&pi)) { //Dbg("CreateProcess failed (%d).\n", GetLastError()); return -1; } DWORD dwErr = GetLastError(); // Wait until child process exits. WaitForSingleObject( pi.hProcess, INFINITE ); // Close process and thread handles. CloseHandle( pi.hProcess ); CloseHandle( pi.hThread ); return 0; #endif //linux } bool FrameworkRollBack() { bool bVerRollback = VersionRollback(); LogToFile(false,false,false,"version rollback "); if (true) FrameworkShutdown(); return true; } bool ReadRuninfoContent(string &strData) { fstream runinfo; string strGdRuninfoPath; #ifdef linux //todo oiltestlinux strGdRuninfoPath = "/opt/run/runinfo/runcfg/gdruninfo"; #else string strDisk(chDisk); strGdRuninfoPath = strDisk + ":\\Run\\runinfo\\runcfg\\gdruninfo"; #endif //linux runinfo.open(strGdRuninfoPath,std::fstream::in|std::fstream::out|std::fstream::binary); if (!runinfo.is_open()) { LogToFile(true, true,false, "open gdruninfo(read) failed.",strerror(errno), errno); return false; } runinfo.seekg(0,ios::end); int size = runinfo.tellg(); if (size <= 0) return false; char *pData = new char[size+1]; memset(pData,0,size+1); runinfo.seekg(0,ios::beg); runinfo.read(pData,size); strData = string(pData); LogToFile(true, false,false, "read runinfo ", strData.c_str()); return true; } bool WriteRunInfoContent(const char* pData) { ofstream runinfo; string strGdRuninfoPath; #ifdef linux //todo oiltestlinux strGdRuninfoPath = "/opt/run/runinfo/runcfg/gdruninfo"; #else string strDisk(chDisk); strGdRuninfoPath = strDisk + ":\\Run\\runinfo\\runcfg\\gdruninfo"; #endif //linux runinfo.open(strGdRuninfoPath,std::ofstream::in|std::ofstream::binary|std::ofstream::trunc); if (!runinfo.is_open()) { ServerReportEvent("open gdruninfo(write) failed."); return false; } runinfo.write(pData,strlen(pData)); runinfo.close(); return true; } bool IsStartTimeFileExist() { ofstream runinfo; string strStartTimePath; #ifdef linux //todo oiltestlinux strStartTimePath = "/opt/run/runinfo/runcfg/starttime.dat"; #else string strDisk(chDisk); strStartTimePath = strDisk + ":\\Run\\runinfo\\runcfg\\starttime.dat"; #endif //linux runinfo.open(strStartTimePath, std::fstream::in | std::fstream::out | std::fstream::binary); if (!runinfo.is_open()) return false; else { runinfo.close(); return true; } } #ifdef linux void CheckDoWork(int sig) { cout << "CheckDoWork" << endl; if (SIGALRM == sig) { LogSingleMsg("to check value(linux)"); EnterCriticalSectionRVC(g_cs); if (!g_bFrameQuit) { ULONGLONG dwTmpBegin = g_dwTimeBegin; ULONGLONG dwUpgradeTmpBegin = g_dwUpgradeRestartTimeBegin; LeaveCriticalSectionRVC(g_cs); ULONGLONG dwTimeEnd = GetTickCountRVC(); //oilyang@20190828 add //升级重启后,在10分钟内,只要离最后一次交互时间大于2分钟,重启框架 if ((g_bInUpgrade && ((dwTimeEnd - dwUpgradeTmpBegin) < MAX_WAIT_TIME_TO_RESTART)) && (!g_bAuthSuc && ((dwTimeEnd - dwTmpBegin) > MAX_WAIT_TIME_TO_RESTART_UPGRADE))) { LogSingleMsg("**in upgrade restart**,to restart framework(linux)."); cout << "oiltest 0127" << endl; FrameworkShutdown(true, true); } if ((dwTimeEnd - dwTmpBegin) > MAX_WAIT_TIME_TO_RESTART) { LogSingleMsg("framework maybe down."); string strRunInfo; if (ReadRuninfoContent(strRunInfo)) { LogSingleMsg("to check if need rollback."); LogSingleMsg((char*)strRunInfo.c_str()); if (strRunInfo.compare("111") == 0 && IsStartTimeFileExist()) { EnterCriticalSectionRVC(g_cs); g_needToRollBack = 1; LeaveCriticalSectionRVC(g_cs); } } else LogSingleMsg("read run info failed."); if (g_needToRollBack) { LogSingleMsg("after upgrade,time elapse,but can't wait the shake hands,so rollback."); FrameworkRollBack(); } else { //framework is down,to restart it! oilyang 20150413 FrameworkShutdown(); } } } else LeaveCriticalSectionRVC(g_cs); alarm(2 * 60); //we contimue set the timer } return; } void* DoWorkLinux(void* arg) { //LogSingleMsg("to wait."); cout << "DoWorkLinux" << endl; signal(SIGALRM, CheckDoWork); //relate the signal and function alarm(2 * 60); //trigger the timer EndThreadRVC(); //return 0; } void* DoNetControlLinux(void* arg) { cout << "to end DoNetControlLinux" << endl; EndThreadRVC(); cout << "after end DoNetControlLinux" << endl; } void DataProcessLinux(int socket,const char*data) { GuardianInfo* pInfo = (GuardianInfo*)data; LogToFile(false, true, false, "eType:", "", pInfo->eType); cout << "eType:" << pInfo->eType << ",p1:" << pInfo->dwParam1 << ",p2:" << pInfo->dwParam2 << ",dwSize:" << pInfo->dwSize << endl; //LogToFile(false,true,false,"clientsocket:", "", pPerHandleData->Socket); switch (pInfo->eType) { case GdOpShakeHand: { LogToFile(false, false, false, "Shake hand."); if (!g_bFrameOnline) { g_bFrameOnline = true; StartDoNetControlRVC(); } int rc, err; EnterCriticalSectionRVC(g_cs); g_bFrameQuit = false; g_dwTimeBegin = GetTickCountRVC(); LeaveCriticalSectionRVC(g_cs); char* pBuf = new char[8]; memset(pBuf, 0, 8); //get guardian state //ex:u(update),g(guardian),r(reboot),b(rollback) if (cnt % 2 == 0) memcpy(pBuf, "g", 1); else memcpy(pBuf, "u", 1); cnt++; rc = send(socket, pBuf, 8, 0); delete[]pBuf; close(socket); } break; case GdOpUpdateTask: { if (!g_bFrameOnline) { g_bFrameOnline = true; //_beginthreadex(NULL,0,DoNetControl,NULL,0,NULL); StartDoNetControlRVC(); } } break; case GdOpQueryInstall: { if (!g_bFrameOnline) { g_bFrameOnline = true; //_beginthreadex(NULL,0,DoNetControl,NULL,0,NULL); StartDoNetControlRVC(); } int rc, err; char* pBuf = new char[8]; memset(pBuf, 0, 8); if (cnt % 2 == 0) memcpy(pBuf, "y", 1); else memcpy(pBuf, "n", 1); cnt++; rc = send(socket, pBuf, 8, 0); delete[]pBuf; close(socket); } break; case GdOpUpgradeRestart: { if (pInfo->dwParam1 == 4)//just know framework is starting... { LogSingleMsg("framework is starting..."); cout << "framework is starting..." << endl; g_bFrameOnline = true; g_bAuthSuc = false; //_beginthreadex(NULL,0,DoNetControl,NULL,0,NULL); StartDoNetControlRVC(); cout << "to break upgrade..." << endl; close(socket); break; } if (pInfo->dwParam1 == 5) { LogSingleMsg("framework auth ok."); g_bInUpgrade = false; g_bAuthSuc = true; } if (!g_bFrameOnline) { g_bFrameOnline = true; //_beginthreadex(NULL,0,DoNetControl,NULL,0,NULL); StartDoNetControlRVC(); } if (pInfo->dwParam1 == 1 || pInfo->dwParam1 == 3) g_dwTimeBegin = GetTickCountRVC(); ServerReportEvent("upgrade restart"); LogToFile(false, true, false, "upgrade restart ", "", pInfo->dwParam1); if (pInfo->dwParam1 == 1)//framework to restart after upgrade { g_bInUpgrade = true; WriteRunInfoContent("111"); g_dwUpgradeRestartTimeBegin = GetTickCountRVC(); } else if (pInfo->dwParam1 == 2)//need rollback after upgrade { LogSingleMsg("upgrade restart 222"); WriteRunInfoContent("222"); //rollback EnterCriticalSectionRVC(g_cs); g_needToRollBack = 0; LeaveCriticalSectionRVC(g_cs); LogSingleMsg("healthmanager said to rollback"); FrameworkRollBack(); } else if (pInfo->dwParam1 == 3)//upgrade succeeded { LogSingleMsg("upgrade restart ok"); WriteRunInfoContent("333"); EnterCriticalSectionRVC(g_cs); g_needToRollBack = 0; LeaveCriticalSectionRVC(g_cs); } //runinfo.close(); close(socket); } break; case GdOpFrameQuit: if (!g_bFrameOnline) { g_bFrameOnline = true; //_beginthreadex(NULL,0,DoNetControl,NULL,0,NULL); StartDoNetControlRVC(); } EnterCriticalSectionRVC(g_cs); g_bFrameQuit = true; LeaveCriticalSectionRVC(g_cs); close(socket); break; default: break; } cout << "quit of DataProcessLinux" << endl; } #else void DataProcess(LPPER_HANDLE_DATA pPerHandleData,LPPER_IO_OPERATION_DATA pPerIoData) { GuardianInfo* pInfo = (GuardianInfo*)pPerIoData->Buffer; LogToFile(false, true, false,"eType:", "", pInfo->eType); //LogToFile(false,true,false,"clientsocket:", "", pPerHandleData->Socket); switch(pInfo->eType) { case GdOpShakeHand: { LogToFile(false, false,false, "Shake hand."); if (!g_bFrameOnline) { g_bFrameOnline = true; StartDoNetControlRVC(); } int rc,err; EnterCriticalSectionRVC(g_cs); g_bFrameQuit = false; g_dwTimeBegin = GetTickCountRVC(); LeaveCriticalSectionRVC(g_cs); char* pBuf = new char[8]; memset(pBuf,0,8); //get guardian state //ex:u(update),g(guardian),r(reboot),b(rollback) if (cnt%2 == 0) memcpy(pBuf,"g",1); else memcpy(pBuf,"u",1); cnt++; rc = send(pPerHandleData->Socket,pBuf,8,0); delete []pBuf; closesocket(pPerHandleData->Socket); } break; case GdOpUpdateTask: { if (!g_bFrameOnline) { g_bFrameOnline = true; //_beginthreadex(NULL,0,DoNetControl,NULL,0,NULL); StartDoNetControlRVC(); } } break; case GdOpQueryInstall: { if (!g_bFrameOnline) { g_bFrameOnline = true; //_beginthreadex(NULL,0,DoNetControl,NULL,0,NULL); StartDoNetControlRVC(); } int rc,err; char* pBuf = new char[8]; memset(pBuf,0,8); if (cnt%2 == 0) memcpy(pBuf,"y",1); else memcpy(pBuf,"n",1); cnt++; rc = send(pPerHandleData->Socket,pBuf,8,0); delete []pBuf; closesocket(pPerHandleData->Socket); } break; case GdOpUpgradeRestart: { if (pInfo->dwParam1 == 4)//just know framework is starting... { LogSingleMsg("framework is starting..."); g_bFrameOnline = true; g_bAuthSuc = false; //_beginthreadex(NULL,0,DoNetControl,NULL,0,NULL); StartDoNetControlRVC(); break; } if (pInfo->dwParam1 == 5) { LogSingleMsg("framework auth ok."); g_bInUpgrade = false; g_bAuthSuc = true; } if (!g_bFrameOnline) { g_bFrameOnline = true; //_beginthreadex(NULL,0,DoNetControl,NULL,0,NULL); StartDoNetControlRVC(); } if (pInfo->dwParam1 == 1 || pInfo->dwParam1 == 3) g_dwTimeBegin = GetTickCountRVC(); ServerReportEvent("upgrade restart"); LogToFile(false, true,false, "upgrade restart ", "", pInfo->dwParam1); if (pInfo->dwParam1 == 1)//framework to restart after upgrade { g_bInUpgrade = true; WriteRunInfoContent("111"); g_dwUpgradeRestartTimeBegin = GetTickCountRVC(); } else if (pInfo->dwParam1 == 2)//need rollback after upgrade { LogSingleMsg("upgrade restart 222"); WriteRunInfoContent("222"); //rollback EnterCriticalSectionRVC(g_cs); g_needToRollBack = 0; LeaveCriticalSectionRVC(g_cs); LogSingleMsg("healthmanager said to rollback"); FrameworkRollBack(); }else if (pInfo->dwParam1 == 3)//upgrade succeeded { LogSingleMsg("upgrade restart ok"); WriteRunInfoContent("333"); EnterCriticalSectionRVC(g_cs); g_needToRollBack = 0; LeaveCriticalSectionRVC(g_cs); } //runinfo.close(); closesocket(pPerHandleData->Socket); } break; case GdOpFrameQuit: if (!g_bFrameOnline) { g_bFrameOnline = true; //_beginthreadex(NULL,0,DoNetControl,NULL,0,NULL); StartDoNetControlRVC(); } EnterCriticalSectionRVC(g_cs); g_bFrameQuit = true; LeaveCriticalSectionRVC(g_cs); closesocket(pPerHandleData->Socket); break; default: break; } } DWORD WINAPI ProcessIO(LPVOID lpParam) { HANDLE CompletionPort = (HANDLE)lpParam; DWORD BytesTransferred; LPPER_HANDLE_DATA PerHandleData; LPPER_IO_OPERATION_DATA PerIoData; while(true) { if(0 == GetQueuedCompletionStatus(CompletionPort, &BytesTransferred, (LPDWORD)&PerHandleData, (LPOVERLAPPED*)&PerIoData, INFINITE)) { if( (GetLastError() == WAIT_TIMEOUT) || (GetLastError() == ERROR_NETNAME_DELETED) ) { LogToFile(false, true,false, "closing socket(1)", "", PerHandleData->Socket); closesocket(PerHandleData->Socket); delete PerIoData; delete PerHandleData; continue; } else { //OutErr("GetQueuedCompletionStatus failed!"); } return 0; } // client quit if(BytesTransferred == 0) { LogToFile(false, true,false, "closing socket(2)", "", PerHandleData->Socket); closesocket(PerHandleData->Socket); delete PerIoData; delete PerHandleData; continue; } //MessageBoxA(0,0,0,0); //LogToFile(false, true,false, "socket", "", PerHandleData->Socket); // receiving data process DataProcess(PerHandleData,PerIoData); // socket WSARecv DWORD Flags = 0; DWORD dwRecv = 0; ZeroMemory(PerIoData, sizeof(PER_IO_OPERATION_DATA)); PerIoData->DataBuf.buf = PerIoData->Buffer; PerIoData->DataBuf.len = DATA_BUFSIZE; WSARecv(PerHandleData->Socket, &PerIoData->DataBuf, 1, &dwRecv, &Flags, &PerIoData->Overlapped, NULL); } return 0; } unsigned int __stdcall DoWork(void* pData) { LogSingleMsg("to wait."); HANDLE hTimer; LARGE_INTEGER li; hTimer = CreateWaitableTimer(NULL,FALSE,NULL); const int nTimerUnitsPerSecond = 10000000; li.QuadPart = -(1*60*nTimerUnitsPerSecond);//oiltmp 1 minute SetWaitableTimer(hTimer,&li,2*60*1000,NULL,NULL,FALSE); while(1) { WaitForSingleObject(hTimer,INFINITE); LogSingleMsg("to check value"); EnterCriticalSectionRVC(g_cs); if (!g_bFrameQuit) { ULONGLONG dwTmpBegin = g_dwTimeBegin; ULONGLONG dwUpgradeTmpBegin = g_dwUpgradeRestartTimeBegin; LeaveCriticalSectionRVC(g_cs); ULONGLONG dwTimeEnd = GetTickCountRVC(); //oilyang@20190828 add //升级重启后,在10分钟内,只要离最后一次交互时间大于2分钟,重启框架 if ((g_bInUpgrade && ((dwTimeEnd - dwUpgradeTmpBegin) < MAX_WAIT_TIME_TO_RESTART)) && (!g_bAuthSuc && ((dwTimeEnd - dwTmpBegin) > MAX_WAIT_TIME_TO_RESTART_UPGRADE))) { LogSingleMsg("**in upgrade restart**,to restart framework."); FrameworkShutdown(true,true); } if ((dwTimeEnd-dwTmpBegin) > MAX_WAIT_TIME_TO_RESTART) { LogSingleMsg("framework maybe down."); string strRunInfo; if (ReadRuninfoContent(strRunInfo)) { LogSingleMsg("to check if need rollback."); LogSingleMsg((char*)strRunInfo.c_str()); if (strRunInfo.compare("111") == 0 && IsStartTimeFileExist()) { EnterCriticalSectionRVC(g_cs); g_needToRollBack = 1; LeaveCriticalSectionRVC(g_cs); } } else LogSingleMsg("read run info failed."); if (g_needToRollBack) { LogSingleMsg("after upgrade,time elapse,but can't wait the shake hands,so rollback."); FrameworkRollBack(); } else { //framework is down,to restart it! oilyang 20150413 FrameworkShutdown(); } } } else LeaveCriticalSectionRVC(g_cs); } //_endthreadex(0); EndThreadRVC(); return 0; } unsigned int __stdcall DoNetControl(void *pData) { ServerReportEvent("DoNetControl start"); HANDLE hSnapshot; //find spshell.exe hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hSnapshot) { PROCESSENTRY32 pe; pe.dwSize = sizeof(pe); if (Process32First(hSnapshot, &pe)) { do { if (_stricmp(&pe.szExeFile[0], "spshell.exe") == 0) { //ServerReportEvent("find spshell.exe"); LogToFile(false, false, false, "find spshell.exe"); //DWORD dwExit = 0; //do //{ // GetExitCodeProcess(&pe.th32ProcessID,&dwExit); // if (dwExit != STILL_ACTIVE) // break; //}while(1); HANDLE hP = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe.th32ProcessID ); WaitForSingleObject(hP, INFINITE ); LogToFile(false, false, false, "spshell.exe quit"); //ServerReportEvent("spshell.exe quit"); NetControl(); break; } } while (Process32Next(hSnapshot, &pe)); } CloseHandle(hSnapshot); } else ServerReportEvent("create snapshot failed."); //_endthreadex(0); EndThreadRVC(); return 0; } #endif //linux unsigned int InitListenSocketRVC() { #ifdef linux socklen_t clilen; epfd = epoll_create(256); struct sockaddr_in clientaddr; struct sockaddr_in serveraddr; g_sListen = socket(AF_INET, SOCK_STREAM, 0); //setnonblocking(listenfd); ev.data.fd = g_sListen; ev.events = EPOLLIN | EPOLLET; epoll_ctl(epfd, EPOLL_CTL_ADD, g_sListen, &ev); memset(&serveraddr, 0, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; char* local_addr = "127.0.0.1"; inet_aton(local_addr, &(serveraddr.sin_addr)); serveraddr.sin_port = htons(default_port); bind(g_sListen, (sockaddr*)& serveraddr, sizeof(serveraddr)); listen(g_sListen, LISTENQ); cout << "listen on:" << g_sListen << endl; return g_sListen; #else WSADATA wsaData; int iResult; struct addrinfo* result = NULL; struct addrinfo hints; int iSendResult; char recvbuf[DEFAULT_BUFLEN]; int recvbuflen = DEFAULT_BUFLEN; // Initialize Winsock iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); if (iResult != 0) { LogToFile(false, true, false, "WSAStartup failed with error:", "", iResult); return 1; } ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = AI_PASSIVE; // Resolve the server address and port iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result); if (iResult != 0) { LogToFile(false, true, false, "getaddrinfo failed with error:", "", iResult); WSACleanup(); return 1; } // get system info to create work thread SYSTEM_INFO SystemInfo; GetSystemInfo(&SystemInfo); // Create a SOCKET for connecting to server g_sListen = socket(result->ai_family, result->ai_socktype, result->ai_protocol); if (g_sListen == INVALID_SOCKET) { LogToFile(false, true, false, "socket failed with error:", "", WSAGetLastError()); freeaddrinfo(result); WSACleanup(); return 1; } // Setup the TCP listening socket struct sockaddr_in* sockaddr_ipv4 = (struct sockaddr_in*) result->ai_addr; LogToFile(true, false, false, "ip:", inet_ntoa(sockaddr_ipv4->sin_addr)); iResult = bind(g_sListen, result->ai_addr, (int)result->ai_addrlen); if (iResult == SOCKET_ERROR) { printf("bind failed with error: %d\n", WSAGetLastError()); freeaddrinfo(result); closesocket(g_sListen); WSACleanup(); return 1; } freeaddrinfo(result); LogToFile(false, false, false, "to listen."); iResult = listen(g_sListen, SOMAXCONN); if (iResult == SOCKET_ERROR) { printf("listen failed with error: %d\n", WSAGetLastError()); closesocket(g_sListen); WSACleanup(); return 1; } LogToFile(false, false, false, "listen ok."); return g_sListen; #endif //linux } void AcceptReqRVC() { #ifdef linux StartDoWorkRVC(); cout << "AcceptReqRVC:after StartDoWorkRVC" << endl; int maxi, connfd, sockfd, nfds; struct epoll_event events[20]; struct sockaddr_in clientaddr; socklen_t clilen = sizeof(struct sockaddr); ssize_t n; maxi = 0; char line[MAXLINE]; for (; ; ) { //等待epoll事件的发生 nfds = epoll_wait(epfd, events, 20, 500); //处理所发生的所有事件 for (int i = 0; i < nfds; ++i) { if (events[i].data.fd == g_sListen)//new connection { connfd = accept(g_sListen, (sockaddr*)& clientaddr, &clilen); if (connfd < 0) { perror("connfd<0"); exit(1); } //setnonblocking(connfd); char* str = inet_ntoa(clientaddr.sin_addr); cout << "accapt a connection from " << str << endl; ev.data.fd = connfd; ev.events = EPOLLIN | EPOLLET; //ev.events=EPOLLIN; epoll_ctl(epfd, EPOLL_CTL_ADD, connfd, &ev); } else if (events[i].events & EPOLLIN) { cout << "EPOLLIN,i:" << i << ",sock:" << events[i].data.fd << endl; if ((sockfd = events[i].data.fd) < 0) continue; if ((n = read(sockfd, line, MAXLINE)) < 0) { if (errno == ECONNRESET) { close(sockfd); events[i].data.fd = -1; } else std::cout << "readline error" << strerror(errno) << std::endl; } else if (n == 0) { close(sockfd); events[i].data.fd = -1; } DataProcessLinux(sockfd,line); line[n] = '\0'; cout << "read " << line << endl; ev.data.fd = sockfd; ev.events = EPOLLOUT | EPOLLET; epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev); } else if (events[i].events & EPOLLOUT) { cout << "epoll out" << endl; sockfd = events[i].data.fd; write(sockfd, line, n); ev.data.fd = sockfd; ev.events = EPOLLIN | EPOLLET; epoll_ctl(epfd, EPOLL_CTL_MOD, sockfd, &ev); } } } #else HANDLE hCompletionPort; hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); // get system info to create work thread SYSTEM_INFO SystemInfo; GetSystemInfo(&SystemInfo); for (int i = 0; i < SystemInfo.dwNumberOfProcessors * 2; i++) { HANDLE hProcessIO = CreateThread(NULL, 0, ProcessIO, hCompletionPort, 0, NULL); if (hProcessIO) CloseHandle(hProcessIO); } //waiting thread //_beginthreadex(NULL,0,DoWork,NULL,0,NULL); StartDoWorkRVC(); SOCKET sClient; LPPER_HANDLE_DATA PerHandleData; LPPER_IO_OPERATION_DATA PerIoData; while (true) { //sClient = WSAAccept(sListen, NULL, NULL, NULL, 0); sClient = accept(g_sListen, NULL, NULL); //cout << "Socket " << sClient << "connect" << endl; PerHandleData = new PER_HANDLE_DATA(); PerHandleData->Socket = sClient; // client completion port CreateIoCompletionPort((HANDLE)sClient, hCompletionPort, (DWORD)PerHandleData, 0); // PerIoData = new PER_IO_OPERATION_DATA(); ZeroMemory(PerIoData, sizeof(PER_IO_OPERATION_DATA)); PerIoData->DataBuf.buf = PerIoData->Buffer; PerIoData->DataBuf.len = DATA_BUFSIZE; // WSARecv DWORD Flags = 0; DWORD dwRecv = 0; WSARecv(sClient, &PerIoData->DataBuf, 1, &dwRecv, &Flags, &PerIoData->Overlapped, NULL); LogToFile(false, false, false, "hold"); } DWORD dwByteTrans; PostQueuedCompletionStatus(hCompletionPort, dwByteTrans, 0, 0); closesocket(g_sListen); #endif //linux } void CheckGuardianDbgDirAndCreateDbgFile(bool bChangeDay = false) { #ifdef linux //todo oiltestlinux string guardianLogDir("/opt/rvc/dbg/guardian"); if (opendir(guardianLogDir.c_str()) == NULL) { ServerReportEvent("Can't find guardian dbg dir,to create it."); mkdir(guardianLogDir.c_str(), 0775); } #else ZeroMemory(currDirBuf, sizeof(currDirBuf)); ZeroMemory(chDisk, sizeof(chDisk)); GetCurrentDirectory(256, currDirBuf); chDisk[0] = currDirBuf[0]; // C:\Run\version\1.7.0.1 string strDir(chDisk), guardianLogDir(""), strGuardian("\\rvc\\dbg\\guardian"); guardianLogDir = strDir + ":" + strGuardian; WIN32_FIND_DATA wfd; bool rValue = false; HANDLE hFind = FindFirstFile(guardianLogDir.c_str(), &wfd); if ((hFind != INVALID_HANDLE_VALUE) && (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { ServerReportEvent("find guardian log dir."); } else { ServerReportEvent("can't find guardian log dir:"); int ret = _mkdir(guardianLogDir.c_str()); if (ret != 0) { ServerReportEvent("Create guardian log dir failed."); ServerReportEvent(guardianLogDir.c_str()); return; } else ServerReportEvent("Create guardian log dir suc."); } FindClose(hFind); #endif //linux SYSTEMTIME st; GetLocalTimeRVC(st); g_startDay = st.wDay; char date[12]; memset(date,0,12); sprintf(date, "%.4d%.2d%.2d", st.wYear, st.wMonth, st.wDay); string strLogFile(""), strDate(date); strLogFile = guardianLogDir + "/" + date + ".log"; if (!bChangeDay) LogSingleMsg(strLogFile.c_str()); logFile.open(strLogFile.c_str(), std::ofstream::binary | ios::app); if (logFile.is_open()) { if (!bChangeDay) LogSingleMsg("open guardian dbg file suc."); g_bLogFileOpen = true; if (!bChangeDay){ LogToFile(false, false, false, "==============guardian start=============="); LogToFile(false, false, false, strLogFile.c_str()); } } else { if (!bChangeDay){ LogSingleMsg("open guardian dbg file failed.",errno); LogSingleMsg(strerror(errno)); } } } int main() { //attach file descriptors 0,1,2 to /dev/null(for deamon app) int fd0, fd1, fd2; fd0 = open("/dev/null", O_RDWR); fd1 = dup(0); fd2 = dup(0); g_bFrameOnline = true; #ifdef linux pthread_mutex_init(&g_cs_event,NULL); pthread_mutex_init(&g_cs_log,NULL); pthread_mutex_init(&g_cs,NULL); #else InitializeCriticalSectionAndSpinCount(&g_cs_event, 100); InitializeCriticalSectionAndSpinCount(&g_cs_log, 100); InitializeCriticalSectionAndSpinCount(&g_cs, 100); g_logHandle = CreateEventA(NULL, FALSE, FALSE, NULL); #endif g_dwTimeBegin = GetTickCountRVC(); int i=1000; CheckGuardianDbgDirAndCreateDbgFile(); StartDoNetControlRVC(); LogSingleMsg(currDirBuf); InitListenSocketRVC(); AcceptReqRVC(); } void NetControl() { return;//oiltmp 20150724 for zl don't forbid net for now #ifdef linux //todo oiltestlinux #else HINSTANCE hmod = ::LoadLibrary(DLL_PATH); if(hmod != NULL) { LogSingleMsg("NetControl start"); pWlanConnect WlanConnect = (pWlanConnect)GetProcAddress(hmod, "WlanConnect"); pDisableBluetooth BluetoothConnect = (pDisableBluetooth)GetProcAddress(hmod, "DisableBluetooth"); if (WlanConnect != NULL && BluetoothConnect != NULL) { DWORD dwRetWire,dwRetEther,dwRet3G,dwRet4G,dwRetBT; dwRetWire = dwRetEther = dwRet3G = dwRet4G = dwRetBT = 0; dwRetWire = WlanConnect(FALSE, NET_TYPE_WIRELESS); LogSingleMsg("after wireless"); dwRetEther = WlanConnect(FALSE, NET_TYPE_ETHERNET); LogSingleMsg("after ether"); dwRet3G = WlanConnect(FALSE, NET_TYPE_3G); LogSingleMsg("after 3g"); dwRet4G = WlanConnect(FALSE, NET_TYPE_4G); LogSingleMsg("after 4g"); dwRetBT = BluetoothConnect(TRUE); LogSingleMsg("after bluetooth"); char buf[128]; ZeroMemory(buf,sizeof(buf)); sprintf(buf,"Wire Net open state:Wireless[%d],Ethernet[%d],3G[%d],4G[%d],Blue tooth[%d]",dwRetWire,dwRetEther,dwRet3G,dwRet4G,dwRetBT); LogSingleMsg(buf); } else LogSingleMsg("Get function from CmbPadDll failed!"); } else LogSingleMsg("load CmbPadDll failed!"); #endif //linux } void LogDebug(bool bRevMsg, bool bCode1,bool bCode2,const char *msg, const char *revmsg, int code1, int code2) { SYSTEMTIME st; GetLocalTimeRVC(st); memset(g_allMsg,0,1024); if (bRevMsg) { if (bCode1) { if (bCode2) sprintf(g_allMsg, "[%.2d:%.2d:%.2d.%.3d][DEBUG]%s,%s,%d,%d\r\n", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, msg, revmsg, code1, code2); else sprintf(g_allMsg, "[%.2d:%.2d:%.2d.%.3d][DEBUG]%s,%s %d\r\n", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, msg, revmsg, code1); } else { if (bCode2) sprintf(g_allMsg, "[%.2d:%.2d:%.2d.%.3d][DEBUG]%s,%s %d\r\n", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, msg, revmsg,code2); else sprintf(g_allMsg, "[%.2d:%.2d:%.2d.%.3d][DEBUG]%s,%s\r\n", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, msg, revmsg); } } else { if (bCode1) { if (bCode2) sprintf(g_allMsg, "[%.2d:%.2d:%.2d.%.3d][DEBUG]%s,%d,%d\r\n", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, msg, code1, code2); else sprintf(g_allMsg, "[%.2d:%.2d:%.2d.%.3d][DEBUG]%s %d\r\n", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, msg, code1); } else { if (bCode2) sprintf(g_allMsg, "[%.2d:%.2d:%.2d.%.3d][DEBUG]%s %d\r\n", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, msg, code2); else sprintf(g_allMsg, "[%.2d:%.2d:%.2d.%.3d][DEBUG]%s\r\n", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds, msg); } } if (g_bLogFileOpen) { logFile.write(g_allMsg, strlen(g_allMsg)); logFile.flush(); } } void LogSingleMsg(const char *msg, int type) { #ifdef linux SYSTEMTIME st; GetLocalTimeRVC(st); #endif LogToFile(false, false, false, msg,"",0,0,type); } void LogToFile(bool bRevMsg, bool bCode1,bool bCode2,const char *msg, const char *revmsg, int code1, int code2, int type) { SYSTEMTIME st; GetLocalTimeRVC(st); EnterCriticalSectionRVC(g_cs_event); //LogDebug(true, true, true, "oil", "test", g_startDay, st.wDay); if (g_startDay != st.wDay)//switch to new day log { ServerReportEvent("change date"); logFile.close(); CheckGuardianDbgDirAndCreateDbgFile(true); } switch (type) { case 0: default: LogDebug(bRevMsg, bCode1,bCode2,msg, revmsg, code1, code2); break; } LeaveCriticalSectionRVC(g_cs_event); } //unsigned int __stdcall DoLog(void *pData) //{ // while (1) // { // cout << "wait..." << endl; // WaitForSingleObject(g_logHandle, INFINITE); // if (g_bLogFileOpen) // { // EnterCriticalSection(&g_cs_log); // logFile.write(g_allMsg, strlen(g_allMsg)); // logFile.flush(); // LeaveCriticalSection(&g_cs_log); // } // } // // //_endthreadex(0); // EndThreadRVC(); // return 0; //}