Index: src/OFDNSResolver.h ================================================================== --- src/OFDNSResolver.h +++ src/OFDNSResolver.h @@ -163,27 +163,31 @@ * @param selector The selector to call on the target. The signature must be * the following: * @parblock * * void (OFDNSResolver *resolver, OFString *domainName, - * OFArray<__kindof OFDNSResourceRecord *> + * OFArray *> * *_Nullable answerRecords, - * OFArray<__kindof OFDNSResourceRecord *> + * OFArray *> * *_Nullable authorityRecords, - * OFArray<__kindof OFDNSResourceRecord *> + * OFArray *> * *_Nullable additionalRecords, * id _Nullable context, id _Nullable exception) * * `resolver` is the acting resolver.@n * `domainName` is the fully qualified domain name used to * resolve the host.@n - * `answerRecords` are the answer records from the name server. + * `answerRecords` are the answer records from the name server, + * grouped by domain name. * @n * `authorityRecords` are the authority records from the name - * server.@n + * server, grouped by domain name.@n * `additionalRecords` are additional records sent by the name - * server.@n + * server, grouped by domain name.@n * `context` is the context object originally passed.@n * `exception` is an exception that happened during resolving, * otherwise nil. * @endparblock * @param context A context object to pass along to the target @@ -203,27 +207,31 @@ * @param selector The selector to call on the target. The signature must be * the following: * @parblock * * void (OFDNSResolver *resolver, OFString *domainName, - * OFArray<__kindof OFDNSResourceRecord *> + * OFArray *> * *_Nullable answerRecords, - * OFArray<__kindof OFDNSResourceRecord *> + * OFArray *> * *_Nullable authorityRecords, - * OFArray<__kindof OFDNSResourceRecord *> + * OFArray *> * *_Nullable additionalRecords, * id _Nullable context, id _Nullable exception) * * `resolver` is the acting resolver.@n * `domainName` is the fully qualified domain name used to * resolve the host.@n - * `answerRecords` are the answer records from the name server. + * `answerRecords` are the answer records from the name server, + * grouped by domain name. * @n * `authorityRecords` are the authority records from the name - * server.@n + * server, grouped by domain name.@n * `additionalRecords` are additional records sent by the name - * server.@n + * server, grouped by domain name.@n * `context` is the context object originally passed.@n * `exception` is an exception that happened during resolving, * otherwise nil. * @endparblock * @param context A context object to pass along to the target Index: src/OFDNSResolver.m ================================================================== --- src/OFDNSResolver.m +++ src/OFDNSResolver.m @@ -172,13 +172,13 @@ target: (id)target selector: (SEL)selector context: (id)context; - (void)resolver: (OFDNSResolver *)resolver didResolveDomainName: (OFString *)domainName - answerRecords: (OFArray *)answerRecords - authorityRecords: (OFArray *)authorityRecords - additionalRecords: (OFArray *)additionalRecords + answerRecords: (OFDictionary *)answerRecords + authorityRecords: (OFDictionary *)authorityRecords + additionalRecords: (OFDictionary *)additionalRecords context: (id)context exception: (id)exception; @end @interface OFDNSResolver () @@ -585,15 +585,17 @@ recordClass: recordClass recordType: recordType TTL: TTL] autorelease]; } -static OFArray * +static OFDictionary * parseSection(const unsigned char *buffer, size_t length, size_t *i, uint_fast16_t count) { - OFMutableArray *ret = [OFMutableArray array]; + OFMutableDictionary *ret = [OFMutableDictionary dictionary]; + OFEnumerator OF_GENERIC(OFMutableArray *) *objectEnumerator; + 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; @@ -618,26 +620,39 @@ record = parseResourceRecord(name, recordClass, recordType, TTL, buffer, length, *i, dataLength); *i += dataLength; - [ret addObject: record]; + array = [ret objectForKey: name]; + + if (array == nil) { + array = [OFMutableArray array]; + [ret setObject: array + forKey: name]; + } + + [array addObject: record]; } + + objectEnumerator = [ret objectEnumerator]; + while ((array = [objectEnumerator nextObject]) != nil) + [array makeImmutable]; [ret makeImmutable]; return ret; } static void callback(id target, SEL selector, OFDNSResolver *resolver, - OFString *domainName, OFArray *answerRecords, OFArray *authorityRecords, - OFArray *additionalRecords, id context, id exception) + OFString *domainName, OFDictionary *answerRecords, + OFDictionary *authorityRecords, OFDictionary *additionalRecords, id context, + id exception) { - void (*method)(id, SEL, OFDNSResolver *, OFString *, OFArray *, - OFArray *, OFArray *, id, id) = (void (*)(id, SEL, OFDNSResolver *, - OFString *, OFArray *, OFArray *, OFArray *, id, id)) - [target methodForSelector: selector]; + void (*method)(id, SEL, OFDNSResolver *, OFString *, OFDictionary *, + OFDictionary *, OFDictionary *, id, id) = (void (*)(id, SEL, + OFDNSResolver *, OFString *, OFDictionary *, OFDictionary *, + OFDictionary *, id, id))[target methodForSelector: selector]; method(target, selector, resolver, domainName, answerRecords, authorityRecords, additionalRecords, context, exception); } @@ -814,13 +829,13 @@ [super dealloc]; } - (void)resolver: (OFDNSResolver *)resolver didResolveDomainName: (OFString *)domainName - answerRecords: (OFArray *)answerRecords - authorityRecords: (OFArray *)authorityRecords - additionalRecords: (OFArray *)additionalRecords + answerRecords: (OFDictionary *)answerRecords + authorityRecords: (OFDictionary *)authorityRecords + additionalRecords: (OFDictionary *)additionalRecords context: (id)context exception: (id)exception { /* * TODO: Error handling could be improved. Ignore error if there are @@ -830,14 +845,12 @@ of_socket_address_family_t addressFamily = [context intValue]; _expectedResponses--; if (exception == nil) { - for (OFDNSResourceRecord *record in answerRecords) { - if (![[record name] isEqual: domainName]) - continue; - + for (OFDNSResourceRecord *record in + [answerRecords objectForKey: domainName]) { if ([record recordClass] != OF_DNS_RESOURCE_RECORD_CLASS_IN) continue; switch ([record recordType]) { @@ -1611,12 +1624,12 @@ length: (size_t)length sender: (of_socket_address_t)sender context: (id)context exception: (id)exception { - OFArray *answerRecords = nil, *authorityRecords = nil; - OFArray *additionalRecords = nil; + OFDictionary *answerRecords = nil, *authorityRecords = nil; + OFDictionary *additionalRecords = nil; OFNumber *ID; OFDNSResolverQuery *query; if (exception != nil) { if ([exception respondsToSelector: @selector(errNo)])