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. |
| 73 // |
| 74 // response[0]: reply port (SendPort) |
| 75 // response[1]: request type (int) |
| 76 // response[2]: record type (int) |
| 77 // response[3]: data (Uint8List) |
| 78 // response[4]: timeout in milliseconds (int) |
78 _service.send([_incoming.sendPort, | 79 _service.send([_incoming.sendPort, |
79 RequestType.lookupRequest.index, | 80 RequestType.lookupRequest.index, |
80 name]); | 81 type, |
| 82 name, |
| 83 timeout.inMilliseconds]); |
81 | 84 |
82 return result; | 85 return result; |
83 } | 86 } |
84 | 87 |
85 // Process incoming responses. | 88 // Process incoming responses. |
86 _handleIncoming(response) { | 89 _handleIncoming(response) { |
87 // Right now the only response we can get is the response to a | 90 // Right now the only response we can get is the response to a |
88 // lookupRequest where the response looks like this: | 91 // lookupRequest where the response looks like this: |
89 // | 92 // |
90 // response[0]: hostname (String) | 93 // response[0]: fullname (String) |
91 // response[1]: IPv4 address (Uint8List) | 94 // response[1]: type (int) |
92 if (response is List && response.length == 2) { | 95 // response[2]: ttl (int) |
| 96 // response[3]: data (Uint8List) |
| 97 if (response is List && response.length == 4) { |
93 if (response[0] is String && | 98 if (response[0] is String && |
94 response[1] is List && response[1].length == 4) { | 99 response[1] is int && |
95 response = new ResourceRecord( | 100 response[2] is int && |
96 RRType.A, | 101 response[3] is List) { |
97 response[0], | 102 String fqdn = response[0]; |
98 response[1].codeUnits, | 103 // The strings from the C system can have \032 for spaces. |
99 // TODO(karlklose): modify extension to return TTL too. For new | 104 fqdn = fqdn.replaceAll(r'\032', ' '); |
100 // we set it to 2 seconds. | 105 int type = response[1]; |
101 new DateTime.now().millisecondsSinceEpoch + 2000); | 106 int ttl = response[2]; |
102 _resolver.handleResponse([response]); | 107 List<int> data = response[3]; |
| 108 |
| 109 int validUntil = new DateTime.now().millisecondsSinceEpoch + ttl * 1000; |
| 110 ResourceRecord result; |
| 111 switch (type) { |
| 112 case RRType.A: |
| 113 if (data.length == 4) { |
| 114 var address = |
| 115 new InternetAddress(data.map((n) => '$n').join('.')); |
| 116 result = new ResourceRecord(type, fqdn, address, validUntil); |
| 117 } |
| 118 break; |
| 119 case RRType.SRV: |
| 120 // Skip the SRV record header for now - only read the name. |
| 121 if (data.length > srvHeaderSize) { |
| 122 var rData = readFQDN(data, srvHeaderSize); |
| 123 result = new ResourceRecord(type, fqdn, rData, validUntil); |
| 124 } |
| 125 break; |
| 126 case RRType.PTR: |
| 127 var rData = readFQDN(data); |
| 128 result = new ResourceRecord(type, fqdn, rData, validUntil); |
| 129 break; |
| 130 } |
| 131 if (result != null) { |
| 132 _resolver.handleResponse([result]); |
| 133 } |
103 } else { | 134 } else { |
104 // TODO(sgjesse): Improve the error handling. | 135 // TODO(sgjesse): Improve the error handling. |
105 print('mDNS Response not understood'); | 136 print('mDNS Response not understood'); |
106 } | 137 } |
107 } | 138 } |
108 } | 139 } |
109 } | 140 } |
110 | 141 |
111 Future nativeExtensionEchoTest(dynamic message) async { | 142 Future nativeExtensionEchoTest(dynamic message) async { |
112 await native_extension_api.loadLibrary(); | 143 await native_extension_api.loadLibrary(); |
113 SendPort service = native_extension_api.servicePort(); | 144 SendPort service = native_extension_api.servicePort(); |
114 ReceivePort port = new ReceivePort(); | 145 ReceivePort port = new ReceivePort(); |
115 try { | 146 try { |
116 service.send([port.sendPort, RequestType.echoRequest.index, message]); | 147 service.send([port.sendPort, RequestType.echoRequest.index, message]); |
117 return await port.first; | 148 return await port.first; |
118 } finally { | 149 } finally { |
119 port.close(); | 150 port.close(); |
120 } | 151 } |
121 } | 152 } |
OLD | NEW |