blob: d17ead7624b702bec1a141eba6c0cab522d6000b [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>
Josh Gao8e7c9722021-06-17 04:19:45 -070060#include "client/usb.h"
Fabien Sanglard3d155b62023-11-30 14:52:40 -080061#include "devices.pb.h"
Josh Gao8e7c9722021-06-17 04:19:45 -070062#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";
Todd Kennedyaff9c672015-11-10 00:03:25 +0000101
Luis Hector Chavezda74b902018-04-17 14:25:04 -0700102namespace {
103
Josh Gao5c47e9f2018-07-31 18:28:32 -0700104#if ADB_HOST
Vince Harron5703eb32021-11-12 12:40:58 -0800105
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700106// Tracks and handles atransport*s that are attempting reconnection.
107class ReconnectHandler {
108 public:
109 ReconnectHandler() = default;
110 ~ReconnectHandler() = default;
111
112 // Starts the ReconnectHandler thread.
113 void Start();
114
115 // Requests the ReconnectHandler thread to stop.
116 void Stop();
117
118 // Adds the atransport* to the queue of reconnect attempts.
119 void TrackTransport(atransport* transport);
120
Josh Gao13cb8c02018-08-10 14:44:54 -0700121 // Wake up the ReconnectHandler thread to have it check for kicked transports.
122 void CheckForKicked();
123
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700124 private:
125 // The main thread loop.
126 void Run();
127
128 // Tracks a reconnection attempt.
129 struct ReconnectAttempt {
130 atransport* transport;
Josh Gaoc4deb392018-07-30 18:51:55 -0700131 std::chrono::steady_clock::time_point reconnect_time;
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700132 size_t attempts_left;
Josh Gaob0182892018-07-31 14:12:59 -0700133
134 bool operator<(const ReconnectAttempt& rhs) const {
Josh Gaod2ea0652018-08-10 14:28:24 -0700135 if (reconnect_time == rhs.reconnect_time) {
136 return reinterpret_cast<uintptr_t>(transport) <
137 reinterpret_cast<uintptr_t>(rhs.transport);
138 }
139 return reconnect_time < rhs.reconnect_time;
Josh Gaob0182892018-07-31 14:12:59 -0700140 }
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700141 };
142
143 // Only retry for up to one minute.
Josh Gao04ef6962020-10-15 18:32:55 -0700144 static constexpr const std::chrono::seconds kDefaultTimeout = 3s;
145 static constexpr const size_t kMaxAttempts = 20;
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700146
147 // Protects all members.
148 std::mutex reconnect_mutex_;
149 bool running_ GUARDED_BY(reconnect_mutex_) = true;
150 std::thread handler_thread_;
151 std::condition_variable reconnect_cv_;
Josh Gaod2ea0652018-08-10 14:28:24 -0700152 std::set<ReconnectAttempt> reconnect_queue_ GUARDED_BY(reconnect_mutex_);
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700153
154 DISALLOW_COPY_AND_ASSIGN(ReconnectHandler);
155};
156
157void ReconnectHandler::Start() {
Shaju Mathew705fa1c2022-12-31 19:36:54 -0800158 fdevent_check_looper();
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700159 handler_thread_ = std::thread(&ReconnectHandler::Run, this);
160}
161
162void ReconnectHandler::Stop() {
Shaju Mathew705fa1c2022-12-31 19:36:54 -0800163 fdevent_check_looper();
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700164 {
165 std::lock_guard<std::mutex> lock(reconnect_mutex_);
166 running_ = false;
167 }
168 reconnect_cv_.notify_one();
169 handler_thread_.join();
170
171 // Drain the queue to free all resources.
172 std::lock_guard<std::mutex> lock(reconnect_mutex_);
173 while (!reconnect_queue_.empty()) {
Josh Gaod2ea0652018-08-10 14:28:24 -0700174 ReconnectAttempt attempt = *reconnect_queue_.begin();
175 reconnect_queue_.erase(reconnect_queue_.begin());
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700176 remove_transport(attempt.transport);
177 }
178}
179
180void ReconnectHandler::TrackTransport(atransport* transport) {
Shaju Mathew705fa1c2022-12-31 19:36:54 -0800181 fdevent_check_looper();
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700182 {
183 std::lock_guard<std::mutex> lock(reconnect_mutex_);
184 if (!running_) return;
Josh Gaob0182892018-07-31 14:12:59 -0700185 // Arbitrary sleep to give adbd time to get ready, if we disconnected because it exited.
186 auto reconnect_time = std::chrono::steady_clock::now() + 250ms;
187 reconnect_queue_.emplace(
188 ReconnectAttempt{transport, reconnect_time, ReconnectHandler::kMaxAttempts});
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700189 }
190 reconnect_cv_.notify_one();
191}
192
Josh Gao13cb8c02018-08-10 14:44:54 -0700193void ReconnectHandler::CheckForKicked() {
194 reconnect_cv_.notify_one();
195}
196
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700197void ReconnectHandler::Run() {
198 while (true) {
199 ReconnectAttempt attempt;
200 {
201 std::unique_lock<std::mutex> lock(reconnect_mutex_);
Josh Gao8aa57d22019-02-12 13:59:03 -0800202 ScopedLockAssertion assume_lock(reconnect_mutex_);
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700203
Josh Gaoc4deb392018-07-30 18:51:55 -0700204 if (!reconnect_queue_.empty()) {
205 // FIXME: libstdc++ (used on Windows) implements condition_variable with
206 // system_clock as its clock, so we're probably hosed if the clock changes,
207 // even if we use steady_clock throughout. This problem goes away once we
208 // switch to libc++.
Josh Gaod2ea0652018-08-10 14:28:24 -0700209 reconnect_cv_.wait_until(lock, reconnect_queue_.begin()->reconnect_time);
Josh Gaoc4deb392018-07-30 18:51:55 -0700210 } else {
211 reconnect_cv_.wait(lock);
212 }
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700213
214 if (!running_) return;
Josh Gao13cb8c02018-08-10 14:44:54 -0700215
216 // Scan the whole list for kicked transports, so that we immediately handle an explicit
217 // disconnect request.
Josh Gao13cb8c02018-08-10 14:44:54 -0700218 for (auto it = reconnect_queue_.begin(); it != reconnect_queue_.end();) {
219 if (it->transport->kicked()) {
220 D("transport %s was kicked. giving up on it.", it->transport->serial.c_str());
221 remove_transport(it->transport);
222 it = reconnect_queue_.erase(it);
223 } else {
224 ++it;
225 }
Josh Gao13cb8c02018-08-10 14:44:54 -0700226 }
227
Josh Gaoc4deb392018-07-30 18:51:55 -0700228 if (reconnect_queue_.empty()) continue;
229
Josh Gao13cb8c02018-08-10 14:44:54 -0700230 // Go back to sleep if we either woke up spuriously, or we were woken up to remove
231 // a kicked transport, and the first transport isn't ready for reconnection yet.
Josh Gaoc4deb392018-07-30 18:51:55 -0700232 auto now = std::chrono::steady_clock::now();
Josh Gaod2ea0652018-08-10 14:28:24 -0700233 if (reconnect_queue_.begin()->reconnect_time > now) {
Josh Gaoc4deb392018-07-30 18:51:55 -0700234 continue;
235 }
236
Josh Gaod2ea0652018-08-10 14:28:24 -0700237 attempt = *reconnect_queue_.begin();
238 reconnect_queue_.erase(reconnect_queue_.begin());
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700239 }
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700240 D("attempting to reconnect %s", attempt.transport->serial.c_str());
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700241
Josh Gaod24580d2018-08-30 11:37:00 -0700242 switch (attempt.transport->Reconnect()) {
243 case ReconnectResult::Retry: {
244 D("attempting to reconnect %s failed.", attempt.transport->serial.c_str());
245 if (attempt.attempts_left == 0) {
246 D("transport %s exceeded the number of retry attempts. giving up on it.",
247 attempt.transport->serial.c_str());
248 remove_transport(attempt.transport);
249 continue;
250 }
251
252 std::lock_guard<std::mutex> lock(reconnect_mutex_);
253 reconnect_queue_.emplace(ReconnectAttempt{
254 attempt.transport,
255 std::chrono::steady_clock::now() + ReconnectHandler::kDefaultTimeout,
256 attempt.attempts_left - 1});
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700257 continue;
258 }
259
Josh Gaod24580d2018-08-30 11:37:00 -0700260 case ReconnectResult::Success:
261 D("reconnection to %s succeeded.", attempt.transport->serial.c_str());
262 register_transport(attempt.transport);
263 continue;
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700264
Josh Gaod24580d2018-08-30 11:37:00 -0700265 case ReconnectResult::Abort:
266 D("cancelling reconnection attempt to %s.", attempt.transport->serial.c_str());
267 remove_transport(attempt.transport);
268 continue;
269 }
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700270 }
271}
272
273static auto& reconnect_handler = *new ReconnectHandler();
274
Josh Gao5c47e9f2018-07-31 18:28:32 -0700275#endif
276
Luis Hector Chavezda74b902018-04-17 14:25:04 -0700277} // namespace
278
Josh Gaob39e4152017-08-16 16:57:01 -0700279TransportId NextTransportId() {
280 static std::atomic<TransportId> next(1);
281 return next++;
282}
283
Josh Gao3a2172b2019-03-28 15:47:44 -0700284void Connection::Reset() {
285 LOG(INFO) << "Connection::Reset(): stopping";
286 Stop();
287}
288
Josh Gao7852ca42021-06-17 04:17:25 -0700289std::string Connection::Serial() const {
290 return transport_ ? transport_->serial_name() : "<unknown>";
291}
292
Josh Gao715fe602018-02-16 13:24:58 -0800293BlockingConnectionAdapter::BlockingConnectionAdapter(std::unique_ptr<BlockingConnection> connection)
294 : underlying_(std::move(connection)) {}
295
296BlockingConnectionAdapter::~BlockingConnectionAdapter() {
Josh Gao7852ca42021-06-17 04:17:25 -0700297 LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): destructing";
Josh Gao715fe602018-02-16 13:24:58 -0800298 Stop();
299}
300
301void BlockingConnectionAdapter::Start() {
Josh Gao13781e82018-04-03 12:55:18 -0700302 std::lock_guard<std::mutex> lock(mutex_);
303 if (started_) {
Josh Gao7852ca42021-06-17 04:17:25 -0700304 LOG(FATAL) << "BlockingConnectionAdapter(" << Serial() << "): started multiple times";
Josh Gao13781e82018-04-03 12:55:18 -0700305 }
306
Joshua Duong64fab752020-01-21 13:19:42 -0800307 StartReadThread();
Josh Gao715fe602018-02-16 13:24:58 -0800308
309 write_thread_ = std::thread([this]() {
Josh Gao7852ca42021-06-17 04:17:25 -0700310 LOG(INFO) << Serial() << ": write thread spawning";
Josh Gao715fe602018-02-16 13:24:58 -0800311 while (true) {
312 std::unique_lock<std::mutex> lock(mutex_);
Josh Gao8aa57d22019-02-12 13:59:03 -0800313 ScopedLockAssertion assume_locked(mutex_);
Josh Gao13781e82018-04-03 12:55:18 -0700314 cv_.wait(lock, [this]() REQUIRES(mutex_) {
315 return this->stopped_ || !this->write_queue_.empty();
316 });
317
Josh Gao715fe602018-02-16 13:24:58 -0800318 if (this->stopped_) {
319 return;
320 }
321
322 std::unique_ptr<apacket> packet = std::move(this->write_queue_.front());
323 this->write_queue_.pop_front();
324 lock.unlock();
325
326 if (!this->underlying_->Write(packet.get())) {
327 break;
328 }
329 }
Josh Gao7852ca42021-06-17 04:17:25 -0700330 std::call_once(this->error_flag_, [this]() { transport_->HandleError("write failed"); });
Josh Gao715fe602018-02-16 13:24:58 -0800331 });
Josh Gao13781e82018-04-03 12:55:18 -0700332
333 started_ = true;
Josh Gao715fe602018-02-16 13:24:58 -0800334}
335
Joshua Duong64fab752020-01-21 13:19:42 -0800336void BlockingConnectionAdapter::StartReadThread() {
337 read_thread_ = std::thread([this]() {
Josh Gao7852ca42021-06-17 04:17:25 -0700338 LOG(INFO) << Serial() << ": read thread spawning";
Joshua Duong64fab752020-01-21 13:19:42 -0800339 while (true) {
340 auto packet = std::make_unique<apacket>();
341 if (!underlying_->Read(packet.get())) {
Josh Gao7852ca42021-06-17 04:17:25 -0700342 PLOG(INFO) << Serial() << ": read failed";
Joshua Duong64fab752020-01-21 13:19:42 -0800343 break;
344 }
345
346 bool got_stls_cmd = false;
347 if (packet->msg.command == A_STLS) {
348 got_stls_cmd = true;
349 }
350
Josh Gao7852ca42021-06-17 04:17:25 -0700351 transport_->HandleRead(std::move(packet));
Joshua Duong64fab752020-01-21 13:19:42 -0800352
353 // If we received the STLS packet, we are about to perform the TLS
354 // handshake. So this read thread must stop and resume after the
355 // handshake completes otherwise this will interfere in the process.
356 if (got_stls_cmd) {
Josh Gao7852ca42021-06-17 04:17:25 -0700357 LOG(INFO) << Serial() << ": Received STLS packet. Stopping read thread.";
Joshua Duong64fab752020-01-21 13:19:42 -0800358 return;
359 }
360 }
Josh Gao7852ca42021-06-17 04:17:25 -0700361 std::call_once(this->error_flag_, [this]() { transport_->HandleError("read failed"); });
Joshua Duong64fab752020-01-21 13:19:42 -0800362 });
363}
364
365bool BlockingConnectionAdapter::DoTlsHandshake(RSA* key, std::string* auth_key) {
366 std::lock_guard<std::mutex> lock(mutex_);
367 if (read_thread_.joinable()) {
368 read_thread_.join();
369 }
370 bool success = this->underlying_->DoTlsHandshake(key, auth_key);
371 StartReadThread();
372 return success;
373}
374
Josh Gao3a2172b2019-03-28 15:47:44 -0700375void BlockingConnectionAdapter::Reset() {
376 {
377 std::lock_guard<std::mutex> lock(mutex_);
378 if (!started_) {
Josh Gao7852ca42021-06-17 04:17:25 -0700379 LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): not started";
Josh Gao3a2172b2019-03-28 15:47:44 -0700380 return;
381 }
382
383 if (stopped_) {
Josh Gao7852ca42021-06-17 04:17:25 -0700384 LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): already stopped";
Josh Gao3a2172b2019-03-28 15:47:44 -0700385 return;
386 }
387 }
388
Josh Gao7852ca42021-06-17 04:17:25 -0700389 LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): resetting";
Josh Gao3a2172b2019-03-28 15:47:44 -0700390 this->underlying_->Reset();
391 Stop();
392}
393
Josh Gao715fe602018-02-16 13:24:58 -0800394void BlockingConnectionAdapter::Stop() {
Josh Gao13781e82018-04-03 12:55:18 -0700395 {
396 std::lock_guard<std::mutex> lock(mutex_);
397 if (!started_) {
Josh Gao7852ca42021-06-17 04:17:25 -0700398 LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): not started";
Josh Gao13781e82018-04-03 12:55:18 -0700399 return;
400 }
Josh Gao715fe602018-02-16 13:24:58 -0800401
Josh Gao13781e82018-04-03 12:55:18 -0700402 if (stopped_) {
Josh Gao7852ca42021-06-17 04:17:25 -0700403 LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): already stopped";
Josh Gao13781e82018-04-03 12:55:18 -0700404 return;
405 }
406
407 stopped_ = true;
408 }
Josh Gao715fe602018-02-16 13:24:58 -0800409
Josh Gao7852ca42021-06-17 04:17:25 -0700410 LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): stopping";
Josh Gao715fe602018-02-16 13:24:58 -0800411
412 this->underlying_->Close();
Josh Gao715fe602018-02-16 13:24:58 -0800413 this->cv_.notify_one();
Josh Gao13781e82018-04-03 12:55:18 -0700414
415 // Move the threads out into locals with the lock taken, and then unlock to let them exit.
416 std::thread read_thread;
417 std::thread write_thread;
418
419 {
420 std::lock_guard<std::mutex> lock(mutex_);
421 read_thread = std::move(read_thread_);
422 write_thread = std::move(write_thread_);
423 }
424
425 read_thread.join();
426 write_thread.join();
Josh Gao715fe602018-02-16 13:24:58 -0800427
Josh Gao7852ca42021-06-17 04:17:25 -0700428 LOG(INFO) << "BlockingConnectionAdapter(" << Serial() << "): stopped";
429 std::call_once(this->error_flag_, [this]() { transport_->HandleError("requested stop"); });
Josh Gao715fe602018-02-16 13:24:58 -0800430}
431
432bool BlockingConnectionAdapter::Write(std::unique_ptr<apacket> packet) {
433 {
Josh Gao13781e82018-04-03 12:55:18 -0700434 std::lock_guard<std::mutex> lock(this->mutex_);
Josh Gao715fe602018-02-16 13:24:58 -0800435 write_queue_.emplace_back(std::move(packet));
436 }
437
438 cv_.notify_one();
439 return true;
440}
441
Joshua Duong64fab752020-01-21 13:19:42 -0800442FdConnection::FdConnection(unique_fd fd) : fd_(std::move(fd)) {}
443
444FdConnection::~FdConnection() {}
445
446bool FdConnection::DispatchRead(void* buf, size_t len) {
447 if (tls_ != nullptr) {
448 // The TlsConnection doesn't allow 0 byte reads
449 if (len == 0) {
450 return true;
451 }
452 return tls_->ReadFully(buf, len);
453 }
454
455 return ReadFdExactly(fd_.get(), buf, len);
456}
457
458bool FdConnection::DispatchWrite(void* buf, size_t len) {
459 if (tls_ != nullptr) {
460 // The TlsConnection doesn't allow 0 byte writes
461 if (len == 0) {
462 return true;
463 }
464 return tls_->WriteFully(std::string_view(reinterpret_cast<const char*>(buf), len));
465 }
466
467 return WriteFdExactly(fd_.get(), buf, len);
468}
469
Josh Gao395b86a2018-01-28 20:32:46 -0800470bool FdConnection::Read(apacket* packet) {
Joshua Duong64fab752020-01-21 13:19:42 -0800471 if (!DispatchRead(&packet->msg, sizeof(amessage))) {
Josh Gao395b86a2018-01-28 20:32:46 -0800472 D("remote local: read terminated (message)");
473 return false;
474 }
475
Josh Gao839b9322018-02-05 18:49:10 -0800476 if (packet->msg.data_length > MAX_PAYLOAD) {
Josh Gaob14756a2018-02-02 14:38:04 -0800477 D("remote local: read overflow (data length = %" PRIu32 ")", packet->msg.data_length);
478 return false;
479 }
480
Josh Gao839b9322018-02-05 18:49:10 -0800481 packet->payload.resize(packet->msg.data_length);
482
Joshua Duong64fab752020-01-21 13:19:42 -0800483 if (!DispatchRead(&packet->payload[0], packet->payload.size())) {
Josh Gao395b86a2018-01-28 20:32:46 -0800484 D("remote local: terminated (data)");
485 return false;
486 }
487
488 return true;
489}
490
491bool FdConnection::Write(apacket* packet) {
Joshua Duong64fab752020-01-21 13:19:42 -0800492 if (!DispatchWrite(&packet->msg, sizeof(packet->msg))) {
Josh Gao395b86a2018-01-28 20:32:46 -0800493 D("remote local: write terminated");
494 return false;
495 }
496
Josh Gao839b9322018-02-05 18:49:10 -0800497 if (packet->msg.data_length) {
Joshua Duong64fab752020-01-21 13:19:42 -0800498 if (!DispatchWrite(&packet->payload[0], packet->msg.data_length)) {
Josh Gao839b9322018-02-05 18:49:10 -0800499 D("remote local: write terminated");
500 return false;
501 }
502 }
503
Josh Gao395b86a2018-01-28 20:32:46 -0800504 return true;
505}
506
Joshua Duong64fab752020-01-21 13:19:42 -0800507bool FdConnection::DoTlsHandshake(RSA* key, std::string* auth_key) {
508 bssl::UniquePtr<EVP_PKEY> evp_pkey(EVP_PKEY_new());
509 if (!EVP_PKEY_set1_RSA(evp_pkey.get(), key)) {
510 LOG(ERROR) << "EVP_PKEY_set1_RSA failed";
511 return false;
512 }
513 auto x509 = GenerateX509Certificate(evp_pkey.get());
514 auto x509_str = X509ToPEMString(x509.get());
515 auto evp_str = Key::ToPEMString(evp_pkey.get());
Joshua Duongdd19e862020-03-24 09:50:59 -0700516
Yurii Zubrytskyi3c0574f2020-03-26 18:16:36 -0700517 int osh = cast_handle_to_int(adb_get_os_handle(fd_));
Joshua Duong64fab752020-01-21 13:19:42 -0800518#if ADB_HOST
Joshua Duong77b8ff32020-04-16 15:58:19 -0700519 tls_ = TlsConnection::Create(TlsConnection::Role::Client, x509_str, evp_str, osh);
Joshua Duong64fab752020-01-21 13:19:42 -0800520#else
Joshua Duong77b8ff32020-04-16 15:58:19 -0700521 tls_ = TlsConnection::Create(TlsConnection::Role::Server, x509_str, evp_str, osh);
Joshua Duong64fab752020-01-21 13:19:42 -0800522#endif
Joshua Duong64fab752020-01-21 13:19:42 -0800523 CHECK(tls_);
524#if ADB_HOST
525 // TLS 1.3 gives the client no message if the server rejected the
526 // certificate. This will enable a check in the tls connection to check
527 // whether the client certificate got rejected. Note that this assumes
528 // that, on handshake success, the server speaks first.
529 tls_->EnableClientPostHandshakeCheck(true);
530 // Add callback to set the certificate when server issues the
531 // CertificateRequest.
532 tls_->SetCertificateCallback(adb_tls_set_certificate);
533 // Allow any server certificate
534 tls_->SetCertVerifyCallback([](X509_STORE_CTX*) { return 1; });
535#else
536 // Add callback to check certificate against a list of known public keys
537 tls_->SetCertVerifyCallback(
538 [auth_key](X509_STORE_CTX* ctx) { return adbd_tls_verify_cert(ctx, auth_key); });
539 // Add the list of allowed client CA issuers
540 auto ca_list = adbd_tls_client_ca_list();
541 tls_->SetClientCAList(ca_list.get());
542#endif
543
544 auto err = tls_->DoHandshake();
545 if (err == TlsError::Success) {
546 return true;
547 }
548
549 tls_.reset();
550 return false;
551}
552
Josh Gao395b86a2018-01-28 20:32:46 -0800553void FdConnection::Close() {
554 adb_shutdown(fd_.get());
555 fd_.reset();
556}
557
Josh Gao67ac3792016-10-06 13:31:44 -0700558void send_packet(apacket* p, atransport* t) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800559 p->msg.magic = p->msg.command ^ 0xffffffff;
Tim Murrayee7b44d2017-12-07 11:40:00 -0800560 // compute a checksum for connection/auth packets for compatibility reasons
561 if (t->get_protocol_version() >= A_VERSION_SKIP_CHECKSUM) {
562 p->msg.data_check = 0;
563 } else {
564 p->msg.data_check = calculate_apacket_checksum(p);
565 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800566
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700567 VLOG(TRANSPORT) << dump_packet(t->serial.c_str(), "to remote", p);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800568
Yi Kong86e67182018-07-13 18:15:16 -0700569 if (t == nullptr) {
Elliott Hughese64126b2018-10-19 13:59:44 -0700570 LOG(FATAL) << "Transport is null";
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800571 }
572
Josh Gao715fe602018-02-16 13:24:58 -0800573 if (t->Write(p) != 0) {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700574 D("%s: failed to enqueue packet, closing transport", t->serial.c_str());
Josh Gao715fe602018-02-16 13:24:58 -0800575 t->Kick();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800576 }
577}
578
Josh Gao3a2172b2019-03-28 15:47:44 -0700579void kick_transport(atransport* t, bool reset) {
Josh Gaoaaa82f72017-08-17 13:50:51 -0700580 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Yabin Cuid78ed222016-04-05 13:50:44 -0700581 // As kick_transport() can be called from threads without guarantee that t is valid,
582 // check if the transport is in transport_list first.
Josh Gaob39e4152017-08-16 16:57:01 -0700583 //
584 // TODO(jmgao): WTF? Is this actually true?
Yabin Cuid78ed222016-04-05 13:50:44 -0700585 if (std::find(transport_list.begin(), transport_list.end(), t) != transport_list.end()) {
Josh Gao3a2172b2019-03-28 15:47:44 -0700586 if (reset) {
587 t->Reset();
588 } else {
589 t->Kick();
590 }
Yabin Cuid78ed222016-04-05 13:50:44 -0700591 }
Josh Gao13cb8c02018-08-10 14:44:54 -0700592
593#if ADB_HOST
594 reconnect_handler.CheckForKicked();
595#endif
Yabin Cui4d64fd82015-08-27 12:03:11 -0700596}
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800597
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800598#if ADB_HOST
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800599
600/* this adds support required by the 'track-devices' service.
601 * this is used to send the content of "list_transport" to any
602 * number of client connections that want it through a single
603 * live TCP connection
604 */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800605struct device_tracker {
Josh Gao0d6aa992016-11-22 14:32:34 -0800606 asocket socket;
Josh Gao5cb76ce2018-02-12 17:24:00 -0800607 bool update_needed = false;
Fabien Sanglard3d155b62023-11-30 14:52:40 -0800608 TrackerOutputType output_type = SHORT_TEXT;
Josh Gao5cb76ce2018-02-12 17:24:00 -0800609 device_tracker* next = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800610};
611
612/* linked list of all device trackers */
Josh Gao0d6aa992016-11-22 14:32:34 -0800613static device_tracker* device_tracker_list;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800614
Josh Gao0d6aa992016-11-22 14:32:34 -0800615static void device_tracker_remove(device_tracker* tracker) {
616 device_tracker** pnode = &device_tracker_list;
617 device_tracker* node = *pnode;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800618
Josh Gaoaaa82f72017-08-17 13:50:51 -0700619 std::lock_guard<std::recursive_mutex> lock(transport_lock);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800620 while (node) {
621 if (node == tracker) {
622 *pnode = node->next;
623 break;
624 }
625 pnode = &node->next;
Josh Gao0d6aa992016-11-22 14:32:34 -0800626 node = *pnode;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800627 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800628}
629
Josh Gao0d6aa992016-11-22 14:32:34 -0800630static void device_tracker_close(asocket* socket) {
631 device_tracker* tracker = (device_tracker*)socket;
632 asocket* peer = socket->peer;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800633
Josh Gao0d6aa992016-11-22 14:32:34 -0800634 D("device tracker %p removed", tracker);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800635 if (peer) {
Yi Kong86e67182018-07-13 18:15:16 -0700636 peer->peer = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800637 peer->close(peer);
638 }
639 device_tracker_remove(tracker);
Josh Gao5cb76ce2018-02-12 17:24:00 -0800640 delete tracker;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800641}
642
Josh Gaocd2a5292018-03-07 16:52:28 -0800643static int device_tracker_enqueue(asocket* socket, apacket::payload_type) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800644 /* you can't read from a device tracker, close immediately */
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800645 device_tracker_close(socket);
646 return -1;
647}
648
Elliott Hughes88b4c852015-04-30 17:32:03 -0700649static int device_tracker_send(device_tracker* tracker, const std::string& string) {
Elliott Hughes88b4c852015-04-30 17:32:03 -0700650 asocket* peer = tracker->socket.peer;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800651
Josh Gaocd2a5292018-03-07 16:52:28 -0800652 apacket::payload_type data;
Josh Gaoa7d9d712018-02-01 13:17:50 -0800653 data.resize(4 + string.size());
654 char buf[5];
655 snprintf(buf, sizeof(buf), "%04x", static_cast<int>(string.size()));
656 memcpy(&data[0], buf, 4);
657 memcpy(&data[4], string.data(), string.size());
658 return peer->enqueue(peer, std::move(data));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800659}
660
Elliott Hughes88b4c852015-04-30 17:32:03 -0700661static void device_tracker_ready(asocket* socket) {
662 device_tracker* tracker = reinterpret_cast<device_tracker*>(socket);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800663
Elliott Hughes88b4c852015-04-30 17:32:03 -0700664 // We want to send the device list when the tracker connects
665 // for the first time, even if no update occurred.
Josh Gao32124632017-08-14 18:57:54 -0700666 if (tracker->update_needed) {
667 tracker->update_needed = false;
Fabien Sanglard3d155b62023-11-30 14:52:40 -0800668 device_tracker_send(tracker, list_transports(tracker->output_type));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800669 }
670}
671
Fabien Sanglard3d155b62023-11-30 14:52:40 -0800672asocket* create_device_tracker(TrackerOutputType output_type) {
Josh Gao5cb76ce2018-02-12 17:24:00 -0800673 device_tracker* tracker = new device_tracker();
Elliott Hughese64126b2018-10-19 13:59:44 -0700674 if (tracker == nullptr) LOG(FATAL) << "cannot allocate device tracker";
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800675
Josh Gao0d6aa992016-11-22 14:32:34 -0800676 D("device tracker %p created", tracker);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800677
678 tracker->socket.enqueue = device_tracker_enqueue;
Josh Gao0d6aa992016-11-22 14:32:34 -0800679 tracker->socket.ready = device_tracker_ready;
680 tracker->socket.close = device_tracker_close;
Josh Gao32124632017-08-14 18:57:54 -0700681 tracker->update_needed = true;
Fabien Sanglard3d155b62023-11-30 14:52:40 -0800682 tracker->output_type = output_type;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800683
Josh Gao0d6aa992016-11-22 14:32:34 -0800684 tracker->next = device_tracker_list;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800685 device_tracker_list = tracker;
686
687 return &tracker->socket;
688}
689
Josh Gao1e3bf732017-05-03 22:37:10 -0700690// Check if all of the USB transports are connected.
691bool iterate_transports(std::function<bool(const atransport*)> fn) {
Josh Gaoaaa82f72017-08-17 13:50:51 -0700692 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gao1e3bf732017-05-03 22:37:10 -0700693 for (const auto& t : transport_list) {
694 if (!fn(t)) {
695 return false;
696 }
697 }
698 for (const auto& t : pending_list) {
699 if (!fn(t)) {
700 return false;
701 }
702 }
703 return true;
704}
705
Elliott Hughes88b4c852015-04-30 17:32:03 -0700706// Call this function each time the transport list has changed.
707void update_transports() {
Josh Gao1e3bf732017-05-03 22:37:10 -0700708 update_transport_status();
709
710 // Notify `adb track-devices` clients.
Elliott Hughes88b4c852015-04-30 17:32:03 -0700711 device_tracker* tracker = device_tracker_list;
712 while (tracker != nullptr) {
713 device_tracker* next = tracker->next;
714 // This may destroy the tracker if the connection is closed.
Fabien Sanglard3d155b62023-11-30 14:52:40 -0800715 device_tracker_send(tracker, list_transports(tracker->output_type));
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800716 tracker = next;
717 }
718}
Elliott Hughes88b4c852015-04-30 17:32:03 -0700719
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800720#else
Elliott Hughes88b4c852015-04-30 17:32:03 -0700721
722void update_transports() {
723 // Nothing to do on the device side.
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800724}
Elliott Hughes88b4c852015-04-30 17:32:03 -0700725
Josh Gao0d6aa992016-11-22 14:32:34 -0800726#endif // ADB_HOST
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800727
Josh Gao8e7c9722021-06-17 04:19:45 -0700728#if ADB_HOST
Shaju Mathew36c85202023-06-13 08:00:16 -0700729static bool usb_devices_start_detached() {
Josh Gao8e7c9722021-06-17 04:19:45 -0700730 static const char* env = getenv("ADB_LIBUSB_START_DETACHED");
731 static bool result = env && strcmp("1", env) == 0;
732 return should_use_libusb() && result;
Josh Gao8e7c9722021-06-17 04:19:45 -0700733}
Shaju Mathew36c85202023-06-13 08:00:16 -0700734#endif
Josh Gao8e7c9722021-06-17 04:19:45 -0700735
Fabien Sanglard4292ce52023-10-19 18:01:07 -0700736static void fdevent_unregister_transport(atransport* t) {
737 D("transport: %s deleting", t->serial.c_str());
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800738
Fabien Sanglard4292ce52023-10-19 18:01:07 -0700739 {
740 std::lock_guard<std::recursive_mutex> lock(transport_lock);
741 transport_list.remove(t);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800742 }
743
Fabien Sanglard4292ce52023-10-19 18:01:07 -0700744 delete t;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800745
Fabien Sanglard4292ce52023-10-19 18:01:07 -0700746 update_transports();
747}
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800748
Fabien Sanglard4292ce52023-10-19 18:01:07 -0700749static void fdevent_register_transport(atransport* t) {
Mike Lockwoode45583f2009-08-08 12:37:44 -0400750 /* don't create transport threads for inaccessible devices */
Yabin Cui3cf1b362017-03-10 16:01:01 -0800751 if (t->GetConnectionState() != kCsNoPerm) {
Josh Gao7852ca42021-06-17 04:17:25 -0700752 t->connection()->SetTransport(t);
Josh Gao8e7c9722021-06-17 04:19:45 -0700753
Shaju Mathew36c85202023-06-13 08:00:16 -0700754 if (t->type == kTransportUsb
755#if ADB_HOST
756 && usb_devices_start_detached() // -d setting propagated from the
757 // host device, hence n/a on-device.
758#endif
759 ) {
Josh Gao8e7c9722021-06-17 04:19:45 -0700760 t->SetConnectionState(kCsDetached);
761 } else {
762 t->connection()->Start();
Josh Gao715fe602018-02-16 13:24:58 -0800763#if ADB_HOST
Josh Gao8e7c9722021-06-17 04:19:45 -0700764 send_connect(t);
Josh Gao715fe602018-02-16 13:24:58 -0800765#endif
Josh Gao8e7c9722021-06-17 04:19:45 -0700766 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800767 }
768
Josh Gaoe7daf572016-09-21 12:37:10 -0700769 {
Josh Gaoaaa82f72017-08-17 13:50:51 -0700770 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700771 auto it = std::find(pending_list.begin(), pending_list.end(), t);
772 if (it != pending_list.end()) {
773 pending_list.remove(t);
774 transport_list.push_front(t);
775 }
Josh Gaoe7daf572016-09-21 12:37:10 -0700776 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800777
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800778 update_transports();
779}
780
Josh Gao5c47e9f2018-07-31 18:28:32 -0700781#if ADB_HOST
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700782void init_reconnect_handler(void) {
783 reconnect_handler.Start();
784}
Josh Gao5c47e9f2018-07-31 18:28:32 -0700785#endif
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700786
Josh Gao165460f2017-05-09 13:43:35 -0700787void kick_all_transports() {
Josh Gao5c47e9f2018-07-31 18:28:32 -0700788#if ADB_HOST
Luis Hector Chavez0aeda102018-04-20 10:31:29 -0700789 reconnect_handler.Stop();
Josh Gao5c47e9f2018-07-31 18:28:32 -0700790#endif
Josh Gao165460f2017-05-09 13:43:35 -0700791 // To avoid only writing part of a packet to a transport after exit, kick all transports.
Josh Gaoaaa82f72017-08-17 13:50:51 -0700792 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gao165460f2017-05-09 13:43:35 -0700793 for (auto t : transport_list) {
794 t->Kick();
795 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800796}
797
Joshua Duong64fab752020-01-21 13:19:42 -0800798void kick_all_tcp_tls_transports() {
799 std::lock_guard<std::recursive_mutex> lock(transport_lock);
800 for (auto t : transport_list) {
801 if (t->IsTcpDevice() && t->use_tls) {
802 t->Kick();
803 }
804 }
805}
806
807#if !ADB_HOST
808void kick_all_transports_by_auth_key(std::string_view auth_key) {
809 std::lock_guard<std::recursive_mutex> lock(transport_lock);
810 for (auto t : transport_list) {
811 if (auth_key == t->auth_key) {
812 t->Kick();
813 }
814 }
815}
816#endif
817
Josh Gao3a34bc52018-10-11 16:33:05 -0700818void register_transport(atransport* transport) {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700819 D("transport: %s registered", transport->serial.c_str());
Fabien Sanglard4292ce52023-10-19 18:01:07 -0700820 fdevent_run_on_looper([=]() { fdevent_register_transport(transport); });
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800821}
822
Josh Gao0d6aa992016-11-22 14:32:34 -0800823static void remove_transport(atransport* transport) {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700824 D("transport: %s removed", transport->serial.c_str());
Fabien Sanglard4292ce52023-10-19 18:01:07 -0700825 fdevent_run_on_looper([=]() { fdevent_unregister_transport(transport); });
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800826}
827
Josh Gao14ed9f92019-12-09 13:45:31 -0800828static void transport_destroy(atransport* t) {
Shaju Mathew705fa1c2022-12-31 19:36:54 -0800829 fdevent_check_looper();
Yabin Cui4d64fd82015-08-27 12:03:11 -0700830 CHECK(t != nullptr);
Josh Gaoe7daf572016-09-21 12:37:10 -0700831
Josh Gao4d299742017-09-13 13:40:57 -0700832 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gao14ed9f92019-12-09 13:45:31 -0800833 LOG(INFO) << "destroying transport " << t->serial_name();
834 t->connection()->Stop();
Josh Gao5c47e9f2018-07-31 18:28:32 -0700835#if ADB_HOST
Josh Gao14ed9f92019-12-09 13:45:31 -0800836 if (t->IsTcpDevice() && !t->kicked()) {
837 D("transport: %s destroy (attempting reconnection)", t->serial.c_str());
Josh Gaoeb656522018-12-04 01:07:50 -0800838
Josh Gao14ed9f92019-12-09 13:45:31 -0800839 // We need to clear the transport's keys, so that on the next connection, it tries
840 // again from the beginning.
841 t->ResetKeys();
842 reconnect_handler.TrackTransport(t);
843 return;
844 }
Josh Gao5c47e9f2018-07-31 18:28:32 -0700845#endif
846
Josh Gao14ed9f92019-12-09 13:45:31 -0800847 D("transport: %s destroy (kicking and closing)", t->serial.c_str());
848 remove_transport(t);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800849}
850
Josh Gao65d18e22020-04-22 20:57:26 -0700851#if ADB_HOST
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700852static int qual_match(const std::string& to_test, const char* prefix, const std::string& qual,
Josh Gao0d6aa992016-11-22 14:32:34 -0800853 bool sanitize_qual) {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700854 if (to_test.empty()) /* Return true if both the qual and to_test are empty strings. */
855 return qual.empty();
Scott Anderson27042382012-05-30 18:11:27 -0700856
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700857 if (qual.empty()) return 0;
Scott Anderson27042382012-05-30 18:11:27 -0700858
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700859 const char* ptr = to_test.c_str();
Scott Anderson27042382012-05-30 18:11:27 -0700860 if (prefix) {
861 while (*prefix) {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700862 if (*prefix++ != *ptr++) return 0;
Scott Anderson27042382012-05-30 18:11:27 -0700863 }
864 }
865
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700866 for (char ch : qual) {
Josh Gao0d6aa992016-11-22 14:32:34 -0800867 if (sanitize_qual && !isalnum(ch)) ch = '_';
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700868 if (ch != *ptr++) return 0;
Scott Anderson27042382012-05-30 18:11:27 -0700869 }
870
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -0700871 /* Everything matched so far. Return true if *ptr is a NUL. */
872 return !*ptr;
Scott Anderson27042382012-05-30 18:11:27 -0700873}
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800874
Vince Harron5703eb32021-11-12 12:40:58 -0800875// Contains either a device serial string or a USB device address like "usb:2-6"
876const char* __transport_server_one_device = nullptr;
877
878void transport_set_one_device(const char* adb_one_device) {
879 __transport_server_one_device = adb_one_device;
880}
881
882const char* transport_get_one_device() {
883 return __transport_server_one_device;
884}
885
886bool transport_server_owns_device(std::string_view serial) {
887 if (!__transport_server_one_device) {
888 // If the server doesn't own one device, server owns all devices.
889 return true;
890 }
891 return serial.compare(__transport_server_one_device) == 0;
892}
893
894bool transport_server_owns_device(std::string_view dev_path, std::string_view serial) {
895 if (!__transport_server_one_device) {
896 // If the server doesn't own one device, server owns all devices.
897 return true;
898 }
899 return serial.compare(__transport_server_one_device) == 0 ||
900 dev_path.compare(__transport_server_one_device) == 0;
901}
902
Josh Gaob39e4152017-08-16 16:57:01 -0700903atransport* acquire_one_transport(TransportType type, const char* serial, TransportId transport_id,
904 bool* is_ambiguous, std::string* error_out,
905 bool accept_any_state) {
Elliott Hughes67943d12015-10-07 14:55:10 -0700906 atransport* result = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800907
Josh Gaob39e4152017-08-16 16:57:01 -0700908 if (transport_id != 0) {
Josh Gao7852ca42021-06-17 04:17:25 -0700909 *error_out = android::base::StringPrintf("no device with transport id '%" PRIu64 "'",
910 transport_id);
Josh Gaob39e4152017-08-16 16:57:01 -0700911 } else if (serial) {
Elliott Hughes67943d12015-10-07 14:55:10 -0700912 *error_out = android::base::StringPrintf("device '%s' not found", serial);
913 } else if (type == kTransportLocal) {
914 *error_out = "no emulators found";
915 } else if (type == kTransportAny) {
916 *error_out = "no devices/emulators found";
917 } else {
918 *error_out = "no devices found";
919 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800920
Josh Gaoaaa82f72017-08-17 13:50:51 -0700921 std::unique_lock<std::recursive_mutex> lock(transport_lock);
Elliott Hughes67943d12015-10-07 14:55:10 -0700922 for (const auto& t : transport_list) {
Yabin Cui3cf1b362017-03-10 16:01:01 -0800923 if (t->GetConnectionState() == kCsNoPerm) {
David Pursell6e5c7eb2015-12-02 15:14:31 -0800924 *error_out = UsbNoPermissionsLongHelpText();
Mike Lockwoodadc16b32009-08-08 13:53:16 -0400925 continue;
926 }
Mike Lockwoode45583f2009-08-08 12:37:44 -0400927
Josh Gaob39e4152017-08-16 16:57:01 -0700928 if (transport_id) {
929 if (t->id == transport_id) {
930 result = t;
931 break;
932 }
933 } else if (serial) {
David Pursellc929c6f2016-03-01 08:58:26 -0800934 if (t->MatchesTarget(serial)) {
Scott Anderson27042382012-05-30 18:11:27 -0700935 if (result) {
Elliott Hughes73abffa2022-06-09 16:30:24 +0000936 *error_out = "more than one device with serial "s + serial;
Elliott Hughes67943d12015-10-07 14:55:10 -0700937 if (is_ambiguous) *is_ambiguous = true;
938 result = nullptr;
Scott Anderson27042382012-05-30 18:11:27 -0700939 break;
940 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800941 result = t;
Scott Anderson6dfaf4b2012-04-20 11:21:14 -0700942 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800943 } else {
Elliott Hughes3aec2ba2015-05-05 13:10:43 -0700944 if (type == kTransportUsb && t->type == kTransportUsb) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800945 if (result) {
Elliott Hughes73abffa2022-06-09 16:30:24 +0000946 *error_out = "more than one USB device";
Elliott Hughes67943d12015-10-07 14:55:10 -0700947 if (is_ambiguous) *is_ambiguous = true;
948 result = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800949 break;
950 }
951 result = t;
Elliott Hughes3aec2ba2015-05-05 13:10:43 -0700952 } else if (type == kTransportLocal && t->type == kTransportLocal) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800953 if (result) {
Elliott Hughes24f52762015-06-23 13:00:32 -0700954 *error_out = "more than one emulator";
Elliott Hughes67943d12015-10-07 14:55:10 -0700955 if (is_ambiguous) *is_ambiguous = true;
956 result = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800957 break;
958 }
959 result = t;
Elliott Hughes3aec2ba2015-05-05 13:10:43 -0700960 } else if (type == kTransportAny) {
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800961 if (result) {
Elliott Hughes24f52762015-06-23 13:00:32 -0700962 *error_out = "more than one device/emulator";
Elliott Hughes67943d12015-10-07 14:55:10 -0700963 if (is_ambiguous) *is_ambiguous = true;
964 result = nullptr;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800965 break;
966 }
967 result = t;
968 }
969 }
970 }
Josh Gaoe7daf572016-09-21 12:37:10 -0700971 lock.unlock();
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -0800972
Josh Gao7a7c5cb2018-05-04 16:04:49 -0700973 if (result && !accept_any_state) {
974 // The caller requires an active transport.
975 // Make sure that we're actually connected.
976 ConnectionState state = result->GetConnectionState();
977 switch (state) {
978 case kCsConnecting:
979 *error_out = "device still connecting";
980 result = nullptr;
981 break;
Benoit Goby3f9f9ce2013-03-29 18:22:36 -0700982
Josh Gao7a7c5cb2018-05-04 16:04:49 -0700983 case kCsAuthorizing:
984 *error_out = "device still authorizing";
985 result = nullptr;
986 break;
987
988 case kCsUnauthorized: {
989 *error_out = "device unauthorized.\n";
990 char* ADB_VENDOR_KEYS = getenv("ADB_VENDOR_KEYS");
991 *error_out += "This adb server's $ADB_VENDOR_KEYS is ";
992 *error_out += ADB_VENDOR_KEYS ? ADB_VENDOR_KEYS : "not set";
993 *error_out += "\n";
994 *error_out += "Try 'adb kill-server' if that seems wrong.\n";
995 *error_out += "Otherwise check for a confirmation dialog on your device.";
996 result = nullptr;
997 break;
998 }
999
1000 case kCsOffline:
1001 *error_out = "device offline";
1002 result = nullptr;
1003 break;
1004
1005 default:
1006 break;
1007 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001008 }
1009
1010 if (result) {
Elliott Hughes24f52762015-06-23 13:00:32 -07001011 *error_out = "success";
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001012 }
1013
1014 return result;
1015}
1016
Luis Hector Chavezda74b902018-04-17 14:25:04 -07001017bool ConnectionWaitable::WaitForConnection(std::chrono::milliseconds timeout) {
1018 std::unique_lock<std::mutex> lock(mutex_);
Josh Gao8aa57d22019-02-12 13:59:03 -08001019 ScopedLockAssertion assume_locked(mutex_);
Luis Hector Chavezda74b902018-04-17 14:25:04 -07001020 return cv_.wait_for(lock, timeout, [&]() REQUIRES(mutex_) {
1021 return connection_established_ready_;
1022 }) && connection_established_;
1023}
1024
1025void ConnectionWaitable::SetConnectionEstablished(bool success) {
1026 {
1027 std::lock_guard<std::mutex> lock(mutex_);
1028 if (connection_established_ready_) return;
1029 connection_established_ready_ = true;
1030 connection_established_ = success;
1031 D("connection established with %d", success);
1032 }
1033 cv_.notify_one();
1034}
Josh Gao65d18e22020-04-22 20:57:26 -07001035#endif
Luis Hector Chavezda74b902018-04-17 14:25:04 -07001036
1037atransport::~atransport() {
Josh Gao65d18e22020-04-22 20:57:26 -07001038#if ADB_HOST
Luis Hector Chavezda74b902018-04-17 14:25:04 -07001039 // If the connection callback had not been run before, run it now.
1040 SetConnectionEstablished(false);
Josh Gao65d18e22020-04-22 20:57:26 -07001041#endif
Luis Hector Chavezda74b902018-04-17 14:25:04 -07001042}
1043
Yabin Cui3cf1b362017-03-10 16:01:01 -08001044int atransport::Write(apacket* p) {
Luis Hector Chavez3c7881d2018-04-25 08:56:41 -07001045 return this->connection()->Write(std::unique_ptr<apacket>(p)) ? 0 : -1;
Yabin Cui3cf1b362017-03-10 16:01:01 -08001046}
1047
Josh Gao3a2172b2019-03-28 15:47:44 -07001048void atransport::Reset() {
1049 if (!kicked_.exchange(true)) {
1050 LOG(INFO) << "resetting transport " << this << " " << this->serial;
1051 this->connection()->Reset();
1052 }
1053}
1054
Yabin Cuif2a9f9b2016-04-18 11:22:34 -07001055void atransport::Kick() {
Luis Hector Chavez0aeda102018-04-20 10:31:29 -07001056 if (!kicked_.exchange(true)) {
Josh Gao3a2172b2019-03-28 15:47:44 -07001057 LOG(INFO) << "kicking transport " << this << " " << this->serial;
Luis Hector Chavez3c7881d2018-04-25 08:56:41 -07001058 this->connection()->Stop();
Yabin Cuif2a9f9b2016-04-18 11:22:34 -07001059 }
1060}
1061
Yabin Cui3cf1b362017-03-10 16:01:01 -08001062ConnectionState atransport::GetConnectionState() const {
1063 return connection_state_;
1064}
1065
1066void atransport::SetConnectionState(ConnectionState state) {
Shaju Mathew705fa1c2022-12-31 19:36:54 -08001067 fdevent_check_looper();
Yabin Cui3cf1b362017-03-10 16:01:01 -08001068 connection_state_ = state;
Joshua Duongccde5202021-03-08 15:01:48 -08001069 update_transports();
Yabin Cui3cf1b362017-03-10 16:01:01 -08001070}
1071
Josh Gao8e7c9722021-06-17 04:19:45 -07001072#if ADB_HOST
1073bool atransport::Attach(std::string* error) {
1074 D("%s: attach", serial.c_str());
Shaju Mathew705fa1c2022-12-31 19:36:54 -08001075 fdevent_check_looper();
Josh Gao8e7c9722021-06-17 04:19:45 -07001076
1077 if (!should_use_libusb()) {
1078 *error = "attach/detach only implemented for libusb backend";
1079 return false;
1080 }
1081
1082 if (GetConnectionState() != ConnectionState::kCsDetached) {
1083 *error = android::base::StringPrintf("transport %s is not detached", serial.c_str());
1084 return false;
1085 }
1086
1087 ResetKeys();
1088
1089 {
1090 std::lock_guard<std::mutex> lock(mutex_);
1091 if (!connection_->Attach(error)) {
1092 return false;
1093 }
1094 }
1095
1096 send_connect(this);
1097 return true;
1098}
1099
1100bool atransport::Detach(std::string* error) {
1101 D("%s: detach", serial.c_str());
Shaju Mathew705fa1c2022-12-31 19:36:54 -08001102 fdevent_check_looper();
Josh Gao8e7c9722021-06-17 04:19:45 -07001103
1104 if (!should_use_libusb()) {
1105 *error = "attach/detach only implemented for libusb backend";
1106 return false;
1107 }
1108
1109 if (GetConnectionState() == ConnectionState::kCsDetached) {
1110 *error = android::base::StringPrintf("transport %s is already detached", serial.c_str());
1111 return false;
1112 }
1113
1114 handle_offline(this);
1115
1116 {
1117 std::lock_guard<std::mutex> lock(mutex_);
1118 if (!connection_->Detach(error)) {
1119 return false;
1120 }
1121 }
1122
1123 this->SetConnectionState(kCsDetached);
1124 return true;
1125}
Shaju Mathew36c85202023-06-13 08:00:16 -07001126#endif // ADB_HOST
Josh Gao8e7c9722021-06-17 04:19:45 -07001127
Josh Gaof2d6af52021-04-27 20:32:02 -07001128void atransport::SetConnection(std::shared_ptr<Connection> connection) {
Luis Hector Chavez3c7881d2018-04-25 08:56:41 -07001129 std::lock_guard<std::mutex> lock(mutex_);
1130 connection_ = std::shared_ptr<Connection>(std::move(connection));
1131}
1132
Josh Gao7852ca42021-06-17 04:17:25 -07001133bool atransport::HandleRead(std::unique_ptr<apacket> p) {
1134 if (!check_header(p.get(), this)) {
1135 D("%s: remote read: bad header", serial.c_str());
1136 return false;
1137 }
1138
1139 VLOG(TRANSPORT) << dump_packet(serial.c_str(), "from remote", p.get());
1140 apacket* packet = p.release();
1141
Shaju Mathew705fa1c2022-12-31 19:36:54 -08001142 // This needs to run on the looper thread since the associated fdevent
Shaju Mathew13508c12022-06-25 14:57:31 +00001143 // message pump exists in that context.
Shaju Mathew705fa1c2022-12-31 19:36:54 -08001144 fdevent_run_on_looper([packet, this]() { handle_packet(packet, this); });
Shaju Mathew13508c12022-06-25 14:57:31 +00001145
Josh Gao7852ca42021-06-17 04:17:25 -07001146 return true;
1147}
1148
1149void atransport::HandleError(const std::string& error) {
1150 LOG(INFO) << serial_name() << ": connection terminated: " << error;
Shaju Mathew705fa1c2022-12-31 19:36:54 -08001151 fdevent_run_on_looper([this]() {
Josh Gao7852ca42021-06-17 04:17:25 -07001152 handle_offline(this);
1153 transport_destroy(this);
1154 });
1155}
1156
Tamas Berghammera1c60c02015-07-13 19:12:28 +01001157void atransport::update_version(int version, size_t payload) {
1158 protocol_version = std::min(version, A_VERSION);
1159 max_payload = std::min(payload, MAX_PAYLOAD);
1160}
1161
1162int atransport::get_protocol_version() const {
1163 return protocol_version;
1164}
1165
Joshua Duong64fab752020-01-21 13:19:42 -08001166int atransport::get_tls_version() const {
1167 return tls_version;
1168}
1169
Tamas Berghammera1c60c02015-07-13 19:12:28 +01001170size_t atransport::get_max_payload() const {
1171 return max_payload;
1172}
1173
Josh Gaobd1f3002021-12-29 21:15:12 -08001174#if ADB_HOST
1175static bool delayed_ack_enabled() {
1176 static const char* env = getenv("ADB_DELAYED_ACK");
1177 static bool result = env && strcmp(env, "1") == 0;
1178 return result;
1179}
1180#endif
1181
Dan Albertbe8e54b2015-05-18 13:06:53 -07001182const FeatureSet& supported_features() {
Josh Gaobd1f3002021-12-29 21:15:12 -08001183 static const android::base::NoDestructor<FeatureSet> features([]() {
1184 // Increment ADB_SERVER_VERSION when adding a feature that adbd needs
1185 // to know about. Otherwise, the client can be stuck running an old
1186 // version of the server even after upgrading their copy of adb.
1187 // (http://b/24370690)
1188
1189 // clang-format off
1190 FeatureSet result {
1191 kFeatureShell2,
1192 kFeatureCmd,
1193 kFeatureStat2,
1194 kFeatureLs2,
1195 kFeatureFixedPushMkdir,
1196 kFeatureApex,
1197 kFeatureAbb,
1198 kFeatureFixedPushSymlinkTimestamp,
1199 kFeatureAbbExec,
1200 kFeatureRemountShell,
1201 kFeatureTrackApp,
1202 kFeatureSendRecv2,
1203 kFeatureSendRecv2Brotli,
1204 kFeatureSendRecv2LZ4,
1205 kFeatureSendRecv2Zstd,
1206 kFeatureSendRecv2DryRunSend,
1207 kFeatureOpenscreenMdns,
Fabien Sanglard3d155b62023-11-30 14:52:40 -08001208 kFeatureDeviceTrackerProtoFormat,
Yurii Zubrytskyi816c2d22020-03-26 18:19:28 -07001209 };
Josh Gaobd1f3002021-12-29 21:15:12 -08001210 // clang-format on
1211
1212#if ADB_HOST
1213 if (delayed_ack_enabled()) {
1214 result.push_back(kFeatureDelayedAck);
1215 }
1216#else
1217 result.push_back(kFeatureDelayedAck);
1218#endif
1219 return result;
Yurii Zubrytskyi816c2d22020-03-26 18:19:28 -07001220 }());
David Pursella07dbad2015-09-22 10:43:08 -07001221
1222 return *features;
1223}
1224
1225std::string FeatureSetToString(const FeatureSet& features) {
Elliott Hughesc3462f42018-09-05 12:13:11 -07001226 return android::base::Join(features, ',');
David Pursella07dbad2015-09-22 10:43:08 -07001227}
1228
1229FeatureSet StringToFeatureSet(const std::string& features_string) {
David Pursell3d9072b2015-09-25 13:04:21 -07001230 if (features_string.empty()) {
1231 return FeatureSet();
1232 }
1233
Yurii Zubrytskyi816c2d22020-03-26 18:19:28 -07001234 return android::base::Split(features_string, ",");
1235}
1236
1237template <class Range, class Value>
1238static bool contains(const Range& r, const Value& v) {
1239 return std::find(std::begin(r), std::end(r), v) != std::end(r);
Dan Albertbe8e54b2015-05-18 13:06:53 -07001240}
1241
David Pursell22fc5e92015-09-30 13:35:42 -07001242bool CanUseFeature(const FeatureSet& feature_set, const std::string& feature) {
Yurii Zubrytskyi816c2d22020-03-26 18:19:28 -07001243 return contains(feature_set, feature) && contains(supported_features(), feature);
David Pursell22fc5e92015-09-30 13:35:42 -07001244}
1245
Dan Albertbe8e54b2015-05-18 13:06:53 -07001246bool atransport::has_feature(const std::string& feature) const {
Yurii Zubrytskyi816c2d22020-03-26 18:19:28 -07001247 return contains(features_, feature);
Dan Albertbe8e54b2015-05-18 13:06:53 -07001248}
1249
David Pursella07dbad2015-09-22 10:43:08 -07001250void atransport::SetFeatures(const std::string& features_string) {
1251 features_ = StringToFeatureSet(features_string);
Josh Gaobd1f3002021-12-29 21:15:12 -08001252 delayed_ack_ = CanUseFeature(features_, kFeatureDelayedAck);
Dan Albertbe8e54b2015-05-18 13:06:53 -07001253}
1254
Yabin Cui2d4c1982015-08-28 15:09:44 -07001255void atransport::AddDisconnect(adisconnect* disconnect) {
1256 disconnects_.push_back(disconnect);
1257}
1258
1259void atransport::RemoveDisconnect(adisconnect* disconnect) {
1260 disconnects_.remove(disconnect);
1261}
1262
1263void atransport::RunDisconnects() {
Elliott Hughes85952832015-10-07 15:59:35 -07001264 for (const auto& disconnect : disconnects_) {
Yabin Cui2d4c1982015-08-28 15:09:44 -07001265 disconnect->func(disconnect->opaque, this);
1266 }
1267 disconnects_.clear();
1268}
1269
Josh Gao65d18e22020-04-22 20:57:26 -07001270#if ADB_HOST
David Pursellc929c6f2016-03-01 08:58:26 -08001271bool atransport::MatchesTarget(const std::string& target) const {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -07001272 if (!serial.empty()) {
David Pursellc929c6f2016-03-01 08:58:26 -08001273 if (target == serial) {
1274 return true;
1275 } else if (type == kTransportLocal) {
1276 // Local transports can match [tcp:|udp:]<hostname>[:port].
1277 const char* local_target_ptr = target.c_str();
1278
1279 // For fastboot compatibility, ignore protocol prefixes.
1280 if (android::base::StartsWith(target, "tcp:") ||
Josh Gao0d6aa992016-11-22 14:32:34 -08001281 android::base::StartsWith(target, "udp:")) {
David Pursellc929c6f2016-03-01 08:58:26 -08001282 local_target_ptr += 4;
1283 }
1284
1285 // Parse our |serial| and the given |target| to check if the hostnames and ports match.
1286 std::string serial_host, error;
1287 int serial_port = -1;
Josh Gao7852ca42021-06-17 04:17:25 -07001288 if (android::base::ParseNetAddress(serial, &serial_host, &serial_port, nullptr,
1289 &error)) {
David Pursellc929c6f2016-03-01 08:58:26 -08001290 // |target| may omit the port to default to ours.
1291 std::string target_host;
1292 int target_port = serial_port;
1293 if (android::base::ParseNetAddress(local_target_ptr, &target_host, &target_port,
1294 nullptr, &error) &&
Josh Gao0d6aa992016-11-22 14:32:34 -08001295 serial_host == target_host && serial_port == target_port) {
David Pursellc929c6f2016-03-01 08:58:26 -08001296 return true;
1297 }
1298 }
1299 }
1300 }
1301
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -07001302 return (target == devpath) || qual_match(target, "product:", product, false) ||
1303 qual_match(target, "model:", model, true) ||
1304 qual_match(target, "device:", device, false);
David Pursellc929c6f2016-03-01 08:58:26 -08001305}
1306
Luis Hector Chavezda74b902018-04-17 14:25:04 -07001307void atransport::SetConnectionEstablished(bool success) {
1308 connection_waitable_->SetConnectionEstablished(success);
1309}
1310
Josh Gaod24580d2018-08-30 11:37:00 -07001311ReconnectResult atransport::Reconnect() {
Luis Hector Chavez0aeda102018-04-20 10:31:29 -07001312 return reconnect_(this);
1313}
1314
Josh Gaob39e4152017-08-16 16:57:01 -07001315// We use newline as our delimiter, make sure to never output it.
1316static std::string sanitize(std::string str, bool alphanumeric) {
1317 auto pred = alphanumeric ? [](const char c) { return !isalnum(c); }
1318 : [](const char c) { return c == '\n'; };
1319 std::replace_if(str.begin(), str.end(), pred, '_');
1320 return str;
1321}
1322
Fabien Sanglard3d155b62023-11-30 14:52:40 -08001323static adb::proto::ConnectionState adbStateFromProto(ConnectionState state) {
1324 switch (state) {
1325 case kCsConnecting:
1326 return adb::proto::ConnectionState::CONNECTING;
1327 case kCsAuthorizing:
1328 return adb::proto::ConnectionState::AUTHORIZING;
1329 case kCsUnauthorized:
1330 return adb::proto::ConnectionState::UNAUTHORIZED;
1331 case kCsNoPerm:
1332 return adb::proto::ConnectionState::NOPERMISSION;
1333 case kCsDetached:
1334 return adb::proto::ConnectionState::DETACHED;
1335 case kCsOffline:
1336 return adb::proto::ConnectionState::OFFLINE;
1337 case kCsBootloader:
1338 return adb::proto::ConnectionState::BOOTLOADER;
1339 case kCsDevice:
1340 return adb::proto::ConnectionState::DEVICE;
1341 case kCsHost:
1342 return adb::proto::ConnectionState::HOST;
1343 case kCsRecovery:
1344 return adb::proto::ConnectionState::RECOVERY;
1345 case kCsSideload:
1346 return adb::proto::ConnectionState::SIDELOAD;
1347 case kCsRescue:
1348 return adb::proto::ConnectionState::RESCUE;
1349 case kCsAny:
1350 return adb::proto::ConnectionState::ANY;
1351 }
1352}
1353
1354static std::string transportListToProto(const std::list<atransport*>& sorted_transport_list,
1355 bool text_version) {
1356 adb::proto::Devices devices;
1357 for (const auto& t : sorted_transport_list) {
1358 auto* device = devices.add_device();
1359 device->set_serial(t->serial.c_str());
1360 device->set_connection_type(t->type == kTransportUsb ? adb::proto::ConnectionType::USB
1361 : adb::proto::ConnectionType::SOCKET);
1362 device->set_state(adbStateFromProto(t->GetConnectionState()));
1363 device->set_bus_address(sanitize(t->devpath, false));
1364 device->set_product(sanitize(t->product, false));
1365 device->set_model(sanitize(t->model, true));
1366 device->set_device(sanitize(t->device, false));
Fabien Sanglard3d155b62023-11-30 14:52:40 -08001367 device->set_negotiated_speed(t->connection()->NegotiatedSpeedMbps());
Fabien Sanglarde8d239f2023-12-15 11:48:09 -08001368 device->set_max_speed(t->connection()->MaxSpeedMbps());
1369 device->set_transport_id(t->id);
Fabien Sanglard3d155b62023-11-30 14:52:40 -08001370 }
1371
1372 std::string proto;
1373 if (text_version) {
1374 google::protobuf::TextFormat::PrintToString(devices, &proto);
1375 } else {
1376 devices.SerializeToString(&proto);
1377 }
1378 return proto;
1379}
1380
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -07001381static void append_transport_info(std::string* result, const char* key, const std::string& value,
Josh Gaob39e4152017-08-16 16:57:01 -07001382 bool alphanumeric) {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -07001383 if (value.empty()) {
Scott Anderson27042382012-05-30 18:11:27 -07001384 return;
Scott Anderson27042382012-05-30 18:11:27 -07001385 }
1386
Elliott Hughes88b4c852015-04-30 17:32:03 -07001387 *result += ' ';
1388 *result += key;
Josh Gaob39e4152017-08-16 16:57:01 -07001389 *result += sanitize(value, alphanumeric);
Scott Anderson27042382012-05-30 18:11:27 -07001390}
1391
Josh Gao0d6aa992016-11-22 14:32:34 -08001392static void append_transport(const atransport* t, std::string* result, bool long_listing) {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -07001393 std::string serial = t->serial;
1394 if (serial.empty()) {
Dan Alberta8c34142015-05-06 16:48:52 -07001395 serial = "(no serial number)";
Elliott Hughes88b4c852015-04-30 17:32:03 -07001396 }
Scott Anderson27042382012-05-30 18:11:27 -07001397
1398 if (!long_listing) {
Elliott Hughes88b4c852015-04-30 17:32:03 -07001399 *result += serial;
1400 *result += '\t';
Josh Gao6256d992021-05-20 18:28:13 -07001401 *result += to_string(t->GetConnectionState());
Scott Anderson27042382012-05-30 18:11:27 -07001402 } else {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -07001403 android::base::StringAppendF(result, "%-22s %s", serial.c_str(),
Josh Gao6256d992021-05-20 18:28:13 -07001404 to_string(t->GetConnectionState()).c_str());
Scott Anderson27042382012-05-30 18:11:27 -07001405
Elliott Hughes88b4c852015-04-30 17:32:03 -07001406 append_transport_info(result, "", t->devpath, false);
1407 append_transport_info(result, "product:", t->product, false);
1408 append_transport_info(result, "model:", t->model, true);
1409 append_transport_info(result, "device:", t->device, false);
Josh Gaob39e4152017-08-16 16:57:01 -07001410
1411 // Put id at the end, so that anyone parsing the output here can always find it by scanning
1412 // backwards from newlines, even with hypothetical devices named 'transport_id:1'.
1413 *result += " transport_id:";
1414 *result += std::to_string(t->id);
Scott Anderson27042382012-05-30 18:11:27 -07001415 }
Elliott Hughes88b4c852015-04-30 17:32:03 -07001416 *result += '\n';
Scott Anderson27042382012-05-30 18:11:27 -07001417}
1418
Fabien Sanglard3d155b62023-11-30 14:52:40 -08001419static std::string transportListToText(const std::list<atransport*>& sorted_transport_list,
1420 bool long_listing) {
1421 std::string result;
1422 for (const auto& t : sorted_transport_list) {
1423 append_transport(t, &result, long_listing);
1424 }
1425 return result;
1426}
1427
1428std::string list_transports(TrackerOutputType outputType) {
Josh Gaoaaa82f72017-08-17 13:50:51 -07001429 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Artem Iglikov4dd35012017-12-17 10:56:07 +00001430
1431 auto sorted_transport_list = transport_list;
1432 sorted_transport_list.sort([](atransport*& x, atransport*& y) {
1433 if (x->type != y->type) {
1434 return x->type < y->type;
1435 }
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -07001436 return x->serial < y->serial;
Artem Iglikov4dd35012017-12-17 10:56:07 +00001437 });
1438
Fabien Sanglard3d155b62023-11-30 14:52:40 -08001439 switch (outputType) {
1440 case SHORT_TEXT:
1441 case LONG_TEXT: {
1442 return transportListToText(sorted_transport_list, outputType == LONG_TEXT);
1443 }
1444 case PROTOBUF:
1445 case TEXT_PROTOBUF: {
1446 return transportListToProto(sorted_transport_list, outputType == TEXT_PROTOBUF);
1447 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001448 }
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001449}
1450
Josh Gao3a2172b2019-03-28 15:47:44 -07001451void close_usb_devices(std::function<bool(const atransport*)> predicate, bool reset) {
Josh Gaoaaa82f72017-08-17 13:50:51 -07001452 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gao4e562502016-10-27 14:01:08 -07001453 for (auto& t : transport_list) {
1454 if (predicate(t)) {
Josh Gao3a2172b2019-03-28 15:47:44 -07001455 if (reset) {
1456 t->Reset();
1457 } else {
1458 t->Kick();
1459 }
Josh Gao4e562502016-10-27 14:01:08 -07001460 }
1461 }
1462}
1463
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001464/* hack for osx */
Josh Gao3a2172b2019-03-28 15:47:44 -07001465void close_usb_devices(bool reset) {
1466 close_usb_devices([](const atransport*) { return true; }, reset);
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001467}
Josh Gao65d18e22020-04-22 20:57:26 -07001468#endif
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001469
Shaju Mathew36c0c0d2023-01-04 16:34:39 -08001470bool validate_transport_list(const std::list<atransport*>& list, const std::string& serial,
1471 atransport* t, int* error) {
1472 for (const auto& transport : list) {
1473 if (serial == transport->serial) {
1474 const std::string list_name(&list == &pending_list ? "pending" : "transport");
1475 VLOG(TRANSPORT) << "socket transport " << transport->serial << " is already in the "
1476 << list_name << " list and fails to register";
1477 delete t;
1478 if (error) *error = EALREADY;
1479 return false;
1480 }
1481 }
1482 return true;
1483}
1484
Josh Gao597044d2018-08-08 16:20:14 -07001485bool register_socket_transport(unique_fd s, std::string serial, int port, int local,
Joshua Duong64fab752020-01-21 13:19:42 -08001486 atransport::ReconnectCallback reconnect, bool use_tls, int* error) {
Luis Hector Chavez0aeda102018-04-20 10:31:29 -07001487 atransport* t = new atransport(std::move(reconnect), kCsOffline);
Joshua Duong64fab752020-01-21 13:19:42 -08001488 t->use_tls = use_tls;
Dmitry Ivanov6d14d352022-12-11 18:19:23 +01001489 t->serial = std::move(serial);
David 'Digit' Turner58f59682011-01-06 14:11:07 +01001490
Dmitry Ivanov6d14d352022-12-11 18:19:23 +01001491 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 -07001492 if (init_socket_transport(t, std::move(s), port, local) < 0) {
Dan Albertecce5032015-05-18 16:46:31 -07001493 delete t;
Josh Gao597044d2018-08-08 16:20:14 -07001494 if (error) *error = errno;
1495 return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001496 }
Benoit Goby3f9f9ce2013-03-29 18:22:36 -07001497
Josh Gaoaaa82f72017-08-17 13:50:51 -07001498 std::unique_lock<std::recursive_mutex> lock(transport_lock);
Dmitry Ivanov6d14d352022-12-11 18:19:23 +01001499 if (!validate_transport_list(pending_list, t->serial, t, error)) {
Shaju Mathew36c0c0d2023-01-04 16:34:39 -08001500 return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001501 }
Benoit Goby3f9f9ce2013-03-29 18:22:36 -07001502
Dmitry Ivanov6d14d352022-12-11 18:19:23 +01001503 if (!validate_transport_list(transport_list, t->serial, t, error)) {
Shaju Mathew36c0c0d2023-01-04 16:34:39 -08001504 return false;
Benoit Goby3f9f9ce2013-03-29 18:22:36 -07001505 }
1506
Dan Albertecce5032015-05-18 16:46:31 -07001507 pending_list.push_front(t);
Josh Gaoe7daf572016-09-21 12:37:10 -07001508
1509 lock.unlock();
Benoit Goby3f9f9ce2013-03-29 18:22:36 -07001510
Josh Gao65d18e22020-04-22 20:57:26 -07001511#if ADB_HOST
Luis Hector Chavezda74b902018-04-17 14:25:04 -07001512 auto waitable = t->connection_waitable();
Josh Gao65d18e22020-04-22 20:57:26 -07001513#endif
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001514 register_transport(t);
Luis Hector Chavezda74b902018-04-17 14:25:04 -07001515
Luis Hector Chavez25bc41c2018-05-01 17:12:16 -07001516 if (local == 1) {
1517 // Do not wait for emulator transports.
Josh Gao597044d2018-08-08 16:20:14 -07001518 return true;
Luis Hector Chavez25bc41c2018-05-01 17:12:16 -07001519 }
1520
Josh Gao65d18e22020-04-22 20:57:26 -07001521#if ADB_HOST
Josh Gao597044d2018-08-08 16:20:14 -07001522 if (!waitable->WaitForConnection(std::chrono::seconds(10))) {
1523 if (error) *error = ETIMEDOUT;
1524 return false;
1525 }
1526
1527 if (t->GetConnectionState() == kCsUnauthorized) {
1528 if (error) *error = EPERM;
1529 return false;
1530 }
Josh Gao65d18e22020-04-22 20:57:26 -07001531#endif
Josh Gao597044d2018-08-08 16:20:14 -07001532
1533 return true;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001534}
1535
Mike Lockwood81ffe172009-10-11 23:04:18 -04001536#if ADB_HOST
Josh Gao0d6aa992016-11-22 14:32:34 -08001537atransport* find_transport(const char* serial) {
Dan Albertecce5032015-05-18 16:46:31 -07001538 atransport* result = nullptr;
Mike Lockwood81ffe172009-10-11 23:04:18 -04001539
Josh Gaoaaa82f72017-08-17 13:50:51 -07001540 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Yabin Cui4d64fd82015-08-27 12:03:11 -07001541 for (auto& t : transport_list) {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -07001542 if (strcmp(serial, t->serial.c_str()) == 0) {
Dan Albertecce5032015-05-18 16:46:31 -07001543 result = t;
Mike Lockwood81ffe172009-10-11 23:04:18 -04001544 break;
1545 }
Dan Albertecce5032015-05-18 16:46:31 -07001546 }
Mike Lockwood81ffe172009-10-11 23:04:18 -04001547
Dan Albertecce5032015-05-18 16:46:31 -07001548 return result;
Mike Lockwood81ffe172009-10-11 23:04:18 -04001549}
1550
Yabin Cui4d64fd82015-08-27 12:03:11 -07001551void kick_all_tcp_devices() {
Josh Gaoaaa82f72017-08-17 13:50:51 -07001552 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Yabin Cui4d64fd82015-08-27 12:03:11 -07001553 for (auto& t : transport_list) {
Yabin Cuif401ead2016-04-29 16:53:52 -07001554 if (t->IsTcpDevice()) {
Yabin Cui4e222292015-08-31 11:50:24 -07001555 // Kicking breaks the read_transport thread of this transport out of any read, then
1556 // the read_transport thread will notify the main thread to make this transport
1557 // offline. Then the main thread will notify the write_transport thread to exit.
Yabin Cui4d64fd82015-08-27 12:03:11 -07001558 // Finally, this transport will be closed and freed in the main thread.
Yabin Cuif2a9f9b2016-04-18 11:22:34 -07001559 t->Kick();
Mike Lockwood01c2c302010-05-24 10:44:35 -04001560 }
Dan Albertecce5032015-05-18 16:46:31 -07001561 }
Josh Gao13cb8c02018-08-10 14:44:54 -07001562 reconnect_handler.CheckForKicked();
Mike Lockwood01c2c302010-05-24 10:44:35 -04001563}
1564
Shaju Mathew36c85202023-06-13 08:00:16 -07001565#if ADB_HOST
Josh Gaof2d6af52021-04-27 20:32:02 -07001566void register_usb_transport(std::shared_ptr<Connection> connection, const char* serial,
1567 const char* devpath, unsigned writeable) {
1568 atransport* t = new atransport(writeable ? kCsOffline : kCsNoPerm);
1569 if (serial) {
1570 t->serial = serial;
1571 }
1572 if (devpath) {
1573 t->devpath = devpath;
1574 }
1575
1576 t->SetConnection(std::move(connection));
1577 t->type = kTransportUsb;
1578
1579 {
1580 std::lock_guard<std::recursive_mutex> lock(transport_lock);
1581 pending_list.push_front(t);
1582 }
1583
1584 register_transport(t);
1585}
1586
Josh Gao0d6aa992016-11-22 14:32:34 -08001587void register_usb_transport(usb_handle* usb, const char* serial, const char* devpath,
1588 unsigned writeable) {
Luis Hector Chavez0aeda102018-04-20 10:31:29 -07001589 atransport* t = new atransport(writeable ? kCsOffline : kCsNoPerm);
Dan Albertecce5032015-05-18 16:46:31 -07001590
Josh Gao0d6aa992016-11-22 14:32:34 -08001591 D("transport: %p init'ing for usb_handle %p (sn='%s')", t, usb, serial ? serial : "");
Yabin Cui3cf1b362017-03-10 16:01:01 -08001592 init_usb_transport(t, usb);
Josh Gao0d6aa992016-11-22 14:32:34 -08001593 if (serial) {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -07001594 t->serial = serial;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001595 }
Dan Albertecce5032015-05-18 16:46:31 -07001596
1597 if (devpath) {
Luis Hector Chavezb4edbdf2018-07-18 21:18:27 -07001598 t->devpath = devpath;
Scott Anderson6dfaf4b2012-04-20 11:21:14 -07001599 }
Benoit Goby3f9f9ce2013-03-29 18:22:36 -07001600
Josh Gaoe7daf572016-09-21 12:37:10 -07001601 {
Josh Gaoaaa82f72017-08-17 13:50:51 -07001602 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gaoe7daf572016-09-21 12:37:10 -07001603 pending_list.push_front(t);
1604 }
Benoit Goby3f9f9ce2013-03-29 18:22:36 -07001605
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001606 register_transport(t);
1607}
1608
Dan Albert9a50f4c2015-05-18 16:43:57 -07001609// This should only be used for transports with connection_state == kCsNoPerm.
Josh Gao0d6aa992016-11-22 14:32:34 -08001610void unregister_usb_transport(usb_handle* usb) {
Josh Gaoaaa82f72017-08-17 13:50:51 -07001611 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gao395b86a2018-01-28 20:32:46 -08001612 transport_list.remove_if([usb](atransport* t) {
Josh Gao68f2c382018-12-11 13:11:52 -08001613 return t->GetUsbHandle() == usb && t->GetConnectionState() == kCsNoPerm;
Josh Gao395b86a2018-01-28 20:32:46 -08001614 });
Mike Lockwoode45583f2009-08-08 12:37:44 -04001615}
Shaju Mathew36c85202023-06-13 08:00:16 -07001616#endif
Shaju Mathew13508c12022-06-25 14:57:31 +00001617
1618// Track reverse:forward commands, so that info can be used to develop
1619// an 'allow-list':
1620// - adb reverse tcp:<device_port> localhost:<host_port> : responds with the
1621// device_port
1622// - adb reverse --remove tcp:<device_port> : responds OKAY
1623// - adb reverse --remove-all : responds OKAY
1624void atransport::UpdateReverseConfig(std::string_view service_addr) {
Shaju Mathew705fa1c2022-12-31 19:36:54 -08001625 fdevent_check_looper();
Shaju Mathew13508c12022-06-25 14:57:31 +00001626 if (!android::base::ConsumePrefix(&service_addr, "reverse:")) {
1627 return;
1628 }
1629
1630 if (android::base::ConsumePrefix(&service_addr, "forward:")) {
1631 // forward:[norebind:]<remote>;<local>
1632 bool norebind = android::base::ConsumePrefix(&service_addr, "norebind:");
1633 auto it = service_addr.find(';');
1634 if (it == std::string::npos) {
1635 return;
1636 }
1637 std::string remote(service_addr.substr(0, it));
1638
1639 if (norebind && reverse_forwards_.find(remote) != reverse_forwards_.end()) {
1640 // This will fail, don't update the map.
1641 LOG(DEBUG) << "ignoring reverse forward that will fail due to norebind";
1642 return;
1643 }
1644
1645 std::string local(service_addr.substr(it + 1));
1646 reverse_forwards_[remote] = local;
1647 } else if (android::base::ConsumePrefix(&service_addr, "killforward:")) {
1648 // kill-forward:<remote>
1649 auto it = service_addr.find(';');
1650 if (it != std::string::npos) {
1651 return;
1652 }
1653 reverse_forwards_.erase(std::string(service_addr));
1654 } else if (service_addr == "killforward-all") {
1655 reverse_forwards_.clear();
1656 } else if (service_addr == "list-forward") {
1657 LOG(DEBUG) << __func__ << " ignoring --list";
1658 } else { // Anything else we need to know about?
1659 LOG(FATAL) << "unhandled reverse service: " << service_addr;
1660 }
1661}
1662
1663// Is this an authorized :connect request?
1664bool atransport::IsReverseConfigured(const std::string& local_addr) {
Shaju Mathew705fa1c2022-12-31 19:36:54 -08001665 fdevent_check_looper();
Shaju Mathew13508c12022-06-25 14:57:31 +00001666 for (const auto& [remote, local] : reverse_forwards_) {
1667 if (local == local_addr) {
1668 return true;
1669 }
1670 }
1671 return false;
1672}
1673
Josh Gao3a34bc52018-10-11 16:33:05 -07001674#endif
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001675
Josh Gao67b683a2017-05-16 15:02:45 -07001676bool check_header(apacket* p, atransport* t) {
Josh Gao0d6aa992016-11-22 14:32:34 -08001677 if (p->msg.magic != (p->msg.command ^ 0xffffffff)) {
Yabin Cui3cf1b362017-03-10 16:01:01 -08001678 VLOG(RWX) << "check_header(): invalid magic command = " << std::hex << p->msg.command
1679 << ", magic = " << p->msg.magic;
Josh Gao67b683a2017-05-16 15:02:45 -07001680 return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001681 }
1682
Josh Gao0d6aa992016-11-22 14:32:34 -08001683 if (p->msg.data_length > t->get_max_payload()) {
1684 VLOG(RWX) << "check_header(): " << p->msg.data_length
1685 << " atransport::max_payload = " << t->get_max_payload();
Josh Gao67b683a2017-05-16 15:02:45 -07001686 return false;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001687 }
1688
Josh Gao67b683a2017-05-16 15:02:45 -07001689 return true;
The Android Open Source Project9ca14dc2009-03-03 19:32:55 -08001690}
1691
Josh Gaoeac20582016-10-05 19:02:29 -07001692#if ADB_HOST
Joshua Duong64fab752020-01-21 13:19:42 -08001693std::shared_ptr<RSA> atransport::Key() {
1694 if (keys_.empty()) {
1695 return nullptr;
1696 }
1697
1698 std::shared_ptr<RSA> result = keys_[0];
1699 return result;
1700}
1701
Josh Gao22cb70b2016-08-18 22:00:12 -07001702std::shared_ptr<RSA> atransport::NextKey() {
Josh Gaoeb656522018-12-04 01:07:50 -08001703 if (keys_.empty()) {
1704 LOG(INFO) << "fetching keys for transport " << this->serial_name();
1705 keys_ = adb_auth_get_private_keys();
1706
1707 // We should have gotten at least one key: the one that's automatically generated.
1708 CHECK(!keys_.empty());
Joshua Duong64fab752020-01-21 13:19:42 -08001709 } else {
1710 keys_.pop_front();
Josh Gaoeb656522018-12-04 01:07:50 -08001711 }
Elliott Hughes801066a2016-06-29 17:42:01 -07001712
Josh Gaod60bafd2020-06-11 21:07:27 -07001713 return Key();
Elliott Hughes801066a2016-06-29 17:42:01 -07001714}
Josh Gaoeb656522018-12-04 01:07:50 -08001715
1716void atransport::ResetKeys() {
1717 keys_.clear();
1718}
Josh Gaoeac20582016-10-05 19:02:29 -07001719#endif