Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
805 - 1
//
2
//  AsyncSocket.h
3
//  
4
//  This class is in the public domain.
5
//  Originally created by Dustin Voss on Wed Jan 29 2003.
6
//  Updated and maintained by Deusty Designs and the Mac development community.
7
//
8
//  http://code.google.com/p/cocoaasyncsocket/
9
//
10
 
11
#import <Foundation/Foundation.h>
12
 
13
@class AsyncSocket;
14
@class AsyncReadPacket;
15
@class AsyncWritePacket;
16
 
17
extern NSString *const AsyncSocketException;
18
extern NSString *const AsyncSocketErrorDomain;
19
 
20
enum AsyncSocketError
21
{
22
        AsyncSocketCFSocketError = kCFSocketError,      // From CFSocketError enum.
23
        AsyncSocketNoError = 0,                                         // Never used.
24
        AsyncSocketCanceledError,                                       // onSocketWillConnect: returned NO.
25
        AsyncSocketConnectTimeoutError,
26
        AsyncSocketReadMaxedOutError,               // Reached set maxLength without completing
27
        AsyncSocketReadTimeoutError,
28
        AsyncSocketWriteTimeoutError
29
};
30
typedef enum AsyncSocketError AsyncSocketError;
31
 
32
@interface NSObject (AsyncSocketDelegate)
33
 
34
/**
35
 * In the event of an error, the socket is closed.
36
 * You may call "unreadData" during this call-back to get the last bit of data off the socket.
37
 * When connecting, this delegate method may be called
38
 * before"onSocket:didAcceptNewSocket:" or "onSocket:didConnectToHost:".
39
**/
40
- (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err;
41
 
42
/**
43
 * Called when a socket disconnects with or without error.  If you want to release a socket after it disconnects,
44
 * do so here. It is not safe to do that during "onSocket:willDisconnectWithError:".
45
 *
46
 * If you call the disconnect method, and the socket wasn't already disconnected,
47
 * this delegate method will be called before the disconnect method returns.
48
**/
49
- (void)onSocketDidDisconnect:(AsyncSocket *)sock;
50
 
51
/**
52
 * Called when a socket accepts a connection.  Another socket is spawned to handle it. The new socket will have
53
 * the same delegate and will call "onSocket:didConnectToHost:port:".
54
**/
55
- (void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket;
56
 
57
/**
58
 * Called when a new socket is spawned to handle a connection.  This method should return the run-loop of the
59
 * thread on which the new socket and its delegate should operate. If omitted, [NSRunLoop currentRunLoop] is used.
60
**/
61
- (NSRunLoop *)onSocket:(AsyncSocket *)sock wantsRunLoopForNewSocket:(AsyncSocket *)newSocket;
62
 
63
/**
64
 * Called when a socket is about to connect. This method should return YES to continue, or NO to abort.
65
 * If aborted, will result in AsyncSocketCanceledError.
66
 *
67
 * If the connectToHost:onPort:error: method was called, the delegate will be able to access and configure the
68
 * CFReadStream and CFWriteStream as desired prior to connection.
69
 *
70
 * If the connectToAddress:error: method was called, the delegate will be able to access and configure the
71
 * CFSocket and CFSocketNativeHandle (BSD socket) as desired prior to connection. You will be able to access and
72
 * configure the CFReadStream and CFWriteStream in the onSocket:didConnectToHost:port: method.
73
**/
74
- (BOOL)onSocketWillConnect:(AsyncSocket *)sock;
75
 
76
/**
77
 * Called when a socket connects and is ready for reading and writing.
78
 * The host parameter will be an IP address, not a DNS name.
79
**/
80
- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port;
81
 
82
/**
83
 * Called when a socket has completed reading the requested data into memory.
84
 * Not called if there is an error.
85
**/
86
- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag;
87
 
88
/**
89
 * Called when a socket has read in data, but has not yet completed the read.
90
 * This would occur if using readToData: or readToLength: methods.
91
 * It may be used to for things such as updating progress bars.
92
**/
93
- (void)onSocket:(AsyncSocket *)sock didReadPartialDataOfLength:(CFIndex)partialLength tag:(long)tag;
94
 
95
/**
96
 * Called when a socket has completed writing the requested data. Not called if there is an error.
97
**/
98
- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag;
99
 
100
/**
101
 * Called when a socket has written some data, but has not yet completed the entire write.
102
 * It may be used to for things such as updating progress bars.
103
**/
104
- (void)onSocket:(AsyncSocket *)sock didWritePartialDataOfLength:(CFIndex)partialLength tag:(long)tag;
105
 
106
/**
107
 * Called if a read operation has reached its timeout without completing.
108
 * This method allows you to optionally extend the timeout.
109
 * If you return a positive time interval (> 0) the read's timeout will be extended by the given amount.
110
 * If you don't implement this method, or return a non-positive time interval (<= 0) the read will timeout as usual.
111
 *
112
 * The elapsed parameter is the sum of the original timeout, plus any additions previously added via this method.
113
 * The length parameter is the number of bytes that have been read so far for the read operation.
114
 *
115
 * Note that this method may be called multiple times for a single read if you return positive numbers.
116
**/
117
- (NSTimeInterval)onSocket:(AsyncSocket *)sock
118
  shouldTimeoutReadWithTag:(long)tag
119
                                   elapsed:(NSTimeInterval)elapsed
120
                                 bytesDone:(CFIndex)length;
121
 
122
/**
123
 * Called if a write operation has reached its timeout without completing.
124
 * This method allows you to optionally extend the timeout.
125
 * If you return a positive time interval (> 0) the write's timeout will be extended by the given amount.
126
 * If you don't implement this method, or return a non-positive time interval (<= 0) the write will timeout as usual.
127
 *
128
 * The elapsed parameter is the sum of the original timeout, plus any additions previously added via this method.
129
 * The length parameter is the number of bytes that have been written so far for the write operation.
130
 *
131
 * Note that this method may be called multiple times for a single write if you return positive numbers.
132
**/
133
- (NSTimeInterval)onSocket:(AsyncSocket *)sock
134
 shouldTimeoutWriteWithTag:(long)tag
135
                                   elapsed:(NSTimeInterval)elapsed
136
                                 bytesDone:(CFIndex)length;
137
 
138
/**
139
 * Called after the socket has successfully completed SSL/TLS negotiation.
140
 * This method is not called unless you use the provided startTLS method.
141
 *
142
 * If a SSL/TLS negotiation fails (invalid certificate, etc) then the socket will immediately close,
143
 * and the onSocket:willDisconnectWithError: delegate method will be called with the specific SSL error code.
144
**/
145
- (void)onSocketDidSecure:(AsyncSocket *)sock;
146
 
147
@end
148
 
149
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
150
#pragma mark -
151
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
152
 
153
@interface AsyncSocket : NSObject
154
{
155
        CFSocketRef theSocket4;            // IPv4 accept or connect socket
156
        CFSocketRef theSocket6;            // IPv6 accept or connect socket
157
        CFReadStreamRef theReadStream;
158
        CFWriteStreamRef theWriteStream;
159
 
160
        CFRunLoopSourceRef theSource4;     // For theSocket4
161
        CFRunLoopSourceRef theSource6;     // For theSocket6
162
        CFRunLoopRef theRunLoop;
163
        CFSocketContext theContext;
164
        NSArray *theRunLoopModes;
165
 
166
        NSTimer *theConnectTimer;
167
 
168
        NSMutableArray *theReadQueue;
169
        AsyncReadPacket *theCurrentRead;
170
        NSTimer *theReadTimer;
171
        NSMutableData *partialReadBuffer;
172
 
173
        NSMutableArray *theWriteQueue;
174
        AsyncWritePacket *theCurrentWrite;
175
        NSTimer *theWriteTimer;
176
 
177
        id theDelegate;
178
        UInt16 theFlags;
179
 
180
        long theUserData;
181
}
182
 
183
- (id)init;
184
- (id)initWithDelegate:(id)delegate;
185
- (id)initWithDelegate:(id)delegate userData:(long)userData;
186
 
187
/* String representation is long but has no "\n". */
188
- (NSString *)description;
189
 
190
/**
191
 * Use "canSafelySetDelegate" to see if there is any pending business (reads and writes) with the current delegate
192
 * before changing it.  It is, of course, safe to change the delegate before connecting or accepting connections.
193
**/
194
- (id)delegate;
195
- (BOOL)canSafelySetDelegate;
196
- (void)setDelegate:(id)delegate;
197
 
198
/* User data can be a long, or an id or void * cast to a long. */
199
- (long)userData;
200
- (void)setUserData:(long)userData;
201
 
202
/* Don't use these to read or write. And don't close them either! */
203
- (CFSocketRef)getCFSocket;
204
- (CFReadStreamRef)getCFReadStream;
205
- (CFWriteStreamRef)getCFWriteStream;
206
 
207
// Once one of the accept or connect methods are called, the AsyncSocket instance is locked in
208
// and the other accept/connect methods can't be called without disconnecting the socket first.
209
// If the attempt fails or times out, these methods either return NO or
210
// call "onSocket:willDisconnectWithError:" and "onSockedDidDisconnect:".
211
 
212
// When an incoming connection is accepted, AsyncSocket invokes several delegate methods.
213
// These methods are (in chronological order):
214
// 1. onSocket:didAcceptNewSocket:
215
// 2. onSocket:wantsRunLoopForNewSocket:
216
// 3. onSocketWillConnect:
217
// 
218
// Your server code will need to retain the accepted socket (if you want to accept it).
219
// The best place to do this is probably in the onSocket:didAcceptNewSocket: method.
220
// 
221
// After the read and write streams have been setup for the newly accepted socket,
222
// the onSocket:didConnectToHost:port: method will be called on the proper run loop.
223
// 
224
// Multithreading Note: If you're going to be moving the newly accepted socket to another run
225
// loop by implementing onSocket:wantsRunLoopForNewSocket:, then you should wait until the
226
// onSocket:didConnectToHost:port: method before calling read, write, or startTLS methods.
227
// Otherwise read/write events are scheduled on the incorrect runloop, and chaos may ensue.
228
 
229
/**
230
 * Tells the socket to begin listening and accepting connections on the given port.
231
 * When a connection comes in, the AsyncSocket instance will call the various delegate methods (see above).
232
 * The socket will listen on all available interfaces (e.g. wifi, ethernet, etc)
233
**/
234
- (BOOL)acceptOnPort:(UInt16)port error:(NSError **)errPtr;
235
 
236
/**
237
 * This method is the same as acceptOnPort:error: with the additional option
238
 * of specifying which interface to listen on. So, for example, if you were writing code for a server that
239
 * has multiple IP addresses, you could specify which address you wanted to listen on.  Or you could use it
240
 * to specify that the socket should only accept connections over ethernet, and not other interfaces such as wifi.
241
 * You may also use the special strings "localhost" or "loopback" to specify that
242
 * the socket only accept connections from the local machine.
243
 *
244
 * To accept connections on any interface pass nil, or simply use the acceptOnPort:error: method.
245
**/
246
- (BOOL)acceptOnInterface:(NSString *)interface port:(UInt16)port error:(NSError **)errPtr;
247
 
248
/**
249
 * Connects to the given host and port.
250
 * The host may be a domain name (e.g. "deusty.com") or an IP address string (e.g. "192.168.0.2")
251
**/
252
- (BOOL)connectToHost:(NSString *)hostname onPort:(UInt16)port error:(NSError **)errPtr;
253
 
254
/**
255
 * This method is the same as connectToHost:onPort:error: with an additional timeout option.
256
 * To not time out use a negative time interval, or simply use the connectToHost:onPort:error: method.
257
**/
258
- (BOOL)connectToHost:(NSString *)hostname
259
                           onPort:(UInt16)port
260
                  withTimeout:(NSTimeInterval)timeout
261
                                error:(NSError **)errPtr;
262
 
263
/**
264
 * Connects to the given address, specified as a sockaddr structure wrapped in a NSData object.
265
 * For example, a NSData object returned from NSNetservice's addresses method.
266
 *
267
 * If you have an existing struct sockaddr you can convert it to a NSData object like so:
268
 * struct sockaddr sa  -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len];
269
 * struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len];
270
**/
271
- (BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError **)errPtr;
272
 
273
/**
274
 * This method is the same as connectToAddress:error: with an additional timeout option.
275
 * To not time out use a negative time interval, or simply use the connectToAddress:error: method.
276
**/
277
- (BOOL)connectToAddress:(NSData *)remoteAddr withTimeout:(NSTimeInterval)timeout error:(NSError **)errPtr;
278
 
279
/**
280
 * Disconnects immediately. Any pending reads or writes are dropped.
281
 * If the socket is not already disconnected, the onSocketDidDisconnect delegate method
282
 * will be called immediately, before this method returns.
283
 *
284
 * Please note the recommended way of releasing an AsyncSocket instance (e.g. in a dealloc method)
285
 * [asyncSocket setDelegate:nil];
286
 * [asyncSocket disconnect];
287
 * [asyncSocket release];
288
**/
289
- (void)disconnect;
290
 
291
/**
292
 * Disconnects after all pending reads have completed.
293
 * After calling this, the read and write methods will do nothing.
294
 * The socket will disconnect even if there are still pending writes.
295
**/
296
- (void)disconnectAfterReading;
297
 
298
/**
299
 * Disconnects after all pending writes have completed.
300
 * After calling this, the read and write methods will do nothing.
301
 * The socket will disconnect even if there are still pending reads.
302
**/
303
- (void)disconnectAfterWriting;
304
 
305
/**
306
 * Disconnects after all pending reads and writes have completed.
307
 * After calling this, the read and write methods will do nothing.
308
**/
309
- (void)disconnectAfterReadingAndWriting;
310
 
311
/* Returns YES if the socket and streams are open, connected, and ready for reading and writing. */
312
- (BOOL)isConnected;
313
 
314
/**
315
 * Returns the local or remote host and port to which this socket is connected, or nil and 0 if not connected.
316
 * The host will be an IP address.
317
**/
318
- (NSString *)connectedHost;
319
- (UInt16)connectedPort;
320
 
321
- (NSString *)localHost;
322
- (UInt16)localPort;
323
 
324
/**
325
 * Returns the local or remote address to which this socket is connected,
326
 * specified as a sockaddr structure wrapped in a NSData object.
327
 *
328
 * See also the connectedHost, connectedPort, localHost and localPort methods.
329
**/
330
- (NSData *)connectedAddress;
331
- (NSData *)localAddress;
332
 
333
/**
334
 * Returns whether the socket is IPv4 or IPv6.
335
 * An accepting socket may be both.
336
**/
337
- (BOOL)isIPv4;
338
- (BOOL)isIPv6;
339
 
340
// The readData and writeData methods won't block.
341
// 
342
// You may optionally set a timeout for any read/write operation. (To not timeout, use a negative time interval.)
343
// If a read/write opertion times out, the corresponding "onSocket:shouldTimeout..." delegate method
344
// is called to optionally allow you to extend the timeout.
345
// Upon a timeout, the "onSocket:willDisconnectWithError:" method is called, followed by "onSocketDidDisconnect".
346
// 
347
// The tag is for your convenience.
348
// You can use it as an array index, step number, state id, pointer, etc., just like the socket's user data.
349
 
350
/**
351
 * This will read a certain number of bytes into memory, and call the delegate method when those bytes have been read.
352
 *
353
 * If the length is 0, this method does nothing and the delegate is not called.
354
 * If the timeout value is negative, the read operation will not use a timeout.
355
**/
356
- (void)readDataToLength:(CFIndex)length withTimeout:(NSTimeInterval)timeout tag:(long)tag;
357
 
358
/**
359
 * This reads bytes until (and including) the passed "data" parameter, which acts as a separator.
360
 * The bytes and the separator are returned by the delegate method.
361
 *
362
 * If you pass nil or zero-length data as the "data" parameter,
363
 * the method will do nothing, and the delegate will not be called.
364
 * If the timeout value is negative, the read operation will not use a timeout.
365
 *
366
 * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter.
367
 * Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for
368
 * a character, the read will prematurely end.
369
**/
370
- (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;
371
 
372
/**
373
 * Same as readDataToData:withTimeout:tag, with the additional restriction that the amount of data read
374
 * may not surpass the given maxLength (specified in bytes).
375
 *
376
 * If you pass a maxLength parameter that is less than the length of the data parameter,
377
 * the method will do nothing, and the delegate will not be called.
378
 *
379
 * If the max length is surpassed, it is treated the same as a timeout - the socket is closed.
380
 *
381
 * Pass -1 as maxLength if no length restriction is desired, or simply use the readDataToData:withTimeout:tag method.
382
**/
383
- (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout maxLength:(CFIndex)length tag:(long)tag;
384
 
385
/**
386
 * Reads the first available bytes that become available on the socket.
387
 *
388
 * If the timeout value is negative, the read operation will not use a timeout.
389
**/
390
- (void)readDataWithTimeout:(NSTimeInterval)timeout tag:(long)tag;
391
 
392
/**
393
 * Writes data to the socket, and calls the delegate when finished.
394
 *
395
 * If you pass in nil or zero-length data, this method does nothing and the delegate will not be called.
396
 * If the timeout value is negative, the write operation will not use a timeout.
397
**/
398
- (void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;
399
 
400
/**
401
 * Returns progress of current read or write, from 0.0 to 1.0, or NaN if no read/write (use isnan() to check).
402
 * "tag", "done" and "total" will be filled in if they aren't NULL.
403
**/
404
- (float)progressOfReadReturningTag:(long *)tag bytesDone:(CFIndex *)done total:(CFIndex *)total;
405
- (float)progressOfWriteReturningTag:(long *)tag bytesDone:(CFIndex *)done total:(CFIndex *)total;
406
 
407
/**
408
 * Secures the connection using SSL/TLS.
409
 *
410
 * This method may be called at any time, and the TLS handshake will occur after all pending reads and writes
411
 * are finished. This allows one the option of sending a protocol dependent StartTLS message, and queuing
412
 * the upgrade to TLS at the same time, without having to wait for the write to finish.
413
 * Any reads or writes scheduled after this method is called will occur over the secured connection.
414
 *
415
 * The possible keys and values for the TLS settings are well documented.
416
 * Some possible keys are:
417
 * - kCFStreamSSLLevel
418
 * - kCFStreamSSLAllowsExpiredCertificates
419
 * - kCFStreamSSLAllowsExpiredRoots
420
 * - kCFStreamSSLAllowsAnyRoot
421
 * - kCFStreamSSLValidatesCertificateChain
422
 * - kCFStreamSSLPeerName
423
 * - kCFStreamSSLCertificates
424
 * - kCFStreamSSLIsServer
425
 *
426
 * Please refer to Apple's documentation for associated values, as well as other possible keys.
427
 *
428
 * If you pass in nil or an empty dictionary, the default settings will be used.
429
 *
430
 * The default settings will check to make sure the remote party's certificate is signed by a
431
 * trusted 3rd party certificate agency (e.g. verisign) and that the certificate is not expired.
432
 * However it will not verify the name on the certificate unless you
433
 * give it a name to verify against via the kCFStreamSSLPeerName key.
434
 * The security implications of this are important to understand.
435
 * Imagine you are attempting to create a secure connection to MySecureServer.com,
436
 * but your socket gets directed to MaliciousServer.com because of a hacked DNS server.
437
 * If you simply use the default settings, and MaliciousServer.com has a valid certificate,
438
 * the default settings will not detect any problems since the certificate is valid.
439
 * To properly secure your connection in this particular scenario you
440
 * should set the kCFStreamSSLPeerName property to "MySecureServer.com".
441
 * If you do not know the peer name of the remote host in advance (for example, you're not sure
442
 * if it will be "domain.com" or "www.domain.com"), then you can use the default settings to validate the
443
 * certificate, and then use the X509Certificate class to verify the issuer after the socket has been secured.
444
 * The X509Certificate class is part of the CocoaAsyncSocket open source project.
445
**/
446
- (void)startTLS:(NSDictionary *)tlsSettings;
447
 
448
/**
449
 * For handling readDataToData requests, data is necessarily read from the socket in small increments.
450
 * The performance can be much improved by allowing AsyncSocket to read larger chunks at a time and
451
 * store any overflow in a small internal buffer.
452
 * This is termed pre-buffering, as some data may be read for you before you ask for it.
453
 * If you use readDataToData a lot, enabling pre-buffering will result in better performance, especially on the iPhone.
454
 *
455
 * The default pre-buffering state is controlled by the DEFAULT_PREBUFFERING definition.
456
 * It is highly recommended one leave this set to YES.
457
 *
458
 * This method exists in case pre-buffering needs to be disabled by default for some unforeseen reason.
459
 * In that case, this method exists to allow one to easily enable pre-buffering when ready.
460
**/
461
- (void)enablePreBuffering;
462
 
463
/**
464
 * When you create an AsyncSocket, it is added to the runloop of the current thread.
465
 * So for manually created sockets, it is easiest to simply create the socket on the thread you intend to use it.
466
 *
467
 * If a new socket is accepted, the delegate method onSocket:wantsRunLoopForNewSocket: is called to
468
 * allow you to place the socket on a separate thread. This works best in conjunction with a thread pool design.
469
 *
470
 * If, however, you need to move the socket to a separate thread at a later time, this
471
 * method may be used to accomplish the task.
472
 *
473
 * This method must be called from the thread/runloop the socket is currently running on.
474
 *
475
 * Note: After calling this method, all further method calls to this object should be done from the given runloop.
476
 * Also, all delegate calls will be sent on the given runloop.
477
**/
478
- (BOOL)moveToRunLoop:(NSRunLoop *)runLoop;
479
 
480
/**
481
 * Allows you to configure which run loop modes the socket uses.
482
 * The default set of run loop modes is NSDefaultRunLoopMode.
483
 *
484
 * If you'd like your socket to continue operation during other modes, you may want to add modes such as
485
 * NSModalPanelRunLoopMode or NSEventTrackingRunLoopMode. Or you may simply want to use NSRunLoopCommonModes.
486
 *
487
 * Accepted sockets will automatically inherit the same run loop modes as the listening socket.
488
 *
489
 * Note: NSRunLoopCommonModes is defined in 10.5. For previous versions one can use kCFRunLoopCommonModes.
490
**/
491
- (BOOL)setRunLoopModes:(NSArray *)runLoopModes;
492
 
493
/**
494
 * Returns the current run loop modes the AsyncSocket instance is operating in.
495
 * The default set of run loop modes is NSDefaultRunLoopMode.
496
**/
497
- (NSArray *)runLoopModes;
498
 
499
/**
500
 * In the event of an error, this method may be called during onSocket:willDisconnectWithError: to read
501
 * any data that's left on the socket.
502
**/
503
- (NSData *)unreadData;
504
 
505
/* A few common line separators, for use with the readDataToData:... methods. */
506
+ (NSData *)CRLFData;   // 0x0D0A
507
+ (NSData *)CRData;     // 0x0D
508
+ (NSData *)LFData;     // 0x0A
509
+ (NSData *)ZeroData;   // 0x00
510
 
511
@end