blob: 25ed36654e7463449913bc1e79fe02caac21c72a [file] [log] [blame]
The Android Open Source Projectdd7bc332009-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 Cuiaed3c612015-09-22 15:52:57 -070017#define TRACE_TAG TRANSPORT
Dan Albert76649012015-02-24 15:51:19 -080018
Dan Albert33134262015-03-19 15:21:08 -070019#include "sysdeps.h"
Josh Gao31b5be62018-03-07 16:51:08 -080020
Dan Albert76649012015-02-24 15:51:19 -080021#include "transport.h"
22
Dan Albert055f1aa2015-02-20 17:24:58 -080023#include <ctype.h>
Dan Albert76649012015-02-24 15:51:19 -080024#include <errno.h>
Josh Gaob122b172017-08-16 16:57:01 -070025#include <inttypes.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080026#include <stdio.h>
27#include <stdlib.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080028#include <string.h>
Dan Albert76649012015-02-24 15:51:19 -080029#include <unistd.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080030
Spencer Low363af562015-11-07 18:51:54 -080031#include <algorithm>
Dan Albertc7915a32015-05-18 16:46:31 -070032#include <list>
Pirama Arumuga Nainar29e3dd82018-08-08 10:33:24 -070033#include <memory>
Josh Gao0cd3ae12016-09-21 12:37:10 -070034#include <mutex>
Josh Gao8a40c8a2018-08-10 14:28:24 -070035#include <set>
Josh Gaoe1dacfc2017-04-12 17:00:49 -070036#include <thread>
Dan Albertc7915a32015-05-18 16:46:31 -070037
Joshua Duong5cf78682020-01-21 13:19:42 -080038#include <adb/crypto/rsa_2048_key.h>
39#include <adb/crypto/x509_generator.h>
40#include <adb/tls/tls_connection.h>
Elliott Hughes4f713192015-12-04 22:00:26 -080041#include <android-base/logging.h>
Yurii Zubrytskyi6fc26df2020-03-26 18:19:28 -070042#include <android-base/no_destructor.h>
David Pursell3f902aa2016-03-01 08:58:26 -080043#include <android-base/parsenetaddress.h>
Elliott Hughes4f713192015-12-04 22:00:26 -080044#include <android-base/stringprintf.h>
45#include <android-base/strings.h>
Josh Gaob122b172017-08-16 16:57:01 -070046#include <android-base/thread_annotations.h>
Elliott Hughese67f1f82015-04-30 17:32:03 -070047
Josh Gao27768452018-01-02 12:01:43 -080048#include <diagnose_usb.h>
49
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080050#include "adb.h"
Elliott Hughes0aeb5052016-06-29 17:42:01 -070051#include "adb_auth.h"
Josh Gaob800d882018-01-28 20:32:46 -080052#include "adb_io.h"
Josh Gaocfe72e22016-11-29 09:40:29 -080053#include "adb_trace.h"
Elliott Hughese67f1f82015-04-30 17:32:03 -070054#include "adb_utils.h"
Josh Gao57e09b12019-06-28 13:50:37 -070055#include "fdevent/fdevent.h"
Josh Gaoe445a6d2018-07-31 14:12:59 -070056#include "sysdeps/chrono.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080057
Joshua Duong5cf78682020-01-21 13:19:42 -080058using namespace adb::crypto;
59using namespace adb::tls;
Josh Gao982f7bd2019-02-12 13:59:03 -080060using android::base::ScopedLockAssertion;
Joshua Duong5cf78682020-01-21 13:19:42 -080061using TlsError = TlsConnection::TlsError;
Josh Gao982f7bd2019-02-12 13:59:03 -080062
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -070063static void remove_transport(atransport* transport);
Josh Gao9a8366b2019-12-09 13:45:31 -080064static void transport_destroy(atransport* transport);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080065
Josh Gaob122b172017-08-16 16:57:01 -070066// TODO: unordered_map<TransportId, atransport*>
Josh Gaob7b1edf2015-11-11 17:56:12 -080067static auto& transport_list = *new std::list<atransport*>();
68static auto& pending_list = *new std::list<atransport*>();
Benoit Goby1c45ee92013-03-29 18:22:36 -070069
Josh Gao1db71af2017-08-17 13:50:51 -070070static auto& transport_lock = *new std::recursive_mutex();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080071
Todd Kennedy51c05ec2015-11-10 00:03:25 +000072const char* const kFeatureShell2 = "shell_v2";
73const char* const kFeatureCmd = "cmd";
Josh Gao5a1e3fd2016-12-05 17:11:34 -080074const char* const kFeatureStat2 = "stat_v2";
Josh Gao34a478f2019-08-07 14:23:17 -070075const char* const kFeatureLs2 = "ls_v2";
Josh Gao5d1756c2017-02-22 17:07:01 -080076const char* const kFeatureLibusb = "libusb";
Dan Albert5176df82017-05-23 14:30:00 -070077const char* const kFeaturePushSync = "push_sync";
Dario Freni29814de2018-10-04 16:26:40 +010078const char* const kFeatureApex = "apex";
Josh Gaofb085102018-10-22 13:00:05 -070079const char* const kFeatureFixedPushMkdir = "fixed_push_mkdir";
Alex Buynytskyy01a65ee2019-01-17 13:13:56 -080080const char* const kFeatureAbb = "abb";
Josh Gao7b1cb662019-02-20 13:01:40 -080081const char* const kFeatureFixedPushSymlinkTimestamp = "fixed_push_symlink_timestamp";
Alex Buynytskyy05626c12019-02-21 14:22:51 -080082const char* const kFeatureAbbExec = "abb_exec";
Josh Gao8c2198c2019-07-11 14:15:32 -070083const char* const kFeatureRemountShell = "remount_shell";
Shukang Zhouf4ffae12020-02-13 17:01:39 -080084const char* const kFeatureTrackApp = "track_app";
Josh Gao939fc192020-03-04 19:34:08 -080085const char* const kFeatureSendRecv2 = "sendrecv_v2";
86const char* const kFeatureSendRecv2Brotli = "sendrecv_v2_brotli";
Josh Gaoec44d352020-03-26 22:02:03 -070087const char* const kFeatureSendRecv2LZ4 = "sendrecv_v2_lz4";
Josh Gao5949fcc2020-03-30 23:25:16 -070088const char* const kFeatureSendRecv2DryRunSend = "sendrecv_v2_dry_run_send";
Todd Kennedy51c05ec2015-11-10 00:03:25 +000089
Luis Hector Chavez56fe7532018-04-17 14:25:04 -070090namespace {
91
Josh Gaodef91c02018-07-31 18:28:32 -070092#if ADB_HOST
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -070093// Tracks and handles atransport*s that are attempting reconnection.
94class ReconnectHandler {
95 public:
96 ReconnectHandler() = default;
97 ~ReconnectHandler() = default;
98
99 // Starts the ReconnectHandler thread.
100 void Start();
101
102 // Requests the ReconnectHandler thread to stop.
103 void Stop();
104
105 // Adds the atransport* to the queue of reconnect attempts.
106 void TrackTransport(atransport* transport);
107
Josh Gao902dace2018-08-10 14:44:54 -0700108 // Wake up the ReconnectHandler thread to have it check for kicked transports.
109 void CheckForKicked();
110
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700111 private:
112 // The main thread loop.
113 void Run();
114
115 // Tracks a reconnection attempt.
116 struct ReconnectAttempt {
117 atransport* transport;
Josh Gao95af6412018-07-30 18:51:55 -0700118 std::chrono::steady_clock::time_point reconnect_time;
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700119 size_t attempts_left;
Josh Gaoe445a6d2018-07-31 14:12:59 -0700120
121 bool operator<(const ReconnectAttempt& rhs) const {
Josh Gao8a40c8a2018-08-10 14:28:24 -0700122 if (reconnect_time == rhs.reconnect_time) {
123 return reinterpret_cast<uintptr_t>(transport) <
124 reinterpret_cast<uintptr_t>(rhs.transport);
125 }
126 return reconnect_time < rhs.reconnect_time;
Josh Gaoe445a6d2018-07-31 14:12:59 -0700127 }
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700128 };
129
130 // Only retry for up to one minute.
Josh Gaoe445a6d2018-07-31 14:12:59 -0700131 static constexpr const std::chrono::seconds kDefaultTimeout = 10s;
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700132 static constexpr const size_t kMaxAttempts = 6;
133
134 // Protects all members.
135 std::mutex reconnect_mutex_;
136 bool running_ GUARDED_BY(reconnect_mutex_) = true;
137 std::thread handler_thread_;
138 std::condition_variable reconnect_cv_;
Josh Gao8a40c8a2018-08-10 14:28:24 -0700139 std::set<ReconnectAttempt> reconnect_queue_ GUARDED_BY(reconnect_mutex_);
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700140
141 DISALLOW_COPY_AND_ASSIGN(ReconnectHandler);
142};
143
144void ReconnectHandler::Start() {
145 check_main_thread();
146 handler_thread_ = std::thread(&ReconnectHandler::Run, this);
147}
148
149void ReconnectHandler::Stop() {
150 check_main_thread();
151 {
152 std::lock_guard<std::mutex> lock(reconnect_mutex_);
153 running_ = false;
154 }
155 reconnect_cv_.notify_one();
156 handler_thread_.join();
157
158 // Drain the queue to free all resources.
159 std::lock_guard<std::mutex> lock(reconnect_mutex_);
160 while (!reconnect_queue_.empty()) {
Josh Gao8a40c8a2018-08-10 14:28:24 -0700161 ReconnectAttempt attempt = *reconnect_queue_.begin();
162 reconnect_queue_.erase(reconnect_queue_.begin());
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700163 remove_transport(attempt.transport);
164 }
165}
166
167void ReconnectHandler::TrackTransport(atransport* transport) {
168 check_main_thread();
169 {
170 std::lock_guard<std::mutex> lock(reconnect_mutex_);
171 if (!running_) return;
Josh Gaoe445a6d2018-07-31 14:12:59 -0700172 // Arbitrary sleep to give adbd time to get ready, if we disconnected because it exited.
173 auto reconnect_time = std::chrono::steady_clock::now() + 250ms;
174 reconnect_queue_.emplace(
175 ReconnectAttempt{transport, reconnect_time, ReconnectHandler::kMaxAttempts});
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700176 }
177 reconnect_cv_.notify_one();
178}
179
Josh Gao902dace2018-08-10 14:44:54 -0700180void ReconnectHandler::CheckForKicked() {
181 reconnect_cv_.notify_one();
182}
183
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700184void ReconnectHandler::Run() {
185 while (true) {
186 ReconnectAttempt attempt;
187 {
188 std::unique_lock<std::mutex> lock(reconnect_mutex_);
Josh Gao982f7bd2019-02-12 13:59:03 -0800189 ScopedLockAssertion assume_lock(reconnect_mutex_);
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700190
Josh Gao95af6412018-07-30 18:51:55 -0700191 if (!reconnect_queue_.empty()) {
192 // FIXME: libstdc++ (used on Windows) implements condition_variable with
193 // system_clock as its clock, so we're probably hosed if the clock changes,
194 // even if we use steady_clock throughout. This problem goes away once we
195 // switch to libc++.
Josh Gao8a40c8a2018-08-10 14:28:24 -0700196 reconnect_cv_.wait_until(lock, reconnect_queue_.begin()->reconnect_time);
Josh Gao95af6412018-07-30 18:51:55 -0700197 } else {
198 reconnect_cv_.wait(lock);
199 }
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700200
201 if (!running_) return;
Josh Gao902dace2018-08-10 14:44:54 -0700202
203 // Scan the whole list for kicked transports, so that we immediately handle an explicit
204 // disconnect request.
205 bool kicked = false;
206 for (auto it = reconnect_queue_.begin(); it != reconnect_queue_.end();) {
207 if (it->transport->kicked()) {
208 D("transport %s was kicked. giving up on it.", it->transport->serial.c_str());
209 remove_transport(it->transport);
210 it = reconnect_queue_.erase(it);
211 } else {
212 ++it;
213 }
214 kicked = true;
215 }
216
Josh Gao95af6412018-07-30 18:51:55 -0700217 if (reconnect_queue_.empty()) continue;
218
Josh Gao902dace2018-08-10 14:44:54 -0700219 // Go back to sleep if we either woke up spuriously, or we were woken up to remove
220 // a kicked transport, and the first transport isn't ready for reconnection yet.
Josh Gao95af6412018-07-30 18:51:55 -0700221 auto now = std::chrono::steady_clock::now();
Josh Gao8a40c8a2018-08-10 14:28:24 -0700222 if (reconnect_queue_.begin()->reconnect_time > now) {
Josh Gao95af6412018-07-30 18:51:55 -0700223 continue;
224 }
225
Josh Gao8a40c8a2018-08-10 14:28:24 -0700226 attempt = *reconnect_queue_.begin();
227 reconnect_queue_.erase(reconnect_queue_.begin());
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700228 }
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700229 D("attempting to reconnect %s", attempt.transport->serial.c_str());
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700230
Josh Gaofc2e56f2018-08-30 11:37:00 -0700231 switch (attempt.transport->Reconnect()) {
232 case ReconnectResult::Retry: {
233 D("attempting to reconnect %s failed.", attempt.transport->serial.c_str());
234 if (attempt.attempts_left == 0) {
235 D("transport %s exceeded the number of retry attempts. giving up on it.",
236 attempt.transport->serial.c_str());
237 remove_transport(attempt.transport);
238 continue;
239 }
240
241 std::lock_guard<std::mutex> lock(reconnect_mutex_);
242 reconnect_queue_.emplace(ReconnectAttempt{
243 attempt.transport,
244 std::chrono::steady_clock::now() + ReconnectHandler::kDefaultTimeout,
245 attempt.attempts_left - 1});
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700246 continue;
247 }
248
Josh Gaofc2e56f2018-08-30 11:37:00 -0700249 case ReconnectResult::Success:
250 D("reconnection to %s succeeded.", attempt.transport->serial.c_str());
251 register_transport(attempt.transport);
252 continue;
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700253
Josh Gaofc2e56f2018-08-30 11:37:00 -0700254 case ReconnectResult::Abort:
255 D("cancelling reconnection attempt to %s.", attempt.transport->serial.c_str());
256 remove_transport(attempt.transport);
257 continue;
258 }
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700259 }
260}
261
262static auto& reconnect_handler = *new ReconnectHandler();
263
Josh Gaodef91c02018-07-31 18:28:32 -0700264#endif
265
Luis Hector Chavez56fe7532018-04-17 14:25:04 -0700266} // namespace
267
Josh Gaob122b172017-08-16 16:57:01 -0700268TransportId NextTransportId() {
269 static std::atomic<TransportId> next(1);
270 return next++;
271}
272
Josh Gao3705b342019-03-28 15:47:44 -0700273void Connection::Reset() {
274 LOG(INFO) << "Connection::Reset(): stopping";
275 Stop();
276}
277
Josh Gao0bbf69c2018-02-16 13:24:58 -0800278BlockingConnectionAdapter::BlockingConnectionAdapter(std::unique_ptr<BlockingConnection> connection)
279 : underlying_(std::move(connection)) {}
280
281BlockingConnectionAdapter::~BlockingConnectionAdapter() {
282 LOG(INFO) << "BlockingConnectionAdapter(" << this->transport_name_ << "): destructing";
283 Stop();
284}
285
286void BlockingConnectionAdapter::Start() {
Josh Gaoc251ec52018-04-03 12:55:18 -0700287 std::lock_guard<std::mutex> lock(mutex_);
288 if (started_) {
289 LOG(FATAL) << "BlockingConnectionAdapter(" << this->transport_name_
290 << "): started multiple times";
291 }
292
Joshua Duong5cf78682020-01-21 13:19:42 -0800293 StartReadThread();
Josh Gao0bbf69c2018-02-16 13:24:58 -0800294
295 write_thread_ = std::thread([this]() {
296 LOG(INFO) << this->transport_name_ << ": write thread spawning";
297 while (true) {
298 std::unique_lock<std::mutex> lock(mutex_);
Josh Gao982f7bd2019-02-12 13:59:03 -0800299 ScopedLockAssertion assume_locked(mutex_);
Josh Gaoc251ec52018-04-03 12:55:18 -0700300 cv_.wait(lock, [this]() REQUIRES(mutex_) {
301 return this->stopped_ || !this->write_queue_.empty();
302 });
303
Josh Gao0bbf69c2018-02-16 13:24:58 -0800304 if (this->stopped_) {
305 return;
306 }
307
308 std::unique_ptr<apacket> packet = std::move(this->write_queue_.front());
309 this->write_queue_.pop_front();
310 lock.unlock();
311
312 if (!this->underlying_->Write(packet.get())) {
313 break;
314 }
315 }
316 std::call_once(this->error_flag_, [this]() { this->error_callback_(this, "write failed"); });
317 });
Josh Gaoc251ec52018-04-03 12:55:18 -0700318
319 started_ = true;
Josh Gao0bbf69c2018-02-16 13:24:58 -0800320}
321
Joshua Duong5cf78682020-01-21 13:19:42 -0800322void BlockingConnectionAdapter::StartReadThread() {
323 read_thread_ = std::thread([this]() {
324 LOG(INFO) << this->transport_name_ << ": read thread spawning";
325 while (true) {
326 auto packet = std::make_unique<apacket>();
327 if (!underlying_->Read(packet.get())) {
328 PLOG(INFO) << this->transport_name_ << ": read failed";
329 break;
330 }
331
332 bool got_stls_cmd = false;
333 if (packet->msg.command == A_STLS) {
334 got_stls_cmd = true;
335 }
336
337 read_callback_(this, std::move(packet));
338
339 // If we received the STLS packet, we are about to perform the TLS
340 // handshake. So this read thread must stop and resume after the
341 // handshake completes otherwise this will interfere in the process.
342 if (got_stls_cmd) {
343 LOG(INFO) << this->transport_name_
344 << ": Received STLS packet. Stopping read thread.";
345 return;
346 }
347 }
348 std::call_once(this->error_flag_, [this]() { this->error_callback_(this, "read failed"); });
349 });
350}
351
352bool BlockingConnectionAdapter::DoTlsHandshake(RSA* key, std::string* auth_key) {
353 std::lock_guard<std::mutex> lock(mutex_);
354 if (read_thread_.joinable()) {
355 read_thread_.join();
356 }
357 bool success = this->underlying_->DoTlsHandshake(key, auth_key);
358 StartReadThread();
359 return success;
360}
361
Josh Gao3705b342019-03-28 15:47:44 -0700362void BlockingConnectionAdapter::Reset() {
363 {
364 std::lock_guard<std::mutex> lock(mutex_);
365 if (!started_) {
366 LOG(INFO) << "BlockingConnectionAdapter(" << this->transport_name_ << "): not started";
367 return;
368 }
369
370 if (stopped_) {
371 LOG(INFO) << "BlockingConnectionAdapter(" << this->transport_name_
372 << "): already stopped";
373 return;
374 }
375 }
376
377 LOG(INFO) << "BlockingConnectionAdapter(" << this->transport_name_ << "): resetting";
378 this->underlying_->Reset();
379 Stop();
380}
381
Josh Gao0bbf69c2018-02-16 13:24:58 -0800382void BlockingConnectionAdapter::Stop() {
Josh Gaoc251ec52018-04-03 12:55:18 -0700383 {
384 std::lock_guard<std::mutex> lock(mutex_);
385 if (!started_) {
386 LOG(INFO) << "BlockingConnectionAdapter(" << this->transport_name_ << "): not started";
387 return;
388 }
Josh Gao0bbf69c2018-02-16 13:24:58 -0800389
Josh Gaoc251ec52018-04-03 12:55:18 -0700390 if (stopped_) {
391 LOG(INFO) << "BlockingConnectionAdapter(" << this->transport_name_
392 << "): already stopped";
393 return;
394 }
395
396 stopped_ = true;
397 }
Josh Gao0bbf69c2018-02-16 13:24:58 -0800398
399 LOG(INFO) << "BlockingConnectionAdapter(" << this->transport_name_ << "): stopping";
400
401 this->underlying_->Close();
Josh Gao0bbf69c2018-02-16 13:24:58 -0800402 this->cv_.notify_one();
Josh Gaoc251ec52018-04-03 12:55:18 -0700403
404 // Move the threads out into locals with the lock taken, and then unlock to let them exit.
405 std::thread read_thread;
406 std::thread write_thread;
407
408 {
409 std::lock_guard<std::mutex> lock(mutex_);
410 read_thread = std::move(read_thread_);
411 write_thread = std::move(write_thread_);
412 }
413
414 read_thread.join();
415 write_thread.join();
Josh Gao0bbf69c2018-02-16 13:24:58 -0800416
417 LOG(INFO) << "BlockingConnectionAdapter(" << this->transport_name_ << "): stopped";
418 std::call_once(this->error_flag_, [this]() { this->error_callback_(this, "requested stop"); });
419}
420
421bool BlockingConnectionAdapter::Write(std::unique_ptr<apacket> packet) {
422 {
Josh Gaoc251ec52018-04-03 12:55:18 -0700423 std::lock_guard<std::mutex> lock(this->mutex_);
Josh Gao0bbf69c2018-02-16 13:24:58 -0800424 write_queue_.emplace_back(std::move(packet));
425 }
426
427 cv_.notify_one();
428 return true;
429}
430
Joshua Duong5cf78682020-01-21 13:19:42 -0800431FdConnection::FdConnection(unique_fd fd) : fd_(std::move(fd)) {}
432
433FdConnection::~FdConnection() {}
434
435bool FdConnection::DispatchRead(void* buf, size_t len) {
436 if (tls_ != nullptr) {
437 // The TlsConnection doesn't allow 0 byte reads
438 if (len == 0) {
439 return true;
440 }
441 return tls_->ReadFully(buf, len);
442 }
443
444 return ReadFdExactly(fd_.get(), buf, len);
445}
446
447bool FdConnection::DispatchWrite(void* buf, size_t len) {
448 if (tls_ != nullptr) {
449 // The TlsConnection doesn't allow 0 byte writes
450 if (len == 0) {
451 return true;
452 }
453 return tls_->WriteFully(std::string_view(reinterpret_cast<const char*>(buf), len));
454 }
455
456 return WriteFdExactly(fd_.get(), buf, len);
457}
458
Josh Gaob800d882018-01-28 20:32:46 -0800459bool FdConnection::Read(apacket* packet) {
Joshua Duong5cf78682020-01-21 13:19:42 -0800460 if (!DispatchRead(&packet->msg, sizeof(amessage))) {
Josh Gaob800d882018-01-28 20:32:46 -0800461 D("remote local: read terminated (message)");
462 return false;
463 }
464
Josh Gaof571fcb2018-02-05 18:49:10 -0800465 if (packet->msg.data_length > MAX_PAYLOAD) {
Josh Gao5caaebd2018-02-02 14:38:04 -0800466 D("remote local: read overflow (data length = %" PRIu32 ")", packet->msg.data_length);
467 return false;
468 }
469
Josh Gaof571fcb2018-02-05 18:49:10 -0800470 packet->payload.resize(packet->msg.data_length);
471
Joshua Duong5cf78682020-01-21 13:19:42 -0800472 if (!DispatchRead(&packet->payload[0], packet->payload.size())) {
Josh Gaob800d882018-01-28 20:32:46 -0800473 D("remote local: terminated (data)");
474 return false;
475 }
476
477 return true;
478}
479
480bool FdConnection::Write(apacket* packet) {
Joshua Duong5cf78682020-01-21 13:19:42 -0800481 if (!DispatchWrite(&packet->msg, sizeof(packet->msg))) {
Josh Gaob800d882018-01-28 20:32:46 -0800482 D("remote local: write terminated");
483 return false;
484 }
485
Josh Gaof571fcb2018-02-05 18:49:10 -0800486 if (packet->msg.data_length) {
Joshua Duong5cf78682020-01-21 13:19:42 -0800487 if (!DispatchWrite(&packet->payload[0], packet->msg.data_length)) {
Josh Gaof571fcb2018-02-05 18:49:10 -0800488 D("remote local: write terminated");
489 return false;
490 }
491 }
492
Josh Gaob800d882018-01-28 20:32:46 -0800493 return true;
494}
495
Joshua Duong5cf78682020-01-21 13:19:42 -0800496bool FdConnection::DoTlsHandshake(RSA* key, std::string* auth_key) {
497 bssl::UniquePtr<EVP_PKEY> evp_pkey(EVP_PKEY_new());
498 if (!EVP_PKEY_set1_RSA(evp_pkey.get(), key)) {
499 LOG(ERROR) << "EVP_PKEY_set1_RSA failed";
500 return false;
501 }
502 auto x509 = GenerateX509Certificate(evp_pkey.get());
503 auto x509_str = X509ToPEMString(x509.get());
504 auto evp_str = Key::ToPEMString(evp_pkey.get());
Joshua Duong1b273ed2020-03-24 09:50:59 -0700505
Yurii Zubrytskyie3e64b82020-03-26 18:16:36 -0700506 int osh = cast_handle_to_int(adb_get_os_handle(fd_));
Joshua Duong5cf78682020-01-21 13:19:42 -0800507#if ADB_HOST
Joshua Duong81f2db42020-04-16 15:58:19 -0700508 tls_ = TlsConnection::Create(TlsConnection::Role::Client, x509_str, evp_str, osh);
Joshua Duong5cf78682020-01-21 13:19:42 -0800509#else
Joshua Duong81f2db42020-04-16 15:58:19 -0700510 tls_ = TlsConnection::Create(TlsConnection::Role::Server, x509_str, evp_str, osh);
Joshua Duong5cf78682020-01-21 13:19:42 -0800511#endif
Joshua Duong5cf78682020-01-21 13:19:42 -0800512 CHECK(tls_);
513#if ADB_HOST
514 // TLS 1.3 gives the client no message if the server rejected the
515 // certificate. This will enable a check in the tls connection to check
516 // whether the client certificate got rejected. Note that this assumes
517 // that, on handshake success, the server speaks first.
518 tls_->EnableClientPostHandshakeCheck(true);
519 // Add callback to set the certificate when server issues the
520 // CertificateRequest.
521 tls_->SetCertificateCallback(adb_tls_set_certificate);
522 // Allow any server certificate
523 tls_->SetCertVerifyCallback([](X509_STORE_CTX*) { return 1; });
524#else
525 // Add callback to check certificate against a list of known public keys
526 tls_->SetCertVerifyCallback(
527 [auth_key](X509_STORE_CTX* ctx) { return adbd_tls_verify_cert(ctx, auth_key); });
528 // Add the list of allowed client CA issuers
529 auto ca_list = adbd_tls_client_ca_list();
530 tls_->SetClientCAList(ca_list.get());
531#endif
532
533 auto err = tls_->DoHandshake();
534 if (err == TlsError::Success) {
535 return true;
536 }
537
538 tls_.reset();
539 return false;
540}
541
Josh Gaob800d882018-01-28 20:32:46 -0800542void FdConnection::Close() {
543 adb_shutdown(fd_.get());
544 fd_.reset();
545}
546
Josh Gao06d61d42016-10-06 13:31:44 -0700547void send_packet(apacket* p, atransport* t) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800548 p->msg.magic = p->msg.command ^ 0xffffffff;
Tim Murrayde471942017-12-07 11:40:00 -0800549 // compute a checksum for connection/auth packets for compatibility reasons
550 if (t->get_protocol_version() >= A_VERSION_SKIP_CHECKSUM) {
551 p->msg.data_check = 0;
552 } else {
553 p->msg.data_check = calculate_apacket_checksum(p);
554 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800555
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700556 VLOG(TRANSPORT) << dump_packet(t->serial.c_str(), "to remote", p);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800557
Yi Kongaed415c2018-07-13 18:15:16 -0700558 if (t == nullptr) {
Elliott Hughes4679a392018-10-19 13:59:44 -0700559 LOG(FATAL) << "Transport is null";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800560 }
561
Josh Gao0bbf69c2018-02-16 13:24:58 -0800562 if (t->Write(p) != 0) {
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700563 D("%s: failed to enqueue packet, closing transport", t->serial.c_str());
Josh Gao0bbf69c2018-02-16 13:24:58 -0800564 t->Kick();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800565 }
566}
567
Josh Gao3705b342019-03-28 15:47:44 -0700568void kick_transport(atransport* t, bool reset) {
Josh Gao1db71af2017-08-17 13:50:51 -0700569 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Yabin Cui1f4ec192016-04-05 13:50:44 -0700570 // As kick_transport() can be called from threads without guarantee that t is valid,
571 // check if the transport is in transport_list first.
Josh Gaob122b172017-08-16 16:57:01 -0700572 //
573 // TODO(jmgao): WTF? Is this actually true?
Yabin Cui1f4ec192016-04-05 13:50:44 -0700574 if (std::find(transport_list.begin(), transport_list.end(), t) != transport_list.end()) {
Josh Gao3705b342019-03-28 15:47:44 -0700575 if (reset) {
576 t->Reset();
577 } else {
578 t->Kick();
579 }
Yabin Cui1f4ec192016-04-05 13:50:44 -0700580 }
Josh Gao902dace2018-08-10 14:44:54 -0700581
582#if ADB_HOST
583 reconnect_handler.CheckForKicked();
584#endif
Yabin Cuif4b99282015-08-27 12:03:11 -0700585}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800586
587static int transport_registration_send = -1;
588static int transport_registration_recv = -1;
Josh Gao71f775a2018-05-14 11:14:33 -0700589static fdevent* transport_registration_fde;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800590
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800591#if ADB_HOST
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800592
593/* this adds support required by the 'track-devices' service.
594 * this is used to send the content of "list_transport" to any
595 * number of client connections that want it through a single
596 * live TCP connection
597 */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800598struct device_tracker {
Josh Gao1290fbf2016-11-22 14:32:34 -0800599 asocket socket;
Josh Gaoe0361d12018-02-12 17:24:00 -0800600 bool update_needed = false;
601 bool long_output = false;
602 device_tracker* next = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800603};
604
605/* linked list of all device trackers */
Josh Gao1290fbf2016-11-22 14:32:34 -0800606static device_tracker* device_tracker_list;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800607
Josh Gao1290fbf2016-11-22 14:32:34 -0800608static void device_tracker_remove(device_tracker* tracker) {
609 device_tracker** pnode = &device_tracker_list;
610 device_tracker* node = *pnode;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800611
Josh Gao1db71af2017-08-17 13:50:51 -0700612 std::lock_guard<std::recursive_mutex> lock(transport_lock);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800613 while (node) {
614 if (node == tracker) {
615 *pnode = node->next;
616 break;
617 }
618 pnode = &node->next;
Josh Gao1290fbf2016-11-22 14:32:34 -0800619 node = *pnode;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800620 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800621}
622
Josh Gao1290fbf2016-11-22 14:32:34 -0800623static void device_tracker_close(asocket* socket) {
624 device_tracker* tracker = (device_tracker*)socket;
625 asocket* peer = socket->peer;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800626
Josh Gao1290fbf2016-11-22 14:32:34 -0800627 D("device tracker %p removed", tracker);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800628 if (peer) {
Yi Kongaed415c2018-07-13 18:15:16 -0700629 peer->peer = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800630 peer->close(peer);
631 }
632 device_tracker_remove(tracker);
Josh Gaoe0361d12018-02-12 17:24:00 -0800633 delete tracker;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800634}
635
Josh Gao1ce99572018-03-07 16:52:28 -0800636static int device_tracker_enqueue(asocket* socket, apacket::payload_type) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800637 /* you can't read from a device tracker, close immediately */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800638 device_tracker_close(socket);
639 return -1;
640}
641
Elliott Hughese67f1f82015-04-30 17:32:03 -0700642static int device_tracker_send(device_tracker* tracker, const std::string& string) {
Elliott Hughese67f1f82015-04-30 17:32:03 -0700643 asocket* peer = tracker->socket.peer;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800644
Josh Gao1ce99572018-03-07 16:52:28 -0800645 apacket::payload_type data;
Josh Gao27cb7dc2018-02-01 13:17:50 -0800646 data.resize(4 + string.size());
647 char buf[5];
648 snprintf(buf, sizeof(buf), "%04x", static_cast<int>(string.size()));
649 memcpy(&data[0], buf, 4);
650 memcpy(&data[4], string.data(), string.size());
651 return peer->enqueue(peer, std::move(data));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800652}
653
Elliott Hughese67f1f82015-04-30 17:32:03 -0700654static void device_tracker_ready(asocket* socket) {
655 device_tracker* tracker = reinterpret_cast<device_tracker*>(socket);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800656
Elliott Hughese67f1f82015-04-30 17:32:03 -0700657 // We want to send the device list when the tracker connects
658 // for the first time, even if no update occurred.
Josh Gaob0c18022017-08-14 18:57:54 -0700659 if (tracker->update_needed) {
660 tracker->update_needed = false;
Elliott Hughesfc2f5f62019-07-31 14:13:57 -0700661 device_tracker_send(tracker, list_transports(tracker->long_output));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800662 }
663}
664
Josh Gaob0c18022017-08-14 18:57:54 -0700665asocket* create_device_tracker(bool long_output) {
Josh Gaoe0361d12018-02-12 17:24:00 -0800666 device_tracker* tracker = new device_tracker();
Elliott Hughes4679a392018-10-19 13:59:44 -0700667 if (tracker == nullptr) LOG(FATAL) << "cannot allocate device tracker";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800668
Josh Gao1290fbf2016-11-22 14:32:34 -0800669 D("device tracker %p created", tracker);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800670
671 tracker->socket.enqueue = device_tracker_enqueue;
Josh Gao1290fbf2016-11-22 14:32:34 -0800672 tracker->socket.ready = device_tracker_ready;
673 tracker->socket.close = device_tracker_close;
Josh Gaob0c18022017-08-14 18:57:54 -0700674 tracker->update_needed = true;
675 tracker->long_output = long_output;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800676
Josh Gao1290fbf2016-11-22 14:32:34 -0800677 tracker->next = device_tracker_list;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800678 device_tracker_list = tracker;
679
680 return &tracker->socket;
681}
682
Josh Gaofd713e52017-05-03 22:37:10 -0700683// Check if all of the USB transports are connected.
684bool iterate_transports(std::function<bool(const atransport*)> fn) {
Josh Gao1db71af2017-08-17 13:50:51 -0700685 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gaofd713e52017-05-03 22:37:10 -0700686 for (const auto& t : transport_list) {
687 if (!fn(t)) {
688 return false;
689 }
690 }
691 for (const auto& t : pending_list) {
692 if (!fn(t)) {
693 return false;
694 }
695 }
696 return true;
697}
698
Elliott Hughese67f1f82015-04-30 17:32:03 -0700699// Call this function each time the transport list has changed.
700void update_transports() {
Josh Gaofd713e52017-05-03 22:37:10 -0700701 update_transport_status();
702
703 // Notify `adb track-devices` clients.
Elliott Hughese67f1f82015-04-30 17:32:03 -0700704 device_tracker* tracker = device_tracker_list;
705 while (tracker != nullptr) {
706 device_tracker* next = tracker->next;
707 // This may destroy the tracker if the connection is closed.
Elliott Hughesfc2f5f62019-07-31 14:13:57 -0700708 device_tracker_send(tracker, list_transports(tracker->long_output));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800709 tracker = next;
710 }
711}
Elliott Hughese67f1f82015-04-30 17:32:03 -0700712
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800713#else
Elliott Hughese67f1f82015-04-30 17:32:03 -0700714
715void update_transports() {
716 // Nothing to do on the device side.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800717}
Elliott Hughese67f1f82015-04-30 17:32:03 -0700718
Josh Gao1290fbf2016-11-22 14:32:34 -0800719#endif // ADB_HOST
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800720
Josh Gao1290fbf2016-11-22 14:32:34 -0800721struct tmsg {
722 atransport* transport;
723 int action;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800724};
725
Josh Gao1290fbf2016-11-22 14:32:34 -0800726static int transport_read_action(int fd, struct tmsg* m) {
727 char* p = (char*)m;
728 int len = sizeof(*m);
729 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800730
Josh Gao1290fbf2016-11-22 14:32:34 -0800731 while (len > 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800732 r = adb_read(fd, p, len);
Josh Gao1290fbf2016-11-22 14:32:34 -0800733 if (r > 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800734 len -= r;
Josh Gao1290fbf2016-11-22 14:32:34 -0800735 p += r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800736 } else {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700737 D("transport_read_action: on fd %d: %s", fd, strerror(errno));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800738 return -1;
739 }
740 }
741 return 0;
742}
743
Josh Gao1290fbf2016-11-22 14:32:34 -0800744static int transport_write_action(int fd, struct tmsg* m) {
745 char* p = (char*)m;
746 int len = sizeof(*m);
747 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800748
Josh Gao1290fbf2016-11-22 14:32:34 -0800749 while (len > 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800750 r = adb_write(fd, p, len);
Josh Gao1290fbf2016-11-22 14:32:34 -0800751 if (r > 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800752 len -= r;
Josh Gao1290fbf2016-11-22 14:32:34 -0800753 p += r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800754 } else {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700755 D("transport_write_action: on fd %d: %s", fd, strerror(errno));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800756 return -1;
757 }
758 }
759 return 0;
760}
761
Josh Gao0bbf69c2018-02-16 13:24:58 -0800762static void transport_registration_func(int _fd, unsigned ev, void*) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800763 tmsg m;
Josh Gao1290fbf2016-11-22 14:32:34 -0800764 atransport* t;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800765
Josh Gao1290fbf2016-11-22 14:32:34 -0800766 if (!(ev & FDE_READ)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800767 return;
768 }
769
Josh Gao1290fbf2016-11-22 14:32:34 -0800770 if (transport_read_action(_fd, &m)) {
Elliott Hughes4679a392018-10-19 13:59:44 -0700771 PLOG(FATAL) << "cannot read transport registration socket";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800772 }
773
774 t = m.transport;
775
Dan Albert1792c232015-05-18 13:06:53 -0700776 if (m.action == 0) {
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700777 D("transport: %s deleting", t->serial.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800778
Josh Gao0cd3ae12016-09-21 12:37:10 -0700779 {
Josh Gao1db71af2017-08-17 13:50:51 -0700780 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gao0cd3ae12016-09-21 12:37:10 -0700781 transport_list.remove(t);
782 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800783
Dan Albertc7915a32015-05-18 16:46:31 -0700784 delete t;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800785
786 update_transports();
787 return;
788 }
789
Mike Lockwood0927bf92009-08-08 12:37:44 -0400790 /* don't create transport threads for inaccessible devices */
Yabin Cuib5e11412017-03-10 16:01:01 -0800791 if (t->GetConnectionState() != kCsNoPerm) {
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700792 // The connection gets a reference to the atransport. It will release it
793 // upon a read/write error.
Luis Hector Chavez9a388d52018-04-25 08:56:41 -0700794 t->connection()->SetTransportName(t->serial_name());
795 t->connection()->SetReadCallback([t](Connection*, std::unique_ptr<apacket> p) {
Josh Gao0bbf69c2018-02-16 13:24:58 -0800796 if (!check_header(p.get(), t)) {
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700797 D("%s: remote read: bad header", t->serial.c_str());
Josh Gao0bbf69c2018-02-16 13:24:58 -0800798 return false;
799 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800800
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700801 VLOG(TRANSPORT) << dump_packet(t->serial.c_str(), "from remote", p.get());
Josh Gao0bbf69c2018-02-16 13:24:58 -0800802 apacket* packet = p.release();
Mike Lockwood0927bf92009-08-08 12:37:44 -0400803
Josh Gao0bbf69c2018-02-16 13:24:58 -0800804 // TODO: Does this need to run on the main thread?
805 fdevent_run_on_main_thread([packet, t]() { handle_packet(packet, t); });
806 return true;
807 });
Luis Hector Chavez9a388d52018-04-25 08:56:41 -0700808 t->connection()->SetErrorCallback([t](Connection*, const std::string& error) {
Josh Gaoc51726c2018-10-11 16:33:05 -0700809 LOG(INFO) << t->serial_name() << ": connection terminated: " << error;
Josh Gao0bbf69c2018-02-16 13:24:58 -0800810 fdevent_run_on_main_thread([t]() {
811 handle_offline(t);
Josh Gao9a8366b2019-12-09 13:45:31 -0800812 transport_destroy(t);
Josh Gao0bbf69c2018-02-16 13:24:58 -0800813 });
814 });
Mike Lockwood0927bf92009-08-08 12:37:44 -0400815
Luis Hector Chavez9a388d52018-04-25 08:56:41 -0700816 t->connection()->Start();
Josh Gao0bbf69c2018-02-16 13:24:58 -0800817#if ADB_HOST
818 send_connect(t);
819#endif
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800820 }
821
Josh Gao0cd3ae12016-09-21 12:37:10 -0700822 {
Josh Gao1db71af2017-08-17 13:50:51 -0700823 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700824 auto it = std::find(pending_list.begin(), pending_list.end(), t);
825 if (it != pending_list.end()) {
826 pending_list.remove(t);
827 transport_list.push_front(t);
828 }
Josh Gao0cd3ae12016-09-21 12:37:10 -0700829 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800830
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800831 update_transports();
832}
833
Josh Gaodef91c02018-07-31 18:28:32 -0700834#if ADB_HOST
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700835void init_reconnect_handler(void) {
836 reconnect_handler.Start();
837}
Josh Gaodef91c02018-07-31 18:28:32 -0700838#endif
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700839
Josh Gao1290fbf2016-11-22 14:32:34 -0800840void init_transport_registration(void) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800841 int s[2];
842
Josh Gao1290fbf2016-11-22 14:32:34 -0800843 if (adb_socketpair(s)) {
Elliott Hughes4679a392018-10-19 13:59:44 -0700844 PLOG(FATAL) << "cannot open transport registration socketpair";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800845 }
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700846 D("socketpair: (%d,%d)", s[0], s[1]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800847
848 transport_registration_send = s[0];
849 transport_registration_recv = s[1];
850
Josh Gao71f775a2018-05-14 11:14:33 -0700851 transport_registration_fde =
Yi Kongaed415c2018-07-13 18:15:16 -0700852 fdevent_create(transport_registration_recv, transport_registration_func, nullptr);
Josh Gao71f775a2018-05-14 11:14:33 -0700853 fdevent_set(transport_registration_fde, FDE_READ);
Josh Gao01b7bc42017-05-09 13:43:35 -0700854}
855
856void kick_all_transports() {
Josh Gaodef91c02018-07-31 18:28:32 -0700857#if ADB_HOST
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700858 reconnect_handler.Stop();
Josh Gaodef91c02018-07-31 18:28:32 -0700859#endif
Josh Gao01b7bc42017-05-09 13:43:35 -0700860 // To avoid only writing part of a packet to a transport after exit, kick all transports.
Josh Gao1db71af2017-08-17 13:50:51 -0700861 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gao01b7bc42017-05-09 13:43:35 -0700862 for (auto t : transport_list) {
863 t->Kick();
864 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800865}
866
Joshua Duong5cf78682020-01-21 13:19:42 -0800867void kick_all_tcp_tls_transports() {
868 std::lock_guard<std::recursive_mutex> lock(transport_lock);
869 for (auto t : transport_list) {
870 if (t->IsTcpDevice() && t->use_tls) {
871 t->Kick();
872 }
873 }
874}
875
876#if !ADB_HOST
877void kick_all_transports_by_auth_key(std::string_view auth_key) {
878 std::lock_guard<std::recursive_mutex> lock(transport_lock);
879 for (auto t : transport_list) {
880 if (auth_key == t->auth_key) {
881 t->Kick();
882 }
883 }
884}
885#endif
886
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800887/* the fdevent select pump is single threaded */
Josh Gaoc51726c2018-10-11 16:33:05 -0700888void register_transport(atransport* transport) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800889 tmsg m;
890 m.transport = transport;
891 m.action = 1;
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700892 D("transport: %s registered", transport->serial.c_str());
Josh Gao1290fbf2016-11-22 14:32:34 -0800893 if (transport_write_action(transport_registration_send, &m)) {
Elliott Hughes4679a392018-10-19 13:59:44 -0700894 PLOG(FATAL) << "cannot write transport registration socket";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800895 }
896}
897
Josh Gao1290fbf2016-11-22 14:32:34 -0800898static void remove_transport(atransport* transport) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800899 tmsg m;
900 m.transport = transport;
901 m.action = 0;
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700902 D("transport: %s removed", transport->serial.c_str());
Josh Gao1290fbf2016-11-22 14:32:34 -0800903 if (transport_write_action(transport_registration_send, &m)) {
Elliott Hughes4679a392018-10-19 13:59:44 -0700904 PLOG(FATAL) << "cannot write transport registration socket";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800905 }
906}
907
Josh Gao9a8366b2019-12-09 13:45:31 -0800908static void transport_destroy(atransport* t) {
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700909 check_main_thread();
Yabin Cuif4b99282015-08-27 12:03:11 -0700910 CHECK(t != nullptr);
Josh Gao0cd3ae12016-09-21 12:37:10 -0700911
Josh Gaoe48ecce2017-09-13 13:40:57 -0700912 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gao9a8366b2019-12-09 13:45:31 -0800913 LOG(INFO) << "destroying transport " << t->serial_name();
914 t->connection()->Stop();
Josh Gaodef91c02018-07-31 18:28:32 -0700915#if ADB_HOST
Josh Gao9a8366b2019-12-09 13:45:31 -0800916 if (t->IsTcpDevice() && !t->kicked()) {
917 D("transport: %s destroy (attempting reconnection)", t->serial.c_str());
Josh Gao4414e4c2018-12-04 01:07:50 -0800918
Josh Gao9a8366b2019-12-09 13:45:31 -0800919 // We need to clear the transport's keys, so that on the next connection, it tries
920 // again from the beginning.
921 t->ResetKeys();
922 reconnect_handler.TrackTransport(t);
923 return;
924 }
Josh Gaodef91c02018-07-31 18:28:32 -0700925#endif
926
Josh Gao9a8366b2019-12-09 13:45:31 -0800927 D("transport: %s destroy (kicking and closing)", t->serial.c_str());
928 remove_transport(t);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800929}
930
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700931static int qual_match(const std::string& to_test, const char* prefix, const std::string& qual,
Josh Gao1290fbf2016-11-22 14:32:34 -0800932 bool sanitize_qual) {
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700933 if (to_test.empty()) /* Return true if both the qual and to_test are empty strings. */
934 return qual.empty();
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700935
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700936 if (qual.empty()) return 0;
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700937
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700938 const char* ptr = to_test.c_str();
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700939 if (prefix) {
940 while (*prefix) {
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700941 if (*prefix++ != *ptr++) return 0;
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700942 }
943 }
944
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700945 for (char ch : qual) {
Josh Gao1290fbf2016-11-22 14:32:34 -0800946 if (sanitize_qual && !isalnum(ch)) ch = '_';
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700947 if (ch != *ptr++) return 0;
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700948 }
949
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700950 /* Everything matched so far. Return true if *ptr is a NUL. */
951 return !*ptr;
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700952}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800953
Josh Gaob122b172017-08-16 16:57:01 -0700954atransport* acquire_one_transport(TransportType type, const char* serial, TransportId transport_id,
955 bool* is_ambiguous, std::string* error_out,
956 bool accept_any_state) {
Elliott Hughes8d28e192015-10-07 14:55:10 -0700957 atransport* result = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800958
Josh Gaob122b172017-08-16 16:57:01 -0700959 if (transport_id != 0) {
960 *error_out =
961 android::base::StringPrintf("no device with transport id '%" PRIu64 "'", transport_id);
962 } else if (serial) {
Elliott Hughes8d28e192015-10-07 14:55:10 -0700963 *error_out = android::base::StringPrintf("device '%s' not found", serial);
964 } else if (type == kTransportLocal) {
965 *error_out = "no emulators found";
966 } else if (type == kTransportAny) {
967 *error_out = "no devices/emulators found";
968 } else {
969 *error_out = "no devices found";
970 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800971
Josh Gao1db71af2017-08-17 13:50:51 -0700972 std::unique_lock<std::recursive_mutex> lock(transport_lock);
Elliott Hughes8d28e192015-10-07 14:55:10 -0700973 for (const auto& t : transport_list) {
Yabin Cuib5e11412017-03-10 16:01:01 -0800974 if (t->GetConnectionState() == kCsNoPerm) {
David Purselld2acbd12015-12-02 15:14:31 -0800975 *error_out = UsbNoPermissionsLongHelpText();
Mike Lockwood37d31112009-08-08 13:53:16 -0400976 continue;
977 }
Mike Lockwood0927bf92009-08-08 12:37:44 -0400978
Josh Gaob122b172017-08-16 16:57:01 -0700979 if (transport_id) {
980 if (t->id == transport_id) {
981 result = t;
982 break;
983 }
984 } else if (serial) {
David Pursell3f902aa2016-03-01 08:58:26 -0800985 if (t->MatchesTarget(serial)) {
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700986 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700987 *error_out = "more than one device";
Elliott Hughes8d28e192015-10-07 14:55:10 -0700988 if (is_ambiguous) *is_ambiguous = true;
989 result = nullptr;
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700990 break;
991 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800992 result = t;
Scott Andersone109d262012-04-20 11:21:14 -0700993 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800994 } else {
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700995 if (type == kTransportUsb && t->type == kTransportUsb) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800996 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700997 *error_out = "more than one device";
Elliott Hughes8d28e192015-10-07 14:55:10 -0700998 if (is_ambiguous) *is_ambiguous = true;
999 result = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001000 break;
1001 }
1002 result = t;
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001003 } else if (type == kTransportLocal && t->type == kTransportLocal) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001004 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -07001005 *error_out = "more than one emulator";
Elliott Hughes8d28e192015-10-07 14:55:10 -07001006 if (is_ambiguous) *is_ambiguous = true;
1007 result = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001008 break;
1009 }
1010 result = t;
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001011 } else if (type == kTransportAny) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001012 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -07001013 *error_out = "more than one device/emulator";
Elliott Hughes8d28e192015-10-07 14:55:10 -07001014 if (is_ambiguous) *is_ambiguous = true;
1015 result = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001016 break;
1017 }
1018 result = t;
1019 }
1020 }
1021 }
Josh Gao0cd3ae12016-09-21 12:37:10 -07001022 lock.unlock();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001023
Josh Gao704494b2018-05-04 16:04:49 -07001024 if (result && !accept_any_state) {
1025 // The caller requires an active transport.
1026 // Make sure that we're actually connected.
1027 ConnectionState state = result->GetConnectionState();
1028 switch (state) {
1029 case kCsConnecting:
1030 *error_out = "device still connecting";
1031 result = nullptr;
1032 break;
Benoit Goby77e8e582013-01-15 12:36:47 -08001033
Josh Gao704494b2018-05-04 16:04:49 -07001034 case kCsAuthorizing:
1035 *error_out = "device still authorizing";
1036 result = nullptr;
1037 break;
1038
1039 case kCsUnauthorized: {
1040 *error_out = "device unauthorized.\n";
1041 char* ADB_VENDOR_KEYS = getenv("ADB_VENDOR_KEYS");
1042 *error_out += "This adb server's $ADB_VENDOR_KEYS is ";
1043 *error_out += ADB_VENDOR_KEYS ? ADB_VENDOR_KEYS : "not set";
1044 *error_out += "\n";
1045 *error_out += "Try 'adb kill-server' if that seems wrong.\n";
1046 *error_out += "Otherwise check for a confirmation dialog on your device.";
1047 result = nullptr;
1048 break;
1049 }
1050
1051 case kCsOffline:
1052 *error_out = "device offline";
1053 result = nullptr;
1054 break;
1055
1056 default:
1057 break;
1058 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001059 }
1060
1061 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -07001062 *error_out = "success";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001063 }
1064
1065 return result;
1066}
1067
Luis Hector Chavez56fe7532018-04-17 14:25:04 -07001068bool ConnectionWaitable::WaitForConnection(std::chrono::milliseconds timeout) {
1069 std::unique_lock<std::mutex> lock(mutex_);
Josh Gao982f7bd2019-02-12 13:59:03 -08001070 ScopedLockAssertion assume_locked(mutex_);
Luis Hector Chavez56fe7532018-04-17 14:25:04 -07001071 return cv_.wait_for(lock, timeout, [&]() REQUIRES(mutex_) {
1072 return connection_established_ready_;
1073 }) && connection_established_;
1074}
1075
1076void ConnectionWaitable::SetConnectionEstablished(bool success) {
1077 {
1078 std::lock_guard<std::mutex> lock(mutex_);
1079 if (connection_established_ready_) return;
1080 connection_established_ready_ = true;
1081 connection_established_ = success;
1082 D("connection established with %d", success);
1083 }
1084 cv_.notify_one();
1085}
1086
1087atransport::~atransport() {
1088 // If the connection callback had not been run before, run it now.
1089 SetConnectionEstablished(false);
1090}
1091
Yabin Cuib5e11412017-03-10 16:01:01 -08001092int atransport::Write(apacket* p) {
Luis Hector Chavez9a388d52018-04-25 08:56:41 -07001093 return this->connection()->Write(std::unique_ptr<apacket>(p)) ? 0 : -1;
Yabin Cuib5e11412017-03-10 16:01:01 -08001094}
1095
Josh Gao3705b342019-03-28 15:47:44 -07001096void atransport::Reset() {
1097 if (!kicked_.exchange(true)) {
1098 LOG(INFO) << "resetting transport " << this << " " << this->serial;
1099 this->connection()->Reset();
1100 }
1101}
1102
Yabin Cui7f274902016-04-18 11:22:34 -07001103void atransport::Kick() {
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -07001104 if (!kicked_.exchange(true)) {
Josh Gao3705b342019-03-28 15:47:44 -07001105 LOG(INFO) << "kicking transport " << this << " " << this->serial;
Luis Hector Chavez9a388d52018-04-25 08:56:41 -07001106 this->connection()->Stop();
Yabin Cui7f274902016-04-18 11:22:34 -07001107 }
1108}
1109
Yabin Cuib5e11412017-03-10 16:01:01 -08001110ConnectionState atransport::GetConnectionState() const {
1111 return connection_state_;
1112}
1113
1114void atransport::SetConnectionState(ConnectionState state) {
1115 check_main_thread();
1116 connection_state_ = state;
1117}
1118
Luis Hector Chavez9a388d52018-04-25 08:56:41 -07001119void atransport::SetConnection(std::unique_ptr<Connection> connection) {
1120 std::lock_guard<std::mutex> lock(mutex_);
1121 connection_ = std::shared_ptr<Connection>(std::move(connection));
1122}
1123
Josh Gaoffbd3362018-02-28 14:44:23 -08001124std::string atransport::connection_state_name() const {
Yabin Cuib5e11412017-03-10 16:01:01 -08001125 ConnectionState state = GetConnectionState();
1126 switch (state) {
Josh Gao1290fbf2016-11-22 14:32:34 -08001127 case kCsOffline:
1128 return "offline";
1129 case kCsBootloader:
1130 return "bootloader";
1131 case kCsDevice:
1132 return "device";
1133 case kCsHost:
1134 return "host";
1135 case kCsRecovery:
1136 return "recovery";
Tao Bao55d407e2019-04-07 23:24:03 -07001137 case kCsRescue:
1138 return "rescue";
Josh Gao1290fbf2016-11-22 14:32:34 -08001139 case kCsNoPerm:
1140 return UsbNoPermissionsShortHelpText();
1141 case kCsSideload:
1142 return "sideload";
1143 case kCsUnauthorized:
1144 return "unauthorized";
Josh Gao704494b2018-05-04 16:04:49 -07001145 case kCsAuthorizing:
1146 return "authorizing";
1147 case kCsConnecting:
1148 return "connecting";
Josh Gao1290fbf2016-11-22 14:32:34 -08001149 default:
1150 return "unknown";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001151 }
1152}
1153
Tamas Berghammer3d2904c2015-07-13 19:12:28 +01001154void atransport::update_version(int version, size_t payload) {
1155 protocol_version = std::min(version, A_VERSION);
1156 max_payload = std::min(payload, MAX_PAYLOAD);
1157}
1158
1159int atransport::get_protocol_version() const {
1160 return protocol_version;
1161}
1162
Joshua Duong5cf78682020-01-21 13:19:42 -08001163int atransport::get_tls_version() const {
1164 return tls_version;
1165}
1166
Tamas Berghammer3d2904c2015-07-13 19:12:28 +01001167size_t atransport::get_max_payload() const {
1168 return max_payload;
1169}
1170
Dan Albert1792c232015-05-18 13:06:53 -07001171const FeatureSet& supported_features() {
Yurii Zubrytskyi6fc26df2020-03-26 18:19:28 -07001172 static const android::base::NoDestructor<FeatureSet> features([] {
1173 return FeatureSet{
1174 kFeatureShell2,
1175 kFeatureCmd,
1176 kFeatureStat2,
1177 kFeatureLs2,
1178 kFeatureFixedPushMkdir,
1179 kFeatureApex,
1180 kFeatureAbb,
1181 kFeatureFixedPushSymlinkTimestamp,
1182 kFeatureAbbExec,
1183 kFeatureRemountShell,
1184 kFeatureTrackApp,
1185 kFeatureSendRecv2,
1186 kFeatureSendRecv2Brotli,
1187 kFeatureSendRecv2LZ4,
1188 kFeatureSendRecv2DryRunSend,
1189 // Increment ADB_SERVER_VERSION when adding a feature that adbd needs
1190 // to know about. Otherwise, the client can be stuck running an old
1191 // version of the server even after upgrading their copy of adb.
1192 // (http://b/24370690)
1193 };
1194 }());
David Pursell4e2fd362015-09-22 10:43:08 -07001195
1196 return *features;
1197}
1198
1199std::string FeatureSetToString(const FeatureSet& features) {
Elliott Hughes86ab9ff2018-09-05 12:13:11 -07001200 return android::base::Join(features, ',');
David Pursell4e2fd362015-09-22 10:43:08 -07001201}
1202
1203FeatureSet StringToFeatureSet(const std::string& features_string) {
David Purselld2b588e2015-09-25 13:04:21 -07001204 if (features_string.empty()) {
1205 return FeatureSet();
1206 }
1207
Yurii Zubrytskyi6fc26df2020-03-26 18:19:28 -07001208 return android::base::Split(features_string, ",");
1209}
1210
1211template <class Range, class Value>
1212static bool contains(const Range& r, const Value& v) {
1213 return std::find(std::begin(r), std::end(r), v) != std::end(r);
Dan Albert1792c232015-05-18 13:06:53 -07001214}
1215
David Pursell70ef7b42015-09-30 13:35:42 -07001216bool CanUseFeature(const FeatureSet& feature_set, const std::string& feature) {
Yurii Zubrytskyi6fc26df2020-03-26 18:19:28 -07001217 return contains(feature_set, feature) && contains(supported_features(), feature);
David Pursell70ef7b42015-09-30 13:35:42 -07001218}
1219
Dan Albert1792c232015-05-18 13:06:53 -07001220bool atransport::has_feature(const std::string& feature) const {
Yurii Zubrytskyi6fc26df2020-03-26 18:19:28 -07001221 return contains(features_, feature);
Dan Albert1792c232015-05-18 13:06:53 -07001222}
1223
David Pursell4e2fd362015-09-22 10:43:08 -07001224void atransport::SetFeatures(const std::string& features_string) {
1225 features_ = StringToFeatureSet(features_string);
Dan Albert1792c232015-05-18 13:06:53 -07001226}
1227
Yabin Cuib3298242015-08-28 15:09:44 -07001228void atransport::AddDisconnect(adisconnect* disconnect) {
1229 disconnects_.push_back(disconnect);
1230}
1231
1232void atransport::RemoveDisconnect(adisconnect* disconnect) {
1233 disconnects_.remove(disconnect);
1234}
1235
1236void atransport::RunDisconnects() {
Elliott Hughes65fe2512015-10-07 15:59:35 -07001237 for (const auto& disconnect : disconnects_) {
Yabin Cuib3298242015-08-28 15:09:44 -07001238 disconnect->func(disconnect->opaque, this);
1239 }
1240 disconnects_.clear();
1241}
1242
David Pursell3f902aa2016-03-01 08:58:26 -08001243bool atransport::MatchesTarget(const std::string& target) const {
Luis Hector Chavez6150a372018-07-18 21:18:27 -07001244 if (!serial.empty()) {
David Pursell3f902aa2016-03-01 08:58:26 -08001245 if (target == serial) {
1246 return true;
1247 } else if (type == kTransportLocal) {
1248 // Local transports can match [tcp:|udp:]<hostname>[:port].
1249 const char* local_target_ptr = target.c_str();
1250
1251 // For fastboot compatibility, ignore protocol prefixes.
1252 if (android::base::StartsWith(target, "tcp:") ||
Josh Gao1290fbf2016-11-22 14:32:34 -08001253 android::base::StartsWith(target, "udp:")) {
David Pursell3f902aa2016-03-01 08:58:26 -08001254 local_target_ptr += 4;
1255 }
1256
1257 // Parse our |serial| and the given |target| to check if the hostnames and ports match.
1258 std::string serial_host, error;
1259 int serial_port = -1;
Josh Gao1290fbf2016-11-22 14:32:34 -08001260 if (android::base::ParseNetAddress(serial, &serial_host, &serial_port, nullptr, &error)) {
David Pursell3f902aa2016-03-01 08:58:26 -08001261 // |target| may omit the port to default to ours.
1262 std::string target_host;
1263 int target_port = serial_port;
1264 if (android::base::ParseNetAddress(local_target_ptr, &target_host, &target_port,
1265 nullptr, &error) &&
Josh Gao1290fbf2016-11-22 14:32:34 -08001266 serial_host == target_host && serial_port == target_port) {
David Pursell3f902aa2016-03-01 08:58:26 -08001267 return true;
1268 }
1269 }
1270 }
1271 }
1272
Luis Hector Chavez6150a372018-07-18 21:18:27 -07001273 return (target == devpath) || qual_match(target, "product:", product, false) ||
1274 qual_match(target, "model:", model, true) ||
1275 qual_match(target, "device:", device, false);
David Pursell3f902aa2016-03-01 08:58:26 -08001276}
1277
Luis Hector Chavez56fe7532018-04-17 14:25:04 -07001278void atransport::SetConnectionEstablished(bool success) {
1279 connection_waitable_->SetConnectionEstablished(success);
1280}
1281
Josh Gaofc2e56f2018-08-30 11:37:00 -07001282ReconnectResult atransport::Reconnect() {
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -07001283 return reconnect_(this);
1284}
1285
Elliott Hughese67f1f82015-04-30 17:32:03 -07001286#if ADB_HOST
1287
Josh Gaob122b172017-08-16 16:57:01 -07001288// We use newline as our delimiter, make sure to never output it.
1289static std::string sanitize(std::string str, bool alphanumeric) {
1290 auto pred = alphanumeric ? [](const char c) { return !isalnum(c); }
1291 : [](const char c) { return c == '\n'; };
1292 std::replace_if(str.begin(), str.end(), pred, '_');
1293 return str;
1294}
1295
Luis Hector Chavez6150a372018-07-18 21:18:27 -07001296static void append_transport_info(std::string* result, const char* key, const std::string& value,
Josh Gaob122b172017-08-16 16:57:01 -07001297 bool alphanumeric) {
Luis Hector Chavez6150a372018-07-18 21:18:27 -07001298 if (value.empty()) {
Scott Anderson2ca3e6b2012-05-30 18:11:27 -07001299 return;
Scott Anderson2ca3e6b2012-05-30 18:11:27 -07001300 }
1301
Elliott Hughese67f1f82015-04-30 17:32:03 -07001302 *result += ' ';
1303 *result += key;
Josh Gaob122b172017-08-16 16:57:01 -07001304 *result += sanitize(value, alphanumeric);
Scott Anderson2ca3e6b2012-05-30 18:11:27 -07001305}
1306
Josh Gao1290fbf2016-11-22 14:32:34 -08001307static void append_transport(const atransport* t, std::string* result, bool long_listing) {
Luis Hector Chavez6150a372018-07-18 21:18:27 -07001308 std::string serial = t->serial;
1309 if (serial.empty()) {
Dan Albertd99d9022015-05-06 16:48:52 -07001310 serial = "(no serial number)";
Elliott Hughese67f1f82015-04-30 17:32:03 -07001311 }
Scott Anderson2ca3e6b2012-05-30 18:11:27 -07001312
1313 if (!long_listing) {
Elliott Hughese67f1f82015-04-30 17:32:03 -07001314 *result += serial;
1315 *result += '\t';
1316 *result += t->connection_state_name();
Scott Anderson2ca3e6b2012-05-30 18:11:27 -07001317 } else {
Luis Hector Chavez6150a372018-07-18 21:18:27 -07001318 android::base::StringAppendF(result, "%-22s %s", serial.c_str(),
1319 t->connection_state_name().c_str());
Scott Anderson2ca3e6b2012-05-30 18:11:27 -07001320
Elliott Hughese67f1f82015-04-30 17:32:03 -07001321 append_transport_info(result, "", t->devpath, false);
1322 append_transport_info(result, "product:", t->product, false);
1323 append_transport_info(result, "model:", t->model, true);
1324 append_transport_info(result, "device:", t->device, false);
Josh Gaob122b172017-08-16 16:57:01 -07001325
1326 // Put id at the end, so that anyone parsing the output here can always find it by scanning
1327 // backwards from newlines, even with hypothetical devices named 'transport_id:1'.
1328 *result += " transport_id:";
1329 *result += std::to_string(t->id);
Scott Anderson2ca3e6b2012-05-30 18:11:27 -07001330 }
Elliott Hughese67f1f82015-04-30 17:32:03 -07001331 *result += '\n';
Scott Anderson2ca3e6b2012-05-30 18:11:27 -07001332}
1333
Elliott Hughese67f1f82015-04-30 17:32:03 -07001334std::string list_transports(bool long_listing) {
Josh Gao1db71af2017-08-17 13:50:51 -07001335 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Artem Iglikov04398a92017-12-17 10:56:07 +00001336
1337 auto sorted_transport_list = transport_list;
1338 sorted_transport_list.sort([](atransport*& x, atransport*& y) {
1339 if (x->type != y->type) {
1340 return x->type < y->type;
1341 }
Luis Hector Chavez6150a372018-07-18 21:18:27 -07001342 return x->serial < y->serial;
Artem Iglikov04398a92017-12-17 10:56:07 +00001343 });
1344
1345 std::string result;
1346 for (const auto& t : sorted_transport_list) {
Elliott Hughese67f1f82015-04-30 17:32:03 -07001347 append_transport(t, &result, long_listing);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001348 }
Elliott Hughese67f1f82015-04-30 17:32:03 -07001349 return result;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001350}
1351
Josh Gao3705b342019-03-28 15:47:44 -07001352void close_usb_devices(std::function<bool(const atransport*)> predicate, bool reset) {
Josh Gao1db71af2017-08-17 13:50:51 -07001353 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gao22d2b3e2016-10-27 14:01:08 -07001354 for (auto& t : transport_list) {
1355 if (predicate(t)) {
Josh Gao3705b342019-03-28 15:47:44 -07001356 if (reset) {
1357 t->Reset();
1358 } else {
1359 t->Kick();
1360 }
Josh Gao22d2b3e2016-10-27 14:01:08 -07001361 }
1362 }
1363}
1364
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001365/* hack for osx */
Josh Gao3705b342019-03-28 15:47:44 -07001366void close_usb_devices(bool reset) {
1367 close_usb_devices([](const atransport*) { return true; }, reset);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001368}
Josh Gao1290fbf2016-11-22 14:32:34 -08001369#endif // ADB_HOST
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001370
Josh Gao362e6962018-08-08 16:20:14 -07001371bool register_socket_transport(unique_fd s, std::string serial, int port, int local,
Joshua Duong5cf78682020-01-21 13:19:42 -08001372 atransport::ReconnectCallback reconnect, bool use_tls, int* error) {
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -07001373 atransport* t = new atransport(std::move(reconnect), kCsOffline);
Joshua Duong5cf78682020-01-21 13:19:42 -08001374 t->use_tls = use_tls;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +01001375
Josh Gao3b4de3c2018-08-02 13:58:24 -07001376 D("transport: %s init'ing for socket %d, on port %d", serial.c_str(), s.get(), port);
Josh Gao56300c92018-07-25 17:21:49 -07001377 if (init_socket_transport(t, std::move(s), port, local) < 0) {
Dan Albertc7915a32015-05-18 16:46:31 -07001378 delete t;
Josh Gao362e6962018-08-08 16:20:14 -07001379 if (error) *error = errno;
1380 return false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001381 }
Benoit Goby1c45ee92013-03-29 18:22:36 -07001382
Josh Gao1db71af2017-08-17 13:50:51 -07001383 std::unique_lock<std::recursive_mutex> lock(transport_lock);
Elliott Hughes65fe2512015-10-07 15:59:35 -07001384 for (const auto& transport : pending_list) {
Josh Gao3b4de3c2018-08-02 13:58:24 -07001385 if (serial == transport->serial) {
Yabin Cuib74c6492016-04-29 16:53:52 -07001386 VLOG(TRANSPORT) << "socket transport " << transport->serial
Josh Gao1290fbf2016-11-22 14:32:34 -08001387 << " is already in pending_list and fails to register";
Dan Albertc7915a32015-05-18 16:46:31 -07001388 delete t;
Josh Gao362e6962018-08-08 16:20:14 -07001389 if (error) *error = EALREADY;
1390 return false;
Benoit Goby1c45ee92013-03-29 18:22:36 -07001391 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001392 }
Benoit Goby1c45ee92013-03-29 18:22:36 -07001393
Elliott Hughes65fe2512015-10-07 15:59:35 -07001394 for (const auto& transport : transport_list) {
Josh Gao3b4de3c2018-08-02 13:58:24 -07001395 if (serial == transport->serial) {
Yabin Cuib74c6492016-04-29 16:53:52 -07001396 VLOG(TRANSPORT) << "socket transport " << transport->serial
Josh Gao1290fbf2016-11-22 14:32:34 -08001397 << " is already in transport_list and fails to register";
Dan Albertc7915a32015-05-18 16:46:31 -07001398 delete t;
Josh Gao362e6962018-08-08 16:20:14 -07001399 if (error) *error = EALREADY;
1400 return false;
Benoit Goby1c45ee92013-03-29 18:22:36 -07001401 }
1402 }
1403
Josh Gao3b4de3c2018-08-02 13:58:24 -07001404 t->serial = std::move(serial);
Dan Albertc7915a32015-05-18 16:46:31 -07001405 pending_list.push_front(t);
Josh Gao0cd3ae12016-09-21 12:37:10 -07001406
1407 lock.unlock();
Benoit Goby1c45ee92013-03-29 18:22:36 -07001408
Luis Hector Chavez56fe7532018-04-17 14:25:04 -07001409 auto waitable = t->connection_waitable();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001410 register_transport(t);
Luis Hector Chavez56fe7532018-04-17 14:25:04 -07001411
Luis Hector Chavezc587f022018-05-01 17:12:16 -07001412 if (local == 1) {
1413 // Do not wait for emulator transports.
Josh Gao362e6962018-08-08 16:20:14 -07001414 return true;
Luis Hector Chavezc587f022018-05-01 17:12:16 -07001415 }
1416
Josh Gao362e6962018-08-08 16:20:14 -07001417 if (!waitable->WaitForConnection(std::chrono::seconds(10))) {
1418 if (error) *error = ETIMEDOUT;
1419 return false;
1420 }
1421
1422 if (t->GetConnectionState() == kCsUnauthorized) {
1423 if (error) *error = EPERM;
1424 return false;
1425 }
1426
1427 return true;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001428}
1429
Mike Lockwood8cf0d592009-10-11 23:04:18 -04001430#if ADB_HOST
Josh Gao1290fbf2016-11-22 14:32:34 -08001431atransport* find_transport(const char* serial) {
Dan Albertc7915a32015-05-18 16:46:31 -07001432 atransport* result = nullptr;
Mike Lockwood8cf0d592009-10-11 23:04:18 -04001433
Josh Gao1db71af2017-08-17 13:50:51 -07001434 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Yabin Cuif4b99282015-08-27 12:03:11 -07001435 for (auto& t : transport_list) {
Luis Hector Chavez6150a372018-07-18 21:18:27 -07001436 if (strcmp(serial, t->serial.c_str()) == 0) {
Dan Albertc7915a32015-05-18 16:46:31 -07001437 result = t;
Mike Lockwood8cf0d592009-10-11 23:04:18 -04001438 break;
1439 }
Dan Albertc7915a32015-05-18 16:46:31 -07001440 }
Mike Lockwood8cf0d592009-10-11 23:04:18 -04001441
Dan Albertc7915a32015-05-18 16:46:31 -07001442 return result;
Mike Lockwood8cf0d592009-10-11 23:04:18 -04001443}
1444
Yabin Cuif4b99282015-08-27 12:03:11 -07001445void kick_all_tcp_devices() {
Josh Gao1db71af2017-08-17 13:50:51 -07001446 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Yabin Cuif4b99282015-08-27 12:03:11 -07001447 for (auto& t : transport_list) {
Yabin Cuib74c6492016-04-29 16:53:52 -07001448 if (t->IsTcpDevice()) {
Yabin Cuid6ab3c22015-08-31 11:50:24 -07001449 // Kicking breaks the read_transport thread of this transport out of any read, then
1450 // the read_transport thread will notify the main thread to make this transport
1451 // offline. Then the main thread will notify the write_transport thread to exit.
Yabin Cuif4b99282015-08-27 12:03:11 -07001452 // Finally, this transport will be closed and freed in the main thread.
Yabin Cui7f274902016-04-18 11:22:34 -07001453 t->Kick();
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001454 }
Dan Albertc7915a32015-05-18 16:46:31 -07001455 }
Josh Gao902dace2018-08-10 14:44:54 -07001456#if ADB_HOST
1457 reconnect_handler.CheckForKicked();
1458#endif
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001459}
1460
Mike Lockwood8cf0d592009-10-11 23:04:18 -04001461#endif
1462
Josh Gao08718242020-03-27 18:09:56 -07001463#if ADB_HOST
Josh Gao1290fbf2016-11-22 14:32:34 -08001464void register_usb_transport(usb_handle* usb, const char* serial, const char* devpath,
1465 unsigned writeable) {
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -07001466 atransport* t = new atransport(writeable ? kCsOffline : kCsNoPerm);
Dan Albertc7915a32015-05-18 16:46:31 -07001467
Josh Gao1290fbf2016-11-22 14:32:34 -08001468 D("transport: %p init'ing for usb_handle %p (sn='%s')", t, usb, serial ? serial : "");
Yabin Cuib5e11412017-03-10 16:01:01 -08001469 init_usb_transport(t, usb);
Josh Gao1290fbf2016-11-22 14:32:34 -08001470 if (serial) {
Luis Hector Chavez6150a372018-07-18 21:18:27 -07001471 t->serial = serial;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001472 }
Dan Albertc7915a32015-05-18 16:46:31 -07001473
1474 if (devpath) {
Luis Hector Chavez6150a372018-07-18 21:18:27 -07001475 t->devpath = devpath;
Scott Andersone109d262012-04-20 11:21:14 -07001476 }
Benoit Goby1c45ee92013-03-29 18:22:36 -07001477
Josh Gao0cd3ae12016-09-21 12:37:10 -07001478 {
Josh Gao1db71af2017-08-17 13:50:51 -07001479 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gao0cd3ae12016-09-21 12:37:10 -07001480 pending_list.push_front(t);
1481 }
Benoit Goby1c45ee92013-03-29 18:22:36 -07001482
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001483 register_transport(t);
1484}
Josh Gao08718242020-03-27 18:09:56 -07001485#endif
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001486
Josh Gaoc51726c2018-10-11 16:33:05 -07001487#if ADB_HOST
Dan Albertdcd78a12015-05-18 16:43:57 -07001488// This should only be used for transports with connection_state == kCsNoPerm.
Josh Gao1290fbf2016-11-22 14:32:34 -08001489void unregister_usb_transport(usb_handle* usb) {
Josh Gao1db71af2017-08-17 13:50:51 -07001490 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gaob800d882018-01-28 20:32:46 -08001491 transport_list.remove_if([usb](atransport* t) {
Josh Gaoce5ce872018-12-11 13:11:52 -08001492 return t->GetUsbHandle() == usb && t->GetConnectionState() == kCsNoPerm;
Josh Gaob800d882018-01-28 20:32:46 -08001493 });
Mike Lockwood0927bf92009-08-08 12:37:44 -04001494}
Josh Gaoc51726c2018-10-11 16:33:05 -07001495#endif
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001496
Josh Gao36dadca2017-05-16 15:02:45 -07001497bool check_header(apacket* p, atransport* t) {
Josh Gao1290fbf2016-11-22 14:32:34 -08001498 if (p->msg.magic != (p->msg.command ^ 0xffffffff)) {
Yabin Cuib5e11412017-03-10 16:01:01 -08001499 VLOG(RWX) << "check_header(): invalid magic command = " << std::hex << p->msg.command
1500 << ", magic = " << p->msg.magic;
Josh Gao36dadca2017-05-16 15:02:45 -07001501 return false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001502 }
1503
Josh Gao1290fbf2016-11-22 14:32:34 -08001504 if (p->msg.data_length > t->get_max_payload()) {
1505 VLOG(RWX) << "check_header(): " << p->msg.data_length
1506 << " atransport::max_payload = " << t->get_max_payload();
Josh Gao36dadca2017-05-16 15:02:45 -07001507 return false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001508 }
1509
Josh Gao36dadca2017-05-16 15:02:45 -07001510 return true;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001511}
1512
Josh Gao3bd28792016-10-05 19:02:29 -07001513#if ADB_HOST
Joshua Duong5cf78682020-01-21 13:19:42 -08001514std::shared_ptr<RSA> atransport::Key() {
1515 if (keys_.empty()) {
1516 return nullptr;
1517 }
1518
1519 std::shared_ptr<RSA> result = keys_[0];
1520 return result;
1521}
1522
Josh Gao2e671202016-08-18 22:00:12 -07001523std::shared_ptr<RSA> atransport::NextKey() {
Josh Gao4414e4c2018-12-04 01:07:50 -08001524 if (keys_.empty()) {
1525 LOG(INFO) << "fetching keys for transport " << this->serial_name();
1526 keys_ = adb_auth_get_private_keys();
1527
1528 // We should have gotten at least one key: the one that's automatically generated.
1529 CHECK(!keys_.empty());
Joshua Duong5cf78682020-01-21 13:19:42 -08001530 } else {
1531 keys_.pop_front();
Josh Gao4414e4c2018-12-04 01:07:50 -08001532 }
Elliott Hughes0aeb5052016-06-29 17:42:01 -07001533
Josh Gao2e671202016-08-18 22:00:12 -07001534 std::shared_ptr<RSA> result = keys_[0];
Elliott Hughes0aeb5052016-06-29 17:42:01 -07001535 return result;
1536}
Josh Gao4414e4c2018-12-04 01:07:50 -08001537
1538void atransport::ResetKeys() {
1539 keys_.clear();
1540}
Josh Gao3bd28792016-10-05 19:02:29 -07001541#endif