Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/source/lobby/XmppClient.cpp
/* Copyright (C) 2020 Wildfire Games. | /* Copyright (C) 2021 Wildfire Games. | ||||
* This file is part of 0 A.D. | * This file is part of 0 A.D. | ||||
* | * | ||||
* 0 A.D. is free software: you can redistribute it and/or modify | * 0 A.D. is free software: you can redistribute it and/or modify | ||||
* it under the terms of the GNU General Public License as published by | * it under the terms of the GNU General Public License as published by | ||||
* the Free Software Foundation, either version 2 of the License, or | * the Free Software Foundation, either version 2 of the License, or | ||||
* (at your option) any later version. | * (at your option) any later version. | ||||
* | * | ||||
* 0 A.D. is distributed in the hope that it will be useful, | * 0 A.D. is distributed in the hope that it will be useful, | ||||
Show All 13 Lines | |||||
#ifdef WIN32 | #ifdef WIN32 | ||||
# include <winsock2.h> | # include <winsock2.h> | ||||
#endif | #endif | ||||
#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/StunClient.h" | #include "network/StunClient.h" | ||||
#include "ps/CLogger.h" | #include "ps/CLogger.h" | ||||
#include "ps/ConfigDB.h" | #include "ps/ConfigDB.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 <gloox/gloox.h> | #include <gloox/gloox.h> | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | : m_ScriptInterface(scriptInterface), | ||||
m_username(sUsername), | m_username(sUsername), | ||||
m_password(sPassword), | m_password(sPassword), | ||||
m_room(sRoom), | m_room(sRoom), | ||||
m_nick(sNick), | m_nick(sNick), | ||||
m_initialLoadComplete(false), | m_initialLoadComplete(false), | ||||
m_isConnected(false), | m_isConnected(false), | ||||
m_sessionManager(nullptr), | m_sessionManager(nullptr), | ||||
m_certStatus(gloox::CertStatus::CertOk), | m_certStatus(gloox::CertStatus::CertOk), | ||||
m_PlayerMapUpdate(false) | m_PlayerMapUpdate(false), | ||||
m_connectionDataJid(), | |||||
m_connectionDataIqId() | |||||
{ | { | ||||
if (m_ScriptInterface) | if (m_ScriptInterface) | ||||
JS_AddExtraGCRootsTracer(m_ScriptInterface->GetGeneralJSContext(), XmppClient::Trace, this); | JS_AddExtraGCRootsTracer(m_ScriptInterface->GetGeneralJSContext(), XmppClient::Trace, this); | ||||
// Read lobby configuration from default.cfg | // Read lobby configuration from default.cfg | ||||
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); | ||||
Show All 37 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) | ||||
m_client->registerIqHandler(this, EXTBOARDLISTQUERY); | m_client->registerIqHandler(this, EXTBOARDLISTQUERY); | ||||
m_client->registerStanzaExtension(new ProfileQuery()); | m_client->registerStanzaExtension(new ProfileQuery()); | ||||
m_client->registerIqHandler(this, EXTPROFILEQUERY); | m_client->registerIqHandler(this, EXTPROFILEQUERY); | ||||
m_client->registerStanzaExtension(new LobbyAuth()); | m_client->registerStanzaExtension(new LobbyAuth()); | ||||
m_client->registerIqHandler(this, EXTLOBBYAUTH); | m_client->registerIqHandler(this, EXTLOBBYAUTH); | ||||
m_client->registerStanzaExtension(new ConnectionData()); | |||||
m_client->registerIqHandler(this, EXTCONNECTIONDATA); | |||||
m_client->registerMessageHandler(this); | m_client->registerMessageHandler(this); | ||||
// Uncomment to see the raw stanzas | // Uncomment to see the raw stanzas | ||||
//m_client->getWrapped()->logInstance().registerLogHandler( gloox::LogLevelDebug, gloox::LogAreaAll, this ); | //m_client->getWrapped()->logInstance().registerLogHandler( gloox::LogLevelDebug, gloox::LogAreaAll, this ); | ||||
if (!regOpt) | if (!regOpt) | ||||
{ | { | ||||
// Create a Multi User Chat Room | // Create a Multi User Chat Room | ||||
▲ Show 20 Lines • Show All 198 Lines • ▼ Show 20 Lines | void XmppClient::SendIqGetProfile(const std::string& player) | ||||
b->m_Command = player; | b->m_Command = player; | ||||
glooxwrapper::IQ iq(gloox::IQ::Get, echelonJid, m_client->getID()); | glooxwrapper::IQ iq(gloox::IQ::Get, echelonJid, m_client->getID()); | ||||
iq.addExtension(b); | iq.addExtension(b); | ||||
DbgXMPP("SendIqGetProfile [" << tag_xml(iq) << "]"); | DbgXMPP("SendIqGetProfile [" << tag_xml(iq) << "]"); | ||||
m_client->send(iq); | m_client->send(iq); | ||||
} | } | ||||
/** | /** | ||||
* Request the Connection data (ip, port...) from the server. | |||||
*/ | |||||
void XmppClient::SendIqGetConnectionData(const std::string& jid, const std::string& password) | |||||
{ | |||||
glooxwrapper::JID targetJID(jid); | |||||
ConnectionData* connectionData = new ConnectionData(); | |||||
connectionData->m_Password = password; | |||||
glooxwrapper::IQ iq(gloox::IQ::Get, targetJID, m_client->getID()); | |||||
iq.addExtension(connectionData); | |||||
m_connectionDataJid = jid; | |||||
m_connectionDataIqId = iq.id().to_string(); | |||||
DbgXMPP("SendIqGetConnectionData [" << tag_xml(iq) << "]"); | |||||
m_client->send(iq); | |||||
} | |||||
/** | |||||
* Send game report containing numerous game properties to the server. | * Send game report containing numerous game properties to the server. | ||||
* | * | ||||
* @param data A JS array of game statistics | * @param data A JS array of game statistics | ||||
*/ | */ | ||||
void XmppClient::SendIqGameReport(const ScriptInterface& scriptInterface, JS::HandleValue data) | void XmppClient::SendIqGameReport(const ScriptInterface& scriptInterface, JS::HandleValue data) | ||||
{ | { | ||||
glooxwrapper::JID echelonJid(m_echelonId); | glooxwrapper::JID echelonJid(m_echelonId); | ||||
▲ Show 20 Lines • Show All 195 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
void XmppClient::GUIGetGameList(const ScriptInterface& scriptInterface, JS::MutableHandleValue ret) | void XmppClient::GUIGetGameList(const ScriptInterface& scriptInterface, JS::MutableHandleValue ret) | ||||
{ | { | ||||
ScriptRequest rq(scriptInterface); | ScriptRequest rq(scriptInterface); | ||||
ScriptInterface::CreateArray(rq, ret); | ScriptInterface::CreateArray(rq, ret); | ||||
int j = 0; | int j = 0; | ||||
const char* stats[] = { "name", "ip", "port", "stunIP", "stunPort", "hostUsername", "state", | const char* stats[] = { "name", "hostUsername", "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 221 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
DbgXMPP("handleIq [" << tag_xml(iq) << "]"); | DbgXMPP("handleIq [" << tag_xml(iq) << "]"); | ||||
if (iq.subtype() == gloox::IQ::Result) | if (iq.subtype() == gloox::IQ::Result) | ||||
{ | { | ||||
const GameListQuery* gq = iq.findExtension<GameListQuery>(EXTGAMELISTQUERY); | const GameListQuery* gq = iq.findExtension<GameListQuery>(EXTGAMELISTQUERY); | ||||
const BoardListQuery* bq = iq.findExtension<BoardListQuery>(EXTBOARDLISTQUERY); | const BoardListQuery* bq = iq.findExtension<BoardListQuery>(EXTBOARDLISTQUERY); | ||||
const ProfileQuery* pq = iq.findExtension<ProfileQuery>(EXTPROFILEQUERY); | const ProfileQuery* pq = iq.findExtension<ProfileQuery>(EXTPROFILEQUERY); | ||||
const ConnectionData* cd = iq.findExtension<ConnectionData>(EXTCONNECTIONDATA); | |||||
if (cd) | |||||
{ | |||||
if (g_NetServer || !g_NetClient) | |||||
return true; | |||||
if (!m_connectionDataJid.empty() && m_connectionDataJid.compare(iq.from().full()) != 0) | |||||
return true; | |||||
if (!m_connectionDataIqId.empty() && m_connectionDataIqId.compare(iq.id().to_string()) != 0) | |||||
return true; | |||||
if (!cd->m_Error.empty()) | |||||
{ | |||||
g_NetClient->HandleGetServerDataFailed(cd->m_Error.c_str()); | |||||
return true; | |||||
} | |||||
g_NetClient->SetupServerData(cd->m_Ip.to_string(), stoi(cd->m_Port.to_string()), !cd->m_UseSTUN.empty()); | |||||
g_NetClient->TryToConnect(iq.from().full()); | |||||
} | |||||
if (gq) | if (gq) | ||||
{ | { | ||||
for (const glooxwrapper::Tag* const& t : m_GameList) | for (const glooxwrapper::Tag* const& t : m_GameList) | ||||
glooxwrapper::Tag::free(t); | glooxwrapper::Tag::free(t); | ||||
m_GameList.clear(); | m_GameList.clear(); | ||||
for (const glooxwrapper::Tag* const& t : gq->m_GameList) | for (const glooxwrapper::Tag* const& t : gq->m_GameList) | ||||
m_GameList.emplace_back(t->clone()); | m_GameList.emplace_back(t->clone()); | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | if (lobbyAuth) | ||||
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!"); | LOGERROR("Received lobby authentication request, but not hosting currently!"); | ||||
} | } | ||||
} | } | ||||
else if (iq.subtype() == gloox::IQ::Get) | |||||
{ | |||||
const ConnectionData* cd = iq.findExtension<ConnectionData>(EXTCONNECTIONDATA); | |||||
if (cd) | |||||
{ | |||||
LOGMESSAGE("XmppClient: Recieved request for connection data from %s", iq.from().username()); | |||||
if (!g_NetServer) | |||||
{ | |||||
glooxwrapper::IQ response(gloox::IQ::Result, iq.from(), iq.id()); | |||||
ConnectionData* connectionData = new ConnectionData(); | |||||
connectionData->m_Error = "not_server"; | |||||
response.addExtension(connectionData); | |||||
m_client->send(response); | |||||
return true; | |||||
} | |||||
if (!g_NetServer->CheckPassword(CStr(cd->m_Password.c_str()))) | |||||
{ | |||||
glooxwrapper::IQ response(gloox::IQ::Result, iq.from(), iq.id()); | |||||
ConnectionData* connectionData = new ConnectionData(); | |||||
connectionData->m_Error = "invalid_password"; | |||||
response.addExtension(connectionData); | |||||
m_client->send(response); | |||||
return true; | |||||
} | |||||
glooxwrapper::IQ response(gloox::IQ::Result, iq.from(), iq.id()); | |||||
ConnectionData* connectionData = new ConnectionData(); | |||||
connectionData->m_Ip = g_NetServer->GetPublicIp();; | |||||
connectionData->m_Port = std::to_string(g_NetServer->GetPublicPort()); | |||||
connectionData->m_UseSTUN = g_NetServer->GetUseSTUN() ? "true" : ""; | |||||
response.addExtension(connectionData); | |||||
m_client->send(response); | |||||
} | |||||
} | |||||
else if (iq.subtype() == gloox::IQ::Error) | else if (iq.subtype() == gloox::IQ::Error) | ||||
CreateGUIMessage("system", "error", std::time(nullptr), "text", iq.error_error()); | CreateGUIMessage("system", "error", std::time(nullptr), "text", iq.error_error()); | ||||
else | else | ||||
{ | { | ||||
CreateGUIMessage("system", "error", std::time(nullptr), "text", wstring_from_utf8(g_L10n.Translate("unknown subtype (see logs)"))); | CreateGUIMessage("system", "error", std::time(nullptr), "text", wstring_from_utf8(g_L10n.Translate("unknown subtype (see logs)"))); | ||||
LOGMESSAGE("unknown subtype '%s'", tag_name(iq).c_str()); | LOGMESSAGE("unknown subtype '%s'", tag_name(iq).c_str()); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 492 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator