Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/multicast_dns/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.3.0

* Migrate package to null safety.

## 0.2.2
* Fixes parsing of TXT records. Continues parsing on non-utf8 strings.

Expand Down
45 changes: 24 additions & 21 deletions packages/multicast_dns/lib/multicast_dns.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,13 @@ class MDnsClient {

bool _starting = false;
bool _started = false;
RawDatagramSocket _incoming;
final List<RawDatagramSocket> _sockets = <RawDatagramSocket>[];
final LookupResolver _resolver = LookupResolver();
final ResourceRecordCache _cache = ResourceRecordCache();
final RawDatagramSocketFactory _rawDatagramSocketFactory;

InternetAddress _mDnsAddress;
int _mDnsPort;
InternetAddress? _mDnsAddress;
int? _mDnsPort;

/// Find all network interfaces with an the [InternetAddressType] specified.
static NetworkInterfacesFactory allInterfacesFactory =
Expand All @@ -82,14 +81,14 @@ class MDnsClient {
/// for the mDNS query. If not provided, defaults to either `224.0.0.251` or
/// or `FF02::FB`.
Future<void> start({
InternetAddress listenAddress,
NetworkInterfacesFactory interfacesFactory,
InternetAddress? listenAddress,
NetworkInterfacesFactory? interfacesFactory,
int mDnsPort = mDnsPort,
InternetAddress mDnsAddress,
InternetAddress? mDnsAddress,
}) async {
listenAddress ??= InternetAddress.anyIPv4;
interfacesFactory ??= allInterfacesFactory;
_mDnsPort = mDnsPort;
final int selectedMDnsPort = _mDnsPort = mDnsPort;
_mDnsAddress = mDnsAddress;

assert(listenAddress.address == InternetAddress.anyIPv4.address ||
Expand All @@ -101,32 +100,32 @@ class MDnsClient {
_starting = true;

// Listen on all addresses.
_incoming = await _rawDatagramSocketFactory(
final RawDatagramSocket incoming = await _rawDatagramSocketFactory(
listenAddress.address,
_mDnsPort,
selectedMDnsPort,
reuseAddress: true,
reusePort: true,
ttl: 255,
);

// Can't send to IPv6 any address.
if (_incoming.address != InternetAddress.anyIPv6) {
_sockets.add(_incoming);
if (incoming.address != InternetAddress.anyIPv6) {
_sockets.add(incoming);
}

_mDnsAddress ??= _incoming.address.type == InternetAddressType.IPv4
_mDnsAddress ??= incoming.address.type == InternetAddressType.IPv4
? mDnsAddressIPv4
: mDnsAddressIPv6;

final List<NetworkInterface> interfaces =
await interfacesFactory(listenAddress.type);
(await interfacesFactory(listenAddress.type)).toList();

for (NetworkInterface interface in interfaces) {
// Create a socket for sending on each adapter.
final InternetAddress targetAddress = interface.addresses[0];
final RawDatagramSocket socket = await _rawDatagramSocketFactory(
targetAddress,
_mDnsPort,
selectedMDnsPort,
reuseAddress: true,
reusePort: true,
ttl: 255,
Expand All @@ -147,9 +146,9 @@ class MDnsClient {
));
}
// Join multicast on this interface.
_incoming.joinMulticast(_mDnsAddress, interface);
incoming.joinMulticast(_mDnsAddress!, interface);
}
_incoming.listen(_handleIncoming);
incoming.listen((RawSocketEvent event) => _handleIncoming(event, incoming));
_started = true;
_starting = false;
}
Expand Down Expand Up @@ -186,7 +185,8 @@ class MDnsClient {
ResourceRecordQuery query, {
Duration timeout = const Duration(seconds: 5),
}) {
if (!_started) {
final int? selectedMDnsPort = _mDnsPort;
if (!_started || selectedMDnsPort == null) {
throw StateError('mDNS client must be started before calling lookup.');
}
// Look for entries in the cache.
Expand All @@ -207,18 +207,21 @@ class MDnsClient {
// Send the request on all interfaces.
final List<int> packet = query.encode();
for (RawDatagramSocket socket in _sockets) {
socket.send(packet, _mDnsAddress, _mDnsPort);
socket.send(packet, _mDnsAddress!, selectedMDnsPort);
}
return results;
}

// Process incoming datagrams.
void _handleIncoming(RawSocketEvent event) {
void _handleIncoming(RawSocketEvent event, RawDatagramSocket incoming) {
if (event == RawSocketEvent.read) {
final Datagram datagram = _incoming.receive();
final Datagram? datagram = incoming.receive();
if (datagram == null) {
return;
}

// Check for published responses.
final List<ResourceRecord> response = decodeMDnsResponse(datagram.data);
final List<ResourceRecord>? response = decodeMDnsResponse(datagram.data);
if (response != null) {
_cache.updateRecords(response);
_resolver.handleResponse(response);
Expand Down
8 changes: 4 additions & 4 deletions packages/multicast_dns/lib/src/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,20 @@ final InternetAddress mDnsAddressIPv6 = InternetAddress('FF02::FB');
const int mDnsPort = 5353;

/// Enumeration of supported resource record class types.
class ResourceRecordClass {
abstract class ResourceRecordClass {
// This class is intended to be used as a namespace, and should not be
// extended directly.
factory ResourceRecordClass._() => null;

@jonahwilliams jonahwilliams Mar 3, 2021

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pattern is no longer allowed.

ResourceRecordClass._();

/// Internet address class ("IN").
static const int internet = 1;
}

/// Enumeration of DNS question types.
class QuestionType {
abstract class QuestionType {
// This class is intended to be used as a namespace, and should not be
// extended directly.
factory QuestionType._() => null;
QuestionType._();

/// "QU" Question.
static const int unicast = 0x8000;
Expand Down
4 changes: 2 additions & 2 deletions packages/multicast_dns/lib/src/lookup_resolver.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class PendingRequest extends LinkedListEntry<PendingRequest> {
final StreamController<ResourceRecord> controller;

/// The timer for the request.
Timer timer;
Timer? timer;
}

/// Class for keeping track of pending lookups and processing incoming
Expand Down Expand Up @@ -89,7 +89,7 @@ class LookupResolver {
while (_pendingRequests.isNotEmpty) {
final PendingRequest request = _pendingRequests.first;
request.unlink();
request.timer.cancel();
request.timer?.cancel();
request.controller.close();
}
}
Expand Down
15 changes: 8 additions & 7 deletions packages/multicast_dns/lib/src/native_protocol_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class ResourceRecordCache {
for (final SplayTreeMap<String, List<ResourceRecord>> map
in _cache.values) {
for (final List<ResourceRecord> records in map.values) {
count += records?.length;
count += records.length;
}
}
return count;
Expand All @@ -45,14 +45,15 @@ class ResourceRecordCache {
// TODO(dnfield): Update this to use set literal syntax when we're able to bump the SDK constraint.
seenRecordTypes[record.resourceRecordType] ??=
Set<String>(); // ignore: prefer_collection_literals
if (seenRecordTypes[record.resourceRecordType].add(record.name)) {
if (seenRecordTypes[record.resourceRecordType]!.add(record.name)) {
_cache[record.resourceRecordType] ??=
SplayTreeMap<String, List<ResourceRecord>>();

_cache[record.resourceRecordType]
[record.name] = <ResourceRecord>[record];
_cache[record.resourceRecordType]![record.name] = <ResourceRecord>[
record
];
} else {
_cache[record.resourceRecordType][record.name].add(record);
_cache[record.resourceRecordType]![record.name]!.add(record);
}
}
}
Expand All @@ -62,12 +63,12 @@ class ResourceRecordCache {
String name, int type, List<T> results) {
assert(ResourceRecordType.debugAssertValid(type));
final int time = DateTime.now().millisecondsSinceEpoch;
final SplayTreeMap<String, List<ResourceRecord>> candidates = _cache[type];
final SplayTreeMap<String, List<ResourceRecord>>? candidates = _cache[type];
if (candidates == null) {
return;
}

final List<ResourceRecord> candidateRecords = candidates[name];
final List<ResourceRecord>? candidateRecords = candidates[name];
if (candidateRecords == null) {
return;
}
Expand Down
14 changes: 5 additions & 9 deletions packages/multicast_dns/lib/src/packet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ const int _kHeaderSize = 12;
/// Will attempt to append 'local' if the name is something like '_http._tcp',
/// and '._tcp.local' if name is something like '_http'.
List<String> processDnsNameParts(String name) {
assert(name != null);
final List<String> parts = name.split('.');
if (parts.length == 1) {
return <String>[parts[0], '_tcp', 'local'];
Expand All @@ -47,9 +46,7 @@ List<int> encodeMDnsQuery(
int type = ResourceRecordType.addressIPv4,
bool multicast = true,
}) {
assert(name != null);
assert(ResourceRecordType.debugAssertValid(type));
assert(multicast != null);

final List<String> nameParts = processDnsNameParts(name);
final List<List<int>> rawNameParts =
Expand Down Expand Up @@ -179,7 +176,7 @@ _FQDNReadResult _readFQDN(
/// If decoding fails (e.g. due to an invalid packet), `null` is returned.
///
/// See https://tools.ietf.org/html/rfc1035 for format.
ResourceRecordQuery decodeMDnsQuery(List<int> packet) {
ResourceRecordQuery? decodeMDnsQuery(List<int> packet) {
final int length = packet.length;
if (length < _kHeaderSize) {
return null;
Expand Down Expand Up @@ -214,7 +211,7 @@ ResourceRecordQuery decodeMDnsQuery(List<int> packet) {
/// If decoding fails (e.g. due to an invalid packet) `null` is returned.
///
/// See https://tools.ietf.org/html/rfc1035 for the format.
List<ResourceRecord> decodeMDnsResponse(List<int> packet) {
List<ResourceRecord>? decodeMDnsResponse(List<int> packet) {
final int length = packet.length;
if (length < _kHeaderSize) {
return null;
Expand Down Expand Up @@ -242,7 +239,7 @@ List<ResourceRecord> decodeMDnsResponse(List<int> packet) {
}
}

ResourceRecord readResourceRecord() {
ResourceRecord? readResourceRecord() {
// First read the FQDN.
final _FQDNReadResult result = _readFQDN(data, packetBytes, offset, length);
final String fqdn = result.fqdn;
Expand Down Expand Up @@ -319,7 +316,6 @@ List<ResourceRecord> decodeMDnsResponse(List<int> packet) {
priority: priority,
weight: weight,
);
break;
case ResourceRecordType.serverPointer:
checkLength(offset + readDataLength);
final _FQDNReadResult result =
Expand Down Expand Up @@ -373,7 +369,7 @@ List<ResourceRecord> decodeMDnsResponse(List<int> packet) {
offset += 4;
}
for (int i = 0; i < remainingCount; i++) {
final ResourceRecord record = readResourceRecord();
final ResourceRecord? record = readResourceRecord();
if (record != null) {
result.add(record);
}
Expand All @@ -391,7 +387,7 @@ class MDnsDecodeException implements Exception {
/// specified [offset].
///
/// The [offset] parameter should not be null.
const MDnsDecodeException(this.offset) : assert(offset != null);
const MDnsDecodeException(this.offset);

/// The offset in the packet at which the exception occurred.
final int offset;
Expand Down
Loading