Added master server stuff

coverity_scan^2
Koncord 8 years ago
parent 02a447c589
commit c695923825

@ -48,6 +48,7 @@ set(SERVER
Networking.cpp
Utils.cpp
Log.cpp
MasterClient.cpp
Script/Script.cpp Script/ScriptFunction.cpp
Script/ScriptFunctions.cpp
Script/Functions/Translocations.cpp Script/Functions/Stats.cpp Script/Functions/Items.cpp

@ -0,0 +1,172 @@
//
// Created by koncord on 14.08.16.
//
#include <RakSleep.h>
#include <Getche.h>
#include <sstream>
#include <iostream>
#include <RakPeerInterface.h>
#include "MasterClient.hpp"
#include "Log.hpp"
#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)
{
httpConnection = RakNet::HTTPConnection2::GetInstance();
tcpInterface.Start(0, 64);
tcpInterface.AttachPlugin(httpConnection);
players = 0;
maxPlayers = 0;
motd = "";
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::SetMOTD(std::string &motd)
{
mutexData.lock();
this->motd = motd.substr(0, 200);
mutexData.unlock();
}
RakNet::RakString MasterClient::Send(std::string motd, unsigned players, unsigned maxPlayers, bool update)
{
/*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 << "\"motd\": \"" << motd << "\", ";
sstr << "\"players\": " << players << ", ";
sstr << "\"max_players\": " << maxPlayers;
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)
LOG_MESSAGE_SIMPLE(Log::INFO, "Connected to master server: %s", sa.ToString());
sa = tcpInterface.HasFailedConnectionAttempt();
if (sa != RakNet::UNASSIGNED_SYSTEM_ADDRESS)
{
LOG_MESSAGE_SIMPLE(Log::WARNING, "Failed to connect to master server: %s", sa.ToString());
return "FAIL_CONNECT";
}
sa = tcpInterface.HasLostConnection();
if (sa != RakNet::UNASSIGNED_SYSTEM_ADDRESS)
{
LOG_MESSAGE_SIMPLE(Log::WARNING, "Lost connection to master server: %s", sa.ToString());
return "LOST_CONNECTION";
}
for (packet = tcpInterface.Receive(); packet; tcpInterface.DeallocatePacket(
packet), packet = tcpInterface.Receive());
if (httpConnection->GetResponse(transmitted, hostTransmitted, response, hostReceived, contentOffset))
{
if(contentOffset < 0)
return "NO_CONTENT"; // no content
tcpInterface.CloseConnection(sa);
return (response.C_String() + contentOffset);
}
RakSleep(30);
}
}
void MasterClient::Update()
{
assert(!sRun);
RakNet::RakString response = Send(motd, players, maxPlayers, false);
bool update = true;
sRun = true;
while (sRun)
{
if (response == "Created")
LOG_MESSAGE_SIMPLE(Log::INFO, "Server registered on the master server.", "");
else if (response == "Accepted")
LOG_MESSAGE_SIMPLE(Log::INFO, "Server updated information about himself on the master server.", "");
else if (response == "bad request")
{
LOG_MESSAGE_SIMPLE(Log::WARNING, "Update rate is too low, and the master server has deleted information about"
" the server. Trying low rate...", "");
SetUpdateRate(timeout - step_rate);
update = false;
}
else
{
/*cout << "Error: \""<< response << "\"" << endl;
cout << response.GetLength() << endl;*/
}
RakSleep(timeout);
;
players = mwmp::Networking::Get().NumberOfConnections();
response = Send(motd, players, maxPlayers, update);
update = true;
}
}
void MasterClient::Stop()
{
sRun = false;
}
void MasterClient::SetUpdateRate(unsigned int rate)
{
if(timeout < min_rate)
timeout = min_rate;
else if (timeout > max_rate)
timeout = max_rate;
timeout = rate;
}

@ -0,0 +1,46 @@
//
// Created by koncord on 14.08.16.
//
#ifndef OPENMW_MASTERCLIENT_HPP
#define OPENMW_MASTERCLIENT_HPP
#include <string>
#include <raknet/HTTPConnection2.h>
#include <raknet/TCPInterface.h>
#include <mutex>
class MasterClient
{
public:
static const unsigned int step_rate = 1000;
static const unsigned int min_rate = 1000;
static const unsigned int max_rate = 30000;
public:
MasterClient(std::string queryAddr, unsigned short queryPort, std::string serverAddr, unsigned short serverPort);
void SetPlayers(unsigned pl);
void SetMaxPlayers(unsigned pl);
void SetMOTD(std::string &motd);
void Update();
void Stop();
void SetUpdateRate(unsigned int rate);
private:
RakNet::RakString Send(std::string motd, unsigned players, unsigned maxPlayers, bool update = true);
private:
std::string queryAddr;
unsigned short queryPort;
std::string serverAddr;
unsigned short serverPort;
std::string motd;
unsigned players, maxPlayers;
RakNet::HTTPConnection2 *httpConnection;
RakNet::TCPInterface tcpInterface;
unsigned int timeout;
static bool sRun;
std::mutex mutexData;
};
#endif //OPENMW_MASTERCLIENT_HPP

