Index: src/OFDNSResolver.m ================================================================== --- src/OFDNSResolver.m +++ src/OFDNSResolver.m @@ -248,149 +248,115 @@ static OF_KINDOF(OFDNSResourceRecord *) createResourceRecord(OFString *name, of_dns_resource_record_class_t recordClass, of_dns_resource_record_type_t recordType, uint32_t TTL, const unsigned char *buffer, size_t length, size_t i, size_t dataLength) { - uint16_t preference; - id data; - - if (recordClass == OF_DNS_RESOURCE_RECORD_CLASS_IN) { - size_t j; - - switch (recordType) { - case OF_DNS_RESOURCE_RECORD_TYPE_A: - if (dataLength != 4) - @throw [OFInvalidServerReplyException - exception]; - - data = [OFString stringWithFormat: - @"%u.%u.%u.%u", - buffer[i], buffer[i + 1], - buffer[i + 2], buffer[i + 3]]; - - return [[[OFADNSResourceRecord alloc] - initWithName: name - recordClass: recordClass - recordType: recordType - data: data - TTL: TTL] autorelease]; - case OF_DNS_RESOURCE_RECORD_TYPE_NS: - j = i; - - data = parseName(buffer, length, &j, - ALLOWED_POINTER_LEVELS); - - if (j != i + dataLength) - @throw [OFInvalidServerReplyException - exception]; - - return [[[OFNSDNSResourceRecord alloc] - initWithName: name - recordClass: recordClass - recordType: recordType - data: data - TTL: TTL] autorelease]; - case OF_DNS_RESOURCE_RECORD_TYPE_CNAME: - j = i; - - data = parseName(buffer, length, &j, - ALLOWED_POINTER_LEVELS); - - if (j != i + dataLength) - @throw [OFInvalidServerReplyException - exception]; - - return [[[OFCNAMEDNSResourceRecord alloc] - initWithName: name - recordClass: recordClass - recordType: recordType - data: data - TTL: TTL] autorelease]; - case OF_DNS_RESOURCE_RECORD_TYPE_PTR: - j = i; - - data = parseName(buffer, length, &j, - ALLOWED_POINTER_LEVELS); - - if (j != i + dataLength) - @throw [OFInvalidServerReplyException - exception]; - - return [[[OFPTRDNSResourceRecord alloc] - initWithName: name - recordClass: recordClass - recordType: recordType - data: data - TTL: TTL] autorelease]; - case OF_DNS_RESOURCE_RECORD_TYPE_MX: - if (dataLength < 2) - @throw [OFInvalidServerReplyException - exception]; - - preference = (buffer[i] << 8) | buffer[i + 1]; - - j = i + 2; - - data = parseName(buffer, length, &j, - ALLOWED_POINTER_LEVELS); - - if (j != i + dataLength) - @throw [OFInvalidServerReplyException - exception]; - - return [[[OFMXDNSResourceRecord alloc] - initWithName: name - recordClass: recordClass - recordType: recordType - preference: preference - data: data - TTL: TTL] autorelease]; - case OF_DNS_RESOURCE_RECORD_TYPE_TXT: - data = [OFData dataWithItems: &buffer[i] - count: dataLength]; - - return [[[OFTXTDNSResourceRecord alloc] - initWithName: name - recordClass: recordClass - recordType: recordType - data: data - TTL: TTL] autorelease]; - case OF_DNS_RESOURCE_RECORD_TYPE_AAAA: - if (dataLength != 16) - @throw [OFInvalidServerReplyException - exception]; - - data = parseAAAAData(&buffer[i]); - - return [[[OFAAAADNSResourceRecord alloc] - initWithName: name - recordClass: recordClass - recordType: recordType - data: data - TTL: TTL] autorelease]; - default: - data = [OFData dataWithItems: &buffer[i] - count: dataLength]; - - return [[[OFDNSResourceRecord alloc] - initWithName: name - recordClass: recordClass - recordType: recordType - data: data - TTL: TTL] autorelease]; - } - } else { - data = [OFData dataWithItems: &buffer[i] - count: dataLength]; - - return [[[OFDNSResourceRecord alloc] - initWithName: name - recordClass: recordClass - recordType: recordType - data: data - TTL: TTL] autorelease]; - } + if (recordType == OF_DNS_RESOURCE_RECORD_TYPE_A && + recordClass == OF_DNS_RESOURCE_RECORD_CLASS_IN) { + OFString *address; + + if (dataLength != 4) + @throw [OFInvalidServerReplyException exception]; + + address = [OFString stringWithFormat: @"%u.%u.%u.%u", + buffer[i], buffer[i + 1], buffer[i + 2], buffer[i + 3]]; + + return [[[OFADNSResourceRecord alloc] + initWithName: name + address: address + TTL: TTL] autorelease]; + } else if (recordType == OF_DNS_RESOURCE_RECORD_TYPE_NS) { + size_t j = i; + OFString *authoritativeHost = parseName(buffer, length, &j, + ALLOWED_POINTER_LEVELS); + + if (j != i + dataLength) + @throw [OFInvalidServerReplyException exception]; + + return [[[OFNSDNSResourceRecord alloc] + initWithName: name + recordClass: recordClass + authoritativeHost: authoritativeHost + TTL: TTL] autorelease]; + } else if (recordType == OF_DNS_RESOURCE_RECORD_TYPE_CNAME) { + size_t j = i; + OFString *alias = parseName(buffer, length, &j, + ALLOWED_POINTER_LEVELS); + + if (j != i + dataLength) + @throw [OFInvalidServerReplyException exception]; + + return [[[OFCNAMEDNSResourceRecord alloc] + initWithName: name + recordClass: recordClass + alias: alias + TTL: TTL] autorelease]; + } else if (recordType == OF_DNS_RESOURCE_RECORD_TYPE_PTR) { + size_t j = i; + OFString *domainName = parseName(buffer, length, &j, + ALLOWED_POINTER_LEVELS); + + if (j != i + dataLength) + @throw [OFInvalidServerReplyException exception]; + + return [[[OFPTRDNSResourceRecord alloc] + initWithName: name + recordClass: recordClass + domainName: domainName + TTL: TTL] autorelease]; + } else if (recordType == OF_DNS_RESOURCE_RECORD_TYPE_MX) { + uint16_t preference; + size_t j; + OFString *mailExchange; + + if (dataLength < 2) + @throw [OFInvalidServerReplyException exception]; + + preference = (buffer[i] << 8) | buffer[i + 1]; + + j = i + 2; + mailExchange = parseName(buffer, length, &j, + ALLOWED_POINTER_LEVELS); + + if (j != i + dataLength) + @throw [OFInvalidServerReplyException exception]; + + return [[[OFMXDNSResourceRecord alloc] + initWithName: name + recordClass: recordClass + 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 + textData: textData + TTL: TTL] autorelease]; + } else if (recordType == OF_DNS_RESOURCE_RECORD_TYPE_AAAA && + recordClass == OF_DNS_RESOURCE_RECORD_CLASS_IN) { + OFString *address; + + if (dataLength != 16) + @throw [OFInvalidServerReplyException + exception]; + + address = parseAAAAData(&buffer[i]); + + return [[[OFAAAADNSResourceRecord alloc] + initWithName: name + address: address + TTL: TTL] autorelease]; + } else + return [[[OFDNSResourceRecord alloc] + initWithName: name + recordClass: recordClass + recordType: recordType + TTL: TTL] autorelease]; } @implementation OFDNSResolver_context @synthesize host = _host, nameServers = _nameServers; @synthesize searchDomains = _searchDomains; Index: src/OFDNSResourceRecord.h ================================================================== --- src/OFDNSResourceRecord.h +++ src/OFDNSResourceRecord.h @@ -46,10 +46,12 @@ OF_DNS_RESOURCE_RECORD_TYPE_CNAME = 5, /*! SOA */ OF_DNS_RESOURCE_RECORD_TYPE_SOA = 6, /*! PTR */ OF_DNS_RESOURCE_RECORD_TYPE_PTR = 12, + /*! HINFO */ + OF_DNS_RESOURCE_RECORD_TYPE_HINFO = 13, /*! MX */ OF_DNS_RESOURCE_RECORD_TYPE_MX = 15, /*! TXT */ OF_DNS_RESOURCE_RECORD_TYPE_TXT = 16, /*! AAAA */ @@ -66,11 +68,10 @@ @interface OFDNSResourceRecord: OFObject { OFString *_name; of_dns_resource_record_class_t _recordClass; of_dns_resource_record_type_t _recordType; - id _data; uint32_t _TTL; } /** * @brief The domain name to which the resource record belongs. @@ -85,75 +86,132 @@ /*! * @brief The resource record type code. */ @property (readonly, nonatomic) of_dns_resource_record_type_t recordType; -/*! - * The class and type-dependent data of the resource. - */ -@property (readonly, nonatomic) id data; - /*! * @brief The number of seconds after which the resource record should be * discarded from the cache. */ @property (readonly, nonatomic) uint32_t TTL; /*! * @brief Initializes an already allocated OFDNSResourceRecord with the - * specified name, resource record class, resource record type, resource - * record data and resource record time to live. + * specified name, class, type, data and time to live. * - * @param name The name of the resource record + * @param name The name for the resource record * @param recordClass The class code for the resource record * @param recordType The type code for the resource record - * @param data The data for the resource record * @param TTL The time to live for the resource record */ - (instancetype)initWithName: (OFString *)name recordClass: (of_dns_resource_record_class_t)recordClass recordType: (of_dns_resource_record_type_t)recordType - data: (id)data TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER; @end /*! * @class OFADNSResourceRecord OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h * * @brief A class representing an A DNS resource record. */ @interface OFADNSResourceRecord: OFDNSResourceRecord +{ + OFString *_address; +} + +/*! + * The IPv4 address of the resource record. + */ +@property (readonly, nonatomic) OFString *address; + +- (instancetype)initWithName: (OFString *)name + recordClass: (of_dns_resource_record_class_t)recordClass + recordType: (of_dns_resource_record_type_t)recordType + TTL: (uint32_t)TTL OF_UNAVAILABLE; + /*! - * A string with the IP address. + * @brief Initializes an already allocated OFADNSResourceRecord with the + * specified name, class, address and time to live. + * + * @param name The name for the resource record + * @param address The address for the resource record + * @param TTL The time to live for the resource record */ -@property (readonly, nonatomic) OFString *data; +- (instancetype)initWithName: (OFString *)name + address: (OFString *)address + TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER; @end /*! * @class OFAAAADNSResourceRecord \ * OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h * * @brief A class represenging a DNS resource record. */ @interface OFAAAADNSResourceRecord: OFDNSResourceRecord +{ + OFString *_address; +} + +/*! + * The IPv6 address of the resource record. + */ +@property (readonly, nonatomic) OFString *address; + +- (instancetype)initWithName: (OFString *)name + recordClass: (of_dns_resource_record_class_t)recordClass + recordType: (of_dns_resource_record_type_t)recordType + TTL: (uint32_t)TTL OF_UNAVAILABLE; + /*! - * A string with the IP address. + * @brief Initializes an already allocated OFAAAADNSResourceRecord with the + * specified name, class, address and time to live. + * + * @param name The name for the resource record + * @param address The address for the resource record + * @param TTL The time to live for the resource record */ -@property (readonly, nonatomic) OFString *data; +- (instancetype)initWithName: (OFString *)name + address: (OFString *)address + TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER; @end /*! * @class OFCNAMEDNSResourceRecord \ * OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h * * @brief A class representing a CNAME DNS resource record. */ @interface OFCNAMEDNSResourceRecord: OFDNSResourceRecord +{ + OFString *_alias; +} + +/*! + * The alias of the resource record. + */ +@property (readonly, nonatomic) OFString *alias; + +- (instancetype)initWithName: (OFString *)name + recordClass: (of_dns_resource_record_class_t)recordClass + recordType: (of_dns_resource_record_type_t)recordType + TTL: (uint32_t)TTL OF_UNAVAILABLE; + /*! - * A string with the alias. + * @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 alias The alias for the resource record + * @param TTL The time to live for the resource record */ -@property (readonly, nonatomic) OFString *data; +- (instancetype)initWithName: (OFString *)name + recordClass: (of_dns_resource_record_class_t)recordClass + alias: (OFString *)alias + TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER; @end /*! * @class OFMXDNSResourceRecord \ * OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h @@ -161,86 +219,151 @@ * @brief A class representing an MX DNS resource record. */ @interface OFMXDNSResourceRecord: OFDNSResourceRecord { uint16_t _preference; + OFString *_mailExchange; } /*! * The preference of the resource record. */ @property (readonly, nonatomic) uint16_t preference; /*! - * A string with the mail exchange. + * The mail exchange of the resource record. */ -@property (readonly, nonatomic) OFString *data; +@property (readonly, nonatomic) OFString *mailExchange; - (instancetype)initWithName: (OFString *)name recordClass: (of_dns_resource_record_class_t)recordClass recordType: (of_dns_resource_record_type_t)recordType - data: (id)data TTL: (uint32_t)TTL OF_UNAVAILABLE; /*! * @brief Initializes an already allocated OFMXDNSResourceRecord with the - * specified name, resource record class, resource record type, resource - * record preference, resource record data and resource record time to - * live. + * specified name, class, preference, mail exchange and time to live. * - * @param name The name of the resource record + * @param name The name for the resource record * @param recordClass The class code for the resource record - * @param recordType The type code for the resource record - * @param preference The preference of the resource record - * @param data The data 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 */ - (instancetype)initWithName: (OFString *)name recordClass: (of_dns_resource_record_class_t)recordClass - recordType: (of_dns_resource_record_type_t)recordType preference: (uint16_t)preference - data: (id)data + mailExchange: (OFString *)mailExchange TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER; @end /*! * @class OFNSDNSResourceRecord \ * OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h * - * @brief A class representing a CNAME DNS resource record. + * @brief A class representing an NS DNS resource record. */ @interface OFNSDNSResourceRecord: OFDNSResourceRecord +{ + OFString *_authoritativeHost; +} + +/*! + * The authoritative host of the resource record. + */ +@property (readonly, nonatomic) OFString *authoritativeHost; + +- (instancetype)initWithName: (OFString *)name + recordClass: (of_dns_resource_record_class_t)recordClass + recordType: (of_dns_resource_record_type_t)recordType + TTL: (uint32_t)TTL OF_UNAVAILABLE; + /*! - * A string with the authoritative host of the resource record. + * @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 authoritativeHost The authoritative host for the resource record + * @param TTL The time to live for the resource record */ -@property (readonly, nonatomic) OFString *data; +- (instancetype)initWithName: (OFString *)name + recordClass: (of_dns_resource_record_class_t)recordClass + authoritativeHost: (OFString *)authoritativeHost + TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER; @end /*! * @class OFPTRDNSResourceRecord \ * OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h * - * @brief A class representing a CNAME DNS resource record. + * @brief A class representing a PTR DNS resource record. */ @interface OFPTRDNSResourceRecord: OFDNSResourceRecord +{ + OFString *_domainName; +} + +/*! + * The domain name of the resource record. + */ +@property (readonly, nonatomic) OFString *domainName; + +- (instancetype)initWithName: (OFString *)name + recordClass: (of_dns_resource_record_class_t)recordClass + recordType: (of_dns_resource_record_type_t)recordType + TTL: (uint32_t)TTL OF_UNAVAILABLE; + /*! - * A string with the domain name for the resource record. + * @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 domainName The domain name for the resource record + * @param TTL The time to live for the resource record */ -@property (readonly, nonatomic) OFString *data; +- (instancetype)initWithName: (OFString *)name + recordClass: (of_dns_resource_record_class_t)recordClass + domainName: (OFString *)domainName + TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER; @end /*! * @class OFTXTDNSResourceRecord \ * OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h * - * @brief A class representing a CNAME DNS resource record. + * @brief A class representing a TXT DNS resource record. */ @interface OFTXTDNSResourceRecord: OFDNSResourceRecord +{ + OFData *_textData; +} + +/*! + * The text of the resource record. + */ +@property (readonly, nonatomic) OFData *textData; + +- (instancetype)initWithName: (OFString *)name + recordClass: (of_dns_resource_record_class_t)recordClass + recordType: (of_dns_resource_record_type_t)recordType + TTL: (uint32_t)TTL OF_UNAVAILABLE; + /*! - * Data with the text of the resource record. + * @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 textData The data for the resource record + * @param TTL The time to live for the resource record */ -@property (readonly, nonatomic) OFString *data; +- (instancetype)initWithName: (OFString *)name + recordClass: (of_dns_resource_record_class_t)recordClass + textData: (OFData *)textData + TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER; @end #ifdef __cplusplus extern "C" { #endif Index: src/OFDNSResourceRecord.m ================================================================== --- src/OFDNSResourceRecord.m +++ src/OFDNSResourceRecord.m @@ -48,10 +48,12 @@ return @"CNAME"; case OF_DNS_RESOURCE_RECORD_TYPE_SOA: return @"SOA"; case OF_DNS_RESOURCE_RECORD_TYPE_PTR: return @"PTR"; + case OF_DNS_RESOURCE_RECORD_TYPE_HINFO: + return @"HINFO"; case OF_DNS_RESOURCE_RECORD_TYPE_MX: return @"MX"; case OF_DNS_RESOURCE_RECORD_TYPE_TXT: return @"TXT"; case OF_DNS_RESOURCE_RECORD_TYPE_AAAA: @@ -63,25 +65,23 @@ } } @implementation OFDNSResourceRecord @synthesize name = _name, recordClass = _recordClass, recordType = _recordType; -@synthesize data = _data, TTL = _TTL; +@synthesize TTL = _TTL; - (instancetype)initWithName: (OFString *)name recordClass: (of_dns_resource_record_class_t)recordClass recordType: (of_dns_resource_record_type_t)recordType - data: (id)data TTL: (uint32_t)TTL { self = [super init]; @try { _name = [name copy]; _recordClass = recordClass; _recordType = recordType; - _data = [data copy]; _TTL = TTL; } @catch (id e) { [self release]; @throw e; } @@ -90,20 +90,647 @@ } - (void)dealloc { [_name release]; - [_data release]; + + [super dealloc]; +} + +- (OFString *)description +{ + return [OFString stringWithFormat: + @"<%@:\n" + @"\tName = %@\n" + @"\tClass = %@\n" + @"\tType = %@\n" + @"\tTTL = %" PRIu32 "\n" + @">", + [self className], _name, + of_dns_resource_record_class_to_string(_recordClass), + of_dns_resource_record_type_to_string(_recordType), _TTL]; +} +@end + +@implementation OFADNSResourceRecord +@synthesize address = _address; + +- (instancetype)initWithName: (OFString *)name + recordClass: (of_dns_resource_record_class_t)recordClass + recordType: (of_dns_resource_record_type_t)recordType + TTL: (uint32_t)TTL +{ + OF_INVALID_INIT_METHOD +} + +- (instancetype)initWithName: (OFString *)name + address: (OFString *)address + TTL: (uint32_t)TTL +{ + self = [super initWithName: name + recordClass: OF_DNS_RESOURCE_RECORD_CLASS_IN + recordType: OF_DNS_RESOURCE_RECORD_TYPE_A + TTL: TTL]; + + @try { + _address = [address copy]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_address release]; + + [super dealloc]; +} + +- (bool)isEqual: (id)otherObject +{ + OFADNSResourceRecord *otherRecord; + + if (![otherObject isKindOfClass: [OFADNSResourceRecord class]]) + return false; + + otherRecord = otherObject; + + if (otherRecord->_name != _name && ![otherRecord->_name isEqual: _name]) + return false; + + if (otherRecord->_recordClass != _recordClass) + return false; + + if (otherRecord->_recordType != _recordType) + return false; + + if (otherRecord->_address != _address && + ![otherRecord->_address isEqual: _address]) + return false; + + return true; +} + +- (uint32_t)hash +{ + 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, _recordType >> 8); + OF_HASH_ADD(hash, _recordType); + OF_HASH_ADD_HASH(hash, [_address hash]); + + OF_HASH_FINALIZE(hash); + + return hash; +} + +- (OFString *)description +{ + return [OFString stringWithFormat: + @"<%@:\n" + @"\tName = %@\n" + @"\tAddress = %@\n" + @"\tTTL = %" PRIu32 "\n" + @">", + [self className], _name, _address, _TTL]; +} +@end + +@implementation OFAAAADNSResourceRecord +@synthesize address = _address; + +- (instancetype)initWithName: (OFString *)name + recordClass: (of_dns_resource_record_class_t)recordClass + recordType: (of_dns_resource_record_type_t)recordType + TTL: (uint32_t)TTL +{ + OF_INVALID_INIT_METHOD +} + +- (instancetype)initWithName: (OFString *)name + address: (OFString *)address + TTL: (uint32_t)TTL +{ + self = [super initWithName: name + recordClass: OF_DNS_RESOURCE_RECORD_CLASS_IN + recordType: OF_DNS_RESOURCE_RECORD_TYPE_AAAA + TTL: TTL]; + + @try { + _address = [address copy]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_address release]; + + [super dealloc]; +} + +- (bool)isEqual: (id)otherObject +{ + OFAAAADNSResourceRecord *otherRecord; + + if (![otherObject isKindOfClass: [OFAAAADNSResourceRecord class]]) + return false; + + otherRecord = otherObject; + + if (otherRecord->_name != _name && ![otherRecord->_name isEqual: _name]) + return false; + + if (otherRecord->_recordClass != _recordClass) + return false; + + if (otherRecord->_recordType != _recordType) + return false; + + if (otherRecord->_address != _address && + ![otherRecord->_address isEqual: _address]) + return false; + + return true; +} + +- (uint32_t)hash +{ + 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, _recordType >> 8); + OF_HASH_ADD(hash, _recordType); + OF_HASH_ADD_HASH(hash, [_address hash]); + + OF_HASH_FINALIZE(hash); + + return hash; +} + +- (OFString *)description +{ + return [OFString stringWithFormat: + @"<%@:\n" + @"\tName = %@\n" + @"\tAddress = %@\n" + @"\tTTL = %" PRIu32 "\n" + @">", + [self className], _name, _address, _TTL]; +} +@end + +@implementation OFCNAMEDNSResourceRecord +@synthesize alias = _alias; + +- (instancetype)initWithName: (OFString *)name + recordClass: (of_dns_resource_record_class_t)recordClass + 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 + alias: (OFString *)alias + TTL: (uint32_t)TTL +{ + self = [super initWithName: name + recordClass: recordClass + recordType: OF_DNS_RESOURCE_RECORD_TYPE_CNAME + TTL: TTL]; + + @try { + _alias = [alias copy]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_alias release]; + + [super dealloc]; +} + +- (bool)isEqual: (id)otherObject +{ + OFCNAMEDNSResourceRecord *otherRecord; + + if (![otherObject isKindOfClass: [OFCNAMEDNSResourceRecord class]]) + return false; + + otherRecord = otherObject; + + if (otherRecord->_name != _name && ![otherRecord->_name isEqual: _name]) + return false; + + if (otherRecord->_recordClass != _recordClass) + return false; + + if (otherRecord->_recordType != _recordType) + return false; + + if (otherRecord->_alias != _alias && + ![otherRecord->_alias isEqual: _alias]) + return false; + + return true; +} + +- (uint32_t)hash +{ + 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, _recordType >> 8); + OF_HASH_ADD(hash, _recordType); + OF_HASH_ADD_HASH(hash, [_alias hash]); + + OF_HASH_FINALIZE(hash); + + return hash; +} + +- (OFString *)description +{ + return [OFString stringWithFormat: + @"<%@:\n" + @"\tName = %@\n" + @"\tClass = %@\n" + @"\tAlias = %@\n" + @"\tTTL = %" PRIu32 "\n" + @">", + [self className], _name, + of_dns_resource_record_class_to_string(_recordClass), _alias, _TTL]; +} +@end + +@implementation OFMXDNSResourceRecord +@synthesize preference = _preference, mailExchange = _mailExchange; + +- (instancetype)initWithName: (OFString *)name + recordClass: (of_dns_resource_record_class_t)recordClass + 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 + preference: (uint16_t)preference + mailExchange: (OFString *)mailExchange + TTL: (uint32_t)TTL +{ + self = [super initWithName: name + recordClass: recordClass + recordType: OF_DNS_RESOURCE_RECORD_TYPE_MX + TTL: TTL]; + + @try { + _preference = preference; + _mailExchange = [mailExchange copy]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_mailExchange release]; + + [super dealloc]; +} + +- (bool)isEqual: (id)otherObject +{ + OFMXDNSResourceRecord *otherRecord; + + if (![otherObject isKindOfClass: [OFMXDNSResourceRecord class]]) + return false; + + otherRecord = otherObject; + + if (otherRecord->_name != _name && ![otherRecord->_name isEqual: _name]) + return false; + + if (otherRecord->_recordClass != _recordClass) + return false; + + if (otherRecord->_recordType != _recordType) + return false; + + if (otherRecord->_preference != _preference) + return false; + + if (otherRecord->_mailExchange != _mailExchange && + ![otherRecord->_mailExchange isEqual: _mailExchange]) + return false; + + return true; +} + +- (uint32_t)hash +{ + 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, _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]); + + OF_HASH_FINALIZE(hash); + + return hash; +} + +- (OFString *)description +{ + return [OFString stringWithFormat: + @"<%@:\n" + @"\tName = %@\n" + @"\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]; +} +@end + +@implementation OFNSDNSResourceRecord +@synthesize authoritativeHost = _authoritativeHost; + +- (instancetype)initWithName: (OFString *)name + recordClass: (of_dns_resource_record_class_t)recordClass + 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 + authoritativeHost: (OFString *)authoritativeHost + TTL: (uint32_t)TTL +{ + self = [super initWithName: name + recordClass: recordClass + recordType: OF_DNS_RESOURCE_RECORD_TYPE_NS + TTL: TTL]; + + @try { + _authoritativeHost = [authoritativeHost copy]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_authoritativeHost release]; + + [super dealloc]; +} + +- (bool)isEqual: (id)otherObject +{ + OFNSDNSResourceRecord *otherRecord; + + if (![otherObject isKindOfClass: [OFNSDNSResourceRecord class]]) + return false; + + otherRecord = otherObject; + + if (otherRecord->_name != _name && ![otherRecord->_name isEqual: _name]) + return false; + + if (otherRecord->_recordClass != _recordClass) + return false; + + if (otherRecord->_recordType != _recordType) + return false; + + if (otherRecord->_authoritativeHost != _authoritativeHost && + ![otherRecord->_authoritativeHost isEqual: _authoritativeHost]) + return false; + + return true; +} + +- (uint32_t)hash +{ + 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, _recordType >> 8); + OF_HASH_ADD(hash, _recordType); + OF_HASH_ADD_HASH(hash, [_authoritativeHost hash]); + + OF_HASH_FINALIZE(hash); + + return hash; +} + +- (OFString *)description +{ + return [OFString stringWithFormat: + @"<%@:\n" + @"\tName = %@\n" + @"\tClass = %@\n" + @"\tAuthoritative Host = %@\n" + @"\tTTL = %" PRIu32 "\n" + @">", + [self className], _name, + of_dns_resource_record_class_to_string(_recordClass), + _authoritativeHost, _TTL]; +} +@end + +@implementation OFPTRDNSResourceRecord +@synthesize domainName = _domainName; + +- (instancetype)initWithName: (OFString *)name + recordClass: (of_dns_resource_record_class_t)recordClass + 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 + domainName: (OFString *)domainName + TTL: (uint32_t)TTL +{ + self = [super initWithName: name + recordClass: recordClass + recordType: OF_DNS_RESOURCE_RECORD_TYPE_PTR + TTL: TTL]; + + @try { + _domainName = [domainName copy]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_domainName release]; + + [super dealloc]; +} + +- (bool)isEqual: (id)otherObject +{ + OFPTRDNSResourceRecord *otherRecord; + + if (![otherObject isKindOfClass: [OFPTRDNSResourceRecord class]]) + return false; + + otherRecord = otherObject; + + if (otherRecord->_name != _name && ![otherRecord->_name isEqual: _name]) + return false; + + if (otherRecord->_recordClass != _recordClass) + return false; + + if (otherRecord->_recordType != _recordType) + return false; + + if (otherRecord->_domainName != _domainName && + ![otherRecord->_domainName isEqual: _domainName]) + return false; + + return true; +} + +- (uint32_t)hash +{ + 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, _recordType >> 8); + OF_HASH_ADD(hash, _recordType); + OF_HASH_ADD_HASH(hash, [_domainName hash]); + + OF_HASH_FINALIZE(hash); + + return hash; +} + +- (OFString *)description +{ + return [OFString stringWithFormat: + @"<%@:\n" + @"\tName = %@\n" + @"\tClass = %@\n" + @"\tDomain Name = %@\n" + @"\tTTL = %" PRIu32 "\n" + @">", + [self className], _name, + of_dns_resource_record_class_to_string(_recordClass), _domainName, + _TTL]; +} +@end + +@implementation OFTXTDNSResourceRecord +@synthesize textData = _textData; + +- (instancetype)initWithName: (OFString *)name + recordClass: (of_dns_resource_record_class_t)recordClass + 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 + textData: (OFData *)textData + TTL: (uint32_t)TTL +{ + self = [super initWithName: name + recordClass: recordClass + recordType: OF_DNS_RESOURCE_RECORD_TYPE_TXT + TTL: TTL]; + + @try { + _textData = [textData copy]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_textData release]; [super dealloc]; } - (bool)isEqual: (id)otherObject { - OFDNSResourceRecord *otherRecord; + OFTXTDNSResourceRecord *otherRecord; - if (![otherObject isKindOfClass: [OFDNSResourceRecord class]]) + if (![otherObject isKindOfClass: [OFTXTDNSResourceRecord class]]) return false; otherRecord = otherObject; if (otherRecord->_name != _name && ![otherRecord->_name isEqual: _name]) @@ -113,14 +740,12 @@ return false; if (otherRecord->_recordType != _recordType) return false; - if (otherRecord->_data != _data && ![otherRecord->_data isEqual: _data]) - return false; - - if (otherRecord->_TTL != _TTL) + if (otherRecord->_textData != _textData && + ![otherRecord->_textData isEqual: _textData]) return false; return true; } @@ -133,15 +758,11 @@ OF_HASH_ADD_HASH(hash, [_name hash]); OF_HASH_ADD(hash, _recordClass >> 8); OF_HASH_ADD(hash, _recordClass); OF_HASH_ADD(hash, _recordType >> 8); OF_HASH_ADD(hash, _recordType); - OF_HASH_ADD_HASH(hash, [_data hash]); - OF_HASH_ADD(hash, _TTL >> 24); - OF_HASH_ADD(hash, _TTL >> 16); - OF_HASH_ADD(hash, _TTL >> 8); - OF_HASH_ADD(hash, _TTL); + OF_HASH_ADD_HASH(hash, [_textData hash]); OF_HASH_FINALIZE(hash); return hash; } @@ -150,120 +771,13 @@ { return [OFString stringWithFormat: @"<%@:\n" @"\tName = %@\n" @"\tClass = %@\n" - @"\tType = %@\n" - @"\tData = %@\n" - @"\tTTL = %" PRIu32 "\n" - @">", - [self className], _name, - of_dns_resource_record_class_to_string(_recordClass), - of_dns_resource_record_type_to_string(_recordType), _data, _TTL]; -} -@end - -@implementation OFADNSResourceRecord -@dynamic data; -@end - -@implementation OFAAAADNSResourceRecord -@dynamic data; -@end - -@implementation OFCNAMEDNSResourceRecord -@dynamic data; -@end - -@implementation OFMXDNSResourceRecord -@dynamic data; -@synthesize preference = _preference; - -- (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass - recordType: (of_dns_resource_record_type_t)recordType - data: (id)data - TTL: (uint32_t)TTL -{ - OF_INVALID_INIT_METHOD -} - -- (instancetype)initWithName: (OFString *)name - recordClass: (of_dns_resource_record_class_t)recordClass - recordType: (of_dns_resource_record_type_t)recordType - preference: (uint16_t)preference - data: (id)data - TTL: (uint32_t)TTL -{ - self = [super initWithName: name - recordClass: recordClass - recordType: recordType - data: data - TTL: TTL]; - - _preference = preference; - - return self; -} - -- (bool)isEqual: (id)otherObject -{ - OFMXDNSResourceRecord *otherRecord; - - if (![otherObject isKindOfClass: [OFMXDNSResourceRecord class]]) - return false; - - otherRecord = otherObject; - - if (![super isEqual: otherRecord]) - return false; - - if (otherRecord->_preference != _preference) - return false; - - return true; -} - -- (uint32_t)hash -{ - uint32_t hash; - - OF_HASH_INIT(hash); - - OF_HASH_ADD_HASH(hash, [super hash]); - OF_HASH_ADD(hash, _preference >> 8); - OF_HASH_ADD(hash, _preference); - - OF_HASH_FINALIZE(hash); - - return hash; -} - -- (OFString *)description -{ - return [OFString stringWithFormat: - @"<%@:\n" - @"\tName = %@\n" - @"\tClass = %@\n" - @"\tType = %@\n" - @"\tPreference = %" PRIu16 "\n" - @"\tData = %@\n" - @"\tTTL = %" PRIu32 "\n" - @">", - [self className], _name, - of_dns_resource_record_class_to_string(_recordClass), - of_dns_resource_record_type_to_string(_recordType), _preference, - _data, _TTL]; -} -@end - -@implementation OFNSDNSResourceRecord -@dynamic data; -@end - -@implementation OFPTRDNSResourceRecord -@dynamic data; -@end - -@implementation OFTXTDNSResourceRecord -@dynamic data; + @"\tText Data = %@\n" + @"\tTTL = %" PRIu32 "\n" + @">", + [self className], _name, + of_dns_resource_record_class_to_string(_recordClass), _textData, + _TTL]; +} @end