diff --git a/include/transport/rostermanager.h b/include/transport/rostermanager.h index 0fb5eac2..29c460ca 100644 --- a/include/transport/rostermanager.h +++ b/include/transport/rostermanager.h @@ -70,6 +70,10 @@ class RosterManager { /// \return User User *getUser() { return m_user; } + bool isRemoteRosterSupported() { + return m_supportRemoteRoster; + } + /// Called when new Buddy is added to this roster. /// \param buddy newly added Buddy boost::signal onBuddySet; @@ -101,6 +105,7 @@ class RosterManager { void sendRIE(); void handleBuddyRosterPushResponse(Swift::ErrorPayload::ref error, Swift::SetRosterRequest::ref request, const std::string &key); + void handleRemoteRosterResponse(boost::shared_ptr roster, Swift::ErrorPayload::ref error); std::map, boost::pool_allocator< std::pair > > m_buddies; Component *m_component; @@ -109,6 +114,7 @@ class RosterManager { Swift::Timer::ref m_setBuddyTimer; Swift::Timer::ref m_RIETimer; std::list m_requests; + bool m_supportRemoteRoster; }; } diff --git a/src/localbuddy.cpp b/src/localbuddy.cpp index 0c43b8a3..ce64ad87 100644 --- a/src/localbuddy.cpp +++ b/src/localbuddy.cpp @@ -35,7 +35,9 @@ void LocalBuddy::setAlias(const std::string &alias) { m_alias = alias; if (changed) { - getRosterManager()->sendBuddyRosterPush(this); + if (getRosterManager()->getUser()->getComponent()->inServerMode() || getRosterManager()->isRemoteRosterSupported()) { + getRosterManager()->sendBuddyRosterPush(this); + } getRosterManager()->storeBuddy(this); } } diff --git a/src/mysqlbackend.cpp b/src/mysqlbackend.cpp index 91faefed..fb425afc 100644 --- a/src/mysqlbackend.cpp +++ b/src/mysqlbackend.cpp @@ -209,7 +209,7 @@ MySQLBackend::Statement& MySQLBackend::Statement::operator << (const T& t) { int *data = (int *) m_params[m_offset].buffer; *data = (int) t; - LOG4CXX_INFO(logger, "adding " << m_offset << ":" << (int) t); +// LOG4CXX_INFO(logger, "adding " << m_offset << ":" << (int) t); m_offset++; return *this; } @@ -217,7 +217,7 @@ MySQLBackend::Statement& MySQLBackend::Statement::operator << (const T& t) { MySQLBackend::Statement& MySQLBackend::Statement::operator << (const std::string& str) { if (m_offset >= m_params.size()) return *this; - LOG4CXX_INFO(logger, "adding " << m_offset << ":" << str << "(" << str.size() << ")"); +// LOG4CXX_INFO(logger, "adding " << m_offset << ":" << str << "(" << str.size() << ")"); strncpy((char*) m_params[m_offset].buffer, str.c_str(), 4096); *m_params[m_offset].length = str.size(); m_offset++; @@ -232,7 +232,7 @@ MySQLBackend::Statement& MySQLBackend::Statement::operator >> (T& t) { if (!m_results[m_resultOffset].is_null) { T *data = (T *) m_results[m_resultOffset].buffer; t = *data; - std::cout << "getting " << m_resultOffset << " " << (int) t << "\n"; +// std::cout << "getting " << m_resultOffset << " " << (int) t << "\n"; } if (++m_resultOffset == m_results.size()) @@ -241,7 +241,7 @@ MySQLBackend::Statement& MySQLBackend::Statement::operator >> (T& t) { } MySQLBackend::Statement& MySQLBackend::Statement::operator >> (std::string& t) { - std::cout << "getting " << m_resultOffset << "\n"; +// std::cout << "getting " << m_resultOffset << "\n"; if (m_resultOffset > m_results.size()) return *this; diff --git a/src/rostermanager.cpp b/src/rostermanager.cpp index 25226421..69a26d23 100644 --- a/src/rostermanager.cpp +++ b/src/rostermanager.cpp @@ -41,6 +41,16 @@ namespace Transport { static LoggerPtr logger = Logger::getLogger("RosterManager"); +// TODO: Once Swiften GetRosterRequest will support setting to="", this can be removed +class AddressedRosterRequest : public Swift::GenericRequest { + public: + typedef boost::shared_ptr ref; + + AddressedRosterRequest(Swift::IQRouter* router, Swift::JID to) : + Swift::GenericRequest(Swift::IQ::Get, to, boost::shared_ptr(new Swift::RosterPayload()), router) { + } +}; + RosterManager::RosterManager(User *user, Component *component){ m_rosterStorage = NULL; m_user = user; @@ -48,6 +58,14 @@ RosterManager::RosterManager(User *user, Component *component){ m_setBuddyTimer = m_component->getNetworkFactories()->getTimerFactory()->createTimer(1000); m_RIETimer = m_component->getNetworkFactories()->getTimerFactory()->createTimer(5000); m_RIETimer->onTick.connect(boost::bind(&RosterManager::sendRIE, this)); + + m_supportRemoteRoster = false; + + if (!m_component->inServerMode()) { + AddressedRosterRequest::ref request = AddressedRosterRequest::ref(new AddressedRosterRequest(m_component->getIQRouter(), m_user->getJID().toBare())); + request->onResponse.connect(boost::bind(&RosterManager::handleRemoteRosterResponse, this, _1, _2)); + request->send(); + } } RosterManager::~RosterManager() { @@ -89,7 +107,9 @@ void RosterManager::setBuddy(Buddy *buddy) { } void RosterManager::sendBuddyRosterPush(Buddy *buddy) { - if (!m_user->isConnected()) + // user can't receive anything in server mode if he's not logged in. + // He will ask for roster later (handled in rosterreponsder.cpp) + if (m_component->inServerMode() && !m_user->isConnected()) return; Swift::RosterPayload::ref payload = Swift::RosterPayload::ref(new Swift::RosterPayload()); @@ -138,13 +158,18 @@ void RosterManager::setBuddyCallback(Buddy *buddy) { if (m_setBuddyTimer->onTick.empty()) { m_setBuddyTimer->stop(); - // Send RIE only if there's resource which supports it. - Swift::JID jidWithRIE = m_user->getJIDWithFeature("http://jabber.org/protocol/rosterx"); - if (jidWithRIE.isValid()) { - m_RIETimer->start(); + if (m_supportRemoteRoster) { + sendBuddyRosterPush(buddy); } else { - sendBuddySubscribePresence(buddy); + // Send RIE only if there's resource which supports it. + Swift::JID jidWithRIE = m_user->getJIDWithFeature("http://jabber.org/protocol/rosterx"); + if (jidWithRIE.isValid()) { + m_RIETimer->start(); + } + else { + sendBuddySubscribePresence(buddy); + } } } } @@ -175,6 +200,34 @@ void RosterManager::handleBuddyRosterPushResponse(Swift::ErrorPayload::ref error request->onResponse.disconnect_all_slots(); } +void RosterManager::handleRemoteRosterResponse(boost::shared_ptr payload, Swift::ErrorPayload::ref error) { + if (error) { + m_supportRemoteRoster = false; + LOG4CXX_INFO(logger, m_user->getJID().toString() << ": This server does not support remote roster protoXEP"); + return; + } + + LOG4CXX_INFO(logger, m_user->getJID().toString() << ": This server supports remote roster protoXEP"); + m_supportRemoteRoster = true; + + BOOST_FOREACH(const Swift::RosterItemPayload &item, payload->getItems()) { + std::string legacyName = Buddy::JIDToLegacyName(item.getJID()); + if (m_buddies.find(legacyName) == m_buddies.end()) { + continue; + } + + BuddyInfo buddyInfo; + buddyInfo.id = -1; + buddyInfo.alias = item.getName(); + buddyInfo.legacyName = legacyName; + buddyInfo.subscription = "both"; + buddyInfo.flags = 0; + + Buddy *buddy = m_component->getFactory()->createBuddy(this, buddyInfo); + setBuddy(buddy); + } +} + Buddy *RosterManager::getBuddy(const std::string &name) { return m_buddies[name]; } @@ -209,7 +262,7 @@ void RosterManager::sendRIE() { item.setJID(buddy->getJID().toBare()); item.setName(buddy->getAlias()); item.setAction(Swift::RosterItemExchangePayload::Item::Add); -// item.setGroups(buddy->getGroups()); + item.setGroups(buddy->getGroups()); payload->addItem(item); }