mirror of
https://github.com/vcmi/vcmi.git
synced 2025-07-05 00:49:09 +02:00
Refactor enet-related code
This commit is contained in:
@ -11,7 +11,6 @@
|
|||||||
//
|
//
|
||||||
#include "StdInc.h"
|
#include "StdInc.h"
|
||||||
|
|
||||||
#include <enet/enet.h>
|
|
||||||
#include <boost/program_options.hpp>
|
#include <boost/program_options.hpp>
|
||||||
|
|
||||||
#include <vcmi/scripting/Service.h>
|
#include <vcmi/scripting/Service.h>
|
||||||
@ -251,11 +250,6 @@ int main(int argc, char * argv[])
|
|||||||
*console->cb = processCommand;
|
*console->cb = processCommand;
|
||||||
console->start();
|
console->start();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(enet_initialize() != 0)
|
|
||||||
{
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
const bfs::path logPath = VCMIDirs::get().userLogsPath() / "VCMI_Client_log.txt";
|
const bfs::path logPath = VCMIDirs::get().userLogsPath() / "VCMI_Client_log.txt";
|
||||||
logConfig = new CBasicLogConfigurator(logPath, console);
|
logConfig = new CBasicLogConfigurator(logPath, console);
|
||||||
|
@ -55,7 +55,6 @@
|
|||||||
#include "../lib/serializer/Cast.h"
|
#include "../lib/serializer/Cast.h"
|
||||||
|
|
||||||
#include <vcmi/events/EventBus.h>
|
#include <vcmi/events/EventBus.h>
|
||||||
#include <enet/enet.h>
|
|
||||||
|
|
||||||
#ifdef VCMI_WINDOWS
|
#ifdef VCMI_WINDOWS
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
@ -121,21 +120,27 @@ extern std::string NAME;
|
|||||||
CServerHandler::CServerHandler()
|
CServerHandler::CServerHandler()
|
||||||
: state(EClientState::NONE), mx(std::make_shared<boost::recursive_mutex>()), client(nullptr), loadMode(0), campaignStateToSend(nullptr), campaignServerRestartLock(false)
|
: state(EClientState::NONE), mx(std::make_shared<boost::recursive_mutex>()), client(nullptr), loadMode(0), campaignStateToSend(nullptr), campaignServerRestartLock(false)
|
||||||
{
|
{
|
||||||
enetClient = enet_host_create(NULL, 1, 2, 0, 0);
|
|
||||||
uuid = boost::uuids::to_string(boost::uuids::random_generator()());
|
uuid = boost::uuids::to_string(boost::uuids::random_generator()());
|
||||||
//read from file to restore last session
|
//read from file to restore last session
|
||||||
if(!settings["server"]["uuid"].isNull() && !settings["server"]["uuid"].String().empty())
|
if(!settings["server"]["uuid"].isNull() && !settings["server"]["uuid"].String().empty())
|
||||||
uuid = settings["server"]["uuid"].String();
|
uuid = settings["server"]["uuid"].String();
|
||||||
applier = std::make_shared<CApplier<CBaseForLobbyApply>>();
|
applier = std::make_shared<CApplier<CBaseForLobbyApply>>();
|
||||||
registerTypesLobbyPacks(*applier);
|
registerTypesLobbyPacks(*applier);
|
||||||
|
|
||||||
threadPollClient = std::make_shared<boost::thread>(&CServerHandler::threadPoll, this);
|
|
||||||
threadPollClient->detach();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CServerHandler::~CServerHandler()
|
CServerHandler::~CServerHandler()
|
||||||
{
|
{
|
||||||
enet_host_destroy(enetClient);
|
}
|
||||||
|
|
||||||
|
void CServerHandler::handleConnection(std::shared_ptr<EnetConnection> _c)
|
||||||
|
{
|
||||||
|
c = std::make_shared<CConnection>(_c, NAME, uuid);
|
||||||
|
c->handler = std::make_shared<boost::thread>(&CServerHandler::threadHandleConnection, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CServerHandler::handleDisconnection(std::shared_ptr<EnetConnection> _c)
|
||||||
|
{
|
||||||
|
state = EClientState::DISCONNECTING;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CServerHandler::resetStateForLobby(const StartInfo::EMode mode, const std::vector<std::string> * names)
|
void CServerHandler::resetStateForLobby(const StartInfo::EMode mode, const std::vector<std::string> * names)
|
||||||
@ -179,50 +184,6 @@ void CServerHandler::resetStateForLobby(const StartInfo::EMode mode, const std::
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void CServerHandler::threadPoll()
|
|
||||||
{
|
|
||||||
ENetEvent event;
|
|
||||||
while(true)
|
|
||||||
{
|
|
||||||
if(enet_host_service(enetClient, &event, 2) > 0)
|
|
||||||
{
|
|
||||||
switch(event.type)
|
|
||||||
{
|
|
||||||
case ENET_EVENT_TYPE_CONNECT: {
|
|
||||||
enet_packet_destroy(event.packet);
|
|
||||||
if(c && c->getPeer() == event.peer)
|
|
||||||
{
|
|
||||||
state = EClientState::CONNECTING;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case ENET_EVENT_TYPE_RECEIVE: {
|
|
||||||
if(c && c->getPeer() == event.peer)
|
|
||||||
{
|
|
||||||
c->dispatch(event.packet);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
enet_packet_destroy(event.packet);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case ENET_EVENT_TYPE_DISCONNECT:
|
|
||||||
{
|
|
||||||
enet_packet_destroy(event.packet);
|
|
||||||
if(c && c->getPeer() == event.peer)
|
|
||||||
{
|
|
||||||
c.reset();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CServerHandler::startLocalServerAndConnect()
|
void CServerHandler::startLocalServerAndConnect()
|
||||||
{
|
{
|
||||||
/*auto errorMsg = CGI->generaltexth->localizedTexts["server"]["errors"]["existingProcess"].String();
|
/*auto errorMsg = CGI->generaltexth->localizedTexts["server"]["errors"]["existingProcess"].String();
|
||||||
@ -320,21 +281,11 @@ void CServerHandler::startLocalServerAndConnect()
|
|||||||
|
|
||||||
void CServerHandler::justConnectToServer(const std::string & addr, const ui16 port)
|
void CServerHandler::justConnectToServer(const std::string & addr, const ui16 port)
|
||||||
{
|
{
|
||||||
while(!c && state != EClientState::CONNECTION_CANCELLED)
|
while(!valid() && state != EClientState::CONNECTION_CANCELLED)
|
||||||
{
|
{
|
||||||
try
|
logNetwork->info("Establishing connection...");
|
||||||
{
|
init(port ? port : getHostPort(), addr.size() ? addr : getHostAddress());
|
||||||
logNetwork->info("Establishing connection...");
|
boost::this_thread::sleep(boost::posix_time::seconds(1));
|
||||||
c = std::make_shared<CConnection>(enetClient,
|
|
||||||
addr.size() ? addr : getHostAddress(),
|
|
||||||
port ? port : getHostPort(),
|
|
||||||
NAME, uuid);
|
|
||||||
}
|
|
||||||
catch(...)
|
|
||||||
{
|
|
||||||
logNetwork->error("\nCannot establish connection! Retrying within 1 second");
|
|
||||||
boost::this_thread::sleep(boost::posix_time::seconds(1));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while(state != EClientState::CONNECTING)
|
while(state != EClientState::CONNECTING)
|
||||||
@ -346,9 +297,6 @@ void CServerHandler::justConnectToServer(const std::string & addr, const ui16 po
|
|||||||
}
|
}
|
||||||
boost::this_thread::sleep(boost::posix_time::milliseconds(100));
|
boost::this_thread::sleep(boost::posix_time::milliseconds(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
c->init();
|
|
||||||
c->handler = std::make_shared<boost::thread>(&CServerHandler::threadHandleConnection, this);
|
|
||||||
|
|
||||||
if(!addr.empty() && addr != getHostAddress())
|
if(!addr.empty() && addr != getHostAddress())
|
||||||
{
|
{
|
||||||
|
@ -9,12 +9,11 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <enet/enet.h>
|
|
||||||
|
|
||||||
#include "../lib/CStopWatch.h"
|
#include "../lib/CStopWatch.h"
|
||||||
|
|
||||||
#include "../lib/StartInfo.h"
|
#include "../lib/StartInfo.h"
|
||||||
#include "../lib/CondSh.h"
|
#include "../lib/CondSh.h"
|
||||||
|
#include "../lib/EnetService.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
@ -74,7 +73,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// structure to handle running server and connecting to it
|
/// structure to handle running server and connecting to it
|
||||||
class CServerHandler : public IServerAPI, public LobbyInfo
|
class CServerHandler : public IServerAPI, public LobbyInfo, public EnetService
|
||||||
{
|
{
|
||||||
std::shared_ptr<CApplier<CBaseForLobbyApply>> applier;
|
std::shared_ptr<CApplier<CBaseForLobbyApply>> applier;
|
||||||
|
|
||||||
@ -82,15 +81,17 @@ class CServerHandler : public IServerAPI, public LobbyInfo
|
|||||||
std::list<CPackForLobby *> packsForLobbyScreen; //protected by mx
|
std::list<CPackForLobby *> packsForLobbyScreen; //protected by mx
|
||||||
|
|
||||||
std::vector<std::string> myNames;
|
std::vector<std::string> myNames;
|
||||||
ENetHost * enetClient;
|
|
||||||
|
|
||||||
void threadHandleConnection();
|
void threadHandleConnection();
|
||||||
void threadRunServer();
|
void threadRunServer();
|
||||||
void threadPoll();
|
|
||||||
void onServerFinished();
|
void onServerFinished();
|
||||||
void sendLobbyPack(const CPackForLobby & pack) const override;
|
void sendLobbyPack(const CPackForLobby & pack) const override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
void handleDisconnection(std::shared_ptr<EnetConnection>) override;
|
||||||
|
void handleConnection(std::shared_ptr<EnetConnection>) override;
|
||||||
|
|
||||||
std::atomic<EClientState> state;
|
std::atomic<EClientState> state;
|
||||||
////////////////////
|
////////////////////
|
||||||
// FIXME: Bunch of crutches to glue it all together
|
// FIXME: Bunch of crutches to glue it all together
|
||||||
@ -104,8 +105,6 @@ public:
|
|||||||
|
|
||||||
std::unique_ptr<CStopWatch> th;
|
std::unique_ptr<CStopWatch> th;
|
||||||
std::shared_ptr<boost::thread> threadRunLocalServer;
|
std::shared_ptr<boost::thread> threadRunLocalServer;
|
||||||
std::shared_ptr<boost::thread> threadPollClient;
|
|
||||||
|
|
||||||
std::shared_ptr<CConnection> c;
|
std::shared_ptr<CConnection> c;
|
||||||
CClient * client;
|
CClient * client;
|
||||||
|
|
||||||
|
@ -179,6 +179,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
|
|||||||
${MAIN_LIB_DIR}/CStack.cpp
|
${MAIN_LIB_DIR}/CStack.cpp
|
||||||
${MAIN_LIB_DIR}/CThreadHelper.cpp
|
${MAIN_LIB_DIR}/CThreadHelper.cpp
|
||||||
${MAIN_LIB_DIR}/CTownHandler.cpp
|
${MAIN_LIB_DIR}/CTownHandler.cpp
|
||||||
|
${MAIN_LIB_DIR}/EnetService.cpp
|
||||||
${MAIN_LIB_DIR}/GameConstants.cpp
|
${MAIN_LIB_DIR}/GameConstants.cpp
|
||||||
${MAIN_LIB_DIR}/HeroBonus.cpp
|
${MAIN_LIB_DIR}/HeroBonus.cpp
|
||||||
${MAIN_LIB_DIR}/IGameCallback.cpp
|
${MAIN_LIB_DIR}/IGameCallback.cpp
|
||||||
@ -420,6 +421,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE)
|
|||||||
${MAIN_LIB_DIR}/CStopWatch.h
|
${MAIN_LIB_DIR}/CStopWatch.h
|
||||||
${MAIN_LIB_DIR}/CThreadHelper.h
|
${MAIN_LIB_DIR}/CThreadHelper.h
|
||||||
${MAIN_LIB_DIR}/CTownHandler.h
|
${MAIN_LIB_DIR}/CTownHandler.h
|
||||||
|
${MAIN_LIB_DIR}/EnetService.h
|
||||||
${MAIN_LIB_DIR}/FunctionList.h
|
${MAIN_LIB_DIR}/FunctionList.h
|
||||||
${MAIN_LIB_DIR}/GameConstants.h
|
${MAIN_LIB_DIR}/GameConstants.h
|
||||||
${MAIN_LIB_DIR}/HeroBonus.h
|
${MAIN_LIB_DIR}/HeroBonus.h
|
||||||
|
270
lib/EnetService.cpp
Normal file
270
lib/EnetService.cpp
Normal file
@ -0,0 +1,270 @@
|
|||||||
|
//
|
||||||
|
// EnetService.cpp
|
||||||
|
// vcmi
|
||||||
|
//
|
||||||
|
// Created by nordsoft on 17.01.2023.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "EnetService.h"
|
||||||
|
#include "StdInc.h"
|
||||||
|
#include "CThreadHelper.h"
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
EnetConnection::EnetConnection(ENetPeer * _peer):
|
||||||
|
peer(_peer)
|
||||||
|
{
|
||||||
|
connected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
EnetConnection::EnetConnection(ENetHost * client, const std::string & host, ui16 port)
|
||||||
|
{
|
||||||
|
connected = false;
|
||||||
|
ENetAddress address;
|
||||||
|
enet_address_set_host(&address, host.c_str());
|
||||||
|
address.port = port;
|
||||||
|
|
||||||
|
peer = enet_host_connect(client, &address, 2, 0);
|
||||||
|
if(!peer)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Can't establish connection :(");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EnetConnection::~EnetConnection()
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
kill();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EnetConnection::isOpen() const
|
||||||
|
{
|
||||||
|
return connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnetConnection::open()
|
||||||
|
{
|
||||||
|
connected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnetConnection::close()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> guard(mutexWrite);
|
||||||
|
connected = false;
|
||||||
|
enet_peer_disconnect(peer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnetConnection::kill()
|
||||||
|
{
|
||||||
|
connected = false;
|
||||||
|
if(peer)
|
||||||
|
enet_peer_reset(peer);
|
||||||
|
peer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ENetPeer * EnetConnection::getPeer() const
|
||||||
|
{
|
||||||
|
return peer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnetConnection::dispatch(ENetPacket * packet)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> guard(mutexRead);
|
||||||
|
packets.push_back(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnetConnection::write(const void * data, unsigned size)
|
||||||
|
{
|
||||||
|
if(size == 0 || !isOpen())
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> guard(mutexWrite);
|
||||||
|
ENetPacket * packet = enet_packet_create(data, size, ENET_PACKET_FLAG_RELIABLE);
|
||||||
|
enet_peer_send(peer, channel, packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnetConnection::read(void * data, unsigned size)
|
||||||
|
{
|
||||||
|
if(!size)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while(packets.empty())
|
||||||
|
{
|
||||||
|
if(!isOpen())
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(READ_REFRESH));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> guard(mutexRead);
|
||||||
|
auto * packet = packets.front();
|
||||||
|
packets.pop_front();
|
||||||
|
|
||||||
|
if(packet->dataLength > 0)
|
||||||
|
memcpy(data, packet->data, packet->dataLength);
|
||||||
|
|
||||||
|
assert(size == packet->dataLength);
|
||||||
|
enet_packet_destroy(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
EnetService::EnetService():
|
||||||
|
service(nullptr), flagValid(false)
|
||||||
|
{
|
||||||
|
if(enet_initialize() != 0)
|
||||||
|
throw std::runtime_error("Cannot initialize enet");
|
||||||
|
|
||||||
|
doMonitoring = true;
|
||||||
|
threadMonitoring = std::make_unique<std::thread>(&EnetService::monitor, this);
|
||||||
|
threadMonitoring->detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
EnetService::~EnetService()
|
||||||
|
{
|
||||||
|
stop();
|
||||||
|
doMonitoring = false;
|
||||||
|
if(threadMonitoring)
|
||||||
|
threadMonitoring->join();
|
||||||
|
|
||||||
|
enet_deinitialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnetService::init(short port, const std::string & host)
|
||||||
|
{
|
||||||
|
init(0);
|
||||||
|
active.insert(std::make_shared<EnetConnection>(service, host, port));
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnetService::init(short port)
|
||||||
|
{
|
||||||
|
ENetAddress address;
|
||||||
|
address.host = ENET_HOST_ANY;
|
||||||
|
address.port = port;
|
||||||
|
|
||||||
|
service = enet_host_create(port ? &address : nullptr, port ? CONNECTIONS : 1, CHANNELS, 0, 0);
|
||||||
|
if(service)
|
||||||
|
flagValid = true;
|
||||||
|
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnetService::start()
|
||||||
|
{
|
||||||
|
stop();
|
||||||
|
doPolling = true;
|
||||||
|
|
||||||
|
if(service)
|
||||||
|
{
|
||||||
|
threadPolling = std::make_unique<std::thread>(&EnetService::poll, this);
|
||||||
|
threadPolling->detach();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnetService::monitor()
|
||||||
|
{
|
||||||
|
setThreadName("EnetService::monitor");
|
||||||
|
while(doMonitoring)
|
||||||
|
{
|
||||||
|
while(!disconnecting.empty())
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> guard(mutex);
|
||||||
|
if(disconnecting.front()->isOpen())
|
||||||
|
disconnecting.front()->kill();
|
||||||
|
handleDisconnection(disconnecting.front());
|
||||||
|
disconnecting.pop_front();
|
||||||
|
}
|
||||||
|
while(!connecting.empty())
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> guard(mutex);
|
||||||
|
connecting.front()->open();
|
||||||
|
handleConnection(connecting.front());
|
||||||
|
connecting.pop_front();
|
||||||
|
}
|
||||||
|
if(service)
|
||||||
|
enet_host_flush(service);
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(MONITOR_INTERVAL));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnetService::stop()
|
||||||
|
{
|
||||||
|
doPolling = false;
|
||||||
|
if(threadPolling)
|
||||||
|
threadPolling->join();
|
||||||
|
threadPolling.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EnetService::valid() const
|
||||||
|
{
|
||||||
|
return flagValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnetService::poll()
|
||||||
|
{
|
||||||
|
setThreadName("EnetService::poll");
|
||||||
|
ENetEvent event;
|
||||||
|
while(doPolling)
|
||||||
|
{
|
||||||
|
if(enet_host_service(service, &event, POLL_INTERVAL) > 0)
|
||||||
|
{
|
||||||
|
switch(event.type)
|
||||||
|
{
|
||||||
|
case ENET_EVENT_TYPE_CONNECT: {
|
||||||
|
bool receiverFound = false;
|
||||||
|
for(auto & c : active)
|
||||||
|
{
|
||||||
|
if(c->getPeer() == event.peer)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> guard(mutex);
|
||||||
|
connecting.push_back(c);
|
||||||
|
receiverFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!receiverFound)
|
||||||
|
{
|
||||||
|
auto c = std::make_shared<EnetConnection>(event.peer);
|
||||||
|
active.insert(c);
|
||||||
|
std::lock_guard<std::mutex> guard(mutex);
|
||||||
|
connecting.push_back(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
enet_packet_destroy(event.packet);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ENET_EVENT_TYPE_RECEIVE: {
|
||||||
|
bool receiverFound = false;
|
||||||
|
for(auto & c : active)
|
||||||
|
{
|
||||||
|
if(c->getPeer() == event.peer)
|
||||||
|
{
|
||||||
|
c->dispatch(event.packet);
|
||||||
|
receiverFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!receiverFound)
|
||||||
|
enet_packet_destroy(event.packet);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ENET_EVENT_TYPE_DISCONNECT: {
|
||||||
|
for(auto c : active)
|
||||||
|
{
|
||||||
|
if(c->getPeer() == event.peer)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> guard(mutex);
|
||||||
|
disconnecting.push_back(c);
|
||||||
|
active.erase(c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enet_packet_destroy(event.packet);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
82
lib/EnetService.h
Normal file
82
lib/EnetService.h
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
//
|
||||||
|
// EnetService.hpp
|
||||||
|
// vcmi
|
||||||
|
//
|
||||||
|
// Created by nordsoft on 17.01.2023.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <enet/enet.h>
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
class DLL_LINKAGE EnetConnection
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
const unsigned int READ_REFRESH = 20; //ms
|
||||||
|
|
||||||
|
std::list<ENetPacket*> packets;
|
||||||
|
int channel = 0;
|
||||||
|
ENetPeer * peer = nullptr;
|
||||||
|
std::atomic<bool> connected;
|
||||||
|
|
||||||
|
std::mutex mutexRead, mutexWrite;
|
||||||
|
|
||||||
|
public:
|
||||||
|
EnetConnection(ENetPeer * peer);
|
||||||
|
EnetConnection(ENetHost * client, const std::string & host, ui16 port);
|
||||||
|
virtual ~EnetConnection();
|
||||||
|
|
||||||
|
bool isOpen() const;
|
||||||
|
void open();
|
||||||
|
void close();
|
||||||
|
void kill();
|
||||||
|
const ENetPeer * getPeer() const;
|
||||||
|
void dispatch(ENetPacket * packet);
|
||||||
|
|
||||||
|
void write(const void * data, unsigned size);
|
||||||
|
void read(void * data, unsigned size);
|
||||||
|
};
|
||||||
|
|
||||||
|
class DLL_LINKAGE EnetService
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
const unsigned int CHANNELS = 2;
|
||||||
|
const unsigned int CONNECTIONS = 16;
|
||||||
|
const unsigned int POLL_INTERVAL = 4; //ms
|
||||||
|
const unsigned int MONITOR_INTERVAL = 50; //ms
|
||||||
|
|
||||||
|
ENetHost * service;
|
||||||
|
|
||||||
|
std::set<std::shared_ptr<EnetConnection>> active;
|
||||||
|
std::list<std::shared_ptr<EnetConnection>> connecting, disconnecting;
|
||||||
|
|
||||||
|
std::atomic<bool> doPolling, doMonitoring;
|
||||||
|
bool flagValid;
|
||||||
|
|
||||||
|
std::unique_ptr<std::thread> threadPolling, threadMonitoring;
|
||||||
|
std::mutex mutex;
|
||||||
|
|
||||||
|
void poll();
|
||||||
|
void monitor();
|
||||||
|
void start();
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
EnetService();
|
||||||
|
virtual ~EnetService();
|
||||||
|
|
||||||
|
void init(short port);
|
||||||
|
void init(short port, const std::string & host);
|
||||||
|
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
bool valid() const;
|
||||||
|
|
||||||
|
virtual void handleDisconnection(std::shared_ptr<EnetConnection>) = 0;
|
||||||
|
virtual void handleConnection(std::shared_ptr<EnetConnection>) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
@ -51,76 +51,30 @@ void CConnection::init()
|
|||||||
iser.fileVersion = SERIALIZATION_VERSION;
|
iser.fileVersion = SERIALIZATION_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
CConnection::CConnection(ENetHost * _client, ENetPeer * _peer, std::string Name, std::string UUID)
|
CConnection::CConnection(std::shared_ptr<EnetConnection> _c, std::string Name, std::string UUID)
|
||||||
: client(_client), peer(_peer), iser(this), oser(this), name(Name), uuid(UUID), connectionID(0), connected(false), channel(1)
|
: enetConnection(_c), iser(this), oser(this), name(Name), uuid(UUID), connectionID(0), connected(false)
|
||||||
{
|
{
|
||||||
//init();
|
init();
|
||||||
}
|
|
||||||
|
|
||||||
CConnection::CConnection(ENetHost * _client, std::string host, ui16 port, std::string Name, std::string UUID)
|
|
||||||
: client(_client), iser(this), oser(this), name(Name), uuid(UUID), connectionID(0), connected(false), channel(0)
|
|
||||||
{
|
|
||||||
ENetAddress address;
|
|
||||||
enet_address_set_host(&address, host.c_str());
|
|
||||||
address.port = port;
|
|
||||||
|
|
||||||
peer = enet_host_connect(client, &address, 2, 0);
|
|
||||||
if(peer == NULL)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("Can't establish connection :(");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CConnection::dispatch(ENetPacket * packet)
|
|
||||||
{
|
|
||||||
boost::unique_lock<boost::mutex> lock(mutexRead);
|
|
||||||
packets.push_back(packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
const ENetPeer * CConnection::getPeer() const
|
|
||||||
{
|
|
||||||
return peer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int CConnection::write(const void * data, unsigned size)
|
int CConnection::write(const void * data, unsigned size)
|
||||||
{
|
{
|
||||||
if(size == 0)
|
if(connected)
|
||||||
return 0;
|
enetConnection->write(data, size);
|
||||||
boost::unique_lock<boost::mutex> lock(mutexWrite);
|
|
||||||
ENetPacket * packet = enet_packet_create(data, size, ENET_PACKET_FLAG_RELIABLE);
|
|
||||||
enet_peer_send(peer, channel, packet);
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CConnection::read(void * data, unsigned size)
|
int CConnection::read(void * data, unsigned size)
|
||||||
{
|
{
|
||||||
const int timout = 1000;
|
if(connected)
|
||||||
if(size == 0)
|
enetConnection->read(data, size);
|
||||||
return 0;
|
return size;
|
||||||
for(int i = 0; packets.empty() && (i < timout || connected); ++i)
|
|
||||||
{
|
|
||||||
boost::this_thread::sleep(boost::posix_time::milliseconds(10));
|
|
||||||
}
|
|
||||||
boost::unique_lock<boost::mutex> lock(mutexRead);
|
|
||||||
auto * packet = packets.front();
|
|
||||||
packets.pop_front();
|
|
||||||
|
|
||||||
if(packet->dataLength > 0)
|
|
||||||
memcpy(data, packet->data, packet->dataLength);
|
|
||||||
int ret = packet->dataLength;
|
|
||||||
assert(ret == size);
|
|
||||||
enet_packet_destroy(packet);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CConnection::~CConnection()
|
CConnection::~CConnection()
|
||||||
{
|
{
|
||||||
if(handler)
|
if(handler)
|
||||||
handler->join();
|
handler->join();
|
||||||
|
|
||||||
for(auto * packet : packets)
|
|
||||||
enet_packet_destroy(packet);
|
|
||||||
|
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
@ -134,11 +88,18 @@ CConnection & CConnection::operator&(const T &t) {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::shared_ptr<EnetConnection> CConnection::getEnetConnection() const
|
||||||
|
{
|
||||||
|
return enetConnection;
|
||||||
|
}
|
||||||
|
|
||||||
void CConnection::close()
|
void CConnection::close()
|
||||||
{
|
{
|
||||||
boost::unique_lock<boost::mutex> lock(mutexWrite);
|
connected = false;
|
||||||
enet_peer_disconnect(peer, 0);
|
if(enetConnection->isOpen())
|
||||||
enet_peer_reset(peer);
|
enetConnection->close();
|
||||||
|
else
|
||||||
|
enetConnection->kill();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CConnection::isOpen() const
|
bool CConnection::isOpen() const
|
||||||
@ -179,9 +140,7 @@ void CConnection::sendPack(const CPack * pack)
|
|||||||
{
|
{
|
||||||
logNetwork->trace("Sending a pack of type %s", typeid(*pack).name());
|
logNetwork->trace("Sending a pack of type %s", typeid(*pack).name());
|
||||||
|
|
||||||
|
|
||||||
oser & pack;
|
oser & pack;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CConnection::disableStackSendingByID()
|
void CConnection::disableStackSendingByID()
|
||||||
|
@ -9,10 +9,9 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <enet/enet.h>
|
|
||||||
|
|
||||||
#include "BinaryDeserializer.h"
|
#include "BinaryDeserializer.h"
|
||||||
#include "BinarySerializer.h"
|
#include "BinarySerializer.h"
|
||||||
|
#include "../EnetService.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
@ -24,16 +23,13 @@ struct ConnectionBuffers;
|
|||||||
class DLL_LINKAGE CConnection
|
class DLL_LINKAGE CConnection
|
||||||
: public IBinaryReader, public IBinaryWriter, public std::enable_shared_from_this<CConnection>
|
: public IBinaryReader, public IBinaryWriter, public std::enable_shared_from_this<CConnection>
|
||||||
{
|
{
|
||||||
|
std::shared_ptr<EnetConnection> enetConnection;
|
||||||
|
|
||||||
void reportState(vstd::CLoggerBase * out) override;
|
void reportState(vstd::CLoggerBase * out) override;
|
||||||
|
|
||||||
int write(const void * data, unsigned size) override;
|
int write(const void * data, unsigned size) override;
|
||||||
int read(void * data, unsigned size) override;
|
int read(void * data, unsigned size) override;
|
||||||
|
|
||||||
std::list<ENetPacket*> packets;
|
|
||||||
int channel;
|
|
||||||
ENetPeer * peer = nullptr;
|
|
||||||
ENetHost * client = nullptr;
|
|
||||||
|
|
||||||
BinaryDeserializer iser;
|
BinaryDeserializer iser;
|
||||||
BinarySerializer oser;
|
BinarySerializer oser;
|
||||||
|
|
||||||
@ -51,12 +47,11 @@ public:
|
|||||||
int connectionID;
|
int connectionID;
|
||||||
std::shared_ptr<boost::thread> handler;
|
std::shared_ptr<boost::thread> handler;
|
||||||
|
|
||||||
CConnection(ENetHost * client, ENetPeer * peer, std::string Name, std::string UUID);
|
CConnection(std::shared_ptr<EnetConnection>, std::string Name, std::string UUID);
|
||||||
CConnection(ENetHost * client, std::string host, ui16 port, std::string Name, std::string UUID);
|
|
||||||
void init(); //must be called from outside after connection message received
|
const std::shared_ptr<EnetConnection> getEnetConnection() const;
|
||||||
void dispatch(ENetPacket * packet);
|
|
||||||
const ENetPeer * getPeer() const;
|
|
||||||
|
|
||||||
|
void init();
|
||||||
void close();
|
void close();
|
||||||
bool isOpen() const;
|
bool isOpen() const;
|
||||||
template<class T>
|
template<class T>
|
||||||
|
@ -127,18 +127,9 @@ CVCMIServer::CVCMIServer(boost::program_options::variables_map & opts)
|
|||||||
port = cmdLineOptions["port"].as<ui16>();
|
port = cmdLineOptions["port"].as<ui16>();
|
||||||
logNetwork->info("Port %d will be used", port);
|
logNetwork->info("Port %d will be used", port);
|
||||||
|
|
||||||
const int maxConnections = 8;
|
init(port);
|
||||||
const int maxChannels = 2;
|
if(!valid())
|
||||||
|
state = EServerState::SHUTDOWN;
|
||||||
ENetAddress address;
|
|
||||||
address.host = ENET_HOST_ANY;
|
|
||||||
address.port = port;
|
|
||||||
server = enet_host_create(&address, maxConnections, maxChannels, 0, 0);
|
|
||||||
if(!server)
|
|
||||||
{
|
|
||||||
logNetwork->error("Can't create host at port %d", port);
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
logNetwork->info("Listening for connections at port %d", port);
|
logNetwork->info("Listening for connections at port %d", port);
|
||||||
}
|
}
|
||||||
@ -151,8 +142,68 @@ CVCMIServer::~CVCMIServer()
|
|||||||
announceLobbyThread->join();
|
announceLobbyThread->join();
|
||||||
if(lobbyConnectionsThread)
|
if(lobbyConnectionsThread)
|
||||||
lobbyConnectionsThread->join();
|
lobbyConnectionsThread->join();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CVCMIServer::handleConnection(std::shared_ptr<EnetConnection> _c)
|
||||||
|
{
|
||||||
|
auto c = *connections.insert(std::make_shared<CConnection>(_c, SERVER_NAME, uuid)).first;
|
||||||
|
c->handler = std::make_shared<boost::thread>(&CVCMIServer::threadHandleClient, this, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CVCMIServer::handleDisconnection(std::shared_ptr<EnetConnection> _c)
|
||||||
|
{
|
||||||
|
std::shared_ptr<CConnection> c;
|
||||||
|
for(auto cc : connections)
|
||||||
|
{
|
||||||
|
if(cc->getEnetConnection() == _c)
|
||||||
|
{
|
||||||
|
c = cc;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(c);
|
||||||
|
c->close();
|
||||||
|
connections -= c;
|
||||||
|
if(connections.empty() || hostClient == c)
|
||||||
|
{
|
||||||
|
state = EServerState::SHUTDOWN;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
enet_host_destroy(server);
|
PlayerReinitInterface startAiPack;
|
||||||
|
startAiPack.playerConnectionId = PlayerSettings::PLAYER_AI;
|
||||||
|
|
||||||
|
for(auto it = playerNames.begin(); it != playerNames.end();)
|
||||||
|
{
|
||||||
|
if(it->second.connection != c->connectionID)
|
||||||
|
{
|
||||||
|
++it;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int id = it->first;
|
||||||
|
std::string playerLeftMsgText = boost::str(boost::format("%s (pid %d cid %d) left the game") % id % playerNames[id].name % c->connectionID);
|
||||||
|
announceTxt(playerLeftMsgText); //send lobby text, it will be ignored for non-lobby clients
|
||||||
|
auto * playerSettings = si->getPlayersSettings(id);
|
||||||
|
if(!playerSettings)
|
||||||
|
{
|
||||||
|
++it;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
it = playerNames.erase(it);
|
||||||
|
setPlayerConnectedId(*playerSettings, PlayerSettings::PLAYER_AI);
|
||||||
|
|
||||||
|
if(gh && si && state == EServerState::GAMEPLAY)
|
||||||
|
{
|
||||||
|
gh->playerMessage(playerSettings->color, playerLeftMsgText, ObjectInstanceID{});
|
||||||
|
gh->connections[playerSettings->color].insert(hostClient);
|
||||||
|
startAiPack.players.push_back(playerSettings->color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!startAiPack.players.empty())
|
||||||
|
gh->sendAndApply(&startAiPack);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CVCMIServer::run()
|
void CVCMIServer::run()
|
||||||
@ -172,9 +223,6 @@ void CVCMIServer::run()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(!lobbyConnectionsThread)
|
|
||||||
lobbyConnectionsThread = std::make_unique<boost::thread>(&CVCMIServer::startAsyncAccept, this);
|
|
||||||
|
|
||||||
/*if(!remoteConnectionsThread && cmdLineOptions.count("lobby"))
|
/*if(!remoteConnectionsThread && cmdLineOptions.count("lobby"))
|
||||||
{
|
{
|
||||||
remoteConnectionsThread = vstd::make_unique<boost::thread>(&CVCMIServer::establishRemoteConnections, this);
|
remoteConnectionsThread = vstd::make_unique<boost::thread>(&CVCMIServer::establishRemoteConnections, this);
|
||||||
@ -193,7 +241,6 @@ void CVCMIServer::run()
|
|||||||
|
|
||||||
while(state == EServerState::LOBBY || state == EServerState::GAMEPLAY_STARTING)
|
while(state == EServerState::LOBBY || state == EServerState::GAMEPLAY_STARTING)
|
||||||
{
|
{
|
||||||
connectionAccepted();
|
|
||||||
boost::this_thread::sleep(boost::posix_time::milliseconds(50));
|
boost::this_thread::sleep(boost::posix_time::milliseconds(50));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,7 +271,7 @@ void CVCMIServer::connectToRemote(const std::string & addr, int port)
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
logNetwork->info("Establishing connection...");
|
logNetwork->info("Establishing connection...");
|
||||||
c = std::make_shared<CConnection>(server, addr, port, SERVER_NAME, uuid);
|
//c = std::make_shared<CConnection>(server, addr, port, SERVER_NAME, uuid);
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
@ -316,72 +363,6 @@ void CVCMIServer::startGameImmidiately()
|
|||||||
state = EServerState::GAMEPLAY;
|
state = EServerState::GAMEPLAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CVCMIServer::startAsyncAccept()
|
|
||||||
{
|
|
||||||
ENetEvent event;
|
|
||||||
while(state != EServerState::SHUTDOWN)
|
|
||||||
{
|
|
||||||
if(enet_host_service(server, &event, 2) > 0)
|
|
||||||
{
|
|
||||||
switch(event.type)
|
|
||||||
{
|
|
||||||
case ENET_EVENT_TYPE_CONNECT: {
|
|
||||||
if(state == EServerState::LOBBY)
|
|
||||||
{
|
|
||||||
upcomingConnection = std::make_shared<CConnection>(server, event.peer, SERVER_NAME, uuid);
|
|
||||||
connections.insert(upcomingConnection);
|
|
||||||
}
|
|
||||||
enet_packet_destroy(event.packet);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case ENET_EVENT_TYPE_RECEIVE: {
|
|
||||||
|
|
||||||
bool receiverFound = false;
|
|
||||||
for(auto & c : connections)
|
|
||||||
{
|
|
||||||
if(c->getPeer() == event.peer)
|
|
||||||
{
|
|
||||||
c->dispatch(event.packet);
|
|
||||||
receiverFound = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!receiverFound)
|
|
||||||
enet_packet_destroy(event.packet);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case ENET_EVENT_TYPE_DISCONNECT: {
|
|
||||||
enet_packet_destroy(event.packet);
|
|
||||||
for(auto & c : connections)
|
|
||||||
{
|
|
||||||
if(c->getPeer() == event.peer)
|
|
||||||
{
|
|
||||||
clientDisconnected(c);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CVCMIServer::connectionAccepted()
|
|
||||||
{
|
|
||||||
if(upcomingConnection)
|
|
||||||
{
|
|
||||||
upcomingConnection->init();
|
|
||||||
upcomingConnection->handler = std::make_shared<boost::thread>(&CVCMIServer::threadHandleClient, this, upcomingConnection);
|
|
||||||
upcomingConnection.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CVCMIServer::threadHandleClient(std::shared_ptr<CConnection> c)
|
void CVCMIServer::threadHandleClient(std::shared_ptr<CConnection> c)
|
||||||
{
|
{
|
||||||
setThreadName("CVCMIServer::handleConnection");
|
setThreadName("CVCMIServer::handleConnection");
|
||||||
@ -555,51 +536,6 @@ void CVCMIServer::clientConnected(std::shared_ptr<CConnection> c, std::vector<st
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CVCMIServer::clientDisconnected(std::shared_ptr<CConnection> c)
|
|
||||||
{
|
|
||||||
connections -= c;
|
|
||||||
if(connections.empty() || hostClient == c)
|
|
||||||
{
|
|
||||||
state = EServerState::SHUTDOWN;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PlayerReinitInterface startAiPack;
|
|
||||||
startAiPack.playerConnectionId = PlayerSettings::PLAYER_AI;
|
|
||||||
|
|
||||||
for(auto it = playerNames.begin(); it != playerNames.end();)
|
|
||||||
{
|
|
||||||
if(it->second.connection != c->connectionID)
|
|
||||||
{
|
|
||||||
++it;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int id = it->first;
|
|
||||||
std::string playerLeftMsgText = boost::str(boost::format("%s (pid %d cid %d) left the game") % id % playerNames[id].name % c->connectionID);
|
|
||||||
announceTxt(playerLeftMsgText); //send lobby text, it will be ignored for non-lobby clients
|
|
||||||
auto * playerSettings = si->getPlayersSettings(id);
|
|
||||||
if(!playerSettings)
|
|
||||||
{
|
|
||||||
++it;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
it = playerNames.erase(it);
|
|
||||||
setPlayerConnectedId(*playerSettings, PlayerSettings::PLAYER_AI);
|
|
||||||
|
|
||||||
if(gh && si && state == EServerState::GAMEPLAY)
|
|
||||||
{
|
|
||||||
gh->playerMessage(playerSettings->color, playerLeftMsgText, ObjectInstanceID{});
|
|
||||||
gh->connections[playerSettings->color].insert(hostClient);
|
|
||||||
startAiPack.players.push_back(playerSettings->color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!startAiPack.players.empty())
|
|
||||||
gh->sendAndApply(&startAiPack);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CVCMIServer::reconnectPlayer(int connId)
|
void CVCMIServer::reconnectPlayer(int connId)
|
||||||
{
|
{
|
||||||
PlayerReinitInterface startAiPack;
|
PlayerReinitInterface startAiPack;
|
||||||
@ -1073,10 +1009,6 @@ static void handleCommandOptions(int argc, char * argv[], boost::program_options
|
|||||||
int main(int argc, char * argv[])
|
int main(int argc, char * argv[])
|
||||||
{
|
{
|
||||||
#if !defined(VCMI_ANDROID) && !defined(SINGLE_PROCESS_APP)
|
#if !defined(VCMI_ANDROID) && !defined(SINGLE_PROCESS_APP)
|
||||||
if(enet_initialize() != 0)
|
|
||||||
{
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
// Correct working dir executable folder (not bundle folder) so we can use executable relative paths
|
// Correct working dir executable folder (not bundle folder) so we can use executable relative paths
|
||||||
boost::filesystem::current_path(boost::filesystem::system_complete(argv[0]).parent_path());
|
boost::filesystem::current_path(boost::filesystem::system_complete(argv[0]).parent_path());
|
||||||
#endif
|
#endif
|
||||||
@ -1126,7 +1058,6 @@ int main(int argc, char * argv[])
|
|||||||
#endif
|
#endif
|
||||||
logConfig.deconfigure();
|
logConfig.deconfigure();
|
||||||
vstd::clear_pointer(VLC);
|
vstd::clear_pointer(VLC);
|
||||||
enet_deinitialize();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
#include "../lib/serializer/Connection.h"
|
#include "../lib/serializer/Connection.h"
|
||||||
#include "../lib/StartInfo.h"
|
#include "../lib/StartInfo.h"
|
||||||
#include <enet/enet.h>
|
#include "../lib/EnetService.h"
|
||||||
|
|
||||||
#include <boost/program_options.hpp>
|
#include <boost/program_options.hpp>
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ enum class EServerState : ui8
|
|||||||
SHUTDOWN
|
SHUTDOWN
|
||||||
};
|
};
|
||||||
|
|
||||||
class CVCMIServer : public LobbyInfo
|
class CVCMIServer : public LobbyInfo, public EnetService
|
||||||
{
|
{
|
||||||
std::atomic<bool> restartGameplay; // FIXME: this is just a hack
|
std::atomic<bool> restartGameplay; // FIXME: this is just a hack
|
||||||
|
|
||||||
@ -53,9 +53,10 @@ class CVCMIServer : public LobbyInfo
|
|||||||
std::shared_ptr<CApplier<CBaseForServerApply>> applier;
|
std::shared_ptr<CApplier<CBaseForServerApply>> applier;
|
||||||
std::unique_ptr<boost::thread> announceLobbyThread, lobbyConnectionsThread, remoteConnectionsThread;
|
std::unique_ptr<boost::thread> announceLobbyThread, lobbyConnectionsThread, remoteConnectionsThread;
|
||||||
|
|
||||||
ENetHost * server;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
void handleDisconnection(std::shared_ptr<EnetConnection>) override;
|
||||||
|
void handleConnection(std::shared_ptr<EnetConnection>) override;
|
||||||
|
|
||||||
std::shared_ptr<CGameHandler> gh;
|
std::shared_ptr<CGameHandler> gh;
|
||||||
std::atomic<EServerState> state;
|
std::atomic<EServerState> state;
|
||||||
ui16 port;
|
ui16 port;
|
||||||
@ -67,7 +68,6 @@ public:
|
|||||||
std::atomic<int> currentClientId;
|
std::atomic<int> currentClientId;
|
||||||
std::atomic<ui8> currentPlayerId;
|
std::atomic<ui8> currentPlayerId;
|
||||||
std::shared_ptr<CConnection> hostClient;
|
std::shared_ptr<CConnection> hostClient;
|
||||||
std::shared_ptr<CConnection> upcomingConnection;
|
|
||||||
|
|
||||||
CVCMIServer(boost::program_options::variables_map & opts);
|
CVCMIServer(boost::program_options::variables_map & opts);
|
||||||
~CVCMIServer();
|
~CVCMIServer();
|
||||||
@ -78,8 +78,6 @@ public:
|
|||||||
|
|
||||||
void establishRemoteConnections();
|
void establishRemoteConnections();
|
||||||
void connectToRemote(const std::string & addr, int port);
|
void connectToRemote(const std::string & addr, int port);
|
||||||
void startAsyncAccept();
|
|
||||||
void connectionAccepted();
|
|
||||||
void threadHandleClient(std::shared_ptr<CConnection> c);
|
void threadHandleClient(std::shared_ptr<CConnection> c);
|
||||||
void threadAnnounceLobby();
|
void threadAnnounceLobby();
|
||||||
void handleReceivedPack(std::unique_ptr<CPackForLobby> pack);
|
void handleReceivedPack(std::unique_ptr<CPackForLobby> pack);
|
||||||
@ -95,7 +93,6 @@ public:
|
|||||||
void updateStartInfoOnMapChange(std::shared_ptr<CMapInfo> mapInfo, std::shared_ptr<CMapGenOptions> mapGenOpt = {});
|
void updateStartInfoOnMapChange(std::shared_ptr<CMapInfo> mapInfo, std::shared_ptr<CMapGenOptions> mapGenOpt = {});
|
||||||
|
|
||||||
void clientConnected(std::shared_ptr<CConnection> c, std::vector<std::string> & names, std::string uuid, StartInfo::EMode mode);
|
void clientConnected(std::shared_ptr<CConnection> c, std::vector<std::string> & names, std::string uuid, StartInfo::EMode mode);
|
||||||
void clientDisconnected(std::shared_ptr<CConnection> c);
|
|
||||||
void reconnectPlayer(int connId);
|
void reconnectPlayer(int connId);
|
||||||
|
|
||||||
void updateAndPropagateLobbyState();
|
void updateAndPropagateLobbyState();
|
||||||
|
@ -129,7 +129,6 @@ bool LobbyClientDisconnected::checkClientPermissions(CVCMIServer * srv) const
|
|||||||
|
|
||||||
bool LobbyClientDisconnected::applyOnServer(CVCMIServer * srv)
|
bool LobbyClientDisconnected::applyOnServer(CVCMIServer * srv)
|
||||||
{
|
{
|
||||||
srv->clientDisconnected(c);
|
|
||||||
c->close();
|
c->close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user