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

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: 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
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 class ResourceRecordCache {
Søren Gjesse 2015/11/06 08:44:48 Maybe explain how this cache works. Any reason for
karlklose 2015/11/06 12:20:00 Done. The main reason was to control the size of
17 final List buffer;
18 final int size;
19 int position;
20
21 ResourceRecordCache({int size: 32})
22 : buffer = new List(size),
23 size = size,
24 position = 0;
25
26 void updateRecords(List<ResourceRecord> records) {
27 // TODO(karlklose): include flush bit in the record and only flush if
28 // necessary.
29 for (int i = position; i < position + size; i++) {
Søren Gjesse 2015/11/06 08:44:48 The clearing could just run from 0 to size, but ma
30 ResourceRecord r = buffer[i % size];
31 if (r == null) continue;
32 String name = r.name;
33 int type = r.type;
34 for (ResourceRecord record in records) {
35 if (name == record.name && type == record.type) {
36 buffer[i % size] = null;
37 break;
38 }
39 }
40 }
41
42 for (ResourceRecord record in records) {
43 buffer[position] = record;
44 position = (position + 1) % size;
45 }
46 }
47
48 void lookup(String name, int type, List results) {
49 int time = new DateTime.now().millisecondsSinceEpoch;
50 for (int i = position + size; i >= position; i--) {
51 int index = i % size;
52 ResourceRecord record = buffer[index];
53 if (record == null) continue;
54 if (record.validUntil < time) {
55 buffer[index] = null;
56 } else if (record.name == name && record.type == type) {
57 results.add(record);
58 }
59 }
60 }
61 }
62
16 // Implementation of mDNS client using the native protocol. 63 // Implementation of mDNS client using the native protocol.
17 class NativeProtocolMDnsClient implements MDnsClient { 64 class NativeProtocolMDnsClient implements MDnsClient {
18 bool _starting = false; 65 bool _starting = false;
19 bool _started = false; 66 bool _started = false;
20 RawDatagramSocket _incoming; 67 RawDatagramSocket _incoming;
21 final List<RawDatagramSocket> _sockets = <RawDatagramSocket>[]; 68 final List<RawDatagramSocket> _sockets = <RawDatagramSocket>[];
22 final LookupResolver _resolver = new LookupResolver(); 69 final LookupResolver _resolver = new LookupResolver();
70 ResourceRecordCache cache = new ResourceRecordCache();
23 71
24 /// Start the mDNS client. 72 /// Start the mDNS client.
25 Future start() async { 73 Future start() async {
26 if (_started && _starting) { 74 if (_started && _starting) {
27 throw new StateError('mDNS client already started'); 75 throw new StateError('mDNS client already started');
28 } 76 }
29 _starting = true; 77 _starting = true;
30 78
31 // Listen on all addresses. 79 // Listen on all addresses.
32 _incoming = await RawDatagramSocket.bind( 80 _incoming = await RawDatagramSocket.bind(
(...skipping 22 matching lines...) Expand all
55 if (_starting) { 103 if (_starting) {
56 throw new StateError('Cannot stop mDNS client wile it is starting'); 104 throw new StateError('Cannot stop mDNS client wile it is starting');
57 } 105 }
58 106
59 _sockets.forEach((socket) => socket.close()); 107 _sockets.forEach((socket) => socket.close());
60 _incoming.close(); 108 _incoming.close();
61 109
62 _started = false; 110 _started = false;
63 } 111 }
64 112
65 Future<InternetAddress> lookup( 113 Stream<InternetAddress> lookup(
66 String hostname, {Duration timeout: const Duration(seconds: 5)}) { 114 int type,
115 String name,
116 {Duration timeout: const Duration(seconds: 5)}) {
67 if (!_started) { 117 if (!_started) {
68 throw new StateError('mDNS client is not started'); 118 throw new StateError('mDNS client is not started');
69 } 119 }
70 120
121 // Look for entries in the cache.
122 List<ResourceRecordCache> cached = <ResourceRecord>[];
123 cache.lookup(name, type, cached);
124 if (cached.isNotEmpty) {
125 StreamController controller = new StreamController();
126 cached.forEach(controller.add);
127 controller.close();
128 return controller.stream;
129 }
130
71 // Add the pending request before sending the query. 131 // Add the pending request before sending the query.
72 var future = _resolver.addPendingRequest(hostname, timeout); 132 var results = _resolver.addPendingRequest(type, name, timeout);
73 133
74 // Send the request on all interfaces. 134 // Send the request on all interfaces.
75 List<int> packet = encodeMDnsQuery(hostname); 135 List<int> packet = encodeMDnsQuery(name, type);
76 for (int i = 0; i < _sockets.length; i++) { 136 for (int i = 0; i < _sockets.length; i++) {
77 _sockets[i].send(packet, mDnsAddress, mDnsPort); 137 _sockets[i].send(packet, mDnsAddress, mDnsPort);
78 } 138 }
79 139
80 return future; 140 return results;
81 } 141 }
82 142
83 // Process incoming datagrams. 143 // Process incoming datagrams.
84 _handleIncoming(event) { 144 _handleIncoming(event) {
85 if (event == RawSocketEvent.READ) { 145 if (event == RawSocketEvent.READ) {
86 var data = _incoming.receive(); 146 Datagram datagram = _incoming.receive();
87 var response = decodeMDnsResponse(data.data); 147 List<ResourceRecord> response = decodeMDnsResponse(datagram.data);
88 if (response != null) { 148 if (response != null) {
149 cache.updateRecords(response);
89 _resolver.handleResponse(response); 150 _resolver.handleResponse(response);
90 } 151 }
91 } 152 }
92 } 153 }
93 } 154 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698