Index: src/OFColor.h ================================================================== --- src/OFColor.h +++ src/OFColor.h @@ -17,11 +17,11 @@ #import "OFObject.h" OF_ASSUME_NONNULL_BEGIN -/** +/*! * @class OFColor OFColor.h ObjFW/OFColor.h * * @brief A class for storing a color. */ @interface OFColor: OFObject Index: src/OFDNSResolver.h ================================================================== --- src/OFDNSResolver.h +++ src/OFDNSResolver.h @@ -25,10 +25,41 @@ @class OFDictionary OF_GENERIC(KeyType, ObjectType); @class OFMutableDictionary OF_GENERIC(KeyType, ObjectType); @class OFNumber; @class OFUDPSocket; +/*! + * @enum of_dns_resolver_error_t OFDNSResolver.h ObjFW/OFDNSResolver.h + * + * @brief An enum describing why resolving a host failed. + */ +typedef enum of_dns_resolver_error_t { + /*! An unknown error */ + OF_DNS_RESOLVER_ERROR_UNKNOWN, + /*! The query timed out */ + OF_DNS_RESOLVER_ERROR_TIMEOUT, + /*! The query was canceled */ + OF_DNS_RESOLVER_ERROR_CANCELED, + /*! + * No result for the specified host with the specified type and class. + * + * This is only used in situations where this is an error, e.g. when + * trying to connect to a host. + */ + OF_DNS_RESOLVER_ERROR_NO_RESULT, + /*! The server considered the query to be malformed */ + OF_DNS_RESOLVER_ERROR_SERVER_INVALID_FORMAT, + /*! The server was unable to process due to an internal error */ + OF_DNS_RESOLVER_ERROR_SERVER_FAILURE, + /*! The server returned an error that the domain does not exist */ + OF_DNS_RESOLVER_ERROR_SERVER_NAME_ERROR, + /*! The server does not have support for the requested query */ + OF_DNS_RESOLVER_ERROR_SERVER_NOT_IMPLEMENTED, + /*! The server refused the query */ + OF_DNS_RESOLVER_ERROR_SERVER_REFUSED +} of_dns_resolver_error_t; + /*! * @class OFDNSResolver OFDNSResolver.h ObjFW/OFDNSResolver.h * * @brief A class for resolving DNS names. */ @@ -124,8 +155,13 @@ recordClass: (of_dns_resource_record_class_t)recordClass recordType: (of_dns_resource_record_type_t)recordType target: (id)target selector: (SEL)selector context: (nullable id)context; + +/*! + * @brief Closes all sockets and cancels all ongoing requests. + */ +- (void)close; @end OF_ASSUME_NONNULL_END Index: src/OFDNSResolver.m ================================================================== --- src/OFDNSResolver.m +++ src/OFDNSResolver.m @@ -36,10 +36,11 @@ #import "OFInvalidArgumentException.h" #import "OFInvalidServerReplyException.h" #import "OFOpenItemFailedException.h" #import "OFOutOfRangeException.h" +#import "OFResolveHostFailedException.h" #import "OFTruncatedDataException.h" #ifdef OF_WINDOWS # define interface struct # include @@ -64,34 +65,40 @@ */ @interface OFDNSResolver_context: OFObject { OFString *_host; + of_dns_resource_record_class_t _recordClass; + of_dns_resource_record_type_t _recordType; + OFNumber *_ID; OFArray OF_GENERIC(OFString *) *_nameServers, *_searchDomains; size_t _nameServersIndex, _searchDomainsIndex; - OFNumber *_ID; OFMutableData *_queryData; id _target; SEL _selector; id _userContext; } @property (readonly, nonatomic) OFString *host; +@property (readonly, nonatomic) of_dns_resource_record_class_t recordClass; +@property (readonly, nonatomic) of_dns_resource_record_type_t recordType; +@property (readonly, nonatomic) OFNumber *ID; @property (readonly, nonatomic) OFArray OF_GENERIC(OFString *) *nameServers; @property (readonly, nonatomic) OFArray OF_GENERIC(OFString *) *searchDomains; @property (nonatomic) size_t nameServersIndex; @property (nonatomic) size_t searchDomainsIndex; -@property (readonly, nonatomic) OFNumber *ID; @property (readonly, nonatomic) OFMutableData *queryData; @property (readonly, nonatomic) id target; @property (readonly, nonatomic) SEL selector; @property (readonly, nonatomic) id userContext; - (instancetype)initWithHost: (OFString *)host + recordClass: (of_dns_resource_record_class_t)recordClass + recordType: (of_dns_resource_record_type_t)recordType + ID: (OFNumber *)ID nameServers: (OFArray OF_GENERIC(OFString *) *)nameServers searchDomains: (OFArray OF_GENERIC(OFString *) *)searchDomains - ID: (OFNumber *)ID queryData: (OFMutableData *)queryData target: (id)target selector: (SEL)selector userContext: (id)userContext; @end @@ -488,33 +495,37 @@ recordType: recordType TTL: TTL] autorelease]; } @implementation OFDNSResolver_context -@synthesize host = _host, nameServers = _nameServers; +@synthesize host = _host, recordClass = _recordClass, recordType = _recordType; +@synthesize ID = _ID, nameServers = _nameServers; @synthesize searchDomains = _searchDomains; @synthesize nameServersIndex = _nameServersIndex; -@synthesize searchDomainsIndex = _searchDomainsIndex, ID = _ID; -@synthesize queryData = _queryData, target = _target, selector = _selector; -@synthesize userContext = _userContext; +@synthesize searchDomainsIndex = _searchDomainsIndex, queryData = _queryData; +@synthesize target = _target, selector = _selector, userContext = _userContext; - (instancetype)initWithHost: (OFString *)host + recordClass: (of_dns_resource_record_class_t)recordClass + recordType: (of_dns_resource_record_type_t)recordType + ID: (OFNumber *)ID nameServers: (OFArray OF_GENERIC(OFString *) *)nameServers searchDomains: (OFArray OF_GENERIC(OFString *) *)searchDomains - ID: (OFNumber *)ID queryData: (OFMutableData *)queryData target: (id)target selector: (SEL)selector userContext: (id)userContext { self = [super init]; @try { _host = [host copy]; - _nameServers = [nameServers copy]; - _searchDomains = [searchDomains copy]; + _recordClass = recordClass; + _recordType = recordType; _ID = [ID retain]; + _nameServers = [nameServers copy]; + _searchDomains = [searchDomains copy]; _queryData = [queryData retain]; _target = [target retain]; _selector = selector; _userContext = [userContext retain]; } @catch (id e) { @@ -526,13 +537,13 @@ } - (void)dealloc { [_host release]; + [_ID release]; [_nameServers release]; [_searchDomains release]; - [_ID release]; [_queryData release]; [_target release]; [_userContext release]; [super dealloc]; @@ -904,10 +915,11 @@ queryData = [DNSResolverContext queryData]; @try { const unsigned char *queryBuffer; size_t i; + of_dns_resolver_error_t error; uint16_t numQuestions, numAnswers; if (length < 12) @throw [OFTruncatedDataException exception]; @@ -926,24 +938,40 @@ /* TC */ if (buffer[2] & 0x02) @throw [OFTruncatedDataException exception]; - /* RA */ - if ((buffer[3] & 0x80) == 0) - /* Server doesn't handle recursive queries */ - /* TODO: Better exception */ - @throw [OFInvalidServerReplyException exception]; - /* RCODE */ switch (buffer[3] & 0x0F) { case 0: break; + case 1: + error = OF_DNS_RESOLVER_ERROR_SERVER_INVALID_FORMAT; + break; + case 2: + error = OF_DNS_RESOLVER_ERROR_SERVER_FAILURE; + break; + case 3: + error = OF_DNS_RESOLVER_ERROR_SERVER_NAME_ERROR; + break; + case 4: + error = OF_DNS_RESOLVER_ERROR_SERVER_NOT_IMPLEMENTED; + break; + case 5: + error = OF_DNS_RESOLVER_ERROR_SERVER_REFUSED; + break; default: - /* TODO: Better exception */ - @throw [OFInvalidServerReplyException exception]; + error = OF_DNS_RESOLVER_ERROR_UNKNOWN; + break; } + + if (buffer[3] & 0x0F) + @throw [OFResolveHostFailedException + exceptionWithHost: [DNSResolverContext host] + recordClass: [DNSResolverContext recordClass] + recordType: [DNSResolverContext recordType] + error: error]; numQuestions = (buffer[4] << 8) | buffer[5]; numAnswers = (buffer[6] << 8) | buffer[7]; answers = [OFMutableArray arrayWithCapacity: numAnswers]; @@ -1119,13 +1147,15 @@ [data addItems: &tmp count: 2]; DNSResolverContext = [[[OFDNSResolver_context alloc] initWithHost: host + recordClass: recordClass + recordType: recordType + ID: ID nameServers: _nameServers searchDomains: _searchDomains - ID: ID queryData: data target: target selector: selector userContext: context] autorelease]; [_queries setObject: DNSResolverContext @@ -1169,10 +1199,14 @@ objc_autoreleasePoolPop(pool); } - (void)close { + void *pool = objc_autoreleasePoolPush(); + OFEnumerator *enumerator; + OFDNSResolver_context *DNSResolverContext; + [_IPv4Socket cancelAsyncRequests]; [_IPv4Socket close]; [_IPv4Socket release]; _IPv4Socket = nil; @@ -1180,7 +1214,30 @@ [_IPv6Socket cancelAsyncRequests]; [_IPv6Socket close]; [_IPv6Socket release]; _IPv6Socket = nil; #endif + + enumerator = [_queries objectEnumerator]; + while ((DNSResolverContext = [enumerator nextObject]) != nil) { + id target = [[[DNSResolverContext target] retain] autorelease]; + SEL selector = [DNSResolverContext selector]; + void (*callback)(id, SEL, OFArray *, id, id) = + (void (*)(id, SEL, OFArray *, id, id)) + [target methodForSelector: selector]; + OFResolveHostFailedException *exception; + + exception = [OFResolveHostFailedException + exceptionWithHost: [DNSResolverContext host] + recordClass: [DNSResolverContext recordClass] + recordType: [DNSResolverContext recordType] + error: OF_DNS_RESOLVER_ERROR_CANCELED]; + + callback(target, selector, nil, + [DNSResolverContext userContext], exception); + } + + [_queries removeAllObjects]; + + objc_autoreleasePoolPop(pool); } @end Index: src/OFSystemInfo.h ================================================================== --- src/OFSystemInfo.h +++ src/OFSystemInfo.h @@ -91,19 +91,19 @@ * * @return The minor version of ObjFW */ + (unsigned int)ObjFWVersionMinor; -/** +/*! * @brief Returns the name of the operating system the application is running * on. * * @return The name of the operating system the application is running on */ + (nullable OFString *)operatingSystemName; -/** +/*! * @brief Returns the version of the operating system the application is * running on. * * @return The version of the operating system the application is running on */ Index: src/ObjFW.h ================================================================== --- src/ObjFW.h +++ src/ObjFW.h @@ -130,13 +130,13 @@ #import "OFAllocFailedException.h" #import "OFException.h" #ifdef OF_HAVE_SOCKETS # import "OFAcceptFailedException.h" -# import "OFAddressTranslationFailedException.h" # import "OFAlreadyConnectedException.h" # import "OFBindFailedException.h" +# import "OFResolveHostFailedException.h" #endif #import "OFChangeCurrentDirectoryPathFailedException.h" #import "OFChecksumMismatchException.h" #ifdef OF_HAVE_THREADS # import "OFConditionBroadcastFailedException.h" Index: src/exceptions/Makefile ================================================================== --- src/exceptions/Makefile +++ src/exceptions/Makefile @@ -53,17 +53,17 @@ ${USE_SRCS_THREADS} \ ${USE_SRCS_WINDOWS} SRCS_FILES = OFGetCurrentDirectoryPathFailedException.m SRCS_PLUGINS = OFLoadPluginFailedException.m SRCS_SOCKETS = OFAcceptFailedException.m \ - OFAddressTranslationFailedException.m \ OFAlreadyConnectedException.m \ OFBindFailedException.m \ OFConnectionFailedException.m \ OFHTTPRequestFailedException.m \ OFListenFailedException.m \ - OFObserveFailedException.m + OFObserveFailedException.m \ + OFResolveHostFailedException.m SRCS_THREADS = OFConditionBroadcastFailedException.m \ OFConditionSignalFailedException.m \ OFConditionStillWaitingException.m \ OFConditionWaitFailedException.m \ OFThreadJoinFailedException.m \ DELETED src/exceptions/OFAddressTranslationFailedException.h Index: src/exceptions/OFAddressTranslationFailedException.h ================================================================== --- src/exceptions/OFAddressTranslationFailedException.h +++ src/exceptions/OFAddressTranslationFailedException.h @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, - * 2018 - * 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" - -#ifndef OF_HAVE_SOCKETS -# error No sockets available! -#endif - -OF_ASSUME_NONNULL_BEGIN - -/*! - * @class OFAddressTranslationFailedException \ - * OFAddressTranslationFailedException.h \ - * ObjFW/OFAddressTranslationFailedException.h - * - * @brief An exception indicating the translation of an address failed. - */ -@interface OFAddressTranslationFailedException: OFException -{ - OFString *_host; - int _error; -} - -/*! - * @brief The host for which the address translation was requested. - */ -@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFString *host; - -/*! - * @brief Creates a new, autoreleased address translation failed exception. - * - * @param host The host for which translation was requested - * @return A new, autoreleased address translation failed exception - */ -+ (instancetype)exceptionWithHost: (nullable OFString *)host; - -+ (instancetype)exceptionWithError: (int)error; -+ (instancetype)exceptionWithHost: (nullable OFString *)host - error: (int)error; - -/*! - * @brief Initializes an already allocated address translation failed exception. - * - * @param host The host for which translation was requested - * @return An initialized address translation failed exception - */ -- (instancetype)initWithHost: (nullable OFString *)host; - -- (instancetype)initWithError: (int)error; -- (instancetype)initWithHost: (nullable OFString *)host - error: (int)error OF_DESIGNATED_INITIALIZER; -@end - -OF_ASSUME_NONNULL_END DELETED src/exceptions/OFAddressTranslationFailedException.m Index: src/exceptions/OFAddressTranslationFailedException.m ================================================================== --- src/exceptions/OFAddressTranslationFailedException.m +++ src/exceptions/OFAddressTranslationFailedException.m @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, - * 2018 - * 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 "OFAddressTranslationFailedException.h" -#import "OFString.h" - -#import "OFInitializationFailedException.h" -#import "OFLockFailedException.h" -#import "OFUnlockFailedException.h" - -#include "socket_helpers.h" - -#if !defined(HAVE_THREADSAFE_GETADDRINFO) && defined(OF_HAVE_THREADS) -# include "threading.h" - -static of_mutex_t mutex; -#endif - -@implementation OFAddressTranslationFailedException -@synthesize host = _host; - -#if !defined(HAVE_THREADSAFE_GETADDRINFO) && defined(OF_HAVE_THREADS) -+ (void)initialize -{ - if (self != [OFAddressTranslationFailedException class]) - return; - - if (!of_mutex_new(&mutex)) - @throw [OFInitializationFailedException - exceptionWithClass: [self class]]; -} -#endif - -+ (instancetype)exceptionWithHost: (OFString *)host -{ - return [[[self alloc] initWithHost: host] autorelease]; -} - -+ (instancetype)exceptionWithError: (int)error -{ - return [[[self alloc] initWithError: error] autorelease]; -} - -+ (instancetype)exceptionWithHost: (OFString *)host - error: (int)error -{ - return [[[self alloc] initWithHost: host - error: error] autorelease]; -} - -- (instancetype)init -{ - return [self initWithHost: nil - error: 0]; -} - -- (instancetype)initWithHost: (OFString *)host -{ - return [self initWithHost: host - error: 0]; -} - -- (instancetype)initWithError: (int)error -{ - return [self initWithHost: nil - error: error]; -} - -- (instancetype)initWithHost: (OFString *)host - error: (int)error -{ - self = [super init]; - - @try { - _host = [host copy]; - _error = error; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - [_host release]; - - [super dealloc]; -} - -- (OFString *)description -{ - /* FIXME: Add proper description for Win32 */ -#ifndef OF_WINDOWS - if (_error == 0) { -#endif - if (_host != nil) - return [OFString stringWithFormat: - @"The host %@ could not be translated to an " - @"address!", - _host]; - else - return @"An address could not be translated!"; -#ifndef OF_WINDOWS - } - -# ifdef HAVE_GETADDRINFO -# if defined(OF_HAVE_THREADS) && !defined(HAVE_THREADSAFE_GETADDRINFO) - if (!of_mutex_lock(&mutex)) - @throw [OFLockFailedException exception]; - - @try { -# endif - if (_host != nil) - return [OFString stringWithFormat: - @"The host %@ could not be translated to an " - @"address: %s", - _host, gai_strerror(_error)]; - else - return [OFString stringWithFormat: - @"An address could not be translated: %s", - gai_strerror(_error)]; -# if defined(OF_HAVE_THREADS) && !defined(HAVE_THREADSAFE_GETADDRINFO) - } @finally { - if (!of_mutex_unlock(&mutex)) - @throw [OFUnlockFailedException exception]; - } -# endif -# else -# ifdef OF_HAVE_THREADS - if (!of_mutex_lock(&mutex)) - @throw [OFLockFailedException exception]; - - @try { -# endif - if (_host != nil) - return [OFString stringWithFormat: - @"The host %@ could not be translated to an " - "address: %s", - _host, hstrerror(_error)]; - else - return [OFString stringWithFormat: - @"An address could not be translated: %s", - hstrerror(_error)]; -# ifdef OF_HAVE_THREADS - } @finally { - if (!of_mutex_unlock(&mutex)) - @throw [OFUnlockFailedException exception]; - } -# endif -# endif -#endif -} -@end ADDED src/exceptions/OFResolveHostFailedException.h Index: src/exceptions/OFResolveHostFailedException.h ================================================================== --- src/exceptions/OFResolveHostFailedException.h +++ src/exceptions/OFResolveHostFailedException.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + * 2018 + * 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" +#import "OFDNSResourceRecord.h" + +OF_ASSUME_NONNULL_BEGIN + +/*! + * @class OFResolveHostFailedException \ + * OFResolveHostFailedException.h ObjFW/OFResolveHostFailedException.h + * + * @brief An exception indicating the resolving a host failed. + */ +@interface OFResolveHostFailedException: OFException +{ + OFString *_host; + of_dns_resource_record_class_t _recordClass; + of_dns_resource_record_type_t _recordType; + of_dns_resolver_error_t _error; +} + +/*! + * @brief The host which could not be resolved. + */ +@property (readonly, nonatomic) OFString *host; + +/*! + * @brief The class code for the resource record to resolve to. + */ +@property (readonly, nonatomic) of_dns_resource_record_class_t recordClass; + +/*! + * @brief The type code for the resource record to resolve to. + */ +@property (readonly, nonatomic) of_dns_resource_record_type_t recordType; + +/*! + * @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 recordClass The class code for the resource record to resolve to + * @param recordType The type code for the resource record to resolve to + * @param error The error from the resolver + * @return A new, autoreleased address translation failed exception + */ ++ (instancetype)exceptionWithHost: (OFString *)host + recordClass: (of_dns_resource_record_class_t)recordClass + recordType: (of_dns_resource_record_type_t)recordType + error: (of_dns_resolver_error_t)error; + +/*! + * @brief Initializes an already allocated address translation failed exception. + * + * @param host The host for which translation was requested + * @param recordClass The class code for the resource record to resolve to + * @param recordType The type code for the resource record to resolve to + * @param error The error from the resolver + * @return An initialized address translation failed exception + */ +- (instancetype)initWithHost: (OFString *)host + recordClass: (of_dns_resource_record_class_t)recordClass + recordType: (of_dns_resource_record_type_t)recordType + 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,105 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, + * 2018 + * 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 "OFString.h" + +@implementation OFResolveHostFailedException +@synthesize host = _host, recordClass = _recordClass, recordType = _recordType; +@synthesize error = _error; + ++ (instancetype)exceptionWithHost: (OFString *)host + recordClass: (of_dns_resource_record_class_t)recordClass + recordType: (of_dns_resource_record_type_t)recordType + error: (of_dns_resolver_error_t)error +{ + return [[[self alloc] initWithHost: host + recordClass: recordClass + recordType: recordType + error: error] autorelease]; +} + +- (instancetype)initWithHost: (OFString *)host + recordClass: (of_dns_resource_record_class_t)recordClass + recordType: (of_dns_resource_record_type_t)recordType + error: (of_dns_resolver_error_t)error +{ + self = [super init]; + + @try { + _host = [host copy]; + _recordClass = recordClass; + _recordType = recordType; + _error = error; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_host release]; + + [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: + @"The host %@ could not be resolved: %@", _host, error]; +} +@end Index: src/resolver.m ================================================================== --- src/resolver.m +++ src/resolver.m @@ -30,19 +30,19 @@ #if !defined(HAVE_THREADSAFE_GETADDRINFO) && defined(OF_HAVE_THREADS) # include "threading.h" #endif -#import "OFAddressTranslationFailedException.h" #import "OFInitializationFailedException.h" #import "OFInvalidArgumentException.h" #import "OFOutOfMemoryException.h" #import "OFOutOfRangeException.h" #if !defined(HAVE_THREADSAFE_GETADDRINFO) && defined(OF_HAVE_THREADS) # import "OFLockFailedException.h" # import "OFUnlockFailedException.h" #endif +#import "OFResolveHostFailedException.h" #import "socket_helpers.h" #if !defined(HAVE_THREADSAFE_GETADDRINFO) && defined(OF_HAVE_THREADS) static of_mutex_t mutex; @@ -73,26 +73,29 @@ if (!of_mutex_lock(&mutex)) @throw [OFLockFailedException exception]; @try { # endif - int error; - - if ((error = getaddrinfo([host UTF8String], portCString, &hints, - &res0)) != 0) - @throw [OFAddressTranslationFailedException + if (getaddrinfo([host UTF8String], portCString, &hints, + &res0) != 0) + @throw [OFResolveHostFailedException exceptionWithHost: host - error: error]; + recordClass: OF_DNS_RESOURCE_RECORD_CLASS_IN + recordType: 0 + error: OF_DNS_RESOLVER_ERROR_UNKNOWN]; count = 0; for (res = res0; res != NULL; res = res->ai_next) count++; if (count == 0) { freeaddrinfo(res0); - @throw [OFAddressTranslationFailedException - exceptionWithHost: host]; + @throw [OFResolveHostFailedException + exceptionWithHost: host + recordClass: OF_DNS_RESOURCE_RECORD_CLASS_IN + recordType: 0 + error: OF_DNS_RESOLVER_ERROR_NO_RESULT]; } if ((ret = calloc(count + 1, sizeof(*ret))) == NULL) { freeaddrinfo(res0); @throw [OFOutOfMemoryException @@ -190,21 +193,26 @@ return ret; } if ((he = gethostbyname((const void *)[host UTF8String])) == NULL || he->h_addrtype != AF_INET) - @throw [OFAddressTranslationFailedException + @throw [OFResolveHostFailedException exceptionWithHost: host - error: h_errno]; + recordClass: OF_DNS_RESOURCE_RECORD_CLASS_IN + recordType: 0 + error: OF_DNS_RESOLVER_ERROR_UNKNOWN]; count = 0; for (ip = (char **)he->h_addr_list; *ip != NULL; ip++) count++; if (count == 0) - @throw [OFAddressTranslationFailedException - exceptionWithHost: host]; + @throw [OFResolveHostFailedException + exceptionWithHost: host + recordClass: OF_DNS_RESOURCE_RECORD_CLASS_IN + recordType: 0 + error: OF_DNS_RESOLVER_ERROR_NO_RESULT]; if ((ret = calloc(count + 1, sizeof(*ret))) == NULL) @throw [OFOutOfMemoryException exceptionWithRequestedSize: (count + 1) * sizeof(*ret)]; Index: utils/ofhttp/OFHTTP.m ================================================================== --- utils/ofhttp/OFHTTP.m +++ utils/ofhttp/OFHTTP.m @@ -33,18 +33,18 @@ #import "OFTLSSocket.h" #import "OFURL.h" #import "OFLocale.h" #import "OFSandbox.h" -#import "OFAddressTranslationFailedException.h" #import "OFConnectionFailedException.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" @@ -564,18 +564,18 @@ - (void)client: (OFHTTPClient *)client didEncounterException: (id)e request: (OFHTTPRequest *)request context: (id)context { - if ([e isKindOfClass: [OFAddressTranslationFailedException class]]) { + if ([e isKindOfClass: [OFResolveHostFailedException class]]) { if (!_quiet) [of_stdout writeString: @"\n"]; [of_stderr writeLine: - OF_LOCALIZED(@"download_failed_address_translation", + OF_LOCALIZED(@"download_failed_resolve_host_failed", @"%[prog]: Failed to download <%[url]>!\n" - @" Address translation 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 @@ -32,11 +32,11 @@ ], "output_only_with_one_url": [ "%[prog]: -o / --output kann nicht mit mehr als einer URL benutzt ", "werden!" ], - "download_failed_address_translation": [ + "download_failed_resolve_host_failed": [ "%[prog]: Fehler beim Download von <%[url]>!\n", " Adressauflösung fehlgeschlagen: %[exception]" ], "download_failed_connection_failed": [ "%[prog]: Fehler beim Download von <%[url]>!\n",