@ -402,3 +402,8 @@ void Networking::KickPlayer(RakNet::RakNetGUID guid)
{
peer->CloseConnection(guid, true);
}
unsigned short Networking::NumberOfConnections() const
{
return peer->NumberOfConnections();
}

@ -6,6 +6,7 @@
#define OPENMW_NETWORKING_HPP
#include <components/openmw-mp/PacketsController.hpp>
#include "Player.hpp"
namespace mwmp
{
@ -19,6 +20,7 @@ namespace mwmp
void DisconnectPlayer(RakNet::RakNetGUID guid);
void KickPlayer(RakNet::RakNetGUID guid);
void Update(RakNet::Packet *packet);
unsigned short NumberOfConnections() const;
int MainLoop();

@ -2,6 +2,7 @@
#include <BitStream.h>
#include "Player.hpp"
#include "Networking.hpp"
#include "MasterClient.hpp"
#include "Log.hpp"
#include <RakPeer.h>
#include <MessageIdentifiers.h>
@ -10,6 +11,7 @@
#include <iostream>
#include <components/files/configurationmanager.hpp>
#include <components/settings/settings.hpp>
#include <thread>
using namespace std;
using namespace mwmp;
@ -64,6 +66,11 @@ std::string loadSettings (Settings::Manager & settings)
return settingspath;
}
void queryThread(MasterClient *mclient)
{
mclient->Update();
}
int main(int argc, char *argv[])
{
Settings::Manager mgr;
@ -76,6 +83,7 @@ int main(int argc, char *argv[])
LOG_INIT(logLevel);
int players = mgr.getInt("players", "General");
string addr = mgr.getString("address", "General");
int port = mgr.getInt("port", "General");
string plugin_home = mgr.getString("home", "Plugins");
@ -99,7 +107,7 @@ int main(int argc, char *argv[])
const char passw[8] = "1234567";
peer->SetIncomingPassword(passw, sizeof(passw));
RakNet::SocketDescriptor sd((unsigned short)port, 0);
RakNet::SocketDescriptor sd((unsigned short)port, addr.c_str());
if (peer->Startup((unsigned)players, &sd, 1) != RakNet::RAKNET_STARTED)
return 0;
@ -107,11 +115,33 @@ int main(int argc, char *argv[])
Networking networking(peer);
bool masterEnabled = mgr.getBool("enabled", "MasterServer");
thread thrQuery;
MasterClient *mclient;
if(masterEnabled)
{
LOG_MESSAGE_SIMPLE(Log::INFO, "%s", "Sharing server query info to master enabled.");
string masterAddr = mgr.getString("address", "MasterServer");
int masterPort = mgr.getInt("port", "MasterServer");
mclient = new MasterClient(masterAddr, (unsigned short) masterPort, addr, (unsigned short) port);
mclient->SetMaxPlayers((unsigned)players);
string motd = mgr.getString("motd", "General");
mclient->SetMOTD(motd);
thrQuery = thread(queryThread, mclient);
}
int code = networking.MainLoop();
RakNet::RakPeerInterface::DestroyInstance(peer);
if(thrQuery.joinable())
{
mclient->Stop();
thrQuery.join();
}
if (code == 0)
printf("Quitting peacefully.\n");
LOG_MESSAGE_SIMPLE(Log::INFO, "%s", "Quitting peacefully.");
LOG_QUIT();

@ -1,12 +1,18 @@
[General]
;master = master.tes3mp.com:8088
# from 3 to 0. 3 - only errors, 0 - all messages
loglevel = 0
motd = My TES3MP server
address = server.tes3mp.com
port = 25565
;query = false #enable query server
;query-port = 25566
players = 4
[Plugins]
;home = ~/local/openmw/tes3mp
#home = ~/local/openmw/tes3mp
home = ~/ClionProjects/PS-dev
plugins = tes3mp.lua,chat_parser.lua
[MasterServer]
enabled = true
address = master.tes3mp.com
port = 8080
rate = 1000
Loading…
Cancel
Save