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

Side by Side Diff: pkg/mdns/lib/src/native_protocol_client.dart

Issue 1412063015: Improve resource record implementation in the mdns package. (Closed) Base URL: https://github.com/dart-lang/fletch.git@master
Patch Set: Remove unnecessary await. 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 unified diff | Download patch
« no previous file with comments | « pkg/mdns/lib/src/native_extension_client.dart ('k') | pkg/mdns/lib/src/packet.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015, the Fletch project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Fletch project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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.md file. 3 // BSD-style license that can be found in the LICENSE.md file.
4 4
5 library mdns.src.native_protocol_client; 5 library mdns.src.native_protocol_client;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:collection'; 8 import 'dart:collection';
9 import 'dart:io'; 9 import 'dart:io';
10 10
11 import 'package:mdns/mdns.dart'; 11 import 'package:mdns/mdns.dart';
12 import 'package:mdns/src/constants.dart'; 12 import 'package:mdns/src/constants.dart';
13 import 'package:mdns/src/lookup_resolver.dart'; 13 import 'package:mdns/src/lookup_resolver.dart';
14 import 'package:mdns/src/packet.dart'; 14 import 'package:mdns/src/packet.dart';
15 15
16 /// Cache for resource records that have been received.
17 ///
18 /// There can be multiple entries for the same name and type.
19 ///
20 /// The cached is updated with a list of records, because it needs to remove
21 /// all entries that correspond to name and type of the name/type combinations
22 /// of records that should be updated. For example, a host may remove one
23 /// of its IP addresses and report the remaining address as a response - then
24 /// we need to clear all previous entries for that host before updating the
25 /// cache.
26 class ResourceRecordCache {
27 final List buffer;
28 final int size;
29 int position;
30
31 ResourceRecordCache({int size: 32})
32 : buffer = new List(size),
33 size = size,
34 position = 0;
35
36 void updateRecords(List<ResourceRecord> records) {
37 // TODO(karlklose): include flush bit in the record and only flush if
38 // necessary.
39 // Clear the cache for all name/type combinations to be updated.
40 for (int i = 0; i < size; i++) {
41 ResourceRecord r = buffer[i % size];
42 if (r == null) continue;
43 String name = r.name;
44 int type = r.type;
45 for (ResourceRecord record in records) {
46 if (name == record.name && type == record.type) {
47 buffer[i % size] = null;
48 break;
49 }
50 }
51 }
52 // Add the new records.
53 for (ResourceRecord record in records) {
54 buffer[position] = record;
55 position = (position + 1) % size;
56 }
57 }
58
59 void lookup(String name, int type, List results) {
60 int time = new DateTime.now().millisecondsSinceEpoch;
61 for (int i = position + size; i >= position; i--) {
62 int index = i % size;
63 ResourceRecord record = buffer[index];
64 if (record == null) continue;
65 if (record.validUntil < time) {
66 buffer[index] = null;
67 } else if (record.name == name && record.type == type) {
68 results.add(record);
69 }
70 }
71 }
72 }
73
16 // Implementation of mDNS client using the native protocol. 74 // Implementation of mDNS client using the native protocol.
17 class NativeProtocolMDnsClient implements MDnsClient { 75 class NativeProtocolMDnsClient implements MDnsClient {
18 bool _starting = false; 76 bool _starting = false;
19 bool _started = false; 77 bool _started = false;
20 RawDatagramSocket _incoming; 78 RawDatagramSocket _incoming;
21 final List<RawDatagramSocket> _sockets = <RawDatagramSocket>[]; 79 final List<RawDatagramSocket> _sockets = <RawDatagramSocket>[];
22 final LookupResolver _resolver = new LookupResolver(); 80 final LookupResolver _resolver = new LookupResolver();
81 ResourceRecordCache cache = new ResourceRecordCache();
23 82
24 /// Start the mDNS client. 83 /// Start the mDNS client.
25 Future start() async { 84 Future start() async {
26 if (_started && _starting) { 85 if (_started && _starting) {
27 throw new StateError('mDNS client already started'); 86 throw new StateError('mDNS client already started');
28 } 87 }
29 _starting = true; 88 _starting = true;
30 89
31 // Listen on all addresses. 90 // Listen on all addresses.
32 _incoming = await RawDatagramSocket.bind( 91 _incoming = await RawDatagramSocket.bind(
(...skipping 19 matching lines...) Expand all
52 111
53 void stop() { 112 void stop() {
54 if (!_started) return; 113 if (!_started) return;
55 if (_starting) { 114 if (_starting) {
56 throw new StateError('Cannot stop mDNS client wile it is starting'); 115 throw new StateError('Cannot stop mDNS client wile it is starting');
57 } 116 }
58 117
59 _sockets.forEach((socket) => socket.close()); 118 _sockets.forEach((socket) => socket.close());
60 _incoming.close(); 119 _incoming.close();
61 120
121 _resolver.clearPendingRequests();
122
62 _started = false; 123 _started = false;
63 } 124 }
64 125
65 Future<InternetAddress> lookup( 126 Stream<ResourceRecord> lookup(
66 String hostname, {Duration timeout: const Duration(seconds: 5)}) { 127 int type,
128 String name,
129 {Duration timeout: const Duration(seconds: 5)}) {
67 if (!_started) { 130 if (!_started) {
68 throw new StateError('mDNS client is not started'); 131 throw new StateError('mDNS client is not started');
69 } 132 }
70 133
134 // Look for entries in the cache.
135 List<ResourceRecordCache> cached = <ResourceRecord>[];
136 cache.lookup(name, type, cached);
137 if (cached.isNotEmpty) {
138 StreamController controller = new StreamController();
139 cached.forEach(controller.add);
140 controller.close();
141 return controller.stream;
142 }
143
71 // Add the pending request before sending the query. 144 // Add the pending request before sending the query.
72 var future = _resolver.addPendingRequest(hostname, timeout); 145 var results = _resolver.addPendingRequest(type, name, timeout);
73 146
74 // Send the request on all interfaces. 147 // Send the request on all interfaces.
75 List<int> packet = encodeMDnsQuery(hostname); 148 List<int> packet = encodeMDnsQuery(name, type);
76 for (int i = 0; i < _sockets.length; i++) { 149 for (int i = 0; i < _sockets.length; i++) {
77 _sockets[i].send(packet, mDnsAddress, mDnsPort); 150 _sockets[i].send(packet, mDnsAddress, mDnsPort);
78 } 151 }
79 152
80 return future; 153 return results;
81 } 154 }
82 155
83 // Process incoming datagrams. 156 // Process incoming datagrams.
84 _handleIncoming(event) { 157 _handleIncoming(event) {
85 if (event == RawSocketEvent.READ) { 158 if (event == RawSocketEvent.READ) {
86 var data = _incoming.receive(); 159 Datagram datagram = _incoming.receive();
87 var response = decodeMDnsResponse(data.data); 160 List<ResourceRecord> response = decodeMDnsResponse(datagram.data);
88 if (response != null) { 161 if (response != null) {
162 cache.updateRecords(response);
89 _resolver.handleResponse(response); 163 _resolver.handleResponse(response);
90 } 164 }
91 } 165 }
92 } 166 }
93 } 167 }
OLDNEW
« no previous file with comments | « pkg/mdns/lib/src/native_extension_client.dart ('k') | pkg/mdns/lib/src/packet.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698