From 1fd40424e484b5308d8122f23a8c30faa3159e43 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Mon, 4 Jan 2016 00:00:07 +0100 Subject: [PATCH] Some discovery stuff. --- src/Components/Loader.cpp | 5 +- src/Components/Loader.hpp | 1 + src/Components/Modules/Dedicated.cpp | 30 +----- src/Components/Modules/Discovery.cpp | 59 +++++++++-- src/Components/Modules/Discovery.hpp | 2 + src/Components/Modules/Flags.cpp | 46 +++++++++ src/Components/Modules/Flags.hpp | 17 ++++ src/Components/Modules/Network.cpp | 51 +++++++++- src/Components/Modules/Network.hpp | 5 +- src/Components/Modules/Party.cpp | 6 +- src/Components/Modules/ServerList.cpp | 135 +++++++++++++++++++------- src/Components/Modules/ServerList.hpp | 10 ++ src/Components/Modules/Singleton.cpp | 2 +- src/Game/Functions.cpp | 4 + src/Game/Functions.hpp | 6 ++ src/Game/Structs.hpp | 8 +- src/STDInclude.hpp | 2 + 17 files changed, 306 insertions(+), 83 deletions(-) create mode 100644 src/Components/Modules/Flags.cpp create mode 100644 src/Components/Modules/Flags.hpp diff --git a/src/Components/Loader.cpp b/src/Components/Loader.cpp index 65882eea..7a08886b 100644 --- a/src/Components/Loader.cpp +++ b/src/Components/Loader.cpp @@ -6,7 +6,7 @@ namespace Components void Loader::Initialize() { - Loader::Register(new Dedicated()); + Loader::Register(new Flags()); Loader::Register(new Singleton()); Loader::Register(new Dvar()); @@ -26,8 +26,9 @@ namespace Components Loader::Register(new Renderer()); Loader::Register(new UIFeeder()); Loader::Register(new UIScript()); - Loader::Register(new FastFiles()); + Loader::Register(new Dedicated()); Loader::Register(new Discovery()); + Loader::Register(new FastFiles()); Loader::Register(new Materials()); Loader::Register(new FileSystem()); Loader::Register(new QuickPatch()); diff --git a/src/Components/Loader.hpp b/src/Components/Loader.hpp index db1292ad..08af4696 100644 --- a/src/Components/Loader.hpp +++ b/src/Components/Loader.hpp @@ -23,6 +23,7 @@ namespace Components #include "Modules\Dvar.hpp" #include "Modules\Maps.hpp" #include "Modules\News.hpp" +#include "Modules\Flags.hpp" #include "Modules\Menus.hpp" #include "Modules\Colors.hpp" #include "Modules\Logger.hpp" diff --git a/src/Components/Modules/Dedicated.cpp b/src/Components/Modules/Dedicated.cpp index 135defd2..285c9c14 100644 --- a/src/Components/Modules/Dedicated.cpp +++ b/src/Components/Modules/Dedicated.cpp @@ -7,7 +7,7 @@ namespace Components bool Dedicated::IsDedicated() { - return (Dedicated::Dedi.Get() != 0); + return Flags::HasFlag("dedicated"); } void Dedicated::InitDedicatedServer() @@ -23,7 +23,7 @@ namespace Components "patch_mp" }; - memcpy((void*)0x66E1CB0, &fastfiles, sizeof(fastfiles)); + memcpy(reinterpret_cast(0x66E1CB0), &fastfiles, sizeof(fastfiles)); Game::LoadInitialFF(); Utils::Hook::Call(0x4F84C0)(); @@ -163,32 +163,10 @@ namespace Components Dedicated::Dedicated() { - Dedicated::Dedi = Dvar::Register("dedicated", 0, 0, 2, Game::dvar_flag::DVAR_FLAG_SERVERINFO | Game::dvar_flag::DVAR_FLAG_WRITEPROTECTED, "Start as dedicated"); - - // TODO: Beautify! - char* cmd = GetCommandLineA(); - char* value = strstr(cmd, " dedicated"); - - if (value) - { - value += 10; - - while (*value == ' ' || *value == '"') - value++; - - char num[2] = { 0, 0 }; - num[0] = *value; - - int dediVal = atoi(num); - - if (dediVal && dediVal < 3) - { - Dedicated::Dedi.SetRaw(dediVal); - } - } - if (Dedicated::IsDedicated()) { + Dvar::Register("sv_lanOnly", false, Game::dvar_flag::DVAR_FLAG_NONE, "Don't register at the master server"); + Utils::Hook(0x60BE98, Dedicated::InitDedicatedServer, HOOK_CALL).Install()->Quick(); Utils::Hook::Set(0x683370, 0xC3); // steam sometimes doesn't like the server diff --git a/src/Components/Modules/Discovery.cpp b/src/Components/Modules/Discovery.cpp index 2b82cd93..24621995 100644 --- a/src/Components/Modules/Discovery.cpp +++ b/src/Components/Modules/Discovery.cpp @@ -1,19 +1,60 @@ #include "..\..\STDInclude.hpp" -#include namespace Components { + void Discovery::Perform() + { + static bool performing = false; + if (performing) return; + + std::async([] () + { + performing = true; + int start = Game::Com_Milliseconds(); + + Logger::Print("Starting local server discovery...\n"); + + //Network::BroadcastAll("discovery\n"); + Network::BroadcastRange(28960, 38960, "discovery\n"); + + Logger::Print("Discovery sent within %dms, awaiting responses...\n", Game::Com_Milliseconds() - start); + performing = false; + }); + } + Discovery::Discovery() { - Command::Add("bcast", [] (Command::Params params) + Network::Handle("discovery", [] (Network::Address address, std::string data) { - std::async([]() - { - int start = Game::Com_Milliseconds(); - OutputDebugStringA("Start!"); - Network::BroadcastAll("getinfo xxx\n"); - OutputDebugStringA(Utils::VA("End: %d", Game::Com_Milliseconds() - start)); - }); + if (address.IsSelf()) return; + + if (!address.IsLocal()) + { + Logger::Print("Received discovery request from non-local address: %s\n", address.GetString()); + return; + } + + Logger::Print("Received discovery request from %s\n", address.GetString()); + Network::Send(address, "discoveryResponse\n"); + }); + + Network::Handle("discoveryResponse", [] (Network::Address address, std::string data) + { + if (address.IsSelf()) return; + + if (!address.IsLocal()) + { + Logger::Print("Received discovery response from non-local address: %s\n", address.GetString()); + return; + } + + Logger::Print("Received discovery response from %s\n", address.GetString()); + + if (ServerList::IsOfflineList()) + { + OutputDebugStringA("Inserting!"); + ServerList::InsertRequest(address, true); + } }); } diff --git a/src/Components/Modules/Discovery.hpp b/src/Components/Modules/Discovery.hpp index 504b8c9e..96640e4c 100644 --- a/src/Components/Modules/Discovery.hpp +++ b/src/Components/Modules/Discovery.hpp @@ -6,5 +6,7 @@ namespace Components Discovery(); ~Discovery(); const char* GetName() { return "Discovery"; }; + + static void Perform(); }; } diff --git a/src/Components/Modules/Flags.cpp b/src/Components/Modules/Flags.cpp new file mode 100644 index 00000000..2075a338 --- /dev/null +++ b/src/Components/Modules/Flags.cpp @@ -0,0 +1,46 @@ +#include "..\..\STDInclude.hpp" + +namespace Components +{ + std::vector Flags::EnabledFlags; + + bool Flags::HasFlag(std::string flag) + { + for (auto entry : Flags::EnabledFlags) + { + if (Utils::StrToLower(entry) == Utils::StrToLower(flag)) + { + return true; + } + } + + return false; + } + + void Flags::ParseFlags() + { + int numArgs; + LPCWSTR commandLine = GetCommandLineW(); + LPWSTR* argv = CommandLineToArgvW(commandLine, &numArgs); + + for (int i = 0; i < numArgs;i++) + { + std::wstring wFlag = argv[i]; + if (wFlag[0] == L'-') + { + Flags::EnabledFlags.push_back(std::string(++wFlag.begin(), wFlag.end())); + OutputDebugStringA(Flags::EnabledFlags[Flags::EnabledFlags.size() - 1].data()); + } + } + } + + Flags::Flags() + { + Flags::ParseFlags(); + } + + Flags::~Flags() + { + Flags::EnabledFlags.clear(); + } +} diff --git a/src/Components/Modules/Flags.hpp b/src/Components/Modules/Flags.hpp new file mode 100644 index 00000000..fdafc839 --- /dev/null +++ b/src/Components/Modules/Flags.hpp @@ -0,0 +1,17 @@ +namespace Components +{ + class Flags : public Component + { + public: + Flags(); + ~Flags(); + const char* GetName() { return "Flags"; }; + + static bool HasFlag(std::string flag); + + private: + static std::vector EnabledFlags; + + static void ParseFlags(); + }; +} diff --git a/src/Components/Modules/Network.cpp b/src/Components/Modules/Network.cpp index 8e8565a0..3fc1c8bc 100644 --- a/src/Components/Modules/Network.cpp +++ b/src/Components/Modules/Network.cpp @@ -23,11 +23,15 @@ namespace Components } void Network::Address::SetIP(DWORD ip) { - *(DWORD*)this->address.ip = ip; + this->address.ip.full = ip; } - DWORD Network::Address::GetIP() + void Network::Address::SetIP(Game::netIP_t ip) { - return *(DWORD*)this->address.ip; + this->address.ip = ip; + } + Game::netIP_t Network::Address::GetIP() + { + return this->address.ip; } void Network::Address::SetType(Game::netadrtype_t type) { @@ -45,6 +49,38 @@ namespace Components { return Game::NET_AdrToString(this->address); } + bool Network::Address::IsLocal() + { + // According to: https://en.wikipedia.org/wiki/Private_network + + // 10.X.X.X + if (this->GetIP().bytes[0] == 10) return true; + + // 192.168.X.X + if (this->GetIP().bytes[0] == 192 && this->GetIP().bytes[1] == 168) return true; + + // 172.16.X.X - 172.31.X.X + if (this->GetIP().bytes[0] == 172 && (this->GetIP().bytes[1] >= 16) && (this->GetIP().bytes[1] < 32)) return true; + + // TODO: Maybe check for matching localIPs and subnet mask + + return false; + } + bool Network::Address::IsSelf() + { + if (Game::NET_IsLocalAddress(this->address)) return true; // Loopback + if (this->GetPort() != (Dvar::Var("net_port").Get() & 0xFFFF)) return false; // Port not equal + + for (int i = 0; i < *Game::numIP; i++) + { + if (this->GetIP().full == Game::localIP[i].full) + { + return true; + } + } + + return false; + } void Network::Handle(std::string packet, Network::Callback callback) { @@ -107,7 +143,14 @@ namespace Components // Check if custom handler exists for (auto i = Network::PacketHandlers.begin(); i != Network::PacketHandlers.end(); i++) { - if (!_strnicmp(i->first.data(), packet, i->first.size())) + std::string packetCommand = packet; + auto pos = packetCommand.find_first_of("\n "); + if (pos != std::string::npos) + { + packetCommand = packetCommand.substr(0, pos); + } + + if (Utils::StrToLower(i->first) == Utils::StrToLower(packetCommand)) { Network::SelectedPacket = i->first; return 0; diff --git a/src/Components/Modules/Network.hpp b/src/Components/Modules/Network.hpp index 9aae8068..6aaeb531 100644 --- a/src/Components/Modules/Network.hpp +++ b/src/Components/Modules/Network.hpp @@ -18,7 +18,8 @@ namespace Components unsigned short GetPort(); void SetIP(DWORD ip); - DWORD GetIP(); + void SetIP(Game::netIP_t ip); + Game::netIP_t GetIP(); void SetType(Game::netadrtype_t type); Game::netadrtype_t GetType(); @@ -26,6 +27,8 @@ namespace Components Game::netadr_t* Get(); const char* GetString(); + bool IsLocal(); + bool IsSelf(); private: Game::netadr_t address; diff --git a/src/Components/Modules/Party.cpp b/src/Components/Modules/Party.cpp index 1ea43f1c..147da77d 100644 --- a/src/Components/Modules/Party.cpp +++ b/src/Components/Modules/Party.cpp @@ -43,11 +43,11 @@ namespace Components if (key == "addr") { - return Utils::VA("%d", address.Get()->ip[0] | (address.Get()->ip[1] << 8) | (address.Get()->ip[2] << 16) | (address.Get()->ip[3] << 24)); + return Utils::VA("%d", address.GetIP().full); } else if (key =="port") { - return Utils::VA("%d", htons(address.GetPort())); + return Utils::VA("%d", address.GetPort()); } } @@ -228,7 +228,6 @@ namespace Components // Basic info handler Network::Handle("getInfo", [] (Network::Address address, std::string data) { - OutputDebugStringA(Utils::VA("Received inforequest from: %s", address.GetString())); int clientCount = 0; int maxclientCount = *Game::svs_numclients; @@ -295,7 +294,6 @@ namespace Components Network::Handle("infoResponse", [] (Network::Address address, std::string data) { - OutputDebugStringA(Utils::VA("Received inforesponse from: %s", address.GetString())); Utils::InfoString info(data); // Handle connection diff --git a/src/Components/Modules/ServerList.cpp b/src/Components/Modules/ServerList.cpp index 8f8fa335..b476bd0e 100644 --- a/src/Components/Modules/ServerList.cpp +++ b/src/Components/Modules/ServerList.cpp @@ -4,11 +4,49 @@ namespace Components { bool ServerList::SortAsc = true; int ServerList::SortKey = ServerList::Column::Ping; + unsigned int ServerList::CurrentServer = 0; ServerList::Container ServerList::RefreshContainer; + std::vector ServerList::OnlineList; + std::vector ServerList::OfflineList; + std::vector ServerList::FavouriteList; + std::vector ServerList::VisibleList; + std::vector& ServerList::GetList() + { + int source = Dvar::Var("ui_netSource").Get(); + + if (ServerList::IsFavouriteList()) + { + return ServerList::FavouriteList; + } + else if (ServerList::IsOfflineList()) + { + return ServerList::OfflineList; + } + else + { + return ServerList::OnlineList; + } + } + + bool ServerList::IsFavouriteList() + { + return (Dvar::Var("ui_netSource").Get() == 2); + } + + bool ServerList::IsOfflineList() + { + return (Dvar::Var("ui_netSource").Get() == 0); + } + + bool ServerList::IsOnlineList() + { + return (Dvar::Var("ui_netSource").Get() == 1); + } + int ServerList::GetServerCount() { return (int)ServerList::VisibleList.size(); @@ -71,7 +109,10 @@ namespace Components void ServerList::Refresh() { - ServerList::OnlineList.clear(); +// ServerList::OnlineList.clear(); +// ServerList::OfflineList.clear(); +// ServerList::FavouriteList.clear(); + ServerList::GetList().clear(); ServerList::VisibleList.clear(); ServerList::RefreshContainer.Mutex.lock(); @@ -81,18 +122,56 @@ namespace Components ServerList::RefreshContainer.SendCount = 0; ServerList::RefreshContainer.SentCount = 0; - ServerList::RefreshContainer.AwatingList = true; - ServerList::RefreshContainer.AwaitTime = Game::Com_Milliseconds(); + if (ServerList::IsOfflineList()) + { + Discovery::Perform(); + } + else if (ServerList::IsOnlineList()) + { + ServerList::RefreshContainer.AwatingList = true; + ServerList::RefreshContainer.AwaitTime = Game::Com_Milliseconds(); - int masterPort = Dvar::Var("masterPort").Get(); - const char* masterServerName = Dvar::Var("masterServerName").Get(); + int masterPort = Dvar::Var("masterPort").Get(); + const char* masterServerName = Dvar::Var("masterServerName").Get(); - ServerList::RefreshContainer.Host = Network::Address(Utils::VA("%s:%u", masterServerName, masterPort)); + ServerList::RefreshContainer.Host = Network::Address(Utils::VA("%s:%u", masterServerName, masterPort)); - Logger::Print("Sending serverlist request to master: %s:%u\n", masterServerName, masterPort); + Logger::Print("Sending serverlist request to master: %s:%u\n", masterServerName, masterPort); - Network::Send(ServerList::RefreshContainer.Host, Utils::VA("getservers IW4 %i full empty", PROTOCOL)); - //Network::Send(ServerList::RefreshContainer.Host, "getservers 0 full empty\n"); + Network::Send(ServerList::RefreshContainer.Host, Utils::VA("getservers IW4 %i full empty", PROTOCOL)); + //Network::Send(ServerList::RefreshContainer.Host, "getservers 0 full empty\n"); + } + else if (ServerList::IsFavouriteList()) + { + // TODO: Whatever + } + } + + void ServerList::InsertRequest(Network::Address address, bool accquireMutex) + { + if (accquireMutex) ServerList::RefreshContainer.Mutex.lock(); + + ServerList::Container::ServerContainer container; + container.Sent = false; + container.Target = address; + + bool alreadyInserted = false; + for (auto &server : ServerList::RefreshContainer.Servers) + { + if (server.Target == container.Target) + { + alreadyInserted = true; + break; + } + } + + if (!alreadyInserted) + { + ServerList::RefreshContainer.Servers.push_back(container); + ServerList::RefreshContainer.SendCount++; + } + + if (accquireMutex) ServerList::RefreshContainer.Mutex.unlock(); } void ServerList::Insert(Network::Address address, Utils::InfoString info) @@ -131,11 +210,11 @@ namespace Components // Check if already inserted and remove int k = 0; - for (auto j = ServerList::OnlineList.begin(); j != ServerList::OnlineList.end(); j++, k++) + for (auto j = ServerList::GetList().begin(); j != ServerList::GetList().end(); j++, k++) { if (j->Addr == address) { - ServerList::OnlineList.erase(j); + ServerList::GetList().erase(j); break; } } @@ -151,10 +230,12 @@ namespace Components if (info.Get("gamename") == "IW4" && server.MatchType && server.Shortversion == VERSION_STR) { - int index = ServerList::OnlineList.size(); - ServerList::OnlineList.push_back(server); + int index = ServerList::GetList().size(); + ServerList::GetList().push_back(server); ServerList::VisibleList.push_back(index); ServerList::SortList(); + + OutputDebugStringA(Utils::VA("Inserted with IP: %s", server.Addr.GetString())); } break; @@ -202,9 +283,9 @@ namespace Components { if (ServerList::VisibleList.size() > (unsigned int)index) { - if (ServerList::OnlineList.size() > (unsigned int)ServerList::VisibleList[index]) + if (ServerList::GetList().size() > (unsigned int)ServerList::VisibleList[index]) { - return &ServerList::OnlineList[ServerList::VisibleList[index]]; + return &ServerList::GetList()[ServerList::VisibleList[index]]; } } @@ -286,27 +367,9 @@ namespace Components Network::Address serverAddr = address; serverAddr.SetIP(entry[i].IP); serverAddr.SetPort(ntohs(entry[i].Port)); - serverAddr.Get()->type = Game::NA_IP; + serverAddr.SetType(Game::NA_IP); - ServerList::Container::ServerContainer container; - container.Sent = false; - container.Target = serverAddr; - - bool alreadyInserted = false; - for (auto &server : ServerList::RefreshContainer.Servers) - { - if (server.Target == container.Target) - { - alreadyInserted = true; - break; - } - } - - if (!alreadyInserted) - { - ServerList::RefreshContainer.Servers.push_back(container); - ServerList::RefreshContainer.SendCount++; - } + ServerList::InsertRequest(serverAddr, false); } Logger::Print("Parsed %d servers from master\n", ServerList::RefreshContainer.Servers.size() - count); @@ -356,6 +419,8 @@ namespace Components ServerList::~ServerList() { ServerList::OnlineList.clear(); + ServerList::OfflineList.clear(); + ServerList::FavouriteList.clear(); ServerList::VisibleList.clear(); } } diff --git a/src/Components/Modules/ServerList.hpp b/src/Components/Modules/ServerList.hpp index 4f4e2634..24d1cdcf 100644 --- a/src/Components/Modules/ServerList.hpp +++ b/src/Components/Modules/ServerList.hpp @@ -26,8 +26,13 @@ namespace Components const char* GetName() { return "ServerList"; }; static void Refresh(); + static void InsertRequest(Network::Address address, bool accquireMutex = true); static void Insert(Network::Address address, Utils::InfoString info); + static bool IsFavouriteList(); + static bool IsOfflineList(); + static bool IsOnlineList(); + private: enum Column { @@ -93,13 +98,18 @@ namespace Components static void SortList(); static ServerInfo* GetServer(int index); + static std::vector& GetList(); static int SortKey; static bool SortAsc; static unsigned int CurrentServer; static Container RefreshContainer; + static std::vector OnlineList; + static std::vector OfflineList; + static std::vector FavouriteList; + static std::vector VisibleList; }; } diff --git a/src/Components/Modules/Singleton.cpp b/src/Components/Modules/Singleton.cpp index 9774c09b..4f4c6640 100644 --- a/src/Components/Modules/Singleton.cpp +++ b/src/Components/Modules/Singleton.cpp @@ -25,7 +25,7 @@ namespace Components else { //No connect command was provided, continuing with normal processing. - if (!Singleton::FirstInstance && MessageBoxA(0, "Do you want to start a second instance?", "Game already running", MB_ICONEXCLAMATION | MB_YESNO) == IDNO) + if (!Singleton::FirstInstance && MessageBoxA(0, "Do you want to start another instance?", "Game already running", MB_ICONEXCLAMATION | MB_YESNO) == IDNO) { ExitProcess(0); } diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index feba05d8..4455cc58 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -62,6 +62,7 @@ namespace Game NET_AdrToString_t NET_AdrToString = (NET_AdrToString_t)0x469880; NET_CompareAdr_t NET_CompareAdr = (NET_CompareAdr_t)0x4D0AA0; + NET_IsLocalAddress_t NET_IsLocalAddress = (NET_IsLocalAddress_t)0x402BD0; NET_StringToAdr_t NET_StringToAdr = (NET_StringToAdr_t)0x409010; Live_MPAcceptInvite_t Live_MPAcceptInvite = (Live_MPAcceptInvite_t)0x420A6D; @@ -128,6 +129,9 @@ namespace Game party_t** partyIngame = (party_t**)0x1081C00; PartyData_s** partyData = (PartyData_s**)0x107E500; + int* numIP = (int*)0x64A1E68; + netIP_t* localIP = (netIP_t*)0x64A1E28; + void* ReallocateAssetPool(XAssetType type, unsigned int newSize) { int elSize = DB_GetXAssetSizeHandlers[type](); diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index 6d83c1c3..701fb32a 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -145,6 +145,9 @@ namespace Game typedef bool(__cdecl * NET_CompareAdr_t)(netadr_t, netadr_t); extern NET_CompareAdr_t NET_CompareAdr; + typedef bool(__cdecl * NET_IsLocalAddress_t)(netadr_t); + extern NET_IsLocalAddress_t NET_IsLocalAddress; + typedef bool(__cdecl * NET_StringToAdr_t)(const char*, netadr_t*); extern NET_StringToAdr_t NET_StringToAdr; @@ -247,6 +250,9 @@ namespace Game extern party_t** partyIngame; extern PartyData_s** partyData; + extern int* numIP; + extern netIP_t* localIP; + void* ReallocateAssetPool(XAssetType type, unsigned int newSize); void Menu_FreeItemMemory(Game::itemDef_t* item); void OOBPrintT(int type, netadr_t netadr, const char* message); diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index f6719f28..1affdd2f 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -626,10 +626,16 @@ namespace Game NS_SERVER } netsrc_t; + typedef union + { + BYTE bytes[4]; + DWORD full; + } netIP_t; + typedef struct { netadrtype_t type; - BYTE ip[4]; + netIP_t ip; unsigned short port; BYTE ipx[10]; } netadr_t; diff --git a/src/STDInclude.hpp b/src/STDInclude.hpp index 42d9856d..0b5c2426 100644 --- a/src/STDInclude.hpp +++ b/src/STDInclude.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -22,6 +23,7 @@ #include #include #include +#include #include