Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/source/lobby/XmppClient.cpp
Show All 26 Lines | |||||
#include "i18n/L10n.h" | #include "i18n/L10n.h" | ||||
#include "lib/external_libraries/enet.h" | #include "lib/external_libraries/enet.h" | ||||
#include "lib/utf8.h" | #include "lib/utf8.h" | ||||
#include "network/NetServer.h" | #include "network/NetServer.h" | ||||
#include "network/NetClient.h" | #include "network/NetClient.h" | ||||
#include "network/StunClient.h" | #include "network/StunClient.h" | ||||
#include "ps/CLogger.h" | #include "ps/CLogger.h" | ||||
#include "ps/ConfigDB.h" | #include "ps/ConfigDB.h" | ||||
#include "ps/GUID.h" | |||||
#include "ps/Pyrogenesis.h" | #include "ps/Pyrogenesis.h" | ||||
#include "scriptinterface/ScriptExtraHeaders.h" // StructuredClone | #include "scriptinterface/ScriptExtraHeaders.h" // StructuredClone | ||||
#include "scriptinterface/ScriptInterface.h" | #include "scriptinterface/ScriptInterface.h" | ||||
#include <iostream> | #include <iostream> | ||||
//debug | //debug | ||||
#if 1 | #if 1 | ||||
▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | XmppClient::XmppClient(const ScriptInterface* scriptInterface, const std::string& sUsername, const std::string& sPassword, const std::string& sRoom, const std::string& sNick, const int historyRequestSize, bool regOpt) | ||||
std::string sXpartamupp; | std::string sXpartamupp; | ||||
std::string sEchelon; | std::string sEchelon; | ||||
CFG_GET_VAL("lobby.server", m_server); | CFG_GET_VAL("lobby.server", m_server); | ||||
CFG_GET_VAL("lobby.xpartamupp", sXpartamupp); | CFG_GET_VAL("lobby.xpartamupp", sXpartamupp); | ||||
CFG_GET_VAL("lobby.echelon", sEchelon); | CFG_GET_VAL("lobby.echelon", sEchelon); | ||||
m_xpartamuppId = sXpartamupp + "@" + m_server + "/CC"; | m_xpartamuppId = sXpartamupp + "@" + m_server + "/CC"; | ||||
m_echelonId = sEchelon + "@" + 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); | glooxwrapper::JID roomJid(m_room + "@conference." + m_server + "/" + sNick); | ||||
// If we are connecting, use the full jid and a password | // If we are connecting, use the full jid and a password | ||||
// If we are registering, only use the server name | // If we are registering, only use the server name | ||||
if (!regOpt) | if (!regOpt) | ||||
m_client = new glooxwrapper::Client(clientJid, sPassword); | m_client = new glooxwrapper::Client(clientJid, sPassword); | ||||
else | else | ||||
m_client = new glooxwrapper::Client(m_server); | m_client = new glooxwrapper::Client(m_server); | ||||
▲ Show 20 Lines • Show All 299 Lines • ▼ Show 20 Lines | |||||
* | * | ||||
* @param data A JS array of game attributes | * @param data A JS array of game attributes | ||||
*/ | */ | ||||
void XmppClient::SendIqRegisterGame(const ScriptInterface& scriptInterface, JS::HandleValue data) | void XmppClient::SendIqRegisterGame(const ScriptInterface& scriptInterface, JS::HandleValue data) | ||||
{ | { | ||||
glooxwrapper::JID xpartamuppJid(m_xpartamuppId); | glooxwrapper::JID xpartamuppJid(m_xpartamuppId); | ||||
// Setup some base stanza attributes | // Setup some base stanza attributes | ||||
GameListQuery* g = new GameListQuery(); | std::unique_ptr<GameListQuery> g = std::make_unique<GameListQuery>(); | ||||
g->m_Command = "register"; | g->m_Command = "register"; | ||||
glooxwrapper::Tag* game = glooxwrapper::Tag::allocate("game"); | glooxwrapper::Tag* game = glooxwrapper::Tag::allocate("game"); | ||||
// Iterate through all the properties reported and add them to the stanza. | // Iterate through all the properties reported and add them to the stanza. | ||||
std::vector<std::string> properties; | std::vector<std::string> properties; | ||||
scriptInterface.EnumeratePropertyNames(data, true, properties); | scriptInterface.EnumeratePropertyNames(data, true, properties); | ||||
for (const std::string& p : properties) | for (const std::string& p : properties) | ||||
{ | { | ||||
std::wstring value; | std::string value; | ||||
scriptInterface.GetProperty(data, p.c_str(), value); | if (!scriptInterface.GetProperty(data, p.c_str(), value)) | ||||
game->addAttribute(p, utf8_from_wstring(value)); | { | ||||
LOGERROR("Could not parse attribute '%s' as string.", p); | |||||
return; | |||||
} | |||||
game->addAttribute(p, value); | |||||
} | } | ||||
// Overwrite some attributes to make it slightly less trivial to do bad things, | |||||
// and explicit some invariants. | |||||
// The JID must point to ourself. | |||||
game->addAttribute("hostJID", GetJID()); | |||||
// Push the stanza onto the IQ | // Push the stanza onto the IQ | ||||
g->m_GameList.emplace_back(game); | g->m_GameList.emplace_back(game); | ||||
// Send IQ | // Send IQ | ||||
glooxwrapper::IQ iq(gloox::IQ::Set, xpartamuppJid, m_client->getID()); | glooxwrapper::IQ iq(gloox::IQ::Set, xpartamuppJid, m_client->getID()); | ||||
iq.addExtension(g); | iq.addExtension(g.release()); | ||||
DbgXMPP("SendIqRegisterGame [" << tag_xml(iq) << "]"); | DbgXMPP("SendIqRegisterGame [" << tag_xml(iq) << "]"); | ||||
m_client->send(iq); | m_client->send(iq); | ||||
} | } | ||||
/** | /** | ||||
* Send a request to unregister a game to the server. | * Send a request to unregister a game to the server. | ||||
*/ | */ | ||||
void XmppClient::SendIqUnregisterGame() | void XmppClient::SendIqUnregisterGame() | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | |||||
/** | /** | ||||
* Send lobby authentication token. | * Send lobby authentication token. | ||||
*/ | */ | ||||
void XmppClient::SendIqLobbyAuth(const std::string& to, const std::string& token) | void XmppClient::SendIqLobbyAuth(const std::string& to, const std::string& token) | ||||
{ | { | ||||
LobbyAuth* auth = new LobbyAuth(); | LobbyAuth* auth = new LobbyAuth(); | ||||
auth->m_Token = token; | 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()); | glooxwrapper::IQ iq(gloox::IQ::Set, clientJid, m_client->getID()); | ||||
iq.addExtension(auth); | iq.addExtension(auth); | ||||
DbgXMPP("SendIqLobbyAuth [" << tag_xml(iq) << "]"); | DbgXMPP("SendIqLobbyAuth [" << tag_xml(iq) << "]"); | ||||
m_client->send(iq); | m_client->send(iq); | ||||
} | } | ||||
/***************************************************** | /***************************************************** | ||||
* Account registration * | * Account registration * | ||||
▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | |||||
JS::Value XmppClient::GUIGetGameList(const ScriptInterface& scriptInterface) | JS::Value XmppClient::GUIGetGameList(const ScriptInterface& scriptInterface) | ||||
{ | { | ||||
ScriptRequest rq(scriptInterface); | ScriptRequest rq(scriptInterface); | ||||
JS::RootedValue ret(rq.cx); | JS::RootedValue ret(rq.cx); | ||||
ScriptInterface::CreateArray(rq, &ret); | ScriptInterface::CreateArray(rq, &ret); | ||||
int j = 0; | 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", | "nbp", "maxnbp", "players", "mapName", "niceMapName", "mapSize", "mapType", | ||||
"victoryConditions", "startTime", "mods" }; | "victoryConditions", "startTime", "mods" }; | ||||
for(const glooxwrapper::Tag* const& t : m_GameList) | for(const glooxwrapper::Tag* const& t : m_GameList) | ||||
{ | { | ||||
JS::RootedValue game(rq.cx); | JS::RootedValue game(rq.cx); | ||||
ScriptInterface::CreateObject(rq, &game); | ScriptInterface::CreateObject(rq, &game); | ||||
▲ Show 20 Lines • Show All 238 Lines • ▼ Show 20 Lines | if (cd) | ||||
return true; | return true; | ||||
if (!m_connectionDataJid.empty() && m_connectionDataJid.compare(iq.from().full()) != 0) { | if (!m_connectionDataJid.empty() && m_connectionDataJid.compare(iq.from().full()) != 0) { | ||||
LOGMESSAGE("XmppClient: Received connection data from invalid host: %s", iq.from().username()); | LOGMESSAGE("XmppClient: Received connection data from invalid host: %s", iq.from().username()); | ||||
return true; | return true; | ||||
} | } | ||||
if (!m_connectionDataIqId.empty() && m_connectionDataIqId.compare(iq.id().to_string()) != 0) { | if (!m_connectionDataIqId.empty() && m_connectionDataIqId.compare(iq.id().to_string()) != 0) { | ||||
LOGWARNING("XmppClient: Received connection data with invalid id"); | LOGMESSAGE("XmppClient: Received connection data with invalid id"); | ||||
return true; | return true; | ||||
} | } | ||||
if (!cd->m_Error.empty()) | if (!cd->m_Error.empty()) | ||||
{ | { | ||||
g_NetClient->HandleGetServerDataFailed(cd->m_Error.c_str()); | g_NetClient->HandleGetServerDataFailed(cd->m_Error.c_str()); | ||||
return true; | return true; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 76 Lines • ▼ Show 20 Lines | if (lobbyAuth) | ||||
LOGMESSAGE("XmppClient: Received lobby auth: %s from %s", lobbyAuth->m_Token.to_string(), iq.from().username()); | LOGMESSAGE("XmppClient: Received lobby auth: %s from %s", lobbyAuth->m_Token.to_string(), iq.from().username()); | ||||
glooxwrapper::IQ response(gloox::IQ::Result, iq.from(), iq.id()); | glooxwrapper::IQ response(gloox::IQ::Result, iq.from(), iq.id()); | ||||
m_client->send(response); | m_client->send(response); | ||||
if (g_NetServer) | if (g_NetServer) | ||||
g_NetServer->OnLobbyAuth(iq.from().username(), lobbyAuth->m_Token.to_string()); | g_NetServer->OnLobbyAuth(iq.from().username(), lobbyAuth->m_Token.to_string()); | ||||
else | else | ||||
LOGERROR("Received lobby authentication request, but not hosting currently!"); | LOGMESSAGE("Received lobby authentication request, but not hosting currently!"); | ||||
} | } | ||||
} | } | ||||
else if (iq.subtype() == gloox::IQ::Get) | else if (iq.subtype() == gloox::IQ::Get) | ||||
{ | { | ||||
const ConnectionData* cd = iq.findExtension<ConnectionData>(EXTCONNECTIONDATA); | const ConnectionData* cd = iq.findExtension<ConnectionData>(EXTCONNECTIONDATA); | ||||
if (cd) | if (cd) | ||||
{ | { | ||||
LOGMESSAGE("XmppClient: Received request for connection data from %s", iq.from().username()); | LOGMESSAGE("XmppClient: Received request for connection data from %s", iq.from().username()); | ||||
▲ Show 20 Lines • Show All 204 Lines • ▼ Show 20 Lines | |||||
void XmppClient::SetNick(const std::string& nick) | void XmppClient::SetNick(const std::string& nick) | ||||
{ | { | ||||
m_mucRoom->setNick(nick); | m_mucRoom->setNick(nick); | ||||
} | } | ||||
/** | /** | ||||
* Get current nickname. | * Get current nickname. | ||||
*/ | */ | ||||
std::string XmppClient::GetNick() | std::string XmppClient::GetNick() const | ||||
{ | { | ||||
return m_mucRoom->nick().to_string(); | return m_mucRoom->nick().to_string(); | ||||
} | } | ||||
std::string XmppClient::GetJID() const | |||||
{ | |||||
return m_client->getJID().to_string(); | |||||
} | |||||
/** | /** | ||||
* Kick a player from the current room. | * Kick a player from the current room. | ||||
* | * | ||||
* @param nick Nickname to be kicked | * @param nick Nickname to be kicked | ||||
* @param reason Reason the player was kicked | * @param reason Reason the player was kicked | ||||
*/ | */ | ||||
void XmppClient::kick(const std::string& nick, const std::string& reason) | void XmppClient::kick(const std::string& nick, const std::string& reason) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 319 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator