Index: binaries/data/mods/public/gui/gamesetup/NetMessages/GameRegisterStanza.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/NetMessages/GameRegisterStanza.js +++ binaries/data/mods/public/gui/gamesetup/NetMessages/GameRegisterStanza.js @@ -83,6 +83,7 @@ let stanza = { "name": this.serverName, "hostUsername": Engine.LobbyGetNick(), + "hostJID": Engine.LobbyGetJID(), "mapName": g_GameAttributes.map, "niceMapName": this.mapCache.getTranslatableMapName(g_GameAttributes.mapType, g_GameAttributes.map), "mapSize": g_GameAttributes.mapType == "random" ? g_GameAttributes.settings.Size : "Default", Index: binaries/data/mods/public/gui/gamesetup_mp/gamesetup_mp.js =================================================================== --- binaries/data/mods/public/gui/gamesetup_mp/gamesetup_mp.js +++ binaries/data/mods/public/gui/gamesetup_mp/gamesetup_mp.js @@ -378,7 +378,7 @@ try { - Engine.StartNetworkHost(playername + (g_UserRating ? " (" + g_UserRating + ")" : ""), port, playername, useSTUN, password); + Engine.StartNetworkHost(playername + (g_UserRating ? " (" + g_UserRating + ")" : ""), port, useSTUN, password); } catch (e) { Index: binaries/data/mods/public/gui/lobby/LobbyPage/Buttons/JoinButton.js =================================================================== --- binaries/data/mods/public/gui/lobby/LobbyPage/Buttons/JoinButton.js +++ binaries/data/mods/public/gui/lobby/LobbyPage/Buttons/JoinButton.js @@ -73,7 +73,7 @@ "name": g_Nickname, "rating": this.getRejoinRating(stanza), "hasPassword": !!stanza.hasPassword, - "hostJID": stanza.hostUsername + "@" + Engine.ConfigDB_GetValue("user", "lobby.server") + "/0ad" + "hostJID": stanza.hostJID }); } Index: binaries/data/mods/public/gui/lobby/LobbyPage/Game.js =================================================================== --- binaries/data/mods/public/gui/lobby/LobbyPage/Game.js +++ binaries/data/mods/public/gui/lobby/LobbyPage/Game.js @@ -282,6 +282,7 @@ "name", "hasPassword", "hostUsername", + "hostJID", "state", "nbp", "maxnbp", Index: source/lobby/IXmppClient.h =================================================================== --- source/lobby/IXmppClient.h +++ source/lobby/IXmppClient.h @@ -45,6 +45,7 @@ virtual void SendIqLobbyAuth(const std::string& to, const std::string& token) = 0; virtual void SetNick(const std::string& nick) = 0; virtual void GetNick(std::string& nick) = 0; + virtual std::string GetJID() const = 0; virtual void kick(const std::string& nick, const std::string& reason) = 0; virtual void ban(const std::string& nick, const std::string& reason) = 0; virtual void SetPresence(const std::string& presence) = 0; Index: source/lobby/XmppClient.h =================================================================== --- source/lobby/XmppClient.h +++ source/lobby/XmppClient.h @@ -92,6 +92,7 @@ void SendIqLobbyAuth(const std::string& to, const std::string& token); void SetNick(const std::string& nick); void GetNick(std::string& nick); + std::string GetJID() const; void kick(const std::string& nick, const std::string& reason); void ban(const std::string& nick, const std::string& reason); void SetPresence(const std::string& presence); Index: source/lobby/XmppClient.cpp =================================================================== --- source/lobby/XmppClient.cpp +++ source/lobby/XmppClient.cpp @@ -32,6 +32,7 @@ #include "network/StunClient.h" #include "ps/CLogger.h" #include "ps/ConfigDB.h" +#include "ps/GUID.h" #include "ps/Pyrogenesis.h" #include "scriptinterface/ScriptExtraHeaders.h" // StructuredClone #include "scriptinterface/ScriptInterface.h" @@ -111,7 +112,8 @@ m_xpartamuppId = sXpartamupp + "@" + m_server + "/CC"; m_echelonId = sEchelon + "@" + m_server + "/CC"; - glooxwrapper::JID clientJid(sUsername + "@" + m_server + "/0ad"); + // Generate a unique, unpredictable resource to allow multiple 0 A.D. instances to connect to the lobby. + glooxwrapper::JID clientJid(sUsername + "@" + m_server + "/0ad-" + ps_generate_guid()); glooxwrapper::JID roomJid(m_room + "@conference." + m_server + "/" + sNick); // If we are connecting, use the full jid and a password @@ -506,7 +508,7 @@ LobbyAuth* auth = new LobbyAuth(); auth->m_Token = token; - glooxwrapper::JID clientJid(to + "@" + m_server + "/0ad"); + glooxwrapper::JID clientJid(to); glooxwrapper::IQ iq(gloox::IQ::Set, clientJid, m_client->getID()); iq.addExtension(auth); DbgXMPP("SendIqLobbyAuth [" << tag_xml(iq) << "]"); @@ -594,7 +596,7 @@ ScriptInterface::CreateArray(rq, ret); int j = 0; - const char* stats[] = { "name", "hostUsername", "state", "hasPassword", + const char* stats[] = { "name", "hostUsername", "hostJID", "state", "hasPassword", "nbp", "maxnbp", "players", "mapName", "niceMapName", "mapSize", "mapType", "victoryConditions", "startTime", "mods" }; @@ -1165,6 +1167,11 @@ nick = m_mucRoom->nick().to_string(); } +std::string XmppClient::GetJID() const +{ + return m_client->getJID().to_string(); +} + /** * Kick a player from the current room. * Index: source/lobby/glooxwrapper/glooxwrapper.h =================================================================== --- source/lobby/glooxwrapper/glooxwrapper.h +++ source/lobby/glooxwrapper/glooxwrapper.h @@ -408,6 +408,7 @@ bool connect(bool block = true); gloox::ConnectionError recv(int timeout = -1); const string getID() const; + const string getJID() const; void send(const IQ& iq); void setTls(gloox::TLSPolicy tls); Index: source/lobby/glooxwrapper/glooxwrapper.cpp =================================================================== --- source/lobby/glooxwrapper/glooxwrapper.cpp +++ source/lobby/glooxwrapper/glooxwrapper.cpp @@ -354,6 +354,11 @@ return m_Wrapped->getID(); } +const glooxwrapper::string glooxwrapper::Client::getJID() const +{ + return m_Wrapped->jid().full(); +} + void glooxwrapper::Client::send(const IQ& iq) { m_Wrapped->send(iq.getWrapped()); Index: source/lobby/scripting/JSInterface_Lobby.h =================================================================== --- source/lobby/scripting/JSInterface_Lobby.h +++ source/lobby/scripting/JSInterface_Lobby.h @@ -55,6 +55,7 @@ void LobbySetPlayerPresence(ScriptInterface::CmptPrivate* pCmptPrivate, const std::wstring& presence); void LobbySetNick(ScriptInterface::CmptPrivate* pCmptPrivate, const std::wstring& nick); std::wstring LobbyGetNick(ScriptInterface::CmptPrivate* pCmptPrivate); + std::string LobbyGetJID(ScriptInterface::CmptPrivate* pCmptPrivate); void LobbyKick(ScriptInterface::CmptPrivate* pCmptPrivate, const std::wstring& nick, const std::wstring& reason); void LobbyBan(ScriptInterface::CmptPrivate* pCmptPrivate, const std::wstring& nick, const std::wstring& reason); const char* LobbyGetPlayerPresence(ScriptInterface::CmptPrivate* pCmptPrivate, const std::wstring& nickname); Index: source/lobby/scripting/JSInterface_Lobby.cpp =================================================================== --- source/lobby/scripting/JSInterface_Lobby.cpp +++ source/lobby/scripting/JSInterface_Lobby.cpp @@ -61,6 +61,7 @@ scriptInterface.RegisterFunction("LobbySetPlayerPresence"); scriptInterface.RegisterFunction("LobbySetNick"); scriptInterface.RegisterFunction("LobbyGetNick"); + scriptInterface.RegisterFunction("LobbyGetJID"); scriptInterface.RegisterFunction("LobbyKick"); scriptInterface.RegisterFunction("LobbyBan"); scriptInterface.RegisterFunction("LobbyGetPlayerPresence"); @@ -398,6 +399,18 @@ return wstring_from_utf8(nick); } +std::string JSI_Lobby::LobbyGetJID(ScriptInterface::CmptPrivate* pCmptPrivate) +{ + if (!g_XmppClient) + { + ScriptRequest rq(pCmptPrivate->pScriptInterface); + ScriptException::Raise(rq, "Cannot call LobbyGetJID without an initialized XmppClient!"); + return std::string(); + } + + return g_XmppClient->GetJID(); +} + void JSI_Lobby::LobbyKick(ScriptInterface::CmptPrivate* pCmptPrivate, const std::wstring& nick, const std::wstring& reason) { if (!g_XmppClient) Index: source/network/NetClient.h =================================================================== --- source/network/NetClient.h +++ source/network/NetClient.h @@ -94,10 +94,10 @@ void SetUserName(const CStrW& username); /** - * Set the name of the hosting player. + * Store the JID of the host. * This is needed for the secure lobby authentication. */ - void SetHostingPlayerName(const CStr& hostingPlayerName); + void SetHostJID(const CStr& jid); /** * Set the game password. @@ -293,7 +293,8 @@ CGame *m_Game; CStrW m_UserName; - CStr m_HostingPlayerName; + + CStr m_HostJID; CStr m_ServerAddress; u16 m_ServerPort; bool m_UseSTUN; Index: source/network/NetClient.cpp =================================================================== --- source/network/NetClient.cpp +++ source/network/NetClient.cpp @@ -170,9 +170,9 @@ m_UserName = username; } -void CNetClient::SetHostingPlayerName(const CStr& hostingPlayerName) +void CNetClient::SetHostJID(const CStr& jid) { - m_HostingPlayerName = hostingPlayerName; + m_HostJID = jid; } void CNetClient::SetGamePassword(const CStr& hashedPassword) @@ -619,8 +619,8 @@ if (message->m_Flags & PS_NETWORK_FLAG_REQUIRE_LOBBYAUTH) { - if (g_XmppClient && !client->m_HostingPlayerName.empty()) - g_XmppClient->SendIqLobbyAuth(client->m_HostingPlayerName, client->m_GUID); + if (g_XmppClient && !client->m_HostJID.empty()) + g_XmppClient->SendIqLobbyAuth(client->m_HostJID, client->m_GUID); else { client->PushGuiMessage( Index: source/network/scripting/JSInterface_Network.h =================================================================== --- source/network/scripting/JSInterface_Network.h +++ source/network/scripting/JSInterface_Network.h @@ -29,7 +29,7 @@ bool HasNetClient(ScriptInterface::CmptPrivate* pCmptPrivate); void StartNetworkGame(ScriptInterface::CmptPrivate* pCmptPrivate); void SetNetworkGameAttributes(ScriptInterface::CmptPrivate* pCmptPrivate, JS::HandleValue attribs1); - void StartNetworkHost(ScriptInterface::CmptPrivate* pCmptPrivate, const CStrW& playerName, const u16 serverPort, const CStr& hostLobbyName, bool useSTUN, const CStr& password); + void StartNetworkHost(ScriptInterface::CmptPrivate* pCmptPrivate, const CStrW& playerName, const u16 serverPort, bool useSTUN, const CStr& password); void StartNetworkJoin(ScriptInterface::CmptPrivate* pCmptPrivate, const CStrW& playerName, const CStr& serverAddress, u16 serverPort, bool useSTUN, const CStr& hostJID); /** * Requires XmppClient to send iq request to the server to get server's ip and port based on passed password. Index: source/network/scripting/JSInterface_Network.cpp =================================================================== --- source/network/scripting/JSInterface_Network.cpp +++ source/network/scripting/JSInterface_Network.cpp @@ -78,7 +78,7 @@ return CStr(Hexify(encrypted, DIGESTSIZE)).UpperCase(); } -void JSI_Network::StartNetworkHost(ScriptInterface::CmptPrivate* pCmptPrivate, const CStrW& playerName, const u16 serverPort, const CStr& hostLobbyName, bool useSTUN, const CStr& password) +void JSI_Network::StartNetworkHost(ScriptInterface::CmptPrivate* pCmptPrivate, const CStrW& playerName, const u16 serverPort, bool useSTUN, const CStr& password) { ENSURE(!g_NetClient); ENSURE(!g_NetServer); @@ -127,7 +127,8 @@ g_Game = new CGame(true); g_NetClient = new CNetClient(g_Game, true); g_NetClient->SetUserName(playerName); - g_NetClient->SetHostingPlayerName(hostLobbyName); + if (hasLobby) + g_NetClient->SetHostJID(g_XmppClient->GetJID()); g_NetClient->SetGamePassword(hashedPass); g_NetClient->SetupServerData("127.0.0.1", serverPort, false); @@ -149,7 +150,7 @@ g_Game = new CGame(true); g_NetClient = new CNetClient(g_Game, false); g_NetClient->SetUserName(playerName); - g_NetClient->SetHostingPlayerName(hostJID.substr(0, hostJID.find("@"))); + g_NetClient->SetHostJID(hostJID); g_NetClient->SetupServerData(serverAddress, serverPort, useSTUN); if (!g_NetClient->SetupConnection(nullptr)) @@ -172,7 +173,7 @@ g_Game = new CGame(true); g_NetClient = new CNetClient(g_Game, false); g_NetClient->SetUserName(playerName); - g_NetClient->SetHostingPlayerName(hostJID.substr(0, hostJID.find("@"))); + g_NetClient->SetHostJID(hostJID); g_NetClient->SetGamePassword(hashedPass); g_XmppClient->SendIqGetConnectionData(hostJID, hashedPass.c_str()); } @@ -271,7 +272,7 @@ scriptInterface.RegisterFunction("GetDefaultPort"); scriptInterface.RegisterFunction("HasNetServer"); scriptInterface.RegisterFunction("HasNetClient"); - scriptInterface.RegisterFunction("StartNetworkHost"); + scriptInterface.RegisterFunction("StartNetworkHost"); scriptInterface.RegisterFunction("StartNetworkJoin"); scriptInterface.RegisterFunction("StartNetworkJoinLobby"); scriptInterface.RegisterFunction("DisconnectNetworkGame");