Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -214,10 +214,11 @@ ${LIBBASES_M} SRCS_FILES += OFFileURLHandler.m \ OFINIFileSettings.m SRCS_SOCKETS += OFDNSResolverSettings.m \ OFHTTPURLHandler.m \ + OFHostAddressResolver.m \ OFKernelEventObserver.m \ ${OFEPOLLKERNELEVENTOBSERVER_M} \ ${OFKQUEUEKERNELEVENTOBSERVER_M} \ ${OFPOLLKERNELEVENTOBSERVER_M} \ ${OFSELECTKERNELEVENTOBSERVER_M} Index: src/OFDNSQuery.h ================================================================== --- src/OFDNSQuery.h +++ src/OFDNSQuery.h @@ -18,79 +18,64 @@ #import "OFObject.h" #import "OFDNSResourceRecord.h" OF_ASSUME_NONNULL_BEGIN +@class OFString; + /*! * @class OFDNSQuery OFDNSQuery.h ObjFW/OFDNSQuery.h * * @brief A class representing a DNS query. */ @interface OFDNSQuery: OFObject { - OFString *_host; - of_dns_resource_record_class_t _recordClass; + OFString *_domainName; + of_dns_class_t _DNSClass; of_dns_resource_record_type_t _recordType; OF_RESERVE_IVARS(4) } /*! - * @brief The host to resolve. + * @brief The domain name of the query. */ -@property (readonly, nonatomic) OFString *host; +@property (readonly, nonatomic) OFString *domainName; /*! - * @brief The record class of the query. + * @brief The DNS class of the query. */ -@property (readonly, nonatomic) of_dns_resource_record_class_t recordClass; +@property (readonly, nonatomic) of_dns_class_t DNSClass; /*! * @brief The record type of the query. */ @property (readonly, nonatomic) of_dns_resource_record_type_t recordType; -/*! - * @brief Creates a new, autoreleased OFDNSQuery with IN class and type ALL. - * - * @param host The host to resolve - * @return A new, autoreleased OFDNSQuery - */ -+ (instancetype)queryWithHost: (OFString *)host; - /*! * @brief Creates a new, autoreleased OFDNSQuery. * - * @param host The host to resolve - * @param recordClass The record class of the query + * @param domainName The domain name to query + * @param DNSClass The DNS class of the query * @param recordType The record type of the query * @return A new, autoreleased OFDNSQuery */ -+ (instancetype)queryWithHost: (OFString *)host - recordClass: (of_dns_resource_record_class_t)recordClass - recordType: (of_dns_resource_record_type_t)recordType; - -/*! - * @brief Initializes an already allocated OFDNSQuery with IN class and type - * ALL. - * - * @param host The host to resolve - * @return An initialized OFDNSQuery - */ -- (instancetype)initWithHost: (OFString *)host; ++ (instancetype)queryWithDomainName: (OFString *)domainName + DNSClass: (of_dns_class_t)DNSClass + recordType: (of_dns_resource_record_type_t)recordType; /*! * @brief Initializes an already allocated OFDNSQuery. * - * @param host The host to resolve - * @param recordClass The record class of the query + * @param domainName The domain name to query + * @param DNSClass The DNS class of the query * @param recordType The record type of the query * @return An initialized OFDNSQuery */ -- (instancetype)initWithHost: (OFString *)host - recordClass: (of_dns_resource_record_class_t)recordClass - recordType: (of_dns_resource_record_type_t)recordType +- (instancetype)initWithDomainName: (OFString *)domainName + DNSClass: (of_dns_class_t)DNSClass + recordType: (of_dns_resource_record_type_t)recordType OF_DESIGNATED_INITIALIZER; - (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/OFDNSQuery.m ================================================================== --- src/OFDNSQuery.m +++ src/OFDNSQuery.m @@ -19,43 +19,39 @@ #import "OFDNSQuery.h" #import "OFString.h" @implementation OFDNSQuery -@synthesize host = _host, recordClass = _recordClass, recordType = _recordType; - -+ (instancetype)queryWithHost: (OFString *)host -{ - return [[[self alloc] initWithHost: host] autorelease]; -} - -+ (instancetype)queryWithHost: (OFString *)host - recordClass: (of_dns_resource_record_class_t)recordClass - recordType: (of_dns_resource_record_type_t)recordType -{ - return [[[self alloc] initWithHost: host - recordClass: recordClass - recordType: recordType] autorelease]; -} - -- (instancetype)initWithHost: (OFString *)host -{ - return [self initWithHost: host - recordClass: OF_DNS_RESOURCE_RECORD_CLASS_IN - recordType: OF_DNS_RESOURCE_RECORD_TYPE_ALL]; -} - -- (instancetype)initWithHost: (OFString *)host - recordClass: (of_dns_resource_record_class_t)recordClass - recordType: (of_dns_resource_record_type_t)recordType +@synthesize domainName = _domainName, DNSClass = _DNSClass; +@synthesize recordType = _recordType; + ++ (instancetype)queryWithDomainName: (OFString *)domainName + DNSClass: (of_dns_class_t)DNSClass + recordType: (of_dns_resource_record_type_t)recordType +{ + return [[[self alloc] initWithDomainName: domainName + DNSClass: DNSClass + recordType: recordType] autorelease]; +} + +- (instancetype)initWithDomainName: (OFString *)domainName + DNSClass: (of_dns_class_t)DNSClass + recordType: (of_dns_resource_record_type_t)recordType { self = [super init]; @try { - _host = [host copy]; - _recordClass = recordClass; + void *pool = objc_autoreleasePoolPush(); + + if (![domainName hasSuffix: @"."]) + domainName = [domainName stringByAppendingString: @"."]; + + _domainName = [domainName copy]; + _DNSClass = DNSClass; _recordType = recordType; + + objc_autoreleasePoolPop(pool); } @catch (id e) { [self release]; @throw e; } @@ -67,11 +63,11 @@ OF_INVALID_INIT_METHOD } - (void)dealloc { - [_host release]; + [_domainName release]; [super dealloc]; } - (bool)isEqual: (id)object @@ -81,13 +77,14 @@ if (![object isKindOfClass: [OFDNSQuery class]]) return false; query = object; - if (query->_host != _host && ![query->_host isEqual: _host]) + if (query->_domainName != _domainName && + ![query->_domainName isEqual: _domainName]) return false; - if (query->_recordClass != _recordClass) + if (query->_DNSClass != _DNSClass) return false; if (query->_recordType != _recordType) return false; return true; @@ -96,12 +93,12 @@ - (uint32_t)hash { uint32_t hash; OF_HASH_INIT(hash); - OF_HASH_ADD_HASH(hash, _host.hash); - OF_HASH_ADD(hash, _recordClass); + OF_HASH_ADD_HASH(hash, _domainName.hash); + OF_HASH_ADD(hash, _DNSClass); OF_HASH_ADD(hash, _recordType); OF_HASH_FINALIZE(hash); return hash; } @@ -112,10 +109,9 @@ } - (OFString *)description { return [OFString stringWithFormat: @"<%@ %@ %@ %@>", - self.className, _host, - of_dns_resource_record_class_to_string(_recordClass), + self.className, _domainName, of_dns_class_to_string(_DNSClass), of_dns_resource_record_type_to_string(_recordType)]; } @end Index: src/OFDNSResolver.h ================================================================== --- src/OFDNSResolver.h +++ src/OFDNSResolver.h @@ -26,11 +26,11 @@ #define OF_DNS_RESOLVER_BUFFER_LENGTH 512 @class OFArray OF_GENERIC(ObjectType); @class OFDNSResolver; -@class OFDNSResolverQuery; +@class OFDNSResolverContext; @class OFDNSResolverSettings; @class OFDate; @class OFDictionary OF_GENERIC(KeyType, ObjectType); @class OFMutableDictionary OF_GENERIC(KeyType, ObjectType); @class OFNumber; @@ -73,37 +73,37 @@ * @brief A delegate for OFDNSResolver. */ @protocol OFDNSResolverDelegate @optional /*! - * @brief This method is called when a DNS resolver resolved a domain name. + * @brief This method is called when a DNS resolver performed a query. * * @param resolver The acting resolver - * @param domainName The fully qualified domain name used to resolve the host + * @param query The query performed by the resolver * @param response The response from the DNS server, or nil on error * @param exception An exception that happened during resolving, or nil on * success */ -- (void)resolver: (OFDNSResolver *)resolver - didResolveDomainName: (OFString *)domainName - response: (nullable OFDNSResponse *)response - exception: (nullable id)exception; +- (void)resolver: (OFDNSResolver *)resolver + didPerformQuery: (OFDNSQuery *)query + response: (nullable OFDNSResponse *)response + exception: (nullable id)exception; /*! - * @brief This method is called when a DNS resolver resolved a domain name to - * socket addresses. + * @brief This method is called when a DNS resolver resolved a host to + * addresses. * * @param resolver The acting resolver - * @param domainName The fully qualified domain name used to resolve the host - * @param socketAddresses OFData containing several of_socket_address_t + * @param host The host the resolver resolved + * @param addresses OFData containing several of_socket_address_t * @param exception The exception that occurred during resolving, or nil on * success */ -- (void)resolver: (OFDNSResolver *)resolver - didResolveDomainName: (OFString *)domainName - socketAddresses: (nullable OFData *)socketAddresses - exception: (nullable id)exception; +- (void)resolver: (OFDNSResolver *)resolver + didResolveHost: (OFString *)host + addresses: (nullable OFData *)addresses + exception: (nullable id)exception; @end /*! * @class OFDNSResolver OFDNSResolver.h ObjFW/OFDNSResolver.h * @@ -121,11 +121,11 @@ OFUDPSocket *_IPv4Socket; #ifdef OF_HAVE_IPV6 OFUDPSocket *_IPv6Socket; #endif char _buffer[OF_DNS_RESOLVER_BUFFER_LENGTH]; - OFMutableDictionary OF_GENERIC(OFNumber *, OFDNSResolverQuery *) + OFMutableDictionary OF_GENERIC(OFNumber *, OFDNSResolverContext *) *_queries; } /*! * @brief A dictionary of static hosts. @@ -216,55 +216,49 @@ * @brief Asynchronously resolves the specified host to socket addresses. * * @param host The host to resolve * @param delegate The delegate to use for callbacks */ -- (void)asyncResolveSocketAddressesForHost: (OFString *)host - delegate: (id ) - delegate; +- (void)asyncResolveAddressesForHost: (OFString *)host + delegate: (id )delegate; /*! * @brief Asynchronously resolves the specified host to socket addresses. * * @param host The host to resolve * @param addressFamily The desired socket address family * @param delegate The delegate to use for callbacks */ -- (void)asyncResolveSocketAddressesForHost: (OFString *)host - addressFamily: (of_socket_address_family_t) - addressFamily - delegate: (id ) - delegate; +- (void)asyncResolveAddressesForHost: (OFString *)host + addressFamily: (of_socket_address_family_t)addressFamily + delegate: (id )delegate; /*! * @brief Asynchronously resolves the specified host to socket addresses. * * @param host The host to resolve * @param addressFamily The desired socket address family * @param runLoopMode The run loop mode in which to resolve * @param delegate The delegate to use for callbacks */ -- (void)asyncResolveSocketAddressesForHost: (OFString *)host - addressFamily: (of_socket_address_family_t) - addressFamily - runLoopMode: (of_run_loop_mode_t)runLoopMode - delegate: (id ) - delegate; +- (void)asyncResolveAddressesForHost: (OFString *)host + addressFamily: (of_socket_address_family_t)addressFamily + runLoopMode: (of_run_loop_mode_t)runLoopMode + delegate: (id )delegate; /*! * @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; +- (OFData *)resolveAddressesForHost: (OFString *)host + addressFamily: (of_socket_address_family_t)addressFamily; /*! * @brief Closes all sockets and cancels all ongoing queries. */ - (void)close; @end OF_ASSUME_NONNULL_END Index: src/OFDNSResolver.m ================================================================== --- src/OFDNSResolver.m +++ src/OFDNSResolver.m @@ -25,10 +25,11 @@ #import "OFDNSResolverSettings.h" #import "OFDNSResponse.h" #import "OFData.h" #import "OFDate.h" #import "OFDictionary.h" +#import "OFHostAddressResolver.h" #import "OFNumber.h" #import "OFPair.h" #import "OFString.h" #import "OFTimer.h" #import "OFUDPSocket.h" @@ -62,117 +63,33 @@ * TODO: * * - Fallback to TCP */ -static const of_run_loop_mode_t resolveRunLoopMode = - @"of_dns_resolver_resolve_mode"; +@interface OFDNSResolver () +- (void)of_contextTimedOut: (OFDNSResolverContext *)context; +@end -@interface OFDNSResolverQuery: OFObject +@interface OFDNSResolverContext: OFObject { @public OFDNSQuery *_query; - OFString *_domainName; OFNumber *_ID; OFDNSResolverSettings *_settings; - size_t _nameServersIndex, _searchDomainsIndex; + size_t _nameServersIndex; unsigned int _attempt; - id _target; - SEL _selector; - id _context; + id _delegate; OFData *_queryData; of_socket_address_t _usedNameServer; OFTimer *_cancelTimer; } - (instancetype)initWithQuery: (OFDNSQuery *)query - 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; - id _delegate; - OFMutableArray OF_GENERIC(OF_KINDOF(OFDNSResourceRecord *)) *_records; - OFDNSResolver *_resolver; - OFString *_domainName; -@public - unsigned int _expectedResponses; -} - -- (instancetype)initWithHost: (OFString *)host - delegate: (id)delegate; -- (bool)parseRecords: (OFArray *)records - response: (OFDNSResponse *)response - recordType: (of_dns_resource_record_type_t)recordType - recursion: (unsigned int)recursion - result: (OFMutableArray *)result; -- (void)resolveCNAME: (OFCNAMEDNSResourceRecord *)CNAME - response: (OFDNSResponse *)response - recordType: (of_dns_resource_record_type_t)recordType - recursion: (unsigned int)recursion - result: (OFMutableArray *)result; -- (void)resolver: (OFDNSResolver *)resolver - didResolveCNAME: (OFString *)CNAME - response: (OFDNSResponse *)response - context: (OFNumber *)context - exception: (id)exception; -- (void)done; -- (void)resolver: (OFDNSResolver *)resolver - didResolveDomainName: (OFString *)domainName - response: (OFDNSResponse *)response - context: (OFNumber *)context - exception: (id)exception; -@end - -@interface OFDNSResolverResolveSocketAddressesDelegate: OFObject - -{ -@public - bool _done; - OFData *_socketAddresses; - id _exception; -} -@end - -@interface OFDNSResolver () -- (void)of_asyncPerformQuery: (OFDNSQuery *)query - 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_sendQuery: (OFDNSResolverQuery *)query - runLoopMode: (of_run_loop_mode_t)runLoopMode; -- (void)of_queryWithIDTimedOut: (OFDNSResolverQuery *)query; -@end - -static bool -isFQDN(OFString *host, OFDNSResolverSettings *settings) -{ - const char *UTF8String = host.UTF8String; - size_t length = host.UTF8StringLength; - unsigned int dots = 0; - - if ([host hasSuffix: @"."]) - return true; - - for (size_t i = 0; i < length; i++) - if (UTF8String[i] == '.') - dots++; - - return (dots >= settings->_minNumberOfDotsInAbsoluteName); -} + delegate: (id )delegate; +@end static OFString * parseString(const unsigned char *buffer, size_t length, size_t *i) { uint8_t stringLength; @@ -250,16 +167,16 @@ return [components componentsJoinedByString: @"."]; } static OF_KINDOF(OFDNSResourceRecord *) -parseResourceRecord(OFString *name, of_dns_resource_record_class_t recordClass, +parseResourceRecord(OFString *name, of_dns_class_t DNSClass, of_dns_resource_record_type_t recordType, uint32_t TTL, const unsigned char *buffer, size_t length, size_t i, uint16_t dataLength) { if (recordType == OF_DNS_RESOURCE_RECORD_TYPE_A && - recordClass == OF_DNS_RESOURCE_RECORD_CLASS_IN) { + DNSClass == OF_DNS_CLASS_IN) { of_socket_address_t address; if (dataLength != 4) @throw [OFInvalidServerReplyException exception]; @@ -282,11 +199,11 @@ if (j != i + dataLength) @throw [OFInvalidServerReplyException exception]; return [[[OFNSDNSResourceRecord alloc] initWithName: name - recordClass: recordClass + DNSClass: DNSClass authoritativeHost: authoritativeHost TTL: TTL] autorelease]; } else if (recordType == OF_DNS_RESOURCE_RECORD_TYPE_CNAME) { size_t j = i; OFString *alias = parseName(buffer, length, &j, @@ -295,11 +212,11 @@ if (j != i + dataLength) @throw [OFInvalidServerReplyException exception]; return [[[OFCNAMEDNSResourceRecord alloc] initWithName: name - recordClass: recordClass + DNSClass: DNSClass alias: alias TTL: TTL] autorelease]; } else if (recordType == OF_DNS_RESOURCE_RECORD_TYPE_SOA) { size_t j = i; OFString *primaryNameServer = parseName(buffer, length, &j, @@ -330,11 +247,11 @@ minTTL = (buffer[j + 16] << 24) | (buffer[j + 17] << 16) | (buffer[j + 18] << 8) | buffer[j + 19]; return [[[OFSOADNSResourceRecord alloc] initWithName: name - recordClass: recordClass + DNSClass: DNSClass primaryNameServer: primaryNameServer responsiblePerson: responsiblePerson serialNumber: serialNumber refreshInterval: refreshInterval retryInterval: retryInterval @@ -349,11 +266,11 @@ if (j != i + dataLength) @throw [OFInvalidServerReplyException exception]; return [[[OFPTRDNSResourceRecord alloc] initWithName: name - recordClass: recordClass + DNSClass: DNSClass domainName: domainName TTL: TTL] autorelease]; } else if (recordType == OF_DNS_RESOURCE_RECORD_TYPE_HINFO) { size_t j = i; OFString *CPU = parseString(buffer, length, &j); @@ -367,11 +284,11 @@ if (j != i + dataLength) @throw [OFInvalidServerReplyException exception]; return [[[OFHINFODNSResourceRecord alloc] initWithName: name - recordClass: recordClass + DNSClass: DNSClass CPU: CPU OS: OS TTL: TTL] autorelease]; } else if (recordType == OF_DNS_RESOURCE_RECORD_TYPE_MX) { uint16_t preference; @@ -390,21 +307,21 @@ if (j != i + dataLength) @throw [OFInvalidServerReplyException exception]; return [[[OFMXDNSResourceRecord alloc] initWithName: name - recordClass: recordClass + DNSClass: DNSClass preference: preference mailExchange: mailExchange TTL: TTL] autorelease]; } else if (recordType == OF_DNS_RESOURCE_RECORD_TYPE_TXT) { OFData *textData = [OFData dataWithItems: &buffer[i] count: dataLength]; return [[[OFTXTDNSResourceRecord alloc] initWithName: name - recordClass: recordClass + DNSClass: DNSClass textData: textData TTL: TTL] autorelease]; } else if (recordType == OF_DNS_RESOURCE_RECORD_TYPE_RP) { size_t j = i; OFString *mailbox = parseName(buffer, length, &j, @@ -420,16 +337,16 @@ if (j != i + dataLength) @throw [OFInvalidServerReplyException exception]; return [[[OFRPDNSResourceRecord alloc] initWithName: name - recordClass: recordClass + DNSClass: DNSClass mailbox: mailbox TXTDomainName: TXTDomainName TTL: TTL] autorelease]; } else if (recordType == OF_DNS_RESOURCE_RECORD_TYPE_AAAA && - recordClass == OF_DNS_RESOURCE_RECORD_CLASS_IN) { + DNSClass == OF_DNS_CLASS_IN) { of_socket_address_t address; if (dataLength != 16) @throw [OFInvalidServerReplyException exception]; @@ -447,11 +364,11 @@ return [[[OFAAAADNSResourceRecord alloc] initWithName: name address: &address TTL: TTL] autorelease]; } else if (recordType == OF_DNS_RESOURCE_RECORD_TYPE_SRV && - recordClass == OF_DNS_RESOURCE_RECORD_CLASS_IN) { + DNSClass == OF_DNS_CLASS_IN) { uint16_t priority, weight, port; size_t j; OFString *target; if (dataLength < 6) @@ -475,11 +392,11 @@ port: port TTL: TTL] autorelease]; } else return [[[OFDNSResourceRecord alloc] initWithName: name - recordClass: recordClass + DNSClass: DNSClass recordType: recordType TTL: TTL] autorelease]; } static OFDictionary * @@ -491,31 +408,31 @@ OFMutableArray *array; for (uint_fast16_t j = 0; j < count; j++) { OFString *name = parseName(buffer, length, i, MAX_ALLOWED_POINTERS); - of_dns_resource_record_class_t recordClass; + of_dns_class_t DNSClass; of_dns_resource_record_type_t recordType; uint32_t TTL; uint16_t dataLength; OFDNSResourceRecord *record; if (*i + 10 > length) @throw [OFTruncatedDataException exception]; recordType = (buffer[*i] << 16) | buffer[*i + 1]; - recordClass = (buffer[*i + 2] << 16) | buffer[*i + 3]; + DNSClass = (buffer[*i + 2] << 16) | buffer[*i + 3]; TTL = (buffer[*i + 4] << 24) | (buffer[*i + 5] << 16) | (buffer[*i + 6] << 8) | buffer[*i + 7]; dataLength = (buffer[*i + 8] << 16) | buffer[*i + 9]; *i += 10; if (*i + dataLength > length) @throw [OFTruncatedDataException exception]; - record = parseResourceRecord(name, recordClass, recordType, TTL, + record = parseResourceRecord(name, DNSClass, recordType, TTL, buffer, length, *i, dataLength); *i += dataLength; array = [ret objectForKey: name]; @@ -535,49 +452,27 @@ [ret makeImmutable]; return ret; } -static void -callback(id target, SEL selector, OFDNSResolver *resolver, OFString *domainName, - OFDNSResponse *response, id context, id exception) -{ - void (*method)(id, SEL, OFDNSResolver *, OFString *, OFDNSResponse *, - id, id) = (void (*)(id, SEL, OFDNSResolver *, OFString *, - OFDNSResponse *, id, id))[target methodForSelector: selector]; - - method(target, selector, resolver, domainName, response, context, - exception); -} - -@implementation OFDNSResolverQuery +@implementation OFDNSResolverContext - (instancetype)initWithQuery: (OFDNSQuery *)query - 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 + delegate: (id )delegate { self = [super init]; @try { void *pool = objc_autoreleasePoolPush(); OFMutableData *queryData; uint16_t tmp; _query = [query copy]; - _domainName = [domainName copy]; _ID = [ID retain]; _settings = [settings copy]; - _nameServersIndex = nameServersIndex; - _searchDomainsIndex = searchDomainsIndex; - _target = [target retain]; - _selector = selector; - _context = [context retain]; + _delegate = [delegate retain]; queryData = [OFMutableData dataWithCapacity: 512]; /* Header */ @@ -600,11 +495,11 @@ /* Question */ /* QNAME */ for (OFString *component in - [_domainName componentsSeparatedByString: @"."]) { + [_query.domainName componentsSeparatedByString: @"."]) { size_t length = component.UTF8StringLength; uint8_t length8; if (length > 63 || queryData.count + length > 512) @throw [OFOutOfRangeException exception]; @@ -619,11 +514,11 @@ tmp = OF_BSWAP16_IF_LE(_query.recordType); [queryData addItems: &tmp count: 2]; /* QCLASS */ - tmp = OF_BSWAP16_IF_LE(_query.recordClass); + tmp = OF_BSWAP16_IF_LE(_query.DNSClass); [queryData addItems: &tmp count: 2]; [queryData makeImmutable]; @@ -639,314 +534,18 @@ } - (void)dealloc { [_query release]; - [_domainName release]; [_ID release]; [_settings release]; - [_target release]; - [_context release]; + [_delegate release]; [_queryData release]; [_cancelTimer release]; [super dealloc]; } -@end - -@implementation OFDNSResolverAsyncResolveSocketAddressesContext -- (instancetype)initWithHost: (OFString *)host - delegate: (id)delegate -{ - self = [super init]; - - @try { - _host = [host copy]; - _delegate = [delegate retain]; - - _records = [[OFMutableArray alloc] init]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - [_host release]; - [_delegate release]; - [_records release]; - [_resolver release]; - [_domainName release]; - - [super dealloc]; -} - -- (bool)parseRecords: (OFArray *)records - response: (OFDNSResponse *)response - recordType: (of_dns_resource_record_type_t)recordType - recursion: (unsigned int)recursion - result: (OFMutableArray *)result -{ - bool found = false; - - for (OF_KINDOF(OFDNSResourceRecord *) record in records) { - if ([record recordClass] != OF_DNS_RESOURCE_RECORD_CLASS_IN) - continue; - - if ([record recordType] == recordType) { - [result addObject: record]; - found = true; - } else if ([record recordType] == - OF_DNS_RESOURCE_RECORD_TYPE_CNAME) { - [self resolveCNAME: record - response: response - recordType: recordType - recursion: recursion - result: result]; - found = true; - } - } - - return found; -} - -- (void)resolveCNAME: (OFCNAMEDNSResourceRecord *)CNAME - response: (OFDNSResponse *)response - recordType: (of_dns_resource_record_type_t)recordType - recursion: (unsigned int)recursion - result: (OFMutableArray *)result -{ - OFString *alias = CNAME.alias; - bool found = false; - - if (recursion == 0) - return; - - if ([self parseRecords: [response.answerRecords objectForKey: alias] - response: response - recordType: recordType - recursion: recursion - 1 - result: result]) - found = true; - - if ([self parseRecords: [response.additionalRecords objectForKey: alias] - response: response - recordType: recordType - recursion: recursion - 1 - result: result]) - found = true; - - if (!found) { - of_run_loop_mode_t runLoopMode = - [OFRunLoop currentRunLoop].currentMode; - OFNumber *recordTypeNumber = - [OFNumber numberWithInt: recordType]; - OFDNSQuery *query; - - _expectedResponses++; - - [result addObject: - [OFPair pairWithFirstObject: CNAME - secondObject: recordTypeNumber]]; - - query = [OFDNSQuery - queryWithHost: alias - recordClass: OF_DNS_RESOURCE_RECORD_CLASS_IN - recordType: recordType]; - [_resolver of_asyncPerformQuery: query - settings: nil - nameServersIndex: 0 - searchDomainsIndex: 0 - runLoopMode: runLoopMode - target: self - selector: @selector(resolver: - didResolveCNAME:response: - context:exception:) - context: recordTypeNumber]; - } -} - -- (void)resolver: (OFDNSResolver *)resolver - didResolveCNAME: (OFString *)CNAME - response: (OFDNSResponse *)response - context: (OFNumber *)context - exception: (id)exception -{ - /* - * TODO: Error handling could be improved. Ignore error if there are - * responses, otherwise propagate error. - */ - - of_dns_resource_record_type_t recordType = context.unsignedIntValue; - bool found = false; - OFMutableArray *records; - size_t count; - - OF_ENSURE(resolver == _resolver); - - _expectedResponses--; - - if (exception != nil) { - if (_expectedResponses == 0) - [self done]; - - return; - } - - records = [OFMutableArray array]; - - if ([self parseRecords: [response.answerRecords objectForKey: CNAME] - response: response - recordType: recordType - recursion: CNAME_RECURSION - result: records]) - found = true; - - if ([self parseRecords: [response.additionalRecords objectForKey: CNAME] - response: response - recordType: recordType - recursion: CNAME_RECURSION - result: records]) - found = true; - - if (!found) { - if (_expectedResponses == 0) - [self done]; - - return; - } - - count = _records.count; - for (size_t i = 0; i < count; i++) { - id object = [_records objectAtIndex: i]; - - if (![object isKindOfClass: [OFPair class]]) - continue; - - if (![[[object firstObject] alias] isEqual: CNAME]) - continue; - - if ([[object secondObject] unsignedIntValue] != recordType) - continue; - - [_records removeObjectAtIndex: i]; - [_records insertObjectsFromArray: records - atIndex: i]; - i += records.count - 1; - } - - if (_expectedResponses == 0) - [self done]; -} - -- (void)done -{ - OFMutableData *addresses = - [OFMutableData dataWithItemSize: sizeof(of_socket_address_t)]; - id exception = nil; - - for (id record in _records) { - if (![record isKindOfClass: [OFDNSResourceRecord class]]) - continue; - - switch ([record recordType]) { - case OF_DNS_RESOURCE_RECORD_TYPE_A: - case OF_DNS_RESOURCE_RECORD_TYPE_AAAA: - [addresses addItem: [record address]]; - break; - default: - break; - } - } - - [addresses makeImmutable]; - - if (addresses.count == 0) { - OFDNSQuery *query = [OFDNSQuery - queryWithHost: _host - recordClass: OF_DNS_RESOURCE_RECORD_CLASS_IN - recordType: 0]; - - exception = [OFDNSQueryFailedException - exceptionWithQuery: query - error: OF_DNS_RESOLVER_ERROR_UNKNOWN]; - } - - if ([_delegate respondsToSelector: @selector( - resolver:didResolveDomainName:socketAddresses:exception:)]) - [_delegate resolver: _resolver - didResolveDomainName: _domainName - socketAddresses: (exception == nil ? addresses : nil) - exception: exception]; -} - -- (void)resolver: (OFDNSResolver *)resolver - didResolveDomainName: (OFString *)domainName - response: (OFDNSResponse *)response - context: (OFNumber *)context - exception: (id)exception -{ - /* - * TODO: Error handling could be improved. Ignore error if there are - * responses, otherwise propagate error. - */ - - of_dns_resource_record_type_t recordType = context.unsignedIntValue; - - if (_resolver != nil) - OF_ENSURE(resolver == _resolver); - else - _resolver = [resolver retain]; - - _expectedResponses--; - - if (_domainName != nil) { - if (![domainName isEqual: _domainName]) - /* Did the config change in between? */ - return; - } else - _domainName = [domainName copy]; - - if (exception != nil) { - if (_expectedResponses == 0) - [self done]; - - return; - } - - [self parseRecords: [response.answerRecords objectForKey: _domainName] - response: response - recordType: recordType - recursion: CNAME_RECURSION - result: _records]; - - if (_expectedResponses == 0) - [self done]; -} -@end - -@implementation OFDNSResolverResolveSocketAddressesDelegate -- (void)dealloc -{ - [_socketAddresses release]; - [_exception release]; - - [super dealloc]; -} - -- (void)resolver: (OFDNSResolver *)resolver - didResolveDomainName: (OFString *)domainName - socketAddresses: (OFData *)socketAddresses - exception: (id)exception -{ - _socketAddresses = [socketAddresses retain]; - _exception = [exception retain]; - _done = true; -} @end @implementation OFDNSResolver #ifdef OF_AMIGAOS + (void)initialize @@ -1089,138 +688,35 @@ - (void)setConfigReloadInterval: (of_time_interval_t)configReloadInterval { _settings->_configReloadInterval = configReloadInterval; } -- (void)of_asyncPerformQuery: (OFDNSQuery *)query - 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 *host, *domainName; - OFDNSResolverQuery *resolverQuery; - - if (settings == nil) { - [_settings reload]; - settings = _settings; - } - - /* Random, unused ID */ - do { - ID = [OFNumber numberWithUInt16: (uint16_t)of_random()]; - } while ([_queries objectForKey: ID] != nil); - - host = query.host; - if (isFQDN(host, settings)) { - domainName = host; - - if (![domainName hasSuffix: @"."]) - domainName = [domainName stringByAppendingString: @"."]; - } else { - OFString *searchDomain = [settings->_searchDomains - objectAtIndex: searchDomainsIndex]; - - domainName = [OFString stringWithFormat: @"%@.%@.", - host, searchDomain]; - } - - if (domainName.UTF8StringLength > 253) - @throw [OFOutOfRangeException exception]; - - resolverQuery = [[[OFDNSResolverQuery alloc] - initWithQuery: query - domainName: domainName - ID: ID - settings: settings - nameServersIndex: nameServersIndex - searchDomainsIndex: searchDomainsIndex - target: target - selector: selector - context: context] autorelease]; - [_queries setObject: resolverQuery - forKey: ID]; - - [self of_sendQuery: resolverQuery - runLoopMode: runLoopMode]; - - objc_autoreleasePoolPop(pool); -} - -- (void)of_resolver: (OFDNSResolver *)resolver - didResolveDomainName: (OFString *)domainName - response: (OFDNSResponse *)response - context: (id)delegate - exception: (id)exception -{ - if ([delegate respondsToSelector: @selector(resolver: - didResolveDomainName:response:exception:)]) - [delegate resolver: resolver - didResolveDomainName: domainName - response: response - exception: exception]; -} - -- (void)asyncPerformQuery: (OFDNSQuery *)query - delegate: (id )delegate -{ - [self of_asyncPerformQuery: query - settings: nil - nameServersIndex: 0 - searchDomainsIndex: 0 - runLoopMode: of_run_loop_mode_default - target: self - selector: @selector(of_resolver:didResolveDomainName: - response:context:exception:) - context: delegate]; -} - -- (void)asyncPerformQuery: (OFDNSQuery *)query - runLoopMode: (of_run_loop_mode_t)runLoopMode - delegate: (id )delegate -{ - [self of_asyncPerformQuery: query - settings: nil - nameServersIndex: 0 - searchDomainsIndex: 0 - runLoopMode: runLoopMode - target: self - selector: @selector(of_resolver:didResolveDomainName: - response:context:exception:) - context: delegate]; -} - -- (void)of_sendQuery: (OFDNSResolverQuery *)query - runLoopMode: (of_run_loop_mode_t)runLoopMode +- (void)of_sendQueryForContext: (OFDNSResolverContext *)context + runLoopMode: (of_run_loop_mode_t)runLoopMode { OFUDPSocket *sock; OFString *nameServer; - [query->_cancelTimer invalidate]; - [query->_cancelTimer release]; - query->_cancelTimer = nil; - query->_cancelTimer = [[OFTimer alloc] + [context->_cancelTimer invalidate]; + [context->_cancelTimer release]; + context->_cancelTimer = nil; + context->_cancelTimer = [[OFTimer alloc] initWithFireDate: [OFDate dateWithTimeIntervalSinceNow: - query->_settings->_timeout] - interval: query->_settings->_timeout + context->_settings->_timeout] + interval: context->_settings->_timeout target: self - selector: @selector(of_queryWithIDTimedOut:) - object: query + selector: @selector(of_contextTimedOut:) + object: context repeats: false]; - [[OFRunLoop currentRunLoop] addTimer: query->_cancelTimer + [[OFRunLoop currentRunLoop] addTimer: context->_cancelTimer forMode: runLoopMode]; - nameServer = [query->_settings->_nameServers - objectAtIndex: query->_nameServersIndex]; - query->_usedNameServer = of_socket_address_parse_ip(nameServer, 53); + nameServer = [context->_settings->_nameServers + objectAtIndex: context->_nameServersIndex]; + context->_usedNameServer = of_socket_address_parse_ip(nameServer, 53); - switch (query->_usedNameServer.family) { + switch (context->_usedNameServer.family) { #ifdef OF_HAVE_IPV6 case OF_SOCKET_ADDRESS_FAMILY_IPV6: if (_IPv6Socket == nil) { of_socket_address_t address = of_socket_address_parse_ip(@"::", 0); @@ -1228,12 +724,10 @@ _IPv6Socket = [[OFUDPSocket alloc] init]; [_IPv6Socket of_bindToAddress: &address extraType: SOCK_DNS]; _IPv6Socket.blocking = false; _IPv6Socket.delegate = self; - [_IPv6Socket asyncReceiveIntoBuffer: _buffer - length: BUFFER_LENGTH]; } sock = _IPv6Socket; break; #endif @@ -1245,50 +739,87 @@ _IPv4Socket = [[OFUDPSocket alloc] init]; [_IPv4Socket of_bindToAddress: &address extraType: SOCK_DNS]; _IPv4Socket.blocking = false; _IPv4Socket.delegate = self; - [_IPv4Socket asyncReceiveIntoBuffer: _buffer - length: BUFFER_LENGTH]; } sock = _IPv4Socket; break; default: @throw [OFInvalidArgumentException exception]; } - [sock asyncSendData: query->_queryData - receiver: &query->_usedNameServer - runLoopMode: runLoopMode]; -} - -- (void)of_queryWithIDTimedOut: (OFDNSResolverQuery *)query -{ - OFDNSQueryFailedException *exception; - - if (query == nil) - return; - - if (query->_nameServersIndex + 1 < - query->_settings->_nameServers.count) { - query->_nameServersIndex++; - [self of_sendQuery: query - runLoopMode: [OFRunLoop currentRunLoop].currentMode]; - return; - } - - if (query->_attempt < query->_settings->_maxAttempts) { - query->_attempt++; - query->_nameServersIndex = 0; - [self of_sendQuery: query - runLoopMode: [OFRunLoop currentRunLoop].currentMode]; - return; - } - - query = [[query retain] autorelease]; - [_queries removeObjectForKey: query->_ID]; + [sock asyncSendData: context->_queryData + receiver: &context->_usedNameServer + runLoopMode: runLoopMode]; + [sock asyncReceiveIntoBuffer: _buffer + length: BUFFER_LENGTH + runLoopMode: runLoopMode]; +} + +- (void)asyncPerformQuery: (OFDNSQuery *)query + delegate: (id )delegate +{ + [self asyncPerformQuery: query + runLoopMode: of_run_loop_mode_default + delegate: delegate]; +} + +- (void)asyncPerformQuery: (OFDNSQuery *)query + runLoopMode: (of_run_loop_mode_t)runLoopMode + delegate: (id )delegate +{ + void *pool = objc_autoreleasePoolPush(); + OFNumber *ID; + OFDNSResolverContext *context; + + /* Random, unused ID */ + do { + ID = [OFNumber numberWithUInt16: (uint16_t)of_random()]; + } while ([_queries objectForKey: ID] != nil); + + if (query.domainName.UTF8StringLength > 253) + @throw [OFOutOfRangeException exception]; + + context = [[[OFDNSResolverContext alloc] + initWithQuery: query + ID: ID + settings: _settings + delegate: delegate] autorelease]; + [_queries setObject: context + forKey: ID]; + + [self of_sendQueryForContext: context + runLoopMode: runLoopMode]; + + objc_autoreleasePoolPop(pool); +} + +- (void)of_contextTimedOut: (OFDNSResolverContext *)context +{ + of_run_loop_mode_t runLoopMode = [OFRunLoop currentRunLoop].currentMode; + OFDNSQueryFailedException *exception; + + if (context->_nameServersIndex + 1 < + context->_settings->_nameServers.count) { + context->_nameServersIndex++; + [self of_sendQueryForContext: context + runLoopMode: runLoopMode]; + return; + } + + if (context->_attempt < context->_settings->_maxAttempts) { + context->_attempt++; + context->_nameServersIndex = 0; + [self of_sendQueryForContext: context + runLoopMode: runLoopMode]; + return; + } + + context = [[context retain] autorelease]; + [_queries removeObjectForKey: context->_ID]; /* * Cancel any pending queries, to avoid a send being still pending and * trying to access the query once it no longer exists. */ @@ -1300,15 +831,19 @@ [_IPv6Socket asyncReceiveIntoBuffer: _buffer length: BUFFER_LENGTH]; #endif exception = [OFDNSQueryFailedException - exceptionWithQuery: query->_query + exceptionWithQuery: context->_query error: OF_DNS_RESOLVER_ERROR_TIMEOUT]; - callback(query->_target, query->_selector, self, query->_domainName, - nil, query->_context, exception); + if ([context->_delegate respondsToSelector: + @selector(resolver:didPerformQuery:response:exception:)]) + [context->_delegate resolver: self + didPerformQuery: context->_query + response: nil + exception: exception]; } - (bool)socket: (OFUDPSocket *)sock didReceiveIntoBuffer: (void *)buffer_ length: (size_t)length @@ -1318,31 +853,31 @@ unsigned char *buffer = buffer_; OFDictionary *answerRecords = nil, *authorityRecords = nil; OFDictionary *additionalRecords = nil; OFDNSResponse *response = nil; OFNumber *ID; - OFDNSResolverQuery *query; + OFDNSResolverContext *context; if (exception != nil) return true; if (length < 2) - /* We can't get the ID to get the query. Ignore packet. */ + /* We can't get the ID to get the context. Ignore packet. */ return true; ID = [OFNumber numberWithUInt16: (buffer[0] << 8) | buffer[1]]; - query = [[[_queries objectForKey: ID] retain] autorelease]; + context = [[[_queries objectForKey: ID] retain] autorelease]; - if (query == nil) + if (context == nil) return true; - if (!of_socket_address_equal(sender, &query->_usedNameServer)) + if (!of_socket_address_equal(sender, &context->_usedNameServer)) return true; - [query->_cancelTimer invalidate]; - [query->_cancelTimer release]; - query->_cancelTimer = nil; + [context->_cancelTimer invalidate]; + [context->_cancelTimer release]; + context->_cancelTimer = nil; [_queries removeObjectForKey: ID]; @try { bool tryNextNameServer = false; const unsigned char *queryDataBuffer; @@ -1352,15 +887,15 @@ uint16_t numAdditionalRecords; if (length < 12) @throw [OFTruncatedDataException exception]; - if (query->_queryData.itemSize != 1 || - query->_queryData.count < 12) + if (context->_queryData.itemSize != 1 || + context->_queryData.count < 12) @throw [OFInvalidArgumentException exception]; - queryDataBuffer = query->_queryData.items; + queryDataBuffer = context->_queryData.items; /* QR */ if ((buffer[2] & 0x80) == 0) @throw [OFInvalidServerReplyException exception]; @@ -1399,37 +934,26 @@ tryNextNameServer = true; break; } if (tryNextNameServer) { - if (query->_searchDomainsIndex + 1 < - query->_settings->_searchDomains.count) { + if (context->_nameServersIndex + 1 < + context->_settings->_nameServers.count) { of_run_loop_mode_t runLoopMode = [OFRunLoop currentRunLoop].currentMode; - size_t nameServersIndex = - query->_nameServersIndex + 1; - size_t searchDomainsIndex = - query->_searchDomainsIndex + 1; - - query->_searchDomainsIndex++; - - [self of_asyncPerformQuery: query->_query - settings: query->_settings - nameServersIndex: nameServersIndex - searchDomainsIndex: searchDomainsIndex - runLoopMode: runLoopMode - target: query->_target - selector: query->_selector - context: query->_context]; - - return true; + + context->_nameServersIndex++; + + [self of_sendQueryForContext: context + runLoopMode: runLoopMode]; + return false; } } if (buffer[3] & 0x0F) @throw [OFDNSQueryFailedException - exceptionWithQuery: query->_query + exceptionWithQuery: context->_query error: error]; numQuestions = (buffer[4] << 8) | buffer[5]; numAnswers = (buffer[6] << 8) | buffer[7]; numAuthorityRecords = (buffer[8] << 8) | buffer[9]; @@ -1452,283 +976,91 @@ authorityRecords = parseSection(buffer, length, &i, numAuthorityRecords); additionalRecords = parseSection(buffer, length, &i, numAdditionalRecords); response = [OFDNSResponse - responseWithAnswerRecords: answerRecords - authorityRecords: authorityRecords - additionalRecords: additionalRecords]; - } @catch (id e) { - callback(query->_target, query->_selector, self, - query->_domainName, nil, query->_context, e); - return true; - } - - callback(query->_target, query->_selector, self, query->_domainName, - response, query->_context, nil); - - return true; -} - -- (void)asyncResolveSocketAddressesForHost: (OFString *)host - delegate: (id )delegate -{ - [self asyncResolveSocketAddressesForHost: host - addressFamily: OF_SOCKET_ADDRESS_FAMILY_ANY - runLoopMode: of_run_loop_mode_default - delegate: delegate]; -} - -- (void)asyncResolveSocketAddressesForHost: (OFString *)host - addressFamily: (of_socket_address_family_t) - addressFamily - delegate: (id )delegate -{ - [self asyncResolveSocketAddressesForHost: host - addressFamily: addressFamily - runLoopMode: of_run_loop_mode_default - delegate: delegate]; -} - -- (void)asyncResolveSocketAddressesForHost: (OFString *)host - addressFamily: (of_socket_address_family_t) - addressFamily - runLoopMode: (of_run_loop_mode_t)runLoopMode - delegate: (id )delegate -{ - OFArray OF_GENERIC(OFString *) *aliases; - void *pool; - OFDNSResolverAsyncResolveSocketAddressesContext *context; - - @try { - of_socket_address_t address = - of_socket_address_parse_ip(host, 0); - OFData *addresses = nil; - id exception = nil; - - if (addressFamily == OF_SOCKET_ADDRESS_FAMILY_ANY || - addressFamily == address.family) - addresses = [OFData dataWithItems: &address - itemSize: sizeof(address) - count: 1]; - else - exception = [OFInvalidArgumentException exception]; - - if ([delegate respondsToSelector: @selector(resolver: - didResolveDomainName:socketAddresses:exception:)]) { - OFTimer *timer = [OFTimer - timerWithTimeInterval: 0 - target: delegate - selector: @selector(resolver: - didResolveDomainName: - socketAddresses: - exception:) - object: self - object: host - object: addresses - object: exception - repeats: false]; - [[OFRunLoop currentRunLoop] addTimer: timer - forMode: runLoopMode]; - } - - return; - } @catch (OFInvalidFormatException *e) { - } - - if ((aliases = [_settings->_staticHosts objectForKey: host]) != nil) { - OFMutableData *addresses = [OFMutableData - dataWithItemSize: sizeof(of_socket_address_t)]; - id exception = nil; - - for (OFString *alias in aliases) { - of_socket_address_t address; - - @try { - address = of_socket_address_parse_ip(alias, 0); - } @catch (OFInvalidFormatException *e) { - continue; - } - - if (addressFamily != OF_SOCKET_ADDRESS_FAMILY_ANY && - address.family != addressFamily) - continue; - - [addresses addItem: &address]; - } - - [addresses makeImmutable]; - - if (addresses.count == 0) { - of_dns_resource_record_type_t recordType = 0; - - addresses = nil; - - switch (addressFamily) { - case OF_SOCKET_ADDRESS_FAMILY_ANY: - recordType = OF_DNS_RESOURCE_RECORD_TYPE_ALL; - break; - case OF_SOCKET_ADDRESS_FAMILY_IPV4: - recordType = OF_DNS_RESOURCE_RECORD_TYPE_A; - break; - case OF_SOCKET_ADDRESS_FAMILY_IPV6: - recordType = OF_DNS_RESOURCE_RECORD_TYPE_AAAA; - break; - default: - exception = - [OFInvalidArgumentException exception]; - break; - } - - 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; - OFDNSQuery *query = [OFDNSQuery - queryWithHost: host - recordClass: recordClass - recordType: recordType]; - - exception = [OFDNSQueryFailedException - exceptionWithQuery: query - error: error]; - } - } - - if ([delegate respondsToSelector: @selector(resolver: - didResolveDomainName:socketAddresses:exception:)]) { - OFTimer *timer = [OFTimer - timerWithTimeInterval: 0 - target: delegate - selector: @selector(resolver: - didResolveDomainName: - socketAddresses: - exception:) - object: self - object: host - object: addresses - object: exception - repeats: false]; - [[OFRunLoop currentRunLoop] addTimer: timer - forMode: runLoopMode]; - } - - return; - } - - pool = objc_autoreleasePoolPush(); - - context = [[[OFDNSResolverAsyncResolveSocketAddressesContext alloc] - initWithHost: host - delegate: delegate] autorelease]; - - switch (addressFamily) { - case OF_SOCKET_ADDRESS_FAMILY_IPV4: -#ifdef OF_HAVE_IPV6 - case OF_SOCKET_ADDRESS_FAMILY_IPV6: -#endif - context->_expectedResponses = 1; - break; - case OF_SOCKET_ADDRESS_FAMILY_ANY: -#ifdef OF_HAVE_IPV6 - context->_expectedResponses = 2; -#else - context->_expectedResponses = 1; -#endif - break; - default: - @throw [OFInvalidArgumentException exception]; - } - -#ifdef OF_HAVE_IPV6 - if (addressFamily == OF_SOCKET_ADDRESS_FAMILY_IPV6 || - addressFamily == OF_SOCKET_ADDRESS_FAMILY_ANY) { - OFDNSQuery *query = [OFDNSQuery - queryWithHost: 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_asyncPerformQuery: query - settings: nil - nameServersIndex: 0 - searchDomainsIndex: 0 - 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) { - OFDNSQuery *query = [OFDNSQuery - queryWithHost: 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_asyncPerformQuery: query - settings: nil - nameServersIndex: 0 - searchDomainsIndex: 0 - runLoopMode: runLoopMode - target: context - selector: @selector(resolver: - didResolveDomainName:response: - context:exception:) - context: recordTypeNumber]; - } - - objc_autoreleasePoolPop(pool); -} - -- (OFData *)resolveSocketAddressesForHost: (OFString *)host - addressFamily: (of_socket_address_family_t) - addressFamily -{ - void *pool = objc_autoreleasePoolPush(); - OFRunLoop *runLoop = [OFRunLoop currentRunLoop]; - OFDNSResolverResolveSocketAddressesDelegate *delegate; - OFData *ret; - - delegate = [[[OFDNSResolverResolveSocketAddressesDelegate - alloc] init] autorelease]; - - [self asyncResolveSocketAddressesForHost: host - addressFamily: addressFamily - runLoopMode: resolveRunLoopMode - delegate: delegate]; - - while (!delegate->_done) - [runLoop runMode: resolveRunLoopMode - beforeDate: nil]; - - /* Cleanup */ - [runLoop runMode: resolveRunLoopMode - beforeDate: [OFDate date]]; - - if (delegate->_exception != nil) - @throw delegate->_exception; - - ret = [delegate->_socketAddresses retain]; - - objc_autoreleasePoolPop(pool); - - return [ret autorelease]; + responseWithDomainName: context->_query.domainName + answerRecords: answerRecords + authorityRecords: authorityRecords + additionalRecords: additionalRecords]; + } @catch (id e) { + exception = e; + } + + if ([context->_delegate respondsToSelector: + @selector(resolver:didPerformQuery:response:exception:)]) + [context->_delegate resolver: self + didPerformQuery: context->_query + response: response + exception: exception]; + + return false; +} + +- (void)asyncResolveAddressesForHost: (OFString *)host + delegate: (id )delegate +{ + [self asyncResolveAddressesForHost: host + addressFamily: OF_SOCKET_ADDRESS_FAMILY_ANY + runLoopMode: of_run_loop_mode_default + delegate: delegate]; +} + +- (void)asyncResolveAddressesForHost: (OFString *)host + addressFamily: (of_socket_address_family_t)addressFamily + delegate: (id )delegate +{ + [self asyncResolveAddressesForHost: host + addressFamily: addressFamily + runLoopMode: of_run_loop_mode_default + delegate: delegate]; +} + +- (void)asyncResolveAddressesForHost: (OFString *)host + addressFamily: (of_socket_address_family_t)addressFamily + runLoopMode: (of_run_loop_mode_t)runLoopMode + delegate: (id )delegate +{ + void *pool = objc_autoreleasePoolPush(); + OFHostAddressResolver *resolver = [[[OFHostAddressResolver alloc] + initWithHost: host + addressFamily: addressFamily + resolver: self + settings: _settings + runLoopMode: runLoopMode + delegate: delegate] autorelease]; + + [resolver asyncResolve]; + + objc_autoreleasePoolPop(pool); +} + +- (OFData *)resolveAddressesForHost: (OFString *)host + addressFamily: (of_socket_address_family_t)addressFamily +{ + void *pool = objc_autoreleasePoolPush(); + OFHostAddressResolver *resolver = [[[OFHostAddressResolver alloc] + initWithHost: host + addressFamily: addressFamily + resolver: self + settings: _settings + runLoopMode: nil + delegate: nil] autorelease]; + OFData *addresses = [resolver resolve]; + + [addresses retain]; + + objc_autoreleasePoolPop(pool); + + return [addresses autorelease]; } - (void)close { void *pool = objc_autoreleasePoolPush(); - OFEnumerator OF_GENERIC(OFDNSResolverQuery *) *enumerator; - OFDNSResolverQuery *query; + OFEnumerator OF_GENERIC(OFDNSResolverContext *) *enumerator; + OFDNSResolverContext *context; [_IPv4Socket cancelAsyncRequests]; [_IPv4Socket release]; _IPv4Socket = nil; @@ -1737,21 +1069,25 @@ [_IPv6Socket release]; _IPv6Socket = nil; #endif enumerator = [_queries objectEnumerator]; - while ((query = [enumerator nextObject]) != nil) { + while ((context = [enumerator nextObject]) != nil) { OFDNSQueryFailedException *exception; exception = [OFDNSQueryFailedException - exceptionWithQuery: query->_query + exceptionWithQuery: context->_query error: OF_DNS_RESOLVER_ERROR_CANCELED]; - callback(query->_target, query->_selector, self, - query->_domainName, nil, query->_context, exception); + if ([context->_delegate respondsToSelector: + @selector(resolver:didPerformQuery:response:exception:)]) + [context->_delegate resolver: self + didPerformQuery: context->_query + response: nil + exception: exception]; } [_queries removeAllObjects]; objc_autoreleasePoolPop(pool); } @end Index: src/OFDNSResourceRecord.h ================================================================== --- src/OFDNSResourceRecord.h +++ src/OFDNSResourceRecord.h @@ -25,18 +25,18 @@ /*! @file */ @class OFData; /*! - * @brief The class of a DNS resource record. + * @brief The DNS class. */ typedef enum { /*! IN */ - OF_DNS_RESOURCE_RECORD_CLASS_IN = 1, + OF_DNS_CLASS_IN = 1, /*! Any class. Only for queries. */ - OF_DNS_RESOURCE_RECORD_CLASS_ANY = 255, -} of_dns_resource_record_class_t; + OF_DNS_CLASS_ANY = 255, +} of_dns_class_t; /*! * @brief The type of a DNS resource record. */ typedef enum { @@ -72,11 +72,11 @@ * @brief A class representing a DNS resource record. */ @interface OFDNSResourceRecord: OFObject { OFString *_name; - of_dns_resource_record_class_t _recordClass; + of_dns_class_t _DNSClass; of_dns_resource_record_type_t _recordType; uint32_t _TTL; OF_RESERVE_IVARS(4) } @@ -84,13 +84,13 @@ * @brief The domain name to which the resource record belongs. */ @property (readonly, nonatomic) OFString *name; /*! - * @brief The resource record class code. + * @brief The DNS class. */ -@property (readonly, nonatomic) of_dns_resource_record_class_t recordClass; +@property (readonly, nonatomic) of_dns_class_t DNSClass; /*! * @brief The resource record type code. */ @property (readonly, nonatomic) of_dns_resource_record_type_t recordType; @@ -104,17 +104,17 @@ /*! * @brief Initializes an already allocated OFDNSResourceRecord with the * specified name, class, type, data and time to live. * * @param name The name for the resource record - * @param recordClass The class code for the resource record + * @param DNSClass The class code for the resource record * @param recordType The type code for the resource record * @param TTL The time to live for the resource record * @return An initialized OFDNSResourceRecord */ - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass recordType: (of_dns_resource_record_type_t)recordType TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER; @end /*! @@ -132,11 +132,11 @@ * @brief The IPv4 address of the resource record. */ @property (readonly, nonatomic) const of_socket_address_t *address; - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass recordType: (of_dns_resource_record_type_t)recordType TTL: (uint32_t)TTL OF_UNAVAILABLE; /*! * @brief Initializes an already allocated OFADNSResourceRecord with the @@ -168,11 +168,11 @@ * @brief The IPv6 address of the resource record. */ @property (readonly, nonatomic) const of_socket_address_t *address; - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass recordType: (of_dns_resource_record_type_t)recordType TTL: (uint32_t)TTL OF_UNAVAILABLE; /*! * @brief Initializes an already allocated OFAAAADNSResourceRecord with the @@ -204,26 +204,26 @@ * @brief The alias of the resource record. */ @property (readonly, nonatomic) OFString *alias; - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass recordType: (of_dns_resource_record_type_t)recordType TTL: (uint32_t)TTL OF_UNAVAILABLE; /*! * @brief Initializes an already allocated OFCNAMEDNSResourceRecord with the * specified name, class, alias and time to live. * * @param name The name for the resource record - * @param recordClass The class code for the resource record + * @param DNSClass The class code for the resource record * @param alias The alias for the resource record * @param TTL The time to live for the resource record * @return An initialized OFCNAMEDNSResourceRecord */ - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass alias: (OFString *)alias TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER; @end /*! @@ -247,27 +247,27 @@ * @brief The OS of the host info of the resource record. */ @property (readonly, nonatomic) OFString *OS; - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass recordType: (of_dns_resource_record_type_t)recordType TTL: (uint32_t)TTL OF_UNAVAILABLE; /*! * @brief Initializes an already allocated OFHINFODNSResourceRecord with the * specified name, class, domain name and time to live. * * @param name The name for the resource record - * @param recordClass The class code for the resource record + * @param DNSClass The class code for the resource record * @param CPU The CPU of the host info for the resource record * @param OS The OS of the host info for the resource record * @param TTL The time to live for the resource record * @return An initialized OFHINFODNSResourceRecord */ - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass CPU: (OFString *)CPU OS: (OFString *)OS TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER; @end @@ -293,27 +293,27 @@ * @brief The mail exchange of the resource record. */ @property (readonly, nonatomic) OFString *mailExchange; - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass recordType: (of_dns_resource_record_type_t)recordType TTL: (uint32_t)TTL OF_UNAVAILABLE; /*! * @brief Initializes an already allocated OFMXDNSResourceRecord with the * specified name, class, preference, mail exchange and time to live. * * @param name The name for the resource record - * @param recordClass The class code for the resource record + * @param DNSClass The class code for the resource record * @param preference The preference for the resource record * @param mailExchange The mail exchange for the resource record * @param TTL The time to live for the resource record * @return An initialized OFMXDNSResourceRecord */ - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass preference: (uint16_t)preference mailExchange: (OFString *)mailExchange TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER; @end @@ -333,26 +333,26 @@ * @brief The authoritative host of the resource record. */ @property (readonly, nonatomic) OFString *authoritativeHost; - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass recordType: (of_dns_resource_record_type_t)recordType TTL: (uint32_t)TTL OF_UNAVAILABLE; /*! * @brief Initializes an already allocated OFNSDNSResourceRecord with the * specified name, class, authoritative host and time to live. * * @param name The name for the resource record - * @param recordClass The class code for the resource record + * @param DNSClass The class code for the resource record * @param authoritativeHost The authoritative host for the resource record * @param TTL The time to live for the resource record * @return An initialized OFNSDNSResourceRecord */ - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass authoritativeHost: (OFString *)authoritativeHost TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER; @end /*! @@ -371,26 +371,26 @@ * @brief The domain name of the resource record. */ @property (readonly, nonatomic) OFString *domainName; - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass recordType: (of_dns_resource_record_type_t)recordType TTL: (uint32_t)TTL OF_UNAVAILABLE; /*! * @brief Initializes an already allocated OFPTRDNSResourceRecord with the * specified name, class, domain name and time to live. * * @param name The name for the resource record - * @param recordClass The class code for the resource record + * @param DNSClass The class code for the resource record * @param domainName The domain name for the resource record * @param TTL The time to live for the resource record * @return An initialized OFPTRDNSResourceRecord */ - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass domainName: (OFString *)domainName TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER; @end /*! @@ -415,28 +415,28 @@ * person of the resource record. */ @property (readonly, nonatomic) OFString *TXTDomainName; - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass recordType: (of_dns_resource_record_type_t)recordType TTL: (uint32_t)TTL OF_UNAVAILABLE; /*! * @brief Initializes an already allocated OFRPDNSResourceRecord with the * specified name, class, alias and time to live. * * @param name The name for the resource record - * @param recordClass The class code for the resource record + * @param DNSClass The class code for the resource record * @param mailbox The mailbox of the responsible person of the resource record * @param TXTDomainName A domain name that contains a TXT resource record for * the responsible person of the resource record * @param TTL The time to live for the resource record * @return An initialized OFRPDNSResourceRecord */ - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass mailbox: (OFString *)mailbox TXTDomainName: (OFString *)TXTDomainName TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER; @end @@ -488,20 +488,20 @@ * @brief The minimum TTL of the zone. */ @property (readonly, nonatomic) uint32_t minTTL; - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass recordType: (of_dns_resource_record_type_t)recordType TTL: (uint32_t)TTL OF_UNAVAILABLE; /*! * @brief Initializes an already allocated OFSOADNSResourceRecord with the * specified name, class, text data and time to live. * * @param name The name for the resource record - * @param recordClass The class code for the resource record + * @param DNSClass The class code for the resource record * @param primaryNameServer The the primary name server for the zone * @param responsiblePerson The mailbox of the person responsible for the zone * @param serialNumber The serial number of the original copy of the zone * @param refreshInterval The refresh interval of the zone * @param retryInterval The retry interval of the zone @@ -509,11 +509,11 @@ * @param minTTL The minimum TTL of the zone * @param TTL The time to live for the resource record * @return An initialized OFSOADNSResourceRecord */ - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass primaryNameServer: (OFString *)primaryNameServer responsiblePerson: (OFString *)responsiblePerson serialNumber: (uint32_t)serialNumber refreshInterval: (uint32_t)refreshInterval retryInterval: (uint32_t)retryInterval @@ -555,11 +555,11 @@ * @brief The port on the target of the resource record. */ @property (readonly, nonatomic) uint16_t port; - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass recordType: (of_dns_resource_record_type_t)recordType TTL: (uint32_t)TTL OF_UNAVAILABLE; /*! * @brief Initializes an already allocated OFSRVDNSResourceRecord with the @@ -597,41 +597,39 @@ * @brief The text of the resource record. */ @property (readonly, nonatomic) OFData *textData; - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass recordType: (of_dns_resource_record_type_t)recordType TTL: (uint32_t)TTL OF_UNAVAILABLE; /*! * @brief Initializes an already allocated OFTXTDNSResourceRecord with the * specified name, class, text data and time to live. * * @param name The name for the resource record - * @param recordClass The class code for the resource record + * @param DNSClass The class code for the resource record * @param textData The data for the resource record * @param TTL The time to live for the resource record * @return An initialized OFTXTDNSResourceRecord */ - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass textData: (OFData *)textData TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER; @end #ifdef __cplusplus extern "C" { #endif -extern OFString *_Nonnull of_dns_resource_record_class_to_string( - of_dns_resource_record_class_t recordClass); +extern OFString *_Nonnull of_dns_class_to_string(of_dns_class_t DNSClass); extern OFString *_Nonnull of_dns_resource_record_type_to_string( of_dns_resource_record_type_t recordType); -extern of_dns_resource_record_class_t of_dns_resource_record_class_parse( - OFString *_Nonnull string); +extern of_dns_class_t of_dns_class_parse(OFString *_Nonnull string); extern of_dns_resource_record_type_t of_dns_resource_record_type_parse( OFString *_Nonnull string); #ifdef __cplusplus } #endif OF_ASSUME_NONNULL_END Index: src/OFDNSResourceRecord.m ================================================================== --- src/OFDNSResourceRecord.m +++ src/OFDNSResourceRecord.m @@ -22,20 +22,19 @@ #import "OFInvalidArgumentException.h" #import "OFInvalidFormatException.h" OFString * -of_dns_resource_record_class_to_string( - of_dns_resource_record_class_t recordClass) +of_dns_class_to_string(of_dns_class_t DNSClass) { - switch (recordClass) { - case OF_DNS_RESOURCE_RECORD_CLASS_IN: + switch (DNSClass) { + case OF_DNS_CLASS_IN: return @"IN"; - case OF_DNS_RESOURCE_RECORD_CLASS_ANY: + case OF_DNS_CLASS_ANY: return @"any"; default: - return [OFString stringWithFormat: @"%u", recordClass]; + return [OFString stringWithFormat: @"%u", DNSClass]; } } OFString * of_dns_resource_record_type_to_string(of_dns_resource_record_type_t recordType) @@ -68,26 +67,25 @@ default: return [OFString stringWithFormat: @"%u", recordType]; } } -of_dns_resource_record_class_t of_dns_resource_record_class_parse( - OFString *string) +of_dns_class_t of_dns_class_parse(OFString *string) { void *pool = objc_autoreleasePoolPush(); - of_dns_resource_record_class_t recordClass; + of_dns_class_t DNSClass; string = string.uppercaseString; if ([string isEqual: @"IN"]) - recordClass = OF_DNS_RESOURCE_RECORD_CLASS_IN; + DNSClass = OF_DNS_CLASS_IN; else @throw [OFInvalidArgumentException exception]; objc_autoreleasePoolPop(pool); - return recordClass; + return DNSClass; } of_dns_resource_record_type_t of_dns_resource_record_type_parse( OFString *string) { @@ -125,23 +123,23 @@ return recordType; } @implementation OFDNSResourceRecord -@synthesize name = _name, recordClass = _recordClass, recordType = _recordType; +@synthesize name = _name, DNSClass = _DNSClass, recordType = _recordType; @synthesize TTL = _TTL; - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass recordType: (of_dns_resource_record_type_t)recordType TTL: (uint32_t)TTL { self = [super init]; @try { _name = [name copy]; - _recordClass = recordClass; + _DNSClass = DNSClass; _recordType = recordType; _TTL = TTL; } @catch (id e) { [self release]; @throw e; @@ -169,19 +167,18 @@ @"\tName = %@\n" @"\tClass = %@\n" @"\tType = %@\n" @"\tTTL = %" PRIu32 "\n" @">", - self.className, _name, - of_dns_resource_record_class_to_string(_recordClass), + self.className, _name, of_dns_class_to_string(_DNSClass), of_dns_resource_record_type_to_string(_recordType), _TTL]; } @end @implementation OFADNSResourceRecord - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass recordType: (of_dns_resource_record_type_t)recordType TTL: (uint32_t)TTL { OF_INVALID_INIT_METHOD } @@ -189,11 +186,11 @@ - (instancetype)initWithName: (OFString *)name address: (const of_socket_address_t *)address TTL: (uint32_t)TTL { self = [super initWithName: name - recordClass: OF_DNS_RESOURCE_RECORD_CLASS_IN + DNSClass: OF_DNS_CLASS_IN recordType: OF_DNS_RESOURCE_RECORD_TYPE_A TTL: TTL]; _address = *address; @@ -215,11 +212,11 @@ otherRecord = otherObject; if (otherRecord->_name != _name && ![otherRecord->_name isEqual: _name]) return false; - if (otherRecord->_recordClass != _recordClass) + if (otherRecord->_DNSClass != _DNSClass) return false; if (otherRecord->_recordType != _recordType) return false; @@ -234,12 +231,12 @@ uint32_t hash; OF_HASH_INIT(hash); OF_HASH_ADD_HASH(hash, _name.hash); - OF_HASH_ADD(hash, _recordClass >> 8); - OF_HASH_ADD(hash, _recordClass); + OF_HASH_ADD(hash, _DNSClass >> 8); + OF_HASH_ADD(hash, _DNSClass); OF_HASH_ADD(hash, _recordType >> 8); OF_HASH_ADD(hash, _recordType); OF_HASH_ADD_HASH(hash, of_socket_address_hash(&_address)); OF_HASH_FINALIZE(hash); @@ -260,11 +257,11 @@ } @end @implementation OFAAAADNSResourceRecord - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass recordType: (of_dns_resource_record_type_t)recordType TTL: (uint32_t)TTL { OF_INVALID_INIT_METHOD } @@ -272,11 +269,11 @@ - (instancetype)initWithName: (OFString *)name address: (const of_socket_address_t *)address TTL: (uint32_t)TTL { self = [super initWithName: name - recordClass: OF_DNS_RESOURCE_RECORD_CLASS_IN + DNSClass: OF_DNS_CLASS_IN recordType: OF_DNS_RESOURCE_RECORD_TYPE_AAAA TTL: TTL]; _address = *address; @@ -298,11 +295,11 @@ otherRecord = otherObject; if (otherRecord->_name != _name && ![otherRecord->_name isEqual: _name]) return false; - if (otherRecord->_recordClass != _recordClass) + if (otherRecord->_DNSClass != _DNSClass) return false; if (otherRecord->_recordType != _recordType) return false; @@ -317,12 +314,12 @@ uint32_t hash; OF_HASH_INIT(hash); OF_HASH_ADD_HASH(hash, _name.hash); - OF_HASH_ADD(hash, _recordClass >> 8); - OF_HASH_ADD(hash, _recordClass); + OF_HASH_ADD(hash, _DNSClass >> 8); + OF_HASH_ADD(hash, _DNSClass); OF_HASH_ADD(hash, _recordType >> 8); OF_HASH_ADD(hash, _recordType); OF_HASH_ADD_HASH(hash, of_socket_address_hash(&_address)); OF_HASH_FINALIZE(hash); @@ -345,24 +342,24 @@ @implementation OFCNAMEDNSResourceRecord @synthesize alias = _alias; - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass recordType: (of_dns_resource_record_type_t)recordType TTL: (uint32_t)TTL { OF_INVALID_INIT_METHOD } - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass alias: (OFString *)alias TTL: (uint32_t)TTL { self = [super initWithName: name - recordClass: recordClass + DNSClass: DNSClass recordType: OF_DNS_RESOURCE_RECORD_TYPE_CNAME TTL: TTL]; @try { _alias = [alias copy]; @@ -391,11 +388,11 @@ otherRecord = otherObject; if (otherRecord->_name != _name && ![otherRecord->_name isEqual: _name]) return false; - if (otherRecord->_recordClass != _recordClass) + if (otherRecord->_DNSClass != _DNSClass) return false; if (otherRecord->_recordType != _recordType) return false; @@ -411,12 +408,12 @@ uint32_t hash; OF_HASH_INIT(hash); OF_HASH_ADD_HASH(hash, _name.hash); - OF_HASH_ADD(hash, _recordClass >> 8); - OF_HASH_ADD(hash, _recordClass); + OF_HASH_ADD(hash, _DNSClass >> 8); + OF_HASH_ADD(hash, _DNSClass); OF_HASH_ADD(hash, _recordType >> 8); OF_HASH_ADD(hash, _recordType); OF_HASH_ADD_HASH(hash, _alias.hash); OF_HASH_FINALIZE(hash); @@ -431,34 +428,34 @@ @"\tName = %@\n" @"\tClass = %@\n" @"\tAlias = %@\n" @"\tTTL = %" PRIu32 "\n" @">", - self.className, _name, - of_dns_resource_record_class_to_string(_recordClass), _alias, _TTL]; + self.className, _name, of_dns_class_to_string(_DNSClass), _alias, + _TTL]; } @end @implementation OFHINFODNSResourceRecord @synthesize CPU = _CPU, OS = _OS; - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass recordType: (of_dns_resource_record_type_t)recordType TTL: (uint32_t)TTL { OF_INVALID_INIT_METHOD } - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass CPU: (OFString *)CPU OS: (OFString *)OS TTL: (uint32_t)TTL { self = [super initWithName: name - recordClass: recordClass + DNSClass: DNSClass recordType: OF_DNS_RESOURCE_RECORD_TYPE_HINFO TTL: TTL]; @try { _CPU = [CPU copy]; @@ -489,11 +486,11 @@ otherRecord = otherObject; if (otherRecord->_name != _name && ![otherRecord->_name isEqual: _name]) return false; - if (otherRecord->_recordClass != _recordClass) + if (otherRecord->_DNSClass != _DNSClass) return false; if (otherRecord->_recordType != _recordType) return false; @@ -511,12 +508,12 @@ uint32_t hash; OF_HASH_INIT(hash); OF_HASH_ADD_HASH(hash, _name.hash); - OF_HASH_ADD(hash, _recordClass >> 8); - OF_HASH_ADD(hash, _recordClass); + OF_HASH_ADD(hash, _DNSClass >> 8); + OF_HASH_ADD(hash, _DNSClass); OF_HASH_ADD(hash, _recordType >> 8); OF_HASH_ADD(hash, _recordType); OF_HASH_ADD_HASH(hash, _CPU.hash); OF_HASH_ADD_HASH(hash, _OS.hash); @@ -533,35 +530,34 @@ @"\tClass = %@\n" @"\tCPU = %@\n" @"\tOS = %@\n" @"\tTTL = %" PRIu32 "\n" @">", - self.className, _name, - of_dns_resource_record_class_to_string(_recordClass), _CPU, _OS, + self.className, _name, of_dns_class_to_string(_DNSClass), _CPU, _OS, _TTL]; } @end @implementation OFMXDNSResourceRecord @synthesize preference = _preference, mailExchange = _mailExchange; - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass recordType: (of_dns_resource_record_type_t)recordType TTL: (uint32_t)TTL { OF_INVALID_INIT_METHOD } - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass preference: (uint16_t)preference mailExchange: (OFString *)mailExchange TTL: (uint32_t)TTL { self = [super initWithName: name - recordClass: recordClass + DNSClass: DNSClass recordType: OF_DNS_RESOURCE_RECORD_TYPE_MX TTL: TTL]; @try { _preference = preference; @@ -591,11 +587,11 @@ otherRecord = otherObject; if (otherRecord->_name != _name && ![otherRecord->_name isEqual: _name]) return false; - if (otherRecord->_recordClass != _recordClass) + if (otherRecord->_DNSClass != _DNSClass) return false; if (otherRecord->_recordType != _recordType) return false; @@ -614,12 +610,12 @@ uint32_t hash; OF_HASH_INIT(hash); OF_HASH_ADD_HASH(hash, _name.hash); - OF_HASH_ADD(hash, _recordClass >> 8); - OF_HASH_ADD(hash, _recordClass); + OF_HASH_ADD(hash, _DNSClass >> 8); + OF_HASH_ADD(hash, _DNSClass); OF_HASH_ADD(hash, _recordType >> 8); OF_HASH_ADD(hash, _recordType); OF_HASH_ADD(hash, _preference >> 8); OF_HASH_ADD(hash, _preference); OF_HASH_ADD_HASH(hash, _mailExchange.hash); @@ -637,34 +633,33 @@ @"\tClass = %@\n" @"\tPreference = %" PRIu16 "\n" @"\tMail Exchange = %@\n" @"\tTTL = %" PRIu32 "\n" @">", - self.className, _name, - of_dns_resource_record_class_to_string(_recordClass), _preference, - _mailExchange, _TTL]; + self.className, _name, of_dns_class_to_string(_DNSClass), + _preference, _mailExchange, _TTL]; } @end @implementation OFNSDNSResourceRecord @synthesize authoritativeHost = _authoritativeHost; - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass recordType: (of_dns_resource_record_type_t)recordType TTL: (uint32_t)TTL { OF_INVALID_INIT_METHOD } - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass authoritativeHost: (OFString *)authoritativeHost TTL: (uint32_t)TTL { self = [super initWithName: name - recordClass: recordClass + DNSClass: DNSClass recordType: OF_DNS_RESOURCE_RECORD_TYPE_NS TTL: TTL]; @try { _authoritativeHost = [authoritativeHost copy]; @@ -693,11 +688,11 @@ otherRecord = otherObject; if (otherRecord->_name != _name && ![otherRecord->_name isEqual: _name]) return false; - if (otherRecord->_recordClass != _recordClass) + if (otherRecord->_DNSClass != _DNSClass) return false; if (otherRecord->_recordType != _recordType) return false; @@ -713,12 +708,12 @@ uint32_t hash; OF_HASH_INIT(hash); OF_HASH_ADD_HASH(hash, _name.hash); - OF_HASH_ADD(hash, _recordClass >> 8); - OF_HASH_ADD(hash, _recordClass); + OF_HASH_ADD(hash, _DNSClass >> 8); + OF_HASH_ADD(hash, _DNSClass); OF_HASH_ADD(hash, _recordType >> 8); OF_HASH_ADD(hash, _recordType); OF_HASH_ADD_HASH(hash, _authoritativeHost.hash); OF_HASH_FINALIZE(hash); @@ -733,34 +728,33 @@ @"\tName = %@\n" @"\tClass = %@\n" @"\tAuthoritative Host = %@\n" @"\tTTL = %" PRIu32 "\n" @">", - self.className, _name, - of_dns_resource_record_class_to_string(_recordClass), + self.className, _name, of_dns_class_to_string(_DNSClass), _authoritativeHost, _TTL]; } @end @implementation OFPTRDNSResourceRecord @synthesize domainName = _domainName; - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass recordType: (of_dns_resource_record_type_t)recordType TTL: (uint32_t)TTL { OF_INVALID_INIT_METHOD } - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass domainName: (OFString *)domainName TTL: (uint32_t)TTL { self = [super initWithName: name - recordClass: recordClass + DNSClass: DNSClass recordType: OF_DNS_RESOURCE_RECORD_TYPE_PTR TTL: TTL]; @try { _domainName = [domainName copy]; @@ -789,11 +783,11 @@ otherRecord = otherObject; if (otherRecord->_name != _name && ![otherRecord->_name isEqual: _name]) return false; - if (otherRecord->_recordClass != _recordClass) + if (otherRecord->_DNSClass != _DNSClass) return false; if (otherRecord->_recordType != _recordType) return false; @@ -809,12 +803,12 @@ uint32_t hash; OF_HASH_INIT(hash); OF_HASH_ADD_HASH(hash, _name.hash); - OF_HASH_ADD(hash, _recordClass >> 8); - OF_HASH_ADD(hash, _recordClass); + OF_HASH_ADD(hash, _DNSClass >> 8); + OF_HASH_ADD(hash, _DNSClass); OF_HASH_ADD(hash, _recordType >> 8); OF_HASH_ADD(hash, _recordType); OF_HASH_ADD_HASH(hash, _domainName.hash); OF_HASH_FINALIZE(hash); @@ -829,35 +823,34 @@ @"\tName = %@\n" @"\tClass = %@\n" @"\tDomain Name = %@\n" @"\tTTL = %" PRIu32 "\n" @">", - self.className, _name, - of_dns_resource_record_class_to_string(_recordClass), _domainName, - _TTL]; + self.className, _name, of_dns_class_to_string(_DNSClass), + _domainName, _TTL]; } @end @implementation OFRPDNSResourceRecord @synthesize mailbox = _mailbox, TXTDomainName = _TXTDomainName; - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass recordType: (of_dns_resource_record_type_t)recordType TTL: (uint32_t)TTL { OF_INVALID_INIT_METHOD } - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass mailbox: (OFString *)mailbox TXTDomainName: (OFString *)TXTDomainName TTL: (uint32_t)TTL { self = [super initWithName: name - recordClass: recordClass + DNSClass: DNSClass recordType: OF_DNS_RESOURCE_RECORD_TYPE_RP TTL: TTL]; @try { _mailbox = [mailbox copy]; @@ -888,11 +881,11 @@ otherRecord = otherObject; if (otherRecord->_name != _name && ![otherRecord->_name isEqual: _name]) return false; - if (otherRecord->_recordClass != _recordClass) + if (otherRecord->_DNSClass != _DNSClass) return false; if (otherRecord->_recordType != _recordType) return false; @@ -912,12 +905,12 @@ uint32_t hash; OF_HASH_INIT(hash); OF_HASH_ADD_HASH(hash, _name.hash); - OF_HASH_ADD(hash, _recordClass >> 8); - OF_HASH_ADD(hash, _recordClass); + OF_HASH_ADD(hash, _DNSClass >> 8); + OF_HASH_ADD(hash, _DNSClass); OF_HASH_ADD(hash, _recordType >> 8); OF_HASH_ADD(hash, _recordType); OF_HASH_ADD_HASH(hash, _mailbox.hash); OF_HASH_ADD_HASH(hash, _TXTDomainName.hash); @@ -934,12 +927,11 @@ @"\tClass = %@\n" @"\tMailbox = %@\n" @"\tTXT Domain Name = %@\n" @"\tTTL = %" PRIu32 "\n" @">", - self.className, _name, - of_dns_resource_record_class_to_string(_recordClass), _mailbox, + self.className, _name, of_dns_class_to_string(_DNSClass), _mailbox, _TXTDomainName, _TTL]; } @end @implementation OFSOADNSResourceRecord @@ -948,19 +940,19 @@ @synthesize serialNumber = _serialNumber, refreshInterval = _refreshInterval; @synthesize retryInterval = _retryInterval; @synthesize expirationInterval = _expirationInterval, minTTL = _minTTL; - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass recordType: (of_dns_resource_record_type_t)recordType TTL: (uint32_t)TTL { OF_INVALID_INIT_METHOD } - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass primaryNameServer: (OFString *)primaryNameServer responsiblePerson: (OFString *)responsiblePerson serialNumber: (uint32_t)serialNumber refreshInterval: (uint32_t)refreshInterval retryInterval: (uint32_t)retryInterval @@ -967,11 +959,11 @@ expirationInterval: (uint32_t)expirationInterval minTTL: (uint32_t)minTTL TTL: (uint32_t)TTL { self = [super initWithName: name - recordClass: recordClass + DNSClass: DNSClass recordType: OF_DNS_RESOURCE_RECORD_TYPE_SOA TTL: TTL]; @try { _primaryNameServer = [primaryNameServer copy]; @@ -1007,11 +999,11 @@ otherRecord = otherObject; if (otherRecord->_name != _name && ![otherRecord->_name isEqual: _name]) return false; - if (otherRecord->_recordClass != _recordClass) + if (otherRecord->_DNSClass != _DNSClass) return false; if (otherRecord->_recordType != _recordType) return false; @@ -1046,12 +1038,12 @@ uint32_t hash; OF_HASH_INIT(hash); OF_HASH_ADD_HASH(hash, _name.hash); - OF_HASH_ADD(hash, _recordClass >> 8); - OF_HASH_ADD(hash, _recordClass); + OF_HASH_ADD(hash, _DNSClass >> 8); + OF_HASH_ADD(hash, _DNSClass); OF_HASH_ADD(hash, _recordType >> 8); OF_HASH_ADD(hash, _recordType); OF_HASH_ADD_HASH(hash, _primaryNameServer.hash); OF_HASH_ADD_HASH(hash, _responsiblePerson.hash); OF_HASH_ADD(hash, _serialNumber >> 24); @@ -1093,12 +1085,11 @@ @"\tRetry Interval = %" PRIu32 "\n" @"\tExpiration Interval = %" PRIu32 "\n" @"\tMinimum TTL = %" PRIu32 "\n" @"\tTTL = %" PRIu32 "\n" @">", - self.className, _name, - of_dns_resource_record_class_to_string(_recordClass), + self.className, _name, of_dns_class_to_string(_DNSClass), _primaryNameServer, _responsiblePerson, _serialNumber, _refreshInterval, _retryInterval, _expirationInterval, _minTTL, _TTL]; } @end @@ -1106,11 +1097,11 @@ @implementation OFSRVDNSResourceRecord @synthesize priority = _priority, weight = _weight, target = _target; @synthesize port = _port; - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass recordType: (of_dns_resource_record_type_t)recordType TTL: (uint32_t)TTL { OF_INVALID_INIT_METHOD } @@ -1121,11 +1112,11 @@ target: (OFString *)target port: (uint16_t)port TTL: (uint32_t)TTL { self = [super initWithName: name - recordClass: OF_DNS_RESOURCE_RECORD_CLASS_IN + DNSClass: OF_DNS_CLASS_IN recordType: OF_DNS_RESOURCE_RECORD_TYPE_SRV TTL: TTL]; @try { _priority = priority; @@ -1157,11 +1148,11 @@ otherRecord = otherObject; if (otherRecord->_name != _name && ![otherRecord->_name isEqual: _name]) return false; - if (otherRecord->_recordClass != _recordClass) + if (otherRecord->_DNSClass != _DNSClass) return false; if (otherRecord->_recordType != _recordType) return false; @@ -1186,12 +1177,12 @@ uint32_t hash; OF_HASH_INIT(hash); OF_HASH_ADD_HASH(hash, _name.hash); - OF_HASH_ADD(hash, _recordClass >> 8); - OF_HASH_ADD(hash, _recordClass); + OF_HASH_ADD(hash, _DNSClass >> 8); + OF_HASH_ADD(hash, _DNSClass); OF_HASH_ADD(hash, _recordType >> 8); OF_HASH_ADD(hash, _recordType); OF_HASH_ADD(hash, _priority >> 8); OF_HASH_ADD(hash, _priority); OF_HASH_ADD(hash, _weight >> 8); @@ -1222,24 +1213,24 @@ @implementation OFTXTDNSResourceRecord @synthesize textData = _textData; - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass recordType: (of_dns_resource_record_type_t)recordType TTL: (uint32_t)TTL { OF_INVALID_INIT_METHOD } - (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass + DNSClass: (of_dns_class_t)DNSClass textData: (OFData *)textData TTL: (uint32_t)TTL { self = [super initWithName: name - recordClass: recordClass + DNSClass: DNSClass recordType: OF_DNS_RESOURCE_RECORD_TYPE_TXT TTL: TTL]; @try { _textData = [textData copy]; @@ -1268,11 +1259,11 @@ otherRecord = otherObject; if (otherRecord->_name != _name && ![otherRecord->_name isEqual: _name]) return false; - if (otherRecord->_recordClass != _recordClass) + if (otherRecord->_DNSClass != _DNSClass) return false; if (otherRecord->_recordType != _recordType) return false; @@ -1288,12 +1279,12 @@ uint32_t hash; OF_HASH_INIT(hash); OF_HASH_ADD_HASH(hash, _name.hash); - OF_HASH_ADD(hash, _recordClass >> 8); - OF_HASH_ADD(hash, _recordClass); + OF_HASH_ADD(hash, _DNSClass >> 8); + OF_HASH_ADD(hash, _DNSClass); OF_HASH_ADD(hash, _recordType >> 8); OF_HASH_ADD(hash, _recordType); OF_HASH_ADD_HASH(hash, _textData.hash); OF_HASH_FINALIZE(hash); @@ -1308,10 +1299,9 @@ @"\tName = %@\n" @"\tClass = %@\n" @"\tText Data = %@\n" @"\tTTL = %" PRIu32 "\n" @">", - self.className, _name, - of_dns_resource_record_class_to_string(_recordClass), _textData, + self.className, _name, of_dns_class_to_string(_DNSClass), _textData, _TTL]; } @end Index: src/OFDNSResponse.h ================================================================== --- src/OFDNSResponse.h +++ src/OFDNSResponse.h @@ -31,33 +31,45 @@ * * @brief A class storing a response from @ref OFDNSResolver. */ @interface OFDNSResponse: OFObject { - of_dns_response_records_t _Nullable _answerRecords; - of_dns_response_records_t _Nullable _authorityRecords; - of_dns_response_records_t _Nullable _additionalRecords; + OFString *_domainName; + of_dns_response_records_t _answerRecords; + of_dns_response_records_t _authorityRecords; + of_dns_response_records_t _additionalRecords; OF_RESERVE_IVARS(4) } +/*! + * @brief The domain name of the response. + */ +@property (readonly, nonatomic) OFString *domainName; + /*! * @brief The answer records of the response. + * + * This is a dictionary with the key being the domain name and the value being + * an array of @ref OFDNSResourceRecord. */ -@property OF_NULLABLE_PROPERTY (readonly, nonatomic) - of_dns_response_records_t answerRecords; +@property (readonly, nonatomic) of_dns_response_records_t answerRecords; /*! * @brief The authority records of the response. + * + * This is a dictionary with the key being the domain name and the value being + * an array of @ref OFDNSResourceRecord. */ -@property OF_NULLABLE_PROPERTY (readonly, nonatomic) - of_dns_response_records_t authorityRecords; +@property (readonly, nonatomic) of_dns_response_records_t authorityRecords; /*! * @brief The additional records of the response. + * + * This is a dictionary with the key being the domain name and the value being + * an array of @ref OFDNSResourceRecord. */ -@property OF_NULLABLE_PROPERTY (readonly, nonatomic) - of_dns_response_records_t additionalRecords; +@property (readonly, nonatomic) of_dns_response_records_t additionalRecords; /*! * @brief Creates a new, autoreleased OFDNSResponse. * * @param answerRecords The answer records of the response @@ -64,15 +76,14 @@ * @param authorityRecords The authority records of the response * @param additionalRecords The additional records of the response * @return A new, autoreleased OFDNSResponse */ + (instancetype) - responseWithAnswerRecords: (nullable of_dns_response_records_t)answerRecords - authorityRecords: (nullable of_dns_response_records_t) - authorityRecords - additionalRecords: (nullable of_dns_response_records_t) - additionalRecords; + responseWithDomainName: (OFString *)domainName + answerRecords: (of_dns_response_records_t)answerRecords + authorityRecords: (of_dns_response_records_t)authorityRecords + additionalRecords: (of_dns_response_records_t)additionalRecords; /*! * @brief Initializes an already allocated OFDNSResponse. * * @param answerRecords The answer records of the response @@ -79,14 +90,15 @@ * @param authorityRecords The authority records of the response * @param additionalRecords The additional records of the response * @return An initialized OFDNSResponse */ - (instancetype) - initWithAnswerRecords: (nullable of_dns_response_records_t)answerRecords - authorityRecords: (nullable of_dns_response_records_t)authorityRecords - additionalRecords: (nullable of_dns_response_records_t)additionalRecords + initWithDomainName: (OFString *)domainName + answerRecords: (of_dns_response_records_t)answerRecords + authorityRecords: (of_dns_response_records_t)authorityRecords + additionalRecords: (of_dns_response_records_t)additionalRecords OF_DESIGNATED_INITIALIZER; - (instancetype)init OF_UNAVAILABLE; @end OF_ASSUME_NONNULL_END Index: src/OFDNSResponse.m ================================================================== --- src/OFDNSResponse.m +++ src/OFDNSResponse.m @@ -20,33 +20,36 @@ #import "OFDNSResponse.h" #import "OFDictionary.h" #import "OFString.h" @implementation OFDNSResponse -@synthesize answerRecords = _answerRecords; +@synthesize domainName = _domainName, answerRecords = _answerRecords; @synthesize authorityRecords = _authorityRecords; @synthesize additionalRecords = _additionalRecords; + (instancetype) - responseWithAnswerRecords: (of_dns_response_records_t)answerRecords - authorityRecords: (of_dns_response_records_t)authorityRecords - additionalRecords: (of_dns_response_records_t)additionalRecords + responseWithDomainName: (OFString *)domainName + answerRecords: (of_dns_response_records_t)answerRecords + authorityRecords: (of_dns_response_records_t)authorityRecords + additionalRecords: (of_dns_response_records_t)additionalRecords { return [[[self alloc] - initWithAnswerRecords: answerRecords - authorityRecords: authorityRecords - additionalRecords: additionalRecords] autorelease]; + initWithDomainName: domainName + answerRecords: answerRecords + authorityRecords: authorityRecords + additionalRecords: additionalRecords] autorelease]; } -- (instancetype) - initWithAnswerRecords: (of_dns_response_records_t)answerRecords - authorityRecords: (of_dns_response_records_t)authorityRecords - additionalRecords: (of_dns_response_records_t)additionalRecords +- (instancetype)initWithDomainName: (OFString *)domainName + answerRecords: (of_dns_response_records_t)answerRecords + authorityRecords: (of_dns_response_records_t)authorityRecords + additionalRecords: (of_dns_response_records_t)additionalRecords { self = [super init]; @try { + _domainName = [domainName copy]; _answerRecords = [answerRecords copy]; _authorityRecords = [authorityRecords copy]; _additionalRecords = [additionalRecords copy]; } @catch (id e) { [self release]; @@ -61,34 +64,38 @@ OF_INVALID_INIT_METHOD } - (void)dealloc { + [_domainName release]; [_answerRecords release]; [_authorityRecords release]; [_additionalRecords release]; [super dealloc]; } - (bool)isEqual: (id)object { - OFDNSResponse *other; + OFDNSResponse *response; if (![object isKindOfClass: [OFDNSResponse class]]) return false; - other = object; - - if (other->_answerRecords != _answerRecords && - ![other->_answerRecords isEqual: _answerRecords]) - return false; - if (other->_authorityRecords != _authorityRecords && - ![other->_authorityRecords isEqual: _authorityRecords]) - return false; - if (other->_additionalRecords != _additionalRecords && - ![other->_additionalRecords isEqual: _additionalRecords]) + response = object; + + if (response->_domainName != _domainName && + ![response->_domainName isEqual: _domainName]) + return false; + if (response->_answerRecords != _answerRecords && + ![response->_answerRecords isEqual: _answerRecords]) + return false; + if (response->_authorityRecords != _authorityRecords && + ![response->_authorityRecords isEqual: _authorityRecords]) + return false; + if (response->_additionalRecords != _additionalRecords && + ![response->_additionalRecords isEqual: _additionalRecords]) return false; return true; } @@ -95,10 +102,11 @@ - (uint32_t)hash { uint32_t hash; OF_HASH_INIT(hash); + OF_HASH_ADD_HASH(hash, _domainName.hash); OF_HASH_ADD_HASH(hash, [_answerRecords hash]); OF_HASH_ADD_HASH(hash, [_authorityRecords hash]); OF_HASH_ADD_HASH(hash, [_additionalRecords hash]); OF_HASH_FINALIZE(hash); @@ -117,12 +125,14 @@ stringByReplacingOccurrencesOfString: @"\n" withString: @"\n\t"]; return [OFString stringWithFormat: @"<%@:\n" + @"\tDomain name = %@\n" @"\tAnswer records = %@\n" @"\tAuthority records = %@\n" @"\tAdditional records = %@\n" @">", - self.className, answerRecords, authorityRecords, additionalRecords]; + self.className, _domainName, answerRecords, authorityRecords, + additionalRecords]; } @end ADDED src/OFHostAddressResolver.h Index: src/OFHostAddressResolver.h ================================================================== --- src/OFHostAddressResolver.h +++ src/OFHostAddressResolver.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + * 2018, 2019 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFObject.h" +#import "OFDNSResolver.h" +#import "OFRunLoop.h" + +#import "socket.h" + +OF_ASSUME_NONNULL_BEGIN + +@class OFDNSResolverSettings; +@class OFDNSResourceRecord; +@class OFMutableArray OF_GENERIC(ObjectType); +@class OFMutableData; +@class OFString; + +@interface OFHostAddressResolver: OFObject +{ + OFString *_host; + of_socket_address_family_t _addressFamily; + OFDNSResolver *_resolver; + OFDNSResolverSettings *_settings; + of_run_loop_mode_t _Nullable _runLoopMode; + id _Nullable _delegate; + unsigned int _numExpectedResponses; + OFMutableData *_addresses; +} + +- (instancetype)initWithHost: (OFString *)host + addressFamily: (of_socket_address_family_t)addressFamily + resolver: (OFDNSResolver *)resolver + settings: (OFDNSResolverSettings *)settings + runLoopMode: (nullable of_run_loop_mode_t)runLoopMode + delegate: (nullable id )delegate; +- (void)asyncResolve; +- (OFData *)resolve; +@end + +OF_ASSUME_NONNULL_END ADDED src/OFHostAddressResolver.m Index: src/OFHostAddressResolver.m ================================================================== --- src/OFHostAddressResolver.m +++ src/OFHostAddressResolver.m @@ -0,0 +1,343 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + * 2018, 2019 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFHostAddressResolver.h" +#import "OFDNSResolver.h" +#import "OFDNSResolverSettings.h" +#import "OFData.h" +#import "OFDate.h" +#import "OFDictionary.h" +#import "OFRunLoop.h" +#import "OFString.h" +#import "OFTimer.h" + +#import "OFInvalidArgumentException.h" +#import "OFInvalidFormatException.h" +#import "OFResolveHostFailedException.h" + +@interface OFHostAddressResolverDelegate: OFObject +{ +@public + bool _done; + OFData *_addresses; + id _exception; +} +@end + +static const of_run_loop_mode_t resolveRunLoopMode = + @"of_host_address_resolver_resolve_mode"; + +static bool +addressForRecord(OF_KINDOF(OFDNSResourceRecord *) record, + const of_socket_address_t **address, + of_socket_address_family_t addressFamily) +{ + switch ([record recordType]) { +#ifdef OF_HAVE_IPV6 + case OF_DNS_RESOURCE_RECORD_TYPE_AAAA: + if (addressFamily != OF_SOCKET_ADDRESS_FAMILY_IPV6 && + addressFamily != OF_SOCKET_ADDRESS_FAMILY_ANY) + return false; + break; +#endif + case OF_DNS_RESOURCE_RECORD_TYPE_A: + if (addressFamily != OF_SOCKET_ADDRESS_FAMILY_IPV4 && + addressFamily != OF_SOCKET_ADDRESS_FAMILY_ANY) + return false; + break; + default: + return false; + } + + *address = [record address]; + return true; +} + +static void +callDelegateInMode(of_run_loop_mode_t runLoopMode, + id delegate, OFDNSResolver *resolver, + OFString *host, OFData *addresses, id exception) +{ + SEL selector = @selector(resolver:didResolveHost:addresses:exception:); + + if ([delegate respondsToSelector: selector]) { + OFTimer *timer = [OFTimer + timerWithTimeInterval: 0 + target: delegate + selector: selector + object: resolver + object: host + object: addresses + object: exception + repeats: false]; + [[OFRunLoop currentRunLoop] addTimer: timer + forMode: runLoopMode]; + } +} + +@implementation OFHostAddressResolver: OFObject +- (instancetype)initWithHost: (OFString *)host + addressFamily: (of_socket_address_family_t)addressFamily + resolver: (OFDNSResolver *)resolver + settings: (OFDNSResolverSettings *)settings + runLoopMode: (of_run_loop_mode_t)runLoopMode + delegate: (id )delegate +{ + self = [super init]; + + @try { + _host = [host copy]; + _addressFamily = addressFamily; + _resolver = [resolver retain]; + _settings = [settings copy]; + _runLoopMode = [runLoopMode copy]; + _delegate = [delegate retain]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_host release]; + [_resolver release]; + [_settings release]; + [_runLoopMode release]; + [_delegate release]; + [_addresses release]; + + [super dealloc]; +} + +- (void)resolver: (OFDNSResolver *)resolver + didPerformQuery: (OFDNSQuery *)query + response: (OFDNSResponse *)response + exception: (id)exception +{ + _numExpectedResponses--; + + if (exception != nil && _numExpectedResponses == 0) { + if ([_delegate respondsToSelector: + @selector(resolver:didResolveHost:addresses:exception:)]) + [_delegate resolver: _resolver + didResolveHost: _host + addresses: nil + exception: exception]; + return; + } + + for (OF_KINDOF(OFDNSResourceRecord *) record in + [response.answerRecords objectForKey: query.domainName]) { + const of_socket_address_t *address; + OFDNSQuery *CNAMEQuery; + + if ([record DNSClass] != OF_DNS_CLASS_IN) + continue; + + if (addressForRecord(record, &address, _addressFamily)) { + [_addresses addItem: address]; + continue; + } + + if ([record recordType] != OF_DNS_RESOURCE_RECORD_TYPE_CNAME) + continue; + + /* FIXME: Check if it's already in answers */ + CNAMEQuery = [OFDNSQuery queryWithDomainName: [record alias] + DNSClass: OF_DNS_CLASS_IN + recordType: query.recordType]; + _numExpectedResponses++; + [_resolver asyncPerformQuery: CNAMEQuery + runLoopMode: _runLoopMode + delegate: self]; + } + + if (_numExpectedResponses > 0) + return; + + [_addresses makeImmutable]; + + if ([_delegate respondsToSelector: + @selector(resolver:didResolveHost:addresses:exception:)]) + [_delegate resolver: _resolver + didResolveHost: _host + addresses: _addresses + exception: exception]; +} + +- (void)sendQueries +{ + /* FIXME: Add seach domain */ + OFString *domainName = _host; + OFDNSQuery *query; + +#ifdef OF_HAVE_IPV6 + if (_addressFamily == OF_SOCKET_ADDRESS_FAMILY_IPV6 || + _addressFamily == OF_SOCKET_ADDRESS_FAMILY_ANY) { + query = [OFDNSQuery + queryWithDomainName: domainName + DNSClass: OF_DNS_CLASS_IN + recordType: OF_DNS_RESOURCE_RECORD_TYPE_AAAA]; + _numExpectedResponses++; + [_resolver asyncPerformQuery: query + runLoopMode: _runLoopMode + delegate: self]; + } +#endif + + if (_addressFamily == OF_SOCKET_ADDRESS_FAMILY_IPV4 || + _addressFamily == OF_SOCKET_ADDRESS_FAMILY_ANY) { + query = [OFDNSQuery + queryWithDomainName: domainName + DNSClass: OF_DNS_CLASS_IN + recordType: OF_DNS_RESOURCE_RECORD_TYPE_A]; + _numExpectedResponses++; + [_resolver asyncPerformQuery: query + runLoopMode: _runLoopMode + delegate: self]; + } +} + +- (void)asyncResolve +{ + void *pool = objc_autoreleasePoolPush(); + OFArray OF_GENERIC(OFString *) *aliases; + + @try { + of_socket_address_t address = + of_socket_address_parse_ip(_host, 0); + OFData *addresses = nil; + id exception = nil; + + if (_addressFamily == address.family || + _addressFamily == OF_SOCKET_ADDRESS_FAMILY_ANY) + addresses = [OFData dataWithItems: &address + itemSize: sizeof(address) + count: 1]; + else + exception = [OFInvalidArgumentException exception]; + + callDelegateInMode(_runLoopMode, _delegate, _resolver, _host, + addresses, exception); + + objc_autoreleasePoolPop(pool); + return; + } @catch (OFInvalidFormatException *e) { + } + + if ((aliases = [_settings->_staticHosts objectForKey: _host]) != nil) { + OFMutableData *addresses = [OFMutableData + dataWithItemSize: sizeof(of_socket_address_t)]; + id exception = nil; + + for (OFString *alias in aliases) { + of_socket_address_t address; + + @try { + address = of_socket_address_parse_ip(alias, 0); + } @catch (OFInvalidFormatException *e) { + continue; + } + + if (_addressFamily != address.family && + _addressFamily != OF_SOCKET_ADDRESS_FAMILY_ANY) + continue; + + [addresses addItem: &address]; + } + + [addresses makeImmutable]; + + if (addresses.count == 0) { + addresses = nil; + exception = [OFResolveHostFailedException + exceptionWithHost: _host + addressFamily: _addressFamily + error: OF_DNS_RESOLVER_ERROR_NO_RESULT]; + } + + callDelegateInMode(_runLoopMode, _delegate, _resolver, _host, + addresses, exception); + + objc_autoreleasePoolPop(pool); + return; + } + + _addresses = [[OFMutableData alloc] + initWithItemSize: sizeof(of_socket_address_t)]; + + [self sendQueries]; + + objc_autoreleasePoolPop(pool); +} + +- (OFData *)resolve +{ + void *pool = objc_autoreleasePoolPush(); + OFRunLoop *runLoop = [OFRunLoop currentRunLoop]; + OFHostAddressResolverDelegate *delegate; + OFData *ret; + + delegate = [[[OFHostAddressResolverDelegate alloc] init] autorelease]; + _runLoopMode = [resolveRunLoopMode copy]; + _delegate = [delegate retain]; + + [self asyncResolve]; + + while (!delegate->_done) + [runLoop runMode: resolveRunLoopMode + beforeDate: nil]; + + /* Cleanup */ + [runLoop runMode: resolveRunLoopMode + beforeDate: [OFDate date]]; + + if (delegate->_exception != nil) + @throw delegate->_exception; + + ret = [delegate->_addresses copy]; + + objc_autoreleasePoolPop(pool); + + return [ret autorelease]; +} +@end + +@implementation OFHostAddressResolverDelegate +- (void)dealloc +{ + [_addresses release]; + [_exception release]; + + [super dealloc]; +} + +- (void)resolver: (OFDNSResolver *)resolver + didResolveHost: (OFString *)host + addresses: (OFData *)addresses + exception: (id)exception +{ + _addresses = [addresses copy]; + _exception = [exception retain]; + _done = true; +} +@end Index: src/OFTCPSocket.m ================================================================== --- src/OFTCPSocket.m +++ src/OFTCPSocket.m @@ -319,22 +319,22 @@ #endif [self didConnect]; } -- (void)resolver: (OFDNSResolver *)resolver - didResolveDomainName: (OFString *)domainName - socketAddresses: (OFData *)socketAddresses - exception: (id)exception +- (void)resolver: (OFDNSResolver *)resolver + didResolveHost: (OFString *)host + addresses: (OFData *)addresses + exception: (id)exception { if (exception != nil) { _exception = [exception retain]; [self didConnect]; return; } - _socketAddresses = [socketAddresses copy]; + _socketAddresses = [addresses copy]; [self tryNextAddressWithRunLoopMode: [OFRunLoop currentRunLoop].currentMode]; } @@ -367,14 +367,14 @@ return; } @catch (OFInvalidFormatException *e) { } [[OFThread DNSResolver] - asyncResolveSocketAddressesForHost: host - addressFamily: OF_SOCKET_ADDRESS_FAMILY_ANY - runLoopMode: runLoopMode - delegate: self]; + asyncResolveAddressesForHost: host + addressFamily: OF_SOCKET_ADDRESS_FAMILY_ANY + runLoopMode: runLoopMode + delegate: self]; } - (void)sendSOCKS5Request { OFData *data = [OFData dataWithItems: "\x05\x01\x00" @@ -810,12 +810,12 @@ if (_SOCKS5Host != nil) @throw [OFNotImplementedException exceptionWithSelector: _cmd object: self]; socketAddresses = [[OFThread DNSResolver] - resolveSocketAddressesForHost: host - addressFamily: OF_SOCKET_ADDRESS_FAMILY_ANY]; + resolveAddressesForHost: host + addressFamily: OF_SOCKET_ADDRESS_FAMILY_ANY]; address = *(of_socket_address_t *)[socketAddresses itemAtIndex: 0]; of_socket_address_set_port(&address, port); if ((_socket = socket(address.sockaddr.sockaddr.sa_family, Index: src/OFUDPSocket.m ================================================================== --- src/OFUDPSocket.m +++ src/OFUDPSocket.m @@ -264,12 +264,12 @@ if (_socket != INVALID_SOCKET) @throw [OFAlreadyConnectedException exceptionWithSocket: self]; socketAddresses = [[OFThread DNSResolver] - resolveSocketAddressesForHost: host - addressFamily: OF_SOCKET_ADDRESS_FAMILY_ANY]; + resolveAddressesForHost: host + addressFamily: OF_SOCKET_ADDRESS_FAMILY_ANY]; address = *(of_socket_address_t *)[socketAddresses itemAtIndex: 0]; of_socket_address_set_port(&address, port); port = [self of_bindToAddress: &address Index: src/ObjFW.h ================================================================== --- src/ObjFW.h +++ src/ObjFW.h @@ -146,11 +146,10 @@ #import "OFException.h" #ifdef OF_HAVE_SOCKETS # import "OFAcceptFailedException.h" # import "OFAlreadyConnectedException.h" # import "OFBindFailedException.h" -# import "OFDNSQueryFailedException.h" #endif #import "OFChangeCurrentDirectoryPathFailedException.h" #import "OFChecksumMismatchException.h" #ifdef OF_HAVE_THREADS # import "OFConditionBroadcastFailedException.h" @@ -164,10 +163,15 @@ #import "OFCopyItemFailedException.h" #import "OFCreateDirectoryFailedException.h" #import "OFCreateSymbolicLinkFailedException.h" #ifdef OF_WINDOWS # import "OFCreateWindowsRegistryKeyFailedException.h" +#endif +#ifdef OF_HAVE_SOCKETS +# import "OFDNSQueryFailedException.h" +#endif +#ifdef OF_WINDOWS # import "OFDeleteWindowsRegistryKeyFailedException.h" # import "OFDeleteWindowsRegistryValueFailedException.h" #endif #import "OFEnumerationMutationException.h" #ifdef OF_HAVE_FILES @@ -210,10 +214,13 @@ #import "OFOutOfMemoryException.h" #import "OFOutOfRangeException.h" #import "OFReadFailedException.h" #import "OFReadOrWriteFailedException.h" #import "OFRemoveItemFailedException.h" +#ifdef OF_HAVE_SOCKETS +# import "OFResolveHostFailedException.h" +#endif #import "OFRetrieveItemAttributesFailedException.h" #import "OFSandboxActivationFailedException.h" #import "OFSeekFailedException.h" #import "OFSetItemAttributesFailedException.h" #import "OFSetOptionFailedException.h" Index: src/exceptions/Makefile ================================================================== --- src/exceptions/Makefile +++ src/exceptions/Makefile @@ -59,11 +59,12 @@ OFBindFailedException.m \ OFConnectionFailedException.m \ OFDNSQueryFailedException.m \ OFHTTPRequestFailedException.m \ OFListenFailedException.m \ - OFObserveFailedException.m + OFObserveFailedException.m \ + OFResolveHostFailedException.m SRCS_THREADS = OFConditionBroadcastFailedException.m \ OFConditionSignalFailedException.m \ OFConditionStillWaitingException.m \ OFConditionWaitFailedException.m \ OFThreadJoinFailedException.m \ Index: src/exceptions/OFDNSQueryFailedException.h ================================================================== --- src/exceptions/OFDNSQueryFailedException.h +++ src/exceptions/OFDNSQueryFailedException.h @@ -24,11 +24,11 @@ /*! * @class OFDNSQueryFailedException \ * OFDNSQueryFailedException.h ObjFW/OFDNSQueryFailedException.h * - * @brief An exception indicating the resolving a host failed. + * @brief An exception indicating that a DNS query failed. */ @interface OFDNSQueryFailedException: OFException { OFDNSQuery *_query; of_dns_resolver_error_t _error; @@ -43,26 +43,34 @@ * @brief The error from the resolver. */ @property (readonly, nonatomic) of_dns_resolver_error_t error; /*! - * @brief Creates a new, autoreleased resolve host failed exception. + * @brief Creates a new, autoreleased DNS query failed exception. * * @param query The query which could not be performed * @param error The error from the resolver * @return A new, autoreleased address translation failed exception */ + (instancetype)exceptionWithQuery: (OFDNSQuery *)query error: (of_dns_resolver_error_t)error; /*! - * @brief Initializes an already allocated address translation failed exception. + * @brief Initializes an already allocated DNS query failed exception. * * @param query The query which could not be performed * @param error The error from the resolver * @return An initialized address translation failed exception */ - (instancetype)initWithQuery: (OFDNSQuery *)query error: (of_dns_resolver_error_t)error; @end + +#ifdef __cplusplus +extern "C" { +#endif +extern OFString *of_dns_resolver_error_to_string(of_dns_resolver_error_t error); +#ifdef __cplusplus +} +#endif OF_ASSUME_NONNULL_END Index: src/exceptions/OFDNSQueryFailedException.m ================================================================== --- src/exceptions/OFDNSQueryFailedException.m +++ src/exceptions/OFDNSQueryFailedException.m @@ -17,10 +17,39 @@ #include "config.h" #import "OFDNSQueryFailedException.h" #import "OFString.h" + +OFString * +of_dns_resolver_error_to_string(of_dns_resolver_error_t error) +{ + switch (error) { + case OF_DNS_RESOLVER_ERROR_TIMEOUT: + return @"The query timed out."; + case OF_DNS_RESOLVER_ERROR_CANCELED: + return @"The query was canceled."; + case OF_DNS_RESOLVER_ERROR_NO_RESULT: + return @"No result for the specified host with the specified " + @"type and class."; + case OF_DNS_RESOLVER_ERROR_SERVER_INVALID_FORMAT: + return @"The server considered the query to be malformed."; + case OF_DNS_RESOLVER_ERROR_SERVER_FAILURE: + return @"The server was unable to process due to an internal " + @"error."; + case OF_DNS_RESOLVER_ERROR_SERVER_NAME_ERROR: + return @"The server returned an error that the domain does not " + @"exist."; + case OF_DNS_RESOLVER_ERROR_SERVER_NOT_IMPLEMENTED: + return @"The server does not have support for the requested " + @"query."; + case OF_DNS_RESOLVER_ERROR_SERVER_REFUSED: + return @"The server refused the query."; + default: + return @"Unknown error."; + } +} @implementation OFDNSQueryFailedException @synthesize query = _query, error = _error; + (instancetype)exceptionWithQuery: (OFDNSQuery *)query @@ -53,44 +82,10 @@ [super dealloc]; } - (OFString *)description { - OFString *error; - - switch (_error) { - case OF_DNS_RESOLVER_ERROR_TIMEOUT: - error = @"The query timed out."; - break; - case OF_DNS_RESOLVER_ERROR_CANCELED: - error = @"The query was canceled."; - break; - case OF_DNS_RESOLVER_ERROR_NO_RESULT: - error = @"No result for the specified host with the specified " - @"type and class."; - break; - case OF_DNS_RESOLVER_ERROR_SERVER_INVALID_FORMAT: - error = @"The server considered the query to be malformed."; - break; - case OF_DNS_RESOLVER_ERROR_SERVER_FAILURE: - error = @"The server was unable to process due to an internal " - @"error."; - break; - case OF_DNS_RESOLVER_ERROR_SERVER_NAME_ERROR: - error = @"The server returned an error that the domain does " - @"not exist."; - break; - case OF_DNS_RESOLVER_ERROR_SERVER_NOT_IMPLEMENTED: - error = @"The server does not have support for the requested " - @"query."; - case OF_DNS_RESOLVER_ERROR_SERVER_REFUSED: - error = @"The server refused the query."; - break; - default: - error = @"Unknown error."; - break; - } - return [OFString stringWithFormat: - @"Query %@ could not be performed: %@", _query, error]; + @"DNS query %@ could not be performed: %@", + _query, of_dns_resolver_error_to_string(_error)]; } @end ADDED src/exceptions/OFResolveHostFailedException.h Index: src/exceptions/OFResolveHostFailedException.h ================================================================== --- src/exceptions/OFResolveHostFailedException.h +++ src/exceptions/OFResolveHostFailedException.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + * 2018, 2019 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#import "OFException.h" +#import "OFDNSResolver.h" + +OF_ASSUME_NONNULL_BEGIN + +/*! + * @class OFResolveHostFailedException \ + * OFResolveHostFailedException.h ObjFW/OFResolveHostFailedException.h + * + * @brief An exception indicating that resolving a host failed. + */ +@interface OFResolveHostFailedException: OFException +{ + OFString *_host; + of_socket_address_family_t _addressFamily; + of_dns_resolver_error_t _error; +} + +/*! + * @brief The host which could not be resolved. + */ +@property (readonly, nonatomic) OFString *host; + +/*! + * @brief The address family for which the host could not be resolved. + */ +@property (readonly, nonatomic) of_socket_address_family_t addressFamily; + +/*! + * @brief The error from the resolver. + */ +@property (readonly, nonatomic) of_dns_resolver_error_t error; + +/*! + * @brief Creates a new, autoreleased resolve host failed exception. + * + * @param host The host which could not be resolved + * @param addressFamily The address family for which the host could not be + * resolved + * @param error The error from the resolver + * @return A new, autoreleased address translation failed exception + */ ++ (instancetype)exceptionWithHost: (OFString *)host + addressFamily: (of_socket_address_family_t)addressFamily + error: (of_dns_resolver_error_t)error; + +/*! + * @brief Initializes an already allocated resolve host failed exception. + * + * @param host The host which could not be resolved + * @param addressFamily The address family for which the host could not be + * resolved + * @param error The error from the resolver + * @return An initialized address translation failed exception + */ +- (instancetype)initWithHost: (OFString *)host + addressFamily: (of_socket_address_family_t)addressFamily + error: (of_dns_resolver_error_t)error; +@end + +OF_ASSUME_NONNULL_END ADDED src/exceptions/OFResolveHostFailedException.m Index: src/exceptions/OFResolveHostFailedException.m ================================================================== --- src/exceptions/OFResolveHostFailedException.m +++ src/exceptions/OFResolveHostFailedException.m @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + * 2018, 2019 + * Jonathan Schleifer + * + * All rights reserved. + * + * This file is part of ObjFW. It may be distributed under the terms of the + * Q Public License 1.0, which can be found in the file LICENSE.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * Public License, either version 2 or 3, which can be found in the file + * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this + * file. + */ + +#include "config.h" + +#import "OFResolveHostFailedException.h" +#import "OFDNSQueryFailedException.h" +#import "OFString.h" + +@implementation OFResolveHostFailedException +@synthesize host = _host, addressFamily = _addressFamily, error = _error; + ++ (instancetype)exceptionWithHost: (OFString *)host + addressFamily: (of_socket_address_family_t)addressFamily + error: (of_dns_resolver_error_t)error +{ + return [[[self alloc] initWithHost: host + addressFamily: addressFamily + error: error] autorelease]; +} + +- (instancetype)initWithHost: (OFString *)host + addressFamily: (of_socket_address_family_t)addressFamily + error: (of_dns_resolver_error_t)error +{ + self = [super init]; + + @try { + _host = [host copy]; + _addressFamily = addressFamily; + _error = error; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_host release]; + + [super dealloc]; +} + +- (OFString *)description +{ + return [OFString stringWithFormat: + @"The host %@ could not be resolved: %@", + _host, of_dns_resolver_error_to_string(_error)]; +} +@end Index: utils/ofdns/OFDNS.m ================================================================== --- utils/ofdns/OFDNS.m +++ utils/ofdns/OFDNS.m @@ -27,32 +27,29 @@ @end OF_APPLICATION_DELEGATE(OFDNS) @implementation OFDNS -- (void)resolver: (OFDNSResolver *)resolver - didResolveDomainName: (OFString *)domainName - response: (OFDNSResponse *)response - exception: (id)exception +- (void)resolver: (OFDNSResolver *)resolver + didPerformQuery: (OFDNSQuery *)query + response: (OFDNSResponse *)response + exception: (id)exception { if (exception != nil) { [of_stderr writeFormat: @"Failed to resolve: %@\n", exception]; [OFApplication terminateWithStatus: 1]; } - [of_stdout writeFormat: @"FQDN: %@\n" - @"Response: %@\n", - domainName, response]; + [of_stdout writeFormat: @"%@\n", response]; [OFApplication terminate]; } - (void)applicationDidFinishLaunching { OFArray OF_GENERIC(OFString *) *arguments = [OFApplication arguments]; - of_dns_resource_record_class_t recordClass = - OF_DNS_RESOURCE_RECORD_CLASS_ANY; + of_dns_class_t DNSClass = OF_DNS_CLASS_ANY; of_dns_resource_record_type_t recordType = OF_DNS_RESOURCE_RECORD_TYPE_ALL; OFDNSQuery *query; OFDNSResolver *resolver; @@ -80,21 +77,20 @@ if (arguments.count >= 2) recordType = of_dns_resource_record_type_parse( [arguments objectAtIndex: 1]); if (arguments.count >= 3) - recordClass = of_dns_resource_record_class_parse( - [arguments objectAtIndex: 2]); + DNSClass = of_dns_class_parse([arguments objectAtIndex: 2]); if (arguments.count >= 4) { resolver.configReloadInterval = 0; resolver.nameServers = [arguments objectsInRange: of_range(3, 1)]; } - query = [OFDNSQuery queryWithHost: [arguments objectAtIndex: 0] - recordClass: recordClass - recordType: recordType]; + query = [OFDNSQuery queryWithDomainName: [arguments objectAtIndex: 0] + DNSClass: DNSClass + recordType: recordType]; [resolver asyncPerformQuery: query delegate: self]; } @end Index: utils/ofhttp/OFHTTP.m ================================================================== --- utils/ofhttp/OFHTTP.m +++ utils/ofhttp/OFHTTP.m @@ -34,17 +34,17 @@ #import "OFTCPSocket.h" #import "OFTLSSocket.h" #import "OFURL.h" #import "OFConnectionFailedException.h" -#import "OFDNSQueryFailedException.h" #import "OFHTTPRequestFailedException.h" #import "OFInvalidFormatException.h" #import "OFInvalidServerReplyException.h" #import "OFOpenItemFailedException.h" #import "OFOutOfRangeException.h" #import "OFReadFailedException.h" +#import "OFResolveHostFailedException.h" #import "OFRetrieveItemAttributesFailedException.h" #import "OFUnsupportedProtocolException.h" #import "OFWriteFailedException.h" #import "ProgressBar.h" @@ -610,18 +610,18 @@ - (void)client: (OFHTTPClient *)client didFailWithException: (id)e request: (OFHTTPRequest *)request { - if ([e isKindOfClass: [OFDNSQueryFailedException class]]) { + if ([e isKindOfClass: [OFResolveHostFailedException class]]) { if (!_quiet) [of_stdout writeString: @"\n"]; [of_stderr writeLine: - OF_LOCALIZED(@"download_dns_query_failed", + OF_LOCALIZED(@"download_resolve_host_failed", @"%[prog]: Failed to download <%[url]>!\n" - @" DNS query failed: %[exception]", + @" Failed to resolve host: %[exception]", @"prog", [OFApplication programName], @"url", request.URL.string, @"exception", e)]; } else if ([e isKindOfClass: [OFConnectionFailedException class]]) { if (!_quiet) Index: utils/ofhttp/lang/de.json ================================================================== --- utils/ofhttp/lang/de.json +++ utils/ofhttp/lang/de.json @@ -36,13 +36,13 @@ ], "output_only_with_one_url": [ "%[prog]: -o / --output kann nicht mit mehr als einer URL benutzt ", "werden!" ], - "download_dns_query_failed": [ + "download_resolve_host_failed": [ "%[prog]: Fehler beim Download von <%[url]>!\n", - " DNS-Abfrage fehlgeschlagen: %[exception]" + " Host auflösen fehlgeschlagen: %[exception]" ], "download_failed_connection_failed": [ "%[prog]: Fehler beim Download von <%[url]>!\n", " Verbindung fehlgeschlagen: %[exception]" ],