/* Copyright (C) 2025 Wildfire Games. * This file is part of 0 A.D. * * 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 * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * 0 A.D. is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 0 A.D. If not, see . */ #ifndef XXXMPPCLIENT_H #define XXXMPPCLIENT_H #include "IXmppClient.h" #include "lib/external_libraries/gloox.h" #include #include #include #include class ScriptRequest; class XmppClient : public IXmppClient, public gloox::ConnectionListener, public gloox::MUCRoomHandler, public gloox::IqHandler, public gloox::RegistrationHandler, public gloox::MessageHandler, public gloox::Jingle::SessionHandler, public gloox::LogHandler { NONCOPYABLE(XmppClient); private: // Components gloox::Client* m_client; gloox::MUCRoom* m_mucRoom; gloox::Registration* m_registration; gloox::Jingle::SessionManager* m_sessionManager; // Account infos std::string m_username; std::string m_password; std::string m_server; std::string m_room; std::string m_nick; std::string m_xpartamuppId; std::string m_echelonId; // Security std::string m_connectionDataJid; std::string m_connectionDataIqId; // State gloox::CertStatus m_certStatus; bool m_initialLoadComplete; bool m_isConnected; bool m_regOpt; public: // Basic XmppClient(const ScriptInterface* scriptInterface, const std::string& sUsername, const std::string& sPassword, const std::string& sRoom, const std::string& sNick, const int historyRequestSize = 0, const bool regOpt = false); virtual ~XmppClient(); // JS::Heap is better for GC performance than JS::PersistentRooted static void Trace(JSTracer *trc, void *data) { static_cast(data)->TraceMember(trc); } void TraceMember(JSTracer *trc); // Network void connect() override; void disconnect() override; bool isConnected() override; void recv() override; void SendIqGetBoardList() override; void SendIqGetProfile(const std::string& player) override; void SendIqGameReport(const ScriptRequest& rq, JS::HandleValue data) override; void SendIqRegisterGame(const ScriptRequest& rq, JS::HandleValue data) override; void SendIqGetConnectionData(const std::string& jid, const std::string& password, const std::string& clientSalt, bool localIP) override; void SendIqUnregisterGame() override; void SendIqChangeStateGame(const std::string& nbp, const std::string& players) override; void SendIqLobbyAuth(const std::string& to, const std::string& token) override; void SetNick(const std::string& nick) override; std::string GetNick() const override; std::string GetJID() const override; std::string GetUsername() const override; void ChangePassword(const std::string& newPassword) override; void kick(const std::string& nick, const std::string& reason) override; void ban(const std::string& nick, const std::string& reason) override; void SetPresence(const std::string& presence) override; const char* GetPresence(const std::string& nickname) override; const char* GetRole(const std::string& nickname) override; std::wstring GetRating(const std::string& nickname) override; const std::wstring& GetSubject() override; JS::Value GUIGetPlayerList(const ScriptRequest& rq) override; JS::Value GUIGetGameList(const ScriptRequest& rq) override; JS::Value GUIGetBoardList(const ScriptRequest& rq) override; JS::Value GUIGetProfile(const ScriptRequest& rq) override; void SendStunEndpointToHost(const std::string& ip, u16 port, const std::string& hostJID) override; /** * Convert gloox values to string or time. */ static const char* GetPresenceString(const gloox::Presence::PresenceType presenceType); static const char* GetRoleString(const gloox::MUCRoomRole role); static std::string StanzaErrorToString(gloox::StanzaError err); static std::string RegistrationResultToString(gloox::RegistrationResult res); static std::string ConnectionErrorToString(gloox::ConnectionError err); static std::string CertificateErrorToString(gloox::CertStatus status); static std::time_t ComputeTimestamp(const gloox::Message& msg); protected: /* Xmpp handlers */ /* MUC handlers */ void handleMUCParticipantPresence(gloox::MUCRoom* room, gloox::MUCRoomParticipant, const gloox::Presence&) override; void handleMUCError(gloox::MUCRoom* room, gloox::StanzaError) override; void handleMUCMessage(gloox::MUCRoom* room, const gloox::Message& msg, bool priv) override; void handleMUCSubject(gloox::MUCRoom* room, const std::string& nick, const std::string& subject) override; // Currently unused, provide noop implemtation for pure virtual functions. bool handleMUCRoomCreation(gloox::MUCRoom*) override { return false; } void handleMUCInviteDecline(gloox::MUCRoom*, const gloox::JID&, const std::string&) override {} void handleMUCInfo(gloox::MUCRoom*, int, const std::string&, const gloox::DataForm*) override {} void handleMUCItems(gloox::MUCRoom*, const std::list >&) override {} /* Log handler */ void handleLog(gloox::LogLevel level, gloox::LogArea area, const std::string& message) override; /* ConnectionListener handlers*/ void onConnect() override; void onDisconnect(gloox::ConnectionError e) override; bool onTLSConnect(const gloox::CertInfo& info) override; /* Iq Handlers */ bool handleIq(const gloox::IQ& iq) override; void handleIqID(const gloox::IQ&, int) override {} /* Registration Handlers */ void handleRegistrationFields(const gloox::JID& /*from*/, int fields, std::string instructions ) override; #if GLOOXVERSION >= 0x010100 void handleRegistrationResult(const gloox::JID& /*from*/, gloox::RegistrationResult result, const gloox::Error* /*error*/) override; #else void handleRegistrationResult(const gloox::JID& /*from*/, gloox::RegistrationResult result) override; #endif void handleAlreadyRegistered(const gloox::JID& /*from*/) override; void handleDataForm(const gloox::JID& /*from*/, const gloox::DataForm& /*form*/) override; void handleOOB(const gloox::JID& /*from*/, const gloox::OOB& oob) override; /* Message Handler */ void handleMessage(const gloox::Message& msg, gloox::MessageSession* session) override; /* Session Handler */ void handleSessionAction(gloox::Jingle::Action action, gloox::Jingle::Session* session, const gloox::Jingle::Session::Jingle* jingle) override; void handleSessionActionError(gloox::Jingle::Action /*action*/, gloox::Jingle::Session* /*session*/, const gloox::Error* /*error*/) override {} void handleIncomingSession(gloox::Jingle::Session* /*session*/) override {} private: void handleSessionInitiation(gloox::Jingle::Session* session, const gloox::Jingle::Session::Jingle* jingle); public: JS::Value GuiPollNewMessages(const ScriptInterface& guiInterface) override; JS::Value GuiPollHistoricMessages(const ScriptInterface& guiInterface) override; bool GuiPollHasPlayerListUpdate() override; void SendMUCMessage(const std::string& message) override; protected: template void CreateGUIMessage( const std::string& type, const std::string& level, const std::time_t time, Args const&... args); private: struct SPlayer { SPlayer(const gloox::Presence::PresenceType presence, const gloox::MUCRoomRole role, const std::string& rating) : m_Presence(presence), m_Role(role), m_Rating(rating) { } gloox::Presence::PresenceType m_Presence; gloox::MUCRoomRole m_Role; std::string m_Rating; }; using PlayerMap = std::map; /// Map of players PlayerMap m_PlayerMap; /// Whether or not the playermap has changed since the last time the GUI checked. bool m_PlayerMapUpdate; /// List of games std::vector m_GameList; /// List of rankings std::vector m_BoardList; /// Profile data std::vector m_Profile; /// ScriptInterface to root the values const ScriptInterface* m_ScriptInterface; /// Queue of messages for the GUI std::deque > m_GuiMessageQueue; /// Cache of all GUI messages received since the login std::vector > m_HistoricGuiMessages; /// Current room subject/topic. std::wstring m_Subject; }; #endif // XMPPCLIENT_H