XMPPCapabilities.h
14.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
#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