1
1
//
2
2
// SocketIO.m
3
- // v0.3.3 ARC
3
+ // v0.4 ARC
4
4
//
5
5
// based on
6
6
// socketio-cocoa https://github.com/fpotter/socketio-cocoa
37
37
#define DEBUGLOG (...)
38
38
#endif
39
39
40
- static NSString * kInsecureHandshakeURL = @" http://%@ /socket.io/1/?t=%d %@ " ;
41
- static NSString * kInsecureHandshakePortURL = @" http://%@ :%d /socket.io/1/?t=%d %@ " ;
42
- static NSString * kSecureHandshakePortURL = @" https://%@ :%d /socket.io/1/?t=%d %@ " ;
43
- static NSString * kSecureHandshakeURL = @" https://%@ /socket.io/1/?t=%d %@ " ;
40
+ static NSString * kResourceName = @" socket.io" ;
41
+ static NSString * kHandshakeURL = @" %@ ://%@%@ /%@ /1/?t=%d %@ " ;
42
+ static NSString * kForceDisconnectURL = @" %@ ://%@%@ /%@ /1/xhr-polling/%@ ?disconnect" ;
43
+
44
+ float const defaultConnectionTimeout = 10 .0f ;
44
45
45
46
NSString * const SocketIOError = @" SocketIOError" ;
46
47
NSString * const SocketIOException = @" SocketIOException" ;
@@ -95,15 +96,27 @@ - (id) initWithDelegate:(id<SocketIODelegate>)delegate
95
96
96
97
- (void ) connectToHost : (NSString *)host onPort : (NSInteger )port
97
98
{
98
- [self connectToHost: host onPort: port withParams: nil withNamespace: @" " ];
99
+ [self connectToHost: host onPort: port withParams: nil withNamespace: @" " withConnectionTimeout: defaultConnectionTimeout ];
99
100
}
100
101
101
102
- (void ) connectToHost : (NSString *)host onPort : (NSInteger )port withParams : (NSDictionary *)params
102
103
{
103
- [self connectToHost: host onPort: port withParams: params withNamespace: @" " ];
104
+ [self connectToHost: host onPort: port withParams: params withNamespace: @" " withConnectionTimeout: defaultConnectionTimeout ];
104
105
}
105
106
106
- - (void ) connectToHost : (NSString *)host onPort : (NSInteger )port withParams : (NSDictionary *)params withNamespace : (NSString *)endpoint
107
+ - (void ) connectToHost : (NSString *)host
108
+ onPort : (NSInteger )port
109
+ withParams : (NSDictionary *)params
110
+ withNamespace : (NSString *)endpoint
111
+ {
112
+ [self connectToHost: host onPort: port withParams: params withNamespace: @" " withConnectionTimeout: defaultConnectionTimeout];
113
+ }
114
+
115
+ - (void ) connectToHost : (NSString *)host
116
+ onPort : (NSInteger )port
117
+ withParams : (NSDictionary *)params
118
+ withNamespace : (NSString *)endpoint
119
+ withConnectionTimeout : (NSTimeInterval )connectionTimeout
107
120
{
108
121
if (!_isConnected && !_isConnecting) {
109
122
_isConnecting = YES ;
@@ -120,31 +133,22 @@ - (void) connectToHost:(NSString *)host onPort:(NSInteger)port withParams:(NSDic
120
133
}];
121
134
122
135
// do handshake via HTTP request
123
- NSString *s;
124
- NSString *format;
125
- if (_port) {
126
- format = _useSecure ? kSecureHandshakePortURL : kInsecureHandshakePortURL ;
127
- s = [NSString stringWithFormat: format, _host, _port, rand (), query];
128
- }
129
- else {
130
- format = _useSecure ? kSecureHandshakeURL : kInsecureHandshakeURL ;
131
- s = [NSString stringWithFormat: format, _host, rand (), query];
132
- }
133
- DEBUGLOG (@" Connecting to socket with URL: %@ " , s);
134
- NSURL *url = [NSURL URLWithString: s];
136
+ NSString *protocol = _useSecure ? @" https" : @" http" ;
137
+ NSString *port = _port ? [NSString stringWithFormat: @" :%d " , _port] : @" " ;
138
+ NSString *handshakeUrl = [NSString stringWithFormat: kHandshakeURL , protocol, _host, port, kResourceName , rand (), query];
139
+
140
+ DEBUGLOG (@" Connecting to socket with URL: %@ " , handshakeUrl);
135
141
query = nil ;
136
-
137
142
138
143
// make a request
139
- NSURLRequest *request = [NSURLRequest requestWithURL: url
144
+ NSURLRequest *request = [NSURLRequest requestWithURL: [ NSURL URLWithString: handshakeUrl]
140
145
cachePolicy: NSURLRequestReloadIgnoringLocalAndRemoteCacheData
141
- timeoutInterval: 10.0 ];
146
+ timeoutInterval: connectionTimeout ];
142
147
143
- _handshake = [[NSURLConnection alloc ] initWithRequest: request
144
- delegate: self startImmediately: NO ];
145
- [_handshake scheduleInRunLoop: [NSRunLoop mainRunLoop ]
146
- forMode: NSDefaultRunLoopMode ];
148
+ _handshake = [[NSURLConnection alloc ] initWithRequest: request delegate: self startImmediately: NO ];
149
+ [_handshake scheduleInRunLoop: [NSRunLoop mainRunLoop ] forMode: NSDefaultRunLoopMode ];
147
150
[_handshake start ];
151
+
148
152
if (_handshake) {
149
153
_httpRequestData = [NSMutableData data ];
150
154
}
@@ -162,9 +166,31 @@ - (void) disconnect
162
166
}
163
167
else if (_isConnecting) {
164
168
[_handshake cancel ];
169
+ [self onDisconnect: nil ];
165
170
}
166
171
}
167
172
173
+ - (void ) disconnectForced
174
+ {
175
+ NSString *protocol = [self useSecure ] ? @" https" : @" http" ;
176
+ NSString *port = _port ? [NSString stringWithFormat: @" :%d " , _port] : @" " ;
177
+ NSString *urlString = [NSString stringWithFormat: kForceDisconnectURL , protocol, _host, port, kResourceName , _sid];
178
+ NSURL *url = [NSURL URLWithString: urlString];
179
+ DEBUGLOG (@" Force disconnect at: %@ " , urlString);
180
+
181
+ NSURLRequest *request = [NSURLRequest requestWithURL: url];
182
+ NSError *error = nil ;
183
+ NSHTTPURLResponse *response = nil ;
184
+
185
+ [NSURLConnection sendSynchronousRequest: request returningResponse: &response error: &error];
186
+
187
+ if (error || [response statusCode ] != 200 ) {
188
+ DEBUGLOG (@" Error during disconnect: %@ " , error);
189
+ }
190
+
191
+ [self onDisconnect: error];
192
+ }
193
+
168
194
- (void ) sendMessage : (NSString *)data
169
195
{
170
196
[self sendMessage: data withAcknowledge: nil ];
@@ -224,13 +250,19 @@ - (void) sendAcknowledgement:(NSString *)pId withArgs:(NSArray *)data
224
250
[self send: packet];
225
251
}
226
252
253
+ - (void ) setResourceName : (NSString *)name
254
+ {
255
+ kResourceName = [name copy ];
256
+ }
257
+
227
258
# pragma mark -
228
259
# pragma mark private methods
229
260
230
261
- (void ) sendDisconnect
231
262
{
232
263
SocketIOPacket *packet = [[SocketIOPacket alloc ] initWithType: @" disconnect" ];
233
264
[self send: packet];
265
+ [self onDisconnect: nil ];
234
266
}
235
267
236
268
- (void ) sendConnect
@@ -246,7 +278,11 @@ - (void) sendHeartbeat
246
278
}
247
279
248
280
- (void ) send : (SocketIOPacket *)packet
249
- {
281
+ {
282
+ if (![self isConnected ] && ![self isConnecting ]) {
283
+ DEBUGLOG (@" Already disconnected!" );
284
+ return ;
285
+ }
250
286
DEBUGLOG (@" send()" );
251
287
NSNumber *type = [packet typeAsNumber ];
252
288
NSMutableArray *encoded = [NSMutableArray arrayWithObject: type];
@@ -359,6 +395,11 @@ - (void) removeAcknowledgeForKey:(NSString *)key
359
395
360
396
- (void ) onTimeout
361
397
{
398
+ if (_timeout) {
399
+ dispatch_source_cancel (_timeout);
400
+ _timeout = NULL ;
401
+ }
402
+
362
403
DEBUGLOG (@" Timed out waiting for heartbeat." );
363
404
[self onDisconnect: [NSError errorWithDomain: SocketIOError
364
405
code: SocketIOHeartbeatTimeout
@@ -368,16 +409,29 @@ - (void) onTimeout
368
409
- (void ) setTimeout
369
410
{
370
411
DEBUGLOG (@" start/reset timeout" );
371
- if (_timeout != nil ) {
372
- [ _timeout invalidate ] ;
373
- _timeout = nil ;
412
+ if (_timeout) {
413
+ dispatch_source_cancel ( _timeout) ;
414
+ _timeout = NULL ;
374
415
}
375
416
376
- _timeout = [NSTimer scheduledTimerWithTimeInterval: _heartbeatTimeout
377
- target: self
378
- selector: @selector (onTimeout )
379
- userInfo: nil
380
- repeats: NO ];
417
+ _timeout = dispatch_source_create (DISPATCH_SOURCE_TYPE_TIMER,
418
+ 0 ,
419
+ 0 ,
420
+ dispatch_get_main_queue ());
421
+
422
+ dispatch_source_set_timer (_timeout,
423
+ dispatch_time (DISPATCH_TIME_NOW, _heartbeatTimeout * NSEC_PER_SEC),
424
+ 0 ,
425
+ 0 );
426
+
427
+ __weak SocketIO *weakSelf = self;
428
+
429
+ dispatch_source_set_event_handler (_timeout, ^{
430
+ [weakSelf onTimeout ];
431
+ });
432
+
433
+ dispatch_resume (_timeout);
434
+
381
435
}
382
436
383
437
@@ -556,9 +610,9 @@ - (void) onDisconnect:(NSError *)error
556
610
[_queue removeAllObjects ];
557
611
558
612
// Kill the heartbeat timer
559
- if (_timeout != nil ) {
560
- [ _timeout invalidate ] ;
561
- _timeout = nil ;
613
+ if (_timeout) {
614
+ dispatch_source_cancel ( _timeout) ;
615
+ _timeout = NULL ;
562
616
}
563
617
564
618
// Disconnect the websocket, just in case
@@ -762,14 +816,20 @@ - (void) connection:(NSURLConnection *)connection
762
816
763
817
- (void ) dealloc
764
818
{
819
+ [_handshake cancel ];
820
+ _handshake = nil ;
821
+
765
822
_host = nil ;
766
823
_sid = nil ;
767
824
_endpoint = nil ;
768
825
826
+ _transport.delegate = nil ;
769
827
_transport = nil ;
770
828
771
- [_timeout invalidate ];
772
- _timeout = nil ;
829
+ if (_timeout) {
830
+ dispatch_source_cancel (_timeout);
831
+ _timeout = NULL ;
832
+ }
773
833
774
834
_queue = nil ;
775
835
_acks = nil ;
0 commit comments