-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
XMPPIDTracker.h
153 lines (124 loc) · 4.74 KB
/
XMPPIDTracker.h
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
#import <Foundation/Foundation.h>
@protocol XMPPTrackingInfo;
/**
* A common operation in XMPP is to send some kind of request with a unique id,
* and wait for the response to come back.
* The most common example is sending an IQ of type='get' with a unique id, and then awaiting the response.
*
* In order to properly handle the response, the id must be stored.
* If there are multiple queries going out and/or different kinds of queries,
* then information about the appropriate handling of the response must also be stored.
* This may be accomplished by storing the appropriate selector, or perhaps a block handler.
* Additionally one may need to setup timeouts and handle those properly as well.
*
* This class provides the scaffolding to simplify the tasks associated with this common operation.
* Essentially, it provides the following:
* - a dictionary where the unique id is the key, and the needed tracking info is the object
* - an optional timer to fire upon a timeout
*
* The class is designed to be flexible.
* You can provide a target/selector or a block handler to be invoked.
* Additionally, you can use the basic tracking info, or you can extend it to suit your needs.
*
* It is best illustrated with a few examples.
*
* ---- EXAMPLE 1 - SIMPLE TRACKING WITH TARGET / SELECTOR ----
*
* XMPPIQ *iq = ...
* [iqTracker addID:[iq elementID] target:self selector:@selector(processBookQuery:withInfo:) timeout:15.0];
*
* - (void)processBookQueury:(XMPPIQ *)iq withInfo:(id <XMPPTrackingInfo)info {
* ...
* }
*
* - (BOOL)xmppStream:(XMPPStream *)stream didReceiveIQ:(XMPPIQ *)iq
* {
* NSString *type = [iq type];
*
* if ([type isEqualToString:@"result"] || [type isEqualToString:@"error"])
* {
* return [iqTracker invokeForID:[iq elementID] withObject:iq];
* }
* else
* {
* ...
* }
* }
*
* ---- EXAMPLE 2 - SIMPLE TRACKING WITH BLOCK HANDLER ----
*
* XMPPIQ *iq = ...
*
* void (^blockHandler)(XMPPIQ *, id <XMPPTrackingInfo>) = ^(XMPPIQ *iq, id <XMPPTrackingInfo> info) {
* ...
* };
* [iqTracker addID:[iq elementID] block:blockHandler timeout:15.0];
*
* // Same xmppStream:didReceiveIQ: as example 1
*
* ---- EXAMPLE 2 - ADVANCED TRACKING ----
*
* @interface PingTrackingInfo : XMPPBasicTrackingInfo
* ...
* @end
*
* XMPPIQ *ping = ...
* PingTrackingInfo *pingInfo = ...
*
* [iqTracker addID:[ping elementID] trackingInfo:pingInfo];
*
* - (void)handlePong:(XMPPIQ *)iq withInfo:(PingTrackingInfo *)info {
* ...
* }
*
* // Same xmppStream:didReceiveIQ: as example 1
*
*
* This class is NOT thread-safe.
* It is designed to be used within a thread-safe context (e.g. within a single dispatch_queue).
**/
@interface XMPPIDTracker : NSObject
{
dispatch_queue_t queue;
NSMutableDictionary *dict;
}
- (id)initWithDispatchQueue:(dispatch_queue_t)queue;
- (void)addID:(NSString *)elementID target:(id)target selector:(SEL)selector timeout:(NSTimeInterval)timeout;
- (void)addID:(NSString *)elementID
block:(void (^)(id obj, id <XMPPTrackingInfo> info))block
timeout:(NSTimeInterval)timeout;
- (void)addID:(NSString *)elementID trackingInfo:(id <XMPPTrackingInfo>)trackingInfo;
- (BOOL)invokeForID:(NSString *)elementID withObject:(id)obj;
- (void)removeID:(NSString *)elementID;
- (void)removeAllIDs;
@end
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark -
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@protocol XMPPTrackingInfo <NSObject>
@property (nonatomic, readonly) NSTimeInterval timeout;
@property (nonatomic, readwrite, copy) NSString *elementID;
- (void)createTimerWithDispatchQueue:(dispatch_queue_t)queue;
- (void)cancelTimer;
- (void)invokeWithObject:(id)obj;
@end
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark -
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@interface XMPPBasicTrackingInfo : NSObject <XMPPTrackingInfo>
{
id target;
SEL selector;
void (^block)(id obj, id <XMPPTrackingInfo> info);
NSTimeInterval timeout;
NSString *elementID;
dispatch_source_t timer;
}
- (id)initWithTarget:(id)target selector:(SEL)selector timeout:(NSTimeInterval)timeout;
- (id)initWithBlock:(void (^)(id obj, id <XMPPTrackingInfo> info))block timeout:(NSTimeInterval)timeout;
@property (nonatomic, readonly) NSTimeInterval timeout;
@property (nonatomic, readwrite, copy) NSString *elementID;
- (void)createTimerWithDispatchQueue:(dispatch_queue_t)queue;
- (void)cancelTimer;
- (void)invokeWithObject:(id)obj;
@end