diff --git a/apps/browser/CMakeLists.txt b/apps/browser/CMakeLists.txt index 95f09bfec..a8389077e 100644 --- a/apps/browser/CMakeLists.txt +++ b/apps/browser/CMakeLists.txt @@ -1,5 +1,5 @@ -set (CMAKE_CXX_STANDARD 11) +set (CMAKE_CXX_STANDARD 14) set(BROWSER_UI ${CMAKE_SOURCE_DIR}/files/tes3mp/ui/Main.ui @@ -14,6 +14,7 @@ set(BROWSER MySortFilterProxyModel.cpp netutils/HTTPNetwork.cpp netutils/Utils.cpp + netutils/QueryClient.cpp ${CMAKE_SOURCE_DIR}/files/tes3mp/browser.rc ) @@ -29,6 +30,7 @@ set(BROWSER_HEADER NetController.hpp netutils/HTTPNetwork.hpp netutils/Utils.hpp + netutils/QueryClient.hpp ) source_group(browser FILES ${BROWSER} ${BROWSER_HEADER}) diff --git a/apps/browser/netutils/QueryClient.cpp b/apps/browser/netutils/QueryClient.cpp new file mode 100644 index 000000000..2efc739df --- /dev/null +++ b/apps/browser/netutils/QueryClient.cpp @@ -0,0 +1,148 @@ +// +// Created by koncord on 24.04.17. +// + +#include "QueryClient.hpp" +#include +#include +#include + +using namespace RakNet; +using namespace std; +using namespace mwmp; + +QueryClient::QueryClient() +{ + peer = RakPeerInterface::GetInstance(); + pmq = new PacketMasterQuery(peer); + pmu = new PacketMasterUpdate(peer); + RakNet::SocketDescriptor sd; + peer->Startup(8, &sd, 1); + status = -1; +} + +QueryClient::~QueryClient() +{ + delete pmq; + delete pmu; + RakPeerInterface::DestroyInstance(peer); +} + +void QueryClient::SetServer(std::string addr, unsigned short port) +{ + masterAddr = SystemAddress(addr.c_str(), port); +} + +QueryClient &QueryClient::Get() +{ + static QueryClient myInstance; + return myInstance; +} + +map QueryClient::Query() +{ + map query; + if (Connect() == IS_NOT_CONNECTED) + { + status = -1; + return query; + } + + BitStream bs; + bs.Write((unsigned char) (ID_MASTER_QUERY)); + peer->Send(&bs, HIGH_PRIORITY, RELIABLE_ORDERED, CHANNEL_MASTER, masterAddr, false); + + pmq->SetServers(&query); + status = GetAnswer(); + return query; +} + +pair QueryClient::Update(RakNet::SystemAddress addr) +{ + pair server; + if (Connect() == IS_NOT_CONNECTED) + { + status = -1; + return server; + } + + BitStream bs; + bs.Write((unsigned char) (ID_MASTER_UPDATE)); + bs.Write(addr); + peer->Send(&bs, HIGH_PRIORITY, RELIABLE_ORDERED, CHANNEL_MASTER, masterAddr, false); + + pmu->SetServer(&server); + status = GetAnswer(); + return server; +} + +MASTER_PACKETS QueryClient::GetAnswer() +{ + RakNet::Packet *packet; + bool update = true; + unsigned char pid = 0; + int id; + while(update) + { + for (packet = peer->Receive(); packet; peer->DeallocatePacket(packet), packet = peer->Receive()) + { + BitStream data(packet->data, packet->length, false); + pmq->SetReadStream(&data); + pmu->SetReadStream(&data); + data.Read(pid); + switch(pid) + { + case ID_MASTER_QUERY: + pmq->Read(); + update = false; + id = pid; + break; + case ID_MASTER_UPDATE: + pmu->Read(); + update = false; + id = pid; + break; + case ID_MASTER_ANNOUNCE: + update = false; + id = pid; + break; + default: + break; + } + } + RakSleep(500); + } + return (MASTER_PACKETS)(id); +} + +ConnectionState QueryClient::Connect() +{ + ConnectionAttemptResult car = peer->Connect(masterAddr.ToString(false), masterAddr.GetPort(), "pass", strlen("pass"), 0, 0, 5, 500); + + while (true) + { + ConnectionState state = peer->GetConnectionState(masterAddr); + switch (state) + { + case IS_CONNECTED: + return IS_CONNECTED; + case IS_NOT_CONNECTED: + case IS_DISCONNECTED: + case IS_SILENTLY_DISCONNECTING: + case IS_DISCONNECTING: + { + //LOG_MESSAGE_SIMPLE(Log::LOG_WARN, "Cannot connect to master server: %d", masterAddr.ToString()); + return IS_NOT_CONNECTED; + } + case IS_PENDING: + case IS_CONNECTING: + break; + } + RakSleep(500); + } +} + +int QueryClient::Status() +{ + return status; +} diff --git a/apps/browser/netutils/QueryClient.hpp b/apps/browser/netutils/QueryClient.hpp new file mode 100644 index 000000000..4acd6f553 --- /dev/null +++ b/apps/browser/netutils/QueryClient.hpp @@ -0,0 +1,44 @@ +// +// Created by koncord on 24.04.17. +// + +#ifndef OPENMW_QUERYCLIENT_HPP +#define OPENMW_QUERYCLIENT_HPP + +#include +#include +#include +#include +#include + +class QueryClient +{ +private: + QueryClient(QueryClient const &) = delete; + QueryClient(QueryClient &&) = delete; + QueryClient &operator=(QueryClient const &) = delete; + QueryClient &operator=(QueryClient &&) = delete; +public: + static QueryClient &Get(); + void SetServer(std::string addr, unsigned short port); + std::map Query(); + std::pair Update(RakNet::SystemAddress addr); + int Status(); +private: + RakNet::ConnectionState Connect(); + MASTER_PACKETS GetAnswer(); +protected: + QueryClient(); + ~QueryClient(); +private: + int status; + RakNet::RakPeerInterface *peer; + RakNet::SystemAddress masterAddr; + mwmp::PacketMasterQuery *pmq; + mwmp::PacketMasterUpdate *pmu; + std::pair server; + +}; + + +#endif //OPENMW_QUERYCLIENT_HPP