1 /*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define TRACE_TAG TRANSPORT
18
19 #include "transport.h"
20
21 #ifdef _WIN32
22 #include <winsock2.h>
23 #else
24 #include <arpa/inet.h>
25 #endif
26
27 #include <memory>
28 #include <thread>
29 #include <unordered_set>
30 #include <vector>
31
32 #include <android-base/stringprintf.h>
33 #include <android-base/strings.h>
34
35 #include <discovery/common/config.h>
36 #include <discovery/common/reporting_client.h>
37 #include <discovery/public/dns_sd_service_factory.h>
38 #include <platform/api/network_interface.h>
39 #include <platform/api/serial_delete_ptr.h>
40 #include <platform/base/error.h>
41 #include <platform/base/interface_info.h>
42
43 #include "adb_client.h"
44 #include "adb_mdns.h"
45 #include "adb_trace.h"
46 #include "adb_utils.h"
47 #include "adb_wifi.h"
48 #include "client/mdns_utils.h"
49 #include "client/openscreen/mdns_service_watcher.h"
50 #include "client/openscreen/platform/task_runner.h"
51 #include "fdevent/fdevent.h"
52 #include "sysdeps.h"
53
54 namespace {
55
56 using namespace mdns;
57 using namespace openscreen;
58 using ServicesUpdatedState = mdns::ServiceReceiver::ServicesUpdatedState;
59
60 struct DiscoveryState;
61 DiscoveryState* g_state = nullptr;
62 // TODO: remove once openscreen has bonjour client APIs.
63 bool g_using_bonjour = false;
64 AdbMdnsResponderFuncs g_adb_mdnsresponder_funcs;
65
66 class DiscoveryReportingClient : public discovery::ReportingClient {
67 public:
OnFatalError(Error error)68 void OnFatalError(Error error) override {
69 // The multicast port 5353 may fail to bind because of another process already binding
70 // to it (bonjour). So let's fallback to bonjour client APIs.
71 // TODO: Remove this once openscreen implements the bonjour client APIs.
72 LOG(ERROR) << "Encountered fatal discovery error: " << error;
73 got_fatal_ = true;
74 }
75
OnRecoverableError(Error error)76 void OnRecoverableError(Error error) override {
77 LOG(ERROR) << "Encountered recoverable discovery error: " << error;
78 }
79
GotFatalError() const80 bool GotFatalError() const { return got_fatal_; }
81
82 private:
83 std::atomic<bool> got_fatal_{false};
84 };
85
86 struct DiscoveryState {
87 SerialDeletePtr<discovery::DnsSdService> service;
88 std::unique_ptr<DiscoveryReportingClient> reporting_client;
89 std::unique_ptr<AdbOspTaskRunner> task_runner;
90 std::vector<std::unique_ptr<ServiceReceiver>> receivers;
91 InterfaceInfo interface_info;
92 };
93
94 // Callback provided to service receiver for updates.
OnServiceReceiverResult(std::vector<std::reference_wrapper<const ServiceInfo>> infos,std::reference_wrapper<const ServiceInfo> info,ServicesUpdatedState state)95 void OnServiceReceiverResult(std::vector<std::reference_wrapper<const ServiceInfo>> infos,
96 std::reference_wrapper<const ServiceInfo> info,
97 ServicesUpdatedState state) {
98 LOG(INFO) << "Endpoint state=" << static_cast<int>(state)
99 << " instance_name=" << info.get().instance_name
100 << " service_name=" << info.get().service_name << " addr=" << info.get().v4_address
101 << " addrv6=" << info.get().v6_address << " total_serv=" << infos.size();
102
103 switch (state) {
104 case ServicesUpdatedState::EndpointCreated:
105 case ServicesUpdatedState::EndpointUpdated:
106 if (adb_DNSServiceShouldAutoConnect(info.get().service_name,
107 info.get().instance_name) &&
108 info.get().v4_address) {
109 auto index = adb_DNSServiceIndexByName(info.get().service_name);
110 if (!index) {
111 return;
112 }
113
114 // Don't try to auto-connect if not in the keystore.
115 if (*index == kADBSecureConnectServiceRefIndex &&
116 !adb_wifi_is_known_host(info.get().instance_name)) {
117 LOG(INFO) << "instance_name=" << info.get().instance_name << " not in keystore";
118 return;
119 }
120 std::string response;
121 LOG(INFO) << "Attempting to auto-connect to instance=" << info.get().instance_name
122 << " service=" << info.get().service_name << " addr4=%s"
123 << info.get().v4_address << ":" << info.get().port;
124 connect_device(
125 android::base::StringPrintf("%s.%s", info.get().instance_name.c_str(),
126 info.get().service_name.c_str()),
127 &response);
128 }
129 break;
130 default:
131 break;
132 }
133 }
134
GetConfigForAllInterfaces()135 std::optional<discovery::Config> GetConfigForAllInterfaces() {
136 auto interface_infos = GetNetworkInterfaces();
137
138 discovery::Config config;
139 for (const auto interface : interface_infos) {
140 discovery::Config::NetworkInfo::AddressFamilies supported_address_families =
141 discovery::Config::NetworkInfo::kNoAddressFamily;
142 if (interface.GetIpAddressV4()) {
143 supported_address_families |= discovery::Config::NetworkInfo::kUseIpV4;
144 }
145 if (interface.GetIpAddressV6()) {
146 supported_address_families |= discovery::Config::NetworkInfo::kUseIpV6;
147 }
148 if (supported_address_families == discovery::Config::NetworkInfo::kNoAddressFamily) {
149 LOG(INFO) << "Interface [" << interface << "] doesn't support ipv4 or ipv6."
150 << " Ignoring interface.";
151 continue;
152 }
153 config.network_info.push_back({interface, supported_address_families});
154 LOG(VERBOSE) << "Listening on interface [" << interface << "]";
155 }
156
157 if (config.network_info.empty()) {
158 LOG(INFO) << "No available network interfaces for mDNS discovery";
159 return std::nullopt;
160 }
161
162 return config;
163 }
164
StartDiscovery()165 void StartDiscovery() {
166 CHECK(!g_state);
167 g_state = new DiscoveryState();
168 g_state->task_runner = std::make_unique<AdbOspTaskRunner>();
169 g_state->reporting_client = std::make_unique<DiscoveryReportingClient>();
170
171 g_state->task_runner->PostTask([]() {
172 auto config = GetConfigForAllInterfaces();
173 if (!config) {
174 return;
175 }
176
177 g_state->service = discovery::CreateDnsSdService(g_state->task_runner.get(),
178 g_state->reporting_client.get(), *config);
179 // Register a receiver for each service type
180 for (int i = 0; i < kNumADBDNSServices; ++i) {
181 auto receiver = std::make_unique<ServiceReceiver>(
182 g_state->service.get(), kADBDNSServices[i], OnServiceReceiverResult);
183 receiver->StartDiscovery();
184 g_state->receivers.push_back(std::move(receiver));
185
186 if (g_state->reporting_client->GotFatalError()) {
187 for (auto& r : g_state->receivers) {
188 if (r->is_running()) {
189 r->StopDiscovery();
190 }
191 }
192 g_using_bonjour = true;
193 break;
194 }
195 }
196
197 if (g_using_bonjour) {
198 LOG(INFO) << "Fallback to MdnsResponder client for discovery";
199 g_adb_mdnsresponder_funcs = StartMdnsResponderDiscovery();
200 }
201 });
202 }
203
ForEachService(const std::unique_ptr<ServiceReceiver> & receiver,std::string_view wanted_instance_name,adb_secure_foreach_service_callback cb)204 void ForEachService(const std::unique_ptr<ServiceReceiver>& receiver,
205 std::string_view wanted_instance_name, adb_secure_foreach_service_callback cb) {
206 if (!receiver->is_running()) {
207 return;
208 }
209 auto services = receiver->GetServices();
210 for (const auto& s : services) {
211 if (wanted_instance_name.empty() || s.get().instance_name == wanted_instance_name) {
212 std::stringstream ss;
213 ss << s.get().v4_address;
214 cb(s.get().instance_name.c_str(), s.get().service_name.c_str(), ss.str().c_str(),
215 s.get().port);
216 }
217 }
218 }
219
ConnectAdbSecureDevice(const MdnsInfo & info)220 bool ConnectAdbSecureDevice(const MdnsInfo& info) {
221 if (!adb_wifi_is_known_host(info.service_name)) {
222 LOG(INFO) << "serviceName=" << info.service_name << " not in keystore";
223 return false;
224 }
225
226 std::string response;
227 connect_device(android::base::StringPrintf("%s.%s", info.service_name.c_str(),
228 info.service_type.c_str()),
229 &response);
230 D("Secure connect to %s regtype %s (%s:%hu) : %s", info.service_name.c_str(),
231 info.service_type.c_str(), info.addr.c_str(), info.port, response.c_str());
232 return true;
233 }
234
235 } // namespace
236
237 /////////////////////////////////////////////////////////////////////////////////
mdns_cleanup()238 void mdns_cleanup() {
239 if (g_using_bonjour) {
240 return g_adb_mdnsresponder_funcs.mdns_cleanup();
241 }
242 }
243
init_mdns_transport_discovery(void)244 void init_mdns_transport_discovery(void) {
245 // TODO(joshuaduong): Use openscreen discovery by default for all platforms.
246 const char* mdns_osp = getenv("ADB_MDNS_OPENSCREEN");
247 if (mdns_osp && strcmp(mdns_osp, "1") == 0) {
248 LOG(INFO) << "Openscreen mdns discovery enabled";
249 StartDiscovery();
250 } else {
251 // Original behavior is to use Bonjour client.
252 g_using_bonjour = true;
253 g_adb_mdnsresponder_funcs = StartMdnsResponderDiscovery();
254 }
255 }
256
adb_secure_connect_by_service_name(const std::string & instance_name)257 bool adb_secure_connect_by_service_name(const std::string& instance_name) {
258 if (g_using_bonjour) {
259 return g_adb_mdnsresponder_funcs.adb_secure_connect_by_service_name(instance_name);
260 }
261
262 if (!g_state || g_state->receivers.empty()) {
263 LOG(INFO) << "Mdns not enabled";
264 return false;
265 }
266
267 std::optional<MdnsInfo> info;
268 auto cb = [&](const std::string& instance_name, const std::string& service_name,
269 const std::string& ip_addr,
270 uint16_t port) { info.emplace(instance_name, service_name, ip_addr, port); };
271 ForEachService(g_state->receivers[kADBSecureConnectServiceRefIndex], instance_name, cb);
272 if (info.has_value()) {
273 return ConnectAdbSecureDevice(*info);
274 }
275 return false;
276 }
277
mdns_check()278 std::string mdns_check() {
279 if (!g_state && !g_using_bonjour) {
280 return "ERROR: mdns discovery disabled";
281 }
282
283 if (g_using_bonjour) {
284 return g_adb_mdnsresponder_funcs.mdns_check();
285 }
286
287 return "mdns daemon version [Openscreen discovery 0.0.0]";
288 }
289
mdns_list_discovered_services()290 std::string mdns_list_discovered_services() {
291 if (g_using_bonjour) {
292 return g_adb_mdnsresponder_funcs.mdns_list_discovered_services();
293 }
294
295 if (!g_state || g_state->receivers.empty()) {
296 return "";
297 }
298
299 std::string result;
300 auto cb = [&](const std::string& instance_name, const std::string& service_name,
301 const std::string& ip_addr, uint16_t port) {
302 result += android::base::StringPrintf("%s\t%s\t%s:%u\n", instance_name.data(),
303 service_name.data(), ip_addr.data(), port);
304 };
305
306 for (const auto& receiver : g_state->receivers) {
307 ForEachService(receiver, "", cb);
308 }
309 return result;
310 }
311
mdns_get_connect_service_info(const std::string & name)312 std::optional<MdnsInfo> mdns_get_connect_service_info(const std::string& name) {
313 CHECK(!name.empty());
314
315 if (g_using_bonjour) {
316 return g_adb_mdnsresponder_funcs.mdns_get_connect_service_info(name);
317 }
318
319 if (!g_state || g_state->receivers.empty()) {
320 return std::nullopt;
321 }
322
323 auto mdns_instance = mdns::mdns_parse_instance_name(name);
324 if (!mdns_instance.has_value()) {
325 D("Failed to parse mDNS name [%s]", name.data());
326 return std::nullopt;
327 }
328
329 std::optional<MdnsInfo> info;
330 auto cb = [&](const std::string& instance_name, const std::string& service_name,
331 const std::string& ip_addr,
332 uint16_t port) { info.emplace(instance_name, service_name, ip_addr, port); };
333
334 std::string reg_type;
335 // Service name was provided.
336 if (!mdns_instance->service_name.empty()) {
337 reg_type = android::base::StringPrintf("%s.%s", mdns_instance->service_name.data(),
338 mdns_instance->transport_type.data());
339 const auto index = adb_DNSServiceIndexByName(reg_type);
340 if (!index) {
341 return std::nullopt;
342 }
343 switch (*index) {
344 case kADBTransportServiceRefIndex:
345 case kADBSecureConnectServiceRefIndex:
346 ForEachService(g_state->receivers[*index], mdns_instance->instance_name, cb);
347 break;
348 default:
349 D("Not a connectable service name [%s]", reg_type.data());
350 return std::nullopt;
351 }
352 return info;
353 }
354
355 // No mdns service name provided. Just search for the instance name in all adb connect services.
356 // Prefer the secured connect service over the other.
357 ForEachService(g_state->receivers[kADBSecureConnectServiceRefIndex], name, cb);
358 if (!info.has_value()) {
359 ForEachService(g_state->receivers[kADBTransportServiceRefIndex], name, cb);
360 }
361
362 return info;
363 }
364
mdns_get_pairing_service_info(const std::string & name)365 std::optional<MdnsInfo> mdns_get_pairing_service_info(const std::string& name) {
366 CHECK(!name.empty());
367
368 if (g_using_bonjour) {
369 return g_adb_mdnsresponder_funcs.mdns_get_pairing_service_info(name);
370 }
371
372 if (!g_state || g_state->receivers.empty()) {
373 return std::nullopt;
374 }
375
376 auto mdns_instance = mdns::mdns_parse_instance_name(name);
377 if (!mdns_instance.has_value()) {
378 D("Failed to parse mDNS name [%s]", name.data());
379 return std::nullopt;
380 }
381
382 std::optional<MdnsInfo> info;
383 auto cb = [&](const std::string& instance_name, const std::string& service_name,
384 const std::string& ip_addr,
385 uint16_t port) { info.emplace(instance_name, service_name, ip_addr, port); };
386
387 std::string reg_type;
388 // Verify it's a pairing service if user explicitly inputs it.
389 if (!mdns_instance->service_name.empty()) {
390 reg_type = android::base::StringPrintf("%s.%s", mdns_instance->service_name.data(),
391 mdns_instance->transport_type.data());
392 const auto index = adb_DNSServiceIndexByName(reg_type);
393 if (!index) {
394 return std::nullopt;
395 }
396 switch (*index) {
397 case kADBSecurePairingServiceRefIndex:
398 break;
399 default:
400 D("Not an adb pairing reg_type [%s]", reg_type.data());
401 return std::nullopt;
402 }
403 return info;
404 }
405
406 ForEachService(g_state->receivers[kADBSecurePairingServiceRefIndex], name, cb);
407
408 return info;
409 }
410