1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-24 08:32:34 +02:00

Merge pull request #4253 from smanolloff/random-port

Bind VCMI server to a random TCP port
This commit is contained in:
Ivan Savenko 2024-07-16 12:25:29 +03:00 committed by GitHub
commit 696cce7f7f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 58 additions and 31 deletions

View File

@ -238,9 +238,9 @@ void CServerHandler::startLocalServerAndConnect(bool connectToLobby)
si->difficulty = lastDifficulty.Integer();
logNetwork->trace("\tStarting local server");
serverRunner->start(getLocalPort(), connectToLobby, si);
uint16_t srvport = serverRunner->start(getLocalPort(), connectToLobby, si);
logNetwork->trace("\tConnecting to local server");
connectToServer(getLocalHostname(), getLocalPort());
connectToServer(getLocalHostname(), srvport);
logNetwork->trace("\tWaiting for connection");
}

View File

@ -20,22 +20,35 @@
#include <boost/process/io.hpp>
#endif
#include <future>
ServerThreadRunner::ServerThreadRunner() = default;
ServerThreadRunner::~ServerThreadRunner() = default;
void ServerThreadRunner::start(uint16_t port, bool connectToLobby, std::shared_ptr<StartInfo> startingInfo)
uint16_t ServerThreadRunner::start(uint16_t cfgport, bool connectToLobby, std::shared_ptr<StartInfo> startingInfo)
{
server = std::make_unique<CVCMIServer>(port, connectToLobby, true);
// cfgport may be 0 -- the real port is returned after calling prepare()
server = std::make_unique<CVCMIServer>(cfgport, true);
if (startingInfo)
{
server->si = startingInfo; //Else use default
}
threadRunLocalServer = boost::thread([this]{
std::promise<uint16_t> promise;
threadRunLocalServer = boost::thread([this, connectToLobby, &promise]{
setThreadName("runServer");
uint16_t port = server->prepare(connectToLobby);
promise.set_value(port);
server->run();
});
logNetwork->trace("Waiting for server port...");
auto srvport = promise.get_future().get();
logNetwork->debug("Server port: %d", srvport);
return srvport;
}
void ServerThreadRunner::shutdown()
@ -73,7 +86,7 @@ int ServerProcessRunner::exitCode()
return child->exit_code();
}
void ServerProcessRunner::start(uint16_t port, bool connectToLobby, std::shared_ptr<StartInfo> startingInfo)
uint16_t ServerProcessRunner::start(uint16_t port, bool connectToLobby, std::shared_ptr<StartInfo> startingInfo)
{
boost::filesystem::path serverPath = VCMIDirs::get().serverPath();
boost::filesystem::path logPath = VCMIDirs::get().userLogsPath() / "server_log.txt";
@ -88,6 +101,8 @@ void ServerProcessRunner::start(uint16_t port, bool connectToLobby, std::shared_
if (ec)
throw std::runtime_error("Failed to start server! Reason: " + ec.message());
return port;
}
#endif

View File

@ -20,7 +20,7 @@ class CVCMIServer;
class IServerRunner
{
public:
virtual void start(uint16_t port, bool connectToLobby, std::shared_ptr<StartInfo> startingInfo) = 0;
virtual uint16_t start(uint16_t port, bool connectToLobby, std::shared_ptr<StartInfo> startingInfo) = 0;
virtual void shutdown() = 0;
virtual void wait() = 0;
virtual int exitCode() = 0;
@ -34,7 +34,7 @@ class ServerThreadRunner : public IServerRunner, boost::noncopyable
std::unique_ptr<CVCMIServer> server;
boost::thread threadRunLocalServer;
public:
void start(uint16_t port, bool connectToLobby, std::shared_ptr<StartInfo> startingInfo) override;
uint16_t start(uint16_t port, bool connectToLobby, std::shared_ptr<StartInfo> startingInfo) override;
void shutdown() override;
void wait() override;
int exitCode() override;
@ -56,7 +56,7 @@ class ServerProcessRunner : public IServerRunner, boost::noncopyable
std::unique_ptr<boost::process::child> child;
public:
void start(uint16_t port, bool connectToLobby, std::shared_ptr<StartInfo> startingInfo) override;
uint16_t start(uint16_t port, bool connectToLobby, std::shared_ptr<StartInfo> startingInfo) override;
void shutdown() override;
void wait() override;
int exitCode() override;

View File

@ -40,7 +40,7 @@ class DLL_LINKAGE INetworkServer : boost::noncopyable
public:
virtual ~INetworkServer() = default;
virtual void start(uint16_t port) = 0;
virtual uint16_t start(uint16_t port) = 0;
};
/// Base interface that must be implemented by user of networking API to handle any connection callbacks

View File

@ -19,16 +19,17 @@ NetworkServer::NetworkServer(INetworkServerListener & listener, const std::share
{
}
void NetworkServer::start(uint16_t port)
uint16_t NetworkServer::start(uint16_t port)
{
acceptor = std::make_shared<NetworkAcceptor>(*io, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port));
startAsyncAccept();
return startAsyncAccept();
}
void NetworkServer::startAsyncAccept()
uint16_t NetworkServer::startAsyncAccept()
{
auto upcomingConnection = std::make_shared<NetworkSocket>(*io);
acceptor->async_accept(*upcomingConnection, [this, upcomingConnection](const auto & ec) { connectionAccepted(upcomingConnection, ec); });
return acceptor->local_endpoint().port();
}
void NetworkServer::connectionAccepted(std::shared_ptr<NetworkSocket> upcomingConnection, const boost::system::error_code & ec)

View File

@ -22,14 +22,14 @@ class NetworkServer : public INetworkConnectionListener, public INetworkServer
INetworkServerListener & listener;
void connectionAccepted(std::shared_ptr<NetworkSocket>, const boost::system::error_code & ec);
void startAsyncAccept();
uint16_t startAsyncAccept();
void onDisconnected(const std::shared_ptr<INetworkConnection> & connection, const std::string & errorMessage) override;
void onPacketReceived(const std::shared_ptr<INetworkConnection> & connection, const std::vector<std::byte> & message) override;
public:
NetworkServer(INetworkServerListener & listener, const std::shared_ptr<NetworkContext> & context);
void start(uint16_t port) override;
uint16_t start(uint16_t port) override;
};
VCMI_LIB_NAMESPACE_END

View File

@ -118,7 +118,7 @@ public:
}
};
CVCMIServer::CVCMIServer(uint16_t port, bool connectToLobby, bool runByClient)
CVCMIServer::CVCMIServer(uint16_t port, bool runByClient)
: currentClientId(1)
, currentPlayerId(1)
, port(port)
@ -130,22 +130,30 @@ CVCMIServer::CVCMIServer(uint16_t port, bool connectToLobby, bool runByClient)
registerTypesLobbyPacks(*applier);
networkHandler = INetworkHandler::createHandler();
if(connectToLobby)
lobbyProcessor = std::make_unique<GlobalLobbyProcessor>(*this);
else
startAcceptingIncomingConnections();
}
CVCMIServer::~CVCMIServer() = default;
void CVCMIServer::startAcceptingIncomingConnections()
{
logNetwork->info("Port %d will be used", port);
uint16_t CVCMIServer::prepare(bool connectToLobby) {
if(connectToLobby) {
lobbyProcessor = std::make_unique<GlobalLobbyProcessor>(*this);
return 0;
} else {
return startAcceptingIncomingConnections();
}
}
uint16_t CVCMIServer::startAcceptingIncomingConnections()
{
port
? logNetwork->info("Port %d will be used", port)
: logNetwork->info("Randomly assigned port will be used");
// config port may be 0 => srvport will contain the OS-assigned port value
networkServer = networkHandler->createServerTCP(*this);
networkServer->start(port);
logNetwork->info("Listening for connections at port %d", port);
auto srvport = networkServer->start(port);
logNetwork->info("Listening for connections at port %d", srvport);
return srvport;
}
void CVCMIServer::onNewConnection(const std::shared_ptr<INetworkConnection> & connection)

View File

@ -66,6 +66,8 @@ public:
/// List of all active connections
std::vector<std::shared_ptr<CConnection>> activeConnections;
uint16_t prepare(bool connectToLobby);
// INetworkListener impl
void onDisconnected(const std::shared_ptr<INetworkConnection> & connection, const std::string & errorMessage) override;
void onPacketReceived(const std::shared_ptr<INetworkConnection> & connection, const std::vector<std::byte> & message) override;
@ -74,7 +76,7 @@ public:
std::shared_ptr<CGameHandler> gh;
CVCMIServer(uint16_t port, bool connectToLobby, bool runByClient);
CVCMIServer(uint16_t port, bool runByClient);
~CVCMIServer();
void run();
@ -83,7 +85,7 @@ public:
bool prepareToStartGame();
void prepareToRestart();
void startGameImmediately();
void startAcceptingIncomingConnections();
uint16_t startAcceptingIncomingConnections();
void threadHandleClient(std::shared_ptr<CConnection> c);

View File

@ -15,6 +15,7 @@
#include "../lib/logging/CBasicLogConfigurator.h"
#include "../lib/VCMIDirs.h"
#include "../lib/VCMI_Lib.h"
#include "../lib/CConfigHandler.h"
#include <boost/program_options.hpp>
@ -86,12 +87,12 @@ int main(int argc, const char * argv[])
{
bool connectToLobby = opts.count("lobby");
bool runByClient = opts.count("runByClient");
uint16_t port = 3030;
uint16_t port = settings["server"]["localPort"].Integer();
if(opts.count("port"))
port = opts["port"].as<uint16_t>();
CVCMIServer server(port, connectToLobby, runByClient);
CVCMIServer server(port, runByClient);
server.prepare(connectToLobby);
server.run();
// CVCMIServer destructor must be called here - before VLC cleanup