summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Swift/Controllers/Chat/ChatsManager.cpp16
-rw-r--r--Swift/Controllers/Chat/ChatsManager.h5
-rw-r--r--Swift/Controllers/Chat/MUCController.cpp8
-rw-r--r--Swift/Controllers/Chat/MUCController.h4
-rw-r--r--Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp14
-rw-r--r--Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp34
-rw-r--r--Swift/Controllers/MainController.cpp4
-rw-r--r--Swift/Controllers/RosterController.cpp18
-rw-r--r--Swift/Controllers/RosterController.h11
-rw-r--r--Swift/Controllers/UnitTest/RosterControllerTest.cpp10
-rw-r--r--Swiften/Client/Client.cpp21
-rw-r--r--Swiften/Client/Client.h23
-rw-r--r--Swiften/MUC/MUC.cpp9
-rw-r--r--Swiften/MUC/MUC.h20
-rw-r--r--Swiften/MUC/MUCManager.cpp18
-rw-r--r--Swiften/MUC/MUCManager.h29
-rw-r--r--Swiften/Presence/DirectedPresenceSender.cpp66
-rw-r--r--Swiften/Presence/DirectedPresenceSender.h33
-rw-r--r--Swiften/Presence/PresenceOracle.cpp5
-rw-r--r--Swiften/Presence/PresenceOracle.h2
-rw-r--r--Swiften/Presence/PresenceSender.cpp73
-rw-r--r--Swiften/Presence/PresenceSender.h22
-rw-r--r--Swiften/Presence/StanzaChannelPresenceSender.cpp23
-rw-r--r--Swiften/Presence/StanzaChannelPresenceSender.h25
-rw-r--r--Swiften/Presence/SubscriptionManager.cpp57
-rw-r--r--Swiften/Presence/SubscriptionManager.h41
-rw-r--r--Swiften/Presence/UnitTest/DirectedPresenceSenderTest.cpp (renamed from Swiften/Presence/UnitTest/PresenceSenderTest.cpp)28
-rw-r--r--Swiften/Presence/UnitTest/PresenceOracleTest.cpp6
-rw-r--r--Swiften/SConscript6
29 files changed, 446 insertions, 185 deletions
diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp
index 4a9e164..5a32ced 100644
--- a/Swift/Controllers/Chat/ChatsManager.cpp
+++ b/Swift/Controllers/Chat/ChatsManager.cpp
@@ -18,6 +18,7 @@
#include "Swift/Controllers/UIEvents/EditMUCBookmarkUIEvent.h"
#include "Swift/Controllers/UIInterfaces/ChatListWindowFactory.h"
#include "Swiften/Presence/PresenceSender.h"
+#include "Swiften/MUC/MUCManager.h"
#include "Swiften/Elements/ChatState.h"
#include "Swiften/MUC/MUCBookmarkManager.h"
@@ -26,7 +27,7 @@ namespace Swift {
typedef std::pair<JID, ChatController*> JIDChatControllerPair;
typedef std::pair<JID, MUCController*> JIDMUCControllerPair;
-ChatsManager::ChatsManager(JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRouter, EventController* eventController, ChatWindowFactory* chatWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, PresenceSender* presenceSender, UIEventStream* uiEventStream, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency, TimerFactory* timerFactory, MUCRegistry* mucRegistry, EntityCapsManager* entityCapsManager) : jid_(jid), useDelayForLatency_(useDelayForLatency), mucRegistry_(mucRegistry), entityCapsManager_(entityCapsManager) {
+ChatsManager::ChatsManager(JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRouter, EventController* eventController, ChatWindowFactory* chatWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, PresenceSender* presenceSender, UIEventStream* uiEventStream, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency, TimerFactory* timerFactory, MUCRegistry* mucRegistry, EntityCapsManager* entityCapsManager, MUCManager* mucManager) : jid_(jid), useDelayForLatency_(useDelayForLatency), mucRegistry_(mucRegistry), entityCapsManager_(entityCapsManager), mucManager(mucManager) {
timerFactory_ = timerFactory;
eventController_ = eventController;
stanzaChannel_ = stanzaChannel;
@@ -83,7 +84,6 @@ void ChatsManager::handleUserLeftMUC(MUCController* mucController) {
std::map<JID, MUCController*>::iterator it;
for (it = mucControllers_.begin(); it != mucControllers_.end(); it++) {
if ((*it).second == mucController) {
- mucRegistry_->removeMUC(it->first);
mucControllers_.erase(it);
delete mucController;
return;
@@ -214,19 +214,19 @@ void ChatsManager::rebindControllerJID(const JID& from, const JID& to) {
chatControllers_[to]->setToJID(to);
}
-void ChatsManager::handleJoinMUCRequest(const JID &muc, const boost::optional<String>& nickMaybe) {
- std::map<JID, MUCController*>::iterator it = mucControllers_.find(muc);
+void ChatsManager::handleJoinMUCRequest(const JID &mucJID, const boost::optional<String>& nickMaybe) {
+ std::map<JID, MUCController*>::iterator it = mucControllers_.find(mucJID);
if (it != mucControllers_.end()) {
it->second->rejoin();
} else {
String nick = nickMaybe ? nickMaybe.get() : jid_.getNode();
- MUCController* controller = new MUCController(jid_, muc, nick, stanzaChannel_, presenceSender_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory_, eventController_);
- mucControllers_[muc] = controller;
+ MUC::ref muc = mucManager->createMUC(mucJID);
+ MUCController* controller = new MUCController(jid_, muc, nick, stanzaChannel_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory_, eventController_);
+ mucControllers_[mucJID] = controller;
controller->setAvailableServerFeatures(serverDiscoInfo_);
controller->onUserLeft.connect(boost::bind(&ChatsManager::handleUserLeftMUC, this, controller));
- mucRegistry_->addMUC(muc);
}
- mucControllers_[muc]->activateChatWindow();
+ mucControllers_[mucJID]->activateChatWindow();
}
void ChatsManager::handleIncomingMessage(boost::shared_ptr<Message> message) {
diff --git a/Swift/Controllers/Chat/ChatsManager.h b/Swift/Controllers/Chat/ChatsManager.h
index 724701c..0880f80 100644
--- a/Swift/Controllers/Chat/ChatsManager.h
+++ b/Swift/Controllers/Chat/ChatsManager.h
@@ -23,6 +23,7 @@ namespace Swift {
class EventController;
class ChatController;
class MUCController;
+ class MUCManager;
class ChatWindowFactory;
class NickResolver;
class PresenceOracle;
@@ -35,10 +36,11 @@ namespace Swift {
class ChatListWindowFactory;
class TimerFactory;
class EntityCapsManager;
+ class DirectedPresenceSender;
class ChatsManager {
public:
- ChatsManager(JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRouter, EventController* eventController, ChatWindowFactory* chatWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, PresenceSender* presenceSender, UIEventStream* uiEventStream, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency, TimerFactory* timerFactory, MUCRegistry* mucRegistry, EntityCapsManager* entityCapsManager);
+ ChatsManager(JID jid, StanzaChannel* stanzaChannel, IQRouter* iqRouter, EventController* eventController, ChatWindowFactory* chatWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, PresenceSender* presenceSender, UIEventStream* uiEventStream, ChatListWindowFactory* chatListWindowFactory, bool useDelayForLatency, TimerFactory* timerFactory, MUCRegistry* mucRegistry, EntityCapsManager* entityCapsManager, MUCManager* mucManager);
virtual ~ChatsManager();
void setAvatarManager(AvatarManager* avatarManager);
void setOnline(bool enabled);
@@ -78,5 +80,6 @@ namespace Swift {
TimerFactory* timerFactory_;
MUCRegistry* mucRegistry_;
EntityCapsManager* entityCapsManager_;
+ MUCManager* mucManager;
};
}
diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp
index ff102e7..259b715 100644
--- a/Swift/Controllers/Chat/MUCController.cpp
+++ b/Swift/Controllers/Chat/MUCController.cpp
@@ -36,10 +36,9 @@ namespace Swift {
*/
MUCController::MUCController (
const JID& self,
- const JID &muc,
+ MUC::ref muc,
const String &nick,
StanzaChannel* stanzaChannel,
- PresenceSender* presenceSender,
IQRouter* iqRouter,
ChatWindowFactory* chatWindowFactory,
PresenceOracle* presenceOracle,
@@ -48,7 +47,7 @@ MUCController::MUCController (
bool useDelayForLatency,
TimerFactory* timerFactory,
EventController* eventController) :
- ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, muc, presenceOracle, avatarManager, useDelayForLatency, uiEventStream, eventController, timerFactory), muc_(new MUC(stanzaChannel, iqRouter, presenceSender, muc)), nick_(nick) {
+ ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, muc->getJID(), presenceOracle, avatarManager, useDelayForLatency, uiEventStream, eventController, timerFactory), muc_(muc), nick_(nick) {
parting_ = true;
joined_ = false;
lastWasPresence_ = false;
@@ -59,7 +58,7 @@ MUCController::MUCController (
completer_ = new TabComplete();
chatWindow_->setRosterModel(roster_);
chatWindow_->setTabComplete(completer_);
- chatWindow_->setName(muc.getNode());
+ chatWindow_->setName(muc->getJID().getNode());
chatWindow_->onClosed.connect(boost::bind(&MUCController::handleWindowClosed, this));
muc_->onJoinComplete.connect(boost::bind(&MUCController::handleJoinComplete, this, _1));
muc_->onJoinFailed.connect(boost::bind(&MUCController::handleJoinFailed, this, _1));
@@ -80,7 +79,6 @@ MUCController::MUCController (
}
MUCController::~MUCController() {
- delete muc_;
chatWindow_->setRosterModel(NULL);
delete roster_;
if (loginCheckTimer_) {
diff --git a/Swift/Controllers/Chat/MUCController.h b/Swift/Controllers/Chat/MUCController.h
index 2a6536c..1af9c58 100644
--- a/Swift/Controllers/Chat/MUCController.h
+++ b/Swift/Controllers/Chat/MUCController.h
@@ -41,7 +41,7 @@ namespace Swift {
class MUCController : public ChatControllerBase {
public:
- MUCController(const JID& self, const JID &muc, const String &nick, StanzaChannel* stanzaChannel, PresenceSender* presenceSender, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, PresenceOracle* presenceOracle, AvatarManager* avatarManager, UIEventStream* events, bool useDelayForLatency, TimerFactory* timerFactory, EventController* eventController);
+ MUCController(const JID& self, MUC::ref muc, const String &nick, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, PresenceOracle* presenceOracle, AvatarManager* avatarManager, UIEventStream* events, bool useDelayForLatency, TimerFactory* timerFactory, EventController* eventController);
~MUCController();
boost::signal<void ()> onUserLeft;
virtual void setOnline(bool online);
@@ -80,7 +80,7 @@ namespace Swift {
void processUserPart();
private:
- MUC* muc_;
+ MUC::ref muc_;
UIEventStream* events_;
String nick_;
Roster* roster_;
diff --git a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
index 44fbcfe..08106e6 100644
--- a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
+++ b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
@@ -16,15 +16,17 @@
#include "Swiften/Client/Client.h"
#include "Swiften/Disco/EntityCapsManager.h"
#include "Swiften/Disco/CapsProvider.h"
+#include "Swiften/MUC/MUCManager.h"
#include "Swift/Controllers/Chat/ChatController.h"
#include "Swift/Controllers/XMPPEvents/EventController.h"
#include "Swift/Controllers/Chat/MUCController.h"
-#include "Swiften/Presence/PresenceSender.h"
+#include "Swiften/Presence/StanzaChannelPresenceSender.h"
#include "Swiften/Avatars/NullAvatarManager.h"
#include "Swiften/Avatars/AvatarMemoryStorage.h"
#include "Swiften/VCards/VCardManager.h"
#include "Swiften/VCards/VCardMemoryStorage.h"
#include "Swiften/Client/NickResolver.h"
+#include "Swiften/Presence/DirectedPresenceSender.h"
#include "Swiften/Roster/XMPPRosterImpl.h"
#include "Swift/Controllers/UnitTest/MockChatWindow.h"
#include "Swiften/Client/DummyStanzaChannel.h"
@@ -71,12 +73,14 @@ public:
nickResolver_ = new NickResolver(jid_.toBare(), xmppRoster_, NULL, mucRegistry_);
presenceOracle_ = new PresenceOracle(stanzaChannel_);
serverDiscoInfo_ = boost::shared_ptr<DiscoInfo>(new DiscoInfo());
- presenceSender_ = new PresenceSender(stanzaChannel_);
+ presenceSender_ = new StanzaChannelPresenceSender(stanzaChannel_);
+ directedPresenceSender_ = new DirectedPresenceSender(presenceSender_);
+ mucManager_ = new MUCManager(stanzaChannel_, iqRouter_, directedPresenceSender_, mucRegistry_);
uiEventStream_ = new UIEventStream();
entityCapsManager_ = new EntityCapsManager(capsProvider_, stanzaChannel_);
chatListWindowFactory_ = mocks_->InterfaceMock<ChatListWindowFactory>();
mocks_->ExpectCall(chatListWindowFactory_, ChatListWindowFactory::createWindow).With(uiEventStream_).Return(NULL);
- manager_ = new ChatsManager(jid_, stanzaChannel_, iqRouter_, eventController_, chatWindowFactory_, nickResolver_, presenceOracle_, presenceSender_, uiEventStream_, chatListWindowFactory_, true, NULL, mucRegistry_, entityCapsManager_);
+ manager_ = new ChatsManager(jid_, stanzaChannel_, iqRouter_, eventController_, chatWindowFactory_, nickResolver_, presenceOracle_, directedPresenceSender_, uiEventStream_, chatListWindowFactory_, true, NULL, mucRegistry_, entityCapsManager_, mucManager_);
avatarManager_ = new NullAvatarManager();
manager_->setAvatarManager(avatarManager_);
@@ -87,6 +91,7 @@ public:
delete mocks_;
delete avatarManager_;
delete manager_;
+ delete directedPresenceSender_;
delete presenceSender_;
delete presenceOracle_;
delete nickResolver_;
@@ -96,6 +101,7 @@ public:
delete iqChannel_;
delete iqRouter_;
delete uiEventStream_;
+ delete mucManager_;
delete xmppRoster_;
delete entityCapsManager_;
delete capsProvider_;
@@ -329,8 +335,10 @@ private:
UIEventStream* uiEventStream_;
ChatListWindowFactory* chatListWindowFactory_;
MUCRegistry* mucRegistry_;
+ DirectedPresenceSender* directedPresenceSender_;
EntityCapsManager* entityCapsManager_;
CapsProvider* capsProvider_;
+ MUCManager* mucManager_;
};
CPPUNIT_TEST_SUITE_REGISTRATION(ChatsManagerTest);
diff --git a/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp b/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp
index ea5a705..fb3a0ee 100644
--- a/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp
+++ b/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp
@@ -9,7 +9,8 @@
#include "3rdParty/hippomocks.h"
#include "Swift/Controllers/XMPPEvents/EventController.h"
-#include "Swiften/Presence/PresenceSender.h"
+#include "Swiften/Presence/DirectedPresenceSender.h"
+#include "Swiften/Presence/StanzaChannelPresenceSender.h"
#include "Swiften/Avatars/NullAvatarManager.h"
#include "Swift/Controllers/Chat/MUCController.h"
#include "Swift/Controllers/UIInterfaces/ChatWindow.h"
@@ -42,7 +43,6 @@ public:
void setUp() {
self_ = JID("girl@wonderland.lit/rabbithole");
- muc_ = JID("teaparty@rooms.wonderland.lit");
nick_ = "aLiCe";
mocks_ = new MockRepository();
stanzaChannel_ = new DummyStanzaChannel();
@@ -51,14 +51,16 @@ public:
eventController_ = new EventController();
chatWindowFactory_ = mocks_->InterfaceMock<ChatWindowFactory>();
presenceOracle_ = new PresenceOracle(stanzaChannel_);
- presenceSender_ = new PresenceSender(stanzaChannel_);
+ presenceSender_ = new StanzaChannelPresenceSender(stanzaChannel_);
+ directedPresenceSender_ = new DirectedPresenceSender(presenceSender_);
uiEventStream_ = new UIEventStream();
avatarManager_ = new NullAvatarManager();
TimerFactory* timerFactory = NULL;
window_ = new MockChatWindow();//mocks_->InterfaceMock<ChatWindow>();
- mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(muc_, uiEventStream_).Return(window_);
- controller_ = new MUCController (self_, muc_, nick_, stanzaChannel_, presenceSender_,
- iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory, eventController_);
+ mucRegistry_ = new MUCRegistry();
+ muc_ = MUC::ref(new MUC(stanzaChannel_, iqRouter_, directedPresenceSender_, JID("teaparty@rooms.wonderland.lit"), mucRegistry_));
+ mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(muc_->getJID(), uiEventStream_).Return(window_);
+ controller_ = new MUCController (self_, muc_, nick_, stanzaChannel_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory, eventController_);
};
void tearDown() {
@@ -69,14 +71,16 @@ public:
delete uiEventStream_;
delete stanzaChannel_;
delete presenceSender_;
+ delete directedPresenceSender_;
delete iqRouter_;
delete iqChannel_;
+ delete mucRegistry_;
delete avatarManager_;
}
void finishJoin() {
Presence::ref presence(new Presence());
- presence->setFrom(JID(muc_.toString() + "/" + nick_));
+ presence->setFrom(JID(muc_->getJID().toString() + "/" + nick_));
MUCUserPayload::ref status(new MUCUserPayload());
MUCUserPayload::StatusCode code;
code.code = 110;
@@ -90,20 +94,20 @@ public:
Message::ref message(new Message());
message = Message::ref(new Message());
- message->setFrom(JID(muc_.toString() + "/otherperson"));
+ message->setFrom(JID(muc_->getJID().toString() + "/otherperson"));
message->setBody(nick_ + ": hi there");
message->setType(Message::Groupchat);
controller_->handleIncomingMessage(MessageEvent::ref(new MessageEvent(message)));
CPPUNIT_ASSERT_EQUAL((size_t)1, eventController_->getEvents().size());
- message->setFrom(JID(muc_.toString() + "/other"));
+ message->setFrom(JID(muc_->getJID().toString() + "/other"));
message->setBody("Hi there " + nick_);
message->setType(Message::Groupchat);
controller_->handleIncomingMessage(MessageEvent::ref(new MessageEvent(message)));
CPPUNIT_ASSERT_EQUAL((size_t)2, eventController_->getEvents().size());
message = Message::ref(new Message());
- message->setFrom(JID(muc_.toString() + "/other2"));
+ message->setFrom(JID(muc_->getJID().toString() + "/other2"));
message->setBody("Hi " + nick_.getLowerCase());
message->setType(Message::Groupchat);
controller_->handleIncomingMessage(MessageEvent::ref(new MessageEvent(message)));
@@ -113,7 +117,7 @@ public:
void testNotAddressedToSelf() {
finishJoin();
Message::ref message(new Message());
- message->setFrom(JID(muc_.toString() + "/other3"));
+ message->setFrom(JID(muc_->getJID().toString() + "/other3"));
message->setBody("Hi there Hatter");
message->setType(Message::Groupchat);
controller_->handleIncomingMessage(MessageEvent::ref(new MessageEvent(message)));
@@ -123,7 +127,7 @@ public:
void testAddressedToSelfBySelf() {
finishJoin();
Message::ref message(new Message());
- message->setFrom(JID(muc_.toString() + "/" + nick_));
+ message->setFrom(JID(muc_->getJID().toString() + "/" + nick_));
message->setBody("Hi there " + nick_);
message->setType(Message::Groupchat);
controller_->handleIncomingMessage(MessageEvent::ref(new MessageEvent(message)));
@@ -200,7 +204,7 @@ public:
private:
JID self_;
- JID muc_;
+ MUC::ref muc_;
String nick_;
StanzaChannel* stanzaChannel_;
IQChannel* iqChannel_;
@@ -211,10 +215,12 @@ private:
// NickResolver* nickResolver_;
PresenceOracle* presenceOracle_;
AvatarManager* avatarManager_;
- PresenceSender* presenceSender_;
+ StanzaChannelPresenceSender* presenceSender_;
+ DirectedPresenceSender* directedPresenceSender_;
MockRepository* mocks_;
UIEventStream* uiEventStream_;
MockChatWindow* window_;
+ MUCRegistry* mucRegistry_;
};
CPPUNIT_TEST_SUITE_REGISTRATION(MUCControllerTest);
diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp
index 4501f2c..f3b9977 100644
--- a/Swift/Controllers/MainController.cpp
+++ b/Swift/Controllers/MainController.cpp
@@ -231,11 +231,11 @@ void MainController::handleConnected() {
bool freshLogin = rosterController_ == NULL;
myStatusLooksOnline_ = true;
if (freshLogin) {
- rosterController_ = new RosterController(jid_, client_->getRoster(), client_->getAvatarManager(), mainWindowFactory_, client_->getNickResolver(), client_->getPresenceOracle(), client_->getPresenceSender(), eventController_, uiEventStream_, client_->getIQRouter(), settings_);
+ rosterController_ = new RosterController(jid_, client_->getRoster(), client_->getAvatarManager(), mainWindowFactory_, client_->getNickResolver(), client_->getPresenceOracle(), client_->getSubscriptionManager(), eventController_, uiEventStream_, client_->getIQRouter(), settings_);
rosterController_->onChangeStatusRequest.connect(boost::bind(&MainController::handleChangeStatusRequest, this, _1, _2));
rosterController_->onSignOutRequest.connect(boost::bind(&MainController::signOut, this));
- chatsManager_ = new ChatsManager(jid_, client_->getStanzaChannel(), client_->getIQRouter(), eventController_, chatWindowFactory_, client_->getNickResolver(), client_->getPresenceOracle(), client_->getPresenceSender(), uiEventStream_, chatListWindowFactory_, useDelayForLatency_, &timerFactory_, client_->getMUCRegistry(), client_->getEntityCapsManager());
+ chatsManager_ = new ChatsManager(jid_, client_->getStanzaChannel(), client_->getIQRouter(), eventController_, chatWindowFactory_, client_->getNickResolver(), client_->getPresenceOracle(), client_->getPresenceSender(), uiEventStream_, chatListWindowFactory_, useDelayForLatency_, &timerFactory_, client_->getMUCRegistry(), client_->getEntityCapsManager(), client_->getMUCManager());
client_->onMessageReceived.connect(boost::bind(&ChatsManager::handleIncomingMessage, chatsManager_, _1));
chatsManager_->setAvatarManager(client_->getAvatarManager());
diff --git a/Swift/Controllers/RosterController.cpp b/Swift/Controllers/RosterController.cpp
index 1ce3266..242f974 100644
--- a/Swift/Controllers/RosterController.cpp
+++ b/Swift/Controllers/RosterController.cpp
@@ -17,7 +17,7 @@
#include "Swift/Controllers/XMPPEvents/SubscriptionRequestEvent.h"
#include "Swift/Controllers/XMPPEvents/ErrorEvent.h"
#include "Swiften/Presence/PresenceOracle.h"
-#include "Swiften/Presence/PresenceSender.h"
+#include "Swiften/Presence/SubscriptionManager.h"
#include "Swift/Controllers/XMPPEvents/EventController.h"
#include "Swiften/Queries/IQRouter.h"
#include "Swiften/Roster/Roster.h"
@@ -37,11 +37,11 @@ namespace Swift {
/**
* The controller does not gain ownership of these parameters.
*/
-RosterController::RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, PresenceSender* presenceSender, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter, SettingsProvider* settings)
+RosterController::RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, SubscriptionManager* subscriptionManager, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter, SettingsProvider* settings)
: myJID_(jid), xmppRoster_(xmppRoster), mainWindowFactory_(mainWindowFactory), mainWindow_(mainWindowFactory_->createMainWindow(uiEventStream)), roster_(new Roster()), offlineFilter_(new OfflineRosterFilter()) {
iqRouter_ = iqRouter;
presenceOracle_ = presenceOracle;
- presenceSender_ = presenceSender;
+ subscriptionManager_ = subscriptionManager;
eventController_ = eventController;
expandiness_ = new RosterGroupExpandinessPersister(roster_, settings);
roster_->addFilter(offlineFilter_);
@@ -54,7 +54,7 @@ RosterController::RosterController(const JID& jid, XMPPRoster* xmppRoster, Avata
xmppRoster_->onJIDUpdated.connect(boost::bind(&RosterController::handleOnJIDUpdated, this, _1, _2, _3));
xmppRoster_->onJIDRemoved.connect(boost::bind(&RosterController::handleOnJIDRemoved, this, _1));
xmppRoster_->onRosterCleared.connect(boost::bind(&RosterController::handleRosterCleared, this));
- presenceOracle_->onPresenceSubscriptionRequest.connect(boost::bind(&RosterController::handleSubscriptionRequest, this, _1, _2));
+ subscriptionManager_->onPresenceSubscriptionRequest.connect(boost::bind(&RosterController::handleSubscriptionRequest, this, _1, _2));
presenceOracle_->onPresenceChange.connect(boost::bind(&RosterController::handleIncomingPresence, this, _1));
uiEventConnection_ = uiEventStream->onUIEvent.connect(boost::bind(&RosterController::handleUIEvent, this, _1));
avatarManager_ = avatarManager;
@@ -167,7 +167,7 @@ void RosterController::handleUIEvent(boost::shared_ptr<UIEvent> event) {
SetRosterRequest::ref request = SetRosterRequest::create(roster, iqRouter_);
request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster));
request->send();
- presenceSender_->requestSubscription(addContactEvent->getJID());
+ subscriptionManager_->requestSubscription(addContactEvent->getJID());
return;
}
boost::shared_ptr<RemoveRosterItemUIEvent> removeEvent = boost::dynamic_pointer_cast<RemoveRosterItemUIEvent>(event);
@@ -240,7 +240,7 @@ void RosterController::handleIncomingPresence(Presence::ref newPresence) {
void RosterController::handleSubscriptionRequest(const JID& jid, const String& message) {
if (xmppRoster_->containsJID(jid) && (xmppRoster_->getSubscriptionStateForJID(jid) == RosterItemPayload::To || xmppRoster_->getSubscriptionStateForJID(jid) == RosterItemPayload::Both)) {
- presenceSender_->confirmSubscription(jid);
+ subscriptionManager_->confirmSubscription(jid);
return;
}
SubscriptionRequestEvent* eventPointer = new SubscriptionRequestEvent(jid, message);
@@ -251,14 +251,14 @@ void RosterController::handleSubscriptionRequest(const JID& jid, const String& m
}
void RosterController::handleSubscriptionRequestAccepted(SubscriptionRequestEvent* event) {
- presenceSender_->confirmSubscription(event->getJID());
+ subscriptionManager_->confirmSubscription(event->getJID());
if (!xmppRoster_->containsJID(event->getJID()) || xmppRoster_->getSubscriptionStateForJID(event->getJID()) == RosterItemPayload::None || xmppRoster_->getSubscriptionStateForJID(event->getJID()) == RosterItemPayload::From) {
- presenceSender_->requestSubscription(event->getJID());
+ subscriptionManager_->requestSubscription(event->getJID());
}
}
void RosterController::handleSubscriptionRequestDeclined(SubscriptionRequestEvent* event) {
- presenceSender_->cancelSubscription(event->getJID());
+ subscriptionManager_->cancelSubscription(event->getJID());
}
void RosterController::handleAvatarChanged(const JID& jid) {
diff --git a/Swift/Controllers/RosterController.h b/Swift/Controllers/RosterController.h
index 3cb3812..cc51d23 100644
--- a/Swift/Controllers/RosterController.h
+++ b/Swift/Controllers/RosterController.h
@@ -4,8 +4,7 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#ifndef SWIFTEN_RosterController_H
-#define SWIFTEN_RosterController_H
+#pragma once
#include "Swiften/JID/JID.h"
#include "Swiften/Base/String.h"
@@ -28,7 +27,7 @@ namespace Swift {
class OfflineRosterFilter;
class NickResolver;
class PresenceOracle;
- class PresenceSender;
+ class SubscriptionManager;
class EventController;
class SubscriptionRequestEvent;
class UIEventStream;
@@ -37,7 +36,7 @@ namespace Swift {
class RosterController {
public:
- RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, PresenceSender* presenceSender, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter_, SettingsProvider* settings);
+ RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickResolver* nickResolver, PresenceOracle* presenceOracle, SubscriptionManager* subscriptionManager, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter_, SettingsProvider* settings);
~RosterController();
void showRosterWindow();
MainWindow* getWindow() {return mainWindow_;};
@@ -70,7 +69,7 @@ namespace Swift {
AvatarManager* avatarManager_;
NickResolver* nickResolver_;
PresenceOracle* presenceOracle_;
- PresenceSender* presenceSender_;
+ SubscriptionManager* subscriptionManager_;
EventController* eventController_;
RosterGroupExpandinessPersister* expandiness_;
IQRouter* iqRouter_;
@@ -80,5 +79,3 @@ namespace Swift {
boost::bsignals::scoped_connection uiEventConnection_;
};
}
-#endif
-
diff --git a/Swift/Controllers/UnitTest/RosterControllerTest.cpp b/Swift/Controllers/UnitTest/RosterControllerTest.cpp
index c0c0319..50419f9 100644
--- a/Swift/Controllers/UnitTest/RosterControllerTest.cpp
+++ b/Swift/Controllers/UnitTest/RosterControllerTest.cpp
@@ -24,7 +24,7 @@
#include "Swiften/Avatars/NullAvatarManager.h"
#include "Swift/Controllers/XMPPEvents/EventController.h"
#include "Swiften/Presence/PresenceOracle.h"
-#include "Swiften/Presence/PresenceSender.h"
+#include "Swiften/Presence/SubscriptionManager.h"
#include "Swiften/Client/NickResolver.h"
#include "Swift/Controllers/UIEvents/UIEventStream.h"
#include "Swift/Controllers/UIEvents/RenameRosterItemUIEvent.h"
@@ -63,11 +63,11 @@ class RosterControllerTest : public CppUnit::TestFixture
router_ = new IQRouter(channel_);
stanzaChannel_ = new DummyStanzaChannel();
presenceOracle_ = new PresenceOracle(stanzaChannel_);
- presenceSender_ = new PresenceSender(stanzaChannel_);
+ subscriptionManager_ = new SubscriptionManager(stanzaChannel_);
eventController_ = new EventController();
uiEventStream_ = new UIEventStream();
settings_ = new DummySettingsProvider();
- rosterController_ = new RosterController(jid_, xmppRoster_, avatarManager_, mainWindowFactory_, nickResolver_, presenceOracle_, presenceSender_, eventController_, uiEventStream_, router_, settings_);
+ rosterController_ = new RosterController(jid_, xmppRoster_, avatarManager_, mainWindowFactory_, nickResolver_, presenceOracle_, subscriptionManager_, eventController_, uiEventStream_, router_, settings_);
mainWindow_ = mainWindowFactory_->last;
};
@@ -80,7 +80,7 @@ class RosterControllerTest : public CppUnit::TestFixture
delete channel_;
delete router_;
delete eventController_;
- delete presenceSender_;
+ delete subscriptionManager_;
delete presenceOracle_;
delete stanzaChannel_;
delete uiEventStream_;
@@ -310,7 +310,7 @@ class RosterControllerTest : public CppUnit::TestFixture
DummyStanzaChannel* stanzaChannel_;
IQRouter* router_;
PresenceOracle* presenceOracle_;
- PresenceSender* presenceSender_;
+ SubscriptionManager* subscriptionManager_;
EventController* eventController_;
UIEventStream* uiEventStream_;
MockMainWindow* mainWindow_;
diff --git a/Swiften/Client/Client.cpp b/Swiften/Client/Client.cpp
index 45eeeff..7dbcb70 100644
--- a/Swiften/Client/Client.cpp
+++ b/Swiften/Client/Client.cpp
@@ -10,8 +10,10 @@
#include "Swiften/Roster/XMPPRosterImpl.h"
#include "Swiften/Roster/XMPPRosterController.h"
#include "Swiften/Presence/PresenceOracle.h"
-#include "Swiften/Presence/PresenceSender.h"
+#include "Swiften/Presence/StanzaChannelPresenceSender.h"
+#include "Swiften/Presence/DirectedPresenceSender.h"
#include "Swiften/MUC/MUCRegistry.h"
+#include "Swiften/MUC/MUCManager.h"
#include "Swiften/Client/MemoryStorages.h"
#include "Swiften/VCards/VCardManager.h"
#include "Swiften/VCards/VCardManager.h"
@@ -19,6 +21,7 @@
#include "Swiften/Disco/CapsManager.h"
#include "Swiften/Disco/EntityCapsManager.h"
#include "Swiften/Client/NickResolver.h"
+#include "Swiften/Presence/SubscriptionManager.h"
namespace Swift {
@@ -31,13 +34,16 @@ Client::Client(EventLoop* eventLoop, const JID& jid, const String& password, Sto
roster = new XMPPRosterImpl();
rosterController = new XMPPRosterController(getIQRouter(), roster);
+ subscriptionManager = new SubscriptionManager(getStanzaChannel());
+
presenceOracle = new PresenceOracle(getStanzaChannel());
presenceOracle->onPresenceChange.connect(boost::ref(onPresenceChange));
- presenceOracle->onPresenceSubscriptionRequest.connect(boost::ref(onPresenceSubscriptionRequest));
- presenceSender = new PresenceSender(getStanzaChannel());
+ stanzaChannelPresenceSender = new StanzaChannelPresenceSender(getStanzaChannel());
+ directedPresenceSender = new DirectedPresenceSender(stanzaChannelPresenceSender);
mucRegistry = new MUCRegistry();
+ mucManager = new MUCManager(getStanzaChannel(), getIQRouter(), directedPresenceSender, mucRegistry);
vcardManager = new VCardManager(jid, getIQRouter(), getStorages()->getVCardStorage());
avatarManager = new AvatarManagerImpl(vcardManager, getStanzaChannel(), getStorages()->getAvatarStorage(), mucRegistry);
@@ -55,11 +61,14 @@ Client::~Client() {
delete avatarManager;
delete vcardManager;
+ delete mucManager;
delete mucRegistry;
- delete presenceSender;
+ delete directedPresenceSender;
+ delete stanzaChannelPresenceSender;
delete presenceOracle;
+ delete subscriptionManager;
delete rosterController;
delete roster;
@@ -81,7 +90,6 @@ void Client::requestRoster() {
rosterController->requestRoster();
}
-
Presence::ref Client::getLastPresence(const JID& jid) const {
return presenceOracle->getLastPresence(jid);
}
@@ -97,5 +105,8 @@ Storages* Client::getStorages() const {
return memoryStorages;
}
+PresenceSender* Client::getPresenceSender() const {
+ return directedPresenceSender;
+}
}
diff --git a/Swiften/Client/Client.h b/Swiften/Client/Client.h
index 7e11df9..adfd549 100644
--- a/Swiften/Client/Client.h
+++ b/Swiften/Client/Client.h
@@ -12,9 +12,12 @@ namespace Swift {
class SoftwareVersionResponder;
class XMPPRoster;
class XMPPRosterImpl;
+ class MUCManager;
class XMPPRosterController;
class PresenceOracle;
class PresenceSender;
+ class DirectedPresenceSender;
+ class StanzaChannelPresenceSender;
class MUCRegistry;
class Storages;
class MemoryStorages;
@@ -23,6 +26,7 @@ namespace Swift {
class CapsManager;
class EntityCapsManager;
class NickResolver;
+ class SubscriptionManager;
/**
* Provides the core functionality for writing XMPP client software.
@@ -88,8 +92,10 @@ namespace Swift {
return presenceOracle;
}
- PresenceSender* getPresenceSender() const {
- return presenceSender;
+ PresenceSender* getPresenceSender() const;
+
+ MUCManager* getMUCManager() const {
+ return mucManager;
}
MUCRegistry* getMUCRegistry() const {
@@ -112,15 +118,17 @@ namespace Swift {
return nickResolver;
}
+ SubscriptionManager* getSubscriptionManager() const {
+ return subscriptionManager;
+ }
+
public:
/**
* This signal is emitted when a JID changes presence.
*/
boost::signal<void (Presence::ref)> onPresenceChange;
- /**
- * This signal is emitted when a presence subscription request is received.
- */
+
boost::signal<void (const JID&, const String&)> onPresenceSubscriptionRequest;
private:
@@ -133,12 +141,15 @@ namespace Swift {
XMPPRosterImpl* roster;
XMPPRosterController* rosterController;
PresenceOracle* presenceOracle;
- PresenceSender* presenceSender;
+ DirectedPresenceSender* directedPresenceSender;
+ StanzaChannelPresenceSender* stanzaChannelPresenceSender;
MUCRegistry* mucRegistry;
VCardManager* vcardManager;
AvatarManager* avatarManager;
CapsManager* capsManager;
EntityCapsManager* entityCapsManager;
NickResolver* nickResolver;
+ SubscriptionManager* subscriptionManager;
+ MUCManager* mucManager;
};
}
diff --git a/Swiften/MUC/MUC.cpp b/Swiften/MUC/MUC.cpp
index cfd468c..9f7c500 100644
--- a/Swiften/MUC/MUC.cpp
+++ b/Swiften/MUC/MUC.cpp
@@ -9,7 +9,7 @@
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
-#include "Swiften/Presence/PresenceSender.h"
+#include "Swiften/Presence/DirectedPresenceSender.h"
#include "Swiften/Client/StanzaChannel.h"
#include "Swiften/Queries/IQRouter.h"
#include "Swiften/Elements/Form.h"
@@ -17,13 +17,15 @@
#include "Swiften/Elements/MUCUserPayload.h"
#include "Swiften/Elements/MUCOwnerPayload.h"
#include "Swiften/Elements/MUCPayload.h"
+#include "Swiften/MUC/MUCRegistry.h"
namespace Swift {
typedef std::pair<String, MUCOccupant> StringMUCOccupantPair;
-MUC::MUC(StanzaChannel* stanzaChannel, IQRouter* iqRouter, PresenceSender* presenceSender, const JID &muc) : ownMUCJID(muc), stanzaChannel(stanzaChannel), iqRouter_(iqRouter), presenceSender(presenceSender), muc_(muc) {
+MUC::MUC(StanzaChannel* stanzaChannel, IQRouter* iqRouter, DirectedPresenceSender* presenceSender, const JID &muc, MUCRegistry* mucRegistry) : ownMUCJID(muc), stanzaChannel(stanzaChannel), iqRouter_(iqRouter), presenceSender(presenceSender), mucRegistry(mucRegistry) {
scopedConnection_ = stanzaChannel->onPresenceReceived.connect(boost::bind(&MUC::handleIncomingPresence, this, _1));
+ mucRegistry->addMUC(getJID());
}
//FIXME: discover reserved nickname
@@ -57,6 +59,7 @@ void MUC::joinWithContextSince(const String &nick) {
void MUC::part() {
presenceSender->removeDirectedPresenceReceiver(ownMUCJID);
+ mucRegistry->removeMUC(getJID());
}
void MUC::handleUserLeft(LeavingType type) {
@@ -157,7 +160,7 @@ void MUC::handleIncomingPresence(boost::shared_ptr<Presence> presence) {
/* Currently deal with this by making an instant room */
boost::shared_ptr<MUCOwnerPayload> mucPayload(new MUCOwnerPayload());
mucPayload->setPayload(boost::shared_ptr<Payload>(new Form(Form::SubmitType)));
- boost::shared_ptr<IQ> iq(IQ::createRequest(IQ::Set, muc_, iqRouter_->getNewIQID(), mucPayload));
+ boost::shared_ptr<IQ> iq(IQ::createRequest(IQ::Set, getJID(), iqRouter_->getNewIQID(), mucPayload));
iqRouter_->sendIQ(iq);
}
}
diff --git a/Swiften/MUC/MUC.h b/Swiften/MUC/MUC.h
index ea20ac4..29dbbe1 100644
--- a/Swiften/MUC/MUC.h
+++ b/Swiften/MUC/MUC.h
@@ -11,6 +11,7 @@
#include "Swiften/Elements/Message.h"
#include "Swiften/Elements/Presence.h"
#include "Swiften/MUC/MUCOccupant.h"
+#include "Swiften/MUC/MUCRegistry.h"
#include <boost/shared_ptr.hpp>
#include "Swiften/Base/boost_bsignals.h"
@@ -21,15 +22,24 @@
namespace Swift {
class StanzaChannel;
class IQRouter;
- class PresenceSender;
+ class DirectedPresenceSender;
class MUC {
public:
+ typedef boost::shared_ptr<MUC> ref;
+
enum JoinResult { JoinSucceeded, JoinFailed };
- enum LeavingType { Part, Disconnect };
+ enum LeavingType { Part, Disconnect };
public:
- MUC(StanzaChannel* stanzaChannel, IQRouter* iqRouter, PresenceSender* presenceSender, const JID &muc);
+ MUC(StanzaChannel* stanzaChannel, IQRouter* iqRouter, DirectedPresenceSender* presenceSender, const JID &muc, MUCRegistry* mucRegistry);
+
+ /**
+ * Returns the (bare) JID of the MUC.
+ */
+ JID getJID() const {
+ return ownMUCJID.toBare();
+ }
void joinAs(const String &nick);
void joinWithContextSince(const String &nick);
@@ -70,8 +80,8 @@ namespace Swift {
JID ownMUCJID;
StanzaChannel* stanzaChannel;
IQRouter* iqRouter_;
- PresenceSender* presenceSender;
- JID muc_;
+ DirectedPresenceSender* presenceSender;
+ MUCRegistry* mucRegistry;
std::map<String, MUCOccupant> occupants;
bool joinComplete_;
boost::bsignals::scoped_connection scopedConnection_;
diff --git a/Swiften/MUC/MUCManager.cpp b/Swiften/MUC/MUCManager.cpp
new file mode 100644
index 0000000..8950029
--- /dev/null
+++ b/Swiften/MUC/MUCManager.cpp
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include "Swiften/MUC/MUCManager.h"
+
+namespace Swift {
+
+MUCManager::MUCManager(StanzaChannel* stanzaChannel, IQRouter* iqRouter, DirectedPresenceSender* presenceSender, MUCRegistry* mucRegistry) : stanzaChannel(stanzaChannel), iqRouter(iqRouter), presenceSender(presenceSender), mucRegistry(mucRegistry) {
+}
+
+MUC::ref MUCManager::createMUC(const JID& jid) {
+ return MUC::ref(new MUC(stanzaChannel, iqRouter, presenceSender, jid, mucRegistry));
+}
+
+}
diff --git a/Swiften/MUC/MUCManager.h b/Swiften/MUC/MUCManager.h
new file mode 100644
index 0000000..0efdf9a
--- /dev/null
+++ b/Swiften/MUC/MUCManager.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include "Swiften/MUC/MUC.h"
+
+namespace Swift {
+ class IQRouter;
+ class StanzaChannel;
+ class DirectedPresenceSender;
+ class MUCRegistry;
+
+ class MUCManager {
+ public:
+ MUCManager(StanzaChannel* stanzaChannel, IQRouter* iqRouter, DirectedPresenceSender* presenceSender, MUCRegistry* mucRegistry);
+
+ MUC::ref createMUC(const JID&);
+
+ private:
+ StanzaChannel* stanzaChannel;
+ IQRouter* iqRouter;
+ DirectedPresenceSender* presenceSender;
+ MUCRegistry* mucRegistry;
+ };
+}
diff --git a/Swiften/Presence/DirectedPresenceSender.cpp b/Swiften/Presence/DirectedPresenceSender.cpp
new file mode 100644
index 0000000..aade6cf
--- /dev/null
+++ b/Swiften/Presence/DirectedPresenceSender.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include "Swiften/Presence/DirectedPresenceSender.h"
+#include "Swiften/Base/foreach.h"
+
+namespace Swift {
+
+DirectedPresenceSender::DirectedPresenceSender(PresenceSender* sender) : sender(sender) {
+}
+
+void DirectedPresenceSender::sendPresence(boost::shared_ptr<Presence> presence) {
+ if (!sender->isAvailable()) {
+ return;
+ }
+
+ sender->sendPresence(presence);
+
+ if (!presence->getTo().isValid()) {
+ boost::shared_ptr<Presence> presenceCopy(new Presence(*presence));
+ foreach(const JID& jid, directedPresenceReceivers) {
+ presenceCopy->setTo(jid);
+ sender->sendPresence(presenceCopy);
+ }
+
+ lastSentUndirectedPresence = presence;
+ }
+}
+
+/**
+ * Gets either the last broadcast presence, or an empty stanza if none has been sent.
+ */
+boost::shared_ptr<Presence> DirectedPresenceSender::getLastSentUndirectedPresence() {
+ boost::shared_ptr<Presence> presenceCopy(lastSentUndirectedPresence ? new Presence(*lastSentUndirectedPresence) : new Presence());
+ return presenceCopy;
+}
+
+void DirectedPresenceSender::addDirectedPresenceReceiver(const JID& jid) {
+ directedPresenceReceivers.insert(jid);
+ if (sender->isAvailable()) {
+ if (lastSentUndirectedPresence && lastSentUndirectedPresence->getType() == Presence::Available) {
+ boost::shared_ptr<Presence> presenceCopy(new Presence(*lastSentUndirectedPresence));
+ presenceCopy->setTo(jid);
+ sender->sendPresence(presenceCopy);
+ }
+ }
+}
+
+void DirectedPresenceSender::removeDirectedPresenceReceiver(const JID& jid) {
+ directedPresenceReceivers.erase(jid);
+ if (sender->isAvailable()) {
+ boost::shared_ptr<Presence> presence(new Presence());
+ presence->setType(Presence::Unavailable);
+ presence->setTo(jid);
+ sender->sendPresence(presence);
+ }
+}
+
+bool DirectedPresenceSender::isAvailable() const {
+ return sender->isAvailable();
+}
+
+}
diff --git a/Swiften/Presence/DirectedPresenceSender.h b/Swiften/Presence/DirectedPresenceSender.h
new file mode 100644
index 0000000..b63a50e
--- /dev/null
+++ b/Swiften/Presence/DirectedPresenceSender.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <set>
+
+#include "Swiften/Elements/Presence.h"
+#include "Swiften/Presence/PresenceSender.h"
+
+namespace Swift {
+ class DirectedPresenceSender : public PresenceSender {
+ public:
+ DirectedPresenceSender(PresenceSender*);
+
+ void addDirectedPresenceReceiver(const JID&);
+ void removeDirectedPresenceReceiver(const JID&);
+
+ void sendPresence(Presence::ref);
+
+ Presence::ref getLastSentUndirectedPresence();
+
+ bool isAvailable() const;
+
+ private:
+ Presence::ref lastSentUndirectedPresence;
+ PresenceSender* sender;
+ std::set<JID> directedPresenceReceivers;
+ };
+}
diff --git a/Swiften/Presence/PresenceOracle.cpp b/Swiften/Presence/PresenceOracle.cpp
index fb4be3f..387ad42 100644
--- a/Swiften/Presence/PresenceOracle.cpp
+++ b/Swiften/Presence/PresenceOracle.cpp
@@ -33,12 +33,11 @@ void PresenceOracle::handleStanzaChannelAvailableChanged(bool available) {
void PresenceOracle::handleIncomingPresence(Presence::ref presence) {
JID bareJID(presence->getFrom().toBare());
if (presence->getType() == Presence::Subscribe) {
- onPresenceSubscriptionRequest(bareJID, presence->getStatus());
- } else {
+ }
+ else {
Presence::ref passedPresence = presence;
if (presence->getType() == Presence::Unsubscribe) {
/* 3921bis says that we don't follow up with an unavailable, so simulate this ourselves */
- onPresenceSubscriptionRevoked(bareJID, presence->getStatus());
passedPresence = Presence::ref(new Presence());
passedPresence->setType(Presence::Unavailable);
passedPresence->setFrom(bareJID);
diff --git a/Swiften/Presence/PresenceOracle.h b/Swiften/Presence/PresenceOracle.h
index f30d05d..e846984 100644
--- a/Swiften/Presence/PresenceOracle.h
+++ b/Swiften/Presence/PresenceOracle.h
@@ -25,8 +25,6 @@ class StanzaChannel;
public:
boost::signal<void (Presence::ref)> onPresenceChange;
- boost::signal<void (const JID&, const String&)> onPresenceSubscriptionRequest;
- boost::signal<void (const JID&, const String&)> onPresenceSubscriptionRevoked;
private:
void handleIncomingPresence(Presence::ref presence);
diff --git a/Swiften/Presence/PresenceSender.cpp b/Swiften/Presence/PresenceSender.cpp
index 6df02b8..50d75eb 100644
--- a/Swiften/Presence/PresenceSender.cpp
+++ b/Swiften/Presence/PresenceSender.cpp
@@ -5,81 +5,10 @@
*/
#include "Swiften/Presence/PresenceSender.h"
-#include "Swiften/Base/foreach.h"
-#include "Swiften/Client/StanzaChannel.h"
namespace Swift {
-PresenceSender::PresenceSender(StanzaChannel* channel) : channel(channel) {
-}
-
-void PresenceSender::sendPresence(boost::shared_ptr<Presence> presence) {
- if (!channel->isAvailable()) {
- return;
- }
-
- channel->sendPresence(presence);
-
- if (!presence->getTo().isValid()) {
- boost::shared_ptr<Presence> presenceCopy(new Presence(*presence));
- foreach(const JID& jid, directedPresenceReceivers) {
- presenceCopy->setTo(jid);
- channel->sendPresence(presenceCopy);
- }
-
- lastSentUndirectedPresence = presence;
- }
-}
-
-/**
- * Gets either the last broadcast presence, or an empty stanza if none has been sent.
- */
-boost::shared_ptr<Presence> PresenceSender::getLastSentUndirectedPresence() {
- boost::shared_ptr<Presence> presenceCopy(lastSentUndirectedPresence ? new Presence(*lastSentUndirectedPresence) : new Presence());
- return presenceCopy;
-}
-
-void PresenceSender::addDirectedPresenceReceiver(const JID& jid) {
- directedPresenceReceivers.insert(jid);
- if (channel->isAvailable()) {
- if (lastSentUndirectedPresence && lastSentUndirectedPresence->getType() == Presence::Available) {
- boost::shared_ptr<Presence> presenceCopy(new Presence(*lastSentUndirectedPresence));
- presenceCopy->setTo(jid);
- channel->sendPresence(presenceCopy);
- }
- }
-}
-
-void PresenceSender::removeDirectedPresenceReceiver(const JID& jid) {
- directedPresenceReceivers.erase(jid);
- if (channel->isAvailable()) {
- boost::shared_ptr<Presence> presence(new Presence());
- presence->setType(Presence::Unavailable);
- presence->setTo(jid);
- channel->sendPresence(presence);
- }
-}
-
-void PresenceSender::cancelSubscription(const JID& jid) {
- boost::shared_ptr<Presence> stanza(new Presence());
- stanza->setType(Presence::Unsubscribed);
- stanza->setTo(jid);
- channel->sendPresence(stanza);
-}
-
-void PresenceSender::confirmSubscription(const JID& jid) {
- boost::shared_ptr<Presence> stanza(new Presence());
- stanza->setType(Presence::Subscribed);
- stanza->setTo(jid);
- channel->sendPresence(stanza);
-}
-
-
-void PresenceSender::requestSubscription(const JID& jid) {
- boost::shared_ptr<Presence> stanza(new Presence());
- stanza->setType(Presence::Subscribe);
- stanza->setTo(jid);
- channel->sendPresence(stanza);
+PresenceSender::~PresenceSender() {
}
}
diff --git a/Swiften/Presence/PresenceSender.h b/Swiften/Presence/PresenceSender.h
index 3336523..5abf2f3 100644
--- a/Swiften/Presence/PresenceSender.h
+++ b/Swiften/Presence/PresenceSender.h
@@ -6,31 +6,15 @@
#pragma once
-#include <set>
-
#include "Swiften/Elements/Presence.h"
namespace Swift {
- class StanzaChannel;
-
class PresenceSender {
public:
- PresenceSender(StanzaChannel*);
-
- void addDirectedPresenceReceiver(const JID&);
- void removeDirectedPresenceReceiver(const JID&);
-
- void sendPresence(boost::shared_ptr<Presence>);
-
- void cancelSubscription(const JID& jid);
- void confirmSubscription(const JID& jid);
- void requestSubscription(const JID& jid);
+ virtual ~PresenceSender();
- boost::shared_ptr<Presence> getLastSentUndirectedPresence();
+ virtual void sendPresence(Presence::ref) = 0;
- private:
- boost::shared_ptr<Presence> lastSentUndirectedPresence;
- StanzaChannel* channel;
- std::set<JID> directedPresenceReceivers;
+ virtual bool isAvailable() const = 0;
};
}
diff --git a/Swiften/Presence/StanzaChannelPresenceSender.cpp b/Swiften/Presence/StanzaChannelPresenceSender.cpp
new file mode 100644
index 0000000..654b7e7
--- /dev/null
+++ b/Swiften/Presence/StanzaChannelPresenceSender.cpp
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include "Swiften/Presence/StanzaChannelPresenceSender.h"
+#include "Swiften/Client/StanzaChannel.h"
+
+namespace Swift {
+
+StanzaChannelPresenceSender::StanzaChannelPresenceSender(StanzaChannel* channel) : channel(channel) {
+}
+
+void StanzaChannelPresenceSender::sendPresence(Presence::ref presence) {
+ channel->sendPresence(presence);
+}
+
+bool StanzaChannelPresenceSender::isAvailable() const {
+ return channel->isAvailable();
+}
+
+}
diff --git a/Swiften/Presence/StanzaChannelPresenceSender.h b/Swiften/Presence/StanzaChannelPresenceSender.h
new file mode 100644
index 0000000..23230ab
--- /dev/null
+++ b/Swiften/Presence/StanzaChannelPresenceSender.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include "Swiften/Presence/PresenceSender.h"
+
+namespace Swift {
+ class StanzaChannel;
+
+ class StanzaChannelPresenceSender : public PresenceSender {
+ public:
+ StanzaChannelPresenceSender(StanzaChannel*);
+
+ void sendPresence(Presence::ref);
+
+ bool isAvailable() const;
+
+ private:
+ StanzaChannel* channel;
+ };
+}
diff --git a/Swiften/Presence/SubscriptionManager.cpp b/Swiften/Presence/SubscriptionManager.cpp
new file mode 100644
index 0000000..12534dc
--- /dev/null
+++ b/Swiften/Presence/SubscriptionManager.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include "Swiften/Presence/SubscriptionManager.h"
+
+#include <boost/bind.hpp>
+
+#include "Swiften/Base/foreach.h"
+#include "Swiften/Client/StanzaChannel.h"
+
+namespace Swift {
+
+SubscriptionManager::SubscriptionManager(StanzaChannel* channel) : stanzaChannel(channel) {
+ stanzaChannel->onPresenceReceived.connect(boost::bind(&SubscriptionManager::handleIncomingPresence, this, _1));
+}
+
+SubscriptionManager::~SubscriptionManager() {
+ stanzaChannel->onPresenceReceived.disconnect(boost::bind(&SubscriptionManager::handleIncomingPresence, this, _1));
+}
+
+void SubscriptionManager::cancelSubscription(const JID& jid) {
+ Presence::ref stanza(new Presence());
+ stanza->setType(Presence::Unsubscribed);
+ stanza->setTo(jid);
+ stanzaChannel->sendPresence(stanza);
+}
+
+void SubscriptionManager::confirmSubscription(const JID& jid) {
+ Presence::ref stanza(new Presence());
+ stanza->setType(Presence::Subscribed);
+ stanza->setTo(jid);
+ stanzaChannel->sendPresence(stanza);
+}
+
+
+void SubscriptionManager::requestSubscription(const JID& jid) {
+ Presence::ref stanza(new Presence());
+ stanza->setType(Presence::Subscribe);
+ stanza->setTo(jid);
+ stanzaChannel->sendPresence(stanza);
+}
+
+void SubscriptionManager::handleIncomingPresence(Presence::ref presence) {
+ JID bareJID(presence->getFrom().toBare());
+ if (presence->getType() == Presence::Subscribe) {
+ onPresenceSubscriptionRequest(bareJID, presence->getStatus());
+ }
+ else if (presence->getType() == Presence::Unsubscribe) {
+ onPresenceSubscriptionRevoked(bareJID, presence->getStatus());
+ }
+}
+
+
+}
diff --git a/Swiften/Presence/SubscriptionManager.h b/Swiften/Presence/SubscriptionManager.h
new file mode 100644
index 0000000..477a2fd
--- /dev/null
+++ b/Swiften/Presence/SubscriptionManager.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <map>
+
+#include "Swiften/Base/String.h"
+#include "Swiften/JID/JID.h"
+#include "Swiften/Base/boost_bsignals.h"
+#include "Swiften/Elements/Presence.h"
+
+namespace Swift {
+ class StanzaChannel;
+
+ class SubscriptionManager {
+ public:
+ SubscriptionManager(StanzaChannel* stanzaChannel);
+ ~SubscriptionManager();
+
+ void cancelSubscription(const JID& jid);
+ void confirmSubscription(const JID& jid);
+ void requestSubscription(const JID& jid);
+
+ /**
+ * This signal is emitted when a presence subscription request is received.
+ */
+ boost::signal<void (const JID&, const String&)> onPresenceSubscriptionRequest;
+
+ boost::signal<void (const JID&, const String&)> onPresenceSubscriptionRevoked;
+
+ private:
+ void handleIncomingPresence(Presence::ref presence);
+
+ private:
+ StanzaChannel* stanzaChannel;
+ };
+}
diff --git a/Swiften/Presence/UnitTest/PresenceSenderTest.cpp b/Swiften/Presence/UnitTest/DirectedPresenceSenderTest.cpp
index 737f317..a60c429 100644
--- a/Swiften/Presence/UnitTest/PresenceSenderTest.cpp
+++ b/Swiften/Presence/UnitTest/DirectedPresenceSenderTest.cpp
@@ -8,12 +8,13 @@
#include <cppunit/extensions/TestFactoryRegistry.h>
#include "Swiften/Client/DummyStanzaChannel.h"
-#include "Swiften/Presence/PresenceSender.h"
+#include "Swiften/Presence/DirectedPresenceSender.h"
+#include "Swiften/Presence/StanzaChannelPresenceSender.h"
using namespace Swift;
-class PresenceSenderTest : public CppUnit::TestFixture {
- CPPUNIT_TEST_SUITE(PresenceSenderTest);
+class DirectedPresenceSenderTest : public CppUnit::TestFixture {
+ CPPUNIT_TEST_SUITE(DirectedPresenceSenderTest);
CPPUNIT_TEST(testSendPresence);
CPPUNIT_TEST(testSendPresence_UndirectedPresenceWithDirectedPresenceReceivers);
CPPUNIT_TEST(testSendPresence_DirectedPresenceWithDirectedPresenceReceivers);
@@ -29,14 +30,16 @@ class PresenceSenderTest : public CppUnit::TestFixture {
testPresence->setStatus("Foo");
secondTestPresence = boost::shared_ptr<Presence>(new Presence());
secondTestPresence->setStatus("Bar");
+ stanzaChannelPresenceSender = new StanzaChannelPresenceSender(channel);
}
void tearDown() {
+ delete stanzaChannelPresenceSender;
delete channel;
}
void testSendPresence() {
- std::auto_ptr<PresenceSender> testling(createPresenceSender());
+ std::auto_ptr<DirectedPresenceSender> testling(createPresenceSender());
testling->sendPresence(testPresence);
CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(channel->sentStanzas.size()));
@@ -45,7 +48,7 @@ class PresenceSenderTest : public CppUnit::TestFixture {
}
void testSendPresence_UndirectedPresenceWithDirectedPresenceReceivers() {
- std::auto_ptr<PresenceSender> testling(createPresenceSender());
+ std::auto_ptr<DirectedPresenceSender> testling(createPresenceSender());
testling->addDirectedPresenceReceiver(JID("alice@wonderland.lit/teaparty"));
testling->sendPresence(testPresence);
@@ -59,7 +62,7 @@ class PresenceSenderTest : public CppUnit::TestFixture {
}
void testSendPresence_DirectedPresenceWithDirectedPresenceReceivers() {
- std::auto_ptr<PresenceSender> testling(createPresenceSender());
+ std::auto_ptr<DirectedPresenceSender> testling(createPresenceSender());
testling->addDirectedPresenceReceiver(JID("alice@wonderland.lit/teaparty"));
channel->sentStanzas.clear();
@@ -72,7 +75,7 @@ class PresenceSenderTest : public CppUnit::TestFixture {
}
void testAddDirectedPresenceReceiver() {
- std::auto_ptr<PresenceSender> testling(createPresenceSender());
+ std::auto_ptr<DirectedPresenceSender> testling(createPresenceSender());
testling->sendPresence(testPresence);
channel->sentStanzas.clear();
@@ -85,7 +88,7 @@ class PresenceSenderTest : public CppUnit::TestFixture {
}
void testAddDirectedPresenceReceiver_AfterSendingDirectedPresence() {
- std::auto_ptr<PresenceSender> testling(createPresenceSender());
+ std::auto_ptr<DirectedPresenceSender> testling(createPresenceSender());
testling->sendPresence(testPresence);
secondTestPresence->setTo(JID("foo@bar.com"));
testling->sendPresence(secondTestPresence);
@@ -100,7 +103,7 @@ class PresenceSenderTest : public CppUnit::TestFixture {
}
void testRemoveDirectedPresenceReceiver() {
- std::auto_ptr<PresenceSender> testling(createPresenceSender());
+ std::auto_ptr<DirectedPresenceSender> testling(createPresenceSender());
testling->addDirectedPresenceReceiver(JID("alice@wonderland.lit/teaparty"));
channel->sentStanzas.clear();
@@ -113,14 +116,15 @@ class PresenceSenderTest : public CppUnit::TestFixture {
}
private:
- PresenceSender* createPresenceSender() {
- return new PresenceSender(channel);
+ DirectedPresenceSender* createPresenceSender() {
+ return new DirectedPresenceSender(stanzaChannelPresenceSender);
}
private:
DummyStanzaChannel* channel;
+ StanzaChannelPresenceSender* stanzaChannelPresenceSender;
boost::shared_ptr<Presence> testPresence;
boost::shared_ptr<Presence> secondTestPresence;
};
-CPPUNIT_TEST_SUITE_REGISTRATION(PresenceSenderTest);
+CPPUNIT_TEST_SUITE_REGISTRATION(DirectedPresenceSenderTest);
diff --git a/Swiften/Presence/UnitTest/PresenceOracleTest.cpp b/Swiften/Presence/UnitTest/PresenceOracleTest.cpp
index d3b4b20..aa450a2 100644
--- a/Swiften/Presence/UnitTest/PresenceOracleTest.cpp
+++ b/Swiften/Presence/UnitTest/PresenceOracleTest.cpp
@@ -11,6 +11,7 @@
#include "Swiften/Presence/PresenceOracle.h"
#include "Swiften/Client/DummyStanzaChannel.h"
+#include "Swiften/Presence/SubscriptionManager.h"
using namespace Swift;
@@ -31,13 +32,15 @@ class PresenceOracleTest : public CppUnit::TestFixture {
stanzaChannel_ = new DummyStanzaChannel();
oracle_ = new PresenceOracle(stanzaChannel_);
oracle_->onPresenceChange.connect(boost::bind(&PresenceOracleTest::handlePresenceChange, this, _1));
- oracle_->onPresenceSubscriptionRequest.connect(boost::bind(&PresenceOracleTest::handlePresenceSubscriptionRequest, this, _1, _2));
+ subscriptionManager_ = new SubscriptionManager(stanzaChannel_);
+ subscriptionManager_->onPresenceSubscriptionRequest.connect(boost::bind(&PresenceOracleTest::handlePresenceSubscriptionRequest, this, _1, _2));
user1 = JID("user1@foo.com/Foo");
user1alt = JID("user1@foo.com/Bar");
user2 = JID("user2@bar.com/Bar");
}
void tearDown() {
+ delete subscriptionManager_;
delete oracle_;
delete stanzaChannel_;
}
@@ -181,6 +184,7 @@ class PresenceOracleTest : public CppUnit::TestFixture {
String reason;
};
PresenceOracle* oracle_;
+ SubscriptionManager* subscriptionManager_;
DummyStanzaChannel* stanzaChannel_;
std::vector<Presence::ref> changes;
std::vector<SubscriptionRequestInfo> subscriptionRequests;
diff --git a/Swiften/SConscript b/Swiften/SConscript
index 886051f..5790672 100644
--- a/Swiften/SConscript
+++ b/Swiften/SConscript
@@ -47,11 +47,15 @@ if env["SCONS_STAGE"] == "build" :
"Elements/Stanza.cpp",
"Elements/VCard.cpp",
"MUC/MUC.cpp",
+ "MUC/MUCManager.cpp",
"MUC/MUCOccupant.cpp",
"MUC/MUCRegistry.cpp",
"MUC/MUCBookmarkManager.cpp",
"Presence/PresenceOracle.cpp",
"Presence/PresenceSender.cpp",
+ "Presence/DirectedPresenceSender.cpp",
+ "Presence/StanzaChannelPresenceSender.cpp",
+ "Presence/SubscriptionManager.cpp",
"Queries/IQChannel.cpp",
"Queries/IQHandler.cpp",
"Queries/IQRouter.cpp",
@@ -218,7 +222,7 @@ if env["SCONS_STAGE"] == "build" :
File("Parser/UnitTest/XMLParserTest.cpp"),
File("Parser/UnitTest/XMPPParserTest.cpp"),
File("Presence/UnitTest/PresenceOracleTest.cpp"),
- File("Presence/UnitTest/PresenceSenderTest.cpp"),
+ File("Presence/UnitTest/DirectedPresenceSenderTest.cpp"),
File("Queries/Requests/UnitTest/GetPrivateStorageRequestTest.cpp"),
File("Disco/UnitTest/DiscoInfoResponderTest.cpp"),
File("Queries/UnitTest/IQRouterTest.cpp"),