PNXMPPFramework/Extensions/XEP-0115/XMPPCapabilities.h
2016-02-24 16:56:39 +01:00

381 lines
15 KiB
Objective-C

#import <Foundation/Foundation.h>
#import "XMPP.h"
#define _XMPP_CAPABILITIES_H
@protocol XMPPCapabilitiesStorage;
/**
* This class provides support for capabilities discovery.
*
* It collects our capabilities and publishes them according to the XEP by:
* - Injecting the <c/> element into outgoing presence stanzas
* - Responding to incoming disco#info queries
*
* It also collects the capabilities of available resources,
* provides a mechanism to persistently store XEP-0115 hased caps,
* and makes available a simple API to query (disco#info) a resource or server.
**/
@interface XMPPCapabilities : XMPPModule
{
__strong id <XMPPCapabilitiesStorage> xmppCapabilitiesStorage;
NSString *myCapabilitiesNode;
NSXMLElement *myCapabilitiesQuery; // Full list of capabilites <query/>
NSXMLElement *myCapabilitiesC; // Hashed element <c/>
BOOL collectingMyCapabilities;
NSMutableSet *discoRequestJidSet;
NSMutableDictionary *discoRequestHashDict;
NSMutableDictionary *discoTimerJidDict;
BOOL autoFetchHashedCapabilities;
BOOL autoFetchNonHashedCapabilities;
BOOL autoFetchMyServerCapabilities;
NSTimeInterval capabilitiesRequestTimeout;
NSMutableSet *timers;
}
- (id)initWithCapabilitiesStorage:(id <XMPPCapabilitiesStorage>)storage;
- (id)initWithCapabilitiesStorage:(id <XMPPCapabilitiesStorage>)storage dispatchQueue:(dispatch_queue_t)queue;
@property (nonatomic, strong, readonly) id <XMPPCapabilitiesStorage> xmppCapabilitiesStorage;
/**
* Defines the node attribute in a <c/> element qualified by the 'http://jabber.org/protocol/caps' namespace.
*
* It is RECOMMENDED for the value of the 'node' attribute to be an HTTP URL
* at which a user could find further information about the software product,
* such as "http://github.com/robbiehanson/XMPPFramework"
*
* This MUST NOT be nil
*
* The default value is http://github.com/robbiehanson/XMPPFramework
**/
@property (nonatomic, copy) NSString *myCapabilitiesNode;
/**
* Defines fetching behavior for entities using the XEP-0115 standard.
*
* XEP-0115 defines a technique for hashing capabilities (disco info responses),
* and broadcasting them within a presence element.
* Due to the standardized hashing technique, capabilities associated with a hash may be persisted indefinitely.
*
* The end result is that capabilities need to be fetched less often
* since they are already known due to the caching of responses.
*
* The default value is YES.
**/
@property (assign) BOOL autoFetchHashedCapabilities;
/**
* Defines fetching behavior for entities NOT using the XEP-0115 standard.
*
* Because the capabilities are not associated with a standardized hash,
* it is not possible to cache the capabilities between sessions.
*
* The default value is NO.
*
* It is recommended you leave this value set to NO unless you
* know that you'll need the capabilities of every resource,
* and that fetching of the capabilities cannot be delayed.
*
* You may always fetch the capabilities (if/when needed) via the fetchCapabilitiesForJID method.
**/
@property (assign) BOOL autoFetchNonHashedCapabilities;
/**
* Auto fetch the capabilities of the server upon authentication.
* This uses the non hashed approach outlined in XEP-0030: Service Discovery.
*
* The default value is NO.
**/
@property (assign) BOOL autoFetchMyServerCapabilities;
/**
* Manually fetch the capabilities for the given jid.
*
* The jid must be a full jid (user@domain/resource) or a domain JID (domain without user or resource).
* You would pass a full jid if you wanted to know the capabilities of a particular user's resource.
* You would pass a domain jid if you wanted to know the capabilities of a particular server.
*
* If there is an existing disco request associated with the given jid, this method does nothing.
*
* When the capabilities are received,
* the xmppCapabilities:didDiscoverCapabilities:forJID: delegate method is invoked.
**/
- (void)fetchCapabilitiesForJID:(XMPPJID *)jid;
/**
* This module automatically collects my capabilities.
* See the xmppCapabilities:collectingMyCapabilities: delegate method.
*
* The design of XEP-115 is such that capabilites are expected to remain rather static.
* However, if the capabilities change, this method may be used to perform a manual update.
**/
- (void)recollectMyCapabilities;
@end
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark -
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@protocol XMPPCapabilitiesStorage <NSObject>
@required
//
//
// -- PUBLIC METHODS --
//
//
/**
* Returns whether or not we know the capabilities for a given jid.
*
* The stream parameter is optional.
* If given, the jid must have been registered via the given stream.
* Otherwise it will match the given jid from any stream this storage instance is managing.
**/
- (BOOL)areCapabilitiesKnownForJID:(XMPPJID *)jid xmppStream:(XMPPStream *)stream;
/**
* Returns the capabilities for the given jid.
* The returned element is the <query/> element response to a disco#info request.
*
* The stream parameter is optional.
* If given, the jid must have been registered via the given stream.
* Otherwise it will match the given jid from any stream this storage instance is managing.
**/
- (NSXMLElement *)capabilitiesForJID:(XMPPJID *)jid xmppStream:(XMPPStream *)stream;
/**
* Returns the capabilities for the given jid.
* The returned element is the <query/> element response to a disco#info request.
*
* The given jid should be a full jid (user@domain/resource) or a domin JID (domain without user or resource).
*
* If the jid has broadcast capabilities via the legacy format of XEP-0115,
* the extension list may optionally be retrieved via the ext parameter.
*
* For example, the jid may send a presence element like:
*
* <presence from="jid">
* <c node="imclient.com/caps" ver="1.2" ext="rdserver rdclient avcap"/>
* </presence>
*
* In the above example, the ext string would be set to "rdserver rdclient avcap".
*
* You may pass nil for extPtr if you don't care about the legacy attributes,
* or you could simply use the capabilitiesForJID: method above.
*
* The stream parameter is optional.
* If given, the jid must have been registered via the given stream.
* Otherwise it will match the given jid from any stream this storage instance is managing.
**/
- (NSXMLElement *)capabilitiesForJID:(XMPPJID *)jid ext:(NSString **)extPtr xmppStream:(XMPPStream *)stream;
//
//
// -- PRIVATE METHODS --
//
// These methods are designed to be used ONLY by the XMPPCapabilities class.
//
//
/**
* Configures the capabilities storage class, passing it's parent and parent's dispatch queue.
*
* This method is called by the init methods of the XMPPCapabilities class.
* This method is designed to inform the storage class of it's parent
* and of the dispatch queue the parent will be operating on.
*
* A storage class may choose to operate on the same queue as it's parent,
* as the majority of the time it will be getting called by the parent.
* If both are operating on the same queue, the combination may run faster.
*
* Some storage classes support multiple xmppStreams,
* and may choose to operate on their own internal queue.
*
* This method should return YES if it was configured properly.
* It should return NO only if configuration failed.
* For example, a storage class designed to be used only with a single xmppStream is being added to a second stream.
* The XMPPCapabilites class is configured to ignore the passed
* storage class in it's init method if this method returns NO.
**/
- (BOOL)configureWithParent:(XMPPCapabilities *)aParent queue:(dispatch_queue_t)queue;
/**
* Sets metadata for the given jid.
*
* This method should return:
* - YES if the capabilities for the given jid are known.
* - NO if the capabilities for the given jid are NOT known.
*
* If the hash and algorithm are given, and an associated set of capabilities matches the hash/algorithm,
* this method should link the jid to the capabilities and return YES.
*
* If the linked set of capabilities was not previously linked to the jid,
* the newCapabilities parameter shoud be filled out.
*
* This method may be called multiple times for a given jid with the same information.
* If this method sets the newCapabilitiesPtr parameter,
* the XMPPCapabilities module will invoke the xmppCapabilities:didDiscoverCapabilities:forJID: delegate method.
* This delegate method is designed to be invoked only when the capabilities for the given JID have changed.
* That is, the capabilities for the jid have been discovered for the first time (jid just signed in)
* or the capabilities for the given jid have changed (jid broadcast new capabilities).
**/
- (BOOL)setCapabilitiesNode:(NSString *)node
ver:(NSString *)ver
ext:(NSString *)ext
hash:(NSString *)hash
algorithm:(NSString *)hashAlg
forJID:(XMPPJID *)jid
xmppStream:(XMPPStream *)stream
andGetNewCapabilities:(NSXMLElement **)newCapabilitiesPtr;
/**
* Fetches the associated capabilities hash for a given jid.
*
* If the jid is not associated with a capabilities hash, this method should return NO.
* Otherwise it should return YES, and set the corresponding variables.
**/
- (BOOL)getCapabilitiesHash:(NSString **)hashPtr
algorithm:(NSString **)hashAlgPtr
forJID:(XMPPJID *)jid
xmppStream:(XMPPStream *)stream;
/**
* Clears any associated hash from a jid.
* If the jid is linked to a set of capabilities, it should be unlinked.
*
* This method should not clear the actual capabilities information itself.
* It should simply unlink the connection between the jid and the capabilities.
**/
- (void)clearCapabilitiesHashAndAlgorithmForJID:(XMPPJID *)jid xmppStream:(XMPPStream *)stream;
/**
* Gets the metadata for the given jid.
*
* If the capabilities are known, the areCapabilitiesKnown boolean should be set to YES.
**/
- (void)getCapabilitiesKnown:(BOOL *)areCapabilitiesKnownPtr
failed:(BOOL *)haveFailedFetchingBeforePtr
node:(NSString **)nodePtr
ver:(NSString **)verPtr
ext:(NSString **)extPtr
hash:(NSString **)hashPtr
algorithm:(NSString **)hashAlgPtr
forJID:(XMPPJID *)jid
xmppStream:(XMPPStream *)stream;
/**
* Sets the capabilities associated with a given hash.
*
* Since the capabilities are linked to a hash, these capabilities (and associated hash)
* should be persisted to disk and persisted between multiple sessions/streams.
*
* It is the responsibility of the storage implementation to link the
* associated jids (those with the given hash) to the given set of capabilities.
*
* Implementation Note:
*
* If we receive multiple simultaneous presence elements from
* multiple jids all broadcasting the same capabilities hash:
*
* - A single disco request will be sent to one of the jids.
* - When the response comes back, the setCapabilities:forHash:algorithm: method will be invoked.
*
* The setCapabilities:forJID: method will NOT be invoked for each corresponding jid.
* This is by design to allow the storage implementation to optimize itself.
**/
- (void)setCapabilities:(NSXMLElement *)caps forHash:(NSString *)hash algorithm:(NSString *)hashAlg;
/**
* Sets the capabilities for a given jid.
*
* The jid is guaranteed NOT to be associated with a capabilities hash.
*
* Since the capabilities are NOT linked to a hash,
* these capabilities should not be persisted between multiple sessions/streams.
* See the various clear methods below.
**/
- (void)setCapabilities:(NSXMLElement *)caps forJID:(XMPPJID *)jid xmppStream:(XMPPStream *)stream;
/**
* Marks the disco fetch request as failed so we know not to bother trying again.
*
* This is temporary metadata associated with the jid.
* It should be cleared when we go unavailable or offline, or if the given jid goes unavailable.
* See the various clear methods below.
**/
- (void)setCapabilitiesFetchFailedForJID:(XMPPJID *)jid xmppStream:(XMPPStream *)stream;
/**
* This method is called when we go unavailable or offline.
*
* This method should clear all metadata (node, ver, ext, hash, algorithm, failed) from all jids in the roster.
* All jids should be unlinked from associated capabilities.
*
* If the associated capabilities are persistent, they should not be cleared.
* That is, if the associated capabilities are associated with a hash, they should be persisted.
*
* Non persistent capabilities (those not associated with a hash)
* should be cleared at this point as they will no longer be linked to any users.
**/
- (void)clearAllNonPersistentCapabilitiesForXMPPStream:(XMPPStream *)stream;
/**
* This method is called when the given jid goes unavailable.
*
* This method should clear all metadata (node, ver, ext, hash ,algorithm, failed) from the given jid.
* The jid should be unlinked from associated capabilities.
*
* If the associated capabilities are persistent, they should not be cleared.
* That is, if the associated capabilities are associated with a hash, they should be persisted.
*
* Non persistent capabilities (those not associated with a hash) should be cleared.
**/
- (void)clearNonPersistentCapabilitiesForJID:(XMPPJID *)jid xmppStream:(XMPPStream *)stream;
@end
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark -
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@protocol XMPPCapabilitiesDelegate
@optional
/**
* Use this delegate method to add specific capabilities.
* This method in invoked automatically when the stream is connected for the first time,
* or if the module detects an outgoing presence element and my capabilities haven't been collected yet
*
* The design of XEP-115 is such that capabilites are expected to remain rather static.
* However, if the capabilities change, the recollectMyCapabilities method may be used to perform a manual update.
**/
- (void)xmppCapabilities:(XMPPCapabilities *)sender collectingMyCapabilities:(NSXMLElement *)query;
/**
* Use this delegate method to return the feature you want to have in your capabilities e.g. @[@"urn:xmpp:archive"]
* Duplicate features are automatically discarded
* For more control over your capablities use xmppCapabilities:collectingMyCapabilities:
**/
- (NSArray *)myFeaturesForXMPPCapabilities:(XMPPCapabilities *)sender;
/**
* Invoked when capabilities have been discovered for an available JID.
*
* The caps element is the <query/> element response to a disco#info request.
**/
- (void)xmppCapabilities:(XMPPCapabilities *)sender didDiscoverCapabilities:(NSXMLElement *)caps forJID:(XMPPJID *)jid;
@end