Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2032)

Unified Diff: pkg/mdns/lib/src/packet.dart

Issue 1412063015: Improve resource record implementation in the mdns package. (Closed) Base URL: https://github.com/dart-lang/fletch.git@master
Patch Set: Address comments Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/mdns/lib/src/packet.dart
diff --git a/pkg/mdns/lib/src/packet.dart b/pkg/mdns/lib/src/packet.dart
index 123517d890f73d7a7cf434feefe6cb3cfeb77319..8ae3a3907975c9f49a053372468a403442dc6e0d 100644
--- a/pkg/mdns/lib/src/packet.dart
+++ b/pkg/mdns/lib/src/packet.dart
@@ -11,8 +11,8 @@ import 'dart:typed_data';
import 'package:mdns/src/constants.dart';
// Encode a mDNS query packet.
-List<int> encodeMDnsQuery(String hostname) {
- List parts = hostname.split('.');
+List<int> encodeMDnsQuery(String name, [int type = RRType.A]) {
+ List parts = name.split('.');
// Calculate the size of the packet.
int size = headerSize;
@@ -44,21 +44,49 @@ List<int> encodeMDnsQuery(String hostname) {
}
data[offset] = 0; // Empty part.
offset++;
- bd.setUint16(offset, 1); // QTYPE.
+ bd.setUint16(offset, type); // QTYPE.
offset += 2;
- bd.setUint16(offset, 1); // QCLASS.
+ bd.setUint16(offset, RRClass.IN | 0x8000); // QCLASS + QU.
return data;
}
-/// FQDN and address decoded from response.
-class DecodeResult {
+/// Partial implementation of DNS resource records (RRs).
+class ResourceRecord {
+ final int type;
final String name;
- final InternetAddress address;
- DecodeResult(this.name, this.address);
+ final _data;
+ final int validUntil;
+ // TODO(karlklose): add missing header bits.
+
+ ResourceRecord(this.type, this.name, this._data, this.validUntil);
+
+ InternetAddress get address {
+ if (type != RRType.A) {
+ // TODO(karlklose): add IPv6 address support.
+ throw new StateError("'address' is only supported for type A.");
+ }
+ return _data;
+ }
+
+ String get domainName {
+ if (type != RRType.PTR) {
+ throw new StateError("'domain name' is only supported for type PTR.");
+ }
+ return _data;
+ }
+
+ String get target {
+ if (type != RRType.SRV) {
+ throw new StateError("'target' is only supported for type SRV.");
+ }
+ return _data;
+ }
+
+ toString() => 'RR $type $_data';
}
-/// Result of reading a FQDN. The FQDN parts and the bytes consumed.
+/// Result of reading a FQDN.
class FQDNReadResult {
final List<String> fqdn;
final int bytesRead;
@@ -70,7 +98,7 @@ class FQDNReadResult {
/// If decoding fails (e.g. due to an invalid packet) `null` is returned.
///
/// See https://tools.ietf.org/html/rfc1035 for the format.
-List<DecodeResult> decodeMDnsResponse(List<int> packet) {
+List<ResourceRecord> decodeMDnsResponse(List<int> packet) {
int length = packet.length;
if (length < headerSize) return null;
@@ -133,7 +161,7 @@ List<DecodeResult> decodeMDnsResponse(List<int> packet) {
return new FQDNReadResult(parts, offset - prevOffset);
}
- DecodeResult readAddress() {
+ ResourceRecord readResourceRecord() {
// First read the FQDN.
FQDNReadResult result = readFQDN(offset);
var fqdn = result.fqdn.join('.');
@@ -141,40 +169,80 @@ List<DecodeResult> decodeMDnsResponse(List<int> packet) {
checkLength(offset + 2);
int type = bd.getUint16(offset);
offset += 2;
+ // The first bit of the rrclass field is set to indicate that the answer is
+ // unique and the querier should flush the cached answer for this name
+ // (RFC 6762, Sec. 10.2). We ignore it for now since we don't cache answers.
checkLength(offset + 2);
- int cls = bd.getUint16(offset);
+ int cls = bd.getUint16(offset) & 0x7fff;
offset += 2;
checkLength(offset + 4);
int ttl = bd.getInt32(offset);
offset += 4;
+
+ var rData;
checkLength(offset + 2);
- int addressLength = bd.getUint16(offset);
+ int rDataLength = bd.getUint16(offset);
offset += 2;
- checkLength(offset + addressLength);
- var addressBytes = new Uint8List.view(data.buffer, offset, addressLength);
- offset += addressLength;
-
- if (type == ipV4AddressType && cls == ipV4Class && addressLength == 4) {
- String addr = addressBytes.map((n) => n.toString()).join('.');
- return new DecodeResult(fqdn, new InternetAddress(addr));
- } else {
+ switch (type) {
+ case RRType.A:
+ checkLength(offset + rDataLength);
+ rData = new Uint8List.view(data.buffer, offset, rDataLength);
+ String addr = rData.map((n) => n.toString()).join('.');
+ rData = new InternetAddress(addr);
+ offset += rDataLength;
+ break;
+ case RRType.SRV:
+ checkLength(offset + 2);
+ int priority = bd.getUint16(offset);
+ offset += 2;
+ checkLength(offset + 2);
+ int weight = bd.getUint16(offset);
+ offset += 2;
+ checkLength(offset + 2);
+ int port = bd.getUint16(offset);
+ offset += 2;
+ FQDNReadResult result = readFQDN(offset);
+ rData = result.fqdn.join('.');
+ offset += rDataLength - 6;
+ break;
+ case RRType.PTR:
+ checkLength(offset + rDataLength);
+ FQDNReadResult result = readFQDN(offset);
+ offset += rDataLength;
+ rData = result.fqdn.join('.');
+ break;
+ case RRType.TXT:
+ // TODO(karlklose): convert to a String or Map.
+ default:
+ checkLength(offset + rDataLength);
+ rData = new Uint8List.view(data.buffer, offset, rDataLength);
+ offset += rDataLength;
+ break;
+ }
+ assert(rData != null);
+
+ if (cls != RRClass.IN) {
+ // We do not support other classes at the moment.
return null;
}
+
+ int validUntil = new DateTime.now().millisecondsSinceEpoch +
+ ttl * 1000;
+ return new ResourceRecord(type, fqdn, rData, validUntil);
}
- // We don't use the number of records - just read through all
- // resource records and filter.
- var result = [];
+ List<ResourceRecord> result = <ResourceRecord>[];
try {
- while (data.length - offset >= 16) {
- var address = readAddress();
- if (address != null) result.add(address);
+ for (int i = 0; i < ancount; i++) {
+ ResourceRecord record = readResourceRecord();
+ if (record != null) {
+ result.add(record);
+ }
}
} on MDnsDecodeException catch (e, s) {
// If decoding fails return null.
return null;
}
-
return result;
}

Powered by Google App Engine
This is Rietveld 408576698