blob: 35db37c7a4bb68b8c108b50ede0d0219fa78d556 [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
59#include "client/usb.h"
60#endif
61
Joshua Duong64fab752020-01-21 13:19:42 -080062using namespace adb::crypto;
63using namespace adb::tls;
Elliott Hughes73abffa2022-06-09 16:30:24 +000064using namespace std::string_literals;
Josh Gao8aa57d22019-02-12 13:59:03 -080065using android::base::ScopedLockAssertion;
Joshua Duong64fab752020-01-21 13:19:42 -080066using TlsError = TlsConnection::TlsError;
Josh Gao8aa57d22019-02-12 13:59:03 -080067
Luis Hector Chavez0aeda102018-04-20 10:31:29 -070068static void remove_transport(atransport* transport);
Josh Gao14ed9f92019-12-09 13:45:31 -080069static void transport_destroy(atransport* transport);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080070
Josh Gaob39e4152017-08-16 16:57:01 -070071// TODO: unordered_map<TransportId, atransport*>
Josh Gaoe3a87d02015-11-11 17:56:12 -080072static auto& transport_list = *new std::list<atransport*>();
73static auto& pending_list = *new std::list<atransport*>();
Benoit Goby3f9f9ce2013-03-29 18:22:36 -070074
Josh Gaoaaa82f72017-08-17 13:50:51 -070075static auto& transport_lock = *new std::recursive_mutex();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -080076
Todd Kennedyaff9c672015-11-10 00:03:25 +000077const char* const kFeatureShell2 = "shell_v2";
78const char* const kFeatureCmd = "cmd";
Josh Gaoa2cf3752016-12-05 17:11:34 -080079const char* const kFeatureStat2 = "stat_v2";
Josh Gao7b083072019-08-07 14:23:17 -070080const char* const kFeatureLs2 = "ls_v2";
Josh Gao210b63f2017-02-22 17:07:01 -080081const char* const kFeatureLibusb = "libusb";
Dan Albert27983bc2017-05-23 14:30:00 -070082const char* const kFeaturePushSync = "push_sync";
Dario Frenidcb4c362018-10-04 16:26:40 +010083const char* const kFeatureApex = "apex";
Josh Gao281aab72018-10-22 13:00:05 -070084const char* const kFeatureFixedPushMkdir = "fixed_push_mkdir";
Alex Buynytskyye1fa8142019-01-17 13:13:56 -080085const char* const kFeatureAbb = "abb";
Josh Gao9eeb9f72019-02-20 13:01:40 -080086const char* const kFeatureFixedPushSymlinkTimestamp = "fixed_push_symlink_timestamp";
Alex Buynytskyy4f3fa052019-02-21 14:22:51 -080087const char* const kFeatureAbbExec = "abb_exec";
Josh Gaof764d572019-07-11 14:15:32 -070088const char* const kFeatureRemountShell = "remount_shell";
Shukang Zhou420ad552020-02-13 17:01:39 -080089const char* const kFeatureTrackApp = "track_app";
Josh Gao2f0f9eb2020-03-04 19:34:08 -080090const char* const kFeatureSendRecv2 = "sendrecv_v2";
91const char* const kFeatureSendRecv2Brotli = "sendrecv_v2_brotli";
Josh Gaofb386cc2020-03-26 22:02:03 -070092const char* const kFeatureSendRecv2LZ4 = "sendrecv_v2_lz4";
Josh Gaobdebc9b2020-05-27 17:52:52 -070093const char* const kFeatureSendRecv2Zstd = "sendrecv_v2_zstd";
Josh Gao8a410a02020-03-30 23:25:16 -070094const char* const kFeatureSendRecv2DryRunSend = "sendrecv_v2_dry_run_send";
Josh Gaobd1f3002021-12-29 21:15:12 -080095const char* const kFeatureDelayedAck = "delayed_ack";
Joshua Duongf4ba8d72021-01-13 12:18:15 -080096// TODO(joshuaduong): Bump to v2 when openscreen discovery is enabled by default
97const char* const kFeatureOpenscreenMdns = "openscreen_mdns";
Todd Kennedyaff9c672015-11-10 00:03:25 +000098
Luis Hector Chavezda74b902018-04-17 14:25:04 -070099namespace {
100
Josh Gao5c47e9f2018-07-31 18:28:32 -0700101#if ADB_HOST
Vince Harron5703eb32021-11-12 12:40:58 -0800102
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700103// Tracks and handles atransport*s that are attempting reconnection.
104class ReconnectHandler {
105 public:
106 ReconnectHandler() = default;
107 ~ReconnectHandler() = default;
108
109 // Starts the ReconnectHandler thread.
110 void Start();
111
112 // Requests the ReconnectHandler thread to stop.
113 void Stop();
114
115 // Adds the atransport* to the queue of reconnect attempts.
116 void TrackTransport(atransport* transport);
117
Josh Gao13cb8c02018-08-10 14:44:54 -0700118 // Wake up the ReconnectHandler thread to have it check for kicked transports.
119 void CheckForKicked();
120
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700121 private:
122 // The main thread loop.
123 void Run();
124
125 // Tracks a reconnection attempt.
126 struct ReconnectAttempt {
127 atransport* transport;
Josh Gaoc4deb392018-07-30 18:51:55 -0700128 std::chrono::steady_clock::time_point reconnect_time;
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700129 size_t attempts_left;
Josh Gaob0182892018-07-31 14:12:59 -0700130
131 bool operator<(const ReconnectAttempt& rhs) const {
Josh Gaod2ea0652018-08-10 14:28:24 -0700132 if (reconnect_time == rhs.reconnect_time) {
133 return reinterpret_cast<uintptr_t>(transport) <
134 reinterpret_cast<uintptr_t>(rhs.transport);
135 }
136 return reconnect_time < rhs.reconnect_time;
Josh Gaob0182892018-07-31 14:12:59 -0700137 }
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700138 };
139
140 // Only retry for up to one minute.
Josh Gao04ef6962020-10-15 18:32:55 -0700141 static constexpr const std::chrono::seconds kDefaultTimeout = 3s;
142 static constexpr const size_t kMaxAttempts = 20;
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700143
144 // Protects all members.
145 std::mutex reconnect_mutex_;
146 bool running_ GUARDED_BY(reconnect_mutex_) = true;
147 std::thread handler_thread_;
148 std::condition_variable reconnect_cv_;
Josh Gaod2ea0652018-08-10 14:28:24 -0700149 std::set<ReconnectAttempt> reconnect_queue_ GUARDED_BY(reconnect_mutex_);
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700150
151 DISALLOW_COPY_AND_ASSIGN(ReconnectHandler);
152};
153
154void ReconnectHandler::Start() {
Shaju Mathew705fa1c2022-12-31 19:36:54 -0800155 fdevent_check_looper();
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700156 handler_thread_ = std::thread(&ReconnectHandler::Run, this);
157}
158
159void ReconnectHandler::Stop() {
Shaju Mathew705fa1c2022-12-31 19:36:54 -0800160 fdevent_check_looper();
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700161 {
162 std::lock_guard<std::mutex> lock(reconnect_mutex_);
163 running_ = false;
164 }
165 reconnect_cv_.notify_one();
166 handler_thread_.join();
167
168 // Drain the queue to free all resources.
169 std::lock_guard<std::mutex> lock(reconnect_mutex_);
170 while (!reconnect_queue_.empty()) {
Josh Gaod2ea0652018-08-10 14:28:24 -0700171 ReconnectAttempt attempt = *reconnect_queue_.begin();
172 reconnect_queue_.erase(reconnect_queue_.begin());
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700173 remove_transport(attempt.transport);
174 }
175}
176
177void ReconnectHandler::TrackTransport(atransport* transport) {
Shaju Mathew705fa1c2022-12-31 19:36:54 -0800178 fdevent_check_looper();
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700179 {
180 std::lock_guard<std::mutex> lock(reconnect_mutex_);
181 if (!running_) return;
Josh Gaob0182892018-07-31 14:12:59 -0700182 // Arbitrary sleep to give adbd time to get ready, if we disconnected because it exited.
183 auto reconnect_time = std::chrono::steady_clock::now() + 250ms;
184 reconnect_queue_.emplace(
185 ReconnectAttempt{transport, reconnect_time, ReconnectHandler::kMaxAttempts});
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700186 }
187 reconnect_cv_.notify_one();
188}
189
Josh Gao13cb8c02018-08-10 14:44:54 -0700190void ReconnectHandler::CheckForKicked() {
191 reconnect_cv_.notify_one();
192}
193
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700194void ReconnectHandler::Run() {
195 while (true) {
196 ReconnectAttempt attempt;
197 {
198 std::unique_lock<std::mutex> lock(reconnect_mutex_);
Josh Gao8aa57d22019-02-12 13:59:03 -0800199 ScopedLockAssertion assume_lock(reconnect_mutex_);
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700200
Josh Gaoc4deb392018-07-30 18:51:55 -0700201 if (!reconnect_queue_.empty()) {
202 // FIXME: libstdc++ (used on Windows) implements condition_variable with
203 // system_clock as its clock, so we're probably hosed if the clock changes,
204 // even if we use steady_clock throughout. This problem goes away once we
205 // switch to libc++.
Josh Gaod2ea0652018-08-10 14:28:24 -0700206 reconnect_cv_.wait_until(lock, reconnect_queue_.begin()->reconnect_time);
Josh Gaoc4deb392018-07-30 18:51:55 -0700207 } else {
208 reconnect_cv_.wait(lock);
209 }
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700210
211 if (!running_) return;
Josh Gao13cb8c02018-08-10 14:44:54 -0700212
213 // Scan the whole list for kicked transports, so that we immediately handle an explicit
214 // disconnect request.
Josh Gao13cb8c02018-08-10 14:44:54 -0700215 for (auto it = reconnect_queue_.begin(); it != reconnect_queue_.end();) {
216 if (it->transport->kicked()) {
217 D("transport %s was kicked. giving up on it.", it->transport->serial.c_str());
218 remove_transport(it->transport);
219 it = reconnect_queue_.erase(it);
220 } else {
221 ++it;
222 }
Josh Gao13cb8c02018-08-10 14:44:54 -0700223 }
224
Josh Gaoc4deb392018-07-30 18:51:55 -0700225 if (reconnect_queue_.empty()) continue;
226
Josh Gao13cb8c02018-08-10 14:44:54 -0700227 // Go back to sleep if we either woke up spuriously, or we were woken up to remove
228 // a kicked transport, and the first transport isn't ready for reconnection yet.
Josh Gaoc4deb392018-07-30 18:51:55 -0700229 auto now = std::chrono::steady_clock::now();
Josh Gaod2ea0652018-08-10 14:28:24 -0700230 if (reconnect_queue_.begin()->reconnect_time > now) {
Josh Gaoc4deb392018-07-30 18:51:55 -0700231 continue;
232 }
233
Josh Gaod2ea0652018-08-10 14:28:24 -0700234 attempt = *reconnect_queue_.begin();
235 reconnect_queue_.erase(reconnect_queue_.begin());
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700236 }
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700237 D("attempting to reconnect %s", attempt.transport->serial.c_str());
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700238
Josh Gaod24580d2018-08-30 11:37:00 -0700239 switch (attempt.transport->Reconnect()) {
240 case ReconnectResult::Retry: {
241 D("attempting to reconnect %s failed.", attempt.transport->serial.c_str());
242 if (attempt.attempts_left == 0) {
243 D("transport %s exceeded the number of retry attempts. giving up on it.",
244 attempt.transport->serial.c_str());
245 remove_transport(attempt.transport);
246 continue;
247 }
248
249 std::lock_guard<std::mutex> lock(reconnect_mutex_);
250 reconnect_queue_.emplace(ReconnectAttempt{
251 attempt.transport,
252 std::chrono::steady_clock::now() + ReconnectHandler::kDefaultTimeout,
253 attempt.attempts_left - 1});
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700254 continue;
255 }
256
Josh Gaod24580d2018-08-30 11:37:00 -0700257 case ReconnectResult::Success:
258 D("reconnection to %s succeeded.", attempt.transport->serial.c_str());
259 register_transport(attempt.transport);
260 continue;
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700261
Josh Gaod24580d2018-08-30 11:37:00 -0700262 case ReconnectResult::Abort:
263 D("cancelling reconnection attempt to %s.", attempt.transport->serial.c_str());
264 remove_transport(attempt.transport);
265 continue;
266 }
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700267 }
268}
269
270static auto& reconnect_handler = *new ReconnectHandler();
271
Josh Gao5c47e9f2018-07-31 18:28:32 -0700272#endif
273
Luis Hector Chavezda74b902018-04-17 14:25:04 -0700274} // namespace
275
Josh Gaob39e4152017-08-16 16:57:01 -0700276TransportId NextTransportId() {
277 static std::atomic<TransportId> next(1);
278 return next++;
279}
280
Josh Gao3a2172b2019-03-28 15:47:44 -0700281void Connection::Reset() {
282 LOG(INFO) << "Connection::Reset(): stopping";
283 Stop();
284}
285
Josh Gao7852ca42021-06-17 04:17:25 -0700286std::string Connection::Serial() const {
287 return transport_ ? transport_->serial_name() : "<unknown>";
288}
289
Josh Gao715fe602018-02-16 13:24:58 -0800290BlockingConnectionAdapter::BlockingConnectionAdapter(std::unique_ptr<BlockingConnection> connection)
291 : underlying_(std::move(connection)) {}
292
293BlockingConnectionAdapter::~BlockingConnectionAdapter() {
Josh Gao7852ca42021-06-17 04:17:25 -0700294 LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): destructing";
Josh Gao715fe602018-02-16 13:24:58 -0800295 Stop();
296}
297
298void BlockingConnectionAdapter::Start() {
Josh Gao13781e82018-04-03 12:55:18 -0700299 std::lock_guard<std::mutex> lock(mutex_);
300 if (started_) {
Josh Gao7852ca42021-06-17 04:17:25 -0700301 LOG(FATAL) << "BlockingConnectionAdapter(" << Serial() << "): started multiple times";
Josh Gao13781e82018-04-03 12:55:18 -0700302 }
303
Joshua Duong64fab752020-01-21 13:19:42 -0800304 StartReadThread();
Josh Gao715fe602018-02-16 13:24:58 -0800305
306 write_thread_ = std::thread([this]() {
Josh Gao7852ca42021-06-17 04:17:25 -0700307 LOG(INFO) << Serial() << ": write thread spawning";
Josh Gao715fe602018-02-16 13:24:58 -0800308 while (true) {
309 std::unique_lock<std::mutex> lock(mutex_);
Josh Gao8aa57d22019-02-12 13:59:03 -0800310 ScopedLockAssertion assume_locked(mutex_);
Josh Gao13781e82018-04-03 12:55:18 -0700311 cv_.wait(lock, [this]() REQUIRES(mutex_) {
312 return this->stopped_ || !this->write_queue_.empty();
313 });
314
Josh Gao715fe602018-02-16 13:24:58 -0800315 if (this->stopped_) {
316 return;
317 }
318
319 std::unique_ptr<apacket> packet = std::move(this->write_queue_.front());
320 this->write_queue_.pop_front();
321 lock.unlock();
322
323 if (!this->underlying_->Write(packet.get())) {
324 break;
325 }
326 }
Josh Gao7852ca42021-06-17 04:17:25 -0700327 std::call_once(this->error_flag_, [this]() { transport_->HandleError("write failed"); });
Josh Gao715fe602018-02-16 13:24:58 -0800328 });
Josh Gao13781e82018-04-03 12:55:18 -0700329
330 started_ = true;
Josh Gao715fe602018-02-16 13:24:58 -0800331}
332
Joshua Duong64fab752020-01-21 13:19:42 -0800333void BlockingConnectionAdapter::StartReadThread() {
334 read_thread_ = std::thread([this]() {
Josh Gao7852ca42021-06-17 04:17:25 -0700335 LOG(INFO) << Serial() << ": read thread spawning";
Joshua Duong64fab752020-01-21 13:19:42 -0800336 while (true) {
337 auto packet = std::make_unique<apacket>();
338 if (!underlying_->Read(packet.get())) {
Josh Gao7852ca42021-06-17 04:17:25 -0700339 PLOG(INFO) << Serial() << ": read failed";
Joshua Duong64fab752020-01-21 13:19:42 -0800340 break;
341 }
342
343 bool got_stls_cmd = false;
344 if (packet->msg.command == A_STLS) {
345 got_stls_cmd = true;
346 }
347
Josh Gao7852ca42021-06-17 04:17:25 -0700348 transport_->HandleRead(std::move(packet));
Joshua Duong64fab752020-01-21 13:19:42 -0800349
350 // If we received the STLS packet, we are about to perform the TLS
351 // handshake. So this read thread must stop and resume after the
352 // handshake completes otherwise this will interfere in the process.
353 if (got_stls_cmd) {
Josh Gao7852ca42021-06-17 04:17:25 -0700354 LOG(INFO) << Serial() << ": Received STLS packet. Stopping read thread.";
Joshua Duong64fab752020-01-21 13:19:42 -0800355 return;
356 }
357 }
Josh Gao7852ca42021-06-17 04:17:25 -0700358 std::call_once(this->error_flag_, [this]() { transport_->HandleError("read failed"); });
Joshua Duong64fab752020-01-21 13:19:42 -0800359 });
360}
361
362bool BlockingConnectionAdapter::DoTlsHandshake(RSA* key, std::string* auth_key) {
363 std::lock_guard<std::mutex> lock(mutex_);
364 if (read_thread_.joinable()) {
365 read_thread_.join();
366 }
367 bool success = this->underlying_->DoTlsHandshake(key, auth_key);
368 StartReadThread();
369 return success;
370}
371
Josh Gao3a2172b2019-03-28 15:47:44 -0700372void BlockingConnectionAdapter::Reset() {
373 {
374 std::lock_guard<std::mutex> lock(mutex_);
375 if (!started_) {
Josh Gao7852ca42021-06-17 04:17:25 -0700376 LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): not started";
Josh Gao3a2172b2019-03-28 15:47:44 -0700377 return;
378 }
379
380 if (stopped_) {
Josh Gao7852ca42021-06-17 04:17:25 -0700381 LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): already stopped";
Josh Gao3a2172b2019-03-28 15:47:44 -0700382 return;
383 }
384 }
385
Josh Gao7852ca42021-06-17 04:17:25 -0700386 LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): resetting";
Josh Gao3a2172b2019-03-28 15:47:44 -0700387 this->underlying_->Reset();
388 Stop();
389}
390
Josh Gao715fe602018-02-16 13:24:58 -0800391void BlockingConnectionAdapter::Stop() {
Josh Gao13781e82018-04-03 12:55:18 -0700392 {
393 std::lock_guard<std::mutex> lock(mutex_);
394 if (!started_) {
Josh Gao7852ca42021-06-17 04:17:25 -0700395 LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): not started";
Josh Gao13781e82018-04-03 12:55:18 -0700396 return;
397 }
Josh Gao715fe602018-02-16 13:24:58 -0800398
Josh Gao13781e82018-04-03 12:55:18 -0700399 if (stopped_) {
Josh Gao7852ca42021-06-17 04:17:25 -0700400 LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): already stopped";
Josh Gao13781e82018-04-03 12:55:18 -0700401 return;
402 }
403
404 stopped_ = true;
405 }
Josh Gao715fe602018-02-16 13:24:58 -0800406
Josh Gao7852ca42021-06-17 04:17:25 -0700407 LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): stopping";
Josh Gao715fe602018-02-16 13:24:58 -0800408
409 this->underlying_->Close();
Josh Gao715fe602018-02-16 13:24:58 -0800410 this->cv_.notify_one();
Josh Gao13781e82018-04-03 12:55:18 -0700411
412 // Move the threads out into locals with the lock taken, and then unlock to let them exit.
413 std::thread read_thread;
414 std::thread write_thread;
415
416 {
417 std::lock_guard<std::mutex> lock(mutex_);
418 read_thread = std::move(read_thread_);
419 write_thread = std::move(write_thread_);
420 }
421
422 read_thread.join();
423 write_thread.join();
Josh Gao715fe602018-02-16 13:24:58 -0800424
Josh Gao7852ca42021-06-17 04:17:25 -0700425 LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): stopped";
426 std::call_once(this->error_flag_, [this]() { transport_->HandleError("requested stop"); });
Josh Gao715fe602018-02-16 13:24:58 -0800427}
428
429bool BlockingConnectionAdapter::Write(std::unique_ptr<apacket> packet) {
430 {
Josh Gao13781e82018-04-03 12:55:18 -0700431 std::lock_guard<std::mutex> lock(this->mutex_);
Josh Gao715fe602018-02-16 13:24:58 -0800432 write_queue_.emplace_back(std::move(packet));
433 }
434
435 cv_.notify_one();
436 return true;
437}
438
Joshua Duong64fab752020-01-21 13:19:42 -0800439FdConnection::FdConnection(unique_fd fd) : fd_(std::move(fd)) {}
440
441FdConnection::~FdConnection() {}
442
443bool FdConnection::DispatchRead(void* buf, size_t len) {
444 if (tls_ != nullptr) {
445 // The TlsConnection doesn't allow 0 byte reads
446 if (len == 0) {
447 return true;
448 }
449 return tls_->ReadFully(buf, len);
450 }
451
452 return ReadFdExactly(fd_.get(), buf, len);
453}
454
455bool FdConnection::DispatchWrite(void* buf, size_t len) {
456 if (tls_ != nullptr) {
457 // The TlsConnection doesn't allow 0 byte writes
458 if (len == 0) {
459 return true;
460 }
461 return tls_->WriteFully(std::string_view(reinterpret_cast<const char*>(buf), len));
462 }
463
464 return WriteFdExactly(fd_.get(), buf, len);
465}
466
Josh Gao395b86a2018-01-28 20:32:46 -0800467bool FdConnection::Read(apacket* packet) {
Joshua Duong64fab752020-01-21 13:19:42 -0800468 if (!DispatchRead(&packet->msg, sizeof(amessage))) {
Josh Gao395b86a2018-01-28 20:32:46 -0800469 D("remote local: read terminated (message)");
470 return false;
471 }
472
Josh Gao839b9322018-02-05 18:49:10 -0800473 if (packet->msg.data_length > MAX_PAYLOAD) {
Josh Gaob14756a2018-02-02 14:38:04 -0800474 D("remote local: read overflow (data length = %" PRIu32 ")", packet->msg.data_length);
475 return false;
476 }
477
Josh Gao839b9322018-02-05 18:49:10 -0800478 packet->payload.resize(packet->msg.data_length);
479
Joshua Duong64fab752020-01-21 13:19:42 -0800480 if (!DispatchRead(&packet->payload[0], packet->payload.size())) {
Josh Gao395b86a2018-01-28 20:32:46 -0800481 D("remote local: terminated (data)");
482 return false;
483 }
484
485 return true;
486}
487
488bool FdConnection::Write(apacket* packet) {
Joshua Duong64fab752020-01-21 13:19:42 -0800489 if (!DispatchWrite(&packet->msg, sizeof(packet->msg))) {
Josh Gao395b86a2018-01-28 20:32:46 -0800490 D("remote local: write terminated");
491 return false;
492 }
493
Josh Gao839b9322018-02-05 18:49:10 -0800494 if (packet->msg.data_length) {
Joshua Duong64fab752020-01-21 13:19:42 -0800495 if (!DispatchWrite(&packet->payload[0], packet->msg.data_length)) {
Josh Gao839b9322018-02-05 18:49:10 -0800496 D("remote local: write terminated");
497 return false;
498 }
499 }
500
Josh Gao395b86a2018-01-28 20:32:46 -0800501 return true;
502}
503
Joshua Duong64fab752020-01-21 13:19:42 -0800504bool FdConnection::DoTlsHandshake(RSA* key, std::string* auth_key) {
505 bssl::UniquePtr<EVP_PKEY> evp_pkey(EVP_PKEY_new());
506 if (!EVP_PKEY_set1_RSA(evp_pkey.get(), key)) {
507 LOG(ERROR) << "EVP_PKEY_set1_RSA failed";
508 return false;
509 }
510 auto x509 = GenerateX509Certificate(evp_pkey.get());
511 auto x509_str = X509ToPEMString(x509.get());
512 auto evp_str = Key::ToPEMString(evp_pkey.get());
Joshua Duongdd19e862020-03-24 09:50:59 -0700513
Yurii Zubrytskyi3c0574f2020-03-26 18:16:36 -0700514 int osh = cast_handle_to_int(adb_get_os_handle(fd_));
Joshua Duong64fab752020-01-21 13:19:42 -0800515#if ADB_HOST
Joshua Duong77b8ff32020-04-16 15:58:19 -0700516 tls_ = TlsConnection::Create(TlsConnection::Role::Client, x509_str, evp_str, osh);
Joshua Duong64fab752020-01-21 13:19:42 -0800517#else
Joshua Duong77b8ff32020-04-16 15:58:19 -0700518 tls_ = TlsConnection::Create(TlsConnection::Role::Server, x509_str, evp_str, osh);
Joshua Duong64fab752020-01-21 13:19:42 -0800519#endif
Joshua Duong64fab752020-01-21 13:19:42 -0800520 CHECK(tls_);
521#if ADB_HOST
522 // TLS 1.3 gives the client no message if the server rejected the
523 // certificate. This will enable a check in the tls connection to check
524 // whether the client certificate got rejected. Note that this assumes
525 // that, on handshake success, the server speaks first.
526 tls_->EnableClientPostHandshakeCheck(true);
527 // Add callback to set the certificate when server issues the
528 // CertificateRequest.
529 tls_->SetCertificateCallback(adb_tls_set_certificate);
530 // Allow any server certificate
531 tls_->SetCertVerifyCallback([](X509_STORE_CTX*) { return 1; });
532#else
533 // Add callback to check certificate against a list of known public keys
534 tls_->SetCertVerifyCallback(
535 [auth_key](X509_STORE_CTX* ctx) { return adbd_tls_verify_cert(ctx, auth_key); });
536 // Add the list of allowed client CA issuers
537 auto ca_list = adbd_tls_client_ca_list();
538 tls_->SetClientCAList(ca_list.get());
539#endif
540
541 auto err = tls_->DoHandshake();
542 if (err == TlsError::Success) {
543 return true;
544 }
545
546 tls_.reset();
547 return false;
548}
549
Josh Gao395b86a2018-01-28 20:32:46 -0800550void FdConnection::Close() {
551 adb_shutdown(fd_.get());
552 fd_.reset();
553}
554
Josh Gao67ac3792016-10-06 13:31:44 -0700555void send_packet(apacket* p, atransport* t) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800556 p->msg.magic = p->msg.command ^ 0xffffffff;
Tim Murrayee7b44d2017-12-07 11:40:00 -0800557 // compute a checksum for connection/auth packets for compatibility reasons
558 if (t->get_protocol_version() >= A_VERSION_SKIP_CHECKSUM) {
559 p->msg.data_check = 0;
560 } else {
561 p->msg.data_check = calculate_apacket_checksum(p);
562 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800563
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700564 VLOG(TRANSPORT) << dump_packet(t->serial.c_str(), "to remote", p);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800565
Yi Kong86e67182018-07-13 18:15:16 -0700566 if (t == nullptr) {
Elliott Hughese64126b2018-10-19 13:59:44 -0700567 LOG(FATAL) << "Transport is null";
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800568 }
569
Josh Gao715fe602018-02-16 13:24:58 -0800570 if (t->Write(p) != 0) {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700571 D("%s: failed to enqueue packet, closing transport", t->serial.c_str());
Josh Gao715fe602018-02-16 13:24:58 -0800572 t->Kick();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800573 }
574}
575
Josh Gao3a2172b2019-03-28 15:47:44 -0700576void kick_transport(atransport* t, bool reset) {
Josh Gaoaaa82f72017-08-17 13:50:51 -0700577 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Yabin Cuid78ed222016-04-05 13:50:44 -0700578 // As kick_transport() can be called from threads without guarantee that t is valid,
579 // check if the transport is in transport_list first.
Josh Gaob39e4152017-08-16 16:57:01 -0700580 //
581 // TODO(jmgao): WTF? Is this actually true?
Yabin Cuid78ed222016-04-05 13:50:44 -0700582 if (std::find(transport_list.begin(), transport_list.end(), t) != transport_list.end()) {
Josh Gao3a2172b2019-03-28 15:47:44 -0700583 if (reset) {
584 t->Reset();
585 } else {
586 t->Kick();
587 }
Yabin Cuid78ed222016-04-05 13:50:44 -0700588 }
Josh Gao13cb8c02018-08-10 14:44:54 -0700589
590#if ADB_HOST
591 reconnect_handler.CheckForKicked();
592#endif
Yabin Cui4d64fd82015-08-27 12:03:11 -0700593}
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800594
595static int transport_registration_send = -1;
596static int transport_registration_recv = -1;
Josh Gao9528df22018-05-14 11:14:33 -0700597static fdevent* transport_registration_fde;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800598
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800599#if ADB_HOST
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800600
601/* this adds support required by the 'track-devices' service.
602 * this is used to send the content of "list_transport" to any
603 * number of client connections that want it through a single
604 * live TCP connection
605 */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800606struct device_tracker {
Josh Gao0d6aa992016-11-22 14:32:34 -0800607 asocket socket;
Josh Gao5cb76ce2018-02-12 17:24:00 -0800608 bool update_needed = false;
609 bool long_output = false;
610 device_tracker* next = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800611};
612
613/* linked list of all device trackers */
Josh Gao0d6aa992016-11-22 14:32:34 -0800614static device_tracker* device_tracker_list;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800615
Josh Gao0d6aa992016-11-22 14:32:34 -0800616static void device_tracker_remove(device_tracker* tracker) {
617 device_tracker** pnode = &device_tracker_list;
618 device_tracker* node = *pnode;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800619
Josh Gaoaaa82f72017-08-17 13:50:51 -0700620 std::lock_guard<std::recursive_mutex> lock(transport_lock);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800621 while (node) {
622 if (node == tracker) {
623 *pnode = node->next;
624 break;
625 }
626 pnode = &node->next;
Josh Gao0d6aa992016-11-22 14:32:34 -0800627 node = *pnode;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800628 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800629}
630
Josh Gao0d6aa992016-11-22 14:32:34 -0800631static void device_tracker_close(asocket* socket) {
632 device_tracker* tracker = (device_tracker*)socket;
633 asocket* peer = socket->peer;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800634
Josh Gao0d6aa992016-11-22 14:32:34 -0800635 D("device tracker %p removed", tracker);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800636 if (peer) {
Yi Kong86e67182018-07-13 18:15:16 -0700637 peer->peer = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800638 peer->close(peer);
639 }
640 device_tracker_remove(tracker);
Josh Gao5cb76ce2018-02-12 17:24:00 -0800641 delete tracker;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800642}
643
Josh Gaocd2a5292018-03-07 16:52:28 -0800644static int device_tracker_enqueue(asocket* socket, apacket::payload_type) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800645 /* you can't read from a device tracker, close immediately */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800646 device_tracker_close(socket);
647 return -1;
648}
649
Elliott Hughes88b4c852015-04-30 17:32:03 -0700650static int device_tracker_send(device_tracker* tracker, const std::string& string) {
Elliott Hughes88b4c852015-04-30 17:32:03 -0700651 asocket* peer = tracker->socket.peer;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800652
Josh Gaocd2a5292018-03-07 16:52:28 -0800653 apacket::payload_type data;
Josh Gaoa7d9d712018-02-01 13:17:50 -0800654 data.resize(4 + string.size());
655 char buf[5];
656 snprintf(buf, sizeof(buf), "%04x", static_cast<int>(string.size()));
657 memcpy(&data[0], buf, 4);
658 memcpy(&data[4], string.data(), string.size());
659 return peer->enqueue(peer, std::move(data));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800660}
661
Elliott Hughes88b4c852015-04-30 17:32:03 -0700662static void device_tracker_ready(asocket* socket) {
663 device_tracker* tracker = reinterpret_cast<device_tracker*>(socket);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800664
Elliott Hughes88b4c852015-04-30 17:32:03 -0700665 // We want to send the device list when the tracker connects
666 // for the first time, even if no update occurred.
Josh Gao32124632017-08-14 18:57:54 -0700667 if (tracker->update_needed) {
668 tracker->update_needed = false;
Elliott Hughes3d792f42019-07-31 14:13:57 -0700669 device_tracker_send(tracker, list_transports(tracker->long_output));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800670 }
671}
672
Josh Gao32124632017-08-14 18:57:54 -0700673asocket* create_device_tracker(bool long_output) {
Josh Gao5cb76ce2018-02-12 17:24:00 -0800674 device_tracker* tracker = new device_tracker();
Elliott Hughese64126b2018-10-19 13:59:44 -0700675 if (tracker == nullptr) LOG(FATAL) << "cannot allocate device tracker";
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800676
Josh Gao0d6aa992016-11-22 14:32:34 -0800677 D("device tracker %p created", tracker);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800678
679 tracker->socket.enqueue = device_tracker_enqueue;
Josh Gao0d6aa992016-11-22 14:32:34 -0800680 tracker->socket.ready = device_tracker_ready;
681 tracker->socket.close = device_tracker_close;
Josh Gao32124632017-08-14 18:57:54 -0700682 tracker->update_needed = true;
683 tracker->long_output = long_output;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800684
Josh Gao0d6aa992016-11-22 14:32:34 -0800685 tracker->next = device_tracker_list;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800686 device_tracker_list = tracker;
687
688 return &tracker->socket;
689}
690
Josh Gao1e3bf732017-05-03 22:37:10 -0700691// Check if all of the USB transports are connected.
692bool iterate_transports(std::function<bool(const atransport*)> fn) {
Josh Gaoaaa82f72017-08-17 13:50:51 -0700693 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gao1e3bf732017-05-03 22:37:10 -0700694 for (const auto& t : transport_list) {
695 if (!fn(t)) {
696 return false;
697 }
698 }
699 for (const auto& t : pending_list) {
700 if (!fn(t)) {
701 return false;
702 }
703 }
704 return true;
705}
706
Elliott Hughes88b4c852015-04-30 17:32:03 -0700707// Call this function each time the transport list has changed.
708void update_transports() {
Josh Gao1e3bf732017-05-03 22:37:10 -0700709 update_transport_status();
710
711 // Notify `adb track-devices` clients.
Elliott Hughes88b4c852015-04-30 17:32:03 -0700712 device_tracker* tracker = device_tracker_list;
713 while (tracker != nullptr) {
714 device_tracker* next = tracker->next;
715 // This may destroy the tracker if the connection is closed.
Elliott Hughes3d792f42019-07-31 14:13:57 -0700716 device_tracker_send(tracker, list_transports(tracker->long_output));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800717 tracker = next;
718 }
719}
Elliott Hughes88b4c852015-04-30 17:32:03 -0700720
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800721#else
Elliott Hughes88b4c852015-04-30 17:32:03 -0700722
723void update_transports() {
724 // Nothing to do on the device side.
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800725}
Elliott Hughes88b4c852015-04-30 17:32:03 -0700726
Josh Gao0d6aa992016-11-22 14:32:34 -0800727#endif // ADB_HOST
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800728
Fabien Sanglardaf8259b2022-08-24 11:34:52 -0700729// The transport listeners communicate with the transports list via fdevent. tmsg structure is a
730// container used as message unit and written to a pipe in order to communicate the transport
731// (pointer) and the action to perform.
732//
733// Transport listener FDEVENT Transports list
734// --------------------------------------------------------------
735// (&transport,action) -> tmsg -> (&transport, action)
736//
737// TODO: Figure out if this fdevent bridge really is necessary? With the re-entrant lock to sync
738// access, what prevents us from "simply" updating the transport_list directly?
739
Josh Gao0d6aa992016-11-22 14:32:34 -0800740struct tmsg {
741 atransport* transport;
Fabien Sanglardaf8259b2022-08-24 11:34:52 -0700742
743 enum struct Action : int {
744 UNREGISTER = 0, // Unregister the transport from transport list (typically a device has
745 // been unplugged from USB or disconnected from TCP.
746 REGISTER = 1, // Register the transport to the transport list (typically a device has been
747 // plugged via USB or connected via TCP.
748 };
749 Action action;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800750};
751
Josh Gao0d6aa992016-11-22 14:32:34 -0800752static int transport_read_action(int fd, struct tmsg* m) {
753 char* p = (char*)m;
754 int len = sizeof(*m);
755 int r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800756
Josh Gao0d6aa992016-11-22 14:32:34 -0800757 while (len > 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800758 r = adb_read(fd, p, len);
Josh Gao0d6aa992016-11-22 14:32:34 -0800759 if (r > 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800760 len -= r;
Josh Gao0d6aa992016-11-22 14:32:34 -0800761 p += r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800762 } else {
Yabin Cui815ad882015-09-02 17:44:28 -0700763 D("transport_read_action: on fd %d: %s", fd, strerror(errno));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800764 return -1;
765 }
766 }
767 return 0;
768}
769
Josh Gao0d6aa992016-11-22 14:32:34 -0800770static int transport_write_action(int fd, struct tmsg* m) {
771 char* p = (char*)m;
772 int len = sizeof(*m);
773 int r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800774
Josh Gao0d6aa992016-11-22 14:32:34 -0800775 while (len > 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800776 r = adb_write(fd, p, len);
Josh Gao0d6aa992016-11-22 14:32:34 -0800777 if (r > 0) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800778 len -= r;
Josh Gao0d6aa992016-11-22 14:32:34 -0800779 p += r;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800780 } else {
Yabin Cui815ad882015-09-02 17:44:28 -0700781 D("transport_write_action: on fd %d: %s", fd, strerror(errno));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800782 return -1;
783 }
784 }
785 return 0;
786}
787
Josh Gao8e7c9722021-06-17 04:19:45 -0700788static bool usb_devices_start_detached() {
789#if ADB_HOST
790 static const char* env = getenv("ADB_LIBUSB_START_DETACHED");
791 static bool result = env && strcmp("1", env) == 0;
792 return should_use_libusb() && result;
793#else
794 return false;
795#endif
796}
797
Josh Gao715fe602018-02-16 13:24:58 -0800798static void transport_registration_func(int _fd, unsigned ev, void*) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800799 tmsg m;
Josh Gao0d6aa992016-11-22 14:32:34 -0800800 atransport* t;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800801
Josh Gao0d6aa992016-11-22 14:32:34 -0800802 if (!(ev & FDE_READ)) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800803 return;
804 }
805
Josh Gao0d6aa992016-11-22 14:32:34 -0800806 if (transport_read_action(_fd, &m)) {
Elliott Hughese64126b2018-10-19 13:59:44 -0700807 PLOG(FATAL) << "cannot read transport registration socket";
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800808 }
809
810 t = m.transport;
811
Fabien Sanglardaf8259b2022-08-24 11:34:52 -0700812 if (m.action == tmsg::Action::UNREGISTER) {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700813 D("transport: %s deleting", t->serial.c_str());
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800814
Josh Gaoe7daf572016-09-21 12:37:10 -0700815 {
Josh Gaoaaa82f72017-08-17 13:50:51 -0700816 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gaoe7daf572016-09-21 12:37:10 -0700817 transport_list.remove(t);
818 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800819
Dan Albertecce5032015-05-18 16:46:31 -0700820 delete t;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800821
822 update_transports();
823 return;
824 }
825
Mike Lockwoode45583f2009-08-08 12:37:44 -0400826 /* don't create transport threads for inaccessible devices */
Yabin Cui3cf1b362017-03-10 16:01:01 -0800827 if (t->GetConnectionState() != kCsNoPerm) {
Josh Gao7852ca42021-06-17 04:17:25 -0700828 t->connection()->SetTransport(t);
Josh Gao8e7c9722021-06-17 04:19:45 -0700829
830 if (t->type == kTransportUsb && usb_devices_start_detached()) {
831 t->SetConnectionState(kCsDetached);
832 } else {
833 t->connection()->Start();
Josh Gao715fe602018-02-16 13:24:58 -0800834#if ADB_HOST
Josh Gao8e7c9722021-06-17 04:19:45 -0700835 send_connect(t);
Josh Gao715fe602018-02-16 13:24:58 -0800836#endif
Josh Gao8e7c9722021-06-17 04:19:45 -0700837 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800838 }
839
Josh Gaoe7daf572016-09-21 12:37:10 -0700840 {
Josh Gaoaaa82f72017-08-17 13:50:51 -0700841 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700842 auto it = std::find(pending_list.begin(), pending_list.end(), t);
843 if (it != pending_list.end()) {
844 pending_list.remove(t);
845 transport_list.push_front(t);
846 }
Josh Gaoe7daf572016-09-21 12:37:10 -0700847 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800848
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800849 update_transports();
850}
851
Josh Gao5c47e9f2018-07-31 18:28:32 -0700852#if ADB_HOST
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700853void init_reconnect_handler(void) {
854 reconnect_handler.Start();
855}
Josh Gao5c47e9f2018-07-31 18:28:32 -0700856#endif
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700857
Josh Gao0d6aa992016-11-22 14:32:34 -0800858void init_transport_registration(void) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800859 int s[2];
860
Josh Gao0d6aa992016-11-22 14:32:34 -0800861 if (adb_socketpair(s)) {
Elliott Hughese64126b2018-10-19 13:59:44 -0700862 PLOG(FATAL) << "cannot open transport registration socketpair";
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800863 }
Yabin Cui815ad882015-09-02 17:44:28 -0700864 D("socketpair: (%d,%d)", s[0], s[1]);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800865
866 transport_registration_send = s[0];
867 transport_registration_recv = s[1];
868
Josh Gao9528df22018-05-14 11:14:33 -0700869 transport_registration_fde =
Josh Gao7852ca42021-06-17 04:17:25 -0700870 fdevent_create(transport_registration_recv, transport_registration_func, nullptr);
Josh Gao9528df22018-05-14 11:14:33 -0700871 fdevent_set(transport_registration_fde, FDE_READ);
Josh Gao165460f2017-05-09 13:43:35 -0700872}
873
874void kick_all_transports() {
Josh Gao5c47e9f2018-07-31 18:28:32 -0700875#if ADB_HOST
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700876 reconnect_handler.Stop();
Josh Gao5c47e9f2018-07-31 18:28:32 -0700877#endif
Josh Gao165460f2017-05-09 13:43:35 -0700878 // To avoid only writing part of a packet to a transport after exit, kick all transports.
Josh Gaoaaa82f72017-08-17 13:50:51 -0700879 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gao165460f2017-05-09 13:43:35 -0700880 for (auto t : transport_list) {
881 t->Kick();
882 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800883}
884
Joshua Duong64fab752020-01-21 13:19:42 -0800885void kick_all_tcp_tls_transports() {
886 std::lock_guard<std::recursive_mutex> lock(transport_lock);
887 for (auto t : transport_list) {
888 if (t->IsTcpDevice() && t->use_tls) {
889 t->Kick();
890 }
891 }
892}
893
894#if !ADB_HOST
895void kick_all_transports_by_auth_key(std::string_view auth_key) {
896 std::lock_guard<std::recursive_mutex> lock(transport_lock);
897 for (auto t : transport_list) {
898 if (auth_key == t->auth_key) {
899 t->Kick();
900 }
901 }
902}
903#endif
904
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800905/* the fdevent select pump is single threaded */
Josh Gao3a34bc52018-10-11 16:33:05 -0700906void register_transport(atransport* transport) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800907 tmsg m;
908 m.transport = transport;
Fabien Sanglardaf8259b2022-08-24 11:34:52 -0700909 m.action = tmsg::Action::REGISTER;
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700910 D("transport: %s registered", transport->serial.c_str());
Josh Gao0d6aa992016-11-22 14:32:34 -0800911 if (transport_write_action(transport_registration_send, &m)) {
Elliott Hughese64126b2018-10-19 13:59:44 -0700912 PLOG(FATAL) << "cannot write transport registration socket";
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800913 }
914}
915
Josh Gao0d6aa992016-11-22 14:32:34 -0800916static void remove_transport(atransport* transport) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800917 tmsg m;
918 m.transport = transport;
Fabien Sanglardaf8259b2022-08-24 11:34:52 -0700919 m.action = tmsg::Action::UNREGISTER;
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700920 D("transport: %s removed", transport->serial.c_str());
Josh Gao0d6aa992016-11-22 14:32:34 -0800921 if (transport_write_action(transport_registration_send, &m)) {
Elliott Hughese64126b2018-10-19 13:59:44 -0700922 PLOG(FATAL) << "cannot write transport registration socket";
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800923 }
924}
925
Josh Gao14ed9f92019-12-09 13:45:31 -0800926static void transport_destroy(atransport* t) {
Shaju Mathew705fa1c2022-12-31 19:36:54 -0800927 fdevent_check_looper();
Yabin Cui4d64fd82015-08-27 12:03:11 -0700928 CHECK(t != nullptr);
Josh Gaoe7daf572016-09-21 12:37:10 -0700929
Josh Gao4d299742017-09-13 13:40:57 -0700930 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gao14ed9f92019-12-09 13:45:31 -0800931 LOG(INFO) << "destroying transport " << t->serial_name();
932 t->connection()->Stop();
Josh Gao5c47e9f2018-07-31 18:28:32 -0700933#if ADB_HOST
Josh Gao14ed9f92019-12-09 13:45:31 -0800934 if (t->IsTcpDevice() && !t->kicked()) {
935 D("transport: %s destroy (attempting reconnection)", t->serial.c_str());
Josh Gaoeb656522018-12-04 01:07:50 -0800936
Josh Gao14ed9f92019-12-09 13:45:31 -0800937 // We need to clear the transport's keys, so that on the next connection, it tries
938 // again from the beginning.
939 t->ResetKeys();
940 reconnect_handler.TrackTransport(t);
941 return;
942 }
Josh Gao5c47e9f2018-07-31 18:28:32 -0700943#endif
944
Josh Gao14ed9f92019-12-09 13:45:31 -0800945 D("transport: %s destroy (kicking and closing)", t->serial.c_str());
946 remove_transport(t);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800947}
948
Josh Gao65d18e22020-04-22 20:57:26 -0700949#if ADB_HOST
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700950static int qual_match(const std::string& to_test, const char* prefix, const std::string& qual,
Josh Gao0d6aa992016-11-22 14:32:34 -0800951 bool sanitize_qual) {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700952 if (to_test.empty()) /* Return true if both the qual and to_test are empty strings. */
953 return qual.empty();
Scott Anderson27042382012-05-30 18:11:27 -0700954
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700955 if (qual.empty()) return 0;
Scott Anderson27042382012-05-30 18:11:27 -0700956
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700957 const char* ptr = to_test.c_str();
Scott Anderson27042382012-05-30 18:11:27 -0700958 if (prefix) {
959 while (*prefix) {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700960 if (*prefix++ != *ptr++) return 0;
Scott Anderson27042382012-05-30 18:11:27 -0700961 }
962 }
963
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700964 for (char ch : qual) {
Josh Gao0d6aa992016-11-22 14:32:34 -0800965 if (sanitize_qual && !isalnum(ch)) ch = '_';
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700966 if (ch != *ptr++) return 0;
Scott Anderson27042382012-05-30 18:11:27 -0700967 }
968
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700969 /* Everything matched so far. Return true if *ptr is a NUL. */
970 return !*ptr;
Scott Anderson27042382012-05-30 18:11:27 -0700971}
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800972
Vince Harron5703eb32021-11-12 12:40:58 -0800973// Contains either a device serial string or a USB device address like "usb:2-6"
974const char* __transport_server_one_device = nullptr;
975
976void transport_set_one_device(const char* adb_one_device) {
977 __transport_server_one_device = adb_one_device;
978}
979
980const char* transport_get_one_device() {
981 return __transport_server_one_device;
982}
983
984bool transport_server_owns_device(std::string_view serial) {
985 if (!__transport_server_one_device) {
986 // If the server doesn't own one device, server owns all devices.
987 return true;
988 }
989 return serial.compare(__transport_server_one_device) == 0;
990}
991
992bool transport_server_owns_device(std::string_view dev_path, std::string_view serial) {
993 if (!__transport_server_one_device) {
994 // If the server doesn't own one device, server owns all devices.
995 return true;
996 }
997 return serial.compare(__transport_server_one_device) == 0 ||
998 dev_path.compare(__transport_server_one_device) == 0;
999}
1000
Josh Gaob39e4152017-08-16 16:57:01 -07001001atransport* acquire_one_transport(TransportType type, const char* serial, TransportId transport_id,
1002 bool* is_ambiguous, std::string* error_out,
1003 bool accept_any_state) {
Elliott Hughes67943d12015-10-07 14:55:10 -07001004 atransport* result = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001005
Josh Gaob39e4152017-08-16 16:57:01 -07001006 if (transport_id != 0) {
Josh Gao7852ca42021-06-17 04:17:25 -07001007 *error_out = android::base::StringPrintf("no device with transport id '%" PRIu64 "'",
1008 transport_id);
Josh Gaob39e4152017-08-16 16:57:01 -07001009 } else if (serial) {
Elliott Hughes67943d12015-10-07 14:55:10 -07001010 *error_out = android::base::StringPrintf("device '%s' not found", serial);
1011 } else if (type == kTransportLocal) {
1012 *error_out = "no emulators found";
1013 } else if (type == kTransportAny) {
1014 *error_out = "no devices/emulators found";
1015 } else {
1016 *error_out = "no devices found";
1017 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001018
Josh Gaoaaa82f72017-08-17 13:50:51 -07001019 std::unique_lock<std::recursive_mutex> lock(transport_lock);
Elliott Hughes67943d12015-10-07 14:55:10 -07001020 for (const auto& t : transport_list) {
Yabin Cui3cf1b362017-03-10 16:01:01 -08001021 if (t->GetConnectionState() == kCsNoPerm) {
David Pursell6e5c7eb2015-12-02 15:14:31 -08001022 *error_out = UsbNoPermissionsLongHelpText();
Mike Lockwoodadc16b32009-08-08 13:53:16 -04001023 continue;
1024 }
Mike Lockwoode45583f2009-08-08 12:37:44 -04001025
Josh Gaob39e4152017-08-16 16:57:01 -07001026 if (transport_id) {
1027 if (t->id == transport_id) {
1028 result = t;
1029 break;
1030 }
1031 } else if (serial) {
David Pursellc929c6f2016-03-01 08:58:26 -08001032 if (t->MatchesTarget(serial)) {
Scott Anderson27042382012-05-30 18:11:27 -07001033 if (result) {
Elliott Hughes73abffa2022-06-09 16:30:24 +00001034 *error_out = "more than one device with serial "s + serial;
Elliott Hughes67943d12015-10-07 14:55:10 -07001035 if (is_ambiguous) *is_ambiguous = true;
1036 result = nullptr;
Scott Anderson27042382012-05-30 18:11:27 -07001037 break;
1038 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001039 result = t;
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001040 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001041 } else {
Elliott Hughes3aec2ba2015-05-05 13:10:43 -07001042 if (type == kTransportUsb && t->type == kTransportUsb) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001043 if (result) {
Elliott Hughes73abffa2022-06-09 16:30:24 +00001044 *error_out = "more than one USB device";
Elliott Hughes67943d12015-10-07 14:55:10 -07001045 if (is_ambiguous) *is_ambiguous = true;
1046 result = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001047 break;
1048 }
1049 result = t;
Elliott Hughes3aec2ba2015-05-05 13:10:43 -07001050 } else if (type == kTransportLocal && t->type == kTransportLocal) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001051 if (result) {
Elliott Hughes24f52762015-06-23 13:00:32 -07001052 *error_out = "more than one emulator";
Elliott Hughes67943d12015-10-07 14:55:10 -07001053 if (is_ambiguous) *is_ambiguous = true;
1054 result = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001055 break;
1056 }
1057 result = t;
Elliott Hughes3aec2ba2015-05-05 13:10:43 -07001058 } else if (type == kTransportAny) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001059 if (result) {
Elliott Hughes24f52762015-06-23 13:00:32 -07001060 *error_out = "more than one device/emulator";
Elliott Hughes67943d12015-10-07 14:55:10 -07001061 if (is_ambiguous) *is_ambiguous = true;
1062 result = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001063 break;
1064 }
1065 result = t;
1066 }
1067 }
1068 }
Josh Gaoe7daf572016-09-21 12:37:10 -07001069 lock.unlock();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001070
Josh Gao7a7c5cb2018-05-04 16:04:49 -07001071 if (result && !accept_any_state) {
1072 // The caller requires an active transport.
1073 // Make sure that we're actually connected.
1074 ConnectionState state = result->GetConnectionState();
1075 switch (state) {
1076 case kCsConnecting:
1077 *error_out = "device still connecting";
1078 result = nullptr;
1079 break;
Benoit Goby3f9f9ce2013-03-29 18:22:36 -07001080
Josh Gao7a7c5cb2018-05-04 16:04:49 -07001081 case kCsAuthorizing:
1082 *error_out = "device still authorizing";
1083 result = nullptr;
1084 break;
1085
1086 case kCsUnauthorized: {
1087 *error_out = "device unauthorized.\n";
1088 char* ADB_VENDOR_KEYS = getenv("ADB_VENDOR_KEYS");
1089 *error_out += "This adb server's $ADB_VENDOR_KEYS is ";
1090 *error_out += ADB_VENDOR_KEYS ? ADB_VENDOR_KEYS : "not set";
1091 *error_out += "\n";
1092 *error_out += "Try 'adb kill-server' if that seems wrong.\n";
1093 *error_out += "Otherwise check for a confirmation dialog on your device.";
1094 result = nullptr;
1095 break;
1096 }
1097
1098 case kCsOffline:
1099 *error_out = "device offline";
1100 result = nullptr;
1101 break;
1102
1103 default:
1104 break;
1105 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001106 }
1107
1108 if (result) {
Elliott Hughes24f52762015-06-23 13:00:32 -07001109 *error_out = "success";
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001110 }
1111
1112 return result;
1113}
1114
Luis Hector Chavezda74b902018-04-17 14:25:04 -07001115bool ConnectionWaitable::WaitForConnection(std::chrono::milliseconds timeout) {
1116 std::unique_lock<std::mutex> lock(mutex_);
Josh Gao8aa57d22019-02-12 13:59:03 -08001117 ScopedLockAssertion assume_locked(mutex_);
Luis Hector Chavezda74b902018-04-17 14:25:04 -07001118 return cv_.wait_for(lock, timeout, [&]() REQUIRES(mutex_) {
1119 return connection_established_ready_;
1120 }) && connection_established_;
1121}
1122
1123void ConnectionWaitable::SetConnectionEstablished(bool success) {
1124 {
1125 std::lock_guard<std::mutex> lock(mutex_);
1126 if (connection_established_ready_) return;
1127 connection_established_ready_ = true;
1128 connection_established_ = success;
1129 D("connection established with %d", success);
1130 }
1131 cv_.notify_one();
1132}
Josh Gao65d18e22020-04-22 20:57:26 -07001133#endif
Luis Hector Chavezda74b902018-04-17 14:25:04 -07001134
1135atransport::~atransport() {
Josh Gao65d18e22020-04-22 20:57:26 -07001136#if ADB_HOST
Luis Hector Chavezda74b902018-04-17 14:25:04 -07001137 // If the connection callback had not been run before, run it now.
1138 SetConnectionEstablished(false);
Josh Gao65d18e22020-04-22 20:57:26 -07001139#endif
Luis Hector Chavezda74b902018-04-17 14:25:04 -07001140}
1141
Yabin Cui3cf1b362017-03-10 16:01:01 -08001142int atransport::Write(apacket* p) {
Luis Hector Chavez3c7881d2018-04-25 08:56:41 -07001143 return this->connection()->Write(std::unique_ptr<apacket>(p)) ? 0 : -1;
Yabin Cui3cf1b362017-03-10 16:01:01 -08001144}
1145
Josh Gao3a2172b2019-03-28 15:47:44 -07001146void atransport::Reset() {
1147 if (!kicked_.exchange(true)) {
1148 LOG(INFO) << "resetting transport " << this << " " << this->serial;
1149 this->connection()->Reset();
1150 }
1151}
1152
Yabin Cuif2a9f9b2016-04-18 11:22:34 -07001153void atransport::Kick() {
Luis Hector Chavez0aeda102018-04-20 10:31:29 -07001154 if (!kicked_.exchange(true)) {
Josh Gao3a2172b2019-03-28 15:47:44 -07001155 LOG(INFO) << "kicking transport " << this << " " << this->serial;
Luis Hector Chavez3c7881d2018-04-25 08:56:41 -07001156 this->connection()->Stop();
Yabin Cuif2a9f9b2016-04-18 11:22:34 -07001157 }
1158}
1159
Yabin Cui3cf1b362017-03-10 16:01:01 -08001160ConnectionState atransport::GetConnectionState() const {
1161 return connection_state_;
1162}
1163
1164void atransport::SetConnectionState(ConnectionState state) {
Shaju Mathew705fa1c2022-12-31 19:36:54 -08001165 fdevent_check_looper();
Yabin Cui3cf1b362017-03-10 16:01:01 -08001166 connection_state_ = state;
Joshua Duongccde5202021-03-08 15:01:48 -08001167 update_transports();
Yabin Cui3cf1b362017-03-10 16:01:01 -08001168}
1169
Josh Gao8e7c9722021-06-17 04:19:45 -07001170#if ADB_HOST
1171bool atransport::Attach(std::string* error) {
1172 D("%s: attach", serial.c_str());
Shaju Mathew705fa1c2022-12-31 19:36:54 -08001173 fdevent_check_looper();
Josh Gao8e7c9722021-06-17 04:19:45 -07001174
1175 if (!should_use_libusb()) {
1176 *error = "attach/detach only implemented for libusb backend";
1177 return false;
1178 }
1179
1180 if (GetConnectionState() != ConnectionState::kCsDetached) {
1181 *error = android::base::StringPrintf("transport %s is not detached", serial.c_str());
1182 return false;
1183 }
1184
1185 ResetKeys();
1186
1187 {
1188 std::lock_guard<std::mutex> lock(mutex_);
1189 if (!connection_->Attach(error)) {
1190 return false;
1191 }
1192 }
1193
1194 send_connect(this);
1195 return true;
1196}
1197
1198bool atransport::Detach(std::string* error) {
1199 D("%s: detach", serial.c_str());
Shaju Mathew705fa1c2022-12-31 19:36:54 -08001200 fdevent_check_looper();
Josh Gao8e7c9722021-06-17 04:19:45 -07001201
1202 if (!should_use_libusb()) {
1203 *error = "attach/detach only implemented for libusb backend";
1204 return false;
1205 }
1206
1207 if (GetConnectionState() == ConnectionState::kCsDetached) {
1208 *error = android::base::StringPrintf("transport %s is already detached", serial.c_str());
1209 return false;
1210 }
1211
1212 handle_offline(this);
1213
1214 {
1215 std::lock_guard<std::mutex> lock(mutex_);
1216 if (!connection_->Detach(error)) {
1217 return false;
1218 }
1219 }
1220
1221 this->SetConnectionState(kCsDetached);
1222 return true;
1223}
1224#endif
1225
Josh Gaof2d6af52021-04-27 20:32:02 -07001226void atransport::SetConnection(std::shared_ptr<Connection> connection) {
Luis Hector Chavez3c7881d2018-04-25 08:56:41 -07001227 std::lock_guard<std::mutex> lock(mutex_);
1228 connection_ = std::shared_ptr<Connection>(std::move(connection));
1229}
1230
Josh Gao7852ca42021-06-17 04:17:25 -07001231bool atransport::HandleRead(std::unique_ptr<apacket> p) {
1232 if (!check_header(p.get(), this)) {
1233 D("%s: remote read: bad header", serial.c_str());
1234 return false;
1235 }
1236
1237 VLOG(TRANSPORT) << dump_packet(serial.c_str(), "from remote", p.get());
1238 apacket* packet = p.release();
1239
Shaju Mathew705fa1c2022-12-31 19:36:54 -08001240 // This needs to run on the looper thread since the associated fdevent
Shaju Mathew13508c12022-06-25 14:57:31 +00001241 // message pump exists in that context.
Shaju Mathew705fa1c2022-12-31 19:36:54 -08001242 fdevent_run_on_looper([packet, this]() { handle_packet(packet, this); });
Shaju Mathew13508c12022-06-25 14:57:31 +00001243
Josh Gao7852ca42021-06-17 04:17:25 -07001244 return true;
1245}
1246
1247void atransport::HandleError(const std::string& error) {
1248 LOG(INFO) << serial_name() << ": connection terminated: " << error;
Shaju Mathew705fa1c2022-12-31 19:36:54 -08001249 fdevent_run_on_looper([this]() {
Josh Gao7852ca42021-06-17 04:17:25 -07001250 handle_offline(this);
1251 transport_destroy(this);
1252 });
1253}
1254
Tamas Berghammera1c60c02015-07-13 19:12:28 +01001255void atransport::update_version(int version, size_t payload) {
1256 protocol_version = std::min(version, A_VERSION);
1257 max_payload = std::min(payload, MAX_PAYLOAD);
1258}
1259
1260int atransport::get_protocol_version() const {
1261 return protocol_version;
1262}
1263
Joshua Duong64fab752020-01-21 13:19:42 -08001264int atransport::get_tls_version() const {
1265 return tls_version;
1266}
1267
Tamas Berghammera1c60c02015-07-13 19:12:28 +01001268size_t atransport::get_max_payload() const {
1269 return max_payload;
1270}
1271
Josh Gaobd1f3002021-12-29 21:15:12 -08001272#if ADB_HOST
1273static bool delayed_ack_enabled() {
1274 static const char* env = getenv("ADB_DELAYED_ACK");
1275 static bool result = env && strcmp(env, "1") == 0;
1276 return result;
1277}
1278#endif
1279
Dan Albertbe8e54b2015-05-18 13:06:53 -07001280const FeatureSet& supported_features() {
Josh Gaobd1f3002021-12-29 21:15:12 -08001281 static const android::base::NoDestructor<FeatureSet> features([]() {
1282 // Increment ADB_SERVER_VERSION when adding a feature that adbd needs
1283 // to know about. Otherwise, the client can be stuck running an old
1284 // version of the server even after upgrading their copy of adb.
1285 // (http://b/24370690)
1286
1287 // clang-format off
1288 FeatureSet result {
1289 kFeatureShell2,
1290 kFeatureCmd,
1291 kFeatureStat2,
1292 kFeatureLs2,
1293 kFeatureFixedPushMkdir,
1294 kFeatureApex,
1295 kFeatureAbb,
1296 kFeatureFixedPushSymlinkTimestamp,
1297 kFeatureAbbExec,
1298 kFeatureRemountShell,
1299 kFeatureTrackApp,
1300 kFeatureSendRecv2,
1301 kFeatureSendRecv2Brotli,
1302 kFeatureSendRecv2LZ4,
1303 kFeatureSendRecv2Zstd,
1304 kFeatureSendRecv2DryRunSend,
1305 kFeatureOpenscreenMdns,
Yurii Zubrytskyi816c2d22020-03-26 18:19:28 -07001306 };
Josh Gaobd1f3002021-12-29 21:15:12 -08001307 // clang-format on
1308
1309#if ADB_HOST
1310 if (delayed_ack_enabled()) {
1311 result.push_back(kFeatureDelayedAck);
1312 }
1313#else
1314 result.push_back(kFeatureDelayedAck);
1315#endif
1316 return result;
Yurii Zubrytskyi816c2d22020-03-26 18:19:28 -07001317 }());
David Pursella07dbad2015-09-22 10:43:08 -07001318
1319 return *features;
1320}
1321
1322std::string FeatureSetToString(const FeatureSet& features) {
Elliott Hughesc3462f42018-09-05 12:13:11 -07001323 return android::base::Join(features, ',');
David Pursella07dbad2015-09-22 10:43:08 -07001324}
1325
1326FeatureSet StringToFeatureSet(const std::string& features_string) {
David Pursell3d9072b2015-09-25 13:04:21 -07001327 if (features_string.empty()) {
1328 return FeatureSet();
1329 }
1330
Yurii Zubrytskyi816c2d22020-03-26 18:19:28 -07001331 return android::base::Split(features_string, ",");
1332}
1333
1334template <class Range, class Value>
1335static bool contains(const Range& r, const Value& v) {
1336 return std::find(std::begin(r), std::end(r), v) != std::end(r);
Dan Albertbe8e54b2015-05-18 13:06:53 -07001337}
1338
David Pursell22fc5e92015-09-30 13:35:42 -07001339bool CanUseFeature(const FeatureSet& feature_set, const std::string& feature) {
Yurii Zubrytskyi816c2d22020-03-26 18:19:28 -07001340 return contains(feature_set, feature) && contains(supported_features(), feature);
David Pursell22fc5e92015-09-30 13:35:42 -07001341}
1342
Dan Albertbe8e54b2015-05-18 13:06:53 -07001343bool atransport::has_feature(const std::string& feature) const {
Yurii Zubrytskyi816c2d22020-03-26 18:19:28 -07001344 return contains(features_, feature);
Dan Albertbe8e54b2015-05-18 13:06:53 -07001345}
1346
David Pursella07dbad2015-09-22 10:43:08 -07001347void atransport::SetFeatures(const std::string& features_string) {
1348 features_ = StringToFeatureSet(features_string);
Josh Gaobd1f3002021-12-29 21:15:12 -08001349 delayed_ack_ = CanUseFeature(features_, kFeatureDelayedAck);
Dan Albertbe8e54b2015-05-18 13:06:53 -07001350}
1351
Yabin Cui2d4c1982015-08-28 15:09:44 -07001352void atransport::AddDisconnect(adisconnect* disconnect) {
1353 disconnects_.push_back(disconnect);
1354}
1355
1356void atransport::RemoveDisconnect(adisconnect* disconnect) {
1357 disconnects_.remove(disconnect);
1358}
1359
1360void atransport::RunDisconnects() {
Elliott Hughes85952832015-10-07 15:59:35 -07001361 for (const auto& disconnect : disconnects_) {
Yabin Cui2d4c1982015-08-28 15:09:44 -07001362 disconnect->func(disconnect->opaque, this);
1363 }
1364 disconnects_.clear();
1365}
1366
Josh Gao65d18e22020-04-22 20:57:26 -07001367#if ADB_HOST
David Pursellc929c6f2016-03-01 08:58:26 -08001368bool atransport::MatchesTarget(const std::string& target) const {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -07001369 if (!serial.empty()) {
David Pursellc929c6f2016-03-01 08:58:26 -08001370 if (target == serial) {
1371 return true;
1372 } else if (type == kTransportLocal) {
1373 // Local transports can match [tcp:|udp:]<hostname>[:port].
1374 const char* local_target_ptr = target.c_str();
1375
1376 // For fastboot compatibility, ignore protocol prefixes.
1377 if (android::base::StartsWith(target, "tcp:") ||
Josh Gao0d6aa992016-11-22 14:32:34 -08001378 android::base::StartsWith(target, "udp:")) {
David Pursellc929c6f2016-03-01 08:58:26 -08001379 local_target_ptr += 4;
1380 }
1381
1382 // Parse our |serial| and the given |target| to check if the hostnames and ports match.
1383 std::string serial_host, error;
1384 int serial_port = -1;
Josh Gao7852ca42021-06-17 04:17:25 -07001385 if (android::base::ParseNetAddress(serial, &serial_host, &serial_port, nullptr,
1386 &error)) {
David Pursellc929c6f2016-03-01 08:58:26 -08001387 // |target| may omit the port to default to ours.
1388 std::string target_host;
1389 int target_port = serial_port;
1390 if (android::base::ParseNetAddress(local_target_ptr, &target_host, &target_port,
1391 nullptr, &error) &&
Josh Gao0d6aa992016-11-22 14:32:34 -08001392 serial_host == target_host && serial_port == target_port) {
David Pursellc929c6f2016-03-01 08:58:26 -08001393 return true;
1394 }
1395 }
1396 }
1397 }
1398
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -07001399 return (target == devpath) || qual_match(target, "product:", product, false) ||
1400 qual_match(target, "model:", model, true) ||
1401 qual_match(target, "device:", device, false);
David Pursellc929c6f2016-03-01 08:58:26 -08001402}
1403
Luis Hector Chavezda74b902018-04-17 14:25:04 -07001404void atransport::SetConnectionEstablished(bool success) {
1405 connection_waitable_->SetConnectionEstablished(success);
1406}
1407
Josh Gaod24580d2018-08-30 11:37:00 -07001408ReconnectResult atransport::Reconnect() {
Luis Hector Chavez0aeda102018-04-20 10:31:29 -07001409 return reconnect_(this);
1410}
1411
Josh Gaob39e4152017-08-16 16:57:01 -07001412// We use newline as our delimiter, make sure to never output it.
1413static std::string sanitize(std::string str, bool alphanumeric) {
1414 auto pred = alphanumeric ? [](const char c) { return !isalnum(c); }
1415 : [](const char c) { return c == '\n'; };
1416 std::replace_if(str.begin(), str.end(), pred, '_');
1417 return str;
1418}
1419
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -07001420static void append_transport_info(std::string* result, const char* key, const std::string& value,
Josh Gaob39e4152017-08-16 16:57:01 -07001421 bool alphanumeric) {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -07001422 if (value.empty()) {
Scott Anderson27042382012-05-30 18:11:27 -07001423 return;
Scott Anderson27042382012-05-30 18:11:27 -07001424 }
1425
Elliott Hughes88b4c852015-04-30 17:32:03 -07001426 *result += ' ';
1427 *result += key;
Josh Gaob39e4152017-08-16 16:57:01 -07001428 *result += sanitize(value, alphanumeric);
Scott Anderson27042382012-05-30 18:11:27 -07001429}
1430
Josh Gao0d6aa992016-11-22 14:32:34 -08001431static void append_transport(const atransport* t, std::string* result, bool long_listing) {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -07001432 std::string serial = t->serial;
1433 if (serial.empty()) {
Dan Alberta8c34142015-05-06 16:48:52 -07001434 serial = "(no serial number)";
Elliott Hughes88b4c852015-04-30 17:32:03 -07001435 }
Scott Anderson27042382012-05-30 18:11:27 -07001436
1437 if (!long_listing) {
Elliott Hughes88b4c852015-04-30 17:32:03 -07001438 *result += serial;
1439 *result += '\t';
Josh Gao6256d992021-05-20 18:28:13 -07001440 *result += to_string(t->GetConnectionState());
Scott Anderson27042382012-05-30 18:11:27 -07001441 } else {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -07001442 android::base::StringAppendF(result, "%-22s %s", serial.c_str(),
Josh Gao6256d992021-05-20 18:28:13 -07001443 to_string(t->GetConnectionState()).c_str());
Scott Anderson27042382012-05-30 18:11:27 -07001444
Elliott Hughes88b4c852015-04-30 17:32:03 -07001445 append_transport_info(result, "", t->devpath, false);
1446 append_transport_info(result, "product:", t->product, false);
1447 append_transport_info(result, "model:", t->model, true);
1448 append_transport_info(result, "device:", t->device, false);
Josh Gaob39e4152017-08-16 16:57:01 -07001449
1450 // Put id at the end, so that anyone parsing the output here can always find it by scanning
1451 // backwards from newlines, even with hypothetical devices named 'transport_id:1'.
1452 *result += " transport_id:";
1453 *result += std::to_string(t->id);
Scott Anderson27042382012-05-30 18:11:27 -07001454 }
Elliott Hughes88b4c852015-04-30 17:32:03 -07001455 *result += '\n';
Scott Anderson27042382012-05-30 18:11:27 -07001456}
1457
Elliott Hughes88b4c852015-04-30 17:32:03 -07001458std::string list_transports(bool long_listing) {
Josh Gaoaaa82f72017-08-17 13:50:51 -07001459 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Artem Iglikov4dd35012017-12-17 10:56:07 +00001460
1461 auto sorted_transport_list = transport_list;
1462 sorted_transport_list.sort([](atransport*& x, atransport*& y) {
1463 if (x->type != y->type) {
1464 return x->type < y->type;
1465 }
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -07001466 return x->serial < y->serial;
Artem Iglikov4dd35012017-12-17 10:56:07 +00001467 });
1468
1469 std::string result;
1470 for (const auto& t : sorted_transport_list) {
Elliott Hughes88b4c852015-04-30 17:32:03 -07001471 append_transport(t, &result, long_listing);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001472 }
Elliott Hughes88b4c852015-04-30 17:32:03 -07001473 return result;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001474}
1475
Josh Gao3a2172b2019-03-28 15:47:44 -07001476void close_usb_devices(std::function<bool(const atransport*)> predicate, bool reset) {
Josh Gaoaaa82f72017-08-17 13:50:51 -07001477 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gao4e562502016-10-27 14:01:08 -07001478 for (auto& t : transport_list) {
1479 if (predicate(t)) {
Josh Gao3a2172b2019-03-28 15:47:44 -07001480 if (reset) {
1481 t->Reset();
1482 } else {
1483 t->Kick();
1484 }
Josh Gao4e562502016-10-27 14:01:08 -07001485 }
1486 }
1487}
1488
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001489/* hack for osx */
Josh Gao3a2172b2019-03-28 15:47:44 -07001490void close_usb_devices(bool reset) {
1491 close_usb_devices([](const atransport*) { return true; }, reset);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001492}
Josh Gao65d18e22020-04-22 20:57:26 -07001493#endif
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001494
Shaju Mathew36c0c0d2023-01-04 16:34:39 -08001495bool validate_transport_list(const std::list<atransport*>& list, const std::string& serial,
1496 atransport* t, int* error) {
1497 for (const auto& transport : list) {
1498 if (serial == transport->serial) {
1499 const std::string list_name(&list == &pending_list ? "pending" : "transport");
1500 VLOG(TRANSPORT) << "socket transport " << transport->serial << " is already in the "
1501 << list_name << " list and fails to register";
1502 delete t;
1503 if (error) *error = EALREADY;
1504 return false;
1505 }
1506 }
1507 return true;
1508}
1509
Josh Gao597044d2018-08-08 16:20:14 -07001510bool register_socket_transport(unique_fd s, std::string serial, int port, int local,
Joshua Duong64fab752020-01-21 13:19:42 -08001511 atransport::ReconnectCallback reconnect, bool use_tls, int* error) {
Luis Hector Chavez0aeda102018-04-20 10:31:29 -07001512 atransport* t = new atransport(std::move(reconnect), kCsOffline);
Joshua Duong64fab752020-01-21 13:19:42 -08001513 t->use_tls = use_tls;
Dmitry Ivanov6d14d352022-12-11 18:19:23 +01001514 t->serial = std::move(serial);
David 'Digit' Turner58f59682011-01-06 14:11:07 +01001515
Dmitry Ivanov6d14d352022-12-11 18:19:23 +01001516 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 -07001517 if (init_socket_transport(t, std::move(s), port, local) < 0) {
Dan Albertecce5032015-05-18 16:46:31 -07001518 delete t;
Josh Gao597044d2018-08-08 16:20:14 -07001519 if (error) *error = errno;
1520 return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001521 }
Benoit Goby3f9f9ce2013-03-29 18:22:36 -07001522
Josh Gaoaaa82f72017-08-17 13:50:51 -07001523 std::unique_lock<std::recursive_mutex> lock(transport_lock);
Dmitry Ivanov6d14d352022-12-11 18:19:23 +01001524 if (!validate_transport_list(pending_list, t->serial, t, error)) {
Shaju Mathew36c0c0d2023-01-04 16:34:39 -08001525 return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001526 }
Benoit Goby3f9f9ce2013-03-29 18:22:36 -07001527
Dmitry Ivanov6d14d352022-12-11 18:19:23 +01001528 if (!validate_transport_list(transport_list, t->serial, t, error)) {
Shaju Mathew36c0c0d2023-01-04 16:34:39 -08001529 return false;
Benoit Goby3f9f9ce2013-03-29 18:22:36 -07001530 }
1531
Dan Albertecce5032015-05-18 16:46:31 -07001532 pending_list.push_front(t);
Josh Gaoe7daf572016-09-21 12:37:10 -07001533
1534 lock.unlock();
Benoit Goby3f9f9ce2013-03-29 18:22:36 -07001535
Josh Gao65d18e22020-04-22 20:57:26 -07001536#if ADB_HOST
Luis Hector Chavezda74b902018-04-17 14:25:04 -07001537 auto waitable = t->connection_waitable();
Josh Gao65d18e22020-04-22 20:57:26 -07001538#endif
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001539 register_transport(t);
Luis Hector Chavezda74b902018-04-17 14:25:04 -07001540
Luis Hector Chavez25bc41c2018-05-01 17:12:16 -07001541 if (local == 1) {
1542 // Do not wait for emulator transports.
Josh Gao597044d2018-08-08 16:20:14 -07001543 return true;
Luis Hector Chavez25bc41c2018-05-01 17:12:16 -07001544 }
1545
Josh Gao65d18e22020-04-22 20:57:26 -07001546#if ADB_HOST
Josh Gao597044d2018-08-08 16:20:14 -07001547 if (!waitable->WaitForConnection(std::chrono::seconds(10))) {
1548 if (error) *error = ETIMEDOUT;
1549 return false;
1550 }
1551
1552 if (t->GetConnectionState() == kCsUnauthorized) {
1553 if (error) *error = EPERM;
1554 return false;
1555 }
Josh Gao65d18e22020-04-22 20:57:26 -07001556#endif
Josh Gao597044d2018-08-08 16:20:14 -07001557
1558 return true;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001559}
1560
Mike Lockwood81ffe172009-10-11 23:04:18 -04001561#if ADB_HOST
Josh Gao0d6aa992016-11-22 14:32:34 -08001562atransport* find_transport(const char* serial) {
Dan Albertecce5032015-05-18 16:46:31 -07001563 atransport* result = nullptr;
Mike Lockwood81ffe172009-10-11 23:04:18 -04001564
Josh Gaoaaa82f72017-08-17 13:50:51 -07001565 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Yabin Cui4d64fd82015-08-27 12:03:11 -07001566 for (auto& t : transport_list) {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -07001567 if (strcmp(serial, t->serial.c_str()) == 0) {
Dan Albertecce5032015-05-18 16:46:31 -07001568 result = t;
Mike Lockwood81ffe172009-10-11 23:04:18 -04001569 break;
1570 }
Dan Albertecce5032015-05-18 16:46:31 -07001571 }
Mike Lockwood81ffe172009-10-11 23:04:18 -04001572
Dan Albertecce5032015-05-18 16:46:31 -07001573 return result;
Mike Lockwood81ffe172009-10-11 23:04:18 -04001574}
1575
Yabin Cui4d64fd82015-08-27 12:03:11 -07001576void kick_all_tcp_devices() {
Josh Gaoaaa82f72017-08-17 13:50:51 -07001577 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Yabin Cui4d64fd82015-08-27 12:03:11 -07001578 for (auto& t : transport_list) {
Yabin Cuif401ead2016-04-29 16:53:52 -07001579 if (t->IsTcpDevice()) {
Yabin Cui4e222292015-08-31 11:50:24 -07001580 // Kicking breaks the read_transport thread of this transport out of any read, then
1581 // the read_transport thread will notify the main thread to make this transport
1582 // offline. Then the main thread will notify the write_transport thread to exit.
Yabin Cui4d64fd82015-08-27 12:03:11 -07001583 // Finally, this transport will be closed and freed in the main thread.
Yabin Cuif2a9f9b2016-04-18 11:22:34 -07001584 t->Kick();
Mike Lockwood01c2c302010-05-24 10:44:35 -04001585 }
Dan Albertecce5032015-05-18 16:46:31 -07001586 }
Josh Gao13cb8c02018-08-10 14:44:54 -07001587 reconnect_handler.CheckForKicked();
Mike Lockwood01c2c302010-05-24 10:44:35 -04001588}
1589
Josh Gaof2d6af52021-04-27 20:32:02 -07001590void register_usb_transport(std::shared_ptr<Connection> connection, const char* serial,
1591 const char* devpath, unsigned writeable) {
1592 atransport* t = new atransport(writeable ? kCsOffline : kCsNoPerm);
1593 if (serial) {
1594 t->serial = serial;
1595 }
1596 if (devpath) {
1597 t->devpath = devpath;
1598 }
1599
1600 t->SetConnection(std::move(connection));
1601 t->type = kTransportUsb;
1602
1603 {
1604 std::lock_guard<std::recursive_mutex> lock(transport_lock);
1605 pending_list.push_front(t);
1606 }
1607
1608 register_transport(t);
1609}
1610
Josh Gao0d6aa992016-11-22 14:32:34 -08001611void register_usb_transport(usb_handle* usb, const char* serial, const char* devpath,
1612 unsigned writeable) {
Luis Hector Chavez0aeda102018-04-20 10:31:29 -07001613 atransport* t = new atransport(writeable ? kCsOffline : kCsNoPerm);
Dan Albertecce5032015-05-18 16:46:31 -07001614
Josh Gao0d6aa992016-11-22 14:32:34 -08001615 D("transport: %p init'ing for usb_handle %p (sn='%s')", t, usb, serial ? serial : "");
Yabin Cui3cf1b362017-03-10 16:01:01 -08001616 init_usb_transport(t, usb);
Josh Gao0d6aa992016-11-22 14:32:34 -08001617 if (serial) {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -07001618 t->serial = serial;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001619 }
Dan Albertecce5032015-05-18 16:46:31 -07001620
1621 if (devpath) {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -07001622 t->devpath = devpath;
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001623 }
Benoit Goby3f9f9ce2013-03-29 18:22:36 -07001624
Josh Gaoe7daf572016-09-21 12:37:10 -07001625 {
Josh Gaoaaa82f72017-08-17 13:50:51 -07001626 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gaoe7daf572016-09-21 12:37:10 -07001627 pending_list.push_front(t);
1628 }
Benoit Goby3f9f9ce2013-03-29 18:22:36 -07001629
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001630 register_transport(t);
1631}
1632
Dan Albert9a50f4c2015-05-18 16:43:57 -07001633// This should only be used for transports with connection_state == kCsNoPerm.
Josh Gao0d6aa992016-11-22 14:32:34 -08001634void unregister_usb_transport(usb_handle* usb) {
Josh Gaoaaa82f72017-08-17 13:50:51 -07001635 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gao395b86a2018-01-28 20:32:46 -08001636 transport_list.remove_if([usb](atransport* t) {
Josh Gao68f2c382018-12-11 13:11:52 -08001637 return t->GetUsbHandle() == usb && t->GetConnectionState() == kCsNoPerm;
Josh Gao395b86a2018-01-28 20:32:46 -08001638 });
Mike Lockwoode45583f2009-08-08 12:37:44 -04001639}
Shaju Mathew13508c12022-06-25 14:57:31 +00001640
1641// Track reverse:forward commands, so that info can be used to develop
1642// an 'allow-list':
1643// - adb reverse tcp:<device_port> localhost:<host_port> : responds with the
1644// device_port
1645// - adb reverse --remove tcp:<device_port> : responds OKAY
1646// - adb reverse --remove-all : responds OKAY
1647void atransport::UpdateReverseConfig(std::string_view service_addr) {
Shaju Mathew705fa1c2022-12-31 19:36:54 -08001648 fdevent_check_looper();
Shaju Mathew13508c12022-06-25 14:57:31 +00001649 if (!android::base::ConsumePrefix(&service_addr, "reverse:")) {
1650 return;
1651 }
1652
1653 if (android::base::ConsumePrefix(&service_addr, "forward:")) {
1654 // forward:[norebind:]<remote>;<local>
1655 bool norebind = android::base::ConsumePrefix(&service_addr, "norebind:");
1656 auto it = service_addr.find(';');
1657 if (it == std::string::npos) {
1658 return;
1659 }
1660 std::string remote(service_addr.substr(0, it));
1661
1662 if (norebind && reverse_forwards_.find(remote) != reverse_forwards_.end()) {
1663 // This will fail, don't update the map.
1664 LOG(DEBUG) << "ignoring reverse forward that will fail due to norebind";
1665 return;
1666 }
1667
1668 std::string local(service_addr.substr(it + 1));
1669 reverse_forwards_[remote] = local;
1670 } else if (android::base::ConsumePrefix(&service_addr, "killforward:")) {
1671 // kill-forward:<remote>
1672 auto it = service_addr.find(';');
1673 if (it != std::string::npos) {
1674 return;
1675 }
1676 reverse_forwards_.erase(std::string(service_addr));
1677 } else if (service_addr == "killforward-all") {
1678 reverse_forwards_.clear();
1679 } else if (service_addr == "list-forward") {
1680 LOG(DEBUG) << __func__ << " ignoring --list";
1681 } else { // Anything else we need to know about?
1682 LOG(FATAL) << "unhandled reverse service: " << service_addr;
1683 }
1684}
1685
1686// Is this an authorized :connect request?
1687bool atransport::IsReverseConfigured(const std::string& local_addr) {
Shaju Mathew705fa1c2022-12-31 19:36:54 -08001688 fdevent_check_looper();
Shaju Mathew13508c12022-06-25 14:57:31 +00001689 for (const auto& [remote, local] : reverse_forwards_) {
1690 if (local == local_addr) {
1691 return true;
1692 }
1693 }
1694 return false;
1695}
1696
Josh Gao3a34bc52018-10-11 16:33:05 -07001697#endif
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001698
Josh Gao67b683a2017-05-16 15:02:45 -07001699bool check_header(apacket* p, atransport* t) {
Josh Gao0d6aa992016-11-22 14:32:34 -08001700 if (p->msg.magic != (p->msg.command ^ 0xffffffff)) {
Yabin Cui3cf1b362017-03-10 16:01:01 -08001701 VLOG(RWX) << "check_header(): invalid magic command = " << std::hex << p->msg.command
1702 << ", magic = " << p->msg.magic;
Josh Gao67b683a2017-05-16 15:02:45 -07001703 return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001704 }
1705
Josh Gao0d6aa992016-11-22 14:32:34 -08001706 if (p->msg.data_length > t->get_max_payload()) {
1707 VLOG(RWX) << "check_header(): " << p->msg.data_length
1708 << " atransport::max_payload = " << t->get_max_payload();
Josh Gao67b683a2017-05-16 15:02:45 -07001709 return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001710 }
1711
Josh Gao67b683a2017-05-16 15:02:45 -07001712 return true;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001713}
1714
Josh Gaoeac20582016-10-05 19:02:29 -07001715#if ADB_HOST
Joshua Duong64fab752020-01-21 13:19:42 -08001716std::shared_ptr<RSA> atransport::Key() {
1717 if (keys_.empty()) {
1718 return nullptr;
1719 }
1720
1721 std::shared_ptr<RSA> result = keys_[0];
1722 return result;
1723}
1724
Josh Gao22cb70b2016-08-18 22:00:12 -07001725std::shared_ptr<RSA> atransport::NextKey() {
Josh Gaoeb656522018-12-04 01:07:50 -08001726 if (keys_.empty()) {
1727 LOG(INFO) << "fetching keys for transport " << this->serial_name();
1728 keys_ = adb_auth_get_private_keys();
1729
1730 // We should have gotten at least one key: the one that's automatically generated.
1731 CHECK(!keys_.empty());
Joshua Duong64fab752020-01-21 13:19:42 -08001732 } else {
1733 keys_.pop_front();
Josh Gaoeb656522018-12-04 01:07:50 -08001734 }
Elliott Hughes801066a2016-06-29 17:42:01 -07001735
Josh Gaod60bafd2020-06-11 21:07:27 -07001736 return Key();
Elliott Hughes801066a2016-06-29 17:42:01 -07001737}
Josh Gaoeb656522018-12-04 01:07:50 -08001738
1739void atransport::ResetKeys() {
1740 keys_.clear();
1741}
Josh Gaoeac20582016-10-05 19:02:29 -07001742#endif