Line data Source code
1 : import 'package:multicast_dns/multicast_dns.dart';
2 : import 'package:network_tools/network_tools.dart';
3 : import 'package:network_tools/src/mdns_scanner/get_srv_list_by_os/srv_list.dart';
4 : import 'package:network_tools/src/network_tools_utils.dart';
5 : import 'package:universal_io/io.dart';
6 :
7 : class MdnsScannerServiceImpl extends MdnsScannerService {
8 : /// This method searching for all the mdns devices in the network.
9 : /// TODO: The implementation is **Lacking!** and will not find all the
10 : /// TODO: results that actual exist in the network!, only some of them.
11 : /// TODO: This is because missing functionality in dart
12 : /// TODO: https://github.com/flutter/flutter/issues/97210
13 : /// TODO: In some cases we resolve this missing functionality using
14 : /// TODO: specific os tools.
15 :
16 1 : @override
17 : Future<List<ActiveHost>> searchMdnsDevices({
18 : bool forceUseOfSavedSrvRecordList = false,
19 : }) async {
20 : List<String> srvRecordListToSearchIn;
21 :
22 : if (forceUseOfSavedSrvRecordList) {
23 0 : srvRecordListToSearchIn = tcpSrvRecordsList;
24 0 : srvRecordListToSearchIn.addAll(udpSrvRecordsList);
25 : } else {
26 1 : final List<String>? srvRecordsFromOs = await SrvList.getSrvRecordList();
27 :
28 1 : if (srvRecordsFromOs == null || srvRecordsFromOs.isEmpty) {
29 1 : srvRecordListToSearchIn = tcpSrvRecordsList;
30 2 : srvRecordListToSearchIn.addAll(udpSrvRecordsList);
31 : } else {
32 : srvRecordListToSearchIn = srvRecordsFromOs;
33 : }
34 : }
35 :
36 1 : final List<Future<List<ActiveHost>>> activeHostListsFuture = [];
37 2 : for (final String srvRecord in srvRecordListToSearchIn) {
38 2 : activeHostListsFuture.add(findingMdnsWithAddress(srvRecord));
39 : }
40 :
41 1 : final List<ActiveHost> activeHostList = [];
42 :
43 : for (final Future<List<ActiveHost>> activeHostListFuture
44 2 : in activeHostListsFuture) {
45 1 : activeHostList.addAll(await activeHostListFuture);
46 : }
47 :
48 : return activeHostList;
49 : }
50 :
51 1 : @override
52 : Future<List<ActiveHost>> findingMdnsWithAddress(String serviceType) async {
53 1 : final MDnsClient client = MDnsClient(
54 : rawDatagramSocketFactory:
55 1 : (
56 : dynamic host,
57 : int port, {
58 : bool? reuseAddress,
59 : bool? reusePort,
60 : int? ttl,
61 : }) {
62 1 : return RawDatagramSocket.bind(
63 : host,
64 : port,
65 2 : reusePort: !Platform.isWindows && !Platform.isAndroid,
66 : ttl: ttl!,
67 : );
68 : },
69 : );
70 :
71 1 : final List<ActiveHost> listOfActiveHost = [];
72 1 : await client.start();
73 :
74 2 : await for (final PtrResourceRecord ptr in client.lookup<PtrResourceRecord>(
75 1 : ResourceRecordQuery.serverPointer(serviceType),
76 0 : )) {
77 0 : await for (final SrvResourceRecord srv
78 0 : in client.lookup<SrvResourceRecord>(
79 0 : ResourceRecordQuery.service(ptr.domainName),
80 0 : )) {
81 0 : await for (final TxtResourceRecord txtRecords
82 0 : in client.lookup<TxtResourceRecord>(
83 0 : ResourceRecordQuery.text(ptr.domainName),
84 0 : )) {
85 0 : listOfActiveHost.addAll(
86 0 : await findAllActiveHostForSrv(
87 0 : addressType: InternetAddress.anyIPv4,
88 : client: client,
89 : ptr: ptr,
90 : srv: srv,
91 : txt: txtRecords,
92 : ),
93 : );
94 0 : listOfActiveHost.addAll(
95 0 : await findAllActiveHostForSrv(
96 0 : addressType: InternetAddress.anyIPv6,
97 : client: client,
98 : ptr: ptr,
99 : srv: srv,
100 : txt: txtRecords,
101 : ),
102 : );
103 : }
104 : }
105 : }
106 1 : client.stop();
107 :
108 : return listOfActiveHost;
109 : }
110 :
111 0 : @override
112 : Future<List<ActiveHost>> findAllActiveHostForSrv({
113 : required InternetAddress addressType,
114 : required MDnsClient client,
115 : required PtrResourceRecord ptr,
116 : required SrvResourceRecord srv,
117 : required TxtResourceRecord txt,
118 : }) async {
119 0 : final List<ActiveHost> listOfActiveHost = [];
120 : try {
121 : Stream<IPAddressResourceRecord> iPAddressResourceRecordStream;
122 :
123 0 : if (addressType == InternetAddress.anyIPv4) {
124 0 : iPAddressResourceRecordStream = client.lookup<IPAddressResourceRecord>(
125 0 : ResourceRecordQuery.addressIPv4(srv.target),
126 : );
127 : } else {
128 0 : iPAddressResourceRecordStream = client.lookup<IPAddressResourceRecord>(
129 0 : ResourceRecordQuery.addressIPv6(srv.target),
130 : );
131 : }
132 0 : await for (final IPAddressResourceRecord ip
133 0 : in iPAddressResourceRecordStream) {
134 0 : final ActiveHost activeHost = convertSrvToHostName(
135 0 : internetAddress: InternetAddress.fromRawAddress(
136 0 : ip.address.rawAddress,
137 : ),
138 : ptr: ptr,
139 : srv: srv,
140 : txt: txt,
141 : );
142 :
143 0 : listOfActiveHost.add(activeHost);
144 : }
145 : } catch (e) {
146 0 : logger.severe(
147 0 : 'Error finding ip of mdns record ${ptr.name} srv target ${srv.target}, will add it with ip 0.0.0.0\n$e',
148 : );
149 0 : final ActiveHost activeHost = convertSrvToHostName(
150 0 : internetAddress: InternetAddress('0.0.0.0'),
151 : srv: srv,
152 : ptr: ptr,
153 : txt: txt,
154 : );
155 0 : listOfActiveHost.add(activeHost);
156 : }
157 : return listOfActiveHost;
158 : }
159 :
160 0 : @override
161 : ActiveHost convertSrvToHostName({
162 : required InternetAddress internetAddress,
163 : required PtrResourceRecord ptr,
164 : required SrvResourceRecord srv,
165 : required TxtResourceRecord txt,
166 : }) {
167 0 : final MdnsInfo mdnsInfo = MdnsInfo(
168 : srvResourceRecord: srv,
169 : ptrResourceRecord: ptr,
170 : txtResourceRecord: txt,
171 : );
172 0 : return ActiveHost(internetAddress: internetAddress, mdnsInfoVar: mdnsInfo);
173 : }
174 : }
|