summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Smith <git@kismith.co.uk>2010-05-22 20:45:53 (GMT)
committerKevin Smith <git@kismith.co.uk>2010-05-23 08:15:20 (GMT)
commita68530cbbfeb17e01fd684b1ef41b960bc173f66 (patch)
tree98b5cd195f04d781164cf1394cee9092bb7b2497 /Swiften/MUC
parentc9659b556b932e2f887cf1d8ab6c5a0bead835eb (diff)
downloadswift-a68530cbbfeb17e01fd684b1ef41b960bc173f66.zip
swift-a68530cbbfeb17e01fd684b1ef41b960bc173f66.tar.bz2
Implement XEP-0045 joining, and appropriate error handling.
Resolves: #211
Diffstat (limited to 'Swiften/MUC')
-rw-r--r--Swiften/MUC/MUC.cpp77
-rw-r--r--Swiften/MUC/MUC.h14
-rw-r--r--Swiften/MUC/MUCOccupant.cpp25
-rw-r--r--Swiften/MUC/MUCOccupant.h22
4 files changed, 97 insertions, 41 deletions
diff --git a/Swiften/MUC/MUC.cpp b/Swiften/MUC/MUC.cpp
index e52eae4..60b81a0 100644
--- a/Swiften/MUC/MUC.cpp
+++ b/Swiften/MUC/MUC.cpp
@@ -1,17 +1,20 @@
/*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include "Swiften/MUC/MUC.h"
+#include <iostream>
+
#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/MUCUserPayload.h"
#include "Swiften/Elements/MUCPayload.h"
namespace Swift {
@@ -25,9 +28,9 @@ MUC::MUC(StanzaChannel* stanzaChannel, PresenceSender* presenceSender, const JID
//FIXME: discover reserved nickname
void MUC::joinAs(const String &nick) {
- //FIXME: password
- //FIXME: history request
- firstPresenceSeen = false;
+ //TODO: password
+ //TODO: history request
+ joinComplete_ = false;
ownMUCJID = JID(ownMUCJID.getNode(), ownMUCJID.getDomain(), nick);
@@ -45,53 +48,73 @@ void MUC::handleIncomingPresence(boost::shared_ptr<Presence> presence) {
if (!isFromMUC(presence->getFrom())) {
return;
}
-
- if (!firstPresenceSeen) {
+ boost::shared_ptr<MUCUserPayload> mucPayload;
+ foreach (boost::shared_ptr<MUCUserPayload> payload, presence->getPayloads<MUCUserPayload>()) {
+ if (payload->getItems().size() > 0 || payload->getStatusCodes().size() > 0) {
+ mucPayload = payload;
+ }
+ }
+
+ if (!joinComplete_) {
if (presence->getType() == Presence::Error) {
- onJoinComplete(JoinFailed);
- //FIXME: parse error element
- //Wrong password
- //Members-only
- //Banned
- //Nickname-conflict
- //Max-users
- //Locked-room
-
+ String reason;
+ onJoinFailed(presence->getPayload<ErrorPayload>());
return;
}
- firstPresenceSeen = true;
- onJoinComplete(JoinSucceeded);
- presenceSender->addDirectedPresenceReceiver(ownMUCJID);
}
String nick = presence->getFrom().getResource();
if (nick.isEmpty()) {
return;
}
- //FIXME: occupant affiliation, role.
- //FIXME: if status code='110', This is me, stop talking.
- //FIXME: what's status 210?
+ MUCOccupant::Role role(MUCOccupant::NoRole);
+ MUCOccupant::Affiliation affiliation(MUCOccupant::NoAffiliation);
+ if (mucPayload && mucPayload->getItems().size() > 0) {
+ role = mucPayload->getItems()[0].role;
+ affiliation = mucPayload->getItems()[0].affiliation;
+ }
+
//100 is non-anonymous
- //FIXME: 100 may also be specified in a <message/>
- //Once I've got my nick (110), everything new is a join
+ //TODO: 100 may also be specified in a <message/>
//170 is room logging to http
- //FIXME: full JIDs
- //FIXME: Nick changes
+ //TODO: Nick changes
if (presence->getType() == Presence::Unavailable) {
std::map<String,MUCOccupant>::iterator i = occupants.find(nick);
if (i != occupants.end()) {
- //FIXME: part type
+ //TODO: part type
onOccupantLeft(i->second, Part, "");
occupants.erase(i);
}
}
else if (presence->getType() == Presence::Available) {
- std::pair<std::map<String,MUCOccupant>::iterator, bool> result = occupants.insert(std::make_pair(nick, MUCOccupant(nick)));
+ std::map<String, MUCOccupant>::iterator it = occupants.find(nick);
+ if (it != occupants.end()) {
+ MUCOccupant oldOccupant = it->second;
+ if (oldOccupant.getRole() != role) {
+ onOccupantRoleChanged(nick, role, oldOccupant.getRole());
+ }
+ if (oldOccupant.getAffiliation() != affiliation) {
+ onOccupantAffiliationChanged(nick, affiliation, oldOccupant.getAffiliation());
+ }
+ }
+ std::pair<std::map<String, MUCOccupant>::iterator, bool> result = occupants.insert(std::make_pair(nick, MUCOccupant(nick, role, affiliation)));
if (result.second) {
onOccupantJoined(result.first->second);
}
onOccupantPresenceChange(presence);
}
+ if (mucPayload && !joinComplete_) {
+ foreach (MUCUserPayload::StatusCode status, mucPayload->getStatusCodes()) {
+ if (status.code == 110) {
+ /* Simply knowing this is your presence is enough, 210 doesn't seem to be necessary. */
+ joinComplete_ = true;
+ ownMUCJID = presence->getFrom();
+ onJoinComplete(getOwnNick());
+ presenceSender->addDirectedPresenceReceiver(ownMUCJID);
+ }
+ }
+ }
+
}
//FIXME: Recognise Topic changes
diff --git a/Swiften/MUC/MUC.h b/Swiften/MUC/MUC.h
index e306f11..fc691f1 100644
--- a/Swiften/MUC/MUC.h
+++ b/Swiften/MUC/MUC.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
@@ -25,10 +25,7 @@ namespace Swift {
class MUC {
public:
enum JoinResult { JoinSucceeded, JoinFailed };
- enum LeavingType { Part };
- enum Roles {Moderator, Participant, Visitor, NoRole};
- enum Affiliations {Owner, Admin, Member, Outcast, NoAffiliation};
-
+ enum LeavingType { Part };
public:
MUC(StanzaChannel* stanzaChannel, PresenceSender* presenceSender, const JID &muc);
@@ -41,8 +38,11 @@ namespace Swift {
void handleIncomingMessage(boost::shared_ptr<Message> message);
public:
- boost::signal<void (JoinResult)> onJoinComplete;
+ boost::signal<void (const String& /*nick*/)> onJoinComplete;
+ boost::signal<void (boost::shared_ptr<ErrorPayload>)> onJoinFailed;
boost::signal<void (boost::shared_ptr<Presence>)> onOccupantPresenceChange;
+ boost::signal<void (const String&, const MUCOccupant::Role& /*new*/, const MUCOccupant::Role& /*old*/)> onOccupantRoleChanged;
+ boost::signal<void (const String&, const MUCOccupant::Affiliation& /*new*/, const MUCOccupant::Affiliation& /*old*/)> onOccupantAffiliationChanged;
boost::signal<void (const MUCOccupant&)> onOccupantJoined;
boost::signal<void (const MUCOccupant&, LeavingType, const String& /*reason*/)> onOccupantLeft;
/* boost::signal<void (const MUCInfo&)> onInfoResult; */
@@ -66,7 +66,7 @@ namespace Swift {
StanzaChannel* stanzaChannel;
PresenceSender* presenceSender;
std::map<String, MUCOccupant> occupants;
- bool firstPresenceSeen;
+ bool joinComplete_;
boost::bsignals::scoped_connection scopedConnection_;
};
}
diff --git a/Swiften/MUC/MUCOccupant.cpp b/Swiften/MUC/MUCOccupant.cpp
index 0bd9787..3e907ab 100644
--- a/Swiften/MUC/MUCOccupant.cpp
+++ b/Swiften/MUC/MUCOccupant.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
@@ -8,7 +8,7 @@
namespace Swift {
-MUCOccupant::MUCOccupant(const String &nick) : nick_(nick) {
+MUCOccupant::MUCOccupant(const String &nick, Role role, Affiliation affiliation) : nick_(nick), role_(role), affiliation_(affiliation) {
}
MUCOccupant::~MUCOccupant() {
@@ -18,4 +18,25 @@ String MUCOccupant::getNick() const {
return nick_;
}
+MUCOccupant::Role MUCOccupant::getRole() const {
+ return role_;
+}
+
+MUCOccupant::Affiliation MUCOccupant::getAffiliation() const {
+ return affiliation_;
+}
+
+void MUCOccupant::setRealJID(const JID& realJID) {
+ realJID_ = realJID;
+}
+
+void MUCOccupant::setNick(const String& nick) {
+ nick_ = nick;
+}
+
+
+boost::optional<JID> MUCOccupant::getRealJID() const {
+ return realJID_;
+}
+
}
diff --git a/Swiften/MUC/MUCOccupant.h b/Swiften/MUC/MUCOccupant.h
index 939d634..c9551de 100644
--- a/Swiften/MUC/MUCOccupant.h
+++ b/Swiften/MUC/MUCOccupant.h
@@ -1,27 +1,39 @@
/*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#ifndef SWIFTEN_MUCOccupant_H
-#define SWIFTEN_MUCOccupant_H
+#pragma once
+
+#include <boost/optional.hpp>
#include "Swiften/Base/String.h"
+#include "Swiften/JID/JID.h"
namespace Swift {
class Client;
class MUCOccupant {
public:
- MUCOccupant(const String &nick);
+ enum Role {Moderator, Participant, Visitor, NoRole};
+ enum Affiliation {Owner, Admin, Member, Outcast, NoAffiliation};
+
+ MUCOccupant(const String &nick, Role role, Affiliation affiliation);
~MUCOccupant();
String getNick() const;
+ Role getRole() const;
+ Affiliation getAffiliation() const;
+ boost::optional<JID> getRealJID() const;
+ void setRealJID(const JID& jid);
+ void setNick(const String& nick);
private:
String nick_;
+ Role role_;
+ Affiliation affiliation_;
+ boost::optional<JID> realJID_;
};
}
-#endif