@@ -30,11 +30,11 @@ # include #endif #import "OFTCPSocket.h" #import "OFTCPSocket+Private.h" -#import "OFTCPSocket+SOCKS5.h" +#import "OFDate.h" #import "OFDNSResolver.h" #import "OFData.h" #import "OFRunLoop.h" #import "OFRunLoop+Private.h" #import "OFString.h" @@ -57,23 +57,17 @@ #import "socket.h" #import "socket_helpers.h" #import "resolver.h" -/* References for static linking */ -void -_references_to_categories_of_OFTCPSocket(void) -{ - _OFTCPSocket_SOCKS5_reference = 1; -} - Class of_tls_socket_class = Nil; +static of_run_loop_mode_t connectRunLoopMode = @"of_tcp_socket_connect_mode"; static OFString *defaultSOCKS5Host = nil; static uint16_t defaultSOCKS5Port = 1080; -@interface OFTCPSocket_ConnectContext: OFObject +@interface OFTCPSocket_AsyncConnectContext: OFObject { OFTCPSocket *_socket; OFString *_host; uint16_t _port; OFString *_SOCKS5Host; @@ -149,11 +143,23 @@ length: (size_t)length context: (id)context exception: (id)exception; @end -@implementation OFTCPSocket_ConnectContext +@interface OFTCPSocket_ConnectContext: OFObject +{ +@public + bool _connected; + id _exception; +} + +- (void)socketDidConnect: (OFTCPSocket *)sock + context: (id)context + exception: (id)exception; +@end + +@implementation OFTCPSocket_AsyncConnectContext - (instancetype)initWithSocket: (OFTCPSocket *)sock host: (OFString *)host port: (uint16_t)port SOCKS5Host: (OFString *)SOCKS5Host SOCKS5Port: (uint16_t)SOCKS5Port @@ -633,10 +639,29 @@ length:context:exception:) context: nil]; return false; } @end + +@implementation OFTCPSocket_ConnectContext +- (void)dealloc +{ + [_exception release]; + + [super dealloc]; +} + +- (void)socketDidConnect: (OFTCPSocket *)sock + context: (id)context + exception: (id)exception +{ + if (exception != nil) + _exception = [exception retain]; + + _connected = true; +} +@end @implementation OFTCPSocket @synthesize SOCKS5Host = _SOCKS5Host, SOCKS5Port = _SOCKS5Port; + (void)setSOCKS5Host: (OFString *)host @@ -741,79 +766,34 @@ } - (void)connectToHost: (OFString *)host port: (uint16_t)port { - OFString *destinationHost = host; - uint16_t destinationPort = port; - of_resolver_result_t **results, **iter; - int errNo = 0; - - if (_socket != INVALID_SOCKET) - @throw [OFAlreadyConnectedException exceptionWithSocket: self]; - - if (_SOCKS5Host != nil) { - /* Connect to the SOCKS5 proxy instead */ - host = _SOCKS5Host; - port = _SOCKS5Port; - } - - results = of_resolve_host(host, port, SOCK_STREAM); - - for (iter = results; *iter != NULL; iter++) { - of_resolver_result_t *result = *iter; - of_socket_address_t address; - - switch (result->family) { - case AF_INET: - address.family = OF_SOCKET_ADDRESS_FAMILY_IPV4; - break; -#ifdef AF_INET6 - case AF_INET6: - address.family = OF_SOCKET_ADDRESS_FAMILY_IPV6; - break; -#endif - default: - errNo = EAFNOSUPPORT; - continue; - } - - if (result->addressLength > sizeof(address)) { - errNo = EOVERFLOW; - continue; - } - - address.length = result->addressLength; - memcpy(&address.sockaddr.sockaddr, result->address, - result->addressLength); - - if (![self of_createSocketForAddress: &address - errNo: &errNo]) - continue; - - _blocking = true; - - if (![self of_connectSocketToAddress: &address - errNo: &errNo]) { - [self of_closeSocket]; - continue; - } - - break; - } - - of_resolver_free(results); - - if (_socket == INVALID_SOCKET) - @throw [OFConnectionFailedException exceptionWithHost: host - port: port - socket: self - errNo: errNo]; - - if (_SOCKS5Host != nil) - [self OF_SOCKS5ConnectToHost: destinationHost - port: destinationPort]; + void *pool = objc_autoreleasePoolPush(); + OFTCPSocket_ConnectContext *context = + [[[OFTCPSocket_ConnectContext alloc] init] autorelease]; + OFRunLoop *runLoop = [OFRunLoop currentRunLoop]; + + [self asyncConnectToHost: host + port: port + runLoopMode: connectRunLoopMode + target: context + selector: @selector(socketDidConnect:context:exception:) + context: nil]; + + while (!context->_connected) + [runLoop runMode: connectRunLoopMode + beforeDate: nil]; + + /* Cleanup */ + [runLoop runMode: connectRunLoopMode + beforeDate: [OFDate date]]; + + if (context->_exception != nil) + @throw context->_exception; + + objc_autoreleasePoolPop(pool); } - (void)asyncConnectToHost: (OFString *)host port: (uint16_t)port target: (id)target @@ -835,11 +815,11 @@ selector: (SEL)selector context: (id)context { void *pool = objc_autoreleasePoolPush(); - [[[[OFTCPSocket_ConnectContext alloc] + [[[[OFTCPSocket_AsyncConnectContext alloc] initWithSocket: self host: host port: port SOCKS5Host: _SOCKS5Host SOCKS5Port: _SOCKS5Port @@ -867,11 +847,11 @@ runLoopMode: (of_run_loop_mode_t)runLoopMode block: (of_tcp_socket_async_connect_block_t)block { void *pool = objc_autoreleasePoolPush(); - [[[[OFTCPSocket_ConnectContext alloc] + [[[[OFTCPSocket_AsyncConnectContext alloc] initWithSocket: self host: host port: port SOCKS5Host: _SOCKS5Host SOCKS5Port: _SOCKS5Port