Changeset View
Changeset View
Standalone View
Standalone View
source/lobby/XmppClient.cpp
Show All 19 Lines | |||||
#include "XmppClient.h" | #include "XmppClient.h" | ||||
#include "StanzaExtensions.h" | #include "StanzaExtensions.h" | ||||
#ifdef WIN32 | #ifdef WIN32 | ||||
# include <winsock2.h> | # include <winsock2.h> | ||||
#endif | #endif | ||||
#include "i18n/L10n.h" | #include "i18n/L10n.h" | ||||
#include "lobby/scripting/GlooxScriptConversions.cpp" | |||||
#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/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/ScriptInterface.h" | #include "scriptinterface/ScriptInterface.h" | ||||
#include <gloox/gloox.h> | #include <gloox/gloox.h> | ||||
//debug | //debug | ||||
#if 1 | #if 0 | ||||
Stan: Intended ? | |||||
Done Inline ActionsYes, because I uploaded it as a backup and because the DbgXMPP calls must be tested as they are changed too. elexis: Yes, because I uploaded it as a backup and because the DbgXMPP calls must be tested as they are… | |||||
#define DbgXMPP(x) | #define DbgXMPP(x) | ||||
#else | #else | ||||
#define DbgXMPP(x) std::cout << x << std::endl; | #define DbgXMPP(x) std::cout << x << std::endl; | ||||
static std::string tag_xml(const glooxwrapper::IQ& iq) | static std::string tag_xml(const glooxwrapper::IQ& iq) | ||||
{ | { | ||||
std::string ret; | std::string ret; | ||||
glooxwrapper::Tag* tag = iq.tag(); | glooxwrapper::Tag* tag = iq.tag(); | ||||
▲ Show 20 Lines • Show All 230 Lines • ▼ Show 20 Lines | void XmppClient::onDisconnect(gloox::ConnectionError error) | ||||
m_Profile.clear(); | m_Profile.clear(); | ||||
m_HistoricGuiMessages.clear(); | m_HistoricGuiMessages.clear(); | ||||
m_isConnected = false; | m_isConnected = false; | ||||
CreateGUIMessage( | CreateGUIMessage( | ||||
"system", | "system", | ||||
"disconnected", | "disconnected", | ||||
std::time(nullptr), | std::time(nullptr), | ||||
"reason", ConnectionErrorToString(error), | "reason", error, | ||||
"certificate_status", CertificateErrorToString(m_certStatus)); | "certificate_status", m_certStatus); | ||||
} | } | ||||
/** | /** | ||||
* Handle TLS connection. | * Handle TLS connection. | ||||
*/ | */ | ||||
bool XmppClient::onTLSConnect(const glooxwrapper::CertInfo& info) | bool XmppClient::onTLSConnect(const glooxwrapper::CertInfo& info) | ||||
{ | { | ||||
DbgXMPP("onTLSConnect"); | DbgXMPP("onTLSConnect"); | ||||
Show All 15 Lines | bool XmppClient::onTLSConnect(const glooxwrapper::CertInfo& info) | ||||
return info.status == gloox::CertOk || !verify_certificate; | return info.status == gloox::CertOk || !verify_certificate; | ||||
} | } | ||||
/** | /** | ||||
* Handle MUC room errors | * Handle MUC room errors | ||||
*/ | */ | ||||
void XmppClient::handleMUCError(glooxwrapper::MUCRoom*, gloox::StanzaError err) | void XmppClient::handleMUCError(glooxwrapper::MUCRoom*, gloox::StanzaError err) | ||||
{ | { | ||||
CreateGUIMessage("system", "error", std::time(nullptr), "text", StanzaErrorToString(err)); | CreateGUIMessage("system", "error", std::time(nullptr), "text", err); | ||||
} | } | ||||
/***************************************************** | /***************************************************** | ||||
* Requests to server * | * Requests to server * | ||||
*****************************************************/ | *****************************************************/ | ||||
/** | /** | ||||
* Request the leaderboard data from the server. | * Request the leaderboard data from the server. | ||||
▲ Show 20 Lines • Show All 170 Lines • ▼ Show 20 Lines | void XmppClient::handleRegistrationFields(const glooxwrapper::JID&, int fields, glooxwrapper::string) | ||||
m_registration->createAccount(fields, vals); | m_registration->createAccount(fields, vals); | ||||
} | } | ||||
void XmppClient::handleRegistrationResult(const glooxwrapper::JID&, gloox::RegistrationResult result) | void XmppClient::handleRegistrationResult(const glooxwrapper::JID&, gloox::RegistrationResult result) | ||||
{ | { | ||||
if (result == gloox::RegistrationSuccess) | if (result == gloox::RegistrationSuccess) | ||||
CreateGUIMessage("system", "registered", std::time(nullptr)); | CreateGUIMessage("system", "registered", std::time(nullptr)); | ||||
else | else | ||||
CreateGUIMessage("system", "error", std::time(nullptr), "text", RegistrationResultToString(result)); | CreateGUIMessage("system", "error", std::time(nullptr), "text", result); | ||||
disconnect(); | disconnect(); | ||||
} | } | ||||
void XmppClient::handleAlreadyRegistered(const glooxwrapper::JID&) | void XmppClient::handleAlreadyRegistered(const glooxwrapper::JID&) | ||||
{ | { | ||||
DbgXMPP("the account already exists"); | DbgXMPP("the account already exists"); | ||||
} | } | ||||
Show All 20 Lines | |||||
void XmppClient::GUIGetPlayerList(const ScriptInterface& scriptInterface, JS::MutableHandleValue ret) | void XmppClient::GUIGetPlayerList(const ScriptInterface& scriptInterface, JS::MutableHandleValue ret) | ||||
{ | { | ||||
JSContext* cx = scriptInterface.GetContext(); | JSContext* cx = scriptInterface.GetContext(); | ||||
JSAutoRequest rq(cx); | JSAutoRequest rq(cx); | ||||
scriptInterface.CreateArray(ret); | scriptInterface.CreateArray(ret); | ||||
int j = 0; | int j = 0; | ||||
for (const std::pair<std::string, std::vector<std::string> >& p : m_PlayerMap) | for (const std::pair<glooxwrapper::string, SPlayer>& p : m_PlayerMap) | ||||
{ | { | ||||
JS::RootedValue player(cx); | JS::RootedValue player(cx); | ||||
scriptInterface.CreateObject( | scriptInterface.CreateObject( | ||||
&player, | &player, | ||||
"name", wstring_from_utf8(p.first), | "name", p.first, | ||||
"presence", wstring_from_utf8(p.second[0]), | "presence", p.second.m_Presence, | ||||
"rating", wstring_from_utf8(p.second[1]), | "rating", p.second.m_Rating, | ||||
"role", wstring_from_utf8(p.second[2])); | "role", p.second.m_Role); | ||||
scriptInterface.SetPropertyInt(ret, j++, player); | scriptInterface.SetPropertyInt(ret, j++, player); | ||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* Handle requests from the GUI for the list of all active games. | * Handle requests from the GUI for the list of all active games. | ||||
* | * | ||||
Show All 12 Lines | const char* stats[] = { "name", "ip", "port", "stunIP", "stunPort", "hostUsername", "state", | ||||
"victoryCondition", "startTime", "mods" }; | "victoryCondition", "startTime", "mods" }; | ||||
for(const glooxwrapper::Tag* const& t : m_GameList) | for(const glooxwrapper::Tag* const& t : m_GameList) | ||||
{ | { | ||||
JS::RootedValue game(cx); | JS::RootedValue game(cx); | ||||
scriptInterface.CreateObject(&game); | scriptInterface.CreateObject(&game); | ||||
for (size_t i = 0; i < ARRAY_SIZE(stats); ++i) | for (size_t i = 0; i < ARRAY_SIZE(stats); ++i) | ||||
scriptInterface.SetProperty(game, stats[i], wstring_from_utf8(t->findAttribute(stats[i]).to_string())); | scriptInterface.SetProperty(game, stats[i], t->findAttribute(stats[i])); | ||||
scriptInterface.SetPropertyInt(ret, j++, game); | scriptInterface.SetPropertyInt(ret, j++, game); | ||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* Handle requests from the GUI for leaderboard data. | * Handle requests from the GUI for leaderboard data. | ||||
* | * | ||||
Show All 10 Lines | void XmppClient::GUIGetBoardList(const ScriptInterface& scriptInterface, JS::MutableHandleValue ret) | ||||
const char* attributes[] = { "name", "rank", "rating" }; | const char* attributes[] = { "name", "rank", "rating" }; | ||||
for(const glooxwrapper::Tag* const& t : m_BoardList) | for(const glooxwrapper::Tag* const& t : m_BoardList) | ||||
{ | { | ||||
JS::RootedValue board(cx); | JS::RootedValue board(cx); | ||||
scriptInterface.CreateObject(&board); | scriptInterface.CreateObject(&board); | ||||
for (size_t i = 0; i < ARRAY_SIZE(attributes); ++i) | for (size_t i = 0; i < ARRAY_SIZE(attributes); ++i) | ||||
scriptInterface.SetProperty(board, attributes[i], wstring_from_utf8(t->findAttribute(attributes[i]).to_string())); | scriptInterface.SetProperty(board, attributes[i], t->findAttribute(attributes[i])); | ||||
scriptInterface.SetPropertyInt(ret, j++, board); | scriptInterface.SetPropertyInt(ret, j++, board); | ||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* Handle requests from the GUI for profile data. | * Handle requests from the GUI for profile data. | ||||
* | * | ||||
Show All 10 Lines | void XmppClient::GUIGetProfile(const ScriptInterface& scriptInterface, JS::MutableHandleValue ret) | ||||
const char* stats[] = { "player", "rating", "totalGamesPlayed", "highestRating", "wins", "losses", "rank" }; | const char* stats[] = { "player", "rating", "totalGamesPlayed", "highestRating", "wins", "losses", "rank" }; | ||||
for (const glooxwrapper::Tag* const& t : m_Profile) | for (const glooxwrapper::Tag* const& t : m_Profile) | ||||
{ | { | ||||
JS::RootedValue profile(cx); | JS::RootedValue profile(cx); | ||||
scriptInterface.CreateObject(&profile); | scriptInterface.CreateObject(&profile); | ||||
for (size_t i = 0; i < ARRAY_SIZE(stats); ++i) | for (size_t i = 0; i < ARRAY_SIZE(stats); ++i) | ||||
scriptInterface.SetProperty(profile, stats[i], wstring_from_utf8(t->findAttribute(stats[i]).to_string())); | scriptInterface.SetProperty(profile, stats[i], t->findAttribute(stats[i])); | ||||
scriptInterface.SetPropertyInt(ret, j++, profile); | scriptInterface.SetPropertyInt(ret, j++, profile); | ||||
} | } | ||||
} | } | ||||
/***************************************************** | /***************************************************** | ||||
* Message interfaces * | * Message interfaces * | ||||
*****************************************************/ | *****************************************************/ | ||||
▲ Show 20 Lines • Show All 97 Lines • ▼ Show 20 Lines | |||||
void XmppClient::handleMUCMessage(glooxwrapper::MUCRoom*, const glooxwrapper::Message& msg, bool priv) | void XmppClient::handleMUCMessage(glooxwrapper::MUCRoom*, const glooxwrapper::Message& msg, bool priv) | ||||
{ | { | ||||
DbgXMPP(msg.from().resource() << " said " << msg.body()); | DbgXMPP(msg.from().resource() << " said " << msg.body()); | ||||
CreateGUIMessage( | CreateGUIMessage( | ||||
"chat", | "chat", | ||||
priv ? "private-message" : "room-message", | priv ? "private-message" : "room-message", | ||||
ComputeTimestamp(msg), | ComputeTimestamp(msg), | ||||
"from", msg.from().resource().to_string(), | "from", msg.from().resource(), | ||||
"text", msg.body().to_string()); | "text", msg.body()); | ||||
} | } | ||||
/** | /** | ||||
* Handle a private message. | * Handle a private message. | ||||
*/ | */ | ||||
void XmppClient::handleMessage(const glooxwrapper::Message& msg, glooxwrapper::MessageSession*) | void XmppClient::handleMessage(const glooxwrapper::Message& msg, glooxwrapper::MessageSession*) | ||||
{ | { | ||||
DbgXMPP("type " << msg.subtype() << ", subject " << msg.subject() | DbgXMPP("type " << msg.subtype() << ", subject " << msg.subject() | ||||
<< ", message " << msg.body() << ", thread id " << msg.thread()); | << ", message " << msg.body() << ", thread id " << msg.thread()); | ||||
CreateGUIMessage( | CreateGUIMessage( | ||||
"chat", | "chat", | ||||
"private-message", | "private-message", | ||||
ComputeTimestamp(msg), | ComputeTimestamp(msg), | ||||
"from", msg.from().resource().to_string(), | "from", msg.from().resource(), | ||||
"text", msg.body().to_string()); | "text", msg.body()); | ||||
} | } | ||||
/** | /** | ||||
* Handle portions of messages containing custom stanza extensions. | * Handle portions of messages containing custom stanza extensions. | ||||
*/ | */ | ||||
bool XmppClient::handleIq(const glooxwrapper::IQ& iq) | bool XmppClient::handleIq(const glooxwrapper::IQ& iq) | ||||
{ | { | ||||
DbgXMPP("handleIq [" << tag_xml(iq) << "]"); | DbgXMPP("handleIq [" << tag_xml(iq) << "]"); | ||||
Show All 26 Lines | if (bq) | ||||
m_BoardList.emplace_back(t->clone()); | m_BoardList.emplace_back(t->clone()); | ||||
CreateGUIMessage("game", "leaderboard", std::time(nullptr)); | CreateGUIMessage("game", "leaderboard", std::time(nullptr)); | ||||
} | } | ||||
else if (bq->m_Command == "ratinglist") | else if (bq->m_Command == "ratinglist") | ||||
{ | { | ||||
for (const glooxwrapper::Tag* const& t : bq->m_StanzaBoardList) | for (const glooxwrapper::Tag* const& t : bq->m_StanzaBoardList) | ||||
{ | { | ||||
std::string name = t->findAttribute("name").to_string(); | PlayerMap::iterator it = m_PlayerMap.find(t->findAttribute("name")); | ||||
if (m_PlayerMap.find(name) != m_PlayerMap.end()) | if (it != m_PlayerMap.end()) | ||||
{ | { | ||||
m_PlayerMap[name][1] = t->findAttribute("rating").to_string(); | it->second.m_Rating = t->findAttribute("rating"); | ||||
m_PlayerMapUpdate = true; | m_PlayerMapUpdate = true; | ||||
} | } | ||||
} | } | ||||
CreateGUIMessage("game", "ratinglist", std::time(nullptr)); | CreateGUIMessage("game", "ratinglist", std::time(nullptr)); | ||||
} | } | ||||
} | } | ||||
if (pq) | if (pq) | ||||
{ | { | ||||
Show All 19 Lines | if (lobbyAuth) | ||||
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::Error) | else if (iq.subtype() == gloox::IQ::Error) | ||||
CreateGUIMessage("system", "error", std::time(nullptr), "text", StanzaErrorToString(iq.error_error())); | CreateGUIMessage("system", "error", std::time(nullptr), "text", iq.error_error()); | ||||
else | else | ||||
{ | { | ||||
CreateGUIMessage("system", "error", std::time(nullptr), "text", 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()); | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
/** | /** | ||||
* Update local data when a user changes presence. | * Update local data when a user changes presence. | ||||
*/ | */ | ||||
void XmppClient::handleMUCParticipantPresence(glooxwrapper::MUCRoom*, const glooxwrapper::MUCRoomParticipant participant, const glooxwrapper::Presence& presence) | void XmppClient::handleMUCParticipantPresence(glooxwrapper::MUCRoom*, const glooxwrapper::MUCRoomParticipant participant, const glooxwrapper::Presence& presence) | ||||
{ | { | ||||
std::string nick = participant.nick->resource().to_string(); | const glooxwrapper::string& nick = participant.nick->resource(); | ||||
gloox::Presence::PresenceType presenceType = presence.presence(); | |||||
std::string presenceString, roleString; | |||||
GetPresenceString(presenceType, presenceString); | |||||
GetRoleString(participant.role, roleString); | |||||
if (presenceType == gloox::Presence::Unavailable) | if (presence.presence() == gloox::Presence::Unavailable) | ||||
{ | { | ||||
if (!participant.newNick.empty() && (participant.flags & (gloox::UserNickChanged | gloox::UserSelf))) | if (!participant.newNick.empty() && (participant.flags & (gloox::UserNickChanged | gloox::UserSelf))) | ||||
{ | { | ||||
// we have a nick change | // we have a nick change | ||||
std::string newNick = participant.newNick.to_string(); | if (m_PlayerMap.find(participant.newNick) == m_PlayerMap.end()) | ||||
m_PlayerMap[newNick].resize(3); | m_PlayerMap.emplace( | ||||
Done Inline Actions
elexis: 1. s/nick/newNick
2. Piecewise construct in place and post a LOGERROR if the item already… | |||||
m_PlayerMap[newNick][0] = presenceString; | std::piecewise_construct, | ||||
m_PlayerMap[newNick][2] = roleString; | std::forward_as_tuple(participant.newNick), | ||||
std::forward_as_tuple(presence.presence(), m_PlayerMap.at(nick).m_Rating, participant.role)); | |||||
else | |||||
LOGERROR("Nickname changed to an existing nick!"); | |||||
DbgXMPP(nick << " is now known as " << participant.newNick.to_string()); | DbgXMPP(nick << " is now known as " << participant.newNick); | ||||
CreateGUIMessage("chat", "nick", std::time(nullptr), "oldnick", nick, "newnick", participant.newNick.to_string()); | CreateGUIMessage( | ||||
"chat", | |||||
"nick", | |||||
std::time(nullptr), | |||||
"oldnick", nick, | |||||
"newnick", participant.newNick); | |||||
} | } | ||||
else if (participant.flags & gloox::UserKicked) | else if (participant.flags & gloox::UserKicked) | ||||
{ | { | ||||
DbgXMPP(nick << " was kicked. Reason: " << participant.reason.to_string()); | DbgXMPP(nick << " was kicked. Reason: " << participant.reason); | ||||
CreateGUIMessage("chat", "kicked", std::time(nullptr), "nick", nick, "reason", participant.reason.to_string()); | CreateGUIMessage( | ||||
"chat", | |||||
"kicked", | |||||
std::time(nullptr), | |||||
"nick", nick, | |||||
"reason", participant.reason); | |||||
} | } | ||||
else if (participant.flags & gloox::UserBanned) | else if (participant.flags & gloox::UserBanned) | ||||
{ | { | ||||
DbgXMPP(nick << " was banned. Reason: " << participant.reason.to_string()); | DbgXMPP(nick << " was banned. Reason: " << participant.reason); | ||||
CreateGUIMessage("chat", "banned", std::time(nullptr), "nick", nick, "reason", participant.reason.to_string()); | CreateGUIMessage( | ||||
"chat", | |||||
"banned", | |||||
std::time(nullptr), | |||||
"nick", nick, | |||||
"reason", participant.reason); | |||||
} | } | ||||
else | else | ||||
{ | { | ||||
DbgXMPP(nick << " left the room (flags " << participant.flags << ")"); | DbgXMPP(nick << " left the room (flags " << participant.flags << ")"); | ||||
CreateGUIMessage("chat", "leave", std::time(nullptr), "nick", nick); | CreateGUIMessage( | ||||
"chat", | |||||
"leave", | |||||
std::time(nullptr), | |||||
"nick", nick); | |||||
} | } | ||||
m_PlayerMap.erase(nick); | m_PlayerMap.erase(nick); | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
/* During the initialization process, we receive join messages for everyone | /* During the initialization process, we receive join messages for everyone | ||||
* currently in the room. We don't want to display these, so we filter them | * currently in the room. We don't want to display these, so we filter them | ||||
* out. We will always be the last to join during initialization. | * out. We will always be the last to join during initialization. | ||||
*/ | */ | ||||
if (!m_initialLoadComplete) | if (!m_initialLoadComplete) | ||||
{ | { | ||||
if (m_mucRoom->nick().to_string() == nick) | if (m_mucRoom->nick() == nick) | ||||
m_initialLoadComplete = true; | m_initialLoadComplete = true; | ||||
} | } | ||||
else if (m_PlayerMap.find(nick) == m_PlayerMap.end()) | else if (m_PlayerMap.find(nick) == m_PlayerMap.end()) | ||||
CreateGUIMessage("chat", "join", std::time(nullptr), "nick", nick); | { | ||||
else if (m_PlayerMap[nick][2] != roleString) | CreateGUIMessage( | ||||
CreateGUIMessage("chat", "role", std::time(nullptr), "nick", nick, "oldrole", m_PlayerMap[nick][2], "newrole", roleString); | "chat", | ||||
"join", | |||||
std::time(nullptr), | |||||
"nick", nick); | |||||
} | |||||
else if (m_PlayerMap.at(nick).m_Role != participant.role) | |||||
{ | |||||
CreateGUIMessage( | |||||
"chat", | |||||
"role", | |||||
std::time(nullptr), | |||||
"nick", nick, | |||||
"oldrole", m_PlayerMap.at(nick).m_Role, | |||||
"newrole", participant.role); | |||||
} | |||||
else | else | ||||
{ | { | ||||
// Don't create a GUI message for regular presence changes, because | // Don't create a GUI message for regular presence changes, because | ||||
// several hundreds of them accumulate during a match, impacting performance terribly and | // several hundreds of them accumulate during a match, impacting performance terribly and | ||||
// the only way they are used is to determine whether to update the playerlist. | // the only way they are used is to determine whether to update the playerlist. | ||||
} | } | ||||
DbgXMPP(nick << " is in the room, presence : " << (int)presenceType); | DbgXMPP( | ||||
m_PlayerMap[nick].resize(3); | nick << " is in the room, " | ||||
m_PlayerMap[nick][0] = presenceString; | "presence: " << GetPresenceString(presence.presence()) << ", " | ||||
Done Inline ActionsCan avoid the second [] operator which compares each key of the map until it found the correct one by saving a reference after the first [] operator call! (Also the debug string is to be improved) elexis: Can avoid the second `[]` operator which compares each key of the map until it found the… | |||||
m_PlayerMap[nick][2] = roleString; | "role: "<< GetRoleString(participant.role)); | ||||
// Insert or update | |||||
SPlayer& player = m_PlayerMap[nick]; | |||||
player.m_Presence = presence.presence(); | |||||
player.m_Role = participant.role; | |||||
} | } | ||||
m_PlayerMapUpdate = true; | m_PlayerMapUpdate = true; | ||||
} | } | ||||
/** | /** | ||||
* Update local cache when subject changes. | * Update local cache when subject changes. | ||||
*/ | */ | ||||
void XmppClient::handleMUCSubject(glooxwrapper::MUCRoom*, const glooxwrapper::string& nick, const glooxwrapper::string& subject) | void XmppClient::handleMUCSubject(glooxwrapper::MUCRoom*, const glooxwrapper::string& nick, const glooxwrapper::string& subject) | ||||
{ | { | ||||
m_Subject = subject.c_str(); | m_Subject = wstring_from_utf8(subject.to_string()); | ||||
CreateGUIMessage("chat", "subject", std::time(nullptr), "nick", nick.c_str(), "subject", m_Subject); | |||||
CreateGUIMessage( | |||||
"chat", | |||||
"subject", | |||||
std::time(nullptr), | |||||
"nick", nick, | |||||
"subject", m_Subject); | |||||
} | } | ||||
/** | /** | ||||
* Get current subject. | * Get current subject. | ||||
* | |||||
* @param topic Variable to store subject in. | |||||
*/ | */ | ||||
void XmppClient::GetSubject(std::string& subject) | const std::wstring& XmppClient::GetSubject() | ||||
{ | { | ||||
subject = m_Subject; | return m_Subject; | ||||
} | } | ||||
/** | /** | ||||
* Request nick change, real change via mucRoomHandler. | * Request nick change, real change via mucRoomHandler. | ||||
* | * | ||||
* @param nick Desired nickname | * @param nick Desired nickname | ||||
*/ | */ | ||||
void XmppClient::SetNick(const std::string& nick) | void XmppClient::SetNick(const std::string& nick) | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | #define IF(x,y) if (presence == x) m_mucRoom->setPresence(gloox::Presence::y) | ||||
else IF("offline", Unavailable); | else IF("offline", Unavailable); | ||||
// The others are not to be set | // The others are not to be set | ||||
#undef IF | #undef IF | ||||
else LOGERROR("Unknown presence '%s'", presence.c_str()); | else LOGERROR("Unknown presence '%s'", presence.c_str()); | ||||
} | } | ||||
/** | /** | ||||
* Get the current xmpp presence of the given nick. | * Get the current xmpp presence of the given nick. | ||||
* | |||||
* @param nick Nickname to look up presence for | |||||
* @param presence Variable to store the presence in | |||||
*/ | */ | ||||
void XmppClient::GetPresence(const std::string& nick, std::string& presence) | const char* XmppClient::GetPresence(const std::string& nick) | ||||
{ | { | ||||
if (m_PlayerMap.find(nick) != m_PlayerMap.end()) | PlayerMap::iterator it = m_PlayerMap.find(nick); | ||||
presence = m_PlayerMap[nick][0]; | |||||
else | if (it == m_PlayerMap.end()) | ||||
presence = "offline"; | return "offline"; | ||||
return GetPresenceString(it->second.m_Presence); | |||||
} | } | ||||
/** | /** | ||||
* Get the current xmpp role of the given nick. | * Get the current xmpp role of the given nick. | ||||
* | |||||
* @param nick Nickname to look up presence for | |||||
* @param role Variable to store the role in | |||||
*/ | */ | ||||
Done Inline Actionscomments outdated. elexis: comments outdated. | |||||
void XmppClient::GetRole(const std::string& nick, std::string& role) | const char* XmppClient::GetRole(const std::string& nick) | ||||
{ | { | ||||
if (m_PlayerMap.find(nick) != m_PlayerMap.end()) | PlayerMap::iterator it = m_PlayerMap.find(nick); | ||||
Done Inline ActionsHere it finds the same item in the map twice, it could just store the result of the first iterator. elexis: Here it finds the same item in the map twice, it could just store the result of the first… | |||||
role = m_PlayerMap[nick][2]; | |||||
else | if (it == m_PlayerMap.end()) | ||||
role = ""; | return ""; | ||||
return GetRoleString(it->second.m_Role); | |||||
} | } | ||||
/***************************************************** | /***************************************************** | ||||
* Utilities * | * Utilities * | ||||
*****************************************************/ | *****************************************************/ | ||||
/** | /** | ||||
* Parse and return the timestamp of a historic chat message and return the current time for new chat messages. | * Parse and return the timestamp of a historic chat message and return the current time for new chat messages. | ||||
* Historic chat messages are implement as DelayedDelivers as specified in XEP-0203. | * Historic chat messages are implement as DelayedDelivers as specified in XEP-0203. | ||||
* Hence, their timestamp MUST be in UTC and conform to the DateTime format XEP-0082. | * Hence, their timestamp MUST be in UTC and conform to the DateTime format XEP-0082. | ||||
* | * | ||||
* @returns Seconds since the epoch. | * @returns Seconds since the epoch. | ||||
*/ | */ | ||||
std::time_t XmppClient::ComputeTimestamp(const glooxwrapper::Message& msg) const | std::time_t XmppClient::ComputeTimestamp(const glooxwrapper::Message& msg) | ||||
{ | { | ||||
// Only historic messages contain a timestamp! | // Only historic messages contain a timestamp! | ||||
if (!msg.when()) | if (!msg.when()) | ||||
return std::time(nullptr); | return std::time(nullptr); | ||||
// The locale is irrelevant, because the XMPP date format doesn't contain written month names | // The locale is irrelevant, because the XMPP date format doesn't contain written month names | ||||
for (const std::string& format : std::vector<std::string>{ "Y-M-d'T'H:m:sZ", "Y-M-d'T'H:m:s.SZ" }) | for (const std::string& format : std::vector<std::string>{ "Y-M-d'T'H:m:sZ", "Y-M-d'T'H:m:s.SZ" }) | ||||
{ | { | ||||
UDate dateTime = g_L10n.ParseDateTime(msg.when()->stamp().to_string(), format, icu::Locale::getUS()); | UDate dateTime = g_L10n.ParseDateTime(msg.when()->stamp().to_string(), format, icu::Locale::getUS()); | ||||
if (dateTime) | if (dateTime) | ||||
return dateTime / 1000.0; | return dateTime / 1000.0; | ||||
} | } | ||||
return std::time(nullptr); | return std::time(nullptr); | ||||
} | } | ||||
/** | /** | ||||
* Convert a gloox presence type to string. | * Convert a gloox presence type to an untranslated string literal to be used as an identifier by the scripts. | ||||
* | |||||
* @param p Presence to be converted | |||||
* @param presence Variable to store the converted presence string in | |||||
*/ | */ | ||||
void XmppClient::GetPresenceString(const gloox::Presence::PresenceType p, std::string& presence) const | const char* XmppClient::GetPresenceString(const gloox::Presence::PresenceType presenceType) | ||||
{ | { | ||||
switch(p) | switch (presenceType) | ||||
{ | { | ||||
#define CASE(x,y) case gloox::Presence::x: presence = y; break | #define CASE(X,Y) case gloox::Presence::X: return Y | ||||
CASE(Available, "available"); | CASE(Available, "available"); | ||||
CASE(Chat, "chat"); | CASE(Chat, "chat"); | ||||
CASE(Away, "away"); | CASE(Away, "away"); | ||||
CASE(DND, "playing"); | CASE(DND, "playing"); | ||||
CASE(XA, "away"); | CASE(XA, "away"); | ||||
CASE(Unavailable, "offline"); | CASE(Unavailable, "offline"); | ||||
CASE(Probe, "probe"); | CASE(Probe, "probe"); | ||||
CASE(Error, "error"); | CASE(Error, "error"); | ||||
CASE(Invalid, "invalid"); | CASE(Invalid, "invalid"); | ||||
default: | default: | ||||
LOGERROR("Unknown presence type '%d'", (int)p); | LOGERROR("Unknown presence type '%d'", static_cast<int>(presenceType)); | ||||
break; | return ""; | ||||
#undef CASE | #undef CASE | ||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* Convert a gloox role type to string. | * Convert a gloox role type to an untranslated string literal to be used as an identifier by the scripts. | ||||
* | |||||
* @param p Role to be converted | |||||
* @param presence Variable to store the converted role string in | |||||
*/ | */ | ||||
void XmppClient::GetRoleString(const gloox::MUCRoomRole r, std::string& role) const | const char* XmppClient::GetRoleString(const gloox::MUCRoomRole role) | ||||
{ | { | ||||
switch(r) | switch (role) | ||||
{ | { | ||||
#define CASE(X, Y) case gloox::X: role = Y; break | #define CASE(X, Y) case gloox::X: return Y | ||||
CASE(RoleNone, "none"); | CASE(RoleNone, "none"); | ||||
CASE(RoleVisitor, "visitor"); | CASE(RoleVisitor, "visitor"); | ||||
CASE(RoleParticipant, "participant"); | CASE(RoleParticipant, "participant"); | ||||
CASE(RoleModerator, "moderator"); | CASE(RoleModerator, "moderator"); | ||||
CASE(RoleInvalid, "invalid"); | CASE(RoleInvalid, "invalid"); | ||||
default: | default: | ||||
LOGERROR("Unknown role type '%d'", (int)r); | LOGERROR("Unknown role type '%d'", static_cast<int>(role)); | ||||
break; | return ""; | ||||
#undef CASE | #undef CASE | ||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* Translates a gloox certificate error codes, i.e. gloox certificate statuses except CertOk. | * Translates a gloox certificate error codes, i.e. gloox certificate statuses except CertOk. | ||||
* Keep in sync with specifications. | * Keep in sync with specifications. | ||||
*/ | */ | ||||
std::string XmppClient::CertificateErrorToString(gloox::CertStatus status) const | std::string XmppClient::CertificateErrorToString(gloox::CertStatus status) | ||||
{ | { | ||||
std::map<gloox::CertStatus, std::string> certificateErrorStrings = { | std::map<gloox::CertStatus, std::string> certificateErrorStrings = { | ||||
{ gloox::CertInvalid, g_L10n.Translate("The certificate is not trusted.") }, | { gloox::CertInvalid, g_L10n.Translate("The certificate is not trusted.") }, | ||||
{ gloox::CertSignerUnknown, g_L10n.Translate("The certificate hasn't got a known issuer.") }, | { gloox::CertSignerUnknown, g_L10n.Translate("The certificate hasn't got a known issuer.") }, | ||||
{ gloox::CertRevoked, g_L10n.Translate("The certificate has been revoked.") }, | { gloox::CertRevoked, g_L10n.Translate("The certificate has been revoked.") }, | ||||
{ gloox::CertExpired, g_L10n.Translate("The certificate has expired.") }, | { gloox::CertExpired, g_L10n.Translate("The certificate has expired.") }, | ||||
{ gloox::CertNotActive, g_L10n.Translate("The certifiacte is not yet active.") }, | { gloox::CertNotActive, g_L10n.Translate("The certifiacte is not yet active.") }, | ||||
{ gloox::CertWrongPeer, g_L10n.Translate("The certificate has not been issued for the peer connected to.") }, | { gloox::CertWrongPeer, g_L10n.Translate("The certificate has not been issued for the peer connected to.") }, | ||||
Show All 11 Lines | |||||
/** | /** | ||||
* Convert a gloox stanza error type to string. | * Convert a gloox stanza error type to string. | ||||
* Keep in sync with Gloox documentation | * Keep in sync with Gloox documentation | ||||
* | * | ||||
* @param err Error to be converted | * @param err Error to be converted | ||||
* @return Converted error string | * @return Converted error string | ||||
*/ | */ | ||||
std::string XmppClient::StanzaErrorToString(gloox::StanzaError err) const | std::string XmppClient::StanzaErrorToString(gloox::StanzaError err) | ||||
{ | { | ||||
#define CASE(X, Y) case gloox::X: return Y | #define CASE(X, Y) case gloox::X: return Y | ||||
#define DEBUG_CASE(X, Y) case gloox::X: return g_L10n.Translate("Error") + " (" + Y + ")" | #define DEBUG_CASE(X, Y) case gloox::X: return g_L10n.Translate("Error") + " (" + Y + ")" | ||||
switch (err) | switch (err) | ||||
{ | { | ||||
CASE(StanzaErrorUndefined, g_L10n.Translate("No error")); | CASE(StanzaErrorUndefined, g_L10n.Translate("No error")); | ||||
DEBUG_CASE(StanzaErrorBadRequest, "Server received malformed XML"); | DEBUG_CASE(StanzaErrorBadRequest, "Server received malformed XML"); | ||||
CASE(StanzaErrorConflict, g_L10n.Translate("Player already logged in")); | CASE(StanzaErrorConflict, g_L10n.Translate("Player already logged in")); | ||||
Show All 27 Lines | |||||
/** | /** | ||||
* Convert a gloox connection error enum to string | * Convert a gloox connection error enum to string | ||||
* Keep in sync with Gloox documentation | * Keep in sync with Gloox documentation | ||||
* | * | ||||
* @param err Error to be converted | * @param err Error to be converted | ||||
* @return Converted error string | * @return Converted error string | ||||
*/ | */ | ||||
std::string XmppClient::ConnectionErrorToString(gloox::ConnectionError err) const | std::string XmppClient::ConnectionErrorToString(gloox::ConnectionError err) | ||||
{ | { | ||||
#define CASE(X, Y) case gloox::X: return Y | #define CASE(X, Y) case gloox::X: return Y | ||||
#define DEBUG_CASE(X, Y) case gloox::X: return g_L10n.Translate("Error") + " (" + Y + ")" | #define DEBUG_CASE(X, Y) case gloox::X: return g_L10n.Translate("Error") + " (" + Y + ")" | ||||
switch (err) | switch (err) | ||||
{ | { | ||||
CASE(ConnNoError, g_L10n.Translate("No error")); | CASE(ConnNoError, g_L10n.Translate("No error")); | ||||
CASE(ConnStreamError, g_L10n.Translate("Stream error")); | CASE(ConnStreamError, g_L10n.Translate("Stream error")); | ||||
CASE(ConnStreamVersionError, g_L10n.Translate("The incoming stream version is unsupported")); | CASE(ConnStreamVersionError, g_L10n.Translate("The incoming stream version is unsupported")); | ||||
Show All 22 Lines | |||||
/** | /** | ||||
* Convert a gloox registration result enum to string | * Convert a gloox registration result enum to string | ||||
* Keep in sync with Gloox documentation | * Keep in sync with Gloox documentation | ||||
* | * | ||||
* @param err Enum to be converted | * @param err Enum to be converted | ||||
* @return Converted string | * @return Converted string | ||||
*/ | */ | ||||
std::string XmppClient::RegistrationResultToString(gloox::RegistrationResult res) const | std::string XmppClient::RegistrationResultToString(gloox::RegistrationResult res) | ||||
{ | { | ||||
#define CASE(X, Y) case gloox::X: return Y | #define CASE(X, Y) case gloox::X: return Y | ||||
#define DEBUG_CASE(X, Y) case gloox::X: return g_L10n.Translate("Error") + " (" + Y + ")" | #define DEBUG_CASE(X, Y) case gloox::X: return g_L10n.Translate("Error") + " (" + Y + ")" | ||||
switch (res) | switch (res) | ||||
{ | { | ||||
CASE(RegistrationSuccess, g_L10n.Translate("Your account has been successfully registered")); | CASE(RegistrationSuccess, g_L10n.Translate("Your account has been successfully registered")); | ||||
CASE(RegistrationNotAcceptable, g_L10n.Translate("Not all necessary information provided")); | CASE(RegistrationNotAcceptable, g_L10n.Translate("Not all necessary information provided")); | ||||
CASE(RegistrationConflict, g_L10n.Translate("Username already exists")); | CASE(RegistrationConflict, g_L10n.Translate("Username already exists")); | ||||
▲ Show 20 Lines • Show All 49 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator
Intended ?