@@ -22,10 +22,12 @@ #include "unistd_wrapper.h" #import "OFDNSResolver.h" #import "OFArray.h" #import "OFCharacterSet.h" +#import "OFDNSRequest.h" +#import "OFDNSResponse.h" #import "OFData.h" #import "OFDate.h" #import "OFDictionary.h" #import "OFFile.h" #import "OFLocale.h" @@ -37,18 +39,18 @@ #import "OFUDPSocket+Private.h" #ifdef OF_WINDOWS # import "OFWindowsRegistryKey.h" #endif +#import "OFDNSRequestFailedException.h" #import "OFInitializationFailedException.h" #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" #import "OFInvalidServerReplyException.h" #import "OFOpenItemFailedException.h" #import "OFOutOfMemoryException.h" #import "OFOutOfRangeException.h" -#import "OFResolveHostFailedException.h" #import "OFTruncatedDataException.h" #ifdef OF_WINDOWS # define interface struct # include @@ -119,13 +121,12 @@ @end @interface OFDNSResolverQuery: OFObject { @public - OFString *_host, *_domainName; - of_dns_resource_record_class_t _recordClass; - of_dns_resource_record_type_t _recordType; + OFDNSRequest *_request; + OFString *_domainName; OFNumber *_ID; OFDNSResolverSettings *_settings; size_t _nameServersIndex, _searchDomainsIndex; unsigned int _attempt; id _target; @@ -134,21 +135,19 @@ OFData *_queryData; of_socket_address_t _usedNameServer; OFTimer *_cancelTimer; } -- (instancetype)initWithHost: (OFString *)host - domainName: (OFString *)domainName - recordClass: (of_dns_resource_record_class_t)recordClass - recordType: (of_dns_resource_record_type_t)recordType - ID: (OFNumber *)ID - settings: (OFDNSResolverSettings *)settings - nameServersIndex: (size_t)nameServersIndex - searchDomainsIndex: (size_t)searchDomainsIndex - target: (id)target - selector: (SEL)selector - context: (id)context; +- (instancetype)initWithRequest: (OFDNSRequest *)request + domainName: (OFString *)domainName + ID: (OFNumber *)ID + settings: (OFDNSResolverSettings *)settings + nameServersIndex: (size_t)nameServersIndex + searchDomainsIndex: (size_t)searchDomainsIndex + target: (id)target + selector: (SEL)selector + context: (id)context; @end @interface OFDNSResolverAsyncResolveSocketAddressesContext: OFObject { OFString *_host; @@ -213,27 +212,23 @@ #endif #ifdef OF_NINTENDO_3DS - (void)of_obtainNintendo3DSSytemConfig; #endif - (void)of_reloadSystemConfig; -- (void)of_resolveHost: (OFString *)host - recordClass: (of_dns_resource_record_class_t)recordClass - recordType: (of_dns_resource_record_type_t)recordType - settings: (OFDNSResolverSettings *)settings - nameServersIndex: (size_t)nameServersIndex - searchDomainsIndex: (size_t)searchDomainsIndex - runLoopMode: (of_run_loop_mode_t)runLoopMode - target: (id)target - selector: (SEL)selector - context: (id)context; -- (void)of_asyncResolveHost: (OFString *)host - recordClass: (of_dns_resource_record_class_t)recordClass - recordType: (of_dns_resource_record_type_t)recordType - runLoopMode: (of_run_loop_mode_t)runLoopMode - target: (id)target - selector: (SEL)selector - context: (id)context; +- (void)of_asyncPerformRequest: (OFDNSRequest *)request + settings: (OFDNSResolverSettings *)settings + nameServersIndex: (size_t)nameServersIndex + searchDomainsIndex: (size_t)searchDomainsIndex + runLoopMode: (of_run_loop_mode_t)runLoopMode + target: (id)target + selector: (SEL)selector + context: (id)context; +- (void)of_asyncPerformRequest: (OFDNSRequest *)request + runLoopMode: (of_run_loop_mode_t)runLoopMode + target: (id)target + selector: (SEL)selector + context: (id)context; - (void)of_sendQuery: (OFDNSResolverQuery *)query runLoopMode: (of_run_loop_mode_t)runLoopMode; - (void)of_queryWithIDTimedOut: (OFDNSResolverQuery *)query; @end @@ -696,33 +691,29 @@ [super dealloc]; } @end @implementation OFDNSResolverQuery -- (instancetype)initWithHost: (OFString *)host - domainName: (OFString *)domainName - recordClass: (of_dns_resource_record_class_t)recordClass - recordType: (of_dns_resource_record_type_t)recordType - ID: (OFNumber *)ID - settings: (OFDNSResolverSettings *)settings - nameServersIndex: (size_t)nameServersIndex - searchDomainsIndex: (size_t)searchDomainsIndex - target: (id)target - selector: (SEL)selector - context: (id)context +- (instancetype)initWithRequest: (OFDNSRequest *)request + domainName: (OFString *)domainName + ID: (OFNumber *)ID + settings: (OFDNSResolverSettings *)settings + nameServersIndex: (size_t)nameServersIndex + searchDomainsIndex: (size_t)searchDomainsIndex + target: (id)target + selector: (SEL)selector + context: (id)context { self = [super init]; @try { void *pool = objc_autoreleasePoolPush(); OFMutableData *queryData; uint16_t tmp; - _host = [host copy]; + _request = [request copy]; _domainName = [domainName copy]; - _recordClass = recordClass; - _recordType = recordType; _ID = [ID retain]; _settings = [settings retain]; _nameServersIndex = nameServersIndex; _searchDomainsIndex = searchDomainsIndex; _target = [target retain]; @@ -731,11 +722,11 @@ queryData = [OFMutableData dataWithCapacity: 512]; /* Header */ - tmp = OF_BSWAP16_IF_LE(ID.uInt16Value); + tmp = OF_BSWAP16_IF_LE(_ID.uInt16Value); [queryData addItems: &tmp count: 2]; /* RD */ tmp = OF_BSWAP16_IF_LE(1u << 8); @@ -752,11 +743,11 @@ /* Question */ /* QNAME */ for (OFString *component in - [domainName componentsSeparatedByString: @"."]) { + [_domainName componentsSeparatedByString: @"."]) { size_t length = component.UTF8StringLength; uint8_t length8; if (length > 63 || queryData.count + length > 512) @throw [OFOutOfRangeException exception]; @@ -766,18 +757,18 @@ [queryData addItems: component.UTF8String count: length]; } /* QTYPE */ - tmp = OF_BSWAP16_IF_LE(recordType); + tmp = OF_BSWAP16_IF_LE(_request.recordType); [queryData addItems: &tmp count: 2]; /* QCLASS */ - tmp = OF_BSWAP16_IF_LE(recordClass); + tmp = OF_BSWAP16_IF_LE(_request.recordClass); [queryData addItems: &tmp - count: 2]; + count: 2]; [queryData makeImmutable]; _queryData = [queryData copy]; @@ -790,11 +781,11 @@ return self; } - (void)dealloc { - [_host release]; + [_request release]; [_domainName release]; [_ID release]; [_settings release]; [_target release]; [_context release]; @@ -893,26 +884,29 @@ if (!found) { of_run_loop_mode_t runLoopMode = [OFRunLoop currentRunLoop].currentMode; OFNumber *recordTypeNumber = [OFNumber numberWithInt: recordType]; + OFDNSRequest *request; _expectedResponses++; [result addObject: [OFPair pairWithFirstObject: CNAME secondObject: recordTypeNumber]]; - [_resolver of_asyncResolveHost: alias - recordClass: OF_DNS_RESOURCE_RECORD_CLASS_IN - recordType: recordType - runLoopMode: runLoopMode - target: self - selector: @selector(resolver: - didResolveCNAME:response: - context:exception:) - context: recordTypeNumber]; + request = [OFDNSRequest + requestWithHost: alias + recordClass: OF_DNS_RESOURCE_RECORD_CLASS_IN + recordType: recordType]; + [_resolver of_asyncPerformRequest: request + runLoopMode: runLoopMode + target: self + selector: @selector(resolver: + didResolveCNAME:response: + context:exception:) + context: recordTypeNumber]; } } - (void)resolver: (OFDNSResolver *)resolver didResolveCNAME: (OFString *)CNAME @@ -1007,16 +1001,20 @@ } } [addresses makeImmutable]; - if (addresses.count == 0) - exception = [OFResolveHostFailedException - exceptionWithHost: _host - recordClass: OF_DNS_RESOURCE_RECORD_CLASS_IN - recordType: 0 - error: OF_DNS_RESOLVER_ERROR_UNKNOWN]; + if (addresses.count == 0) { + OFDNSRequest *request = [OFDNSRequest + requestWithHost: _host + recordClass: OF_DNS_RESOURCE_RECORD_CLASS_IN + recordType: 0]; + + exception = [OFDNSRequestFailedException + exceptionWithRequest: request + error: OF_DNS_RESOLVER_ERROR_UNKNOWN]; + } if ([_delegate respondsToSelector: @selector( resolver:didResolveDomainName:socketAddresses:exception:)]) [_delegate resolver: _resolver didResolveDomainName: _domainName @@ -1567,33 +1565,32 @@ _lastConfigReload = nil; [self of_obtainSystemConfig]; } -- (void)of_resolveHost: (OFString *)host - recordClass: (of_dns_resource_record_class_t)recordClass - recordType: (of_dns_resource_record_type_t)recordType - settings: (OFDNSResolverSettings *)settings - nameServersIndex: (size_t)nameServersIndex - searchDomainsIndex: (size_t)searchDomainsIndex - runLoopMode: (of_run_loop_mode_t)runLoopMode - target: (id)target - selector: (SEL)selector - context: (id)context +- (void)of_asyncPerformRequest: (OFDNSRequest *)request + settings: (OFDNSResolverSettings *)settings + nameServersIndex: (size_t)nameServersIndex + searchDomainsIndex: (size_t)searchDomainsIndex + runLoopMode: (of_run_loop_mode_t)runLoopMode + target: (id)target + selector: (SEL)selector + context: (id)context { void *pool = objc_autoreleasePoolPush(); OFNumber *ID; - OFString *domainName; + OFString *host, *domainName; OFDNSResolverQuery *query; [self of_reloadSystemConfig]; /* Random, unused ID */ do { ID = [OFNumber numberWithUInt16: (uint16_t)of_random()]; } while ([_queries objectForKey: ID] != nil); + host = request.host; if (isFQDN(host, settings)) { domainName = host; if (![domainName hasSuffix: @"."]) domainName = [domainName stringByAppendingString: @"."]; @@ -1607,21 +1604,19 @@ if (domainName.UTF8StringLength > 253) @throw [OFOutOfRangeException exception]; query = [[[OFDNSResolverQuery alloc] - initWithHost: host - domainName: domainName - recordClass: recordClass - recordType: recordType - ID: ID - settings: settings - nameServersIndex: nameServersIndex - searchDomainsIndex: searchDomainsIndex - target: target - selector: selector - context: context] autorelease]; + initWithRequest: request + domainName: domainName + ID: ID + settings: settings + nameServersIndex: nameServersIndex + searchDomainsIndex: searchDomainsIndex + target: target + selector: selector + context: context] autorelease]; [_queries setObject: query forKey: ID]; [self of_sendQuery: query runLoopMode: runLoopMode]; @@ -1641,61 +1636,40 @@ didResolveDomainName: domainName response: response exception: exception]; } -- (void)asyncResolveHost: (OFString *)host - delegate: (id )delegate -{ - [self of_asyncResolveHost: host - recordClass: OF_DNS_RESOURCE_RECORD_CLASS_IN - recordType: OF_DNS_RESOURCE_RECORD_TYPE_ALL - runLoopMode: of_run_loop_mode_default - target: self - selector: @selector(of_resolver:didResolveDomainName: - response:context:exception:) - context: delegate]; -} - -- (void)asyncResolveHost: (OFString *)host - recordClass: (of_dns_resource_record_class_t)recordClass - recordType: (of_dns_resource_record_type_t)recordType - delegate: (id )delegate -{ - [self of_asyncResolveHost: host - recordClass: recordClass - recordType: recordType - runLoopMode: of_run_loop_mode_default - target: self - selector: @selector(of_resolver:didResolveDomainName: - response:context:exception:) - context: delegate]; -} - -- (void)asyncResolveHost: (OFString *)host - recordClass: (of_dns_resource_record_class_t)recordClass - recordType: (of_dns_resource_record_type_t)recordType - runLoopMode: (of_run_loop_mode_t)runLoopMode - delegate: (id )delegate -{ - [self of_asyncResolveHost: host - recordClass: recordClass - recordType: recordType - runLoopMode: runLoopMode - target: self - selector: @selector(of_resolver:didResolveDomainName: - response:context:exception:) - context: delegate]; -} - -- (void)of_asyncResolveHost: (OFString *)host - recordClass: (of_dns_resource_record_class_t)recordClass - recordType: (of_dns_resource_record_type_t)recordType - runLoopMode: (of_run_loop_mode_t)runLoopMode - target: (id)target - selector: (SEL)selector - context: (id)context +- (void)asyncPerformRequest: (OFDNSRequest *)request + delegate: (id )delegate +{ + [self of_asyncPerformRequest: request + runLoopMode: of_run_loop_mode_default + target: self + selector: @selector(of_resolver: + didResolveDomainName:response:context: + exception:) + context: delegate]; +} + +- (void)asyncPerformRequest: (OFDNSRequest *)request + runLoopMode: (of_run_loop_mode_t)runLoopMode + delegate: (id )delegate +{ + [self of_asyncPerformRequest: request + runLoopMode: runLoopMode + target: self + selector: @selector(of_resolver: + didResolveDomainName:response:context: + exception:) + context: delegate]; +} + +- (void)of_asyncPerformRequest: (OFDNSRequest *)request + runLoopMode: (of_run_loop_mode_t)runLoopMode + target: (id)target + selector: (SEL)selector + context: (id)context { void *pool = objc_autoreleasePoolPush(); OFDNSResolverSettings *settings = [[[OFDNSResolverSettings alloc] initWithNameServers: _nameServers searchDomains: _searchDomains @@ -1702,20 +1676,18 @@ timeout: _timeout maxAttempts: _maxAttempts minNumberOfDotsInAbsoluteName: _minNumberOfDotsInAbsoluteName] autorelease]; - [self of_resolveHost: host - recordClass: recordClass - recordType: recordType - settings: settings - nameServersIndex: 0 - searchDomainsIndex: 0 - runLoopMode: runLoopMode - target: target - selector: selector - context: context]; + [self of_asyncPerformRequest: request + settings: settings + nameServersIndex: 0 + searchDomainsIndex: 0 + runLoopMode: runLoopMode + target: target + selector: selector + context: context]; objc_autoreleasePoolPop(pool); } - (void)of_sendQuery: (OFDNSResolverQuery *)query @@ -1786,11 +1758,11 @@ runLoopMode: runLoopMode]; } - (void)of_queryWithIDTimedOut: (OFDNSResolverQuery *)query { - OFResolveHostFailedException *exception; + OFDNSRequestFailedException *exception; if (query == nil) return; if (query->_nameServersIndex + 1 < @@ -1823,15 +1795,13 @@ [_IPv6Socket cancelAsyncRequests]; [_IPv6Socket asyncReceiveIntoBuffer: _buffer length: BUFFER_LENGTH]; #endif - exception = [OFResolveHostFailedException - exceptionWithHost: query->_host - recordClass: query->_recordClass - recordType: query->_recordType - error: OF_DNS_RESOLVER_ERROR_TIMEOUT]; + exception = [OFDNSRequestFailedException + exceptionWithRequest: query->_request + error: OF_DNS_RESOLVER_ERROR_TIMEOUT]; callback(query->_target, query->_selector, self, query->_domainName, nil, query->_context, exception); } @@ -1910,23 +1880,25 @@ case 3: if (query->_searchDomainsIndex + 1 < query->_settings->_searchDomains.count) { of_run_loop_mode_t runLoopMode = [OFRunLoop currentRunLoop].currentMode; + size_t nameServersIndex = + query->_nameServersIndex; + size_t searchDomainsIndex = + query->_searchDomainsIndex; query->_searchDomainsIndex++; - [self of_resolveHost: query->_host - recordClass: query->_recordClass - recordType: query->_recordType - settings: query->_settings - nameServersIndex: query->_nameServersIndex - searchDomainsIndex: query->_searchDomainsIndex - runLoopMode: runLoopMode - target: query->_target - selector: query->_selector - context: query->_context]; + [self of_asyncPerformRequest: query->_request + settings: query->_settings + nameServersIndex: nameServersIndex + searchDomainsIndex: searchDomainsIndex + runLoopMode: runLoopMode + target: query->_target + selector: query->_selector + context: query->_context]; return true; } error = OF_DNS_RESOLVER_ERROR_SERVER_NAME_ERROR; @@ -1941,15 +1913,13 @@ error = OF_DNS_RESOLVER_ERROR_UNKNOWN; break; } if (buffer[3] & 0x0F) - @throw [OFResolveHostFailedException - exceptionWithHost: query->_host - recordClass: query->_recordClass - recordType: query->_recordType - error: error]; + @throw [OFDNSRequestFailedException + exceptionWithRequest: query->_request + error: error]; numQuestions = (buffer[4] << 8) | buffer[5]; numAnswers = (buffer[6] << 8) | buffer[7]; numAuthorityRecords = (buffer[8] << 8) | buffer[9]; numAdditionalRecords = (buffer[10] << 8) | buffer[11]; @@ -2101,16 +2071,18 @@ if (exception == nil) { of_dns_resource_record_class_t recordClass = OF_DNS_RESOURCE_RECORD_CLASS_IN; of_dns_resolver_error_t error = OF_DNS_RESOLVER_ERROR_NO_RESULT; + OFDNSRequest *request = [OFDNSRequest + requestWithHost: host + recordClass: recordClass + recordType: recordType]; - exception = [OFResolveHostFailedException - exceptionWithHost: host - recordClass: recordClass - recordType: recordType - error: error]; + exception = [OFDNSRequestFailedException + exceptionWithRequest: request + error: error]; } } if ([delegate respondsToSelector: @selector(resolver: didResolveDomainName:socketAddresses:exception:)]) { @@ -2158,37 +2130,44 @@ } #ifdef OF_HAVE_IPV6 if (addressFamily == OF_SOCKET_ADDRESS_FAMILY_IPV6 || addressFamily == OF_SOCKET_ADDRESS_FAMILY_ANY) { + OFDNSRequest *request = [OFDNSRequest + requestWithHost: host + recordClass: OF_DNS_RESOURCE_RECORD_CLASS_IN + recordType: OF_DNS_RESOURCE_RECORD_TYPE_AAAA]; OFNumber *recordTypeNumber = [OFNumber numberWithInt: OF_DNS_RESOURCE_RECORD_TYPE_AAAA]; - [self of_asyncResolveHost: host - recordClass: OF_DNS_RESOURCE_RECORD_CLASS_IN - recordType: OF_DNS_RESOURCE_RECORD_TYPE_AAAA - runLoopMode: runLoopMode - target: context - selector: @selector(resolver: - didResolveDomainName: - response:context:exception:) - context: recordTypeNumber]; + [self of_asyncPerformRequest: request + runLoopMode: runLoopMode + target: context + selector: @selector(resolver: + didResolveDomainName:response: + context:exception:) + context: recordTypeNumber]; } #endif if (addressFamily == OF_SOCKET_ADDRESS_FAMILY_IPV4 || - addressFamily == OF_SOCKET_ADDRESS_FAMILY_ANY) - [self of_asyncResolveHost: host - recordClass: OF_DNS_RESOURCE_RECORD_CLASS_IN - recordType: OF_DNS_RESOURCE_RECORD_TYPE_A - runLoopMode: runLoopMode - target: context - selector: @selector(resolver: - didResolveDomainName: - response:context:exception:) - context: [OFNumber numberWithInt: - OF_DNS_RESOURCE_RECORD_TYPE_A]]; + addressFamily == OF_SOCKET_ADDRESS_FAMILY_ANY) { + OFDNSRequest *request = [OFDNSRequest + requestWithHost: host + recordClass: OF_DNS_RESOURCE_RECORD_CLASS_IN + recordType: OF_DNS_RESOURCE_RECORD_TYPE_A]; + OFNumber *recordTypeNumber = + [OFNumber numberWithInt: OF_DNS_RESOURCE_RECORD_TYPE_A]; + + [self of_asyncPerformRequest: request + runLoopMode: runLoopMode + target: context + selector: @selector(resolver: + didResolveDomainName:response: + context:exception:) + context: recordTypeNumber]; + } objc_autoreleasePoolPop(pool); } - (OFData *)resolveSocketAddressesForHost: (OFString *)host @@ -2242,17 +2221,15 @@ _IPv6Socket = nil; #endif enumerator = [_queries objectEnumerator]; while ((query = [enumerator nextObject]) != nil) { - OFResolveHostFailedException *exception; + OFDNSRequestFailedException *exception; - exception = [OFResolveHostFailedException - exceptionWithHost: query->_host - recordClass: query->_recordClass - recordType: query->_recordType - error: OF_DNS_RESOLVER_ERROR_CANCELED]; + exception = [OFDNSRequestFailedException + exceptionWithRequest: query->_request + error: OF_DNS_RESOLVER_ERROR_CANCELED]; callback(query->_target, query->_selector, self, query->_domainName, nil, query->_context, exception); }