Skip to content
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

added support for XEP-0030 with tests #736

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions Extensions/XEP-0030/XMPPIQ+XEP_0030.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// XMPPIQ+XEP_0030.h
// XMPPFramework
//
// Created by Andres on 7/07/16.
// Copyright © 2016 Inaka. All rights reserved.
//

#import <XMPPFramework/XMPPFramework.h>
#import "XMPPFramework/XMPPJID.h"

@interface XMPPIQ (XEP_0030)

+ (nonnull XMPPIQ *) discoverItemsAssociatedWithJID:(nonnull XMPPJID *)jid;
+ (nonnull XMPPIQ *) discoverInfoAssociatedWithJID:(nonnull XMPPJID *)jid;
+ (nullable NSArray <NSXMLElement *> *)parseDiscoveredItemsFromIQ:(nonnull XMPPIQ *)iq;
+ (nullable NSArray <NSXMLElement *> *)parseDiscoveredInfoFromIQ:(nonnull XMPPIQ *)iq;

@end
89 changes: 89 additions & 0 deletions Extensions/XEP-0030/XMPPIQ+XEP_0030.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
//
// XMPPIQ+XEP_0030.m
// XMPPFramework
//
// Created by Andres on 7/07/16.
// Copyright © 2016 Inaka. All rights reserved.
//

#import "XMPPIQ+XEP_0030.h"
#import "NSXMLElement+XMPP.h"
#import "XMPPConstants.h"

@implementation XMPPIQ (XEP_0060)

+ (nonnull XMPPIQ *) discoverItemsAssociatedWithJID:(nonnull XMPPJID *)jid {

// <iq type='get'
// from='romeo@montague.net/orchard'
// to='shakespeare.lit'
// id='items1'>
// <query xmlns='http://jabber.org/protocol/disco#items'/> // disco#items
// </iq>

NSString *iqID = [XMPPStream generateUUID];
NSXMLElement *query = [NSXMLElement elementWithName:@"query" xmlns: XMPPDiscoItemsNamespace];
return [XMPPIQ iqWithType:@"get" to:jid elementID:iqID child:query];

}

+ (nonnull XMPPIQ *) discoverInfoAssociatedWithJID:(nonnull XMPPJID *)jid {

// <iq type='get'
// from='romeo@montague.net/orchard'
// to='shakespeare.lit'
// id='items1'>
// <query xmlns='http://jabber.org/protocol/disco#info'/> // disco#info
// </iq>

NSString *iqID = [XMPPStream generateUUID];
NSXMLElement *query = [NSXMLElement elementWithName:@"query" xmlns: XMPPDiscoInfoNamespace];
return [XMPPIQ iqWithType:@"get" to:jid elementID:iqID child:query];

}

