Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -141,13 +141,14 @@ OFSequencedPacketSocket.m \ OFSocket.m \ OFStreamSocket.m \ OFSystemInfo+NetworkInterfaces.m \ OFTCPSocket.m \ - OFTXTDNSResourceRecord.m \ OFTLSStream.m \ + OFTXTDNSResourceRecord.m \ OFUDPSocket.m \ + OFURIDNSResourceRecord.m \ ${USE_SRCS_APPLETALK} \ ${USE_SRCS_IPX} \ ${USE_SRCS_UNIX_SOCKETS} SRCS_APPLETALK = OFDDPSocket.m SRCS_IPX = OFIPXSocket.m \ Index: src/OFDNSResolver.m ================================================================== --- src/OFDNSResolver.m +++ src/OFDNSResolver.m @@ -402,10 +402,30 @@ initWithName: name priority: priority weight: weight target: target port: port + TTL: TTL] autorelease]; + } else if (recordType == OFDNSRecordTypeURI) { + uint16_t priority, weight; + OFString *target; + + if (dataLength < 4) + @throw [OFInvalidServerResponseException exception]; + + priority = (buffer[i] << 8) | buffer[i + 1]; + weight = (buffer[i + 2] << 8) | buffer[i + 3]; + + target = [OFString stringWithUTF8String: (char *)buffer + 4 + length: dataLength - 4]; + + return [[[OFURIDNSResourceRecord alloc] + initWithName: name + DNSClass: DNSClass + priority: priority + weight: weight + target: target TTL: TTL] autorelease]; } else return [[[OFDNSResourceRecord alloc] initWithName: name DNSClass: DNSClass Index: src/OFDNSResourceRecord.h ================================================================== --- src/OFDNSResourceRecord.h +++ src/OFDNSResourceRecord.h @@ -60,10 +60,12 @@ OFDNSRecordTypeAAAA = 28, /** SRV */ OFDNSRecordTypeSRV = 33, /** All types. Only for queries. */ OFDNSRecordTypeAll = 255, + /** URI */ + OFDNSRecordTypeURI = 256, } OFDNSRecordType; /** * @class OFDNSResourceRecord OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h * @@ -166,5 +168,6 @@ #import "OFPTRDNSResourceRecord.h" #import "OFRPDNSResourceRecord.h" #import "OFSOADNSResourceRecord.h" #import "OFSRVDNSResourceRecord.h" #import "OFTXTDNSResourceRecord.h" +#import "OFURIDNSResourceRecord.h" Index: src/OFDNSResourceRecord.m ================================================================== --- src/OFDNSResourceRecord.m +++ src/OFDNSResourceRecord.m @@ -60,10 +60,12 @@ return @"AAAA"; case OFDNSRecordTypeSRV: return @"SRV"; case OFDNSRecordTypeAll: return @"all"; + case OFDNSRecordTypeURI: + return @"URI"; default: return [OFString stringWithFormat: @"%u", recordType]; } } @@ -117,10 +119,12 @@ recordType = OFDNSRecordTypeAAAA; else if ([string isEqual: @"SRV"]) recordType = OFDNSRecordTypeSRV; else if ([string isEqual: @"ALL"]) recordType = OFDNSRecordTypeAll; + else if ([string isEqual: @"URI"]) + recordType = OFDNSRecordTypeURI; else { recordType = (OFDNSRecordType)[string unsignedLongLongValueWithBase: 0]; } Index: src/OFSRVDNSResourceRecord.h ================================================================== --- src/OFSRVDNSResourceRecord.h +++ src/OFSRVDNSResourceRecord.h @@ -56,11 +56,11 @@ recordType: (OFDNSRecordType)recordType TTL: (uint32_t)TTL OF_UNAVAILABLE; /** * @brief Initializes an already allocated OFSRVDNSResourceRecord with the - * specified name, class, preference, mail exchange and time to live. + * specified name, priority, weight, target, port and time to live. * * @param name The name for the resource record * @param priority The priority for the resource record * @param weight The weight for the resource record * @param target The target for the resource record ADDED src/OFURIDNSResourceRecord.h Index: src/OFURIDNSResourceRecord.h ================================================================== --- src/OFURIDNSResourceRecord.h +++ src/OFURIDNSResourceRecord.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2008-2024 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 "OFDNSResourceRecord.h" + +OF_ASSUME_NONNULL_BEGIN + +/** + * @class OFURIDNSResourceRecord \ + * OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h + * + * @brief A class representing an URI DNS resource record. + */ +OF_SUBCLASSING_RESTRICTED +@interface OFURIDNSResourceRecord: OFDNSResourceRecord +{ + uint16_t _priority, _weight; + OFString *_target; +} + +/** + * @brief The priority of the resource record. + */ +@property (readonly, nonatomic) uint16_t priority; + +/** + * @brief The weight of the resource record. + */ +@property (readonly, nonatomic) uint16_t weight; + +/** + * @brief The target of the resource record. + */ +@property (readonly, nonatomic) OFString *target; + +- (instancetype)initWithName: (OFString *)name + DNSClass: (OFDNSClass)DNSClass + recordType: (OFDNSRecordType)recordType + TTL: (uint32_t)TTL OF_UNAVAILABLE; + +/** + * @brief Initializes an already allocated OFURIDNSResourceRecord with the + * specified name, class, priority, weight, target and time to live. + * + * @param name The name for the resource record + * @param DNSClass The class code for the resource record + * @param priority The priority for the resource record + * @param weight The weight for the resource record + * @param target The target for the resource record + * @param TTL The time to live for the resource record + * @return An initialized OFURIDNSResourceRecord + */ +- (instancetype)initWithName: (OFString *)name + DNSClass: (OFDNSClass)DNSClass + priority: (uint16_t)priority + weight: (uint16_t)weight + target: (OFString *)target + TTL: (uint32_t)TTL OF_DESIGNATED_INITIALIZER; +@end + +OF_ASSUME_NONNULL_END ADDED src/OFURIDNSResourceRecord.m Index: src/OFURIDNSResourceRecord.m ================================================================== --- src/OFURIDNSResourceRecord.m +++ src/OFURIDNSResourceRecord.m @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2008-2024 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 "OFURIDNSResourceRecord.h" + +@implementation OFURIDNSResourceRecord +@synthesize priority = _priority, weight = _weight, target = _target; + +- (instancetype)initWithName: (OFString *)name + DNSClass: (OFDNSClass)DNSClass + recordType: (OFDNSRecordType)recordType + TTL: (uint32_t)TTL +{ + OF_INVALID_INIT_METHOD +} + +- (instancetype)initWithName: (OFString *)name + DNSClass: (OFDNSClass)DNSClass + priority: (uint16_t)priority + weight: (uint16_t)weight + target: (OFString *)target + TTL: (uint32_t)TTL +{ + self = [super initWithName: name + DNSClass: DNSClass + recordType: OFDNSRecordTypeURI + TTL: TTL]; + + @try { + _priority = priority; + _weight = weight; + _target = [target copy]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_target release]; + + [super dealloc]; +} + +- (bool)isEqual: (id)object +{ + OFURIDNSResourceRecord *record; + + if (object == self) + return true; + + if (![object isKindOfClass: [OFURIDNSResourceRecord class]]) + return false; + + record = object; + + if (record->_name != _name && ![record->_name isEqual: _name]) + return false; + + if (record->_DNSClass != _DNSClass) + return false; + + if (record->_recordType != _recordType) + return false; + + if (record->_priority != _priority) + return false; + + if (record->_weight != _weight) + return false; + + if (record->_target != _target && ![record->_target isEqual: _target]) + return false; + + return true; +} + +- (unsigned long)hash +{ + unsigned long hash; + + OFHashInit(&hash); + + OFHashAddHash(&hash, _name.hash); + OFHashAddByte(&hash, _DNSClass >> 8); + OFHashAddByte(&hash, _DNSClass); + OFHashAddByte(&hash, _recordType >> 8); + OFHashAddByte(&hash, _recordType); + OFHashAddByte(&hash, _priority >> 8); + OFHashAddByte(&hash, _priority); + OFHashAddByte(&hash, _weight >> 8); + OFHashAddByte(&hash, _weight); + OFHashAddHash(&hash, _target.hash); + + OFHashFinalize(&hash); + + return hash; +} + +- (OFString *)description +{ + return [OFString stringWithFormat: + @"<%@:\n" + @"\tName = %@\n" + @"\tClass = %@\n" + @"\tPriority = %" PRIu16 "\n" + @"\tWeight = %" PRIu16 "\n" + @"\tTarget = %@\n" + @"\tTTL = %" PRIu32 "\n" + @">", + self.className, _name, OFDNSClassName(_DNSClass), _priority, + _weight, _target, _TTL]; +} +@end