ObjFW  Check-in [bd5e1e2014]

Overview
Comment:Create an OFDNSResourceRecord subclass per type
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: bd5e1e20145c784d8a20c31890ef25e62a8c749aee7cd5130af9ffbfd11223e8
User & Date: js on 2018-07-30 22:24:09
Other Links: manifest | tags
Context
2018-07-31
00:41
OFDNSResolver: Add support for parsing MX records check-in: 650fdd14e3 user: js tags: trunk
2018-07-30
22:24
Create an OFDNSResourceRecord subclass per type check-in: bd5e1e2014 user: js tags: trunk
00:07
OFDNSResolver: Add support for parsing AAAAs check-in: 589a3e0f13 user: js tags: trunk
Changes

Modified src/OFDNSResolver.m from [9fbb4cad64] to [16d3a398be].

58
59
60
61
62
63
64

65
66
67
68
69
70
71
 * TODO:
 *
 *  - Timeouts
 *  - Resolve with each search domain
 *  - Iterate through name servers
 *  - IPv6 for talking to the name servers
 *  - Fallback to TCP

 */

@interface OFDNSResolver_context: OFObject
{
	OFString *_host;
	OFArray OF_GENERIC(OFString *) *_nameServers, *_searchDomains;
	size_t _nameServersIndex, _searchDomainsIndex;







>







58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
 * TODO:
 *
 *  - Timeouts
 *  - Resolve with each search domain
 *  - Iterate through name servers
 *  - IPv6 for talking to the name servers
 *  - Fallback to TCP
 *  - More record types
 */

@interface OFDNSResolver_context: OFObject
{
	OFString *_host;
	OFArray OF_GENERIC(OFString *) *_nameServers, *_searchDomains;
	size_t _nameServersIndex, _searchDomainsIndex;
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196

	*idx = i;

	return [components componentsJoinedByString: @"."];
}

static OFString *
parseAAAA(const unsigned char *buffer)
{
	OFMutableString *data = [OFMutableString string];
	int_fast8_t zerosStart = -1, maxZerosStart = -1;
	uint_fast8_t zerosCount = 0, maxZerosCount = 0;
	bool first = true;

	for (uint_fast8_t i = 0; i < 16; i += 2) {







|







183
184
185
186
187
188
189
190
191
192
193
194
195
196
197

	*idx = i;

	return [components componentsJoinedByString: @"."];
}

static OFString *
parseAAAAData(const unsigned char *buffer)
{
	OFMutableString *data = [OFMutableString string];
	int_fast8_t zerosStart = -1, maxZerosStart = -1;
	uint_fast8_t zerosCount = 0, maxZerosCount = 0;
	bool first = true;

	for (uint_fast8_t i = 0; i < 16; i += 2) {
240
241
242
243
244
245
246
247
248
249
250

251

252
253
254
255
256
257
258
259
260
261
262

263
264
265
266
267
268
269
270

271
272
273
274
275
276
277
278
279
280
281
282
283

284
285
286

287
288
289
290
291

292
293
294




295

296
297
298
299
300
301
302
	}

	[data makeImmutable];

	return data;
}

static id
parseData(const unsigned char *buffer, size_t length, size_t i,
    size_t dataLength, of_dns_resource_record_class_t recordClass,
    of_dns_resource_record_type_t recordType)

{

	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]];
			break;
		case OF_DNS_RESOURCE_RECORD_TYPE_CNAME:
			j = i;


			data = parseName(buffer, length, &j,
			    ALLOWED_POINTER_LEVELS);

			if (j != i + dataLength)
				@throw [OFInvalidServerReplyException
				    exception];

			break;
		case OF_DNS_RESOURCE_RECORD_TYPE_AAAA:
			if (dataLength != 16)
				@throw [OFInvalidServerReplyException
				    exception];


			data = parseAAAA(&buffer[i]);
			break;
		default:

			data = [OFData dataWithItems: &buffer[i]
					       count: dataLength];
			break;
		}
	} else

		data = [OFData dataWithItems: &buffer[i]
				       count: dataLength];





	return data;

}

@implementation OFDNSResolver_context
@synthesize host = _host, nameServers = _nameServers;
@synthesize searchDomains = _searchDomains;
@synthesize nameServersIndex = _nameServersIndex;
@synthesize searchDomainsIndex = _searchDomainsIndex, queryData = _queryData;







