• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 MDNS
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 <discovery/public/dns_sd_service_watcher.h>
39 #include <platform/api/network_interface.h>
40 #include <platform/api/serial_delete_ptr.h>
41 #include <platform/base/error.h>
42 #include <platform/base/interface_info.h>
43 
44 #include "adb_client.h"
45 #include "adb_mdns.h"
46 #include "adb_trace.h"
47 #include "adb_utils.h"
48 #include "adb_wifi.h"
49 #include "client/mdns_utils.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 ServiceWatcher = discovery::DnsSdServiceWatcher<ServiceInfo>;
59 using ServicesUpdatedState = ServiceWatcher::ServicesUpdatedState;
60 
61 struct DiscoveryState;
62 DiscoveryState* g_state = nullptr;
63 // TODO: remove once openscreen has bonjour client APIs.
64 bool g_using_bonjour = false;
65 AdbMdnsResponderFuncs g_adb_mdnsresponder_funcs;
66 
67 class DiscoveryReportingClient : public discovery::ReportingClient {
68   public:
OnFatalError(Error error)69     void OnFatalError(Error error) override {
70         // The multicast port 5353 may fail to bind because of another process already binding
71         // to it (bonjour). So let's fallback to bonjour client APIs.
72         // TODO: Remove this once openscreen implements the bonjour client APIs.
73         LOG(ERROR) << "Encountered fatal discovery error: " << error;
74         got_fatal_ = true;
75     }
76 
OnRecoverableError(Error error)77     void OnRecoverableError(Error error) override {
78         LOG(ERROR) << "Encountered recoverable discovery error: " << error;
79     }
80 
GotFatalError() const81     bool GotFatalError() const { return got_fatal_; }
82 
83   private:
84     std::atomic<bool> got_fatal_{false};
85 };
86 
87 struct DiscoveryState {
88     std::optional<discovery::Config> config;
89     SerialDeletePtr<discovery::DnsSdService> service;
90     std::unique_ptr<DiscoveryReportingClient> reporting_client;
91     std::unique_ptr<AdbOspTaskRunner> task_runner;
92     std::vector<std::unique_ptr<ServiceWatcher>> watchers;
93     InterfaceInfo interface_info;
94 };
95 
96 // Callback provided to service receiver for updates.
OnServiceReceiverResult(std::vector<std::reference_wrapper<const ServiceInfo>> infos,std::reference_wrapper<const ServiceInfo> info,ServicesUpdatedState state)97 void OnServiceReceiverResult(std::vector<std::reference_wrapper<const ServiceInfo>> infos,
98                              std::reference_wrapper<const ServiceInfo> info,
99                              ServicesUpdatedState state) {
100     VLOG(MDNS) << "Endpoint state=" << static_cast<int>(state)
101                << " instance_name=" << info.get().instance_name
102                << " service_name=" << info.get().service_name << " addr=" << info.get().v4_address
103                << " addrv6=" << info.get().v6_address << " total_serv=" << infos.size();
104 
105     switch (state) {
106         case ServicesUpdatedState::EndpointCreated:
107         case ServicesUpdatedState::EndpointUpdated:
108             if (adb_DNSServiceShouldAutoConnect(info.get().service_name,
109                                                 info.get().instance_name) &&
110                 info.get().v4_address) {
111                 auto index = adb_DNSServiceIndexByName(info.get().service_name);
112                 if (!index) {
113                     return;
114                 }
115 
116                 // Don't try to auto-connect if not in the keystore.
117                 if (*index == kADBSecureConnectServiceRefIndex &&
118                     !adb_wifi_is_known_host(info.get().instance_name)) {
119                     VLOG(MDNS) << "instance_name=" << info.get().instance_name
120                                << " not in keystore";
121                     return;
122                 }
123                 std::string response;
124                 VLOG(MDNS) << "Attempting to auto-connect to instance=" << info.get().instance_name
125                            << " service=" << info.get().service_name << " addr4=%s"
126                            << info.get().v4_address << ":" << info.get().port;
127                 connect_device(
128                         android::base::StringPrintf("%s.%s", info.get().instance_name.c_str(),
129                                                     info.get().service_name.c_str()),
130                         &response);
131             }
132             break;
133         default:
134             break;
135     }
136 }
137 
GetConfigForAllInterfaces()138 std::optional<discovery::Config> GetConfigForAllInterfaces() {
139     auto interface_infos = GetNetworkInterfaces();
140 
141     discovery::Config config;
142 
143     // The host only consumes mDNS traffic. It doesn't publish anything.
144     // Avoid creating an mDNSResponder that will listen with authority
145     // to answer over no domain.
146     config.enable_publication = false;
147 
148     for (const auto interface : interface_infos) {
149         if (interface.GetIpAddressV4() || interface.GetIpAddressV6()) {
150             config.network_info.push_back({interface});
151             VLOG(MDNS) << "Listening on interface [" << interface << "]";
152         }
153     }
154 
155     if (config.network_info.empty()) {
156         VLOG(MDNS) << "No available network interfaces for mDNS discovery";
157         return std::nullopt;
158     }
159 
160     return config;
161 }
162 
StartDiscovery()163 void StartDiscovery() {
164     CHECK(!g_state);
165     g_state = new DiscoveryState();
166     g_state->task_runner = std::make_unique<AdbOspTaskRunner>();
167     g_state->reporting_client = std::make_unique<DiscoveryReportingClient>();
168 
169     g_state->task_runner->PostTask([]() {
170         g_state->config = GetConfigForAllInterfaces();
171         if (!g_state->config) {
172             VLOG(MDNS) << "No mDNS config. Aborting StartDiscovery()";
173             return;
174         }
175 
176         VLOG(MDNS) << "Starting discovery on " << (*g_state->config).network_info.size()
177                    << " interfaces";
178 
179         g_state->service = discovery::CreateDnsSdService(
180                 g_state->task_runner.get(), g_state->reporting_client.get(), *g_state->config);
181         // Register a receiver for each service type
182         for (int i = 0; i < kNumADBDNSServices; ++i) {
183             auto watcher = std::make_unique<ServiceWatcher>(
184                     g_state->service.get(), kADBDNSServices[i], DnsSdInstanceEndpointToServiceInfo,
185                     OnServiceReceiverResult);
186             watcher->StartDiscovery();
187             g_state->watchers.push_back(std::move(watcher));
188 
189             if (g_state->reporting_client->GotFatalError()) {
190                 for (auto& w : g_state->watchers) {
191                     if (w->is_running()) {
192                         w->StopDiscovery();
193                     }
194                 }
195                 g_using_bonjour = true;
196                 break;
197             }
198         }
199 
200         if (g_using_bonjour) {
201             VLOG(MDNS) << "Fallback to MdnsResponder client for discovery";
202             g_adb_mdnsresponder_funcs = StartMdnsResponderDiscovery();
203         }
204     });
205 }
206 
ForEachService(const std::unique_ptr<ServiceWatcher> & receiver,std::string_view wanted_instance_name,adb_secure_foreach_service_callback cb)207 void ForEachService(const std::unique_ptr<ServiceWatcher>& receiver,
208                     std::string_view wanted_instance_name, adb_secure_foreach_service_callback cb) {
209     if (!receiver->is_running()) {
210         return;
211     }
212     auto services = receiver->GetServices();
213     for (const auto& s : services) {
214         if (wanted_instance_name.empty() || s.get().instance_name == wanted_instance_name) {
215             std::stringstream ss;
216             ss << s.get().v4_address;
217             cb(s.get());
218         }
219     }
220 }
221 
ConnectAdbSecureDevice(const MdnsInfo & info)222 bool ConnectAdbSecureDevice(const MdnsInfo& info) {
223     if (!adb_wifi_is_known_host(info.service_name)) {
224         VLOG(MDNS) << "serviceName=" << info.service_name << " not in keystore";
225         return false;
226     }
227 
228     std::string response;
229     connect_device(android::base::StringPrintf("%s.%s", info.service_name.c_str(),
230                                                info.service_type.c_str()),
231                    &response);
232     D("Secure connect to %s regtype %s (%s:%hu) : %s", info.service_name.c_str(),
233       info.service_type.c_str(), info.addr.c_str(), info.port, response.c_str());
234     return true;
235 }
236 
237 }  // namespace
238 
239 /////////////////////////////////////////////////////////////////////////////////
240 
using_bonjour(void)241 bool using_bonjour(void) {
242     return g_using_bonjour;
243 }
244 
mdns_cleanup()245 void mdns_cleanup() {
246     if (g_using_bonjour) {
247         return g_adb_mdnsresponder_funcs.mdns_cleanup();
248     }
249 }
250 
init_mdns_transport_discovery()251 void init_mdns_transport_discovery() {
252     const char* mdns_osp = getenv("ADB_MDNS_OPENSCREEN");
253     if (mdns_osp && strcmp(mdns_osp, "0") == 0) {
254         g_using_bonjour = true;
255         g_adb_mdnsresponder_funcs = StartMdnsResponderDiscovery();
256     } else {
257         VLOG(MDNS) << "Openscreen mdns discovery enabled";
258         StartDiscovery();
259     }
260 }
261 
adb_secure_connect_by_service_name(const std::string & instance_name)262 bool adb_secure_connect_by_service_name(const std::string& instance_name) {
263     if (g_using_bonjour) {
264         return g_adb_mdnsresponder_funcs.adb_secure_connect_by_service_name(instance_name);
265     }
266 
267     if (!g_state || g_state->watchers.empty()) {
268         VLOG(MDNS) << "Mdns not enabled";
269         return false;
270     }
271 
272     std::optional<MdnsInfo> info;
273     auto cb = [&](const mdns::ServiceInfo& si) {
274         info.emplace(si.instance_name, si.service_name, si.v4_address_string(), si.port);
275     };
276     ForEachService(g_state->watchers[kADBSecureConnectServiceRefIndex], instance_name, cb);
277     if (info.has_value()) {
278         return ConnectAdbSecureDevice(*info);
279     }
280     return false;
281 }
282 
mdns_check()283 std::string mdns_check() {
284     if (!g_state && !g_using_bonjour) {
285         return "ERROR: mdns discovery disabled";
286     }
287 
288     if (g_using_bonjour) {
289         return g_adb_mdnsresponder_funcs.mdns_check();
290     }
291 
292     return "mdns daemon version [Openscreen discovery 0.0.0]";
293 }
294 
mdns_list_discovered_services()295 std::string mdns_list_discovered_services() {
296     if (g_using_bonjour) {
297         return g_adb_mdnsresponder_funcs.mdns_list_discovered_services();
298     }
299 
300     if (!g_state || g_state->watchers.empty()) {
301         return "";
302     }
303 
304     std::string result;
305     auto cb = [&](const mdns::ServiceInfo& si) {
306         result += android::base::StringPrintf("%s\t%s\t%s:%u\n", si.instance_name.data(),
307                                               si.service_name.data(), si.v4_address_string().data(),
308                                               si.port);
309     };
310 
311     for (const auto& receiver : g_state->watchers) {
312         ForEachService(receiver, "", cb);
313     }
314     return result;
315 }
316 
mdns_get_connect_service_info(const std::string & name)317 std::optional<MdnsInfo> mdns_get_connect_service_info(const std::string& name) {
318     CHECK(!name.empty());
319 
320     if (g_using_bonjour) {
321         return g_adb_mdnsresponder_funcs.mdns_get_connect_service_info(name);
322     }
323 
324     if (!g_state || g_state->watchers.empty()) {
325         return std::nullopt;
326     }
327 
328     auto mdns_instance = mdns::mdns_parse_instance_name(name);
329     if (!mdns_instance.has_value()) {
330         D("Failed to parse mDNS name [%s]", name.data());
331         return std::nullopt;
332     }
333 
334     std::optional<MdnsInfo> info;
335     auto cb = [&](const ServiceInfo& si) {
336         info.emplace(si.instance_name, si.service_name, si.v4_address_string(), si.port);
337     };
338 
339     std::string reg_type;
340     // Service name was provided.
341     if (!mdns_instance->service_name.empty()) {
342         reg_type = android::base::StringPrintf("%s.%s", mdns_instance->service_name.data(),
343                                                mdns_instance->transport_type.data());
344         const auto index = adb_DNSServiceIndexByName(reg_type);
345         if (!index) {
346             return std::nullopt;
347         }
348         switch (*index) {
349             case kADBTransportServiceRefIndex:
350             case kADBSecureConnectServiceRefIndex:
351                 ForEachService(g_state->watchers[*index], mdns_instance->instance_name, cb);
352                 break;
353             default:
354                 D("Not a connectable service name [%s]", reg_type.data());
355                 return std::nullopt;
356         }
357         return info;
358     }
359 
360     // No mdns service name provided. Just search for the instance name in all adb connect services.
361     // Prefer the secured connect service over the other.
362     ForEachService(g_state->watchers[kADBSecureConnectServiceRefIndex], name, cb);
363     if (!info.has_value()) {
364         ForEachService(g_state->watchers[kADBTransportServiceRefIndex], name, cb);
365     }
366 
367     return info;
368 }
369 
mdns_get_pairing_service_info(const std::string & name)370 std::optional<MdnsInfo> mdns_get_pairing_service_info(const std::string& name) {
371     CHECK(!name.empty());
372 
373     if (g_using_bonjour) {
374         return g_adb_mdnsresponder_funcs.mdns_get_pairing_service_info(name);
375     }
376 
377     if (!g_state || g_state->watchers.empty()) {
378         return std::nullopt;
379     }
380 
381     auto mdns_instance = mdns::mdns_parse_instance_name(name);
382     if (!mdns_instance.has_value()) {
383         D("Failed to parse mDNS name [%s]", name.data());
384         return std::nullopt;
385     }
386 
387     std::optional<MdnsInfo> info;
388     auto cb = [&](const ServiceInfo& si) {
389         info.emplace(si.instance_name, si.service_name, si.v4_address_string(), si.port);
390     };
391 
392     std::string reg_type;
393     // Verify it's a pairing service if user explicitly inputs it.
394     if (!mdns_instance->service_name.empty()) {
395         reg_type = android::base::StringPrintf("%s.%s", mdns_instance->service_name.data(),
396                                                mdns_instance->transport_type.data());
397         const auto index = adb_DNSServiceIndexByName(reg_type);
398         if (!index) {
399             return std::nullopt;
400         }
401         switch (*index) {
402             case kADBSecurePairingServiceRefIndex:
403                 break;
404             default:
405                 D("Not an adb pairing reg_type [%s]", reg_type.data());
406                 return std::nullopt;
407         }
408         return info;
409     }
410 
411     ForEachService(g_state->watchers[kADBSecurePairingServiceRefIndex], name, cb);
412 
413     return info;
414 }
415