blob: b99e8bcfeb116b0db781781165a9418d3ed01fdd [file] [log] [blame]
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001/*
2 * Copyright (C) 2007 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
Yabin Cui19bec5b2015-09-22 15:52:57 -070017#define TRACE_TAG TRANSPORT
Dan Albertb302d122015-02-24 15:51:19 -080018
Dan Albertdb6fe642015-03-19 15:21:08 -070019#include "sysdeps.h"
Josh Gaof2a988c2018-03-07 16:51:08 -080020
Dan Albertb302d122015-02-24 15:51:19 -080021#include "transport.h"
22
Dan Albert4895c522015-02-20 17:24:58 -080023#include <ctype.h>
Dan Albertb302d122015-02-24 15:51:19 -080024#include <errno.h>
Josh Gaob39e4152017-08-16 16:57:01 -070025#include <inttypes.h>
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080026#include <stdio.h>
27#include <stdlib.h>
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080028#include <string.h>
Dan Albertb302d122015-02-24 15:51:19 -080029#include <unistd.h>
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080030
Spencer Low28bc2cb2015-11-07 18:51:54 -080031#include <algorithm>
Dan Albertecce5032015-05-18 16:46:31 -070032#include <list>
Pirama Arumuga Nainar5231aff2018-08-08 10:33:24 -070033#include <memory>
Josh Gaoe7daf572016-09-21 12:37:10 -070034#include <mutex>
Josh Gaod2ea0652018-08-10 14:28:24 -070035#include <set>
Elliott Hughes73abffa2022-06-09 16:30:24 +000036#include <string>
Josh Gao0f3312a2017-04-12 17:00:49 -070037#include <thread>
Dan Albertecce5032015-05-18 16:46:31 -070038
Joshua Duong64fab752020-01-21 13:19:42 -080039#include <adb/crypto/rsa_2048_key.h>
40#include <adb/crypto/x509_generator.h>
41#include <adb/tls/tls_connection.h>
Elliott Hughesf55ead92015-12-04 22:00:26 -080042#include <android-base/logging.h>
Yurii Zubrytskyi816c2d22020-03-26 18:19:28 -070043#include <android-base/no_destructor.h>
David Pursellc929c6f2016-03-01 08:58:26 -080044#include <android-base/parsenetaddress.h>
Elliott Hughesf55ead92015-12-04 22:00:26 -080045#include <android-base/stringprintf.h>
46#include <android-base/strings.h>
Josh Gaob39e4152017-08-16 16:57:01 -070047#include <android-base/thread_annotations.h>
Josh Gao361148b2018-01-02 12:01:43 -080048#include <diagnose_usb.h>
49
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080050#include "adb.h"
Elliott Hughes801066a2016-06-29 17:42:01 -070051#include "adb_auth.h"
Josh Gao395b86a2018-01-28 20:32:46 -080052#include "adb_io.h"
Josh Gao9e09a972016-11-29 09:40:29 -080053#include "adb_trace.h"
Elliott Hughes88b4c852015-04-30 17:32:03 -070054#include "adb_utils.h"
Josh Gaob51193a2019-06-28 13:50:37 -070055#include "fdevent/fdevent.h"
Josh Gaob0182892018-07-31 14:12:59 -070056#include "sysdeps/chrono.h"
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080057
Josh Gao8e7c9722021-06-17 04:19:45 -070058#if ADB_HOST
Fabien Sanglard3d155b62023-11-30 14:52:40 -080059#include <google/protobuf/text_format.h>
Fabien Sanglard05789412024-05-30 23:00:18 -070060#include "adb_host.pb.h"
Josh Gao8e7c9722021-06-17 04:19:45 -070061#include "client/usb.h"
62#endif
63
Joshua Duong64fab752020-01-21 13:19:42 -080064using namespace adb::crypto;
65using namespace adb::tls;
Elliott Hughes73abffa2022-06-09 16:30:24 +000066using namespace std::string_literals;
Josh Gao8aa57d22019-02-12 13:59:03 -080067using android::base::ScopedLockAssertion;
Joshua Duong64fab752020-01-21 13:19:42 -080068using TlsError = TlsConnection::TlsError;
Josh Gao8aa57d22019-02-12 13:59:03 -080069
Luis Hector Chavez0aeda102018-04-20 10:31:29 -070070static void remove_transport(atransport* transport);
Josh Gao14ed9f92019-12-09 13:45:31 -080071static void transport_destroy(atransport* transport);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080072
Josh Gaob39e4152017-08-16 16:57:01 -070073// TODO: unordered_map<TransportId, atransport*>
Josh Gaoe3a87d02015-11-11 17:56:12 -080074static auto& transport_list = *new std::list<atransport*>();
75static auto& pending_list = *new std::list<atransport*>();
Benoit Goby3f9f9ce2013-03-29 18:22:36 -070076
Josh Gaoaaa82f72017-08-17 13:50:51 -070077static auto& transport_lock = *new std::recursive_mutex();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080078
Todd Kennedyaff9c672015-11-10 00:03:25 +000079const char* const kFeatureShell2 = "shell_v2";
80const char* const kFeatureCmd = "cmd";
Josh Gaoa2cf3752016-12-05 17:11:34 -080081const char* const kFeatureStat2 = "stat_v2";
Josh Gao7b083072019-08-07 14:23:17 -070082const char* const kFeatureLs2 = "ls_v2";
Josh Gao210b63f2017-02-22 17:07:01 -080083const char* const kFeatureLibusb = "libusb";
Dan Albert27983bc2017-05-23 14:30:00 -070084const char* const kFeaturePushSync = "push_sync";
Dario Frenidcb4c362018-10-04 16:26:40 +010085const char* const kFeatureApex = "apex";
Josh Gao281aab72018-10-22 13:00:05 -070086const char* const kFeatureFixedPushMkdir = "fixed_push_mkdir";
Alex Buynytskyye1fa8142019-01-17 13:13:56 -080087const char* const kFeatureAbb = "abb";
Josh Gao9eeb9f72019-02-20 13:01:40 -080088const char* const kFeatureFixedPushSymlinkTimestamp = "fixed_push_symlink_timestamp";
Alex Buynytskyy4f3fa052019-02-21 14:22:51 -080089const char* const kFeatureAbbExec = "abb_exec";
Josh Gaof764d572019-07-11 14:15:32 -070090const char* const kFeatureRemountShell = "remount_shell";
Shukang Zhou420ad552020-02-13 17:01:39 -080091const char* const kFeatureTrackApp = "track_app";
Josh Gao2f0f9eb2020-03-04 19:34:08 -080092const char* const kFeatureSendRecv2 = "sendrecv_v2";
93const char* const kFeatureSendRecv2Brotli = "sendrecv_v2_brotli";
Josh Gaofb386cc2020-03-26 22:02:03 -070094const char* const kFeatureSendRecv2LZ4 = "sendrecv_v2_lz4";
Josh Gaobdebc9b2020-05-27 17:52:52 -070095const char* const kFeatureSendRecv2Zstd = "sendrecv_v2_zstd";
Josh Gao8a410a02020-03-30 23:25:16 -070096const char* const kFeatureSendRecv2DryRunSend = "sendrecv_v2_dry_run_send";
Josh Gaobd1f3002021-12-29 21:15:12 -080097const char* const kFeatureDelayedAck = "delayed_ack";
Joshua Duongf4ba8d72021-01-13 12:18:15 -080098// TODO(joshuaduong): Bump to v2 when openscreen discovery is enabled by default
99const char* const kFeatureOpenscreenMdns = "openscreen_mdns";
Fabien Sanglard3d155b62023-11-30 14:52:40 -0800100const char* const kFeatureDeviceTrackerProtoFormat = "devicetracker_proto_format";
Octavian Purdila4b4421d2024-04-03 23:13:14 -0700101const char* const kFeatureDevRaw = "devraw";
Fabien Sanglard15335e02024-03-05 21:33:44 +0000102const char* const kFeatureAppInfo = "app_info"; // Add information to track-app (package name, ...)
Fabien Sanglard05789412024-05-30 23:00:18 -0700103const char* const kFeatureServerStatus = "server_status"; // Ability to output server status
Todd Kennedyaff9c672015-11-10 00:03:25 +0000104
Luis Hector Chavezda74b902018-04-17 14:25:04 -0700105namespace {
106
Josh Gao5c47e9f2018-07-31 18:28:32 -0700107#if ADB_HOST
Vince Harron5703eb32021-11-12 12:40:58 -0800108
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700109// Tracks and handles atransport*s that are attempting reconnection.
110class ReconnectHandler {
111 public:
112 ReconnectHandler() = default;
113 ~ReconnectHandler() = default;
114
115 // Starts the ReconnectHandler thread.
116 void Start();
117
118 // Requests the ReconnectHandler thread to stop.
119 void Stop();
120
121 // Adds the atransport* to the queue of reconnect attempts.
122 void TrackTransport(atransport* transport);
123
Josh Gao13cb8c02018-08-10 14:44:54 -0700124 // Wake up the ReconnectHandler thread to have it check for kicked transports.
125 void CheckForKicked();
126
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700127 private:
128 // The main thread loop.
129 void Run();
130
131 // Tracks a reconnection attempt.
132 struct ReconnectAttempt {
133 atransport* transport;
Josh Gaoc4deb392018-07-30 18:51:55 -0700134 std::chrono::steady_clock::time_point reconnect_time;
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700135 size_t attempts_left;
Josh Gaob0182892018-07-31 14:12:59 -0700136
137 bool operator<(const ReconnectAttempt& rhs) const {
Josh Gaod2ea0652018-08-10 14:28:24 -0700138 if (reconnect_time == rhs.reconnect_time) {
139 return reinterpret_cast<uintptr_t>(transport) <
140 reinterpret_cast<uintptr_t>(rhs.transport);
141 }
142 return reconnect_time < rhs.reconnect_time;
Josh Gaob0182892018-07-31 14:12:59 -0700143 }
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700144 };
145
146 // Only retry for up to one minute.
Josh Gao04ef6962020-10-15 18:32:55 -0700147 static constexpr const std::chrono::seconds kDefaultTimeout = 3s;
148 static constexpr const size_t kMaxAttempts = 20;
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700149
150 // Protects all members.
151 std::mutex reconnect_mutex_;
152 bool running_ GUARDED_BY(reconnect_mutex_) = true;
153 std::thread handler_thread_;
154 std::condition_variable reconnect_cv_;
Josh Gaod2ea0652018-08-10 14:28:24 -0700155 std::set<ReconnectAttempt> reconnect_queue_ GUARDED_BY(reconnect_mutex_);
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700156
157 DISALLOW_COPY_AND_ASSIGN(ReconnectHandler);
158};
159
160void ReconnectHandler::Start() {
Shaju Mathew705fa1c2022-12-31 19:36:54 -0800161 fdevent_check_looper();
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700162 handler_thread_ = std::thread(&ReconnectHandler::Run, this);
163}
164
165void ReconnectHandler::Stop() {
Shaju Mathew705fa1c2022-12-31 19:36:54 -0800166 fdevent_check_looper();
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700167 {
168 std::lock_guard<std::mutex> lock(reconnect_mutex_);
169 running_ = false;
170 }
171 reconnect_cv_.notify_one();
172 handler_thread_.join();
173
174 // Drain the queue to free all resources.
175 std::lock_guard<std::mutex> lock(reconnect_mutex_);
176 while (!reconnect_queue_.empty()) {
Josh Gaod2ea0652018-08-10 14:28:24 -0700177 ReconnectAttempt attempt = *reconnect_queue_.begin();
178 reconnect_queue_.erase(reconnect_queue_.begin());
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700179 remove_transport(attempt.transport);
180 }
181}
182
183void ReconnectHandler::TrackTransport(atransport* transport) {
Shaju Mathew705fa1c2022-12-31 19:36:54 -0800184 fdevent_check_looper();
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700185 {
186 std::lock_guard<std::mutex> lock(reconnect_mutex_);
187 if (!running_) return;
Josh Gaob0182892018-07-31 14:12:59 -0700188 // Arbitrary sleep to give adbd time to get ready, if we disconnected because it exited.
189 auto reconnect_time = std::chrono::steady_clock::now() + 250ms;
190 reconnect_queue_.emplace(
191 ReconnectAttempt{transport, reconnect_time, ReconnectHandler::kMaxAttempts});
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700192 }
193 reconnect_cv_.notify_one();
194}
195
Josh Gao13cb8c02018-08-10 14:44:54 -0700196void ReconnectHandler::CheckForKicked() {
197 reconnect_cv_.notify_one();
198}
199
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700200void ReconnectHandler::Run() {
201 while (true) {
202 ReconnectAttempt attempt;
203 {
204 std::unique_lock<std::mutex> lock(reconnect_mutex_);
Josh Gao8aa57d22019-02-12 13:59:03 -0800205 ScopedLockAssertion assume_lock(reconnect_mutex_);
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700206
Josh Gaoc4deb392018-07-30 18:51:55 -0700207 if (!reconnect_queue_.empty()) {
208 // FIXME: libstdc++ (used on Windows) implements condition_variable with
209 // system_clock as its clock, so we're probably hosed if the clock changes,
210 // even if we use steady_clock throughout. This problem goes away once we
211 // switch to libc++.
Josh Gaod2ea0652018-08-10 14:28:24 -0700212 reconnect_cv_.wait_until(lock, reconnect_queue_.begin()->reconnect_time);
Josh Gaoc4deb392018-07-30 18:51:55 -0700213 } else {
214 reconnect_cv_.wait(lock);
215 }
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700216
217 if (!running_) return;
Josh Gao13cb8c02018-08-10 14:44:54 -0700218
219 // Scan the whole list for kicked transports, so that we immediately handle an explicit
220 // disconnect request.
Josh Gao13cb8c02018-08-10 14:44:54 -0700221 for (auto it = reconnect_queue_.begin(); it != reconnect_queue_.end();) {
222 if (it->transport->kicked()) {
223 D("transport %s was kicked. giving up on it.", it->transport->serial.c_str());
224 remove_transport(it->transport);
225 it = reconnect_queue_.erase(it);
226 } else {
227 ++it;
228 }
Josh Gao13cb8c02018-08-10 14:44:54 -0700229 }
230
Josh Gaoc4deb392018-07-30 18:51:55 -0700231 if (reconnect_queue_.empty()) continue;
232
Josh Gao13cb8c02018-08-10 14:44:54 -0700233 // Go back to sleep if we either woke up spuriously, or we were woken up to remove
234 // a kicked transport, and the first transport isn't ready for reconnection yet.
Josh Gaoc4deb392018-07-30 18:51:55 -0700235 auto now = std::chrono::steady_clock::now();
Josh Gaod2ea0652018-08-10 14:28:24 -0700236 if (reconnect_queue_.begin()->reconnect_time > now) {
Josh Gaoc4deb392018-07-30 18:51:55 -0700237 continue;
238 }
239
Josh Gaod2ea0652018-08-10 14:28:24 -0700240 attempt = *reconnect_queue_.begin();
241 reconnect_queue_.erase(reconnect_queue_.begin());
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700242 }
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700243 D("attempting to reconnect %s", attempt.transport->serial.c_str());
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700244
Josh Gaod24580d2018-08-30 11:37:00 -0700245 switch (attempt.transport->Reconnect()) {
246 case ReconnectResult::Retry: {
247 D("attempting to reconnect %s failed.", attempt.transport->serial.c_str());
248 if (attempt.attempts_left == 0) {
249 D("transport %s exceeded the number of retry attempts. giving up on it.",
250 attempt.transport->serial.c_str());
251 remove_transport(attempt.transport);
252 continue;
253 }
254
255 std::lock_guard<std::mutex> lock(reconnect_mutex_);
256 reconnect_queue_.emplace(ReconnectAttempt{
257 attempt.transport,
258 std::chrono::steady_clock::now() + ReconnectHandler::kDefaultTimeout,
259 attempt.attempts_left - 1});
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700260 continue;
261 }
262
Josh Gaod24580d2018-08-30 11:37:00 -0700263 case ReconnectResult::Success:
264 D("reconnection to %s succeeded.", attempt.transport->serial.c_str());
265 register_transport(attempt.transport);
266 continue;
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700267
Josh Gaod24580d2018-08-30 11:37:00 -0700268 case ReconnectResult::Abort:
269 D("cancelling reconnection attempt to %s.", attempt.transport->serial.c_str());
270 remove_transport(attempt.transport);
271 continue;
272 }
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700273 }
274}
275
276static auto& reconnect_handler = *new ReconnectHandler();
277
Josh Gao5c47e9f2018-07-31 18:28:32 -0700278#endif
279
Luis Hector Chavezda74b902018-04-17 14:25:04 -0700280} // namespace
281
Josh Gaob39e4152017-08-16 16:57:01 -0700282TransportId NextTransportId() {
283 static std::atomic<TransportId> next(1);
284 return next++;
285}
286
Josh Gao3a2172b2019-03-28 15:47:44 -0700287void Connection::Reset() {
288 LOG(INFO) << "Connection::Reset(): stopping";
289 Stop();
290}
291
Josh Gao7852ca42021-06-17 04:17:25 -0700292std::string Connection::Serial() const {
293 return transport_ ? transport_->serial_name() : "<unknown>";
294}
295
Josh Gao715fe602018-02-16 13:24:58 -0800296BlockingConnectionAdapter::BlockingConnectionAdapter(std::unique_ptr<BlockingConnection> connection)
297 : underlying_(std::move(connection)) {}
298
299BlockingConnectionAdapter::~BlockingConnectionAdapter() {
Josh Gao7852ca42021-06-17 04:17:25 -0700300 LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): destructing";
Josh Gao715fe602018-02-16 13:24:58 -0800301 Stop();
302}
303
304void BlockingConnectionAdapter::Start() {
Josh Gao13781e82018-04-03 12:55:18 -0700305 std::lock_guard<std::mutex> lock(mutex_);
306 if (started_) {
Josh Gao7852ca42021-06-17 04:17:25 -0700307 LOG(FATAL) << "BlockingConnectionAdapter(" << Serial() << "): started multiple times";
Josh Gao13781e82018-04-03 12:55:18 -0700308 }
309
Joshua Duong64fab752020-01-21 13:19:42 -0800310 StartReadThread();
Josh Gao715fe602018-02-16 13:24:58 -0800311
312 write_thread_ = std::thread([this]() {
Josh Gao7852ca42021-06-17 04:17:25 -0700313 LOG(INFO) << Serial() << ": write thread spawning";
Josh Gao715fe602018-02-16 13:24:58 -0800314 while (true) {
315 std::unique_lock<std::mutex> lock(mutex_);
Josh Gao8aa57d22019-02-12 13:59:03 -0800316 ScopedLockAssertion assume_locked(mutex_);
Josh Gao13781e82018-04-03 12:55:18 -0700317 cv_.wait(lock, [this]() REQUIRES(mutex_) {
318 return this->stopped_ || !this->write_queue_.empty();
319 });
320
Josh Gao715fe602018-02-16 13:24:58 -0800321 if (this->stopped_) {
322 return;
323 }
324
325 std::unique_ptr<apacket> packet = std::move(this->write_queue_.front());
326 this->write_queue_.pop_front();
327 lock.unlock();
328
329 if (!this->underlying_->Write(packet.get())) {
330 break;
331 }
332 }
Josh Gao7852ca42021-06-17 04:17:25 -0700333 std::call_once(this->error_flag_, [this]() { transport_->HandleError("write failed"); });
Josh Gao715fe602018-02-16 13:24:58 -0800334 });
Josh Gao13781e82018-04-03 12:55:18 -0700335
336 started_ = true;
Josh Gao715fe602018-02-16 13:24:58 -0800337}
338
Joshua Duong64fab752020-01-21 13:19:42 -0800339void BlockingConnectionAdapter::StartReadThread() {
340 read_thread_ = std::thread([this]() {
Josh Gao7852ca42021-06-17 04:17:25 -0700341 LOG(INFO) << Serial() << ": read thread spawning";
Joshua Duong64fab752020-01-21 13:19:42 -0800342 while (true) {
343 auto packet = std::make_unique<apacket>();
344 if (!underlying_->Read(packet.get())) {
Josh Gao7852ca42021-06-17 04:17:25 -0700345 PLOG(INFO) << Serial() << ": read failed";
Joshua Duong64fab752020-01-21 13:19:42 -0800346 break;
347 }
348
349 bool got_stls_cmd = false;
350 if (packet->msg.command == A_STLS) {
351 got_stls_cmd = true;
352 }
353
Josh Gao7852ca42021-06-17 04:17:25 -0700354 transport_->HandleRead(std::move(packet));
Joshua Duong64fab752020-01-21 13:19:42 -0800355
356 // If we received the STLS packet, we are about to perform the TLS
357 // handshake. So this read thread must stop and resume after the
358 // handshake completes otherwise this will interfere in the process.
359 if (got_stls_cmd) {
Josh Gao7852ca42021-06-17 04:17:25 -0700360 LOG(INFO) << Serial() << ": Received STLS packet. Stopping read thread.";
Joshua Duong64fab752020-01-21 13:19:42 -0800361 return;
362 }
363 }
Josh Gao7852ca42021-06-17 04:17:25 -0700364 std::call_once(this->error_flag_, [this]() { transport_->HandleError("read failed"); });
Joshua Duong64fab752020-01-21 13:19:42 -0800365 });
366}
367
368bool BlockingConnectionAdapter::DoTlsHandshake(RSA* key, std::string* auth_key) {
369 std::lock_guard<std::mutex> lock(mutex_);
370 if (read_thread_.joinable()) {
371 read_thread_.join();
372 }
373 bool success = this->underlying_->DoTlsHandshake(key, auth_key);
374 StartReadThread();
375 return success;
376}
377
Josh Gao3a2172b2019-03-28 15:47:44 -0700378void BlockingConnectionAdapter::Reset() {
379 {
380 std::lock_guard<std::mutex> lock(mutex_);
381 if (!started_) {
Josh Gao7852ca42021-06-17 04:17:25 -0700382 LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): not started";
Josh Gao3a2172b2019-03-28 15:47:44 -0700383 return;
384 }
385
386 if (stopped_) {
Josh Gao7852ca42021-06-17 04:17:25 -0700387 LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): already stopped";
Josh Gao3a2172b2019-03-28 15:47:44 -0700388 return;
389 }
390 }
391
Josh Gao7852ca42021-06-17 04:17:25 -0700392 LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): resetting";
Josh Gao3a2172b2019-03-28 15:47:44 -0700393 this->underlying_->Reset();
394 Stop();
395}
396
Josh Gao715fe602018-02-16 13:24:58 -0800397void BlockingConnectionAdapter::Stop() {
Josh Gao13781e82018-04-03 12:55:18 -0700398 {
399 std::lock_guard<std::mutex> lock(mutex_);
400 if (!started_) {
Josh Gao7852ca42021-06-17 04:17:25 -0700401 LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): not started";
Josh Gao13781e82018-04-03 12:55:18 -0700402 return;
403 }
Josh Gao715fe602018-02-16 13:24:58 -0800404
Josh Gao13781e82018-04-03 12:55:18 -0700405 if (stopped_) {
Josh Gao7852ca42021-06-17 04:17:25 -0700406 LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): already stopped";
Josh Gao13781e82018-04-03 12:55:18 -0700407 return;
408 }
409
410 stopped_ = true;
411 }
Josh Gao715fe602018-02-16 13:24:58 -0800412
Josh Gao7852ca42021-06-17 04:17:25 -0700413 LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): stopping";
Josh Gao715fe602018-02-16 13:24:58 -0800414
415 this->underlying_->Close();
Josh Gao715fe602018-02-16 13:24:58 -0800416 this->cv_.notify_one();
Josh Gao13781e82018-04-03 12:55:18 -0700417
418 // Move the threads out into locals with the lock taken, and then unlock to let them exit.
419 std::thread read_thread;
420 std::thread write_thread;
421
422 {
423 std::lock_guard<std::mutex> lock(mutex_);
424 read_thread = std::move(read_thread_);
425 write_thread = std::move(write_thread_);
426 }
427
428 read_thread.join();
429 write_thread.join();
Josh Gao715fe602018-02-16 13:24:58 -0800430
Josh Gao7852ca42021-06-17 04:17:25 -0700431 LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): stopped";
432 std::call_once(this->error_flag_, [this]() { transport_->HandleError("requested stop"); });
Josh Gao715fe602018-02-16 13:24:58 -0800433}
434
435bool BlockingConnectionAdapter::Write(std::unique_ptr<apacket> packet) {
436 {
Josh Gao13781e82018-04-03 12:55:18 -0700437 std::lock_guard<std::mutex> lock(this->mutex_);
Josh Gao715fe602018-02-16 13:24:58 -0800438 write_queue_.emplace_back(std::move(packet));
439 }
440
441 cv_.notify_one();
442 return true;
443}
444
Joshua Duong64fab752020-01-21 13:19:42 -0800445FdConnection::FdConnection(unique_fd fd) : fd_(std::move(fd)) {}
446
447FdConnection::~FdConnection() {}
448
449bool FdConnection::DispatchRead(void* buf, size_t len) {
450 if (tls_ != nullptr) {
451 // The TlsConnection doesn't allow 0 byte reads
452 if (len == 0) {
453 return true;
454 }
455 return tls_->ReadFully(buf, len);
456 }
457
458 return ReadFdExactly(fd_.get(), buf, len);
459}
460
461bool FdConnection::DispatchWrite(void* buf, size_t len) {
462 if (tls_ != nullptr) {
463 // The TlsConnection doesn't allow 0 byte writes
464 if (len == 0) {
465 return true;
466 }
467 return tls_->WriteFully(std::string_view(reinterpret_cast<const char*>(buf), len));
468 }
469
470 return WriteFdExactly(fd_.get(), buf, len);
471}
472
Josh Gao395b86a2018-01-28 20:32:46 -0800473bool FdConnection::Read(apacket* packet) {
Joshua Duong64fab752020-01-21 13:19:42 -0800474 if (!DispatchRead(&packet->msg, sizeof(amessage))) {
Josh Gao395b86a2018-01-28 20:32:46 -0800475 D("remote local: read terminated (message)");
476 return false;
477 }
478
Josh Gao839b9322018-02-05 18:49:10 -0800479 if (packet->msg.data_length > MAX_PAYLOAD) {
Josh Gaob14756a2018-02-02 14:38:04 -0800480 D("remote local: read overflow (data length = %" PRIu32 ")", packet->msg.data_length);
481 return false;
482 }
483
Josh Gao839b9322018-02-05 18:49:10 -0800484 packet->payload.resize(packet->msg.data_length);
485
Joshua Duong64fab752020-01-21 13:19:42 -0800486 if (!DispatchRead(&packet->payload[0], packet->payload.size())) {
Josh Gao395b86a2018-01-28 20:32:46 -0800487 D("remote local: terminated (data)");
488 return false;
489 }
490
491 return true;
492}
493
494bool FdConnection::Write(apacket* packet) {
Joshua Duong64fab752020-01-21 13:19:42 -0800495 if (!DispatchWrite(&packet->msg, sizeof(packet->msg))) {
Josh Gao395b86a2018-01-28 20:32:46 -0800496 D("remote local: write terminated");
497 return false;
498 }
499
Josh Gao839b9322018-02-05 18:49:10 -0800500 if (packet->msg.data_length) {
Joshua Duong64fab752020-01-21 13:19:42 -0800501 if (!DispatchWrite(&packet->payload[0], packet->msg.data_length)) {
Josh Gao839b9322018-02-05 18:49:10 -0800502 D("remote local: write terminated");
503 return false;
504 }
505 }
506
Josh Gao395b86a2018-01-28 20:32:46 -0800507 return true;
508}
509
Joshua Duong64fab752020-01-21 13:19:42 -0800510bool FdConnection::DoTlsHandshake(RSA* key, std::string* auth_key) {
511 bssl::UniquePtr<EVP_PKEY> evp_pkey(EVP_PKEY_new());
512 if (!EVP_PKEY_set1_RSA(evp_pkey.get(), key)) {
513 LOG(ERROR) << "EVP_PKEY_set1_RSA failed";
514 return false;
515 }
516 auto x509 = GenerateX509Certificate(evp_pkey.get());
517 auto x509_str = X509ToPEMString(x509.get());
518 auto evp_str = Key::ToPEMString(evp_pkey.get());
Joshua Duongdd19e862020-03-24 09:50:59 -0700519
Yurii Zubrytskyi3c0574f2020-03-26 18:16:36 -0700520 int osh = cast_handle_to_int(adb_get_os_handle(fd_));
Joshua Duong64fab752020-01-21 13:19:42 -0800521#if ADB_HOST
Joshua Duong77b8ff32020-04-16 15:58:19 -0700522 tls_ = TlsConnection::Create(TlsConnection::Role::Client, x509_str, evp_str, osh);
Joshua Duong64fab752020-01-21 13:19:42 -0800523#else
Joshua Duong77b8ff32020-04-16 15:58:19 -0700524 tls_ = TlsConnection::Create(TlsConnection::Role::Server, x509_str, evp_str, osh);
Joshua Duong64fab752020-01-21 13:19:42 -0800525#endif
Joshua Duong64fab752020-01-21 13:19:42 -0800526 CHECK(tls_);
527#if ADB_HOST
528 // TLS 1.3 gives the client no message if the server rejected the
529 // certificate. This will enable a check in the tls connection to check
530 // whether the client certificate got rejected. Note that this assumes
531 // that, on handshake success, the server speaks first.
532 tls_->EnableClientPostHandshakeCheck(true);
533 // Add callback to set the certificate when server issues the
534 // CertificateRequest.
535 tls_->SetCertificateCallback(adb_tls_set_certificate);
536 // Allow any server certificate
537 tls_->SetCertVerifyCallback([](X509_STORE_CTX*) { return 1; });
538#else
539 // Add callback to check certificate against a list of known public keys
540 tls_->SetCertVerifyCallback(
541 [auth_key](X509_STORE_CTX* ctx) { return adbd_tls_verify_cert(ctx, auth_key); });
542 // Add the list of allowed client CA issuers
543 auto ca_list = adbd_tls_client_ca_list();
544 tls_->SetClientCAList(ca_list.get());
545#endif
546
547 auto err = tls_->DoHandshake();
548 if (err == TlsError::Success) {
549 return true;
550 }
551
552 tls_.reset();
553 return false;
554}
555
Josh Gao395b86a2018-01-28 20:32:46 -0800556void FdConnection::Close() {
557 adb_shutdown(fd_.get());
558 fd_.reset();
559}
560
Josh Gao67ac3792016-10-06 13:31:44 -0700561void send_packet(apacket* p, atransport* t) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800562 p->msg.magic = p->msg.command ^ 0xffffffff;
Tim Murrayee7b44d2017-12-07 11:40:00 -0800563 // compute a checksum for connection/auth packets for compatibility reasons
564 if (t->get_protocol_version() >= A_VERSION_SKIP_CHECKSUM) {
565 p->msg.data_check = 0;
566 } else {
567 p->msg.data_check = calculate_apacket_checksum(p);
568 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800569
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700570 VLOG(TRANSPORT) << dump_packet(t->serial.c_str(), "to remote", p);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800571
Yi Kong86e67182018-07-13 18:15:16 -0700572 if (t == nullptr) {
Elliott Hughese64126b2018-10-19 13:59:44 -0700573 LOG(FATAL) << "Transport is null";
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800574 }
575
Josh Gao715fe602018-02-16 13:24:58 -0800576 if (t->Write(p) != 0) {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700577 D("%s: failed to enqueue packet, closing transport", t->serial.c_str());
Josh Gao715fe602018-02-16 13:24:58 -0800578 t->Kick();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800579 }
580}
581
Josh Gao3a2172b2019-03-28 15:47:44 -0700582void kick_transport(atransport* t, bool reset) {
Josh Gaoaaa82f72017-08-17 13:50:51 -0700583 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Yabin Cuid78ed222016-04-05 13:50:44 -0700584 // As kick_transport() can be called from threads without guarantee that t is valid,
585 // check if the transport is in transport_list first.
Josh Gaob39e4152017-08-16 16:57:01 -0700586 //
587 // TODO(jmgao): WTF? Is this actually true?
Yabin Cuid78ed222016-04-05 13:50:44 -0700588 if (std::find(transport_list.begin(), transport_list.end(), t) != transport_list.end()) {
Josh Gao3a2172b2019-03-28 15:47:44 -0700589 if (reset) {
590 t->Reset();
591 } else {
592 t->Kick();
593 }
Yabin Cuid78ed222016-04-05 13:50:44 -0700594 }
Josh Gao13cb8c02018-08-10 14:44:54 -0700595
596#if ADB_HOST
597 reconnect_handler.CheckForKicked();
598#endif
Yabin Cui4d64fd82015-08-27 12:03:11 -0700599}
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800600
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800601#if ADB_HOST
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800602
603/* this adds support required by the 'track-devices' service.
604 * this is used to send the content of "list_transport" to any
605 * number of client connections that want it through a single
606 * live TCP connection
607 */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800608struct device_tracker {
Josh Gao0d6aa992016-11-22 14:32:34 -0800609 asocket socket;
Josh Gao5cb76ce2018-02-12 17:24:00 -0800610 bool update_needed = false;
Fabien Sanglard3d155b62023-11-30 14:52:40 -0800611 TrackerOutputType output_type = SHORT_TEXT;
Josh Gao5cb76ce2018-02-12 17:24:00 -0800612 device_tracker* next = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800613};
614
615/* linked list of all device trackers */
Josh Gao0d6aa992016-11-22 14:32:34 -0800616static device_tracker* device_tracker_list;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800617
Josh Gao0d6aa992016-11-22 14:32:34 -0800618static void device_tracker_remove(device_tracker* tracker) {
619 device_tracker** pnode = &device_tracker_list;
620 device_tracker* node = *pnode;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800621
Josh Gaoaaa82f72017-08-17 13:50:51 -0700622 std::lock_guard<std::recursive_mutex> lock(transport_lock);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800623 while (node) {
624 if (node == tracker) {
625 *pnode = node->next;
626 break;
627 }
628 pnode = &node->next;
Josh Gao0d6aa992016-11-22 14:32:34 -0800629 node = *pnode;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800630 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800631}
632
Josh Gao0d6aa992016-11-22 14:32:34 -0800633static void device_tracker_close(asocket* socket) {
634 device_tracker* tracker = (device_tracker*)socket;
635 asocket* peer = socket->peer;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800636
Josh Gao0d6aa992016-11-22 14:32:34 -0800637 D("device tracker %p removed", tracker);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800638 if (peer) {
Yi Kong86e67182018-07-13 18:15:16 -0700639 peer->peer = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800640 peer->close(peer);
641 }
642 device_tracker_remove(tracker);
Josh Gao5cb76ce2018-02-12 17:24:00 -0800643 delete tracker;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800644}
645
Josh Gaocd2a5292018-03-07 16:52:28 -0800646static int device_tracker_enqueue(asocket* socket, apacket::payload_type) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800647 /* you can't read from a device tracker, close immediately */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800648 device_tracker_close(socket);
649 return -1;
650}
651
Elliott Hughes88b4c852015-04-30 17:32:03 -0700652static int device_tracker_send(device_tracker* tracker, const std::string& string) {
Elliott Hughes88b4c852015-04-30 17:32:03 -0700653 asocket* peer = tracker->socket.peer;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800654
Josh Gaocd2a5292018-03-07 16:52:28 -0800655 apacket::payload_type data;
Josh Gaoa7d9d712018-02-01 13:17:50 -0800656 data.resize(4 + string.size());
657 char buf[5];
658 snprintf(buf, sizeof(buf), "%04x", static_cast<int>(string.size()));
659 memcpy(&data[0], buf, 4);
660 memcpy(&data[4], string.data(), string.size());
661 return peer->enqueue(peer, std::move(data));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800662}
663
Elliott Hughes88b4c852015-04-30 17:32:03 -0700664static void device_tracker_ready(asocket* socket) {
665 device_tracker* tracker = reinterpret_cast<device_tracker*>(socket);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800666
Elliott Hughes88b4c852015-04-30 17:32:03 -0700667 // We want to send the device list when the tracker connects
668 // for the first time, even if no update occurred.
Josh Gao32124632017-08-14 18:57:54 -0700669 if (tracker->update_needed) {
670 tracker->update_needed = false;
Fabien Sanglard3d155b62023-11-30 14:52:40 -0800671 device_tracker_send(tracker, list_transports(tracker->output_type));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800672 }
673}
674
Fabien Sanglard3d155b62023-11-30 14:52:40 -0800675asocket* create_device_tracker(TrackerOutputType output_type) {
Josh Gao5cb76ce2018-02-12 17:24:00 -0800676 device_tracker* tracker = new device_tracker();
Elliott Hughese64126b2018-10-19 13:59:44 -0700677 if (tracker == nullptr) LOG(FATAL) << "cannot allocate device tracker";
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800678
Josh Gao0d6aa992016-11-22 14:32:34 -0800679 D("device tracker %p created", tracker);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800680
681 tracker->socket.enqueue = device_tracker_enqueue;
Josh Gao0d6aa992016-11-22 14:32:34 -0800682 tracker->socket.ready = device_tracker_ready;
683 tracker->socket.close = device_tracker_close;
Josh Gao32124632017-08-14 18:57:54 -0700684 tracker->update_needed = true;
Fabien Sanglard3d155b62023-11-30 14:52:40 -0800685 tracker->output_type = output_type;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800686
Josh Gao0d6aa992016-11-22 14:32:34 -0800687 tracker->next = device_tracker_list;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800688 device_tracker_list = tracker;
689
690 return &tracker->socket;
691}
692
Josh Gao1e3bf732017-05-03 22:37:10 -0700693// Check if all of the USB transports are connected.
694bool iterate_transports(std::function<bool(const atransport*)> fn) {
Josh Gaoaaa82f72017-08-17 13:50:51 -0700695 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gao1e3bf732017-05-03 22:37:10 -0700696 for (const auto& t : transport_list) {
697 if (!fn(t)) {
698 return false;
699 }
700 }
701 for (const auto& t : pending_list) {
702 if (!fn(t)) {
703 return false;
704 }
705 }
706 return true;
707}
708
Elliott Hughes88b4c852015-04-30 17:32:03 -0700709// Call this function each time the transport list has changed.
710void update_transports() {
Josh Gao1e3bf732017-05-03 22:37:10 -0700711 update_transport_status();
712
713 // Notify `adb track-devices` clients.
Elliott Hughes88b4c852015-04-30 17:32:03 -0700714 device_tracker* tracker = device_tracker_list;
715 while (tracker != nullptr) {
716 device_tracker* next = tracker->next;
717 // This may destroy the tracker if the connection is closed.
Fabien Sanglard3d155b62023-11-30 14:52:40 -0800718 device_tracker_send(tracker, list_transports(tracker->output_type));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800719 tracker = next;
720 }
721}
Elliott Hughes88b4c852015-04-30 17:32:03 -0700722
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800723#else
Elliott Hughes88b4c852015-04-30 17:32:03 -0700724
725void update_transports() {
726 // Nothing to do on the device side.
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800727}
Elliott Hughes88b4c852015-04-30 17:32:03 -0700728
Josh Gao0d6aa992016-11-22 14:32:34 -0800729#endif // ADB_HOST
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800730
Josh Gao8e7c9722021-06-17 04:19:45 -0700731#if ADB_HOST
Shaju Mathew36c85202023-06-13 08:00:16 -0700732static bool usb_devices_start_detached() {
Josh Gao8e7c9722021-06-17 04:19:45 -0700733 static const char* env = getenv("ADB_LIBUSB_START_DETACHED");
734 static bool result = env && strcmp("1", env) == 0;
Fabien Sanglard7799b4b2024-07-03 13:58:52 -0700735 return is_libusb_enabled() && result;
Josh Gao8e7c9722021-06-17 04:19:45 -0700736}
Shaju Mathew36c85202023-06-13 08:00:16 -0700737#endif
Josh Gao8e7c9722021-06-17 04:19:45 -0700738
Fabien Sanglard4292ce52023-10-19 18:01:07 -0700739static void fdevent_unregister_transport(atransport* t) {
740 D("transport: %s deleting", t->serial.c_str());
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800741
Fabien Sanglard4292ce52023-10-19 18:01:07 -0700742 {
743 std::lock_guard<std::recursive_mutex> lock(transport_lock);
744 transport_list.remove(t);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800745 }
746
Fabien Sanglard4292ce52023-10-19 18:01:07 -0700747 delete t;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800748
Fabien Sanglard4292ce52023-10-19 18:01:07 -0700749 update_transports();
750}
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800751
Fabien Sanglard4292ce52023-10-19 18:01:07 -0700752static void fdevent_register_transport(atransport* t) {
Mike Lockwoode45583f2009-08-08 12:37:44 -0400753 /* don't create transport threads for inaccessible devices */
Yabin Cui3cf1b362017-03-10 16:01:01 -0800754 if (t->GetConnectionState() != kCsNoPerm) {
Josh Gao7852ca42021-06-17 04:17:25 -0700755 t->connection()->SetTransport(t);
Josh Gao8e7c9722021-06-17 04:19:45 -0700756
Shaju Mathew36c85202023-06-13 08:00:16 -0700757 if (t->type == kTransportUsb
758#if ADB_HOST
759 && usb_devices_start_detached() // -d setting propagated from the
760 // host device, hence n/a on-device.
761#endif
762 ) {
Josh Gao8e7c9722021-06-17 04:19:45 -0700763 t->SetConnectionState(kCsDetached);
764 } else {
765 t->connection()->Start();
Josh Gao715fe602018-02-16 13:24:58 -0800766#if ADB_HOST
Josh Gao8e7c9722021-06-17 04:19:45 -0700767 send_connect(t);
Josh Gao715fe602018-02-16 13:24:58 -0800768#endif
Josh Gao8e7c9722021-06-17 04:19:45 -0700769 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800770 }
771
Josh Gaoe7daf572016-09-21 12:37:10 -0700772 {
Josh Gaoaaa82f72017-08-17 13:50:51 -0700773 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700774 auto it = std::find(pending_list.begin(), pending_list.end(), t);
775 if (it != pending_list.end()) {
776 pending_list.remove(t);
777 transport_list.push_front(t);
778 }
Josh Gaoe7daf572016-09-21 12:37:10 -0700779 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800780
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800781 update_transports();
782}
783
Josh Gao5c47e9f2018-07-31 18:28:32 -0700784#if ADB_HOST
Elliott Hughesa8ab5ce2024-06-28 12:10:09 +0000785void init_reconnect_handler() {
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700786 reconnect_handler.Start();
787}
Josh Gao5c47e9f2018-07-31 18:28:32 -0700788#endif
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700789
Josh Gao165460f2017-05-09 13:43:35 -0700790void kick_all_transports() {
Josh Gao5c47e9f2018-07-31 18:28:32 -0700791#if ADB_HOST
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700792 reconnect_handler.Stop();
Josh Gao5c47e9f2018-07-31 18:28:32 -0700793#endif
Josh Gao165460f2017-05-09 13:43:35 -0700794 // To avoid only writing part of a packet to a transport after exit, kick all transports.
Josh Gaoaaa82f72017-08-17 13:50:51 -0700795 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gao165460f2017-05-09 13:43:35 -0700796 for (auto t : transport_list) {
797 t->Kick();
798 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800799}
800
Joshua Duong64fab752020-01-21 13:19:42 -0800801void kick_all_tcp_tls_transports() {
802 std::lock_guard<std::recursive_mutex> lock(transport_lock);
803 for (auto t : transport_list) {
804 if (t->IsTcpDevice() && t->use_tls) {
805 t->Kick();
806 }
807 }
808}
809
810#if !ADB_HOST
811void kick_all_transports_by_auth_key(std::string_view auth_key) {
812 std::lock_guard<std::recursive_mutex> lock(transport_lock);
813 for (auto t : transport_list) {
814 if (auth_key == t->auth_key) {
815 t->Kick();
816 }
817 }
818}
819#endif
820
Josh Gao3a34bc52018-10-11 16:33:05 -0700821void register_transport(atransport* transport) {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700822 D("transport: %s registered", transport->serial.c_str());
Fabien Sanglard4292ce52023-10-19 18:01:07 -0700823 fdevent_run_on_looper([=]() { fdevent_register_transport(transport); });
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800824}
825
Josh Gao0d6aa992016-11-22 14:32:34 -0800826static void remove_transport(atransport* transport) {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700827 D("transport: %s removed", transport->serial.c_str());
Fabien Sanglard4292ce52023-10-19 18:01:07 -0700828 fdevent_run_on_looper([=]() { fdevent_unregister_transport(transport); });
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800829}
830
Josh Gao14ed9f92019-12-09 13:45:31 -0800831static void transport_destroy(atransport* t) {
Shaju Mathew705fa1c2022-12-31 19:36:54 -0800832 fdevent_check_looper();
Yabin Cui4d64fd82015-08-27 12:03:11 -0700833 CHECK(t != nullptr);
Josh Gaoe7daf572016-09-21 12:37:10 -0700834
Josh Gao4d299742017-09-13 13:40:57 -0700835 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gao14ed9f92019-12-09 13:45:31 -0800836 LOG(INFO) << "destroying transport " << t->serial_name();
837 t->connection()->Stop();
Josh Gao5c47e9f2018-07-31 18:28:32 -0700838#if ADB_HOST
Josh Gao14ed9f92019-12-09 13:45:31 -0800839 if (t->IsTcpDevice() && !t->kicked()) {
840 D("transport: %s destroy (attempting reconnection)", t->serial.c_str());
Josh Gaoeb656522018-12-04 01:07:50 -0800841
Josh Gao14ed9f92019-12-09 13:45:31 -0800842 // We need to clear the transport's keys, so that on the next connection, it tries
843 // again from the beginning.
844 t->ResetKeys();
845 reconnect_handler.TrackTransport(t);
846 return;
847 }
Josh Gao5c47e9f2018-07-31 18:28:32 -0700848#endif
849
Josh Gao14ed9f92019-12-09 13:45:31 -0800850 D("transport: %s destroy (kicking and closing)", t->serial.c_str());
851 remove_transport(t);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800852}
853
Josh Gao65d18e22020-04-22 20:57:26 -0700854#if ADB_HOST
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700855static int qual_match(const std::string& to_test, const char* prefix, const std::string& qual,
Josh Gao0d6aa992016-11-22 14:32:34 -0800856 bool sanitize_qual) {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700857 if (to_test.empty()) /* Return true if both the qual and to_test are empty strings. */
858 return qual.empty();
Scott Anderson27042382012-05-30 18:11:27 -0700859
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700860 if (qual.empty()) return 0;
Scott Anderson27042382012-05-30 18:11:27 -0700861
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700862 const char* ptr = to_test.c_str();
Scott Anderson27042382012-05-30 18:11:27 -0700863 if (prefix) {
864 while (*prefix) {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700865 if (*prefix++ != *ptr++) return 0;
Scott Anderson27042382012-05-30 18:11:27 -0700866 }
867 }
868
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700869 for (char ch : qual) {
Josh Gao0d6aa992016-11-22 14:32:34 -0800870 if (sanitize_qual && !isalnum(ch)) ch = '_';
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700871 if (ch != *ptr++) return 0;
Scott Anderson27042382012-05-30 18:11:27 -0700872 }
873
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700874 /* Everything matched so far. Return true if *ptr is a NUL. */
875 return !*ptr;
Scott Anderson27042382012-05-30 18:11:27 -0700876}
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800877
Vince Harron5703eb32021-11-12 12:40:58 -0800878// Contains either a device serial string or a USB device address like "usb:2-6"
879const char* __transport_server_one_device = nullptr;
880
881void transport_set_one_device(const char* adb_one_device) {
882 __transport_server_one_device = adb_one_device;
883}
884
885const char* transport_get_one_device() {
886 return __transport_server_one_device;
887}
888
889bool transport_server_owns_device(std::string_view serial) {
890 if (!__transport_server_one_device) {
891 // If the server doesn't own one device, server owns all devices.
892 return true;
893 }
894 return serial.compare(__transport_server_one_device) == 0;
895}
896
897bool transport_server_owns_device(std::string_view dev_path, std::string_view serial) {
898 if (!__transport_server_one_device) {
899 // If the server doesn't own one device, server owns all devices.
900 return true;
901 }
902 return serial.compare(__transport_server_one_device) == 0 ||
903 dev_path.compare(__transport_server_one_device) == 0;
904}
905
Josh Gaob39e4152017-08-16 16:57:01 -0700906atransport* acquire_one_transport(TransportType type, const char* serial, TransportId transport_id,
907 bool* is_ambiguous, std::string* error_out,
908 bool accept_any_state) {
Elliott Hughes67943d12015-10-07 14:55:10 -0700909 atransport* result = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800910
Josh Gaob39e4152017-08-16 16:57:01 -0700911 if (transport_id != 0) {
Josh Gao7852ca42021-06-17 04:17:25 -0700912 *error_out = android::base::StringPrintf("no device with transport id '%" PRIu64 "'",
913 transport_id);
Josh Gaob39e4152017-08-16 16:57:01 -0700914 } else if (serial) {
Elliott Hughes67943d12015-10-07 14:55:10 -0700915 *error_out = android::base::StringPrintf("device '%s' not found", serial);
916 } else if (type == kTransportLocal) {
917 *error_out = "no emulators found";
918 } else if (type == kTransportAny) {
919 *error_out = "no devices/emulators found";
920 } else {
921 *error_out = "no devices found";
922 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800923
Josh Gaoaaa82f72017-08-17 13:50:51 -0700924 std::unique_lock<std::recursive_mutex> lock(transport_lock);
Elliott Hughes67943d12015-10-07 14:55:10 -0700925 for (const auto& t : transport_list) {
Yabin Cui3cf1b362017-03-10 16:01:01 -0800926 if (t->GetConnectionState() == kCsNoPerm) {
David Pursell6e5c7eb2015-12-02 15:14:31 -0800927 *error_out = UsbNoPermissionsLongHelpText();
Mike Lockwoodadc16b32009-08-08 13:53:16 -0400928 continue;
929 }
Mike Lockwoode45583f2009-08-08 12:37:44 -0400930
Josh Gaob39e4152017-08-16 16:57:01 -0700931 if (transport_id) {
932 if (t->id == transport_id) {
933 result = t;
934 break;
935 }
936 } else if (serial) {
David Pursellc929c6f2016-03-01 08:58:26 -0800937 if (t->MatchesTarget(serial)) {
Scott Anderson27042382012-05-30 18:11:27 -0700938 if (result) {
Elliott Hughes73abffa2022-06-09 16:30:24 +0000939 *error_out = "more than one device with serial "s + serial;
Elliott Hughes67943d12015-10-07 14:55:10 -0700940 if (is_ambiguous) *is_ambiguous = true;
941 result = nullptr;
Scott Anderson27042382012-05-30 18:11:27 -0700942 break;
943 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800944 result = t;
Scott Anderson6dfaf4b2012-04-20 11:21:14 -0700945 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800946 } else {
Elliott Hughes3aec2ba2015-05-05 13:10:43 -0700947 if (type == kTransportUsb && t->type == kTransportUsb) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800948 if (result) {
Elliott Hughes73abffa2022-06-09 16:30:24 +0000949 *error_out = "more than one USB device";
Elliott Hughes67943d12015-10-07 14:55:10 -0700950 if (is_ambiguous) *is_ambiguous = true;
951 result = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800952 break;
953 }
954 result = t;
Elliott Hughes3aec2ba2015-05-05 13:10:43 -0700955 } else if (type == kTransportLocal && t->type == kTransportLocal) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800956 if (result) {
Elliott Hughes24f52762015-06-23 13:00:32 -0700957 *error_out = "more than one emulator";
Elliott Hughes67943d12015-10-07 14:55:10 -0700958 if (is_ambiguous) *is_ambiguous = true;
959 result = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800960 break;
961 }
962 result = t;
Elliott Hughes3aec2ba2015-05-05 13:10:43 -0700963 } else if (type == kTransportAny) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800964 if (result) {
Elliott Hughes24f52762015-06-23 13:00:32 -0700965 *error_out = "more than one device/emulator";
Elliott Hughes67943d12015-10-07 14:55:10 -0700966 if (is_ambiguous) *is_ambiguous = true;
967 result = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800968 break;
969 }
970 result = t;
971 }
972 }
973 }
Josh Gaoe7daf572016-09-21 12:37:10 -0700974 lock.unlock();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800975
Josh Gao7a7c5cb2018-05-04 16:04:49 -0700976 if (result && !accept_any_state) {
977 // The caller requires an active transport.
978 // Make sure that we're actually connected.
979 ConnectionState state = result->GetConnectionState();
980 switch (state) {
981 case kCsConnecting:
982 *error_out = "device still connecting";
983 result = nullptr;
984 break;
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700985
Josh Gao7a7c5cb2018-05-04 16:04:49 -0700986 case kCsAuthorizing:
987 *error_out = "device still authorizing";
988 result = nullptr;
989 break;
990
991 case kCsUnauthorized: {
992 *error_out = "device unauthorized.\n";
993 char* ADB_VENDOR_KEYS = getenv("ADB_VENDOR_KEYS");
994 *error_out += "This adb server's $ADB_VENDOR_KEYS is ";
995 *error_out += ADB_VENDOR_KEYS ? ADB_VENDOR_KEYS : "not set";
996 *error_out += "\n";
997 *error_out += "Try 'adb kill-server' if that seems wrong.\n";
998 *error_out += "Otherwise check for a confirmation dialog on your device.";
999 result = nullptr;
1000 break;
1001 }
1002
1003 case kCsOffline:
1004 *error_out = "device offline";
1005 result = nullptr;
1006 break;
1007
1008 default:
1009 break;
1010 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001011 }
1012
1013 if (result) {
Elliott Hughes24f52762015-06-23 13:00:32 -07001014 *error_out = "success";
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001015 }
1016
1017 return result;
1018}
1019
Luis Hector Chavezda74b902018-04-17 14:25:04 -07001020bool ConnectionWaitable::WaitForConnection(std::chrono::milliseconds timeout) {
1021 std::unique_lock<std::mutex> lock(mutex_);
Josh Gao8aa57d22019-02-12 13:59:03 -08001022 ScopedLockAssertion assume_locked(mutex_);
Luis Hector Chavezda74b902018-04-17 14:25:04 -07001023 return cv_.wait_for(lock, timeout, [&]() REQUIRES(mutex_) {
1024 return connection_established_ready_;
1025 }) && connection_established_;
1026}
1027
1028void ConnectionWaitable::SetConnectionEstablished(bool success) {
1029 {
1030 std::lock_guard<std::mutex> lock(mutex_);
1031 if (connection_established_ready_) return;
1032 connection_established_ready_ = true;
1033 connection_established_ = success;
1034 D("connection established with %d", success);
1035 }
1036 cv_.notify_one();
1037}
Josh Gao65d18e22020-04-22 20:57:26 -07001038#endif
Luis Hector Chavezda74b902018-04-17 14:25:04 -07001039
1040atransport::~atransport() {
Josh Gao65d18e22020-04-22 20:57:26 -07001041#if ADB_HOST
Luis Hector Chavezda74b902018-04-17 14:25:04 -07001042 // If the connection callback had not been run before, run it now.
1043 SetConnectionEstablished(false);
Josh Gao65d18e22020-04-22 20:57:26 -07001044#endif
Luis Hector Chavezda74b902018-04-17 14:25:04 -07001045}
1046
Yabin Cui3cf1b362017-03-10 16:01:01 -08001047int atransport::Write(apacket* p) {
Luis Hector Chavez3c7881d2018-04-25 08:56:41 -07001048 return this->connection()->Write(std::unique_ptr<apacket>(p)) ? 0 : -1;
Yabin Cui3cf1b362017-03-10 16:01:01 -08001049}
1050
Josh Gao3a2172b2019-03-28 15:47:44 -07001051void atransport::Reset() {
1052 if (!kicked_.exchange(true)) {
1053 LOG(INFO) << "resetting transport " << this << " " << this->serial;
1054 this->connection()->Reset();
1055 }
1056}
1057
Yabin Cuif2a9f9b2016-04-18 11:22:34 -07001058void atransport::Kick() {
Luis Hector Chavez0aeda102018-04-20 10:31:29 -07001059 if (!kicked_.exchange(true)) {
Josh Gao3a2172b2019-03-28 15:47:44 -07001060 LOG(INFO) << "kicking transport " << this << " " << this->serial;
Luis Hector Chavez3c7881d2018-04-25 08:56:41 -07001061 this->connection()->Stop();
Yabin Cuif2a9f9b2016-04-18 11:22:34 -07001062 }
1063}
1064
Yabin Cui3cf1b362017-03-10 16:01:01 -08001065ConnectionState atransport::GetConnectionState() const {
1066 return connection_state_;
1067}
1068
1069void atransport::SetConnectionState(ConnectionState state) {
Shaju Mathew705fa1c2022-12-31 19:36:54 -08001070 fdevent_check_looper();
Yabin Cui3cf1b362017-03-10 16:01:01 -08001071 connection_state_ = state;
Joshua Duongccde5202021-03-08 15:01:48 -08001072 update_transports();
Yabin Cui3cf1b362017-03-10 16:01:01 -08001073}
1074
Josh Gao8e7c9722021-06-17 04:19:45 -07001075#if ADB_HOST
1076bool atransport::Attach(std::string* error) {
1077 D("%s: attach", serial.c_str());
Shaju Mathew705fa1c2022-12-31 19:36:54 -08001078 fdevent_check_looper();
Josh Gao8e7c9722021-06-17 04:19:45 -07001079
Fabien Sanglard7799b4b2024-07-03 13:58:52 -07001080 if (!is_libusb_enabled()) {
Josh Gao8e7c9722021-06-17 04:19:45 -07001081 *error = "attach/detach only implemented for libusb backend";
1082 return false;
1083 }
1084
1085 if (GetConnectionState() != ConnectionState::kCsDetached) {
1086 *error = android::base::StringPrintf("transport %s is not detached", serial.c_str());
1087 return false;
1088 }
1089
1090 ResetKeys();
1091
1092 {
1093 std::lock_guard<std::mutex> lock(mutex_);
1094 if (!connection_->Attach(error)) {
1095 return false;
1096 }
1097 }
1098
1099 send_connect(this);
1100 return true;
1101}
1102
1103bool atransport::Detach(std::string* error) {
1104 D("%s: detach", serial.c_str());
Shaju Mathew705fa1c2022-12-31 19:36:54 -08001105 fdevent_check_looper();
Josh Gao8e7c9722021-06-17 04:19:45 -07001106
Fabien Sanglard7799b4b2024-07-03 13:58:52 -07001107 if (!is_libusb_enabled()) {
Josh Gao8e7c9722021-06-17 04:19:45 -07001108 *error = "attach/detach only implemented for libusb backend";
1109 return false;
1110 }
1111
1112 if (GetConnectionState() == ConnectionState::kCsDetached) {
1113 *error = android::base::StringPrintf("transport %s is already detached", serial.c_str());
1114 return false;
1115 }
1116
1117 handle_offline(this);
1118
1119 {
1120 std::lock_guard<std::mutex> lock(mutex_);
1121 if (!connection_->Detach(error)) {
1122 return false;
1123 }
1124 }
1125
1126 this->SetConnectionState(kCsDetached);
1127 return true;
1128}
Shaju Mathew36c85202023-06-13 08:00:16 -07001129#endif // ADB_HOST
Josh Gao8e7c9722021-06-17 04:19:45 -07001130
Josh Gaof2d6af52021-04-27 20:32:02 -07001131void atransport::SetConnection(std::shared_ptr<Connection> connection) {
Luis Hector Chavez3c7881d2018-04-25 08:56:41 -07001132 std::lock_guard<std::mutex> lock(mutex_);
1133 connection_ = std::shared_ptr<Connection>(std::move(connection));
1134}
1135
Josh Gao7852ca42021-06-17 04:17:25 -07001136bool atransport::HandleRead(std::unique_ptr<apacket> p) {
1137 if (!check_header(p.get(), this)) {
1138 D("%s: remote read: bad header", serial.c_str());
1139 return false;
1140 }
1141
1142 VLOG(TRANSPORT) << dump_packet(serial.c_str(), "from remote", p.get());
1143 apacket* packet = p.release();
1144
Shaju Mathew705fa1c2022-12-31 19:36:54 -08001145 // This needs to run on the looper thread since the associated fdevent
Shaju Mathew13508c12022-06-25 14:57:31 +00001146 // message pump exists in that context.
Shaju Mathew705fa1c2022-12-31 19:36:54 -08001147 fdevent_run_on_looper([packet, this]() { handle_packet(packet, this); });
Shaju Mathew13508c12022-06-25 14:57:31 +00001148
Josh Gao7852ca42021-06-17 04:17:25 -07001149 return true;
1150}
1151
1152void atransport::HandleError(const std::string& error) {
1153 LOG(INFO) << serial_name() << ": connection terminated: " << error;
Shaju Mathew705fa1c2022-12-31 19:36:54 -08001154 fdevent_run_on_looper([this]() {
Josh Gao7852ca42021-06-17 04:17:25 -07001155 handle_offline(this);
1156 transport_destroy(this);
1157 });
1158}
1159
Tamas Berghammera1c60c02015-07-13 19:12:28 +01001160void atransport::update_version(int version, size_t payload) {
1161 protocol_version = std::min(version, A_VERSION);
1162 max_payload = std::min(payload, MAX_PAYLOAD);
1163}
1164
1165int atransport::get_protocol_version() const {
1166 return protocol_version;
1167}
1168
Joshua Duong64fab752020-01-21 13:19:42 -08001169int atransport::get_tls_version() const {
1170 return tls_version;
1171}
1172
Tamas Berghammera1c60c02015-07-13 19:12:28 +01001173size_t atransport::get_max_payload() const {
1174 return max_payload;
1175}
1176
Josh Gaobd1f3002021-12-29 21:15:12 -08001177#if ADB_HOST
1178static bool delayed_ack_enabled() {
1179 static const char* env = getenv("ADB_DELAYED_ACK");
1180 static bool result = env && strcmp(env, "1") == 0;
1181 return result;
1182}
1183#endif
1184
Dan Albertbe8e54b2015-05-18 13:06:53 -07001185const FeatureSet& supported_features() {
Josh Gaobd1f3002021-12-29 21:15:12 -08001186 static const android::base::NoDestructor<FeatureSet> features([]() {
1187 // Increment ADB_SERVER_VERSION when adding a feature that adbd needs
1188 // to know about. Otherwise, the client can be stuck running an old
1189 // version of the server even after upgrading their copy of adb.
1190 // (http://b/24370690)
1191
1192 // clang-format off
1193 FeatureSet result {
1194 kFeatureShell2,
1195 kFeatureCmd,
1196 kFeatureStat2,
1197 kFeatureLs2,
1198 kFeatureFixedPushMkdir,
1199 kFeatureApex,
1200 kFeatureAbb,
1201 kFeatureFixedPushSymlinkTimestamp,
1202 kFeatureAbbExec,
1203 kFeatureRemountShell,
1204 kFeatureTrackApp,
1205 kFeatureSendRecv2,
1206 kFeatureSendRecv2Brotli,
1207 kFeatureSendRecv2LZ4,
1208 kFeatureSendRecv2Zstd,
1209 kFeatureSendRecv2DryRunSend,
1210 kFeatureOpenscreenMdns,
Fabien Sanglard3d155b62023-11-30 14:52:40 -08001211 kFeatureDeviceTrackerProtoFormat,
Octavian Purdila4b4421d2024-04-03 23:13:14 -07001212 kFeatureDevRaw,
Fabien Sanglard15335e02024-03-05 21:33:44 +00001213 kFeatureAppInfo,
Fabien Sanglard05789412024-05-30 23:00:18 -07001214 kFeatureServerStatus,
Yurii Zubrytskyi816c2d22020-03-26 18:19:28 -07001215 };
Josh Gaobd1f3002021-12-29 21:15:12 -08001216 // clang-format on
1217
1218#if ADB_HOST
1219 if (delayed_ack_enabled()) {
1220 result.push_back(kFeatureDelayedAck);
1221 }
1222#else
1223 result.push_back(kFeatureDelayedAck);
1224#endif
1225 return result;
Yurii Zubrytskyi816c2d22020-03-26 18:19:28 -07001226 }());
David Pursella07dbad2015-09-22 10:43:08 -07001227
1228 return *features;
1229}
1230
1231std::string FeatureSetToString(const FeatureSet& features) {
Elliott Hughesc3462f42018-09-05 12:13:11 -07001232 return android::base::Join(features, ',');
David Pursella07dbad2015-09-22 10:43:08 -07001233}
1234
1235FeatureSet StringToFeatureSet(const std::string& features_string) {
David Pursell3d9072b2015-09-25 13:04:21 -07001236 if (features_string.empty()) {
1237 return FeatureSet();
1238 }
1239
Yurii Zubrytskyi816c2d22020-03-26 18:19:28 -07001240 return android::base::Split(features_string, ",");
1241}
1242
1243template <class Range, class Value>
1244static bool contains(const Range& r, const Value& v) {
1245 return std::find(std::begin(r), std::end(r), v) != std::end(r);
Dan Albertbe8e54b2015-05-18 13:06:53 -07001246}
1247
David Pursell22fc5e92015-09-30 13:35:42 -07001248bool CanUseFeature(const FeatureSet& feature_set, const std::string& feature) {
Yurii Zubrytskyi816c2d22020-03-26 18:19:28 -07001249 return contains(feature_set, feature) && contains(supported_features(), feature);
David Pursell22fc5e92015-09-30 13:35:42 -07001250}
1251
Dan Albertbe8e54b2015-05-18 13:06:53 -07001252bool atransport::has_feature(const std::string& feature) const {
Yurii Zubrytskyi816c2d22020-03-26 18:19:28 -07001253 return contains(features_, feature);
Dan Albertbe8e54b2015-05-18 13:06:53 -07001254}
1255
David Pursella07dbad2015-09-22 10:43:08 -07001256void atransport::SetFeatures(const std::string& features_string) {
1257 features_ = StringToFeatureSet(features_string);
Josh Gaobd1f3002021-12-29 21:15:12 -08001258 delayed_ack_ = CanUseFeature(features_, kFeatureDelayedAck);
Dan Albertbe8e54b2015-05-18 13:06:53 -07001259}
1260
Yabin Cui2d4c1982015-08-28 15:09:44 -07001261void atransport::AddDisconnect(adisconnect* disconnect) {
1262 disconnects_.push_back(disconnect);
1263}
1264
1265void atransport::RemoveDisconnect(adisconnect* disconnect) {
1266 disconnects_.remove(disconnect);
1267}
1268
1269void atransport::RunDisconnects() {
Elliott Hughes85952832015-10-07 15:59:35 -07001270 for (const auto& disconnect : disconnects_) {
Yabin Cui2d4c1982015-08-28 15:09:44 -07001271 disconnect->func(disconnect->opaque, this);
1272 }
1273 disconnects_.clear();
1274}
1275
Josh Gao65d18e22020-04-22 20:57:26 -07001276#if ADB_HOST
David Pursellc929c6f2016-03-01 08:58:26 -08001277bool atransport::MatchesTarget(const std::string& target) const {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -07001278 if (!serial.empty()) {
David Pursellc929c6f2016-03-01 08:58:26 -08001279 if (target == serial) {
1280 return true;
1281 } else if (type == kTransportLocal) {
1282 // Local transports can match [tcp:|udp:]<hostname>[:port].
1283 const char* local_target_ptr = target.c_str();
1284
1285 // For fastboot compatibility, ignore protocol prefixes.
1286 if (android::base::StartsWith(target, "tcp:") ||
Josh Gao0d6aa992016-11-22 14:32:34 -08001287 android::base::StartsWith(target, "udp:")) {
David Pursellc929c6f2016-03-01 08:58:26 -08001288 local_target_ptr += 4;
1289 }
1290
1291 // Parse our |serial| and the given |target| to check if the hostnames and ports match.
1292 std::string serial_host, error;
1293 int serial_port = -1;
Josh Gao7852ca42021-06-17 04:17:25 -07001294 if (android::base::ParseNetAddress(serial, &serial_host, &serial_port, nullptr,
1295 &error)) {
David Pursellc929c6f2016-03-01 08:58:26 -08001296 // |target| may omit the port to default to ours.
1297 std::string target_host;
1298 int target_port = serial_port;
1299 if (android::base::ParseNetAddress(local_target_ptr, &target_host, &target_port,
1300 nullptr, &error) &&
Josh Gao0d6aa992016-11-22 14:32:34 -08001301 serial_host == target_host && serial_port == target_port) {
David Pursellc929c6f2016-03-01 08:58:26 -08001302 return true;
1303 }
1304 }
1305 }
1306 }
1307
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -07001308 return (target == devpath) || qual_match(target, "product:", product, false) ||
1309 qual_match(target, "model:", model, true) ||
1310 qual_match(target, "device:", device, false);
David Pursellc929c6f2016-03-01 08:58:26 -08001311}
1312
Luis Hector Chavezda74b902018-04-17 14:25:04 -07001313void atransport::SetConnectionEstablished(bool success) {
1314 connection_waitable_->SetConnectionEstablished(success);
1315}
1316
Josh Gaod24580d2018-08-30 11:37:00 -07001317ReconnectResult atransport::Reconnect() {
Luis Hector Chavez0aeda102018-04-20 10:31:29 -07001318 return reconnect_(this);
1319}
1320
Josh Gaob39e4152017-08-16 16:57:01 -07001321// We use newline as our delimiter, make sure to never output it.
1322static std::string sanitize(std::string str, bool alphanumeric) {
1323 auto pred = alphanumeric ? [](const char c) { return !isalnum(c); }
1324 : [](const char c) { return c == '\n'; };
1325 std::replace_if(str.begin(), str.end(), pred, '_');
1326 return str;
1327}
1328
Fabien Sanglard3d155b62023-11-30 14:52:40 -08001329static adb::proto::ConnectionState adbStateFromProto(ConnectionState state) {
1330 switch (state) {
1331 case kCsConnecting:
1332 return adb::proto::ConnectionState::CONNECTING;
1333 case kCsAuthorizing:
1334 return adb::proto::ConnectionState::AUTHORIZING;
1335 case kCsUnauthorized:
1336 return adb::proto::ConnectionState::UNAUTHORIZED;
1337 case kCsNoPerm:
1338 return adb::proto::ConnectionState::NOPERMISSION;
1339 case kCsDetached:
1340 return adb::proto::ConnectionState::DETACHED;
1341 case kCsOffline:
1342 return adb::proto::ConnectionState::OFFLINE;
1343 case kCsBootloader:
1344 return adb::proto::ConnectionState::BOOTLOADER;
1345 case kCsDevice:
1346 return adb::proto::ConnectionState::DEVICE;
1347 case kCsHost:
1348 return adb::proto::ConnectionState::HOST;
1349 case kCsRecovery:
1350 return adb::proto::ConnectionState::RECOVERY;
1351 case kCsSideload:
1352 return adb::proto::ConnectionState::SIDELOAD;
1353 case kCsRescue:
1354 return adb::proto::ConnectionState::RESCUE;
1355 case kCsAny:
1356 return adb::proto::ConnectionState::ANY;
1357 }
1358}
1359
1360static std::string transportListToProto(const std::list<atransport*>& sorted_transport_list,
1361 bool text_version) {
1362 adb::proto::Devices devices;
1363 for (const auto& t : sorted_transport_list) {
1364 auto* device = devices.add_device();
1365 device->set_serial(t->serial.c_str());
1366 device->set_connection_type(t->type == kTransportUsb ? adb::proto::ConnectionType::USB
1367 : adb::proto::ConnectionType::SOCKET);
1368 device->set_state(adbStateFromProto(t->GetConnectionState()));
1369 device->set_bus_address(sanitize(t->devpath, false));
1370 device->set_product(sanitize(t->product, false));
1371 device->set_model(sanitize(t->model, true));
1372 device->set_device(sanitize(t->device, false));
Fabien Sanglard3d155b62023-11-30 14:52:40 -08001373 device->set_negotiated_speed(t->connection()->NegotiatedSpeedMbps());
Fabien Sanglarde8d239f2023-12-15 11:48:09 -08001374 device->set_max_speed(t->connection()->MaxSpeedMbps());
1375 device->set_transport_id(t->id);
Fabien Sanglard3d155b62023-11-30 14:52:40 -08001376 }
1377
1378 std::string proto;
1379 if (text_version) {
1380 google::protobuf::TextFormat::PrintToString(devices, &proto);
1381 } else {
1382 devices.SerializeToString(&proto);
1383 }
1384 return proto;
1385}
1386
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -07001387static void append_transport_info(std::string* result, const char* key, const std::string& value,
Josh Gaob39e4152017-08-16 16:57:01 -07001388 bool alphanumeric) {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -07001389 if (value.empty()) {
Scott Anderson27042382012-05-30 18:11:27 -07001390 return;
Scott Anderson27042382012-05-30 18:11:27 -07001391 }
1392
Elliott Hughes88b4c852015-04-30 17:32:03 -07001393 *result += ' ';
1394 *result += key;
Josh Gaob39e4152017-08-16 16:57:01 -07001395 *result += sanitize(value, alphanumeric);
Scott Anderson27042382012-05-30 18:11:27 -07001396}
1397
Josh Gao0d6aa992016-11-22 14:32:34 -08001398static void append_transport(const atransport* t, std::string* result, bool long_listing) {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -07001399 std::string serial = t->serial;
1400 if (serial.empty()) {
Dan Alberta8c34142015-05-06 16:48:52 -07001401 serial = "(no serial number)";
Elliott Hughes88b4c852015-04-30 17:32:03 -07001402 }
Scott Anderson27042382012-05-30 18:11:27 -07001403
1404 if (!long_listing) {
Elliott Hughes88b4c852015-04-30 17:32:03 -07001405 *result += serial;
1406 *result += '\t';
Josh Gao6256d992021-05-20 18:28:13 -07001407 *result += to_string(t->GetConnectionState());
Scott Anderson27042382012-05-30 18:11:27 -07001408 } else {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -07001409 android::base::StringAppendF(result, "%-22s %s", serial.c_str(),
Josh Gao6256d992021-05-20 18:28:13 -07001410 to_string(t->GetConnectionState()).c_str());
Scott Anderson27042382012-05-30 18:11:27 -07001411
Elliott Hughes88b4c852015-04-30 17:32:03 -07001412 append_transport_info(result, "", t->devpath, false);
1413 append_transport_info(result, "product:", t->product, false);
1414 append_transport_info(result, "model:", t->model, true);
1415 append_transport_info(result, "device:", t->device, false);
Josh Gaob39e4152017-08-16 16:57:01 -07001416
1417 // Put id at the end, so that anyone parsing the output here can always find it by scanning
1418 // backwards from newlines, even with hypothetical devices named 'transport_id:1'.
1419 *result += " transport_id:";
1420 *result += std::to_string(t->id);
Scott Anderson27042382012-05-30 18:11:27 -07001421 }
Elliott Hughes88b4c852015-04-30 17:32:03 -07001422 *result += '\n';
Scott Anderson27042382012-05-30 18:11:27 -07001423}
1424
Fabien Sanglard3d155b62023-11-30 14:52:40 -08001425static std::string transportListToText(const std::list<atransport*>& sorted_transport_list,
1426 bool long_listing) {
1427 std::string result;
1428 for (const auto& t : sorted_transport_list) {
1429 append_transport(t, &result, long_listing);
1430 }
1431 return result;
1432}
1433
1434std::string list_transports(TrackerOutputType outputType) {
Josh Gaoaaa82f72017-08-17 13:50:51 -07001435 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Artem Iglikov4dd35012017-12-17 10:56:07 +00001436
1437 auto sorted_transport_list = transport_list;
1438 sorted_transport_list.sort([](atransport*& x, atransport*& y) {
1439 if (x->type != y->type) {
1440 return x->type < y->type;
1441 }
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -07001442 return x->serial < y->serial;
Artem Iglikov4dd35012017-12-17 10:56:07 +00001443 });
1444
Fabien Sanglard3d155b62023-11-30 14:52:40 -08001445 switch (outputType) {
1446 case SHORT_TEXT:
1447 case LONG_TEXT: {
1448 return transportListToText(sorted_transport_list, outputType == LONG_TEXT);
1449 }
1450 case PROTOBUF:
1451 case TEXT_PROTOBUF: {
1452 return transportListToProto(sorted_transport_list, outputType == TEXT_PROTOBUF);
1453 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001454 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001455}
1456
Josh Gao3a2172b2019-03-28 15:47:44 -07001457void close_usb_devices(std::function<bool(const atransport*)> predicate, bool reset) {
Josh Gaoaaa82f72017-08-17 13:50:51 -07001458 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gao4e562502016-10-27 14:01:08 -07001459 for (auto& t : transport_list) {
1460 if (predicate(t)) {
Josh Gao3a2172b2019-03-28 15:47:44 -07001461 if (reset) {
1462 t->Reset();
1463 } else {
1464 t->Kick();
1465 }
Josh Gao4e562502016-10-27 14:01:08 -07001466 }
1467 }
1468}
1469
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001470/* hack for osx */
Josh Gao3a2172b2019-03-28 15:47:44 -07001471void close_usb_devices(bool reset) {
1472 close_usb_devices([](const atransport*) { return true; }, reset);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001473}
Josh Gao65d18e22020-04-22 20:57:26 -07001474#endif
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001475
Shaju Mathew36c0c0d2023-01-04 16:34:39 -08001476bool validate_transport_list(const std::list<atransport*>& list, const std::string& serial,
1477 atransport* t, int* error) {
1478 for (const auto& transport : list) {
1479 if (serial == transport->serial) {
1480 const std::string list_name(&list == &pending_list ? "pending" : "transport");
1481 VLOG(TRANSPORT) << "socket transport " << transport->serial << " is already in the "
1482 << list_name << " list and fails to register";
1483 delete t;
1484 if (error) *error = EALREADY;
1485 return false;
1486 }
1487 }
1488 return true;
1489}
1490
Josh Gao597044d2018-08-08 16:20:14 -07001491bool register_socket_transport(unique_fd s, std::string serial, int port, int local,
Joshua Duong64fab752020-01-21 13:19:42 -08001492 atransport::ReconnectCallback reconnect, bool use_tls, int* error) {
Luis Hector Chavez0aeda102018-04-20 10:31:29 -07001493 atransport* t = new atransport(std::move(reconnect), kCsOffline);
Joshua Duong64fab752020-01-21 13:19:42 -08001494 t->use_tls = use_tls;
Dmitry Ivanov6d14d352022-12-11 18:19:23 +01001495 t->serial = std::move(serial);
David 'Digit' Turner58f59682011-01-06 14:11:07 +01001496
Dmitry Ivanov6d14d352022-12-11 18:19:23 +01001497 D("transport: %s init'ing for socket %d, on port %d", t->serial.c_str(), s.get(), port);
Josh Gaofa3107e2018-07-25 17:21:49 -07001498 if (init_socket_transport(t, std::move(s), port, local) < 0) {
Dan Albertecce5032015-05-18 16:46:31 -07001499 delete t;
Josh Gao597044d2018-08-08 16:20:14 -07001500 if (error) *error = errno;
1501 return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001502 }
Benoit Goby3f9f9ce2013-03-29 18:22:36 -07001503
Josh Gaoaaa82f72017-08-17 13:50:51 -07001504 std::unique_lock<std::recursive_mutex> lock(transport_lock);
Dmitry Ivanov6d14d352022-12-11 18:19:23 +01001505 if (!validate_transport_list(pending_list, t->serial, t, error)) {
Shaju Mathew36c0c0d2023-01-04 16:34:39 -08001506 return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001507 }
Benoit Goby3f9f9ce2013-03-29 18:22:36 -07001508
Dmitry Ivanov6d14d352022-12-11 18:19:23 +01001509 if (!validate_transport_list(transport_list, t->serial, t, error)) {
Shaju Mathew36c0c0d2023-01-04 16:34:39 -08001510 return false;
Benoit Goby3f9f9ce2013-03-29 18:22:36 -07001511 }
1512
Dan Albertecce5032015-05-18 16:46:31 -07001513 pending_list.push_front(t);
Josh Gaoe7daf572016-09-21 12:37:10 -07001514
1515 lock.unlock();
Benoit Goby3f9f9ce2013-03-29 18:22:36 -07001516
Josh Gao65d18e22020-04-22 20:57:26 -07001517#if ADB_HOST
Luis Hector Chavezda74b902018-04-17 14:25:04 -07001518 auto waitable = t->connection_waitable();
Josh Gao65d18e22020-04-22 20:57:26 -07001519#endif
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001520 register_transport(t);
Luis Hector Chavezda74b902018-04-17 14:25:04 -07001521
Luis Hector Chavez25bc41c2018-05-01 17:12:16 -07001522 if (local == 1) {
1523 // Do not wait for emulator transports.
Josh Gao597044d2018-08-08 16:20:14 -07001524 return true;
Luis Hector Chavez25bc41c2018-05-01 17:12:16 -07001525 }
1526
Josh Gao65d18e22020-04-22 20:57:26 -07001527#if ADB_HOST
Josh Gao597044d2018-08-08 16:20:14 -07001528 if (!waitable->WaitForConnection(std::chrono::seconds(10))) {
1529 if (error) *error = ETIMEDOUT;
1530 return false;
1531 }
1532
1533 if (t->GetConnectionState() == kCsUnauthorized) {
1534 if (error) *error = EPERM;
1535 return false;
1536 }
Josh Gao65d18e22020-04-22 20:57:26 -07001537#endif
Josh Gao597044d2018-08-08 16:20:14 -07001538
1539 return true;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001540}
1541
Mike Lockwood81ffe172009-10-11 23:04:18 -04001542#if ADB_HOST
Josh Gao0d6aa992016-11-22 14:32:34 -08001543atransport* find_transport(const char* serial) {
Dan Albertecce5032015-05-18 16:46:31 -07001544 atransport* result = nullptr;
Mike Lockwood81ffe172009-10-11 23:04:18 -04001545
Josh Gaoaaa82f72017-08-17 13:50:51 -07001546 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Yabin Cui4d64fd82015-08-27 12:03:11 -07001547 for (auto& t : transport_list) {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -07001548 if (strcmp(serial, t->serial.c_str()) == 0) {
Dan Albertecce5032015-05-18 16:46:31 -07001549 result = t;
Mike Lockwood81ffe172009-10-11 23:04:18 -04001550 break;
1551 }
Dan Albertecce5032015-05-18 16:46:31 -07001552 }
Mike Lockwood81ffe172009-10-11 23:04:18 -04001553
Dan Albertecce5032015-05-18 16:46:31 -07001554 return result;
Mike Lockwood81ffe172009-10-11 23:04:18 -04001555}
1556
Yabin Cui4d64fd82015-08-27 12:03:11 -07001557void kick_all_tcp_devices() {
Josh Gaoaaa82f72017-08-17 13:50:51 -07001558 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Yabin Cui4d64fd82015-08-27 12:03:11 -07001559 for (auto& t : transport_list) {
Yabin Cuif401ead2016-04-29 16:53:52 -07001560 if (t->IsTcpDevice()) {
Yabin Cui4e222292015-08-31 11:50:24 -07001561 // Kicking breaks the read_transport thread of this transport out of any read, then
1562 // the read_transport thread will notify the main thread to make this transport
1563 // offline. Then the main thread will notify the write_transport thread to exit.
Yabin Cui4d64fd82015-08-27 12:03:11 -07001564 // Finally, this transport will be closed and freed in the main thread.
Yabin Cuif2a9f9b2016-04-18 11:22:34 -07001565 t->Kick();
Mike Lockwood01c2c302010-05-24 10:44:35 -04001566 }
Dan Albertecce5032015-05-18 16:46:31 -07001567 }
Josh Gao13cb8c02018-08-10 14:44:54 -07001568 reconnect_handler.CheckForKicked();
Mike Lockwood01c2c302010-05-24 10:44:35 -04001569}
1570
Shaju Mathew36c85202023-06-13 08:00:16 -07001571#if ADB_HOST
Josh Gaof2d6af52021-04-27 20:32:02 -07001572void register_usb_transport(std::shared_ptr<Connection> connection, const char* serial,
1573 const char* devpath, unsigned writeable) {
1574 atransport* t = new atransport(writeable ? kCsOffline : kCsNoPerm);
1575 if (serial) {
1576 t->serial = serial;
1577 }
1578 if (devpath) {
1579 t->devpath = devpath;
1580 }
1581
1582 t->SetConnection(std::move(connection));
1583 t->type = kTransportUsb;
1584
1585 {
1586 std::lock_guard<std::recursive_mutex> lock(transport_lock);
1587 pending_list.push_front(t);
1588 }
1589
1590 register_transport(t);
1591}
1592
Josh Gao0d6aa992016-11-22 14:32:34 -08001593void register_usb_transport(usb_handle* usb, const char* serial, const char* devpath,
1594 unsigned writeable) {
Luis Hector Chavez0aeda102018-04-20 10:31:29 -07001595 atransport* t = new atransport(writeable ? kCsOffline : kCsNoPerm);
Dan Albertecce5032015-05-18 16:46:31 -07001596
Josh Gao0d6aa992016-11-22 14:32:34 -08001597 D("transport: %p init'ing for usb_handle %p (sn='%s')", t, usb, serial ? serial : "");
Yabin Cui3cf1b362017-03-10 16:01:01 -08001598 init_usb_transport(t, usb);
Josh Gao0d6aa992016-11-22 14:32:34 -08001599 if (serial) {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -07001600 t->serial = serial;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001601 }
Dan Albertecce5032015-05-18 16:46:31 -07001602
1603 if (devpath) {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -07001604 t->devpath = devpath;
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001605 }
Benoit Goby3f9f9ce2013-03-29 18:22:36 -07001606
Josh Gaoe7daf572016-09-21 12:37:10 -07001607 {
Josh Gaoaaa82f72017-08-17 13:50:51 -07001608 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gaoe7daf572016-09-21 12:37:10 -07001609 pending_list.push_front(t);
1610 }
Benoit Goby3f9f9ce2013-03-29 18:22:36 -07001611
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001612 register_transport(t);
1613}
1614
Dan Albert9a50f4c2015-05-18 16:43:57 -07001615// This should only be used for transports with connection_state == kCsNoPerm.
Josh Gao0d6aa992016-11-22 14:32:34 -08001616void unregister_usb_transport(usb_handle* usb) {
Josh Gaoaaa82f72017-08-17 13:50:51 -07001617 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gao395b86a2018-01-28 20:32:46 -08001618 transport_list.remove_if([usb](atransport* t) {
Josh Gao68f2c382018-12-11 13:11:52 -08001619 return t->GetUsbHandle() == usb && t->GetConnectionState() == kCsNoPerm;
Josh Gao395b86a2018-01-28 20:32:46 -08001620 });
Mike Lockwoode45583f2009-08-08 12:37:44 -04001621}
Shaju Mathew36c85202023-06-13 08:00:16 -07001622#endif
Shaju Mathew13508c12022-06-25 14:57:31 +00001623
1624// Track reverse:forward commands, so that info can be used to develop
1625// an 'allow-list':
1626// - adb reverse tcp:<device_port> localhost:<host_port> : responds with the
1627// device_port
1628// - adb reverse --remove tcp:<device_port> : responds OKAY
1629// - adb reverse --remove-all : responds OKAY
1630void atransport::UpdateReverseConfig(std::string_view service_addr) {
Shaju Mathew705fa1c2022-12-31 19:36:54 -08001631 fdevent_check_looper();
Shaju Mathew13508c12022-06-25 14:57:31 +00001632 if (!android::base::ConsumePrefix(&service_addr, "reverse:")) {
1633 return;
1634 }
1635
1636 if (android::base::ConsumePrefix(&service_addr, "forward:")) {
1637 // forward:[norebind:]<remote>;<local>
1638 bool norebind = android::base::ConsumePrefix(&service_addr, "norebind:");
1639 auto it = service_addr.find(';');
1640 if (it == std::string::npos) {
1641 return;
1642 }
1643 std::string remote(service_addr.substr(0, it));
1644
Elliott Hughesd3e5a5d2024-06-25 11:28:12 +00001645 if (norebind && reverse_forwards_.contains(remote)) {
Shaju Mathew13508c12022-06-25 14:57:31 +00001646 // This will fail, don't update the map.
1647 LOG(DEBUG) << "ignoring reverse forward that will fail due to norebind";
1648 return;
1649 }
1650
1651 std::string local(service_addr.substr(it + 1));
1652 reverse_forwards_[remote] = local;
1653 } else if (android::base::ConsumePrefix(&service_addr, "killforward:")) {
1654 // kill-forward:<remote>
1655 auto it = service_addr.find(';');
1656 if (it != std::string::npos) {
1657 return;
1658 }
1659 reverse_forwards_.erase(std::string(service_addr));
1660 } else if (service_addr == "killforward-all") {
1661 reverse_forwards_.clear();
1662 } else if (service_addr == "list-forward") {
1663 LOG(DEBUG) << __func__ << " ignoring --list";
1664 } else { // Anything else we need to know about?
1665 LOG(FATAL) << "unhandled reverse service: " << service_addr;
1666 }
1667}
1668
1669// Is this an authorized :connect request?
1670bool atransport::IsReverseConfigured(const std::string& local_addr) {
Shaju Mathew705fa1c2022-12-31 19:36:54 -08001671 fdevent_check_looper();
Shaju Mathew13508c12022-06-25 14:57:31 +00001672 for (const auto& [remote, local] : reverse_forwards_) {
1673 if (local == local_addr) {
1674 return true;
1675 }
1676 }
1677 return false;
1678}
1679
Josh Gao3a34bc52018-10-11 16:33:05 -07001680#endif
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001681
Josh Gao67b683a2017-05-16 15:02:45 -07001682bool check_header(apacket* p, atransport* t) {
Josh Gao0d6aa992016-11-22 14:32:34 -08001683 if (p->msg.magic != (p->msg.command ^ 0xffffffff)) {
Yabin Cui3cf1b362017-03-10 16:01:01 -08001684 VLOG(RWX) << "check_header(): invalid magic command = " << std::hex << p->msg.command
1685 << ", magic = " << p->msg.magic;
Josh Gao67b683a2017-05-16 15:02:45 -07001686 return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001687 }
1688
Josh Gao0d6aa992016-11-22 14:32:34 -08001689 if (p->msg.data_length > t->get_max_payload()) {
1690 VLOG(RWX) << "check_header(): " << p->msg.data_length
1691 << " atransport::max_payload = " << t->get_max_payload();
Josh Gao67b683a2017-05-16 15:02:45 -07001692 return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001693 }
1694
Josh Gao67b683a2017-05-16 15:02:45 -07001695 return true;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001696}
1697
Josh Gaoeac20582016-10-05 19:02:29 -07001698#if ADB_HOST
Joshua Duong64fab752020-01-21 13:19:42 -08001699std::shared_ptr<RSA> atransport::Key() {
1700 if (keys_.empty()) {
1701 return nullptr;
1702 }
1703
1704 std::shared_ptr<RSA> result = keys_[0];
1705 return result;
1706}
1707
Josh Gao22cb70b2016-08-18 22:00:12 -07001708std::shared_ptr<RSA> atransport::NextKey() {
Josh Gaoeb656522018-12-04 01:07:50 -08001709 if (keys_.empty()) {
1710 LOG(INFO) << "fetching keys for transport " << this->serial_name();
1711 keys_ = adb_auth_get_private_keys();
1712
1713 // We should have gotten at least one key: the one that's automatically generated.
1714 CHECK(!keys_.empty());
Joshua Duong64fab752020-01-21 13:19:42 -08001715 } else {
1716 keys_.pop_front();
Josh Gaoeb656522018-12-04 01:07:50 -08001717 }
Elliott Hughes801066a2016-06-29 17:42:01 -07001718
Josh Gaod60bafd2020-06-11 21:07:27 -07001719 return Key();
Elliott Hughes801066a2016-06-29 17:42:01 -07001720}
Josh Gaoeb656522018-12-04 01:07:50 -08001721
1722void atransport::ResetKeys() {
1723 keys_.clear();
1724}
Josh Gaoeac20582016-10-05 19:02:29 -07001725#endif