|
<
|
|
>

>











>








>













>
|


>




|
>


|
>
>
>
>
|
>







241
242
243
244
245
246
247
248

249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
	}

	[data makeImmutable];

	return data;
}

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)
{
	Class class;
	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];

			class = [OFADNSResourceRecord class];
			data = [OFString stringWithFormat:
			    @"%u.%u.%u.%u",
			    buffer[i], buffer[i + 1],
			    buffer[i + 2], buffer[i + 3]];
			break;
		case OF_DNS_RESOURCE_RECORD_TYPE_CNAME:
			j = i;

			class = [OFCNAMEDNSResourceRecord class];
			data = parseName(buffer, length, &j,
			    ALLOWED_POINTER_LEVELS);

			if (j != i + dataLength)
				@throw [OFInvalidServerReplyException
				    exception];

			break;
		case OF_DNS_RESOURCE_RECORD_TYPE_AAAA:
			if (dataLength != 16)
				@throw [OFInvalidServerReplyException
				    exception];

			class = [OFAAAADNSResourceRecord class];
			data = parseAAAAData(&buffer[i]);
			break;
		default:
			class = [OFDNSResourceRecord class];
			data = [OFData dataWithItems: &buffer[i]
					       count: dataLength];
			break;
		}
	} else {
		class = [OFDNSResourceRecord class];
		data = [OFData dataWithItems: &buffer[i]
				       count: dataLength];
	}

	return [[[class alloc] initWithName: name
				recordClass: recordClass
				 recordType: recordType
				       data: data
					TTL: TTL] autorelease];
}

@implementation OFDNSResolver_context
@synthesize host = _host, nameServers = _nameServers;
@synthesize searchDomains = _searchDomains;
@synthesize nameServersIndex = _nameServersIndex;
@synthesize searchDomainsIndex = _searchDomainsIndex, queryData = _queryData;
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768

769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
		for (uint_fast16_t j = 0; j < numAnswers; j++) {
			OFString *name = parseName(buffer, length, &i,
			    ALLOWED_POINTER_LEVELS);
			of_dns_resource_record_class_t recordClass;
			of_dns_resource_record_type_t recordType;
			uint32_t TTL;
			uint16_t dataLength;
			id data;
			OFDNSResourceRecord *record;

			if (i + 10 > length)
				@throw [OFTruncatedDataException exception];

			recordType = (buffer[i] << 16) | buffer[i + 1];
			recordClass = (buffer[i + 2] << 16) | buffer[i + 3];
			TTL = (buffer[i + 4] << 24) | (buffer[i + 5] << 16) |
			    (buffer[i + 6] << 8) | buffer[i + 7];
			dataLength = (buffer[i + 8] << 16) | buffer[i + 9];

			i += 10;

			if (i + dataLength > length)
				@throw [OFTruncatedDataException exception];


			data = parseData(buffer, length, i, dataLength,
			    recordClass, recordType);
			i += dataLength;

			record = [[[OFDNSResourceRecord alloc]
			    initWithName: name
			     recordClass: recordClass
			      recordType: recordType
				    data: data
				     TTL: TTL] autorelease];

			[answers addObject: record];
		}
	} @catch (id e) {
		callback(target, selector, nil,
		    [DNSResolverContext userContext], e);
		return false;
	}







<
















>
|
<


<
<
<
<
<
<
<







757
758
759
760
761
762
763

764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781

782
783







784
785
786
787
788
789
790
		for (uint_fast16_t j = 0; j < numAnswers; j++) {
			OFString *name = parseName(buffer, length, &i,
			    ALLOWED_POINTER_LEVELS);
			of_dns_resource_record_class_t recordClass;
			of_dns_resource_record_type_t recordType;
			uint32_t TTL;
			uint16_t dataLength;

			OFDNSResourceRecord *record;

			if (i + 10 > length)
				@throw [OFTruncatedDataException exception];

			recordType = (buffer[i] << 16) | buffer[i + 1];
			recordClass = (buffer[i + 2] << 16) | buffer[i + 3];
			TTL = (buffer[i + 4] << 24) | (buffer[i + 5] << 16) |
			    (buffer[i + 6] << 8) | buffer[i + 7];
			dataLength = (buffer[i + 8] << 16) | buffer[i + 9];

			i += 10;

			if (i + dataLength > length)
				@throw [OFTruncatedDataException exception];

			record = createResourceRecord(name, recordClass,
			    recordType, TTL, buffer, length, i, dataLength);

			i += dataLength;








			[answers addObject: record];
		}
	} @catch (id e) {
		callback(target, selector, nil,
		    [DNSResolverContext userContext], e);
		return false;
	}

