Index: src/OFDNSResolver.h ================================================================== --- src/OFDNSResolver.h +++ src/OFDNSResolver.h @@ -385,12 +385,23 @@ runLoopMode: (of_run_loop_mode_t)runLoopMode target: (id)target selector: (SEL)selector context: (nullable id)context; +/*! + * @brief Synchronously resolves the specified host to socket addresses. + * + * @param host The host to resolve + * @param addressFamily The desired socket address family + * @return OFData containing several of_socket_address_t + */ +- (OFData *)resolveSocketAddressesForHost: (OFString *)host + addressFamily: (of_socket_address_family_t) + addressFamily; + /*! * @brief Closes all sockets and cancels all ongoing requests. */ - (void)close; @end OF_ASSUME_NONNULL_END Index: src/OFDNSResolver.m ================================================================== --- src/OFDNSResolver.m +++ src/OFDNSResolver.m @@ -111,10 +111,12 @@ * TODO: * * - Fallback to TCP */ +static of_run_loop_mode_t resolveRunLoopMode = @"of_dns_resolver_resolve_mode"; + @interface OFDNSResolverSettings: OFObject { @public OFArray OF_GENERIC(OFString *) *_nameServers, *_searchDomains; of_time_interval_t _timeout; @@ -158,11 +160,11 @@ target: (id)target selector: (SEL)selector context: (id)context; @end -@interface OFDNSResolver_ResolveSocketAddressContext: OFObject +@interface OFDNSResolver_AsyncResolveSocketAddressesContext: OFObject { OFString *_host; id _target; SEL _selector; id _context; @@ -203,10 +205,25 @@ authorityRecords: (OFDictionary *)authorityRecords additionalRecords: (OFDictionary *)additionalRecords context: (id)context exception: (id)exception; @end + +@interface OFDNSResolver_ResolveSocketAddressesContext: OFObject +{ +@public + bool _done; + OFData *_socketAddresses; + id _exception; +} + +- (void)resolver: (OFDNSResolver *)resolver + didResolveDomainName: (OFString *)domainName + socketAddresses: (OFData *)socketAddresses + context: (id)context + exception: (id)exception; +@end @interface OFDNSResolver () - (void)of_setDefaults; - (void)of_obtainSystemConfig; #if defined(OF_HAVE_FILES) && !defined(OF_NINTENDO_3DS) @@ -821,11 +838,11 @@ [super dealloc]; } @end -@implementation OFDNSResolver_ResolveSocketAddressContext +@implementation OFDNSResolver_AsyncResolveSocketAddressesContext - (instancetype)initWithHost: (OFString *)host target: (id)target selector: (SEL)selector context: (id)context { @@ -1107,10 +1124,31 @@ if (_expectedResponses == 0) [self done]; } @end + +@implementation OFDNSResolver_ResolveSocketAddressesContext +- (void)dealloc +{ + [_socketAddresses release]; + [_exception release]; + + [super dealloc]; +} + +- (void)resolver: (OFDNSResolver *)resolver + didResolveDomainName: (OFString *)domainName + socketAddresses: (OFData *)socketAddresses + context: (id)context + exception: (id)exception +{ + _socketAddresses = [socketAddresses retain]; + _exception = [exception retain]; + _done = true; +} +@end @implementation OFDNSResolver @synthesize staticHosts = _staticHosts, nameServers = _nameServers; @synthesize localDomain = _localDomain, searchDomains = _searchDomains; @synthesize timeout = _timeout, maxAttempts = _maxAttempts; @@ -2032,13 +2070,13 @@ target: (id)target selector: (SEL)selector context: (id)userContext { void *pool = objc_autoreleasePoolPush(); - OFDNSResolver_ResolveSocketAddressContext *context; + OFDNSResolver_AsyncResolveSocketAddressesContext *context; - context = [[[OFDNSResolver_ResolveSocketAddressContext alloc] + context = [[[OFDNSResolver_AsyncResolveSocketAddressesContext alloc] initWithHost: host target: target selector: selector context: userContext] autorelease]; @@ -2090,10 +2128,50 @@ context: [OFNumber numberWithInt: OF_DNS_RESOURCE_RECORD_TYPE_A]]; objc_autoreleasePoolPop(pool); } + +- (OFData *)resolveSocketAddressesForHost: (OFString *)host + addressFamily: (of_socket_address_family_t) + addressFamily +{ + void *pool = objc_autoreleasePoolPush(); + OFRunLoop *runLoop = [OFRunLoop currentRunLoop]; + OFDNSResolver_ResolveSocketAddressesContext *context; + OFData *ret; + + context = [[[OFDNSResolver_ResolveSocketAddressesContext + alloc] init] autorelease]; + + [self asyncResolveSocketAddressesForHost: host + addressFamily: addressFamily + runLoopMode: resolveRunLoopMode + target: context + selector: @selector(resolver: + didResolveDomainName: + socketAddresses:context: + exception:) + context: nil]; + + while (!context->_done) + [runLoop runMode: resolveRunLoopMode + beforeDate: nil]; + + /* Cleanup */ + [runLoop runMode: resolveRunLoopMode + beforeDate: [OFDate date]]; + + if (context->_exception != nil) + @throw context->_exception; + + ret = [context->_socketAddresses retain]; + + objc_autoreleasePoolPop(pool); + + return [ret autorelease]; +} - (void)close { void *pool = objc_autoreleasePoolPush(); OFEnumerator OF_GENERIC(OFDNSResolverQuery *) *enumerator; Index: src/OFTCPSocket.m ================================================================== --- src/OFTCPSocket.m +++ src/OFTCPSocket.m @@ -146,11 +146,11 @@ @end @interface OFTCPSocket_ConnectContext: OFObject { @public - bool _connected; + bool _done; id _exception; } - (void)socketDidConnect: (OFTCPSocket *)sock context: (id)context @@ -655,14 +655,12 @@ - (void)socketDidConnect: (OFTCPSocket *)sock context: (id)context exception: (id)exception { - if (exception != nil) - _exception = [exception retain]; - - _connected = true; + _exception = [exception retain]; + _done = true; } @end @implementation OFTCPSocket @synthesize SOCKS5Host = _SOCKS5Host, SOCKS5Port = _SOCKS5Port; @@ -781,11 +779,11 @@ runLoopMode: connectRunLoopMode target: context selector: @selector(socketDidConnect:context:exception:) context: nil]; - while (!context->_connected) + while (!context->_done) [runLoop runMode: connectRunLoopMode beforeDate: nil]; /* Cleanup */ [runLoop runMode: connectRunLoopMode