void Widget::stopServer() { logStatusMessage("Stopping all server operations"); pingTimer->stop(); tcpServer->close(); for (int i=0;i<tcpClientsList.size();i++) tcpClientsList[i]->close(); udpSocket->close(); sync.stopSync(); disconnect(ui->sendButton, SIGNAL(clicked()), this, SLOT(sendCmdLine())); disconnect(udpSocket, SIGNAL(readyRead()),this, SLOT(udpProcessPendingDatagrams())); disconnect(tcpServer, SIGNAL(newConnection()), this, SLOT(tcpConnectClient())); disconnect(pingTimer, SIGNAL(timeout()), this, SLOT(checkPingTimeouts())); disconnect(this); }
/// Reads the config file (server.ini) and start the server accordingly void Widget::startServer() { logStatusMessage("Private server v0.5.2"); #ifdef __APPLE__ // this fixes the directory in OSX so we can use the relative CONFIGFILEPATH and etc properly CFBundleRef mainBundle = CFBundleGetMainBundle(); CFURLRef resourcesURL = CFBundleCopyBundleURL(mainBundle); char path[PATH_MAX]; if (!CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8 *)path, PATH_MAX)) { // error! } CFRelease(resourcesURL); // the path we get is to the .app folder, so we go up after we chdir chdir(path); chdir(".."); #endif lastNetviewId=0; lastId=1; /// Read config logStatusMessage("Reading config file ..."); QSettings config(CONFIGFILEPATH, QSettings::IniFormat); loginPort = config.value("loginPort", 1031).toInt(); gamePort = config.value("gamePort", 1039).toInt(); maxConnected = config.value("maxConnected",128).toInt(); maxRegistered = config.value("maxRegistered",2048).toInt(); pingTimeout = config.value("pingTimeout", 15).toInt(); pingCheckInterval = config.value("pingCheckInterval", 5000).toInt(); logInfos = config.value("logInfosMessages", true).toBool(); saltPassword = config.value("saltPassword", "Change Me").toString(); enableSessKeyValidation = config.value("enableSessKeyValidation", true).toBool(); enableLoginServer = config.value("enableLoginServer", true).toBool(); enableGameServer = config.value("enableGameServer", true).toBool(); enableMultiplayer = config.value("enableMultiplayer", true).toBool(); syncInterval = config.value("syncInterval",DEFAULT_SYNC_INTERVAL).toInt(); remoteLoginIP = config.value("remoteLoginIP", "127.0.0.1").toString(); remoteLoginPort = config.value("remoteLoginPort", 1031).toInt(); remoteLoginTimeout = config.value("remoteLoginTimeout", 5000).toInt(); useRemoteLogin = config.value("useRemoteLogin", false).toBool(); enableGetlog = config.value("enableGetlog", true).toBool(); /// Init servers tcpClientsList.clear(); #if defined _WIN32 || defined WIN32 startTimestamp = GetTickCount(); #elif __APPLE__ timeval time; gettimeofday(&time, NULL); startTimestamp = (time.tv_sec * 1000) + (time.tv_usec / 1000); #else struct timespec tp; clock_gettime(CLOCK_MONOTONIC, &tp); startTimestamp = tp.tv_sec*1000 + tp.tv_nsec/1000/1000; #endif /// Read vortex DB if (enableGameServer) { bool corrupted=false; QDir vortexDir("data/vortex/"); QStringList files = vortexDir.entryList(QDir::Files); int nVortex=0; for (int i=0; i<files.size(); i++) // For each vortex file { // Each file is a scene Scene scene(files[i].split('.')[0]); QFile file("data/vortex/"+files[i]); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { logStatusMessage("Error reading vortex DB"); return; } QByteArray data = file.readAll(); data.replace('\r', ""); QList<QByteArray> lines = data.split('\n'); // Each line is a vortex for (int j=0; j<lines.size(); j++) { if (lines[j].size() == 0) // Skip empty lines continue; nVortex++; Vortex vortex; bool ok1, ok2, ok3, ok4; QList<QByteArray> elems = lines[j].split(' '); if (elems.size() < 5) { logStatusMessage("Vortex DB is corrupted. Incorrect line (" +QString().setNum(elems.size())+" elems), file " + files[i]); corrupted=true; break; } vortex.id = elems[0].toInt(&ok1, 16); vortex.destName = elems[1]; for (int j=2; j<elems.size() - 3;j++) // Concatenate the string between id and poss vortex.destName += " "+elems[j]; vortex.destPos.x = elems[elems.size()-3].toFloat(&ok2); vortex.destPos.y = elems[elems.size()-2].toFloat(&ok3); vortex.destPos.z = elems[elems.size()-1].toFloat(&ok4); if (!(ok1&&ok2&&ok3&&ok4)) { logStatusMessage("Vortex DB is corrupted. Conversion failed, file " + files[i]); corrupted=true; break; } scene.vortexes << vortex; //win.logMessage("Add vortex "+QString().setNum(vortex.id)+" to "+vortex.destName+" " // +QString().setNum(vortex.destPos.x)+" " // +QString().setNum(vortex.destPos.y)+" " // +QString().setNum(vortex.destPos.z)); } scenes << scene; } if (corrupted) { stopServer(); return; } logMessage("Loaded " + QString().setNum(nVortex) + " vortexes in " + QString().setNum(scenes.size()) + " scenes"); } /// Read/parse Items.xml if (enableGameServer) { QFile itemsFile("data/data/Items.xml"); if (itemsFile.open(QIODevice::ReadOnly)) { QByteArray data = itemsFile.readAll(); wearablePositionsMap = parseItemsXml(data); win.logMessage("Loaded "+QString().setNum(wearablePositionsMap.size())+" items"); } else { win.logMessage("Couln't open Items.xml"); stopServer(); return; } } /// Read NPC/Quests DB if (enableGameServer) { try { unsigned nQuests = 0; QDir npcsDir("data/npcs/"); QStringList files = npcsDir.entryList(QDir::Files); for (int i=0; i<files.size(); i++, nQuests++) // For each vortex file { try { Quest quest("data/npcs/"+files[i], NULL); quests << quest; npcs << quest.npc; } catch (QString& error) { win.logMessage(error); win.stopServer(); throw error; } } logMessage("Loaded "+QString().setNum(nQuests)+" quests/npcs."); } catch (QString& e) { enableGameServer = false; } } if (enableLoginServer) { // logStatusMessage("Loading players database ..."); tcpPlayers = Player::loadPlayers(); } // TCP server if (enableLoginServer) { logStatusMessage("Starting TCP login server on port "+QString().setNum(loginPort)+" ..."); if (!tcpServer->listen(QHostAddress::Any,loginPort)) { logStatusMessage("TCP: Unable to start server on port "+QString().setNum(loginPort)+": "+tcpServer->errorString()); stopServer(); return; } // If we use a remote login server, try to open a connection preventively. if (useRemoteLogin) remoteLoginSock.connectToHost(remoteLoginIP, remoteLoginPort); } // UDP server if (enableGameServer) { logStatusMessage("Starting UDP game server on port "+QString().setNum(gamePort)+" ..."); if (!udpSocket->bind(gamePort, QUdpSocket::ReuseAddressHint|QUdpSocket::ShareAddress)) { logStatusMessage("UDP: Unable to start server on port "+QString().setNum(gamePort)); stopServer(); return; } } if (enableGameServer) { // Start ping timeout timer pingTimer->start(pingCheckInterval); } if (enableMultiplayer) sync.startSync(); if (enableLoginServer || enableGameServer) logStatusMessage("Server started"); connect(ui->sendButton, SIGNAL(clicked()), this, SLOT(sendCmdLine())); if (enableLoginServer) connect(tcpServer, SIGNAL(newConnection()), this, SLOT(tcpConnectClient())); if (enableGameServer) { connect(udpSocket, SIGNAL(readyRead()),this, SLOT(udpProcessPendingDatagrams())); connect(pingTimer, SIGNAL(timeout()), this, SLOT(checkPingTimeouts())); } }
void Widget::startServer() { logStatusMessage("Private server v0.4.2"); lastNetviewId=0; lastId=0; /// Read config logStatusMessage("Reading config file ..."); QSettings config(CONFIGFILEPATH, QSettings::IniFormat); loginPort = config.value("loginPort", 1031).toInt(); gamePort = config.value("gamePort", 1039).toInt(); maxConnected = config.value("maxConnected",128).toInt(); maxRegistered = config.value("maxRegistered",2048).toInt(); pingTimeout = config.value("pingTimeout", 15).toInt(); pingCheckInterval = config.value("pingCheckInterval", 5000).toInt(); logInfos = config.value("logInfosMessages", true).toBool(); saltPassword = config.value("saltPassword", "Change Me").toString(); enableLoginServer = config.value("enableLoginServer", true).toBool(); enableGameServer = config.value("enableGameServer", true).toBool(); enableMultiplayer = config.value("enableMultiplayer", true).toBool(); syncInterval = config.value("syncInterval",DEFAULT_SYNC_INTERVAL).toInt(); remoteLoginIP = config.value("remoteLoginIP", "127.0.0.1").toString(); remoteLoginPort = config.value("remoteLoginPort", 1031).toInt(); remoteLoginTimeout = config.value("remoteLoginTimeout", 5000).toInt(); useRemoteLogin = config.value("useRemoteLogin", false).toBool(); /// Init servers tcpClientsList.clear(); #ifdef WIN32 startTimestamp = GetTickCount(); #else struct timespec tp; clock_gettime(CLOCK_MONOTONIC, &tp); startTimestamp = tp.tv_sec*1000 + tp.tv_nsec/1000/1000; #endif // Read vortex DB if (enableGameServer) { bool corrupted=false; QDir vortexDir("data/vortex/"); QStringList files = vortexDir.entryList(QDir::Files); int nVortex=0; for (int i=0; i<files.size(); i++) // For each vortex file { Scene scene(files[i].split('.')[0]); QFile file("data/vortex/"+files[i]); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { logStatusMessage("Error reading vortex DB"); return; } QByteArray data = file.readAll(); data.replace('\r', ""); QList<QByteArray> lines = data.split('\n'); for (int j=0; j<lines.size(); j++) { if (lines[j].size() == 0) // Skip empty lines continue; nVortex++; Vortex vortex; bool ok1, ok2, ok3, ok4; QList<QByteArray> elems = lines[j].split(' '); if (elems.size() < 5) { logStatusMessage("Vortex DB is corrupted. Incorrect line (" +QString().setNum(elems.size())+" elems), file " + files[i]); corrupted=true; break; } vortex.id = elems[0].toInt(&ok1, 16); vortex.destName = elems[1]; for (int j=2; j<elems.size() - 3;j++) // Concatenate the string between id and poss vortex.destName += " "+elems[j]; vortex.destPos.x = elems[elems.size()-3].toFloat(&ok2); vortex.destPos.y = elems[elems.size()-2].toFloat(&ok3); vortex.destPos.z = elems[elems.size()-1].toFloat(&ok4); if (!(ok1&&ok2&&ok3&&ok4)) { logStatusMessage("Vortex DB is corrupted. Conversion failed, file " + files[i]); corrupted=true; break; } scene.vortexes << vortex; //win.logMessage("Add vortex "+QString().setNum(vortex.id)+" to "+vortex.destName+" " // +QString().setNum(vortex.destPos.x)+" " // +QString().setNum(vortex.destPos.y)+" " // +QString().setNum(vortex.destPos.z)); } scenes << scene; } if (corrupted) { stopServer(); return; } logMessage("Loaded " + QString().setNum(nVortex) + " vortex in " + QString().setNum(scenes.size()) + " scenes"); } // Read NPC/Quests DB if (enableGameServer) { try { unsigned nQuests = 0; QDir npcsDir("data/npcs/"); QStringList files = npcsDir.entryList(QDir::Files); for (int i=0; i<files.size(); i++, nQuests++) // For each vortex file { Quest *quest = new Quest("data/npcs/"+files[i]); quests << *quest; npcs << quest->npc; } logMessage("Loaded "+QString().setNum(nQuests)+" quests/npcs."); } catch (QString e) { enableGameServer = false; } } if (enableLoginServer) { // logStatusMessage("Loading players database ..."); tcpPlayers = Player::loadPlayers(); } // TCP server if (enableLoginServer) { logStatusMessage("Starting TCP login server on port "+QString().setNum(loginPort)+" ..."); if (!tcpServer->listen(QHostAddress::Any,loginPort)) { logStatusMessage("TCP: Unable to start server on port "+QString().setNum(loginPort)+": "+tcpServer->errorString()); stopServer(); return; } // If we use a remote login server, try to open a connection preventively. if (useRemoteLogin) remoteLoginSock.connectToHost(remoteLoginIP, remoteLoginPort); } // UDP server if (enableGameServer) { logStatusMessage("Starting UDP game server on port "+QString().setNum(gamePort)+" ..."); if (!udpSocket->bind(gamePort, QUdpSocket::ReuseAddressHint|QUdpSocket::ShareAddress)) { logStatusMessage("UDP: Unable to start server on port "+QString().setNum(gamePort)); stopServer(); return; } } if (enableGameServer) { // Start ping timeout timer pingTimer->start(pingCheckInterval); } if (enableMultiplayer) sync.startSync(); if (enableLoginServer || enableGameServer) logStatusMessage("Server started"); connect(ui->sendButton, SIGNAL(clicked()), this, SLOT(sendCmdLine())); if (enableLoginServer) connect(tcpServer, SIGNAL(newConnection()), this, SLOT(tcpConnectClient())); if (enableGameServer) { connect(udpSocket, SIGNAL(readyRead()),this, SLOT(udpProcessPendingDatagrams())); connect(pingTimer, SIGNAL(timeout()), this, SLOT(checkPingTimeouts())); } }
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow) { #ifndef _DEBUG SingleInstance dcapp(_T("{AIRDC-AEE8350A-B49A-4753-AB4B-E55479A48351}")); #else SingleInstance dcapp(_T("{AIRDC-AEE8350A-B49A-4753-AB4B-E55479A48350}")); #endif if(dcapp.IsAnotherInstanceRunning()) { // Allow for more than one instance... bool multiple = false; if(_tcslen(lpstrCmdLine) == 0) { if (::MessageBox(NULL, _T("There is already an instance of AirDC++ running.\nDo you want to launch another instance anyway?"), _T(APPNAME) _T(" ") _T(VERSIONSTRING), MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2 | MB_TOPMOST) == IDYES) { multiple = true; } } if(multiple == false) { HWND hOther = NULL; EnumWindows(searchOtherInstance, (LPARAM)&hOther); if( hOther != NULL ) { // pop up ::SetForegroundWindow(hOther); if( IsIconic(hOther)) { // restore ::ShowWindow(hOther, SW_RESTORE); } sendCmdLine(hOther, lpstrCmdLine); } return FALSE; } } // For SHBrowseForFolder, UPnP_COM HRESULT hRes = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); #ifdef _DEBUG EXTENDEDTRACEINITIALIZE(Util::getPath(Util::PATH_RESOURCES).c_str()); #endif LPTOP_LEVEL_EXCEPTION_FILTER pOldSEHFilter = NULL; pOldSEHFilter = SetUnhandledExceptionFilter(&DCUnhandledExceptionFilter); AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES | ICC_LISTVIEW_CLASSES | ICC_TREEVIEW_CLASSES | ICC_PROGRESS_CLASS | ICC_STANDARD_CLASSES | ICC_TAB_CLASSES | ICC_UPDOWN_CLASS | ICC_USEREX_CLASSES); // add flags to support other controls hRes = _Module.Init(NULL, hInstance); ATLASSERT(SUCCEEDED(hRes)); try { File f(WinUtil::getAppName(), File::READ, File::OPEN); TigerTree tth(TigerTree::calcBlockSize(f.getSize(), 1)); size_t n = 0; size_t n2 = DEBUG_BUFSIZE; while( (n = f.read(buf, n2)) > 0) { tth.update(buf, n); n2 = DEBUG_BUFSIZE; } tth.finalize(); strcpy(::tth, tth.getRoot().toBase32().c_str()); WinUtil::tth = Text::toT(::tth); } catch(const FileException&) { dcdebug("Failed reading exe\n"); } HINSTANCE hInstRich = ::LoadLibrary(_T("MSFTEDIT.DLL")); if (hInstRich == NULL) { MessageBox(NULL, _T("AirDC++ isn't supported in operating systems older than Microsoft Windows XP3"), _T(APPNAME) _T(" ") _T(VERSIONSTRING), MB_OK | MB_ICONEXCLAMATION); return FALSE; } int nRet = Run(lpstrCmdLine, nCmdShow); if ( hInstRich ) { ::FreeLibrary(hInstRich); } // Return back old VS SEH handler if (pOldSEHFilter != NULL) SetUnhandledExceptionFilter(pOldSEHFilter); _Module.Term(); ::CoUninitialize(); #ifdef _DEBUG EXTENDEDTRACEUNINITIALIZE(); #endif return nRet; }
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow) { g_RunningUnderWine = running_under_wine(); #ifdef PPA_INCLUDE_CHECK_UPDATE if (_tcsstr(lpstrCmdLine, _T(PEERS_OPTION_NO_UPDATE)) == NULL) { string updatePath = Text::fromT(AutoUpdate::getUpdateTargetPath()); //TODO нужно еще exists(wstring), чтобы строку не преобразовывать if (File::exists(updatePath) && File::getSize(updatePath) > 0) { if (AutoUpdate::execute()) { return AutoUpdate::EXIT_TO_UPDATE; } } } //TODO else вывести сообщение если архив обновления еще есть. #endif #ifndef _DEBUG SingleInstance dcapp(_T("{DOMODC-AEE8350A-B49A-4753-AB4B-E55479A48351}")); #else SingleInstance dcapp(_T("{DOMODC-AEE8350A-B49A-4753-AB4B-E55479A48350}")); #endif // !SMT!-UI displaying abort message will disable generating exceptioninfo.txt signal(SIGABRT, AbortSignalHandler); #ifndef SMT_CUSTOM _set_abort_behavior(0, _WRITE_ABORT_MSG); #endif bool multipleInstances = false; bool magnet = false; bool delay = false; #ifdef _DEBUG g_DisableSplash = true; #endif if(_tcsstr(lpstrCmdLine, _T("/nologo"))!=NULL || _tcsstr(lpstrCmdLine, _T("/startup"))!=NULL) { g_DisableSplash = true; nCmdShow = SW_SHOWMINIMIZED; } if(_tcsstr(lpstrCmdLine, _T("/wine"))!=NULL) g_RunningUnderWine = true; if(_tcsstr(lpstrCmdLine, _T("/q"))!=NULL) multipleInstances = true; if(_tcsstr(lpstrCmdLine, _T("/magnet"))!=NULL) magnet = true; if(_tcsstr(lpstrCmdLine, _T("/c")) != NULL) { multipleInstances = true; delay = true; } if(dcapp.IsAnotherInstanceRunning()) { // Allow for more than one instance... bool multiple = false; if (multipleInstances == false && magnet == false) { if (::MessageBox(NULL, _T(APPNAME) _T(" уже запущена, или еще не закончила операцию закрытия...\nВы уверены, что хотите загрузить еще одну копию программы?"), _T(APPNAME) _T(" ") _T(VERSIONSTRING), MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2 | MB_TOPMOST) == IDYES) { multiple = true; } } else { multiple = true; } if(delay == true) { Thread::sleep(2500); // let's put this one out for a break } if(multiple == false || magnet == true) { HWND hOther = NULL; EnumWindows(searchOtherInstance, (LPARAM)&hOther); if (hOther != NULL) { // pop up ::SetForegroundWindow(hOther); //if (IsIconic(hOther)) { // ::ShowWindow(hOther, SW_RESTORE); // !SMT!-f - disable, it unlocks password-protected instance //} sendCmdLine(hOther, lpstrCmdLine); } return FALSE; } } srand((unsigned) time(NULL)); // For SHBrowseForFolder, UPnP HRESULT hRes = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); // before next function call Util::initialize(); #ifdef _DEBUG InitSymInfo(Text::toT(Util::getDataPath()).c_str()); #endif LPTOP_LEVEL_EXCEPTION_FILTER pOldSEHFilter = NULL; pOldSEHFilter = SetUnhandledExceptionFilter(&DCUnhandledExceptionFilter); WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES | ICC_LISTVIEW_CLASSES | ICC_TREEVIEW_CLASSES | ICC_PROGRESS_CLASS | ICC_STANDARD_CLASSES | ICC_TAB_CLASSES | ICC_UPDOWN_CLASS | ICC_USEREX_CLASSES); // add flags to support other controls hRes = _Module.Init(NULL, hInstance); ATLASSERT(SUCCEEDED(hRes)); /* !PPA! try { File f(WinUtil::getAppName(), File::READ, File::OPEN); TigerTree tth(TigerTree::calcBlockSize(f.getSize(), 1)); size_t n = 0; size_t n2 = DEBUG_BUFSIZE; while( (n = f.read(buf, n2)) > 0) { tth.update(buf, n); n2 = DEBUG_BUFSIZE; } tth.finalize(); strcpy(::tth, tth.getRoot().toBase32().c_str()); WinUtil::tth = Text::toT(::tth); } catch(const FileException&) { dcdebug("Failed reading exe\n"); } */ HINSTANCE hInstRich = ::LoadLibrary(_T("RICHED20.DLL")); int nRet = Run(lpstrCmdLine, nCmdShow); if ( hInstRich ) { ::FreeLibrary(hInstRich); } // Return back old VS SEH handler if (pOldSEHFilter != NULL) { SetUnhandledExceptionFilter(pOldSEHFilter); } _Module.Term(); ::CoUninitialize(); ::WSACleanup(); #ifdef _DEBUG UninitSymInfo(); #endif return nRet; }