Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@tarun018
Copy link
Contributor

@tarun018 tarun018 commented Aug 4, 2017

Change-Id: Idb9683f45734ac58daa58736fe199dc014b9352a

Copy link
Collaborator

@tfar tfar left a 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.

directedPresenceSender = new DirectedPresenceSender(stanzaChannelPresenceSender);
discoManager = new ClientDiscoManager(getIQRouter(), directedPresenceSender, networkFactories->getCryptoProvider());

mixRegistry = new MIXRegistry(roster);
Copy link
Collaborator

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.

PresenceOracle* presenceOracle;
DirectedPresenceSender* directedPresenceSender;
StanzaChannelPresenceSender* stanzaChannelPresenceSender;
MIXRegistry* mixRegistry;
Copy link
Collaborator

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.

unknownContent_ += c;
}

void setChannel() { isChannel_ = true; }
Copy link
Collaborator

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.

class SWIFTEN_API MIXRegistry {
public:
MIXRegistry(XMPPRoster* xmppRoster);
virtual ~MIXRegistry();
Copy link
Collaborator

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.

blockListManager = new ClientBlockListManager(getIQRouter());

mixSupport = false;
requestFeatures();
Copy link
Collaborator

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.

jingleSessionManager = new JingleSessionManager(getIQRouter());
blockListManager = new ClientBlockListManager(getIQRouter());

mixSupport = false;
Copy link
Collaborator

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.

Copy link
Contributor Author

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.

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;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be onChannelLeft.

}
}

std::unordered_set<std::string> MIXRegistry::getJoinedChannels() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. 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.
  2. Shouldn't it return JIDs rather than strings?
  3. It should return a list of all channels in the roster.

Copy link
Contributor Author

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) {
Copy link
Collaborator

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.

IQRouter* iqRouter_;
XMPPRoster* xmppRoster_;
bool rosterPopulated_;
typedef std::map<JID, MIX::ref> MIXInstanceMap;
Copy link
Collaborator

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.

XMPPRoster* xmppRoster_;
bool rosterPopulated_;
typedef std::map<JID, MIX::ref> MIXInstanceMap;
MIXInstanceMap entries_;
Copy link
Collaborator

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:

  1. You create your Client instance and go online with it.
  2. Ask the MIXRegistry for the channels.
  3. Call MIXRegistry::getMIX(channelJID) to get a shared_ptr<MIX>. MIXRegistry holds a weak_ptr to it so it can hand out the same if another part of the app asks for the same channel.
  4. If the user doesn't need the channel info anymore, it can get rid of its shared_ptr and the MIX instance is freed.

What do you think @intosi ?

Copy link
Member

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.

Copy link
Collaborator

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) {
Copy link
Collaborator

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.

discoManager->handleConnected();
}

void Client::requestFeatures() {
Copy link
Member

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?

Copy link
Collaborator

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.

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());
Copy link
Member

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?

Copy link
Collaborator

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) .

#pragma once

#include <Swiften/Base/API.h>
#include <Swiften/Elements/DiscoInfo.h>
Copy link
Member

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.

}

void setChannel(bool isChannel) { isChannel_ = isChannel; }
bool getChannel() const { return isChannel_; }
Copy link
Member

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?


void MIXRegistry::handleJIDAdded(const JID& jid) {
if (rosterPopulated_ && xmppRoster_->isChannel(jid)) {
std::map<JID, MIX::ref>::iterator i = entries_.find(jid);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not auto?

}
}

std::unordered_set<std::string> MIXRegistry::getJoinedChannels() {
Copy link
Member

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?

Copy link
Collaborator

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.

Copy link
Member

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?

Copy link
Collaborator

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.

Copy link
Member

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);
Copy link
Member

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?

Copy link
Contributor Author

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).

Copy link
Member

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.

XMPPRoster* xmppRoster_;
bool rosterPopulated_;
typedef std::map<JID, MIX::ref> MIXInstanceMap;
MIXInstanceMap entries_;
Copy link
Member

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.

currentItem_.setSubscriptionRequested();
}
} else if (element == "annotate" && ns == "urn:xmpp:mix:roster:0") {
getPayloadInternal()->setAnnotate(true);
Copy link
Member

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?

}

void MIXRegistry::handleJIDRemoved(const JID& jid) {
if (rosterPopulated_ && xmppRoster_->isChannel(jid)) {
Copy link
Member

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?

@tfar
Copy link
Collaborator

tfar commented Aug 7, 2017

@Kev suggested adding bool includeMIX = false to Client::requestRoster and do away with automatic feature discovery. Client::getMIXRegistry() should always return a registry. Feature discovery on whether an account supports MIX or not is supposed to happen by the user of Client.

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
@tarun018
Copy link
Contributor Author

tarun018 commented Aug 9, 2017

Updated based on feedback with unit tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants