Wiselib
|
00001 // 00002 // AsyncSocket.h 00003 // 00004 // This class is in the public domain. 00005 // Originally created by Dustin Voss on Wed Jan 29 2003. 00006 // Updated and maintained by Deusty Designs and the Mac development community. 00007 // 00008 // http://code.google.com/p/cocoaasyncsocket/ 00009 // 00010 00011 #import <Foundation/Foundation.h> 00012 00013 @class AsyncSocket; 00014 @class AsyncReadPacket; 00015 @class AsyncWritePacket; 00016 00017 extern NSString *const AsyncSocketException; 00018 extern NSString *const AsyncSocketErrorDomain; 00019 00020 enum AsyncSocketError 00021 { 00022 AsyncSocketCFSocketError = kCFSocketError, // From CFSocketError enum. 00023 AsyncSocketNoError = 0, // Never used. 00024 AsyncSocketCanceledError, // onSocketWillConnect: returned NO. 00025 AsyncSocketConnectTimeoutError, 00026 AsyncSocketReadMaxedOutError, // Reached set maxLength without completing 00027 AsyncSocketReadTimeoutError, 00028 AsyncSocketWriteTimeoutError 00029 }; 00030 typedef enum AsyncSocketError AsyncSocketError; 00031 00032 @protocol AsyncSocketDelegate 00033 @optional 00034 00041 - (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err; 00042 00050 - (void)onSocketDidDisconnect:(AsyncSocket *)sock; 00051 00056 - (void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket; 00057 00062 - (NSRunLoop *)onSocket:(AsyncSocket *)sock wantsRunLoopForNewSocket:(AsyncSocket *)newSocket; 00063 00075 - (BOOL)onSocketWillConnect:(AsyncSocket *)sock; 00076 00081 - (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port; 00082 00087 - (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag; 00088 00094 - (void)onSocket:(AsyncSocket *)sock didReadPartialDataOfLength:(NSUInteger)partialLength tag:(long)tag; 00095 00099 - (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag; 00100 00105 - (void)onSocket:(AsyncSocket *)sock didWritePartialDataOfLength:(NSUInteger)partialLength tag:(long)tag; 00106 00118 - (NSTimeInterval)onSocket:(AsyncSocket *)sock 00119 shouldTimeoutReadWithTag:(long)tag 00120 elapsed:(NSTimeInterval)elapsed 00121 bytesDone:(NSUInteger)length; 00122 00134 - (NSTimeInterval)onSocket:(AsyncSocket *)sock 00135 shouldTimeoutWriteWithTag:(long)tag 00136 elapsed:(NSTimeInterval)elapsed 00137 bytesDone:(NSUInteger)length; 00138 00146 - (void)onSocketDidSecure:(AsyncSocket *)sock; 00147 00148 @end 00149 00151 #pragma mark - 00152 00153 00154 @interface AsyncSocket : NSObject 00155 { 00156 CFSocketNativeHandle theNativeSocket4; 00157 CFSocketNativeHandle theNativeSocket6; 00158 00159 CFSocketRef theSocket4; // IPv4 accept or connect socket 00160 CFSocketRef theSocket6; // IPv6 accept or connect socket 00161 00162 CFReadStreamRef theReadStream; 00163 CFWriteStreamRef theWriteStream; 00164 00165 CFRunLoopSourceRef theSource4; // For theSocket4 00166 CFRunLoopSourceRef theSource6; // For theSocket6 00167 CFRunLoopRef theRunLoop; 00168 CFSocketContext theContext; 00169 NSArray *theRunLoopModes; 00170 00171 NSTimer *theConnectTimer; 00172 00173 NSMutableArray *theReadQueue; 00174 AsyncReadPacket *theCurrentRead; 00175 NSTimer *theReadTimer; 00176 NSMutableData *partialReadBuffer; 00177 00178 NSMutableArray *theWriteQueue; 00179 AsyncWritePacket *theCurrentWrite; 00180 NSTimer *theWriteTimer; 00181 00182 id theDelegate; 00183 UInt16 theFlags; 00184 00185 long theUserData; 00186 } 00187 00188 - (id)init; 00189 - (id)initWithDelegate:(id)delegate; 00190 - (id)initWithDelegate:(id)delegate userData:(long)userData; 00191 00192 /* String representation is long but has no "\n". */ 00193 - (NSString *)description; 00194 00199 - (id)delegate; 00200 - (BOOL)canSafelySetDelegate; 00201 - (void)setDelegate:(id)delegate; 00202 00203 /* User data can be a long, or an id or void * cast to a long. */ 00204 - (long)userData; 00205 - (void)setUserData:(long)userData; 00206 00207 /* Don't use these to read or write. And don't close them either! */ 00208 - (CFSocketRef)getCFSocket; 00209 - (CFReadStreamRef)getCFReadStream; 00210 - (CFWriteStreamRef)getCFWriteStream; 00211 00212 // Once one of the accept or connect methods are called, the AsyncSocket instance is locked in 00213 // and the other accept/connect methods can't be called without disconnecting the socket first. 00214 // If the attempt fails or times out, these methods either return NO or 00215 // call "onSocket:willDisconnectWithError:" and "onSockedDidDisconnect:". 00216 00217 // When an incoming connection is accepted, AsyncSocket invokes several delegate methods. 00218 // These methods are (in chronological order): 00219 // 1. onSocket:didAcceptNewSocket: 00220 // 2. onSocket:wantsRunLoopForNewSocket: 00221 // 3. onSocketWillConnect: 00222 // 00223 // Your server code will need to retain the accepted socket (if you want to accept it). 00224 // The best place to do this is probably in the onSocket:didAcceptNewSocket: method. 00225 // 00226 // After the read and write streams have been setup for the newly accepted socket, 00227 // the onSocket:didConnectToHost:port: method will be called on the proper run loop. 00228 // 00229 // Multithreading Note: If you're going to be moving the newly accepted socket to another run 00230 // loop by implementing onSocket:wantsRunLoopForNewSocket:, then you should wait until the 00231 // onSocket:didConnectToHost:port: method before calling read, write, or startTLS methods. 00232 // Otherwise read/write events are scheduled on the incorrect runloop, and chaos may ensue. 00233 00239 - (BOOL)acceptOnPort:(UInt16)port error:(NSError **)errPtr; 00240 00251 - (BOOL)acceptOnInterface:(NSString *)interface port:(UInt16)port error:(NSError **)errPtr; 00252 00257 - (BOOL)connectToHost:(NSString *)hostname onPort:(UInt16)port error:(NSError **)errPtr; 00258 00263 - (BOOL)connectToHost:(NSString *)hostname 00264 onPort:(UInt16)port 00265 withTimeout:(NSTimeInterval)timeout 00266 error:(NSError **)errPtr; 00267 00276 - (BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError **)errPtr; 00277 00282 - (BOOL)connectToAddress:(NSData *)remoteAddr withTimeout:(NSTimeInterval)timeout error:(NSError **)errPtr; 00283 00284 - (BOOL)connectToAddress:(NSData *)remoteAddr 00285 viaInterfaceAddress:(NSData *)interfaceAddr 00286 withTimeout:(NSTimeInterval)timeout 00287 error:(NSError **)errPtr; 00288 00299 - (void)disconnect; 00300 00306 - (void)disconnectAfterReading; 00307 00313 - (void)disconnectAfterWriting; 00314 00319 - (void)disconnectAfterReadingAndWriting; 00320 00321 /* Returns YES if the socket and streams are open, connected, and ready for reading and writing. */ 00322 - (BOOL)isConnected; 00323 00328 - (NSString *)connectedHost; 00329 - (UInt16)connectedPort; 00330 00331 - (NSString *)localHost; 00332 - (UInt16)localPort; 00333 00340 - (NSData *)connectedAddress; 00341 - (NSData *)localAddress; 00342 00347 - (BOOL)isIPv4; 00348 - (BOOL)isIPv6; 00349 00350 // The readData and writeData methods won't block (they are asynchronous). 00351 // 00352 // When a read is complete the onSocket:didReadData:withTag: delegate method is called. 00353 // When a write is complete the onSocket:didWriteDataWithTag: delegate method is called. 00354 // 00355 // You may optionally set a timeout for any read/write operation. (To not timeout, use a negative time interval.) 00356 // If a read/write opertion times out, the corresponding "onSocket:shouldTimeout..." delegate method 00357 // is called to optionally allow you to extend the timeout. 00358 // Upon a timeout, the "onSocket:willDisconnectWithError:" method is called, followed by "onSocketDidDisconnect". 00359 // 00360 // The tag is for your convenience. 00361 // You can use it as an array index, step number, state id, pointer, etc. 00362 00368 - (void)readDataWithTimeout:(NSTimeInterval)timeout tag:(long)tag; 00369 00385 - (void)readDataWithTimeout:(NSTimeInterval)timeout 00386 buffer:(NSMutableData *)buffer 00387 bufferOffset:(NSUInteger)offset 00388 tag:(long)tag; 00389 00407 - (void)readDataWithTimeout:(NSTimeInterval)timeout 00408 buffer:(NSMutableData *)buffer 00409 bufferOffset:(NSUInteger)offset 00410 maxLength:(NSUInteger)length 00411 tag:(long)tag; 00412 00420 - (void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)timeout tag:(long)tag; 00421 00438 - (void)readDataToLength:(NSUInteger)length 00439 withTimeout:(NSTimeInterval)timeout 00440 buffer:(NSMutableData *)buffer 00441 bufferOffset:(NSUInteger)offset 00442 tag:(long)tag; 00443 00456 - (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag; 00457 00477 - (void)readDataToData:(NSData *)data 00478 withTimeout:(NSTimeInterval)timeout 00479 buffer:(NSMutableData *)buffer 00480 bufferOffset:(NSUInteger)offset 00481 tag:(long)tag; 00482 00502 - (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout maxLength:(NSUInteger)length tag:(long)tag; 00503 00531 - (void)readDataToData:(NSData *)data 00532 withTimeout:(NSTimeInterval)timeout 00533 buffer:(NSMutableData *)buffer 00534 bufferOffset:(NSUInteger)offset 00535 maxLength:(NSUInteger)length 00536 tag:(long)tag; 00537 00544 - (void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag; 00545 00550 - (float)progressOfReadReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total; 00551 - (float)progressOfWriteReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total; 00552 00592 - (void)startTLS:(NSDictionary *)tlsSettings; 00593 00607 - (void)enablePreBuffering; 00608 00624 - (BOOL)moveToRunLoop:(NSRunLoop *)runLoop; 00625 00637 - (BOOL)setRunLoopModes:(NSArray *)runLoopModes; 00638 - (BOOL)addRunLoopMode:(NSString *)runLoopMode; 00639 - (BOOL)removeRunLoopMode:(NSString *)runLoopMode; 00640 00645 - (NSArray *)runLoopModes; 00646 00651 - (NSData *)unreadData; 00652 00653 /* A few common line separators, for use with the readDataToData:... methods. */ 00654 + (NSData *)CRLFData; // 0x0D0A 00655 + (NSData *)CRData; // 0x0D 00656 + (NSData *)LFData; // 0x0A 00657 + (NSData *)ZeroData; // 0x00 00658 00659 @end