diff options
author | Kevin Smith <git@kismith.co.uk> | 2010-05-22 20:45:53 (GMT) |
---|---|---|
committer | Kevin Smith <git@kismith.co.uk> | 2010-05-23 08:15:20 (GMT) |
commit | a68530cbbfeb17e01fd684b1ef41b960bc173f66 (patch) | |
tree | 98b5cd195f04d781164cf1394cee9092bb7b2497 /Swiften/MUC | |
parent | c9659b556b932e2f887cf1d8ab6c5a0bead835eb (diff) | |
download | swift-contrib-a68530cbbfeb17e01fd684b1ef41b960bc173f66.zip swift-contrib-a68530cbbfeb17e01fd684b1ef41b960bc173f66.tar.bz2 |
Implement XEP-0045 joining, and appropriate error handling.
Resolves: #211
Diffstat (limited to 'Swiften/MUC')
-rw-r--r-- | Swiften/MUC/MUC.cpp | 77 | ||||
-rw-r--r-- | Swiften/MUC/MUC.h | 14 | ||||
-rw-r--r-- | Swiften/MUC/MUCOccupant.cpp | 25 | ||||
-rw-r--r-- | Swiften/MUC/MUCOccupant.h | 22 |
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 |