66
77import "dart:async" ;
88
9+ import "package:basic_utils/basic_utils.dart" ;
910import "package:coap/coap.dart" ;
1011import "package:collection/collection.dart" ;
1112import "package:multicast_dns/multicast_dns.dart" ;
@@ -219,7 +220,7 @@ class ThingDiscovery extends Stream<ThingDescription>
219220 if (dnsName.endsWith ("local" )) {
220221 yield * _discoverUsingMdnssd (dnsName);
221222 } else {
222- throw UnimplementedError ( "Only mDNS-SD is currently supported!" );
223+ yield * _discoverUsingDnsSd (dnsName );
223224 }
224225 }
225226
@@ -239,24 +240,97 @@ class ThingDiscovery extends Stream<ThingDescription>
239240 );
240241 }
241242
243+ Map <String , String > _parseTxtRecords (String txtRecords) {
244+ final recordsList = txtRecords
245+ .split ("\n " )
246+ .map ((property) => property.split ("=" ))
247+ .where ((list) => list.length > 1 )
248+ .map ((list) => MapEntry (list[0 ], list[1 ]));
249+
250+ return Map .fromEntries (recordsList);
251+ }
252+
242253 Future <Map <String , String >?> _lookupTxtRecords (
243254 MDnsClient client,
244255 String domainName,
245256 ) async {
246257 final txtRecords = await client
247258 .lookup <TxtResourceRecord >(ResourceRecordQuery .text (domainName))
248259 .toList ();
249- final recordsList = txtRecords.firstOrNull? .text
250- .split ("\n " )
251- .map ((property) => property.split ("=" ))
252- .where ((list) => list.length > 1 )
253- .map ((list) => MapEntry (list[0 ], list[1 ]));
254260
255- if (recordsList == null ) {
261+ final firstTxtRecord = txtRecords.firstOrNull? .text;
262+
263+ if (firstTxtRecord == null ) {
256264 return null ;
257265 }
258266
259- return Map .fromEntries (recordsList);
267+ return _parseTxtRecords (firstTxtRecord);
268+ }
269+
270+ Stream <ThingDescription > _discoverUsingDnsSd (String name) async * {
271+ // TODO: Refactor
272+ final ptrRecords = await DnsUtils .lookupRecord (name, RRecordType .PTR );
273+ final defaultScheme = _isUdpDiscovery (name) ? "coap" : "http" ;
274+ final discoveredUris = < Uri > {};
275+ const defaultType = "Thing" ;
276+
277+ for (final ptrRecord in ptrRecords ?? < RRecord > []) {
278+ final srvRecords =
279+ await DnsUtils .lookupRecord (ptrRecord.name, RRecordType .SRV );
280+
281+ for (final srvRecord in srvRecords ?? < RRecord > []) {
282+ final srvRecordEntries = srvRecord.data.split (" " );
283+
284+ final validSrvRecord = srvRecordEntries.length == 7 ;
285+
286+ if (! validSrvRecord) {
287+ continue ;
288+ }
289+
290+ final target = srvRecordEntries.last;
291+ final port =
292+ int .tryParse (srvRecordEntries[srvRecordEntries.length - 2 ]);
293+
294+ if (port == null ) {
295+ continue ;
296+ }
297+
298+ final txtRecords =
299+ await DnsUtils .lookupRecord (srvRecord.name, RRecordType .TXT ) ?? [];
300+
301+ final txtRecord = txtRecords.firstOrNull;
302+
303+ if (txtRecord == null ) {
304+ continue ;
305+ }
306+
307+ final parsedTxtRecord = _parseTxtRecords (txtRecord.data);
308+
309+ final uri = Uri (
310+ host: target,
311+ port: port,
312+ path: parsedTxtRecord["td" ],
313+ scheme: parsedTxtRecord["scheme" ] ?? defaultScheme,
314+ );
315+
316+ final duplicate = discoveredUris.add (uri);
317+
318+ if (duplicate) {
319+ continue ;
320+ }
321+
322+ final type = parsedTxtRecord["type" ] ?? defaultType;
323+
324+ print (parsedTxtRecord);
325+ switch (type) {
326+ case "Thing" :
327+ yield * _discoverDirectly (uri);
328+ case "Directory" :
329+ // TODO(JKRhb): Implement directory discovery.
330+ break ;
331+ }
332+ }
333+ }
260334 }
261335
262336 Stream <ThingDescription > _discoverUsingMdnssd (String name) async * {
0 commit comments