mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Bind server to a randomly assigned port
This commit is contained in:
		| @@ -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"); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -23,19 +23,30 @@ | ||||
| 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 port, bool connectToLobby, std::shared_ptr<StartInfo> startingInfo) | ||||
| { | ||||
| 	server = std::make_unique<CVCMIServer>(port, connectToLobby, true); | ||||
| 	server = std::make_unique<CVCMIServer>(port, true); | ||||
|  | ||||
| 	if (startingInfo) | ||||
| 	{ | ||||
| 		server->si = startingInfo; //Else use default | ||||
| 	} | ||||
|  | ||||
| 	threadRunLocalServer = boost::thread([this]{ | ||||
| 	uint16_t srvport = port; | ||||
|  | ||||
| 	threadRunLocalServer = boost::thread([this, connectToLobby, &srvport]{ | ||||
| 		setThreadName("runServer"); | ||||
| 		srvport = server->prepare(connectToLobby); | ||||
| 		server->run(); | ||||
| 	}); | ||||
|  | ||||
| 	while(srvport == 0) { | ||||
| 		logNetwork->trace("Waiting for server port..."); | ||||
| 		boost::this_thread::sleep(boost::posix_time::milliseconds(100)); | ||||
| 		logNetwork->debug("Server port: %d", srvport); | ||||
| 	} | ||||
|  | ||||
| 	return srvport; | ||||
| } | ||||
|  | ||||
| void ServerThreadRunner::shutdown() | ||||
| @@ -73,7 +84,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 +99,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 | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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(); | ||||
| 	acceptor = std::make_shared<NetworkAcceptor>(*io, boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string("127.0.0.1"), port)); | ||||
| 	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) | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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); | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user