-
Notifications
You must be signed in to change notification settings - Fork 63
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Updates roster encoding for MIX channel. #87
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks okay for the parts that are provided. Would be great to have unit and integration tests that check that an account supports MIX and checks that on join of a MIX it's added to the roster.
Swiften/Client/Client.cpp
Outdated
@@ -58,6 +59,8 @@ Client::Client(const JID& jid, const SafeString& password, NetworkFactories* net | |||
directedPresenceSender = new DirectedPresenceSender(stanzaChannelPresenceSender); | |||
discoManager = new ClientDiscoManager(getIQRouter(), directedPresenceSender, networkFactories->getCryptoProvider()); | |||
|
|||
mixRegistry = new MIXRegistry(roster); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably only allocate this if the account supports MIX.
@@ -191,6 +196,7 @@ namespace Swift { | |||
PresenceOracle* presenceOracle; | |||
DirectedPresenceSender* directedPresenceSender; | |||
StanzaChannelPresenceSender* stanzaChannelPresenceSender; | |||
MIXRegistry* mixRegistry; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initialise with nullptr
or better, keep as unique_ptr
.
Swiften/Elements/RosterItemPayload.h
Outdated
@@ -41,12 +41,16 @@ namespace Swift { | |||
unknownContent_ += c; | |||
} | |||
|
|||
void setChannel() { isChannel_ = true; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should have a bool parameter.
Swiften/MIX/MIXRegistry.h
Outdated
class SWIFTEN_API MIXRegistry { | ||
public: | ||
MIXRegistry(XMPPRoster* xmppRoster); | ||
virtual ~MIXRegistry(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No virtual method otherwise, so doesn't need a virtual d-tor.
Swiften/Client/Client.cpp
Outdated
@@ -74,6 +75,9 @@ Client::Client(const JID& jid, const SafeString& password, NetworkFactories* net | |||
jingleSessionManager = new JingleSessionManager(getIQRouter()); | |||
blockListManager = new ClientBlockListManager(getIQRouter()); | |||
|
|||
mixSupport = false; | |||
requestFeatures(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should called when the client went online, not in the constructor.
Swiften/Client/Client.cpp
Outdated
@@ -74,6 +75,9 @@ Client::Client(const JID& jid, const SafeString& password, NetworkFactories* net | |||
jingleSessionManager = new JingleSessionManager(getIQRouter()); | |||
blockListManager = new ClientBlockListManager(getIQRouter()); | |||
|
|||
mixSupport = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This boolean is redundant, not? If MIX is supported, mixRegistry
will be initialised. If not, it will not be initialised.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just used this as a bool to pass to requestRoster. However it is still redundant.
Swiften/MIX/MIXRegistry.h
Outdated
public: | ||
boost::signals2::signal<void (const JID& /* joinedChannel */)> onChannelJoined; | ||
boost::signals2::signal<void (ErrorPayload::ref /* joinResponse */)> onChannelJoinFailed; | ||
boost::signals2::signal<void (const JID& /* leavedChannel */)> onChannelLeaved; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be onChannelLeft
.
Swiften/MIX/MIXRegistry.cpp
Outdated
} | ||
} | ||
|
||
std::unordered_set<std::string> MIXRegistry::getJoinedChannels() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- If I read https://xmpp.org/extensions/xep-0369.html#usecase-roster-management correctly the roster only contains joined channels. So
getChannels
sounds like a better name. - Shouldn't it return JIDs rather than strings?
- It should return a list of all channels in the roster.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll update it to return JID rather than strings. As soon as a JID is added, the handler will check if it is a channel and add it to the map. So it will always return list of channels in the roster.
return results; | ||
} | ||
|
||
MIX::ref MIXRegistry::getMIXInstance(const JID& channelJID) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method should return a MIXImpl
instance for the channel JID, if and only if it is joined, so it is in the roster.
Swiften/MIX/MIXRegistry.h
Outdated
IQRouter* iqRouter_; | ||
XMPPRoster* xmppRoster_; | ||
bool rosterPopulated_; | ||
typedef std::map<JID, MIX::ref> MIXInstanceMap; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this typedef? If it's really needed, it should probably be a using
instead.
Swiften/MIX/MIXRegistry.h
Outdated
XMPPRoster* xmppRoster_; | ||
bool rosterPopulated_; | ||
typedef std::map<JID, MIX::ref> MIXInstanceMap; | ||
MIXInstanceMap entries_; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably map JID to weak_ptr. The idea I'd think is:
- You create your
Client
instance and go online with it. - Ask the
MIXRegistry
for the channels. - Call MIXRegistry::getMIX(channelJID) to get a
shared_ptr<MIX>
.MIXRegistry
holds aweak_ptr
to it so it can hand out the same if another part of the app asks for the same channel. - If the user doesn't need the channel info anymore, it can get rid of its
shared_ptr
and theMIX
instance is freed.
What do you think @intosi ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure that works, does it? I'd expect this to be a shared_ptr, or unique_ptr, personally. I'd consider the MIXRegistry to own all the channel objects.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you have hundreds of MIX channels in your roster you probably don't want hundreds of MIX
instances allocated all the time, right?
|
||
} | ||
|
||
void MIXRegistry::joinChannel(const JID& channelJID, const std::unordered_set<std::string>& nodes) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably check if a channel with channelJID
is already on the roster and log a warning instead of issuing a join.
Swiften/Client/Client.cpp
Outdated
@@ -148,13 +154,27 @@ void Client::handleConnected() { | |||
discoManager->handleConnected(); | |||
} | |||
|
|||
void Client::requestFeatures() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure this happening automatically is consistent with the design elsewhere, where network traffic isn't generally generated without being requested. It might be sensible, but it's not plugged in anywhere else, which means it's going to end up duplicated by the current disco logic in Swift isn't it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah. Currently it would be duplicated.
Swiften/Client/Client.cpp
Outdated
void Client::handleFeaturesReceived(DiscoInfo::ref payload, ErrorPayload::ref /*error*/) { | ||
if (payload && payload->hasFeature(DiscoInfo::MIXFeature)) { | ||
mixSupport = true; | ||
mixRegistry = std::make_unique<MIXRegistry>(getJID(), getIQRouter(), getRoster()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Always having a mixRegistry, but it being empty when not supported, probably makes more sense, doesn't it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah. Already mentioned it in #87 (comment) .
Swiften/Client/Client.h
Outdated
@@ -7,6 +7,8 @@ | |||
#pragma once | |||
|
|||
#include <Swiften/Base/API.h> | |||
#include <Swiften/Elements/DiscoInfo.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check the include ordering please.
Swiften/Elements/RosterItemPayload.h
Outdated
@@ -41,12 +41,16 @@ namespace Swift { | |||
unknownContent_ += c; | |||
} | |||
|
|||
void setChannel(bool isChannel) { isChannel_ = isChannel; } | |||
bool getChannel() const { return isChannel_; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We usually name bools like this isX, rather than getX. Also, does it make sense to explicitly call it a MIXChannel, rather than Channel, to avoid ambiguity with other channels?
Swiften/MIX/MIXRegistry.cpp
Outdated
|
||
void MIXRegistry::handleJIDAdded(const JID& jid) { | ||
if (rosterPopulated_ && xmppRoster_->isChannel(jid)) { | ||
std::map<JID, MIX::ref>::iterator i = entries_.find(jid); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not auto?
Swiften/MIX/MIXRegistry.cpp
Outdated
} | ||
} | ||
|
||
std::unordered_set<std::string> MIXRegistry::getJoinedChannels() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't you expect this to return a list of the channel objects, rather than their JIDs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Depends on whether you always want to have the objects in memory even when you don't need them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd have expected that, if you request the mix bits of the roster, it'd then sort it all out for you populate them and you'd then use them. Is that not the likely use case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you are joined to 100 MIX channels but are currently not interested in the messages as you are on mobile or so, you probably don't want to allocate 100 MIXImpl
instances. This way a MIXController
could ask for the MIX
shared_ptr it needs for its channel which is then created for it on demand. Allocating memory for stuff that isn't really used ultimately leads to bloated applications.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless MIXImpls are much bigger than I think they should be, this doesn't seem like a particularly big issue - 100 MIXs worth of messages you're not interested in seems likely to be a bigger issue (which needs sorting out with protocol).
OK, I'll go along with JIDs here for the moment as it's relatively easy to change later.
|
||
void joinChannel(const JID& channelJID, const std::unordered_set<std::string>& nodes); | ||
|
||
void leaveChannel(const JID& channelJID); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is leave being on the registry or on the object itself more sensible?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd say if registry is handling the join and keeping track of joined channels, leave should also be here as successfully leaving a channel depends on (onJIDRemoved).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not entirely convinced, but not a hill for me to die on.
Swiften/MIX/MIXRegistry.h
Outdated
XMPPRoster* xmppRoster_; | ||
bool rosterPopulated_; | ||
typedef std::map<JID, MIX::ref> MIXInstanceMap; | ||
MIXInstanceMap entries_; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure that works, does it? I'd expect this to be a shared_ptr, or unique_ptr, personally. I'd consider the MIXRegistry to own all the channel objects.
@@ -52,11 +52,15 @@ void RosterParser::handleStartElement(const std::string& element, const std::str | |||
if (attributes.getAttribute("ask") == "subscribe") { | |||
currentItem_.setSubscriptionRequested(); | |||
} | |||
} else if (element == "annotate" && ns == "urn:xmpp:mix:roster:0") { | |||
getPayloadInternal()->setAnnotate(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is MIX-specific, shouldn't it be obvious from the method name? setSupportsMIX or setSupportsMIXAnnotations or something?
Swiften/MIX/MIXRegistry.cpp
Outdated
} | ||
|
||
void MIXRegistry::handleJIDRemoved(const JID& jid) { | ||
if (rosterPopulated_ && xmppRoster_->isChannel(jid)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Won't isChannel always be false at this point, because it's been removed from the roster?
@Kev suggested adding |
Update roster encoding for MIX channel Update roster parser and serializer License: This patch is BSD-licensed, see Documentation/Licenses/BSD-simplified.txt for details. Test-Information: Added tests for joining and leaving channels via MIXRegistry, which passes. Tested on Ubuntu 16.04 LTS. Change-Id: Idb9683f45734ac58daa58736fe199dc014b9352a
Updated based on feedback with unit tests. |
Change-Id: Idb9683f45734ac58daa58736fe199dc014b9352a