+ (nullable NSArray <NSXMLElement *> *)parseDiscoveredItemsFromIQ:(nonnull XMPPIQ *)iq {
// <iq xmlns='jabber:client' from='shakespeare.lit'
// to='test@shakespeare.lit'
// id='items1' type='result'>
// <query xmlns='http://jabber.org/protocol/disco#items'>
// <item jid='muc.erlang-solutions.com'/>
// <item jid='muclight.erlang-solutions.com'/>
// <item jid='pubsub.erlang-solutions.com'/>
// <item jid='vjud.erlang-solutions.com'/>
// </query>
// </iq>

NSXMLElement *query = [iq elementForName:@"query" xmlns: XMPPDiscoItemsNamespace];
if(query) {
return [query elementsForName:@"item"];
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

what happens if !query? Also violates nonnull


return nil;
}

+ (nullable NSArray <NSXMLElement *> *)parseDiscoveredInfoFromIQ:(nonnull XMPPIQ *)iq {
// <iq xmlns='jabber:client' from='shakespeare.lit'
// to='test@shakespeare.lit'
// id='items1' type='result'>
// <query xmlns='http://jabber.org/protocol/disco#info'>
// <identity category='pubsub' type='pep'/>
// <identity category='server' type='im' name='ejabberd'/>
// <feature var='erlang-solutions.com:xmpp:token-auth:0'/>
// <feature var='http://jabber.org/protocol/disco#info'/>
// <feature var='http://jabber.org/protocol/disco#items'/>
// <feature var='http://jabber.org/protocol/pubsub'/>
// <feature var='urn:xmpp:mam:0'/>
// <feature var='urn:xmpp:mam:1'/>
// </query>
// </iq>

NSXMLElement *query = [iq elementForName:@"query" xmlns: XMPPDiscoInfoNamespace];
if(query) {
return [query children] ? [query children] : ((NSArray <NSXMLElement *> *)[[NSArray alloc] init]);
}

return nil;
}

@end
31 changes: 31 additions & 0 deletions Extensions/XEP-0030/XMPPServiceDiscovery.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// XMPPServiceDiscovery.h
// Mangosta
//
// Created by Andres Canal on 4/27/16.
// Copyright © 2016 Inaka. All rights reserved.
//

#import <XMPPFramework/XMPPFramework.h>

@class XMPPIDTracker;

@interface XMPPServiceDiscovery : XMPPModule {
XMPPIDTracker *xmppIDTracker;
}

- (void)discoverInformationAboutJID:(nonnull XMPPJID *)jid;
- (void)discoverItemsAssociatedWithJID:(nonnull XMPPJID *)jid;

@end

@protocol XMPPServiceDiscoveryDelegate

@optional

- (void)xmppServiceDiscovery:(nonnull XMPPServiceDiscovery *)sender didDiscoverInformation:(nonnull NSArray<NSXMLElement *> *)items;
- (void)xmppServiceDiscovery:(nonnull XMPPServiceDiscovery *)sender didDiscoverItems:(nonnull NSArray <NSXMLElement *>*)items;

- (void)xmppServiceDiscovery:(nonnull XMPPServiceDiscovery *)sender didFailToDiscover:(nonnull XMPPIQ *)iq;

@end
99 changes: 99 additions & 0 deletions Extensions/XEP-0030/XMPPServiceDiscovery.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
//
// XMPPServiceDiscovery.m
// Mangosta
//
// Created by Andres Canal on 4/27/16.
// Copyright © 2016 Inaka. All rights reserved.
//

#import "XMPPServiceDiscovery.h"
#import "XMPPIQ+XEP_0030.h"
#import "XMPPIDTracker.h"
#import "XMPPConstants.h"

@implementation XMPPServiceDiscovery

- (BOOL)activate:(XMPPStream *)aXmppStream {

if ([super activate:aXmppStream]) {
xmppIDTracker = [[XMPPIDTracker alloc] initWithDispatchQueue:moduleQueue];

return YES;
}

return NO;
}

- (void)deactivate {
dispatch_block_t block = ^{ @autoreleasepool {

[xmppIDTracker removeAllIDs];
xmppIDTracker = nil;

}};

if (dispatch_get_specific(moduleQueueTag))
block();
else
dispatch_sync(moduleQueue, block);

[super deactivate];
}

- (void) discoverWithIQ:(XMPPIQ *) infoOrItem {

dispatch_block_t block = ^{ @autoreleasepool {

NSString *iqID = [infoOrItem elementID];
[xmppIDTracker addID:iqID
target:self
selector:@selector(handleDiscovery:withInfo:)
timeout:60.0];

[xmppStream sendElement:infoOrItem];
}};

if (dispatch_get_specific(moduleQueueTag))
block();
else
dispatch_async(moduleQueue, block);
}

- (void)discoverInformationAboutJID:(XMPPJID *)jid{
[self discoverWithIQ:[XMPPIQ discoverInfoAssociatedWithJID:jid]];
}


- (void)discoverItemsAssociatedWithJID:(XMPPJID *)jid{
[self discoverWithIQ:[XMPPIQ discoverItemsAssociatedWithJID:jid]];
}

- (void)handleDiscovery:(XMPPIQ *)iq withInfo:(id <XMPPTrackingInfo>)info{

if ([[iq type] isEqualToString:@"result"]){
NSXMLElement *query = [iq elementForName:@"query"];
NSArray *items = [query children];

if ([query.xmlns isEqualToString:XMPPDiscoInfoNamespace]) {
[multicastDelegate xmppServiceDiscovery:self didDiscoverInformation:items];
} else {
[multicastDelegate xmppServiceDiscovery:self didDiscoverItems:items];
}

} else {
[multicastDelegate xmppServiceDiscovery:self didFailToDiscover:iq];
}
}

- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq {

NSString *type = [iq type];

if ([type isEqualToString:@"result"] || [type isEqualToString:@"error"]){
return [xmppIDTracker invokeForID:[iq elementID] withObject:iq];
}

return NO;
}

@end
7 changes: 7 additions & 0 deletions XMPPFramework.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,12 @@ s.source = { :git => 'https://github.com/robbiehanson/XMPPFramework.git', :branc
ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}"
end

s.subspec 'XEP-0030' do |ss|
ss.source_files = 'Extensions/XEP-0030/*.{h,m}'
ss.dependency 'XMPPFramework/Core'
ss.prefix_header_contents = "#define HAVE_XMPP_SUBSPEC_#{name.upcase.sub('-', '_')}"
end

s.subspec 'All' do |ss|
ss.dependency 'XMPPFramework/Core'
ss.dependency 'XMPPFramework/BandwidthMonitor'
Expand Down Expand Up @@ -400,5 +406,6 @@ s.source = { :git => 'https://github.com/robbiehanson/XMPPFramework.git', :branc
ss.dependency 'XMPPFramework/XEP-0363'
ss.dependency 'XMPPFramework/XEP-0313'
ss.dependency 'XMPPFramework/XMPPMUCLight'
ss.dependency 'XMPPFramework/XEP-0030'
end
end
Loading