summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Swift/Controllers/MUCController.cpp3
-rw-r--r--Swift/Controllers/MUCController.h2
-rw-r--r--Swift/Controllers/MainController.cpp10
-rw-r--r--Swift/Controllers/MainController.h2
-rw-r--r--Swiften/Client/DummyStanzaChannel.h10
-rw-r--r--Swiften/Client/StanzaChannel.h5
-rw-r--r--Swiften/Elements/Presence.h5
-rw-r--r--Swiften/MUC/MUC.cpp67
-rw-r--r--Swiften/MUC/MUC.h29
-rw-r--r--Swiften/Presence/PresenceSender.cpp49
-rw-r--r--Swiften/Presence/PresenceSender.h24
-rw-r--r--Swiften/SConscript2
12 files changed, 147 insertions, 61 deletions
diff --git a/Swift/Controllers/MUCController.cpp b/Swift/Controllers/MUCController.cpp
index 848f540..da7a9e7 100644
--- a/Swift/Controllers/MUCController.cpp
+++ b/Swift/Controllers/MUCController.cpp
@@ -21,13 +21,14 @@ MUCController::MUCController (
const JID &muc,
const String &nick,
StanzaChannel* stanzaChannel,
+ PresenceSender* presenceSender,
IQRouter* iqRouter,
ChatWindowFactory* chatWindowFactory,
TreeWidgetFactory *treeWidgetFactory,
PresenceOracle* presenceOracle,
AvatarManager* avatarManager) :
ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, muc, presenceOracle, avatarManager),
- muc_(new MUC(stanzaChannel, muc)),
+ muc_(new MUC(stanzaChannel, presenceSender, muc)),
nick_(nick),
treeWidgetFactory_(treeWidgetFactory) {
roster_ = new Roster(chatWindow_->getTreeWidget(), treeWidgetFactory_);
diff --git a/Swift/Controllers/MUCController.h b/Swift/Controllers/MUCController.h
index af4a23a..7ee6e81 100644
--- a/Swift/Controllers/MUCController.h
+++ b/Swift/Controllers/MUCController.h
@@ -22,7 +22,7 @@ namespace Swift {
class MUCController : public ChatControllerBase {
public:
- MUCController(const JID& self, const JID &muc, const String &nick, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, TreeWidgetFactory *treeWidgetFactory, PresenceOracle* presenceOracle, AvatarManager* avatarManager);
+ MUCController(const JID& self, const JID &muc, const String &nick, StanzaChannel* stanzaChannel, PresenceSender* presenceSender, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, TreeWidgetFactory *treeWidgetFactory, PresenceOracle* presenceOracle, AvatarManager* avatarManager);
~MUCController();
protected:
diff --git a/Swift/Controllers/MainController.cpp b/Swift/Controllers/MainController.cpp
index f54e0a2..22d71e5 100644
--- a/Swift/Controllers/MainController.cpp
+++ b/Swift/Controllers/MainController.cpp
@@ -26,6 +26,7 @@
#include "Swiften/Base/foreach.h"
#include "Swiften/Base/String.h"
#include "Swiften/Client/Client.h"
+#include "Swiften/Presence/PresenceSender.h"
#include "Swiften/Elements/Presence.h"
#include "Swiften/Elements/VCardUpdate.h"
#include "Swiften/Queries/Responders/SoftwareVersionResponder.h"
@@ -60,7 +61,7 @@ typedef std::pair<JID, ChatController*> JIDChatControllerPair;
typedef std::pair<JID, MUCController*> JIDMUCControllerPair;
MainController::MainController(ChatWindowFactory* chatWindowFactory, MainWindowFactory *mainWindowFactory, LoginWindowFactory *loginWindowFactory, TreeWidgetFactory *treeWidgetFactory, SettingsProvider *settings, Application* application, SystemTray* systemTray, SoundPlayer* soundPlayer)
- : timerFactory_(&boostIOServiceThread_.getIOService()), idleDetector_(&idleQuerier_, &timerFactory_, 100), client_(NULL), chatWindowFactory_(chatWindowFactory), mainWindowFactory_(mainWindowFactory), loginWindowFactory_(loginWindowFactory), treeWidgetFactory_(treeWidgetFactory), settings_(settings), xmppRosterController_(NULL), rosterController_(NULL), loginWindow_(NULL), clientVersionResponder_(NULL), nickResolver_(NULL), discoResponder_(NULL) {
+ : timerFactory_(&boostIOServiceThread_.getIOService()), idleDetector_(&idleQuerier_, &timerFactory_, 100), client_(NULL), presenceSender_(NULL), chatWindowFactory_(chatWindowFactory), mainWindowFactory_(mainWindowFactory), loginWindowFactory_(loginWindowFactory), treeWidgetFactory_(treeWidgetFactory), settings_(settings), xmppRosterController_(NULL), rosterController_(NULL), loginWindow_(NULL), clientVersionResponder_(NULL), nickResolver_(NULL), discoResponder_(NULL) {
application_ = application;
presenceOracle_ = NULL;
avatarManager_ = NULL;
@@ -114,6 +115,8 @@ void MainController::resetClient() {
clientVersionResponder_ = NULL;
delete discoResponder_;
discoResponder_ = NULL;
+ delete presenceSender_;
+ presenceSender_ = NULL;
delete client_;
client_ = NULL;
@@ -210,7 +213,7 @@ void MainController::sendPresence(boost::shared_ptr<Presence> presence) {
}
presence->addPayload(capsInfo_);
lastSentPresence_ = presence;
- client_->sendPresence(presence);
+ presenceSender_->sendPresence(presence);
if (presence->getType() == Presence::Unavailable) {
logout();
}
@@ -258,6 +261,7 @@ void MainController::handleLoginRequest(const String &username, const String &pa
void MainController::performLoginFromCachedCredentials() {
if (!client_) {
client_ = new Swift::Client(jid_, password_);
+ presenceSender_ = new PresenceSender(client_);
//client_->onDataRead.connect(&printIncomingData);
//client_->onDataWritten.connect(&printOutgoingData);
if (!certificateFile_.isEmpty()) {
@@ -368,7 +372,7 @@ void MainController::handleChatControllerJIDChanged(const JID& from, const JID&
}
void MainController::handleJoinMUCRequest(const JID &muc, const String &nick) {
- mucControllers_[muc] = new MUCController(jid_, muc, nick, client_, client_, chatWindowFactory_, treeWidgetFactory_, presenceOracle_, avatarManager_);
+ mucControllers_[muc] = new MUCController(jid_, muc, nick, client_, presenceSender_, client_, chatWindowFactory_, treeWidgetFactory_, presenceOracle_, avatarManager_);
mucControllers_[muc]->setAvailableServerFeatures(serverDiscoInfo_);
}
diff --git a/Swift/Controllers/MainController.h b/Swift/Controllers/MainController.h
index 270b131..78e49a2 100644
--- a/Swift/Controllers/MainController.h
+++ b/Swift/Controllers/MainController.h
@@ -33,6 +33,7 @@ namespace Swift {
class NickResolver;
class RosterController;
class XMPPRosterController;
+ class PresenceSender;
class DiscoInfoResponder;
class AvatarManager;
class LoginWindow;
@@ -86,6 +87,7 @@ namespace Swift {
PlatformIdleQuerier idleQuerier_;
ActualIdleDetector idleDetector_;
Client* client_;
+ PresenceSender* presenceSender_;
ChatWindowFactory* chatWindowFactory_;
MainWindowFactory* mainWindowFactory_;
LoginWindowFactory* loginWindowFactory_;
diff --git a/Swiften/Client/DummyStanzaChannel.h b/Swiften/Client/DummyStanzaChannel.h
index 052c470..d618167 100644
--- a/Swiften/Client/DummyStanzaChannel.h
+++ b/Swiften/Client/DummyStanzaChannel.h
@@ -10,19 +10,19 @@ namespace Swift {
DummyStanzaChannel() {}
virtual void sendStanza(boost::shared_ptr<Stanza> stanza) {
- sentStanzas_.push_back(stanza);
+ sentStanzas.push_back(stanza);
}
virtual void sendIQ(boost::shared_ptr<IQ> iq) {
- sentStanzas_.push_back(iq);
+ sentStanzas.push_back(iq);
}
virtual void sendMessage(boost::shared_ptr<Message> message) {
- sentStanzas_.push_back(message);
+ sentStanzas.push_back(message);
}
virtual void sendPresence(boost::shared_ptr<Presence> presence) {
- sentStanzas_.push_back(presence);
+ sentStanzas.push_back(presence);
}
virtual String getNewIQID() {
@@ -33,6 +33,6 @@ namespace Swift {
return true;
}
- std::vector<boost::shared_ptr<Stanza> > sentStanzas_;
+ std::vector<boost::shared_ptr<Stanza> > sentStanzas;
};
}
diff --git a/Swiften/Client/StanzaChannel.h b/Swiften/Client/StanzaChannel.h
index 37c58c7..a0e291d 100644
--- a/Swiften/Client/StanzaChannel.h
+++ b/Swiften/Client/StanzaChannel.h
@@ -1,5 +1,4 @@
-#ifndef SWIFTEN_MessageChannel_H
-#define SWIFTEN_MessageChannel_H
+#pragma once
#include <boost/signal.hpp>
#include <boost/shared_ptr.hpp>
@@ -19,5 +18,3 @@ namespace Swift {
boost::signal<void (boost::shared_ptr<Presence>) > onPresenceReceived;
};
}
-
-#endif
diff --git a/Swiften/Elements/Presence.h b/Swiften/Elements/Presence.h
index 002ed0e..a1f15fa 100644
--- a/Swiften/Elements/Presence.h
+++ b/Swiften/Elements/Presence.h
@@ -1,5 +1,4 @@
-#ifndef SWIFTEN_Presence
-#define SWIFTEN_Presence
+#pragma once
#include "Swiften/Elements/Stanza.h"
#include "Swiften/Elements/Status.h"
@@ -57,5 +56,3 @@ namespace Swift {
Presence::Type type_;
};
}
-
-#endif
diff --git a/Swiften/MUC/MUC.cpp b/Swiften/MUC/MUC.cpp
index 2b8054f..a6fbcbd 100644
--- a/Swiften/MUC/MUC.cpp
+++ b/Swiften/MUC/MUC.cpp
@@ -3,63 +3,64 @@
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
+#include "Swiften/Presence/PresenceSender.h"
#include "Swiften/Client/StanzaChannel.h"
#include "Swiften/Elements/IQ.h"
-#include "Swiften/Elements/Message.h"
#include "Swiften/Elements/MUCPayload.h"
-#include "Swiften/Elements/Presence.h"
namespace Swift {
typedef std::pair<String, MUCOccupant> StringMUCOccupantPair;
-MUC::MUC(StanzaChannel* stanzaChannel, const JID &muc) : muc_(muc), stanzaChannel_(stanzaChannel) {
- stanzaChannel_->onPresenceReceived.connect(boost::bind(&MUC::handleIncomingPresence, this, _1));
-}
-
-MUC::~MUC() {
+MUC::MUC(StanzaChannel* stanzaChannel, PresenceSender* presenceSender, const JID &muc) : ownMUCJID(muc), stanzaChannel(stanzaChannel), presenceSender(presenceSender) {
+ stanzaChannel->onPresenceReceived.connect(boost::bind(&MUC::handleIncomingPresence, this, _1));
}
void MUC::joinAs(const String &nick) {
+ firstPresenceSeen = false;
+
+ ownMUCJID = JID(ownMUCJID.getNode(), ownMUCJID.getDomain(), nick);
+
boost::shared_ptr<Presence> joinPresence(new Presence());
- joinPresence->setTo(JID(muc_.getNode(), muc_.getDomain(), nick));
+ joinPresence->setTo(ownMUCJID);
joinPresence->addPayload(boost::shared_ptr<Payload>(new MUCPayload()));
- stanzaChannel_->sendPresence(joinPresence);
- myNick_ = nick;
+ presenceSender->sendPresence(joinPresence);
}
void MUC::part() {
- boost::shared_ptr<Presence> partPresence(new Presence());
- partPresence->setType(Presence::Unavailable);
- partPresence->setTo(JID(muc_.getNode(), muc_.getDomain(), myNick_));
- stanzaChannel_->sendPresence(partPresence);
+ presenceSender->removeDirectedPresenceReceiver(ownMUCJID);
}
void MUC::handleIncomingPresence(boost::shared_ptr<Presence> presence) {
- if (presence->getFrom().toBare() != muc_ || presence->getFrom().getResource() == "") {
+ if (!isFromMUC(presence->getFrom())) {
return;
}
+
+ if (!firstPresenceSeen) {
+ if (presence->getType() == Presence::Error) {
+ onJoinComplete(JoinFailed);
+ return;
+ }
+ firstPresenceSeen = true;
+ onJoinComplete(JoinSucceeded);
+ presenceSender->addDirectedPresenceReceiver(ownMUCJID);
+ }
+
String nick = presence->getFrom().getResource();
+ if (nick.isEmpty()) {
+ return;
+ }
if (presence->getType() == Presence::Unavailable) {
- foreach (StringMUCOccupantPair occupantPair, occupants_) {
- if (occupantPair.first == nick) {
- occupants_.erase(nick);
- onOccupantLeft(occupantPair.second, Part, "");
- break;
- }
- }
- } else if (presence->getType() == Presence::Available) {
- bool found = false;
- foreach (StringMUCOccupantPair occupantPair, occupants_) {
- if (occupantPair.first == nick) {
- found = true;
- break;
- }
+ std::map<String,MUCOccupant>::iterator i = occupants.find(nick);
+ if (i != occupants.end()) {
+ onOccupantLeft(i->second, Part, "");
+ occupants.erase(i);
}
- if (!found) {
- MUCOccupant occupant(nick);
- occupants_.insert(occupants_.end(), std::pair<String, MUCOccupant>(nick, occupant));
- onOccupantJoined(occupant);
+ }
+ else if (presence->getType() == Presence::Available) {
+ std::pair<std::map<String,MUCOccupant>::iterator, bool> result = occupants.insert(std::make_pair(nick, MUCOccupant(nick)));
+ if (result.second) {
+ onOccupantJoined(result.first->second);
}
onOccupantPresenceChange(presence);
}
diff --git a/Swiften/MUC/MUC.h b/Swiften/MUC/MUC.h
index 45bcbd3..2a327f4 100644
--- a/Swiften/MUC/MUC.h
+++ b/Swiften/MUC/MUC.h
@@ -1,5 +1,4 @@
-#ifndef SWIFTEN_MUC_H
-#define SWIFTEN_MUC_H
+#pragma once
#include "Swiften/JID/JID.h"
#include "Swiften/Base/String.h"
@@ -14,6 +13,7 @@
namespace Swift {
class StanzaChannel;
+ class PresenceSender;
class MUC {
public:
@@ -21,8 +21,7 @@ namespace Swift {
enum LeavingType { Part };
public:
- MUC(StanzaChannel* stanzaChannel, const JID &muc);
- ~MUC();
+ MUC(StanzaChannel* stanzaChannel, PresenceSender* presenceSender, const JID &muc);
void joinAs(const String &nick);
String getCurrentNick();
@@ -38,12 +37,22 @@ namespace Swift {
boost::signal<void (const MUCOccupant&, LeavingType, const String&)> onOccupantLeft;
private:
+ bool isFromMUC(const JID& j) const {
+ return ownMUCJID.equals(j, JID::WithoutResource);
+ }
+
+ const String& getOwnNick() const {
+ return ownMUCJID.getResource();
+ }
+
+ private:
void handleIncomingPresence(boost::shared_ptr<Presence> presence);
- JID muc_;
- StanzaChannel *stanzaChannel_;
- String myNick_;
- std::map<String, MUCOccupant> occupants_;
+
+ private:
+ JID ownMUCJID;
+ StanzaChannel* stanzaChannel;
+ PresenceSender* presenceSender;
+ std::map<String, MUCOccupant> occupants;
+ bool firstPresenceSeen;
};
}
-
-#endif
diff --git a/Swiften/Presence/PresenceSender.cpp b/Swiften/Presence/PresenceSender.cpp
new file mode 100644
index 0000000..8e7ef68
--- /dev/null
+++ b/Swiften/Presence/PresenceSender.cpp
@@ -0,0 +1,49 @@
+#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;
+ }
+}
+
+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);
+ }
+}
+
+}
diff --git a/Swiften/Presence/PresenceSender.h b/Swiften/Presence/PresenceSender.h
new file mode 100644
index 0000000..ef69447
--- /dev/null
+++ b/Swiften/Presence/PresenceSender.h
@@ -0,0 +1,24 @@
+#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>);
+
+ private:
+ boost::shared_ptr<Presence> lastSentUndirectedPresence;
+ StanzaChannel* channel;
+ std::set<JID> directedPresenceReceivers;
+ };
+}
diff --git a/Swiften/SConscript b/Swiften/SConscript
index 9742768..e7e1582 100644
--- a/Swiften/SConscript
+++ b/Swiften/SConscript
@@ -33,6 +33,7 @@ sources = [
"MUC/MUCRegistry.cpp",
"Notifier/Notifier.cpp",
"Presence/PresenceOracle.cpp",
+ "Presence/PresenceSender.cpp",
"Queries/IQChannel.cpp",
"Queries/IQHandler.cpp",
"Queries/IQRouter.cpp",
@@ -155,6 +156,7 @@ env.Append(UNITTEST_SOURCES = [
File("Parser/UnitTest/XMLParserTest.cpp"),
File("Parser/UnitTest/XMPPParserTest.cpp"),
File("Presence/UnitTest/PresenceOracleTest.cpp"),
+ File("Presence/UnitTest/PresenceSenderTest.cpp"),
File("Queries/Requests/UnitTest/GetPrivateStorageRequestTest.cpp"),
File("Queries/Responders/UnitTest/DiscoInfoResponderTest.cpp"),
File("Queries/UnitTest/IQRouterTest.cpp"),