 Chromium Code Reviews
 Chromium Code Reviews| OLD | NEW | 
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 import 'dart:async'; | |
| 6 import 'dart:collection'; | |
| 7 import 'dart:io'; | |
| 8 import 'dart:typed_data'; | |
| 9 | |
| 10 import 'package:mdns/src/constants.dart'; | |
| 11 import 'package:mdns/src/lookup_resolver.dart'; | |
| 12 import 'package:mdns/src/packet.dart'; | |
| 13 | |
| 14 /// Client for DNS lookup using the mDNS protocol. | |
| 15 /// | |
| 16 /// This client only support "One-Shot Multicast DNS Queries" as described in | |
| 17 /// section 5.1 of https://tools.ietf.org/html/rfc6762 | |
| 18 class MDNSClient { | |
| 
karlklose
2015/10/28 10:14:30
I think this should be 'MDnsClient'.
 
Søren Gjesse
2015/10/28 11:36:57
Yes, you are probably right.
 | |
| 19 bool _starting = false; | |
| 20 bool _started = false; | |
| 21 RawDatagramSocket _incoming; | |
| 22 final List<RawDatagramSocket> _sockets = []; | |
| 
karlklose
2015/10/28 10:14:30
Consider adding a type to the list literal to catc
 
Søren Gjesse
2015/10/28 11:36:57
Done.
 | |
| 23 final LookupResolver _resolver = new LookupResolver(); | |
| 24 final Duration _defaultTimeout = new Duration(seconds: 5); | |
| 
karlklose
2015/10/28 10:14:30
Does it make sense to remove this field (it cannot
 
Søren Gjesse
2015/10/28 11:36:57
Absolutely. Done.
 | |
| 25 | |
| 26 MDNSClient(); | |
| 
karlklose
2015/10/28 10:14:30
Not needed.
 
Søren Gjesse
2015/10/28 11:36:57
Removed.
 | |
| 27 | |
| 28 /// Start the mDNS client. | |
| 29 Future start() async { | |
| 30 if (_started && _starting) { | |
| 31 throw new StateError('mDNS client already started'); | |
| 32 } | |
| 33 _starting = true; | |
| 34 | |
| 35 // Listen on all addresses. | |
| 36 _incoming = await RawDatagramSocket.bind( | |
| 37 InternetAddress.ANY_IP_V4, mDNSPort, reuseAddress: true); | |
| 38 | |
| 39 // Find all network interfaces with an IPv4 address. | |
| 40 var interfaces = | |
| 41 await NetworkInterface.list(type: InternetAddressType.IP_V4); | |
| 42 var socket; | |
| 
karlklose
2015/10/28 10:14:30
Move declaration to line 45?
 
Søren Gjesse
2015/10/28 11:36:57
Done.
 | |
| 43 for (int i = 0; i < interfaces.length; i++) { | |
| 
karlklose
2015/10/28 10:14:30
How about:
  for (NetworkInterface interface in i
 
Søren Gjesse
2015/10/28 11:36:57
Sure, done.
 | |
| 44 // Create a socket for sending on each adapter. | |
| 45 socket = await RawDatagramSocket.bind( | |
| 46 interfaces[i].addresses[0], mDNSPort, reuseAddress: true); | |
| 47 _sockets.add(socket); | |
| 48 | |
| 49 // Join multicast on this interface. | |
| 50 _incoming.joinMulticast(mDNSAddress, interfaces[i]); | |
| 51 } | |
| 52 _incoming.listen(_handleIncoming); | |
| 53 | |
| 54 _starting = false; | |
| 55 _started = true; | |
| 56 } | |
| 57 | |
| 58 /// Stop the mDNS client. | |
| 59 void stop() { | |
| 60 if (!_started) return; | |
| 
karlklose
2015/10/28 10:14:30
Should this method throw if '_starting == true'?
 
Søren Gjesse
2015/10/28 11:36:57
Done.
 | |
| 61 | |
| 62 _sockets.forEach((socket) => socket.close()); | |
| 63 _incoming.close(); | |
| 64 | |
| 65 _started = false; | |
| 66 } | |
| 67 | |
| 68 /// Lookup [hostname] using mDNS. | |
| 69 /// | |
| 70 /// The `hostname` must have the form `single-dns-label.local`, | |
| 71 /// e.g. `printer.local`. | |
| 72 /// | |
| 73 /// If no answer has been received within the specified [timeout] | |
| 74 /// this method will complete with the value `null`. | |
| 75 Future<InternetAddress> lookup(String hostname, {Duration timeout}) { | |
| 76 if (!_started) { | |
| 77 throw new StateError('mDNS client is not started'); | |
| 78 } | |
| 79 | |
| 80 // Add the pending request before sending the query. | |
| 81 var future = _resolver.addPendingRequest( | |
| 82 hostname, timeout != null ? timeout : _defaultTimeout); | |
| 83 | |
| 84 // Send the request on all interfaces. | |
| 85 List<int> packet = encodeMDNSQuery(hostname); | |
| 86 for (int i = 0; i < _sockets.length; i++) { | |
| 87 _sockets[i].send(packet, mDNSAddress, mDNSPort); | |
| 88 } | |
| 89 | |
| 90 return future; | |
| 91 } | |
| 92 | |
| 93 // Process incoming datagrams. | |
| 94 _handleIncoming(event) { | |
| 95 if (event == RawSocketEvent.READ) { | |
| 96 var data = _incoming.receive(); | |
| 97 var response = decodeMDNSResponse(data.data); | |
| 98 if (response != null) { | |
| 99 _resolver.handleResponse(response); | |
| 100 } | |
| 101 } | |
| 102 } | |
| 103 } | |
| 104 | |
| 105 // Simple standalone test. | |
| 106 main() async { | |
| 107 var client = new MDNSClient(); | |
| 108 await client.start(); | |
| 109 var address = await client.lookup('raspberrypi.local'); | |
| 110 client.stop(); | |
| 111 print(address); | |
| 112 } | |
| OLD | NEW |