1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-07-03 00:46:55 +02:00

Implemented connecting to server via proxy

This commit is contained in:
Ivan Savenko
2024-01-29 22:05:11 +02:00
parent bed05eb52d
commit c5c46a7c9a
15 changed files with 160 additions and 61 deletions

View File

@ -139,6 +139,7 @@ CServerHandler::CServerHandler()
, state(EClientState::NONE) , state(EClientState::NONE)
, campaignStateToSend(nullptr) , campaignStateToSend(nullptr)
, screenType(ESelectionScreen::unknown) , screenType(ESelectionScreen::unknown)
, serverMode(EServerMode::NONE)
, loadMode(ELoadMode::NONE) , loadMode(ELoadMode::NONE)
, client(nullptr) , client(nullptr)
, campaignServerRestartLock(false) , campaignServerRestartLock(false)
@ -156,10 +157,11 @@ void CServerHandler::threadRunNetwork()
logGlobal->info("Ending network thread"); logGlobal->info("Ending network thread");
} }
void CServerHandler::resetStateForLobby(EStartMode mode, ESelectionScreen screen, const std::vector<std::string> & names) void CServerHandler::resetStateForLobby(EStartMode mode, ESelectionScreen screen, EServerMode newServerMode, const std::vector<std::string> & names)
{ {
hostClientId = -1; hostClientId = -1;
state = EClientState::NONE; state = EClientState::NONE;
serverMode = newServerMode;
mapToStart = nullptr; mapToStart = nullptr;
th = std::make_unique<CStopWatch>(); th = std::make_unique<CStopWatch>();
c.reset(); c.reset();
@ -297,11 +299,18 @@ void CServerHandler::onTimer()
networkHandler->connectToRemote(*this, getLocalHostname(), getLocalPort()); networkHandler->connectToRemote(*this, getLocalHostname(), getLocalPort());
} }
void CServerHandler::onConnectionEstablished(const std::shared_ptr<INetworkConnection> & netConnection) void CServerHandler::onConnectionEstablished(const NetworkConnectionPtr & netConnection)
{ {
networkConnection = netConnection; networkConnection = netConnection;
logNetwork->info("Connection established"); logNetwork->info("Connection established");
if (serverMode == EServerMode::LOBBY_GUEST)
{
// say hello to lobby to switch connection to proxy mode
getGlobalLobby().sendProxyConnectionLogin(netConnection);
}
c = std::make_shared<CConnection>(netConnection); c = std::make_shared<CConnection>(netConnection);
nextClient = std::make_unique<CClient>(); nextClient = std::make_unique<CClient>();
c->uuid = uuid; c->uuid = uuid;
@ -791,12 +800,12 @@ void CServerHandler::debugStartTest(std::string filename, bool save)
auto mapInfo = std::make_shared<CMapInfo>(); auto mapInfo = std::make_shared<CMapInfo>();
if(save) if(save)
{ {
resetStateForLobby(EStartMode::LOAD_GAME, ESelectionScreen::loadGame, {}); resetStateForLobby(EStartMode::LOAD_GAME, ESelectionScreen::loadGame, EServerMode::LOCAL, {});
mapInfo->saveInit(ResourcePath(filename, EResType::SAVEGAME)); mapInfo->saveInit(ResourcePath(filename, EResType::SAVEGAME));
} }
else else
{ {
resetStateForLobby(EStartMode::NEW_GAME, ESelectionScreen::newGame, {}); resetStateForLobby(EStartMode::NEW_GAME, ESelectionScreen::newGame, EServerMode::LOCAL, {});
mapInfo->mapInit(filename); mapInfo->mapInit(filename);
} }
if(settings["session"]["donotstartserver"].Bool()) if(settings["session"]["donotstartserver"].Bool())

View File

@ -57,6 +57,14 @@ enum class EClientState : ui8
CONNECTION_FAILED // We could not connect to server CONNECTION_FAILED // We could not connect to server
}; };
enum class EServerMode : uint8_t
{
NONE = 0,
LOCAL, // no global lobby
LOBBY_HOST, // We are hosting global server available via global lobby
LOBBY_GUEST // Connecting to a remote server via proxy provided by global lobby
};
class IServerAPI class IServerAPI
{ {
protected: protected:
@ -106,10 +114,10 @@ class CServerHandler final : public IServerAPI, public LobbyInfo, public INetwor
void onServerFinished(); void onServerFinished();
void sendLobbyPack(const CPackForLobby & pack) const override; void sendLobbyPack(const CPackForLobby & pack) const override;
void onPacketReceived(const std::shared_ptr<INetworkConnection> &, const std::vector<uint8_t> & message) override; void onPacketReceived(const NetworkConnectionPtr &, const std::vector<uint8_t> & message) override;
void onConnectionFailed(const std::string & errorMessage) override; void onConnectionFailed(const std::string & errorMessage) override;
void onConnectionEstablished(const std::shared_ptr<INetworkConnection> &) override; void onConnectionEstablished(const NetworkConnectionPtr &) override;
void onDisconnected(const std::shared_ptr<INetworkConnection> &) override; void onDisconnected(const NetworkConnectionPtr &) override;
void onTimer() override; void onTimer() override;
void applyPackOnLobbyScreen(CPackForLobby & pack); void applyPackOnLobbyScreen(CPackForLobby & pack);
@ -132,6 +140,7 @@ public:
std::shared_ptr<CampaignState> campaignStateToSend; std::shared_ptr<CampaignState> campaignStateToSend;
ESelectionScreen screenType; // To create lobby UI only after server is setup ESelectionScreen screenType; // To create lobby UI only after server is setup
EServerMode serverMode;
ELoadMode loadMode; // For saves filtering in SelectionTab ELoadMode loadMode; // For saves filtering in SelectionTab
//////////////////// ////////////////////
@ -146,7 +155,7 @@ public:
CServerHandler(); CServerHandler();
~CServerHandler(); ~CServerHandler();
void resetStateForLobby(EStartMode mode, ESelectionScreen screen, const std::vector<std::string> & names); void resetStateForLobby(EStartMode mode, ESelectionScreen screen, EServerMode serverMode, const std::vector<std::string> & names);
void startLocalServerAndConnect(bool connectToLobby); void startLocalServerAndConnect(bool connectToLobby);
void connectToServer(const std::string & addr, const ui16 port); void connectToServer(const std::string & addr, const ui16 port);

View File

@ -53,6 +53,7 @@ void ApplyOnLobbyHandlerNetPackVisitor::visitLobbyClientConnected(LobbyClientCon
if (!GH.windows().findWindows<GlobalLobbyServerSetup>().empty()) if (!GH.windows().findWindows<GlobalLobbyServerSetup>().empty())
{ {
assert(handler.serverMode == EServerMode::LOBBY_HOST);
// announce opened game room // announce opened game room
// TODO: find better approach? // TODO: find better approach?
int roomType = settings["lobby"]["roomType"].Integer(); int roomType = settings["lobby"]["roomType"].Integer();

View File

@ -18,6 +18,7 @@
#include "../gui/WindowHandler.h" #include "../gui/WindowHandler.h"
#include "../windows/InfoWindows.h" #include "../windows/InfoWindows.h"
#include "../CServerHandler.h" #include "../CServerHandler.h"
#include "../mainmenu/CMainMenu.h"
#include "../../lib/CConfigHandler.h" #include "../../lib/CConfigHandler.h"
#include "../../lib/MetaString.h" #include "../../lib/MetaString.h"
@ -190,7 +191,18 @@ void GlobalLobbyClient::receiveActiveGameRooms(const JsonNode & json)
void GlobalLobbyClient::receiveJoinRoomSuccess(const JsonNode & json) void GlobalLobbyClient::receiveJoinRoomSuccess(const JsonNode & json)
{ {
// TODO: store "gameRoomID" field and use it for future queries Settings configRoom = settings.write["lobby"]["roomID"];
configRoom->String() = json["gameRoomID"].String();
if (json["proxyMode"].Bool())
{
CSH->resetStateForLobby(EStartMode::NEW_GAME, ESelectionScreen::newGame, EServerMode::LOBBY_GUEST, {});
CSH->loadMode = ELoadMode::MULTI;
std::string hostname = settings["lobby"]["hostname"].String();
int16_t port = settings["lobby"]["port"].Integer();
CSH->connectToServer(hostname, port);
}
} }
void GlobalLobbyClient::onConnectionEstablished(const std::shared_ptr<INetworkConnection> & connection) void GlobalLobbyClient::onConnectionEstablished(const std::shared_ptr<INetworkConnection> & connection)
@ -334,3 +346,22 @@ void GlobalLobbyClient::activateInterface()
else else
GH.windows().pushWindow(createLoginWindow()); GH.windows().pushWindow(createLoginWindow());
} }
void GlobalLobbyClient::sendProxyConnectionLogin(const NetworkConnectionPtr & netConnection)
{
JsonNode toSend;
toSend["type"].String() = "clientProxyLogin";
toSend["accountID"] = settings["lobby"]["accountID"];
toSend["accountCookie"] = settings["lobby"]["accountCookie"];
toSend["gameRoomID"] = settings["lobby"]["roomID"];
std::string payloadString = toSend.toJson(true);
// FIXME: find better approach
uint8_t * payloadBegin = reinterpret_cast<uint8_t *>(payloadString.data());
uint8_t * payloadEnd = payloadBegin + payloadString.size();
std::vector<uint8_t> payloadBuffer(payloadBegin, payloadEnd);
netConnection->sendPacket(payloadBuffer);
}

View File

@ -63,6 +63,8 @@ public:
void sendOpenPublicRoom(); void sendOpenPublicRoom();
void sendOpenPrivateRoom(); void sendOpenPrivateRoom();
void sendProxyConnectionLogin(const NetworkConnectionPtr & netConnection);
void connect(); void connect();
bool isConnected(); bool isConnected();
}; };

View File

@ -125,9 +125,9 @@ void GlobalLobbyServerSetup::onGameModeChanged(int value)
void GlobalLobbyServerSetup::onCreate() void GlobalLobbyServerSetup::onCreate()
{ {
if(toggleGameMode->getSelected() == 0) if(toggleGameMode->getSelected() == 0)
CSH->resetStateForLobby(EStartMode::NEW_GAME, ESelectionScreen::newGame, {}); CSH->resetStateForLobby(EStartMode::NEW_GAME, ESelectionScreen::newGame, EServerMode::LOBBY_HOST, {});
else else
CSH->resetStateForLobby(EStartMode::LOAD_GAME, ESelectionScreen::loadGame, {}); CSH->resetStateForLobby(EStartMode::LOAD_GAME, ESelectionScreen::loadGame, EServerMode::LOBBY_HOST, {});
CSH->loadMode = ELoadMode::MULTI; CSH->loadMode = ELoadMode::MULTI;
CSH->startLocalServerAndConnect(true); CSH->startLocalServerAndConnect(true);

View File

@ -361,7 +361,7 @@ void CMainMenu::update()
void CMainMenu::openLobby(ESelectionScreen screenType, bool host, const std::vector<std::string> & names, ELoadMode loadMode) void CMainMenu::openLobby(ESelectionScreen screenType, bool host, const std::vector<std::string> & names, ELoadMode loadMode)
{ {
CSH->resetStateForLobby(screenType == ESelectionScreen::newGame ? EStartMode::NEW_GAME : EStartMode::LOAD_GAME, screenType, names); CSH->resetStateForLobby(screenType == ESelectionScreen::newGame ? EStartMode::NEW_GAME : EStartMode::LOAD_GAME, screenType, EServerMode::LOCAL, names);
CSH->loadMode = loadMode; CSH->loadMode = loadMode;
GH.windows().createAndPushWindow<CSimpleJoinScreen>(host); GH.windows().createAndPushWindow<CSimpleJoinScreen>(host);
@ -376,7 +376,7 @@ void CMainMenu::openCampaignLobby(const std::string & campaignFileName, std::str
void CMainMenu::openCampaignLobby(std::shared_ptr<CampaignState> campaign) void CMainMenu::openCampaignLobby(std::shared_ptr<CampaignState> campaign)
{ {
CSH->resetStateForLobby(EStartMode::CAMPAIGN, ESelectionScreen::campaignList, {}); CSH->resetStateForLobby(EStartMode::CAMPAIGN, ESelectionScreen::campaignList, EServerMode::LOCAL, {});
CSH->campaignStateToSend = campaign; CSH->campaignStateToSend = campaign;
GH.windows().createAndPushWindow<CSimpleJoinScreen>(); GH.windows().createAndPushWindow<CSimpleJoinScreen>();
} }

View File

@ -553,28 +553,24 @@
"type" : "object", "type" : "object",
"additionalProperties" : false, "additionalProperties" : false,
"default" : {}, "default" : {},
"required" : [ "mapPreview", "accountID", "accountCookie", "displayName", "hostname", "port", "roomPlayerLimit", "roomType", "roomMode" ], "required" : [ "mapPreview", "accountID", "accountCookie", "displayName", "hostname", "port", "roomPlayerLimit", "roomType", "roomMode", "roomID" ],
"properties" : { "properties" : {
"mapPreview" : { "mapPreview" : {
"type" : "boolean", "type" : "boolean",
"default" : true "default" : true
}, },
"accountID" : { "accountID" : {
"type" : "string", "type" : "string",
"default" : "" "default" : ""
}, },
"accountCookie" : { "accountCookie" : {
"type" : "string", "type" : "string",
"default" : "" "default" : ""
}, },
"displayName" : { "displayName" : {
"type" : "string", "type" : "string",
"default" : "" "default" : ""
}, },
"hostname" : { "hostname" : {
"type" : "string", "type" : "string",
"default" : "127.0.0.1" "default" : "127.0.0.1"
@ -583,21 +579,22 @@
"type" : "number", "type" : "number",
"default" : 30303 "default" : 30303
}, },
"roomPlayerLimit" : { "roomPlayerLimit" : {
"type" : "number", "type" : "number",
"default" : 2 "default" : 2
}, },
"roomType" : { "roomType" : {
"type" : "number", "type" : "number",
"default" : 0 "default" : 0
}, },
"roomMode" : { "roomMode" : {
"type" : "number", "type" : "number",
"default" : 0 "default" : 0
}, },
"roomID" : {
"type" : "string",
"default" : ""
}
} }
}, },
"gameTweaks" : { "gameTweaks" : {

View File

@ -53,15 +53,20 @@ void NetworkServer::sendPacket(const std::shared_ptr<INetworkConnection> & conne
void NetworkServer::closeConnection(const std::shared_ptr<INetworkConnection> & connection) void NetworkServer::closeConnection(const std::shared_ptr<INetworkConnection> & connection)
{ {
logNetwork->info("Closing connection!");
assert(connections.count(connection)); assert(connections.count(connection));
connections.erase(connection); connections.erase(connection);
} }
void NetworkServer::onDisconnected(const std::shared_ptr<INetworkConnection> & connection) void NetworkServer::onDisconnected(const std::shared_ptr<INetworkConnection> & connection)
{ {
logNetwork->info("Connection lost!");
assert(connections.count(connection)); assert(connections.count(connection));
if (connections.count(connection)) // how? Connection was explicitly closed before?
{
connections.erase(connection); connections.erase(connection);
listener.onDisconnected(connection); listener.onDisconnected(connection);
}
} }
void NetworkServer::onPacketReceived(const std::shared_ptr<INetworkConnection> & connection, const std::vector<uint8_t> & message) void NetworkServer::onPacketReceived(const std::shared_ptr<INetworkConnection> & connection, const std::vector<uint8_t> & message)

View File

@ -155,6 +155,12 @@ void LobbyDatabase::prepareStatements()
LIMIT 1 LIMIT 1
)"; )";
static const std::string getGameRoomStatusText = R"(
SELECT status
FROM gameRooms
WHERE roomID = ?
)";
static const std::string getAccountGameRoomText = R"( static const std::string getAccountGameRoomText = R"(
SELECT grp.roomID SELECT grp.roomID
FROM gameRoomPlayers grp FROM gameRoomPlayers grp
@ -209,14 +215,16 @@ void LobbyDatabase::prepareStatements()
static const std::string isPlayerInGameRoomText = R"( static const std::string isPlayerInGameRoomText = R"(
SELECT COUNT(accountID) SELECT COUNT(accountID)
FROM gameRoomPlayers FROM gameRoomPlayers grp
WHERE accountID = ? AND roomID = ? LEFT JOIN gameRooms gr ON gr.roomID = grp.roomID
WHERE accountID = ? AND grp.roomID = ? AND status IN (1, 2)
)"; )";
static const std::string isPlayerInAnyGameRoomText = R"( static const std::string isPlayerInAnyGameRoomText = R"(
SELECT COUNT(accountID) SELECT COUNT(accountID)
FROM gameRoomPlayers FROM gameRoomPlayers grp
WHERE accountID = ? LEFT JOIN gameRooms gr ON gr.roomID = grp.roomID
WHERE accountID = ? AND status IN (1, 2)
)"; )";
static const std::string isAccountIDExistsText = R"( static const std::string isAccountIDExistsText = R"(
@ -247,6 +255,7 @@ void LobbyDatabase::prepareStatements()
getRecentMessageHistoryStatement = database->prepare(getRecentMessageHistoryText); getRecentMessageHistoryStatement = database->prepare(getRecentMessageHistoryText);
getIdleGameRoomStatement = database->prepare(getIdleGameRoomText); getIdleGameRoomStatement = database->prepare(getIdleGameRoomText);
getGameRoomStatusStatement = database->prepare(getGameRoomStatusText);
getAccountGameRoomStatement = database->prepare(getAccountGameRoomText); getAccountGameRoomStatement = database->prepare(getAccountGameRoomText);
getActiveAccountsStatement = database->prepare(getActiveAccountsText); getActiveAccountsStatement = database->prepare(getActiveAccountsText);
getActiveGameRoomsStatement = database->prepare(getActiveGameRoomsText); getActiveGameRoomsStatement = database->prepare(getActiveGameRoomsText);
@ -406,7 +415,16 @@ LobbyInviteStatus LobbyDatabase::getAccountInviteStatus(const std::string & acco
LobbyRoomState LobbyDatabase::getGameRoomStatus(const std::string & roomID) LobbyRoomState LobbyDatabase::getGameRoomStatus(const std::string & roomID)
{ {
return {}; int result = -1;
getGameRoomStatusStatement->setBinds(roomID);
if(getGameRoomStatusStatement->execute())
getGameRoomStatusStatement->getColumns(result);
getGameRoomStatusStatement->reset();
if (result != -1)
return static_cast<LobbyRoomState>(result);
return LobbyRoomState::CLOSED;
} }
uint32_t LobbyDatabase::getGameRoomFreeSlots(const std::string & roomID) uint32_t LobbyDatabase::getGameRoomFreeSlots(const std::string & roomID)

View File

@ -37,6 +37,7 @@ class LobbyDatabase
SQLiteStatementPtr getRecentMessageHistoryStatement; SQLiteStatementPtr getRecentMessageHistoryStatement;
SQLiteStatementPtr getIdleGameRoomStatement; SQLiteStatementPtr getIdleGameRoomStatement;
SQLiteStatementPtr getGameRoomStatusStatement;
SQLiteStatementPtr getActiveGameRoomsStatement; SQLiteStatementPtr getActiveGameRoomsStatement;
SQLiteStatementPtr getActiveAccountsStatement; SQLiteStatementPtr getActiveAccountsStatement;
SQLiteStatementPtr getAccountGameRoomStatement; SQLiteStatementPtr getAccountGameRoomStatement;

View File

@ -148,7 +148,7 @@ void LobbyServer::broadcastActiveAccounts()
sendMessage(connection.first, reply); sendMessage(connection.first, reply);
} }
void LobbyServer::broadcastActiveGameRooms() JsonNode LobbyServer::prepareActiveGameRooms()
{ {
auto activeGameRoomStats = database->getActiveGameRooms(); auto activeGameRoomStats = database->getActiveGameRooms();
JsonNode reply; JsonNode reply;
@ -167,6 +167,13 @@ void LobbyServer::broadcastActiveGameRooms()
reply["gameRooms"].Vector().push_back(jsonEntry); reply["gameRooms"].Vector().push_back(jsonEntry);
} }
return reply;
}
void LobbyServer::broadcastActiveGameRooms()
{
auto reply = prepareActiveGameRooms();
for(const auto & connection : activeAccounts) for(const auto & connection : activeAccounts)
sendMessage(connection.first, reply); sendMessage(connection.first, reply);
} }
@ -179,11 +186,12 @@ void LobbyServer::sendAccountJoinsRoom(const NetworkConnectionPtr & target, cons
sendMessage(target, reply); sendMessage(target, reply);
} }
void LobbyServer::sendJoinRoomSuccess(const NetworkConnectionPtr & target, const std::string & gameRoomID) void LobbyServer::sendJoinRoomSuccess(const NetworkConnectionPtr & target, const std::string & gameRoomID, bool proxyMode)
{ {
JsonNode reply; JsonNode reply;
reply["type"].String() = "joinRoomSuccess"; reply["type"].String() = "joinRoomSuccess";
reply["gameRoomID"].String() = gameRoomID; reply["gameRoomID"].String() = gameRoomID;
reply["proxyMode"].Bool() = proxyMode;
sendMessage(target, reply); sendMessage(target, reply);
} }
@ -230,8 +238,9 @@ void LobbyServer::onPacketReceived(const NetworkConnectionPtr & connection, cons
{ {
auto lockedPtr = activeProxies.at(connection).lock(); auto lockedPtr = activeProxies.at(connection).lock();
if(lockedPtr) if(lockedPtr)
lockedPtr->sendPacket(message); return lockedPtr->sendPacket(message);
return;
throw std::runtime_error("Received unexpected message for inactive proxy!");
} }
JsonNode json(message.data(), message.size()); JsonNode json(message.data(), message.size());
@ -257,7 +266,7 @@ void LobbyServer::onPacketReceived(const NetworkConnectionPtr & connection, cons
if(json["type"].String() == "declineInvite") if(json["type"].String() == "declineInvite")
return receiveDeclineInvite(connection, json); return receiveDeclineInvite(connection, json);
return; throw std::runtime_error("Received unexpected message of type " + json["type"].String());
} }
// communication messages from vcmiserver // communication messages from vcmiserver
@ -266,7 +275,7 @@ void LobbyServer::onPacketReceived(const NetworkConnectionPtr & connection, cons
if(json["type"].String() == "leaveGameRoom") if(json["type"].String() == "leaveGameRoom")
return receiveLeaveGameRoom(connection, json); return receiveLeaveGameRoom(connection, json);
return; throw std::runtime_error("Received unexpected message of type " + json["type"].String());
} }
// unauthorized connections - permit only login or register attempts // unauthorized connections - permit only login or register attempts
@ -287,6 +296,8 @@ void LobbyServer::onPacketReceived(const NetworkConnectionPtr & connection, cons
// TODO: add logging of suspicious connections. // TODO: add logging of suspicious connections.
networkServer->closeConnection(connection); networkServer->closeConnection(connection);
throw std::runtime_error("Received unexpected message of type " + json["type"].String());
} }
void LobbyServer::receiveSendChatMessage(const NetworkConnectionPtr & connection, const JsonNode & json) void LobbyServer::receiveSendChatMessage(const NetworkConnectionPtr & connection, const JsonNode & json)
@ -358,6 +369,7 @@ void LobbyServer::receiveClientLogin(const NetworkConnectionPtr & connection, co
// send active accounts list to new account // send active accounts list to new account
// and update acount list to everybody else // and update acount list to everybody else
broadcastActiveAccounts(); broadcastActiveAccounts();
sendMessage(connection, prepareActiveGameRooms());
} }
void LobbyServer::receiveServerLogin(const NetworkConnectionPtr & connection, const JsonNode & json) void LobbyServer::receiveServerLogin(const NetworkConnectionPtr & connection, const JsonNode & json)
@ -420,18 +432,19 @@ void LobbyServer::receiveServerProxyLogin(const NetworkConnectionPtr & connectio
{ {
std::string gameRoomID = json["gameRoomID"].String(); std::string gameRoomID = json["gameRoomID"].String();
std::string guestAccountID = json["guestAccountID"].String(); std::string guestAccountID = json["guestAccountID"].String();
std::string hostCookie = json["hostCookie"].String(); std::string accountCookie = json["accountCookie"].String();
auto clientCookieStatus = database->getGameRoomCookieStatus(gameRoomID, hostCookie, accountCookieLifetime); // FIXME: find host account ID and validate his cookie
//auto clientCookieStatus = database->getAccountCookieStatus(hostAccountID, accountCookie, accountCookieLifetime);
if(clientCookieStatus != LobbyCookieStatus::INVALID) //if(clientCookieStatus != LobbyCookieStatus::INVALID)
{ {
NetworkConnectionPtr targetAccount = findAccount(guestAccountID); NetworkConnectionPtr targetAccount = findAccount(guestAccountID);
if(targetAccount == nullptr) if(targetAccount == nullptr)
return; // unknown / disconnected account return; // unknown / disconnected account
sendJoinRoomSuccess(targetAccount, gameRoomID); sendJoinRoomSuccess(targetAccount, gameRoomID, true);
AwaitingProxyState proxy; AwaitingProxyState proxy;
proxy.accountID = guestAccountID; proxy.accountID = guestAccountID;
@ -441,7 +454,7 @@ void LobbyServer::receiveServerProxyLogin(const NetworkConnectionPtr & connectio
return; return;
} }
networkServer->closeConnection(connection); //networkServer->closeConnection(connection);
} }
void LobbyServer::receiveOpenGameRoom(const NetworkConnectionPtr & connection, const JsonNode & json) void LobbyServer::receiveOpenGameRoom(const NetworkConnectionPtr & connection, const JsonNode & json)
@ -467,7 +480,7 @@ void LobbyServer::receiveOpenGameRoom(const NetworkConnectionPtr & connection, c
database->insertPlayerIntoGameRoom(accountID, gameRoomID); database->insertPlayerIntoGameRoom(accountID, gameRoomID);
broadcastActiveGameRooms(); broadcastActiveGameRooms();
sendJoinRoomSuccess(connection, gameRoomID); sendJoinRoomSuccess(connection, gameRoomID, false);
} }
void LobbyServer::receiveJoinGameRoom(const NetworkConnectionPtr & connection, const JsonNode & json) void LobbyServer::receiveJoinGameRoom(const NetworkConnectionPtr & connection, const JsonNode & json)

View File

@ -70,13 +70,15 @@ class LobbyServer : public INetworkServerListener
void broadcastActiveAccounts(); void broadcastActiveAccounts();
void broadcastActiveGameRooms(); void broadcastActiveGameRooms();
JsonNode prepareActiveGameRooms();
void sendChatMessage(const NetworkConnectionPtr & target, const std::string & roomMode, const std::string & roomName, const std::string & accountID, const std::string & displayName, const std::string & messageText); void sendChatMessage(const NetworkConnectionPtr & target, const std::string & roomMode, const std::string & roomName, const std::string & accountID, const std::string & displayName, const std::string & messageText);
void sendAccountCreated(const NetworkConnectionPtr & target, const std::string & accountID, const std::string & accountCookie); void sendAccountCreated(const NetworkConnectionPtr & target, const std::string & accountID, const std::string & accountCookie);
void sendLoginFailed(const NetworkConnectionPtr & target, const std::string & reason); void sendLoginFailed(const NetworkConnectionPtr & target, const std::string & reason);
void sendLoginSuccess(const NetworkConnectionPtr & target, const std::string & accountCookie, const std::string & displayName); void sendLoginSuccess(const NetworkConnectionPtr & target, const std::string & accountCookie, const std::string & displayName);
void sendChatHistory(const NetworkConnectionPtr & target, const std::vector<LobbyChatMessage> &); void sendChatHistory(const NetworkConnectionPtr & target, const std::vector<LobbyChatMessage> &);
void sendAccountJoinsRoom(const NetworkConnectionPtr & target, const std::string & accountID); void sendAccountJoinsRoom(const NetworkConnectionPtr & target, const std::string & accountID);
void sendJoinRoomSuccess(const NetworkConnectionPtr & target, const std::string & gameRoomID); void sendJoinRoomSuccess(const NetworkConnectionPtr & target, const std::string & gameRoomID, bool proxyMode);
void sendInviteReceived(const NetworkConnectionPtr & target, const std::string & accountID, const std::string & gameRoomID); void sendInviteReceived(const NetworkConnectionPtr & target, const std::string & accountID, const std::string & gameRoomID);
void receiveClientRegister(const NetworkConnectionPtr & connection, const JsonNode & json); void receiveClientRegister(const NetworkConnectionPtr & connection, const JsonNode & json);

View File

@ -34,6 +34,8 @@ void GlobalLobbyProcessor::onDisconnected(const std::shared_ptr<INetworkConnecti
void GlobalLobbyProcessor::onPacketReceived(const std::shared_ptr<INetworkConnection> & connection, const std::vector<uint8_t> & message) void GlobalLobbyProcessor::onPacketReceived(const std::shared_ptr<INetworkConnection> & connection, const std::vector<uint8_t> & message)
{ {
if (connection == controlConnection)
{
JsonNode json(message.data(), message.size()); JsonNode json(message.data(), message.size());
if(json["type"].String() == "loginFailed") if(json["type"].String() == "loginFailed")
@ -46,17 +48,25 @@ void GlobalLobbyProcessor::onPacketReceived(const std::shared_ptr<INetworkConnec
return receiveAccountJoinsRoom(json); return receiveAccountJoinsRoom(json);
throw std::runtime_error("Received unexpected message from lobby server: " + json["type"].String()); throw std::runtime_error("Received unexpected message from lobby server: " + json["type"].String());
}
else
{
// received game message via proxy connection
owner.onPacketReceived(connection, message);
}
} }
void GlobalLobbyProcessor::receiveLoginFailed(const JsonNode & json) void GlobalLobbyProcessor::receiveLoginFailed(const JsonNode & json)
{ {
logGlobal->info("Lobby: Failed to login into a lobby server!");
throw std::runtime_error("Failed to login into a lobby server!"); throw std::runtime_error("Failed to login into a lobby server!");
} }
void GlobalLobbyProcessor::receiveLoginSuccess(const JsonNode & json) void GlobalLobbyProcessor::receiveLoginSuccess(const JsonNode & json)
{ {
// no-op, wait just for any new commands from lobby // no-op, wait just for any new commands from lobby
logGlobal->info("Succesfully connected to lobby server"); logGlobal->info("Lobby: Succesfully connected to lobby server");
owner.startAcceptingIncomingConnections(); owner.startAcceptingIncomingConnections();
} }
@ -64,6 +74,7 @@ void GlobalLobbyProcessor::receiveAccountJoinsRoom(const JsonNode & json)
{ {
std::string accountID = json["accountID"].String(); std::string accountID = json["accountID"].String();
logGlobal->info("Lobby: Account %s will join our room!", accountID);
assert(proxyConnections.count(accountID) == 0); assert(proxyConnections.count(accountID) == 0);
proxyConnections[accountID] = nullptr; proxyConnections[accountID] = nullptr;
@ -87,29 +98,29 @@ void GlobalLobbyProcessor::onConnectionEstablished(const std::shared_ptr<INetwor
toSend["gameRoomID"].String() = owner.uuid; toSend["gameRoomID"].String() = owner.uuid;
toSend["accountID"] = settings["lobby"]["accountID"]; toSend["accountID"] = settings["lobby"]["accountID"];
toSend["accountCookie"] = settings["lobby"]["accountCookie"]; toSend["accountCookie"] = settings["lobby"]["accountCookie"];
sendMessage(toSend); sendMessage(connection, toSend);
} }
else else
{ {
// Proxy connection for a player // Proxy connection for a player
std::string accountID; std::string guestAccountID;
for (auto const & proxies : proxyConnections) for (auto const & proxies : proxyConnections)
if (proxies.second == nullptr) if (proxies.second == nullptr)
accountID = proxies.first; guestAccountID = proxies.first;
JsonNode toSend; JsonNode toSend;
toSend["type"].String() = "serverProxyLogin"; toSend["type"].String() = "serverProxyLogin";
toSend["gameRoomID"].String() = owner.uuid; toSend["gameRoomID"].String() = owner.uuid;
toSend["accountID"].String() = accountID; toSend["guestAccountID"].String() = guestAccountID;
toSend["accountCookie"] = settings["lobby"]["accountCookie"]; toSend["accountCookie"] = settings["lobby"]["accountCookie"];
sendMessage(toSend); sendMessage(connection, toSend);
proxyConnections[accountID] = connection; proxyConnections[guestAccountID] = connection;
owner.onNewConnection(connection); owner.onNewConnection(connection);
} }
} }
void GlobalLobbyProcessor::sendMessage(const JsonNode & data) void GlobalLobbyProcessor::sendMessage(const NetworkConnectionPtr & target, const JsonNode & data)
{ {
std::string payloadString = data.toJson(true); std::string payloadString = data.toJson(true);
@ -119,5 +130,5 @@ void GlobalLobbyProcessor::sendMessage(const JsonNode & data)
std::vector<uint8_t> payloadBuffer(payloadBegin, payloadEnd); std::vector<uint8_t> payloadBuffer(payloadBegin, payloadEnd);
controlConnection->sendPacket(payloadBuffer); target->sendPacket(payloadBuffer);
} }

View File

@ -21,15 +21,15 @@ class GlobalLobbyProcessor : public INetworkClientListener
{ {
CVCMIServer & owner; CVCMIServer & owner;
std::shared_ptr<INetworkConnection> controlConnection; NetworkConnectionPtr controlConnection;
std::map<std::string, std::shared_ptr<INetworkConnection>> proxyConnections; std::map<std::string, NetworkConnectionPtr> proxyConnections;
void onDisconnected(const std::shared_ptr<INetworkConnection> & connection) override; void onDisconnected(const std::shared_ptr<INetworkConnection> & connection) override;
void onPacketReceived(const std::shared_ptr<INetworkConnection> & connection, const std::vector<uint8_t> & message) override; void onPacketReceived(const std::shared_ptr<INetworkConnection> & connection, const std::vector<uint8_t> & message) override;
void onConnectionFailed(const std::string & errorMessage) override; void onConnectionFailed(const std::string & errorMessage) override;
void onConnectionEstablished(const std::shared_ptr<INetworkConnection> &) override; void onConnectionEstablished(const std::shared_ptr<INetworkConnection> &) override;
void sendMessage(const JsonNode & data); void sendMessage(const NetworkConnectionPtr & target, const JsonNode & data);
void receiveLoginFailed(const JsonNode & json); void receiveLoginFailed(const JsonNode & json);
void receiveLoginSuccess(const JsonNode & json); void receiveLoginSuccess(const JsonNode & json);