1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-15 21:19:57 +00:00
openmw-tes3mp/apps/openmw-mp/MasterClient.cpp

198 lines
6 KiB
C++
Raw Normal View History

2016-08-14 23:48:25 +00:00
//
// Created by koncord on 14.08.16.
//
#include <RakSleep.h>
#include <Getche.h>
#include <sstream>
#include <iostream>
#include <thread>
2016-08-14 23:48:25 +00:00
#include <RakPeerInterface.h>
#include "MasterClient.hpp"
2016-08-17 03:15:44 +00:00
#include <components/openmw-mp/Log.hpp>
#include <components/openmw-mp/Version.hpp>
2016-08-14 23:48:25 +00:00
#include "Networking.hpp"
using namespace std;
bool MasterClient::sRun = false;
MasterClient::MasterClient(std::string queryAddr, unsigned short queryPort, std::string serverAddr,
unsigned short serverPort) : queryAddr(queryAddr), queryPort(queryPort),
serverAddr(serverAddr), serverPort(serverPort)
{
players = 0;
maxPlayers = 0;
hostname = "";
modname = "";
2016-08-14 23:48:25 +00:00
timeout = 1000; // every 1 seconds
}
void MasterClient::SetPlayers(unsigned pl)
{
mutexData.lock();
players = pl;
mutexData.unlock();
}
void MasterClient::SetMaxPlayers(unsigned pl)
{
mutexData.lock();
maxPlayers = pl;
mutexData.unlock();
}
void MasterClient::SetHostname(std::string hostname)
2016-08-14 23:48:25 +00:00
{
mutexData.lock();
this->hostname = hostname.substr(0, 200);
2016-08-14 23:48:25 +00:00
mutexData.unlock();
}
void MasterClient::SetModname(std::string modname)
{
mutexData.lock();
this->modname = modname.substr(0, 200);
mutexData.unlock();
}
RakNet::RakString
MasterClient::Send(std::string hostname, std::string modname, unsigned maxPlayers, bool update, unsigned players)
2016-08-14 23:48:25 +00:00
{
/*static unsigned short oldServerPort, oldQueryPort;
static string oldMotd;
static unsigned oldPlayers, oldMaxPlayers;*/
std::stringstream sstr;
mutexData.lock();
sstr << "{";
sstr << "\"port\": " << serverPort << ", ";
sstr << "\"query_port\": " << queryPort << ", ";
sstr << "\"hostname\": \"" << hostname.c_str() << "\", ";
2017-01-10 12:35:23 +00:00
sstr << "\"modname\": \"" << modname.c_str() << "\", ";
2016-08-14 23:48:25 +00:00
sstr << "\"players\": " << players << ", ";
sstr << "\"max_players\": " << maxPlayers << ", ";
sstr << "\"version\": \"" << TES3MP_VERSION << "\", ";
sstr << "\"passw\": " << (mwmp::Networking::get().isPassworded() ? "true" : "false");
2016-08-14 23:48:25 +00:00
sstr << "}";
mutexData.unlock();
std::string contentType = "application/json";
RakNet::RakString createRequest;
if (update)
createRequest = RakNet::RakString::FormatForPUT(
string("/api/servers/" + serverAddr + ":" + to_string(serverPort)).c_str(), contentType.c_str(),
sstr.str().c_str());
else
createRequest = RakNet::RakString::FormatForPOST("/api/servers", contentType.c_str(),
sstr.str().c_str());
httpConnection->TransmitRequest(createRequest.C_String(), queryAddr.c_str(), queryPort);
RakNet::Packet *packet;
RakNet::SystemAddress sa;
RakNet::RakString transmitted, hostTransmitted;
RakNet::RakString response;
RakNet::SystemAddress hostReceived;
int contentOffset;
while (true)
{
// This is kind of crappy, but for TCP plugins, always do HasCompletedConnectionAttempt,
// then Receive(), then HasFailedConnectionAttempt(),HasLostConnection()
sa = tcpInterface.HasCompletedConnectionAttempt();
if (sa != RakNet::UNASSIGNED_SYSTEM_ADDRESS)
2016-08-15 13:33:18 +00:00
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Connected to master server: %s", sa.ToString());
2016-08-14 23:48:25 +00:00
sa = tcpInterface.HasFailedConnectionAttempt();
if (sa != RakNet::UNASSIGNED_SYSTEM_ADDRESS)
{
2016-08-15 13:33:18 +00:00
LOG_MESSAGE_SIMPLE(Log::LOG_WARN, "Failed to connect to master server: %s", sa.ToString());
2016-08-14 23:48:25 +00:00
return "FAIL_CONNECT";
}
sa = tcpInterface.HasLostConnection();
if (sa != RakNet::UNASSIGNED_SYSTEM_ADDRESS)
{
2016-08-15 13:33:18 +00:00
LOG_MESSAGE_SIMPLE(Log::LOG_WARN, "Lost connection to master server: %s", sa.ToString());
2016-08-14 23:48:25 +00:00
return "LOST_CONNECTION";
}
for (packet = tcpInterface.Receive(); packet; tcpInterface.DeallocatePacket(
packet), packet = tcpInterface.Receive());
if (httpConnection->GetResponse(transmitted, hostTransmitted, response, hostReceived, contentOffset))
{
2016-08-17 15:20:36 +00:00
if (contentOffset < 0)
2016-08-14 23:48:25 +00:00
return "NO_CONTENT"; // no content
tcpInterface.CloseConnection(sa);
return (response.C_String() + contentOffset);
}
RakSleep(30);
}
}
void MasterClient::Update()
{
assert(!sRun);
httpConnection = RakNet::HTTPConnection2::GetInstance();
tcpInterface.Start(0, 64);
tcpInterface.AttachPlugin(httpConnection);
2017-01-10 12:36:39 +00:00
RakNet::RakString response = Send(hostname, modname, maxPlayers, false, players);
2016-08-14 23:48:25 +00:00
bool update = true;
sRun = true;
while (sRun)
{
if (response == "Created")
2016-11-17 04:39:35 +00:00
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Server registered on the master server.");
2016-08-14 23:48:25 +00:00
else if (response == "Accepted")
LOG_MESSAGE_SIMPLE(Log::LOG_VERBOSE, "Sent info update to master server.");
2016-08-14 23:48:25 +00:00
else if (response == "bad request")
{
2016-08-15 13:33:18 +00:00
LOG_MESSAGE_SIMPLE(Log::LOG_WARN, "Update rate is too low, and the master server has deleted information about"
2016-11-17 04:39:35 +00:00
" the server. Trying low rate...");
if ((timeout - step_rate) >= step_rate)
2017-01-10 12:38:33 +00:00
SetUpdateRate(timeout - step_rate);
2016-08-14 23:48:25 +00:00
update = false;
}
else
{
/*cout << "Error: \""<< response << "\"" << endl;
cout << response.GetLength() << endl;*/
}
RakSleep(timeout);
2017-01-10 12:36:39 +00:00
2017-02-02 16:55:59 +00:00
players = Players::getPlayers()->size();
2017-01-10 12:36:39 +00:00
response = Send(hostname, modname, maxPlayers, update, players);
2016-08-14 23:48:25 +00:00
update = true;
}
}
void MasterClient::Start()
{
thrQuery = thread(&MasterClient::Update, this);
}
2016-08-14 23:48:25 +00:00
void MasterClient::Stop()
{
if (!sRun)
return;
2016-08-14 23:48:25 +00:00
sRun = false;
if (thrQuery.joinable())
thrQuery.join();
2016-08-14 23:48:25 +00:00
}
void MasterClient::SetUpdateRate(unsigned int rate)
{
2016-08-17 15:04:35 +00:00
if (timeout < min_rate)
2016-08-14 23:48:25 +00:00
timeout = min_rate;
else if (timeout > max_rate)
timeout = max_rate;
timeout = rate;
}