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" ;
@@ -222,7 +223,7 @@ class ThingDiscovery extends Stream<ThingDescription>
222223 if (dnsName.endsWith ("local" )) {
223224 yield * _discoverUsingMdnssd (dnsName);
224225 } else {
225- throw UnimplementedError ( "Only mDNS-SD is currently supported!" );
226+ yield * _discoverUsingDnsSd (dnsName );
226227 }
227228 }
228229
@@ -242,24 +243,97 @@ class ThingDiscovery extends Stream<ThingDescription>
242243 );
243244 }
244245
246+ Map <String , String > _parseTxtRecords (String txtRecords) {
247+ final recordsList = txtRecords
248+ .split ("\n " )
249+ .map ((property) => property.split ("=" ))
250+ .where ((list) => list.length > 1 )
251+ .map ((list) => MapEntry (list[0 ], list[1 ]));
252+
253+ return Map .fromEntries (recordsList);
254+ }
255+
245256 Future <Map <String , String >?> _lookupTxtRecords (
246257 MDnsClient client,
247258 String domainName,
248259 ) async {
249260 final txtRecords = await client
250261 .lookup <TxtResourceRecord >(ResourceRecordQuery .text (domainName))
251262 .toList ();
252- final recordsList = txtRecords.firstOrNull? .text
253- .split ("\n " )
254- .map ((property) => property.split ("=" ))
255- .where ((list) => list.length > 1 )
256- .map ((list) => MapEntry (list[0 ], list[1 ]));
257263
258- if (recordsList == null ) {
264+ final firstTxtRecord = txtRecords.firstOrNull? .text;
265+
266+ if (firstTxtRecord == null ) {
259267 return null ;
260268 }
261269
262- return Map .fromEntries (recordsList);
270+ return _parseTxtRecords (firstTxtRecord);
271+ }
272+
273+ Stream <ThingDescription > _discoverUsingDnsSd (String name) async * {
274+ // TODO: Refactor
275+ final ptrRecords = await DnsUtils .lookupRecord (name, RRecordType .PTR );
276+ final defaultScheme = _isUdpDiscovery (name) ? "coap" : "http" ;
277+ final discoveredUris = < Uri > {};
278+ const defaultType = "Thing" ;
279+
280+ for (final ptrRecord in ptrRecords ?? < RRecord > []) {
281+ final srvRecords =
282+ await DnsUtils .lookupRecord (ptrRecord.name, RRecordType .SRV );
283+
284+ for (final srvRecord in srvRecords ?? < RRecord > []) {
285+ final srvRecordEntries = srvRecord.data.split (" " );
286+
287+ final validSrvRecord = srvRecordEntries.length == 7 ;
288+
289+ if (! validSrvRecord) {
290+ continue ;
291+ }
292+
293+ final target = srvRecordEntries.last;
294+ final port =
295+ int .tryParse (srvRecordEntries[srvRecordEntries.length - 2 ]);
296+
297+ if (port == null ) {
298+ continue ;
299+ }
300+
301+ final txtRecords =
302+ await DnsUtils .lookupRecord (srvRecord.name, RRecordType .TXT ) ?? [];
303+
304+ final txtRecord = txtRecords.firstOrNull;
305+
306+ if (txtRecord == null ) {
307+ continue ;
308+ }
309+
310+ final parsedTxtRecord = _parseTxtRecords (txtRecord.data);
311+
312+ final uri = Uri (
313+ host: target,
314+ port: port,
315+ path: parsedTxtRecord["td" ],
316+ scheme: parsedTxtRecord["scheme" ] ?? defaultScheme,
317+ );
318+
319+ final duplicate = discoveredUris.add (uri);
320+
321+ if (duplicate) {
322+ continue ;
323+ }
324+
325+ final type = parsedTxtRecord["type" ] ?? defaultType;
326+
327+ print (parsedTxtRecord);
328+ switch (type) {
329+ case "Thing" :
330+ yield * _discoverDirectly (uri);
331+ case "Directory" :
332+ // TODO(JKRhb): Implement directory discovery.
333+ break ;
334+ }
335+ }
336+ }
263337 }
264338
265339 Stream <ThingDescription > _discoverUsingMdnssd (String name) async * {
0 commit comments