-
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
Add MIXRegistry, Limber MIX Mock Server and MIX Example #88
base: master
Are you sure you want to change the base?
Conversation
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
License: This patch is BSD-licensed, see Documentation/Licenses/BSD-simplified.txt for details. Test-Information: Tests added for joining and leaving MIX channels as in XEP-0369, which passes. Tested on Ubuntu 16.04 LTS. Change-Id: Ib85d6e866e09db060b9b2da428f074dfbfd26385
Limber/MIXMockServer.cpp
Outdated
channels_.insert(channelJID); | ||
} | ||
|
||
std::unordered_set<std::string>& getChannels() { |
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.
Shouldn't this be a const reference?
Limber/MIXMockServer.cpp
Outdated
|
||
//If request comes to domain service | ||
if (stanza->getTo().isValid() && stanza->getTo() == session->getLocalJID()) { | ||
if (std::shared_ptr<IQ> iq = std::dynamic_pointer_cast<IQ>(stanza)) { |
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.
Are you masking the existing iq variable with the same contents deliberately here?
Limber/MIXMockServer.cpp
Outdated
if(iq->getPayload<RosterPayload>()) { | ||
SWIFT_LOG(debug) << "Query: Roster" << std::endl; | ||
session->sendElement(IQ::createResult(iq->getFrom(), iq->getID(), std::make_shared<RosterPayload>())); | ||
} |
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.
Continuing processing the rest of handleElementReceived after this sendElement (and the ones below) isn't really useful, is it?
Limber/MIXMockServer.cpp
Outdated
SimpleEventLoop eventLoop; | ||
SimpleUserRegistry userRegistry; | ||
|
||
userRegistry.addUser(JID("[email protected]"), "mixtest"); |
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 think I would prefer it if you used example.com, which is guaranteed to never mask existing domains, instead of assuming there will never be a .tg TLD.
assert(mixRegistry_); | ||
assert(mixRegistry_->getMIXInstance(jid)); | ||
|
||
cout << "Successfully joined channel " << jid << std::endl; |
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.
Mixing prefixed and non-prefixed iostream bits looks odd. I think I'd prefer the prefixed ones here.
Swiften/Roster/XMPPRosterImpl.cpp
Outdated
@@ -40,6 +40,15 @@ void XMPPRosterImpl::clear() { | |||
onRosterCleared(); | |||
} | |||
|
|||
bool XMPPRosterImpl::isMIXChannel(const JID& jid) { | |||
std::map<JID, XMPPRosterItem>::const_iterator i = entries_.find(jid.toBare()); |
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.
Assuming you really need the explicit const iterator here, I would prefer RosterMap::const_iterator instead.
Limber/MIXMockServer.cpp
Outdated
if (iq) { | ||
if(iq->getPayload<RosterPayload>()) { | ||
SWIFT_LOG(debug) << "Query: Roster" << std::endl; | ||
session->sendElement(IQ::createResult(iq->getFrom(), iq->getID(), std::make_shared<RosterPayload>())); |
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 isn't the final version right? I would expect it to return the MIX channels which the user has joined.
Swiften/Client/Client.h
Outdated
@@ -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.
This could be a unique_ptr
, right?
Updated based on feedback and added roster sync between clients: Example (Client 1) : ./Swiften/Examples/MIXListAndJoin/MIXListAndJoin [email protected]/some mixtest2 example.com
Connecting...Connected
Request list of channels.
List of rooms at example.com
1. coven - [email protected]
Request supported nodes for MIX channel: [email protected]
Nodes supported by channel [email protected]
1. urn:xmpp:mix:nodes:participants
2. urn:xmpp:mix:nodes:messages
3. urn:xmpp:mix:nodes:presence
4. urn:xmpp:mix:nodes:jidmap
Already Joined channels:
No channels already joined.
Successfully joined channel [email protected]
[warning] Swiften/MIX/MIXRegistry.cpp:40 joinChannel: Channel already joined: [email protected]
However (client 2 of the same user): ./Swiften/Examples/MIXListAndJoin/MIXListAndJoin [email protected]/someelse mixtest2 example.com
Connecting...Connected
Request list of channels.
List of rooms at example.com
1. coven - [email protected]
Request supported nodes for MIX channel: [email protected]
Nodes supported by channel [email protected]
1. urn:xmpp:mix:nodes:participants
2. urn:xmpp:mix:nodes:messages
3. urn:xmpp:mix:nodes:presence
4. urn:xmpp:mix:nodes:jidmap
Already Joined channels:
1. coven - [email protected]
[warning] Swiften/MIX/MIXRegistry.cpp:40 joinChannel: Channel already joined: [email protected] |
d8ef76f
to
acb0f16
Compare
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.
Some feedback inline.
Limber/MIXMockServer.cpp
Outdated
* All rights reserved. | ||
* See the COPYING file for more information. | ||
*/ | ||
/* |
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.
Please leave a newline between copyright blocks.
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.
Will udpate.
Limber/MIXMockServer.cpp
Outdated
//If request comes to own local server | ||
if (stanza->getTo().isValid() && stanza->getTo() == session->getRemoteJID().toBare()) { | ||
if (auto incomingJoinPayload = iq->getPayload<MIXJoin>()) { | ||
if (boost::optional<JID> channelJID = incomingJoinPayload->getChannel()) { |
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 use auto
in the line above, but not here?
Limber/MIXMockServer.cpp
Outdated
} | ||
|
||
if (auto incomingLeavePayload = iq->getPayload<MIXLeave>()) { | ||
if (boost::optional<JID> channelJID = incomingLeavePayload->getChannel()) { |
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 use auto
in the line above, but not here?
Limber/MIXMockServer.cpp
Outdated
return; | ||
} | ||
} else { | ||
session->sendElement(IQ::createError(iq->getFrom(), iq->getID(), ErrorPayload::BadRequest, ErrorPayload::Cancel)); |
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 it's not an IQ you can't return an IQ error. You should probably just ignore it in this case.
Limber/MIXMockServer.cpp
Outdated
stanza->setFrom(session->getRemoteJID()); | ||
|
||
auto iq = std::dynamic_pointer_cast<IQ>(stanza); | ||
if (iq) { |
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.
It probably makes more sense to test for !iq
and handle the error case there and afterwards check if it's a roster payload.
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, makes more sense.
Limber/MIXMockServer.cpp
Outdated
} | ||
|
||
//If request comes to domain service | ||
if (stanza->getTo().isValid() && stanza->getTo() == session->getLocalJID()) { |
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 the isValid()
test required here?
Limber/MIXMockServer.cpp
Outdated
} | ||
return; | ||
} | ||
} |
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 is quite long. It probably makes sense to split it up in parts. Like handleElementReceivedForAccount
, handleElementReceivedForMIXService
, handleElementReceivedForMIXChannel
, etc.
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've split the function into the three cases now.
Swiften/Elements/RosterPayload.h
Outdated
@@ -42,7 +42,16 @@ namespace Swift { | |||
version_ = version; | |||
} | |||
|
|||
bool hasMIXAnnotationSupport() const { |
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 name doesn't make it clear what it is for. You probably want to enable requesting MIX annotations for roster requests. How about hasRequestMIXAnnotations()
? Similar for the following method.
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.
Updated.
c6aa5b3
to
6c07dce
Compare
Updated based on feedback. |
Limber/MIXMockServer.cpp
Outdated
|
||
auto iq = std::dynamic_pointer_cast<IQ>(stanza); | ||
if (!iq) { | ||
session->sendElement(IQ::createError(iq->getFrom(), iq->getID(), ErrorPayload::BadRequest, ErrorPayload::Cancel)); |
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 it's not an IQ, you cannot respond with an IQ error!!!! IQ errors are when you receive an IQ but do not understand the content and cannot sensibly handle 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.
I am now returning if element is not an iq.
Limber/MIXMockServer.cpp
Outdated
} | ||
|
||
//If request comes to domain service | ||
if (stanza->getTo() == session->getLocalJID()) { |
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.
These should probably be else if
statements, or does it make sense to have an IQ handled by multiple handleELementReceivedForX
methods?
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.
Updated.
Limber/MIXMockServer.cpp
Outdated
|
||
void handleElementReceivedForAccount(IQ::ref iq, std::shared_ptr<ServerFromClientSession> session) { | ||
if (auto incomingJoinPayload = iq->getPayload<MIXJoin>()) { | ||
if (auto channelJID = incomingJoinPayload->getChannel()) { |
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.
Creating two helper methods to handle join and leave would help to further improve readability of the code. You could then simply call them in here.
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.
Added handleJoin and handleLeave methods.
Limber/MIXMockServer.cpp
Outdated
session->sendElement(IQ::createError(iq->getFrom(), iq->getID(), ErrorPayload::BadRequest, ErrorPayload::Cancel)); | ||
} | ||
} | ||
return; |
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.
Could you remove return
statements at the end of void
methods. Thanks.
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 PR is slowly getting there. 👍
Limber/MIXMockServer.cpp
Outdated
return; | ||
} | ||
|
||
if(iq->getPayload<RosterPayload>()) { |
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.
Shouldn't this if be in the handleElementReceivedForAccount
method? After all roster queries go to the account, not?
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.
Roster queries does not have a "to" field, therefore if conditions down there won't pass.
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.
handleElementReceivedForAccount is handling all queries for user's own local server.
Limber/MIXMockServer.cpp
Outdated
handleElementReceivedForMIXChannel(iq, session); | ||
} | ||
|
||
//If request comes to domain service |
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.
Could you move the comments for these if inside the if block so that the else if (…
directly follows the line with the }
, thanks. The current style makes it appear an if statement has ended while the corresponding else is following up a couple lines below.
Limber/MIXMockServer.cpp
Outdated
|
||
private: | ||
IDGenerator idGenerator_; | ||
PlatformXMLParserFactory xmlParserFactory; |
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.
Inconsistent, should end with _
as well.
f4035e2
to
67238a4
Compare
This allows different client of same user to connect to server and retrieves already connected channels. License: This patch is BSD-licensed, see Documentation/Licenses/BSD-simplified.txt for details. Test-Information: Tests added for joining and leaving MIX channels as in XEP-0369, which passes. Tested on Ubuntu 16.04 LTS. Change-Id: I31d0b68528ea0653685e6bcbc66e8131cb2c0eb4
Limber/MIXMockServer.cpp
Outdated
//If request comes to domain service | ||
handleElementReceivedForMIXService(iq, session); | ||
} else if (stanza->getTo() == session->getRemoteJID().toBare() || stanza->getTo() == JID()) { | ||
//If request comes to own local server |
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 is to the account and not to the local server, the local server would be to='server domain'
.
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.
Updated the comment.
Limber/MIXMockServer.cpp
Outdated
} | ||
|
||
std::shared_ptr<RosterPayload> getRosterPayloadFromXMPPRoster(std::shared_ptr<XMPPRosterImpl> roster) { | ||
auto rosterPayload = std::make_shared<RosterPayload>(); |
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.
getFoo()
usually describes a getter method. This seems to be a) not a method to retrieve a member and b) a method that does not otherwise access members, so can be static, right?
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.
Yes this can be a static method.
|
||
#include <iostream> | ||
#include <memory> | ||
#include <unordered_set> |
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.
You are using assert()
but do not #include
cassert header.
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.
Included.
int channelCount = 0; | ||
std::cout << "Already Joined channels: " << std::endl; | ||
for (auto item : xmppRoster->getItems()) { | ||
channelCount++; |
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.
Channels are only those in the roster that have the mix annotation. However, the MIX registry should probably be used to fetch the already joined channels, which has access to the roster. This way if the user wants to do something MIX related, they can always go tho the MIXRegistry
, right? Opinions, @tarun018 @Kev ?
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.
Seems like a sensible idea. I wanted to hold my client till onInitialRosterPopulated is emitted and syncRegistryWithRoster is successfully executed.
mixRegistry_->onChannelJoinFailed.connect(&handleChannelJoinFailed); | ||
mixRegistry_->onChannelLeft.connect(&handleChannelLeft); | ||
|
||
XMPPRoster* xmppRoster = client->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.
Please use auto
here.
} | ||
|
||
static void handleRosterPopulated() { | ||
XMPPRoster* xmppRoster = client->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.
Please use auto
here.
std::cout << "Connecting..." << std::flush; | ||
client->connect(options); | ||
{ | ||
Timer::ref timer = networkFactories.getTimerFactory()->createTimer(30000); |
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.
Please use `auto´ here.
Timer::ref timer = networkFactories.getTimerFactory()->createTimer(30000); | ||
timer->onTick.connect(boost::bind(&SimpleEventLoop::stop, &eventLoop)); | ||
|
||
Timer::ref disconnectTimer = networkFactories.getTimerFactory()->createTimer(25000); |
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.
Please use auto
here.
Swiften/MIX/MIXRegistry.h
Outdated
#pragma once | ||
|
||
#include <memory> | ||
#include <unordered_set> |
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.
Missing a #include <string>
.
@@ -7,6 +7,7 @@ | |||
#include <iostream> | |||
#include <memory> | |||
#include <unordered_set> | |||
#include <cassert> |
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.
Please sort headers, there is a script for this.
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.
Updated.
Swiften/MIX/MIXRegistry.h
Outdated
@@ -8,6 +8,7 @@ | |||
|
|||
#include <memory> | |||
#include <unordered_set> | |||
#include <string> |
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.
Please sort headers.
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.
Updated.
Change-Id: I98bda1d18847cd1fabffde2c0f92fced31d2a5f3
Change-Id: Iab547e141952b29f4c9703035d2a1808927554c4
Swiften/MIX/MIXRegistry.cpp
Outdated
namespace Swift { | ||
|
||
MIXRegistry::MIXRegistry(const JID& ownJID, IQRouter* iqRouter, XMPPRoster* xmppRoster) : ownJID_(ownJID), iqRouter_(iqRouter), xmppRoster_(xmppRoster) { | ||
scopedConnection_ = xmppRoster_->onInitialRosterPopulated.connect(boost::bind(&MIXRegistry::syncRegistryWithRoster, this)); |
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.
scopedConnection_
doesn't sensibly describe the variable. That it is a scoped connection is clear from the type. Maybe name it initialRosterPopulationConnection_
or something like that
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.
Updated.
Swiften/MIX/MIXRegistry.cpp
Outdated
|
||
} | ||
|
||
void MIXRegistry::syncRegistryWithRoster() { |
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 can be a C++11 lambda instead in the ctor, as the method name doesn't match project convention anyway (handle*
).
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.
Added a lambda function.
Swiften/MIX/MIXRegistry.cpp
Outdated
SWIFT_LOG(debug) << "Syncing with roster items. " << std::endl; | ||
for (auto item : xmppRoster_->getItems()) { | ||
if (item.isMIXChannel()) { | ||
SWIFT_LOG(debug) << item.getJID() << std::endl; |
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.
Pretty detailed logging. Probably not needed.
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.
Updated.
Swiften/MIX/MIXRegistry.cpp
Outdated
SWIFT_LOG(debug) << item.getJID() << std::endl; | ||
auto i = entries_.find(item.getJID()); | ||
if (i == entries_.end()) { | ||
SWIFT_LOG(debug) << "Adding " << item.getJID() << std::endl; |
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.
Pretty detailed logging. Probably not needed.
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.
Updated.
Swiften/MIX/MIXRegistry.h
Outdated
void handleJoinResponse(MIXJoin::ref, ErrorPayload::ref); | ||
void handleLeaveResponse(MIXLeave::ref, ErrorPayload::ref); | ||
|
||
public: |
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.
Please move those in front of the the private methods above.
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.
Updated.
Change-Id: Ie4a349c6b9ef35f08f367885755446c316f1e20e
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 ok to me now. What do you think @Kev ?
Standard output shows:
Connecting...Connected
Request list of channels.
List of rooms at example.tg
1. coven - [email protected]
Request supported nodes for MIX channel: [email protected]
Nodes supported by channel [email protected]
1. urn:xmpp:mix:nodes:participants
2. urn:xmpp:mix:nodes:messages
3. urn:xmpp:mix:nodes:presence
4. urn:xmpp:mix:nodes:jidmap
Successfully joined channel [email protected]
[warning] Swiften/MIX/MIXRegistry.cpp:24 joinChannel: Channel already joined: [email protected]
Successfully left channel [email protected]
Warning is intentional to notify about asking to join an already joined channel.