XMPPStreamManagement.h
26.7 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
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
#import <Foundation/Foundation.h>
#import "XMPP.h"
#define _XMPP_STREAM_MANAGEMENT_H
@protocol XMPPStreamManagementStorage;
@interface XMPPStreamManagement : XMPPModule <XMPPCustomBinding>
/**
* The XMPPStreamManagement extension implements XEP-0198:
* http://xmpp.org/extensions/xep-0198.html
*
* @param storage
* You must configure the extension with a storage module.
* A persistent storage layer is recommended for distribution.
* For testing, or if you're not planning on using stream resumption, then the memory storage solution will work.
*
* @param queue
* The standard dispatch_queue option, with which to run the extension on.
**/
- (id)initWithStorage:(id <XMPPStreamManagementStorage>)storage;
- (id)initWithStorage:(id <XMPPStreamManagementStorage>)storage dispatchQueue:(dispatch_queue_t)queue;
@property (nonatomic, strong, readonly) id <XMPPStreamManagementStorage> storage;
#pragma mark Enable
/**
* This method sends the <enable> stanza to the server to request enabling stream management.
*
* XEP-0198 specifies that the <enable> stanza should only be sent by clients after authentication,
* and after binding has occurred.
*
* The servers response is reported via the delegate methods:
* @see xmppStreamManagement:wasEnabled:
* @see xmppStreamManagement:wasNotEnabled:
*
* @param supportsResumption
* Whether the client should request resumptions support.
* If YES, the resume attribute will be included. E.g. <enable resume='true'/>
*
* @param maxTimeout
* Allows you to specify the client's preferred maximum resumption time.
* This is optional, and will only be sent if you provide a positive value (maxTimeout > 0.0).
* Note that XEP-0198 only supports sending this value in seconds.
* So it the provided maxTimeout includes millisecond precision, this will be ignored via truncation
* (rounding down to nearest whole seconds value).
*
* @see supportsStreamManagement
**/
- (void)enableStreamManagementWithResumption:(BOOL)supportsResumption maxTimeout:(NSTimeInterval)maxTimeout;
#pragma mark Resume
/**
* If set to YES, then the extension will automatically attempt to resume any sessions that appear resumable.
*
* That is, if the canResumeStream method would return YES, then the module will automatically plug into the xmppStream,
* and attempts to resume the session. If the attempt fails, the xmppStream will automatically fall back to
* the standard binding process.
*
* Remember: If the extension does not believe that resumption is possible, then it won't attempt to resume.
* That is, if it doesn't have data in storage that matches the current connection, or the data is expired,
* then it allows the xmppStream to perform standard binding immediately, without attempting to resume.
*
* If you wish to handle stream resumption manually, then you can simply implement xmppStreamWillBind:,
* and return this extension instance according to your own conditions.
*
* In order to determine if a stream was resumed, you should invoke didResumeWithAckedStanzaIds:serverResponse:
* from within the xmppStreamDidAuthenticate: callback.
*
* The default value is NO.
**/
@property (atomic, readwrite) BOOL autoResume;
/**
* This method is meant to be called by other extensions when they receive an xmppStreamDidAuthenticate callback.
*
* Returns YES if the stream was resumed during the authentication process.
* Returns NO otherwise (if resume wasn't available, or it failed).
*
* Other extensions may wish to skip certain setup processes that aren't
* needed if the stream was resumed (since the previous session state has been restored server-side).
**/
@property (atomic, readonly) BOOL didResume;
/**
* This method is meant to be called when you receive an xmppStreamDidAuthenticate callback.
*
* It is used instead of a standard delegate method in order to provide a cleaner API.
* By using this method, one can put all the logic for handling authentication in a single place.
* But more importantly, it solves several subtle timing and threading issues.
*
* > A delegate method could have hit either before or after xmppStreamDidAuthenticate, depending on thread scheduling.
* > We could have queued it up, and forced it to hit after.
* > But your code would likely still have needed to add a check within xmppStreamDidAuthenticate...
*
* @param stanzaIdsPtr (optional)
* Just like the stanzaIdsPtr provided in xmppStreamManagement:didReceiveAckForStanzaIds:.
* This comes from the h value provided within the <resumed h='X'/> stanza sent by the server.
*
* @param responsePtr (optional)
* Returns the response we got from the server. Either <resumed/> or <failed/>.
* This will be nil if resume wasn't tried.
*
* @return
* YES if the stream was resumed.
* NO otherwise.
**/
- (BOOL)didResumeWithAckedStanzaIds:(NSArray **)stanzaIdsPtr
serverResponse:(NSXMLElement **)responsePtr;
/**
* Returns YES if the stream can be resumed.
*
* This would be the case if there's an available resumptionId for the authenticated xmppStream,
* and the timeout from the last stream has not been exceeded.
**/
- (BOOL)canResumeStream;
#pragma mark Requesting Acks
/**
* Sends a request <r/> element, requesting the server reply with an ack <a h='lastHandled'/>.
*
* You can also configure the extension to automatically sends requests.
* @see automaticallyRequestAcksAfterStanzaCount:orTimeout:
*
* When the server replies with an ack, the delegate method will be invoked.
* @see xmppStreamManagement:didReceiveAckForStanzaIds:
**/
- (void)requestAck;
/**
* The module can be configured to automatically request acks (send <r/>) based on your criteria.
* The algorithm to do this takes into account:
*
* - The number of stanzas that have been sent since the last request was sent.
* - The amount of time that has elapsed since the first stanza (after the last request) was sent.
*
* So, for example, if you set the stanzaCount to 5, and the timeout to 2.0 seconds then:
* - Sending 5 stanzas back-to-back will automatically trigger an outgoing request
* - Sending 1 stanza will automatically trigger an outgoing request to be sent 2.0 seconds later,
* which will get preempted if 4 more stanzas are sent before the 2.0 second timer expires.
*
* In other words, whichever event takes place FIRST will trigger the request to be sent.
*
* You can disable either trigger by setting its value to zero.
* So, for example, if you only want to use a timeout of 5 seconds,
* then you could set the stanzaCount to zero and the timeout to 5 seconds.
*
* @param stanzaCount
* The stanzaCount to use for the auto request algorithm.
* If stanzaCount is zero, then the number of stanzas will be ignored in the algorithm.
*
* @param timeout
* The timeout to use for the auto request algorithm.
* If the timeout is zero (or negative), then the timer will be ignored in the algorithm.
*
* The default stanzaCount is 0 (disabled).
* The default timeout is 0.0 seconds (disabled).
**/
- (void)automaticallyRequestAcksAfterStanzaCount:(NSUInteger)stanzaCount orTimeout:(NSTimeInterval)timeout;
/**
* Returns the current auto-request configuration.
*
* @see automaticallyRequestAcksAfterStanzaCount:orTimeout:
**/
- (void)getAutomaticallyRequestAcksAfterStanzaCount:(NSUInteger *)stanzaCountPtr orTimeout:(NSTimeInterval *)timeoutPtr;
#pragma mark Sending Acks
/**
* Sends an unrequested ack <a h='lastHandled'/> element, acking the server's recently received (and handled) elements.
*
* You can also configure the extension to automatically sends acks.
* @see automaticallySendAcksAfterStanzaCount:orTimeout:
*
* Keep in mind that the extension will automatically send an ack if it receives an explicit request.
**/
- (void)sendAck;
/**
* The module can be configured to automatically send unrequested acks.
* That is, rather than waiting to receive explicit requests <r/> from the server,
* the client automatically sends them based on configurable criteria.
*
* The algorithm to do this takes into account:
*
* - The number of stanzas that have been received since the last ack was sent.
* - The amount of time that has elapsed since the first stanza (after the last ack) was received.
*
* In other words, whichever event takes place FIRST will trigger the request to be sent.
* You can disable either trigger by setting its value to zero.
*
* As would be expected, if you manually send an unrequested ack (via the sendAck method),
* or if an ack is sent out in response to a received request </r> from the server,
* then the stanzaCount & timeout are reset.
*
* @param stanzaCount
* The stanzaCount to use for the auto ack algorithm.
* If stanzaCount is zero, then the number of stanzas will be ignored in the algorithm.
*
* @param timeout
* The timeout to sue fo the auto ack algorithm.
* If the timeout is zero (or negative), then the timer will be ignored in the algorithm.
*
* The default stanzaCount is 0 (disabled).
* The default timeout is 0.0 seconds (disabled).
**/
- (void)automaticallySendAcksAfterStanzaCount:(NSUInteger)stanzaCount orTimeout:(NSTimeInterval)timeout;
/**
* Returns the current "auto-send unrequested acks" configuration.
*
* @see automaticallySendAcksAfterStanzaCount:orTimeout:
**/
- (void)getAutomaticallySendAcksAfterStanzaCount:(NSUInteger *)stanzaCountPtr orTimeout:(NSTimeInterval *)timeoutPtr;
/**
* If an explicit request <r/> is received from the server, should we delay sending the ack <a/> ?
* From XEP-0198 :
*
* > When an <r/> element ("request") is received, the recipient MUST acknowledge it by sending an <a/> element
* > to the sender containing a value of 'h' that is equal to the number of stanzas handled by the recipient of
* > the <r/> element. The response SHOULD be sent as soon as possible after receiving the <r/> element,
* > and MUST NOT be withheld for any condition other than a timeout. For example, a client with a slow connection
* > might want to collect many stanzas over a period of time before acking, and a server might want to throttle
* > incoming stanzas.
*
* Thus the XEP recommends that you do not use a delay.
* However, it acknowledges that there may be certain situations in which a delay could prove helpful.
*
* The default value is 0.0 (as recommended by XEP-0198)
**/
@property (atomic, assign, readwrite) NSTimeInterval ackResponseDelay;
/**
* It's critically important to understand what an ACK means.
*
* Every ACK contains an 'h' attribute, which stands for "handled".
* To paraphrase XEP-0198 (in client-side terminology):
*
* Acknowledging a previously received element indicates that the stanza has been "handled" by the client.
* By "handled" we mean that the client has successfully processed the stanza
* (including possibly saving the item to the database if needed);
* Until a stanza has been affirmed as handled by the client, that stanza is the responsibility of the server
* (e.g., to resend it or generate an error if it is never affirmed as handled by the client).
*
* This means that if your processing of certain elements includes saving them to a database,
* then you should not mark those elements as handled until after your database has confirmed the data is on disk.
*
* You should note that this is a critical component of any networking app that claims to have "reliable messaging".
*
* By default, all elements will be marked as handled as soon as they arrive.
* You'll want to override the default behavior for important elements that require proper handling by your app.
* For example, messages that need to be saved to the database.
* Here's how to do so:
*
* - Implement the delegate method xmppStreamManagement:getIsHandled:stanzaId:forReceivedElement:
*
* This method is invoked for all received elements.
* You can inspect the element, and if it is important and requires special handling by the app,
* then flag the element as NOT handled (overriding the default).
* Also assign the element a "stanzaId". This can be anything you want, such as the elementID,
* or maybe something more app-specific (e.g. something you already use that's associated with the message).
*
* - Handle the important element however you need to
*
* If you're saving something to the database,
* then wait until after the database commit has completed successfully.
*
* - Notify the module that the element has been handled via the method markHandledStanzaId:
*
* You must pass the stanzaId that you returned from the delegate method.
*
*
* @see xmppStreamManagement:getIsHandled:stanzaId:forReceivedElement:
**/
- (void)markHandledStanzaId:(id)stanzaId;
@end
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark -
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@protocol XMPPStreamManagementDelegate
@optional
/**
* Notifies delegates of the server's response from sending the <enable> stanza.
**/
- (void)xmppStreamManagement:(XMPPStreamManagement *)sender wasEnabled:(NSXMLElement *)enabled;
- (void)xmppStreamManagement:(XMPPStreamManagement *)sender wasNotEnabled:(NSXMLElement *)failed;
/**
* Notifies delegates that a request <r/> for an ack from the server was sent.
**/
- (void)xmppStreamManagementDidRequestAck:(XMPPStreamManagement *)sender;
/**
* Invoked when an ack is received from the server, and new stanzas have been acked.
*
* @param stanzaIds
* Includes all "stanzaIds" of sent elements that were just acked.
*
* What is a "stanzaId" ?
*
* A stanzaId is a unique identifier that ** YOU can provide ** in order to track an element.
* It could simply be the elementId of the sent element. Or,
* it could be something custom that you provide in order to properly lookup a message in your data store.
*
* For more information, see the delegate method xmppStreamManagement:stanzaIdForSentElement:
**/
- (void)xmppStreamManagement:(XMPPStreamManagement *)sender didReceiveAckForStanzaIds:(NSArray *)stanzaIds;
/**
* XEP-0198 reports the following regarding duplicate stanzas:
*
* Because unacknowledged stanzas might have been received by the other party,
* resending them might result in duplicates; there is no way to prevent such a
* result in this protocol, although use of the XMPP 'id' attribute on all stanzas
* can at least assist the intended recipients in weeding out duplicate stanzas.
*
* In other words, there are edge cases in which you might receive duplicates.
* And the proper way to fix this is to use some kind of identifier in order to detect duplicates.
*
* What kind of identifier to use is up to you. (It's app specific.)
* The XEP notes that you might use the 'id' attribute for this purpose. And this is certainly the most common case.
* However, you may have an alternative scheme that works better for your purposes.
* In which case you can use this delegate method to opt-in.
*
* For example:
* You store all your messages in YapDatabase, which is a collection/key/value storage system.
* Perhaps the collection is the conversationId, and the key is a messageId.
* Therefore, to efficiently lookup a message in your datastore you'd prefer a collection/key tuple.
*
* To achieve this, you would implement this method, and return a YapCollectionKey object for message elements.
* This way, when the xmppStreamManagement:didReceiveAckForStanzaIds: method is invoked,
* you'll get a list that contains your collection/key tuple objects. And then you can quickly and efficiently
* fetch and update your message objects.
*
* If there are no delegates that implement this method,
* or all delegates return nil, then the stanza's elementId is used as the stanzaId.
*
* If the stanza isn't assigned a stanzaId (via a delegate method),
* and it doesn't have an elementId, then it isn't reported in the acked stanzaIds array.
**/
- (id)xmppStreamManagement:(XMPPStreamManagement *)sender stanzaIdForSentElement:(XMPPElement *)element;
/**
* It's critically important to understand what an ACK means.
*
* Every ACK contains an 'h' attribute, which stands for "handled".
* To paraphrase XEP-0198 (in client-side terminology):
*
* Acknowledging a previously received element indicates that the stanza has been "handled" by the client.
* By "handled" we mean that the client has successfully processed the stanza
* (including possibly saving the item to the database if needed);
* Until a stanza has been affirmed as handled by the client, that stanza is the responsibility of the server
* (e.g., to resend it or generate an error if it is never affirmed as handled by the client).
*
* This means that if your processing of certain elements includes saving them to a database,
* then you should not mark those elements as handled until after your database has confirmed the data is on disk.
*
* You should note that this is a critical component of any networking app that claims to have "reliable messaging".
*
* By default, all elements will be marked as handled as soon as they arrive.
* You'll want to override the default behavior for important elements that require proper handling by your app.
* For example, messages that need to be saved to the database.
* Here's how to do so:
*
* - Implement the delegate method xmppStreamManagement:getIsHandled:stanzaId:forReceivedElement:
*
* This method is invoked for all received elements.
* You can inspect the element, and if it is important and requires special handling by the app,
* then flag the element as NOT handled (overriding the default).
* Also assign the element a "stanzaId". This can be anything you want, such as the elementID,
* or maybe something more app-specific (e.g. something you already use that's associated with the message).
*
* - Handle the important element however you need to
*
* If you're saving something to the database,
* then wait until after the database commit has completed successfully.
*
* - Notify the module that the element has been handled via the method markHandledStanzaId:
*
* You must pass the stanzaId that you returned from this delegate method.
*
*
* @see markHandledStanzaId:
**/
- (void)xmppStreamManagement:(XMPPStreamManagement *)sender
getIsHandled:(BOOL *)isHandledPtr
stanzaId:(id *)stanzaIdPtr
forReceivedElement:(XMPPElement *)element;
@end
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark -
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@protocol XMPPStreamManagementStorage <NSObject>
@required
//
//
// -- PRIVATE METHODS --
//
// These methods are designed to be used ONLY by the XMPPStreamManagement class.
//
//
/**
* Configures the storage class, passing it's parent and the parent's dispatch queue.
*
* This method is called by the init methods of the XMPPStreamManagement 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.
**/
- (BOOL)configureWithParent:(XMPPStreamManagement *)parent queue:(dispatch_queue_t)queue;
/**
* Invoked after we receive <enabled/> from the server.
*
* @param resumptionId
* The ID required to resume the session, given to us by the server.
*
* @param timeout
* The timeout in seconds.
* After a disconnect, the server will maintain our state for this long.
* If we attempt to resume the session after this timeout it likely won't work.
*
* @param lastDisconnect
* Used to reset the lastDisconnect value.
* This value is often updated during the session, to ensure it closely resemble the date the server will use.
* That is, if the client application is killed (or crashes) we want a relatively accurate lastDisconnect date.
*
* @param stream
* The associated xmppStream (standard parameter for storage classes)
*
* This method should also nil out the following values (if needed) associated with the account:
* - lastHandledByClient
* - lastHandledByServer
* - pendingOutgoingStanzas
**/
- (void)setResumptionId:(NSString *)resumptionId
timeout:(uint32_t)timeout
lastDisconnect:(NSDate *)date
forStream:(XMPPStream *)stream;
/**
* This method is invoked ** often ** during stream operation.
* It is not invoked when the xmppStream is disconnected.
*
* Important: See the note below: "Optimizing storage demands during active stream usage"
*
* @param date
* Updates the previous lastDisconnect value.
*
* @param lastHandledByClient
* The most recent 'h' value we can safely send to the server.
*
* @param stream
* The associated xmppStream (standard parameter for storage classes)
**/
- (void)setLastDisconnect:(NSDate *)date
lastHandledByClient:(uint32_t)lastHandledByClient
forStream:(XMPPStream *)stream;
/**
* This method is invoked ** often ** during stream operation.
* It is not invoked when the xmppStream is disconnected.
*
* Important: See the note below: "Optimizing storage demands during active stream usage"
*
* @param date
* Updates the previous lastDisconnect value.
*
* @param lastHandledByServer
* The most recent 'h' value we've received from the server.
*
* @param pendingOutgoingStanzas
* An array of XMPPStreamManagementOutgoingStanza objects.
* The storage layer is in charge of properly persisting this array, including:
* - the array count
* - the stanzaId of each element, including those that are nil
*
* @param stream
* The associated xmppStream (standard parameter for storage classes)
**/
- (void)setLastDisconnect:(NSDate *)date
lastHandledByServer:(uint32_t)lastHandledByServer
pendingOutgoingStanzas:(NSArray *)pendingOutgoingStanzas
forStream:(XMPPStream *)stream;
/// ***** Optimizing storage demands during active stream usage *****
///
/// There are 2 methods that are invoked frequently during stream activity:
///
/// - setLastDisconnect:lastHandledByClient:forStream:
/// - setLastDisconnect:lastHandledByServer:pendingOutgoingStanzas:forStream:
///
/// They are invoked any time the 'h' values change, or whenver the pendingStanzaIds change.
/// In other words, they are invoked continually as stanzas get sent and received.
/// And it is the job of the storage layer to decide how to handle the traffic.
/// There are a few things to consider here:
///
/// - How much chatter does the xmppStream do?
/// - How fast is the storage layer?
/// - How does the overhead on the storage layer affect the rest of the app?
///
/// If your xmppStream isn't very chatty, and you've got a fast concurrent database,
/// then you may be able to simply pipe all these method calls to the database without thinking.
/// However, if your xmppStream is always constantly sending/receiving presence stanzas, and pinging the server,
/// then you might consider a bit of optimzation here. Below is a simple recommendation for how to accomplish this.
///
/// You could choose to queue the changes from these method calls, and dump them to the database after a timeout.
/// Thus you'll be able to consolidate a large traffic surge into a small handful of database operations.
///
/// Also, you could expose a 'flush' operation on the storage layer.
/// And invoke the flush operation when the app is backgrounded, or about to quit.
/**
* This method is invoked immediately after an accidental disconnect.
* And may be invoked post-disconnect if the state changes, such as for the following edge cases:
*
* - due to continued processing of stanzas received pre-disconnect,
* that are just now being marked as handled by the delegate(s)
* - due to a delayed response from the delegate(s),
* such that we didn't receive the stanzaId for an outgoing stanza until after the disconnect occurred.
*
* This method is not invoked if stream management is started on a connected xmppStream.
*
* @param date
* This value will be the actual disconnect date.
*
* @param lastHandledByClient
* The most recent 'h' value we can safely send to the server.
*
* @param lastHandledByServer
* The most recent 'h' value we've received from the server.
*
* @param pendingOutgoingStanzas
* An array of XMPPStreamManagementOutgoingStanza objects.
* The storage layer is in charge of properly persisting this array, including:
* - the array count
* - the stanzaId of each element, including those that are nil
*
* @param stream
* The associated xmppStream (standard parameter for storage classes)
**/
- (void)setLastDisconnect:(NSDate *)date
lastHandledByClient:(uint32_t)lastHandledByClient
lastHandledByServer:(uint32_t)lastHandledByServer
pendingOutgoingStanzas:(NSArray *)pendingOutgoingStanzas
forStream:(XMPPStream *)stream;
/**
* Invoked when the extension needs values from a previous session.
* This method is used to get values needed in order to determine if it can resume a previous stream.
**/
- (void)getResumptionId:(NSString **)resumptionIdPtr
timeout:(uint32_t *)timeoutPtr
lastDisconnect:(NSDate **)lastDisconnectPtr
forStream:(XMPPStream *)stream;
/**
* Invoked when the extension needs values from a previous session.
* This method is used to get values needed in order to resume a previous stream.
**/
- (void)getLastHandledByClient:(uint32_t *)lastHandledByClientPtr
lastHandledByServer:(uint32_t *)lastHandledByServerPtr
pendingOutgoingStanzas:(NSArray **)pendingOutgoingStanzasPtr
forStream:(XMPPStream *)stream;
/**
* Instructs the storage layer to remove all values stored for the given stream.
* This occurs after the extension detects a "cleanly closed stream",
* in which case the stream cannot be resumed next time.
**/
- (void)removeAllForStream:(XMPPStream *)stream;
@end
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark -
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@interface XMPPStream (XMPPStreamManagement)
/**
* Returns whether or not the server's <stream:features> includes <sm xmlns='urn:xmpp:sm:3'/>.
**/
- (BOOL)supportsStreamManagement;
@end