Skip to content

Commit 49c0b2d

Browse files
committed
feat: implement unicast DNS-SD
1 parent d0bf7ad commit 49c0b2d

File tree

2 files changed

+83
-8
lines changed

2 files changed

+83
-8
lines changed

lib/src/core/thing_discovery.dart

Lines changed: 82 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import 'dart:async';
88

9+
import 'package:basic_utils/basic_utils.dart';
910
import 'package:coap/coap.dart';
1011
import 'package:collection/collection.dart';
1112
import 'package:multicast_dns/multicast_dns.dart';
@@ -231,7 +232,7 @@ class ThingDiscovery extends Stream<ThingDescription>
231232
if (dnsName.endsWith('local')) {
232233
yield* _discoverUsingMdnssd(dnsName);
233234
} else {
234-
throw UnimplementedError('Only mDNS-SD is currently supported!');
235+
yield* _discoverUsingDnsSd(dnsName);
235236
}
236237
}
237238

@@ -251,24 +252,97 @@ class ThingDiscovery extends Stream<ThingDescription>
251252
);
252253
}
253254

255+
Map<String, String> _parseTxtRecords(String txtRecords) {
256+
final recordsList = txtRecords
257+
.split('\n')
258+
.map((property) => property.split('='))
259+
.where((list) => list.length > 1)
260+
.map((list) => MapEntry(list[0], list[1]));
261+
262+
return Map.fromEntries(recordsList);
263+
}
264+
254265
Future<Map<String, String>?> _lookupTxtRecords(
255266
MDnsClient client,
256267
String domainName,
257268
) async {
258269
final txtRecords = await client
259270
.lookup<TxtResourceRecord>(ResourceRecordQuery.text(domainName))
260271
.toList();
261-
final recordsList = txtRecords.firstOrNull?.text
262-
.split('\n')
263-
.map((property) => property.split('='))
264-
.where((list) => list.length > 1)
265-
.map((list) => MapEntry(list[0], list[1]));
266272

267-
if (recordsList == null) {
273+
final firstTxtRecord = txtRecords.firstOrNull?.text;
274+
275+
if (firstTxtRecord == null) {
268276
return null;
269277
}
270278

271-
return Map.fromEntries(recordsList);
279+
return _parseTxtRecords(firstTxtRecord);
280+
}
281+
282+
Stream<ThingDescription> _discoverUsingDnsSd(String name) async* {
283+
// TODO: Refactor
284+
final ptrRecords = await DnsUtils.lookupRecord(name, RRecordType.PTR);
285+
final defaultScheme = _isUdpDiscovery(name) ? 'coap' : 'http';
286+
final discoveredUris = <Uri>{};
287+
const defaultType = 'Thing';
288+
289+
for (final ptrRecord in ptrRecords ?? <RRecord>[]) {
290+
final srvRecords =
291+
await DnsUtils.lookupRecord(ptrRecord.name, RRecordType.SRV);
292+
293+
for (final srvRecord in srvRecords ?? <RRecord>[]) {
294+
final srvRecordEntries = srvRecord.data.split(' ');
295+
296+
final validSrvRecord = srvRecordEntries.length == 7;
297+
298+
if (!validSrvRecord) {
299+
continue;
300+
}
301+
302+
final target = srvRecordEntries.last;
303+
final port =
304+
int.tryParse(srvRecordEntries[srvRecordEntries.length - 2]);
305+
306+
if (port == null) {
307+
continue;
308+
}
309+
310+
final txtRecords =
311+
await DnsUtils.lookupRecord(srvRecord.name, RRecordType.TXT) ?? [];
312+
313+
final txtRecord = txtRecords.firstOrNull;
314+
315+
if (txtRecord == null) {
316+
continue;
317+
}
318+
319+
final parsedTxtRecord = _parseTxtRecords(txtRecord.data);
320+
321+
final uri = Uri(
322+
host: target,
323+
port: port,
324+
path: parsedTxtRecord['td'],
325+
scheme: parsedTxtRecord['scheme'] ?? defaultScheme,
326+
);
327+
328+
final duplicate = discoveredUris.add(uri);
329+
330+
if (duplicate) {
331+
continue;
332+
}
333+
334+
final type = parsedTxtRecord['type'] ?? defaultType;
335+
336+
print(parsedTxtRecord);
337+
switch (type) {
338+
case 'Thing':
339+
yield* _discoverDirectly(uri);
340+
case 'Directory':
341+
// TODO(JKRhb): Implement directory discovery.
342+
break;
343+
}
344+
}
345+
}
272346
}
273347

274348
Stream<ThingDescription> _discoverUsingMdnssd(String name) async* {

pubspec.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ dev_dependencies:
1515
test: ^1.24.3
1616

1717
dependencies:
18+
basic_utils: ^5.6.1
1819
cbor: ^6.1.0
1920
coap: ^9.0.0
2021
collection: ^1.17.2

0 commit comments

Comments
 (0)