PageRenderTime 96ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 1ms

/Pods/CocoaAsyncSocket/GCD/GCDAsyncSocket.m

https://gitlab.com/mba811/tokaidoapp
Objective C | 7825 lines | 5189 code | 1691 blank | 945 comment | 1158 complexity | 1d291c75e68fd0db60f37271abe308b7 MD5 | raw file
Possible License(s): BSD-3-Clause
  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 <sys/un.h>
  26. #import <unistd.h>
  27. #if ! __has_feature(objc_arc)
  28. #warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
  29. // For more information see: https://github.com/robbiehanson/CocoaAsyncSocket/wiki/ARC
  30. #endif
  31. /**
  32. * Does ARC support support GCD objects?
  33. * It does if the minimum deployment target is iOS 6+ or Mac OS X 10.8+
  34. **/
  35. #if TARGET_OS_IPHONE
  36. // Compiling for iOS
  37. #if __IPHONE_OS_VERSION_MIN_REQUIRED >= 60000 // iOS 6.0 or later
  38. #define NEEDS_DISPATCH_RETAIN_RELEASE 0
  39. #else // iOS 5.X or earlier
  40. #define NEEDS_DISPATCH_RETAIN_RELEASE 1
  41. #endif
  42. #else
  43. // Compiling for Mac OS X
  44. #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 // Mac OS X 10.8 or later
  45. #define NEEDS_DISPATCH_RETAIN_RELEASE 0
  46. #else
  47. #define NEEDS_DISPATCH_RETAIN_RELEASE 1 // Mac OS X 10.7 or earlier
  48. #endif
  49. #endif
  50. #if 0
  51. // Logging Enabled - See log level below
  52. // Logging uses the CocoaLumberjack framework (which is also GCD based).
  53. // https://github.com/robbiehanson/CocoaLumberjack
  54. //
  55. // It allows us to do a lot of logging without significantly slowing down the code.
  56. #import "DDLog.h"
  57. #define LogAsync YES
  58. #define LogContext 65535
  59. #define LogObjc(flg, frmt, ...) LOG_OBJC_MAYBE(LogAsync, logLevel, flg, LogContext, frmt, ##__VA_ARGS__)
  60. #define LogC(flg, frmt, ...) LOG_C_MAYBE(LogAsync, logLevel, flg, LogContext, frmt, ##__VA_ARGS__)
  61. #define LogError(frmt, ...) LogObjc(LOG_FLAG_ERROR, (@"%@: " frmt), THIS_FILE, ##__VA_ARGS__)
  62. #define LogWarn(frmt, ...) LogObjc(LOG_FLAG_WARN, (@"%@: " frmt), THIS_FILE, ##__VA_ARGS__)
  63. #define LogInfo(frmt, ...) LogObjc(LOG_FLAG_INFO, (@"%@: " frmt), THIS_FILE, ##__VA_ARGS__)
  64. #define LogVerbose(frmt, ...) LogObjc(LOG_FLAG_VERBOSE, (@"%@: " frmt), THIS_FILE, ##__VA_ARGS__)
  65. #define LogCError(frmt, ...) LogC(LOG_FLAG_ERROR, (@"%@: " frmt), THIS_FILE, ##__VA_ARGS__)
  66. #define LogCWarn(frmt, ...) LogC(LOG_FLAG_WARN, (@"%@: " frmt), THIS_FILE, ##__VA_ARGS__)
  67. #define LogCInfo(frmt, ...) LogC(LOG_FLAG_INFO, (@"%@: " frmt), THIS_FILE, ##__VA_ARGS__)
  68. #define LogCVerbose(frmt, ...) LogC(LOG_FLAG_VERBOSE, (@"%@: " frmt), THIS_FILE, ##__VA_ARGS__)
  69. #define LogTrace() LogObjc(LOG_FLAG_VERBOSE, @"%@: %@", THIS_FILE, THIS_METHOD)
  70. #define LogCTrace() LogC(LOG_FLAG_VERBOSE, @"%@: %s", THIS_FILE, __FUNCTION__)
  71. // Log levels : off, error, warn, info, verbose
  72. static const int logLevel = LOG_LEVEL_VERBOSE;
  73. #else
  74. // Logging Disabled
  75. #define LogError(frmt, ...) {}
  76. #define LogWarn(frmt, ...) {}
  77. #define LogInfo(frmt, ...) {}
  78. #define LogVerbose(frmt, ...) {}
  79. #define LogCError(frmt, ...) {}
  80. #define LogCWarn(frmt, ...) {}
  81. #define LogCInfo(frmt, ...) {}
  82. #define LogCVerbose(frmt, ...) {}
  83. #define LogTrace() {}
  84. #define LogCTrace(frmt, ...) {}
  85. #endif
  86. /**
  87. * Seeing a return statements within an inner block
  88. * can sometimes be mistaken for a return point of the enclosing method.
  89. * This makes inline blocks a bit easier to read.
  90. **/
  91. #define return_from_block return
  92. /**
  93. * A socket file descriptor is really just an integer.
  94. * It represents the index of the socket within the kernel.
  95. * This makes invalid file descriptor comparisons easier to read.
  96. **/
  97. #define SOCKET_NULL -1
  98. NSString *const GCDAsyncSocketException = @"GCDAsyncSocketException";
  99. NSString *const GCDAsyncSocketErrorDomain = @"GCDAsyncSocketErrorDomain";
  100. NSString *const GCDAsyncSocketQueueName = @"GCDAsyncSocket";
  101. NSString *const GCDAsyncSocketThreadName = @"GCDAsyncSocket-CFStream";
  102. #if SECURE_TRANSPORT_MAYBE_AVAILABLE
  103. NSString *const GCDAsyncSocketSSLCipherSuites = @"GCDAsyncSocketSSLCipherSuites";
  104. #if TARGET_OS_IPHONE
  105. NSString *const GCDAsyncSocketSSLProtocolVersionMin = @"GCDAsyncSocketSSLProtocolVersionMin";
  106. NSString *const GCDAsyncSocketSSLProtocolVersionMax = @"GCDAsyncSocketSSLProtocolVersionMax";
  107. #else
  108. NSString *const GCDAsyncSocketSSLDiffieHellmanParameters = @"GCDAsyncSocketSSLDiffieHellmanParameters";
  109. #endif
  110. #endif
  111. enum GCDAsyncSocketFlags
  112. {
  113. kSocketStarted = 1 << 0, // If set, socket has been started (accepting/connecting)
  114. kConnected = 1 << 1, // If set, the socket is connected
  115. kForbidReadsWrites = 1 << 2, // If set, no new reads or writes are allowed
  116. kReadsPaused = 1 << 3, // If set, reads are paused due to possible timeout
  117. kWritesPaused = 1 << 4, // If set, writes are paused due to possible timeout
  118. kDisconnectAfterReads = 1 << 5, // If set, disconnect after no more reads are queued
  119. kDisconnectAfterWrites = 1 << 6, // If set, disconnect after no more writes are queued
  120. kSocketCanAcceptBytes = 1 << 7, // If set, we know socket can accept bytes. If unset, it's unknown.
  121. kReadSourceSuspended = 1 << 8, // If set, the read source is suspended
  122. kWriteSourceSuspended = 1 << 9, // If set, the write source is suspended
  123. kQueuedTLS = 1 << 10, // If set, we've queued an upgrade to TLS
  124. kStartingReadTLS = 1 << 11, // If set, we're waiting for TLS negotiation to complete
  125. kStartingWriteTLS = 1 << 12, // If set, we're waiting for TLS negotiation to complete
  126. kSocketSecure = 1 << 13, // If set, socket is using secure communication via SSL/TLS
  127. kSocketHasReadEOF = 1 << 14, // If set, we have read EOF from socket
  128. kReadStreamClosed = 1 << 15, // If set, we've read EOF plus prebuffer has been drained
  129. #if TARGET_OS_IPHONE
  130. kAddedStreamsToRunLoop = 1 << 16, // If set, CFStreams have been added to listener thread
  131. kUsingCFStreamForTLS = 1 << 17, // If set, we're forced to use CFStream instead of SecureTransport
  132. kSecureSocketHasBytesAvailable = 1 << 18, // If set, CFReadStream has notified us of bytes available
  133. #endif
  134. };
  135. enum GCDAsyncSocketConfig
  136. {
  137. kIPv4Disabled = 1 << 0, // If set, IPv4 is disabled
  138. kIPv6Disabled = 1 << 1, // If set, IPv6 is disabled
  139. kPreferIPv6 = 1 << 2, // If set, IPv6 is preferred over IPv4
  140. kAllowHalfDuplexConnection = 1 << 3, // If set, the socket will stay open even if the read stream closes
  141. };
  142. #if TARGET_OS_IPHONE
  143. static NSThread *cfstreamThread; // Used for CFStreams
  144. #endif
  145. @interface GCDAsyncSocket (Private)
  146. // Accepting
  147. - (BOOL)doAccept:(int)socketFD;
  148. // Connecting
  149. - (void)startConnectTimeout:(NSTimeInterval)timeout;
  150. - (void)endConnectTimeout;
  151. - (void)doConnectTimeout;
  152. - (void)lookup:(int)aConnectIndex host:(NSString *)host port:(uint16_t)port;
  153. - (void)lookup:(int)aConnectIndex didSucceedWithAddress4:(NSData *)address4 address6:(NSData *)address6;
  154. - (void)lookup:(int)aConnectIndex didFail:(NSError *)error;
  155. - (BOOL)connectWithAddress4:(NSData *)address4 address6:(NSData *)address6 error:(NSError **)errPtr;
  156. - (BOOL)connectWithAddressUN:(NSData *)address error:(NSError **)errPtr;
  157. - (void)didConnect:(int)aConnectIndex;
  158. - (void)didNotConnect:(int)aConnectIndex error:(NSError *)error;
  159. // Disconnect
  160. - (void)closeWithError:(NSError *)error;
  161. - (void)close;
  162. - (void)maybeClose;
  163. // Errors
  164. - (NSError *)badConfigError:(NSString *)msg;
  165. - (NSError *)badParamError:(NSString *)msg;
  166. - (NSError *)gaiError:(int)gai_error;
  167. - (NSError *)errnoError;
  168. - (NSError *)errnoErrorWithReason:(NSString *)reason;
  169. - (NSError *)connectTimeoutError;
  170. - (NSError *)otherError:(NSString *)msg;
  171. // Diagnostics
  172. - (NSString *)connectedHost4;
  173. - (NSString *)connectedHost6;
  174. - (uint16_t)connectedPort4;
  175. - (uint16_t)connectedPort6;
  176. - (NSString *)localHost4;
  177. - (NSString *)localHost6;
  178. - (uint16_t)localPort4;
  179. - (uint16_t)localPort6;
  180. - (NSString *)connectedHostFromSocket4:(int)socketFD;
  181. - (NSString *)connectedHostFromSocket6:(int)socketFD;
  182. - (uint16_t)connectedPortFromSocket4:(int)socketFD;
  183. - (uint16_t)connectedPortFromSocket6:(int)socketFD;
  184. - (NSURL *)connectedUrlFromSocketUN:(int)socketFD;
  185. - (NSString *)localHostFromSocket4:(int)socketFD;
  186. - (NSString *)localHostFromSocket6:(int)socketFD;
  187. - (uint16_t)localPortFromSocket4:(int)socketFD;
  188. - (uint16_t)localPortFromSocket6:(int)socketFD;
  189. // Utilities
  190. - (void)getInterfaceAddress4:(NSMutableData **)addr4Ptr
  191. address6:(NSMutableData **)addr6Ptr
  192. fromDescription:(NSString *)interfaceDescription
  193. port:(uint16_t)port;
  194. - (NSData *)getInterfaceAddressFromUrl:(NSURL *)url;
  195. - (void)setupReadAndWriteSourcesForNewlyConnectedSocket:(int)socketFD;
  196. - (void)suspendReadSource;
  197. - (void)resumeReadSource;
  198. - (void)suspendWriteSource;
  199. - (void)resumeWriteSource;
  200. // Reading
  201. - (void)maybeDequeueRead;
  202. - (void)flushSSLBuffers;
  203. - (void)doReadData;
  204. - (void)doReadEOF;
  205. - (void)completeCurrentRead;
  206. - (void)endCurrentRead;
  207. - (void)setupReadTimerWithTimeout:(NSTimeInterval)timeout;
  208. - (void)doReadTimeout;
  209. - (void)doReadTimeoutWithExtension:(NSTimeInterval)timeoutExtension;
  210. // Writing
  211. - (void)maybeDequeueWrite;
  212. - (void)doWriteData;
  213. - (void)completeCurrentWrite;
  214. - (void)endCurrentWrite;
  215. - (void)setupWriteTimerWithTimeout:(NSTimeInterval)timeout;
  216. - (void)doWriteTimeout;
  217. - (void)doWriteTimeoutWithExtension:(NSTimeInterval)timeoutExtension;
  218. // Security
  219. - (void)maybeStartTLS;
  220. #if SECURE_TRANSPORT_MAYBE_AVAILABLE
  221. - (void)ssl_startTLS;
  222. - (void)ssl_continueSSLHandshake;
  223. #endif
  224. #if TARGET_OS_IPHONE
  225. - (void)cf_startTLS;
  226. #endif
  227. // CFStream
  228. #if TARGET_OS_IPHONE
  229. + (void)startCFStreamThreadIfNeeded;
  230. - (BOOL)createReadAndWriteStream;
  231. - (BOOL)registerForStreamCallbacksIncludingReadWrite:(BOOL)includeReadWrite;
  232. - (BOOL)addStreamsToRunLoop;
  233. - (BOOL)openStreams;
  234. - (void)removeStreamsFromRunLoop;
  235. #endif
  236. // Class Methods
  237. + (NSString *)hostFromSockaddr4:(const struct sockaddr_in *)pSockaddr4;
  238. + (NSString *)hostFromSockaddr6:(const struct sockaddr_in6 *)pSockaddr6;
  239. + (uint16_t)portFromSockaddr4:(const struct sockaddr_in *)pSockaddr4;
  240. + (uint16_t)portFromSockaddr6:(const struct sockaddr_in6 *)pSockaddr6;
  241. + (NSURL *)urlFromSockaddrUN:(const struct sockaddr_un *)pSockaddr;
  242. @end
  243. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  244. #pragma mark -
  245. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  246. /**
  247. * A PreBuffer is used when there is more data available on the socket
  248. * than is being requested by current read request.
  249. * In this case we slurp up all data from the socket (to minimize sys calls),
  250. * and store additional yet unread data in a "prebuffer".
  251. *
  252. * The prebuffer is entirely drained before we read from the socket again.
  253. * In other words, a large chunk of data is written is written to the prebuffer.
  254. * The prebuffer is then drained via a series of one or more reads (for subsequent read request(s)).
  255. *
  256. * A ring buffer was once used for this purpose.
  257. * But a ring buffer takes up twice as much memory as needed (double the size for mirroring).
  258. * In fact, it generally takes up more than twice the needed size as everything has to be rounded up to vm_page_size.
  259. * And since the prebuffer is always completely drained after being written to, a full ring buffer isn't needed.
  260. *
  261. * The current design is very simple and straight-forward, while also keeping memory requirements lower.
  262. **/
  263. @interface GCDAsyncSocketPreBuffer : NSObject
  264. {
  265. uint8_t *preBuffer;
  266. size_t preBufferSize;
  267. uint8_t *readPointer;
  268. uint8_t *writePointer;
  269. }
  270. - (id)initWithCapacity:(size_t)numBytes;
  271. - (void)ensureCapacityForWrite:(size_t)numBytes;
  272. - (size_t)availableBytes;
  273. - (uint8_t *)readBuffer;
  274. - (void)getReadBuffer:(uint8_t **)bufferPtr availableBytes:(size_t *)availableBytesPtr;
  275. - (size_t)availableSpace;
  276. - (uint8_t *)writeBuffer;
  277. - (void)getWriteBuffer:(uint8_t **)bufferPtr availableSpace:(size_t *)availableSpacePtr;
  278. - (void)didRead:(size_t)bytesRead;
  279. - (void)didWrite:(size_t)bytesWritten;
  280. - (void)reset;
  281. @end
  282. @implementation GCDAsyncSocketPreBuffer
  283. - (id)initWithCapacity:(size_t)numBytes
  284. {
  285. if ((self = [super init]))
  286. {
  287. preBufferSize = numBytes;
  288. preBuffer = malloc(preBufferSize);
  289. readPointer = preBuffer;
  290. writePointer = preBuffer;
  291. }
  292. return self;
  293. }
  294. - (void)dealloc
  295. {
  296. if (preBuffer)
  297. free(preBuffer);
  298. }
  299. - (void)ensureCapacityForWrite:(size_t)numBytes
  300. {
  301. size_t availableSpace = preBufferSize - (writePointer - readPointer);
  302. if (numBytes > availableSpace)
  303. {
  304. size_t additionalBytes = numBytes - availableSpace;
  305. size_t newPreBufferSize = preBufferSize + additionalBytes;
  306. uint8_t *newPreBuffer = realloc(preBuffer, newPreBufferSize);
  307. size_t readPointerOffset = readPointer - preBuffer;
  308. size_t writePointerOffset = writePointer - preBuffer;
  309. preBuffer = newPreBuffer;
  310. preBufferSize = newPreBufferSize;
  311. readPointer = preBuffer + readPointerOffset;
  312. writePointer = preBuffer + writePointerOffset;
  313. }
  314. }
  315. - (size_t)availableBytes
  316. {
  317. return writePointer - readPointer;
  318. }
  319. - (uint8_t *)readBuffer
  320. {
  321. return readPointer;
  322. }
  323. - (void)getReadBuffer:(uint8_t **)bufferPtr availableBytes:(size_t *)availableBytesPtr
  324. {
  325. if (bufferPtr) *bufferPtr = readPointer;
  326. if (availableBytesPtr) *availableBytesPtr = writePointer - readPointer;
  327. }
  328. - (void)didRead:(size_t)bytesRead
  329. {
  330. readPointer += bytesRead;
  331. if (readPointer == writePointer)
  332. {
  333. // The prebuffer has been drained. Reset pointers.
  334. readPointer = preBuffer;
  335. writePointer = preBuffer;
  336. }
  337. }
  338. - (size_t)availableSpace
  339. {
  340. return preBufferSize - (writePointer - readPointer);
  341. }
  342. - (uint8_t *)writeBuffer
  343. {
  344. return writePointer;
  345. }
  346. - (void)getWriteBuffer:(uint8_t **)bufferPtr availableSpace:(size_t *)availableSpacePtr
  347. {
  348. if (bufferPtr) *bufferPtr = writePointer;
  349. if (availableSpacePtr) *availableSpacePtr = preBufferSize - (writePointer - readPointer);
  350. }
  351. - (void)didWrite:(size_t)bytesWritten
  352. {
  353. writePointer += bytesWritten;
  354. }
  355. - (void)reset
  356. {
  357. readPointer = preBuffer;
  358. writePointer = preBuffer;
  359. }
  360. @end
  361. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  362. #pragma mark -
  363. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  364. /**
  365. * The GCDAsyncReadPacket encompasses the instructions for any given read.
  366. * The content of a read packet allows the code to determine if we're:
  367. * - reading to a certain length
  368. * - reading to a certain separator
  369. * - or simply reading the first chunk of available data
  370. **/
  371. @interface GCDAsyncReadPacket : NSObject
  372. {
  373. @public
  374. NSMutableData *buffer;
  375. NSUInteger startOffset;
  376. NSUInteger bytesDone;
  377. NSUInteger maxLength;
  378. NSTimeInterval timeout;
  379. NSUInteger readLength;
  380. NSData *term;
  381. BOOL bufferOwner;
  382. NSUInteger originalBufferLength;
  383. long tag;
  384. }
  385. - (id)initWithData:(NSMutableData *)d
  386. startOffset:(NSUInteger)s
  387. maxLength:(NSUInteger)m
  388. timeout:(NSTimeInterval)t
  389. readLength:(NSUInteger)l
  390. terminator:(NSData *)e
  391. tag:(long)i;
  392. - (void)ensureCapacityForAdditionalDataOfLength:(NSUInteger)bytesToRead;
  393. - (NSUInteger)optimalReadLengthWithDefault:(NSUInteger)defaultValue shouldPreBuffer:(BOOL *)shouldPreBufferPtr;
  394. - (NSUInteger)readLengthForNonTermWithHint:(NSUInteger)bytesAvailable;
  395. - (NSUInteger)readLengthForTermWithHint:(NSUInteger)bytesAvailable shouldPreBuffer:(BOOL *)shouldPreBufferPtr;
  396. - (NSUInteger)readLengthForTermWithPreBuffer:(GCDAsyncSocketPreBuffer *)preBuffer found:(BOOL *)foundPtr;
  397. - (NSInteger)searchForTermAfterPreBuffering:(ssize_t)numBytes;
  398. @end
  399. @implementation GCDAsyncReadPacket
  400. - (id)initWithData:(NSMutableData *)d
  401. startOffset:(NSUInteger)s
  402. maxLength:(NSUInteger)m
  403. timeout:(NSTimeInterval)t
  404. readLength:(NSUInteger)l
  405. terminator:(NSData *)e
  406. tag:(long)i
  407. {
  408. if((self = [super init]))
  409. {
  410. bytesDone = 0;
  411. maxLength = m;
  412. timeout = t;
  413. readLength = l;
  414. term = [e copy];
  415. tag = i;
  416. if (d)
  417. {
  418. buffer = d;
  419. startOffset = s;
  420. bufferOwner = NO;
  421. originalBufferLength = [d length];
  422. }
  423. else
  424. {
  425. if (readLength > 0)
  426. buffer = [[NSMutableData alloc] initWithLength:readLength];
  427. else
  428. buffer = [[NSMutableData alloc] initWithLength:0];
  429. startOffset = 0;
  430. bufferOwner = YES;
  431. originalBufferLength = 0;
  432. }
  433. }
  434. return self;
  435. }
  436. /**
  437. * Increases the length of the buffer (if needed) to ensure a read of the given size will fit.
  438. **/
  439. - (void)ensureCapacityForAdditionalDataOfLength:(NSUInteger)bytesToRead
  440. {
  441. NSUInteger buffSize = [buffer length];
  442. NSUInteger buffUsed = startOffset + bytesDone;
  443. NSUInteger buffSpace = buffSize - buffUsed;
  444. if (bytesToRead > buffSpace)
  445. {
  446. NSUInteger buffInc = bytesToRead - buffSpace;
  447. [buffer increaseLengthBy:buffInc];
  448. }
  449. }
  450. /**
  451. * This method is used when we do NOT know how much data is available to be read from the socket.
  452. * This method returns the default value unless it exceeds the specified readLength or maxLength.
  453. *
  454. * Furthermore, the shouldPreBuffer decision is based upon the packet type,
  455. * and whether the returned value would fit in the current buffer without requiring a resize of the buffer.
  456. **/
  457. - (NSUInteger)optimalReadLengthWithDefault:(NSUInteger)defaultValue shouldPreBuffer:(BOOL *)shouldPreBufferPtr
  458. {
  459. NSUInteger result;
  460. if (readLength > 0)
  461. {
  462. // Read a specific length of data
  463. result = MIN(defaultValue, (readLength - bytesDone));
  464. // There is no need to prebuffer since we know exactly how much data we need to read.
  465. // Even if the buffer isn't currently big enough to fit this amount of data,
  466. // it would have to be resized eventually anyway.
  467. if (shouldPreBufferPtr)
  468. *shouldPreBufferPtr = NO;
  469. }
  470. else
  471. {
  472. // Either reading until we find a specified terminator,
  473. // or we're simply reading all available data.
  474. //
  475. // In other words, one of:
  476. //
  477. // - readDataToData packet
  478. // - readDataWithTimeout packet
  479. if (maxLength > 0)
  480. result = MIN(defaultValue, (maxLength - bytesDone));
  481. else
  482. result = defaultValue;
  483. // Since we don't know the size of the read in advance,
  484. // the shouldPreBuffer decision is based upon whether the returned value would fit
  485. // in the current buffer without requiring a resize of the buffer.
  486. //
  487. // This is because, in all likelyhood, the amount read from the socket will be less than the default value.
  488. // Thus we should avoid over-allocating the read buffer when we can simply use the pre-buffer instead.
  489. if (shouldPreBufferPtr)
  490. {
  491. NSUInteger buffSize = [buffer length];
  492. NSUInteger buffUsed = startOffset + bytesDone;
  493. NSUInteger buffSpace = buffSize - buffUsed;
  494. if (buffSpace >= result)
  495. *shouldPreBufferPtr = NO;
  496. else
  497. *shouldPreBufferPtr = YES;
  498. }
  499. }
  500. return result;
  501. }
  502. /**
  503. * For read packets without a set terminator, returns the amount of data
  504. * that can be read without exceeding the readLength or maxLength.
  505. *
  506. * The given parameter indicates the number of bytes estimated to be available on the socket,
  507. * which is taken into consideration during the calculation.
  508. *
  509. * The given hint MUST be greater than zero.
  510. **/
  511. - (NSUInteger)readLengthForNonTermWithHint:(NSUInteger)bytesAvailable
  512. {
  513. NSAssert(term == nil, @"This method does not apply to term reads");
  514. NSAssert(bytesAvailable > 0, @"Invalid parameter: bytesAvailable");
  515. if (readLength > 0)
  516. {
  517. // Read a specific length of data
  518. return MIN(bytesAvailable, (readLength - bytesDone));
  519. // No need to avoid resizing the buffer.
  520. // If the user provided their own buffer,
  521. // and told us to read a certain length of data that exceeds the size of the buffer,
  522. // then it is clear that our code will resize the buffer during the read operation.
  523. //
  524. // This method does not actually do any resizing.
  525. // The resizing will happen elsewhere if needed.
  526. }
  527. else
  528. {
  529. // Read all available data
  530. NSUInteger result = bytesAvailable;
  531. if (maxLength > 0)
  532. {
  533. result = MIN(result, (maxLength - bytesDone));
  534. }
  535. // No need to avoid resizing the buffer.
  536. // If the user provided their own buffer,
  537. // and told us to read all available data without giving us a maxLength,
  538. // then it is clear that our code might resize the buffer during the read operation.
  539. //
  540. // This method does not actually do any resizing.
  541. // The resizing will happen elsewhere if needed.
  542. return result;
  543. }
  544. }
  545. /**
  546. * For read packets with a set terminator, returns the amount of data
  547. * that can be read without exceeding the maxLength.
  548. *
  549. * The given parameter indicates the number of bytes estimated to be available on the socket,
  550. * which is taken into consideration during the calculation.
  551. *
  552. * To optimize memory allocations, mem copies, and mem moves
  553. * the shouldPreBuffer boolean value will indicate if the data should be read into a prebuffer first,
  554. * or if the data can be read directly into the read packet's buffer.
  555. **/
  556. - (NSUInteger)readLengthForTermWithHint:(NSUInteger)bytesAvailable shouldPreBuffer:(BOOL *)shouldPreBufferPtr
  557. {
  558. NSAssert(term != nil, @"This method does not apply to non-term reads");
  559. NSAssert(bytesAvailable > 0, @"Invalid parameter: bytesAvailable");
  560. NSUInteger result = bytesAvailable;
  561. if (maxLength > 0)
  562. {
  563. result = MIN(result, (maxLength - bytesDone));
  564. }
  565. // Should the data be read into the read packet's buffer, or into a pre-buffer first?
  566. //
  567. // One would imagine the preferred option is the faster one.
  568. // So which one is faster?
  569. //
  570. // Reading directly into the packet's buffer requires:
  571. // 1. Possibly resizing packet buffer (malloc/realloc)
  572. // 2. Filling buffer (read)
  573. // 3. Searching for term (memcmp)
  574. // 4. Possibly copying overflow into prebuffer (malloc/realloc, memcpy)
  575. //
  576. // Reading into prebuffer first:
  577. // 1. Possibly resizing prebuffer (malloc/realloc)
  578. // 2. Filling buffer (read)
  579. // 3. Searching for term (memcmp)
  580. // 4. Copying underflow into packet buffer (malloc/realloc, memcpy)
  581. // 5. Removing underflow from prebuffer (memmove)
  582. //
  583. // Comparing the performance of the two we can see that reading
  584. // data into the prebuffer first is slower due to the extra memove.
  585. //
  586. // However:
  587. // The implementation of NSMutableData is open source via core foundation's CFMutableData.
  588. // Decreasing the length of a mutable data object doesn't cause a realloc.
  589. // In other words, the capacity of a mutable data object can grow, but doesn't shrink.
  590. //
  591. // This means the prebuffer will rarely need a realloc.
  592. // The packet buffer, on the other hand, may often need a realloc.
  593. // This is especially true if we are the buffer owner.
  594. // Furthermore, if we are constantly realloc'ing the packet buffer,
  595. // and then moving the overflow into the prebuffer,
  596. // then we're consistently over-allocating memory for each term read.
  597. // And now we get into a bit of a tradeoff between speed and memory utilization.
  598. //
  599. // The end result is that the two perform very similarly.
  600. // And we can answer the original question very simply by another means.
  601. //
  602. // If we can read all the data directly into the packet's buffer without resizing it first,
  603. // then we do so. Otherwise we use the prebuffer.
  604. if (shouldPreBufferPtr)
  605. {
  606. NSUInteger buffSize = [buffer length];
  607. NSUInteger buffUsed = startOffset + bytesDone;
  608. if ((buffSize - buffUsed) >= result)
  609. *shouldPreBufferPtr = NO;
  610. else
  611. *shouldPreBufferPtr = YES;
  612. }
  613. return result;
  614. }
  615. /**
  616. * For read packets with a set terminator,
  617. * returns the amount of data that can be read from the given preBuffer,
  618. * without going over a terminator or the maxLength.
  619. *
  620. * It is assumed the terminator has not already been read.
  621. **/
  622. - (NSUInteger)readLengthForTermWithPreBuffer:(GCDAsyncSocketPreBuffer *)preBuffer found:(BOOL *)foundPtr
  623. {
  624. NSAssert(term != nil, @"This method does not apply to non-term reads");
  625. NSAssert([preBuffer availableBytes] > 0, @"Invoked with empty pre buffer!");
  626. // We know that the terminator, as a whole, doesn't exist in our own buffer.
  627. // But it is possible that a _portion_ of it exists in our buffer.
  628. // So we're going to look for the terminator starting with a portion of our own buffer.
  629. //
  630. // Example:
  631. //
  632. // term length = 3 bytes
  633. // bytesDone = 5 bytes
  634. // preBuffer length = 5 bytes
  635. //
  636. // If we append the preBuffer to our buffer,
  637. // it would look like this:
  638. //
  639. // ---------------------
  640. // |B|B|B|B|B|P|P|P|P|P|
  641. // ---------------------
  642. //
  643. // So we start our search here:
  644. //
  645. // ---------------------
  646. // |B|B|B|B|B|P|P|P|P|P|
  647. // -------^-^-^---------
  648. //
  649. // And move forwards...
  650. //
  651. // ---------------------
  652. // |B|B|B|B|B|P|P|P|P|P|
  653. // ---------^-^-^-------
  654. //
  655. // Until we find the terminator or reach the end.
  656. //
  657. // ---------------------
  658. // |B|B|B|B|B|P|P|P|P|P|
  659. // ---------------^-^-^-
  660. BOOL found = NO;
  661. NSUInteger termLength = [term length];
  662. NSUInteger preBufferLength = [preBuffer availableBytes];
  663. if ((bytesDone + preBufferLength) < termLength)
  664. {
  665. // Not enough data for a full term sequence yet
  666. return preBufferLength;
  667. }
  668. NSUInteger maxPreBufferLength;
  669. if (maxLength > 0) {
  670. maxPreBufferLength = MIN(preBufferLength, (maxLength - bytesDone));
  671. // Note: maxLength >= termLength
  672. }
  673. else {
  674. maxPreBufferLength = preBufferLength;
  675. }
  676. uint8_t seq[termLength];
  677. const void *termBuf = [term bytes];
  678. NSUInteger bufLen = MIN(bytesDone, (termLength - 1));
  679. uint8_t *buf = (uint8_t *)[buffer mutableBytes] + startOffset + bytesDone - bufLen;
  680. NSUInteger preLen = termLength - bufLen;
  681. const uint8_t *pre = [preBuffer readBuffer];
  682. NSUInteger loopCount = bufLen + maxPreBufferLength - termLength + 1; // Plus one. See example above.
  683. NSUInteger result = maxPreBufferLength;
  684. NSUInteger i;
  685. for (i = 0; i < loopCount; i++)
  686. {
  687. if (bufLen > 0)
  688. {
  689. // Combining bytes from buffer and preBuffer
  690. memcpy(seq, buf, bufLen);
  691. memcpy(seq + bufLen, pre, preLen);
  692. if (memcmp(seq, termBuf, termLength) == 0)
  693. {
  694. result = preLen;
  695. found = YES;
  696. break;
  697. }
  698. buf++;
  699. bufLen--;
  700. preLen++;
  701. }
  702. else
  703. {
  704. // Comparing directly from preBuffer
  705. if (memcmp(pre, termBuf, termLength) == 0)
  706. {
  707. NSUInteger preOffset = pre - [preBuffer readBuffer]; // pointer arithmetic
  708. result = preOffset + termLength;
  709. found = YES;
  710. break;
  711. }
  712. pre++;
  713. }
  714. }
  715. // There is no need to avoid resizing the buffer in this particular situation.
  716. if (foundPtr) *foundPtr = found;
  717. return result;
  718. }
  719. /**
  720. * For read packets with a set terminator, scans the packet buffer for the term.
  721. * It is assumed the terminator had not been fully read prior to the new bytes.
  722. *
  723. * If the term is found, the number of excess bytes after the term are returned.
  724. * If the term is not found, this method will return -1.
  725. *
  726. * Note: A return value of zero means the term was found at the very end.
  727. *
  728. * Prerequisites:
  729. * The given number of bytes have been added to the end of our buffer.
  730. * Our bytesDone variable has NOT been changed due to the prebuffered bytes.
  731. **/
  732. - (NSInteger)searchForTermAfterPreBuffering:(ssize_t)numBytes
  733. {
  734. NSAssert(term != nil, @"This method does not apply to non-term reads");
  735. // The implementation of this method is very similar to the above method.
  736. // See the above method for a discussion of the algorithm used here.
  737. uint8_t *buff = [buffer mutableBytes];
  738. NSUInteger buffLength = bytesDone + numBytes;
  739. const void *termBuff = [term bytes];
  740. NSUInteger termLength = [term length];
  741. // Note: We are dealing with unsigned integers,
  742. // so make sure the math doesn't go below zero.
  743. NSUInteger i = ((buffLength - numBytes) >= termLength) ? (buffLength - numBytes - termLength + 1) : 0;
  744. while (i + termLength <= buffLength)
  745. {
  746. uint8_t *subBuffer = buff + startOffset + i;
  747. if (memcmp(subBuffer, termBuff, termLength) == 0)
  748. {
  749. return buffLength - (i + termLength);
  750. }
  751. i++;
  752. }
  753. return -1;
  754. }
  755. @end
  756. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  757. #pragma mark -
  758. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  759. /**
  760. * The GCDAsyncWritePacket encompasses the instructions for any given write.
  761. **/
  762. @interface GCDAsyncWritePacket : NSObject
  763. {
  764. @public
  765. NSData *buffer;
  766. NSUInteger bytesDone;
  767. long tag;
  768. NSTimeInterval timeout;
  769. }
  770. - (id)initWithData:(NSData *)d timeout:(NSTimeInterval)t tag:(long)i;
  771. @end
  772. @implementation GCDAsyncWritePacket
  773. - (id)initWithData:(NSData *)d timeout:(NSTimeInterval)t tag:(long)i
  774. {
  775. if((self = [super init]))
  776. {
  777. buffer = d; // Retain not copy. For performance as documented in header file.
  778. bytesDone = 0;
  779. timeout = t;
  780. tag = i;
  781. }
  782. return self;
  783. }
  784. @end
  785. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  786. #pragma mark -
  787. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  788. /**
  789. * The GCDAsyncSpecialPacket encompasses special instructions for interruptions in the read/write queues.
  790. * This class my be altered to support more than just TLS in the future.
  791. **/
  792. @interface GCDAsyncSpecialPacket : NSObject
  793. {
  794. @public
  795. NSDictionary *tlsSettings;
  796. }
  797. - (id)initWithTLSSettings:(NSDictionary *)settings;
  798. @end
  799. @implementation GCDAsyncSpecialPacket
  800. - (id)initWithTLSSettings:(NSDictionary *)settings
  801. {
  802. if((self = [super init]))
  803. {
  804. tlsSettings = [settings copy];
  805. }
  806. return self;
  807. }
  808. @end
  809. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  810. #pragma mark -
  811. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  812. @implementation GCDAsyncSocket
  813. - (id)init
  814. {
  815. return [self initWithDelegate:nil delegateQueue:NULL socketQueue:NULL];
  816. }
  817. - (id)initWithSocketQueue:(dispatch_queue_t)sq
  818. {
  819. return [self initWithDelegate:nil delegateQueue:NULL socketQueue:sq];
  820. }
  821. - (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq
  822. {
  823. return [self initWithDelegate:aDelegate delegateQueue:dq socketQueue:NULL];
  824. }
  825. - (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq socketQueue:(dispatch_queue_t)sq
  826. {
  827. if((self = [super init]))
  828. {
  829. delegate = aDelegate;
  830. delegateQueue = dq;
  831. #if NEEDS_DISPATCH_RETAIN_RELEASE
  832. if (dq) dispatch_retain(dq);
  833. #endif
  834. socket4FD = SOCKET_NULL;
  835. socket6FD = SOCKET_NULL;
  836. socketUN = SOCKET_NULL;
  837. socketUrl = nil;
  838. connectIndex = 0;
  839. if (sq)
  840. {
  841. NSAssert(sq != dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0),
  842. @"The given socketQueue parameter must not be a concurrent queue.");
  843. NSAssert(sq != dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),
  844. @"The given socketQueue parameter must not be a concurrent queue.");
  845. NSAssert(sq != dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
  846. @"The given socketQueue parameter must not be a concurrent queue.");
  847. socketQueue = sq;
  848. #if NEEDS_DISPATCH_RETAIN_RELEASE
  849. dispatch_retain(sq);
  850. #endif
  851. }
  852. else
  853. {
  854. socketQueue = dispatch_queue_create([GCDAsyncSocketQueueName UTF8String], NULL);
  855. }
  856. readQueue = [[NSMutableArray alloc] initWithCapacity:5];
  857. currentRead = nil;
  858. writeQueue = [[NSMutableArray alloc] initWithCapacity:5];
  859. currentWrite = nil;
  860. preBuffer = [[GCDAsyncSocketPreBuffer alloc] initWithCapacity:(1024 * 4)];
  861. }
  862. return self;
  863. }
  864. - (void)dealloc
  865. {
  866. LogInfo(@"%@ - %@ (start)", THIS_METHOD, self);
  867. if (dispatch_get_current_queue() == socketQueue)
  868. {
  869. [self closeWithError:nil];
  870. }
  871. else
  872. {
  873. dispatch_sync(socketQueue, ^{
  874. [self closeWithError:nil];
  875. });
  876. }
  877. delegate = nil;
  878. #if NEEDS_DISPATCH_RETAIN_RELEASE
  879. if (delegateQueue) dispatch_release(delegateQueue);
  880. #endif
  881. delegateQueue = NULL;
  882. #if NEEDS_DISPATCH_RETAIN_RELEASE
  883. if (socketQueue) dispatch_release(socketQueue);
  884. #endif
  885. socketQueue = NULL;
  886. LogInfo(@"%@ - %@ (finish)", THIS_METHOD, self);
  887. }
  888. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  889. #pragma mark Configuration
  890. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  891. - (id)delegate
  892. {
  893. if (dispatch_get_current_queue() == socketQueue)
  894. {
  895. return delegate;
  896. }
  897. else
  898. {
  899. __block id result;
  900. dispatch_sync(socketQueue, ^{
  901. result = delegate;
  902. });
  903. return result;
  904. }
  905. }
  906. - (void)setDelegate:(id)newDelegate synchronously:(BOOL)synchronously
  907. {
  908. dispatch_block_t block = ^{
  909. delegate = newDelegate;
  910. };
  911. if (dispatch_get_current_queue() == socketQueue) {
  912. block();
  913. }
  914. else {
  915. if (synchronously)
  916. dispatch_sync(socketQueue, block);
  917. else
  918. dispatch_async(socketQueue, block);
  919. }
  920. }
  921. - (void)setDelegate:(id)newDelegate
  922. {
  923. [self setDelegate:newDelegate synchronously:NO];
  924. }
  925. - (void)synchronouslySetDelegate:(id)newDelegate
  926. {
  927. [self setDelegate:newDelegate synchronously:YES];
  928. }
  929. - (dispatch_queue_t)delegateQueue
  930. {
  931. if (dispatch_get_current_queue() == socketQueue)
  932. {
  933. return delegateQueue;
  934. }
  935. else
  936. {
  937. __block dispatch_queue_t result;
  938. dispatch_sync(socketQueue, ^{
  939. result = delegateQueue;
  940. });
  941. return result;
  942. }
  943. }
  944. - (void)setDelegateQueue:(dispatch_queue_t)newDelegateQueue synchronously:(BOOL)synchronously
  945. {
  946. dispatch_block_t block = ^{
  947. #if NEEDS_DISPATCH_RETAIN_RELEASE
  948. if (delegateQueue) dispatch_release(delegateQueue);
  949. if (newDelegateQueue) dispatch_retain(newDelegateQueue);
  950. #endif
  951. delegateQueue = newDelegateQueue;
  952. };
  953. if (dispatch_get_current_queue() == socketQueue) {
  954. block();
  955. }
  956. else {
  957. if (synchronously)
  958. dispatch_sync(socketQueue, block);
  959. else
  960. dispatch_async(socketQueue, block);
  961. }
  962. }
  963. - (void)setDelegateQueue:(dispatch_queue_t)newDelegateQueue
  964. {
  965. [self setDelegateQueue:newDelegateQueue synchronously:NO];
  966. }
  967. - (void)synchronouslySetDelegateQueue:(dispatch_queue_t)newDelegateQueue
  968. {
  969. [self setDelegateQueue:newDelegateQueue synchronously:YES];
  970. }
  971. - (void)getDelegate:(id *)delegatePtr delegateQueue:(dispatch_queue_t *)delegateQueuePtr
  972. {
  973. if (dispatch_get_current_queue() == socketQueue)
  974. {
  975. if (delegatePtr) *delegatePtr = delegate;
  976. if (delegateQueuePtr) *delegateQueuePtr = delegateQueue;
  977. }
  978. else
  979. {
  980. __block id dPtr = NULL;
  981. __block dispatch_queue_t dqPtr = NULL;
  982. dispatch_sync(socketQueue, ^{
  983. dPtr = delegate;
  984. dqPtr = delegateQueue;
  985. });
  986. if (delegatePtr) *delegatePtr = dPtr;
  987. if (delegateQueuePtr) *delegateQueuePtr = dqPtr;
  988. }
  989. }
  990. - (void)setDelegate:(id)newDelegate delegateQueue:(dispatch_queue_t)newDelegateQueue synchronously:(BOOL)synchronously
  991. {
  992. dispatch_block_t block = ^{
  993. delegate = newDelegate;
  994. #if NEEDS_DISPATCH_RETAIN_RELEASE
  995. if (delegateQueue) dispatch_release(delegateQueue);
  996. if (newDelegateQueue) dispatch_retain(newDelegateQueue);
  997. #endif
  998. delegateQueue = newDelegateQueue;
  999. };
  1000. if (dispatch_get_current_queue() == socketQueue) {
  1001. block();
  1002. }
  1003. else {
  1004. if (synchronously)
  1005. dispatch_sync(socketQueue, block);
  1006. else
  1007. dispatch_async(socketQueue, block);
  1008. }
  1009. }
  1010. - (void)setDelegate:(id)newDelegate delegateQueue:(dispatch_queue_t)newDelegateQueue
  1011. {
  1012. [self setDelegate:newDelegate delegateQueue:newDelegateQueue synchronously:NO];
  1013. }
  1014. - (void)synchronouslySetDelegate:(id)newDelegate delegateQueue:(dispatch_queue_t)newDelegateQueue
  1015. {
  1016. [self setDelegate:newDelegate delegateQueue:newDelegateQueue synchronously:YES];
  1017. }
  1018. - (BOOL)autoDisconnectOnClosedReadStream
  1019. {
  1020. // Note: YES means kAllowHalfDuplexConnection is OFF
  1021. if (dispatch_get_current_queue() == socketQueue)
  1022. {
  1023. return ((config & kAllowHalfDuplexConnection) == 0);
  1024. }
  1025. else
  1026. {
  1027. __block BOOL result;
  1028. dispatch_sync(socketQueue, ^{
  1029. result = ((config & kAllowHalfDuplexConnection) == 0);
  1030. });
  1031. return result;
  1032. }
  1033. }
  1034. - (void)setAutoDisconnectOnClosedReadStream:(BOOL)flag
  1035. {
  1036. // Note: YES means kAllowHalfDuplexConnection is OFF
  1037. dispatch_block_t block = ^{
  1038. if (flag)
  1039. config &= ~kAllowHalfDuplexConnection;
  1040. else
  1041. config |= kAllowHalfDuplexConnection;
  1042. };
  1043. if (dispatch_get_current_queue() == socketQueue)
  1044. block();
  1045. else
  1046. dispatch_async(socketQueue, block);
  1047. }
  1048. - (BOOL)isIPv4Enabled
  1049. {
  1050. // Note: YES means kIPv4Disabled is OFF
  1051. if (dispatch_get_current_queue() == socketQueue)
  1052. {
  1053. return ((config & kIPv4Disabled) == 0);
  1054. }
  1055. else
  1056. {
  1057. __block BOOL result;
  1058. dispatch_sync(socketQueue, ^{
  1059. result = ((config & kIPv4Disabled) == 0);
  1060. });
  1061. return result;
  1062. }
  1063. }
  1064. - (void)setIPv4Enabled:(BOOL)flag
  1065. {
  1066. // Note: YES means kIPv4Disabled is OFF
  1067. dispatch_block_t block = ^{
  1068. if (flag)
  1069. config &= ~kIPv4Disabled;
  1070. else
  1071. config |= kIPv4Disabled;
  1072. };
  1073. if (dispatch_get_current_queue() == socketQueue)
  1074. block();
  1075. else
  1076. dispatch_async(socketQueue, block);
  1077. }
  1078. - (BOOL)isIPv6Enabled
  1079. {
  1080. // Note: YES means kIPv6Disabled is OFF
  1081. if (dispatch_get_current_queue() == socketQueue)
  1082. {
  1083. return ((config & kIPv6Disabled) == 0);
  1084. }
  1085. else
  1086. {
  1087. __block BOOL result;
  1088. dispatch_sync(socketQueue, ^{
  1089. result = ((config & kIPv6Disabled) == 0);
  1090. });
  1091. return result;
  1092. }
  1093. }
  1094. - (void)setIPv6Enabled:(BOOL)flag
  1095. {
  1096. // Note: YES means kIPv6Disabled is OFF
  1097. dispatch_block_t block = ^{
  1098. if (flag)
  1099. config &= ~kIPv6Disabled;
  1100. else
  1101. config |= kIPv6Disabled;
  1102. };
  1103. if (dispatch_get_current_queue() == socketQueue)
  1104. block();
  1105. else
  1106. dispatch_async(socketQueue, block);
  1107. }
  1108. - (BOOL)isIPv4PreferredOverIPv6
  1109. {
  1110. // Note: YES means kPreferIPv6 is OFF
  1111. if (dispatch_get_current_queue() == socketQueue)
  1112. {
  1113. return ((config & kPreferIPv6) == 0);
  1114. }
  1115. else
  1116. {
  1117. __block BOOL result;
  1118. dispatch_sync(socketQueue, ^{
  1119. result = ((config & kPreferIPv6) == 0);
  1120. });
  1121. return result;
  1122. }
  1123. }
  1124. - (void)setPreferIPv4OverIPv6:(BOOL)flag
  1125. {
  1126. // Note: YES means kPreferIPv6 is OFF
  1127. dispatch_block_t block = ^{
  1128. if (flag)
  1129. config &= ~kPreferIPv6;
  1130. else
  1131. config |= kPreferIPv6;
  1132. };
  1133. if (dispatch_get_current_queue() == socketQueue)
  1134. block();
  1135. else
  1136. dispatch_async(socketQueue, block);
  1137. }
  1138. - (id)userData
  1139. {
  1140. __block id result = nil;
  1141. dispatch_block_t block = ^{
  1142. result = userData;
  1143. };
  1144. if (dispatch_get_current_queue() == socketQueue)
  1145. block();
  1146. else
  1147. dispatch_sync(socketQueue, block);
  1148. return result;
  1149. }
  1150. - (void)setUserData:(id)arbitraryUserData
  1151. {
  1152. dispatch_block_t block = ^{
  1153. if (userData != arbitraryUserData)
  1154. {
  1155. userData = arbitraryUserData;
  1156. }
  1157. };
  1158. if (dispatch_get_current_queue() == socketQueue)
  1159. block();
  1160. else
  1161. dispatch_async(socketQueue, block);
  1162. }
  1163. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1164. #pragma mark Accepting
  1165. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1166. - (BOOL)acceptOnPort:(uint16_t)port error:(NSError **)errPtr
  1167. {
  1168. return [self acceptOnInterface:nil port:port error:errPtr];
  1169. }
  1170. - (BOOL)acceptOnInterface:(NSString *)inInterface port:(uint16_t)port error:(NSError **)errPtr
  1171. {
  1172. LogTrace();
  1173. // Just in-case interface parameter is immutable.
  1174. NSString *interface = [inInterface copy];
  1175. __block BOOL result = NO;
  1176. __block NSError *err = nil;
  1177. // CreateSocket Block
  1178. // This block will be invoked within the dispatch block below.
  1179. int(^createSocket)(int, NSData*) = ^int (int domain, NSData *interfaceAddr) {
  1180. int socketFD = socket(domain, SOCK_STREAM, 0);
  1181. if (socketFD == SOCKET_NULL)
  1182. {
  1183. NSString *reason = @"Error in socket() function";
  1184. err = [self errnoErrorWithReason:reason];
  1185. return SOCKET_NULL;
  1186. }
  1187. int status;
  1188. // Set socket options
  1189. status = fcntl(socketFD, F_SETFL, O_NONBLOCK);
  1190. if (status == -1)
  1191. {
  1192. NSString *reason = @"Error enabling non-blocking IO on socket (fcntl)";
  1193. err = [self errnoErrorWithReason:reason];
  1194. LogVerbose(@"close(socketFD)");
  1195. close(socketFD);
  1196. return SOCKET_NULL;
  1197. }
  1198. int reuseOn = 1;
  1199. status = setsockopt(socketFD, SOL_SOCKET, SO_REUSEADDR, &reuseOn, sizeof(reuseOn));
  1200. if (status == -1)
  1201. {
  1202. NSString *reason = @"Error enabling address reuse (setsockopt)";
  1203. err = [self errnoErrorWithReason:reason];
  1204. LogVerbose(@"close(socketFD)");
  1205. close(socketFD);
  1206. return SOCKET_NULL;
  1207. }
  1208. // Bind socket
  1209. const struct sockaddr *addr = (const struct sockaddr *)[interfaceAddr bytes];
  1210. status = bind(socketFD, addr, addr->sa_len);
  1211. if (status == -1)
  1212. {
  1213. NSString *reason = @"Error in bind() function";
  1214. err = [self errnoErrorWithReason:reason];
  1215. LogVerbose(@"close(socketFD)");
  1216. close(socketFD);
  1217. return SOCKET_NULL;
  1218. }
  1219. // Listen
  1220. status = listen(socketFD, 1024);
  1221. if (status == -1)
  1222. {
  1223. NSString *reason = @"Error in listen() function";
  1224. err = [self errnoErrorWithReason:reason];
  1225. LogVerbose(@"close(socketFD)");
  1226. close(socketFD);
  1227. return SOCKET_NULL;
  1228. }
  1229. return socketFD;
  1230. };
  1231. // Create dispatch block and run on socketQueue
  1232. dispatch_block_t block = ^{ @autoreleasepool {
  1233. if (delegate == nil) // Must have delegate set
  1234. {
  1235. NSString *msg = @"Attempting to accept without a delegate. Set a delegate first.";
  1236. err = [self badConfigError:msg];
  1237. return_from_block;
  1238. }
  1239. if (delegateQueue == NULL) // Must have delegate queue set
  1240. {
  1241. NSString *msg = @"Attempting to accept without a delegate queue. Set a delegate queue first.";
  1242. err = [self badConfigError:msg];
  1243. return_from_block;
  1244. }
  1245. BOOL isIPv4Disabled = (config & kIPv4Disabled) ? YES : NO;
  1246. BOOL isIPv6Disabled = (config & kIPv6Disabled) ? YES : NO;
  1247. if (isIPv4Disabled && isIPv6Disabled) // Must have IPv4 or IPv6 enabled
  1248. {
  1249. NSString *msg = @"Both IPv4 and IPv6 have been disabled. Must enable at least one protocol first.";
  1250. err = [self badConfigError:msg];
  1251. return_from_block;
  1252. }
  1253. if (![self isDisconnected]) // Must be disconnected
  1254. {
  1255. NSString *msg = @"Attempting to accept while connected or accepting connections. Disconnect first.";
  1256. err = [self badConfigError:msg];
  1257. return_from_block;
  1258. }
  1259. // Clear queues (spurious read/write requests post disconnect)
  1260. [readQueue removeAllObjects];
  1261. [writeQueue removeAllObjects];
  1262. // Resolve interface from description
  1263. NSMutableData *interface4 = nil;
  1264. NSMutableData *interface6 = nil;
  1265. [self getInterfaceAddress4:&interface4 address6:&interface6 fromDescription:interface port:port];
  1266. if ((interface4 == nil) && (interface6 == nil))
  1267. {
  1268. NSString *msg = @"Unknown interface. Specify valid interface by name (e.g. \"en1\") or IP address.";
  1269. err = [self badParamError:msg];
  1270. return_from_block;
  1271. }
  1272. if (isIPv4Disabled && (interface6 == nil))
  1273. {
  1274. NSString *msg = @"IPv4 has been disabled and specified interface doesn't support IPv6.";
  1275. err = [self badParamError:msg];
  1276. return_from_block;
  1277. }
  1278. if (isIPv6Disabled && (interface4 == nil))
  1279. {
  1280. NSString *msg = @"IPv6 has been disabled and specified interface doesn't support IPv4.";
  1281. err = [self badParamError:msg];
  1282. return_from_block;
  1283. }
  1284. BOOL enableIPv4 = !isIPv4Disabled && (interface4 != nil);
  1285. BOOL enableIPv6 = !isIPv6Disabled && (interface6 != nil);
  1286. // Create sockets, configure, bind, and listen
  1287. if (enableIPv4)
  1288. {
  1289. LogVerbose(@"Creating IPv4 socket");
  1290. socket4FD = createSocket(AF_INET, interface4);
  1291. if (socket4FD == SOCKET_NULL)
  1292. {
  1293. return_from_block;
  1294. }
  1295. }
  1296. if (enableIPv6)
  1297. {
  1298. LogVerbose(@"Creating IPv6 socket");
  1299. if (enableIPv4 && (port == 0))
  1300. {
  1301. // No specific port was specified, so we allowed the OS to pick an available port for us.
  1302. // Now we need to make sure the IPv6 socket listens on the same port as the IPv4 socket.
  1303. struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)[interface6 mutableBytes];
  1304. addr6->sin6_port = htons([self localPort4]);
  1305. }
  1306. socket6FD = createSocket(AF_INET6, interface6);
  1307. if (socket6FD == SOCKET_NULL)
  1308. {
  1309. if (socket4FD != SOCKET_NULL)
  1310. {
  1311. LogVerbose(@"close(socket4FD)");
  1312. close(socket4FD);
  1313. }
  1314. return_from_block;
  1315. }
  1316. }
  1317. // Create accept sources
  1318. if (enableIPv4)
  1319. {
  1320. accept4Source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, socket4FD, 0, socketQueue);
  1321. int socketFD = socket4FD;
  1322. dispatch_source_t acceptSource = accept4Source;
  1323. dispatch_source_set_event_handler(accept4Source, ^{ @autoreleasepool {
  1324. LogVerbose(@"event4Block");
  1325. unsigned long i = 0;
  1326. unsigned long numPendingConnections = dispatch_source_get_data(acceptSource);
  1327. LogVerbose(@"numPendingConnections: %lu", numPendingConnections);
  1328. while ([self doAccept:socketFD] && (++i < numPendingConnections));
  1329. }});
  1330. dispatch_source_set_cancel_handler(accept4Source, ^{
  1331. #if NEEDS_DISPATCH_RETAIN_RELEASE
  1332. LogVerbose(@"dispatch_release(accept4Source)");
  1333. dispatch_release(acceptSource);
  1334. #endif
  1335. LogVerbose(@"close(socket4FD)");
  1336. close(socketFD);
  1337. });
  1338. LogVerbose(@"dispatch_resume(accept4Source)");
  1339. dispatch_resume(accept4Source);
  1340. }
  1341. if (enableIPv6)
  1342. {
  1343. accept6Source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, socket6FD, 0, socketQueue);
  1344. int socketFD = socket6FD;
  1345. dispatch_source_t acceptSource = accept6Source;
  1346. dispatch_source_set_event_handler(accept6Source, ^{ @autoreleasepool {
  1347. LogVerbose(@"event6Block");
  1348. unsigned long i = 0;
  1349. unsigned long numPendingConnections = dispatch_source_get_data(acceptSource);
  1350. LogVerbose(@"numPendingConnections: %lu", numPendingConnections);
  1351. while ([self doAccept:socketFD] && (++i < numPendingConnections));
  1352. }});
  1353. dispatch_source_set_cancel_handler(accept6Source, ^{
  1354. #if NEEDS_DISPATCH_RETAIN_RELEASE
  1355. LogVerbose(@"dispatch_release(accept6Source)");
  1356. dispatch_release(acceptSource);
  1357. #endif
  1358. LogVerbose(@"close(socket6FD)");
  1359. close(socketFD);
  1360. });
  1361. LogVerbose(@"dispatch_resume(accept6Source)");
  1362. dispatch_resume(accept6Source);
  1363. }
  1364. flags |= kSocketStarted;
  1365. result = YES;
  1366. }};
  1367. if (dispatch_get_current_queue() == socketQueue)
  1368. block();
  1369. else
  1370. dispatch_sync(socketQueue, block);
  1371. if (result == NO)
  1372. {
  1373. LogInfo(@"Error in accept: %@", err);
  1374. if (errPtr)
  1375. *errPtr = err;
  1376. }
  1377. return result;
  1378. }
  1379. - (BOOL)acceptOnUrl:(NSURL *)url error:(NSError **)errPtr;
  1380. {
  1381. LogTrace();
  1382. __block BOOL result = NO;
  1383. __block NSError *err = nil;
  1384. // CreateSocket Block
  1385. // This block will be invoked within the dispatch block below.
  1386. int(^createSocket)(int, NSData*) = ^int (int domain, NSData *interfaceAddr) {
  1387. int socketFD = socket(domain, SOCK_STREAM, 0);
  1388. if (socketFD == SOCKET_NULL)
  1389. {
  1390. NSString *reason = @"Error in socket() function";
  1391. err = [self errnoErrorWithReason:reason];
  1392. return SOCKET_NULL;
  1393. }
  1394. int status;
  1395. // Set socket options
  1396. status = fcntl(socketFD, F_SETFL, O_NONBLOCK);
  1397. if (status == -1)
  1398. {
  1399. NSString *reason = @"Error enabling non-blocking IO on socket (fcntl)";
  1400. err = [self errnoErrorWithReason:reason];
  1401. LogVerbose(@"close(socketFD)");
  1402. close(socketFD);
  1403. return SOCKET_NULL;
  1404. }
  1405. int reuseOn = 1;
  1406. status = setsockopt(socketFD, SOL_SOCKET, SO_REUSEADDR, &reuseOn, sizeof(reuseOn));
  1407. if (status == -1)
  1408. {
  1409. NSString *reason = @"Error enabling address reuse (setsockopt)";
  1410. err = [self errnoErrorWithReason:reason];
  1411. LogVerbose(@"close(socketFD)");
  1412. close(socketFD);
  1413. return SOCKET_NULL;
  1414. }
  1415. // Bind socket
  1416. status = bind(socketFD, (const struct sockaddr *)[interfaceAddr bytes], (socklen_t)[interfaceAddr length]);
  1417. if (status == -1)
  1418. {
  1419. NSString *reason = @"Error in bind() function";
  1420. err = [self errnoErrorWithReason:reason];
  1421. LogVerbose(@"close(socketFD)");
  1422. close(socketFD);
  1423. return SOCKET_NULL;
  1424. }
  1425. // Listen
  1426. status = listen(socketFD, 1024);
  1427. if (status == -1)
  1428. {
  1429. NSString *reason = @"Error in listen() function";
  1430. err = [self errnoErrorWithReason:reason];
  1431. LogVerbose(@"close(socketFD)");
  1432. close(socketFD);
  1433. return SOCKET_NULL;
  1434. }
  1435. return socketFD;
  1436. };
  1437. // Create dispatch block and run on socketQueue
  1438. dispatch_block_t block = ^{ @autoreleasepool {
  1439. if (delegate == nil) // Must have delegate set
  1440. {
  1441. NSString *msg = @"Attempting to accept without a delegate. Set a delegate first.";
  1442. err = [self badConfigError:msg];
  1443. return_from_block;
  1444. }
  1445. if (delegateQueue == NULL) // Must have delegate queue set
  1446. {
  1447. NSString *msg = @"Attempting to accept without a delegate queue. Set a delegate queue first.";
  1448. err = [self badConfigError:msg];
  1449. return_from_block;
  1450. }
  1451. if (![self isDisconnected]) // Must be disconnected
  1452. {
  1453. NSString *msg = @"Attempting to accept while connected or accepting connections. Disconnect first.";
  1454. err = [self badConfigError:msg];
  1455. return_from_block;
  1456. }
  1457. // Clear queues (spurious read/write requests post disconnect)
  1458. [readQueue removeAllObjects];
  1459. [writeQueue removeAllObjects];
  1460. // Remove a previous socket
  1461. NSError *error = nil;
  1462. NSFileManager *fileManager = [NSFileManager defaultManager];
  1463. if ([fileManager fileExistsAtPath:url.path]) {
  1464. if (![[NSFileManager defaultManager] removeItemAtURL:url error:&error]) {
  1465. NSString *msg = @"Could not remove previous unix domain socket at given url.";
  1466. err = [self otherError:msg];
  1467. return_from_block;
  1468. }
  1469. }
  1470. // Resolve interface from description
  1471. NSData *interface = [self getInterfaceAddressFromUrl:url];
  1472. if (interface == nil)
  1473. {
  1474. NSString *msg = @"Invalid unix domain url. Specify a valid file url that does not exist (e.g. \"file:///tmp/socket\")";
  1475. err = [self badParamError:msg];
  1476. return_from_block;
  1477. }
  1478. // Create sockets, configure, bind, and listen
  1479. LogVerbose(@"Creating unix domain socket");
  1480. socketUN = createSocket(AF_UNIX, interface);
  1481. if (socketUN == SOCKET_NULL)
  1482. {
  1483. return_from_block;
  1484. }
  1485. socketUrl = url;
  1486. // Create accept sources
  1487. acceptUNSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, socketUN, 0, socketQueue);
  1488. int socketFD = socketUN;
  1489. dispatch_source_t acceptSource = acceptUNSource;
  1490. dispatch_source_set_event_handler(acceptUNSource, ^{ @autoreleasepool {
  1491. LogVerbose(@"eventUNBlock");
  1492. unsigned long i = 0;
  1493. unsigned long numPendingConnections = dispatch_source_get_data(acceptSource);
  1494. LogVerbose(@"numPendingConnections: %lu", numPendingConnections);
  1495. while ([self doAccept:socketFD] && (++i < numPendingConnections));
  1496. }});
  1497. dispatch_source_set_cancel_handler(acceptUNSource, ^{
  1498. #if NEEDS_DISPATCH_RETAIN_RELEASE
  1499. LogVerbose(@"dispatch_release(accept4Source)");
  1500. dispatch_release(acceptSource);
  1501. #endif
  1502. LogVerbose(@"close(socket4FD)");
  1503. close(socketFD);
  1504. });
  1505. LogVerbose(@"dispatch_resume(accept4Source)");
  1506. dispatch_resume(acceptUNSource);
  1507. flags |= kSocketStarted;
  1508. result = YES;
  1509. }};
  1510. if (dispatch_get_current_queue() == socketQueue)
  1511. block();
  1512. else
  1513. dispatch_sync(socketQueue, block);
  1514. if (result == NO)
  1515. {
  1516. LogInfo(@"Error in accept: %@", err);
  1517. if (errPtr)
  1518. *errPtr = err;
  1519. }
  1520. return result;
  1521. }
  1522. - (BOOL)doAccept:(int)parentSocketFD
  1523. {
  1524. LogTrace();
  1525. int socketType;
  1526. int childSocketFD;
  1527. NSData *childSocketAddress;
  1528. if (parentSocketFD == socket4FD)
  1529. {
  1530. socketType = 0;
  1531. struct sockaddr_in addr;
  1532. socklen_t addrLen = sizeof(addr);
  1533. childSocketFD = accept(parentSocketFD, (struct sockaddr *)&addr, &addrLen);
  1534. if (childSocketFD == -1)
  1535. {
  1536. LogWarn(@"Accept failed with error: %@", [self errnoError]);
  1537. return NO;
  1538. }
  1539. childSocketAddress = [NSData dataWithBytes:&addr length:addrLen];
  1540. }
  1541. else if (parentSocketFD == socket6FD)
  1542. {
  1543. socketType = 1;
  1544. struct sockaddr_in6 addr;
  1545. socklen_t addrLen = sizeof(addr);
  1546. childSocketFD = accept(parentSocketFD, (struct sockaddr *)&addr, &addrLen);
  1547. if (childSocketFD == -1)
  1548. {
  1549. LogWarn(@"Accept failed with error: %@", [self errnoError]);
  1550. return NO;
  1551. }
  1552. childSocketAddress = [NSData dataWithBytes:&addr length:addrLen];
  1553. }
  1554. else // if (parentSocketFD == socketUN)
  1555. {
  1556. socketType = 2;
  1557. struct sockaddr_un addr;
  1558. socklen_t addrLen = sizeof(addr);
  1559. childSocketFD = accept(parentSocketFD, (struct sockaddr *)&addr, &addrLen);
  1560. if (childSocketFD == -1)
  1561. {
  1562. LogWarn(@"Accept failed with error: %@", [self errnoError]);
  1563. return NO;
  1564. }
  1565. childSocketAddress = [NSData dataWithBytes:&addr length:addrLen];
  1566. }
  1567. // Enable non-blocking IO on the socket
  1568. int result = fcntl(childSocketFD, F_SETFL, O_NONBLOCK);
  1569. if (result == -1)
  1570. {
  1571. LogWarn(@"Error enabling non-blocking IO on accepted socket (fcntl)");
  1572. return NO;
  1573. }
  1574. // Prevent SIGPIPE signals
  1575. int nosigpipe = 1;
  1576. setsockopt(childSocketFD, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(nosigpipe));
  1577. // Notify delegate
  1578. if (delegateQueue)
  1579. {
  1580. __strong id theDelegate = delegate;
  1581. dispatch_async(delegateQueue, ^{ @autoreleasepool {
  1582. // Query delegate for custom socket queue
  1583. dispatch_queue_t childSocketQueue = NULL;
  1584. if ([theDelegate respondsToSelector:@selector(newSocketQueueForConnectionFromAddress:onSocket:)])
  1585. {
  1586. childSocketQueue = [theDelegate newSocketQueueForConnectionFromAddress:childSocketAddress
  1587. onSocket:self];
  1588. }
  1589. // Create GCDAsyncSocket instance for accepted socket
  1590. GCDAsyncSocket *acceptedSocket = [[GCDAsyncSocket alloc] initWithDelegate:theDelegate
  1591. delegateQueue:delegateQueue
  1592. socketQueue:childSocketQueue];
  1593. if (socketType == 0)
  1594. acceptedSocket->socket4FD = childSocketFD;
  1595. else if (socketType == 1)
  1596. acceptedSocket->socket6FD = childSocketFD;
  1597. else
  1598. acceptedSocket->socketUN = childSocketFD;
  1599. acceptedSocket->flags = (kSocketStarted | kConnected);
  1600. // Setup read and write sources for accepted socket
  1601. dispatch_async(acceptedSocket->socketQueue, ^{ @autoreleasepool {
  1602. [acceptedSocket setupReadAndWriteSourcesForNewlyConnectedSocket:childSocketFD];
  1603. }});
  1604. // Notify delegate
  1605. if ([theDelegate respondsToSelector:@selector(socket:didAcceptNewSocket:)])
  1606. {
  1607. [theDelegate socket:self didAcceptNewSocket:acceptedSocket];
  1608. }
  1609. // Release the socket queue returned from the delegate (it was retained by acceptedSocket)
  1610. #if NEEDS_DISPATCH_RETAIN_RELEASE
  1611. if (childSocketQueue) dispatch_release(childSocketQueue);
  1612. #endif
  1613. // The accepted socket should have been retained by the delegate.
  1614. // Otherwise it gets properly released when exiting the block.
  1615. }});
  1616. }
  1617. return YES;
  1618. }
  1619. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1620. #pragma mark Connecting
  1621. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1622. /**
  1623. * This method runs through the various checks required prior to a connection attempt.
  1624. * It is shared between the connectToHost and connectToAddress methods.
  1625. *
  1626. **/
  1627. - (BOOL)preConnectWithInterface:(NSString *)interface error:(NSError **)errPtr
  1628. {
  1629. NSAssert(dispatch_get_current_queue() == socketQueue, @"Must be dispatched on socketQueue");
  1630. if (delegate == nil) // Must have delegate set
  1631. {
  1632. if (errPtr)
  1633. {
  1634. NSString *msg = @"Attempting to connect without a delegate. Set a delegate first.";
  1635. *errPtr = [self badConfigError:msg];
  1636. }
  1637. return NO;
  1638. }
  1639. if (delegateQueue == NULL) // Must have delegate queue set
  1640. {
  1641. if (errPtr)
  1642. {
  1643. NSString *msg = @"Attempting to connect without a delegate queue. Set a delegate queue first.";
  1644. *errPtr = [self badConfigError:msg];
  1645. }
  1646. return NO;
  1647. }
  1648. if (![self isDisconnected]) // Must be disconnected
  1649. {
  1650. if (errPtr)
  1651. {
  1652. NSString *msg = @"Attempting to connect while connected or accepting connections. Disconnect first.";
  1653. *errPtr = [self badConfigError:msg];
  1654. }
  1655. return NO;
  1656. }
  1657. BOOL isIPv4Disabled = (config & kIPv4Disabled) ? YES : NO;
  1658. BOOL isIPv6Disabled = (config & kIPv6Disabled) ? YES : NO;
  1659. if (isIPv4Disabled && isIPv6Disabled) // Must have IPv4 or IPv6 enabled
  1660. {
  1661. if (errPtr)
  1662. {
  1663. NSString *msg = @"Both IPv4 and IPv6 have been disabled. Must enable at least one protocol first.";
  1664. *errPtr = [self badConfigError:msg];
  1665. }
  1666. return NO;
  1667. }
  1668. if (interface)
  1669. {
  1670. NSMutableData *interface4 = nil;
  1671. NSMutableData *interface6 = nil;
  1672. [self getInterfaceAddress4:&interface4 address6:&interface6 fromDescription:interface port:0];
  1673. if ((interface4 == nil) && (interface6 == nil))
  1674. {
  1675. if (errPtr)
  1676. {
  1677. NSString *msg = @"Unknown interface. Specify valid interface by name (e.g. \"en1\") or IP address.";
  1678. *errPtr = [self badParamError:msg];
  1679. }
  1680. return NO;
  1681. }
  1682. if (isIPv4Disabled && (interface6 == nil))
  1683. {
  1684. if (errPtr)
  1685. {
  1686. NSString *msg = @"IPv4 has been disabled and specified interface doesn't support IPv6.";
  1687. *errPtr = [self badParamError:msg];
  1688. }
  1689. return NO;
  1690. }
  1691. if (isIPv6Disabled && (interface4 == nil))
  1692. {
  1693. if (errPtr)
  1694. {
  1695. NSString *msg = @"IPv6 has been disabled and specified interface doesn't support IPv4.";
  1696. *errPtr = [self badParamError:msg];
  1697. }
  1698. return NO;
  1699. }
  1700. connectInterface4 = interface4;
  1701. connectInterface6 = interface6;
  1702. }
  1703. // Clear queues (spurious read/write requests post disconnect)
  1704. [readQueue removeAllObjects];
  1705. [writeQueue removeAllObjects];
  1706. return YES;
  1707. }
  1708. - (BOOL)preConnectWithUrl:(NSURL *)url error:(NSError **)errPtr
  1709. {
  1710. NSAssert(dispatch_get_current_queue() == socketQueue, @"Must be dispatched on socketQueue");
  1711. if (delegate == nil) // Must have delegate set
  1712. {
  1713. if (errPtr)
  1714. {
  1715. NSString *msg = @"Attempting to connect without a delegate. Set a delegate first.";
  1716. *errPtr = [self badConfigError:msg];
  1717. }
  1718. return NO;
  1719. }
  1720. if (delegateQueue == NULL) // Must have delegate queue set
  1721. {
  1722. if (errPtr)
  1723. {
  1724. NSString *msg = @"Attempting to connect without a delegate queue. Set a delegate queue first.";
  1725. *errPtr = [self badConfigError:msg];
  1726. }
  1727. return NO;
  1728. }
  1729. if (![self isDisconnected]) // Must be disconnected
  1730. {
  1731. if (errPtr)
  1732. {
  1733. NSString *msg = @"Attempting to connect while connected or accepting connections. Disconnect first.";
  1734. *errPtr = [self badConfigError:msg];
  1735. }
  1736. return NO;
  1737. }
  1738. NSData *interface = [self getInterfaceAddressFromUrl:url];
  1739. if (interface == nil)
  1740. {
  1741. if (errPtr)
  1742. {
  1743. NSString *msg = @"Unknown interface. Specify valid interface by name (e.g. \"en1\") or IP address.";
  1744. *errPtr = [self badParamError:msg];
  1745. }
  1746. return NO;
  1747. }
  1748. connectInterfaceUN = interface;
  1749. // Clear queues (spurious read/write requests post disconnect)
  1750. [readQueue removeAllObjects];
  1751. [writeQueue removeAllObjects];
  1752. return YES;
  1753. }
  1754. - (BOOL)connectToHost:(NSString*)host onPort:(uint16_t)port error:(NSError **)errPtr
  1755. {
  1756. return [self connectToHost:host onPort:port withTimeout:-1 error:errPtr];
  1757. }
  1758. - (BOOL)connectToHost:(NSString *)host
  1759. onPort:(uint16_t)port
  1760. withTimeout:(NSTimeInterval)timeout
  1761. error:(NSError **)errPtr
  1762. {
  1763. return [self connectToHost:host onPort:port viaInterface:nil withTimeout:timeout error:errPtr];
  1764. }
  1765. - (BOOL)connectToHost:(NSString *)inHost
  1766. onPort:(uint16_t)port
  1767. viaInterface:(NSString *)inInterface
  1768. withTimeout:(NSTimeInterval)timeout
  1769. error:(NSError **)errPtr
  1770. {
  1771. LogTrace();
  1772. // Just in case immutable objects were passed
  1773. NSString *host = [inHost copy];
  1774. NSString *interface = [inInterface copy];
  1775. __block BOOL result = NO;
  1776. __block NSError *err = nil;
  1777. dispatch_block_t block = ^{ @autoreleasepool {
  1778. // Check for problems with host parameter
  1779. if ([host length] == 0)
  1780. {
  1781. NSString *msg = @"Invalid host parameter (nil or \"\"). Should be a domain name or IP address string.";
  1782. err = [self badParamError:msg];
  1783. return_from_block;
  1784. }
  1785. // Run through standard pre-connect checks
  1786. if (![self preConnectWithInterface:interface error:&err])
  1787. {
  1788. return_from_block;
  1789. }
  1790. // We've made it past all the checks.
  1791. // It's time to start the connection process.
  1792. flags |= kSocketStarted;
  1793. LogVerbose(@"Dispatching DNS lookup...");
  1794. // It's possible that the given host parameter is actually a NSMutableString.
  1795. // So we want to copy it now, within this block that will be executed synchronously.
  1796. // This way the asynchronous lookup block below doesn't have to worry about it changing.
  1797. int aConnectIndex = connectIndex;
  1798. NSString *hostCpy = [host copy];
  1799. dispatch_queue_t globalConcurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
  1800. dispatch_async(globalConcurrentQueue, ^{ @autoreleasepool {
  1801. [self lookup:aConnectIndex host:hostCpy port:port];
  1802. }});
  1803. [self startConnectTimeout:timeout];
  1804. result = YES;
  1805. }};
  1806. if (dispatch_get_current_queue() == socketQueue)
  1807. block();
  1808. else
  1809. dispatch_sync(socketQueue, block);
  1810. if (result == NO)
  1811. {
  1812. if (errPtr)
  1813. *errPtr = err;
  1814. }
  1815. return result;
  1816. }
  1817. - (BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError **)errPtr
  1818. {
  1819. return [self connectToAddress:remoteAddr viaInterface:nil withTimeout:-1 error:errPtr];
  1820. }
  1821. - (BOOL)connectToAddress:(NSData *)remoteAddr withTimeout:(NSTimeInterval)timeout error:(NSError **)errPtr
  1822. {
  1823. return [self connectToAddress:remoteAddr viaInterface:nil withTimeout:timeout error:errPtr];
  1824. }
  1825. - (BOOL)connectToAddress:(NSData *)inRemoteAddr
  1826. viaInterface:(NSString *)inInterface
  1827. withTimeout:(NSTimeInterval)timeout
  1828. error:(NSError **)errPtr
  1829. {
  1830. LogTrace();
  1831. // Just in case immutable objects were passed
  1832. NSData *remoteAddr = [inRemoteAddr copy];
  1833. NSString *interface = [inInterface copy];
  1834. __block BOOL result = NO;
  1835. __block NSError *err = nil;
  1836. dispatch_block_t block = ^{ @autoreleasepool {
  1837. // Check for problems with remoteAddr parameter
  1838. NSData *address4 = nil;
  1839. NSData *address6 = nil;
  1840. if ([remoteAddr length] >= sizeof(struct sockaddr))
  1841. {
  1842. const struct sockaddr *sockaddr = (const struct sockaddr *)[remoteAddr bytes];
  1843. if (sockaddr->sa_family == AF_INET)
  1844. {
  1845. if ([remoteAddr length] == sizeof(struct sockaddr_in))
  1846. {
  1847. address4 = remoteAddr;
  1848. }
  1849. }
  1850. else if (sockaddr->sa_family == AF_INET6)
  1851. {
  1852. if ([remoteAddr length] == sizeof(struct sockaddr_in6))
  1853. {
  1854. address6 = remoteAddr;
  1855. }
  1856. }
  1857. }
  1858. if ((address4 == nil) && (address6 == nil))
  1859. {
  1860. NSString *msg = @"A valid IPv4 or IPv6 address was not given";
  1861. err = [self badParamError:msg];
  1862. return_from_block;
  1863. }
  1864. BOOL isIPv4Disabled = (config & kIPv4Disabled) ? YES : NO;
  1865. BOOL isIPv6Disabled = (config & kIPv6Disabled) ? YES : NO;
  1866. if (isIPv4Disabled && (address4 != nil))
  1867. {
  1868. NSString *msg = @"IPv4 has been disabled and an IPv4 address was passed.";
  1869. err = [self badParamError:msg];
  1870. return_from_block;
  1871. }
  1872. if (isIPv6Disabled && (address6 != nil))
  1873. {
  1874. NSString *msg = @"IPv6 has been disabled and an IPv6 address was passed.";
  1875. err = [self badParamError:msg];
  1876. return_from_block;
  1877. }
  1878. // Run through standard pre-connect checks
  1879. if (![self preConnectWithInterface:interface error:&err])
  1880. {
  1881. return_from_block;
  1882. }
  1883. // We've made it past all the checks.
  1884. // It's time to start the connection process.
  1885. if (![self connectWithAddress4:address4 address6:address6 error:&err])
  1886. {
  1887. return_from_block;
  1888. }
  1889. flags |= kSocketStarted;
  1890. [self startConnectTimeout:timeout];
  1891. result = YES;
  1892. }};
  1893. if (dispatch_get_current_queue() == socketQueue)
  1894. block();
  1895. else
  1896. dispatch_sync(socketQueue, block);
  1897. if (result == NO)
  1898. {
  1899. if (errPtr)
  1900. *errPtr = err;
  1901. }
  1902. return result;
  1903. }
  1904. - (BOOL)connectToUrl:(NSURL *)url withTimeout:(NSTimeInterval)timeout error:(NSError **)errPtr;
  1905. {
  1906. LogTrace();
  1907. __block BOOL result = NO;
  1908. __block NSError *err = nil;
  1909. dispatch_block_t block = ^{ @autoreleasepool {
  1910. // Check for problems with host parameter
  1911. if ([url.path length] == 0)
  1912. {
  1913. NSString *msg = @"Invalid unix domain socket url.";
  1914. err = [self badParamError:msg];
  1915. return_from_block;
  1916. }
  1917. // Run through standard pre-connect checks
  1918. if (![self preConnectWithUrl:url error:&err])
  1919. {
  1920. return_from_block;
  1921. }
  1922. // We've made it past all the checks.
  1923. // It's time to start the connection process.
  1924. flags |= kSocketStarted;
  1925. // Start the normal connection process
  1926. NSError *err = nil;
  1927. if (![self connectWithAddressUN:connectInterfaceUN error:&err])
  1928. {
  1929. [self closeWithError:err];
  1930. return_from_block;
  1931. }
  1932. [self startConnectTimeout:timeout];
  1933. result = YES;
  1934. }};
  1935. if (dispatch_get_current_queue() == socketQueue)
  1936. block();
  1937. else
  1938. dispatch_sync(socketQueue, block);
  1939. if (result == NO)
  1940. {
  1941. if (errPtr)
  1942. *errPtr = err;
  1943. }
  1944. return result;
  1945. }
  1946. - (void)lookup:(int)aConnectIndex host:(NSString *)host port:(uint16_t)port
  1947. {
  1948. LogTrace();
  1949. // This method is executed on a global concurrent queue.
  1950. // It posts the results back to the socket queue.
  1951. // The lookupIndex is used to ignore the results if the connect operation was cancelled or timed out.
  1952. NSError *error = nil;
  1953. NSData *address4 = nil;
  1954. NSData *address6 = nil;
  1955. if ([host isEqualToString:@"localhost"] || [host isEqualToString:@"loopback"])
  1956. {
  1957. // Use LOOPBACK address
  1958. struct sockaddr_in nativeAddr;
  1959. nativeAddr.sin_len = sizeof(struct sockaddr_in);
  1960. nativeAddr.sin_family = AF_INET;
  1961. nativeAddr.sin_port = htons(port);
  1962. nativeAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  1963. memset(&(nativeAddr.sin_zero), 0, sizeof(nativeAddr.sin_zero));
  1964. struct sockaddr_in6 nativeAddr6;
  1965. nativeAddr6.sin6_len = sizeof(struct sockaddr_in6);
  1966. nativeAddr6.sin6_family = AF_INET6;
  1967. nativeAddr6.sin6_port = htons(port);
  1968. nativeAddr6.sin6_flowinfo = 0;
  1969. nativeAddr6.sin6_addr = in6addr_loopback;
  1970. nativeAddr6.sin6_scope_id = 0;
  1971. // Wrap the native address structures
  1972. address4 = [NSData dataWithBytes:&nativeAddr length:sizeof(nativeAddr)];
  1973. address6 = [NSData dataWithBytes:&nativeAddr6 length:sizeof(nativeAddr6)];
  1974. }
  1975. else
  1976. {
  1977. NSString *portStr = [NSString stringWithFormat:@"%hu", port];
  1978. struct addrinfo hints, *res, *res0;
  1979. memset(&hints, 0, sizeof(hints));
  1980. hints.ai_family = PF_UNSPEC;
  1981. hints.ai_socktype = SOCK_STREAM;
  1982. hints.ai_protocol = IPPROTO_TCP;
  1983. int gai_error = getaddrinfo([host UTF8String], [portStr UTF8String], &hints, &res0);
  1984. if (gai_error)
  1985. {
  1986. error = [self gaiError:gai_error];
  1987. }
  1988. else
  1989. {
  1990. for(res = res0; res; res = res->ai_next)
  1991. {
  1992. if ((address4 == nil) && (res->ai_family == AF_INET))
  1993. {
  1994. // Found IPv4 address
  1995. // Wrap the native address structure
  1996. address4 = [NSData dataWithBytes:res->ai_addr length:res->ai_addrlen];
  1997. }
  1998. else if ((address6 == nil) && (res->ai_family == AF_INET6))
  1999. {
  2000. // Found IPv6 address
  2001. // Wrap the native address structure
  2002. address6 = [NSData dataWithBytes:res->ai_addr length:res->ai_addrlen];
  2003. }
  2004. }
  2005. freeaddrinfo(res0);
  2006. if ((address4 == nil) && (address6 == nil))
  2007. {
  2008. error = [self gaiError:EAI_FAIL];
  2009. }
  2010. }
  2011. }
  2012. if (error)
  2013. {
  2014. dispatch_async(socketQueue, ^{ @autoreleasepool {
  2015. [self lookup:aConnectIndex didFail:error];
  2016. }});
  2017. }
  2018. else
  2019. {
  2020. dispatch_async(socketQueue, ^{ @autoreleasepool {
  2021. [self lookup:aConnectIndex didSucceedWithAddress4:address4 address6:address6];
  2022. }});
  2023. }
  2024. }
  2025. - (void)lookup:(int)aConnectIndex didSucceedWithAddress4:(NSData *)address4 address6:(NSData *)address6
  2026. {
  2027. LogTrace();
  2028. NSAssert(dispatch_get_current_queue() == socketQueue, @"Must be dispatched on socketQueue");
  2029. NSAssert(address4 || address6, @"Expected at least one valid address");
  2030. if (aConnectIndex != connectIndex)
  2031. {
  2032. LogInfo(@"Ignoring lookupDidSucceed, already disconnected");
  2033. // The connect operation has been cancelled.
  2034. // That is, socket was disconnected, or connection has already timed out.
  2035. return;
  2036. }
  2037. // Check for problems
  2038. BOOL isIPv4Disabled = (config & kIPv4Disabled) ? YES : NO;
  2039. BOOL isIPv6Disabled = (config & kIPv6Disabled) ? YES : NO;
  2040. if (isIPv4Disabled && (address6 == nil))
  2041. {
  2042. NSString *msg = @"IPv4 has been disabled and DNS lookup found no IPv6 address.";
  2043. [self closeWithError:[self otherError:msg]];
  2044. return;
  2045. }
  2046. if (isIPv6Disabled && (address4 == nil))
  2047. {
  2048. NSString *msg = @"IPv6 has been disabled and DNS lookup found no IPv4 address.";
  2049. [self closeWithError:[self otherError:msg]];
  2050. return;
  2051. }
  2052. // Start the normal connection process
  2053. NSError *err = nil;
  2054. if (![self connectWithAddress4:address4 address6:address6 error:&err])
  2055. {
  2056. [self closeWithError:err];
  2057. }
  2058. }
  2059. /**
  2060. * This method is called if the DNS lookup fails.
  2061. * This method is executed on the socketQueue.
  2062. *
  2063. * Since the DNS lookup executed synchronously on a global concurrent queue,
  2064. * the original connection request may have already been cancelled or timed-out by the time this method is invoked.
  2065. * The lookupIndex tells us whether the lookup is still valid or not.
  2066. **/
  2067. - (void)lookup:(int)aConnectIndex didFail:(NSError *)error
  2068. {
  2069. LogTrace();
  2070. NSAssert(dispatch_get_current_queue() == socketQueue, @"Must be dispatched on socketQueue");
  2071. if (aConnectIndex != connectIndex)
  2072. {
  2073. LogInfo(@"Ignoring lookup:didFail: - already disconnected");
  2074. // The connect operation has been cancelled.
  2075. // That is, socket was disconnected, or connection has already timed out.
  2076. return;
  2077. }
  2078. [self endConnectTimeout];
  2079. [self closeWithError:error];
  2080. }
  2081. - (BOOL)connectWithAddress4:(NSData *)address4 address6:(NSData *)address6 error:(NSError **)errPtr
  2082. {
  2083. LogTrace();
  2084. NSAssert(dispatch_get_current_queue() == socketQueue, @"Must be dispatched on socketQueue");
  2085. LogVerbose(@"IPv4: %@:%hu", [[self class] hostFromAddress:address4], [[self class] portFromAddress:address4]);
  2086. LogVerbose(@"IPv6: %@:%hu", [[self class] hostFromAddress:address6], [[self class] portFromAddress:address6]);
  2087. // Determine socket type
  2088. BOOL preferIPv6 = (config & kPreferIPv6) ? YES : NO;
  2089. BOOL useIPv6 = ((preferIPv6 && address6) || (address4 == nil));
  2090. // Create the socket
  2091. int socketFD;
  2092. NSData *address;
  2093. NSData *connectInterface;
  2094. if (useIPv6)
  2095. {
  2096. LogVerbose(@"Creating IPv6 socket");
  2097. socket6FD = socket(AF_INET6, SOCK_STREAM, 0);
  2098. socketFD = socket6FD;
  2099. address = address6;
  2100. connectInterface = connectInterface6;
  2101. }
  2102. else
  2103. {
  2104. LogVerbose(@"Creating IPv4 socket");
  2105. socket4FD = socket(AF_INET, SOCK_STREAM, 0);
  2106. socketFD = socket4FD;
  2107. address = address4;
  2108. connectInterface = connectInterface4;
  2109. }
  2110. if (socketFD == SOCKET_NULL)
  2111. {
  2112. if (errPtr)
  2113. *errPtr = [self errnoErrorWithReason:@"Error in socket() function"];
  2114. return NO;
  2115. }
  2116. // Bind the socket to the desired interface (if needed)
  2117. if (connectInterface)
  2118. {
  2119. LogVerbose(@"Binding socket...");
  2120. if ([[self class] portFromAddress:connectInterface] > 0)
  2121. {
  2122. // Since we're going to be binding to a specific port,
  2123. // we should turn on reuseaddr to allow us to override sockets in time_wait.
  2124. int reuseOn = 1;
  2125. setsockopt(socketFD, SOL_SOCKET, SO_REUSEADDR, &reuseOn, sizeof(reuseOn));
  2126. }
  2127. const struct sockaddr *interfaceAddr = (const struct sockaddr *)[connectInterface bytes];
  2128. int result = bind(socketFD, interfaceAddr, (socklen_t)[connectInterface length]);
  2129. if (result != 0)
  2130. {
  2131. if (errPtr)
  2132. *errPtr = [self errnoErrorWithReason:@"Error in bind() function"];
  2133. return NO;
  2134. }
  2135. }
  2136. // Prevent SIGPIPE signals
  2137. int nosigpipe = 1;
  2138. setsockopt(socketFD, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(nosigpipe));
  2139. // Start the connection process in a background queue
  2140. int aConnectIndex = connectIndex;
  2141. dispatch_queue_t globalConcurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
  2142. dispatch_async(globalConcurrentQueue, ^{
  2143. int result = connect(socketFD, (const struct sockaddr *)[address bytes], (socklen_t)[address length]);
  2144. if (result == 0)
  2145. {
  2146. dispatch_async(socketQueue, ^{ @autoreleasepool {
  2147. [self didConnect:aConnectIndex];
  2148. }});
  2149. }
  2150. else
  2151. {
  2152. NSError *error = [self errnoErrorWithReason:@"Error in connect() function"];
  2153. dispatch_async(socketQueue, ^{ @autoreleasepool {
  2154. [self didNotConnect:aConnectIndex error:error];
  2155. }});
  2156. }
  2157. });
  2158. LogVerbose(@"Connecting...");
  2159. return YES;
  2160. }
  2161. - (BOOL)connectWithAddressUN:(NSData *)address error:(NSError **)errPtr
  2162. {
  2163. LogTrace();
  2164. NSAssert(dispatch_get_current_queue() == socketQueue, @"Must be dispatched on socketQueue");
  2165. // Create the socket
  2166. int socketFD;
  2167. LogVerbose(@"Creating unix domain socket");
  2168. socketUN = socket(AF_UNIX, SOCK_STREAM, 0);
  2169. socketFD = socketUN;
  2170. if (socketFD == SOCKET_NULL)
  2171. {
  2172. if (errPtr)
  2173. *errPtr = [self errnoErrorWithReason:@"Error in socket() function"];
  2174. return NO;
  2175. }
  2176. // Bind the socket to the desired interface (if needed)
  2177. LogVerbose(@"Binding socket...");
  2178. int reuseOn = 1;
  2179. setsockopt(socketFD, SOL_SOCKET, SO_REUSEADDR, &reuseOn, sizeof(reuseOn));
  2180. // const struct sockaddr *interfaceAddr = (const struct sockaddr *)[address bytes];
  2181. //
  2182. // int result = bind(socketFD, interfaceAddr, (socklen_t)[address length]);
  2183. // if (result != 0)
  2184. // {
  2185. // if (errPtr)
  2186. // *errPtr = [self errnoErrorWithReason:@"Error in bind() function"];
  2187. //
  2188. // return NO;
  2189. // }
  2190. // Prevent SIGPIPE signals
  2191. int nosigpipe = 1;
  2192. setsockopt(socketFD, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(nosigpipe));
  2193. // Start the connection process in a background queue
  2194. int aConnectIndex = connectIndex;
  2195. dispatch_queue_t globalConcurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
  2196. dispatch_async(globalConcurrentQueue, ^{
  2197. const struct sockaddr *addr = (const struct sockaddr *)[address bytes];
  2198. int result = connect(socketFD, addr, addr->sa_len);
  2199. if (result == 0)
  2200. {
  2201. dispatch_async(socketQueue, ^{ @autoreleasepool {
  2202. [self didConnect:aConnectIndex];
  2203. }});
  2204. }
  2205. else
  2206. {
  2207. // TODO: Bad file descriptor
  2208. perror("connect");
  2209. NSError *error = [self errnoErrorWithReason:@"Error in connect() function"];
  2210. dispatch_async(socketQueue, ^{ @autoreleasepool {
  2211. [self didNotConnect:aConnectIndex error:error];
  2212. }});
  2213. }
  2214. });
  2215. LogVerbose(@"Connecting...");
  2216. return YES;
  2217. }
  2218. - (void)didConnect:(int)aConnectIndex
  2219. {
  2220. LogTrace();
  2221. NSAssert(dispatch_get_current_queue() == socketQueue, @"Must be dispatched on socketQueue");
  2222. if (aConnectIndex != connectIndex)
  2223. {
  2224. LogInfo(@"Ignoring didConnect, already disconnected");
  2225. // The connect operation has been cancelled.
  2226. // That is, socket was disconnected, or connection has already timed out.
  2227. return;
  2228. }
  2229. flags |= kConnected;
  2230. [self endConnectTimeout];
  2231. #if TARGET_OS_IPHONE
  2232. // The endConnectTimeout method executed above incremented the connectIndex.
  2233. aConnectIndex = connectIndex;
  2234. #endif
  2235. // Setup read/write streams (as workaround for specific shortcomings in the iOS platform)
  2236. //
  2237. // Note:
  2238. // There may be configuration options that must be set by the delegate before opening the streams.
  2239. // The primary example is the kCFStreamNetworkServiceTypeVoIP flag, which only works on an unopened stream.
  2240. //
  2241. // Thus we wait until after the socket:didConnectToHost:port: delegate method has completed.
  2242. // This gives the delegate time to properly configure the streams if needed.
  2243. dispatch_block_t SetupStreamsPart1 = ^{
  2244. #if TARGET_OS_IPHONE
  2245. if (![self createReadAndWriteStream])
  2246. {
  2247. [self closeWithError:[self otherError:@"Error creating CFStreams"]];
  2248. return;
  2249. }
  2250. if (![self registerForStreamCallbacksIncludingReadWrite:NO])
  2251. {
  2252. [self closeWithError:[self otherError:@"Error in CFStreamSetClient"]];
  2253. return;
  2254. }
  2255. #endif
  2256. };
  2257. dispatch_block_t SetupStreamsPart2 = ^{
  2258. #if TARGET_OS_IPHONE
  2259. if (aConnectIndex != connectIndex)
  2260. {
  2261. // The socket has been disconnected.
  2262. return;
  2263. }
  2264. if (![self addStreamsToRunLoop])
  2265. {
  2266. [self closeWithError:[self otherError:@"Error in CFStreamScheduleWithRunLoop"]];
  2267. return;
  2268. }
  2269. if (![self openStreams])
  2270. {
  2271. [self closeWithError:[self otherError:@"Error creating CFStreams"]];
  2272. return;
  2273. }
  2274. #endif
  2275. };
  2276. // Notify delegate
  2277. NSString *host = [self connectedHost];
  2278. uint16_t port = [self connectedPort];
  2279. NSURL *url = [self connectedUrl];
  2280. if (delegateQueue && host != nil && [delegate respondsToSelector:@selector(socket:didConnectToHost:port:)])
  2281. {
  2282. SetupStreamsPart1();
  2283. __strong id theDelegate = delegate;
  2284. dispatch_async(delegateQueue, ^{ @autoreleasepool {
  2285. [theDelegate socket:self didConnectToHost:host port:port];
  2286. dispatch_async(socketQueue, ^{ @autoreleasepool {
  2287. SetupStreamsPart2();
  2288. }});
  2289. }});
  2290. }
  2291. else if (delegateQueue && url != nil && [delegate respondsToSelector:@selector(socket:didConnectToUrl:)])
  2292. {
  2293. SetupStreamsPart1();
  2294. __strong id theDelegate = delegate;
  2295. dispatch_async(delegateQueue, ^{ @autoreleasepool {
  2296. [theDelegate socket:self didConnectToUrl:url];
  2297. dispatch_async(socketQueue, ^{ @autoreleasepool {
  2298. SetupStreamsPart2();
  2299. }});
  2300. }});
  2301. }
  2302. else
  2303. {
  2304. SetupStreamsPart1();
  2305. SetupStreamsPart2();
  2306. }
  2307. // Get the connected socket
  2308. int socketFD = (socket4FD != SOCKET_NULL) ? socket4FD : (socket6FD != SOCKET_NULL) ? socket6FD : socketUN;
  2309. // Enable non-blocking IO on the socket
  2310. int result = fcntl(socketFD, F_SETFL, O_NONBLOCK);
  2311. if (result == -1)
  2312. {
  2313. NSString *errMsg = @"Error enabling non-blocking IO on socket (fcntl)";
  2314. [self closeWithError:[self otherError:errMsg]];
  2315. return;
  2316. }
  2317. // Setup our read/write sources
  2318. [self setupReadAndWriteSourcesForNewlyConnectedSocket:socketFD];
  2319. // Dequeue any pending read/write requests
  2320. [self maybeDequeueRead];
  2321. [self maybeDequeueWrite];
  2322. }
  2323. - (void)didNotConnect:(int)aConnectIndex error:(NSError *)error
  2324. {
  2325. LogTrace();
  2326. NSAssert(dispatch_get_current_queue() == socketQueue, @"Must be dispatched on socketQueue");
  2327. if (aConnectIndex != connectIndex)
  2328. {
  2329. LogInfo(@"Ignoring didNotConnect, already disconnected");
  2330. // The connect operation has been cancelled.
  2331. // That is, socket was disconnected, or connection has already timed out.
  2332. return;
  2333. }
  2334. [self closeWithError:error];
  2335. }
  2336. - (void)startConnectTimeout:(NSTimeInterval)timeout
  2337. {
  2338. if (timeout >= 0.0)
  2339. {
  2340. connectTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, socketQueue);
  2341. dispatch_source_set_event_handler(connectTimer, ^{ @autoreleasepool {
  2342. [self doConnectTimeout];
  2343. }});
  2344. #if NEEDS_DISPATCH_RETAIN_RELEASE
  2345. dispatch_source_t theConnectTimer = connectTimer;
  2346. dispatch_source_set_cancel_handler(connectTimer, ^{
  2347. LogVerbose(@"dispatch_release(connectTimer)");
  2348. dispatch_release(theConnectTimer);
  2349. });
  2350. #endif
  2351. dispatch_time_t tt = dispatch_time(DISPATCH_TIME_NOW, (timeout * NSEC_PER_SEC));
  2352. dispatch_source_set_timer(connectTimer, tt, DISPATCH_TIME_FOREVER, 0);
  2353. dispatch_resume(connectTimer);
  2354. }
  2355. }
  2356. - (void)endConnectTimeout
  2357. {
  2358. LogTrace();
  2359. if (connectTimer)
  2360. {
  2361. dispatch_source_cancel(connectTimer);
  2362. connectTimer = NULL;
  2363. }
  2364. // Increment connectIndex.
  2365. // This will prevent us from processing results from any related background asynchronous operations.
  2366. //
  2367. // Note: This should be called from close method even if connectTimer is NULL.
  2368. // This is because one might disconnect a socket prior to a successful connection which had no timeout.
  2369. connectIndex++;
  2370. if (connectInterface4)
  2371. {
  2372. connectInterface4 = nil;
  2373. }
  2374. if (connectInterface6)
  2375. {
  2376. connectInterface6 = nil;
  2377. }
  2378. }
  2379. - (void)doConnectTimeout
  2380. {
  2381. LogTrace();
  2382. [self endConnectTimeout];
  2383. [self closeWithError:[self connectTimeoutError]];
  2384. }
  2385. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2386. #pragma mark Disconnecting
  2387. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2388. - (void)closeWithError:(NSError *)error
  2389. {
  2390. LogTrace();
  2391. NSAssert(dispatch_get_current_queue() == socketQueue, @"Must be dispatched on socketQueue");
  2392. [self endConnectTimeout];
  2393. if (currentRead != nil) [self endCurrentRead];
  2394. if (currentWrite != nil) [self endCurrentWrite];
  2395. [readQueue removeAllObjects];
  2396. [writeQueue removeAllObjects];
  2397. [preBuffer reset];
  2398. #if TARGET_OS_IPHONE
  2399. {
  2400. if (readStream || writeStream)
  2401. {
  2402. [self removeStreamsFromRunLoop];
  2403. if (readStream)
  2404. {
  2405. CFReadStreamSetClient(readStream, kCFStreamEventNone, NULL, NULL);
  2406. CFReadStreamClose(readStream);
  2407. CFRelease(readStream);
  2408. readStream = NULL;
  2409. }
  2410. if (writeStream)
  2411. {
  2412. CFWriteStreamSetClient(writeStream, kCFStreamEventNone, NULL, NULL);
  2413. CFWriteStreamClose(writeStream);
  2414. CFRelease(writeStream);
  2415. writeStream = NULL;
  2416. }
  2417. }
  2418. }
  2419. #endif
  2420. #if SECURE_TRANSPORT_MAYBE_AVAILABLE
  2421. {
  2422. [sslPreBuffer reset];
  2423. sslErrCode = noErr;
  2424. if (sslContext)
  2425. {
  2426. // Getting a linker error here about the SSLx() functions?
  2427. // You need to add the Security Framework to your application.
  2428. SSLClose(sslContext);
  2429. #if TARGET_OS_IPHONE
  2430. CFRelease(sslContext);
  2431. #else
  2432. SSLDisposeContext(sslContext);
  2433. #endif
  2434. sslContext = NULL;
  2435. }
  2436. }
  2437. #endif
  2438. // For some crazy reason (in my opinion), cancelling a dispatch source doesn't
  2439. // invoke the cancel handler if the dispatch source is paused.
  2440. // So we have to unpause the source if needed.
  2441. // This allows the cancel handler to be run, which in turn releases the source and closes the socket.
  2442. if (!accept4Source && !accept6Source && !readSource && !writeSource)
  2443. {
  2444. LogVerbose(@"manually closing close");
  2445. if (socket4FD != SOCKET_NULL)
  2446. {
  2447. LogVerbose(@"close(socket4FD)");
  2448. close(socket4FD);
  2449. socket4FD = SOCKET_NULL;
  2450. }
  2451. if (socket6FD != SOCKET_NULL)
  2452. {
  2453. LogVerbose(@"close(socket6FD)");
  2454. close(socket6FD);
  2455. socket6FD = SOCKET_NULL;
  2456. }
  2457. if (socketUN != SOCKET_NULL)
  2458. {
  2459. LogVerbose(@"close(socketUN)");
  2460. close(socketUN);
  2461. socketUN = SOCKET_NULL;
  2462. unlink(socketUrl.path.fileSystemRepresentation);
  2463. socketUrl = nil;
  2464. }
  2465. }
  2466. else
  2467. {
  2468. if (accept4Source)
  2469. {
  2470. LogVerbose(@"dispatch_source_cancel(accept4Source)");
  2471. dispatch_source_cancel(accept4Source);
  2472. // We never suspend accept4Source
  2473. accept4Source = NULL;
  2474. }
  2475. if (accept6Source)
  2476. {
  2477. LogVerbose(@"dispatch_source_cancel(accept6Source)");
  2478. dispatch_source_cancel(accept6Source);
  2479. // We never suspend accept6Source
  2480. accept6Source = NULL;
  2481. }
  2482. if (acceptUNSource)
  2483. {
  2484. LogVerbose(@"dispatch_source_cancel(acceptUNSource)");
  2485. dispatch_source_cancel(acceptUNSource);
  2486. // We never suspend acceptUNSource
  2487. acceptUNSource = NULL;
  2488. }
  2489. if (readSource)
  2490. {
  2491. LogVerbose(@"dispatch_source_cancel(readSource)");
  2492. dispatch_source_cancel(readSource);
  2493. [self resumeReadSource];
  2494. readSource = NULL;
  2495. }
  2496. if (writeSource)
  2497. {
  2498. LogVerbose(@"dispatch_source_cancel(writeSource)");
  2499. dispatch_source_cancel(writeSource);
  2500. [self resumeWriteSource];
  2501. writeSource = NULL;
  2502. }
  2503. // The sockets will be closed by the cancel handlers of the corresponding source
  2504. socket4FD = SOCKET_NULL;
  2505. socket6FD = SOCKET_NULL;
  2506. socketUN = SOCKET_NULL;
  2507. }
  2508. // If the client has passed the connect/accept method, then the connection has at least begun.
  2509. // Notify delegate that it is now ending.
  2510. BOOL shouldCallDelegate = (flags & kSocketStarted);
  2511. // Clear stored socket info and all flags (config remains as is)
  2512. socketFDBytesAvailable = 0;
  2513. flags = 0;
  2514. if (shouldCallDelegate)
  2515. {
  2516. if (delegateQueue && [delegate respondsToSelector: @selector(socketDidDisconnect:withError:)])
  2517. {
  2518. __strong id theDelegate = delegate;
  2519. dispatch_async(delegateQueue, ^{ @autoreleasepool {
  2520. [theDelegate socketDidDisconnect:self withError:error];
  2521. }});
  2522. }
  2523. }
  2524. }
  2525. - (void)disconnect
  2526. {
  2527. dispatch_block_t block = ^{ @autoreleasepool {
  2528. if (flags & kSocketStarted)
  2529. {
  2530. [self closeWithError:nil];
  2531. }
  2532. }};
  2533. // Synchronous disconnection, as documented in the header file
  2534. if (dispatch_get_current_queue() == socketQueue)
  2535. block();
  2536. else
  2537. dispatch_sync(socketQueue, block);
  2538. }
  2539. - (void)disconnectAfterReading
  2540. {
  2541. dispatch_async(socketQueue, ^{ @autoreleasepool {
  2542. if (flags & kSocketStarted)
  2543. {
  2544. flags |= (kForbidReadsWrites | kDisconnectAfterReads);
  2545. [self maybeClose];
  2546. }
  2547. }});
  2548. }
  2549. - (void)disconnectAfterWriting
  2550. {
  2551. dispatch_async(socketQueue, ^{ @autoreleasepool {
  2552. if (flags & kSocketStarted)
  2553. {
  2554. flags |= (kForbidReadsWrites | kDisconnectAfterWrites);
  2555. [self maybeClose];
  2556. }
  2557. }});
  2558. }
  2559. - (void)disconnectAfterReadingAndWriting
  2560. {
  2561. dispatch_async(socketQueue, ^{ @autoreleasepool {
  2562. if (flags & kSocketStarted)
  2563. {
  2564. flags |= (kForbidReadsWrites | kDisconnectAfterReads | kDisconnectAfterWrites);
  2565. [self maybeClose];
  2566. }
  2567. }});
  2568. }
  2569. /**
  2570. * Closes the socket if possible.
  2571. * That is, if all writes have completed, and we're set to disconnect after writing,
  2572. * or if all reads have completed, and we're set to disconnect after reading.
  2573. **/
  2574. - (void)maybeClose
  2575. {
  2576. NSAssert(dispatch_get_current_queue() == socketQueue, @"Must be dispatched on socketQueue");
  2577. BOOL shouldClose = NO;
  2578. if (flags & kDisconnectAfterReads)
  2579. {
  2580. if (([readQueue count] == 0) && (currentRead == nil))
  2581. {
  2582. if (flags & kDisconnectAfterWrites)
  2583. {
  2584. if (([writeQueue count] == 0) && (currentWrite == nil))
  2585. {
  2586. shouldClose = YES;
  2587. }
  2588. }
  2589. else
  2590. {
  2591. shouldClose = YES;
  2592. }
  2593. }
  2594. }
  2595. else if (flags & kDisconnectAfterWrites)
  2596. {
  2597. if (([writeQueue count] == 0) && (currentWrite == nil))
  2598. {
  2599. shouldClose = YES;
  2600. }
  2601. }
  2602. if (shouldClose)
  2603. {
  2604. [self closeWithError:nil];
  2605. }
  2606. }
  2607. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2608. #pragma mark Errors
  2609. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2610. - (NSError *)badConfigError:(NSString *)errMsg
  2611. {
  2612. NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  2613. return [NSError errorWithDomain:GCDAsyncSocketErrorDomain code:GCDAsyncSocketBadConfigError userInfo:userInfo];
  2614. }
  2615. - (NSError *)badParamError:(NSString *)errMsg
  2616. {
  2617. NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  2618. return [NSError errorWithDomain:GCDAsyncSocketErrorDomain code:GCDAsyncSocketBadParamError userInfo:userInfo];
  2619. }
  2620. - (NSError *)gaiError:(int)gai_error
  2621. {
  2622. NSString *errMsg = [NSString stringWithCString:gai_strerror(gai_error) encoding:NSASCIIStringEncoding];
  2623. NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  2624. return [NSError errorWithDomain:@"kCFStreamErrorDomainNetDB" code:gai_error userInfo:userInfo];
  2625. }
  2626. - (NSError *)errnoErrorWithReason:(NSString *)reason
  2627. {
  2628. NSString *errMsg = [NSString stringWithUTF8String:strerror(errno)];
  2629. NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:errMsg, NSLocalizedDescriptionKey,
  2630. reason, NSLocalizedFailureReasonErrorKey, nil];
  2631. return [NSError errorWithDomain:NSPOSIXErrorDomain code:errno userInfo:userInfo];
  2632. }
  2633. - (NSError *)errnoError
  2634. {
  2635. NSString *errMsg = [NSString stringWithUTF8String:strerror(errno)];
  2636. NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  2637. return [NSError errorWithDomain:NSPOSIXErrorDomain code:errno userInfo:userInfo];
  2638. }
  2639. - (NSError *)sslError:(OSStatus)ssl_error
  2640. {
  2641. NSString *msg = @"Error code definition can be found in Apple's SecureTransport.h";
  2642. NSDictionary *userInfo = [NSDictionary dictionaryWithObject:msg forKey:NSLocalizedRecoverySuggestionErrorKey];
  2643. return [NSError errorWithDomain:@"kCFStreamErrorDomainSSL" code:ssl_error userInfo:userInfo];
  2644. }
  2645. - (NSError *)connectTimeoutError
  2646. {
  2647. NSString *errMsg = NSLocalizedStringWithDefaultValue(@"GCDAsyncSocketConnectTimeoutError",
  2648. @"GCDAsyncSocket", [NSBundle mainBundle],
  2649. @"Attempt to connect to host timed out", nil);
  2650. NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  2651. return [NSError errorWithDomain:GCDAsyncSocketErrorDomain code:GCDAsyncSocketConnectTimeoutError userInfo:userInfo];
  2652. }
  2653. /**
  2654. * Returns a standard AsyncSocket maxed out error.
  2655. **/
  2656. - (NSError *)readMaxedOutError
  2657. {
  2658. NSString *errMsg = NSLocalizedStringWithDefaultValue(@"GCDAsyncSocketReadMaxedOutError",
  2659. @"GCDAsyncSocket", [NSBundle mainBundle],
  2660. @"Read operation reached set maximum length", nil);
  2661. NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  2662. return [NSError errorWithDomain:GCDAsyncSocketErrorDomain code:GCDAsyncSocketReadMaxedOutError userInfo:info];
  2663. }
  2664. /**
  2665. * Returns a standard AsyncSocket write timeout error.
  2666. **/
  2667. - (NSError *)readTimeoutError
  2668. {
  2669. NSString *errMsg = NSLocalizedStringWithDefaultValue(@"GCDAsyncSocketReadTimeoutError",
  2670. @"GCDAsyncSocket", [NSBundle mainBundle],
  2671. @"Read operation timed out", nil);
  2672. NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  2673. return [NSError errorWithDomain:GCDAsyncSocketErrorDomain code:GCDAsyncSocketReadTimeoutError userInfo:userInfo];
  2674. }
  2675. /**
  2676. * Returns a standard AsyncSocket write timeout error.
  2677. **/
  2678. - (NSError *)writeTimeoutError
  2679. {
  2680. NSString *errMsg = NSLocalizedStringWithDefaultValue(@"GCDAsyncSocketWriteTimeoutError",
  2681. @"GCDAsyncSocket", [NSBundle mainBundle],
  2682. @"Write operation timed out", nil);
  2683. NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  2684. return [NSError errorWithDomain:GCDAsyncSocketErrorDomain code:GCDAsyncSocketWriteTimeoutError userInfo:userInfo];
  2685. }
  2686. - (NSError *)connectionClosedError
  2687. {
  2688. NSString *errMsg = NSLocalizedStringWithDefaultValue(@"GCDAsyncSocketClosedError",
  2689. @"GCDAsyncSocket", [NSBundle mainBundle],
  2690. @"Socket closed by remote peer", nil);
  2691. NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  2692. return [NSError errorWithDomain:GCDAsyncSocketErrorDomain code:GCDAsyncSocketClosedError userInfo:userInfo];
  2693. }
  2694. - (NSError *)otherError:(NSString *)errMsg
  2695. {
  2696. NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
  2697. return [NSError errorWithDomain:GCDAsyncSocketErrorDomain code:GCDAsyncSocketOtherError userInfo:userInfo];
  2698. }
  2699. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2700. #pragma mark Diagnostics
  2701. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  2702. - (BOOL)isDisconnected
  2703. {
  2704. __block BOOL result = NO;
  2705. dispatch_block_t block = ^{
  2706. result = (flags & kSocketStarted) ? NO : YES;
  2707. };
  2708. if (dispatch_get_current_queue() == socketQueue)
  2709. block();
  2710. else
  2711. dispatch_sync(socketQueue, block);
  2712. return result;
  2713. }
  2714. - (BOOL)isConnected
  2715. {
  2716. __block BOOL result = NO;
  2717. dispatch_block_t block = ^{
  2718. result = (flags & kConnected) ? YES : NO;
  2719. };
  2720. if (dispatch_get_current_queue() == socketQueue)
  2721. block();
  2722. else
  2723. dispatch_sync(socketQueue, block);
  2724. return result;
  2725. }
  2726. - (NSString *)connectedHost
  2727. {
  2728. if (dispatch_get_current_queue() == socketQueue)
  2729. {
  2730. if (socket4FD != SOCKET_NULL)
  2731. return [self connectedHostFromSocket4:socket4FD];
  2732. if (socket6FD != SOCKET_NULL)
  2733. return [self connectedHostFromSocket6:socket6FD];
  2734. return nil;
  2735. }
  2736. else
  2737. {
  2738. __block NSString *result = nil;
  2739. dispatch_sync(socketQueue, ^{ @autoreleasepool {
  2740. if (socket4FD != SOCKET_NULL)
  2741. result = [self connectedHostFromSocket4:socket4FD];
  2742. else if (socket6FD != SOCKET_NULL)
  2743. result = [self connectedHostFromSocket6:socket6FD];
  2744. }});
  2745. return result;
  2746. }
  2747. }
  2748. - (uint16_t)connectedPort
  2749. {
  2750. if (dispatch_get_current_queue() == socketQueue)
  2751. {
  2752. if (socket4FD != SOCKET_NULL)
  2753. return [self connectedPortFromSocket4:socket4FD];
  2754. if (socket6FD != SOCKET_NULL)
  2755. return [self connectedPortFromSocket6:socket6FD];
  2756. return 0;
  2757. }
  2758. else
  2759. {
  2760. __block uint16_t result = 0;
  2761. dispatch_sync(socketQueue, ^{
  2762. // No need for autorelease pool
  2763. if (socket4FD != SOCKET_NULL)
  2764. result = [self connectedPortFromSocket4:socket4FD];
  2765. else if (socket6FD != SOCKET_NULL)
  2766. result = [self connectedPortFromSocket6:socket6FD];
  2767. });
  2768. return result;
  2769. }
  2770. }
  2771. - (NSURL *)connectedUrl
  2772. {
  2773. if (dispatch_get_current_queue() == socketQueue)
  2774. {
  2775. if (socketUN != SOCKET_NULL)
  2776. return [self connectedUrlFromSocketUN:socketUN];
  2777. return nil;
  2778. }
  2779. else
  2780. {
  2781. __block NSURL *result = nil;
  2782. dispatch_sync(socketQueue, ^{ @autoreleasepool {
  2783. if (socketUN != SOCKET_NULL)
  2784. result = [self connectedUrlFromSocketUN:socketUN];
  2785. }});
  2786. return result;
  2787. }
  2788. }
  2789. - (NSString *)localHost
  2790. {
  2791. if (dispatch_get_current_queue() == socketQueue)
  2792. {
  2793. if (socket4FD != SOCKET_NULL)
  2794. return [self localHostFromSocket4:socket4FD];
  2795. if (socket6FD != SOCKET_NULL)
  2796. return [self localHostFromSocket6:socket6FD];
  2797. return nil;
  2798. }
  2799. else
  2800. {
  2801. __block NSString *result = nil;
  2802. dispatch_sync(socketQueue, ^{ @autoreleasepool {
  2803. if (socket4FD != SOCKET_NULL)
  2804. result = [self localHostFromSocket4:socket4FD];
  2805. else if (socket6FD != SOCKET_NULL)
  2806. result = [self localHostFromSocket6:socket6FD];
  2807. }});
  2808. return result;
  2809. }
  2810. }
  2811. - (uint16_t)localPort
  2812. {
  2813. if (dispatch_get_current_queue() == socketQueue)
  2814. {
  2815. if (socket4FD != SOCKET_NULL)
  2816. return [self localPortFromSocket4:socket4FD];
  2817. if (socket6FD != SOCKET_NULL)
  2818. return [self localPortFromSocket6:socket6FD];
  2819. return 0;
  2820. }
  2821. else
  2822. {
  2823. __block uint16_t result = 0;
  2824. dispatch_sync(socketQueue, ^{
  2825. // No need for autorelease pool
  2826. if (socket4FD != SOCKET_NULL)
  2827. result = [self localPortFromSocket4:socket4FD];
  2828. else if (socket6FD != SOCKET_NULL)
  2829. result = [self localPortFromSocket6:socket6FD];
  2830. });
  2831. return result;
  2832. }
  2833. }
  2834. - (NSString *)connectedHost4
  2835. {
  2836. if (socket4FD != SOCKET_NULL)
  2837. return [self connectedHostFromSocket4:socket4FD];
  2838. return nil;
  2839. }
  2840. - (NSString *)connectedHost6
  2841. {
  2842. if (socket6FD != SOCKET_NULL)
  2843. return [self connectedHostFromSocket6:socket6FD];
  2844. return nil;
  2845. }
  2846. - (uint16_t)connectedPort4
  2847. {
  2848. if (socket4FD != SOCKET_NULL)
  2849. return [self connectedPortFromSocket4:socket4FD];
  2850. return 0;
  2851. }
  2852. - (uint16_t)connectedPort6
  2853. {
  2854. if (socket6FD != SOCKET_NULL)
  2855. return [self connectedPortFromSocket6:socket6FD];
  2856. return 0;
  2857. }
  2858. - (NSString *)localHost4
  2859. {
  2860. if (socket4FD != SOCKET_NULL)
  2861. return [self localHostFromSocket4:socket4FD];
  2862. return nil;
  2863. }
  2864. - (NSString *)localHost6
  2865. {
  2866. if (socket6FD != SOCKET_NULL)
  2867. return [self localHostFromSocket6:socket6FD];
  2868. return nil;
  2869. }
  2870. - (uint16_t)localPort4
  2871. {
  2872. if (socket4FD != SOCKET_NULL)
  2873. return [self localPortFromSocket4:socket4FD];
  2874. return 0;
  2875. }
  2876. - (uint16_t)localPort6
  2877. {
  2878. if (socket6FD != SOCKET_NULL)
  2879. return [self localPortFromSocket6:socket6FD];
  2880. return 0;
  2881. }
  2882. - (NSString *)connectedHostFromSocket4:(int)socketFD
  2883. {
  2884. struct sockaddr_in sockaddr4;
  2885. socklen_t sockaddr4len = sizeof(sockaddr4);
  2886. if (getpeername(socketFD, (struct sockaddr *)&sockaddr4, &sockaddr4len) < 0)
  2887. {
  2888. return nil;
  2889. }
  2890. return [[self class] hostFromSockaddr4:&sockaddr4];
  2891. }
  2892. - (NSString *)connectedHostFromSocket6:(int)socketFD
  2893. {
  2894. struct sockaddr_in6 sockaddr6;
  2895. socklen_t sockaddr6len = sizeof(sockaddr6);
  2896. if (getpeername(socketFD, (struct sockaddr *)&sockaddr6, &sockaddr6len) < 0)
  2897. {
  2898. return nil;
  2899. }
  2900. return [[self class] hostFromSockaddr6:&sockaddr6];
  2901. }
  2902. - (uint16_t)connectedPortFromSocket4:(int)socketFD
  2903. {
  2904. struct sockaddr_in sockaddr4;
  2905. socklen_t sockaddr4len = sizeof(sockaddr4);
  2906. if (getpeername(socketFD, (struct sockaddr *)&sockaddr4, &sockaddr4len) < 0)
  2907. {
  2908. return 0;
  2909. }
  2910. return [[self class] portFromSockaddr4:&sockaddr4];
  2911. }
  2912. - (uint16_t)connectedPortFromSocket6:(int)socketFD
  2913. {
  2914. struct sockaddr_in6 sockaddr6;
  2915. socklen_t sockaddr6len = sizeof(sockaddr6);
  2916. if (getpeername(socketFD, (struct sockaddr *)&sockaddr6, &sockaddr6len) < 0)
  2917. {
  2918. return 0;
  2919. }
  2920. return [[self class] portFromSockaddr6:&sockaddr6];
  2921. }
  2922. - (NSURL *)connectedUrlFromSocketUN:(int)socketFD
  2923. {
  2924. struct sockaddr_un sockaddr;
  2925. socklen_t sockaddrlen = sizeof(sockaddr);
  2926. if (getpeername(socketFD, (struct sockaddr *)&sockaddr, &sockaddrlen) < 0)
  2927. {
  2928. return 0;
  2929. }
  2930. return [[self class] urlFromSockaddrUN:&sockaddr];
  2931. }
  2932. - (NSString *)localHostFromSocket4:(int)socketFD
  2933. {
  2934. struct sockaddr_in sockaddr4;
  2935. socklen_t sockaddr4len = sizeof(sockaddr4);
  2936. if (getsockname(socketFD, (struct sockaddr *)&sockaddr4, &sockaddr4len) < 0)
  2937. {
  2938. return nil;
  2939. }
  2940. return [[self class] hostFromSockaddr4:&sockaddr4];
  2941. }
  2942. - (NSString *)localHostFromSocket6:(int)socketFD
  2943. {
  2944. struct sockaddr_in6 sockaddr6;
  2945. socklen_t sockaddr6len = sizeof(sockaddr6);
  2946. if (getsockname(socketFD, (struct sockaddr *)&sockaddr6, &sockaddr6len) < 0)
  2947. {
  2948. return nil;
  2949. }
  2950. return [[self class] hostFromSockaddr6:&sockaddr6];
  2951. }
  2952. - (uint16_t)localPortFromSocket4:(int)socketFD
  2953. {
  2954. struct sockaddr_in sockaddr4;
  2955. socklen_t sockaddr4len = sizeof(sockaddr4);
  2956. if (getsockname(socketFD, (struct sockaddr *)&sockaddr4, &sockaddr4len) < 0)
  2957. {
  2958. return 0;
  2959. }
  2960. return [[self class] portFromSockaddr4:&sockaddr4];
  2961. }
  2962. - (uint16_t)localPortFromSocket6:(int)socketFD
  2963. {
  2964. struct sockaddr_in6 sockaddr6;
  2965. socklen_t sockaddr6len = sizeof(sockaddr6);
  2966. if (getsockname(socketFD, (struct sockaddr *)&sockaddr6, &sockaddr6len) < 0)
  2967. {
  2968. return 0;
  2969. }
  2970. return [[self class] portFromSockaddr6:&sockaddr6];
  2971. }
  2972. - (NSData *)connectedAddress
  2973. {
  2974. __block NSData *result = nil;
  2975. dispatch_block_t block = ^{
  2976. if (socket4FD != SOCKET_NULL)
  2977. {
  2978. struct sockaddr_in sockaddr4;
  2979. socklen_t sockaddr4len = sizeof(sockaddr4);
  2980. if (getpeername(socket4FD, (struct sockaddr *)&sockaddr4, &sockaddr4len) == 0)
  2981. {
  2982. result = [[NSData alloc] initWithBytes:&sockaddr4 length:sockaddr4len];
  2983. }
  2984. }
  2985. if (socket6FD != SOCKET_NULL)
  2986. {
  2987. struct sockaddr_in6 sockaddr6;
  2988. socklen_t sockaddr6len = sizeof(sockaddr6);
  2989. if (getpeername(socket6FD, (struct sockaddr *)&sockaddr6, &sockaddr6len) == 0)
  2990. {
  2991. result = [[NSData alloc] initWithBytes:&sockaddr6 length:sockaddr6len];
  2992. }
  2993. }
  2994. };
  2995. if (dispatch_get_current_queue() == socketQueue)
  2996. block();
  2997. else
  2998. dispatch_sync(socketQueue, block);
  2999. return result;
  3000. }
  3001. - (NSData *)localAddress
  3002. {
  3003. __block NSData *result = nil;
  3004. dispatch_block_t block = ^{
  3005. if (socket4FD != SOCKET_NULL)
  3006. {
  3007. struct sockaddr_in sockaddr4;
  3008. socklen_t sockaddr4len = sizeof(sockaddr4);
  3009. if (getsockname(socket4FD, (struct sockaddr *)&sockaddr4, &sockaddr4len) == 0)
  3010. {
  3011. result = [[NSData alloc] initWithBytes:&sockaddr4 length:sockaddr4len];
  3012. }
  3013. }
  3014. if (socket6FD != SOCKET_NULL)
  3015. {
  3016. struct sockaddr_in6 sockaddr6;
  3017. socklen_t sockaddr6len = sizeof(sockaddr6);
  3018. if (getsockname(socket6FD, (struct sockaddr *)&sockaddr6, &sockaddr6len) == 0)
  3019. {
  3020. result = [[NSData alloc] initWithBytes:&sockaddr6 length:sockaddr6len];
  3021. }
  3022. }
  3023. };
  3024. if (dispatch_get_current_queue() == socketQueue)
  3025. block();
  3026. else
  3027. dispatch_sync(socketQueue, block);
  3028. return result;
  3029. }
  3030. - (BOOL)isIPv4
  3031. {
  3032. if (dispatch_get_current_queue() == socketQueue)
  3033. {
  3034. return (socket4FD != SOCKET_NULL);
  3035. }
  3036. else
  3037. {
  3038. __block BOOL result = NO;
  3039. dispatch_sync(socketQueue, ^{
  3040. result = (socket4FD != SOCKET_NULL);
  3041. });
  3042. return result;
  3043. }
  3044. }
  3045. - (BOOL)isIPv6
  3046. {
  3047. if (dispatch_get_current_queue() == socketQueue)
  3048. {
  3049. return (socket6FD != SOCKET_NULL);
  3050. }
  3051. else
  3052. {
  3053. __block BOOL result = NO;
  3054. dispatch_sync(socketQueue, ^{
  3055. result = (socket6FD != SOCKET_NULL);
  3056. });
  3057. return result;
  3058. }
  3059. }
  3060. - (BOOL)isSecure
  3061. {
  3062. if (dispatch_get_current_queue() == socketQueue)
  3063. {
  3064. return (flags & kSocketSecure) ? YES : NO;
  3065. }
  3066. else
  3067. {
  3068. __block BOOL result;
  3069. dispatch_sync(socketQueue, ^{
  3070. result = (flags & kSocketSecure) ? YES : NO;
  3071. });
  3072. return result;
  3073. }
  3074. }
  3075. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  3076. #pragma mark Utilities
  3077. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  3078. /**
  3079. * Finds the address of an interface description.
  3080. * An inteface description may be an interface name (en0, en1, lo0) or corresponding IP (192.168.4.34).
  3081. *
  3082. * The interface description may optionally contain a port number at the end, separated by a colon.
  3083. * If a non-zero port parameter is provided, any port number in the interface description is ignored.
  3084. *
  3085. * The returned value is a 'struct sockaddr' wrapped in an NSMutableData object.
  3086. **/
  3087. - (void)getInterfaceAddress4:(NSMutableData **)interfaceAddr4Ptr
  3088. address6:(NSMutableData **)interfaceAddr6Ptr
  3089. fromDescription:(NSString *)interfaceDescription
  3090. port:(uint16_t)port
  3091. {
  3092. NSMutableData *addr4 = nil;
  3093. NSMutableData *addr6 = nil;
  3094. NSString *interface = nil;
  3095. NSArray *components = [interfaceDescription componentsSeparatedByString:@":"];
  3096. if ([components count] > 0)
  3097. {
  3098. NSString *temp = [components objectAtIndex:0];
  3099. if ([temp length] > 0)
  3100. {
  3101. interface = temp;
  3102. }
  3103. }
  3104. if ([components count] > 1 && port == 0)
  3105. {
  3106. long portL = strtol([[components objectAtIndex:1] UTF8String], NULL, 10);
  3107. if (portL > 0 && portL <= UINT16_MAX)
  3108. {
  3109. port = (uint16_t)portL;
  3110. }
  3111. }
  3112. if (interface == nil)
  3113. {
  3114. // ANY address
  3115. struct sockaddr_in sockaddr4;
  3116. memset(&sockaddr4, 0, sizeof(sockaddr4));
  3117. sockaddr4.sin_len = sizeof(sockaddr4);
  3118. sockaddr4.sin_family = AF_INET;
  3119. sockaddr4.sin_port = htons(port);
  3120. sockaddr4.sin_addr.s_addr = htonl(INADDR_ANY);
  3121. struct sockaddr_in6 sockaddr6;
  3122. memset(&sockaddr6, 0, sizeof(sockaddr6));
  3123. sockaddr6.sin6_len = sizeof(sockaddr6);
  3124. sockaddr6.sin6_family = AF_INET6;
  3125. sockaddr6.sin6_port = htons(port);
  3126. sockaddr6.sin6_addr = in6addr_any;
  3127. addr4 = [NSMutableData dataWithBytes:&sockaddr4 length:sizeof(sockaddr4)];
  3128. addr6 = [NSMutableData dataWithBytes:&sockaddr6 length:sizeof(sockaddr6)];
  3129. }
  3130. else if ([interface isEqualToString:@"localhost"] || [interface isEqualToString:@"loopback"])
  3131. {
  3132. // LOOPBACK address
  3133. struct sockaddr_in sockaddr4;
  3134. memset(&sockaddr4, 0, sizeof(sockaddr4));
  3135. sockaddr4.sin_len = sizeof(sockaddr4);
  3136. sockaddr4.sin_family = AF_INET;
  3137. sockaddr4.sin_port = htons(port);
  3138. sockaddr4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  3139. struct sockaddr_in6 sockaddr6;
  3140. memset(&sockaddr6, 0, sizeof(sockaddr6));
  3141. sockaddr6.sin6_len = sizeof(sockaddr6);
  3142. sockaddr6.sin6_family = AF_INET6;
  3143. sockaddr6.sin6_port = htons(port);
  3144. sockaddr6.sin6_addr = in6addr_loopback;
  3145. addr4 = [NSMutableData dataWithBytes:&sockaddr4 length:sizeof(sockaddr4)];
  3146. addr6 = [NSMutableData dataWithBytes:&sockaddr6 length:sizeof(sockaddr6)];
  3147. }
  3148. else
  3149. {
  3150. const char *iface = [interface UTF8String];
  3151. struct ifaddrs *addrs;
  3152. const struct ifaddrs *cursor;
  3153. if ((getifaddrs(&addrs) == 0))
  3154. {
  3155. cursor = addrs;
  3156. while (cursor != NULL)
  3157. {
  3158. if ((addr4 == nil) && (cursor->ifa_addr->sa_family == AF_INET))
  3159. {
  3160. // IPv4
  3161. struct sockaddr_in nativeAddr4;
  3162. memcpy(&nativeAddr4, cursor->ifa_addr, sizeof(nativeAddr4));
  3163. if (strcmp(cursor->ifa_name, iface) == 0)
  3164. {
  3165. // Name match
  3166. nativeAddr4.sin_port = htons(port);
  3167. addr4 = [NSMutableData dataWithBytes:&nativeAddr4 length:sizeof(nativeAddr4)];
  3168. }
  3169. else
  3170. {
  3171. char ip[INET_ADDRSTRLEN];
  3172. const char *conversion = inet_ntop(AF_INET, &nativeAddr4.sin_addr, ip, sizeof(ip));
  3173. if ((conversion != NULL) && (strcmp(ip, iface) == 0))
  3174. {
  3175. // IP match
  3176. nativeAddr4.sin_port = htons(port);
  3177. addr4 = [NSMutableData dataWithBytes:&nativeAddr4 length:sizeof(nativeAddr4)];
  3178. }
  3179. }
  3180. }
  3181. else if ((addr6 == nil) && (cursor->ifa_addr->sa_family == AF_INET6))
  3182. {
  3183. // IPv6
  3184. struct sockaddr_in6 nativeAddr6;
  3185. memcpy(&nativeAddr6, cursor->ifa_addr, sizeof(nativeAddr6));
  3186. if (strcmp(cursor->ifa_name, iface) == 0)
  3187. {
  3188. // Name match
  3189. nativeAddr6.sin6_port = htons(port);
  3190. addr6 = [NSMutableData dataWithBytes:&nativeAddr6 length:sizeof(nativeAddr6)];
  3191. }
  3192. else
  3193. {
  3194. char ip[INET6_ADDRSTRLEN];
  3195. const char *conversion = inet_ntop(AF_INET6, &nativeAddr6.sin6_addr, ip, sizeof(ip));
  3196. if ((conversion != NULL) && (strcmp(ip, iface) == 0))
  3197. {
  3198. // IP match
  3199. nativeAddr6.sin6_port = htons(port);
  3200. addr6 = [NSMutableData dataWithBytes:&nativeAddr6 length:sizeof(nativeAddr6)];
  3201. }
  3202. }
  3203. }
  3204. cursor = cursor->ifa_next;
  3205. }
  3206. freeifaddrs(addrs);
  3207. }
  3208. }
  3209. if (interfaceAddr4Ptr) *interfaceAddr4Ptr = addr4;
  3210. if (interfaceAddr6Ptr) *interfaceAddr6Ptr = addr6;
  3211. }
  3212. - (NSData *)getInterfaceAddressFromUrl:(NSURL *)url;
  3213. {
  3214. NSString *path = url.path;
  3215. if (path.length == 0) {
  3216. return nil;
  3217. }
  3218. struct sockaddr_un nativeAddr;
  3219. nativeAddr.sun_family = AF_UNIX;
  3220. strcpy(nativeAddr.sun_path, path.fileSystemRepresentation);
  3221. nativeAddr.sun_len = SUN_LEN(&nativeAddr);
  3222. NSData *interface = [NSData dataWithBytes:&nativeAddr length:sizeof(struct sockaddr_un)];
  3223. return interface;
  3224. }
  3225. - (void)setupReadAndWriteSourcesForNewlyConnectedSocket:(int)socketFD
  3226. {
  3227. readSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, socketFD, 0, socketQueue);
  3228. writeSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_WRITE, socketFD, 0, socketQueue);
  3229. // Setup event handlers
  3230. dispatch_source_set_event_handler(readSource, ^{ @autoreleasepool {
  3231. LogVerbose(@"readEventBlock");
  3232. socketFDBytesAvailable = dispatch_source_get_data(readSource);
  3233. LogVerbose(@"socketFDBytesAvailable: %lu", socketFDBytesAvailable);
  3234. if (socketFDBytesAvailable > 0)
  3235. [self doReadData];
  3236. else
  3237. [self doReadEOF];
  3238. }});
  3239. dispatch_source_set_event_handler(writeSource, ^{ @autoreleasepool {
  3240. LogVerbose(@"writeEventBlock");
  3241. flags |= kSocketCanAcceptBytes;
  3242. [self doWriteData];
  3243. }});
  3244. // Setup cancel handlers
  3245. __block int socketFDRefCount = 2;
  3246. #if NEEDS_DISPATCH_RETAIN_RELEASE
  3247. dispatch_source_t theReadSource = readSource;
  3248. dispatch_source_t theWriteSource = writeSource;
  3249. #endif
  3250. dispatch_source_set_cancel_handler(readSource, ^{
  3251. LogVerbose(@"readCancelBlock");
  3252. #if NEEDS_DISPATCH_RETAIN_RELEASE
  3253. LogVerbose(@"dispatch_release(readSource)");
  3254. dispatch_release(theReadSource);
  3255. #endif
  3256. if (--socketFDRefCount == 0)
  3257. {
  3258. LogVerbose(@"close(socketFD)");
  3259. close(socketFD);
  3260. }
  3261. });
  3262. dispatch_source_set_cancel_handler(writeSource, ^{
  3263. LogVerbose(@"writeCancelBlock");
  3264. #if NEEDS_DISPATCH_RETAIN_RELEASE
  3265. LogVerbose(@"dispatch_release(writeSource)");
  3266. dispatch_release(theWriteSource);
  3267. #endif
  3268. if (--socketFDRefCount == 0)
  3269. {
  3270. LogVerbose(@"close(socketFD)");
  3271. close(socketFD);
  3272. }
  3273. });
  3274. // We will not be able to read until data arrives.
  3275. // But we should be able to write immediately.
  3276. socketFDBytesAvailable = 0;
  3277. flags &= ~kReadSourceSuspended;
  3278. LogVerbose(@"dispatch_resume(readSource)");
  3279. dispatch_resume(readSource);
  3280. flags |= kSocketCanAcceptBytes;
  3281. flags |= kWriteSourceSuspended;
  3282. }
  3283. - (BOOL)usingCFStreamForTLS
  3284. {
  3285. #if TARGET_OS_IPHONE
  3286. {
  3287. if ((flags & kSocketSecure) && (flags & kUsingCFStreamForTLS))
  3288. {
  3289. // Due to the fact that Apple doesn't give us the full power of SecureTransport on iOS,
  3290. // we are relegated to using the slower, less powerful, and RunLoop based CFStream API. :( Boo!
  3291. //
  3292. // Thus we're not able to use the GCD read/write sources in this particular scenario.
  3293. return YES;
  3294. }
  3295. }
  3296. #endif
  3297. return NO;
  3298. }
  3299. - (BOOL)usingSecureTransportForTLS
  3300. {
  3301. #if TARGET_OS_IPHONE
  3302. {
  3303. return ![self usingCFStreamForTLS];
  3304. }
  3305. #endif
  3306. return YES;
  3307. }
  3308. - (void)suspendReadSource
  3309. {
  3310. if (!(flags & kReadSourceSuspended))
  3311. {
  3312. LogVerbose(@"dispatch_suspend(readSource)");
  3313. dispatch_suspend(readSource);
  3314. flags |= kReadSourceSuspended;
  3315. }
  3316. }
  3317. - (void)resumeReadSource
  3318. {
  3319. if (flags & kReadSourceSuspended)
  3320. {
  3321. LogVerbose(@"dispatch_resume(readSource)");
  3322. dispatch_resume(readSource);
  3323. flags &= ~kReadSourceSuspended;
  3324. }
  3325. }
  3326. - (void)suspendWriteSource
  3327. {
  3328. if (!(flags & kWriteSourceSuspended))
  3329. {
  3330. LogVerbose(@"dispatch_suspend(writeSource)");
  3331. dispatch_suspend(writeSource);
  3332. flags |= kWriteSourceSuspended;
  3333. }
  3334. }
  3335. - (void)resumeWriteSource
  3336. {
  3337. if (flags & kWriteSourceSuspended)
  3338. {
  3339. LogVerbose(@"dispatch_resume(writeSource)");
  3340. dispatch_resume(writeSource);
  3341. flags &= ~kWriteSourceSuspended;
  3342. }
  3343. }
  3344. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  3345. #pragma mark Reading
  3346. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  3347. - (void)readDataWithTimeout:(NSTimeInterval)timeout tag:(long)tag
  3348. {
  3349. [self readDataWithTimeout:timeout buffer:nil bufferOffset:0 maxLength:0 tag:tag];
  3350. }
  3351. - (void)readDataWithTimeout:(NSTimeInterval)timeout
  3352. buffer:(NSMutableData *)buffer
  3353. bufferOffset:(NSUInteger)offset
  3354. tag:(long)tag
  3355. {
  3356. [self readDataWithTimeout:timeout buffer:buffer bufferOffset:offset maxLength:0 tag:tag];
  3357. }
  3358. - (void)readDataWithTimeout:(NSTimeInterval)timeout
  3359. buffer:(NSMutableData *)buffer
  3360. bufferOffset:(NSUInteger)offset
  3361. maxLength:(NSUInteger)length
  3362. tag:(long)tag
  3363. {
  3364. if (offset > [buffer length]) {
  3365. LogWarn(@"Cannot read: offset > [buffer length]");
  3366. return;
  3367. }
  3368. GCDAsyncReadPacket *packet = [[GCDAsyncReadPacket alloc] initWithData:buffer
  3369. startOffset:offset
  3370. maxLength:length
  3371. timeout:timeout
  3372. readLength:0
  3373. terminator:nil
  3374. tag:tag];
  3375. dispatch_async(socketQueue, ^{ @autoreleasepool {
  3376. LogTrace();
  3377. if ((flags & kSocketStarted) && !(flags & kForbidReadsWrites))
  3378. {
  3379. [readQueue addObject:packet];
  3380. [self maybeDequeueRead];
  3381. }
  3382. }});
  3383. // Do not rely on the block being run in order to release the packet,
  3384. // as the queue might get released without the block completing.
  3385. }
  3386. - (void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)timeout tag:(long)tag
  3387. {
  3388. [self readDataToLength:length withTimeout:timeout buffer:nil bufferOffset:0 tag:tag];
  3389. }
  3390. - (void)readDataToLength:(NSUInteger)length
  3391. withTimeout:(NSTimeInterval)timeout
  3392. buffer:(NSMutableData *)buffer
  3393. bufferOffset:(NSUInteger)offset
  3394. tag:(long)tag
  3395. {
  3396. if (length == 0) {
  3397. LogWarn(@"Cannot read: length == 0");
  3398. return;
  3399. }
  3400. if (offset > [buffer length]) {
  3401. LogWarn(@"Cannot read: offset > [buffer length]");
  3402. return;
  3403. }
  3404. GCDAsyncReadPacket *packet = [[GCDAsyncReadPacket alloc] initWithData:buffer
  3405. startOffset:offset
  3406. maxLength:0
  3407. timeout:timeout
  3408. readLength:length
  3409. terminator:nil
  3410. tag:tag];
  3411. dispatch_async(socketQueue, ^{ @autoreleasepool {
  3412. LogTrace();
  3413. if ((flags & kSocketStarted) && !(flags & kForbidReadsWrites))
  3414. {
  3415. [readQueue addObject:packet];
  3416. [self maybeDequeueRead];
  3417. }
  3418. }});
  3419. // Do not rely on the block being run in order to release the packet,
  3420. // as the queue might get released without the block completing.
  3421. }
  3422. - (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag
  3423. {
  3424. [self readDataToData:data withTimeout:timeout buffer:nil bufferOffset:0 maxLength:0 tag:tag];
  3425. }
  3426. - (void)readDataToData:(NSData *)data
  3427. withTimeout:(NSTimeInterval)timeout
  3428. buffer:(NSMutableData *)buffer
  3429. bufferOffset:(NSUInteger)offset
  3430. tag:(long)tag
  3431. {
  3432. [self readDataToData:data withTimeout:timeout buffer:buffer bufferOffset:offset maxLength:0 tag:tag];
  3433. }
  3434. - (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout maxLength:(NSUInteger)length tag:(long)tag
  3435. {
  3436. [self readDataToData:data withTimeout:timeout buffer:nil bufferOffset:0 maxLength:length tag:tag];
  3437. }
  3438. - (void)readDataToData:(NSData *)data
  3439. withTimeout:(NSTimeInterval)timeout
  3440. buffer:(NSMutableData *)buffer
  3441. bufferOffset:(NSUInteger)offset
  3442. maxLength:(NSUInteger)maxLength
  3443. tag:(long)tag
  3444. {
  3445. if ([data length] == 0) {
  3446. LogWarn(@"Cannot read: [data length] == 0");
  3447. return;
  3448. }
  3449. if (offset > [buffer length]) {
  3450. LogWarn(@"Cannot read: offset > [buffer length]");
  3451. return;
  3452. }
  3453. if (maxLength > 0 && maxLength < [data length]) {
  3454. LogWarn(@"Cannot read: maxLength > 0 && maxLength < [data length]");
  3455. return;
  3456. }
  3457. GCDAsyncReadPacket *packet = [[GCDAsyncReadPacket alloc] initWithData:buffer
  3458. startOffset:offset
  3459. maxLength:maxLength
  3460. timeout:timeout
  3461. readLength:0
  3462. terminator:data
  3463. tag:tag];
  3464. dispatch_async(socketQueue, ^{ @autoreleasepool {
  3465. LogTrace();
  3466. if ((flags & kSocketStarted) && !(flags & kForbidReadsWrites))
  3467. {
  3468. [readQueue addObject:packet];
  3469. [self maybeDequeueRead];
  3470. }
  3471. }});
  3472. // Do not rely on the block being run in order to release the packet,
  3473. // as the queue might get released without the block completing.
  3474. }
  3475. - (float)progressOfReadReturningTag:(long *)tagPtr bytesDone:(NSUInteger *)donePtr total:(NSUInteger *)totalPtr
  3476. {
  3477. __block float result = 0.0F;
  3478. dispatch_block_t block = ^{
  3479. if (!currentRead || ![currentRead isKindOfClass:[GCDAsyncReadPacket class]])
  3480. {
  3481. // We're not reading anything right now.
  3482. if (tagPtr != NULL) *tagPtr = 0;
  3483. if (donePtr != NULL) *donePtr = 0;
  3484. if (totalPtr != NULL) *totalPtr = 0;
  3485. result = NAN;
  3486. }
  3487. else
  3488. {
  3489. // It's only possible to know the progress of our read if we're reading to a certain length.
  3490. // If we're reading to data, we of course have no idea when the data will arrive.
  3491. // If we're reading to timeout, then we have no idea when the next chunk of data will arrive.
  3492. NSUInteger done = currentRead->bytesDone;
  3493. NSUInteger total = currentRead->readLength;
  3494. if (tagPtr != NULL) *tagPtr = currentRead->tag;
  3495. if (donePtr != NULL) *donePtr = done;
  3496. if (totalPtr != NULL) *totalPtr = total;
  3497. if (total > 0)
  3498. result = (float)done / (float)total;
  3499. else
  3500. result = 1.0F;
  3501. }
  3502. };
  3503. if (dispatch_get_current_queue() == socketQueue)
  3504. block();
  3505. else
  3506. dispatch_sync(socketQueue, block);
  3507. return result;
  3508. }
  3509. /**
  3510. * This method starts a new read, if needed.
  3511. *
  3512. * It is called when:
  3513. * - a user requests a read
  3514. * - after a read request has finished (to handle the next request)
  3515. * - immediately after the socket opens to handle any pending requests
  3516. *
  3517. * This method also handles auto-disconnect post read/write completion.
  3518. **/
  3519. - (void)maybeDequeueRead
  3520. {
  3521. LogTrace();
  3522. NSAssert(dispatch_get_current_queue() == socketQueue, @"Must be dispatched on socketQueue");
  3523. // If we're not currently processing a read AND we have an available read stream
  3524. if ((currentRead == nil) && (flags & kConnected))
  3525. {
  3526. if ([readQueue count] > 0)
  3527. {
  3528. // Dequeue the next object in the write queue
  3529. currentRead = [readQueue objectAtIndex:0];
  3530. [readQueue removeObjectAtIndex:0];
  3531. if ([currentRead isKindOfClass:[GCDAsyncSpecialPacket class]])
  3532. {
  3533. LogVerbose(@"Dequeued GCDAsyncSpecialPacket");
  3534. // Attempt to start TLS
  3535. flags |= kStartingReadTLS;
  3536. // This method won't do anything unless both kStartingReadTLS and kStartingWriteTLS are set
  3537. [self maybeStartTLS];
  3538. }
  3539. else
  3540. {
  3541. LogVerbose(@"Dequeued GCDAsyncReadPacket");
  3542. // Setup read timer (if needed)
  3543. [self setupReadTimerWithTimeout:currentRead->timeout];
  3544. // Immediately read, if possible
  3545. [self doReadData];
  3546. }
  3547. }
  3548. else if (flags & kDisconnectAfterReads)
  3549. {
  3550. if (flags & kDisconnectAfterWrites)
  3551. {
  3552. if (([writeQueue count] == 0) && (currentWrite == nil))
  3553. {
  3554. [self closeWithError:nil];
  3555. }
  3556. }
  3557. else
  3558. {
  3559. [self closeWithError:nil];
  3560. }
  3561. }
  3562. else if (flags & kSocketSecure)
  3563. {
  3564. [self flushSSLBuffers];
  3565. // Edge case:
  3566. //
  3567. // We just drained all data from the ssl buffers,
  3568. // and all known data from the socket (socketFDBytesAvailable).
  3569. //
  3570. // If we didn't get any data from this process,
  3571. // then we may have reached the end of the TCP stream.
  3572. //
  3573. // Be sure callbacks are enabled so we're notified about a disconnection.
  3574. if ([preBuffer availableBytes] == 0)
  3575. {
  3576. if ([self usingCFStreamForTLS]) {
  3577. // Callbacks never disabled
  3578. }
  3579. else {
  3580. [self resumeReadSource];
  3581. }
  3582. }
  3583. }
  3584. }
  3585. }
  3586. - (void)flushSSLBuffers
  3587. {
  3588. LogTrace();
  3589. NSAssert((flags & kSocketSecure), @"Cannot flush ssl buffers on non-secure socket");
  3590. if ([preBuffer availableBytes] > 0)
  3591. {
  3592. // Only flush the ssl buffers if the prebuffer is empty.
  3593. // This is to avoid growing the prebuffer inifinitely large.
  3594. return;
  3595. }
  3596. #if TARGET_OS_IPHONE
  3597. if ([self usingCFStreamForTLS])
  3598. {
  3599. if ((flags & kSecureSocketHasBytesAvailable) && CFReadStreamHasBytesAvailable(readStream))
  3600. {
  3601. LogVerbose(@"%@ - Flushing ssl buffers into prebuffer...", THIS_METHOD);
  3602. CFIndex defaultBytesToRead = (1024 * 4);
  3603. [preBuffer ensureCapacityForWrite:defaultBytesToRead];
  3604. uint8_t *buffer = [preBuffer writeBuffer];
  3605. CFIndex result = CFReadStreamRead(readStream, buffer, defaultBytesToRead);
  3606. LogVerbose(@"%@ - CFReadStreamRead(): result = %i", THIS_METHOD, (int)result);
  3607. if (result > 0)
  3608. {
  3609. [preBuffer didWrite:result];
  3610. }
  3611. flags &= ~kSecureSocketHasBytesAvailable;
  3612. }
  3613. return;
  3614. }
  3615. #endif
  3616. #if SECURE_TRANSPORT_MAYBE_AVAILABLE
  3617. __block NSUInteger estimatedBytesAvailable = 0;
  3618. dispatch_block_t updateEstimatedBytesAvailable = ^{
  3619. // Figure out if there is any data available to be read
  3620. //
  3621. // socketFDBytesAvailable <- Number of encrypted bytes we haven't read from the bsd socket
  3622. // [sslPreBuffer availableBytes] <- Number of encrypted bytes we've buffered from bsd socket
  3623. // sslInternalBufSize <- Number of decrypted bytes SecureTransport has buffered
  3624. //
  3625. // We call the variable "estimated" because we don't know how many decrypted bytes we'll get
  3626. // from the encrypted bytes in the sslPreBuffer.
  3627. // However, we do know this is an upper bound on the estimation.
  3628. estimatedBytesAvailable = socketFDBytesAvailable + [sslPreBuffer availableBytes];
  3629. size_t sslInternalBufSize = 0;
  3630. SSLGetBufferedReadSize(sslContext, &sslInternalBufSize);
  3631. estimatedBytesAvailable += sslInternalBufSize;
  3632. };
  3633. updateEstimatedBytesAvailable();
  3634. if (estimatedBytesAvailable > 0)
  3635. {
  3636. LogVerbose(@"%@ - Flushing ssl buffers into prebuffer...", THIS_METHOD);
  3637. BOOL done = NO;
  3638. do
  3639. {
  3640. LogVerbose(@"%@ - estimatedBytesAvailable = %lu", THIS_METHOD, (unsigned long)estimatedBytesAvailable);
  3641. // Make sure there's enough room in the prebuffer
  3642. [preBuffer ensureCapacityForWrite:estimatedBytesAvailable];
  3643. // Read data into prebuffer
  3644. uint8_t *buffer = [preBuffer writeBuffer];
  3645. size_t bytesRead = 0;
  3646. OSStatus result = SSLRead(sslContext, buffer, (size_t)estimatedBytesAvailable, &bytesRead);
  3647. LogVerbose(@"%@ - read from secure socket = %u", THIS_METHOD, (unsigned)bytesRead);
  3648. if (bytesRead > 0)
  3649. {
  3650. [preBuffer didWrite:bytesRead];
  3651. }
  3652. LogVerbose(@"%@ - prebuffer.length = %zu", THIS_METHOD, [preBuffer availableBytes]);
  3653. if (result != noErr)
  3654. {
  3655. done = YES;
  3656. }
  3657. else
  3658. {
  3659. updateEstimatedBytesAvailable();
  3660. }
  3661. } while (!done && estimatedBytesAvailable > 0);
  3662. }
  3663. #endif
  3664. }
  3665. - (void)doReadData
  3666. {
  3667. LogTrace();
  3668. // This method is called on the socketQueue.
  3669. // It might be called directly, or via the readSource when data is available to be read.
  3670. if ((currentRead == nil) || (flags & kReadsPaused))
  3671. {
  3672. LogVerbose(@"No currentRead or kReadsPaused");
  3673. // Unable to read at this time
  3674. if (flags & kSocketSecure)
  3675. {
  3676. // Here's the situation:
  3677. //
  3678. // We have an established secure connection.
  3679. // There may not be a currentRead, but there might be encrypted data sitting around for us.
  3680. // When the user does get around to issuing a read, that encrypted data will need to be decrypted.
  3681. //
  3682. // So why make the user wait?
  3683. // We might as well get a head start on decrypting some data now.
  3684. //
  3685. // The other reason we do this has to do with detecting a socket disconnection.
  3686. // The SSL/TLS protocol has it's own disconnection handshake.
  3687. // So when a secure socket is closed, a "goodbye" packet comes across the wire.
  3688. // We want to make sure we read the "goodbye" packet so we can properly detect the TCP disconnection.
  3689. [self flushSSLBuffers];
  3690. }
  3691. if ([self usingCFStreamForTLS])
  3692. {
  3693. // CFReadStream only fires once when there is available data.
  3694. // It won't fire again until we've invoked CFReadStreamRead.
  3695. }
  3696. else
  3697. {
  3698. // If the readSource is firing, we need to pause it
  3699. // or else it will continue to fire over and over again.
  3700. //
  3701. // If the readSource is not firing,
  3702. // we want it to continue monitoring the socket.
  3703. if (socketFDBytesAvailable > 0)
  3704. {
  3705. [self suspendReadSource];
  3706. }
  3707. }
  3708. return;
  3709. }
  3710. BOOL hasBytesAvailable;
  3711. unsigned long estimatedBytesAvailable;
  3712. if ([self usingCFStreamForTLS])
  3713. {
  3714. #if TARGET_OS_IPHONE
  3715. // Relegated to using CFStream... :( Boo! Give us a full SecureTransport stack Apple!
  3716. estimatedBytesAvailable = 0;
  3717. if ((flags & kSecureSocketHasBytesAvailable) && CFReadStreamHasBytesAvailable(readStream))
  3718. hasBytesAvailable = YES;
  3719. else
  3720. hasBytesAvailable = NO;
  3721. #endif
  3722. }
  3723. else
  3724. {
  3725. #if SECURE_TRANSPORT_MAYBE_AVAILABLE
  3726. estimatedBytesAvailable = socketFDBytesAvailable;
  3727. if (flags & kSocketSecure)
  3728. {
  3729. // There are 2 buffers to be aware of here.
  3730. //
  3731. // We are using SecureTransport, a TLS/SSL security layer which sits atop TCP.
  3732. // We issue a read to the SecureTranport API, which in turn issues a read to our SSLReadFunction.
  3733. // Our SSLReadFunction then reads from the BSD socket and returns the encrypted data to SecureTransport.
  3734. // SecureTransport then decrypts the data, and finally returns the decrypted data back to us.
  3735. //
  3736. // The first buffer is one we create.
  3737. // SecureTransport often requests small amounts of data.
  3738. // This has to do with the encypted packets that are coming across the TCP stream.
  3739. // But it's non-optimal to do a bunch of small reads from the BSD socket.
  3740. // So our SSLReadFunction reads all available data from the socket (optimizing the sys call)
  3741. // and may store excess in the sslPreBuffer.
  3742. estimatedBytesAvailable += [sslPreBuffer availableBytes];
  3743. // The second buffer is within SecureTransport.
  3744. // As mentioned earlier, there are encrypted packets coming across the TCP stream.
  3745. // SecureTransport needs the entire packet to decrypt it.
  3746. // But if the entire packet produces X bytes of decrypted data,
  3747. // and we only asked SecureTransport for X/2 bytes of data,
  3748. // it must store the extra X/2 bytes of decrypted data for the next read.
  3749. //
  3750. // The SSLGetBufferedReadSize function will tell us the size of this internal buffer.
  3751. // From the documentation:
  3752. //
  3753. // "This function does not block or cause any low-level read operations to occur."
  3754. size_t sslInternalBufSize = 0;
  3755. SSLGetBufferedReadSize(sslContext, &sslInternalBufSize);
  3756. estimatedBytesAvailable += sslInternalBufSize;
  3757. }
  3758. hasBytesAvailable = (estimatedBytesAvailable > 0);
  3759. #endif
  3760. }
  3761. if ((hasBytesAvailable == NO) && ([preBuffer availableBytes] == 0))
  3762. {
  3763. LogVerbose(@"No data available to read...");
  3764. // No data available to read.
  3765. if (![self usingCFStreamForTLS])
  3766. {
  3767. // Need to wait for readSource to fire and notify us of
  3768. // available data in the socket's internal read buffer.
  3769. [self resumeReadSource];
  3770. }
  3771. return;
  3772. }
  3773. if (flags & kStartingReadTLS)
  3774. {
  3775. LogVerbose(@"Waiting for SSL/TLS handshake to complete");
  3776. // The readQueue is waiting for SSL/TLS handshake to complete.
  3777. if (flags & kStartingWriteTLS)
  3778. {
  3779. if ([self usingSecureTransportForTLS])
  3780. {
  3781. #if SECURE_TRANSPORT_MAYBE_AVAILABLE
  3782. // We are in the process of a SSL Handshake.
  3783. // We were waiting for incoming data which has just arrived.
  3784. [self ssl_continueSSLHandshake];
  3785. #endif
  3786. }
  3787. }
  3788. else
  3789. {
  3790. // We are still waiting for the writeQueue to drain and start the SSL/TLS process.
  3791. // We now know data is available to read.
  3792. if (![self usingCFStreamForTLS])
  3793. {
  3794. // Suspend the read source or else it will continue to fire nonstop.
  3795. [self suspendReadSource];
  3796. }
  3797. }
  3798. return;
  3799. }
  3800. BOOL done = NO; // Completed read operation
  3801. NSError *error = nil; // Error occured
  3802. NSUInteger totalBytesReadForCurrentRead = 0;
  3803. //
  3804. // STEP 1 - READ FROM PREBUFFER
  3805. //
  3806. if ([preBuffer availableBytes] > 0)
  3807. {
  3808. // There are 3 types of read packets:
  3809. //
  3810. // 1) Read all available data.
  3811. // 2) Read a specific length of data.
  3812. // 3) Read up to a particular terminator.
  3813. NSUInteger bytesToCopy;
  3814. if (currentRead->term != nil)
  3815. {
  3816. // Read type #3 - read up to a terminator
  3817. bytesToCopy = [currentRead readLengthForTermWithPreBuffer:preBuffer found:&done];
  3818. }
  3819. else
  3820. {
  3821. // Read type #1 or #2
  3822. bytesToCopy = [currentRead readLengthForNonTermWithHint:[preBuffer availableBytes]];
  3823. }
  3824. // Make sure we have enough room in the buffer for our read.
  3825. [currentRead ensureCapacityForAdditionalDataOfLength:bytesToCopy];
  3826. // Copy bytes from prebuffer into packet buffer
  3827. uint8_t *buffer = (uint8_t *)[currentRead->buffer mutableBytes] + currentRead->startOffset +
  3828. currentRead->bytesDone;
  3829. memcpy(buffer, [preBuffer readBuffer], bytesToCopy);
  3830. // Remove the copied bytes from the preBuffer
  3831. [preBuffer didRead:bytesToCopy];
  3832. LogVerbose(@"copied(%lu) preBufferLength(%zu)", (unsigned long)bytesToCopy, [preBuffer availableBytes]);
  3833. // Update totals
  3834. currentRead->bytesDone += bytesToCopy;
  3835. totalBytesReadForCurrentRead += bytesToCopy;
  3836. // Check to see if the read operation is done
  3837. if (currentRead->readLength > 0)
  3838. {
  3839. // Read type #2 - read a specific length of data
  3840. done = (currentRead->bytesDone == currentRead->readLength);
  3841. }
  3842. else if (currentRead->term != nil)
  3843. {
  3844. // Read type #3 - read up to a terminator
  3845. // Our 'done' variable was updated via the readLengthForTermWithPreBuffer:found: method
  3846. if (!done && currentRead->maxLength > 0)
  3847. {
  3848. // We're not done and there's a set maxLength.
  3849. // Have we reached that maxLength yet?
  3850. if (currentRead->bytesDone >= currentRead->maxLength)
  3851. {
  3852. error = [self readMaxedOutError];
  3853. }
  3854. }
  3855. }
  3856. else
  3857. {
  3858. // Read type #1 - read all available data
  3859. //
  3860. // We're done as soon as
  3861. // - we've read all available data (in prebuffer and socket)
  3862. // - we've read the maxLength of read packet.
  3863. done = ((currentRead->maxLength > 0) && (currentRead->bytesDone == currentRead->maxLength));
  3864. }
  3865. }
  3866. //
  3867. // STEP 2 - READ FROM SOCKET
  3868. //
  3869. BOOL socketEOF = (flags & kSocketHasReadEOF) ? YES : NO; // Nothing more to via socket (end of file)
  3870. BOOL waiting = !done && !error && !socketEOF && !hasBytesAvailable; // Ran out of data, waiting for more
  3871. if (!done && !error && !socketEOF && !waiting && hasBytesAvailable)
  3872. {
  3873. NSAssert(([preBuffer availableBytes] == 0), @"Invalid logic");
  3874. // There are 3 types of read packets:
  3875. //
  3876. // 1) Read all available data.
  3877. // 2) Read a specific length of data.
  3878. // 3) Read up to a particular terminator.
  3879. BOOL readIntoPreBuffer = NO;
  3880. NSUInteger bytesToRead;
  3881. if ([self usingCFStreamForTLS])
  3882. {
  3883. // Since Apple hasn't made the full power of SecureTransport available on iOS,
  3884. // we are relegated to using the slower, less powerful, RunLoop based CFStream API.
  3885. //
  3886. // This API doesn't tell us how much data is available on the socket to be read.
  3887. // If we had that information we could optimize our memory allocations, and sys calls.
  3888. //
  3889. // But alas...
  3890. // So we do it old school, and just read as much data from the socket as we can.
  3891. NSUInteger defaultReadLength = (1024 * 32);
  3892. bytesToRead = [currentRead optimalReadLengthWithDefault:defaultReadLength
  3893. shouldPreBuffer:&readIntoPreBuffer];
  3894. }
  3895. else
  3896. {
  3897. if (currentRead->term != nil)
  3898. {
  3899. // Read type #3 - read up to a terminator
  3900. bytesToRead = [currentRead readLengthForTermWithHint:estimatedBytesAvailable
  3901. shouldPreBuffer:&readIntoPreBuffer];
  3902. }
  3903. else
  3904. {
  3905. // Read type #1 or #2
  3906. bytesToRead = [currentRead readLengthForNonTermWithHint:estimatedBytesAvailable];
  3907. }
  3908. }
  3909. if (bytesToRead > SIZE_MAX) // NSUInteger may be bigger than size_t (read param 3)
  3910. {
  3911. bytesToRead = SIZE_MAX;
  3912. }
  3913. // Make sure we have enough room in the buffer for our read.
  3914. //
  3915. // We are either reading directly into the currentRead->buffer,
  3916. // or we're reading into the temporary preBuffer.
  3917. uint8_t *buffer;
  3918. if (readIntoPreBuffer)
  3919. {
  3920. [preBuffer ensureCapacityForWrite:bytesToRead];
  3921. buffer = [preBuffer writeBuffer];
  3922. }
  3923. else
  3924. {
  3925. [currentRead ensureCapacityForAdditionalDataOfLength:bytesToRead];
  3926. buffer = (uint8_t *)[currentRead->buffer mutableBytes] + currentRead->startOffset + currentRead->bytesDone;
  3927. }
  3928. // Read data into buffer
  3929. size_t bytesRead = 0;
  3930. if (flags & kSocketSecure)
  3931. {
  3932. if ([self usingCFStreamForTLS])
  3933. {
  3934. #if TARGET_OS_IPHONE
  3935. CFIndex result = CFReadStreamRead(readStream, buffer, (CFIndex)bytesToRead);
  3936. LogVerbose(@"CFReadStreamRead(): result = %i", (int)result);
  3937. if (result < 0)
  3938. {
  3939. error = (__bridge_transfer NSError *)CFReadStreamCopyError(readStream);
  3940. }
  3941. else if (result == 0)
  3942. {
  3943. socketEOF = YES;
  3944. }
  3945. else
  3946. {
  3947. waiting = YES;
  3948. bytesRead = (size_t)result;
  3949. }
  3950. // We only know how many decrypted bytes were read.
  3951. // The actual number of bytes read was likely more due to the overhead of the encryption.
  3952. // So we reset our flag, and rely on the next callback to alert us of more data.
  3953. flags &= ~kSecureSocketHasBytesAvailable;
  3954. #endif
  3955. }
  3956. else
  3957. {
  3958. #if SECURE_TRANSPORT_MAYBE_AVAILABLE
  3959. // The documentation from Apple states:
  3960. //
  3961. // "a read operation might return errSSLWouldBlock,
  3962. // indicating that less data than requested was actually transferred"
  3963. //
  3964. // However, starting around 10.7, the function will sometimes return noErr,
  3965. // even if it didn't read as much data as requested. So we need to watch out for that.
  3966. OSStatus result;
  3967. do
  3968. {
  3969. void *loop_buffer = buffer + bytesRead;
  3970. size_t loop_bytesToRead = (size_t)bytesToRead - bytesRead;
  3971. size_t loop_bytesRead = 0;
  3972. result = SSLRead(sslContext, loop_buffer, loop_bytesToRead, &loop_bytesRead);
  3973. LogVerbose(@"read from secure socket = %u", (unsigned)bytesRead);
  3974. bytesRead += loop_bytesRead;
  3975. } while ((result == noErr) && (bytesRead < bytesToRead));
  3976. if (result != noErr)
  3977. {
  3978. if (result == errSSLWouldBlock)
  3979. waiting = YES;
  3980. else
  3981. {
  3982. if (result == errSSLClosedGraceful || result == errSSLClosedAbort)
  3983. {
  3984. // We've reached the end of the stream.
  3985. // Handle this the same way we would an EOF from the socket.
  3986. socketEOF = YES;
  3987. sslErrCode = result;
  3988. }
  3989. else
  3990. {
  3991. error = [self sslError:result];
  3992. }
  3993. }
  3994. // It's possible that bytesRead > 0, even if the result was errSSLWouldBlock.
  3995. // This happens when the SSLRead function is able to read some data,
  3996. // but not the entire amount we requested.
  3997. if (bytesRead <= 0)
  3998. {
  3999. bytesRead = 0;
  4000. }
  4001. }
  4002. // Do not modify socketFDBytesAvailable.
  4003. // It will be updated via the SSLReadFunction().
  4004. #endif
  4005. }
  4006. }
  4007. else
  4008. {
  4009. int socketFD = (socket4FD != SOCKET_NULL) ? socket4FD : (socket6FD != SOCKET_NULL) ? socket6FD : socketUN;
  4010. ssize_t result = read(socketFD, buffer, (size_t)bytesToRead);
  4011. LogVerbose(@"read from socket = %i", (int)result);
  4012. if (result < 0)
  4013. {
  4014. if (errno == EWOULDBLOCK)
  4015. waiting = YES;
  4016. else
  4017. error = [self errnoErrorWithReason:@"Error in read() function"];
  4018. socketFDBytesAvailable = 0;
  4019. }
  4020. else if (result == 0)
  4021. {
  4022. socketEOF = YES;
  4023. socketFDBytesAvailable = 0;
  4024. }
  4025. else
  4026. {
  4027. bytesRead = result;
  4028. if (bytesRead < bytesToRead)
  4029. {
  4030. // The read returned less data than requested.
  4031. // This means socketFDBytesAvailable was a bit off due to timing,
  4032. // because we read from the socket right when the readSource event was firing.
  4033. socketFDBytesAvailable = 0;
  4034. }
  4035. else
  4036. {
  4037. if (socketFDBytesAvailable <= bytesRead)
  4038. socketFDBytesAvailable = 0;
  4039. else
  4040. socketFDBytesAvailable -= bytesRead;
  4041. }
  4042. if (socketFDBytesAvailable == 0)
  4043. {
  4044. waiting = YES;
  4045. }
  4046. }
  4047. }
  4048. if (bytesRead > 0)
  4049. {
  4050. // Check to see if the read operation is done
  4051. if (currentRead->readLength > 0)
  4052. {
  4053. // Read type #2 - read a specific length of data
  4054. //
  4055. // Note: We should never be using a prebuffer when we're reading a specific length of data.
  4056. NSAssert(readIntoPreBuffer == NO, @"Invalid logic");
  4057. currentRead->bytesDone += bytesRead;
  4058. totalBytesReadForCurrentRead += bytesRead;
  4059. done = (currentRead->bytesDone == currentRead->readLength);
  4060. }
  4061. else if (currentRead->term != nil)
  4062. {
  4063. // Read type #3 - read up to a terminator
  4064. if (readIntoPreBuffer)
  4065. {
  4066. // We just read a big chunk of data into the preBuffer
  4067. [preBuffer didWrite:bytesRead];
  4068. LogVerbose(@"read data into preBuffer - preBuffer.length = %zu", [preBuffer availableBytes]);
  4069. // Search for the terminating sequence
  4070. bytesToRead = [currentRead readLengthForTermWithPreBuffer:preBuffer found:&done];
  4071. LogVerbose(@"copying %lu bytes from preBuffer", (unsigned long)bytesToRead);
  4072. // Ensure there's room on the read packet's buffer
  4073. [currentRead ensureCapacityForAdditionalDataOfLength:bytesToRead];
  4074. // Copy bytes from prebuffer into read buffer
  4075. uint8_t *readBuf = (uint8_t *)[currentRead->buffer mutableBytes] + currentRead->startOffset
  4076. + currentRead->bytesDone;
  4077. memcpy(readBuf, [preBuffer readBuffer], bytesToRead);
  4078. // Remove the copied bytes from the prebuffer
  4079. [preBuffer didRead:bytesToRead];
  4080. LogVerbose(@"preBuffer.length = %zu", [preBuffer availableBytes]);
  4081. // Update totals
  4082. currentRead->bytesDone += bytesToRead;
  4083. totalBytesReadForCurrentRead += bytesToRead;
  4084. // Our 'done' variable was updated via the readLengthForTermWithPreBuffer:found: method above
  4085. }
  4086. else
  4087. {
  4088. // We just read a big chunk of data directly into the packet's buffer.
  4089. // We need to move any overflow into the prebuffer.
  4090. NSInteger overflow = [currentRead searchForTermAfterPreBuffering:bytesRead];
  4091. if (overflow == 0)
  4092. {
  4093. // Perfect match!
  4094. // Every byte we read stays in the read buffer,
  4095. // and the last byte we read was the last byte of the term.
  4096. currentRead->bytesDone += bytesRead;
  4097. totalBytesReadForCurrentRead += bytesRead;
  4098. done = YES;
  4099. }
  4100. else if (overflow > 0)
  4101. {
  4102. // The term was found within the data that we read,
  4103. // and there are extra bytes that extend past the end of the term.
  4104. // We need to move these excess bytes out of the read packet and into the prebuffer.
  4105. NSInteger underflow = bytesRead - overflow;
  4106. // Copy excess data into preBuffer
  4107. LogVerbose(@"copying %ld overflow bytes into preBuffer", (long)overflow);
  4108. [preBuffer ensureCapacityForWrite:overflow];
  4109. uint8_t *overflowBuffer = buffer + underflow;
  4110. memcpy([preBuffer writeBuffer], overflowBuffer, overflow);
  4111. [preBuffer didWrite:overflow];
  4112. LogVerbose(@"preBuffer.length = %zu", [preBuffer availableBytes]);
  4113. // Note: The completeCurrentRead method will trim the buffer for us.
  4114. currentRead->bytesDone += underflow;
  4115. totalBytesReadForCurrentRead += underflow;
  4116. done = YES;
  4117. }
  4118. else
  4119. {
  4120. // The term was not found within the data that we read.
  4121. currentRead->bytesDone += bytesRead;
  4122. totalBytesReadForCurrentRead += bytesRead;
  4123. done = NO;
  4124. }
  4125. }
  4126. if (!done && currentRead->maxLength > 0)
  4127. {
  4128. // We're not done and there's a set maxLength.
  4129. // Have we reached that maxLength yet?
  4130. if (currentRead->bytesDone >= currentRead->maxLength)
  4131. {
  4132. error = [self readMaxedOutError];
  4133. }
  4134. }
  4135. }
  4136. else
  4137. {
  4138. // Read type #1 - read all available data
  4139. if (readIntoPreBuffer)
  4140. {
  4141. // We just read a chunk of data into the preBuffer
  4142. [preBuffer didWrite:bytesRead];
  4143. // Now copy the data into the read packet.
  4144. //
  4145. // Recall that we didn't read directly into the packet's buffer to avoid
  4146. // over-allocating memory since we had no clue how much data was available to be read.
  4147. //
  4148. // Ensure there's room on the read packet's buffer
  4149. [currentRead ensureCapacityForAdditionalDataOfLength:bytesRead];
  4150. // Copy bytes from prebuffer into read buffer
  4151. uint8_t *readBuf = (uint8_t *)[currentRead->buffer mutableBytes] + currentRead->startOffset
  4152. + currentRead->bytesDone;
  4153. memcpy(readBuf, [preBuffer readBuffer], bytesRead);
  4154. // Remove the copied bytes from the prebuffer
  4155. [preBuffer didRead:bytesRead];
  4156. // Update totals
  4157. currentRead->bytesDone += bytesRead;
  4158. totalBytesReadForCurrentRead += bytesRead;
  4159. }
  4160. else
  4161. {
  4162. currentRead->bytesDone += bytesRead;
  4163. totalBytesReadForCurrentRead += bytesRead;
  4164. }
  4165. done = YES;
  4166. }
  4167. } // if (bytesRead > 0)
  4168. } // if (!done && !error && !socketEOF && !waiting && hasBytesAvailable)
  4169. if (!done && currentRead->readLength == 0 && currentRead->term == nil)
  4170. {
  4171. // Read type #1 - read all available data
  4172. //
  4173. // We might arrive here if we read data from the prebuffer but not from the socket.
  4174. done = (totalBytesReadForCurrentRead > 0);
  4175. }
  4176. // Check to see if we're done, or if we've made progress
  4177. if (done)
  4178. {
  4179. [self completeCurrentRead];
  4180. if (!error && (!socketEOF || [preBuffer availableBytes] > 0))
  4181. {
  4182. [self maybeDequeueRead];
  4183. }
  4184. }
  4185. else if (totalBytesReadForCurrentRead > 0)
  4186. {
  4187. // We're not done read type #2 or #3 yet, but we have read in some bytes
  4188. if (delegateQueue && [delegate respondsToSelector:@selector(socket:didReadPartialDataOfLength:tag:)])
  4189. {
  4190. __strong id theDelegate = delegate;
  4191. long theReadTag = currentRead->tag;
  4192. dispatch_async(delegateQueue, ^{ @autoreleasepool {
  4193. [theDelegate socket:self didReadPartialDataOfLength:totalBytesReadForCurrentRead tag:theReadTag];
  4194. }});
  4195. }
  4196. }
  4197. // Check for errors
  4198. if (error)
  4199. {
  4200. [self closeWithError:error];
  4201. }
  4202. else if (socketEOF)
  4203. {
  4204. [self doReadEOF];
  4205. }
  4206. else if (waiting)
  4207. {
  4208. if (![self usingCFStreamForTLS])
  4209. {
  4210. // Monitor the socket for readability (if we're not already doing so)
  4211. [self resumeReadSource];
  4212. }
  4213. }
  4214. // Do not add any code here without first adding return statements in the error cases above.
  4215. }
  4216. - (void)doReadEOF
  4217. {
  4218. LogTrace();
  4219. // This method may be called more than once.
  4220. // If the EOF is read while there is still data in the preBuffer,
  4221. // then this method may be called continually after invocations of doReadData to see if it's time to disconnect.
  4222. flags |= kSocketHasReadEOF;
  4223. if (flags & kSocketSecure)
  4224. {
  4225. // If the SSL layer has any buffered data, flush it into the preBuffer now.
  4226. [self flushSSLBuffers];
  4227. }
  4228. BOOL shouldDisconnect;
  4229. NSError *error = nil;
  4230. if ((flags & kStartingReadTLS) || (flags & kStartingWriteTLS))
  4231. {
  4232. // We received an EOF during or prior to startTLS.
  4233. // The SSL/TLS handshake is now impossible, so this is an unrecoverable situation.
  4234. shouldDisconnect = YES;
  4235. if ([self usingSecureTransportForTLS])
  4236. {
  4237. #if SECURE_TRANSPORT_MAYBE_AVAILABLE
  4238. error = [self sslError:errSSLClosedAbort];
  4239. #endif
  4240. }
  4241. }
  4242. else if (flags & kReadStreamClosed)
  4243. {
  4244. // The preBuffer has already been drained.
  4245. // The config allows half-duplex connections.
  4246. // We've previously checked the socket, and it appeared writeable.
  4247. // So we marked the read stream as closed and notified the delegate.
  4248. //
  4249. // As per the half-duplex contract, the socket will be closed when a write fails,
  4250. // or when the socket is manually closed.
  4251. shouldDisconnect = NO;
  4252. }
  4253. else if ([preBuffer availableBytes] > 0)
  4254. {
  4255. LogVerbose(@"Socket reached EOF, but there is still data available in prebuffer");
  4256. // Although we won't be able to read any more data from the socket,
  4257. // there is existing data that has been prebuffered that we can read.
  4258. shouldDisconnect = NO;
  4259. }
  4260. else if (config & kAllowHalfDuplexConnection)
  4261. {
  4262. // We just received an EOF (end of file) from the socket's read stream.
  4263. // This means the remote end of the socket (the peer we're connected to)
  4264. // has explicitly stated that it will not be sending us any more data.
  4265. //
  4266. // Query the socket to see if it is still writeable. (Perhaps the peer will continue reading data from us)
  4267. int socketFD = (socket4FD != SOCKET_NULL) ? socket4FD : (socket6FD != SOCKET_NULL) ? socket6FD : socketUN;
  4268. struct pollfd pfd[1];
  4269. pfd[0].fd = socketFD;
  4270. pfd[0].events = POLLOUT;
  4271. pfd[0].revents = 0;
  4272. poll(pfd, 1, 0);
  4273. if (pfd[0].revents & POLLOUT)
  4274. {
  4275. // Socket appears to still be writeable
  4276. shouldDisconnect = NO;
  4277. flags |= kReadStreamClosed;
  4278. // Notify the delegate that we're going half-duplex
  4279. if (delegateQueue && [delegate respondsToSelector:@selector(socketDidCloseReadStream:)])
  4280. {
  4281. __strong id theDelegate = delegate;
  4282. dispatch_async(delegateQueue, ^{ @autoreleasepool {
  4283. [theDelegate socketDidCloseReadStream:self];
  4284. }});
  4285. }
  4286. }
  4287. else
  4288. {
  4289. shouldDisconnect = YES;
  4290. }
  4291. }
  4292. else
  4293. {
  4294. shouldDisconnect = YES;
  4295. }
  4296. if (shouldDisconnect)
  4297. {
  4298. if (error == nil)
  4299. {
  4300. if ([self usingSecureTransportForTLS])
  4301. {
  4302. #if SECURE_TRANSPORT_MAYBE_AVAILABLE
  4303. if (sslErrCode != noErr && sslErrCode != errSSLClosedGraceful)
  4304. {
  4305. error = [self sslError:sslErrCode];
  4306. }
  4307. else
  4308. {
  4309. error = [self connectionClosedError];
  4310. }
  4311. #endif
  4312. }
  4313. else
  4314. {
  4315. error = [self connectionClosedError];
  4316. }
  4317. }
  4318. [self closeWithError:error];
  4319. }
  4320. else
  4321. {
  4322. if (![self usingCFStreamForTLS])
  4323. {
  4324. // Suspend the read source (if needed)
  4325. [self suspendReadSource];
  4326. }
  4327. }
  4328. }
  4329. - (void)completeCurrentRead
  4330. {
  4331. LogTrace();
  4332. NSAssert(currentRead, @"Trying to complete current read when there is no current read.");
  4333. NSData *result;
  4334. if (currentRead->bufferOwner)
  4335. {
  4336. // We created the buffer on behalf of the user.
  4337. // Trim our buffer to be the proper size.
  4338. [currentRead->buffer setLength:currentRead->bytesDone];
  4339. result = currentRead->buffer;
  4340. }
  4341. else
  4342. {
  4343. // We did NOT create the buffer.
  4344. // The buffer is owned by the caller.
  4345. // Only trim the buffer if we had to increase its size.
  4346. if ([currentRead->buffer length] > currentRead->originalBufferLength)
  4347. {
  4348. NSUInteger readSize = currentRead->startOffset + currentRead->bytesDone;
  4349. NSUInteger origSize = currentRead->originalBufferLength;
  4350. NSUInteger buffSize = MAX(readSize, origSize);
  4351. [currentRead->buffer setLength:buffSize];
  4352. }
  4353. uint8_t *buffer = (uint8_t *)[currentRead->buffer mutableBytes] + currentRead->startOffset;
  4354. result = [NSData dataWithBytesNoCopy:buffer length:currentRead->bytesDone freeWhenDone:NO];
  4355. }
  4356. if (delegateQueue && [delegate respondsToSelector:@selector(socket:didReadData:withTag:)])
  4357. {
  4358. __strong id theDelegate = delegate;
  4359. GCDAsyncReadPacket *theRead = currentRead; // Ensure currentRead retained since result may not own buffer
  4360. dispatch_async(delegateQueue, ^{ @autoreleasepool {
  4361. [theDelegate socket:self didReadData:result withTag:theRead->tag];
  4362. }});
  4363. }
  4364. [self endCurrentRead];
  4365. }
  4366. - (void)endCurrentRead
  4367. {
  4368. if (readTimer)
  4369. {
  4370. dispatch_source_cancel(readTimer);
  4371. readTimer = NULL;
  4372. }
  4373. currentRead = nil;
  4374. }
  4375. - (void)setupReadTimerWithTimeout:(NSTimeInterval)timeout
  4376. {
  4377. if (timeout >= 0.0)
  4378. {
  4379. readTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, socketQueue);
  4380. dispatch_source_set_event_handler(readTimer, ^{ @autoreleasepool {
  4381. [self doReadTimeout];
  4382. }});
  4383. #if NEEDS_DISPATCH_RETAIN_RELEASE
  4384. dispatch_source_t theReadTimer = readTimer;
  4385. dispatch_source_set_cancel_handler(readTimer, ^{
  4386. LogVerbose(@"dispatch_release(readTimer)");
  4387. dispatch_release(theReadTimer);
  4388. });
  4389. #endif
  4390. dispatch_time_t tt = dispatch_time(DISPATCH_TIME_NOW, (timeout * NSEC_PER_SEC));
  4391. dispatch_source_set_timer(readTimer, tt, DISPATCH_TIME_FOREVER, 0);
  4392. dispatch_resume(readTimer);
  4393. }
  4394. }
  4395. - (void)doReadTimeout
  4396. {
  4397. // This is a little bit tricky.
  4398. // Ideally we'd like to synchronously query the delegate about a timeout extension.
  4399. // But if we do so synchronously we risk a possible deadlock.
  4400. // So instead we have to do so asynchronously, and callback to ourselves from within the delegate block.
  4401. flags |= kReadsPaused;
  4402. if (delegateQueue && [delegate respondsToSelector:@selector(socket:shouldTimeoutReadWithTag:elapsed:bytesDone:)])
  4403. {
  4404. __strong id theDelegate = delegate;
  4405. GCDAsyncReadPacket *theRead = currentRead;
  4406. dispatch_async(delegateQueue, ^{ @autoreleasepool {
  4407. NSTimeInterval timeoutExtension = 0.0;
  4408. timeoutExtension = [theDelegate socket:self shouldTimeoutReadWithTag:theRead->tag
  4409. elapsed:theRead->timeout
  4410. bytesDone:theRead->bytesDone];
  4411. dispatch_async(socketQueue, ^{ @autoreleasepool {
  4412. [self doReadTimeoutWithExtension:timeoutExtension];
  4413. }});
  4414. }});
  4415. }
  4416. else
  4417. {
  4418. [self doReadTimeoutWithExtension:0.0];
  4419. }
  4420. }
  4421. - (void)doReadTimeoutWithExtension:(NSTimeInterval)timeoutExtension
  4422. {
  4423. if (currentRead)
  4424. {
  4425. if (timeoutExtension > 0.0)
  4426. {
  4427. currentRead->timeout += timeoutExtension;
  4428. // Reschedule the timer
  4429. dispatch_time_t tt = dispatch_time(DISPATCH_TIME_NOW, (timeoutExtension * NSEC_PER_SEC));
  4430. dispatch_source_set_timer(readTimer, tt, DISPATCH_TIME_FOREVER, 0);
  4431. // Unpause reads, and continue
  4432. flags &= ~kReadsPaused;
  4433. [self doReadData];
  4434. }
  4435. else
  4436. {
  4437. LogVerbose(@"ReadTimeout");
  4438. [self closeWithError:[self readTimeoutError]];
  4439. }
  4440. }
  4441. }
  4442. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  4443. #pragma mark Writing
  4444. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  4445. - (void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag
  4446. {
  4447. if ([data length] == 0) return;
  4448. GCDAsyncWritePacket *packet = [[GCDAsyncWritePacket alloc] initWithData:data timeout:timeout tag:tag];
  4449. dispatch_async(socketQueue, ^{ @autoreleasepool {
  4450. LogTrace();
  4451. if ((flags & kSocketStarted) && !(flags & kForbidReadsWrites))
  4452. {
  4453. [writeQueue addObject:packet];
  4454. [self maybeDequeueWrite];
  4455. }
  4456. }});
  4457. // Do not rely on the block being run in order to release the packet,
  4458. // as the queue might get released without the block completing.
  4459. }
  4460. - (float)progressOfWriteReturningTag:(long *)tagPtr bytesDone:(NSUInteger *)donePtr total:(NSUInteger *)totalPtr
  4461. {
  4462. __block float result = 0.0F;
  4463. dispatch_block_t block = ^{
  4464. if (!currentWrite || ![currentWrite isKindOfClass:[GCDAsyncWritePacket class]])
  4465. {
  4466. // We're not writing anything right now.
  4467. if (tagPtr != NULL) *tagPtr = 0;
  4468. if (donePtr != NULL) *donePtr = 0;
  4469. if (totalPtr != NULL) *totalPtr = 0;
  4470. result = NAN;
  4471. }
  4472. else
  4473. {
  4474. NSUInteger done = currentWrite->bytesDone;
  4475. NSUInteger total = [currentWrite->buffer length];
  4476. if (tagPtr != NULL) *tagPtr = currentWrite->tag;
  4477. if (donePtr != NULL) *donePtr = done;
  4478. if (totalPtr != NULL) *totalPtr = total;
  4479. result = (float)done / (float)total;
  4480. }
  4481. };
  4482. if (dispatch_get_current_queue() == socketQueue)
  4483. block();
  4484. else
  4485. dispatch_sync(socketQueue, block);
  4486. return result;
  4487. }
  4488. /**
  4489. * Conditionally starts a new write.
  4490. *
  4491. * It is called when:
  4492. * - a user requests a write
  4493. * - after a write request has finished (to handle the next request)
  4494. * - immediately after the socket opens to handle any pending requests
  4495. *
  4496. * This method also handles auto-disconnect post read/write completion.
  4497. **/
  4498. - (void)maybeDequeueWrite
  4499. {
  4500. LogTrace();
  4501. NSAssert(dispatch_get_current_queue() == socketQueue, @"Must be dispatched on socketQueue");
  4502. // If we're not currently processing a write AND we have an available write stream
  4503. if ((currentWrite == nil) && (flags & kConnected))
  4504. {
  4505. if ([writeQueue count] > 0)
  4506. {
  4507. // Dequeue the next object in the write queue
  4508. currentWrite = [writeQueue objectAtIndex:0];
  4509. [writeQueue removeObjectAtIndex:0];
  4510. if ([currentWrite isKindOfClass:[GCDAsyncSpecialPacket class]])
  4511. {
  4512. LogVerbose(@"Dequeued GCDAsyncSpecialPacket");
  4513. // Attempt to start TLS
  4514. flags |= kStartingWriteTLS;
  4515. // This method won't do anything unless both kStartingReadTLS and kStartingWriteTLS are set
  4516. [self maybeStartTLS];
  4517. }
  4518. else
  4519. {
  4520. LogVerbose(@"Dequeued GCDAsyncWritePacket");
  4521. // Setup write timer (if needed)
  4522. [self setupWriteTimerWithTimeout:currentWrite->timeout];
  4523. // Immediately write, if possible
  4524. [self doWriteData];
  4525. }
  4526. }
  4527. else if (flags & kDisconnectAfterWrites)
  4528. {
  4529. if (flags & kDisconnectAfterReads)
  4530. {
  4531. if (([readQueue count] == 0) && (currentRead == nil))
  4532. {
  4533. [self closeWithError:nil];
  4534. }
  4535. }
  4536. else
  4537. {
  4538. [self closeWithError:nil];
  4539. }
  4540. }
  4541. }
  4542. }
  4543. - (void)doWriteData
  4544. {
  4545. LogTrace();
  4546. // This method is called by the writeSource via the socketQueue
  4547. if ((currentWrite == nil) || (flags & kWritesPaused))
  4548. {
  4549. LogVerbose(@"No currentWrite or kWritesPaused");
  4550. // Unable to write at this time
  4551. if ([self usingCFStreamForTLS])
  4552. {
  4553. // CFWriteStream only fires once when there is available data.
  4554. // It won't fire again until we've invoked CFWriteStreamWrite.
  4555. }
  4556. else
  4557. {
  4558. // If the writeSource is firing, we need to pause it
  4559. // or else it will continue to fire over and over again.
  4560. if (flags & kSocketCanAcceptBytes)
  4561. {
  4562. [self suspendWriteSource];
  4563. }
  4564. }
  4565. return;
  4566. }
  4567. if (!(flags & kSocketCanAcceptBytes))
  4568. {
  4569. LogVerbose(@"No space available to write...");
  4570. // No space available to write.
  4571. if (![self usingCFStreamForTLS])
  4572. {
  4573. // Need to wait for writeSource to fire and notify us of
  4574. // available space in the socket's internal write buffer.
  4575. [self resumeWriteSource];
  4576. }
  4577. return;
  4578. }
  4579. if (flags & kStartingWriteTLS)
  4580. {
  4581. LogVerbose(@"Waiting for SSL/TLS handshake to complete");
  4582. // The writeQueue is waiting for SSL/TLS handshake to complete.
  4583. if (flags & kStartingReadTLS)
  4584. {
  4585. if ([self usingSecureTransportForTLS])
  4586. {
  4587. #if SECURE_TRANSPORT_MAYBE_AVAILABLE
  4588. // We are in the process of a SSL Handshake.
  4589. // We were waiting for available space in the socket's internal OS buffer to continue writing.
  4590. [self ssl_continueSSLHandshake];
  4591. #endif
  4592. }
  4593. }
  4594. else
  4595. {
  4596. // We are still waiting for the readQueue to drain and start the SSL/TLS process.
  4597. // We now know we can write to the socket.
  4598. if (![self usingCFStreamForTLS])
  4599. {
  4600. // Suspend the write source or else it will continue to fire nonstop.
  4601. [self suspendWriteSource];
  4602. }
  4603. }
  4604. return;
  4605. }
  4606. // Note: This method is not called if currentWrite is a GCDAsyncSpecialPacket (startTLS packet)
  4607. BOOL waiting = NO;
  4608. NSError *error = nil;
  4609. size_t bytesWritten = 0;
  4610. if (flags & kSocketSecure)
  4611. {
  4612. if ([self usingCFStreamForTLS])
  4613. {
  4614. #if TARGET_OS_IPHONE
  4615. //
  4616. // Writing data using CFStream (over internal TLS)
  4617. //
  4618. const uint8_t *buffer = (const uint8_t *)[currentWrite->buffer bytes] + currentWrite->bytesDone;
  4619. NSUInteger bytesToWrite = [currentWrite->buffer length] - currentWrite->bytesDone;
  4620. if (bytesToWrite > SIZE_MAX) // NSUInteger may be bigger than size_t (write param 3)
  4621. {
  4622. bytesToWrite = SIZE_MAX;
  4623. }
  4624. CFIndex result = CFWriteStreamWrite(writeStream, buffer, (CFIndex)bytesToWrite);
  4625. LogVerbose(@"CFWriteStreamWrite(%lu) = %li", (unsigned long)bytesToWrite, result);
  4626. if (result < 0)
  4627. {
  4628. error = (__bridge_transfer NSError *)CFWriteStreamCopyError(writeStream);
  4629. }
  4630. else
  4631. {
  4632. bytesWritten = (size_t)result;
  4633. // We always set waiting to true in this scenario.
  4634. // CFStream may have altered our underlying socket to non-blocking.
  4635. // Thus if we attempt to write without a callback, we may end up blocking our queue.
  4636. waiting = YES;
  4637. }
  4638. #endif
  4639. }
  4640. else
  4641. {
  4642. #if SECURE_TRANSPORT_MAYBE_AVAILABLE
  4643. // We're going to use the SSLWrite function.
  4644. //
  4645. // OSStatus SSLWrite(SSLContextRef context, const void *data, size_t dataLength, size_t *processed)
  4646. //
  4647. // Parameters:
  4648. // context - An SSL session context reference.
  4649. // data - A pointer to the buffer of data to write.
  4650. // dataLength - The amount, in bytes, of data to write.
  4651. // processed - On return, the length, in bytes, of the data actually written.
  4652. //
  4653. // It sounds pretty straight-forward,
  4654. // but there are a few caveats you should be aware of.
  4655. //
  4656. // The SSLWrite method operates in a non-obvious (and rather annoying) manner.
  4657. // According to the documentation:
  4658. //
  4659. // Because you may configure the underlying connection to operate in a non-blocking manner,
  4660. // a write operation might return errSSLWouldBlock, indicating that less data than requested
  4661. // was actually transferred. In this case, you should repeat the call to SSLWrite until some
  4662. // other result is returned.
  4663. //
  4664. // This sounds perfect, but when our SSLWriteFunction returns errSSLWouldBlock,
  4665. // then the SSLWrite method returns (with the proper errSSLWouldBlock return value),
  4666. // but it sets processed to dataLength !!
  4667. //
  4668. // In other words, if the SSLWrite function doesn't completely write all the data we tell it to,
  4669. // then it doesn't tell us how many bytes were actually written. So, for example, if we tell it to
  4670. // write 256 bytes then it might actually write 128 bytes, but then report 0 bytes written.
  4671. //
  4672. // You might be wondering:
  4673. // If the SSLWrite function doesn't tell us how many bytes were written,
  4674. // then how in the world are we supposed to update our parameters (buffer & bytesToWrite)
  4675. // for the next time we invoke SSLWrite?
  4676. //
  4677. // The answer is that SSLWrite cached all the data we told it to write,
  4678. // and it will push out that data next time we call SSLWrite.
  4679. // If we call SSLWrite with new data, it will push out the cached data first, and then the new data.
  4680. // If we call SSLWrite with empty data, then it will simply push out the cached data.
  4681. //
  4682. // For this purpose we're going to break large writes into a series of smaller writes.
  4683. // This allows us to report progress back to the delegate.
  4684. OSStatus result;
  4685. BOOL hasCachedDataToWrite = (sslWriteCachedLength > 0);
  4686. BOOL hasNewDataToWrite = YES;
  4687. if (hasCachedDataToWrite)
  4688. {
  4689. size_t processed = 0;
  4690. result = SSLWrite(sslContext, NULL, 0, &processed);
  4691. if (result == noErr)
  4692. {
  4693. bytesWritten = sslWriteCachedLength;
  4694. sslWriteCachedLength = 0;
  4695. if ([currentWrite->buffer length] == (currentWrite->bytesDone + bytesWritten))
  4696. {
  4697. // We've written all data for the current write.
  4698. hasNewDataToWrite = NO;
  4699. }
  4700. }
  4701. else
  4702. {
  4703. if (result == errSSLWouldBlock)
  4704. {
  4705. waiting = YES;
  4706. }
  4707. else
  4708. {
  4709. error = [self sslError:result];
  4710. }
  4711. // Can't write any new data since we were unable to write the cached data.
  4712. hasNewDataToWrite = NO;
  4713. }
  4714. }
  4715. if (hasNewDataToWrite)
  4716. {
  4717. const uint8_t *buffer = (const uint8_t *)[currentWrite->buffer bytes]
  4718. + currentWrite->bytesDone
  4719. + bytesWritten;
  4720. NSUInteger bytesToWrite = [currentWrite->buffer length] - currentWrite->bytesDone - bytesWritten;
  4721. if (bytesToWrite > SIZE_MAX) // NSUInteger may be bigger than size_t (write param 3)
  4722. {
  4723. bytesToWrite = SIZE_MAX;
  4724. }
  4725. size_t bytesRemaining = bytesToWrite;
  4726. BOOL keepLooping = YES;
  4727. while (keepLooping)
  4728. {
  4729. size_t sslBytesToWrite = MIN(bytesRemaining, 32768);
  4730. size_t sslBytesWritten = 0;
  4731. result = SSLWrite(sslContext, buffer, sslBytesToWrite, &sslBytesWritten);
  4732. if (result == noErr)
  4733. {
  4734. buffer += sslBytesWritten;
  4735. bytesWritten += sslBytesWritten;
  4736. bytesRemaining -= sslBytesWritten;
  4737. keepLooping = (bytesRemaining > 0);
  4738. }
  4739. else
  4740. {
  4741. if (result == errSSLWouldBlock)
  4742. {
  4743. waiting = YES;
  4744. sslWriteCachedLength = sslBytesToWrite;
  4745. }
  4746. else
  4747. {
  4748. error = [self sslError:result];
  4749. }
  4750. keepLooping = NO;
  4751. }
  4752. } // while (keepLooping)
  4753. } // if (hasNewDataToWrite)
  4754. #endif
  4755. }
  4756. }
  4757. else
  4758. {
  4759. //
  4760. // Writing data directly over raw socket
  4761. //
  4762. int socketFD = (socket4FD != SOCKET_NULL) ? socket4FD : (socket6FD != SOCKET_NULL) ? socket6FD : socketUN;
  4763. const uint8_t *buffer = (const uint8_t *)[currentWrite->buffer bytes] + currentWrite->bytesDone;
  4764. NSUInteger bytesToWrite = [currentWrite->buffer length] - currentWrite->bytesDone;
  4765. if (bytesToWrite > SIZE_MAX) // NSUInteger may be bigger than size_t (write param 3)
  4766. {
  4767. bytesToWrite = SIZE_MAX;
  4768. }
  4769. ssize_t result = write(socketFD, buffer, (size_t)bytesToWrite);
  4770. LogVerbose(@"wrote to socket = %zd", result);
  4771. // Check results
  4772. if (result < 0)
  4773. {
  4774. if (errno == EWOULDBLOCK)
  4775. {
  4776. waiting = YES;
  4777. }
  4778. else
  4779. {
  4780. error = [self errnoErrorWithReason:@"Error in write() function"];
  4781. }
  4782. }
  4783. else
  4784. {
  4785. bytesWritten = result;
  4786. }
  4787. }
  4788. // We're done with our writing.
  4789. // If we explictly ran into a situation where the socket told us there was no room in the buffer,
  4790. // then we immediately resume listening for notifications.
  4791. //
  4792. // We must do this before we dequeue another write,
  4793. // as that may in turn invoke this method again.
  4794. //
  4795. // Note that if CFStream is involved, it may have maliciously put our socket in blocking mode.
  4796. if (waiting)
  4797. {
  4798. flags &= ~kSocketCanAcceptBytes;
  4799. if (![self usingCFStreamForTLS])
  4800. {
  4801. [self resumeWriteSource];
  4802. }
  4803. }
  4804. // Check our results
  4805. BOOL done = NO;
  4806. if (bytesWritten > 0)
  4807. {
  4808. // Update total amount read for the current write
  4809. currentWrite->bytesDone += bytesWritten;
  4810. LogVerbose(@"currentWrite->bytesDone = %lu", (unsigned long)currentWrite->bytesDone);
  4811. // Is packet done?
  4812. done = (currentWrite->bytesDone == [currentWrite->buffer length]);
  4813. }
  4814. if (done)
  4815. {
  4816. [self completeCurrentWrite];
  4817. if (!error)
  4818. {
  4819. [self maybeDequeueWrite];
  4820. }
  4821. }
  4822. else
  4823. {
  4824. // We were unable to finish writing the data,
  4825. // so we're waiting for another callback to notify us of available space in the lower-level output buffer.
  4826. if (!waiting & !error)
  4827. {
  4828. // This would be the case if our write was able to accept some data, but not all of it.
  4829. flags &= ~kSocketCanAcceptBytes;
  4830. if (![self usingCFStreamForTLS])
  4831. {
  4832. [self resumeWriteSource];
  4833. }
  4834. }
  4835. if (bytesWritten > 0)
  4836. {
  4837. // We're not done with the entire write, but we have written some bytes
  4838. if (delegateQueue && [delegate respondsToSelector:@selector(socket:didWritePartialDataOfLength:tag:)])
  4839. {
  4840. __strong id theDelegate = delegate;
  4841. long theWriteTag = currentWrite->tag;
  4842. dispatch_async(delegateQueue, ^{ @autoreleasepool {
  4843. [theDelegate socket:self didWritePartialDataOfLength:bytesWritten tag:theWriteTag];
  4844. }});
  4845. }
  4846. }
  4847. }
  4848. // Check for errors
  4849. if (error)
  4850. {
  4851. [self closeWithError:[self errnoErrorWithReason:@"Error in write() function"]];
  4852. }
  4853. // Do not add any code here without first adding a return statement in the error case above.
  4854. }
  4855. - (void)completeCurrentWrite
  4856. {
  4857. LogTrace();
  4858. NSAssert(currentWrite, @"Trying to complete current write when there is no current write.");
  4859. if (delegateQueue && [delegate respondsToSelector:@selector(socket:didWriteDataWithTag:)])
  4860. {
  4861. __strong id theDelegate = delegate;
  4862. long theWriteTag = currentWrite->tag;
  4863. dispatch_async(delegateQueue, ^{ @autoreleasepool {
  4864. [theDelegate socket:self didWriteDataWithTag:theWriteTag];
  4865. }});
  4866. }
  4867. [self endCurrentWrite];
  4868. }
  4869. - (void)endCurrentWrite
  4870. {
  4871. if (writeTimer)
  4872. {
  4873. dispatch_source_cancel(writeTimer);
  4874. writeTimer = NULL;
  4875. }
  4876. currentWrite = nil;
  4877. }
  4878. - (void)setupWriteTimerWithTimeout:(NSTimeInterval)timeout
  4879. {
  4880. if (timeout >= 0.0)
  4881. {
  4882. writeTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, socketQueue);
  4883. dispatch_source_set_event_handler(writeTimer, ^{ @autoreleasepool {
  4884. [self doWriteTimeout];
  4885. }});
  4886. #if NEEDS_DISPATCH_RETAIN_RELEASE
  4887. dispatch_source_t theWriteTimer = writeTimer;
  4888. dispatch_source_set_cancel_handler(writeTimer, ^{
  4889. LogVerbose(@"dispatch_release(writeTimer)");
  4890. dispatch_release(theWriteTimer);
  4891. });
  4892. #endif
  4893. dispatch_time_t tt = dispatch_time(DISPATCH_TIME_NOW, (timeout * NSEC_PER_SEC));
  4894. dispatch_source_set_timer(writeTimer, tt, DISPATCH_TIME_FOREVER, 0);
  4895. dispatch_resume(writeTimer);
  4896. }
  4897. }
  4898. - (void)doWriteTimeout
  4899. {
  4900. // This is a little bit tricky.
  4901. // Ideally we'd like to synchronously query the delegate about a timeout extension.
  4902. // But if we do so synchronously we risk a possible deadlock.
  4903. // So instead we have to do so asynchronously, and callback to ourselves from within the delegate block.
  4904. flags |= kWritesPaused;
  4905. if (delegateQueue && [delegate respondsToSelector:@selector(socket:shouldTimeoutWriteWithTag:elapsed:bytesDone:)])
  4906. {
  4907. __strong id theDelegate = delegate;
  4908. GCDAsyncWritePacket *theWrite = currentWrite;
  4909. dispatch_async(delegateQueue, ^{ @autoreleasepool {
  4910. NSTimeInterval timeoutExtension = 0.0;
  4911. timeoutExtension = [theDelegate socket:self shouldTimeoutWriteWithTag:theWrite->tag
  4912. elapsed:theWrite->timeout
  4913. bytesDone:theWrite->bytesDone];
  4914. dispatch_async(socketQueue, ^{ @autoreleasepool {
  4915. [self doWriteTimeoutWithExtension:timeoutExtension];
  4916. }});
  4917. }});
  4918. }
  4919. else
  4920. {
  4921. [self doWriteTimeoutWithExtension:0.0];
  4922. }
  4923. }
  4924. - (void)doWriteTimeoutWithExtension:(NSTimeInterval)timeoutExtension
  4925. {
  4926. if (currentWrite)
  4927. {
  4928. if (timeoutExtension > 0.0)
  4929. {
  4930. currentWrite->timeout += timeoutExtension;
  4931. // Reschedule the timer
  4932. dispatch_time_t tt = dispatch_time(DISPATCH_TIME_NOW, (timeoutExtension * NSEC_PER_SEC));
  4933. dispatch_source_set_timer(writeTimer, tt, DISPATCH_TIME_FOREVER, 0);
  4934. // Unpause writes, and continue
  4935. flags &= ~kWritesPaused;
  4936. [self doWriteData];
  4937. }
  4938. else
  4939. {
  4940. LogVerbose(@"WriteTimeout");
  4941. [self closeWithError:[self writeTimeoutError]];
  4942. }
  4943. }
  4944. }
  4945. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  4946. #pragma mark Security
  4947. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  4948. - (void)startTLS:(NSDictionary *)tlsSettings
  4949. {
  4950. LogTrace();
  4951. if (tlsSettings == nil)
  4952. {
  4953. // Passing nil/NULL to CFReadStreamSetProperty will appear to work the same as passing an empty dictionary,
  4954. // but causes problems if we later try to fetch the remote host's certificate.
  4955. //
  4956. // To be exact, it causes the following to return NULL instead of the normal result:
  4957. // CFReadStreamCopyProperty(readStream, kCFStreamPropertySSLPeerCertificates)
  4958. //
  4959. // So we use an empty dictionary instead, which works perfectly.
  4960. tlsSettings = [NSDictionary dictionary];
  4961. }
  4962. GCDAsyncSpecialPacket *packet = [[GCDAsyncSpecialPacket alloc] initWithTLSSettings:tlsSettings];
  4963. dispatch_async(socketQueue, ^{ @autoreleasepool {
  4964. if ((flags & kSocketStarted) && !(flags & kQueuedTLS) && !(flags & kForbidReadsWrites))
  4965. {
  4966. [readQueue addObject:packet];
  4967. [writeQueue addObject:packet];
  4968. flags |= kQueuedTLS;
  4969. [self maybeDequeueRead];
  4970. [self maybeDequeueWrite];
  4971. }
  4972. }});
  4973. }
  4974. - (void)maybeStartTLS
  4975. {
  4976. // We can't start TLS until:
  4977. // - All queued reads prior to the user calling startTLS are complete
  4978. // - All queued writes prior to the user calling startTLS are complete
  4979. //
  4980. // We'll know these conditions are met when both kStartingReadTLS and kStartingWriteTLS are set
  4981. if ((flags & kStartingReadTLS) && (flags & kStartingWriteTLS))
  4982. {
  4983. BOOL canUseSecureTransport = YES;
  4984. #if TARGET_OS_IPHONE
  4985. {
  4986. GCDAsyncSpecialPacket *tlsPacket = (GCDAsyncSpecialPacket *)currentRead;
  4987. NSDictionary *tlsSettings = tlsPacket->tlsSettings;
  4988. NSNumber *value;
  4989. value = [tlsSettings objectForKey:(NSString *)kCFStreamSSLAllowsAnyRoot];
  4990. if (value && [value boolValue] == YES)
  4991. canUseSecureTransport = NO;
  4992. value = [tlsSettings objectForKey:(NSString *)kCFStreamSSLAllowsExpiredRoots];
  4993. if (value && [value boolValue] == YES)
  4994. canUseSecureTransport = NO;
  4995. value = [tlsSettings objectForKey:(NSString *)kCFStreamSSLValidatesCertificateChain];
  4996. if (value && [value boolValue] == NO)
  4997. canUseSecureTransport = NO;
  4998. value = [tlsSettings objectForKey:(NSString *)kCFStreamSSLAllowsExpiredCertificates];
  4999. if (value && [value boolValue] == YES)
  5000. canUseSecureTransport = NO;
  5001. }
  5002. #endif
  5003. if (IS_SECURE_TRANSPORT_AVAILABLE && canUseSecureTransport)
  5004. {
  5005. #if SECURE_TRANSPORT_MAYBE_AVAILABLE
  5006. [self ssl_startTLS];
  5007. #endif
  5008. }
  5009. else
  5010. {
  5011. #if TARGET_OS_IPHONE
  5012. [self cf_startTLS];
  5013. #endif
  5014. }
  5015. }
  5016. }
  5017. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  5018. #pragma mark Security via SecureTransport
  5019. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  5020. #if SECURE_TRANSPORT_MAYBE_AVAILABLE
  5021. - (OSStatus)sslReadWithBuffer:(void *)buffer length:(size_t *)bufferLength
  5022. {
  5023. LogVerbose(@"sslReadWithBuffer:%p length:%lu", buffer, (unsigned long)*bufferLength);
  5024. if ((socketFDBytesAvailable == 0) && ([sslPreBuffer availableBytes] == 0))
  5025. {
  5026. LogVerbose(@"%@ - No data available to read...", THIS_METHOD);
  5027. // No data available to read.
  5028. //
  5029. // Need to wait for readSource to fire and notify us of
  5030. // available data in the socket's internal read buffer.
  5031. [self resumeReadSource];
  5032. *bufferLength = 0;
  5033. return errSSLWouldBlock;
  5034. }
  5035. size_t totalBytesRead = 0;
  5036. size_t totalBytesLeftToBeRead = *bufferLength;
  5037. BOOL done = NO;
  5038. BOOL socketError = NO;
  5039. //
  5040. // STEP 1 : READ FROM SSL PRE BUFFER
  5041. //
  5042. size_t sslPreBufferLength = [sslPreBuffer availableBytes];
  5043. if (sslPreBufferLength > 0)
  5044. {
  5045. LogVerbose(@"%@: Reading from SSL pre buffer...", THIS_METHOD);
  5046. size_t bytesToCopy;
  5047. if (sslPreBufferLength > totalBytesLeftToBeRead)
  5048. bytesToCopy = totalBytesLeftToBeRead;
  5049. else
  5050. bytesToCopy = sslPreBufferLength;
  5051. LogVerbose(@"%@: Copying %zu bytes from sslPreBuffer", THIS_METHOD, bytesToCopy);
  5052. memcpy(buffer, [sslPreBuffer readBuffer], bytesToCopy);
  5053. [sslPreBuffer didRead:bytesToCopy];
  5054. LogVerbose(@"%@: sslPreBuffer.length = %zu", THIS_METHOD, [sslPreBuffer availableBytes]);
  5055. totalBytesRead += bytesToCopy;
  5056. totalBytesLeftToBeRead -= bytesToCopy;
  5057. done = (totalBytesLeftToBeRead == 0);
  5058. if (done) LogVerbose(@"%@: Complete", THIS_METHOD);
  5059. }
  5060. //
  5061. // STEP 2 : READ FROM SOCKET
  5062. //
  5063. if (!done && (socketFDBytesAvailable > 0))
  5064. {
  5065. LogVerbose(@"%@: Reading from socket...", THIS_METHOD);
  5066. int socketFD = (socket4FD != SOCKET_NULL) ? socket4FD : (socket6FD != SOCKET_NULL) ? socket6FD : socketUN;
  5067. BOOL readIntoPreBuffer;
  5068. size_t bytesToRead;
  5069. uint8_t *buf;
  5070. if (socketFDBytesAvailable > totalBytesLeftToBeRead)
  5071. {
  5072. // Read all available data from socket into sslPreBuffer.
  5073. // Then copy requested amount into dataBuffer.
  5074. LogVerbose(@"%@: Reading into sslPreBuffer...", THIS_METHOD);
  5075. [sslPreBuffer ensureCapacityForWrite:socketFDBytesAvailable];
  5076. readIntoPreBuffer = YES;
  5077. bytesToRead = (size_t)socketFDBytesAvailable;
  5078. buf = [sslPreBuffer writeBuffer];
  5079. }
  5080. else
  5081. {
  5082. // Read available data from socket directly into dataBuffer.
  5083. LogVerbose(@"%@: Reading directly into dataBuffer...", THIS_METHOD);
  5084. readIntoPreBuffer = NO;
  5085. bytesToRead = totalBytesLeftToBeRead;
  5086. buf = (uint8_t *)buffer + totalBytesRead;
  5087. }
  5088. ssize_t result = read(socketFD, buf, bytesToRead);
  5089. LogVerbose(@"%@: read from socket = %zd", THIS_METHOD, result);
  5090. if (result < 0)
  5091. {
  5092. LogVerbose(@"%@: read errno = %i", THIS_METHOD, errno);
  5093. if (errno != EWOULDBLOCK)
  5094. {
  5095. socketError = YES;
  5096. }
  5097. socketFDBytesAvailable = 0;
  5098. }
  5099. else if (result == 0)
  5100. {
  5101. LogVerbose(@"%@: read EOF", THIS_METHOD);
  5102. socketError = YES;
  5103. socketFDBytesAvailable = 0;
  5104. }
  5105. else
  5106. {
  5107. size_t bytesReadFromSocket = result;
  5108. if (socketFDBytesAvailable > bytesReadFromSocket)
  5109. socketFDBytesAvailable -= bytesReadFromSocket;
  5110. else
  5111. socketFDBytesAvailable = 0;
  5112. if (readIntoPreBuffer)
  5113. {
  5114. [sslPreBuffer didWrite:bytesReadFromSocket];
  5115. size_t bytesToCopy = MIN(totalBytesLeftToBeRead, bytesReadFromSocket);
  5116. LogVerbose(@"%@: Copying %zu bytes out of sslPreBuffer", THIS_METHOD, bytesToCopy);
  5117. memcpy((uint8_t *)buffer + totalBytesRead, [sslPreBuffer readBuffer], bytesToCopy);
  5118. [sslPreBuffer didRead:bytesToCopy];
  5119. totalBytesRead += bytesToCopy;
  5120. totalBytesLeftToBeRead -= bytesToCopy;
  5121. LogVerbose(@"%@: sslPreBuffer.length = %zu", THIS_METHOD, [sslPreBuffer availableBytes]);
  5122. }
  5123. else
  5124. {
  5125. totalBytesRead += bytesReadFromSocket;
  5126. totalBytesLeftToBeRead -= bytesReadFromSocket;
  5127. }
  5128. done = (totalBytesLeftToBeRead == 0);
  5129. if (done) LogVerbose(@"%@: Complete", THIS_METHOD);
  5130. }
  5131. }
  5132. *bufferLength = totalBytesRead;
  5133. if (done)
  5134. return noErr;
  5135. if (socketError)
  5136. return errSSLClosedAbort;
  5137. return errSSLWouldBlock;
  5138. }
  5139. - (OSStatus)sslWriteWithBuffer:(const void *)buffer length:(size_t *)bufferLength
  5140. {
  5141. if (!(flags & kSocketCanAcceptBytes))
  5142. {
  5143. // Unable to write.
  5144. //
  5145. // Need to wait for writeSource to fire and notify us of
  5146. // available space in the socket's internal write buffer.
  5147. [self resumeWriteSource];
  5148. *bufferLength = 0;
  5149. return errSSLWouldBlock;
  5150. }
  5151. size_t bytesToWrite = *bufferLength;
  5152. size_t bytesWritten = 0;
  5153. BOOL done = NO;
  5154. BOOL socketError = NO;
  5155. int socketFD = (socket4FD != SOCKET_NULL) ? socket4FD : (socket6FD != SOCKET_NULL) ? socket6FD : socketUN;
  5156. ssize_t result = write(socketFD, buffer, bytesToWrite);
  5157. if (result < 0)
  5158. {
  5159. if (errno != EWOULDBLOCK)
  5160. {
  5161. socketError = YES;
  5162. }
  5163. flags &= ~kSocketCanAcceptBytes;
  5164. }
  5165. else if (result == 0)
  5166. {
  5167. flags &= ~kSocketCanAcceptBytes;
  5168. }
  5169. else
  5170. {
  5171. bytesWritten = result;
  5172. done = (bytesWritten == bytesToWrite);
  5173. }
  5174. *bufferLength = bytesWritten;
  5175. if (done)
  5176. return noErr;
  5177. if (socketError)
  5178. return errSSLClosedAbort;
  5179. return errSSLWouldBlock;
  5180. }
  5181. static OSStatus SSLReadFunction(SSLConnectionRef connection, void *data, size_t *dataLength)
  5182. {
  5183. GCDAsyncSocket *asyncSocket = (__bridge GCDAsyncSocket *)connection;
  5184. NSCAssert(dispatch_get_current_queue() == asyncSocket->socketQueue, @"What the deuce?");
  5185. return [asyncSocket sslReadWithBuffer:data length:dataLength];
  5186. }
  5187. static OSStatus SSLWriteFunction(SSLConnectionRef connection, const void *data, size_t *dataLength)
  5188. {
  5189. GCDAsyncSocket *asyncSocket = (__bridge GCDAsyncSocket *)connection;
  5190. NSCAssert(dispatch_get_current_queue() == asyncSocket->socketQueue, @"What the deuce?");
  5191. return [asyncSocket sslWriteWithBuffer:data length:dataLength];
  5192. }
  5193. - (void)ssl_startTLS
  5194. {
  5195. LogTrace();
  5196. LogVerbose(@"Starting TLS (via SecureTransport)...");
  5197. OSStatus status;
  5198. GCDAsyncSpecialPacket *tlsPacket = (GCDAsyncSpecialPacket *)currentRead;
  5199. NSDictionary *tlsSettings = tlsPacket->tlsSettings;
  5200. // Create SSLContext, and setup IO callbacks and connection ref
  5201. BOOL isServer = [[tlsSettings objectForKey:(NSString *)kCFStreamSSLIsServer] boolValue];
  5202. #if TARGET_OS_IPHONE
  5203. {
  5204. if (isServer)
  5205. sslContext = SSLCreateContext(kCFAllocatorDefault, kSSLServerSide, kSSLStreamType);
  5206. else
  5207. sslContext = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide, kSSLStreamType);
  5208. if (sslContext == NULL)
  5209. {
  5210. [self closeWithError:[self otherError:@"Error in SSLCreateContext"]];
  5211. return;
  5212. }
  5213. }
  5214. #else
  5215. {
  5216. status = SSLNewContext(isServer, &sslContext);
  5217. if (status != noErr)
  5218. {
  5219. [self closeWithError:[self otherError:@"Error in SSLNewContext"]];
  5220. return;
  5221. }
  5222. }
  5223. #endif
  5224. status = SSLSetIOFuncs(sslContext, &SSLReadFunction, &SSLWriteFunction);
  5225. if (status != noErr)
  5226. {
  5227. [self closeWithError:[self otherError:@"Error in SSLSetIOFuncs"]];
  5228. return;
  5229. }
  5230. status = SSLSetConnection(sslContext, (__bridge SSLConnectionRef)self);
  5231. if (status != noErr)
  5232. {
  5233. [self closeWithError:[self otherError:@"Error in SSLSetConnection"]];
  5234. return;
  5235. }
  5236. // Configure SSLContext from given settings
  5237. //
  5238. // Checklist:
  5239. // 1. kCFStreamSSLPeerName
  5240. // 2. kCFStreamSSLAllowsAnyRoot
  5241. // 3. kCFStreamSSLAllowsExpiredRoots
  5242. // 4. kCFStreamSSLValidatesCertificateChain
  5243. // 5. kCFStreamSSLAllowsExpiredCertificates
  5244. // 6. kCFStreamSSLCertificates
  5245. // 7. kCFStreamSSLLevel (GCDAsyncSocketSSLProtocolVersionMin / GCDAsyncSocketSSLProtocolVersionMax)
  5246. // 8. GCDAsyncSocketSSLCipherSuites
  5247. // 9. GCDAsyncSocketSSLDiffieHellmanParameters (Mac)
  5248. id value;
  5249. // 1. kCFStreamSSLPeerName
  5250. value = [tlsSettings objectForKey:(NSString *)kCFStreamSSLPeerName];
  5251. if ([value isKindOfClass:[NSString class]])
  5252. {
  5253. NSString *peerName = (NSString *)value;
  5254. const char *peer = [peerName UTF8String];
  5255. size_t peerLen = strlen(peer);
  5256. status = SSLSetPeerDomainName(sslContext, peer, peerLen);
  5257. if (status != noErr)
  5258. {
  5259. [self closeWithError:[self otherError:@"Error in SSLSetPeerDomainName"]];
  5260. return;
  5261. }
  5262. }
  5263. // 2. kCFStreamSSLAllowsAnyRoot
  5264. value = [tlsSettings objectForKey:(NSString *)kCFStreamSSLAllowsAnyRoot];
  5265. if (value)
  5266. {
  5267. #if TARGET_OS_IPHONE
  5268. NSAssert(NO, @"Security option unavailable via SecureTransport in iOS - kCFStreamSSLAllowsAnyRoot");
  5269. #else
  5270. BOOL allowsAnyRoot = [value boolValue];
  5271. status = SSLSetAllowsAnyRoot(sslContext, allowsAnyRoot);
  5272. if (status != noErr)
  5273. {
  5274. [self closeWithError:[self otherError:@"Error in SSLSetAllowsAnyRoot"]];
  5275. return;
  5276. }
  5277. #endif
  5278. }
  5279. // 3. kCFStreamSSLAllowsExpiredRoots
  5280. value = [tlsSettings objectForKey:(NSString *)kCFStreamSSLAllowsExpiredRoots];
  5281. if (value)
  5282. {
  5283. #if TARGET_OS_IPHONE
  5284. NSAssert(NO, @"Security option unavailable via SecureTransport in iOS - kCFStreamSSLAllowsExpiredRoots");
  5285. #else
  5286. BOOL allowsExpiredRoots = [value boolValue];
  5287. status = SSLSetAllowsExpiredRoots(sslContext, allowsExpiredRoots);
  5288. if (status != noErr)
  5289. {
  5290. [self closeWithError:[self otherError:@"Error in SSLSetAllowsExpiredRoots"]];
  5291. return;
  5292. }
  5293. #endif
  5294. }
  5295. // 4. kCFStreamSSLValidatesCertificateChain
  5296. value = [tlsSettings objectForKey:(NSString *)kCFStreamSSLValidatesCertificateChain];
  5297. if (value)
  5298. {
  5299. #if TARGET_OS_IPHONE
  5300. NSAssert(NO, @"Security option unavailable via SecureTransport in iOS - kCFStreamSSLValidatesCertificateChain");
  5301. #else
  5302. BOOL validatesCertChain = [value boolValue];
  5303. status = SSLSetEnableCertVerify(sslContext, validatesCertChain);
  5304. if (status != noErr)
  5305. {
  5306. [self closeWithError:[self otherError:@"Error in SSLSetEnableCertVerify"]];
  5307. return;
  5308. }
  5309. #endif
  5310. }
  5311. // 5. kCFStreamSSLAllowsExpiredCertificates
  5312. value = [tlsSettings objectForKey:(NSString *)kCFStreamSSLAllowsExpiredCertificates];
  5313. if (value)
  5314. {
  5315. #if TARGET_OS_IPHONE
  5316. NSAssert(NO, @"Security option unavailable via SecureTransport in iOS - kCFStreamSSLAllowsExpiredCertificates");
  5317. #else
  5318. BOOL allowsExpiredCerts = [value boolValue];
  5319. status = SSLSetAllowsExpiredCerts(sslContext, allowsExpiredCerts);
  5320. if (status != noErr)
  5321. {
  5322. [self closeWithError:[self otherError:@"Error in SSLSetAllowsExpiredCerts"]];
  5323. return;
  5324. }
  5325. #endif
  5326. }
  5327. // 6. kCFStreamSSLCertificates
  5328. value = [tlsSettings objectForKey:(NSString *)kCFStreamSSLCertificates];
  5329. if (value)
  5330. {
  5331. CFArrayRef certs = (__bridge CFArrayRef)value;
  5332. status = SSLSetCertificate(sslContext, certs);
  5333. if (status != noErr)
  5334. {
  5335. [self closeWithError:[self otherError:@"Error in SSLSetCertificate"]];
  5336. return;
  5337. }
  5338. }
  5339. // 7. kCFStreamSSLLevel
  5340. #if TARGET_OS_IPHONE
  5341. {
  5342. NSString *sslLevel = [tlsSettings objectForKey:(NSString *)kCFStreamSSLLevel];
  5343. NSString *sslMinLevel = [tlsSettings objectForKey:GCDAsyncSocketSSLProtocolVersionMin];
  5344. NSString *sslMaxLevel = [tlsSettings objectForKey:GCDAsyncSocketSSLProtocolVersionMax];
  5345. if (sslLevel)
  5346. {
  5347. if (sslMinLevel || sslMaxLevel)
  5348. {
  5349. LogWarn(@"kCFStreamSSLLevel security option ignored. Overriden by "
  5350. @"GCDAsyncSocketSSLProtocolVersionMin and/or GCDAsyncSocketSSLProtocolVersionMax");
  5351. }
  5352. else
  5353. {
  5354. if ([sslLevel isEqualToString:(NSString *)kCFStreamSocketSecurityLevelSSLv3])
  5355. {
  5356. sslMinLevel = sslMaxLevel = @"kSSLProtocol3";
  5357. }
  5358. else if ([sslLevel isEqualToString:(NSString *)kCFStreamSocketSecurityLevelTLSv1])
  5359. {
  5360. sslMinLevel = sslMaxLevel = @"kTLSProtocol1";
  5361. }
  5362. else
  5363. {
  5364. LogWarn(@"Unable to match kCFStreamSSLLevel security option to valid SSL protocol min/max");
  5365. }
  5366. }
  5367. }
  5368. if (sslMinLevel || sslMaxLevel)
  5369. {
  5370. OSStatus status1 = noErr;
  5371. OSStatus status2 = noErr;
  5372. SSLProtocol (^sslProtocolForString)(NSString*) = ^SSLProtocol (NSString *protocolStr) {
  5373. if ([protocolStr isEqualToString:@"kSSLProtocol3"]) return kSSLProtocol3;
  5374. if ([protocolStr isEqualToString:@"kTLSProtocol1"]) return kTLSProtocol1;
  5375. if ([protocolStr isEqualToString:@"kTLSProtocol11"]) return kTLSProtocol11;
  5376. if ([protocolStr isEqualToString:@"kTLSProtocol12"]) return kTLSProtocol12;
  5377. return kSSLProtocolUnknown;
  5378. };
  5379. SSLProtocol minProtocol = sslProtocolForString(sslMinLevel);
  5380. SSLProtocol maxProtocol = sslProtocolForString(sslMaxLevel);
  5381. if (minProtocol != kSSLProtocolUnknown)
  5382. {
  5383. status1 = SSLSetProtocolVersionMin(sslContext, minProtocol);
  5384. }
  5385. if (maxProtocol != kSSLProtocolUnknown)
  5386. {
  5387. status2 = SSLSetProtocolVersionMax(sslContext, maxProtocol);
  5388. }
  5389. if (status1 != noErr || status2 != noErr)
  5390. {
  5391. [self closeWithError:[self otherError:@"Error in SSLSetProtocolVersionMinMax"]];
  5392. return;
  5393. }
  5394. }
  5395. }
  5396. #else
  5397. {
  5398. value = [tlsSettings objectForKey:(NSString *)kCFStreamSSLLevel];
  5399. if (value)
  5400. {
  5401. NSString *sslLevel = (NSString *)value;
  5402. OSStatus status1 = noErr;
  5403. OSStatus status2 = noErr;
  5404. OSStatus status3 = noErr;
  5405. if ([sslLevel isEqualToString:(NSString *)kCFStreamSocketSecurityLevelSSLv2])
  5406. {
  5407. // kCFStreamSocketSecurityLevelSSLv2:
  5408. //
  5409. // Specifies that SSL version 2 be set as the security protocol.
  5410. status1 = SSLSetProtocolVersionEnabled(sslContext, kSSLProtocolAll, NO);
  5411. status2 = SSLSetProtocolVersionEnabled(sslContext, kSSLProtocol2, YES);
  5412. }
  5413. else if ([sslLevel isEqualToString:(NSString *)kCFStreamSocketSecurityLevelSSLv3])
  5414. {
  5415. // kCFStreamSocketSecurityLevelSSLv3:
  5416. //
  5417. // Specifies that SSL version 3 be set as the security protocol.
  5418. // If SSL version 3 is not available, specifies that SSL version 2 be set as the security protocol.
  5419. status1 = SSLSetProtocolVersionEnabled(sslContext, kSSLProtocolAll, NO);
  5420. status2 = SSLSetProtocolVersionEnabled(sslContext, kSSLProtocol2, YES);
  5421. status3 = SSLSetProtocolVersionEnabled(sslContext, kSSLProtocol3, YES);
  5422. }
  5423. else if ([sslLevel isEqualToString:(NSString *)kCFStreamSocketSecurityLevelTLSv1])
  5424. {
  5425. // kCFStreamSocketSecurityLevelTLSv1:
  5426. //
  5427. // Specifies that TLS version 1 be set as the security protocol.
  5428. status1 = SSLSetProtocolVersionEnabled(sslContext, kSSLProtocolAll, NO);
  5429. status2 = SSLSetProtocolVersionEnabled(sslContext, kTLSProtocol1, YES);
  5430. }
  5431. else if ([sslLevel isEqualToString:(NSString *)kCFStreamSocketSecurityLevelNegotiatedSSL])
  5432. {
  5433. // kCFStreamSocketSecurityLevelNegotiatedSSL:
  5434. //
  5435. // Specifies that the highest level security protocol that can be negotiated be used.
  5436. status1 = SSLSetProtocolVersionEnabled(sslContext, kSSLProtocolAll, YES);
  5437. }
  5438. if (status1 != noErr || status2 != noErr || status3 != noErr)
  5439. {
  5440. [self closeWithError:[self otherError:@"Error in SSLSetProtocolVersionEnabled"]];
  5441. return;
  5442. }
  5443. }
  5444. }
  5445. #endif
  5446. // 8. GCDAsyncSocketSSLCipherSuites
  5447. value = [tlsSettings objectForKey:GCDAsyncSocketSSLCipherSuites];
  5448. if (value)
  5449. {
  5450. NSArray *cipherSuites = (NSArray *)value;
  5451. NSUInteger numberCiphers = [cipherSuites count];
  5452. SSLCipherSuite ciphers[numberCiphers];
  5453. NSUInteger cipherIndex;
  5454. for (cipherIndex = 0; cipherIndex < numberCiphers; cipherIndex++)
  5455. {
  5456. NSNumber *cipherObject = [cipherSuites objectAtIndex:cipherIndex];
  5457. ciphers[cipherIndex] = [cipherObject shortValue];
  5458. }
  5459. status = SSLSetEnabledCiphers(sslContext, ciphers, numberCiphers);
  5460. if (status != noErr)
  5461. {
  5462. [self closeWithError:[self otherError:@"Error in SSLSetEnabledCiphers"]];
  5463. return;
  5464. }
  5465. }
  5466. // 9. GCDAsyncSocketSSLDiffieHellmanParameters
  5467. #if !TARGET_OS_IPHONE
  5468. value = [tlsSettings objectForKey:GCDAsyncSocketSSLDiffieHellmanParameters];
  5469. if (value)
  5470. {
  5471. NSData *diffieHellmanData = (NSData *)value;
  5472. status = SSLSetDiffieHellmanParams(sslContext, [diffieHellmanData bytes], [diffieHellmanData length]);
  5473. if (status != noErr)
  5474. {
  5475. [self closeWithError:[self otherError:@"Error in SSLSetDiffieHellmanParams"]];
  5476. return;
  5477. }
  5478. }
  5479. #endif
  5480. // Setup the sslPreBuffer
  5481. //
  5482. // Any data in the preBuffer needs to be moved into the sslPreBuffer,
  5483. // as this data is now part of the secure read stream.
  5484. sslPreBuffer = [[GCDAsyncSocketPreBuffer alloc] initWithCapacity:(1024 * 4)];
  5485. size_t preBufferLength = [preBuffer availableBytes];
  5486. if (preBufferLength > 0)
  5487. {
  5488. [sslPreBuffer ensureCapacityForWrite:preBufferLength];
  5489. memcpy([sslPreBuffer writeBuffer], [preBuffer readBuffer], preBufferLength);
  5490. [preBuffer didRead:preBufferLength];
  5491. [sslPreBuffer didWrite:preBufferLength];
  5492. }
  5493. sslErrCode = noErr;
  5494. // Start the SSL Handshake process
  5495. [self ssl_continueSSLHandshake];
  5496. }
  5497. - (void)ssl_continueSSLHandshake
  5498. {
  5499. LogTrace();
  5500. // If the return value is noErr, the session is ready for normal secure communication.
  5501. // If the return value is errSSLWouldBlock, the SSLHandshake function must be called again.
  5502. // Otherwise, the return value indicates an error code.
  5503. OSStatus status = SSLHandshake(sslContext);
  5504. if (status == noErr)
  5505. {
  5506. LogVerbose(@"SSLHandshake complete");
  5507. flags &= ~kStartingReadTLS;
  5508. flags &= ~kStartingWriteTLS;
  5509. flags |= kSocketSecure;
  5510. if (delegateQueue && [delegate respondsToSelector:@selector(socketDidSecure:)])
  5511. {
  5512. __strong id theDelegate = delegate;
  5513. dispatch_async(delegateQueue, ^{ @autoreleasepool {
  5514. [theDelegate socketDidSecure:self];
  5515. }});
  5516. }
  5517. [self endCurrentRead];
  5518. [self endCurrentWrite];
  5519. [self maybeDequeueRead];
  5520. [self maybeDequeueWrite];
  5521. }
  5522. else if (status == errSSLWouldBlock)
  5523. {
  5524. LogVerbose(@"SSLHandshake continues...");
  5525. // Handshake continues...
  5526. //
  5527. // This method will be called again from doReadData or doWriteData.
  5528. }
  5529. else
  5530. {
  5531. [self closeWithError:[self sslError:status]];
  5532. }
  5533. }
  5534. #endif
  5535. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  5536. #pragma mark Security via CFStream
  5537. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  5538. #if TARGET_OS_IPHONE
  5539. - (void)cf_finishSSLHandshake
  5540. {
  5541. LogTrace();
  5542. if ((flags & kStartingReadTLS) && (flags & kStartingWriteTLS))
  5543. {
  5544. flags &= ~kStartingReadTLS;
  5545. flags &= ~kStartingWriteTLS;
  5546. flags |= kSocketSecure;
  5547. if (delegateQueue && [delegate respondsToSelector:@selector(socketDidSecure:)])
  5548. {
  5549. __strong id theDelegate = delegate;
  5550. dispatch_async(delegateQueue, ^{ @autoreleasepool {
  5551. [theDelegate socketDidSecure:self];
  5552. }});
  5553. }
  5554. [self endCurrentRead];
  5555. [self endCurrentWrite];
  5556. [self maybeDequeueRead];
  5557. [self maybeDequeueWrite];
  5558. }
  5559. }
  5560. - (void)cf_abortSSLHandshake:(NSError *)error
  5561. {
  5562. LogTrace();
  5563. if ((flags & kStartingReadTLS) && (flags & kStartingWriteTLS))
  5564. {
  5565. flags &= ~kStartingReadTLS;
  5566. flags &= ~kStartingWriteTLS;
  5567. [self closeWithError:error];
  5568. }
  5569. }
  5570. - (void)cf_startTLS
  5571. {
  5572. LogTrace();
  5573. LogVerbose(@"Starting TLS (via CFStream)...");
  5574. if ([preBuffer availableBytes] > 0)
  5575. {
  5576. NSString *msg = @"Invalid TLS transition. Handshake has already been read from socket.";
  5577. [self closeWithError:[self otherError:msg]];
  5578. return;
  5579. }
  5580. [self suspendReadSource];
  5581. [self suspendWriteSource];
  5582. socketFDBytesAvailable = 0;
  5583. flags &= ~kSocketCanAcceptBytes;
  5584. flags &= ~kSecureSocketHasBytesAvailable;
  5585. flags |= kUsingCFStreamForTLS;
  5586. if (![self createReadAndWriteStream])
  5587. {
  5588. [self closeWithError:[self otherError:@"Error in CFStreamCreatePairWithSocket"]];
  5589. return;
  5590. }
  5591. if (![self registerForStreamCallbacksIncludingReadWrite:YES])
  5592. {
  5593. [self closeWithError:[self otherError:@"Error in CFStreamSetClient"]];
  5594. return;
  5595. }
  5596. if (![self addStreamsToRunLoop])
  5597. {
  5598. [self closeWithError:[self otherError:@"Error in CFStreamScheduleWithRunLoop"]];
  5599. return;
  5600. }
  5601. NSAssert([currentRead isKindOfClass:[GCDAsyncSpecialPacket class]], @"Invalid read packet for startTLS");
  5602. NSAssert([currentWrite isKindOfClass:[GCDAsyncSpecialPacket class]], @"Invalid write packet for startTLS");
  5603. GCDAsyncSpecialPacket *tlsPacket = (GCDAsyncSpecialPacket *)currentRead;
  5604. CFDictionaryRef tlsSettings = (__bridge CFDictionaryRef)tlsPacket->tlsSettings;
  5605. // Getting an error concerning kCFStreamPropertySSLSettings ?
  5606. // You need to add the CFNetwork framework to your iOS application.
  5607. BOOL r1 = CFReadStreamSetProperty(readStream, kCFStreamPropertySSLSettings, tlsSettings);
  5608. BOOL r2 = CFWriteStreamSetProperty(writeStream, kCFStreamPropertySSLSettings, tlsSettings);
  5609. // For some reason, starting around the time of iOS 4.3,
  5610. // the first call to set the kCFStreamPropertySSLSettings will return true,
  5611. // but the second will return false.
  5612. //
  5613. // Order doesn't seem to matter.
  5614. // So you could call CFReadStreamSetProperty and then CFWriteStreamSetProperty, or you could reverse the order.
  5615. // Either way, the first call will return true, and the second returns false.
  5616. //
  5617. // Interestingly, this doesn't seem to affect anything.
  5618. // Which is not altogether unusual, as the documentation seems to suggest that (for many settings)
  5619. // setting it on one side of the stream automatically sets it for the other side of the stream.
  5620. //
  5621. // Although there isn't anything in the documentation to suggest that the second attempt would fail.
  5622. //
  5623. // Furthermore, this only seems to affect streams that are negotiating a security upgrade.
  5624. // In other words, the socket gets connected, there is some back-and-forth communication over the unsecure
  5625. // connection, and then a startTLS is issued.
  5626. // So this mostly affects newer protocols (XMPP, IMAP) as opposed to older protocols (HTTPS).
  5627. if (!r1 && !r2) // Yes, the && is correct - workaround for apple bug.
  5628. {
  5629. [self closeWithError:[self otherError:@"Error in CFStreamSetProperty"]];
  5630. return;
  5631. }
  5632. if (![self openStreams])
  5633. {
  5634. [self closeWithError:[self otherError:@"Error in CFStreamOpen"]];
  5635. return;
  5636. }
  5637. LogVerbose(@"Waiting for SSL Handshake to complete...");
  5638. }
  5639. #endif
  5640. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  5641. #pragma mark CFStream
  5642. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  5643. #if TARGET_OS_IPHONE
  5644. + (void)startCFStreamThreadIfNeeded
  5645. {
  5646. static dispatch_once_t predicate;
  5647. dispatch_once(&predicate, ^{
  5648. cfstreamThread = [[NSThread alloc] initWithTarget:self
  5649. selector:@selector(cfstreamThread)
  5650. object:nil];
  5651. [cfstreamThread start];
  5652. });
  5653. }
  5654. + (void)cfstreamThread { @autoreleasepool
  5655. {
  5656. [[NSThread currentThread] setName:GCDAsyncSocketThreadName];
  5657. LogInfo(@"CFStreamThread: Started");
  5658. // We can't run the run loop unless it has an associated input source or a timer.
  5659. // So we'll just create a timer that will never fire - unless the server runs for decades.
  5660. [NSTimer scheduledTimerWithTimeInterval:[[NSDate distantFuture] timeIntervalSinceNow]
  5661. target:self
  5662. selector:@selector(doNothingAtAll:)
  5663. userInfo:nil
  5664. repeats:YES];
  5665. [[NSRunLoop currentRunLoop] run];
  5666. LogInfo(@"CFStreamThread: Stopped");
  5667. }}
  5668. + (void)scheduleCFStreams:(GCDAsyncSocket *)asyncSocket
  5669. {
  5670. LogTrace();
  5671. NSAssert([NSThread currentThread] == cfstreamThread, @"Invoked on wrong thread");
  5672. CFRunLoopRef runLoop = CFRunLoopGetCurrent();
  5673. if (asyncSocket->readStream)
  5674. CFReadStreamScheduleWithRunLoop(asyncSocket->readStream, runLoop, kCFRunLoopDefaultMode);
  5675. if (asyncSocket->writeStream)
  5676. CFWriteStreamScheduleWithRunLoop(asyncSocket->writeStream, runLoop, kCFRunLoopDefaultMode);
  5677. }
  5678. + (void)unscheduleCFStreams:(GCDAsyncSocket *)asyncSocket
  5679. {
  5680. LogTrace();
  5681. NSAssert([NSThread currentThread] == cfstreamThread, @"Invoked on wrong thread");
  5682. CFRunLoopRef runLoop = CFRunLoopGetCurrent();
  5683. if (asyncSocket->readStream)
  5684. CFReadStreamUnscheduleFromRunLoop(asyncSocket->readStream, runLoop, kCFRunLoopDefaultMode);
  5685. if (asyncSocket->writeStream)
  5686. CFWriteStreamUnscheduleFromRunLoop(asyncSocket->writeStream, runLoop, kCFRunLoopDefaultMode);
  5687. }
  5688. static void CFReadStreamCallback (CFReadStreamRef stream, CFStreamEventType type, void *pInfo)
  5689. {
  5690. GCDAsyncSocket *asyncSocket = (__bridge GCDAsyncSocket *)pInfo;
  5691. switch(type)
  5692. {
  5693. case kCFStreamEventHasBytesAvailable:
  5694. {
  5695. dispatch_async(asyncSocket->socketQueue, ^{ @autoreleasepool {
  5696. LogCVerbose(@"CFReadStreamCallback - HasBytesAvailable");
  5697. if (asyncSocket->readStream != stream)
  5698. return_from_block;
  5699. if ((asyncSocket->flags & kStartingReadTLS) && (asyncSocket->flags & kStartingWriteTLS))
  5700. {
  5701. // If we set kCFStreamPropertySSLSettings before we opened the streams, this might be a lie.
  5702. // (A callback related to the tcp stream, but not to the SSL layer).
  5703. if (CFReadStreamHasBytesAvailable(asyncSocket->readStream))
  5704. {
  5705. asyncSocket->flags |= kSecureSocketHasBytesAvailable;
  5706. [asyncSocket cf_finishSSLHandshake];
  5707. }
  5708. }
  5709. else
  5710. {
  5711. asyncSocket->flags |= kSecureSocketHasBytesAvailable;
  5712. [asyncSocket doReadData];
  5713. }
  5714. }});
  5715. break;
  5716. }
  5717. default:
  5718. {
  5719. NSError *error = (__bridge_transfer NSError *)CFReadStreamCopyError(stream);
  5720. if (error == nil && type == kCFStreamEventEndEncountered)
  5721. {
  5722. error = [asyncSocket connectionClosedError];
  5723. }
  5724. dispatch_async(asyncSocket->socketQueue, ^{ @autoreleasepool {
  5725. LogCVerbose(@"CFReadStreamCallback - Other");
  5726. if (asyncSocket->readStream != stream)
  5727. return_from_block;
  5728. if ((asyncSocket->flags & kStartingReadTLS) && (asyncSocket->flags & kStartingWriteTLS))
  5729. {
  5730. [asyncSocket cf_abortSSLHandshake:error];
  5731. }
  5732. else
  5733. {
  5734. [asyncSocket closeWithError:error];
  5735. }
  5736. }});
  5737. break;
  5738. }
  5739. }
  5740. }
  5741. static void CFWriteStreamCallback (CFWriteStreamRef stream, CFStreamEventType type, void *pInfo)
  5742. {
  5743. GCDAsyncSocket *asyncSocket = (__bridge GCDAsyncSocket *)pInfo;
  5744. switch(type)
  5745. {
  5746. case kCFStreamEventCanAcceptBytes:
  5747. {
  5748. dispatch_async(asyncSocket->socketQueue, ^{ @autoreleasepool {
  5749. LogCVerbose(@"CFWriteStreamCallback - CanAcceptBytes");
  5750. if (asyncSocket->writeStream != stream)
  5751. return_from_block;
  5752. if ((asyncSocket->flags & kStartingReadTLS) && (asyncSocket->flags & kStartingWriteTLS))
  5753. {
  5754. // If we set kCFStreamPropertySSLSettings before we opened the streams, this might be a lie.
  5755. // (A callback related to the tcp stream, but not to the SSL layer).
  5756. if (CFWriteStreamCanAcceptBytes(asyncSocket->writeStream))
  5757. {
  5758. asyncSocket->flags |= kSocketCanAcceptBytes;
  5759. [asyncSocket cf_finishSSLHandshake];
  5760. }
  5761. }
  5762. else
  5763. {
  5764. asyncSocket->flags |= kSocketCanAcceptBytes;
  5765. [asyncSocket doWriteData];
  5766. }
  5767. }});
  5768. break;
  5769. }
  5770. default:
  5771. {
  5772. NSError *error = (__bridge_transfer NSError *)CFWriteStreamCopyError(stream);
  5773. if (error == nil && type == kCFStreamEventEndEncountered)
  5774. {
  5775. error = [asyncSocket connectionClosedError];
  5776. }
  5777. dispatch_async(asyncSocket->socketQueue, ^{ @autoreleasepool {
  5778. LogCVerbose(@"CFWriteStreamCallback - Other");
  5779. if (asyncSocket->writeStream != stream)
  5780. return_from_block;
  5781. if ((asyncSocket->flags & kStartingReadTLS) && (asyncSocket->flags & kStartingWriteTLS))
  5782. {
  5783. [asyncSocket cf_abortSSLHandshake:error];
  5784. }
  5785. else
  5786. {
  5787. [asyncSocket closeWithError:error];
  5788. }
  5789. }});
  5790. break;
  5791. }
  5792. }
  5793. }
  5794. - (BOOL)createReadAndWriteStream
  5795. {
  5796. LogTrace();
  5797. NSAssert(dispatch_get_current_queue() == socketQueue, @"Must be dispatched on socketQueue");
  5798. if (readStream || writeStream)
  5799. {
  5800. // Streams already created
  5801. return YES;
  5802. }
  5803. int socketFD = (socket4FD != SOCKET_NULL) ? socket4FD : (socket6FD != SOCKET_NULL) ? socket6FD : socketUN;
  5804. if (socketFD == SOCKET_NULL)
  5805. {
  5806. // Cannot create streams without a file descriptor
  5807. return NO;
  5808. }
  5809. if (![self isConnected])
  5810. {
  5811. // Cannot create streams until file descriptor is connected
  5812. return NO;
  5813. }
  5814. LogVerbose(@"Creating read and write stream...");
  5815. CFStreamCreatePairWithSocket(NULL, (CFSocketNativeHandle)socketFD, &readStream, &writeStream);
  5816. // The kCFStreamPropertyShouldCloseNativeSocket property should be false by default (for our case).
  5817. // But let's not take any chances.
  5818. if (readStream)
  5819. CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanFalse);
  5820. if (writeStream)
  5821. CFWriteStreamSetProperty(writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanFalse);
  5822. if ((readStream == NULL) || (writeStream == NULL))
  5823. {
  5824. LogWarn(@"Unable to create read and write stream...");
  5825. if (readStream)
  5826. {
  5827. CFReadStreamClose(readStream);
  5828. CFRelease(readStream);
  5829. readStream = NULL;
  5830. }
  5831. if (writeStream)
  5832. {
  5833. CFWriteStreamClose(writeStream);
  5834. CFRelease(writeStream);
  5835. writeStream = NULL;
  5836. }
  5837. return NO;
  5838. }
  5839. return YES;
  5840. }
  5841. - (BOOL)registerForStreamCallbacksIncludingReadWrite:(BOOL)includeReadWrite
  5842. {
  5843. LogVerbose(@"%@ %@", THIS_METHOD, (includeReadWrite ? @"YES" : @"NO"));
  5844. NSAssert(dispatch_get_current_queue() == socketQueue, @"Must be dispatched on socketQueue");
  5845. NSAssert((readStream != NULL && writeStream != NULL), @"Read/Write stream is null");
  5846. streamContext.version = 0;
  5847. streamContext.info = (__bridge void *)(self);
  5848. streamContext.retain = nil;
  5849. streamContext.release = nil;
  5850. streamContext.copyDescription = nil;
  5851. CFOptionFlags readStreamEvents = kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered;
  5852. if (includeReadWrite)
  5853. readStreamEvents |= kCFStreamEventHasBytesAvailable;
  5854. if (!CFReadStreamSetClient(readStream, readStreamEvents, &CFReadStreamCallback, &streamContext))
  5855. {
  5856. return NO;
  5857. }
  5858. CFOptionFlags writeStreamEvents = kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered;
  5859. if (includeReadWrite)
  5860. writeStreamEvents |= kCFStreamEventCanAcceptBytes;
  5861. if (!CFWriteStreamSetClient(writeStream, writeStreamEvents, &CFWriteStreamCallback, &streamContext))
  5862. {
  5863. return NO;
  5864. }
  5865. return YES;
  5866. }
  5867. - (BOOL)addStreamsToRunLoop
  5868. {
  5869. LogTrace();
  5870. NSAssert(dispatch_get_current_queue() == socketQueue, @"Must be dispatched on socketQueue");
  5871. NSAssert((readStream != NULL && writeStream != NULL), @"Read/Write stream is null");
  5872. if (!(flags & kAddedStreamsToRunLoop))
  5873. {
  5874. LogVerbose(@"Adding streams to runloop...");
  5875. [[self class] startCFStreamThreadIfNeeded];
  5876. [[self class] performSelector:@selector(scheduleCFStreams:)
  5877. onThread:cfstreamThread
  5878. withObject:self
  5879. waitUntilDone:YES];
  5880. flags |= kAddedStreamsToRunLoop;
  5881. }
  5882. return YES;
  5883. }
  5884. - (void)removeStreamsFromRunLoop
  5885. {
  5886. LogTrace();
  5887. NSAssert(dispatch_get_current_queue() == socketQueue, @"Must be dispatched on socketQueue");
  5888. NSAssert((readStream != NULL && writeStream != NULL), @"Read/Write stream is null");
  5889. if (flags & kAddedStreamsToRunLoop)
  5890. {
  5891. LogVerbose(@"Removing streams from runloop...");
  5892. [[self class] performSelector:@selector(unscheduleCFStreams:)
  5893. onThread:cfstreamThread
  5894. withObject:self
  5895. waitUntilDone:YES];
  5896. flags &= ~kAddedStreamsToRunLoop;
  5897. }
  5898. }
  5899. - (BOOL)openStreams
  5900. {
  5901. LogTrace();
  5902. NSAssert(dispatch_get_current_queue() == socketQueue, @"Must be dispatched on socketQueue");
  5903. NSAssert((readStream != NULL && writeStream != NULL), @"Read/Write stream is null");
  5904. CFStreamStatus readStatus = CFReadStreamGetStatus(readStream);
  5905. CFStreamStatus writeStatus = CFWriteStreamGetStatus(writeStream);
  5906. if ((readStatus == kCFStreamStatusNotOpen) || (writeStatus == kCFStreamStatusNotOpen))
  5907. {
  5908. LogVerbose(@"Opening read and write stream...");
  5909. BOOL r1 = CFReadStreamOpen(readStream);
  5910. BOOL r2 = CFWriteStreamOpen(writeStream);
  5911. if (!r1 || !r2)
  5912. {
  5913. LogError(@"Error in CFStreamOpen");
  5914. return NO;
  5915. }
  5916. }
  5917. return YES;
  5918. }
  5919. #endif
  5920. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  5921. #pragma mark Advanced
  5922. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  5923. - (void)performBlock:(dispatch_block_t)block
  5924. {
  5925. dispatch_sync(socketQueue, block);
  5926. }
  5927. - (int)socketFD
  5928. {
  5929. if (dispatch_get_current_queue() != socketQueue)
  5930. {
  5931. LogWarn(@"%@ - Method only available from within the context of a performBlock: invocation", THIS_METHOD);
  5932. return SOCKET_NULL;
  5933. }
  5934. if (socket4FD != SOCKET_NULL)
  5935. return socket4FD;
  5936. else
  5937. return socket6FD;
  5938. }
  5939. - (int)socket4FD
  5940. {
  5941. if (dispatch_get_current_queue() != socketQueue)
  5942. {
  5943. LogWarn(@"%@ - Method only available from within the context of a performBlock: invocation", THIS_METHOD);
  5944. return SOCKET_NULL;
  5945. }
  5946. return socket4FD;
  5947. }
  5948. - (int)socket6FD
  5949. {
  5950. if (dispatch_get_current_queue() != socketQueue)
  5951. {
  5952. LogWarn(@"%@ - Method only available from within the context of a performBlock: invocation", THIS_METHOD);
  5953. return SOCKET_NULL;
  5954. }
  5955. return socket6FD;
  5956. }
  5957. #if TARGET_OS_IPHONE
  5958. - (CFReadStreamRef)readStream
  5959. {
  5960. if (dispatch_get_current_queue() != socketQueue)
  5961. {
  5962. LogWarn(@"%@ - Method only available from within the context of a performBlock: invocation", THIS_METHOD);
  5963. return NULL;
  5964. }
  5965. if (readStream == NULL)
  5966. [self createReadAndWriteStream];
  5967. return readStream;
  5968. }
  5969. - (CFWriteStreamRef)writeStream
  5970. {
  5971. if (dispatch_get_current_queue() != socketQueue)
  5972. {
  5973. LogWarn(@"%@ - Method only available from within the context of a performBlock: invocation", THIS_METHOD);
  5974. return NULL;
  5975. }
  5976. if (writeStream == NULL)
  5977. [self createReadAndWriteStream];
  5978. return writeStream;
  5979. }
  5980. - (BOOL)enableBackgroundingOnSocketWithCaveat:(BOOL)caveat
  5981. {
  5982. if (![self createReadAndWriteStream])
  5983. {
  5984. // Error occured creating streams (perhaps socket isn't open)
  5985. return NO;
  5986. }
  5987. BOOL r1, r2;
  5988. LogVerbose(@"Enabling backgrouding on socket");
  5989. r1 = CFReadStreamSetProperty(readStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);
  5990. r2 = CFWriteStreamSetProperty(writeStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);
  5991. if (!r1 || !r2)
  5992. {
  5993. return NO;
  5994. }
  5995. if (!caveat)
  5996. {
  5997. if (![self openStreams])
  5998. {
  5999. return NO;
  6000. }
  6001. }
  6002. return YES;
  6003. }
  6004. - (BOOL)enableBackgroundingOnSocket
  6005. {
  6006. LogTrace();
  6007. if (dispatch_get_current_queue() != socketQueue)
  6008. {
  6009. LogWarn(@"%@ - Method only available from within the context of a performBlock: invocation", THIS_METHOD);
  6010. return NO;
  6011. }
  6012. return [self enableBackgroundingOnSocketWithCaveat:NO];
  6013. }
  6014. - (BOOL)enableBackgroundingOnSocketWithCaveat // Deprecated in iOS 4.???
  6015. {
  6016. // This method was created as a workaround for a bug in iOS.
  6017. // Apple has since fixed this bug.
  6018. // I'm not entirely sure which version of iOS they fixed it in...
  6019. LogTrace();
  6020. if (dispatch_get_current_queue() != socketQueue)
  6021. {
  6022. LogWarn(@"%@ - Method only available from within the context of a performBlock: invocation", THIS_METHOD);
  6023. return NO;
  6024. }
  6025. return [self enableBackgroundingOnSocketWithCaveat:YES];
  6026. }
  6027. #else
  6028. - (SSLContextRef)sslContext
  6029. {
  6030. if (dispatch_get_current_queue() != socketQueue)
  6031. {
  6032. LogWarn(@"%@ - Method only available from within the context of a performBlock: invocation", THIS_METHOD);
  6033. return NULL;
  6034. }
  6035. return sslContext;
  6036. }
  6037. #endif
  6038. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  6039. #pragma mark Class Methods
  6040. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  6041. + (NSString *)hostFromSockaddr4:(const struct sockaddr_in *)pSockaddr4
  6042. {
  6043. char addrBuf[INET_ADDRSTRLEN];
  6044. if (inet_ntop(AF_INET, &pSockaddr4->sin_addr, addrBuf, (socklen_t)sizeof(addrBuf)) == NULL)
  6045. {
  6046. addrBuf[0] = '\0';
  6047. }
  6048. return [NSString stringWithCString:addrBuf encoding:NSASCIIStringEncoding];
  6049. }
  6050. + (NSString *)hostFromSockaddr6:(const struct sockaddr_in6 *)pSockaddr6
  6051. {
  6052. char addrBuf[INET6_ADDRSTRLEN];
  6053. if (inet_ntop(AF_INET6, &pSockaddr6->sin6_addr, addrBuf, (socklen_t)sizeof(addrBuf)) == NULL)
  6054. {
  6055. addrBuf[0] = '\0';
  6056. }
  6057. return [NSString stringWithCString:addrBuf encoding:NSASCIIStringEncoding];
  6058. }
  6059. + (uint16_t)portFromSockaddr4:(const struct sockaddr_in *)pSockaddr4
  6060. {
  6061. return ntohs(pSockaddr4->sin_port);
  6062. }
  6063. + (uint16_t)portFromSockaddr6:(const struct sockaddr_in6 *)pSockaddr6
  6064. {
  6065. return ntohs(pSockaddr6->sin6_port);
  6066. }
  6067. + (NSURL *)urlFromSockaddrUN:(const struct sockaddr_un *)pSockaddr
  6068. {
  6069. NSString *string = [NSString stringWithUTF8String:pSockaddr->sun_path];
  6070. return [NSURL URLWithString:string];
  6071. }
  6072. + (NSString *)hostFromAddress:(NSData *)address
  6073. {
  6074. NSString *host;
  6075. if ([self getHost:&host port:NULL fromAddress:address])
  6076. return host;
  6077. else
  6078. return nil;
  6079. }
  6080. + (uint16_t)portFromAddress:(NSData *)address
  6081. {
  6082. uint16_t port;
  6083. if ([self getHost:NULL port:&port fromAddress:address])
  6084. return port;
  6085. else
  6086. return 0;
  6087. }
  6088. + (BOOL)getHost:(NSString **)hostPtr port:(uint16_t *)portPtr fromAddress:(NSData *)address
  6089. {
  6090. if ([address length] >= sizeof(struct sockaddr))
  6091. {
  6092. const struct sockaddr *sockaddrX = [address bytes];
  6093. if (sockaddrX->sa_family == AF_INET)
  6094. {
  6095. if ([address length] >= sizeof(struct sockaddr_in))
  6096. {
  6097. struct sockaddr_in sockaddr4;
  6098. memcpy(&sockaddr4, sockaddrX, sizeof(sockaddr4));
  6099. if (hostPtr) *hostPtr = [self hostFromSockaddr4:&sockaddr4];
  6100. if (portPtr) *portPtr = [self portFromSockaddr4:&sockaddr4];
  6101. return YES;
  6102. }
  6103. }
  6104. else if (sockaddrX->sa_family == AF_INET6)
  6105. {
  6106. if ([address length] >= sizeof(struct sockaddr_in6))
  6107. {
  6108. struct sockaddr_in6 sockaddr6;
  6109. memcpy(&sockaddr6, sockaddrX, sizeof(sockaddr6));
  6110. if (hostPtr) *hostPtr = [self hostFromSockaddr6:&sockaddr6];
  6111. if (portPtr) *portPtr = [self portFromSockaddr6:&sockaddr6];
  6112. return YES;
  6113. }
  6114. }
  6115. }
  6116. return NO;
  6117. }
  6118. + (NSData *)CRLFData
  6119. {
  6120. return [NSData dataWithBytes:"\x0D\x0A" length:2];
  6121. }
  6122. + (NSData *)CRData
  6123. {
  6124. return [NSData dataWithBytes:"\x0D" length:1];
  6125. }
  6126. + (NSData *)LFData
  6127. {
  6128. return [NSData dataWithBytes:"\x0A" length:1];
  6129. }
  6130. + (NSData *)ZeroData
  6131. {
  6132. return [NSData dataWithBytes:"" length:1];
  6133. }
  6134. @end