mirror of
https://github.com/status-im/react-native-tcp.git
synced 2025-02-15 03:47:03 +00:00
update CocoaAsyncSocket to latest, fix ipv6 client connecting issue
This commit is contained in:
parent
a66adc7e82
commit
2303105741
@ -19,6 +19,9 @@
|
||||
@class GCDAsyncReadPacket;
|
||||
@class GCDAsyncWritePacket;
|
||||
@class GCDAsyncSocketPreBuffer;
|
||||
@protocol GCDAsyncSocketDelegate;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
extern NSString *const GCDAsyncSocketException;
|
||||
extern NSString *const GCDAsyncSocketErrorDomain;
|
||||
@ -62,6 +65,7 @@ typedef NS_ENUM(NSInteger, GCDAsyncSocketError) {
|
||||
#pragma mark -
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@interface GCDAsyncSocket : NSObject
|
||||
|
||||
/**
|
||||
@ -80,30 +84,30 @@ typedef NS_ENUM(NSInteger, GCDAsyncSocketError) {
|
||||
*
|
||||
* The delegate queue and socket queue can optionally be the same.
|
||||
**/
|
||||
- (id)init;
|
||||
- (id)initWithSocketQueue:(dispatch_queue_t)sq;
|
||||
- (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq;
|
||||
- (id)initWithDelegate:(id)aDelegate delegateQueue:(dispatch_queue_t)dq socketQueue:(dispatch_queue_t)sq;
|
||||
- (instancetype)init;
|
||||
- (instancetype)initWithSocketQueue:(nullable dispatch_queue_t)sq;
|
||||
- (instancetype)initWithDelegate:(nullable id<GCDAsyncSocketDelegate>)aDelegate delegateQueue:(nullable dispatch_queue_t)dq;
|
||||
- (instancetype)initWithDelegate:(nullable id<GCDAsyncSocketDelegate>)aDelegate delegateQueue:(nullable dispatch_queue_t)dq socketQueue:(nullable dispatch_queue_t)sq;
|
||||
|
||||
#pragma mark Configuration
|
||||
|
||||
@property (atomic, weak, readwrite) id delegate;
|
||||
@property (atomic, weak, readwrite, nullable) id<GCDAsyncSocketDelegate> delegate;
|
||||
#if OS_OBJECT_USE_OBJC
|
||||
@property (atomic, strong, readwrite) dispatch_queue_t delegateQueue;
|
||||
@property (atomic, strong, readwrite, nullable) dispatch_queue_t delegateQueue;
|
||||
#else
|
||||
@property (atomic, assign, readwrite) dispatch_queue_t delegateQueue;
|
||||
@property (atomic, assign, readwrite, nullable) dispatch_queue_t delegateQueue;
|
||||
#endif
|
||||
|
||||
- (void)getDelegate:(id *)delegatePtr delegateQueue:(dispatch_queue_t *)delegateQueuePtr;
|
||||
- (void)setDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue;
|
||||
- (void)getDelegate:(id<GCDAsyncSocketDelegate> __nullable * __nullable)delegatePtr delegateQueue:(dispatch_queue_t __nullable * __nullable)delegateQueuePtr;
|
||||
- (void)setDelegate:(nullable id<GCDAsyncSocketDelegate>)delegate delegateQueue:(nullable dispatch_queue_t)delegateQueue;
|
||||
|
||||
/**
|
||||
* If you are setting the delegate to nil within the delegate's dealloc method,
|
||||
* you may need to use the synchronous versions below.
|
||||
**/
|
||||
- (void)synchronouslySetDelegate:(id)delegate;
|
||||
- (void)synchronouslySetDelegateQueue:(dispatch_queue_t)delegateQueue;
|
||||
- (void)synchronouslySetDelegate:(id)delegate delegateQueue:(dispatch_queue_t)delegateQueue;
|
||||
- (void)synchronouslySetDelegate:(nullable id<GCDAsyncSocketDelegate>)delegate;
|
||||
- (void)synchronouslySetDelegateQueue:(nullable dispatch_queue_t)delegateQueue;
|
||||
- (void)synchronouslySetDelegate:(nullable id<GCDAsyncSocketDelegate>)delegate delegateQueue:(nullable dispatch_queue_t)delegateQueue;
|
||||
|
||||
/**
|
||||
* By default, both IPv4 and IPv6 are enabled.
|
||||
@ -123,11 +127,19 @@ typedef NS_ENUM(NSInteger, GCDAsyncSocketError) {
|
||||
|
||||
@property (atomic, assign, readwrite, getter=isIPv4PreferredOverIPv6) BOOL IPv4PreferredOverIPv6;
|
||||
|
||||
/**
|
||||
* When connecting to both IPv4 and IPv6 using Happy Eyeballs (RFC 6555) https://tools.ietf.org/html/rfc6555
|
||||
* this is the delay between connecting to the preferred protocol and the fallback protocol.
|
||||
*
|
||||
* Defaults to 300ms.
|
||||
**/
|
||||
@property (atomic, assign, readwrite) NSTimeInterval alternateAddressDelay;
|
||||
|
||||
/**
|
||||
* User data allows you to associate arbitrary information with the socket.
|
||||
* This data is not used internally by socket in any way.
|
||||
**/
|
||||
@property (atomic, strong, readwrite) id userData;
|
||||
@property (atomic, strong, readwrite, nullable) id userData;
|
||||
|
||||
#pragma mark Accepting
|
||||
|
||||
@ -156,7 +168,7 @@ typedef NS_ENUM(NSInteger, GCDAsyncSocketError) {
|
||||
*
|
||||
* To accept connections on any interface pass nil, or simply use the acceptOnPort:error: method.
|
||||
**/
|
||||
- (BOOL)acceptOnInterface:(NSString *)interface port:(uint16_t)port error:(NSError **)errPtr;
|
||||
- (BOOL)acceptOnInterface:(nullable NSString *)interface port:(uint16_t)port error:(NSError **)errPtr;
|
||||
|
||||
/**
|
||||
* Tells the socket to begin listening and accepting connections on the unix domain at the given url.
|
||||
@ -221,7 +233,7 @@ typedef NS_ENUM(NSInteger, GCDAsyncSocketError) {
|
||||
**/
|
||||
- (BOOL)connectToHost:(NSString *)host
|
||||
onPort:(uint16_t)port
|
||||
viaInterface:(NSString *)interface
|
||||
viaInterface:(nullable NSString *)interface
|
||||
withTimeout:(NSTimeInterval)timeout
|
||||
error:(NSError **)errPtr;
|
||||
|
||||
@ -279,7 +291,7 @@ typedef NS_ENUM(NSInteger, GCDAsyncSocketError) {
|
||||
* This feature is here for networking professionals using very advanced techniques.
|
||||
**/
|
||||
- (BOOL)connectToAddress:(NSData *)remoteAddr
|
||||
viaInterface:(NSString *)interface
|
||||
viaInterface:(nullable NSString *)interface
|
||||
withTimeout:(NSTimeInterval)timeout
|
||||
error:(NSError **)errPtr;
|
||||
/**
|
||||
@ -347,11 +359,11 @@ typedef NS_ENUM(NSInteger, GCDAsyncSocketError) {
|
||||
* Returns the local or remote host and port to which this socket is connected, or nil and 0 if not connected.
|
||||
* The host will be an IP address.
|
||||
**/
|
||||
@property (atomic, readonly) NSString *connectedHost;
|
||||
@property (atomic, readonly, nullable) NSString *connectedHost;
|
||||
@property (atomic, readonly) uint16_t connectedPort;
|
||||
@property (atomic, readonly) NSURL *connectedUrl;
|
||||
@property (atomic, readonly, nullable) NSURL *connectedUrl;
|
||||
|
||||
@property (atomic, readonly) NSString *localHost;
|
||||
@property (atomic, readonly, nullable) NSString *localHost;
|
||||
@property (atomic, readonly) uint16_t localPort;
|
||||
|
||||
/**
|
||||
@ -363,8 +375,8 @@ typedef NS_ENUM(NSInteger, GCDAsyncSocketError) {
|
||||
* @seealso localHost
|
||||
* @seealso localPort
|
||||
**/
|
||||
@property (atomic, readonly) NSData *connectedAddress;
|
||||
@property (atomic, readonly) NSData *localAddress;
|
||||
@property (atomic, readonly, nullable) NSData *connectedAddress;
|
||||
@property (atomic, readonly, nullable) NSData *localAddress;
|
||||
|
||||
/**
|
||||
* Returns whether the socket is IPv4 or IPv6.
|
||||
@ -419,7 +431,7 @@ typedef NS_ENUM(NSInteger, GCDAsyncSocketError) {
|
||||
* the method [NSData dataWithBytesNoCopy:length:freeWhenDone:NO].
|
||||
**/
|
||||
- (void)readDataWithTimeout:(NSTimeInterval)timeout
|
||||
buffer:(NSMutableData *)buffer
|
||||
buffer:(nullable NSMutableData *)buffer
|
||||
bufferOffset:(NSUInteger)offset
|
||||
tag:(long)tag;
|
||||
|
||||
@ -442,7 +454,7 @@ typedef NS_ENUM(NSInteger, GCDAsyncSocketError) {
|
||||
* the method [NSData dataWithBytesNoCopy:length:freeWhenDone:NO].
|
||||
**/
|
||||
- (void)readDataWithTimeout:(NSTimeInterval)timeout
|
||||
buffer:(NSMutableData *)buffer
|
||||
buffer:(nullable NSMutableData *)buffer
|
||||
bufferOffset:(NSUInteger)offset
|
||||
maxLength:(NSUInteger)length
|
||||
tag:(long)tag;
|
||||
@ -475,7 +487,7 @@ typedef NS_ENUM(NSInteger, GCDAsyncSocketError) {
|
||||
**/
|
||||
- (void)readDataToLength:(NSUInteger)length
|
||||
withTimeout:(NSTimeInterval)timeout
|
||||
buffer:(NSMutableData *)buffer
|
||||
buffer:(nullable NSMutableData *)buffer
|
||||
bufferOffset:(NSUInteger)offset
|
||||
tag:(long)tag;
|
||||
|
||||
@ -533,7 +545,7 @@ typedef NS_ENUM(NSInteger, GCDAsyncSocketError) {
|
||||
**/
|
||||
- (void)readDataToData:(NSData *)data
|
||||
withTimeout:(NSTimeInterval)timeout
|
||||
buffer:(NSMutableData *)buffer
|
||||
buffer:(nullable NSMutableData *)buffer
|
||||
bufferOffset:(NSUInteger)offset
|
||||
tag:(long)tag;
|
||||
|
||||
@ -605,7 +617,7 @@ typedef NS_ENUM(NSInteger, GCDAsyncSocketError) {
|
||||
**/
|
||||
- (void)readDataToData:(NSData *)data
|
||||
withTimeout:(NSTimeInterval)timeout
|
||||
buffer:(NSMutableData *)buffer
|
||||
buffer:(nullable NSMutableData *)buffer
|
||||
bufferOffset:(NSUInteger)offset
|
||||
maxLength:(NSUInteger)length
|
||||
tag:(long)tag;
|
||||
@ -614,7 +626,7 @@ typedef NS_ENUM(NSInteger, GCDAsyncSocketError) {
|
||||
* Returns progress of the current read, from 0.0 to 1.0, or NaN if no current read (use isnan() to check).
|
||||
* The parameters "tag", "done" and "total" will be filled in if they aren't NULL.
|
||||
**/
|
||||
- (float)progressOfReadReturningTag:(long *)tagPtr bytesDone:(NSUInteger *)donePtr total:(NSUInteger *)totalPtr;
|
||||
- (float)progressOfReadReturningTag:(nullable long *)tagPtr bytesDone:(nullable NSUInteger *)donePtr total:(nullable NSUInteger *)totalPtr;
|
||||
|
||||
#pragma mark Writing
|
||||
|
||||
@ -641,7 +653,7 @@ typedef NS_ENUM(NSInteger, GCDAsyncSocketError) {
|
||||
* Returns progress of the current write, from 0.0 to 1.0, or NaN if no current write (use isnan() to check).
|
||||
* The parameters "tag", "done" and "total" will be filled in if they aren't NULL.
|
||||
**/
|
||||
- (float)progressOfWriteReturningTag:(long *)tagPtr bytesDone:(NSUInteger *)donePtr total:(NSUInteger *)totalPtr;
|
||||
- (float)progressOfWriteReturningTag:(nullable long *)tagPtr bytesDone:(nullable NSUInteger *)donePtr total:(nullable NSUInteger *)totalPtr;
|
||||
|
||||
#pragma mark Security
|
||||
|
||||
@ -776,7 +788,7 @@ typedef NS_ENUM(NSInteger, GCDAsyncSocketError) {
|
||||
*
|
||||
* You can also perform additional validation in socketDidSecure.
|
||||
**/
|
||||
- (void)startTLS:(NSDictionary *)tlsSettings;
|
||||
- (void)startTLS:(nullable NSDictionary <NSString*,NSObject*>*)tlsSettings;
|
||||
|
||||
#pragma mark Advanced
|
||||
|
||||
@ -950,8 +962,8 @@ typedef NS_ENUM(NSInteger, GCDAsyncSocketError) {
|
||||
*
|
||||
* See also: (BOOL)enableBackgroundingOnSocket
|
||||
**/
|
||||
- (CFReadStreamRef)readStream;
|
||||
- (CFWriteStreamRef)writeStream;
|
||||
- (nullable CFReadStreamRef)readStream;
|
||||
- (nullable CFWriteStreamRef)writeStream;
|
||||
|
||||
/**
|
||||
* This method is only available from within the context of a performBlock: invocation.
|
||||
@ -988,7 +1000,7 @@ typedef NS_ENUM(NSInteger, GCDAsyncSocketError) {
|
||||
*
|
||||
* Provides access to the socket's SSLContext, if SSL/TLS has been started on the socket.
|
||||
**/
|
||||
- (SSLContextRef)sslContext;
|
||||
- (nullable SSLContextRef)sslContext;
|
||||
|
||||
#pragma mark Utilities
|
||||
|
||||
@ -1003,21 +1015,21 @@ typedef NS_ENUM(NSInteger, GCDAsyncSocketError) {
|
||||
* The addresses are specifically for TCP connections.
|
||||
* You can filter the addresses, if needed, using the other utility methods provided by the class.
|
||||
**/
|
||||
+ (NSMutableArray *)lookupHost:(NSString *)host port:(uint16_t)port error:(NSError **)errPtr;
|
||||
+ (nullable NSMutableArray *)lookupHost:(NSString *)host port:(uint16_t)port error:(NSError **)errPtr;
|
||||
|
||||
/**
|
||||
* Extracting host and port information from raw address data.
|
||||
**/
|
||||
|
||||
+ (NSString *)hostFromAddress:(NSData *)address;
|
||||
+ (nullable NSString *)hostFromAddress:(NSData *)address;
|
||||
+ (uint16_t)portFromAddress:(NSData *)address;
|
||||
|
||||
+ (BOOL)isIPv4Address:(NSData *)address;
|
||||
+ (BOOL)isIPv6Address:(NSData *)address;
|
||||
|
||||
+ (BOOL)getHost:(NSString **)hostPtr port:(uint16_t *)portPtr fromAddress:(NSData *)address;
|
||||
+ (BOOL)getHost:( NSString * __nullable * __nullable)hostPtr port:(nullable uint16_t *)portPtr fromAddress:(NSData *)address;
|
||||
|
||||
+ (BOOL)getHost:(NSString **)hostPtr port:(uint16_t *)portPtr family:(sa_family_t *)afPtr fromAddress:(NSData *)address;
|
||||
+ (BOOL)getHost:(NSString * __nullable * __nullable)hostPtr port:(nullable uint16_t *)portPtr family:(nullable sa_family_t *)afPtr fromAddress:(NSData *)address;
|
||||
|
||||
/**
|
||||
* A few common line separators, for use with the readDataToData:... methods.
|
||||
@ -1033,7 +1045,7 @@ typedef NS_ENUM(NSInteger, GCDAsyncSocketError) {
|
||||
#pragma mark -
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@protocol GCDAsyncSocketDelegate
|
||||
@protocol GCDAsyncSocketDelegate <NSObject>
|
||||
@optional
|
||||
|
||||
/**
|
||||
@ -1054,7 +1066,7 @@ typedef NS_ENUM(NSInteger, GCDAsyncSocketError) {
|
||||
* dispatch_retain(myExistingQueue);
|
||||
* return myExistingQueue;
|
||||
**/
|
||||
- (dispatch_queue_t)newSocketQueueForConnectionFromAddress:(NSData *)address onSocket:(GCDAsyncSocket *)sock;
|
||||
- (nullable dispatch_queue_t)newSocketQueueForConnectionFromAddress:(NSData *)address onSocket:(GCDAsyncSocket *)sock;
|
||||
|
||||
/**
|
||||
* Called when a socket accepts a connection.
|
||||
@ -1163,7 +1175,7 @@ typedef NS_ENUM(NSInteger, GCDAsyncSocketError) {
|
||||
*
|
||||
* Of course, this depends on how your state machine is configured.
|
||||
**/
|
||||
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err;
|
||||
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(nullable NSError *)err;
|
||||
|
||||
/**
|
||||
* Called after the socket has successfully completed SSL/TLS negotiation.
|
||||
@ -1195,3 +1207,4 @@ typedef NS_ENUM(NSInteger, GCDAsyncSocketError) {
|
||||
completionHandler:(void (^)(BOOL shouldTrustPeer))completionHandler;
|
||||
|
||||
@end
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
@ -867,7 +867,7 @@ enum GCDAsyncSocketConfig
|
||||
uint32_t flags;
|
||||
uint16_t config;
|
||||
|
||||
__weak id delegate;
|
||||
__weak id<GCDAsyncSocketDelegate> delegate;
|
||||
dispatch_queue_t delegateQueue;
|
||||
|
||||
int socket4FD;
|
||||
@ -914,6 +914,7 @@ enum GCDAsyncSocketConfig
|
||||
void *IsOnSocketQueueOrTargetQueueKey;
|
||||
|
||||
id userData;
|
||||
NSTimeInterval alternateAddressDelay;
|
||||
}
|
||||
|
||||
- (id)init
|
||||
@ -996,6 +997,7 @@ enum GCDAsyncSocketConfig
|
||||
currentWrite = nil;
|
||||
|
||||
preBuffer = [[GCDAsyncSocketPreBuffer alloc] initWithCapacity:(1024 * 4)];
|
||||
alternateAddressDelay = 0.3;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@ -1134,7 +1136,7 @@ enum GCDAsyncSocketConfig
|
||||
[self setDelegateQueue:newDelegateQueue synchronously:YES];
|
||||
}
|
||||
|
||||
- (void)getDelegate:(id *)delegatePtr delegateQueue:(dispatch_queue_t *)delegateQueuePtr
|
||||
- (void)getDelegate:(id<GCDAsyncSocketDelegate> *)delegatePtr delegateQueue:(dispatch_queue_t *)delegateQueuePtr
|
||||
{
|
||||
if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
|
||||
{
|
||||
@ -1305,6 +1307,28 @@ enum GCDAsyncSocketConfig
|
||||
dispatch_async(socketQueue, block);
|
||||
}
|
||||
|
||||
- (NSTimeInterval) alternateAddressDelay {
|
||||
__block NSTimeInterval delay;
|
||||
dispatch_block_t block = ^{
|
||||
delay = alternateAddressDelay;
|
||||
};
|
||||
if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
|
||||
block();
|
||||
else
|
||||
dispatch_sync(socketQueue, block);
|
||||
return delay;
|
||||
}
|
||||
|
||||
- (void) setAlternateAddressDelay:(NSTimeInterval)delay {
|
||||
dispatch_block_t block = ^{
|
||||
alternateAddressDelay = delay;
|
||||
};
|
||||
if (dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey))
|
||||
block();
|
||||
else
|
||||
dispatch_async(socketQueue, block);
|
||||
}
|
||||
|
||||
- (id)userData
|
||||
{
|
||||
__block id result = nil;
|
||||
@ -2226,7 +2250,7 @@ enum GCDAsyncSocketConfig
|
||||
#pragma clang diagnostic warning "-Wimplicit-retain-self"
|
||||
|
||||
NSError *lookupErr = nil;
|
||||
NSMutableArray *addresses = [GCDAsyncSocket lookupHost:hostCpy port:port error:&lookupErr];
|
||||
NSMutableArray *addresses = [[self class] lookupHost:hostCpy port:port error:&lookupErr];
|
||||
|
||||
__strong GCDAsyncSocket *strongSelf = weakSelf;
|
||||
if (strongSelf == nil) return_from_block;
|
||||
@ -2245,11 +2269,11 @@ enum GCDAsyncSocketConfig
|
||||
|
||||
for (NSData *address in addresses)
|
||||
{
|
||||
if (!address4 && [GCDAsyncSocket isIPv4Address:address])
|
||||
if (!address4 && [[self class] isIPv4Address:address])
|
||||
{
|
||||
address4 = address;
|
||||
}
|
||||
else if (!address6 && [GCDAsyncSocket isIPv6Address:address])
|
||||
else if (!address6 && [[self class] isIPv6Address:address])
|
||||
{
|
||||
address6 = address;
|
||||
}
|
||||
@ -2426,10 +2450,10 @@ enum GCDAsyncSocketConfig
|
||||
|
||||
// Start the normal connection process
|
||||
|
||||
NSError *err = nil;
|
||||
if (![self connectWithAddressUN:connectInterfaceUN error:&err])
|
||||
NSError *connectError = nil;
|
||||
if (![self connectWithAddressUN:connectInterfaceUN error:&connectError])
|
||||
{
|
||||
[self closeWithError:err];
|
||||
[self closeWithError:connectError];
|
||||
|
||||
return_from_block;
|
||||
}
|
||||
@ -2527,56 +2551,8 @@ enum GCDAsyncSocketConfig
|
||||
[self closeWithError:error];
|
||||
}
|
||||
|
||||
- (BOOL)connectWithAddress4:(NSData *)address4 address6:(NSData *)address6 error:(NSError **)errPtr
|
||||
- (BOOL)bindSocket:(int)socketFD toInterface:(NSData *)connectInterface error:(NSError **)errPtr
|
||||
{
|
||||
LogTrace();
|
||||
|
||||
NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue");
|
||||
|
||||
LogVerbose(@"IPv4: %@:%hu", [[self class] hostFromAddress:address4], [[self class] portFromAddress:address4]);
|
||||
LogVerbose(@"IPv6: %@:%hu", [[self class] hostFromAddress:address6], [[self class] portFromAddress:address6]);
|
||||
|
||||
// Determine socket type
|
||||
|
||||
BOOL preferIPv6 = (config & kPreferIPv6) ? YES : NO;
|
||||
|
||||
BOOL useIPv6 = ((preferIPv6 && address6) || (address4 == nil));
|
||||
|
||||
// Create the socket
|
||||
|
||||
int socketFD;
|
||||
NSData *address;
|
||||
NSData *connectInterface;
|
||||
|
||||
if (useIPv6)
|
||||
{
|
||||
LogVerbose(@"Creating IPv6 socket");
|
||||
|
||||
socket6FD = socket(AF_INET6, SOCK_STREAM, 0);
|
||||
|
||||
socketFD = socket6FD;
|
||||
address = address6;
|
||||
connectInterface = connectInterface6;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogVerbose(@"Creating IPv4 socket");
|
||||
|
||||
socket4FD = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
socketFD = socket4FD;
|
||||
address = address4;
|
||||
connectInterface = connectInterface4;
|
||||
}
|
||||
|
||||
if (socketFD == SOCKET_NULL)
|
||||
{
|
||||
if (errPtr)
|
||||
*errPtr = [self errnoErrorWithReason:@"Error in socket() function"];
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
// Bind the socket to the desired interface (if needed)
|
||||
|
||||
if (connectInterface)
|
||||
@ -2604,14 +2580,47 @@ enum GCDAsyncSocketConfig
|
||||
}
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (int)createSocket:(int)family connectInterface:(NSData *)connectInterface errPtr:(NSError **)errPtr
|
||||
{
|
||||
int socketFD = socket(family, SOCK_STREAM, 0);
|
||||
|
||||
if (socketFD == SOCKET_NULL)
|
||||
{
|
||||
if (errPtr)
|
||||
*errPtr = [self errnoErrorWithReason:@"Error in socket() function"];
|
||||
|
||||
return socketFD;
|
||||
}
|
||||
|
||||
if (![self bindSocket:socketFD toInterface:connectInterface error:errPtr])
|
||||
{
|
||||
[self closeSocket:socketFD];
|
||||
|
||||
return SOCKET_NULL;
|
||||
}
|
||||
|
||||
// Prevent SIGPIPE signals
|
||||
|
||||
int nosigpipe = 1;
|
||||
setsockopt(socketFD, SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe, sizeof(nosigpipe));
|
||||
|
||||
return socketFD;
|
||||
}
|
||||
|
||||
- (void)connectSocket:(int)socketFD address:(NSData *)address stateIndex:(int)aStateIndex
|
||||
{
|
||||
// If there already is a socket connected, we close socketFD and return
|
||||
if (self.isConnected)
|
||||
{
|
||||
[self closeSocket:socketFD];
|
||||
return;
|
||||
}
|
||||
|
||||
// Start the connection process in a background queue
|
||||
|
||||
int aStateIndex = stateIndex;
|
||||
__weak GCDAsyncSocket *weakSelf = self;
|
||||
|
||||
dispatch_queue_t globalConcurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
|
||||
@ -2624,27 +2633,133 @@ enum GCDAsyncSocketConfig
|
||||
__strong GCDAsyncSocket *strongSelf = weakSelf;
|
||||
if (strongSelf == nil) return_from_block;
|
||||
|
||||
if (result == 0)
|
||||
{
|
||||
dispatch_async(strongSelf->socketQueue, ^{ @autoreleasepool {
|
||||
|
||||
if (strongSelf.isConnected)
|
||||
{
|
||||
[strongSelf closeSocket:socketFD];
|
||||
return_from_block;
|
||||
}
|
||||
|
||||
if (result == 0)
|
||||
{
|
||||
[self closeUnusedSocket:socketFD];
|
||||
|
||||
[strongSelf didConnect:aStateIndex];
|
||||
}});
|
||||
}
|
||||
else
|
||||
{
|
||||
[strongSelf closeSocket:socketFD];
|
||||
|
||||
// If there are no more sockets trying to connect, we inform the error to the delegate
|
||||
if (strongSelf.socket4FD == SOCKET_NULL && strongSelf.socket6FD == SOCKET_NULL)
|
||||
{
|
||||
NSError *error = [strongSelf errnoErrorWithReason:@"Error in connect() function"];
|
||||
|
||||
dispatch_async(strongSelf->socketQueue, ^{ @autoreleasepool {
|
||||
|
||||
[strongSelf didNotConnect:aStateIndex error:error];
|
||||
}});
|
||||
}
|
||||
}
|
||||
}});
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
});
|
||||
|
||||
LogVerbose(@"Connecting...");
|
||||
}
|
||||
|
||||
- (void)closeSocket:(int)socketFD
|
||||
{
|
||||
if (socketFD != SOCKET_NULL &&
|
||||
(socketFD == socket6FD || socketFD == socket4FD))
|
||||
{
|
||||
close(socketFD);
|
||||
|
||||
if (socketFD == socket4FD)
|
||||
{
|
||||
LogVerbose(@"close(socket4FD)");
|
||||
socket4FD = SOCKET_NULL;
|
||||
}
|
||||
else if (socketFD == socket6FD)
|
||||
{
|
||||
LogVerbose(@"close(socket6FD)");
|
||||
socket6FD = SOCKET_NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)closeUnusedSocket:(int)usedSocketFD
|
||||
{
|
||||
if (usedSocketFD != socket4FD)
|
||||
{
|
||||
[self closeSocket:socket4FD];
|
||||
}
|
||||
else if (usedSocketFD != socket6FD)
|
||||
{
|
||||
[self closeSocket:socket6FD];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)connectWithAddress4:(NSData *)address4 address6:(NSData *)address6 error:(NSError **)errPtr
|
||||
{
|
||||
LogTrace();
|
||||
|
||||
NSAssert(dispatch_get_specific(IsOnSocketQueueOrTargetQueueKey), @"Must be dispatched on socketQueue");
|
||||
|
||||
LogVerbose(@"IPv4: %@:%hu", [[self class] hostFromAddress:address4], [[self class] portFromAddress:address4]);
|
||||
LogVerbose(@"IPv6: %@:%hu", [[self class] hostFromAddress:address6], [[self class] portFromAddress:address6]);
|
||||
|
||||
// Determine socket type
|
||||
|
||||
BOOL preferIPv6 = (config & kPreferIPv6) ? YES : NO;
|
||||
|
||||
// Create and bind the sockets
|
||||
|
||||
if (address4)
|
||||
{
|
||||
LogVerbose(@"Creating IPv4 socket");
|
||||
|
||||
socket4FD = [self createSocket:AF_INET connectInterface:connectInterface4 errPtr:errPtr];
|
||||
}
|
||||
|
||||
if (address6)
|
||||
{
|
||||
LogVerbose(@"Creating IPv6 socket");
|
||||
|
||||
socket6FD = [self createSocket:AF_INET6 connectInterface:connectInterface6 errPtr:errPtr];
|
||||
}
|
||||
|
||||
if (socket4FD == SOCKET_NULL && socket6FD == SOCKET_NULL)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
int socketFD, alternateSocketFD;
|
||||
NSData *address, *alternateAddress;
|
||||
|
||||
if ((preferIPv6 && socket6FD != SOCKET_NULL) || socket4FD == SOCKET_NULL)
|
||||
{
|
||||
socketFD = socket6FD;
|
||||
alternateSocketFD = socket4FD;
|
||||
address = address6;
|
||||
alternateAddress = address4;
|
||||
}
|
||||
else
|
||||
{
|
||||
socketFD = socket4FD;
|
||||
alternateSocketFD = socket6FD;
|
||||
address = address4;
|
||||
alternateAddress = address6;
|
||||
}
|
||||
|
||||
int aStateIndex = stateIndex;
|
||||
|
||||
[self connectSocket:socketFD address:address stateIndex:aStateIndex];
|
||||
|
||||
if (alternateAddress)
|
||||
{
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(alternateAddressDelay * NSEC_PER_SEC)), socketQueue, ^{
|
||||
[self connectSocket:alternateSocketFD address:alternateAddress stateIndex:aStateIndex];
|
||||
});
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
@ -6342,8 +6457,10 @@ enum GCDAsyncSocketConfig
|
||||
#if TARGET_OS_IPHONE
|
||||
{
|
||||
GCDAsyncSpecialPacket *tlsPacket = (GCDAsyncSpecialPacket *)currentRead;
|
||||
NSDictionary *tlsSettings = tlsPacket->tlsSettings;
|
||||
|
||||
NSDictionary *tlsSettings = @{};
|
||||
if (tlsPacket) {
|
||||
tlsSettings = tlsPacket->tlsSettings;
|
||||
}
|
||||
NSNumber *value = [tlsSettings objectForKey:GCDAsyncSocketUseCFStreamForTLS];
|
||||
if (value && [value boolValue])
|
||||
useSecureTransport = NO;
|
||||
@ -7380,7 +7497,7 @@ static OSStatus SSLWriteFunction(SSLConnectionRef connection, const void *data,
|
||||
[cfstreamThread cancel]; // set isCancelled flag
|
||||
|
||||
// wake up the thread
|
||||
[GCDAsyncSocket performSelector:@selector(ignore:)
|
||||
[[self class] performSelector:@selector(ignore:)
|
||||
onThread:cfstreamThread
|
||||
withObject:[NSNull null]
|
||||
waitUntilDone:NO];
|
||||
@ -8064,9 +8181,18 @@ static void CFWriteStreamCallback (CFWriteStreamRef stream, CFStreamEventType ty
|
||||
}
|
||||
else if (res->ai_family == AF_INET6)
|
||||
{
|
||||
// Fixes connection issues with IPv6
|
||||
// https://github.com/robbiehanson/CocoaAsyncSocket/issues/429#issuecomment-222477158
|
||||
|
||||
// Found IPv6 address.
|
||||
// Wrap the native address structure, and add to results.
|
||||
|
||||
struct sockaddr_in6 *sockaddr = (struct sockaddr_in6 *)res->ai_addr;
|
||||
in_port_t *portPtr = &sockaddr->sin6_port;
|
||||
if ((portPtr != NULL) && (*portPtr == 0)) {
|
||||
*portPtr = htons(port);
|
||||
}
|
||||
|
||||
NSData *address6 = [NSData dataWithBytes:res->ai_addr length:res->ai_addrlen];
|
||||
[addresses addObject:address6];
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user