OLD | NEW |
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_extension_client; | 5 library mdns.src.native_extension_client; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:io'; | 8 import 'dart:io'; |
9 import 'dart:isolate'; | 9 import 'dart:isolate'; |
10 | 10 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 } | 59 } |
60 | 60 |
61 Stream<ResourceRecord> lookup( | 61 Stream<ResourceRecord> lookup( |
62 int type, | 62 int type, |
63 String name, | 63 String name, |
64 {Duration timeout: const Duration(seconds: 5)}) { | 64 {Duration timeout: const Duration(seconds: 5)}) { |
65 if (!_started) { | 65 if (!_started) { |
66 throw new StateError('mDNS client is not started'); | 66 throw new StateError('mDNS client is not started'); |
67 } | 67 } |
68 | 68 |
69 if (type != RRType.A) { | |
70 // TODO(karlklose): add support. | |
71 throw 'RR type $type not supported.'; | |
72 } | |
73 | |
74 // Add the pending request before sending the query. | 69 // Add the pending request before sending the query. |
75 var result = _resolver.addPendingRequest(type, name, timeout); | 70 var result = _resolver.addPendingRequest(type, name, timeout); |
76 | 71 |
77 // Send the request. | 72 // Send the request. |
78 _service.send([_incoming.sendPort, | 73 _service.send([_incoming.sendPort, |
79 RequestType.lookupRequest.index, | 74 RequestType.lookupRequest.index, |
| 75 type, |
80 name]); | 76 name]); |
81 | 77 |
82 return result; | 78 return result; |
83 } | 79 } |
84 | 80 |
85 // Process incoming responses. | 81 // Process incoming responses. |
86 _handleIncoming(response) { | 82 _handleIncoming(response) { |
87 // Right now the only response we can get is the response to a | 83 // Right now the only response we can get is the response to a |
88 // lookupRequest where the response looks like this: | 84 // lookupRequest where the response looks like this: |
89 // | 85 // |
90 // response[0]: hostname (String) | 86 // response[0]: fullname (String) |
91 // response[1]: IPv4 address (Uint8List) | 87 // response[1]: type (int) |
92 if (response is List && response.length == 2) { | 88 // response[2]: ttl (int) |
| 89 // response[3]: data (Uint8List) |
| 90 if (response is List && response.length == 4) { |
93 if (response[0] is String && | 91 if (response[0] is String && |
94 response[1] is List && response[1].length == 4) { | 92 response[1] is int && |
95 response = new ResourceRecord( | 93 response[2] is int && |
96 RRType.A, | 94 response[3] is List) { |
97 response[0], | 95 String fqdn = response[0]; |
98 response[1].codeUnits, | 96 // The strings from the C system can have \032 for spaces. |
99 // TODO(karlklose): modify extension to return TTL too. For new | 97 fqdn = fqdn.replaceAll(r'\032', ' '); |
100 // we set it to 2 seconds. | 98 int type = response[1]; |
101 new DateTime.now().millisecondsSinceEpoch + 2000); | 99 int ttl = response[2]; |
102 _resolver.handleResponse([response]); | 100 List<int> data = response[3]; |
| 101 |
| 102 int validUntil = new DateTime.now().millisecondsSinceEpoch + ttl * 1000; |
| 103 ResourceRecord result; |
| 104 switch (type) { |
| 105 case RRType.A: |
| 106 if (data.length == 4) { |
| 107 var address = |
| 108 new InternetAddress(data.map((n) => '$n').join('.')); |
| 109 result = new ResourceRecord(type, fqdn, address, validUntil); |
| 110 } |
| 111 break; |
| 112 case RRType.SRV: |
| 113 // Skip the SRV record header for now - only read the name. |
| 114 if (data.length > srvHeaderSize) { |
| 115 var rData = readFQDN(data, srvHeaderSize); |
| 116 result = new ResourceRecord(type, fqdn, rData, validUntil); |
| 117 } |
| 118 break; |
| 119 case RRType.PTR: |
| 120 var rData = readFQDN(data); |
| 121 result = new ResourceRecord(type, fqdn, rData, validUntil); |
| 122 break; |
| 123 } |
| 124 if (result != null) { |
| 125 _resolver.handleResponse([result]); |
| 126 } |
103 } else { | 127 } else { |
104 // TODO(sgjesse): Improve the error handling. | 128 // TODO(sgjesse): Improve the error handling. |
105 print('mDNS Response not understood'); | 129 print('mDNS Response not understood'); |
106 } | 130 } |
107 } | 131 } |
108 } | 132 } |
109 } | 133 } |
110 | 134 |
111 Future nativeExtensionEchoTest(dynamic message) async { | 135 Future nativeExtensionEchoTest(dynamic message) async { |
112 await native_extension_api.loadLibrary(); | 136 await native_extension_api.loadLibrary(); |
113 SendPort service = native_extension_api.servicePort(); | 137 SendPort service = native_extension_api.servicePort(); |
114 ReceivePort port = new ReceivePort(); | 138 ReceivePort port = new ReceivePort(); |
115 try { | 139 try { |
116 service.send([port.sendPort, RequestType.echoRequest.index, message]); | 140 service.send([port.sendPort, RequestType.echoRequest.index, message]); |
117 return await port.first; | 141 return await port.first; |
118 } finally { | 142 } finally { |
119 port.close(); | 143 port.close(); |
120 } | 144 } |
121 } | 145 } |
OLD | NEW |