You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
230 lines
6.6 KiB
230 lines
6.6 KiB
4 months ago
|
/*
|
||
|
* Copyright (C) 2019 The Android Open Source Project
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
|
||
|
#if !ADB_HOST
|
||
|
|
||
|
#define TRACE_TAG ADB_WIRELESS
|
||
|
|
||
|
#include "adb_wifi.h"
|
||
|
|
||
|
#include <unistd.h>
|
||
|
#include <optional>
|
||
|
|
||
|
#include <adbd_auth.h>
|
||
|
#include <android-base/properties.h>
|
||
|
|
||
|
#include "adb.h"
|
||
|
#include "daemon/mdns.h"
|
||
|
#include "sysdeps.h"
|
||
|
#include "transport.h"
|
||
|
|
||
|
using namespace android::base;
|
||
|
|
||
|
namespace {
|
||
|
|
||
|
static AdbdAuthContext* auth_ctx;
|
||
|
|
||
|
static void adb_disconnected(void* unused, atransport* t);
|
||
|
static struct adisconnect adb_disconnect = {adb_disconnected, nullptr};
|
||
|
|
||
|
static void adb_disconnected(void* unused, atransport* t) {
|
||
|
LOG(INFO) << "ADB wifi device disconnected";
|
||
|
CHECK(t->auth_id.has_value());
|
||
|
adbd_auth_tls_device_disconnected(auth_ctx, kAdbTransportTypeWifi, t->auth_id.value());
|
||
|
}
|
||
|
|
||
|
// TODO(b/31559095): need bionic host so that we can use 'prop_info' returned
|
||
|
// from WaitForProperty
|
||
|
#if defined(__ANDROID__)
|
||
|
|
||
|
class TlsServer {
|
||
|
public:
|
||
|
explicit TlsServer(int port);
|
||
|
virtual ~TlsServer();
|
||
|
bool Start();
|
||
|
uint16_t port() { return port_; };
|
||
|
|
||
|
private:
|
||
|
void OnFdEvent(int fd, unsigned ev);
|
||
|
static void StaticOnFdEvent(int fd, unsigned ev, void* opaque);
|
||
|
|
||
|
fdevent* fd_event_ = nullptr;
|
||
|
uint16_t port_;
|
||
|
}; // TlsServer
|
||
|
|
||
|
TlsServer::TlsServer(int port) : port_(port) {}
|
||
|
|
||
|
TlsServer::~TlsServer() {
|
||
|
fdevent* fde = fd_event_;
|
||
|
fdevent_run_on_main_thread([fde]() {
|
||
|
if (fde != nullptr) {
|
||
|
fdevent_destroy(fde);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
bool TlsServer::Start() {
|
||
|
std::condition_variable cv;
|
||
|
std::mutex mutex;
|
||
|
std::optional<bool> success;
|
||
|
auto callback = [&](bool result) {
|
||
|
{
|
||
|
std::lock_guard<std::mutex> lock(mutex);
|
||
|
success = result;
|
||
|
}
|
||
|
cv.notify_one();
|
||
|
};
|
||
|
|
||
|
std::string err;
|
||
|
unique_fd fd(network_inaddr_any_server(port_, SOCK_STREAM, &err));
|
||
|
if (fd.get() == -1) {
|
||
|
LOG(ERROR) << "Failed to start TLS server [" << err << "]";
|
||
|
return false;
|
||
|
}
|
||
|
close_on_exec(fd.get());
|
||
|
int port = socket_get_local_port(fd.get());
|
||
|
if (port <= 0 || port > 65535) {
|
||
|
LOG(ERROR) << "Invalid port for tls server";
|
||
|
return false;
|
||
|
}
|
||
|
port_ = static_cast<uint16_t>(port);
|
||
|
LOG(INFO) << "adbwifi started on port " << port_;
|
||
|
|
||
|
std::unique_lock<std::mutex> lock(mutex);
|
||
|
fdevent_run_on_main_thread([&]() {
|
||
|
fd_event_ = fdevent_create(fd.release(), &TlsServer::StaticOnFdEvent, this);
|
||
|
if (fd_event_ == nullptr) {
|
||
|
LOG(ERROR) << "Failed to create fd event for TlsServer.";
|
||
|
callback(false);
|
||
|
return;
|
||
|
}
|
||
|
callback(true);
|
||
|
});
|
||
|
|
||
|
cv.wait(lock, [&]() { return success.has_value(); });
|
||
|
if (!*success) {
|
||
|
LOG(INFO) << "TlsServer fdevent_create failed";
|
||
|
return false;
|
||
|
}
|
||
|
fdevent_set(fd_event_, FDE_READ);
|
||
|
LOG(INFO) << "TlsServer running on port " << port_;
|
||
|
|
||
|
return *success;
|
||
|
}
|
||
|
|
||
|
// static
|
||
|
void TlsServer::StaticOnFdEvent(int fd, unsigned ev, void* opaque) {
|
||
|
auto server = reinterpret_cast<TlsServer*>(opaque);
|
||
|
server->OnFdEvent(fd, ev);
|
||
|
}
|
||
|
|
||
|
void TlsServer::OnFdEvent(int fd, unsigned ev) {
|
||
|
if ((ev & FDE_READ) == 0 || fd != fd_event_->fd.get()) {
|
||
|
LOG(INFO) << __func__ << ": No read [ev=" << ev << " fd=" << fd << "]";
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
unique_fd new_fd(adb_socket_accept(fd, nullptr, nullptr));
|
||
|
if (new_fd >= 0) {
|
||
|
LOG(INFO) << "New TLS connection [fd=" << new_fd.get() << "]";
|
||
|
close_on_exec(new_fd.get());
|
||
|
disable_tcp_nagle(new_fd.get());
|
||
|
std::string serial = android::base::StringPrintf("host-%d", new_fd.get());
|
||
|
register_socket_transport(
|
||
|
std::move(new_fd), std::move(serial), port_, 1,
|
||
|
[](atransport*) { return ReconnectResult::Abort; }, true);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TlsServer* sTlsServer = nullptr;
|
||
|
const char kWifiPortProp[] = "service.adb.tls.port";
|
||
|
|
||
|
const char kWifiEnabledProp[] = "persist.adb.tls_server.enable";
|
||
|
|
||
|
static void enable_wifi_debugging() {
|
||
|
start_mdnsd();
|
||
|
|
||
|
if (sTlsServer != nullptr) {
|
||
|
delete sTlsServer;
|
||
|
}
|
||
|
sTlsServer = new TlsServer(0);
|
||
|
if (!sTlsServer->Start()) {
|
||
|
LOG(ERROR) << "Failed to start TlsServer";
|
||
|
delete sTlsServer;
|
||
|
sTlsServer = nullptr;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Start mdns connect service for discovery
|
||
|
register_adb_secure_connect_service(sTlsServer->port());
|
||
|
LOG(INFO) << "adb wifi started on port " << sTlsServer->port();
|
||
|
SetProperty(kWifiPortProp, std::to_string(sTlsServer->port()));
|
||
|
}
|
||
|
|
||
|
static void disable_wifi_debugging() {
|
||
|
if (sTlsServer != nullptr) {
|
||
|
delete sTlsServer;
|
||
|
sTlsServer = nullptr;
|
||
|
}
|
||
|
if (is_adb_secure_connect_service_registered()) {
|
||
|
unregister_adb_secure_connect_service();
|
||
|
}
|
||
|
kick_all_tcp_tls_transports();
|
||
|
LOG(INFO) << "adb wifi stopped";
|
||
|
SetProperty(kWifiPortProp, "");
|
||
|
}
|
||
|
|
||
|
// Watches for the #kWifiEnabledProp property to toggle the TlsServer
|
||
|
static void start_wifi_enabled_observer() {
|
||
|
std::thread([]() {
|
||
|
bool wifi_enabled = false;
|
||
|
while (true) {
|
||
|
std::string toggled_val = wifi_enabled ? "0" : "1";
|
||
|
LOG(INFO) << "Waiting for " << kWifiEnabledProp << "=" << toggled_val;
|
||
|
if (WaitForProperty(kWifiEnabledProp, toggled_val)) {
|
||
|
wifi_enabled = !wifi_enabled;
|
||
|
LOG(INFO) << kWifiEnabledProp << " changed to " << toggled_val;
|
||
|
if (wifi_enabled) {
|
||
|
enable_wifi_debugging();
|
||
|
} else {
|
||
|
disable_wifi_debugging();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}).detach();
|
||
|
}
|
||
|
#endif //__ANDROID__
|
||
|
|
||
|
} // namespace
|
||
|
|
||
|
void adbd_wifi_init(AdbdAuthContext* ctx) {
|
||
|
auth_ctx = ctx;
|
||
|
#if defined(__ANDROID__)
|
||
|
start_wifi_enabled_observer();
|
||
|
#endif //__ANDROID__
|
||
|
}
|
||
|
|
||
|
void adbd_wifi_secure_connect(atransport* t) {
|
||
|
t->AddDisconnect(&adb_disconnect);
|
||
|
handle_online(t);
|
||
|
send_connect(t);
|
||
|
LOG(INFO) << __func__ << ": connected " << t->serial;
|
||
|
t->auth_id = adbd_auth_tls_device_connected(auth_ctx, kAdbTransportTypeWifi, t->auth_key.data(),
|
||
|
t->auth_key.size());
|
||
|
}
|
||
|
|
||
|
#endif /* !HOST */
|