PageRenderTime 85ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/XMPP_Demo/Vendor/CocoaAsyncSocket/GCDAsyncSocket.m

https://gitlab.com/praveenvelanati/ios-demo
Objective C | 1831 lines | 1167 code | 374 blank | 290 comment | 179 complexity | 0418b5a0b2948063390508a53aac44e4 MD5 | raw file
  1. //
  2. // GCDAsyncSocket.m
  3. //
  4. // This class is in the public domain.
  5. // Originally created by Robbie Hanson in Q4 2010.
  6. // Updated and maintained by Deusty LLC and the Apple development community.
  7. //
  8. // https://github.com/robbiehanson/CocoaAsyncSocket
  9. //
  10. #import "GCDAsyncSocket.h"
  11. #if TARGET_OS_IPHONE
  12. #import <CFNetwork/CFNetwork.h>
  13. #endif
  14. #import <arpa/inet.h>
  15. #import <fcntl.h>
  16. #import <ifaddrs.h>
  17. #import <netdb.h>
  18. #import <netinet/in.h>
  19. #import <net/if.h>
  20. #import <sys/socket.h>
  21. #import <sys/types.h>
  22. #import <sys/ioctl.h>
  23. #import <sys/poll.h>
  24. #import <sys/uio.h>
  25. #import <unistd.h>
  26. #if ! __has_feature(objc_arc)
  27. #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
  28. // For more information see: https://github.com/robbiehanson/CocoaAsyncSocket/wiki/ARC
  29. #endif
  30. /**
  31. * Does ARC support support GCD objects?
  32. * It does if the minimum deployment target is iOS 6+ or Mac OS X 10.8+
  33. **/
  34. #if TARGET_OS_IPHONE
  35. // Compiling for iOS
  36. #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 60000 // iOS 6.0 or later
  37. #define NEEDS_DISPATCH_RETAIN_RELEASE 0
  38. #else // iOS 5.X or earlier
  39. #define NEEDS_DISPATCH_RETAIN_RELEASE 1
  40. #endif
  41. #else
  42. // Compiling for Mac OS X
  43. #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 // Mac OS X 10.8 or later
  44. #define NEEDS_DISPATCH_RETAIN_RELEASE 0
  45. #else
  46. #define NEEDS_DISPATCH_RETAIN_RELEASE 1 // Mac OS X 10.7 or earlier
  47. #endif
  48. #endif
  49. #if 0
  50. // Logging Enabled - See log level below
  51. // Logging uses the CocoaLumberjack framework (which is also GCD based).
  52. // https://github.com/robbiehanson/CocoaLumberjack
  53. //
  54. // It allows us to do a lot of logging without significantly slowing down the code.
  55. #import "DDLog.h"
  56. #define LogAsync YES
  57. #define LogContext 65535
  58. #define LogObjc(flg, frmt, ...) LOG_OBJC_MAYBE(LogAsync, logLevel, flg, LogContext, frmt, ##__VA_ARGS__)
  59. #define LogC(flg, frmt, ...) LOG_C_MAYBE(LogAsync, logLevel, flg, LogContext, frmt, ##__VA_ARGS__)
  60. #define LogError(frmt, ...) LogObjc(LOG_FLAG_ERROR, (@"%@: " frmt), THIS_FILE, ##__VA_ARGS__)
  61. #define LogWarn(frmt, ...) LogObjc(LOG_FLAG_WARN, (@"%@: " frmt), THIS_FILE, ##__VA_ARGS__)
  62. #define LogInfo(frmt, ...) LogObjc(LOG_FLAG_INFO, (@"%@: " frmt), THIS_FILE, ##__VA_ARGS__)
  63. #define LogVerbose(frmt, ...) LogObjc(LOG_FLAG_VERBOSE, (@"%@: " frmt), THIS_FILE, ##__VA_ARGS__)
  64. #define LogCError(frmt, ...) LogC(LOG_FLAG_ERROR, (@"%@: " frmt), THIS_FILE, ##__VA_ARGS__)
  65. #define LogCWarn(frmt, ...) LogC(LOG_FLAG_WARN, (@"%@: " frmt), THIS_FILE, ##__VA_ARGS__)
  66. #define LogCInfo(frmt, ...) LogC(LOG_FLAG_INFO, (@"%@: " frmt), THIS_FILE, ##__VA_ARGS__)
  67. #define LogCVerbose(frmt, ...) LogC(LOG_FLAG_VERBOSE, (@"%@: " frmt), THIS_FILE, ##__VA_ARGS__)
  68. #define LogTrace() LogObjc(LOG_FLAG_VERBOSE, @"%@: %@", THIS_FILE, THIS_METHOD)
  69. #define LogCTrace() LogC(LOG_FLAG_VERBOSE, @"%@: %s", THIS_FILE, __FUNCTION__)
  70. // Log levels : off, error, warn, info, verbose
  71. static const int logLevel = LOG_LEVEL_VERBOSE;
  72. #else
  73. // Logging Disabled
  74. #define LogError(frmt, ...) {}
  75. #define LogWarn(frmt, ...) {}
  76. #define LogInfo(frmt, ...) {}
  77. #define LogVerbose(frmt, ...) {}
  78. #define LogCError(frmt, ...) {}
  79. #define LogCWarn(frmt, ...) {}
  80. #define LogCInfo(frmt, ...) {}
  81. #define LogCVerbose(frmt, ...) {}
  82. #define LogTrace() {}
  83. #define LogCTrace(frmt, ...) {}
  84. #endif
  85. /**
  86. * Seeing a return statements within an inner block
  87. * can sometimes be mistaken for a return point of the enclosing method.
  88. * This makes inline blocks a bit easier to read.
  89. **/
  90. #define return_from_block return
  91. /**
  92. * A socket file descriptor is really just an integer.
  93. * It represents the index of the socket within the kernel.
  94. * This makes invalid file descriptor comparisons easier to read.
  95. **/
  96. #define SOCKET_NULL -1
  97. NSString *const GCDAsyncSocketException = @"GCDAsyncSocketException";
  98. NSString *const GCDAsyncSocketErrorDomain = @"GCDAsyncSocketErrorDomain";
  99. NSString *const GCDAsyncSocketQueueName = @"GCDAsyncSocket";
  100. NSString *const GCDAsyncSocketThreadName = @"GCDAsyncSocket-CFStream";
  101. #if SECURE_TRANSPORT_MAYBE_AVAILABLE
  102. NSString *const GCDAsyncSocketSSLCipherSuites = @"GCDAsyncSocketSSLCipherSuites";
  103. #if TARGET_OS_IPHONE
  104. NSString *const GCDAsyncSocketSSLProtocolVersionMin = @"GCDAsyncSocketSSLProtocolVersionMin";
  105. NSString *const GCDAsyncSocketSSLProtocolVersionMax = @"GCDAsyncSocketSSLProtocolVersionMax";
  106. #else
  107. NSString *const GCDAsyncSocketSSLDiffieHellmanParameters = @"GCDAsyncSocketSSLDiffieHellmanParameters";
  108. #endif
  109. #endif
  110. enum GCDAsyncSocketFlags
  111. {
  112. kSocketStarted = 1 << 0, // If set, socket has been started (accepting/connecting)
  113. kConnected = 1 << 1, // If set, the socket is connected
  114. kForbidReadsWrites = 1 << 2, // If set, no new reads or writes are allowed
  115. kReadsPaused = 1 << 3, // If set, reads are paused due to possible timeout
  116. kWritesPaused = 1 << 4, // If set, writes are paused due to possible timeout
  117. kDisconnectAfterReads = 1 << 5, // If set, disconnect after no more reads are queued
  118. kDisconnectAfterWrites = 1 << 6, // If set, disconnect after no more writes are queued
  119. kSocketCanAcceptBytes = 1 << 7, // If set, we know socket can accept bytes. If unset, it's unknown.
  120. kReadSourceSuspended = 1 << 8, // If set, the read source is suspended
  121. kWriteSourceSuspended = 1 << 9, // If set, the write source is suspended
  122. kQueuedTLS = 1 << 10, // If set, we've queued an upgrade to TLS
  123. kStartingReadTLS = 1 << 11, // If set, we're waiting for TLS negotiation to complete
  124. kStartingWriteTLS = 1 << 12, // If set, we're waiting for TLS negotiation to complete
  125. kSocketSecure = 1 << 13, // If set, socket is using secure communication via SSL/TLS
  126. kSocketHasReadEOF = 1 << 14, // If set, we have read EOF from socket
  127. kReadStreamClosed = 1 << 15, // If set, we've read EOF plus prebuffer has been drained
  128. #if TARGET_OS_IPHONE
  129. kAddedStreamsToRunLoop = 1 << 16, // If set, CFStreams have been added to listener thread
  130. kUsingCFStreamForTLS = 1 << 17, // If set, we're forced to use CFStream instead of SecureTransport
  131. kSecureSocketHasBytesAvailable = 1 << 18, // If set, CFReadStream has notified us of bytes available
  132. #endif
  133. };
  134. enum GCDAsyncSocketConfig
  135. {
  136. kIPv4Disabled = 1 << 0, // If set, IPv4 is disabled
  137. kIPv6Disabled = 1 << 1, // If set, IPv6 is disabled
  138. kPreferIPv6 = 1 << 2, // If set, IPv6 is preferred over IPv4
  139. kAllowHalfDuplexConnection = 1 << 3, // If set, the socket will stay open even if the read stream closes
  140. };
  141. #if TARGET_OS_IPHONE
  142. static NSThread *cfstreamThread; // Used for CFStreams
  143. #endif
  144. @interface GCDAsyncSocket (Private)
  145. // Accepting
  146. - (BOOL)doAccept:(int)socketFD;
  147. // Connecting
  148. - (void)startConnectTimeout:(NSTimeInterval)timeout;
  149. - (void)endConnectTimeout;
  150. - (void)doConnectTimeout;
  151. - (void)lookup:(int)aConnectIndex host:(NSString *)host port:(uint16_t)port;
  152. - (void)lookup:(int)aConnectIndex didSucceedWithAddress4:(NSData *)address4 address6:(NSData *)address6;
  153. - (void)lookup:(int)aConnectIndex didFail:(NSError *)error;
  154. - (BOOL)connectWithAddress4:(NSData *)address4 address6:(NSData *)address6 error:(NSError **)errPtr;
  155. - (void)didConnect:(int)aConnectIndex;
  156. - (void)didNotConnect:(int)aConnectIndex error:(NSError *)error;
  157. // Disconnect
  158. - (void)closeWithError:(NSError *)error;
  159. - (void)close;
  160. - (void)maybeClose;
  161. // Errors
  162. - (NSError *)badConfigError:(NSString *)msg;
  163. - (NSError *)badParamError:(NSString *)msg;
  164. - (NSError *)gaiError:(int)gai_error;
  165. - (NSError *)errnoError;
  166. - (NSError *)errnoErrorWithReason:(NSString *)reason;
  167. - (NSError *)connectTimeoutError;
  168. - (NSError *)otherError:(NSString *)msg;
  169. // Diagnostics
  170. - (NSString *)connectedHost4;
  171. - (NSString *)connectedHost6;
  172. - (uint16_t)connectedPort4;
  173. - (uint16_t)connectedPort6;
  174. - (NSString *)localHost4;
  175. - (NSString *)localHost6;
  176. - (uint16_t)localPort4;
  177. - (uint16_t)localPort6;
  178. - (NSString *)connectedHostFromSocket4:(int)socketFD;
  179. - (NSString *)connectedHostFromSocket6:(int)socketFD;
  180. - (uint16_t)connectedPortFromSocket4:(int)socketFD;
  181. - (uint16_t)connectedPortFromSocket6:(int)socketFD;
  182. - (NSString *)localHostFromSocket4:(int)socketFD;
  183. - (NSString *)localHostFromSocket6:(int)socketFD;
  184. - (uint16_t)localPortFromSocket4:(int)socketFD;
  185. - (uint16_t)localPortFromSocket6:(int)socketFD;
  186. // Utilities
  187. - (void)getInterfaceAddress4:(NSMutableData **)addr4Ptr
  188. address6:(NSMutableData **)addr6Ptr
  189. fromDescription:(NSString *)interfaceDescription
  190. port:(uint16_t)port;
  191. - (void)setupReadAndWriteSourcesForNewlyConnectedSocket:(int)socketFD;
  192. - (void)suspendReadSource;
  193. - (void)resumeReadSource;
  194. - (void)suspendWriteSource;
  195. - (void)resumeWriteSource;
  196. // Reading
  197. - (void)maybeDequeueRead;
  198. - (void)flushSSLBuffers;
  199. - (void)doReadData;
  200. - (void)doReadEOF;
  201. - (void)completeCurrentRead;
  202. - (void)endCurrentRead;
  203. - (void)setupReadTimerWithTimeout:(NSTimeInterval)timeout;
  204. - (void)doReadTimeout;
  205. - (void)doReadTimeoutWithExtension:(NSTimeInterval)timeoutExtension;
  206. // Writing
  207. - (void)maybeDequeueWrite;
  208. - (void)doWriteData;
  209. - (void)completeCurrentWrite;
  210. - (void)endCurrentWrite;
  211. - (void)setupWriteTimerWithTimeout:(NSTimeInterval)timeout;
  212. - (void)doWriteTimeout;
  213. - (void)doWriteTimeoutWithExtension:(NSTimeInterval)timeoutExtension;
  214. // Security
  215. - (void)maybeStartTLS;
  216. #if SECURE_TRANSPORT_MAYBE_AVAILABLE
  217. - (void)ssl_startTLS;
  218. - (void)ssl_continueSSLHandshake;
  219. #endif
  220. #if TARGET_OS_IPHONE
  221. - (void)cf_startTLS;
  222. #endif
  223. // CFStream
  224. #if TARGET_OS_IPHONE
  225. + (void)startCFStreamThreadIfNeeded;
  226. - (BOOL)createReadAndWriteStream;
  227. - (BOOL)registerForStreamCallbacksIncludingReadWrite:(BOOL)includeReadWrite;
  228. - (BOOL)addStreamsToRunLoop;
  229. - (BOOL)openStreams;
  230. - (void)removeStreamsFromRunLoop;
  231. #endif
  232. // Class Methods
  233. + (NSString *)hostFromSockaddr4:(const struct sockaddr_in *)pSockaddr4;
  234. + (NSString *)hostFromSockaddr6:(const struct sockaddr_in6 *)pSockaddr6;
  235. + (uint16_t)portFromSockaddr4:(const struct sockaddr_in *)pSockaddr4;
  236. + (uint16_t)portFromSockaddr6:(const struct sockaddr_in6 *)pSockaddr6;
  237. @end
  238. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  239. #pragma mark -
  240. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  241. /**
  242. * A PreBuffer is used when there is more data available on the socket
  243. * than is being requested by current read request.
  244. * In this case we slurp up all data from the socket (to minimize sys calls),
  245. * and store additional yet unread data in a "prebuffer".
  246. *
  247. * The prebuffer is entirely drained before we read from the socket again.
  248. * In other words, a large chunk of data is written is written to the prebuffer.
  249. * The prebuffer is then drained via a series of one or more reads (for subsequent read request(s)).
  250. *
  251. * A ring buffer was once used for this purpose.
  252. * But a ring buffer takes up twice as much memory as needed (double the size for mirroring).
  253. * In fact, it generally takes up more than twice the needed size as everything has to be rounded up to vm_page_size.
  254. * And since the prebuffer is always completely drained after being written to, a full ring buffer isn't needed.
  255. *
  256. * The current design is very simple and straight-forward, while also keeping memory requirements lower.
  257. **/
  258. @interface GCDAsyncSocketPreBuffer : NSObject
  259. {
  260. uint8_t *preBuffer;
  261. size_t preBufferSize;
  262. uint8_t *readPointer;
  263. uint8_t *writePointer;
  264. }
  265. - (id)initWithCapacity:(size_t)numBytes;
  266. - (void)ensureCapacityForWrite:(size_t)numBytes;
  267. - (size_t)availableBytes;
  268. - (uint8_t *)readBuffer;
  269. - (void)getReadBuffer:(uint8_t **)bufferPtr availableBytes:(size_t *)availableBytesPtr;
  270. - (size_t)availableSpace;
  271. - (uint8_t *)writeBuffer;
  272. - (void)getWriteBuffer:(uint8_t **)bufferPtr availableSpace:(size_t *)availableSpacePtr;
  273. - (void)didRead:(size_t)bytesRead;
  274. - (void)didWrite:(size_t)bytesWritten;
  275. - (void)reset;
  276. @end
  277. @implementation GCDAsyncSocketPreBuffer
  278. - (id)initWithCapacity:(size_t)numBytes
  279. {
  280. if ((self = [super init]))
  281. {
  282. preBufferSize = numBytes;
  283. preBuffer = malloc(preBufferSize);
  284. readPointer = preBuffer;
  285. writePointer = preBuffer;
  286. }
  287. return self;
  288. }
  289. - (void)dealloc
  290. {
  291. if (preBuffer)
  292. free(preBuffer);
  293. }
  294. - (void)ensureCapacityForWrite:(size_t)numBytes
  295. {
  296. size_t availableSpace = preBufferSize - (writePointer - readPointer);
  297. if (numBytes > availableSpace)
  298. {
  299. size_t additionalBytes = numBytes - availableSpace;
  300. size_t newPreBufferSize = preBufferSize + additionalBytes;
  301. uint8_t *newPreBuffer = realloc(preBuffer, newPreBufferSize);
  302. size_t readPointerOffset = readPointer - preBuffer;
  303. size_t writePointerOffset = writePointer - preBuffer;
  304. preBuffer = newPreBuffer;
  305. preBufferSize = newPreBufferSize;
  306. readPointer = preBuffer + readPointerOffset;
  307. writePointer = preBuffer + writePointerOffset;
  308. }
  309. }
  310. - (size_t)availableBytes
  311. {
  312. return writePointer - readPointer;
  313. }
  314. - (uint8_t *)readBuffer
  315. {
  316. return readPointer;
  317. }
  318. - (void)getReadBuffer:(uint8_t **)bufferPtr availableBytes:(size_t *)availableBytesPtr
  319. {
  320. if (bufferPtr) *bufferPtr = readPointer;
  321. if (availableBytesPtr) *availableBytesPtr = writePointer - readPointer;
  322. }
  323. - (void)didRead:(size_t)bytesRead
  324. {
  325. readPointer += bytesRead;
  326. if (readPointer == writePointer)
  327. {
  328. // The prebuffer has been drained. Reset pointers.
  329. readPointer = preBuffer;
  330. writePointer = preBuffer;
  331. }
  332. }
  333. - (size_t)availableSpace
  334. {
  335. return preBufferSize - (writePointer - readPointer);
  336. }
  337. - (uint8_t *)writeBuffer
  338. {
  339. return writePointer;
  340. }
  341. - (void)getWriteBuffer:(uint8_t **)bufferPtr availableSpace:(size_t *)availableSpacePtr
  342. {
  343. if (bufferPtr) *bufferPtr = writePointer;
  344. if (availableSpacePtr) *availableSpacePtr = preBufferSize - (writePointer - readPointer);
  345. }
  346. - (void)didWrite:(size_t)bytesWritten
  347. {
  348. writePointer += bytesWritten;
  349. }
  350. - (void)reset
  351. {
  352. readPointer = preBuffer;
  353. writePointer = preBuffer;
  354. }
  355. @end
  356. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  357. #pragma mark -
  358. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  359. /**
  360. * The GCDAsyncReadPacket encompasses the instructions for any given read.
  361. * The content of a read packet allows the code to determine if we're:
  362. * - reading to a certain length
  363. * - reading to a certain separator
  364. * - or simply reading the first chunk of available data
  365. **/
  366. @interface GCDAsyncReadPacket : NSObject
  367. {
  368. @public
  369. NSMutableData *buffer;
  370. NSUInteger startOffset;
  371. NSUInteger bytesDone;
  372. NSUInteger maxLength;
  373. NSTimeInterval timeout;
  374. NSUInteger readLength;
  375. NSData *term;
  376. BOOL bufferOwner;
  377. NSUInteger originalBufferLength;
  378. long tag;
  379. }
  380. - (id)initWithData:(NSMutableData *)d
  381. startOffset:(NSUInteger)s
  382. maxLength:(NSUInteger)m
  383. timeout:(NSTimeInterval)t
  384. readLength:(NSUInteger)l
  385. terminator:(NSData *)e
  386. tag:(long)i;
  387. - (void)ensureCapacityForAdditionalDataOfLength:(NSUInteger)bytesToRead;
  388. - (NSUInteger)optimalReadLengthWithDefault:(NSUInteger)defaultValue shouldPreBuffer:(BOOL *)shouldPreBufferPtr;
  389. - (NSUInteger)readLengthForNonTermWithHint:(NSUInteger)bytesAvailable;
  390. - (NSUInteger)readLengthForTermWithHint:(NSUInteger)bytesAvailable shouldPreBuffer:(BOOL *)shouldPreBufferPtr;
  391. - (NSUInteger)readLengthForTermWithPreBuffer:(GCDAsyncSocketPreBuffer *)preBuffer found:(BOOL *)foundPtr;
  392. - (NSInteger)searchForTermAfterPreBuffering:(ssize_t)numBytes;
  393. @end
  394. @implementation GCDAsyncReadPacket
  395. - (id)initWithData:(NSMutableData *)d
  396. startOffset:(NSUInteger)s
  397. maxLength:(NSUInteger)m
  398. timeout:(NSTimeInterval)t
  399. readLength:(NSUInteger)l
  400. terminator:(NSData *)e
  401. tag:(long)i
  402. {
  403. if((self = [super init]))
  404. {
  405. bytesDone = 0;
  406. maxLength = m;
  407. timeout = t;
  408. readLength = l;
  409. term = [e copy];
  410. tag = i;
  411. if (d)
  412. {
  413. buffer = d;
  414. startOffset = s;
  415. bufferOwner = NO;
  416. originalBufferLength = [d length];
  417. }
  418. else
  419. {
  420. if (readLength > 0)
  421. buffer = [[NSMutableData alloc] initWithLength:readLength];
  422. else
  423. buffer = [[NSMutableData alloc] initWithLength:0];
  424. startOffset = 0;
  425. bufferOwner = YES;
  426. originalBufferLength = 0;
  427. }
  428. }
  429. return self;
  430. }
  431. /**
  432. * Increases the length of the buffer (if needed) to ensure a read of the given size will fit.
  433. **/
  434. - (void)ensureCapacityForAdditionalDataOfLength:(NSUInteger)bytesToRead
  435. {
  436. NSUInteger buffSize = [buffer length];
  437. NSUInteger buffUsed = startOffset + bytesDone;
  438. NSUInteger buffSpace = buffSize - buffUsed;
  439. if (bytesToRead > buffSpace)
  440. {
  441. NSUInteger buffInc = bytesToRead - buffSpace;
  442. [buffer increaseLengthBy:buffInc];
  443. }
  444. }
  445. /**
  446. * This method is used when we do NOT know how much data is available to be read from the socket.
  447. * This method returns the default value unless it exceeds the specified readLength or maxLength.
  448. *
  449. * Furthermore, the shouldPreBuffer decision is based upon the packet type,
  450. * and whether the returned value would fit in the current buffer without requiring a resize of the buffer.
  451. **/
  452. - (NSUInteger)optimalReadLengthWithDefault:(NSUInteger)defaultValue shouldPreBuffer:(BOOL *)shouldPreBufferPtr
  453. {
  454. NSUInteger result;
  455. if (readLength > 0)
  456. {
  457. // Read a specific length of data
  458. result = MIN(defaultValue, (readLength - bytesDone));
  459. // There is no need to prebuffer since we know exactly how much data we need to read.
  460. // Even if the buffer isn't currently big enough to fit this amount of data,
  461. // it would have to be resized eventually anyway.
  462. if (shouldPreBufferPtr)
  463. *shouldPreBufferPtr = NO;
  464. }
  465. else
  466. {
  467. // Either reading until we find a specified terminator,
  468. // or we're simply reading all available data.
  469. //
  470. // In other words, one of:
  471. //
  472. // - readDataToData packet
  473. // - readDataWithTimeout packet
  474. if (maxLength > 0)
  475. result = MIN(defaultValue, (maxLength - bytesDone));
  476. else
  477. result = defaultValue;
  478. // Since we don't know the size of the read in advance,
  479. // the shouldPreBuffer decision is based upon whether the returned value would fit
  480. // in the current buffer without requiring a resize of the buffer.
  481. //
  482. // This is because, in all likelyhood, the amount read from the socket will be less than the default value.
  483. // Thus we should avoid over-allocating the read buffer when we can simply use the pre-buffer instead.
  484. if (shouldPreBufferPtr)
  485. {
  486. NSUInteger buffSize = [buffer length];
  487. NSUInteger buffUsed = startOffset + bytesDone;
  488. NSUInteger buffSpace = buffSize - buffUsed;
  489. if (buffSpace >= result)
  490. *shouldPreBufferPtr = NO;
  491. else
  492. *shouldPreBufferPtr = YES;
  493. }
  494. }
  495. return result;
  496. }
  497. /**
  498. * For read packets without a set terminator, returns the amount of data
  499. * that can be read without exceeding the readLength or maxLength.
  500. *
  501. * The given parameter indicates the number of bytes estimated to be available on the socket,
  502. * which is taken into consideration during the calculation.
  503. *
  504. * The given hint MUST be greater than zero.
  505. **/
  506. - (NSUInteger)readLengthForNonTermWithHint:(NSUInteger)bytesAvailable
  507. {
  508. NSAssert(term == nil, @"This method does not apply to term reads");
  509. NSAssert(bytesAvailable > 0, @"Invalid parameter: bytesAvailable");
  510. if (readLength > 0)
  511. {
  512. // Read a specific length of data
  513. return MIN(bytesAvailable, (readLength - bytesDone));
  514. // No need to avoid resizing the buffer.
  515. // If the user provided their own buffer,
  516. // and told us to read a certain length of data that exceeds the size of the buffer,
  517. // then it is clear that our code will resize the buffer during the read operation.
  518. //
  519. // This method does not actually do any resizing.
  520. // The resizing will happen elsewhere if needed.
  521. }
  522. else
  523. {
  524. // Read all available data
  525. NSUInteger result = bytesAvailable;
  526. if (maxLength > 0)
  527. {
  528. result = MIN(result, (maxLength - bytesDone));
  529. }
  530. // No need to avoid resizing the buffer.
  531. // If the user provided their own buffer,
  532. // and told us to read all available data without giving us a maxLength,
  533. // then it is clear that our code might resize the buffer during the read operation.
  534. //
  535. // This method does not actually do any resizing.
  536. // The resizing will happen elsewhere if needed.
  537. return result;
  538. }
  539. }
  540. /**
  541. * For read packets with a set terminator, returns the amount of data
  542. * that can be read without exceeding the maxLength.
  543. *
  544. * The given parameter indicates the number of bytes estimated to be available on the socket,
  545. * which is taken into consideration during the calculation.
  546. *
  547. * To optimize memory allocations, mem copies, and mem moves
  548. * the shouldPreBuffer boolean value will indicate if the data should be read into a prebuffer first,
  549. * or if the data can be read directly into the read packet's buffer.
  550. **/
  551. - (NSUInteger)readLengthForTermWithHint:(NSUInteger)bytesAvailable shouldPreBuffer:(BOOL *)shouldPreBufferPtr
  552. {
  553. NSAssert(term != nil, @"This method does not apply to non-term reads");
  554. NSAssert(bytesAvailable > 0, @"Invalid parameter: bytesAvailable");
  555. NSUInteger result = bytesAvailable;
  556. if (maxLength > 0)
  557. {
  558. result = MIN(result, (maxLength - bytesDone));
  559. }
  560. // Should the data be read into the read packet's buffer, or into a pre-buffer first?
  561. //
  562. // One would imagine the preferred option is the faster one.
  563. // So which one is faster?
  564. //
  565. // Reading directly into the packet's buffer requires:
  566. // 1. Possibly resizing packet buffer (malloc/realloc)
  567. // 2. Filling buffer (read)
  568. // 3. Searching for term (memcmp)
  569. // 4. Possibly copying overflow into prebuffer (malloc/realloc, memcpy)
  570. //
  571. // Reading into prebuffer first:
  572. // 1. Possibly resizing prebuffer (malloc/realloc)
  573. // 2. Filling buffer (read)
  574. // 3. Searching for term (memcmp)
  575. // 4. Copying underflow into packet buffer (malloc/realloc, memcpy)
  576. // 5. Removing underflow from prebuffer (memmove)
  577. //
  578. // Comparing the performance of the two we can see that reading
  579. // data into the prebuffer first is slower due to the extra memove.
  580. //
  581. // However:
  582. // The implementation of NSMutableData is open source via core foundation's CFMutableData.
  583. // Decreasing the length of a mutable data object doesn't cause a realloc.
  584. // In other words, the capacity of a mutable data object can grow, but doesn't shrink.
  585. //
  586. // This means the prebuffer will rarely need a realloc.
  587. // The packet buffer, on the other hand, may often need a realloc.
  588. // This is especially true if we are the buffer owner.
  589. // Furthermore, if we are constantly realloc'ing the packet buffer,
  590. // and then moving the overflow into the prebuffer,
  591. // then we're consistently over-allocating memory for each term read.
  592. // And now we get into a bit of a tradeoff between speed and memory utilization.
  593. //
  594. // The end result is that the two perform very similarly.
  595. // And we can answer the original question very simply by another means.
  596. //
  597. // If we can read all the data directly into the packet's buffer without resizing it first,
  598. // then we do so. Otherwise we use the prebuffer.
  599. if (shouldPreBufferPtr)
  600. {
  601. NSUInteger buffSize = [buffer length];
  602. NSUInteger buffUsed = startOffset + bytesDone;
  603. if ((buffSize - buffUsed) >= result)
  604. *shouldPreBufferPtr = NO;
  605. else
  606. *shouldPreBufferPtr = YES;
  607. }
  608. return result;
  609. }
  610. /**
  611. * For read packets with a set terminator,
  612. * returns the amount of data that can be read from the given preBuffer,
  613. * without going over a terminator or the maxLength.
  614. *
  615. * It is assumed the terminator has not already been read.
  616. **/
  617. - (NSUInteger)readLengthForTermWithPreBuffer:(GCDAsyncSocketPreBuffer *)preBuffer found:(BOOL *)foundPtr
  618. {
  619. NSAssert(term != nil, @"This method does not apply to non-term reads");
  620. NSAssert([preBuffer availableBytes] > 0, @"Invoked with empty pre buffer!");
  621. // We know that the terminator, as a whole, doesn't exist in our own buffer.
  622. // But it is possible that a _portion_ of it exists in our buffer.
  623. // So we're going to look for the terminator starting with a portion of our own buffer.
  624. //
  625. // Example:
  626. //
  627. // term length = 3 bytes
  628. // bytesDone = 5 bytes
  629. // preBuffer length = 5 bytes
  630. //
  631. // If we append the preBuffer to our buffer,
  632. // it would look like this:
  633. //
  634. // ---------------------
  635. // |B|B|B|B|B|P|P|P|P|P|
  636. // ---------------------
  637. //
  638. // So we start our search here:
  639. //
  640. // ---------------------
  641. // |B|B|B|B|B|P|P|P|P|P|
  642. // -------^-^-^---------
  643. //
  644. // And move forwards...
  645. //
  646. // ---------------------
  647. // |B|B|B|B|B|P|P|P|P|P|
  648. // ---------^-^-^-------
  649. //
  650. // Until we find the terminator or reach the end.
  651. //
  652. // ---------------------
  653. // |B|B|B|B|B|P|P|P|P|P|
  654. // ---------------^-^-^-
  655. BOOL found = NO;
  656. NSUInteger termLength = [term length];
  657. NSUInteger preBufferLength = [preBuffer availableBytes];
  658. if ((bytesDone + preBufferLength) < termLength)
  659. {
  660. // Not enough data for a full term sequence yet
  661. return preBufferLength;
  662. }
  663. NSUInteger maxPreBufferLength;
  664. if (maxLength > 0) {
  665. maxPreBufferLength = MIN(preBufferLength, (maxLength - bytesDone));
  666. // Note: maxLength >= termLength
  667. }
  668. else {
  669. maxPreBufferLength = preBufferLength;
  670. }
  671. uint8_t seq[termLength];
  672. const void *termBuf = [term bytes];
  673. NSUInteger bufLen = MIN(bytesDone, (termLength - 1));
  674. uint8_t *buf = (uint8_t *)[buffer mutableBytes] + startOffset + bytesDone - bufLen;
  675. NSUInteger preLen = termLength - bufLen;
  676. const uint8_t *pre = [preBuffer readBuffer];
  677. NSUInteger loopCount = bufLen + maxPreBufferLength - termLength + 1; // Plus one. See example above.
  678. NSUInteger result = maxPreBufferLength;
  679. NSUInteger i;
  680. for (i = 0; i < loopCount; i++)
  681. {
  682. if (bufLen > 0)
  683. {
  684. // Combining bytes from buffer and preBuffer
  685. memcpy(seq, buf, bufLen);
  686. memcpy(seq + bufLen, pre, preLen);
  687. if (memcmp(seq, termBuf, termLength) == 0)
  688. {
  689. result = preLen;
  690. found = YES;
  691. break;
  692. }
  693. buf++;
  694. bufLen--;
  695. preLen++;
  696. }
  697. else
  698. {
  699. // Comparing directly from preBuffer
  700. if (memcmp(pre, termBuf, termLength) == 0)
  701. {
  702. NSUInteger preOffset = pre - [preBuffer readBuffer]; // pointer arithmetic
  703. result = preOffset + termLength;
  704. found = YES;
  705. break;
  706. }
  707. pre++;
  708. }
  709. }
  710. // There is no need to avoid resizing the buffer in this particular situation.
  711. if (foundPtr) *foundPtr = found;
  712. return result;
  713. }
  714. /**
  715. * For read packets with a set terminator, scans the packet buffer for the term.
  716. * It is assumed the terminator had not been fully read prior to the new bytes.
  717. *
  718. * If the term is found, the number of excess bytes after the term are returned.
  719. * If the term is not found, this method will return -1.
  720. *
  721. * Note: A return value of zero means the term was found at the very end.
  722. *
  723. * Prerequisites:
  724. * The given number of bytes have been added to the end of our buffer.
  725. * Our bytesDone variable has NOT been changed due to the prebuffered bytes.
  726. **/
  727. - (NSInteger)searchForTermAfterPreBuffering:(ssize_t)numBytes
  728. {
  729. NSAssert(term != nil, @"This method does not apply to non-term reads");
  730. // The implementation of this method is very similar to the above method.
  731. // See the above method for a discussion of the algorithm used here.
  732. uint8_t *buff = [buffer mutableBytes];
  733. NSUInteger buffLength = bytesDone + numBytes;
  734. const void *termBuff = [term bytes];
  735. NSUInteger termLength = [term length];
  736. // Note: We are dealing with unsigned integers,
  737. // so make sure the math doesn't go below zero.
  738. NSUInteger i = ((buffLength - numBytes) >= termLength) ? (buffLength - numBytes - termLength + 1) : 0;
  739. while (i + termLength <= buffLength)
  740. {
  741. uint8_t *subBuffer = buff + startOffset + i;
  742. if (memcmp(subBuffer, termBuff, termLength) == 0)
  743. {
  744. return buffLength - (i + termLength);
  745. }
  746. i++;
  747. }
  748. return -1;
  749. }
  750. @end
  751. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  752. #pragma mark -
  753. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  754. /**
  755. * The GCDAsyncWritePacket encompasses the instructions for any given write.
  756. **/
  757. @interface GCDAsyncWritePacket : NSObject
  758. {
  759. @public
  760. NSData *buffer;
  761. NSUInteger bytesDone;
  762. long tag;
  763. NSTimeInterval timeout;
  764. }
  765. - (id)initWithData:(NSData *)d timeout:(NSTimeInterval)t tag:(long)i;
  766. @end
  767. @implementation GCDAsyncWritePacket
  768. - (id)initWithData:(NSData *)d timeout:(NSTimeInterval)t tag:(long)i
  769. {
  770. if((self = [super init]))
  771. {
  772. buffer = d; // Retain not copy. For performance as documented in header file.
  773. bytesDone = 0;
  774. timeout = t;
  775. tag = i;
  776. }
  777. return self;
  778. }
  779. @end
  780. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  781. #pragma mark -
  782. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  783. /**
  784. * The GCDAsyncSpecialPacket encompasses special instructions for interruptions in the read/write queues.
  785. * This class my be altered to support more than just TLS in the future.
  786. **/
  787. @interface GCDAsyncSpecialPacket : NSObject
  788. {
  789. @public
  790. NSDictionary *tlsSettings;
  791. }
  792. - (id)initWithTLSSettings:(NSDictionary *)settings;
  793. @end
  794. @implementation GCDAsyncSpecialPacket
  795. - (id)initWithTLSSettings:(NSDictionary *)settings
  796. {
  797. if((self = [super init]))
  798. {
  799. tlsSettings = [settings copy];
  800. }
  801. return self;
  802. }
  803. @end
  804. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  805. #pragma mark -
  806. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  807. @implementation GCDAsyncSocket
  808. - (id)init
  809. {
  810. return [self initWithDelegate:nil delegateQueue:NULL socketQueue:NULL];
  811. }
  812. - (id)initWithSocketQueue:(dispatch_queue_t)sq
  813. {
  814. return [self initWithDelegate:nil delegateQueue:NULL socketQueue:sq];
  815. }
  816. - (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq
  817. {
  818. return [self initWithDelegate:aDelegate delegateQueue:dq socketQueue:NULL];
  819. }
  820. - (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq socketQueue:(dispatch_queue_t)sq
  821. {
  822. if((self = [super init]))
  823. {
  824. delegate = aDelegate;
  825. delegateQueue = dq;
  826. #if NEEDS_DISPATCH_RETAIN_RELEASE
  827. if (dq) dispatch_retain(dq);
  828. #endif
  829. socket4FD = SOCKET_NULL;
  830. socket6FD = SOCKET_NULL;
  831. connectIndex = 0;
  832. if (sq)
  833. {
  834. NSAssert(sq != dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0),
  835. @"The given socketQueue parameter must not be a concurrent queue.");
  836. NSAssert(sq != dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),
  837. @"The given socketQueue parameter must not be a concurrent queue.");
  838. NSAssert(sq != dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
  839. @"The given socketQueue parameter must not be a concurrent queue.");
  840. socketQueue = sq;
  841. #if NEEDS_DISPATCH_RETAIN_RELEASE
  842. dispatch_retain(sq);
  843. #endif
  844. }
  845. else
  846. {
  847. socketQueue = dispatch_queue_create([GCDAsyncSocketQueueName UTF8String], NULL);
  848. }
  849. readQueue = [[NSMutableArray alloc] initWithCapacity:5];
  850. currentRead = nil;
  851. writeQueue = [[NSMutableArray alloc] initWithCapacity:5];
  852. currentWrite = nil;
  853. preBuffer = [[GCDAsyncSocketPreBuffer alloc] initWithCapacity:(1024 * 4)];
  854. }
  855. return self;
  856. }
  857. - (void)dealloc
  858. {
  859. LogInfo(@"%@ - %@ (start)", THIS_METHOD, self);
  860. if (dispatch_get_current_queue() == socketQueue)
  861. {
  862. [self closeWithError:nil];
  863. }
  864. else
  865. {
  866. dispatch_sync(socketQueue, ^{
  867. [self closeWithError:nil];
  868. });
  869. }
  870. delegate = nil;
  871. #if NEEDS_DISPATCH_RETAIN_RELEASE
  872. if (delegateQueue) dispatch_release(delegateQueue);
  873. #endif
  874. delegateQueue = NULL;
  875. #if NEEDS_DISPATCH_RETAIN_RELEASE
  876. if (socketQueue) dispatch_release(socketQueue);
  877. #endif
  878. socketQueue = NULL;
  879. LogInfo(@"%@ - %@ (finish)", THIS_METHOD, self);
  880. }
  881. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  882. #pragma mark Configuration
  883. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  884. - (id)delegate
  885. {
  886. if (dispatch_get_current_queue() == socketQueue)
  887. {
  888. return delegate;
  889. }
  890. else
  891. {
  892. __block id result;
  893. dispatch_sync(socketQueue, ^{
  894. result = delegate;
  895. });
  896. return result;
  897. }
  898. }
  899. - (void)setDelegate:(id)newDelegate synchronously:(BOOL)synchronously
  900. {
  901. dispatch_block_t block = ^{
  902. delegate = newDelegate;
  903. };
  904. if (dispatch_get_current_queue() == socketQueue) {
  905. block();
  906. }
  907. else {
  908. if (synchronously)
  909. dispatch_sync(socketQueue, block);
  910. else
  911. dispatch_async(socketQueue, block);
  912. }
  913. }
  914. - (void)setDelegate:(id)newDelegate
  915. {
  916. [self setDelegate:newDelegate synchronously:NO];
  917. }
  918. - (void)synchronouslySetDelegate:(id)newDelegate
  919. {
  920. [self setDelegate:newDelegate synchronously:YES];
  921. }
  922. - (dispatch_queue_t)delegateQueue
  923. {
  924. if (dispatch_get_current_queue() == socketQueue)
  925. {
  926. return delegateQueue;
  927. }
  928. else
  929. {
  930. __block dispatch_queue_t result;
  931. dispatch_sync(socketQueue, ^{
  932. result = delegateQueue;
  933. });
  934. return result;
  935. }
  936. }
  937. - (void)setDelegateQueue:(dispatch_queue_t)newDelegateQueue synchronously:(BOOL)synchronously
  938. {
  939. dispatch_block_t block = ^{
  940. #if NEEDS_DISPATCH_RETAIN_RELEASE
  941. if (delegateQueue) dispatch_release(delegateQueue);
  942. if (newDelegateQueue) dispatch_retain(newDelegateQueue);
  943. #endif
  944. delegateQueue = newDelegateQueue;
  945. };
  946. if (dispatch_get_current_queue() == socketQueue) {
  947. block();
  948. }
  949. else {
  950. if (synchronously)
  951. dispatch_sync(socketQueue, block);
  952. else
  953. dispatch_async(socketQueue, block);
  954. }
  955. }
  956. - (void)setDelegateQueue:(dispatch_queue_t)newDelegateQueue
  957. {
  958. [self setDelegateQueue:newDelegateQueue synchronously:NO];
  959. }
  960. - (void)synchronouslySetDelegateQueue:(dispatch_queue_t)newDelegateQueue
  961. {
  962. [self setDelegateQueue:newDelegateQueue synchronously:YES];
  963. }
  964. - (void)getDelegate:(id *)delegatePtr delegateQueue:(dispatch_queue_t *)delegateQueuePtr
  965. {
  966. if (dispatch_get_current_queue() == socketQueue)
  967. {
  968. if (delegatePtr) *delegatePtr = delegate;
  969. if (delegateQueuePtr) *delegateQueuePtr = delegateQueue;
  970. }
  971. else
  972. {
  973. __block id dPtr = NULL;
  974. __block dispatch_queue_t dqPtr = NULL;
  975. dispatch_sync(socketQueue, ^{
  976. dPtr = delegate;
  977. dqPtr = delegateQueue;
  978. });
  979. if (delegatePtr) *delegatePtr = dPtr;
  980. if (delegateQueuePtr) *delegateQueuePtr = dqPtr;
  981. }
  982. }
  983. - (void)setDelegate:(id)newDelegate delegateQueue:(dispatch_queue_t)newDelegateQueue synchronously:(BOOL)synchronously
  984. {
  985. dispatch_block_t block = ^{
  986. delegate = newDelegate;
  987. #if NEEDS_DISPATCH_RETAIN_RELEASE
  988. if (delegateQueue) dispatch_release(delegateQueue);
  989. if (newDelegateQueue) dispatch_retain(newDelegateQueue);
  990. #endif
  991. delegateQueue = newDelegateQueue;
  992. };
  993. if (dispatch_get_current_queue() == socketQueue) {
  994. block();
  995. }
  996. else {
  997. if (synchronously)
  998. dispatch_sync(socketQueue, block);
  999. else
  1000. dispatch_async(socketQueue, block);
  1001. }
  1002. }
  1003. - (void)setDelegate:(id)newDelegate delegateQueue:(dispatch_queue_t)newDelegateQueue
  1004. {
  1005. [self setDelegate:newDelegate delegateQueue:newDelegateQueue synchronously:NO];
  1006. }
  1007. - (void)synchronouslySetDelegate:(id)newDelegate delegateQueue:(dispatch_queue_t)newDelegateQueue
  1008. {
  1009. [self setDelegate:newDelegate delegateQueue:newDelegateQueue synchronously:YES];
  1010. }
  1011. - (BOOL)autoDisconnectOnClosedReadStream
  1012. {
  1013. // Note: YES means kAllowHalfDuplexConnection is OFF
  1014. if (dispatch_get_current_queue() == socketQueue)
  1015. {
  1016. return ((config & kAllowHalfDuplexConnection) == 0);
  1017. }
  1018. else
  1019. {
  1020. __block BOOL result;
  1021. dispatch_sync(socketQueue, ^{
  1022. result = ((config & kAllowHalfDuplexConnection) == 0);
  1023. });
  1024. return result;
  1025. }
  1026. }
  1027. - (void)setAutoDisconnectOnClosedReadStream:(BOOL)flag
  1028. {
  1029. // Note: YES means kAllowHalfDuplexConnection is OFF
  1030. dispatch_block_t block = ^{
  1031. if (flag)
  1032. config &= ~kAllowHalfDuplexConnection;
  1033. else
  1034. config |= kAllowHalfDuplexConnection;
  1035. };
  1036. if (dispatch_get_current_queue() == socketQueue)
  1037. block();
  1038. else
  1039. dispatch_async(socketQueue, block);
  1040. }
  1041. - (BOOL)isIPv4Enabled
  1042. {
  1043. // Note: YES means kIPv4Disabled is OFF
  1044. if (dispatch_get_current_queue() == socketQueue)
  1045. {
  1046. return ((config & kIPv4Disabled) == 0);
  1047. }
  1048. else
  1049. {
  1050. __block BOOL result;
  1051. dispatch_sync(socketQueue, ^{
  1052. result = ((config & kIPv4Disabled) == 0);
  1053. });
  1054. return result;
  1055. }
  1056. }
  1057. - (void)setIPv4Enabled:(BOOL)flag
  1058. {
  1059. // Note: YES means kIPv4Disabled is OFF
  1060. dispatch_block_t block = ^{
  1061. if (flag)
  1062. config &= ~kIPv4Disabled;
  1063. else
  1064. config |= kIPv4Disabled;
  1065. };
  1066. if (dispatch_get_current_queue() == socketQueue)
  1067. block();
  1068. else
  1069. dispatch_async(socketQueue, block);
  1070. }
  1071. - (BOOL)isIPv6Enabled
  1072. {
  1073. // Note: YES means kIPv6Disabled is OFF
  1074. if (dispatch_get_current_queue() == socketQueue)
  1075. {
  1076. return ((config & kIPv6Disabled) == 0);
  1077. }
  1078. else
  1079. {
  1080. __block BOOL result;
  1081. dispatch_sync(socketQueue, ^{
  1082. result = ((config & kIPv6Disabled) == 0);
  1083. });
  1084. return result;
  1085. }
  1086. }
  1087. - (void)setIPv6Enabled:(BOOL)flag
  1088. {
  1089. // Note: YES means kIPv6Disabled is OFF
  1090. dispatch_block_t block = ^{
  1091. if (flag)
  1092. config &= ~kIPv6Disabled;
  1093. else
  1094. config |= kIPv6Disabled;
  1095. };
  1096. if (dispatch_get_current_queue() == socketQueue)
  1097. block();
  1098. else
  1099. dispatch_async(socketQueue, block);
  1100. }
  1101. - (BOOL)isIPv4PreferredOverIPv6
  1102. {
  1103. // Note: YES means kPreferIPv6 is OFF
  1104. if (dispatch_get_current_queue() == socketQueue)
  1105. {
  1106. return ((config & kPreferIPv6) == 0);
  1107. }
  1108. else
  1109. {
  1110. __block BOOL result;
  1111. dispatch_sync(socketQueue, ^{
  1112. result = ((config & kPreferIPv6) == 0);
  1113. });
  1114. return result;
  1115. }
  1116. }
  1117. - (void)setPreferIPv4OverIPv6:(BOOL)flag
  1118. {
  1119. // Note: YES means kPreferIPv6 is OFF
  1120. dispatch_block_t block = ^{
  1121. if (flag)
  1122. config &= ~kPreferIPv6;
  1123. else
  1124. config |= kPreferIPv6;
  1125. };
  1126. if (dispatch_get_current_queue() == socketQueue)
  1127. block();
  1128. else
  1129. dispatch_async(socketQueue, block);
  1130. }
  1131. - (id)userData
  1132. {
  1133. __block id result = nil;
  1134. dispatch_block_t block = ^{
  1135. result = userData;
  1136. };
  1137. if (dispatch_get_current_queue() == socketQueue)
  1138. block();
  1139. else
  1140. dispatch_sync(socketQueue, block);
  1141. return result;
  1142. }
  1143. - (void)setUserData:(id)arbitraryUserData
  1144. {
  1145. dispatch_block_t block = ^{
  1146. if (userData != arbitraryUserData)
  1147. {
  1148. userData = arbitraryUserData;
  1149. }
  1150. };
  1151. if (dispatch_get_current_queue() == socketQueue)
  1152. block();
  1153. else
  1154. dispatch_async(socketQueue, block);
  1155. }
  1156. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1157. #pragma mark Accepting
  1158. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1159. - (BOOL)acceptOnPort:(uint16_t)port error:(NSError **)errPtr
  1160. {
  1161. return [self acceptOnInterface:nil port:port error:errPtr];
  1162. }
  1163. - (BOOL)acceptOnInterface:(NSString *)inInterface port:(uint16_t)port error:(NSError **)errPtr
  1164. {
  1165. LogTrace();
  1166. // Just in-case interface parameter is immutable.
  1167. NSString *interface = [inInterface copy];
  1168. __block BOOL result = NO;
  1169. __block NSError *err = nil;
  1170. // CreateSocket Block
  1171. // This block will be invoked within the dispatch block below.
  1172. int(^createSocket)(int, NSData*) = ^int (int domain, NSData *interfaceAddr) {
  1173. int socketFD = socket(domain, SOCK_STREAM, 0);
  1174. if (socketFD == SOCKET_NULL)
  1175. {
  1176. NSString *reason = @"Error in socket() function";
  1177. err = [self errnoErrorWithReason:reason];
  1178. return SOCKET_NULL;
  1179. }
  1180. int status;
  1181. // Set socket options
  1182. status = fcntl(socketFD, F_SETFL, O_NONBLOCK);
  1183. if (status == -1)
  1184. {
  1185. NSString *reason = @"Error enabling non-blocking IO on socket (fcntl)";
  1186. err = [self errnoErrorWithReason:reason];
  1187. LogVerbose(@"close(socketFD)");
  1188. close(socketFD);
  1189. return SOCKET_NULL;
  1190. }
  1191. int reuseOn = 1;
  1192. status = setsockopt(socketFD, SOL_SOCKET, SO_REUSEADDR, &reuseOn, sizeof(reuseOn));
  1193. if (status == -1)
  1194. {
  1195. NSString *reason = @"Error enabling address reuse (setsockopt)";
  1196. err = [self errnoErrorWithReason:reason];
  1197. LogVerbose(@"close(socketFD)");
  1198. close(socketFD);
  1199. return SOCKET_NULL;
  1200. }
  1201. // Bind socket
  1202. status = bind(socketFD, (const struct sockaddr *)[interfaceAddr bytes], (socklen_t)[interfaceAddr length]);
  1203. if (status == -1)
  1204. {
  1205. NSString *reason = @"Error in bind() function";
  1206. err = [self errnoErrorWithReason:reason];
  1207. LogVerbose(@"close(socketFD)");
  1208. close(socketFD);
  1209. return SOCKET_NULL;
  1210. }
  1211. // Listen
  1212. status = listen(socketFD, 1024);
  1213. if (status == -1)
  1214. {
  1215. NSString *reason = @"Error in listen() function";
  1216. err = [self errnoErrorWithReason:reason];
  1217. LogVerbose(@"close(socketFD)");
  1218. close(socketFD);
  1219. return SOCKET_NULL;
  1220. }
  1221. return socketFD;
  1222. };
  1223. // Create dispatch block and run on socketQueue
  1224. dispatch_block_t block = ^{ @autoreleasepool {
  1225. if (delegate == nil) // Must have delegate set
  1226. {
  1227. NSString *msg = @"Attempting to accept without a delegate. Set a delegate first.";
  1228. err = [self badConfigError:msg];
  1229. return_from_block;
  1230. }
  1231. if (delegateQueue == NULL) // Must have delegate queue set
  1232. {
  1233. NSString *msg = @"Attempting to accept without a delegate queue. Set a delegate queue first.";
  1234. err = [self badConfigError:msg];
  1235. return_from_block;
  1236. }
  1237. BOOL isIPv4Disabled = (config & kIPv4Disabled) ? YES : NO;
  1238. BOOL isIPv6Disabled = (config & kIPv6Disabled) ? YES : NO;
  1239. if (isIPv4Disabled && isIPv6Disabled) // Must have IPv4 or IPv6 enabled
  1240. {
  1241. NSString *msg = @"Both IPv4 and IPv6 have been disabled. Must enable at least one protocol first.";
  1242. err = [self badConfigError:msg];
  1243. return_from_block;
  1244. }
  1245. if (![self isDisconnected]) // Must be disconnected
  1246. {
  1247. NSString *msg = @"Attempting to accept while connected or accepting connections. Disconnect first.";
  1248. err = [self badConfigError:msg];
  1249. return_from_block;
  1250. }
  1251. // Clear queues (spurious read/write requests post disconnect)
  1252. [readQueue removeAllObjects];
  1253. [writeQueue removeAllObjects];
  1254. // Resolve interface from description
  1255. NSMutableData *interface4 = nil;
  1256. NSMutableData *interface6 = nil;
  1257. [self getInterfaceAddress4:&interface4 address6:&interface6 fromDescription:interface port:port];
  1258. if ((interface4 == nil) && (interface6 == nil))
  1259. {
  1260. NSString *msg = @"Unknown interface. Specify valid interface by name (e.g. \"en1\") or IP address.";
  1261. err = [self badParamError:msg];
  1262. return_from_block;
  1263. }
  1264. if (isIPv4Disabled && (interface6 == nil))
  1265. {
  1266. NSString *msg = @"IPv4 has been disabled and specified interface doesn't support IPv6.";
  1267. err = [self badParamError:msg];
  1268. return_from_block;
  1269. }
  1270. if (isIPv6Disabled && (interface4 == nil))
  1271. {
  1272. NSString *msg = @"IPv6 has been disabled and specified interface doesn't support IPv4.";
  1273. err = [self badParamError:msg];
  1274. return_from_block;
  1275. }
  1276. BOOL enableIPv4 = !isIPv4Disabled && (interface4 != nil);
  1277. BOOL enableIPv6 = !isIPv6Disabled && (interface6 != nil);
  1278. // Create sockets, configure, bind, and listen
  1279. if (enableIPv4)
  1280. {
  1281. LogVerbose(@"Creating IPv4 socket");
  1282. socket4FD = createSocket(AF_INET, interface4);
  1283. if (socket4FD == SOCKET_NULL)
  1284. {
  1285. return_from_block;
  1286. }
  1287. }
  1288. if (enableIPv6)
  1289. {
  1290. LogVerbose(@"Creating IPv6 socket");
  1291. if (enableIPv4 && (port == 0))
  1292. {
  1293. // No specific port was specified, so we allowed the OS to pick an available port for us.
  1294. // Now we need to make sure the IPv6 socket listens on the same port as the IPv4 socket.
  1295. struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)[interface6 mutableBytes];
  1296. addr6->sin6_port = htons([self localPort4]);
  1297. }
  1298. socket6FD = createSocket(AF_INET6, interface6);
  1299. if (socket6FD == SOCKET_NULL)
  1300. {
  1301. if (socket4FD != SOCKET_NULL)
  1302. {
  1303. LogVerbose(@"close(socket4FD)");
  1304. close(socket4FD);
  1305. }
  1306. return_from_block;
  1307. }
  1308. }
  1309. // Create accept sources
  1310. if (enableIPv4)
  1311. {
  1312. accept4Source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, socket4FD, 0, socketQueue);
  1313. int socketFD = socket4FD;
  1314. dispatch_source_t acceptSource = accept4Source;
  1315. dispatch_source_set_event_handler(accept4Source, ^{ @autoreleasepool {
  1316. LogVerbose(@"event4Block");
  1317. unsigned long i = 0;
  1318. unsigned long numPendingConnections = dispatch_source_get_data(acceptSource);
  1319. LogVerbose(@"numPendingConnections: %lu", numPendingConnections);
  1320. while ([self doAccept:socketFD] && (++i < numPendingConnections));
  1321. }});
  1322. dispatch_source_set_cancel_handler(accept4Source, ^{
  1323. #if NEEDS_DISPATCH_RETAIN_RELEASE
  1324. LogVerbose(@"dispatch_release(accept4Source)");
  1325. dispatch_release(acceptSource);
  1326. #endif
  1327. LogVerbose(@"close(socket4FD)");
  1328. close(socketFD);
  1329. });
  1330. LogVerbose(@"dispatch_resume(accept4Source)");
  1331. dispatch_resume(accept4Source);
  1332. }
  1333. if (enableIPv6)
  1334. {
  1335. accept6Source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, socket6FD, 0, socketQueue);
  1336. int socketFD = socket6FD;
  1337. dispatch_source_t acceptSource = accept6Source;
  1338. dispatch_source_set_event_handler(accept6Source, ^{ @autoreleasepool {
  1339. LogVerbose(@"event6Block");
  1340. unsigned long i = 0;
  1341. unsigned long numPendingConnections = dispatch_source_get_data(acceptSource);
  1342. LogVerbose(@"numPendingConnections: %lu", numPendingConnections);
  1343. while ([self doAccept:socketFD] && (++i < numPendingConnections));
  1344. }});
  1345. dispatch_source_set_cancel_handler(accept6Source, ^{
  1346. #if NEEDS_DISPATCH_RETAIN_RELEASE
  1347. LogVerbose(@"dispatch_release(accept6Source)");
  1348. dispatch_release(acceptSource);
  1349. #endif
  1350. LogVerbose(@"close(socket6FD)");
  1351. close(socketFD);
  1352. });
  1353. LogVerbose(@"dispatch_resume(accept6Source)");
  1354. dispatch_resume(accept6Source);
  1355. }
  1356. flags |= kSocketStarted;
  1357. result = YES;
  1358. }};
  1359. if (dispatch_get_current_queue() == socketQueue)
  1360. block();
  1361. else
  1362. dispatch_sync(socketQueue, block);
  1363. if (result == NO)
  1364. {
  1365. LogInfo(@"Error in accept: %@", err);
  1366. if (errPtr)
  1367. *errPtr = err;
  1368. }
  1369. return result;
  1370. }
  1371. - (BOOL)doAccept:(int)parentSocketFD
  1372. {
  1373. LogTrace();
  1374. BOOL isIPv4;
  1375. int childSocketFD;
  1376. NSData *childSocketAddress;
  1377. if (parentSocketFD == socket4FD)
  1378. {
  1379. isIPv4 = YES;
  1380. struct sockaddr_in addr;
  1381. socklen_t addrLen = sizeof(addr);
  1382. childSocketFD = accept(parentSocketFD, (struct sockaddr *)&addr, &addrLen);
  1383. if (childSocketFD == -1)
  1384. {
  1385. LogWarn(@"Accept failed with error: %@", [self errnoError]);
  1386. return NO;
  1387. }
  1388. childSocketAddress = [NSData dataWithBytes:&addr length:addrLen];
  1389. }
  1390. else // if (parentSocketFD == socket6FD)
  1391. {
  1392. isIPv4 = NO;
  1393. struct sockaddr_in6 addr;
  1394. socklen_t addrLen = sizeof(addr);
  1395. childSocketFD = accept(parentSocketFD, (struct sockaddr *)&addr, &addrLen);
  1396. if (childSocketFD == -1)
  1397. {
  1398. LogWarn(@"Accept failed with error: %@", [self errnoError]);
  1399. return NO;
  1400. }
  1401. childSocketAddress = [NSData dataWithBytes:&addr length:addrLen];
  1402. }
  1403. // Enable non-blocking IO on the socket
  1404. int result = fcntl(childSocketFD, F_SETFL, O_NONBLOCK);
  1405. if (result == -1)
  1406. {
  1407. LogWarn(@"Error enabling non-blocking IO on accepted socket (fcntl)");
  1408. return NO;
  1409. }
  1410. // Prevent SIGPIPE signals
  1411. int nosigpipe = 1;
  1412. setsockopt(childSocketFD, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(nosigpipe));
  1413. // Notify delegate
  1414. if (delegateQueue)
  1415. {
  1416. __strong id theDelegate = delegate;
  1417. dispatch_async(delegateQueue, ^{ @autoreleasepool {
  1418. // Query delegate for custom socket queue
  1419. dispatch_queue_t childSocketQueue = NULL;
  1420. if ([theDelegate respondsToSelector:@selector(newSocketQueueForConnectionFromAddress:onSocket:)])
  1421. {
  1422. childSocketQueue = [theDelegate newSocketQueueForConnectionFromAddress:childSocketAddress
  1423. onSocket:self];
  1424. }
  1425. // Create GCDAsyncSocket instance for accepted socket
  1426. GCDAsyncSocket *acceptedSocket = [[GCDAsyncSocket alloc] initWithDelegate:theDelegate
  1427. delegateQueue:delegateQueue
  1428. socketQueue:childSocketQueue];
  1429. if (isIPv4)
  1430. acceptedSocket->socket4FD = childSocketFD;
  1431. else
  1432. acceptedSocket->socket6FD = childSocketFD;
  1433. acceptedSocket->flags = (kSocketStarted | kConnected);
  1434. // Setup read and write sources for accepted socket
  1435. dispatch_async(acceptedSocket->socketQueue, ^{ @autoreleasepool {
  1436. [acceptedSocket setupReadAndWriteSourcesForNewlyConnectedSocket:childSocketFD];
  1437. }});
  1438. // Notify delegate
  1439. if ([theDelegate respondsToSelector:@selector(socket:didAcceptNewSocket:)])
  1440. {
  1441. [theDelegate socket:self didAcceptNewSocket:acceptedSocket];
  1442. }
  1443. // Release the socket queue returned from the delegate (it was retained by acceptedSocket)
  1444. #if NEEDS_DISPATCH_RETAIN_RELEASE
  1445. if (childSocketQueue) dispatch_release(childSocketQueue);
  1446. #endif
  1447. // The accepted socket should have been retained by the delegate.
  1448. // Otherwise it gets properly released when exiting the block.
  1449. }});
  1450. }
  1451. return YES;
  1452. }
  1453. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1454. #pragma mark Connecting
  1455. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1456. /**
  1457. * Th