DWORD WINAPI Interface::CommandThreadSend( LPVOID data ) { try { while (!wakeup && !endThread) Sleep(10); while ( !endThread ) { CommandList::iterator it; CommandList::iterator insertAt = cmdlist.end(); if ( !tmplist.empty() ) { cs.StartSession(); cmdlist.splice( cmdlist.begin(), tmplist ); cs.EndSession(); } for ( it = cmdlist.begin(); it != cmdlist.end() && !endThread; ) { if ( !tmplist.empty() ) { cs.StartSession(); unsigned int count = tmplist.size(); if ( insertAt != cmdlist.end() ) { CommandList::iterator insertAt_tmp = insertAt; ++insertAt_tmp; cmdlist.splice( insertAt_tmp, tmplist ); } else { CommandList::iterator it_tmp = it; ++it_tmp; cmdlist.splice( it_tmp, tmplist ); } CommandList::iterator it_tmp = it; advance( it_tmp, count ); insertAt = it_tmp; cs.EndSession(); } map<string, string>::iterator al = alias.find(it->first->first); string name = (al != alias.end() ? al->second : it->first->first); string def = defs.find(name)->second; ParamContainer& param = it->first->second; vector<signed int>& data = it->second; if (data[2] != 0) { data[2]--; ++it; continue; } multimap<string, string> cmd = Interface::Evaluate(name, def, param); if (cmd.size() != 0) { signed int key = data[3]; CommandParsed stream = API::Translate(cmd, key); if (stream.size() != 0) { CommandParsed::iterator it2; for (it2 = stream.begin(); it2 != stream.end() && !endThread; ++it2) { char* content = *it2; pipeServer->Send(content); } for (it2 = stream.begin(); it2 != stream.end(); ++it2) { char* content = *it2; delete[] content; } } } if (data[0] == 0) { FreeContainer(param); natives.erase(it->first); it = cmdlist.erase(it); } else ++it; } } } catch (std::exception& e) { try { VaultException& vaulterror = dynamic_cast<VaultException&>(e); vaulterror.Message(); } catch (std::bad_cast& no_vaulterror) { VaultException vaulterror(e.what()); vaulterror.Message(); } #ifdef VAULTMP_DEBUG if (debug != NULL) debug->Print("Send thread is going to terminate (ERROR)", true); #endif return ((DWORD) data); } return ((DWORD) data); }
DWORD WINAPI Interface::CommandThreadReceive( LPVOID data ) { try { pipeClient->SetPipeAttributes( "BethesdaClient", PIPE_LENGTH ); pipeClient->CreateServer(); pipeClient->ConnectToServer(); pipeServer->SetPipeAttributes( "BethesdaServer", PIPE_LENGTH ); while ( !pipeServer->ConnectToServer() && !endThread ); char buffer[PIPE_LENGTH]; char code; if ( !endThread ) { do { ZeroMemory( buffer, sizeof( buffer ) ); pipeClient->Receive( buffer ); code = buffer[0]; char* content = buffer + 1; if ( code == PIPE_OP_RETURN || code == PIPE_OP_RETURN_BIG ) { vector<CommandResult> result = API::Translate( buffer ); vector<CommandResult>::iterator it; for ( it = result.begin(); it != result.end(); ++it ) resultHandler( it->first.first.first, it->first.first.second, it->first.second, it->second ); } else if ( code == PIPE_SYS_WAKEUP ) { wakeup = true; #ifdef VAULTMP_DEBUG if ( debug != NULL ) debug->Print( "vaultmp process waked up (game patched)", true ); #endif } else if ( code ) throw VaultException( "Unknown pipe code identifier %02X", code ); if ( lookupProgramID( ( char* ) data ) == 0 ) { endThread = true; #ifdef VAULTMP_DEBUG if ( debug != NULL ) debug->Print( "Game process missing, shutting down", true ); #endif } } while ( code != PIPE_ERROR_CLOSE && !endThread ); } // kill game process if running } catch ( std::exception& e ) { try { VaultException& vaulterror = dynamic_cast<VaultException&>( e ); vaulterror.Message(); } catch ( std::bad_cast& no_vaulterror ) { VaultException vaulterror( e.what() ); vaulterror.Message(); } #ifdef VAULTMP_DEBUG if ( debug != NULL ) debug->Print( "Receive thread is going to terminate (ERROR)", true ); #endif endThread = true; return ( ( DWORD ) data ); } #ifdef VAULTMP_DEBUG if ( debug != NULL ) debug->Print( "Receive thread is going to terminate", true ); #endif endThread = true; return ( ( DWORD ) data ); }
void Interface::CommandThreadReceive(bool steam) { try { pipeClient->SetPipeAttributes("BethesdaClient", PIPE_LENGTH); pipeClient->CreateServer(); pipeClient->ConnectToServer(); pipeServer->SetPipeAttributes("BethesdaServer", PIPE_LENGTH); while (!pipeServer->ConnectToServer() && !endThread); unsigned char buffer[PIPE_LENGTH]; buffer[0] = steam; pipeClient->Send(buffer); if (!endThread) { unsigned char code; while (!endThread) { ZeroMemory(buffer, sizeof(buffer)); pipeClient->Receive(buffer); code = buffer[0]; if (code == PIPE_OP_RETURN || code == PIPE_OP_RETURN_BIG || code == PIPE_OP_RETURN_RAW) { vector<CommandResult> result = API::Translate(buffer); for (CommandResult& _result : result) { resultHandler(get<0>(_result), get<1>(_result), get<2>(_result), get<3>(_result)); if (endThread) break; } } else if (code == PIPE_SYS_WAKEUP) { wakeup = true; #ifdef VAULTMP_DEBUG if (debug) debug->Print("vaultmp process waked up (game patched)", true); #endif } else if (code == PIPE_ERROR_CLOSE) { if (!endThread) throw VaultException("Error in vaultmp.dll"); } else if (code) throw VaultException("Unknown pipe code identifier %02X", code); else endThread = true; } } } catch (exception& e) { try { VaultException& vaulterror = dynamic_cast<VaultException&>(e); vaulterror.Message(); } catch (bad_cast& no_vaulterror) { VaultException vaulterror(e.what()); vaulterror.Message(); } #ifdef VAULTMP_DEBUG if (debug) debug->Print("Receive thread is going to terminate (ERROR)", true); #endif } endThread = true; }
void Interface::CommandThreadSend() { try { while (!wakeup && !endThread) this_thread::sleep_for(chrono::milliseconds(10)); while (!endThread) { static_cs.StartSession(); for (auto it = static_cmdlist.begin(); (it != static_cmdlist.end() || !dynamic_cmdlist.empty()) && !endThread;) { if (it != static_cmdlist.end()) { const auto& next_list = *it; for (auto it = next_list.begin(); it != next_list.end() && !endThread; ++it) { vector<string> cmd = Interface::Evaluate(*it); if (!cmd.empty()) { CommandParsed stream = API::Translate(cmd); for (auto it = stream.begin(); it != stream.end() && !endThread; ++it) pipeServer->Send(it->get()); } } ++it; } dynamic_cs.StartSession(); for (; !dynamic_cmdlist.empty() && !endThread; natives.erase(dynamic_cmdlist.front().first), dynamic_cmdlist.pop_front()) { dynamic_cs.EndSession(); const auto& dynamic = dynamic_cmdlist.front(); vector<string> cmd = Interface::Evaluate(dynamic.first); if (!cmd.empty()) { CommandParsed stream = API::Translate(cmd, dynamic.second); for (auto it = stream.begin(); it != stream.end() && !endThread; ++it) pipeServer->Send(it->get()); } dynamic_cs.StartSession(); } dynamic_cs.EndSession(); this_thread::sleep_for(chrono::milliseconds(1)); } static_cs.EndSession(); } } catch (exception& e) { try { VaultException& vaulterror = dynamic_cast<VaultException&>(e); vaulterror.Message(); } catch (bad_cast& no_vaulterror) { VaultException vaulterror(e.what()); vaulterror.Message(); } #ifdef VAULTMP_DEBUG if (debug) debug->Print("Send thread is going to terminate (ERROR)", true); #endif } if (wakeup) { unsigned char buffer[PIPE_LENGTH]; buffer[0] = PIPE_ERROR_CLOSE; pipeServer->Send(buffer); } endThread = true; }
int main(int argc, char* argv[]) { #ifdef VAULTMP_DEBUG #ifdef __WIN32__ if (LoadLibrary("exchndl.dll") == NULL) return 0; #else system("ulimit -c unlimited"); #endif #endif #ifdef __WIN32__ printf("Vault-Tec dedicated server %s (Windows)\n----------------------------------------------------------\n", DEDICATED_VERSION); #else printf("Vault-Tec dedicated server %s (Unix)\n----------------------------------------------------------\n", DEDICATED_VERSION); #endif unsigned char game; int port; int players; int fileslots; bool query; bool files; const char* announce; const char* scripts; const char* mods; const char* savegame; dictionary* config = iniparser_load(argc > 1 ? argv[1] : "vaultserver.ini"); const char* game_str = iniparser_getstring(config, "general:game", "fallout3"); if (stricmp(game_str, "newvegas") == 0) game = NEWVEGAS; else game = FALLOUT3; port = iniparser_getint(config, "general:port", RAKNET_STANDARD_PORT); players = iniparser_getint(config, "general:players", RAKNET_STANDARD_CONNECTIONS); query = (bool) iniparser_getboolean(config, "general:query", 1); files = (bool) iniparser_getboolean(config, "general:fileserve", 0); fileslots = iniparser_getint(config, "general:fileslots", 8); announce = iniparser_getstring(config, "general:master", "vaultmp.com"); savegame = iniparser_getstring(config, "general:save", "default.fos"); scripts = iniparser_getstring(config, "scripts:scripts", ""); mods = iniparser_getstring(config, "mods:mods", ""); ServerEntry* self = new ServerEntry(game); self->SetServerRule("version", DEDICATED_VERSION); Dedicated::SetServerEntry(self); char base[MAX_PATH]; _getcwd(base, sizeof(base)); try { putenv(PWNFILES_PATH); char _scripts[strlen(scripts) + 1]; snprintf(_scripts, sizeof(_scripts), "%s", scripts); Script::LoadScripts(_scripts, base); } catch (std::exception& e) { try { VaultException& vaulterror = dynamic_cast<VaultException&>(e); vaulterror.Console(); } catch (std::bad_cast& no_vaulterror) { VaultException vaulterror(e.what()); vaulterror.Console(); } } try { char file[MAX_PATH]; snprintf(file, sizeof(file), "%s/%s/%s", base, SAVEGAME_PATH, savegame); unsigned int crc; if (!Utils::crc32file(file, &crc)) throw VaultException("Could not find savegame %s in folder %s", savegame, SAVEGAME_PATH); Dedicated::SetSavegame(Savegame(string(savegame), crc)); char buf[strlen(mods) + 1]; strcpy(buf, mods); char* token = strtok(buf, ","); ModList modfiles; while (token != NULL) { snprintf(file, sizeof(file), "%s/%s/%s", base, MODFILES_PATH, token); if (!Utils::crc32file(file, &crc)) throw VaultException("Could not find modfile %s in folder %s", token, MODFILES_PATH); modfiles.push_back(pair<string, unsigned int>(string(token), crc)); token = strtok(NULL, ","); } Dedicated::SetModfiles(modfiles); thread hDedicatedThread = Dedicated::InitializeServer(port, players, announce, query, files, fileslots); thread hInputThread = thread(InputThread); hDedicatedThread.join(); if (hInputThread.joinable()) hInputThread.join(); } catch (std::exception& e) { try { VaultException& vaulterror = dynamic_cast<VaultException&>(e); vaulterror.Console(); } catch (std::bad_cast& no_vaulterror) { VaultException vaulterror(e.what()); vaulterror.Console(); } } Script::UnloadScripts(); iniparser_freedict(config); delete self; #ifdef __WIN32__ system("PAUSE"); #endif return 0; }