From 4f9457bdd83a2794e72f93567b0847ab244b7d7f Mon Sep 17 00:00:00 2001 From: HanzZ Date: Sat, 9 Feb 2013 11:09:38 +0100 Subject: [PATCH] Added testing swiften_raw backend which just changes to/from attributes and forwards unchanged stanzas --- backends/CMakeLists.txt | 1 + include/transport/conversation.h | 2 + include/transport/localbuddy.h | 2 + include/transport/networkplugin.h | 8 +- include/transport/networkpluginserver.h | 21 +++- include/transport/protocol.proto | 1 + include/transport/transport.h | 10 +- include/transport/user.h | 1 + plugin/cpp/networkplugin.cpp | 10 ++ src/buddy.cpp | 8 +- src/config.cpp | 1 + src/conversation.cpp | 83 +++++++------ src/networkpluginserver.cpp | 156 ++++++++++++++++++++++++ src/tests/networkpluginserver.cpp | 12 ++ src/transport.cpp | 29 +++++ src/user.cpp | 3 + 16 files changed, 307 insertions(+), 41 deletions(-) diff --git a/backends/CMakeLists.txt b/backends/CMakeLists.txt index 6bb81a77..6dcfb900 100644 --- a/backends/CMakeLists.txt +++ b/backends/CMakeLists.txt @@ -9,6 +9,7 @@ if (PROTOBUF_FOUND) if (ENABLE_SWIFTEN) ADD_SUBDIRECTORY(swiften) + ADD_SUBDIRECTORY(swiften_raw) endif() ADD_SUBDIRECTORY(template) diff --git a/include/transport/conversation.h b/include/transport/conversation.h index cda549cb..78aa5266 100644 --- a/include/transport/conversation.h +++ b/include/transport/conversation.h @@ -70,6 +70,8 @@ class Conversation { /// \param nickname For MUC conversation this is nickname of room participant who sent this message. void handleMessage(boost::shared_ptr &message, const std::string &nickname = ""); + void handleRawMessage(boost::shared_ptr &message); + /// Handles participant change in MUC. /// \param nickname Nickname of participant which changed. diff --git a/include/transport/localbuddy.h b/include/transport/localbuddy.h index 5e80fb10..69c5c153 100644 --- a/include/transport/localbuddy.h +++ b/include/transport/localbuddy.h @@ -65,6 +65,8 @@ class LocalBuddy : public Buddy { std::string m_statusMessage; std::string m_iconHash; Swift::StatusShow m_status; + + friend class NetworkPluginServer; }; } diff --git a/include/transport/networkplugin.h b/include/transport/networkplugin.h index 279a3c5d..7afe3358 100644 --- a/include/transport/networkplugin.h +++ b/include/transport/networkplugin.h @@ -39,18 +39,20 @@ class NetworkPlugin { class PluginConfig { public: - PluginConfig() : m_needPassword(true), m_needRegistration(false), m_supportMUC(false) {} + PluginConfig() : m_needPassword(true), m_needRegistration(false), m_supportMUC(false), m_rawXML(false) {} virtual ~PluginConfig() {} void setNeedRegistration(bool needRegistration = false) { m_needRegistration = needRegistration; } void setNeedPassword(bool needPassword = true) { m_needPassword = needPassword; } void setSupportMUC(bool supportMUC = true) { m_supportMUC = supportMUC; } void setExtraFields(const std::vector &fields) { m_extraFields = fields; } + void setRawXML(bool rawXML = false) { m_rawXML = rawXML; } private: bool m_needPassword; bool m_needRegistration; bool m_supportMUC; + bool m_rawXML; std::vector m_extraFields; friend class NetworkPlugin; @@ -67,6 +69,8 @@ class NetworkPlugin { void sendConfig(const PluginConfig &cfg); + void sendRawXML(std::string &xml); + /// Call this function when legacy network buddy changed. /// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld") /// \param buddyName Name of legacy network buddy. (eg. "user2@gmail.com") @@ -245,6 +249,8 @@ class NetworkPlugin { virtual void handleFTPauseRequest(unsigned long ftID) {} virtual void handleFTContinueRequest(unsigned long ftID) {} + virtual void handleRawXML(const std::string &xml) {} + virtual void handleMemoryUsage(double &res, double &shared) {res = 0; shared = 0;} virtual void handleExitRequest() { exit(1); } diff --git a/include/transport/networkpluginserver.h b/include/transport/networkpluginserver.h index 2aea0fc9..44a20b26 100644 --- a/include/transport/networkpluginserver.h +++ b/include/transport/networkpluginserver.h @@ -28,6 +28,11 @@ #include "Swiften/Elements/ChatState.h" #include "Swiften/Elements/RosterItemPayload.h" #include "Swiften/Elements/VCard.h" +#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h" +#include "Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h" +#include "Swiften/Parser/XMPPParser.h" +#include "Swiften/Parser/XMPPParserClient.h" +#include "Swiften/Serializer/XMPPSerializer.h" #include "storagebackend.h" #include "transport/filetransfermanager.h" @@ -47,7 +52,7 @@ class DummyReadBytestream; class AdminInterface; class DiscoItemsResponder; -class NetworkPluginServer { +class NetworkPluginServer : Swift::XMPPParserClient { public: struct Backend { int pongReceived; @@ -116,6 +121,7 @@ class NetworkPluginServer { void handleQueryPayload(Backend *b, const std::string &payload); void handleBackendConfigPayload(const std::string &payload); void handleRoomListPayload(const std::string &payload); + void handleRawXML(const std::string &xml); void handleUserCreated(User *user); void handleRoomJoined(User *user, const Swift::JID &who, const std::string &room, const std::string &nickname, const std::string &password); @@ -149,6 +155,14 @@ class NetworkPluginServer { Backend *getFreeClient(bool acceptUsers = true, bool longRun = false, bool check = false); void connectWaitingUsers(); void loginDelayFinished(); + void handleRawIQReceived(boost::shared_ptr iq); + void handleRawPresenceReceived(boost::shared_ptr presence); + + void handleStreamStart(const Swift::ProtocolHeader&) {} + + void handleElement(boost::shared_ptr element); + + void handleStreamEnd() {} UserManager *m_userManager; VCardResponder *m_vcardResponder; @@ -171,6 +185,11 @@ class NetworkPluginServer { bool m_startingBackend; DiscoItemsResponder *m_discoItemsResponder; time_t m_lastLogin; + Swift::XMPPParser *m_xmppParser; + Swift::FullPayloadParserFactoryCollection m_collection; + Swift::XMPPSerializer *m_serializer; + Swift::FullPayloadSerializerCollection m_collection2; + std::map m_id2resource; }; } diff --git a/include/transport/protocol.proto b/include/transport/protocol.proto index 796b656c..4a5b8f00 100644 --- a/include/transport/protocol.proto +++ b/include/transport/protocol.proto @@ -180,6 +180,7 @@ message WrapperMessage { TYPE_QUERY = 31; TYPE_ROOM_LIST = 32; TYPE_CONV_MESSAGE_ACK = 33; + TYPE_RAW_XML = 34; } required Type type = 1; optional bytes payload = 2; diff --git a/include/transport/transport.h b/include/transport/transport.h index b27ddd37..51f69018 100644 --- a/include/transport/transport.h +++ b/include/transport/transport.h @@ -30,9 +30,11 @@ #include "Swiften/Network/BoostIOServiceThread.h" #include "Swiften/Server/UserRegistry.h" #include "Swiften/Base/SafeByteArray.h" +#include "Swiften/Queries/IQHandler.h" #include "Swiften/Jingle/JingleSessionManager.h" #include "Swiften/Component/ComponentError.h" #include "Swiften/Component/Component.h" +#include "Swiften/Queries/IQHandler.h" #include #include "transport/config.h" @@ -52,7 +54,7 @@ namespace Transport { /// /// In server mode it represents Jabber server to which users can connect and use /// it as transport. - class Component { + class Component : Swift::IQHandler { public: /// Creates new Component instance. @@ -151,6 +153,8 @@ namespace Transport { /// \param info disco#info with response. boost::signal info)> onUserDiscoInfoReceived; + boost::signal)> onRawIQReceived; + private: void handleConnected(); void handleConnectionError(const Swift::ComponentError &error); @@ -162,6 +166,9 @@ namespace Transport { void handleDiscoInfoResponse(boost::shared_ptr info, Swift::ErrorPayload::ref error, const Swift::JID& jid); void handleCapsChanged(const Swift::JID& jid); + void handleBackendConfigChanged(); + bool handleIQ(boost::shared_ptr); + Swift::NetworkFactories *m_factories; Swift::Component *m_component; Swift::Server *m_server; @@ -181,6 +188,7 @@ namespace Transport { Swift::JID m_jid; Factory *m_factory; Swift::EventLoop *m_loop; + bool m_rawXML; friend class User; friend class UserRegistration; diff --git a/include/transport/user.h b/include/transport/user.h index 580fda41..ad259142 100644 --- a/include/transport/user.h +++ b/include/transport/user.h @@ -133,6 +133,7 @@ class User : public Swift::EntityCapsProvider { boost::signal onReadyToConnect; boost::signal onPresenceChanged; + boost::signal onRawPresenceReceived; boost::signal onRoomJoined; boost::signal onRoomLeft; boost::signal onDisconnected; diff --git a/plugin/cpp/networkplugin.cpp b/plugin/cpp/networkplugin.cpp index 45e39e99..fb660b1f 100644 --- a/plugin/cpp/networkplugin.cpp +++ b/plugin/cpp/networkplugin.cpp @@ -73,6 +73,7 @@ void NetworkPlugin::sendConfig(const PluginConfig &cfg) { data += "[features]\n"; data += std::string("muc=") + (cfg.m_supportMUC ? "1" : "0") + "\n"; + data += std::string("rawxml=") + (cfg.m_rawXML ? "1" : "0") + "\n"; pbnetwork::BackendConfig m; m.set_config(data); @@ -85,6 +86,12 @@ void NetworkPlugin::sendConfig(const PluginConfig &cfg) { send(message); } +void NetworkPlugin::sendRawXML(std::string &xml) { + WRAP(xml, pbnetwork::WrapperMessage_Type_TYPE_RAW_XML); + + send(xml); +} + void NetworkPlugin::handleMessage(const std::string &user, const std::string &legacyName, const std::string &msg, const std::string &nickname, const std::string &xhtml, const std::string ×tamp, bool headline, bool pm) { pbnetwork::ConversationMessage m; m.set_username(user); @@ -647,6 +654,9 @@ void NetworkPlugin::handleDataRead(std::string &data) { case pbnetwork::WrapperMessage_Type_TYPE_EXIT: handleExitRequest(); break; + case pbnetwork::WrapperMessage_Type_TYPE_RAW_XML: + handleRawXML(wrapper.payload()); + break; default: return; } diff --git a/src/buddy.cpp b/src/buddy.cpp index 300053cf..4c112052 100644 --- a/src/buddy.cpp +++ b/src/buddy.cpp @@ -103,15 +103,19 @@ Swift::Presence::ref Buddy::generatePresenceStanza(int features, bool only_new) } Swift::Presence::ref presence = Swift::Presence::create(); - presence->setFrom(m_jid); presence->setTo(m_rosterManager->getUser()->getJID().toBare()); presence->setType(Swift::Presence::Available); if (!statusMessage.empty()) presence->setStatus(statusMessage); - if (s.getType() == Swift::StatusShow::None) + if (s.getType() == Swift::StatusShow::None) { presence->setType(Swift::Presence::Unavailable); + presence->setFrom(Swift::JID(m_jid.getNode(), m_jid.getDomain())); + } + else { + presence->setFrom(m_jid); + } presence->setShow(s.getType()); if (presence->getType() != Swift::Presence::Unavailable) { diff --git a/src/config.cpp b/src/config.cpp index 1a5902e4..f1a476ae 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -315,6 +315,7 @@ void Config::updateBackendConfig(const std::string &backendConfig) { ("registration.extraField", value >()->multitoken(), "") ("features.receipts", value()->default_value(false), "") ("features.muc", value()->default_value(false), "") + ("features.rawxml", value()->default_value(false), "") ; std::stringstream ifs(backendConfig); diff --git a/src/conversation.cpp b/src/conversation.cpp index 4073d8e6..7f4fe73c 100644 --- a/src/conversation.cpp +++ b/src/conversation.cpp @@ -39,6 +39,10 @@ Conversation::Conversation(ConversationManager *conversationManager, const std:: m_muc = isMUC; m_jid = m_conversationManager->getUser()->getJID().toBare(); m_sentInitialPresence = false; + + if (CONFIG_BOOL_DEFAULTED(conversationManager->getComponent()->getConfig(), "features.rawxml", false)) { + m_sentInitialPresence = true; + } } Conversation::~Conversation() { @@ -82,6 +86,47 @@ void Conversation::setRoom(const std::string &room) { m_legacyName = m_room + "/" + m_legacyName; } +void Conversation::handleRawMessage(boost::shared_ptr &message) { + if (message->getType() != Swift::Message::Groupchat) { + if (m_conversationManager->getComponent()->inServerMode() && m_conversationManager->getUser()->shouldCacheMessages()) { + boost::posix_time::ptime timestamp = boost::posix_time::second_clock::universal_time(); + boost::shared_ptr delay(boost::make_shared()); + delay->setStamp(timestamp); + message->addPayload(delay); + m_cachedMessages.push_back(message); + if (m_cachedMessages.size() > 100) { + m_cachedMessages.pop_front(); + } + } + else { + m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(message); + } + } + else { + if (m_jids.empty()) { + boost::posix_time::ptime timestamp = boost::posix_time::second_clock::universal_time(); + boost::shared_ptr delay(boost::make_shared()); + delay->setStamp(timestamp); + message->addPayload(delay); + m_cachedMessages.push_back(message); + if (m_cachedMessages.size() > 100) { + m_cachedMessages.pop_front(); + } + } + else { + BOOST_FOREACH(const Swift::JID &jid, m_jids) { + message->setTo(jid); + // Subject has to be sent after our own presence (the one with code 110) + if (!message->getSubject().empty() && m_sentInitialPresence == false) { + m_subject = message; + return; + } + m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(message); + } + } + } +} + void Conversation::handleMessage(boost::shared_ptr &message, const std::string &nickname) { if (m_muc) { message->setType(Swift::Message::Groupchat); @@ -137,20 +182,6 @@ void Conversation::handleMessage(boost::shared_ptr &message, con message->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), n)); } } - - if (m_conversationManager->getComponent()->inServerMode() && m_conversationManager->getUser()->shouldCacheMessages()) { - boost::posix_time::ptime timestamp = boost::posix_time::second_clock::universal_time(); - boost::shared_ptr delay(boost::make_shared()); - delay->setStamp(timestamp); - message->addPayload(delay); - m_cachedMessages.push_back(message); - if (m_cachedMessages.size() > 100) { - m_cachedMessages.pop_front(); - } - } - else { - m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(message); - } } else { std::string legacyName = m_legacyName; @@ -164,29 +195,9 @@ void Conversation::handleMessage(boost::shared_ptr &message, con } message->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), n)); - - if (m_jids.empty()) { - boost::posix_time::ptime timestamp = boost::posix_time::second_clock::universal_time(); - boost::shared_ptr delay(boost::make_shared()); - delay->setStamp(timestamp); - message->addPayload(delay); - m_cachedMessages.push_back(message); - if (m_cachedMessages.size() > 100) { - m_cachedMessages.pop_front(); - } - } - else { - BOOST_FOREACH(const Swift::JID &jid, m_jids) { - message->setTo(jid); - // Subject has to be sent after our own presence (the one with code 110) - if (!message->getSubject().empty() && m_sentInitialPresence == false) { - m_subject = message; - return; - } - m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(message); - } - } } + + handleRawMessage(message); } void Conversation::sendParticipants(const Swift::JID &to) { diff --git a/src/networkpluginserver.cpp b/src/networkpluginserver.cpp index 6f50b04f..3b189abb 100644 --- a/src/networkpluginserver.cpp +++ b/src/networkpluginserver.cpp @@ -269,11 +269,16 @@ NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, U m_adminInterface = NULL; m_startingBackend = false; m_lastLogin = 0; + m_xmppParser = new Swift::XMPPParser(this, &m_collection, component->getNetworkFactories()->getXMLParserFactory()); + m_xmppParser->parse(""); + m_serializer = new Swift::XMPPSerializer(&m_collection2, Swift::ClientStreamType); m_discoItemsResponder = discoItemsResponder; m_component->m_factory = new NetworkFactory(this); m_userManager->onUserCreated.connect(boost::bind(&NetworkPluginServer::handleUserCreated, this, _1)); m_userManager->onUserDestroyed.connect(boost::bind(&NetworkPluginServer::handleUserDestroyed, this, _1)); + m_component->onRawIQReceived.connect(boost::bind(&NetworkPluginServer::handleRawIQReceived, this, _1)); + m_pingTimer = component->getNetworkFactories()->getTimerFactory()->createTimer(20000); m_pingTimer->onTick.connect(boost::bind(&NetworkPluginServer::pingTimeout, this)); m_pingTimer->start(); @@ -987,6 +992,133 @@ void NetworkPluginServer::handleRoomListPayload(const std::string &data) { } } +void NetworkPluginServer::handleElement(boost::shared_ptr element) { + boost::shared_ptr stanza = boost::dynamic_pointer_cast(element); + if (!stanza) { + return; + } + + User *user = m_userManager->getUser(stanza->getTo().toBare()); + if (!user) + return; + + Swift::JID originalJID = stanza->getFrom(); + LocalBuddy *buddy = (LocalBuddy *) user->getRosterManager()->getBuddy(stanza->getFrom().toBare()); + if (buddy) { + const Swift::JID &jid = buddy->getJID(); + if (stanza->getFrom().getResource().empty()) { + stanza->setFrom(Swift::JID(jid.getNode(), jid.getDomain())); + } + else { + stanza->setFrom(Swift::JID(jid.getNode(), jid.getDomain(), stanza->getFrom().getResource())); + } + } + else { + std::string name = stanza->getFrom().toBare(); + if (CONFIG_BOOL_DEFAULTED(m_config, "service.jid_escaping", true)) { + name = Swift::JID::getEscapedNode(name); + } + else { + if (name.find_last_of("@") != std::string::npos) { + name.replace(name.find_last_of("@"), 1, "%"); + } + } + if (stanza->getFrom().getResource().empty()) { + stanza->setFrom(Swift::JID(name, m_component->getJID().toString())); + } + else { + stanza->setFrom(Swift::JID(name, m_component->getJID().toString(), stanza->getFrom().getResource())); + } + } + + boost::shared_ptr message = boost::dynamic_pointer_cast(stanza); + if (message) { + NetworkConversation *conv = (NetworkConversation *) user->getConversationManager()->getConversation(originalJID.toBare()); + if (conv) { + conv->handleRawMessage(message); + return; + } + + m_component->getStanzaChannel()->sendMessage(message); + return; + } + + boost::shared_ptr presence = boost::dynamic_pointer_cast(stanza); + if (presence) { + m_component->getStanzaChannel()->sendPresence(presence); + if (buddy) { + buddy->m_statusMessage = presence->getStatus(); + buddy->m_status = Swift::StatusShow(presence->getShow()); + } + + return; + } + + boost::shared_ptr iq = boost::dynamic_pointer_cast(stanza); + if (iq) { + if (m_id2resource.find(stanza->getTo().toBare().toString() + stanza->getID()) != m_id2resource.end()) { + iq->setTo(Swift::JID(iq->getTo().getNode(), iq->getTo().getDomain(), m_id2resource[stanza->getTo().toBare().toString() + stanza->getID()])); + m_id2resource.erase(stanza->getTo().toBare().toString() + stanza->getID()); + } + m_component->getIQRouter()->sendIQ(iq); + return; + } +} + +void NetworkPluginServer::handleRawXML(const std::string &xml) { + m_xmppParser->parse(xml); +} + +void NetworkPluginServer::handleRawPresenceReceived(boost::shared_ptr presence) { + User *user = m_userManager->getUser(presence->getFrom().toBare()); + if (!user) + return; + + Backend *c = (Backend *) user->getData(); + if (!c) { + return; + } + + Swift::JID legacyname = Swift::JID(Buddy::JIDToLegacyName(presence->getTo())); + if (!presence->getTo().getResource().empty()) { + presence->setTo(Swift::JID(legacyname.getNode(), legacyname.getDomain(), presence->getTo().getResource())); + } + else { + presence->setTo(Swift::JID(legacyname.getNode(), legacyname.getDomain())); + } + + std::string xml = safeByteArrayToString(m_serializer->serializeElement(presence)); + WRAP(xml, pbnetwork::WrapperMessage_Type_TYPE_RAW_XML); + send(c->connection, xml); +} + +void NetworkPluginServer::handleRawIQReceived(boost::shared_ptr iq) { + User *user = m_userManager->getUser(iq->getFrom().toBare()); + if (!user) + return; + + Backend *c = (Backend *) user->getData(); + if (!c) { + return; + } + + if (iq->getType() == Swift::IQ::Get) { + m_id2resource[iq->getFrom().toBare().toString() + iq->getID()] = iq->getFrom().getResource(); + } + + Swift::JID legacyname = Swift::JID(Buddy::JIDToLegacyName(iq->getTo())); + if (!iq->getTo().getResource().empty()) { + iq->setTo(Swift::JID(legacyname.getNode(), legacyname.getDomain(), iq->getTo().getResource())); + } + else { + iq->setTo(Swift::JID(legacyname.getNode(), legacyname.getDomain())); + } + + std::string xml = safeByteArrayToString(m_serializer->serializeElement(iq)); + WRAP(xml, pbnetwork::WrapperMessage_Type_TYPE_RAW_XML); + send(c->connection, xml); +} + void NetworkPluginServer::handleDataRead(Backend *c, boost::shared_ptr data) { // Append data to buffer c->data.insert(c->data.end(), data->begin(), data->end()); @@ -1098,6 +1230,9 @@ void NetworkPluginServer::handleDataRead(Backend *c, boost::shared_ptronReadyToConnect.connect(boost::bind(&NetworkPluginServer::handleUserReadyToConnect, this, user)); user->onPresenceChanged.connect(boost::bind(&NetworkPluginServer::handleUserPresenceChanged, this, user, _1)); + user->onRawPresenceReceived.connect(boost::bind(&NetworkPluginServer::handleRawPresenceReceived, this, _1)); user->onRoomJoined.connect(boost::bind(&NetworkPluginServer::handleRoomJoined, this, user, _1, _2, _3, _4)); user->onRoomLeft.connect(boost::bind(&NetworkPluginServer::handleRoomLeft, this, user, _1)); @@ -1374,6 +1510,7 @@ void NetworkPluginServer::handleUserDestroyed(User *user) { user->onReadyToConnect.disconnect(boost::bind(&NetworkPluginServer::handleUserReadyToConnect, this, user)); user->onPresenceChanged.disconnect(boost::bind(&NetworkPluginServer::handleUserPresenceChanged, this, user, _1)); + user->onRawPresenceReceived.disconnect(boost::bind(&NetworkPluginServer::handleRawPresenceReceived, this, _1)); user->onRoomJoined.disconnect(boost::bind(&NetworkPluginServer::handleRoomJoined, this, user, _1, _2, _3, _4)); user->onRoomLeft.disconnect(boost::bind(&NetworkPluginServer::handleRoomLeft, this, user, _1)); @@ -1406,6 +1543,25 @@ void NetworkPluginServer::handleUserDestroyed(User *user) { void NetworkPluginServer::handleMessageReceived(NetworkConversation *conv, boost::shared_ptr &msg) { conv->getConversationManager()->getUser()->updateLastActivity(); + + if (CONFIG_BOOL_DEFAULTED(m_config, "features.rawxml", false)) { + Backend *c = (Backend *) conv->getConversationManager()->getUser()->getData(); + if (!c) { + return; + } + Swift::JID legacyname = Swift::JID(Buddy::JIDToLegacyName(msg->getTo())); + if (!msg->getTo().getResource().empty()) { + msg->setTo(Swift::JID(legacyname.getNode(), legacyname.getDomain(), msg->getTo().getResource())); + } + else { + msg->setTo(Swift::JID(legacyname.getNode(), legacyname.getDomain())); + } + std::string xml = safeByteArrayToString(m_serializer->serializeElement(msg)); + WRAP(xml, pbnetwork::WrapperMessage_Type_TYPE_RAW_XML); + send(c->connection, xml); + return; + } + boost::shared_ptr statePayload = msg->getPayload(); if (statePayload) { pbnetwork::WrapperMessage_Type type = pbnetwork::WrapperMessage_Type_TYPE_BUDDY_CHANGED; diff --git a/src/tests/networkpluginserver.cpp b/src/tests/networkpluginserver.cpp index 6d941cd8..3b2fd5f8 100644 --- a/src/tests/networkpluginserver.cpp +++ b/src/tests/networkpluginserver.cpp @@ -53,6 +53,7 @@ class NetworkPluginServerTest : public CPPUNIT_NS :: TestFixture, public BasicTe CPPUNIT_TEST(handleBuddyChangedPayloadUserContactInRoster); CPPUNIT_TEST(handleMessageHeadline); CPPUNIT_TEST(handleConvMessageAckPayload); + CPPUNIT_TEST(handleRawXML); CPPUNIT_TEST(benchmarkHandleBuddyChangedPayload); CPPUNIT_TEST_SUITE_END(); @@ -196,6 +197,17 @@ class NetworkPluginServerTest : public CPPUNIT_NS :: TestFixture, public BasicTe CPPUNIT_ASSERT_EQUAL(0, (int) received.size()); } + void handleRawXML() { + User *user = userManager->getUser("user@localhost"); + + std::string xml = ""; + + serv->handleRawXML(xml); + CPPUNIT_ASSERT_EQUAL(1, (int) received.size()); + CPPUNIT_ASSERT(dynamic_cast(getStanza(received[0]))); + CPPUNIT_ASSERT_EQUAL(std::string("buddy1\\40domain.tld@localhost"), dynamic_cast(getStanza(received[0]))->getFrom().toString()); + } + void handleMessageHeadline() { User *user = userManager->getUser("user@localhost"); diff --git a/src/transport.cpp b/src/transport.cpp index a98f101a..18fc4830 100644 --- a/src/transport.cpp +++ b/src/transport.cpp @@ -52,6 +52,9 @@ #include "Swiften/Parser/PayloadParsers/InvisibleParser.h" #include "Swiften/Serializer/PayloadSerializers/InvisibleSerializer.h" #include "Swiften/Parser/GenericPayloadParserFactory.h" +#include "Swiften/Queries/IQRouter.h" +#include "Swiften/Elements/RosterPayload.h" +#include "Swiften/Elements/InBandRegistrationPayload.h" using namespace Swift; using namespace boost; @@ -67,9 +70,11 @@ Component::Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories, m_server = NULL; m_reconnectCount = 0; m_config = config; + m_config->onBackendConfigUpdated.connect(boost::bind(&Component::handleBackendConfigChanged, this)); m_factory = factory; m_loop = loop; m_userRegistry = userRegistry; + m_rawXML = false; m_jid = Swift::JID(CONFIG_STRING(m_config, "service.jid")); @@ -177,6 +182,30 @@ Component::~Component() { } } +bool Component::handleIQ(boost::shared_ptr iq) { + if (!m_rawXML) { + return false; + } + + if (iq->getPayload() != NULL) { return false; } + if (iq->getPayload() != NULL) { return false; } + if (iq->getPayload() != NULL) { return false; } + + if (iq->getTo().getNode().empty()) { + return false; + } + + onRawIQReceived(iq); + return true; +} + +void Component::handleBackendConfigChanged() { + if (!m_rawXML && CONFIG_BOOL_DEFAULTED(m_config, "features.rawxml", false)) { + m_rawXML = true; + m_iqRouter->addHandler(this); + } +} + Swift::StanzaChannel *Component::getStanzaChannel() { return m_stanzaChannel; } diff --git a/src/user.cpp b/src/user.cpp index 43234bcf..9afab31a 100644 --- a/src/user.cpp +++ b/src/user.cpp @@ -243,6 +243,7 @@ void User::handlePresence(Swift::Presence::ref presence, bool forceJoin) { if (getUserSetting("stay_connected") != "1") { LOG4CXX_INFO(logger, m_jid.toString() << ": Going to left room " << room); + onRawPresenceReceived(presence); onRoomLeft(room); BOOST_FOREACH(Swift::Presence::ref &p, m_joinedRooms) { @@ -284,6 +285,7 @@ void User::handlePresence(Swift::Presence::ref presence, bool forceJoin) { } if (forceJoin) { + onRawPresenceReceived(presence); onRoomJoined(presence->getFrom(), room, presence->getTo().getResource(), password); } return; @@ -311,6 +313,7 @@ void User::handlePresence(Swift::Presence::ref presence, bool forceJoin) { conv->setNickname(presence->getTo().getResource()); conv->addJID(presence->getFrom()); + onRawPresenceReceived(presence); onRoomJoined(presence->getFrom(), room, presence->getTo().getResource(), password); } return;