You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openmw-tes3coop/apps/browser/netutils/QueryClient.cpp

213 lines
6.1 KiB
C++

//
// Created by koncord on 24.04.17.
//
#include "QueryClient.hpp"
#include <RakSleep.h>
#include <components/openmw-mp/NetworkMessages.hpp>
#include <iostream>
#include <components/openmw-mp/Version.hpp>
#include <qdebug.h>
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(const string &addr, unsigned short port)
{
masterAddr = SystemAddress(addr.c_str(), port);
}
QueryClient &QueryClient::Get()
{
static QueryClient myInstance;
return myInstance;
}
map<SystemAddress, QueryData> QueryClient::Query()
{
map<SystemAddress, QueryData> query;
BitStream bs;
bs.Write((unsigned char) (ID_MASTER_QUERY));
qDebug() << "Locking mutex in QueryClient::Query()";
mxServers.lock();
status = -1;
int attempts = 3;
do
{
if (Connect() == IS_NOT_CONNECTED)
{
qDebug() << "Unlocking mutex in QueryClient::Query()";
mxServers.unlock();
return query;
}
int code = peer->Send(&bs, HIGH_PRIORITY, RELIABLE_ORDERED, CHANNEL_MASTER, masterAddr, false);
if (code == 0)
{
qDebug() << "Unlocking mutex in QueryClient::Query()";
mxServers.unlock();
return query;
}
pmq->SetServers(&query);
status = GetAnswer(ID_MASTER_QUERY);
RakSleep(100);
}
while(status != ID_MASTER_QUERY && attempts-- > 0);
if(status != ID_MASTER_QUERY)
qDebug() << "Getting query was failed";
qDebug() << "Unlocking mutex in QueryClient::Query()";
peer->CloseConnection(masterAddr, true);
mxServers.unlock();
qDebug() <<"Answer" << (status == ID_MASTER_QUERY ? "ok." : "wrong.");
return query;
}
pair<SystemAddress, QueryData> QueryClient::Update(const RakNet::SystemAddress &addr)
{
qDebug() << "Locking mutex in QueryClient::Update(RakNet::SystemAddress addr)";
pair<SystemAddress, QueryData> server;
BitStream bs;
bs.Write((unsigned char) (ID_MASTER_UPDATE));
bs.Write(addr);
mxServers.lock();
status = -1;
int attempts = 3;
pmu->SetServer(&server);
do
{
if (Connect() == IS_NOT_CONNECTED)
{
qDebug() << IS_NOT_CONNECTED;
qDebug() << "Unlocking mutex in QueryClient::Update(RakNet::SystemAddress addr)";
mxServers.unlock();
return server;
}
peer->Send(&bs, HIGH_PRIORITY, RELIABLE_ORDERED, CHANNEL_MASTER, masterAddr, false);
status = GetAnswer(ID_MASTER_UPDATE);
RakSleep(100);
}
while(status != ID_MASTER_UPDATE && attempts-- > 0);
if(status != ID_MASTER_UPDATE)
qDebug() << "Getting update was failed";
peer->CloseConnection(masterAddr, true);
qDebug() << "Unlocking mutex in QueryClient::Update(RakNet::SystemAddress addr)";
mxServers.unlock();
return server;
}
MASTER_PACKETS QueryClient::GetAnswer(MASTER_PACKETS waitingPacket)
{
RakNet::Packet *packet;
bool update = true;
unsigned char pid = 0;
int id = -1;
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_CONNECTION_LOST:
qDebug() << "ID_CONNECTION_LOST";
case ID_DISCONNECTION_NOTIFICATION:
qDebug() << "Disconnected";
update = false;
break;
case ID_MASTER_QUERY:
qDebug() << "ID_MASTER_QUERY";
if (waitingPacket == ID_MASTER_QUERY)
pmq->Read();
else
qDebug() << "Got wrong packet";
update = false;
id = pid;
break;
case ID_MASTER_UPDATE:
qDebug() << "ID_MASTER_UPDATE";
if (waitingPacket == ID_MASTER_UPDATE)
pmu->Read();
else
qDebug() << "Got wrong packet";
update = false;
id = pid;
break;
case ID_MASTER_ANNOUNCE:
qDebug() << "ID_MASTER_ANNOUNCE";
update = false;
id = pid;
break;
case ID_CONNECTION_REQUEST_ACCEPTED:
qDebug() << "ID_CONNECTION_REQUEST_ACCEPTED";
break;
default:
break;
}
}
RakSleep(500);
}
return (MASTER_PACKETS)(id);
}
ConnectionState QueryClient::Connect()
{
ConnectionAttemptResult car = peer->Connect(masterAddr.ToString(false), masterAddr.GetPort(), TES3MP_MASTERSERVER_PASSW,
strlen(TES3MP_MASTERSERVER_PASSW), nullptr, 0, 5, 500);
while (true)
{
ConnectionState state = peer->GetConnectionState(masterAddr);
switch (state)
{
case IS_CONNECTED:
qDebug() << "Connected";
return IS_CONNECTED;
case IS_NOT_CONNECTED:
case IS_DISCONNECTED:
case IS_SILENTLY_DISCONNECTING:
case IS_DISCONNECTING:
{
qDebug() << "Cannot connect to the master server. Code:"<< state;
return IS_NOT_CONNECTED;
}
case IS_PENDING:
case IS_CONNECTING:
qDebug() << "Pending";
break;
}
RakSleep(500);
}
}
int QueryClient::Status()
{
return status;
}