From e5aab1415d9e89392413aabe38d322a2d396b2f5 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Fri, 22 Feb 2013 09:45:31 +0100 Subject: [PATCH 01/16] Libtransport: Support for bouncer mode in case of rawxml. Support for more resources in Buddy class. --- backends/skype/skypedb.cpp | 44 +++++++++++++++++- backends/skype/skypedb.h | 4 +- include/transport/buddy.h | 8 +++- include/transport/conversation.h | 11 ++++- include/transport/localbuddy.h | 8 ++-- include/transport/transport.h | 4 ++ src/buddy.cpp | 47 +++++++++++++++----- src/conversation.cpp | 19 ++++---- src/localbuddy.cpp | 9 ++++ src/networkpluginserver.cpp | 13 ++++-- src/rostermanager.cpp | 34 +++++++++----- src/tests/basictest.cpp | 3 ++ src/tests/conversationmanager.cpp | 5 +++ src/tests/localbuddy.cpp | 5 +++ src/tests/networkpluginserver.cpp | 74 +++++++++++++++++++++++++++++-- 15 files changed, 240 insertions(+), 48 deletions(-) diff --git a/backends/skype/skypedb.cpp b/backends/skype/skypedb.cpp index 4daf44ee..16c332a7 100644 --- a/backends/skype/skypedb.cpp +++ b/backends/skype/skypedb.cpp @@ -40,6 +40,10 @@ #include "malloc.h" #endif +#include "skypeplugin.h" + +#include "skypeplugin.h" + // Prepare the SQL statement #define PREP_STMT(sql, str) \ if(sqlite3_prepare_v2(db, std::string(str).c_str(), -1, &sql, NULL)) { \ @@ -104,7 +108,7 @@ bool getAvatar(const std::string &db_path, const std::string &name, std::string FINALIZE_STMT(stmt); } else { - LOG4CXX_ERROR(logger, "Can't created prepared statement"); + LOG4CXX_ERROR(logger, "Can't create prepared statement"); LOG4CXX_ERROR(logger, (sqlite3_errmsg(db) == NULL ? "" : sqlite3_errmsg(db))); } sqlite3_close(db); @@ -112,4 +116,42 @@ bool getAvatar(const std::string &db_path, const std::string &name, std::string return ret; } +bool loadBuddies(Transport::NetworkPlugin *np, const std::string &db_path) { + bool ret = false; +// sqlite3 *db; +// LOG4CXX_INFO(logger, "Opening database " << db_path); +// if (sqlite3_open(db_path.c_str(), &db)) { +// sqlite3_close(db); +// LOG4CXX_ERROR(logger, "Can't open database"); +// } +// else { +// sqlite3_stmt *stmt; +// PREP_STMT(stmt, "SELECT avatar_image FROM Contacts WHERE skypename=?"); +// if (stmt) { +// BEGIN(stmt); +// BIND_STR(stmt, name); +// if(sqlite3_step(stmt) == SQLITE_ROW) { +// int size = sqlite3_column_bytes(stmt, 0); +// const void *data = sqlite3_column_blob(stmt, 0); +// photo = std::string((const char *)data + 1, size - 1); +// ret = true; +// } +// else { +// LOG4CXX_ERROR(logger, (sqlite3_errmsg(db) == NULL ? "" : sqlite3_errmsg(db))); +// } +// +// int ret; +// while((ret = sqlite3_step(stmt)) == SQLITE_ROW) { +// } +// FINALIZE_STMT(stmt); +// } +// else { +// LOG4CXX_ERROR(logger, "Can't create prepared statement"); +// LOG4CXX_ERROR(logger, (sqlite3_errmsg(db) == NULL ? "" : sqlite3_errmsg(db))); +// } +// sqlite3_close(db); +// } + return ret; +} + } diff --git a/backends/skype/skypedb.h b/backends/skype/skypedb.h index d0ba9f27..264157ec 100644 --- a/backends/skype/skypedb.h +++ b/backends/skype/skypedb.h @@ -26,8 +26,10 @@ #include #include +class SkypePlugin; + namespace SkypeDB { bool getAvatar(const std::string &db, const std::string &name, std::string &avatar); - + bool loadBuddies(SkypePlugin *np, const std::string &db); } diff --git a/include/transport/buddy.h b/include/transport/buddy.h index 06792dc8..9d47cf6f 100644 --- a/include/transport/buddy.h +++ b/include/transport/buddy.h @@ -80,7 +80,7 @@ class Buddy { /// \param only_new if True, this function returns Presence stanza only if it's different /// than the previously generated one. /// \return Presence stanza or NULL. - Swift::Presence::ref generatePresenceStanza(int features, bool only_new = false); + std::vector &generatePresenceStanzas(int features, bool only_new = false); void setBlocked(bool block) { if (block) @@ -124,6 +124,8 @@ class Buddy { void sendPresence(); + void handleRawPresence(Swift::Presence::ref); + /// Handles VCard from legacy network and forwards it to XMPP user. /// \param id ID used in IQ-result. @@ -157,6 +159,8 @@ class Buddy { /// \return avatar hash or empty string. virtual std::string getIconHash() = 0; + virtual bool isAvailable() = 0; + /// Returns legacy name of buddy from JID. /// \param jid Jabber ID. @@ -167,10 +171,10 @@ class Buddy { protected: void generateJID(); Swift::JID m_jid; + std::vector m_presences; private: long m_id; -// Swift::Presence::ref m_lastPresence; BuddyFlag m_flags; RosterManager *m_rosterManager; Subscription m_subscription; diff --git a/include/transport/conversation.h b/include/transport/conversation.h index 268326b0..ba02f273 100644 --- a/include/transport/conversation.h +++ b/include/transport/conversation.h @@ -72,6 +72,7 @@ class Conversation { void handleMessage(boost::shared_ptr &message, const std::string &nickname = ""); void handleRawMessage(boost::shared_ptr &message); + void handleRawPresence(Swift::Presence::ref presence); /// Handles participant change in MUC. @@ -163,10 +164,16 @@ class Conversation { bool m_muc; Swift::JID m_jid; std::list m_jids; - std::map m_participants; - boost::shared_ptr m_subject; bool m_sentInitialPresence; + + // TODO: Move this to some extra class to cache the most used + // rooms across different accounts. Just now if we have 10 users + // connected to single room, we store all those things 10 times. + // It would be also great to store last 100 messages per room + // every time, so we can get history messages for IRC for example. + boost::shared_ptr m_subject; std::list > m_cachedMessages; + std::map m_participants; }; } diff --git a/include/transport/localbuddy.h b/include/transport/localbuddy.h index 69c5c153..ebe2c945 100644 --- a/include/transport/localbuddy.h +++ b/include/transport/localbuddy.h @@ -39,10 +39,10 @@ class LocalBuddy : public Buddy { std::string getName() { return m_name; } bool setName(const std::string &name); - bool getStatus(Swift::StatusShow &status, std::string &statusMessage) { - status = m_status; - statusMessage = m_statusMessage; - return true; + bool getStatus(Swift::StatusShow &status, std::string &statusMessage); + + bool isAvailable() { + return m_status.getType() != Swift::StatusShow::None; } void setStatus(const Swift::StatusShow &status, const std::string &statusMessage); diff --git a/include/transport/transport.h b/include/transport/transport.h index 51f69018..318ec673 100644 --- a/include/transport/transport.h +++ b/include/transport/transport.h @@ -155,6 +155,10 @@ namespace Transport { boost::signal)> onRawIQReceived; + bool isRawXMLEnabled() { + return m_rawXML; + } + private: void handleConnected(); void handleConnectionError(const Swift::ComponentError &error); diff --git a/src/buddy.cpp b/src/buddy.cpp index fcb6b138..00aea73c 100644 --- a/src/buddy.cpp +++ b/src/buddy.cpp @@ -40,8 +40,8 @@ Buddy::~Buddy() { } void Buddy::sendPresence() { - Swift::Presence::ref presence = generatePresenceStanza(255); - if (presence) { + std::vector &presences = generatePresenceStanzas(255); + BOOST_FOREACH(Swift::Presence::ref presence, presences) { m_rosterManager->getUser()->getComponent()->getStanzaChannel()->sendPresence(presence); } } @@ -89,17 +89,33 @@ Buddy::Subscription Buddy::getSubscription() { return m_subscription; } -Swift::Presence::ref Buddy::generatePresenceStanza(int features, bool only_new) { - std::string alias = getAlias(); - std::string name = getSafeName(); +void Buddy::handleRawPresence(Swift::Presence::ref presence) { + for (std::vector::iterator it = m_presences.begin(); it != m_presences.end(); it++) { + if ((*it)->getFrom() == presence->getFrom()) { + m_presences.erase(it); + break; + } + } + + m_presences.push_back(presence); + m_rosterManager->getUser()->getComponent()->getStanzaChannel()->sendPresence(presence); +} + +std::vector &Buddy::generatePresenceStanzas(int features, bool only_new) { + if (m_jid.getNode().empty()) { + generateJID(); + } Swift::StatusShow s; std::string statusMessage; - if (!getStatus(s, statusMessage)) - return Swift::Presence::ref(); - - if (m_jid.getNode().empty()) { - generateJID(); + if (!getStatus(s, statusMessage)) { + for (std::vector::iterator it = m_presences.begin(); it != m_presences.end(); it++) { + if ((*it)->getFrom() == m_jid) { + m_presences.erase(it); + break; + } + } + return m_presences; } Swift::Presence::ref presence = Swift::Presence::create(); @@ -128,6 +144,15 @@ Swift::Presence::ref Buddy::generatePresenceStanza(int features, bool only_new) } } + BOOST_FOREACH(Swift::Presence::ref &p, m_presences) { + if (p->getFrom() == presence->getFrom()) { + p = presence; + return m_presences; + } + } + + m_presences.push_back(presence); + // if (only_new) { // if (m_lastPresence) // m_lastPresence->setTo(Swift::JID("")); @@ -137,7 +162,7 @@ Swift::Presence::ref Buddy::generatePresenceStanza(int features, bool only_new) // m_lastPresence = presence; // } - return presence; + return m_presences; } std::string Buddy::getSafeName() { diff --git a/src/conversation.cpp b/src/conversation.cpp index 5e8aa3d1..c02396e5 100644 --- a/src/conversation.cpp +++ b/src/conversation.cpp @@ -198,10 +198,9 @@ void Conversation::handleMessage(boost::shared_ptr &message, con } void Conversation::sendParticipants(const Swift::JID &to) { - for (std::map::iterator it = m_participants.begin(); it != m_participants.end(); it++) { - Swift::Presence::ref presence = generatePresence(it->first, it->second.flag, it->second.status, it->second.statusMessage, ""); - presence->setTo(to); - m_conversationManager->getComponent()->getStanzaChannel()->sendPresence(presence); + for (std::map::iterator it = m_participants.begin(); it != m_participants.end(); it++) { + (*it).second->setTo(to); + m_conversationManager->getComponent()->getStanzaChannel()->sendPresence((*it).second); } } @@ -296,6 +295,12 @@ Swift::Presence::ref Conversation::generatePresence(const std::string &nick, int return presence; } +void Conversation::handleRawPresence(Swift::Presence::ref presence) { + // TODO: Detect nickname change. + m_conversationManager->getComponent()->getStanzaChannel()->sendPresence(presence); + m_participants[presence->getFrom().getResource()] = presence; +} + void Conversation::handleParticipantChanged(const std::string &nick, Conversation::ParticipantFlag flag, int status, const std::string &statusMessage, const std::string &newname) { Swift::Presence::ref presence = generatePresence(nick, flag, status, statusMessage, newname); @@ -303,11 +308,7 @@ void Conversation::handleParticipantChanged(const std::string &nick, Conversatio m_participants.erase(nick); } else { - Participant p; - p.flag = flag; - p.status = status; - p.statusMessage = statusMessage; - m_participants[nick] = p; + m_participants[nick] = presence; } diff --git a/src/localbuddy.cpp b/src/localbuddy.cpp index 47fe2b7f..ef695e17 100644 --- a/src/localbuddy.cpp +++ b/src/localbuddy.cpp @@ -102,4 +102,13 @@ void LocalBuddy::setGroups(const std::vector &groups) { } } +bool LocalBuddy::getStatus(Swift::StatusShow &status, std::string &statusMessage) { + if (getRosterManager()->getUser()->getComponent()->isRawXMLEnabled()) { + return false; + } + status = m_status; + statusMessage = m_statusMessage; + return true; +} + } diff --git a/src/networkpluginserver.cpp b/src/networkpluginserver.cpp index 4059d865..9cf79934 100644 --- a/src/networkpluginserver.cpp +++ b/src/networkpluginserver.cpp @@ -1053,10 +1053,17 @@ void NetworkPluginServer::handleElement(boost::shared_ptr elemen 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()); + if (!buddy->isAvailable() && presence->getType() != Swift::Presence::Unavailable) { + buddy->m_status.setType(Swift::StatusShow::Online); + } + buddy->handleRawPresence(presence); + } + else if (conv) { + conv->handleRawPresence(presence); + } + else { + m_component->getStanzaChannel()->sendPresence(presence); } return; diff --git a/src/rostermanager.cpp b/src/rostermanager.cpp index f9c47e77..4074a66f 100644 --- a/src/rostermanager.cpp +++ b/src/rostermanager.cpp @@ -255,9 +255,11 @@ void RosterManager::storeBuddy(Buddy *buddy) { void RosterManager::handleBuddyRosterPushResponse(Swift::ErrorPayload::ref error, Swift::SetRosterRequest::ref request, const std::string &key) { LOG4CXX_INFO(logger, "handleBuddyRosterPushResponse called for buddy " << key); if (m_buddies[key] != NULL) { - Swift::Presence::ref presence = m_buddies[key]->generatePresenceStanza(255); - if (presence && presence->getType() == Swift::Presence::Available) { - m_component->getStanzaChannel()->sendPresence(presence); + if (m_buddies[key]->isAvailable()) { + std::vector &presences = m_buddies[key]->generatePresenceStanzas(255); + BOOST_FOREACH(Swift::Presence::ref &presence, presences) { + m_component->getStanzaChannel()->sendPresence(presence); + } } } else { @@ -440,13 +442,13 @@ void RosterManager::handleSubscription(Swift::Presence::ref presence) { Buddy *buddy = getBuddy(Buddy::JIDToLegacyName(presence->getTo())); if (buddy) { + std::vector &presences = buddy->generatePresenceStanzas(255); switch (presence->getType()) { // buddy is already there, so nothing to do, just answer case Swift::Presence::Subscribe: onBuddyAdded(buddy); response->setType(Swift::Presence::Subscribed); - currentPresence = buddy->generatePresenceStanza(255); - if (currentPresence) { + BOOST_FOREACH(Swift::Presence::ref ¤tPresence, presences) { currentPresence->setTo(presence->getFrom()); m_component->getStanzaChannel()->sendPresence(currentPresence); } @@ -587,8 +589,11 @@ void RosterManager::sendCurrentPresences(const Swift::JID &to) { if (!buddy) { continue; } - Swift::Presence::ref presence = buddy->generatePresenceStanza(255); - if (presence && presence->getType() == Swift::Presence::Available) { + if (!buddy->isAvailable()) { + continue; + } + std::vector &presences = buddy->generatePresenceStanzas(255); + BOOST_FOREACH(Swift::Presence::ref &presence, presences) { presence->setTo(to); m_component->getStanzaChannel()->sendPresence(presence); } @@ -598,8 +603,8 @@ void RosterManager::sendCurrentPresences(const Swift::JID &to) { void RosterManager::sendCurrentPresence(const Swift::JID &from, const Swift::JID &to) { Buddy *buddy = getBuddy(Buddy::JIDToLegacyName(from)); if (buddy) { - Swift::Presence::ref presence = buddy->generatePresenceStanza(255); - if (presence) { + std::vector &presences = buddy->generatePresenceStanzas(255); + BOOST_FOREACH(Swift::Presence::ref &presence, presences) { presence->setTo(to); m_component->getStanzaChannel()->sendPresence(presence); } @@ -619,11 +624,18 @@ void RosterManager::sendUnavailablePresences(const Swift::JID &to) { if (!buddy) { continue; } - Swift::Presence::ref presence = buddy->generatePresenceStanza(255); - if (presence && presence->getType() == Swift::Presence::Available) { + + if (!buddy->isAvailable()) { + continue; + } + + std::vector &presences = buddy->generatePresenceStanzas(255); + BOOST_FOREACH(Swift::Presence::ref &presence, presences) { + Swift::Presence::Type type = presence->getType(); presence->setTo(to); presence->setType(Swift::Presence::Unavailable); m_component->getStanzaChannel()->sendPresence(presence); + presence->setType(type); } } diff --git a/src/tests/basictest.cpp b/src/tests/basictest.cpp index 6f3545f6..f1df8288 100644 --- a/src/tests/basictest.cpp +++ b/src/tests/basictest.cpp @@ -241,6 +241,9 @@ void BasicTest::disconnectUser() { if (user) { user->addUserSetting("stay_connected", "0"); } + else { + return; + } received.clear(); userManager->disconnectUser("user@localhost"); dynamic_cast(factories->getTimerFactory())->setTime(100); diff --git a/src/tests/conversationmanager.cpp b/src/tests/conversationmanager.cpp index b8f2eb4e..36d90a30 100644 --- a/src/tests/conversationmanager.cpp +++ b/src/tests/conversationmanager.cpp @@ -23,6 +23,7 @@ using namespace Transport; class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTest { CPPUNIT_TEST_SUITE(ConversationManagerTest); + CPPUNIT_TEST(conversationSize); CPPUNIT_TEST(handleNormalMessages); CPPUNIT_TEST(handleNormalMessagesHeadline); CPPUNIT_TEST(handleGroupchatMessages); @@ -60,6 +61,10 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe tearMeDown(); } + void conversationSize() { + std::cout << " = " << sizeof(Conversation) << " B"; + } + void handleMessageReceived(TestingConversation *_conv, boost::shared_ptr &_msg) { m_conv = _conv; m_msg = _msg; diff --git a/src/tests/localbuddy.cpp b/src/tests/localbuddy.cpp index 9300c290..9fe00bdc 100644 --- a/src/tests/localbuddy.cpp +++ b/src/tests/localbuddy.cpp @@ -22,6 +22,7 @@ using namespace Transport; class LocalBuddyTest : public CPPUNIT_NS :: TestFixture, public BasicTest { CPPUNIT_TEST_SUITE(LocalBuddyTest); + CPPUNIT_TEST(localBuddySize); CPPUNIT_TEST(createWithInvalidName); CPPUNIT_TEST(buddyFlagsFromJID); CPPUNIT_TEST(JIDToLegacyName); @@ -43,6 +44,10 @@ class LocalBuddyTest : public CPPUNIT_NS :: TestFixture, public BasicTest { tearMeDown(); } + void localBuddySize() { + std::cout << " = " << sizeof(LocalBuddy) << " B"; + } + void createWithInvalidName() { User *user = userManager->getUser("user@localhost"); CPPUNIT_ASSERT(user); diff --git a/src/tests/networkpluginserver.cpp b/src/tests/networkpluginserver.cpp index 3b2fd5f8..067ce32f 100644 --- a/src/tests/networkpluginserver.cpp +++ b/src/tests/networkpluginserver.cpp @@ -56,6 +56,7 @@ class NetworkPluginServerTest : public CPPUNIT_NS :: TestFixture, public BasicTe CPPUNIT_TEST(handleRawXML); CPPUNIT_TEST(benchmarkHandleBuddyChangedPayload); + CPPUNIT_TEST(benchmarkSendUnavailablePresence); CPPUNIT_TEST_SUITE_END(); public: @@ -140,6 +141,49 @@ class NetworkPluginServerTest : public CPPUNIT_NS :: TestFixture, public BasicTe std::cerr << " " << clk.elapsedTime() << " s"; } + void benchmarkSendUnavailablePresence() { + Clock clk; + std::vector lst; + for (int i = 0; i < 1000; i++) { + pbnetwork::Buddy buddy; + buddy.set_username("user@localhost"); + buddy.set_buddyname("buddy" + boost::lexical_cast(i) + "@test"); + buddy.set_status((pbnetwork::StatusType) 5); + + std::string message; + buddy.SerializeToString(&message); + lst.push_back(message); + } + + std::vector lst2; + for (int i = 0; i < 1000; i++) { + pbnetwork::Buddy buddy; + buddy.set_username("user@localhost"); + buddy.set_buddyname("buddy" + boost::lexical_cast(1000+i) + "@test"); + buddy.set_status((pbnetwork::StatusType) 2); + + std::string message; + buddy.SerializeToString(&message); + lst2.push_back(message); + } + + + for (int i = 0; i < 1000; i++) { + serv->handleBuddyChangedPayload(lst[i]); + received.clear(); + } + for (int i = 0; i < 1000; i++) { + serv->handleBuddyChangedPayload(lst2[i]); + received.clear(); + } + + User *user = userManager->getUser("user@localhost"); + clk.start(); + user->getRosterManager()->sendUnavailablePresences("user@localhost"); + clk.end(); + std::cerr << " " << clk.elapsedTime() << " s"; + } + void handleBuddyChangedPayload() { User *user = userManager->getUser("user@localhost"); @@ -198,14 +242,36 @@ class NetworkPluginServerTest : public CPPUNIT_NS :: TestFixture, public BasicTe } void handleRawXML() { + cfg->updateBackendConfig("[features]\nrawxml=1\n"); User *user = userManager->getUser("user@localhost"); + std::vector grp; + grp.push_back("group1"); + LocalBuddy *buddy = new LocalBuddy(user->getRosterManager(), -1, "buddy1@domain.tld", "Buddy 1", grp, BUDDY_JID_ESCAPING); + user->getRosterManager()->setBuddy(buddy); + received.clear(); - std::string xml = ""; - + std::string xml = ""; serv->handleRawXML(xml); - CPPUNIT_ASSERT_EQUAL(1, (int) received.size()); + + std::string xml2 = ""; + serv->handleRawXML(xml2); + + CPPUNIT_ASSERT_EQUAL(2, (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()); + CPPUNIT_ASSERT_EQUAL(std::string("buddy1\\40domain.tld@localhost/res"), dynamic_cast(getStanza(received[0]))->getFrom().toString()); + CPPUNIT_ASSERT(dynamic_cast(getStanza(received[1]))); + CPPUNIT_ASSERT_EQUAL(std::string("buddy1\\40domain.tld@localhost/res2"), dynamic_cast(getStanza(received[1]))->getFrom().toString()); + + received.clear(); + user->getRosterManager()->sendUnavailablePresences("user@localhost"); + + CPPUNIT_ASSERT_EQUAL(3, (int) received.size()); + CPPUNIT_ASSERT(dynamic_cast(getStanza(received[0]))); + CPPUNIT_ASSERT_EQUAL(std::string("buddy1\\40domain.tld@localhost/res"), dynamic_cast(getStanza(received[0]))->getFrom().toString()); + CPPUNIT_ASSERT_EQUAL(Swift::Presence::Unavailable, dynamic_cast(getStanza(received[0]))->getType()); + CPPUNIT_ASSERT(dynamic_cast(getStanza(received[1]))); + CPPUNIT_ASSERT_EQUAL(std::string("buddy1\\40domain.tld@localhost/res2"), dynamic_cast(getStanza(received[1]))->getFrom().toString()); + CPPUNIT_ASSERT_EQUAL(Swift::Presence::Unavailable, dynamic_cast(getStanza(received[1]))->getType()); } void handleMessageHeadline() { From 76530dd7b4a91cf23056cfbcb28dd4659b3fd398 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Fri, 22 Feb 2013 09:59:17 +0100 Subject: [PATCH 02/16] Use wrapped in libpurple --- backends/libpurple/main.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backends/libpurple/main.cpp b/backends/libpurple/main.cpp index e8004dfb..641ec9d2 100644 --- a/backends/libpurple/main.cpp +++ b/backends/libpurple/main.cpp @@ -940,9 +940,8 @@ static void NodeRemoved(PurpleBlistNode *node, void *data) { } static void buddyListSaveNode(PurpleBlistNode *node) { - if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) + if (!PURPLE_BLIST_NODE_IS_BUDDY_WRAPPED(node)) return; - } static void buddyListSaveAccount(PurpleAccount *account) { From 4ea83ffd8b6b2f1b1a229f88ad8a256aaa105a3a Mon Sep 17 00:00:00 2001 From: HanzZ Date: Fri, 22 Feb 2013 10:27:52 +0100 Subject: [PATCH 03/16] Use wrapped in libpurple --- backends/libpurple/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/libpurple/main.cpp b/backends/libpurple/main.cpp index 641ec9d2..7dcf0cb8 100644 --- a/backends/libpurple/main.cpp +++ b/backends/libpurple/main.cpp @@ -948,7 +948,7 @@ static void buddyListSaveAccount(PurpleAccount *account) { } static void buddyListRemoveNode(PurpleBlistNode *node) { - if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) + if (!PURPLE_BLIST_NODE_IS_BUDDY_WRAPPED(node)) return; } From 5c60ead75cf54989d6e8ca61b8632ebee8e6b9d6 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Fri, 22 Feb 2013 11:15:37 +0100 Subject: [PATCH 04/16] handleRawXMLSplit test --- src/tests/networkpluginserver.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/tests/networkpluginserver.cpp b/src/tests/networkpluginserver.cpp index 067ce32f..8690ce35 100644 --- a/src/tests/networkpluginserver.cpp +++ b/src/tests/networkpluginserver.cpp @@ -25,6 +25,7 @@ #include #include #include // for clock() +#include using namespace Transport; @@ -54,6 +55,7 @@ class NetworkPluginServerTest : public CPPUNIT_NS :: TestFixture, public BasicTe CPPUNIT_TEST(handleMessageHeadline); CPPUNIT_TEST(handleConvMessageAckPayload); CPPUNIT_TEST(handleRawXML); + CPPUNIT_TEST(handleRawXMLSplit); CPPUNIT_TEST(benchmarkHandleBuddyChangedPayload); CPPUNIT_TEST(benchmarkSendUnavailablePresence); @@ -301,6 +303,26 @@ class NetworkPluginServerTest : public CPPUNIT_NS :: TestFixture, public BasicTe CPPUNIT_ASSERT(dynamic_cast(getStanza(received[0]))); CPPUNIT_ASSERT_EQUAL(Swift::Message::Headline, dynamic_cast(getStanza(received[0]))->getType()); } + + void handleRawXMLSplit() { + cfg->updateBackendConfig("[features]\nrawxml=1\n"); + User *user = userManager->getUser("user@localhost"); + std::vector grp; + grp.push_back("group1"); + LocalBuddy *buddy = new LocalBuddy(user->getRosterManager(), -1, "buddy1@domain.tld", "Buddy 1", grp, BUDDY_JID_ESCAPING); + user->getRosterManager()->setBuddy(buddy); + received.clear(); + + std::string xml = "handleRawXML(xml); + + std::string xml2 = " to='user@localhost'/>"; + serv->handleRawXML(xml2); + + CPPUNIT_ASSERT_EQUAL(1, (int) received.size()); + CPPUNIT_ASSERT(dynamic_cast(getStanza(received[0]))); + CPPUNIT_ASSERT_EQUAL(std::string("buddy1\\40domain.tld@localhost/res"), dynamic_cast(getStanza(received[0]))->getFrom().toString()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION (NetworkPluginServerTest); From ba9a34731cd3eeec285815716b5206716c3d5742 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Fri, 22 Feb 2013 13:13:05 +0100 Subject: [PATCH 05/16] Working subscriptions with swiften_raw backend --- backends/swiften_raw/main.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/backends/swiften_raw/main.cpp b/backends/swiften_raw/main.cpp index 9f164a81..5a2c1f37 100644 --- a/backends/swiften_raw/main.cpp +++ b/backends/swiften_raw/main.cpp @@ -296,6 +296,8 @@ class SwiftenPlugin : public NetworkPlugin, Swift::XMPPParserClient { client->getPresenceOracle()->onPresenceChange.connect(boost::bind(&SwiftenPlugin::handleSwiftPresenceChanged, this, user, _1)); client->onDataRead.connect(boost::bind(&SwiftenPlugin::handleSwiftenDataRead, this, _1)); client->onDataWritten.connect(boost::bind(&SwiftenPlugin::handleSwiftenDataWritten, this, _1)); + client->getSubscriptionManager()->onPresenceSubscriptionRequest.connect(boost::bind(&SwiftenPlugin::handleSubscriptionRequest, this, user, _1, _2, _3)); + client->getSubscriptionManager()->onPresenceSubscriptionRevoked.connect(boost::bind(&SwiftenPlugin::handleSubscriptionRevoked, this, user, _1, _2)); Swift::ClientOptions opt; opt.allowPLAINWithoutTLS = true; client->connect(opt); @@ -305,6 +307,18 @@ class SwiftenPlugin : public NetworkPlugin, Swift::XMPPParserClient { m_handlers[user] = handler; } + void handleSubscriptionRequest(const std::string &user, const Swift::JID& jid, const std::string& message, Swift::Presence::ref presence) { + handleSwiftPresenceChanged(user, presence); + } + + void handleSubscriptionRevoked(const std::string &user, const Swift::JID& jid, const std::string& message) { + Swift::Presence::ref presence = Swift::Presence::create(); + presence->setTo(user); + presence->setFrom(jid); + presence->setType(Swift::Presence::Unsubscribe); + handleSwiftPresenceChanged(user, presence); + } + void handleLogoutRequest(const std::string &user, const std::string &legacyName) { boost::shared_ptr client = m_users[user]; if (client) { From 6a98ef2a8d6d7a9f68c796947adc666837479c5e Mon Sep 17 00:00:00 2001 From: HanzZ Date: Sat, 23 Feb 2013 10:57:40 +0100 Subject: [PATCH 06/16] Set BOOST_FILESYSTEM_VERSION if compiling with boost > 1.50.0 --- CMakeLists.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6a6ba6f3..ae65cb78 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -97,7 +97,12 @@ else(WIN32) endif() endif(WIN32) -message( STATUS "Found Boost: ${Boost_LIBRARIES}, ${Boost_INCLUDE_DIR}") +message( STATUS "Found Boost: ${Boost_VERSION}, ${Boost_LIBRARIES}, ${Boost_INCLUDE_DIR}") + +if (${Boost_VERSION} GREATER 104999) + message( STATUS "Using BOOST_FILESYSTEM_VERSION=3") + add_definitions(BOOST_FILESYSTEM_VERSION 3) +endif() # FIND POPT if (NOT WIN32) From 551cb09a502f20f552e615cf1858168be5f28bd8 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Sat, 23 Feb 2013 11:06:48 +0100 Subject: [PATCH 07/16] Set BOOST_FILESYSTEM_VERSION if compiling with boost > 1.50.0 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ae65cb78..7b7ae408 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,7 +101,7 @@ message( STATUS "Found Boost: ${Boost_VERSION}, ${Boost_LIBRARIES}, ${Boost_INCL if (${Boost_VERSION} GREATER 104999) message( STATUS "Using BOOST_FILESYSTEM_VERSION=3") - add_definitions(BOOST_FILESYSTEM_VERSION 3) + add_definitions(-DBOOST_FILESYSTEM_VERSION=3) endif() # FIND POPT From f90bf5d3de74a484866bebeb3d87c0accce598fa Mon Sep 17 00:00:00 2001 From: HanzZ Date: Sat, 23 Feb 2013 14:34:50 +0100 Subject: [PATCH 08/16] Twitter: Fix request_token call by forcing https --- backends/twitter/libtwitcurl/twitcurl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/twitter/libtwitcurl/twitcurl.cpp b/backends/twitter/libtwitcurl/twitcurl.cpp index a22b887c..d8682ddf 100644 --- a/backends/twitter/libtwitcurl/twitcurl.cpp +++ b/backends/twitter/libtwitcurl/twitcurl.cpp @@ -28,7 +28,7 @@ m_curlProxyParamsSet( false ), m_curlLoginParamsSet( false ), m_curlCallbackParamsSet( false ), m_eApiFormatType( twitCurlTypes::eTwitCurlApiFormatXml ), -m_eProtocolType( twitCurlTypes::eTwitCurlProtocolHttp ) +m_eProtocolType( twitCurlTypes::eTwitCurlProtocolHttps ) { /* Clear callback buffers */ clearCurlCallbackBuffers(); From 882d7b2f02ffe24df658c2a533367c6c94f562b5 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Sun, 24 Feb 2013 10:31:05 +0100 Subject: [PATCH 09/16] Load skype buddies from database if it's possible --- backends/skype/skype.cpp | 87 ++++++++++++++++++++------------------ backends/skype/skype.h | 1 + backends/skype/skypedb.cpp | 80 +++++++++++++++++++---------------- backends/skype/skypedb.h | 2 +- 4 files changed, 92 insertions(+), 78 deletions(-) diff --git a/backends/skype/skype.cpp b/backends/skype/skype.cpp index 9f054efe..78c1aad3 100644 --- a/backends/skype/skype.cpp +++ b/backends/skype/skype.cpp @@ -20,6 +20,7 @@ #include "skype.h" #include "skypeplugin.h" +#include "skypedb.h" #include "transport/config.h" #include "transport/logging.h" @@ -95,9 +96,9 @@ void Skype::login() { return; } - std::string db_path = createSkypeDirectory(); + m_db = createSkypeDirectory(); - bool spawned = spawnSkype(db_path); + bool spawned = spawnSkype(m_db); if (!spawned) { m_np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, "Error spawning the Skype instance."); return; @@ -229,51 +230,55 @@ bool Skype::loadSkypeBuddies() { } } - std::string friends = send_command("GET AUTH_CONTACTS_PROFILES"); + // Try to load skype buddies from database, if it fails + // fallback to old method. + if (!SkypeDB::loadBuddies(m_np, m_db, m_user, group_map)) { + std::string friends = send_command("GET AUTH_CONTACTS_PROFILES"); - char **full_friends_list = g_strsplit((strchr(friends.c_str(), ' ')+1), ";", 0); - if (full_friends_list && full_friends_list[0]) - { - //in the format of: username;full name;phone;office phone;mobile phone; - // online status;friendly name;voicemail;mood - // (comma-seperated lines, usernames can have comma's) - - for (int i=0; full_friends_list[i] && full_friends_list[i+1] && *full_friends_list[i] != '\0'; i+=8) + char **full_friends_list = g_strsplit((strchr(friends.c_str(), ' ')+1), ";", 0); + if (full_friends_list && full_friends_list[0]) { - std::string buddy = full_friends_list[i]; + //in the format of: username;full name;phone;office phone;mobile phone; + // online status;friendly name;voicemail;mood + // (comma-seperated lines, usernames can have comma's) - if (buddy[0] == ',') { - buddy.erase(buddy.begin()); + for (int i=0; full_friends_list[i] && full_friends_list[i+1] && *full_friends_list[i] != '\0'; i+=8) + { + std::string buddy = full_friends_list[i]; + + if (buddy[0] == ',') { + buddy.erase(buddy.begin()); + } + + if (buddy.rfind(",") != std::string::npos) { + buddy = buddy.substr(buddy.rfind(",")); + } + + if (buddy[0] == ',') { + buddy.erase(buddy.begin()); + } + + LOG4CXX_INFO(logger, "Got buddy " << buddy); + std::string st = full_friends_list[i + 5]; + + pbnetwork::StatusType status = getStatus(st); + + std::string alias = full_friends_list[i + 6]; + + std::string mood_text = ""; + if (full_friends_list[i + 8] && *full_friends_list[i + 8] != '\0' && *full_friends_list[i + 8] != ',') { + mood_text = full_friends_list[i + 8]; + } + + std::vector groups; + if (group_map.find(buddy) != group_map.end()) { + groups.push_back(group_map[buddy]); + } + m_np->handleBuddyChanged(m_user, buddy, alias, groups, status, mood_text); } - - if (buddy.rfind(",") != std::string::npos) { - buddy = buddy.substr(buddy.rfind(",")); - } - - if (buddy[0] == ',') { - buddy.erase(buddy.begin()); - } - - LOG4CXX_INFO(logger, "Got buddy " << buddy); - std::string st = full_friends_list[i + 5]; - - pbnetwork::StatusType status = getStatus(st); - - std::string alias = full_friends_list[i + 6]; - - std::string mood_text = ""; - if (full_friends_list[i + 8] && *full_friends_list[i + 8] != '\0' && *full_friends_list[i + 8] != ',') { - mood_text = full_friends_list[i + 8]; - } - - std::vector groups; - if (group_map.find(buddy) != group_map.end()) { - groups.push_back(group_map[buddy]); - } - m_np->handleBuddyChanged(m_user, buddy, alias, groups, status, mood_text); } + g_strfreev(full_friends_list); } - g_strfreev(full_friends_list); send_command("SET AUTOAWAY OFF"); send_command("SET USERSTATUS ONLINE"); diff --git a/backends/skype/skype.h b/backends/skype/skype.h index 9b321bc5..5230b4d8 100644 --- a/backends/skype/skype.h +++ b/backends/skype/skype.h @@ -87,5 +87,6 @@ class Skype { int fd_output; std::map m_groups; SkypePlugin *m_np; + std::string m_db; }; diff --git a/backends/skype/skypedb.cpp b/backends/skype/skypedb.cpp index 16c332a7..beff1267 100644 --- a/backends/skype/skypedb.cpp +++ b/backends/skype/skypedb.cpp @@ -42,8 +42,6 @@ #include "skypeplugin.h" -#include "skypeplugin.h" - // Prepare the SQL statement #define PREP_STMT(sql, str) \ if(sqlite3_prepare_v2(db, std::string(str).c_str(), -1, &sql, NULL)) { \ @@ -116,41 +114,51 @@ bool getAvatar(const std::string &db_path, const std::string &name, std::string return ret; } -bool loadBuddies(Transport::NetworkPlugin *np, const std::string &db_path) { +bool loadBuddies(SkypePlugin *np, const std::string &db_path, std::string &user, std::map &group_map) { bool ret = false; -// sqlite3 *db; -// LOG4CXX_INFO(logger, "Opening database " << db_path); -// if (sqlite3_open(db_path.c_str(), &db)) { -// sqlite3_close(db); -// LOG4CXX_ERROR(logger, "Can't open database"); -// } -// else { -// sqlite3_stmt *stmt; -// PREP_STMT(stmt, "SELECT avatar_image FROM Contacts WHERE skypename=?"); -// if (stmt) { -// BEGIN(stmt); -// BIND_STR(stmt, name); -// if(sqlite3_step(stmt) == SQLITE_ROW) { -// int size = sqlite3_column_bytes(stmt, 0); -// const void *data = sqlite3_column_blob(stmt, 0); -// photo = std::string((const char *)data + 1, size - 1); -// ret = true; -// } -// else { -// LOG4CXX_ERROR(logger, (sqlite3_errmsg(db) == NULL ? "" : sqlite3_errmsg(db))); -// } -// -// int ret; -// while((ret = sqlite3_step(stmt)) == SQLITE_ROW) { -// } -// FINALIZE_STMT(stmt); -// } -// else { -// LOG4CXX_ERROR(logger, "Can't create prepared statement"); -// LOG4CXX_ERROR(logger, (sqlite3_errmsg(db) == NULL ? "" : sqlite3_errmsg(db))); -// } -// sqlite3_close(db); -// } + sqlite3 *db; + LOG4CXX_INFO(logger, "Opening database " << db_path); + if (sqlite3_open(db_path.c_str(), &db)) { + sqlite3_close(db); + LOG4CXX_ERROR(logger, "Can't open database"); + } + else { + sqlite3_stmt *stmt; + PREP_STMT(stmt, "select skypename, aliases, fullname, displayname, mood_text from Contacts;"); + if (stmt) { + BEGIN(stmt); + int ret2; + while((ret2 = sqlite3_step(stmt)) == SQLITE_ROW) { + std::string buddy = (const char *) sqlite3_column_text(stmt, 0); + std::string alias = (const char *) sqlite3_column_text(stmt, 1); + std::string fullname = (const char *) sqlite3_column_text(stmt, 2); + std::string displayname = (const char *) sqlite3_column_text(stmt, 3); + std::string mood_text = (const char *) sqlite3_column_text(stmt, 4); + + if (alias.empty()) { + alias = displayname; + } + + std::vector groups; + if (group_map.find(buddy) != group_map.end()) { + groups.push_back(group_map[buddy]); + } + np->handleBuddyChanged(user, buddy, alias, groups, pbnetwork::STATUS_NONE, mood_text); + } + if (ret2 != SQLITE_DONE) { + FINALIZE_STMT(stmt); + ret = false; + } + else { + ret = true; + } + } + else { + LOG4CXX_ERROR(logger, "Can't create prepared statement"); + LOG4CXX_ERROR(logger, (sqlite3_errmsg(db) == NULL ? "" : sqlite3_errmsg(db))); + } + sqlite3_close(db); + } return ret; } diff --git a/backends/skype/skypedb.h b/backends/skype/skypedb.h index 264157ec..d3490b00 100644 --- a/backends/skype/skypedb.h +++ b/backends/skype/skypedb.h @@ -30,6 +30,6 @@ class SkypePlugin; namespace SkypeDB { bool getAvatar(const std::string &db, const std::string &name, std::string &avatar); - bool loadBuddies(SkypePlugin *np, const std::string &db); + bool loadBuddies(SkypePlugin *np, const std::string &db, std::string &user, std::map &group_map); } From deaa8e8dca9b2b83c8da85e9cd20f0e561dc6e21 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Sun, 24 Feb 2013 10:50:24 +0100 Subject: [PATCH 10/16] Load skype buddies from database if it's possible --- backends/skype/skype.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/backends/skype/skype.cpp b/backends/skype/skype.cpp index 78c1aad3..95f1390c 100644 --- a/backends/skype/skype.cpp +++ b/backends/skype/skype.cpp @@ -104,6 +104,7 @@ void Skype::login() { return; } + m_db += "/" + getUsername() + "/main.db"; if (m_connection == NULL) { LOG4CXX_INFO(logger, "Creating DBUS connection."); From afba34111e41c6adc045bdd2d93b6661f933f056 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Sun, 24 Feb 2013 11:09:51 +0100 Subject: [PATCH 11/16] Load skype buddies from database if it's possible --- backends/skype/skypedb.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/backends/skype/skypedb.cpp b/backends/skype/skypedb.cpp index beff1267..b333401b 100644 --- a/backends/skype/skypedb.cpp +++ b/backends/skype/skypedb.cpp @@ -124,16 +124,15 @@ bool loadBuddies(SkypePlugin *np, const std::string &db_path, std::string &user, } else { sqlite3_stmt *stmt; - PREP_STMT(stmt, "select skypename, aliases, fullname, displayname, mood_text from Contacts;"); +// aliases, fullname, + PREP_STMT(stmt, "select skypename, displayname, mood_text from Contacts;"); if (stmt) { BEGIN(stmt); int ret2; while((ret2 = sqlite3_step(stmt)) == SQLITE_ROW) { std::string buddy = (const char *) sqlite3_column_text(stmt, 0); std::string alias = (const char *) sqlite3_column_text(stmt, 1); - std::string fullname = (const char *) sqlite3_column_text(stmt, 2); - std::string displayname = (const char *) sqlite3_column_text(stmt, 3); - std::string mood_text = (const char *) sqlite3_column_text(stmt, 4); + std::string mood_text = (const char *) sqlite3_column_text(stmt, 2); if (alias.empty()) { alias = displayname; From 756f0f07b0b017e590132b0ade3e3c3a7fc6be18 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Sun, 24 Feb 2013 11:21:07 +0100 Subject: [PATCH 12/16] Load skype buddies from database if it's possible --- backends/skype/skypedb.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/backends/skype/skypedb.cpp b/backends/skype/skypedb.cpp index b333401b..a44dcf7e 100644 --- a/backends/skype/skypedb.cpp +++ b/backends/skype/skypedb.cpp @@ -134,10 +134,6 @@ bool loadBuddies(SkypePlugin *np, const std::string &db_path, std::string &user, std::string alias = (const char *) sqlite3_column_text(stmt, 1); std::string mood_text = (const char *) sqlite3_column_text(stmt, 2); - if (alias.empty()) { - alias = displayname; - } - std::vector groups; if (group_map.find(buddy) != group_map.end()) { groups.push_back(group_map[buddy]); From b042541d1ce2050b81222f5167d6e5607dd4f70b Mon Sep 17 00:00:00 2001 From: HanzZ Date: Sun, 24 Feb 2013 12:01:44 +0100 Subject: [PATCH 13/16] Skype: Check for null char * --- backends/skype/skypedb.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backends/skype/skypedb.cpp b/backends/skype/skypedb.cpp index a44dcf7e..24500058 100644 --- a/backends/skype/skypedb.cpp +++ b/backends/skype/skypedb.cpp @@ -132,7 +132,8 @@ bool loadBuddies(SkypePlugin *np, const std::string &db_path, std::string &user, while((ret2 = sqlite3_step(stmt)) == SQLITE_ROW) { std::string buddy = (const char *) sqlite3_column_text(stmt, 0); std::string alias = (const char *) sqlite3_column_text(stmt, 1); - std::string mood_text = (const char *) sqlite3_column_text(stmt, 2); + const char *d = (const char *) sqlite3_column_text(stmt, 2); + std::string mood_text = d ? d : ""; std::vector groups; if (group_map.find(buddy) != group_map.end()) { From 95a144a285b9a44a6f905eece9f13717540cbb40 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Mon, 25 Feb 2013 08:02:49 +0100 Subject: [PATCH 14/16] Rename swiften_raw backend to swiften backend, remove old swiften backend --- backends/swiften/main.cpp | 317 ++++++++++---------- backends/swiften_raw/CMakeLists.txt | 14 - backends/swiften_raw/main.cpp | 441 ---------------------------- 3 files changed, 147 insertions(+), 625 deletions(-) delete mode 100644 backends/swiften_raw/CMakeLists.txt delete mode 100644 backends/swiften_raw/main.cpp diff --git a/backends/swiften/main.cpp b/backends/swiften/main.cpp index 3ccc632e..5a2c1f37 100644 --- a/backends/swiften/main.cpp +++ b/backends/swiften/main.cpp @@ -30,6 +30,7 @@ using namespace boost::program_options; using namespace Transport; DEFINE_LOGGER(logger, "Swiften"); +DEFINE_LOGGER(logger_xml, "backend.xml"); // eventloop Swift::SimpleEventLoop *loop_; @@ -37,96 +38,60 @@ Swift::SimpleEventLoop *loop_; // Plugins class SwiftenPlugin; NetworkPlugin *np = NULL; +Swift::XMPPSerializer *serializer; -class MUCController { +class ForwardIQHandler : public Swift::IQHandler { public: - MUCController(const std::string &user, boost::shared_ptr client, const std::string &room, const std::string &nickname, const std::string &password) { + std::map m_id2resource; + + ForwardIQHandler(NetworkPlugin *np, const std::string &user) { + m_np = np; m_user = user; - m_room = room; - muc = client->getMUCManager()->createMUC(room); - if (!password.empty()) { - muc->setPassword(password); + } + + bool handleIQ(boost::shared_ptr iq) { + if (iq->getPayload() != NULL) { + return false; + } + if (iq->getType() == Swift::IQ::Get) { + m_id2resource[iq->getID()] = iq->getFrom().getResource(); } - muc->onJoinComplete.connect(boost::bind(&MUCController::handleJoinComplete, this, _1)); - muc->onJoinFailed.connect(boost::bind(&MUCController::handleJoinFailed, this, _1)); - muc->onOccupantJoined.connect(boost::bind(&MUCController::handleOccupantJoined, this, _1)); - muc->onOccupantPresenceChange.connect(boost::bind(&MUCController::handleOccupantPresenceChange, this, _1)); - muc->onOccupantLeft.connect(boost::bind(&MUCController::handleOccupantLeft, this, _1, _2, _3)); - muc->onOccupantRoleChanged.connect(boost::bind(&MUCController::handleOccupantRoleChanged, this, _1, _2, _3)); - muc->onOccupantAffiliationChanged.connect(boost::bind(&MUCController::handleOccupantAffiliationChanged, this, _1, _2, _3)); - - muc->joinAs(nickname); - } - - virtual ~MUCController() { - muc->onJoinComplete.disconnect(boost::bind(&MUCController::handleJoinComplete, this, _1)); - muc->onJoinFailed.disconnect(boost::bind(&MUCController::handleJoinFailed, this, _1)); - muc->onOccupantJoined.disconnect(boost::bind(&MUCController::handleOccupantJoined, this, _1)); - muc->onOccupantPresenceChange.disconnect(boost::bind(&MUCController::handleOccupantPresenceChange, this, _1)); - muc->onOccupantLeft.disconnect(boost::bind(&MUCController::handleOccupantLeft, this, _1, _2, _3)); - muc->onOccupantRoleChanged.disconnect(boost::bind(&MUCController::handleOccupantRoleChanged, this, _1, _2, _3)); - muc->onOccupantAffiliationChanged.disconnect(boost::bind(&MUCController::handleOccupantAffiliationChanged, this, _1, _2, _3)); - } - - const std::string &getNickname() { - //return muc->getCurrentNick(); - return m_nick; - } - - void handleOccupantJoined(const Swift::MUCOccupant& occupant) { - np->handleParticipantChanged(m_user, occupant.getNick(), m_room, occupant.getRole() == Swift::MUCOccupant::Moderator, pbnetwork::STATUS_ONLINE); - } - - void handleOccupantLeft(const Swift::MUCOccupant& occupant, Swift::MUC::LeavingType type, const std::string& reason) { - np->handleParticipantChanged(m_user, occupant.getNick(), m_room, occupant.getRole() == Swift::MUCOccupant::Moderator, pbnetwork::STATUS_NONE); - } - - void handleOccupantPresenceChange(boost::shared_ptr presence) { - const Swift::MUCOccupant& occupant = muc->getOccupant(presence->getFrom().getResource()); - np->handleParticipantChanged(m_user, presence->getFrom().getResource(), m_room, (int) occupant.getRole() == Swift::MUCOccupant::Moderator, (pbnetwork::StatusType) presence->getShow(), presence->getStatus()); - } - - void handleOccupantRoleChanged(const std::string& nick, const Swift::MUCOccupant& occupant, const Swift::MUCOccupant::Role& oldRole) { - - } - - void handleOccupantAffiliationChanged(const std::string& nick, const Swift::MUCOccupant::Affiliation& affiliation, const Swift::MUCOccupant::Affiliation& oldAffiliation) { -// np->handleParticipantChanged(m_user, occupant->getNick(), m_room, (int) occupant.getRole() == Swift::MUCOccupant::Moderator, pbnetwork::STATUS_ONLINE); - } - - void handleJoinComplete(const std::string& nick) { - m_nick = nick; - } - - void handleJoinFailed(boost::shared_ptr error) { - - } - - void part() { - muc->part(); + iq->setTo(m_user); + std::string xml = safeByteArrayToString(serializer->serializeElement(iq)); + m_np->sendRawXML(xml); + return true; } private: - Swift::MUC::ref muc; + NetworkPlugin *m_np; std::string m_user; - std::string m_room; - std::string m_nick; + }; -class SwiftenPlugin : public NetworkPlugin { +class SwiftenPlugin : public NetworkPlugin, Swift::XMPPParserClient { public: Swift::BoostNetworkFactories *m_factories; Swift::BoostIOServiceThread m_boostIOServiceThread; boost::shared_ptr m_conn; + bool m_firstPing; + + Swift::FullPayloadSerializerCollection collection; + Swift::XMPPParser *m_xmppParser; + Swift::FullPayloadParserFactoryCollection m_collection2; SwiftenPlugin(Config *config, Swift::SimpleEventLoop *loop, const std::string &host, int port) : NetworkPlugin() { this->config = config; + m_firstPing = true; m_factories = new Swift::BoostNetworkFactories(loop); m_conn = m_factories->getConnectionFactory()->createConnection(); m_conn->onDataRead.connect(boost::bind(&SwiftenPlugin::_handleDataRead, this, _1)); m_conn->connect(Swift::HostAddressPort(Swift::HostAddress(host), port)); + serializer = new Swift::XMPPSerializer(&collection, Swift::ClientStreamType); + m_xmppParser = new Swift::XMPPParser(this, &m_collection2, m_factories->getXMLParserFactory()); + m_xmppParser->parse(""); + LOG4CXX_INFO(logger, "Starting the plugin."); } @@ -137,10 +102,61 @@ class SwiftenPlugin : public NetworkPlugin { // This method has to call handleDataRead with all received data from network plugin server void _handleDataRead(boost::shared_ptr data) { + if (m_firstPing) { + m_firstPing = false; + NetworkPlugin::PluginConfig cfg; + cfg.setRawXML(true); + sendConfig(cfg); + } std::string d(data->begin(), data->end()); handleDataRead(d); } + void handleStreamStart(const Swift::ProtocolHeader&) {} + + void handleElement(boost::shared_ptr element) { + boost::shared_ptr stanza = boost::dynamic_pointer_cast(element); + if (!stanza) { + return; + } + + std::string user = stanza->getFrom().toBare(); + + boost::shared_ptr client = m_users[user]; + if (!client) + return; + + stanza->setFrom(client->getJID()); + + boost::shared_ptr message = boost::dynamic_pointer_cast(stanza); + if (message) { + client->sendMessage(message); + return; + } + + boost::shared_ptr presence = boost::dynamic_pointer_cast(stanza); + if (presence) { + client->sendPresence(presence); + return; + } + + boost::shared_ptr iq = boost::dynamic_pointer_cast(stanza); + if (iq) { + if (m_handlers[user]->m_id2resource.find(stanza->getID()) != m_handlers[user]->m_id2resource.end()) { + iq->setTo(Swift::JID(iq->getTo().getNode(), iq->getTo().getDomain(), m_handlers[user]->m_id2resource[stanza->getID()])); + m_handlers[user]->m_id2resource.erase(stanza->getID()); + } + client->getIQRouter()->sendIQ(iq); + return; + } + } + + void handleStreamEnd() {} + + void handleRawXML(const std::string &xml) { + m_xmppParser->parse(xml); + } + void handleSwiftDisconnected(const std::string &user, const boost::optional &error) { std::string message = ""; bool reconnect = false; @@ -186,7 +202,7 @@ class SwiftenPlugin : public NetworkPlugin { client->onDisconnected.disconnect(boost::bind(&SwiftenPlugin::handleSwiftDisconnected, this, user, _1)); client->onMessageReceived.disconnect(boost::bind(&SwiftenPlugin::handleSwiftMessageReceived, this, user, _1)); m_users.erase(user); - m_mucs.erase(user); + m_handlers.erase(user); } #ifndef WIN32 @@ -219,67 +235,53 @@ class SwiftenPlugin : public NetworkPlugin { } void handleSwiftPresenceChanged(const std::string &user, Swift::Presence::ref presence) { - boost::shared_ptr client = m_users[user]; - if (client->getMUCRegistry()->isMUC(presence->getFrom().toBare())) { - return; - } - - if (presence->getPayload() != NULL || presence->getPayload() != NULL) { - return; - } - - LOG4CXX_INFO(logger, user << ": " << presence->getFrom().toBare().toString() << " presence changed"); - - std::string message = presence->getStatus(); - std::string photo = ""; - - boost::shared_ptr update = presence->getPayload(); - if (update) { - photo = update->getPhotoHash(); - } - - boost::optional item = m_users[user]->getRoster()->getItem(presence->getFrom()); - if (item) { - handleBuddyChanged(user, presence->getFrom().toBare().toString(), item->getName(), item->getGroups(), (pbnetwork::StatusType) presence->getShow(), message, photo); - } - else { - std::vector groups; - handleBuddyChanged(user, presence->getFrom().toBare().toString(), presence->getFrom().toBare(), groups, (pbnetwork::StatusType) presence->getShow(), message, photo); - } +// boost::shared_ptr client = m_users[user]; +// if (client->getMUCRegistry()->isMUC(presence->getFrom().toBare())) { +// return; +// } +// +// if (presence->getPayload() != NULL || presence->getPayload() != NULL) { +// return; +// } +// +// LOG4CXX_INFO(logger, user << ": " << presence->getFrom().toBare().toString() << " presence changed"); +// +// std::string message = presence->getStatus(); +// std::string photo = ""; +// +// boost::shared_ptr update = presence->getPayload(); +// if (update) { +// photo = update->getPhotoHash(); +// } +// +// boost::optional item = m_users[user]->getRoster()->getItem(presence->getFrom()); +// if (item) { +// handleBuddyChanged(user, presence->getFrom().toBare().toString(), item->getName(), item->getGroups(), (pbnetwork::StatusType) presence->getShow(), message, photo); +// } +// else { +// std::vector groups; +// handleBuddyChanged(user, presence->getFrom().toBare().toString(), presence->getFrom().toBare(), groups, (pbnetwork::StatusType) presence->getShow(), message, photo); +// } + presence->setTo(user); + std::string xml = safeByteArrayToString(serializer->serializeElement(presence)); + sendRawXML(xml); } void handleSwiftMessageReceived(const std::string &user, Swift::Message::ref message) { - std::string body = message->getBody(); - boost::shared_ptr client = m_users[user]; - if (client) { - if (message->getType() == Swift::Message::Groupchat) { - boost::shared_ptr delay = message->getPayload(); - std::string timestamp = ""; - if (delay) { - timestamp = boost::posix_time::to_iso_string(delay->getStamp()); - } - handleMessage(user, message->getFrom().toBare().toString(), body, message->getFrom().getResource(), "", timestamp); - } - else { - if (client->getMUCRegistry()->isMUC(message->getFrom().toBare())) { - handleMessage(user, message->getFrom().toBare().toString(), body, message->getFrom().getResource(), "", "", false, true); - } - else { - handleMessage(user, message->getFrom().toBare().toString(), body, "", ""); - } - } + message->setTo(user); + std::string xml = safeByteArrayToString(serializer->serializeElement(message)); + sendRawXML(xml); + } + + void handleSwiftenDataRead(const Swift::SafeByteArray &data) { + std::string d = safeByteArrayToString(data); + if (!boost::starts_with(d, "onMessageReceived.connect(boost::bind(&SwiftenPlugin::handleSwiftMessageReceived, this, user, _1)); client->getRoster()->onInitialRosterPopulated.connect(boost::bind(&SwiftenPlugin::handleSwiftRosterReceived, this, user)); client->getPresenceOracle()->onPresenceChange.connect(boost::bind(&SwiftenPlugin::handleSwiftPresenceChanged, this, user, _1)); + client->onDataRead.connect(boost::bind(&SwiftenPlugin::handleSwiftenDataRead, this, _1)); + client->onDataWritten.connect(boost::bind(&SwiftenPlugin::handleSwiftenDataWritten, this, _1)); + client->getSubscriptionManager()->onPresenceSubscriptionRequest.connect(boost::bind(&SwiftenPlugin::handleSubscriptionRequest, this, user, _1, _2, _3)); + client->getSubscriptionManager()->onPresenceSubscriptionRevoked.connect(boost::bind(&SwiftenPlugin::handleSubscriptionRevoked, this, user, _1, _2)); Swift::ClientOptions opt; opt.allowPLAINWithoutTLS = true; client->connect(opt); + + boost::shared_ptr handler = boost::make_shared(this, user); + client->getIQRouter()->addHandler(handler); + m_handlers[user] = handler; + } + + void handleSubscriptionRequest(const std::string &user, const Swift::JID& jid, const std::string& message, Swift::Presence::ref presence) { + handleSwiftPresenceChanged(user, presence); + } + + void handleSubscriptionRevoked(const std::string &user, const Swift::JID& jid, const std::string& message) { + Swift::Presence::ref presence = Swift::Presence::create(); + presence->setTo(user); + presence->setFrom(jid); + presence->setType(Swift::Presence::Unsubscribe); + handleSwiftPresenceChanged(user, presence); } void handleLogoutRequest(const std::string &user, const std::string &legacyName) { @@ -306,43 +328,20 @@ class SwiftenPlugin : public NetworkPlugin { client->getRoster()->onInitialRosterPopulated.disconnect(boost::bind(&SwiftenPlugin::handleSwiftRosterReceived, this, user)); client->getPresenceOracle()->onPresenceChange.disconnect(boost::bind(&SwiftenPlugin::handleSwiftPresenceChanged, this, user, _1)); client->disconnect(); - m_mucs.erase(user); } } void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &msg, const std::string &xhtml = "", const std::string &id = "") { - LOG4CXX_INFO(logger, "Sending message from " << user << " to " << legacyName << "."); - boost::shared_ptr client = m_users[user]; - if (client) { - boost::shared_ptr message(new Swift::Message()); - message->setTo(Swift::JID(legacyName)); - message->setFrom(client->getJID()); - message->setBody(msg); - if (client->getMUCRegistry()->isMUC(legacyName)) { - message->setType(Swift::Message::Groupchat); - boost::shared_ptr muc = m_mucs[user][legacyName]; -// handleMessage(user, legacyName, msg, muc->getNickname(), xhtml); - } - - client->sendMessage(message); - } } void handleVCardRequest(const std::string &user, const std::string &legacyName, unsigned int id) { - boost::shared_ptr client = m_users[user]; - if (client) { - LOG4CXX_INFO(logger, user << ": fetching VCard of " << legacyName << " id=" << id); - Swift::GetVCardRequest::ref request = Swift::GetVCardRequest::create(Swift::JID(legacyName), client->getIQRouter()); - request->onResponse.connect(boost::bind(&SwiftenPlugin::handleSwiftVCardReceived, this, user, id, _1, _2)); - request->send(); - } } void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector &groups) { boost::shared_ptr client = m_users[user]; if (client) { LOG4CXX_INFO(logger, user << ": Added/Updated buddy " << buddyName << "."); - if (!client->getRoster()->containsJID(buddyName)) { + if (!client->getRoster()->containsJID(buddyName) || client->getRoster()->getSubscriptionStateForJID(buddyName) != Swift::RosterItemPayload::Both) { Swift::RosterItemPayload item; item.setName(alias); item.setJID(buddyName); @@ -381,39 +380,17 @@ class SwiftenPlugin : public NetworkPlugin { } void handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &password) { - boost::shared_ptr client = m_users[user]; - if (client) { - if (client->getMUCRegistry()->isMUC(room)) { - return; - } - boost::shared_ptr muc = boost::shared_ptr( new MUCController(user, client, room, nickname, password)); - m_mucs[user][room] = muc; - } } void handleLeaveRoomRequest(const std::string &user, const std::string &room) { - boost::shared_ptr client = m_users[user]; - if (client) { - if (!client->getMUCRegistry()->isMUC(room)) { - return; - } - boost::shared_ptr muc = m_mucs[user][room]; - if (!muc) { - m_mucs[user].erase(room); - return; - } - - muc->part(); - m_mucs[user].erase(room); - } } private: Config *config; std::map > m_users; - std::map > > m_mucs; + std::map > m_handlers; }; #ifndef WIN32 diff --git a/backends/swiften_raw/CMakeLists.txt b/backends/swiften_raw/CMakeLists.txt deleted file mode 100644 index 5d656002..00000000 --- a/backends/swiften_raw/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -cmake_minimum_required(VERSION 2.6) - -FILE(GLOB SRC *.cpp) - -ADD_EXECUTABLE(spectrum2_swiften_raw_backend ${SRC}) - -IF (NOT WIN32) -target_link_libraries(spectrum2_swiften_raw_backend transport pthread ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES}) -else() -target_link_libraries(spectrum2_swiften_raw_backend transport ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES}) -endif() - -#INSTALL(TARGETS spectrum2_swiften_raw_backend RUNTIME DESTINATION bin) - diff --git a/backends/swiften_raw/main.cpp b/backends/swiften_raw/main.cpp deleted file mode 100644 index 5a2c1f37..00000000 --- a/backends/swiften_raw/main.cpp +++ /dev/null @@ -1,441 +0,0 @@ -// Transport includes -#include "transport/config.h" -#include "transport/networkplugin.h" -#include "transport/logging.h" - -#include "boost/date_time/posix_time/posix_time.hpp" - -// Swiften -#include "Swiften/Swiften.h" - -#ifndef WIN32 -// for signal handler -#include "unistd.h" -#include "signal.h" -#include "sys/wait.h" -#include "sys/signal.h" -#endif - -#ifndef __FreeBSD__ -#ifndef __MACH__ -// malloc_trim -#include "malloc.h" -#endif -#endif - -// Boost -#include -using namespace boost::filesystem; -using namespace boost::program_options; -using namespace Transport; - -DEFINE_LOGGER(logger, "Swiften"); -DEFINE_LOGGER(logger_xml, "backend.xml"); - -// eventloop -Swift::SimpleEventLoop *loop_; - -// Plugins -class SwiftenPlugin; -NetworkPlugin *np = NULL; -Swift::XMPPSerializer *serializer; - -class ForwardIQHandler : public Swift::IQHandler { - public: - std::map m_id2resource; - - ForwardIQHandler(NetworkPlugin *np, const std::string &user) { - m_np = np; - m_user = user; - } - - bool handleIQ(boost::shared_ptr iq) { - if (iq->getPayload() != NULL) { - return false; - } - if (iq->getType() == Swift::IQ::Get) { - m_id2resource[iq->getID()] = iq->getFrom().getResource(); - } - - iq->setTo(m_user); - std::string xml = safeByteArrayToString(serializer->serializeElement(iq)); - m_np->sendRawXML(xml); - return true; - } - - private: - NetworkPlugin *m_np; - std::string m_user; - -}; - -class SwiftenPlugin : public NetworkPlugin, Swift::XMPPParserClient { - public: - Swift::BoostNetworkFactories *m_factories; - Swift::BoostIOServiceThread m_boostIOServiceThread; - boost::shared_ptr m_conn; - bool m_firstPing; - - Swift::FullPayloadSerializerCollection collection; - Swift::XMPPParser *m_xmppParser; - Swift::FullPayloadParserFactoryCollection m_collection2; - - SwiftenPlugin(Config *config, Swift::SimpleEventLoop *loop, const std::string &host, int port) : NetworkPlugin() { - this->config = config; - m_firstPing = true; - m_factories = new Swift::BoostNetworkFactories(loop); - m_conn = m_factories->getConnectionFactory()->createConnection(); - m_conn->onDataRead.connect(boost::bind(&SwiftenPlugin::_handleDataRead, this, _1)); - m_conn->connect(Swift::HostAddressPort(Swift::HostAddress(host), port)); - - serializer = new Swift::XMPPSerializer(&collection, Swift::ClientStreamType); - m_xmppParser = new Swift::XMPPParser(this, &m_collection2, m_factories->getXMLParserFactory()); - m_xmppParser->parse(""); - - LOG4CXX_INFO(logger, "Starting the plugin."); - } - - // NetworkPlugin uses this method to send the data to networkplugin server - void sendData(const std::string &string) { - m_conn->write(Swift::createSafeByteArray(string)); - } - - // This method has to call handleDataRead with all received data from network plugin server - void _handleDataRead(boost::shared_ptr data) { - if (m_firstPing) { - m_firstPing = false; - NetworkPlugin::PluginConfig cfg; - cfg.setRawXML(true); - sendConfig(cfg); - } - std::string d(data->begin(), data->end()); - handleDataRead(d); - } - - void handleStreamStart(const Swift::ProtocolHeader&) {} - - void handleElement(boost::shared_ptr element) { - boost::shared_ptr stanza = boost::dynamic_pointer_cast(element); - if (!stanza) { - return; - } - - std::string user = stanza->getFrom().toBare(); - - boost::shared_ptr client = m_users[user]; - if (!client) - return; - - stanza->setFrom(client->getJID()); - - boost::shared_ptr message = boost::dynamic_pointer_cast(stanza); - if (message) { - client->sendMessage(message); - return; - } - - boost::shared_ptr presence = boost::dynamic_pointer_cast(stanza); - if (presence) { - client->sendPresence(presence); - return; - } - - boost::shared_ptr iq = boost::dynamic_pointer_cast(stanza); - if (iq) { - if (m_handlers[user]->m_id2resource.find(stanza->getID()) != m_handlers[user]->m_id2resource.end()) { - iq->setTo(Swift::JID(iq->getTo().getNode(), iq->getTo().getDomain(), m_handlers[user]->m_id2resource[stanza->getID()])); - m_handlers[user]->m_id2resource.erase(stanza->getID()); - } - client->getIQRouter()->sendIQ(iq); - return; - } - } - - void handleStreamEnd() {} - - void handleRawXML(const std::string &xml) { - m_xmppParser->parse(xml); - } - - void handleSwiftDisconnected(const std::string &user, const boost::optional &error) { - std::string message = ""; - bool reconnect = false; - if (error) { - switch(error->getType()) { - case Swift::ClientError::UnknownError: message = ("Unknown Error"); reconnect = true; break; - case Swift::ClientError::DomainNameResolveError: message = ("Unable to find server"); break; - case Swift::ClientError::ConnectionError: message = ("Error connecting to server"); break; - case Swift::ClientError::ConnectionReadError: message = ("Error while receiving server data"); reconnect = true; break; - case Swift::ClientError::ConnectionWriteError: message = ("Error while sending data to the server"); reconnect = true; break; - case Swift::ClientError::XMLError: message = ("Error parsing server data"); reconnect = true; break; - case Swift::ClientError::AuthenticationFailedError: message = ("Login/password invalid"); break; - case Swift::ClientError::CompressionFailedError: message = ("Error while compressing stream"); break; - case Swift::ClientError::ServerVerificationFailedError: message = ("Server verification failed"); break; - case Swift::ClientError::NoSupportedAuthMechanismsError: message = ("Authentication mechanisms not supported"); break; - case Swift::ClientError::UnexpectedElementError: message = ("Unexpected response"); break; - case Swift::ClientError::ResourceBindError: message = ("Error binding resource"); break; - case Swift::ClientError::SessionStartError: message = ("Error starting session"); break; - case Swift::ClientError::StreamError: message = ("Stream error"); break; - case Swift::ClientError::TLSError: message = ("Encryption error"); break; - case Swift::ClientError::ClientCertificateLoadError: message = ("Error loading certificate (Invalid password?)"); break; - case Swift::ClientError::ClientCertificateError: message = ("Certificate not authorized"); break; - - case Swift::ClientError::UnknownCertificateError: message = ("Unknown certificate"); break; - case Swift::ClientError::CertificateExpiredError: message = ("Certificate has expired"); break; - case Swift::ClientError::CertificateNotYetValidError: message = ("Certificate is not yet valid"); break; - case Swift::ClientError::CertificateSelfSignedError: message = ("Certificate is self-signed"); break; - case Swift::ClientError::CertificateRejectedError: message = ("Certificate has been rejected"); break; - case Swift::ClientError::CertificateUntrustedError: message = ("Certificate is not trusted"); break; - case Swift::ClientError::InvalidCertificatePurposeError: message = ("Certificate cannot be used for encrypting your connection"); break; - case Swift::ClientError::CertificatePathLengthExceededError: message = ("Certificate path length constraint exceeded"); break; - case Swift::ClientError::InvalidCertificateSignatureError: message = ("Invalid certificate signature"); break; - case Swift::ClientError::InvalidCAError: message = ("Invalid Certificate Authority"); break; - case Swift::ClientError::InvalidServerIdentityError: message = ("Certificate does not match the host identity"); break; - } - } - LOG4CXX_INFO(logger, user << ": Disconnected " << message); - handleDisconnected(user, reconnect ? 0 : 3, message); - - boost::shared_ptr client = m_users[user]; - if (client) { - client->onConnected.disconnect(boost::bind(&SwiftenPlugin::handleSwiftConnected, this, user)); - client->onDisconnected.disconnect(boost::bind(&SwiftenPlugin::handleSwiftDisconnected, this, user, _1)); - client->onMessageReceived.disconnect(boost::bind(&SwiftenPlugin::handleSwiftMessageReceived, this, user, _1)); - m_users.erase(user); - m_handlers.erase(user); - } - -#ifndef WIN32 -#ifndef __FreeBSD__ -#ifndef __MACH__ - // force returning of memory chunks allocated by libxml2 to kernel - malloc_trim(0); -#endif -#endif -#endif - } - - void handleSwiftConnected(const std::string &user) { - LOG4CXX_INFO(logger, user << ": Connected to XMPP server."); - handleConnected(user); - m_users[user]->requestRoster(); - Swift::Presence::ref response = Swift::Presence::create(); - response->setFrom(m_users[user]->getJID()); - m_users[user]->sendPresence(response); - } - - void handleSwiftRosterReceived(const std::string &user) { - Swift::PresenceOracle *oracle = m_users[user]->getPresenceOracle(); - BOOST_FOREACH(const Swift::XMPPRosterItem &item, m_users[user]->getRoster()->getItems()) { - Swift::Presence::ref lastPresence = oracle->getLastPresence(item.getJID()); - pbnetwork::StatusType status = lastPresence ? ((pbnetwork::StatusType) lastPresence->getShow()) : pbnetwork::STATUS_NONE; - handleBuddyChanged(user, item.getJID().toBare().toString(), - item.getName(), item.getGroups(), status); - } - } - - void handleSwiftPresenceChanged(const std::string &user, Swift::Presence::ref presence) { -// boost::shared_ptr client = m_users[user]; -// if (client->getMUCRegistry()->isMUC(presence->getFrom().toBare())) { -// return; -// } -// -// if (presence->getPayload() != NULL || presence->getPayload() != NULL) { -// return; -// } -// -// LOG4CXX_INFO(logger, user << ": " << presence->getFrom().toBare().toString() << " presence changed"); -// -// std::string message = presence->getStatus(); -// std::string photo = ""; -// -// boost::shared_ptr update = presence->getPayload(); -// if (update) { -// photo = update->getPhotoHash(); -// } -// -// boost::optional item = m_users[user]->getRoster()->getItem(presence->getFrom()); -// if (item) { -// handleBuddyChanged(user, presence->getFrom().toBare().toString(), item->getName(), item->getGroups(), (pbnetwork::StatusType) presence->getShow(), message, photo); -// } -// else { -// std::vector groups; -// handleBuddyChanged(user, presence->getFrom().toBare().toString(), presence->getFrom().toBare(), groups, (pbnetwork::StatusType) presence->getShow(), message, photo); -// } - presence->setTo(user); - std::string xml = safeByteArrayToString(serializer->serializeElement(presence)); - sendRawXML(xml); - } - - void handleSwiftMessageReceived(const std::string &user, Swift::Message::ref message) { - message->setTo(user); - std::string xml = safeByteArrayToString(serializer->serializeElement(message)); - sendRawXML(xml); - } - - void handleSwiftenDataRead(const Swift::SafeByteArray &data) { - std::string d = safeByteArrayToString(data); - if (!boost::starts_with(d, " client = boost::make_shared(Swift::JID(legacyName), password, m_factories); - m_users[user] = client; - client->setAlwaysTrustCertificates(); - client->onConnected.connect(boost::bind(&SwiftenPlugin::handleSwiftConnected, this, user)); - client->onDisconnected.connect(boost::bind(&SwiftenPlugin::handleSwiftDisconnected, this, user, _1)); - client->onMessageReceived.connect(boost::bind(&SwiftenPlugin::handleSwiftMessageReceived, this, user, _1)); - client->getRoster()->onInitialRosterPopulated.connect(boost::bind(&SwiftenPlugin::handleSwiftRosterReceived, this, user)); - client->getPresenceOracle()->onPresenceChange.connect(boost::bind(&SwiftenPlugin::handleSwiftPresenceChanged, this, user, _1)); - client->onDataRead.connect(boost::bind(&SwiftenPlugin::handleSwiftenDataRead, this, _1)); - client->onDataWritten.connect(boost::bind(&SwiftenPlugin::handleSwiftenDataWritten, this, _1)); - client->getSubscriptionManager()->onPresenceSubscriptionRequest.connect(boost::bind(&SwiftenPlugin::handleSubscriptionRequest, this, user, _1, _2, _3)); - client->getSubscriptionManager()->onPresenceSubscriptionRevoked.connect(boost::bind(&SwiftenPlugin::handleSubscriptionRevoked, this, user, _1, _2)); - Swift::ClientOptions opt; - opt.allowPLAINWithoutTLS = true; - client->connect(opt); - - boost::shared_ptr handler = boost::make_shared(this, user); - client->getIQRouter()->addHandler(handler); - m_handlers[user] = handler; - } - - void handleSubscriptionRequest(const std::string &user, const Swift::JID& jid, const std::string& message, Swift::Presence::ref presence) { - handleSwiftPresenceChanged(user, presence); - } - - void handleSubscriptionRevoked(const std::string &user, const Swift::JID& jid, const std::string& message) { - Swift::Presence::ref presence = Swift::Presence::create(); - presence->setTo(user); - presence->setFrom(jid); - presence->setType(Swift::Presence::Unsubscribe); - handleSwiftPresenceChanged(user, presence); - } - - void handleLogoutRequest(const std::string &user, const std::string &legacyName) { - boost::shared_ptr client = m_users[user]; - if (client) { - client->onConnected.disconnect(boost::bind(&SwiftenPlugin::handleSwiftConnected, this, user)); -// client->onDisconnected.disconnect(boost::bind(&SwiftenPlugin::handleSwiftDisconnected, this, user, _1)); - client->onMessageReceived.disconnect(boost::bind(&SwiftenPlugin::handleSwiftMessageReceived, this, user, _1)); - client->getRoster()->onInitialRosterPopulated.disconnect(boost::bind(&SwiftenPlugin::handleSwiftRosterReceived, this, user)); - client->getPresenceOracle()->onPresenceChange.disconnect(boost::bind(&SwiftenPlugin::handleSwiftPresenceChanged, this, user, _1)); - client->disconnect(); - } - } - - void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &msg, const std::string &xhtml = "", const std::string &id = "") { - } - - void handleVCardRequest(const std::string &user, const std::string &legacyName, unsigned int id) { - } - - void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector &groups) { - boost::shared_ptr client = m_users[user]; - if (client) { - LOG4CXX_INFO(logger, user << ": Added/Updated buddy " << buddyName << "."); - if (!client->getRoster()->containsJID(buddyName) || client->getRoster()->getSubscriptionStateForJID(buddyName) != Swift::RosterItemPayload::Both) { - Swift::RosterItemPayload item; - item.setName(alias); - item.setJID(buddyName); - item.setGroups(groups); - boost::shared_ptr roster(new Swift::RosterPayload()); - roster->addItem(item); - Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(roster, client->getIQRouter()); -// request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster)); - request->send(); - client->getSubscriptionManager()->requestSubscription(buddyName); - } - else { - Swift::JID contact(buddyName); - Swift::RosterItemPayload item(contact, alias, client->getRoster()->getSubscriptionStateForJID(contact)); - item.setGroups(groups); - boost::shared_ptr roster(new Swift::RosterPayload()); - roster->addItem(item); - Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(roster, client->getIQRouter()); -// request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster)); - request->send(); - } - - } - } - - void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector &groups) { - boost::shared_ptr client = m_users[user]; - if (client) { - Swift::RosterItemPayload item(buddyName, "", Swift::RosterItemPayload::Remove); - boost::shared_ptr roster(new Swift::RosterPayload()); - roster->addItem(item); - Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(roster, client->getIQRouter()); -// request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster)); - request->send(); - } - } - - void handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &password) { - - } - - void handleLeaveRoomRequest(const std::string &user, const std::string &room) { - - } - - private: - Config *config; - std::map > m_users; - std::map > m_handlers; -}; - -#ifndef WIN32 -static void spectrum_sigchld_handler(int sig) -{ - int status; - pid_t pid; - - do { - pid = waitpid(-1, &status, WNOHANG); - } while (pid != 0 && pid != (pid_t)-1); - - if ((pid == (pid_t) - 1) && (errno != ECHILD)) { - char errmsg[BUFSIZ]; - snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid); - perror(errmsg); - } -} -#endif - - -int main (int argc, char* argv[]) { - std::string host; - int port; - -#ifndef WIN32 - if (signal(SIGCHLD, spectrum_sigchld_handler) == SIG_ERR) { - std::cout << "SIGCHLD handler can't be set\n"; - return -1; - } -#endif - - std::string error; - Config *cfg = Config::createFromArgs(argc, argv, error, host, port); - if (cfg == NULL) { - std::cerr << error; - return 1; - } - - Logging::initBackendLogging(cfg); - - Swift::SimpleEventLoop eventLoop; - loop_ = &eventLoop; - np = new SwiftenPlugin(cfg, &eventLoop, host, port); - loop_->run(); - - return 0; -} From 7805d876f88df16c93862e16870eac4b448aa32e Mon Sep 17 00:00:00 2001 From: HanzZ Date: Tue, 26 Feb 2013 09:31:57 +0100 Subject: [PATCH 15/16] Libtransport: Send also subject in sendCachedMessages() --- src/conversation.cpp | 11 +++++++++++ src/tests/conversationmanager.cpp | 10 +++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/conversation.cpp b/src/conversation.cpp index c02396e5..dce307c3 100644 --- a/src/conversation.cpp +++ b/src/conversation.cpp @@ -214,6 +214,17 @@ void Conversation::sendCachedMessages(const Swift::JID &to) { } m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(*it); } + + if (m_subject) { + if (to.isValid()) { + m_subject->setTo(to); + } + else { + m_subject->setTo(m_jid.toBare()); + } + m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(m_subject); + } + m_cachedMessages.clear(); } diff --git a/src/tests/conversationmanager.cpp b/src/tests/conversationmanager.cpp index 36d90a30..c5965a9d 100644 --- a/src/tests/conversationmanager.cpp +++ b/src/tests/conversationmanager.cpp @@ -313,6 +313,10 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe conv->setNickname("nickname"); conv->addJID("user@localhost/resource"); + boost::shared_ptr msg0(new Swift::Message()); + msg0->setSubject("subject"); + conv->handleMessage(msg0, "anotheruser"); + CPPUNIT_ASSERT(!user->shouldCacheMessages()); // disconnectUser @@ -350,7 +354,7 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe injectPresence(response); loop->processEvents(); - CPPUNIT_ASSERT_EQUAL(3, (int) received.size()); + CPPUNIT_ASSERT_EQUAL(4, (int) received.size()); CPPUNIT_ASSERT(dynamic_cast(getStanza(received[1]))); CPPUNIT_ASSERT_EQUAL(std::string("hi there!"), dynamic_cast(getStanza(received[1]))->getBody()); CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast(getStanza(received[1]))->getTo().toString()); @@ -361,6 +365,10 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast(getStanza(received[2]))->getTo().toString()); CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast(getStanza(received[2]))->getFrom().toString()); + CPPUNIT_ASSERT(dynamic_cast(getStanza(received[3]))); + CPPUNIT_ASSERT_EQUAL(std::string("subject"), dynamic_cast(getStanza(received[3]))->getSubject()); + CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast(getStanza(received[3]))->getTo().toString()); + CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast(getStanza(received[3]))->getFrom().toString()); } void handleGroupchatMessagesBouncerLeave() { From c5e07954eb6a3277cf0caaba6dd7aa8be73050c1 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Tue, 26 Feb 2013 09:46:42 +0100 Subject: [PATCH 16/16] Do not add swiften_raw subdirectory --- backends/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/backends/CMakeLists.txt b/backends/CMakeLists.txt index 6dcfb900..6bb81a77 100644 --- a/backends/CMakeLists.txt +++ b/backends/CMakeLists.txt @@ -9,7 +9,6 @@ if (PROTOBUF_FOUND) if (ENABLE_SWIFTEN) ADD_SUBDIRECTORY(swiften) - ADD_SUBDIRECTORY(swiften_raw) endif() ADD_SUBDIRECTORY(template)