Allow configuration of port and address

This commit is contained in:
Jonah Williams
2019-07-31 09:46:22 -07:00
committed by GitHub
parent bc85a0b605
commit caf02e0174
4 changed files with 70 additions and 7 deletions

View File

@ -1,3 +1,6 @@
## 0.2.0
* Allow configuration of the port and address the mdns query is performed on.
## 0.1.1 ## 0.1.1
* Fixes [flutter/issue/31854](https://github.com/flutter/flutter/issues/31854) where `decodeMDnsResponse` advanced to incorrect code points and ignored some records. * Fixes [flutter/issue/31854](https://github.com/flutter/flutter/issues/31854) where `decodeMDnsResponse` advanced to incorrect code points and ignored some records.

View File

@ -24,6 +24,14 @@ export 'package:multicast_dns/src/resource_record.dart';
typedef NetworkInterfacesFactory = Future<Iterable<NetworkInterface>> Function( typedef NetworkInterfacesFactory = Future<Iterable<NetworkInterface>> Function(
InternetAddressType type); InternetAddressType type);
/// A factory for construction of datagram sockets.
///
/// This can be injected into the [MDnsClient] to provide alternative
/// implementations of [RawDatagramSocket.bind].
typedef RawDatagramSocketFactory = Future<RawDatagramSocket> Function(
dynamic host, int port,
{bool reuseAddress, bool reusePort, int ttl});
/// Client for DNS lookup and publishing using the mDNS protocol. /// Client for DNS lookup and publishing using the mDNS protocol.
/// ///
/// Users should call [MDnsQuerier.start] when ready to start querying and /// Users should call [MDnsQuerier.start] when ready to start querying and
@ -33,13 +41,21 @@ typedef NetworkInterfacesFactory = Future<Iterable<NetworkInterface>> Function(
/// This client only supports "One-Shot Multicast DNS Queries" as described in /// This client only supports "One-Shot Multicast DNS Queries" as described in
/// section 5.1 of [RFC 6762](https://tools.ietf.org/html/rfc6762). /// section 5.1 of [RFC 6762](https://tools.ietf.org/html/rfc6762).
class MDnsClient { class MDnsClient {
/// Create a new [MDnsClient].
MDnsClient({
RawDatagramSocketFactory rawDatagramSocketFactory = RawDatagramSocket.bind,
}) : _rawDatagramSocketFactory = rawDatagramSocketFactory;
bool _starting = false; bool _starting = false;
bool _started = false; bool _started = false;
RawDatagramSocket _incoming; RawDatagramSocket _incoming;
final List<RawDatagramSocket> _sockets = <RawDatagramSocket>[]; final List<RawDatagramSocket> _sockets = <RawDatagramSocket>[];
final LookupResolver _resolver = LookupResolver(); final LookupResolver _resolver = LookupResolver();
final ResourceRecordCache _cache = ResourceRecordCache(); final ResourceRecordCache _cache = ResourceRecordCache();
final RawDatagramSocketFactory _rawDatagramSocketFactory;
InternetAddress _mDnsAddress; InternetAddress _mDnsAddress;
int _mDnsPort;
/// Find all network interfaces with an the [InternetAddressType] specified. /// Find all network interfaces with an the [InternetAddressType] specified.
static NetworkInterfacesFactory allInterfacesFactory = static NetworkInterfacesFactory allInterfacesFactory =
@ -58,12 +74,23 @@ class MDnsClient {
/// [InternetAddress.anyIPv6], and will default to anyIPv4. /// [InternetAddress.anyIPv6], and will default to anyIPv4.
/// ///
/// The [interfaceFactory] defaults to [allInterfacesFactory]. /// The [interfaceFactory] defaults to [allInterfacesFactory].
///
/// The [mDnsPort] allows configuring what port is used for the mDNS
/// query. If not provided, defaults to `5353`.
///
/// The [mDnsAddress] allows configuring what internet address is used
/// for the mDNS query. If not provided, defaults to either `224.0.0.251` or
/// or `FF02::FB`.
Future<void> start({ Future<void> start({
InternetAddress listenAddress, InternetAddress listenAddress,
NetworkInterfacesFactory interfacesFactory, NetworkInterfacesFactory interfacesFactory,
int mDnsPort = mDnsPort,
InternetAddress mDnsAddress,
}) async { }) async {
listenAddress ??= InternetAddress.anyIPv4; listenAddress ??= InternetAddress.anyIPv4;
interfacesFactory ??= allInterfacesFactory; interfacesFactory ??= allInterfacesFactory;
_mDnsPort = mDnsPort;
_mDnsAddress = mDnsAddress;
assert(listenAddress.address == InternetAddress.anyIPv4.address || assert(listenAddress.address == InternetAddress.anyIPv4.address ||
listenAddress.address == InternetAddress.anyIPv6.address); listenAddress.address == InternetAddress.anyIPv6.address);
@ -74,9 +101,9 @@ class MDnsClient {
_starting = true; _starting = true;
// Listen on all addresses. // Listen on all addresses.
_incoming = await RawDatagramSocket.bind( _incoming = await _rawDatagramSocketFactory(
listenAddress.address, listenAddress.address,
mDnsPort, _mDnsPort,
reuseAddress: true, reuseAddress: true,
reusePort: true, reusePort: true,
ttl: 255, ttl: 255,
@ -87,7 +114,7 @@ class MDnsClient {
_sockets.add(_incoming); _sockets.add(_incoming);
} }
_mDnsAddress = _incoming.address.type == InternetAddressType.IPv4 _mDnsAddress ??= _incoming.address.type == InternetAddressType.IPv4
? mDnsAddressIPv4 ? mDnsAddressIPv4
: mDnsAddressIPv6; : mDnsAddressIPv6;
@ -97,9 +124,9 @@ class MDnsClient {
for (NetworkInterface interface in interfaces) { for (NetworkInterface interface in interfaces) {
// Create a socket for sending on each adapter. // Create a socket for sending on each adapter.
final InternetAddress targetAddress = interface.addresses[0]; final InternetAddress targetAddress = interface.addresses[0];
final RawDatagramSocket socket = await RawDatagramSocket.bind( final RawDatagramSocket socket = await _rawDatagramSocketFactory(
targetAddress, targetAddress,
mDnsPort, _mDnsPort,
reuseAddress: true, reuseAddress: true,
reusePort: true, reusePort: true,
ttl: 255, ttl: 255,
@ -180,7 +207,7 @@ class MDnsClient {
// Send the request on all interfaces. // Send the request on all interfaces.
final List<int> packet = query.encode(); final List<int> packet = query.encode();
for (RawDatagramSocket socket in _sockets) { for (RawDatagramSocket socket in _sockets) {
socket.send(packet, _mDnsAddress, mDnsPort); socket.send(packet, _mDnsAddress, _mDnsPort);
} }
return results; return results;
} }

View File

@ -2,13 +2,14 @@ name: multicast_dns
description: Dart package for mDNS queries (e.g. Bonjour, Avahi). description: Dart package for mDNS queries (e.g. Bonjour, Avahi).
author: Flutter Team <flutter-dev@googlegroups.com> author: Flutter Team <flutter-dev@googlegroups.com>
homepage: https://github.com/flutter/packages/tree/master/packages/multicast_dns homepage: https://github.com/flutter/packages/tree/master/packages/multicast_dns
version: 0.1.1 version: 0.2.0
dependencies: dependencies:
meta: ^1.1.6 meta: ^1.1.6
dev_dependencies: dev_dependencies:
test: "^1.3.4" test: "^1.3.4"
mockito: "^4.1.0"
environment: environment:
sdk: ">=2.1.1-dev.2.0 <3.0.0" sdk: ">=2.1.1-dev.2.0 <3.0.0"

View File

@ -0,0 +1,32 @@
// Copyright (c) 2015, the Dartino project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:io';
import 'package:multicast_dns/multicast_dns.dart';
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';
void main() {
test('Can inject datagram socket factory and configure mdns port', () async {
int lastPort;
final MockRawDatagramSocket mockRawDatagramSocket = MockRawDatagramSocket();
final MDnsClient client = MDnsClient(rawDatagramSocketFactory:
(dynamic host, int port,
{bool reuseAddress, bool reusePort, int ttl = 1}) async {
lastPort = port;
return mockRawDatagramSocket;
});
when(mockRawDatagramSocket.address).thenReturn(InternetAddress.anyIPv4);
await client.start(
mDnsPort: 1234,
interfacesFactory: (InternetAddressType type) async =>
<NetworkInterface>[]);
expect(lastPort, 1234);
});
}
class MockRawDatagramSocket extends Mock implements RawDatagramSocket {}