ObjFW  Check-in [7ba597c52d]

Overview
Comment:OFDNSResolver: Group records by domain name
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 7ba597c52d5afdd7e77eb31eef89ff8a72d9a638382ea98ab813f28466e411bb
User & Date: js on 2018-09-15 13:45:03
Other Links: manifest | tags
Context
2018-09-15
17:39
OFDNSResolver: Resolve CNAMEs for socket addresses check-in: 25b05b7bce user: js tags: trunk
13:45
OFDNSResolver: Group records by domain name check-in: 7ba597c52d user: js tags: trunk
2018-09-10
20:44
OFDNSResolver: Method to resolve host to addresses check-in: 8555d64ee6 user: js tags: trunk
Changes

Modified src/OFDNSResolver.h from [6f6cb9c138] to [ef34cbb838].

161
162
163
164
165
166
167

168
169

170
171

172
173
174
175
176
177
178
179

180
181
182
183
184
185
186
187
188
189
190
191
 * @param host The host to resolve
 * @param target The target to call with the result once resolving is done
 * @param selector The selector to call on the target. The signature must be
 *		   the following:
 *		   @parblock
 *
 *		       void (OFDNSResolver *resolver, OFString *domainName,

 *		           OFArray<__kindof OFDNSResourceRecord *>
 *		           *_Nullable answerRecords,

 *		           OFArray<__kindof OFDNSResourceRecord *>
 *		           *_Nullable authorityRecords,

 *		           OFArray<__kindof OFDNSResourceRecord *>
 *		           *_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.

 *		   @n
 *		   `authorityRecords` are the authority records from the name
 *		   server.@n
 *		   `additionalRecords` are additional records sent by the name
 *		   server.@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
 */
- (void)asyncResolveHost: (OFString *)host







>
|

>
|

>
|






|
>


|

|







161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
 * @param host The host to resolve
 * @param target The target to call with the result once resolving is done
 * @param selector The selector to call on the target. The signature must be
 *		   the following:
 *		   @parblock
 *
 *		       void (OFDNSResolver *resolver, OFString *domainName,
 *		           OFArray<OFDictionary<OFString *,
 *		           __kindof OFDNSResourceRecord *> *>
 *		           *_Nullable answerRecords,
 *		           OFArray<OFDictionary<OFString *,
 *		           __kindof OFDNSResourceRecord *> *>
 *		           *_Nullable authorityRecords,
 *		           OFArray<OFDictionary<OFString *,
 *		           __kindof OFDNSResourceRecord *> *>
 *		           *_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,
 *		   grouped by domain name.
 *		   @n
 *		   `authorityRecords` are the authority records from the name
 *		   server, grouped by domain name.@n
 *		   `additionalRecords` are additional records sent by the name
 *		   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
 */
- (void)asyncResolveHost: (OFString *)host
201
202
203
204
205
206
207

208
209

210
211

212
213
214
215
216
217
218
219

220
221
222
223
224
225
226
227
228
229
230
231
 * @param recordType The desired type of the records to query
 * @param target The target to call with the result once resolving is done
 * @param selector The selector to call on the target. The signature must be
 *		   the following:
 *		   @parblock
 *
 *		       void (OFDNSResolver *resolver, OFString *domainName,

 *		           OFArray<__kindof OFDNSResourceRecord *>
 *		           *_Nullable answerRecords,

 *		           OFArray<__kindof OFDNSResourceRecord *>
 *		           *_Nullable authorityRecords,

 *		           OFArray<__kindof OFDNSResourceRecord *>
 *		           *_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.

 *		   @n
 *		   `authorityRecords` are the authority records from the name
 *		   server.@n
 *		   `additionalRecords` are additional records sent by the name
 *		   server.@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
 */
- (void)asyncResolveHost: (OFString *)host







>
|

>
|

>
|






|
>


|

|







205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
 * @param recordType The desired type of the records to query
 * @param target The target to call with the result once resolving is done
 * @param selector The selector to call on the target. The signature must be
 *		   the following:
 *		   @parblock
 *
 *		       void (OFDNSResolver *resolver, OFString *domainName,
 *		           OFArray<OFDictionary<OFString *,
 *		           __kindof OFDNSResourceRecord *> *>
 *		           *_Nullable answerRecords,
 *		           OFArray<OFDictionary<OFString *,
 *		           __kindof OFDNSResourceRecord *> *>
 *		           *_Nullable authorityRecords,
 *		           OFArray<OFDictionary<OFString *,
 *		           __kindof OFDNSResourceRecord *> *>
 *		           *_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,
 *		   grouped by domain name.
 *		   @n
 *		   `authorityRecords` are the authority records from the name
 *		   server, grouped by domain name.@n
 *		   `additionalRecords` are additional records sent by the name
 *		   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
 */
- (void)asyncResolveHost: (OFString *)host

Modified src/OFDNSResolver.m from [8914dd7f51] to [721e3310ec].

170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186

- (instancetype)initWithHost: (OFString *)host
		      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
	       context: (id)context
	     exception: (id)exception;
@end

@interface OFDNSResolver ()
- (void)of_setDefaults;
- (void)of_obtainSystemConfig;







|
|
|







170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186

- (instancetype)initWithHost: (OFString *)host
		      target: (id)target
		    selector: (SEL)selector
		     context: (id)context;
-	(void)resolver: (OFDNSResolver *)resolver
  didResolveDomainName: (OFString *)domainName
	 answerRecords: (OFDictionary *)answerRecords
      authorityRecords: (OFDictionary *)authorityRecords
     additionalRecords: (OFDictionary *)additionalRecords
	       context: (id)context
	     exception: (id)exception;
@end

@interface OFDNSResolver ()
- (void)of_setDefaults;
- (void)of_obtainSystemConfig;
583
584
585
586
587
588
589
590
591
592
593


594
595
596
597
598
599
600
601
		return [[[OFDNSResourceRecord alloc]
		    initWithName: name
		     recordClass: recordClass
		      recordType: recordType
			     TTL: TTL] autorelease];
}

static OFArray *
parseSection(const unsigned char *buffer, size_t length, size_t *i,
    uint_fast16_t count)
{


	OFMutableArray *ret = [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_resource_record_type_t recordType;
		uint32_t TTL;







|



>
>
|







583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
		return [[[OFDNSResourceRecord alloc]
		    initWithName: name
		     recordClass: recordClass
		      recordType: recordType
			     TTL: TTL] autorelease];
}

static OFDictionary *
parseSection(const unsigned char *buffer, size_t length, size_t *i,
    uint_fast16_t count)
{
	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;
		of_dns_resource_record_type_t recordType;
		uint32_t TTL;
616
617
618
619
620
621
622








623
624




625
626
627
628
629
630
631
632

633
634
635
636
637
638
639
640
641
642
643
644
645
		if (*i + dataLength > length)
			@throw [OFTruncatedDataException exception];

		record = parseResourceRecord(name, recordClass, recordType, TTL,
		    buffer, length, *i, dataLength);
		*i += dataLength;









		[ret addObject: record];
	}





	[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)
{
	void (*method)(id, SEL, OFDNSResolver *, OFString *, OFArray *,
	    OFArray *, OFArray *, id, id) = (void (*)(id, SEL, OFDNSResolver *,
	    OFString *, OFArray *, OFArray *, OFArray *, id, id))
	    [target methodForSelector: selector];

	method(target, selector, resolver, domainName, answerRecords,
	    authorityRecords, additionalRecords, context, exception);
}

@implementation OFDNSResolverSettings
- (instancetype)initWithNameServers: (OFArray *)nameServers







>
>
>
>
>
>
>
>
|

>
>
>
>







|
>
|

|
|
|
|







618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
		if (*i + dataLength > length)
			@throw [OFTruncatedDataException exception];

		record = parseResourceRecord(name, recordClass, recordType, TTL,
		    buffer, length, *i, dataLength);
		*i += dataLength;

		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, OFDictionary *answerRecords,
    OFDictionary *authorityRecords, OFDictionary *additionalRecords, id context,
    id exception)
{
	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);
}

@implementation OFDNSResolverSettings
- (instancetype)initWithNameServers: (OFArray *)nameServers
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
	[_records release];

	[super dealloc];
}

-	(void)resolver: (OFDNSResolver *)resolver
  didResolveDomainName: (OFString *)domainName
	 answerRecords: (OFArray *)answerRecords
      authorityRecords: (OFArray *)authorityRecords
     additionalRecords: (OFArray *)additionalRecords
	       context: (id)context
	     exception: (id)exception
{
	/*
	 * TODO: Error handling could be improved. Ignore error if there are
	 * responses, otherwise propagate error.
	 */

	of_socket_address_family_t addressFamily = [context intValue];

	_expectedResponses--;

	if (exception == nil) {
		for (OFDNSResourceRecord *record in answerRecords) {
			if (![[record name] isEqual: domainName])
				continue;

			if ([record recordClass] !=
			    OF_DNS_RESOURCE_RECORD_CLASS_IN)
				continue;

			switch ([record recordType]) {
			case OF_DNS_RESOURCE_RECORD_TYPE_A:
				if (addressFamily ==







|
|
|













|
|
<
<







827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851


852
853
854
855
856
857
858
	[_records release];

	[super dealloc];
}

-	(void)resolver: (OFDNSResolver *)resolver
  didResolveDomainName: (OFString *)domainName
	 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
	 * responses, otherwise propagate error.
	 */

	of_socket_address_family_t addressFamily = [context intValue];

	_expectedResponses--;

	if (exception == nil) {
		for (OFDNSResourceRecord *record in
		    [answerRecords objectForKey: domainName]) {


			if ([record recordClass] !=
			    OF_DNS_RESOURCE_RECORD_CLASS_IN)
				continue;

			switch ([record recordType]) {
			case OF_DNS_RESOURCE_RECORD_TYPE_A:
				if (addressFamily ==
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
-      (bool)of_socket: (OFUDPSocket *)sock
  didReceiveIntoBuffer: (unsigned char *)buffer
		length: (size_t)length
		sender: (of_socket_address_t)sender
	       context: (id)context
	     exception: (id)exception
{
	OFArray *answerRecords = nil, *authorityRecords = nil;
	OFArray *additionalRecords = nil;
	OFNumber *ID;
	OFDNSResolverQuery *query;

	if (exception != nil) {
		if ([exception respondsToSelector: @selector(errNo)])
			return ([exception errNo] == EINTR);








|
|







1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
-      (bool)of_socket: (OFUDPSocket *)sock
  didReceiveIntoBuffer: (unsigned char *)buffer
		length: (size_t)length
		sender: (of_socket_address_t)sender
	       context: (id)context
	     exception: (id)exception
{
	OFDictionary *answerRecords = nil, *authorityRecords = nil;
	OFDictionary *additionalRecords = nil;
	OFNumber *ID;
	OFDNSResolverQuery *query;

	if (exception != nil) {
		if ([exception respondsToSelector: @selector(errNo)])
			return ([exception errNo] == EINTR);