Modified src/OFDNSResourceRecord.h from [ad1d163440] to [78e8b495b5].

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
	/*! All types. Only for queries. */
	OF_DNS_RESOURCE_RECORD_TYPE_ALL	  = 255,
} of_dns_resource_record_type_t;

/*!
 * @class OFDNSResourceRecord OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class represenging a DNS resource record.
 */
@interface OFDNSResourceRecord: OFObject
{
	OFString *_name;
	of_dns_resource_record_class_t _recordClass;
	of_dns_resource_record_type_t _recordType;
	id _data;







|







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
	/*! All types. Only for queries. */
	OF_DNS_RESOURCE_RECORD_TYPE_ALL	  = 255,
} of_dns_resource_record_type_t;

/*!
 * @class OFDNSResourceRecord OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing a DNS resource record.
 */
@interface OFDNSResourceRecord: OFObject
{
	OFString *_name;
	of_dns_resource_record_class_t _recordClass;
	of_dns_resource_record_type_t _recordType;
	id _data;
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111






































112
113
114
115
116
117
118
119
120
121
122
123
/*!
 * @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.
 *
 * For A and AAAA records, this is a string with the IP address.
 * For CNAME records, this is a string with the alias.
 * For anything else, this is OFData.
 */
@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;

- (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







































#ifdef __cplusplus
extern "C" {
#endif
extern OFString *_Nonnull of_dns_resource_record_class_to_string(
    of_dns_resource_record_class_t recordClass);
extern OFString *_Nonnull of_dns_resource_record_type_to_string(
    of_dns_resource_record_type_t recordType);
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END







<
<
<
<
















>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>












85
86
87
88
89
90
91




92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/*!
 * @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;

- (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
/*!
 * A string with the IP address.
 */
@property (readonly, nonatomic) OFString *data;
@end

/*!
 * @class OFAAAADNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class represenging a DNS resource record.
 */
@interface OFAAAADNSResourceRecord: OFDNSResourceRecord
/*!
 * A string with the IP address.
 */
@property (readonly, nonatomic) OFString *data;
@end

/*!
 * @class OFCNAMEDNSResourceRecord \
 *	  OFDNSResourceRecord.h ObjFW/OFDNSResourceRecord.h
 *
 * @brief A class representing a CNAME DNS resource record.
 */
@interface OFCNAMEDNSResourceRecord: OFDNSResourceRecord
/*!
 * A string with the alias.
 */
@property (readonly, nonatomic) OFString *data;
@end

#ifdef __cplusplus
extern "C" {
#endif
extern OFString *_Nonnull of_dns_resource_record_class_to_string(
    of_dns_resource_record_class_t recordClass);
extern OFString *_Nonnull of_dns_resource_record_type_to_string(
    of_dns_resource_record_type_t recordType);
#ifdef __cplusplus
}
#endif

OF_ASSUME_NONNULL_END

Modified src/OFDNSResourceRecord.m from [9ea581e271] to [745465fb73].

156
157
158
159
160
161
162





















	    @"\tData = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    _name, of_dns_resource_record_class_to_string(_recordClass),
	    of_dns_resource_record_type_to_string(_recordType), _data, _TTL];
}
@end




























>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
	    @"\tData = %@\n"
	    @"\tTTL = %" PRIu32 "\n"
	    @">",
	    _name, of_dns_resource_record_class_to_string(_recordClass),
	    of_dns_resource_record_type_to_string(_recordType), _data, _TTL];
}
@end

@implementation OFADNSResourceRecord
- (OFString *)data
{
	return _data;
}
@end

@implementation OFAAAADNSResourceRecord
- (OFString *)data
{
	return _data;
}
@end

@implementation OFCNAMEDNSResourceRecord
- (OFString *)data
{
	return _data;
}
@end