Libtransport: Allow setting room list per user

This commit is contained in:
Jan Kaluza 2016-02-07 20:53:35 +01:00
parent 5f04f45903
commit 39c8618da6
17 changed files with 176 additions and 32 deletions

View file

@ -1599,7 +1599,17 @@ static void RoomlistProgress(PurpleRoomlist *list, gboolean in_progress)
PurpleRoomlistRoom *room = (PurpleRoomlistRoom *)rooms->data;
m_rooms.push_back(room->name);
}
np->handleRoomList("", m_rooms, m_rooms);
std::string user = "";
if (list->account) {
user = np->m_accounts[list->account];
}
LOG4CXX_INFO(logger, "RoomList is fetched for user " << user);
np->handleRoomList(user, m_rooms, m_rooms);
}
else {
LOG4CXX_INFO(logger, "RoomList is still in progress");
}
}

View file

@ -76,6 +76,8 @@ class User {
UserManager *getUserManager() { return m_userManager; }
virtual void disconnectUser(const std::string &error, Swift::SpectrumErrorPayload::Error e) = 0;
virtual void clearRoomList() {}
virtual void addRoomToRoomList(const std::string &handle, const std::string &name) {}
virtual void requestVCard() {}
void setData(void *data) { m_data = data; }

View file

@ -89,6 +89,7 @@ message Room {
message RoomList {
repeated string room = 1;
repeated string name = 2;
optional string user = 3;
}
enum ParticipantFlag {

View file

@ -994,9 +994,23 @@ void NetworkPluginServer::handleRoomListPayload(const std::string &data) {
return;
}
m_component->getFrontend()->clearRoomList();
for (int i = 0; i < payload.room_size() && i < payload.name_size(); i++) {
m_component->getFrontend()->addRoomToRoomList(Swift::JID::getEscapedNode(payload.room(i)) + "@" + m_component->getJID().toString(), payload.name(i));
if (!payload.user().empty()) {
User *user = m_userManager->getUser(payload.user());
if (!user) {
LOG4CXX_ERROR(logger, "Room list payload received for unknown user " << payload.user());
return;
}
user->clearRoomList();
for (int i = 0; i < payload.room_size() && i < payload.name_size(); i++) {
user->addRoomToRoomList(Swift::JID::getEscapedNode(payload.room(i)) + "@" + m_component->getJID().toString(), payload.name(i));
}
}
else {
m_component->getFrontend()->clearRoomList();
for (int i = 0; i < payload.room_size() && i < payload.name_size(); i++) {
m_component->getFrontend()->addRoomToRoomList(Swift::JID::getEscapedNode(payload.room(i)) + "@" + m_component->getJID().toString(), payload.name(i));
}
}
}
#if HAVE_SWIFTEN_3

View file

@ -376,6 +376,8 @@ void NetworkPlugin::handleRoomList(const std::string &user, const std::list<std:
d.add_name(*it);
}
d.set_user(user);
std::string message;
d.SerializeToString(&message);

View file

@ -31,7 +31,6 @@
#include "transport/Logging.h"
#include "transport/Config.h"
#include "transport/Transport.h"
#include "discoitemsresponder.h"
#include "storageparser.h"
#ifdef _WIN32
#include <Swiften/TLS/CAPICertificate.h>
@ -63,6 +62,7 @@
#include "Swiften/Parser/GenericPayloadParserFactory.h"
#include "Swiften/Queries/IQRouter.h"
#include "Swiften/Elements/RosterPayload.h"
#include "discoitemsresponder.h"
#include "Swiften/Elements/InBandRegistrationPayload.h"
using namespace Swift;
@ -81,6 +81,7 @@ void XMPPFrontend::init(Component *transport, Swift::EventLoop *loop, Swift::Net
m_server = NULL;
m_rawXML = false;
m_config = transport->getConfig();
m_userManager = NULL;
m_jid = Swift::JID(CONFIG_STRING(m_config, "service.jid"));
m_config->onBackendConfigUpdated.connect(boost::bind(&XMPPFrontend::handleBackendConfigChanged, this));
@ -173,9 +174,6 @@ void XMPPFrontend::init(Component *transport, Swift::EventLoop *loop, Swift::Net
m_stanzaChannel->onPresenceReceived.connect(bind(&XMPPFrontend::handleGeneralPresence, this, _1));
m_stanzaChannel->onMessageReceived.connect(bind(&XMPPFrontend::handleMessage, this, _1));
m_discoItemsResponder = new DiscoItemsResponder(transport);
m_discoItemsResponder->start();
}
XMPPFrontend::~XMPPFrontend() {
@ -200,16 +198,16 @@ void XMPPFrontend::handleMessage(boost::shared_ptr<Swift::Message> message) {
void XMPPFrontend::clearRoomList() {
m_discoItemsResponder->clearRooms();
static_cast<XMPPUserManager *>(m_userManager)->getDiscoItemsResponder()->clearRooms();
}
void XMPPFrontend::addRoomToRoomList(const std::string &handle, const std::string &name) {
m_discoItemsResponder->addRoom(handle, name);
static_cast<XMPPUserManager *>(m_userManager)->getDiscoItemsResponder()->addRoom(handle, name);
}
void XMPPFrontend::sendPresence(Swift::Presence::ref presence) {
if (!presence->getFrom().getNode().empty()) {
presence->addPayload(boost::shared_ptr<Swift::Payload>(new Swift::CapsInfo(m_discoItemsResponder->getBuddyCapsInfo())));
presence->addPayload(boost::shared_ptr<Swift::Payload>(new Swift::CapsInfo(static_cast<XMPPUserManager *>(m_userManager)->getDiscoItemsResponder()->getBuddyCapsInfo())));
}
m_stanzaChannel->sendPresence(presence);
@ -277,7 +275,8 @@ User *XMPPFrontend::createUser(const Swift::JID &jid, UserInfo &userInfo, Compon
}
UserManager *XMPPFrontend::createUserManager(Component *component, UserRegistry *userRegistry, StorageBackend *storageBackend) {
return new XMPPUserManager(component, userRegistry, storageBackend);
m_userManager = new XMPPUserManager(component, userRegistry, storageBackend);
return m_userManager;
}
bool XMPPFrontend::handleIQ(boost::shared_ptr<Swift::IQ> iq) {

View file

@ -47,7 +47,6 @@ namespace Transport {
class UserRegistry;
class Frontend;
class Config;
class DiscoItemsResponder;
class VCardResponder;
class XMPPFrontend : public Frontend, Swift::IQHandler {
@ -95,10 +94,6 @@ namespace Transport {
return m_rawXML;
}
DiscoItemsResponder *getDiscoItemsResponder() {
return m_discoItemsResponder;
}
private:
void handleConnected();
void handleConnectionError(const Swift::ComponentError &error);
@ -121,13 +116,13 @@ namespace Transport {
Swift::CapsMemoryStorage *m_capsMemoryStorage;
Swift::StanzaChannel *m_stanzaChannel;
Swift::IQRouter *m_iqRouter;
DiscoItemsResponder *m_discoItemsResponder;
VCardResponder *m_vcardResponder;
Config* m_config;
Swift::JID m_jid;
bool m_rawXML;
Component *m_transport;
UserManager *m_userManager;
friend class XMPPUser;
friend class UserRegistration;

View file

@ -45,6 +45,7 @@ XMPPUser::XMPPUser(const Swift::JID &jid, UserInfo &userInfo, Component *compone
m_component = component;
m_userManager = userManager;
m_userInfo = userInfo;
m_rooms = boost::shared_ptr<Swift::DiscoItems>(new Swift::DiscoItems());
}
XMPPUser::~XMPPUser(){
@ -98,5 +99,13 @@ void XMPPUser::requestVCard() {
m_vcardRequests.push_back(request);
}
void XMPPUser::clearRoomList() {
m_rooms = boost::shared_ptr<Swift::DiscoItems>(new Swift::DiscoItems());
}
void XMPPUser::addRoomToRoomList(const std::string &handle, const std::string &name) {
m_rooms->addItem(Swift::DiscoItems::Item(name, handle));
}
}

View file

@ -30,6 +30,7 @@
#include "Swiften/Network/Timer.h"
#include "Swiften/Network/Connection.h"
#include "Swiften/VCards/GetVCardRequest.h"
#include "Swiften/Elements/DiscoItems.h"
namespace Transport {
@ -57,6 +58,14 @@ class XMPPUser : public User {
void requestVCard();
void clearRoomList();
void addRoomToRoomList(const std::string &handle, const std::string &name);
boost::shared_ptr<Swift::DiscoItems> getRoomList() {
return m_rooms;
}
private:
void onConnectingTimeout();
void handleVCardReceived(boost::shared_ptr<Swift::VCard> vcard, Swift::ErrorPayload::ref error, Swift::GetVCardRequest::ref request);
@ -66,6 +75,7 @@ class XMPPUser : public User {
UserManager *m_userManager;
UserInfo m_userInfo;
std::list <Swift::GetVCardRequest::ref> m_vcardRequests;
boost::shared_ptr<Swift::DiscoItems> m_rooms;
};
}

View file

@ -32,6 +32,7 @@
#include "adhocmanager.h"
#include "settingsadhoccommand.h"
#include "RosterResponder.h"
#include "discoitemsresponder.h"
#include "Swiften/Server/ServerStanzaChannel.h"
#include "Swiften/Elements/StreamError.h"
@ -82,7 +83,10 @@ XMPPUserManager::XMPPUserManager(Component *component, UserRegistry *userRegistr
m_rosterResponder = new RosterResponder(frontend->getIQRouter(), this);
m_rosterResponder->start();
m_adHocManager = new AdHocManager(component, frontend->getDiscoItemsResponder(), this, storageBackend);
m_discoItemsResponder = new DiscoItemsResponder(component, this);
m_discoItemsResponder->start();
m_adHocManager = new AdHocManager(component, m_discoItemsResponder, this, storageBackend);
m_adHocManager->start();
SettingsAdHocCommandFactory *m_settings = new SettingsAdHocCommandFactory();
@ -111,6 +115,9 @@ XMPPUserManager::~XMPPUserManager() {
m_rosterResponder->stop();
delete m_rosterResponder;
m_discoItemsResponder->stop();
delete m_discoItemsResponder;
}
void XMPPUserManager::sendVCard(unsigned int id, Swift::VCard::ref vcard) {

View file

@ -40,6 +40,7 @@ class GatewayResponder;
class AdHocManager;
class SettingsAdHocCommandFactory;
class RosterResponder;
class DiscoItemsResponder;
class XMPPUserManager : public UserManager {
public:
@ -51,6 +52,10 @@ class XMPPUserManager : public UserManager {
UserRegistration *getUserRegistration();
DiscoItemsResponder *getDiscoItemsResponder() {
return m_discoItemsResponder;
}
private:
void handleVCardRequired(User *, const std::string &name, unsigned int id);
void handleVCardUpdated(User *, boost::shared_ptr<Swift::VCard> vcard);
@ -63,6 +68,7 @@ class XMPPUserManager : public UserManager {
AdHocManager *m_adHocManager;
SettingsAdHocCommandFactory *m_settings;
RosterResponder *m_rosterResponder;
DiscoItemsResponder *m_discoItemsResponder;
};
}

View file

@ -30,6 +30,8 @@
#include "transport/Logging.h"
#include "Swiften/Disco/CapsInfoGenerator.h"
#include "XMPPFrontend.h"
#include "transport/UserManager.h"
#include "XMPPUser.h"
using namespace Swift;
using namespace boost;
@ -38,7 +40,7 @@ DEFINE_LOGGER(logger, "DiscoInfoResponder");
namespace Transport {
DiscoInfoResponder::DiscoInfoResponder(Swift::IQRouter *router, Config *config) : Swift::GetResponder<DiscoInfo>(router) {
DiscoInfoResponder::DiscoInfoResponder(Swift::IQRouter *router, Config *config, UserManager *userManager) : Swift::GetResponder<DiscoInfo>(router) {
m_config = config;
m_config->onBackendConfigUpdated.connect(boost::bind(&DiscoInfoResponder::updateFeatures, this));
m_buddyInfo = NULL;
@ -50,6 +52,7 @@ DiscoInfoResponder::DiscoInfoResponder(Swift::IQRouter *router, Config *config)
#endif
updateFeatures();
m_userManager = userManager;
}
DiscoInfoResponder::~DiscoInfoResponder() {
@ -148,21 +151,39 @@ bool DiscoInfoResponder::handleGetRequest(const Swift::JID& from, const Swift::J
res->setNode(info->getNode());
sendResponse(from, id, res);
}
return true;
}
// disco#info for room
else if (m_rooms.find(to.toBare().toString()) != m_rooms.end()) {
if (m_rooms.find(to.toBare().toString()) != m_rooms.end()) {
boost::shared_ptr<DiscoInfo> res(new DiscoInfo());
res->addIdentity(DiscoInfo::Identity(m_rooms[to.toBare().toString()], "conference", "text"));
res->addFeature("http://jabber.org/protocol/muc");
res->setNode(info->getNode());
sendResponse(from, to, id, res);
return true;
}
// disco#info for per-user rooms (like Skype/Facebook groupchats)
XMPPUser *user = static_cast<XMPPUser *>(m_userManager->getUser(from.toBare().toString()));
if (user) {
BOOST_FOREACH(const DiscoItems::Item &item, user->getRoomList()->getItems()) {
LOG4CXX_INFO(logger, "XXX " << item.getNode() << " " << to.toBare().toString());
if (item.getJID().toString() == to.toBare().toString()) {
boost::shared_ptr<DiscoInfo> res(new DiscoInfo());
res->addIdentity(DiscoInfo::Identity(item.getName(), "conference", "text"));
res->addFeature("http://jabber.org/protocol/muc");
res->setNode(info->getNode());
sendResponse(from, to, id, res);
return true;
}
}
}
// disco#info for buddy
else {
boost::shared_ptr<DiscoInfo> res(new DiscoInfo(*m_buddyInfo));
res->setNode(info->getNode());
sendResponse(from, to, id, res);
}
boost::shared_ptr<DiscoInfo> res(new DiscoInfo(*m_buddyInfo));
res->setNode(info->getNode());
sendResponse(from, to, id, res);
return true;
}

View file

@ -37,10 +37,11 @@
namespace Transport {
class Config;
class UserManager;
class DiscoInfoResponder : public Swift::GetResponder<Swift::DiscoInfo> {
public:
DiscoInfoResponder(Swift::IQRouter *router, Config *config);
DiscoInfoResponder(Swift::IQRouter *router, Config *config, UserManager *userManager);
~DiscoInfoResponder();
void setTransportFeatures(std::list<std::string> &features);
@ -70,6 +71,7 @@ class DiscoInfoResponder : public Swift::GetResponder<Swift::DiscoInfo> {
#if HAVE_SWIFTEN_3
boost::shared_ptr<Swift::CryptoProvider> crypto;
#endif
UserManager *m_userManager;
};
}

View file

@ -29,6 +29,8 @@
#include "discoinforesponder.h"
#include "XMPPFrontend.h"
#include "transport/Frontend.h"
#include "transport/UserManager.h"
#include "XMPPUser.h"
using namespace Swift;
using namespace boost;
@ -37,14 +39,16 @@ namespace Transport {
DEFINE_LOGGER(logger, "DiscoItemsResponder");
DiscoItemsResponder::DiscoItemsResponder(Component *component) : Swift::GetResponder<DiscoItems>(static_cast<XMPPFrontend *>(component->getFrontend())->getIQRouter()) {
DiscoItemsResponder::DiscoItemsResponder(Component *component, UserManager *userManager) : Swift::GetResponder<DiscoItems>(static_cast<XMPPFrontend *>(component->getFrontend())->getIQRouter()) {
m_component = component;
m_commands = boost::shared_ptr<DiscoItems>(new DiscoItems());
m_commands->setNode("http://jabber.org/protocol/commands");
m_rooms = boost::shared_ptr<DiscoItems>(new DiscoItems());
m_discoInfoResponder = new DiscoInfoResponder(static_cast<XMPPFrontend *>(component->getFrontend())->getIQRouter(), component->getConfig());
m_discoInfoResponder = new DiscoInfoResponder(static_cast<XMPPFrontend *>(component->getFrontend())->getIQRouter(), component->getConfig(), userManager);
m_discoInfoResponder->start();
m_userManager = userManager;
}
DiscoItemsResponder::~DiscoItemsResponder() {
@ -80,7 +84,21 @@ bool DiscoItemsResponder::handleGetRequest(const Swift::JID& from, const Swift::
sendResponse(from, id, m_commands);
}
else if (to.getNode().empty()) {
sendResponse(from, id, m_rooms);
XMPPUser *user = static_cast<XMPPUser *>(m_userManager->getUser(from.toBare().toString()));
if (!user) {
sendResponse(from, id, m_rooms);
return true;
}
boost::shared_ptr<DiscoItems> rooms = boost::shared_ptr<DiscoItems>(new DiscoItems());
BOOST_FOREACH(const DiscoItems::Item &item, m_rooms->getItems()) {
rooms->addItem(item);
}
BOOST_FOREACH(const DiscoItems::Item &item, user->getRoomList()->getItems()) {
rooms->addItem(item);
}
sendResponse(from, id, rooms);
}
else {
sendResponse(from, id, boost::shared_ptr<DiscoItems>(new DiscoItems()));

View file

@ -29,10 +29,11 @@ namespace Transport {
class Component;
class DiscoInfoResponder;
class UserManager;
class DiscoItemsResponder : public Swift::GetResponder<Swift::DiscoItems> {
public:
DiscoItemsResponder(Component *component);
DiscoItemsResponder(Component *component, UserManager *userManager);
~DiscoItemsResponder();
Swift::CapsInfo &getBuddyCapsInfo();
@ -52,6 +53,7 @@ class DiscoItemsResponder : public Swift::GetResponder<Swift::DiscoItems> {
boost::shared_ptr<Swift::DiscoItems> m_commands;
boost::shared_ptr<Swift::DiscoItems> m_rooms;
DiscoInfoResponder *m_discoInfoResponder;
UserManager *m_userManager;
};
}

View file

@ -55,7 +55,7 @@ void BasicTest::setMeUp (void) {
userManager = frontend->createUserManager(component, userRegistry, storage);
itemsResponder = frontend->getDiscoItemsResponder();
itemsResponder = static_cast<XMPPUserManager *>(userManager)->getDiscoItemsResponder();
payloadSerializers = new Swift::FullPayloadSerializerCollection();
payloadParserFactories = new Swift::FullPayloadParserFactoryCollection();

View file

@ -15,7 +15,9 @@ using namespace Transport;
class DiscoItemsResponderTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
CPPUNIT_TEST_SUITE(DiscoItemsResponderTest);
CPPUNIT_TEST(roomList);
CPPUNIT_TEST(roomListUser);
CPPUNIT_TEST(roomInfo);
CPPUNIT_TEST(roomInfoUser);
CPPUNIT_TEST(roomListEscaping);
CPPUNIT_TEST(roomInfoEscaping);
CPPUNIT_TEST(clearRooms);
@ -50,6 +52,50 @@ class DiscoItemsResponderTest : public CPPUNIT_NS :: TestFixture, public BasicTe
CPPUNIT_ASSERT_EQUAL(std::string("#room"), getStanza(received[0])->getPayload<Swift::DiscoItems>()->getItems()[0].getName());
}
void roomListUser() {
connectUser();
User *user = userManager->getUser("user@localhost");
user->addRoomToRoomList("#room2@localhost", "#room2");
itemsResponder->addRoom("#room@localhost", "#room");
boost::shared_ptr<Swift::DiscoItems> payload(new Swift::DiscoItems());
boost::shared_ptr<Swift::IQ> iq = Swift::IQ::createRequest(Swift::IQ::Get, Swift::JID("localhost"), "id", payload);
iq->setFrom("user@localhost");
injectIQ(iq);
loop->processEvents();
CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
CPPUNIT_ASSERT(dynamic_cast<Swift::IQ *>(getStanza(received[0])));
CPPUNIT_ASSERT_EQUAL(Swift::IQ::Result, dynamic_cast<Swift::IQ *>(getStanza(received[0]))->getType());
CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::DiscoItems>());
CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost"), getStanza(received[0])->getPayload<Swift::DiscoItems>()->getItems()[0].getJID().toString());
CPPUNIT_ASSERT_EQUAL(std::string("#room"), getStanza(received[0])->getPayload<Swift::DiscoItems>()->getItems()[0].getName());
CPPUNIT_ASSERT_EQUAL(std::string("#room2@localhost"), getStanza(received[0])->getPayload<Swift::DiscoItems>()->getItems()[1].getJID().toString());
CPPUNIT_ASSERT_EQUAL(std::string("#room2"), getStanza(received[0])->getPayload<Swift::DiscoItems>()->getItems()[1].getName());
}
void roomInfoUser() {
connectUser();
User *user = userManager->getUser("user@localhost");
user->addRoomToRoomList("#room2@localhost", "#room2");
itemsResponder->addRoom("#room@localhost", "#room");
boost::shared_ptr<Swift::DiscoInfo> payload(new Swift::DiscoInfo());
boost::shared_ptr<Swift::IQ> iq = Swift::IQ::createRequest(Swift::IQ::Get, Swift::JID("localhost"), "id", payload);
iq->setFrom("user@localhost");
iq->setTo("#room2@localhost");
injectIQ(iq);
loop->processEvents();
CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
CPPUNIT_ASSERT(dynamic_cast<Swift::IQ *>(getStanza(received[0])));
CPPUNIT_ASSERT_EQUAL(Swift::IQ::Result, dynamic_cast<Swift::IQ *>(getStanza(received[0]))->getType());
CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::DiscoInfo>());
CPPUNIT_ASSERT_EQUAL(std::string("#room2"), getStanza(received[0])->getPayload<Swift::DiscoInfo>()->getIdentities()[0].getName());
CPPUNIT_ASSERT_EQUAL(std::string("conference"), getStanza(received[0])->getPayload<Swift::DiscoInfo>()->getIdentities()[0].getCategory());
CPPUNIT_ASSERT_EQUAL(std::string("text"), getStanza(received[0])->getPayload<Swift::DiscoInfo>()->getIdentities()[0].getType());
}
void roomInfo() {
itemsResponder->addRoom("#room@localhost", "#room");