AsyncSocket.m.svn-base
上传用户:kc0325
上传日期:2020-06-20
资源大小:204k
文件大小:71k
源码类别:

iPhone

开发平台:

Objective-C

  1. //
  2. //  AsyncSocket.m
  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. #import "AsyncSocket.h"
  11. #import <sys/socket.h>
  12. #import <netinet/in.h>
  13. #import <arpa/inet.h>
  14. #import <netdb.h>
  15. #if TARGET_OS_IPHONE
  16. // Note: You may need to add the CFNetwork Framework to your project
  17. #import <CFNetwork/CFNetwork.h>
  18. #endif
  19. #pragma mark Declarations
  20. #define READQUEUE_CAPACITY 5           // Initial capacity
  21. #define WRITEQUEUE_CAPACITY 5           // Initial capacity
  22. #define READALL_CHUNKSIZE 256         // Incremental increase in buffer size
  23. #define WRITE_CHUNKSIZE    (1024 * 4)   // Limit on size of each write pass
  24. NSString *const AsyncSocketException = @"AsyncSocketException";
  25. NSString *const AsyncSocketErrorDomain = @"AsyncSocketErrorDomain";
  26. // This is a mutex lock used by all instances of AsyncSocket, to protect getaddrinfo.
  27. // The man page says it is not thread-safe. (As of Mac OS X 10.4.7, and possibly earlier)
  28. static NSString *getaddrinfoLock = @"lock";
  29. enum AsyncSocketFlags
  30. {
  31. kEnablePreBuffering   = 1 << 0,   // If set, pre-buffering is enabled.
  32. kDidCallConnectDeleg  = 1 << 1,   // If set, connect delegate has been called.
  33. kDidPassConnectMethod = 1 << 2,   // If set, disconnection results in delegate call.
  34. kForbidReadsWrites    = 1 << 3,   // If set, no new reads or writes are allowed.
  35. kDisconnectSoon       = 1 << 4,   // If set, disconnect as soon as nothing is queued.
  36. kClosingWithError     = 1 << 5,   // If set, the socket is being closed due to an error.
  37. };
  38. @interface AsyncSocket (Private)
  39. // Socket Implementation
  40. - (CFSocketRef) createAcceptSocketForAddress:(NSData *)addr error:(NSError **)errPtr;
  41. - (BOOL) createSocketForAddress:(NSData *)remoteAddr error:(NSError **)errPtr;
  42. - (BOOL) attachSocketsToRunLoop:(NSRunLoop *)runLoop error:(NSError **)errPtr;
  43. - (BOOL) configureSocketAndReturnError:(NSError **)errPtr;
  44. - (BOOL) connectSocketToAddress:(NSData *)remoteAddr error:(NSError **)errPtr;
  45. - (void) doAcceptWithSocket:(CFSocketNativeHandle)newSocket;
  46. - (void) doSocketOpen:(CFSocketRef)sock withCFSocketError:(CFSocketError)err;
  47. // Stream Implementation
  48. - (BOOL) createStreamsFromNative:(CFSocketNativeHandle)native error:(NSError **)errPtr;
  49. - (BOOL) createStreamsToHost:(NSString *)hostname onPort:(UInt16)port error:(NSError **)errPtr;
  50. - (BOOL) attachStreamsToRunLoop:(NSRunLoop *)runLoop error:(NSError **)errPtr;
  51. - (BOOL) configureStreamsAndReturnError:(NSError **)errPtr;
  52. - (BOOL) openStreamsAndReturnError:(NSError **)errPtr;
  53. - (void) doStreamOpen;
  54. - (BOOL) setSocketFromStreamsAndReturnError:(NSError **)errPtr;
  55. // Disconnect Implementation
  56. - (void) closeWithError:(NSError *)err;
  57. - (void) recoverUnreadData;
  58. - (void) emptyQueues;
  59. - (void) close;
  60. // Errors
  61. - (NSError *) getErrnoError;
  62. - (NSError *) getAbortError;
  63. - (NSError *) getStreamError;
  64. - (NSError *) getSocketError;
  65. - (NSError *) getReadMaxedOutError;
  66. - (NSError *) getReadTimeoutError;
  67. - (NSError *) getWriteTimeoutError;
  68. - (NSError *) errorFromCFStreamError:(CFStreamError)err;
  69. // Diagnostics
  70. - (BOOL) isSocketConnected;
  71. - (BOOL) areStreamsConnected;
  72. - (NSString *) connectedHost: (CFSocketRef)socket;
  73. - (UInt16) connectedPort: (CFSocketRef)socket;
  74. - (NSString *) localHost: (CFSocketRef)socket;
  75. - (UInt16) localPort: (CFSocketRef)socket;
  76. - (NSString *) addressHost: (CFDataRef)cfaddr;
  77. - (UInt16) addressPort: (CFDataRef)cfaddr;
  78. // Reading
  79. - (void) doBytesAvailable;
  80. - (void) completeCurrentRead;
  81. - (void) endCurrentRead;
  82. - (void) scheduleDequeueRead;
  83. - (void) maybeDequeueRead;
  84. - (void) doReadTimeout:(NSTimer *)timer;
  85. // Writing
  86. - (void) doSendBytes;
  87. - (void) completeCurrentWrite;
  88. - (void) endCurrentWrite;
  89. - (void) scheduleDequeueWrite;
  90. - (void) maybeDequeueWrite;
  91. - (void) maybeScheduleDisconnect;
  92. - (void) doWriteTimeout:(NSTimer *)timer;
  93. // Callbacks
  94. - (void) doCFCallback:(CFSocketCallBackType)type forSocket:(CFSocketRef)sock withAddress:(NSData *)address withData:(const void *)pData;
  95. - (void) doCFReadStreamCallback:(CFStreamEventType)type forStream:(CFReadStreamRef)stream;
  96. - (void) doCFWriteStreamCallback:(CFStreamEventType)type forStream:(CFWriteStreamRef)stream;
  97. @end
  98. static void MyCFSocketCallback (CFSocketRef, CFSocketCallBackType, CFDataRef, const void *, void *);
  99. static void MyCFReadStreamCallback (CFReadStreamRef stream, CFStreamEventType type, void *pInfo);
  100. static void MyCFWriteStreamCallback (CFWriteStreamRef stream, CFStreamEventType type, void *pInfo);
  101. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  102. #pragma mark -
  103. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  104. /**
  105.  * The AsyncReadPacket encompasses the instructions for a current read.
  106.  * The content of a read packet allows the code to determine if we're:
  107.  * reading to a certain length, reading to a certain separator, or simply reading the first chunk of data.
  108. **/
  109. @interface AsyncReadPacket : NSObject
  110. {
  111. @public
  112. NSMutableData *buffer;
  113. CFIndex bytesDone;
  114. NSTimeInterval timeout;
  115. CFIndex maxLength;
  116. long tag;
  117. NSData *term;
  118. BOOL readAllAvailableData;
  119. }
  120. - (id)initWithData:(NSMutableData *)d
  121.    timeout:(NSTimeInterval)t
  122.    tag:(long)i
  123.   readAllAvailable:(BOOL)a
  124. terminator:(NSData *)e
  125.     maxLength:(CFIndex)m;
  126. - (unsigned)readLengthForTerm;
  127. - (unsigned)prebufferReadLengthForTerm;
  128. - (CFIndex)searchForTermAfterPreBuffering:(CFIndex)numBytes;
  129. - (void)dealloc;
  130. @end
  131. @implementation AsyncReadPacket
  132. - (id)initWithData:(NSMutableData *)d
  133.    timeout:(NSTimeInterval)t
  134.    tag:(long)i
  135.   readAllAvailable:(BOOL)a
  136. terminator:(NSData *)e
  137.          maxLength:(CFIndex)m
  138. {
  139. if(self = [super init])
  140. {
  141. buffer = [d retain];
  142. timeout = t;
  143. tag = i;
  144. readAllAvailableData = a;
  145. term = [e copy];
  146. bytesDone = 0;
  147. maxLength = m;
  148. }
  149. return self;
  150. }
  151. /**
  152.  * For read packets with a set terminator, returns the safe length of data that can be read
  153.  * without going over a terminator, or the maxLength.
  154.  * 
  155.  * It is assumed the terminator has not already been read.
  156. **/
  157. - (unsigned)readLengthForTerm
  158. {
  159. NSAssert(term != nil, @"Searching for term in data when there is no term.");
  160. // What we're going to do is look for a partial sequence of the terminator at the end of the buffer.
  161. // If a partial sequence occurs, then we must assume the next bytes to arrive will be the rest of the term,
  162. // and we can only read that amount.
  163. // Otherwise, we're safe to read the entire length of the term.
  164. unsigned result = [term length];
  165. // i = index within buffer at which to check data
  166. // j = length of term to check against
  167. // Note: Beware of implicit casting rules
  168. // This could give you -1: MAX(0, (0 - [term length] + 1));
  169. CFIndex i = MAX(0, (CFIndex)(bytesDone - [term length] + 1));
  170. CFIndex j = MIN([term length] - 1, bytesDone);
  171. while(i < bytesDone)
  172. {
  173. const void *subBuffer = [buffer bytes] + i;
  174. if(memcmp(subBuffer, [term bytes], j) == 0)
  175. {
  176. result = [term length] - j;
  177. break;
  178. }
  179. i++;
  180. j--;
  181. }
  182. if(maxLength > 0)
  183. return MIN(result, (maxLength - bytesDone));
  184. else
  185. return result;
  186. }
  187. /**
  188.  * Assuming pre-buffering is enabled, returns the amount of data that can be read
  189.  * without going over the maxLength.
  190. **/
  191. - (unsigned)prebufferReadLengthForTerm
  192. {
  193. if(maxLength > 0)
  194. return MIN(READALL_CHUNKSIZE, (maxLength - bytesDone));
  195. else
  196. return READALL_CHUNKSIZE;
  197. }
  198. /**
  199.  * For read packets with a set terminator, scans the packet buffer for the term.
  200.  * It is assumed the terminator had not been fully read prior to the new bytes.
  201.  * 
  202.  * If the term is found, the number of excess bytes after the term are returned.
  203.  * If the term is not found, this method will return -1.
  204.  * 
  205.  * Note: A return value of zero means the term was found at the very end.
  206. **/
  207. - (CFIndex)searchForTermAfterPreBuffering:(CFIndex)numBytes
  208. {
  209. NSAssert(term != nil, @"Searching for term in data when there is no term.");
  210. // We try to start the search such that the first new byte read matches up with the last byte of the term.
  211. // We continue searching forward after this until the term no longer fits into the buffer.
  212. // Note: Beware of implicit casting rules
  213. // This could give you -1: MAX(0, 1 - 1 - [term length] + 1);
  214. CFIndex i = MAX(0, (CFIndex)(bytesDone - numBytes - [term length] + 1));
  215. while(i + [term length] <= bytesDone)
  216. {
  217. const void *subBuffer = [buffer bytes] + i;
  218. if(memcmp(subBuffer, [term bytes], [term length]) == 0)
  219. {
  220. return bytesDone - (i + [term length]);
  221. }
  222. i++;
  223. }
  224. return -1;
  225. }
  226. - (void)dealloc
  227. {
  228. [buffer release];
  229. [term release];
  230. [super dealloc];
  231. }
  232. @end
  233. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  234. #pragma mark -
  235. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  236. @interface AsyncWritePacket : NSObject
  237. {
  238. @public
  239. NSData *buffer;
  240. CFIndex bytesDone;
  241. long tag;
  242. NSTimeInterval timeout;
  243. }
  244. - (id)initWithData:(NSData *)d timeout:(NSTimeInterval)t tag:(long)i;
  245. - (void)dealloc;
  246. @end
  247. @implementation AsyncWritePacket
  248. - (id)initWithData:(NSData *)d timeout:(NSTimeInterval)t tag:(long)i;
  249. {
  250. if(self = [super init])
  251. {
  252. buffer = [d retain];
  253. timeout = t;
  254. tag = i;
  255. bytesDone = 0;
  256. }
  257. return self;
  258. }
  259. - (void)dealloc
  260. {
  261. [buffer release];
  262. [super dealloc];
  263. }
  264. @end
  265. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  266. #pragma mark -
  267. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  268. @implementation AsyncSocket
  269. - (id)init
  270. {
  271. return [self initWithDelegate:nil userData:0];
  272. }
  273. - (id)initWithDelegate:(id)delegate
  274. {
  275. return [self initWithDelegate:delegate userData:0];
  276. }
  277. // Designated initializer.
  278. - (id)initWithDelegate:(id)delegate userData:(long)userData
  279. {
  280. if(self = [super init])
  281. {
  282. theFlags = 0x00;
  283. theDelegate = delegate;
  284. theUserData = userData;
  285. theSocket = NULL;
  286. theSource = NULL;
  287. theSocket6 = NULL;
  288. theSource6 = NULL;
  289. theRunLoop = NULL;
  290. theReadStream = NULL;
  291. theWriteStream = NULL;
  292. theReadQueue = [[NSMutableArray alloc] initWithCapacity:READQUEUE_CAPACITY];
  293. theCurrentRead = nil;
  294. theReadTimer = nil;
  295. partialReadBuffer = [[NSMutableData alloc] initWithCapacity:READALL_CHUNKSIZE];
  296. theWriteQueue = [[NSMutableArray alloc] initWithCapacity:WRITEQUEUE_CAPACITY];
  297. theCurrentWrite = nil;
  298. theWriteTimer = nil;
  299. // Socket context
  300. NSAssert(sizeof(CFSocketContext) == sizeof(CFStreamClientContext), @"CFSocketContext != CFStreamClientContext");
  301. theContext.version = 0;
  302. theContext.info = self;
  303. theContext.retain = nil;
  304. theContext.release = nil;
  305. theContext.copyDescription = nil;
  306. }
  307. return self;
  308. }
  309. // The socket may been initialized in a connected state and auto-released, so this should close it down cleanly.
  310. - (void)dealloc
  311. {
  312. [self close];
  313. [theReadQueue release];
  314. [theWriteQueue release];
  315. [NSObject cancelPreviousPerformRequestsWithTarget:theDelegate selector:@selector(onSocketDidDisconnect:) object:self];
  316. [NSObject cancelPreviousPerformRequestsWithTarget:self];
  317. [super dealloc];
  318. }
  319. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  320. #pragma mark Accessors
  321. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  322. - (long)userData
  323. {
  324. return theUserData;
  325. }
  326. - (void)setUserData:(long)userData
  327. {
  328. theUserData = userData;
  329. }
  330. - (id)delegate
  331. {
  332. return theDelegate;
  333. }
  334. - (void)setDelegate:(id)delegate
  335. {
  336. theDelegate = delegate;
  337. }
  338. - (BOOL)canSafelySetDelegate
  339. {
  340. return ([theReadQueue count] == 0 && [theWriteQueue count] == 0 && theCurrentRead == nil && theCurrentWrite == nil);
  341. }
  342. - (CFSocketRef)getCFSocket
  343. {
  344. if(theSocket)
  345. return theSocket;
  346. else
  347. return theSocket6;
  348. }
  349. - (CFReadStreamRef)getCFReadStream
  350. {
  351. return theReadStream;
  352. }
  353. - (CFWriteStreamRef)getCFWriteStream
  354. {
  355. return theWriteStream;
  356. }
  357. - (float)progressOfReadReturningTag:(long *)tag bytesDone:(CFIndex *)done total:(CFIndex *)total
  358. {
  359. // Check to make sure we're actually reading something right now
  360. if (!theCurrentRead) return NAN;
  361. // It's only possible to know the progress of our read if we're reading to a certain length
  362. // If we're reading to data, we of course have no idea when the data will arrive
  363. // If we're reading to timeout, then we have no idea when the next chunk of data will arrive.
  364. BOOL hasTotal = (theCurrentRead->readAllAvailableData == NO && theCurrentRead->term == nil);
  365. CFIndex d = theCurrentRead->bytesDone;
  366. CFIndex t = hasTotal ? [theCurrentRead->buffer length] : 0;
  367. if (tag != NULL)   *tag = theCurrentRead->tag;
  368. if (done != NULL)  *done = d;
  369. if (total != NULL) *total = t;
  370. float ratio = (float)d/(float)t;
  371. return isnan(ratio) ? 1.0 : ratio; // 0 of 0 bytes is 100% done.
  372. }
  373. - (float)progressOfWriteReturningTag:(long *)tag bytesDone:(CFIndex *)done total:(CFIndex *)total
  374. {
  375. if (!theCurrentWrite) return NAN;
  376. CFIndex d = theCurrentWrite->bytesDone;
  377. CFIndex t = [theCurrentWrite->buffer length];
  378. if (tag != NULL)   *tag = theCurrentWrite->tag;
  379. if (done != NULL)  *done = d;
  380. if (total != NULL) *total = t;
  381. return (float)d/(float)t;
  382. }
  383. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  384. #pragma mark Configuration
  385. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  386. /**
  387.  * See the header file for a full explanation of pre-buffering.
  388. **/
  389. - (void)enablePreBuffering
  390. {
  391. theFlags |= kEnablePreBuffering;
  392. }
  393. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  394. #pragma mark Connection
  395. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  396. - (BOOL)acceptOnPort:(UInt16)port error:(NSError **)errPtr
  397. {
  398. return [self acceptOnAddress:nil port:port error:errPtr];
  399. }
  400. /**
  401.  * To accept on a certain address, pass the address to accept on.
  402.  * To accept on any address, pass nil or an empty string.
  403.  * To accept only connections from localhost pass "localhost" or "loopback".
  404. **/
  405. - (BOOL)acceptOnAddress:(NSString *)hostaddr port:(UInt16)port error:(NSError **)errPtr
  406. {
  407. if (theDelegate == NULL)
  408. [NSException raise:AsyncSocketException format:@"Attempting to accept without a delegate. Set a delegate first."];
  409. if (theSocket != NULL || theSocket6 != NULL)
  410. [NSException raise:AsyncSocketException format:@"Attempting to accept while connected or accepting connections. Disconnect first."];
  411. // Set up the listen sockaddr structs if needed.
  412. NSData *address = nil, *address6 = nil;
  413. if(hostaddr == nil || ([hostaddr length] == 0))
  414. {
  415. // Accept on ANY address
  416. struct sockaddr_in nativeAddr;
  417. nativeAddr.sin_len         = sizeof(struct sockaddr_in);
  418. nativeAddr.sin_family      = AF_INET;
  419. nativeAddr.sin_port        = htons(port);
  420. nativeAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  421. memset(&(nativeAddr.sin_zero), 0, sizeof(nativeAddr.sin_zero));
  422. struct sockaddr_in6 nativeAddr6;
  423. nativeAddr6.sin6_len       = sizeof(struct sockaddr_in6);
  424. nativeAddr6.sin6_family    = AF_INET6;
  425. nativeAddr6.sin6_port      = htons(port);
  426. nativeAddr6.sin6_flowinfo  = 0;
  427. nativeAddr6.sin6_addr      = in6addr_any;
  428. nativeAddr6.sin6_scope_id  = 0;
  429. // Wrap the native address structures for CFSocketSetAddress.
  430. address = [NSData dataWithBytes:&nativeAddr length:sizeof(nativeAddr)];
  431. address6 = [NSData dataWithBytes:&nativeAddr6 length:sizeof(nativeAddr6)];
  432. }
  433. else if([hostaddr isEqualToString:@"localhost"] || [hostaddr isEqualToString:@"loopback"])
  434. {
  435. // Accept only on LOOPBACK address
  436. struct sockaddr_in nativeAddr;
  437. nativeAddr.sin_len         = sizeof(struct sockaddr_in);
  438. nativeAddr.sin_family      = AF_INET;
  439. nativeAddr.sin_port        = htons(port);
  440. nativeAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  441. memset(&(nativeAddr.sin_zero), 0, sizeof(nativeAddr.sin_zero));
  442. struct sockaddr_in6 nativeAddr6;
  443. nativeAddr6.sin6_len       = sizeof(struct sockaddr_in6);
  444. nativeAddr6.sin6_family    = AF_INET6;
  445. nativeAddr6.sin6_port      = htons(port);
  446. nativeAddr6.sin6_flowinfo  = 0;
  447. nativeAddr6.sin6_addr      = in6addr_loopback;
  448. nativeAddr6.sin6_scope_id  = 0;
  449. // Wrap the native address structures for CFSocketSetAddress.
  450. address = [NSData dataWithBytes:&nativeAddr length:sizeof(nativeAddr)];
  451. address6 = [NSData dataWithBytes:&nativeAddr6 length:sizeof(nativeAddr6)];
  452. }
  453. else
  454. {
  455. NSString *portStr = [NSString stringWithFormat:@"%hu", port];
  456. @synchronized (getaddrinfoLock)
  457. {
  458. struct addrinfo hints, *res, *res0;
  459. memset(&hints, 0, sizeof(hints));
  460. hints.ai_family   = PF_UNSPEC;
  461. hints.ai_socktype = SOCK_STREAM;
  462. hints.ai_protocol = IPPROTO_TCP;
  463. hints.ai_flags    = AI_PASSIVE;
  464. int error = getaddrinfo([hostaddr UTF8String], [portStr UTF8String], &hints, &res0);
  465. if(error)
  466. {
  467. if(errPtr)
  468. {
  469. NSString *errMsg = [NSString stringWithCString:gai_strerror(error) encoding:NSASCIIStringEncoding];
  470. NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  471. *errPtr = [NSError errorWithDomain:@"kCFStreamErrorDomainNetDB" code:error userInfo:info];
  472. }
  473. }
  474. for(res = res0; res; res = res->ai_next)
  475. {
  476. if(!address && (res->ai_family == AF_INET))
  477. {
  478. // Found IPv4 address
  479. // Wrap the native address structures for CFSocketSetAddress.
  480. address = [NSData dataWithBytes:res->ai_addr length:res->ai_addrlen];
  481. }
  482. else if(!address6 && (res->ai_family == AF_INET6))
  483. {
  484. // Found IPv6 address
  485. // Wrap the native address structures for CFSocketSetAddress.
  486. address6 = [NSData dataWithBytes:res->ai_addr length:res->ai_addrlen];
  487. }
  488. }
  489. freeaddrinfo(res0);
  490. }
  491. if(!address && !address6) return NO;
  492. }
  493. // Create the sockets.
  494. if (address)
  495. {
  496. theSocket = [self createAcceptSocketForAddress:address error:errPtr];
  497. if (theSocket == NULL) goto Failed;
  498. }
  499. if (address6)
  500. {
  501. theSocket6 = [self createAcceptSocketForAddress:address6 error:errPtr];
  502. // Note: The iPhone doesn't currently support IPv6
  503. #if !TARGET_OS_IPHONE
  504. if (theSocket6 == NULL) goto Failed;
  505. #endif
  506. }
  507. // Attach the sockets to the run loop so that callback methods work
  508. [self attachSocketsToRunLoop:nil error:nil];
  509. // Set the SO_REUSEADDR flags.
  510. int reuseOn = 1;
  511. if (theSocket) setsockopt(CFSocketGetNative(theSocket), SOL_SOCKET, SO_REUSEADDR, &reuseOn, sizeof(reuseOn));
  512. if (theSocket6) setsockopt(CFSocketGetNative(theSocket6), SOL_SOCKET, SO_REUSEADDR, &reuseOn, sizeof(reuseOn));
  513. // Set the local bindings which causes the sockets to start listening.
  514. CFSocketError err;
  515. if (theSocket)
  516. {
  517. err = CFSocketSetAddress (theSocket, (CFDataRef)address);
  518. if (err != kCFSocketSuccess) goto Failed;
  519. //NSLog(@"theSocket4: %hu", [self localPort:theSocket]);
  520. }
  521. if(port == 0 && theSocket && theSocket6)
  522. {
  523. // The user has passed in port 0, which means he wants to allow the kernel to choose the port for them
  524. // However, the kernel will choose a different port for both theSocket and theSocket6
  525. // So we grab the port the kernel choose for theSocket, and set it as the port for theSocket6
  526. UInt16 chosenPort = [self localPort:theSocket];
  527. struct sockaddr_in6 *pSockAddr6 = (struct sockaddr_in6 *)[address6 bytes];
  528. pSockAddr6->sin6_port = htons(chosenPort);
  529.     }
  530. if (theSocket6)
  531. {
  532. err = CFSocketSetAddress (theSocket6, (CFDataRef)address6);
  533. if (err != kCFSocketSuccess) goto Failed;
  534. //NSLog(@"theSocket6: %hu", [self localPort:theSocket6]);
  535. }
  536. theFlags |= kDidPassConnectMethod;
  537. return YES;
  538. Failed:;
  539. if(errPtr) *errPtr = [self getSocketError];
  540. if(theSocket != NULL)
  541. {
  542. CFSocketInvalidate(theSocket);
  543. CFRelease(theSocket);
  544. theSocket = NULL;
  545. }
  546. if(theSocket6 != NULL)
  547. {
  548. CFSocketInvalidate(theSocket6);
  549. CFRelease(theSocket6);
  550. theSocket6 = NULL;
  551. }
  552. return NO;
  553. }
  554. /**
  555.  * This method creates an initial CFReadStream and CFWriteStream to the given host on the given port.
  556.  * The connection is then opened, and the corresponding CFSocket will be extracted after the connection succeeds.
  557.  *
  558.  * Thus the delegate will have access to the CFReadStream and CFWriteStream prior to connection,
  559.  * specifically in the onSocketWillConnect: method.
  560. **/
  561. - (BOOL)connectToHost:(NSString*)hostname onPort:(UInt16)port error:(NSError **)errPtr
  562. {
  563. if(theDelegate == NULL)
  564. {
  565. NSString *message = @"Attempting to connect without a delegate. Set a delegate first.";
  566. [NSException raise:AsyncSocketException format:message];
  567. }
  568. if(theSocket != NULL || theSocket6 != NULL)
  569. {
  570. NSString *message = @"Attempting to connect while connected or accepting connections. Disconnect first.";
  571. [NSException raise:AsyncSocketException format:message];
  572. }
  573. BOOL pass = YES;
  574. if(pass && ![self createStreamsToHost:hostname onPort:port error:errPtr]) pass = NO;
  575. if(pass && ![self attachStreamsToRunLoop:nil error:errPtr])               pass = NO;
  576. if(pass && ![self configureStreamsAndReturnError:errPtr])                 pass = NO;
  577. if(pass && ![self openStreamsAndReturnError:errPtr])                      pass = NO;
  578. if(pass)
  579. theFlags |= kDidPassConnectMethod;
  580. else
  581. [self close];
  582. return pass;
  583. }
  584. /**
  585.  * This method creates an initial CFSocket to the given address.
  586.  * The connection is then opened, and the corresponding CFReadStream and CFWriteStream will be
  587.  * created from the low-level sockets after the connection succeeds.
  588.  *
  589.  * Thus the delegate will have access to the CFSocket and CFSocketNativeHandle (BSD socket) prior to connection,
  590.  * specifically in the onSocketWillConnect: method.
  591.  * 
  592.  * Note: The NSData parameter is expected to be a sockaddr structure. For example, an NSData object returned from
  593.  * NSNetservice addresses method.
  594.  * If you have an existing struct sockaddr you can convert it to an NSData object like so:
  595.  * struct sockaddr sa  -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len];
  596.  * struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len];
  597. **/
  598. - (BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError **)errPtr
  599. {
  600. if (theDelegate == NULL)
  601. {
  602. NSString *message = @"Attempting to connect without a delegate. Set a delegate first.";
  603. [NSException raise:AsyncSocketException format:message];
  604. }
  605. if (theSocket != NULL || theSocket6 != NULL)
  606. {
  607. NSString *message = @"Attempting to connect while connected or accepting connections. Disconnect first.";
  608. [NSException raise:AsyncSocketException format:message];
  609. }
  610. BOOL pass = YES;
  611. if(pass && ![self createSocketForAddress:remoteAddr error:errPtr])   pass = NO;
  612. if(pass && ![self attachSocketsToRunLoop:nil error:errPtr])          pass = NO;
  613. if(pass && ![self configureSocketAndReturnError:errPtr])             pass = NO;
  614. if(pass && ![self connectSocketToAddress:remoteAddr error:errPtr])   pass = NO;
  615. if(pass)
  616. theFlags |= kDidPassConnectMethod;
  617. else
  618. [self close];
  619. return pass;
  620. }
  621. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  622. #pragma mark Socket Implementation:
  623. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  624. /**
  625.  * Creates the accept sockets.
  626.  * Returns true if either IPv4 or IPv6 is created.
  627.  * If either is missing, an error is returned (even though the method may return true).
  628. **/
  629. - (CFSocketRef)createAcceptSocketForAddress:(NSData *)addr error:(NSError **)errPtr
  630. {
  631. struct sockaddr *pSockAddr = (struct sockaddr *)[addr bytes];
  632. int addressFamily = pSockAddr->sa_family;
  633. CFSocketRef socket = CFSocketCreate(kCFAllocatorDefault,
  634. addressFamily,
  635. SOCK_STREAM,
  636. 0,
  637. kCFSocketAcceptCallBack,                // Callback flags
  638. (CFSocketCallBack)&MyCFSocketCallback,  // Callback method
  639. &theContext);
  640. if(socket == NULL)
  641. {
  642. if(errPtr) *errPtr = [self getSocketError];
  643. }
  644. return socket;
  645. }
  646. - (BOOL)createSocketForAddress:(NSData *)remoteAddr error:(NSError **)errPtr
  647. {
  648. struct sockaddr *pSockAddr = (struct sockaddr *)[remoteAddr bytes];
  649. if(pSockAddr->sa_family == AF_INET)
  650. {
  651. theSocket = CFSocketCreate(NULL,                                   // Default allocator
  652.    PF_INET,                                // Protocol Family
  653.    SOCK_STREAM,                            // Socket Type
  654.    IPPROTO_TCP,                            // Protocol
  655.    kCFSocketConnectCallBack,               // Callback flags
  656.    (CFSocketCallBack)&MyCFSocketCallback,  // Callback method
  657.    &theContext);                           // Socket Context
  658. if(theSocket == NULL)
  659. {
  660. if (errPtr) *errPtr = [self getSocketError];
  661. return NO;
  662. }
  663. }
  664. else if(pSockAddr->sa_family == AF_INET6)
  665. {
  666. theSocket6 = CFSocketCreate(NULL,                                   // Default allocator
  667.     PF_INET6,                               // Protocol Family
  668.     SOCK_STREAM,                            // Socket Type
  669.     IPPROTO_TCP,                            // Protocol
  670.     kCFSocketConnectCallBack,               // Callback flags
  671.     (CFSocketCallBack)&MyCFSocketCallback,  // Callback method
  672.     &theContext);                           // Socket Context
  673. if(theSocket6 == NULL)
  674. {
  675. if (errPtr) *errPtr = [self getSocketError];
  676. return NO;
  677. }
  678. }
  679. else
  680. {
  681. if (errPtr) *errPtr = [self getSocketError];
  682. return NO;
  683. }
  684. return YES;
  685. }
  686. /**
  687.  * Adds the CFSocket's to the run-loop so that callbacks will work properly.
  688. **/
  689. - (BOOL)attachSocketsToRunLoop:(NSRunLoop *)runLoop error:(NSError **)errPtr
  690. {
  691. // Get the CFRunLoop to which the socket should be attached.
  692. theRunLoop = (runLoop == nil) ? CFRunLoopGetCurrent() : [runLoop getCFRunLoop];
  693. if(theSocket)
  694. {
  695. theSource  = CFSocketCreateRunLoopSource (kCFAllocatorDefault, theSocket, 0);
  696. CFRunLoopAddSource (theRunLoop, theSource, kCFRunLoopDefaultMode);
  697. }
  698. if(theSocket6)
  699. {
  700. theSource6 = CFSocketCreateRunLoopSource (kCFAllocatorDefault, theSocket6, 0);
  701. CFRunLoopAddSource (theRunLoop, theSource6, kCFRunLoopDefaultMode);
  702. }
  703. return YES;
  704. }
  705. /**
  706.  * Allows the delegate method to configure the CFSocket or CFNativeSocket as desired before we connect.
  707.  * Note that the CFReadStream and CFWriteStream will not be available until after the connection is opened.
  708. **/
  709. - (BOOL)configureSocketAndReturnError:(NSError **)errPtr
  710. {
  711. // Call the delegate method for further configuration.
  712. if([theDelegate respondsToSelector:@selector(onSocketWillConnect:)])
  713. {
  714. if([theDelegate onSocketWillConnect:self] == NO)
  715. {
  716. if (errPtr) *errPtr = [self getAbortError];
  717. return NO;
  718. }
  719. }
  720. return YES;
  721. }
  722. - (BOOL)connectSocketToAddress:(NSData *)remoteAddr error:(NSError **)errPtr
  723. {
  724. // Start connecting to the given address in the background
  725. // The MyCFSocketCallback method will be called when the connection succeeds or fails
  726. if(theSocket)
  727. {
  728. CFSocketError err = CFSocketConnectToAddress(theSocket, (CFDataRef)remoteAddr, -1);
  729. if(err != kCFSocketSuccess)
  730. {
  731. if (errPtr) *errPtr = [self getSocketError];
  732. return NO;
  733. }
  734. }
  735. else if(theSocket6)
  736. {
  737. CFSocketError err = CFSocketConnectToAddress(theSocket6, (CFDataRef)remoteAddr, -1);
  738. if(err != kCFSocketSuccess)
  739. {
  740. if (errPtr) *errPtr = [self getSocketError];
  741. return NO;
  742. }
  743. }
  744. return YES;
  745. }
  746. /**
  747.  * Attempt to make the new socket.
  748.  * If an error occurs, ignore this event.
  749. **/
  750. - (void)doAcceptWithSocket:(CFSocketNativeHandle)newNative
  751. {
  752. AsyncSocket *newSocket = [[[[self class] alloc] initWithDelegate:theDelegate] autorelease];
  753. // Note: We use [self class] to support subclassing AsyncSocket.
  754. if(newSocket)
  755. {
  756. if ([theDelegate respondsToSelector:@selector(onSocket:didAcceptNewSocket:)])
  757. [theDelegate onSocket:self didAcceptNewSocket:newSocket];
  758. NSRunLoop *runLoop = nil;
  759. if ([theDelegate respondsToSelector:@selector(onSocket:wantsRunLoopForNewSocket:)])
  760. runLoop = [theDelegate onSocket:self wantsRunLoopForNewSocket:newSocket];
  761. BOOL pass = YES;
  762. if(pass && ![newSocket createStreamsFromNative:newNative error:nil]) pass = NO;
  763. if(pass && ![newSocket attachStreamsToRunLoop:runLoop error:nil])    pass = NO;
  764. if(pass && ![newSocket configureStreamsAndReturnError:nil])          pass = NO;
  765. if(pass && ![newSocket openStreamsAndReturnError:nil])               pass = NO;
  766. if(pass)
  767. newSocket->theFlags |= kDidPassConnectMethod;
  768. else {
  769. // No NSError, but errors will still get logged from the above functions.
  770. [newSocket close];
  771. }
  772. }
  773. }
  774. /**
  775.  * Description forthcoming...
  776. **/
  777. - (void)doSocketOpen:(CFSocketRef)sock withCFSocketError:(CFSocketError)socketError
  778. {
  779. NSParameterAssert ((sock == theSocket) || (sock == theSocket6));
  780. if(socketError == kCFSocketTimeout || socketError == kCFSocketError)
  781. {
  782. [self closeWithError:[self getSocketError]];
  783. return;
  784. }
  785. // Get the underlying native (BSD) socket
  786. CFSocketNativeHandle nativeSocket = CFSocketGetNative(sock);
  787. // Setup the socket so that invalidating the socket will not close the native socket
  788. CFSocketSetSocketFlags(sock, 0);
  789. // Invalidate and release the CFSocket - All we need from here on out is the nativeSocket
  790. // Note: If we don't invalidate the socket (leaving the native socket open)
  791. // then theReadStream and theWriteStream won't function properly.
  792. // Specifically, their callbacks won't work, with the exception of kCFStreamEventOpenCompleted.
  793. // I'm not entirely sure why this is, but I'm guessing that events on the socket fire to the CFSocket we created,
  794. // as opposed to the CFReadStream/CFWriteStream.
  795. CFSocketInvalidate(sock);
  796. CFRelease(sock);
  797. theSocket = NULL;
  798. theSocket6 = NULL;
  799. NSError *err;
  800. BOOL pass = YES;
  801. if(pass && ![self createStreamsFromNative:nativeSocket error:&err]) pass = NO;
  802. if(pass && ![self attachStreamsToRunLoop:nil error:&err])           pass = NO;
  803. if(pass && ![self openStreamsAndReturnError:&err])                  pass = NO;
  804. if(!pass)
  805. {
  806. [self closeWithError:err];
  807. }
  808. }
  809. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  810. #pragma mark Stream Implementation:
  811. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  812. /**
  813.  * Creates the CFReadStream and CFWriteStream from the given native socket.
  814.  * The CFSocket may be extracted from either stream after the streams have been opened.
  815.  * 
  816.  * Note: The given native socket must already be connected!
  817. **/
  818. - (BOOL)createStreamsFromNative:(CFSocketNativeHandle)native error:(NSError **)errPtr
  819. {
  820. // Create the socket & streams.
  821. CFStreamCreatePairWithSocket(kCFAllocatorDefault, native, &theReadStream, &theWriteStream);
  822. if (theReadStream == NULL || theWriteStream == NULL)
  823. {
  824. NSError *err = [self getStreamError];
  825. NSLog (@"AsyncSocket %p couldn't create streams from accepted socket: %@", self, err);
  826. if (errPtr) *errPtr = err;
  827. return NO;
  828. }
  829. // Ensure the CF & BSD socket is closed when the streams are closed.
  830. CFReadStreamSetProperty(theReadStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
  831. CFWriteStreamSetProperty(theWriteStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
  832. return YES;
  833. }
  834. /**
  835.  * Creates the CFReadStream and CFWriteStream from the given hostname and port number.
  836.  * The CFSocket may be extracted from either stream after the streams have been opened.
  837. **/
  838. - (BOOL)createStreamsToHost:(NSString *)hostname onPort:(UInt16)port error:(NSError **)errPtr
  839. {
  840. // Create the socket & streams.
  841. CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (CFStringRef)hostname, port, &theReadStream, &theWriteStream);
  842. if (theReadStream == NULL || theWriteStream == NULL)
  843. {
  844. if (errPtr) *errPtr = [self getStreamError];
  845. return NO;
  846. }
  847. // Ensure the CF & BSD socket is closed when the streams are closed.
  848. CFReadStreamSetProperty(theReadStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
  849. CFWriteStreamSetProperty(theWriteStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);
  850. return YES;
  851. }
  852. - (BOOL)attachStreamsToRunLoop:(NSRunLoop *)runLoop error:(NSError **)errPtr
  853. {
  854. // Get the CFRunLoop to which the socket should be attached.
  855. theRunLoop = (runLoop == nil) ? CFRunLoopGetCurrent() : [runLoop getCFRunLoop];
  856. // Make read stream non-blocking.
  857. if (!CFReadStreamSetClient (theReadStream,
  858. kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered | kCFStreamEventOpenCompleted,
  859. (CFReadStreamClientCallBack)&MyCFReadStreamCallback,
  860. (CFStreamClientContext *)(&theContext) ))
  861. {
  862. NSError *err = [self getStreamError];
  863. NSLog (@"AsyncSocket %p couldn't attach read stream to run-loop,", self);
  864. NSLog (@"Error: %@", err);
  865. if (errPtr) *errPtr = err;
  866. return NO;
  867. }
  868. CFReadStreamScheduleWithRunLoop (theReadStream, theRunLoop, kCFRunLoopDefaultMode);
  869. // Make write stream non-blocking.
  870. if (!CFWriteStreamSetClient (theWriteStream,
  871. kCFStreamEventCanAcceptBytes | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered | kCFStreamEventOpenCompleted,
  872. (CFWriteStreamClientCallBack)&MyCFWriteStreamCallback,
  873. (CFStreamClientContext *)(&theContext) ))
  874. {
  875. NSError *err = [self getStreamError];
  876. NSLog (@"AsyncSocket %p couldn't attach write stream to run-loop,", self);
  877. NSLog (@"Error: %@", err);
  878. if (errPtr) *errPtr = err;
  879. return NO;
  880. }
  881. CFWriteStreamScheduleWithRunLoop (theWriteStream, theRunLoop, kCFRunLoopDefaultMode);
  882. return YES;
  883. }
  884. /**
  885.  * Allows the delegate method to configure the CFReadStream and/or CFWriteStream as desired before we connect.
  886.  * Note that the CFSocket and CFNativeSocket will not be available until after the connection is opened.
  887. **/
  888. - (BOOL)configureStreamsAndReturnError:(NSError **)errPtr
  889. {
  890. // Call the delegate method for further configuration.
  891. if([theDelegate respondsToSelector:@selector(onSocketWillConnect:)])
  892. {
  893. if([theDelegate onSocketWillConnect:self] == NO)
  894. {
  895. if (errPtr) *errPtr = [self getAbortError];
  896. return NO;
  897. }
  898. }
  899. return YES;
  900. }
  901. - (BOOL)openStreamsAndReturnError:(NSError **)errPtr
  902. {
  903. BOOL pass = YES;
  904. if(pass && !CFReadStreamOpen (theReadStream))
  905. {
  906. NSLog (@"AsyncSocket %p couldn't open read stream,", self);
  907. pass = NO;
  908. }
  909. if(pass && !CFWriteStreamOpen (theWriteStream))
  910. {
  911. NSLog (@"AsyncSocket %p couldn't open write stream,", self);
  912. pass = NO;
  913. }
  914. if(!pass)
  915. {
  916. if (errPtr) *errPtr = [self getStreamError];
  917. }
  918. return pass;
  919. }
  920. /**
  921.  * Called when read or write streams open.
  922.  * When the socket is connected and both streams are open, consider the AsyncSocket instance to be ready.
  923. **/
  924. - (void)doStreamOpen
  925. {
  926. NSError *err = nil;
  927. if ([self areStreamsConnected] && !(theFlags & kDidCallConnectDeleg))
  928. {
  929. // Get the socket.
  930. if (![self setSocketFromStreamsAndReturnError: &err])
  931. {
  932. NSLog (@"AsyncSocket %p couldn't get socket from streams, %@. Disconnecting.", self, err);
  933. [self closeWithError:err];
  934. return;
  935. }
  936. // Call the delegate.
  937. theFlags |= kDidCallConnectDeleg;
  938. if ([theDelegate respondsToSelector:@selector(onSocket:didConnectToHost:port:)])
  939. {
  940. [theDelegate onSocket:self didConnectToHost:[self connectedHost] port:[self connectedPort]];
  941. }
  942. // Immediately deal with any already-queued requests.
  943. [self maybeDequeueRead];
  944. [self maybeDequeueWrite];
  945. }
  946. }
  947. - (BOOL)setSocketFromStreamsAndReturnError:(NSError **)errPtr
  948. {
  949. // Get the CFSocketNativeHandle from theReadStream
  950. CFSocketNativeHandle native;
  951. CFDataRef nativeProp = CFReadStreamCopyProperty(theReadStream, kCFStreamPropertySocketNativeHandle);
  952. if(nativeProp == NULL)
  953. {
  954. if (errPtr) *errPtr = [self getStreamError];
  955. return NO;
  956. }
  957. CFDataGetBytes(nativeProp, CFRangeMake(0, CFDataGetLength(nativeProp)), (UInt8 *)&native);
  958. CFRelease(nativeProp);
  959. CFSocketRef socket = CFSocketCreateWithNative(kCFAllocatorDefault, native, 0, NULL, NULL);
  960. if(socket == NULL)
  961. {
  962. if (errPtr) *errPtr = [self getSocketError];
  963. return NO;
  964. }
  965. // Determine whether the connection was IPv4 or IPv6
  966. CFDataRef peeraddr = CFSocketCopyPeerAddress(socket);
  967. struct sockaddr *sa = (struct sockaddr *)CFDataGetBytePtr(peeraddr);
  968. if(sa->sa_family == AF_INET)
  969. {
  970. theSocket = socket;
  971. }
  972. else
  973. {
  974. theSocket6 = socket;
  975. }
  976. CFRelease(peeraddr);
  977. return YES;
  978. }
  979. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  980. #pragma mark Disconnect Implementation:
  981. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  982. // Sends error message and disconnects
  983. - (void)closeWithError:(NSError *)err
  984. {
  985. theFlags |= kClosingWithError;
  986. if (theFlags & kDidPassConnectMethod)
  987. {
  988. // Try to salvage what data we can.
  989. [self recoverUnreadData];
  990. // Let the delegate know, so it can try to recover if it likes.
  991. if ([theDelegate respondsToSelector:@selector(onSocket:willDisconnectWithError:)])
  992. {
  993. [theDelegate onSocket:self willDisconnectWithError:err];
  994. }
  995. }
  996. [self close];
  997. }
  998. // Prepare partially read data for recovery.
  999. - (void)recoverUnreadData
  1000. {
  1001. if((theCurrentRead != nil) && (theCurrentRead->bytesDone > 0))
  1002. {
  1003. // We never finished the current read.
  1004. // We need to move its data into the front of the partial read buffer.
  1005. [partialReadBuffer replaceBytesInRange:NSMakeRange(0, 0)
  1006.  withBytes:[theCurrentRead->buffer bytes]
  1007. length:theCurrentRead->bytesDone];
  1008. }
  1009. [self emptyQueues];
  1010. }
  1011. - (void)emptyQueues
  1012. {
  1013. if (theCurrentRead != nil) [self endCurrentRead];
  1014. if (theCurrentWrite != nil) [self endCurrentWrite];
  1015. [theReadQueue removeAllObjects];
  1016. [theWriteQueue removeAllObjects];
  1017. [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(maybeDequeueRead) object:nil];
  1018. [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(maybeDequeueWrite) object:nil];
  1019. }
  1020. // Disconnects. This is called for both error and clean disconnections.
  1021. - (void)close
  1022. {
  1023. // Empty queues.
  1024. [self emptyQueues];
  1025. [partialReadBuffer release];
  1026. partialReadBuffer = nil;
  1027. [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(disconnect) object:nil];
  1028. // Close streams.
  1029. if (theReadStream != NULL)
  1030. {
  1031. CFReadStreamSetClient(theReadStream, kCFStreamEventNone, NULL, NULL);
  1032. CFReadStreamUnscheduleFromRunLoop (theReadStream, theRunLoop, kCFRunLoopDefaultMode);
  1033. CFReadStreamClose (theReadStream);
  1034. CFRelease (theReadStream);
  1035. theReadStream = NULL;
  1036. }
  1037. if (theWriteStream != NULL)
  1038. {
  1039. CFWriteStreamSetClient(theWriteStream, kCFStreamEventNone, NULL, NULL);
  1040. CFWriteStreamUnscheduleFromRunLoop (theWriteStream, theRunLoop, kCFRunLoopDefaultMode);
  1041. CFWriteStreamClose (theWriteStream);
  1042. CFRelease (theWriteStream);
  1043. theWriteStream = NULL;
  1044. }
  1045. // Close sockets.
  1046. if (theSocket != NULL)
  1047. {
  1048. CFSocketInvalidate (theSocket);
  1049. CFRelease (theSocket);
  1050. theSocket = NULL;
  1051. }
  1052. if (theSocket6 != NULL)
  1053. {
  1054. CFSocketInvalidate (theSocket6);
  1055. CFRelease (theSocket6);
  1056. theSocket6 = NULL;
  1057. }
  1058. if (theSource != NULL)
  1059. {
  1060. CFRunLoopRemoveSource (theRunLoop, theSource, kCFRunLoopDefaultMode);
  1061. CFRelease (theSource);
  1062. theSource = NULL;
  1063. }
  1064. if (theSource6 != NULL)
  1065. {
  1066. CFRunLoopRemoveSource (theRunLoop, theSource6, kCFRunLoopDefaultMode);
  1067. CFRelease (theSource6);
  1068. theSource6 = NULL;
  1069. }
  1070. theRunLoop = NULL;
  1071. // If the client has passed the connect/accept method, then the connection has at least begun.
  1072. // Notify delegate that it is now ending.
  1073. if (theFlags & kDidPassConnectMethod)
  1074. {
  1075. // Delay notification to give him freedom to release without returning here and core-dumping.
  1076. if ([theDelegate respondsToSelector: @selector(onSocketDidDisconnect:)])
  1077. {
  1078. [theDelegate performSelector:@selector(onSocketDidDisconnect:) withObject:self afterDelay:0];
  1079. }
  1080. }
  1081. // Clear flags.
  1082. theFlags = 0x00;
  1083. }
  1084. /**
  1085.  * Disconnects immediately. Any pending reads or writes are dropped.
  1086. **/
  1087. - (void)disconnect
  1088. {
  1089. [self close];
  1090. }
  1091. /**
  1092.  * Disconnects after all pending writes have completed.
  1093.  * After calling this, the read and write methods (including "readDataWithTimeout:tag:") will do nothing.
  1094.  * The socket will disconnect even if there are still pending reads.
  1095. **/
  1096. - (void)disconnectAfterWriting
  1097. {
  1098. theFlags |= kForbidReadsWrites;
  1099. theFlags |= kDisconnectSoon;
  1100. [self maybeScheduleDisconnect];
  1101. }
  1102. /**
  1103.  * In the event of an error, this method may be called during onSocket:willDisconnectWithError: to read
  1104.  * any data that's left on the socket.
  1105. **/
  1106. - (NSData *)unreadData
  1107. {
  1108. // Ensure this method will only return data in the event of an error
  1109. if(!(theFlags & kClosingWithError)) return nil;
  1110. if(theReadStream == NULL) return nil;
  1111. CFIndex totalBytesRead = [partialReadBuffer length];
  1112. BOOL error = NO;
  1113. while(!error && CFReadStreamHasBytesAvailable(theReadStream))
  1114. {
  1115. [partialReadBuffer increaseLengthBy:READALL_CHUNKSIZE];
  1116. // Number of bytes to read is space left in packet buffer.
  1117. CFIndex bytesToRead = [partialReadBuffer length] - totalBytesRead;
  1118. // Read data into packet buffer
  1119. UInt8 *packetbuf = (UInt8 *)( [partialReadBuffer mutableBytes] + totalBytesRead );
  1120. CFIndex bytesRead = CFReadStreamRead(theReadStream, packetbuf, bytesToRead);
  1121. // Check results
  1122. if(bytesRead < 0)
  1123. {
  1124. error = YES;
  1125. }
  1126. else
  1127. {
  1128. totalBytesRead += bytesRead;
  1129. }
  1130. }
  1131. [partialReadBuffer setLength:totalBytesRead];
  1132. return partialReadBuffer;
  1133. }
  1134. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1135. #pragma mark Errors
  1136. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1137. /**
  1138.  * Returns a standard error object for the current errno value.
  1139.  * Errno is used for low-level BSD socket errors.
  1140. **/
  1141. - (NSError *)getErrnoError
  1142. {
  1143. NSString *errorMsg = [NSString stringWithUTF8String:strerror(errno)];
  1144. NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errorMsg forKey:NSLocalizedDescriptionKey];
  1145. return [NSError errorWithDomain:NSPOSIXErrorDomain code:errno userInfo:userInfo];
  1146. }
  1147. /**
  1148.  * Returns a standard error message for a CFSocket error.
  1149.  * Unfortunately, CFSocket offers no feedback on its errors.
  1150. **/
  1151. - (NSError *)getSocketError
  1152. {
  1153. NSString *errMsg = NSLocalizedStringWithDefaultValue(@"AsyncSocketCFSocketError",
  1154.  @"AsyncSocket", [NSBundle mainBundle],
  1155.  @"General CFSocket error", nil);
  1156. NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  1157. return [NSError errorWithDomain:AsyncSocketErrorDomain code:AsyncSocketCFSocketError userInfo:info];
  1158. }
  1159. - (NSError *) getStreamError
  1160. {
  1161. CFStreamError err;
  1162. if (theReadStream != NULL)
  1163. {
  1164. err = CFReadStreamGetError (theReadStream);
  1165. if (err.error != 0) return [self errorFromCFStreamError: err];
  1166. }
  1167. if (theWriteStream != NULL)
  1168. {
  1169. err = CFWriteStreamGetError (theWriteStream);
  1170. if (err.error != 0) return [self errorFromCFStreamError: err];
  1171. }
  1172. return nil;
  1173. }
  1174. /**
  1175.  * Returns a standard AsyncSocket abort error.
  1176. **/
  1177. - (NSError *)getAbortError
  1178. {
  1179. NSString *errMsg = NSLocalizedStringWithDefaultValue(@"AsyncSocketCanceledError",
  1180.  @"AsyncSocket", [NSBundle mainBundle],
  1181.  @"Connection canceled", nil);
  1182. NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  1183. return [NSError errorWithDomain:AsyncSocketErrorDomain code:AsyncSocketCanceledError userInfo:info];
  1184. }
  1185. - (NSError *)getReadMaxedOutError
  1186. {
  1187. NSString *errMsg = NSLocalizedStringWithDefaultValue(@"AsyncSocketReadMaxedOutError",
  1188.  @"AsyncSocket", [NSBundle mainBundle],
  1189.  @"Read operation reached set maximum length", nil);
  1190. NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  1191. return [NSError errorWithDomain:AsyncSocketErrorDomain code:AsyncSocketReadMaxedOutError userInfo:info];
  1192. }
  1193. /**
  1194.  * Returns a standard AsyncSocket read timeout error.
  1195. **/
  1196. - (NSError *)getReadTimeoutError
  1197. {
  1198. NSString *errMsg = NSLocalizedStringWithDefaultValue(@"AsyncSocketReadTimeoutError",
  1199.  @"AsyncSocket", [NSBundle mainBundle],
  1200.  @"Read operation timed out", nil);
  1201. NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  1202. return [NSError errorWithDomain:AsyncSocketErrorDomain code:AsyncSocketReadTimeoutError userInfo:info];
  1203. }
  1204. /**
  1205.  * Returns a standard AsyncSocket write timeout error.
  1206. **/
  1207. - (NSError *)getWriteTimeoutError
  1208. {
  1209. NSString *errMsg = NSLocalizedStringWithDefaultValue(@"AsyncSocketWriteTimeoutError",
  1210.  @"AsyncSocket", [NSBundle mainBundle],
  1211.  @"Write operation timed out", nil);
  1212. NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  1213. return [NSError errorWithDomain:AsyncSocketErrorDomain code:AsyncSocketWriteTimeoutError userInfo:info];
  1214. }
  1215. - (NSError *)errorFromCFStreamError:(CFStreamError)err
  1216. {
  1217. if (err.domain == 0 && err.error == 0) return nil;
  1218. // Can't use switch; these constants aren't int literals.
  1219. NSString *domain = @"CFStreamError (unlisted domain)";
  1220. NSString *message = nil;
  1221. if(err.domain == kCFStreamErrorDomainPOSIX) {
  1222. domain = NSPOSIXErrorDomain;
  1223. }
  1224. else if(err.domain == kCFStreamErrorDomainMacOSStatus) {
  1225. domain = NSOSStatusErrorDomain;
  1226. }
  1227. else if(err.domain == kCFStreamErrorDomainMach) {
  1228. domain = NSMachErrorDomain;
  1229. }
  1230. else if(err.domain == kCFStreamErrorDomainNetDB)
  1231. {
  1232. domain = @"kCFStreamErrorDomainNetDB";
  1233. message = [NSString stringWithCString:gai_strerror(err.error) encoding:NSASCIIStringEncoding];
  1234. }
  1235. else if(err.domain == kCFStreamErrorDomainNetServices) {
  1236. domain = @"kCFStreamErrorDomainNetServices";
  1237. }
  1238. else if(err.domain == kCFStreamErrorDomainSOCKS) {
  1239. domain = @"kCFStreamErrorDomainSOCKS";
  1240. }
  1241. else if(err.domain == kCFStreamErrorDomainSystemConfiguration) {
  1242. domain = @"kCFStreamErrorDomainSystemConfiguration";
  1243. }
  1244. else if(err.domain == kCFStreamErrorDomainSSL) {
  1245. domain = @"kCFStreamErrorDomainSSL";
  1246. }
  1247. NSDictionary *info = nil;
  1248. if(message != nil)
  1249. {
  1250. info = [NSDictionary dictionaryWithObject:message forKey:NSLocalizedDescriptionKey];
  1251. }
  1252. return [NSError errorWithDomain:domain code:err.error userInfo:info];
  1253. }
  1254. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1255. #pragma mark Diagnostics
  1256. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1257. - (BOOL)isConnected
  1258. {
  1259. return [self isSocketConnected] && [self areStreamsConnected];
  1260. }
  1261. - (NSString *)connectedHost
  1262. {
  1263. if(theSocket)
  1264. return [self connectedHost:theSocket];
  1265. else
  1266. return [self connectedHost:theSocket6];
  1267. }
  1268. - (UInt16)connectedPort
  1269. {
  1270. if(theSocket)
  1271. return [self connectedPort:theSocket];
  1272. else
  1273. return [self connectedPort:theSocket6];
  1274. }
  1275. - (NSString *)localHost
  1276. {
  1277. if(theSocket)
  1278. return [self localHost:theSocket];
  1279. else
  1280. return [self localHost:theSocket6];
  1281. }
  1282. - (UInt16)localPort
  1283. {
  1284. if(theSocket)
  1285. return [self localPort:theSocket];
  1286. else
  1287. return [self localPort:theSocket6];
  1288. }
  1289. - (NSString *)connectedHost:(CFSocketRef)socket
  1290. {
  1291. if (socket == NULL) return nil;
  1292. CFDataRef peeraddr;
  1293. NSString *peerstr = nil;
  1294. if(socket && (peeraddr = CFSocketCopyPeerAddress(socket)))
  1295. {
  1296. peerstr = [self addressHost:peeraddr];
  1297. CFRelease (peeraddr);
  1298. }
  1299. return peerstr;
  1300. }
  1301. - (UInt16)connectedPort:(CFSocketRef)socket
  1302. {
  1303. if (socket == NULL) return 0;
  1304. CFDataRef peeraddr;
  1305. UInt16 peerport = 0;
  1306. if(socket && (peeraddr = CFSocketCopyPeerAddress(socket)))
  1307. {
  1308. peerport = [self addressPort:peeraddr];
  1309. CFRelease (peeraddr);
  1310. }
  1311. return peerport;
  1312. }
  1313. - (NSString *)localHost:(CFSocketRef)socket
  1314. {
  1315. if (socket == NULL) return nil;
  1316. CFDataRef selfaddr;
  1317. NSString *selfstr = nil;
  1318. if(socket && (selfaddr = CFSocketCopyAddress(socket)))
  1319. {
  1320. selfstr = [self addressHost:selfaddr];
  1321. CFRelease (selfaddr);
  1322. }
  1323. return selfstr;
  1324. }
  1325. - (UInt16)localPort:(CFSocketRef)socket
  1326. {
  1327. if (socket == NULL) return 0;
  1328. CFDataRef selfaddr;
  1329. UInt16 selfport = 0;
  1330. if (socket && (selfaddr = CFSocketCopyAddress(socket)))
  1331. {
  1332. selfport = [self addressPort:selfaddr];
  1333. CFRelease (selfaddr);
  1334. }
  1335. return selfport;
  1336. }
  1337. - (BOOL)isSocketConnected
  1338. {
  1339. if(theSocket != NULL)
  1340. return CFSocketIsValid(theSocket);
  1341. else if(theSocket6 != NULL)
  1342. return CFSocketIsValid(theSocket6);
  1343. else
  1344. return NO;
  1345. }
  1346. - (BOOL)areStreamsConnected
  1347. {
  1348. CFStreamStatus s;
  1349. if (theReadStream != NULL)
  1350. {
  1351. s = CFReadStreamGetStatus (theReadStream);
  1352. if ( !(s == kCFStreamStatusOpen || s == kCFStreamStatusReading || s == kCFStreamStatusError) )
  1353. return NO;
  1354. }
  1355. else return NO;
  1356. if (theWriteStream != NULL)
  1357. {
  1358. s = CFWriteStreamGetStatus (theWriteStream);
  1359. if ( !(s == kCFStreamStatusOpen || s == kCFStreamStatusWriting || s == kCFStreamStatusError) )
  1360. return NO;
  1361. }
  1362. else return NO;
  1363. return YES;
  1364. }
  1365. - (NSString *)addressHost:(CFDataRef)cfaddr
  1366. {
  1367. if (cfaddr == NULL) return nil;
  1368. char addrBuf[ MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN) ];
  1369. struct sockaddr *pSockAddr = (struct sockaddr *) CFDataGetBytePtr (cfaddr);
  1370. struct sockaddr_in  *pSockAddrV4 = (struct sockaddr_in *) pSockAddr;
  1371. struct sockaddr_in6 *pSockAddrV6 = (struct sockaddr_in6 *)pSockAddr;
  1372. const void *pAddr = (pSockAddr->sa_family == AF_INET) ?
  1373. (void *)(&(pSockAddrV4->sin_addr)) :
  1374. (void *)(&(pSockAddrV6->sin6_addr));
  1375. const char *pStr = inet_ntop (pSockAddr->sa_family, pAddr, addrBuf, sizeof(addrBuf));
  1376. if (pStr == NULL) [NSException raise: NSInternalInconsistencyException
  1377.   format: @"Cannot convert address to string."];
  1378. return [NSString stringWithCString:pStr encoding:NSASCIIStringEncoding];
  1379. }
  1380. - (UInt16)addressPort:(CFDataRef)cfaddr
  1381. {
  1382. if (cfaddr == NULL) return 0;
  1383. struct sockaddr_in *pAddr = (struct sockaddr_in *) CFDataGetBytePtr (cfaddr);
  1384. return ntohs (pAddr->sin_port);
  1385. }
  1386. - (BOOL)isIPv4
  1387. {
  1388. return (theSocket != NULL);
  1389. }
  1390. - (BOOL)isIPv6
  1391. {
  1392. return (theSocket6 != NULL);
  1393. }
  1394. - (NSString *)description
  1395. {
  1396. static const char *statstr[] = { "not open", "opening", "open", "reading", "writing", "at end", "closed", "has error" };
  1397. CFStreamStatus rs = (theReadStream != NULL) ? CFReadStreamGetStatus (theReadStream) : 0;
  1398. CFStreamStatus ws = (theWriteStream != NULL) ? CFWriteStreamGetStatus (theWriteStream) : 0;
  1399. NSString *peerstr, *selfstr;
  1400. CFDataRef peeraddr = NULL, peeraddr6 = NULL, selfaddr = NULL, selfaddr6 = NULL;
  1401. if (theSocket || theSocket6)
  1402. {
  1403. if (theSocket)  peeraddr  = CFSocketCopyPeerAddress(theSocket);
  1404. if (theSocket6) peeraddr6 = CFSocketCopyPeerAddress(theSocket6);
  1405. if(theSocket6 && theSocket)
  1406. {
  1407. peerstr = [NSString stringWithFormat: @"%@/%@ %u", [self addressHost:peeraddr], [self addressHost:peeraddr6], [self addressPort:peeraddr]];
  1408. }
  1409. else if(theSocket6)
  1410. {
  1411. peerstr = [NSString stringWithFormat: @"%@ %u", [self addressHost:peeraddr6], [self addressPort:peeraddr6]];
  1412. }
  1413. else
  1414. {
  1415. peerstr = [NSString stringWithFormat: @"%@ %u", [self addressHost:peeraddr], [self addressPort:peeraddr]];
  1416. }
  1417. if(peeraddr)  CFRelease(peeraddr);
  1418. if(peeraddr6) CFRelease(peeraddr6);
  1419. peeraddr = NULL;
  1420. peeraddr6 = NULL;
  1421. }
  1422. else peerstr = @"nowhere";
  1423. if (theSocket || theSocket6)
  1424. {
  1425. if (theSocket)  selfaddr  = CFSocketCopyAddress (theSocket);
  1426. if (theSocket6) selfaddr6 = CFSocketCopyAddress (theSocket6);
  1427. if (theSocket6 && theSocket)
  1428. {
  1429. selfstr = [NSString stringWithFormat: @"%@/%@ %u", [self addressHost:selfaddr], [self addressHost:selfaddr6], [self addressPort:selfaddr]];
  1430. }
  1431. else if (theSocket6)
  1432. {
  1433. selfstr = [NSString stringWithFormat: @"%@ %u", [self addressHost:selfaddr6], [self addressPort:selfaddr6]];
  1434. }
  1435. else
  1436. {
  1437. selfstr = [NSString stringWithFormat: @"%@ %u", [self addressHost:selfaddr], [self addressPort:selfaddr]];
  1438. }
  1439. if(selfaddr)  CFRelease(selfaddr);
  1440. if(selfaddr6) CFRelease(selfaddr6);
  1441. selfaddr = NULL;
  1442. selfaddr6 = NULL;
  1443. }
  1444. else selfstr = @"nowhere";
  1445. NSMutableString *ms = [[NSMutableString alloc] init];
  1446. [ms appendString: [NSString stringWithFormat:@"<AsyncSocket %p", self]];
  1447. [ms appendString: [NSString stringWithFormat:@" local %@ remote %@ ", selfstr, peerstr]];
  1448. [ms appendString: [NSString stringWithFormat:@"has queued %d reads %d writes, ", [theReadQueue count], [theWriteQueue count] ]];
  1449. if (theCurrentRead == nil)
  1450. [ms appendString: @"no current read, "];
  1451. else
  1452. {
  1453. int percentDone;
  1454. if ([theCurrentRead->buffer length] != 0)
  1455. percentDone = (float)theCurrentRead->bytesDone /
  1456.   (float)[theCurrentRead->buffer length] * 100.0;
  1457. else
  1458. percentDone = 100;
  1459. [ms appendString: [NSString stringWithFormat:@"currently read %u bytes (%d%% done), ",
  1460. [theCurrentRead->buffer length],
  1461. theCurrentRead->bytesDone ? percentDone : 0]];
  1462. }
  1463. if (theCurrentWrite == nil)
  1464. [ms appendString: @"no current write, "];
  1465. else
  1466. {
  1467. int percentDone;
  1468. if ([theCurrentWrite->buffer length] != 0)
  1469. percentDone = (float)theCurrentWrite->bytesDone /
  1470.   (float)[theCurrentWrite->buffer length] * 100.0;
  1471. else
  1472. percentDone = 100;
  1473. [ms appendString: [NSString stringWithFormat:@"currently written %u (%d%%), ",
  1474. [theCurrentWrite->buffer length],
  1475. theCurrentWrite->bytesDone ? percentDone : 0]];
  1476. }
  1477. [ms appendString: [NSString stringWithFormat:@"read stream %p %s, write stream %p %s", theReadStream, statstr [rs], theWriteStream, statstr [ws] ]];
  1478. if (theFlags & kDisconnectSoon) [ms appendString: @", will disconnect soon"];
  1479. if (![self isConnected]) [ms appendString: @", not connected"];
  1480. [ms appendString: @">"];
  1481. return [ms autorelease];
  1482. }
  1483. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1484. #pragma mark Reading
  1485. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1486. - (void)readDataToLength:(CFIndex)length withTimeout:(NSTimeInterval)timeout tag:(long)tag;
  1487. {
  1488. if(length == 0) return;
  1489. if(theFlags & kForbidReadsWrites) return;
  1490. NSMutableData *buffer = [[NSMutableData alloc] initWithLength:length];
  1491. AsyncReadPacket *packet = [[AsyncReadPacket alloc] initWithData:buffer
  1492. timeout:timeout
  1493. tag:tag
  1494.    readAllAvailable:NO
  1495.  terminator:nil
  1496.   maxLength:length];
  1497. [theReadQueue addObject:packet];
  1498. [self scheduleDequeueRead];
  1499. [packet release];
  1500. [buffer release];
  1501. }
  1502. - (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag
  1503. {
  1504. [self readDataToData:data withTimeout:timeout maxLength:-1 tag:tag];
  1505. }
  1506. - (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout maxLength:(CFIndex)length tag:(long)tag
  1507. {
  1508. if(data == nil || [data length] == 0) return;
  1509. if(length >= 0 && length < [data length]) return;
  1510. if(theFlags & kForbidReadsWrites) return;
  1511. NSMutableData *buffer = [[NSMutableData alloc] initWithLength:0];
  1512. AsyncReadPacket *packet = [[AsyncReadPacket alloc] initWithData:buffer
  1513. timeout:timeout
  1514. tag:tag 
  1515.    readAllAvailable:NO 
  1516.  terminator:data
  1517.   maxLength:length];
  1518. [theReadQueue addObject:packet];
  1519. [self scheduleDequeueRead];
  1520. [packet release];
  1521. [buffer release];
  1522. }
  1523. - (void)readDataWithTimeout:(NSTimeInterval)timeout tag:(long)tag
  1524. {
  1525. if (theFlags & kForbidReadsWrites) return;
  1526. NSMutableData *buffer = [[NSMutableData alloc] initWithLength:0];
  1527. AsyncReadPacket *packet = [[AsyncReadPacket alloc] initWithData:buffer
  1528. timeout:timeout
  1529. tag:tag
  1530.    readAllAvailable:YES
  1531.  terminator:nil
  1532.   maxLength:-1];
  1533. [theReadQueue addObject:packet];
  1534. [self scheduleDequeueRead];
  1535. [packet release];
  1536. [buffer release];
  1537. }
  1538. /**
  1539.  * Puts a maybeDequeueRead on the run loop. 
  1540.  * An assumption here is that selectors will be performed consecutively within their priority.
  1541. **/
  1542. - (void)scheduleDequeueRead
  1543. {
  1544. [self performSelector:@selector(maybeDequeueRead) withObject:nil afterDelay:0];
  1545. }
  1546. /**
  1547.  * This method starts a new read, if needed.
  1548.  * It is called when a user requests a read,
  1549.  * or when a stream opens that may have requested reads sitting in the queue, etc.
  1550. **/
  1551. - (void)maybeDequeueRead
  1552. {
  1553. // If we're not currently processing a read AND
  1554. // we have read requests sitting in the queue AND we have actually have a read stream
  1555. if(theCurrentRead == nil && [theReadQueue count] != 0 && theReadStream != NULL)
  1556. {
  1557. // Get new current read AsyncReadPacket.
  1558. AsyncReadPacket *newPacket = [theReadQueue objectAtIndex:0];
  1559. theCurrentRead = [newPacket retain];
  1560. [theReadQueue removeObjectAtIndex:0];
  1561. // Start time-out timer.
  1562. if(theCurrentRead->timeout >= 0.0)
  1563. {
  1564. theReadTimer = [NSTimer scheduledTimerWithTimeInterval:theCurrentRead->timeout
  1565. target:self 
  1566.   selector:@selector(doReadTimeout:)
  1567.   userInfo:nil
  1568.    repeats:NO];
  1569. }
  1570. // Immediately read, if possible.
  1571. [self doBytesAvailable];
  1572. }
  1573. }
  1574. /**
  1575.  * Call this method in doBytesAvailable instead of CFReadStreamHasBytesAvailable().
  1576.  * This method supports pre-buffering properly.
  1577. **/
  1578. - (BOOL)hasBytesAvailable
  1579. {
  1580. return ([partialReadBuffer length] > 0) || CFReadStreamHasBytesAvailable(theReadStream);
  1581. }
  1582. /**
  1583.  * Call this method in doBytesAvailable instead of CFReadStreamRead().
  1584.  * This method support pre-buffering properly.
  1585. **/
  1586. - (CFIndex)readIntoBuffer:(UInt8 *)buffer maxLength:(CFIndex)length
  1587. {
  1588. if([partialReadBuffer length] > 0)
  1589. {
  1590. // Determine the maximum amount of data to read
  1591. CFIndex bytesToRead = MIN(length, [partialReadBuffer length]);
  1592. // Copy the bytes from the buffer
  1593. memcpy(buffer, [partialReadBuffer bytes], bytesToRead);
  1594. // Remove the copied bytes from the buffer
  1595. [partialReadBuffer replaceBytesInRange:NSMakeRange(0, bytesToRead) withBytes:NULL length:0];
  1596. return bytesToRead;
  1597. }
  1598. else
  1599. {
  1600. return CFReadStreamRead(theReadStream, buffer, length);
  1601. }
  1602. }
  1603. /**
  1604.  * This method is called when a new read is taken from the read queue or when new data becomes available on the stream.
  1605. **/
  1606. - (void)doBytesAvailable
  1607. {
  1608. // If data is available on the stream, but there is no read request, then we don't need to process the data yet.
  1609. // Also, if there is a read request, but no read stream setup yet, we can't process any data yet.
  1610. if(theCurrentRead != nil && theReadStream != NULL)
  1611. {
  1612. CFIndex totalBytesRead = 0;
  1613. BOOL done = NO;
  1614. BOOL socketError = NO;
  1615. BOOL maxoutError = NO;
  1616. while(!done && !socketError && !maxoutError && [self hasBytesAvailable])
  1617. {
  1618. BOOL didPreBuffer = NO;
  1619. // If reading all available data, make sure there's room in the packet buffer.
  1620. if(theCurrentRead->readAllAvailableData == YES)
  1621. {
  1622. // Make sure there is at least READALL_CHUNKSIZE bytes available.
  1623. // We don't want to increase the buffer any more than this or we'll waste space.
  1624. // With prebuffering it's possible to read in a small chunk on the first read.
  1625. unsigned buffInc = READALL_CHUNKSIZE - ([theCurrentRead->buffer length] - theCurrentRead->bytesDone);
  1626. [theCurrentRead->buffer increaseLengthBy:buffInc];
  1627. }
  1628. // If reading until data, we may only want to read a few bytes.
  1629. // Just enough to ensure we don't go past our term or over our max limit.
  1630. // Unless pre-buffering is enabled, in which case we may want to read in a larger chunk.
  1631. if(theCurrentRead->term != nil)
  1632. {
  1633. // If we already have data pre-buffered, we obviously don't want to pre-buffer it again.
  1634. // So in this case we'll just read as usual.
  1635. if(([partialReadBuffer length] > 0) || !(theFlags & kEnablePreBuffering))
  1636. {
  1637. unsigned maxToRead = [theCurrentRead readLengthForTerm];
  1638. unsigned bufInc = maxToRead - ([theCurrentRead->buffer length] - theCurrentRead->bytesDone);
  1639. [theCurrentRead->buffer increaseLengthBy:bufInc];
  1640. }
  1641. else
  1642. {
  1643. didPreBuffer = YES;
  1644. unsigned maxToRead = [theCurrentRead prebufferReadLengthForTerm];
  1645. unsigned buffInc = maxToRead - ([theCurrentRead->buffer length] - theCurrentRead->bytesDone);
  1646. [theCurrentRead->buffer increaseLengthBy:buffInc];
  1647. }
  1648. }
  1649. // Number of bytes to read is space left in packet buffer.
  1650. CFIndex bytesToRead = [theCurrentRead->buffer length] - theCurrentRead->bytesDone;
  1651. // Read data into packet buffer
  1652. UInt8 *subBuffer = (UInt8 *)([theCurrentRead->buffer mutableBytes] + theCurrentRead->bytesDone);
  1653. CFIndex bytesRead = [self readIntoBuffer:subBuffer maxLength:bytesToRead];
  1654. // Check results
  1655. if(bytesRead < 0)
  1656. {
  1657. socketError = YES;
  1658. }
  1659. else
  1660. {
  1661. // Update total amound read for the current read
  1662. theCurrentRead->bytesDone += bytesRead;
  1663. // Update total amount read in this method invocation
  1664. totalBytesRead += bytesRead;
  1665. }
  1666. // Is packet done?
  1667. if(theCurrentRead->readAllAvailableData != YES)
  1668. {
  1669. if(theCurrentRead->term != nil)
  1670. {
  1671. if(didPreBuffer)
  1672. {
  1673. // Search for the terminating sequence within the big chunk we just read.
  1674. CFIndex overflow = [theCurrentRead searchForTermAfterPreBuffering:bytesRead];
  1675. if(overflow > 0)
  1676. {
  1677. // Copy excess data into partialReadBuffer
  1678. NSMutableData *buffer = theCurrentRead->buffer;
  1679. const void *overflowBuffer = [buffer bytes] + theCurrentRead->bytesDone - overflow;
  1680. [partialReadBuffer appendBytes:overflowBuffer length:overflow];
  1681. // Update the bytesDone variable.
  1682. // Note: The completeCurrentRead method will trim the buffer for us.
  1683. theCurrentRead->bytesDone -= overflow;
  1684. }
  1685. done = (overflow >= 0);
  1686. }
  1687. else
  1688. {
  1689. // Search for the terminating sequence at the end of the buffer
  1690. int termlen = [theCurrentRead->term length];
  1691. if(theCurrentRead->bytesDone >= termlen)
  1692. {
  1693. const void *buf = [theCurrentRead->buffer bytes] + (theCurrentRead->bytesDone - termlen);
  1694. const void *seq = [theCurrentRead->term bytes];
  1695. done = (memcmp (buf, seq, termlen) == 0);
  1696. }
  1697. }
  1698. if(!done && theCurrentRead->maxLength >= 0 && theCurrentRead->bytesDone >= theCurrentRead->maxLength)
  1699. {
  1700. // There's a set maxLength, and we've reached that maxLength without completing the read
  1701. maxoutError = YES;
  1702. }
  1703. }
  1704. else
  1705. {
  1706. // Done when (sized) buffer is full.
  1707. done = ([theCurrentRead->buffer length] == theCurrentRead->bytesDone);
  1708. }
  1709. }
  1710. // else readAllAvailable doesn't end until all readable is read.
  1711. }
  1712. if(theCurrentRead->readAllAvailableData && theCurrentRead->bytesDone > 0)
  1713. done = YES; // Ran out of bytes, so the "read-all-data" type packet is done
  1714. if(done)
  1715. {
  1716. [self completeCurrentRead];
  1717. if (!socketError) [self scheduleDequeueRead];
  1718. }
  1719. else if(theCurrentRead->bytesDone > 0)
  1720. {
  1721. // We're not done with the readToLength or readToData yet, but we have read in some bytes
  1722. if ([theDelegate respondsToSelector:@selector(onSocket:didReadPartialDataOfLength:tag:)])
  1723. {
  1724. [theDelegate onSocket:self didReadPartialDataOfLength:totalBytesRead tag:theCurrentRead->tag];
  1725. }
  1726. }
  1727. if(socketError)
  1728. {
  1729. CFStreamError err = CFReadStreamGetError(theReadStream);
  1730. [self closeWithError:[self errorFromCFStreamError:err]];
  1731. return;
  1732. }
  1733. if(maxoutError)
  1734. {
  1735. [self closeWithError:[self getReadMaxedOutError]];
  1736. return;
  1737. }
  1738. }
  1739. }
  1740. // Ends current read and calls delegate.
  1741. - (void)completeCurrentRead
  1742. {
  1743. NSAssert (theCurrentRead, @"Trying to complete current read when there is no current read.");
  1744. [theCurrentRead->buffer setLength:theCurrentRead->bytesDone];
  1745. if([theDelegate respondsToSelector:@selector(onSocket:didReadData:withTag:)])
  1746. {
  1747. [theDelegate onSocket:self didReadData:theCurrentRead->buffer withTag:theCurrentRead->tag];
  1748. }
  1749. if (theCurrentRead != nil) [self endCurrentRead]; // Caller may have disconnected.
  1750. }
  1751. // Ends current read.
  1752. - (void)endCurrentRead
  1753. {
  1754. NSAssert (theCurrentRead, @"Trying to end current read when there is no current read.");
  1755. [theReadTimer invalidate];
  1756. theReadTimer = nil;
  1757. [theCurrentRead release];
  1758. theCurrentRead = nil;
  1759. }
  1760. - (void)doReadTimeout:(NSTimer *)timer
  1761. {
  1762. if (timer != theReadTimer) return; // Old timer. Ignore it.
  1763. if (theCurrentRead != nil)
  1764. {
  1765. [self endCurrentRead];
  1766. }
  1767. [self closeWithError:[self getReadTimeoutError]];
  1768. }
  1769. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1770. #pragma mark Writing
  1771. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1772. - (void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag;
  1773. {
  1774. if (data == nil || [data length] == 0) return;
  1775. if (theFlags & kForbidReadsWrites) return;
  1776. AsyncWritePacket *packet = [[AsyncWritePacket alloc] initWithData:data timeout:timeout tag:tag];
  1777. [theWriteQueue addObject:packet];
  1778. [self scheduleDequeueWrite];
  1779. [packet release];
  1780. }
  1781. - (void)scheduleDequeueWrite
  1782. {
  1783. [self performSelector:@selector(maybeDequeueWrite) withObject:nil afterDelay:0];
  1784. }
  1785. // Start a new write.
  1786. - (void)maybeDequeueWrite
  1787. {
  1788. if (theCurrentWrite == nil && [theWriteQueue count] != 0 && theWriteStream != NULL)
  1789. {
  1790. // Get new current write AsyncWritePacket.
  1791. AsyncWritePacket *newPacket = [theWriteQueue objectAtIndex:0];
  1792. theCurrentWrite = [newPacket retain];
  1793. [theWriteQueue removeObjectAtIndex:0];
  1794. // Start time-out timer.
  1795. if (theCurrentWrite->timeout >= 0.0)
  1796. {
  1797. theWriteTimer = [NSTimer scheduledTimerWithTimeInterval:theCurrentWrite->timeout
  1798.                                                  target:self
  1799.                                                selector:@selector(doWriteTimeout:)
  1800.                                                userInfo:nil
  1801.                                                 repeats:NO];
  1802. }
  1803. // Immediately write, if possible.
  1804. [self doSendBytes];
  1805. }
  1806. }
  1807. - (void)doSendBytes
  1808. {
  1809. if (theCurrentWrite != nil && theWriteStream != NULL)
  1810. {
  1811. BOOL done = NO, error = NO;
  1812. while (!done && !error && CFWriteStreamCanAcceptBytes (theWriteStream))
  1813. {
  1814. // Figure out what to write.
  1815. CFIndex bytesRemaining = [theCurrentWrite->buffer length] - theCurrentWrite->bytesDone;
  1816. CFIndex bytesToWrite = (bytesRemaining < WRITE_CHUNKSIZE) ? bytesRemaining : WRITE_CHUNKSIZE;
  1817. UInt8 *writestart = (UInt8 *)([theCurrentWrite->buffer bytes] + theCurrentWrite->bytesDone);
  1818. // Write.
  1819. CFIndex bytesWritten = CFWriteStreamWrite (theWriteStream, writestart, bytesToWrite);
  1820. // Check results.
  1821. if (bytesWritten < 0)
  1822. {
  1823. bytesWritten = 0;
  1824. error = YES;
  1825. }
  1826. // Is packet done?
  1827. theCurrentWrite->bytesDone += bytesWritten;
  1828. done = ([theCurrentWrite->buffer length] == theCurrentWrite->bytesDone);
  1829. }
  1830. if(done)
  1831. {
  1832. [self completeCurrentWrite];
  1833. if (!error) [self scheduleDequeueWrite];
  1834. }
  1835. if(error)
  1836. {
  1837. CFStreamError err = CFWriteStreamGetError (theWriteStream);
  1838. [self closeWithError: [self errorFromCFStreamError:err]];
  1839. return;
  1840. }
  1841. }
  1842. }
  1843. // Ends current write and calls delegate.
  1844. - (void)completeCurrentWrite
  1845. {
  1846. NSAssert (theCurrentWrite, @"Trying to complete current write when there is no current write.");
  1847. if ([theDelegate respondsToSelector:@selector(onSocket:didWriteDataWithTag:)])
  1848. {
  1849. [theDelegate onSocket:self didWriteDataWithTag:theCurrentWrite->tag];
  1850. }
  1851. if (theCurrentWrite != nil) [self endCurrentWrite]; // Caller may have disconnected.
  1852. }
  1853. // Ends current write.
  1854. - (void)endCurrentWrite
  1855. {
  1856. NSAssert (theCurrentWrite, @"Trying to complete current write when there is no current write.");
  1857. [theWriteTimer invalidate];
  1858. theWriteTimer = nil;
  1859. [theCurrentWrite release];
  1860. theCurrentWrite = nil;
  1861. [self maybeScheduleDisconnect];
  1862. }
  1863. // Checks to see if all writes have been completed for disconnectAfterWriting.
  1864. - (void)maybeScheduleDisconnect
  1865. {
  1866. if(theFlags & kDisconnectSoon)
  1867. {
  1868. if(([theWriteQueue count] == 0) && (theCurrentWrite == nil))
  1869. {
  1870. [self performSelector:@selector(disconnect) withObject:nil afterDelay:0];
  1871. }
  1872. }
  1873. }
  1874. - (void)doWriteTimeout:(NSTimer *)timer
  1875. {
  1876. if (timer != theWriteTimer) return; // Old timer. Ignore it.
  1877. if (theCurrentWrite != nil)
  1878. {
  1879. [self endCurrentWrite];
  1880. }
  1881. [self closeWithError:[self getWriteTimeoutError]];
  1882. }
  1883. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1884. #pragma mark CF Callbacks
  1885. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1886. - (void)doCFSocketCallback:(CFSocketCallBackType)type
  1887.  forSocket:(CFSocketRef)sock
  1888.    withAddress:(NSData *)address
  1889.   withData:(const void *)pData
  1890. {
  1891. NSParameterAssert ((sock == theSocket) || (sock == theSocket6));
  1892. switch (type)
  1893. {
  1894. case kCFSocketConnectCallBack:
  1895. // The data argument is either NULL or a pointer to an SInt32 error code, if the connect failed.
  1896. if(pData)
  1897. [self doSocketOpen:sock withCFSocketError:kCFSocketError];
  1898. else
  1899. [self doSocketOpen:sock withCFSocketError:kCFSocketSuccess];
  1900. break;
  1901. case kCFSocketAcceptCallBack:
  1902. [self doAcceptWithSocket: *((CFSocketNativeHandle *)pData)];
  1903. break;
  1904. default:
  1905. NSLog (@"AsyncSocket %p received unexpected CFSocketCallBackType %d.", self, type);
  1906. break;
  1907. }
  1908. }
  1909. - (void)doCFReadStreamCallback:(CFStreamEventType)type forStream:(CFReadStreamRef)stream
  1910. {
  1911. NSParameterAssert(theReadStream != NULL);
  1912. CFStreamError err;
  1913. switch (type)
  1914. {
  1915. case kCFStreamEventOpenCompleted:
  1916. [self doStreamOpen];
  1917. break;
  1918. case kCFStreamEventHasBytesAvailable:
  1919. [self doBytesAvailable];
  1920. break;
  1921. case kCFStreamEventErrorOccurred:
  1922. case kCFStreamEventEndEncountered:
  1923. err = CFReadStreamGetError (theReadStream);
  1924. [self closeWithError: [self errorFromCFStreamError:err]];
  1925. break;
  1926. default:
  1927. NSLog (@"AsyncSocket %p received unexpected CFReadStream callback, CFStreamEventType %d.", self, type);
  1928. }
  1929. }
  1930. - (void)doCFWriteStreamCallback:(CFStreamEventType)type forStream:(CFWriteStreamRef)stream
  1931. {
  1932. NSParameterAssert(theWriteStream != NULL);
  1933. CFStreamError err;
  1934. switch (type)
  1935. {
  1936. case kCFStreamEventOpenCompleted:
  1937. [self doStreamOpen];
  1938. break;
  1939. case kCFStreamEventCanAcceptBytes:
  1940. [self doSendBytes];
  1941. break;
  1942. case kCFStreamEventErrorOccurred:
  1943. case kCFStreamEventEndEncountered:
  1944. err = CFWriteStreamGetError (theWriteStream);
  1945. [self closeWithError: [self errorFromCFStreamError:err]];
  1946. break;
  1947. default:
  1948. NSLog (@"AsyncSocket %p received unexpected CFWriteStream callback, CFStreamEventType %d.", self, type);
  1949. }
  1950. }
  1951. /**
  1952.  * This is the callback we setup for CFSocket.
  1953.  * This method does nothing but forward the call to it's Objective-C counterpart
  1954. **/
  1955. static void MyCFSocketCallback (CFSocketRef sref, CFSocketCallBackType type, CFDataRef address, const void *pData, void *pInfo)
  1956. {
  1957. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  1958. AsyncSocket *socket = [[(AsyncSocket *)pInfo retain] autorelease];
  1959. [socket doCFSocketCallback:type forSocket:sref withAddress:(NSData *)address withData:pData];
  1960. [pool release];
  1961. }
  1962. /**
  1963.  * This is the callback we setup for CFReadStream.
  1964.  * This method does nothing but forward the call to it's Objective-C counterpart
  1965. **/
  1966. static void MyCFReadStreamCallback (CFReadStreamRef stream, CFStreamEventType type, void *pInfo)
  1967. {
  1968. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  1969. AsyncSocket *socket = [[(AsyncSocket *)pInfo retain] autorelease];
  1970. [socket doCFReadStreamCallback:type forStream:stream];
  1971. [pool release];
  1972. }
  1973. /**
  1974.  * This is the callback we setup for CFWriteStream.
  1975.  * This method does nothing but forward the call to it's Objective-C counterpart
  1976. **/
  1977. static void MyCFWriteStreamCallback (CFWriteStreamRef stream, CFStreamEventType type, void *pInfo)
  1978. {
  1979. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  1980. AsyncSocket *socket = [[(AsyncSocket *)pInfo retain] autorelease];
  1981. [socket doCFWriteStreamCallback:type forStream:stream];
  1982. [pool release];
  1983. }
  1984. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1985. #pragma mark Class Methods
  1986. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1987. // Return line separators.
  1988. + (NSData *)CRLFData
  1989. {
  1990. return [NSData dataWithBytes:"x0Dx0A" length:2];
  1991. }
  1992. + (NSData *)CRData
  1993. {
  1994. return [NSData dataWithBytes:"x0D" length:1];
  1995. }
  1996. + (NSData *)LFData
  1997. {
  1998. return [NSData dataWithBytes:"x0A" length:1];
  1999. }
  2000. + (NSData *)ZeroData
  2001. {
  2002. return [NSData dataWithBytes:"" length:1];
  2003. }
  2004. @end