blob: 963c3c19416a37bf950af752d17a6d005e6bb52c [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
508 tls_ = TlsConnection::Create(TlsConnection::Role::Client,
509#else
510 tls_ = TlsConnection::Create(TlsConnection::Role::Server,
511#endif
Joshua Duong1b273ed2020-03-24 09:50:59 -0700512 x509_str, evp_str, osh);
Joshua Duong5cf78682020-01-21 13:19:42 -0800513 CHECK(tls_);
514#if ADB_HOST
515 // TLS 1.3 gives the client no message if the server rejected the
516 // certificate. This will enable a check in the tls connection to check
517 // whether the client certificate got rejected. Note that this assumes
518 // that, on handshake success, the server speaks first.
519 tls_->EnableClientPostHandshakeCheck(true);
520 // Add callback to set the certificate when server issues the
521 // CertificateRequest.
522 tls_->SetCertificateCallback(adb_tls_set_certificate);
523 // Allow any server certificate
524 tls_->SetCertVerifyCallback([](X509_STORE_CTX*) { return 1; });
525#else
526 // Add callback to check certificate against a list of known public keys
527 tls_->SetCertVerifyCallback(
528 [auth_key](X509_STORE_CTX* ctx) { return adbd_tls_verify_cert(ctx, auth_key); });
529 // Add the list of allowed client CA issuers
530 auto ca_list = adbd_tls_client_ca_list();
531 tls_->SetClientCAList(ca_list.get());
532#endif
533
534 auto err = tls_->DoHandshake();
535 if (err == TlsError::Success) {
536 return true;
537 }
538
539 tls_.reset();
540 return false;
541}
542
Josh Gaob800d882018-01-28 20:32:46 -0800543void FdConnection::Close() {
544 adb_shutdown(fd_.get());
545 fd_.reset();
546}
547
Josh Gao06d61d42016-10-06 13:31:44 -0700548void send_packet(apacket* p, atransport* t) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800549 p->msg.magic = p->msg.command ^ 0xffffffff;
Tim Murrayde471942017-12-07 11:40:00 -0800550 // compute a checksum for connection/auth packets for compatibility reasons
551 if (t->get_protocol_version() >= A_VERSION_SKIP_CHECKSUM) {
552 p->msg.data_check = 0;
553 } else {
554 p->msg.data_check = calculate_apacket_checksum(p);
555 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800556
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700557 VLOG(TRANSPORT) << dump_packet(t->serial.c_str(), "to remote", p);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800558
Yi Kongaed415c2018-07-13 18:15:16 -0700559 if (t == nullptr) {
Elliott Hughes4679a392018-10-19 13:59:44 -0700560 LOG(FATAL) << "Transport is null";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800561 }
562
Josh Gao0bbf69c2018-02-16 13:24:58 -0800563 if (t->Write(p) != 0) {
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700564 D("%s: failed to enqueue packet, closing transport", t->serial.c_str());
Josh Gao0bbf69c2018-02-16 13:24:58 -0800565 t->Kick();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800566 }
567}
568
Josh Gao3705b342019-03-28 15:47:44 -0700569void kick_transport(atransport* t, bool reset) {
Josh Gao1db71af2017-08-17 13:50:51 -0700570 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Yabin Cui1f4ec192016-04-05 13:50:44 -0700571 // As kick_transport() can be called from threads without guarantee that t is valid,
572 // check if the transport is in transport_list first.
Josh Gaob122b172017-08-16 16:57:01 -0700573 //
574 // TODO(jmgao): WTF? Is this actually true?
Yabin Cui1f4ec192016-04-05 13:50:44 -0700575 if (std::find(transport_list.begin(), transport_list.end(), t) != transport_list.end()) {
Josh Gao3705b342019-03-28 15:47:44 -0700576 if (reset) {
577 t->Reset();
578 } else {
579 t->Kick();
580 }
Yabin Cui1f4ec192016-04-05 13:50:44 -0700581 }
Josh Gao902dace2018-08-10 14:44:54 -0700582
583#if ADB_HOST
584 reconnect_handler.CheckForKicked();
585#endif
Yabin Cuif4b99282015-08-27 12:03:11 -0700586}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800587
588static int transport_registration_send = -1;
589static int transport_registration_recv = -1;
Josh Gao71f775a2018-05-14 11:14:33 -0700590static fdevent* transport_registration_fde;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800591
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800592#if ADB_HOST
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800593
594/* this adds support required by the 'track-devices' service.
595 * this is used to send the content of "list_transport" to any
596 * number of client connections that want it through a single
597 * live TCP connection
598 */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800599struct device_tracker {
Josh Gao1290fbf2016-11-22 14:32:34 -0800600 asocket socket;
Josh Gaoe0361d12018-02-12 17:24:00 -0800601 bool update_needed = false;
602 bool long_output = false;
603 device_tracker* next = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800604};
605
606/* linked list of all device trackers */
Josh Gao1290fbf2016-11-22 14:32:34 -0800607static device_tracker* device_tracker_list;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800608
Josh Gao1290fbf2016-11-22 14:32:34 -0800609static void device_tracker_remove(device_tracker* tracker) {
610 device_tracker** pnode = &device_tracker_list;
611 device_tracker* node = *pnode;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800612
Josh Gao1db71af2017-08-17 13:50:51 -0700613 std::lock_guard<std::recursive_mutex> lock(transport_lock);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800614 while (node) {
615 if (node == tracker) {
616 *pnode = node->next;
617 break;
618 }
619 pnode = &node->next;
Josh Gao1290fbf2016-11-22 14:32:34 -0800620 node = *pnode;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800621 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800622}
623
Josh Gao1290fbf2016-11-22 14:32:34 -0800624static void device_tracker_close(asocket* socket) {
625 device_tracker* tracker = (device_tracker*)socket;
626 asocket* peer = socket->peer;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800627
Josh Gao1290fbf2016-11-22 14:32:34 -0800628 D("device tracker %p removed", tracker);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800629 if (peer) {
Yi Kongaed415c2018-07-13 18:15:16 -0700630 peer->peer = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800631 peer->close(peer);
632 }
633 device_tracker_remove(tracker);
Josh Gaoe0361d12018-02-12 17:24:00 -0800634 delete tracker;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800635}
636
Josh Gao1ce99572018-03-07 16:52:28 -0800637static int device_tracker_enqueue(asocket* socket, apacket::payload_type) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800638 /* you can't read from a device tracker, close immediately */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800639 device_tracker_close(socket);
640 return -1;
641}
642
Elliott Hughese67f1f82015-04-30 17:32:03 -0700643static int device_tracker_send(device_tracker* tracker, const std::string& string) {
Elliott Hughese67f1f82015-04-30 17:32:03 -0700644 asocket* peer = tracker->socket.peer;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800645
Josh Gao1ce99572018-03-07 16:52:28 -0800646 apacket::payload_type data;
Josh Gao27cb7dc2018-02-01 13:17:50 -0800647 data.resize(4 + string.size());
648 char buf[5];
649 snprintf(buf, sizeof(buf), "%04x", static_cast<int>(string.size()));
650 memcpy(&data[0], buf, 4);
651 memcpy(&data[4], string.data(), string.size());
652 return peer->enqueue(peer, std::move(data));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800653}
654
Elliott Hughese67f1f82015-04-30 17:32:03 -0700655static void device_tracker_ready(asocket* socket) {
656 device_tracker* tracker = reinterpret_cast<device_tracker*>(socket);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800657
Elliott Hughese67f1f82015-04-30 17:32:03 -0700658 // We want to send the device list when the tracker connects
659 // for the first time, even if no update occurred.
Josh Gaob0c18022017-08-14 18:57:54 -0700660 if (tracker->update_needed) {
661 tracker->update_needed = false;
Elliott Hughesfc2f5f62019-07-31 14:13:57 -0700662 device_tracker_send(tracker, list_transports(tracker->long_output));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800663 }
664}
665
Josh Gaob0c18022017-08-14 18:57:54 -0700666asocket* create_device_tracker(bool long_output) {
Josh Gaoe0361d12018-02-12 17:24:00 -0800667 device_tracker* tracker = new device_tracker();
Elliott Hughes4679a392018-10-19 13:59:44 -0700668 if (tracker == nullptr) LOG(FATAL) << "cannot allocate device tracker";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800669
Josh Gao1290fbf2016-11-22 14:32:34 -0800670 D("device tracker %p created", tracker);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800671
672 tracker->socket.enqueue = device_tracker_enqueue;
Josh Gao1290fbf2016-11-22 14:32:34 -0800673 tracker->socket.ready = device_tracker_ready;
674 tracker->socket.close = device_tracker_close;
Josh Gaob0c18022017-08-14 18:57:54 -0700675 tracker->update_needed = true;
676 tracker->long_output = long_output;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800677
Josh Gao1290fbf2016-11-22 14:32:34 -0800678 tracker->next = device_tracker_list;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800679 device_tracker_list = tracker;
680
681 return &tracker->socket;
682}
683
Josh Gaofd713e52017-05-03 22:37:10 -0700684// Check if all of the USB transports are connected.
685bool iterate_transports(std::function<bool(const atransport*)> fn) {
Josh Gao1db71af2017-08-17 13:50:51 -0700686 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gaofd713e52017-05-03 22:37:10 -0700687 for (const auto& t : transport_list) {
688 if (!fn(t)) {
689 return false;
690 }
691 }
692 for (const auto& t : pending_list) {
693 if (!fn(t)) {
694 return false;
695 }
696 }
697 return true;
698}
699
Elliott Hughese67f1f82015-04-30 17:32:03 -0700700// Call this function each time the transport list has changed.
701void update_transports() {
Josh Gaofd713e52017-05-03 22:37:10 -0700702 update_transport_status();
703
704 // Notify `adb track-devices` clients.
Elliott Hughese67f1f82015-04-30 17:32:03 -0700705 device_tracker* tracker = device_tracker_list;
706 while (tracker != nullptr) {
707 device_tracker* next = tracker->next;
708 // This may destroy the tracker if the connection is closed.
Elliott Hughesfc2f5f62019-07-31 14:13:57 -0700709 device_tracker_send(tracker, list_transports(tracker->long_output));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800710 tracker = next;
711 }
712}
Elliott Hughese67f1f82015-04-30 17:32:03 -0700713
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800714#else
Elliott Hughese67f1f82015-04-30 17:32:03 -0700715
716void update_transports() {
717 // Nothing to do on the device side.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800718}
Elliott Hughese67f1f82015-04-30 17:32:03 -0700719
Josh Gao1290fbf2016-11-22 14:32:34 -0800720#endif // ADB_HOST
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800721
Josh Gao1290fbf2016-11-22 14:32:34 -0800722struct tmsg {
723 atransport* transport;
724 int action;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800725};
726
Josh Gao1290fbf2016-11-22 14:32:34 -0800727static int transport_read_action(int fd, struct tmsg* m) {
728 char* p = (char*)m;
729 int len = sizeof(*m);
730 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800731
Josh Gao1290fbf2016-11-22 14:32:34 -0800732 while (len > 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800733 r = adb_read(fd, p, len);
Josh Gao1290fbf2016-11-22 14:32:34 -0800734 if (r > 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800735 len -= r;
Josh Gao1290fbf2016-11-22 14:32:34 -0800736 p += r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800737 } else {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700738 D("transport_read_action: on fd %d: %s", fd, strerror(errno));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800739 return -1;
740 }
741 }
742 return 0;
743}
744
Josh Gao1290fbf2016-11-22 14:32:34 -0800745static int transport_write_action(int fd, struct tmsg* m) {
746 char* p = (char*)m;
747 int len = sizeof(*m);
748 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800749
Josh Gao1290fbf2016-11-22 14:32:34 -0800750 while (len > 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800751 r = adb_write(fd, p, len);
Josh Gao1290fbf2016-11-22 14:32:34 -0800752 if (r > 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800753 len -= r;
Josh Gao1290fbf2016-11-22 14:32:34 -0800754 p += r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800755 } else {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700756 D("transport_write_action: on fd %d: %s", fd, strerror(errno));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800757 return -1;
758 }
759 }
760 return 0;
761}
762
Josh Gao0bbf69c2018-02-16 13:24:58 -0800763static void transport_registration_func(int _fd, unsigned ev, void*) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800764 tmsg m;
Josh Gao1290fbf2016-11-22 14:32:34 -0800765 atransport* t;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800766
Josh Gao1290fbf2016-11-22 14:32:34 -0800767 if (!(ev & FDE_READ)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800768 return;
769 }
770
Josh Gao1290fbf2016-11-22 14:32:34 -0800771 if (transport_read_action(_fd, &m)) {
Elliott Hughes4679a392018-10-19 13:59:44 -0700772 PLOG(FATAL) << "cannot read transport registration socket";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800773 }
774
775 t = m.transport;
776
Dan Albert1792c232015-05-18 13:06:53 -0700777 if (m.action == 0) {
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700778 D("transport: %s deleting", t->serial.c_str());
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800779
Josh Gao0cd3ae12016-09-21 12:37:10 -0700780 {
Josh Gao1db71af2017-08-17 13:50:51 -0700781 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gao0cd3ae12016-09-21 12:37:10 -0700782 transport_list.remove(t);
783 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800784
Dan Albertc7915a32015-05-18 16:46:31 -0700785 delete t;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800786
787 update_transports();
788 return;
789 }
790
Mike Lockwood0927bf92009-08-08 12:37:44 -0400791 /* don't create transport threads for inaccessible devices */
Yabin Cuib5e11412017-03-10 16:01:01 -0800792 if (t->GetConnectionState() != kCsNoPerm) {
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700793 // The connection gets a reference to the atransport. It will release it
794 // upon a read/write error.
Luis Hector Chavez9a388d52018-04-25 08:56:41 -0700795 t->connection()->SetTransportName(t->serial_name());
796 t->connection()->SetReadCallback([t](Connection*, std::unique_ptr<apacket> p) {
Josh Gao0bbf69c2018-02-16 13:24:58 -0800797 if (!check_header(p.get(), t)) {
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700798 D("%s: remote read: bad header", t->serial.c_str());
Josh Gao0bbf69c2018-02-16 13:24:58 -0800799 return false;
800 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800801
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700802 VLOG(TRANSPORT) << dump_packet(t->serial.c_str(), "from remote", p.get());
Josh Gao0bbf69c2018-02-16 13:24:58 -0800803 apacket* packet = p.release();
Mike Lockwood0927bf92009-08-08 12:37:44 -0400804
Josh Gao0bbf69c2018-02-16 13:24:58 -0800805 // TODO: Does this need to run on the main thread?
806 fdevent_run_on_main_thread([packet, t]() { handle_packet(packet, t); });
807 return true;
808 });
Luis Hector Chavez9a388d52018-04-25 08:56:41 -0700809 t->connection()->SetErrorCallback([t](Connection*, const std::string& error) {
Josh Gaoc51726c2018-10-11 16:33:05 -0700810 LOG(INFO) << t->serial_name() << ": connection terminated: " << error;
Josh Gao0bbf69c2018-02-16 13:24:58 -0800811 fdevent_run_on_main_thread([t]() {
812 handle_offline(t);
Josh Gao9a8366b2019-12-09 13:45:31 -0800813 transport_destroy(t);
Josh Gao0bbf69c2018-02-16 13:24:58 -0800814 });
815 });
Mike Lockwood0927bf92009-08-08 12:37:44 -0400816
Luis Hector Chavez9a388d52018-04-25 08:56:41 -0700817 t->connection()->Start();
Josh Gao0bbf69c2018-02-16 13:24:58 -0800818#if ADB_HOST
819 send_connect(t);
820#endif
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800821 }
822
Josh Gao0cd3ae12016-09-21 12:37:10 -0700823 {
Josh Gao1db71af2017-08-17 13:50:51 -0700824 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700825 auto it = std::find(pending_list.begin(), pending_list.end(), t);
826 if (it != pending_list.end()) {
827 pending_list.remove(t);
828 transport_list.push_front(t);
829 }
Josh Gao0cd3ae12016-09-21 12:37:10 -0700830 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800831
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800832 update_transports();
833}
834
Josh Gaodef91c02018-07-31 18:28:32 -0700835#if ADB_HOST
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700836void init_reconnect_handler(void) {
837 reconnect_handler.Start();
838}
Josh Gaodef91c02018-07-31 18:28:32 -0700839#endif
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700840
Josh Gao1290fbf2016-11-22 14:32:34 -0800841void init_transport_registration(void) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800842 int s[2];
843
Josh Gao1290fbf2016-11-22 14:32:34 -0800844 if (adb_socketpair(s)) {
Elliott Hughes4679a392018-10-19 13:59:44 -0700845 PLOG(FATAL) << "cannot open transport registration socketpair";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800846 }
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700847 D("socketpair: (%d,%d)", s[0], s[1]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800848
849 transport_registration_send = s[0];
850 transport_registration_recv = s[1];
851
Josh Gao71f775a2018-05-14 11:14:33 -0700852 transport_registration_fde =
Yi Kongaed415c2018-07-13 18:15:16 -0700853 fdevent_create(transport_registration_recv, transport_registration_func, nullptr);
Josh Gao71f775a2018-05-14 11:14:33 -0700854 fdevent_set(transport_registration_fde, FDE_READ);
Josh Gao01b7bc42017-05-09 13:43:35 -0700855}
856
857void kick_all_transports() {
Josh Gaodef91c02018-07-31 18:28:32 -0700858#if ADB_HOST
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700859 reconnect_handler.Stop();
Josh Gaodef91c02018-07-31 18:28:32 -0700860#endif
Josh Gao01b7bc42017-05-09 13:43:35 -0700861 // To avoid only writing part of a packet to a transport after exit, kick all transports.
Josh Gao1db71af2017-08-17 13:50:51 -0700862 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gao01b7bc42017-05-09 13:43:35 -0700863 for (auto t : transport_list) {
864 t->Kick();
865 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800866}
867
Joshua Duong5cf78682020-01-21 13:19:42 -0800868void kick_all_tcp_tls_transports() {
869 std::lock_guard<std::recursive_mutex> lock(transport_lock);
870 for (auto t : transport_list) {
871 if (t->IsTcpDevice() && t->use_tls) {
872 t->Kick();
873 }
874 }
875}
876
877#if !ADB_HOST
878void kick_all_transports_by_auth_key(std::string_view auth_key) {
879 std::lock_guard<std::recursive_mutex> lock(transport_lock);
880 for (auto t : transport_list) {
881 if (auth_key == t->auth_key) {
882 t->Kick();
883 }
884 }
885}
886#endif
887
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800888/* the fdevent select pump is single threaded */
Josh Gaoc51726c2018-10-11 16:33:05 -0700889void register_transport(atransport* transport) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800890 tmsg m;
891 m.transport = transport;
892 m.action = 1;
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700893 D("transport: %s registered", transport->serial.c_str());
Josh Gao1290fbf2016-11-22 14:32:34 -0800894 if (transport_write_action(transport_registration_send, &m)) {
Elliott Hughes4679a392018-10-19 13:59:44 -0700895 PLOG(FATAL) << "cannot write transport registration socket";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800896 }
897}
898
Josh Gao1290fbf2016-11-22 14:32:34 -0800899static void remove_transport(atransport* transport) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800900 tmsg m;
901 m.transport = transport;
902 m.action = 0;
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700903 D("transport: %s removed", transport->serial.c_str());
Josh Gao1290fbf2016-11-22 14:32:34 -0800904 if (transport_write_action(transport_registration_send, &m)) {
Elliott Hughes4679a392018-10-19 13:59:44 -0700905 PLOG(FATAL) << "cannot write transport registration socket";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800906 }
907}
908
Josh Gao9a8366b2019-12-09 13:45:31 -0800909static void transport_destroy(atransport* t) {
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -0700910 check_main_thread();
Yabin Cuif4b99282015-08-27 12:03:11 -0700911 CHECK(t != nullptr);
Josh Gao0cd3ae12016-09-21 12:37:10 -0700912
Josh Gaoe48ecce2017-09-13 13:40:57 -0700913 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gao9a8366b2019-12-09 13:45:31 -0800914 LOG(INFO) << "destroying transport " << t->serial_name();
915 t->connection()->Stop();
Josh Gaodef91c02018-07-31 18:28:32 -0700916#if ADB_HOST
Josh Gao9a8366b2019-12-09 13:45:31 -0800917 if (t->IsTcpDevice() && !t->kicked()) {
918 D("transport: %s destroy (attempting reconnection)", t->serial.c_str());
Josh Gao4414e4c2018-12-04 01:07:50 -0800919
Josh Gao9a8366b2019-12-09 13:45:31 -0800920 // We need to clear the transport's keys, so that on the next connection, it tries
921 // again from the beginning.
922 t->ResetKeys();
923 reconnect_handler.TrackTransport(t);
924 return;
925 }
Josh Gaodef91c02018-07-31 18:28:32 -0700926#endif
927
Josh Gao9a8366b2019-12-09 13:45:31 -0800928 D("transport: %s destroy (kicking and closing)", t->serial.c_str());
929 remove_transport(t);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800930}
931
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700932static int qual_match(const std::string& to_test, const char* prefix, const std::string& qual,
Josh Gao1290fbf2016-11-22 14:32:34 -0800933 bool sanitize_qual) {
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700934 if (to_test.empty()) /* Return true if both the qual and to_test are empty strings. */
935 return qual.empty();
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700936
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700937 if (qual.empty()) return 0;
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700938
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700939 const char* ptr = to_test.c_str();
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700940 if (prefix) {
941 while (*prefix) {
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700942 if (*prefix++ != *ptr++) return 0;
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700943 }
944 }
945
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700946 for (char ch : qual) {
Josh Gao1290fbf2016-11-22 14:32:34 -0800947 if (sanitize_qual && !isalnum(ch)) ch = '_';
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700948 if (ch != *ptr++) return 0;
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700949 }
950
Luis Hector Chavez6150a372018-07-18 21:18:27 -0700951 /* Everything matched so far. Return true if *ptr is a NUL. */
952 return !*ptr;
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700953}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800954
Josh Gaob122b172017-08-16 16:57:01 -0700955atransport* acquire_one_transport(TransportType type, const char* serial, TransportId transport_id,
956 bool* is_ambiguous, std::string* error_out,
957 bool accept_any_state) {
Elliott Hughes8d28e192015-10-07 14:55:10 -0700958 atransport* result = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800959
Josh Gaob122b172017-08-16 16:57:01 -0700960 if (transport_id != 0) {
961 *error_out =
962 android::base::StringPrintf("no device with transport id '%" PRIu64 "'", transport_id);
963 } else if (serial) {
Elliott Hughes8d28e192015-10-07 14:55:10 -0700964 *error_out = android::base::StringPrintf("device '%s' not found", serial);
965 } else if (type == kTransportLocal) {
966 *error_out = "no emulators found";
967 } else if (type == kTransportAny) {
968 *error_out = "no devices/emulators found";
969 } else {
970 *error_out = "no devices found";
971 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800972
Josh Gao1db71af2017-08-17 13:50:51 -0700973 std::unique_lock<std::recursive_mutex> lock(transport_lock);
Elliott Hughes8d28e192015-10-07 14:55:10 -0700974 for (const auto& t : transport_list) {
Yabin Cuib5e11412017-03-10 16:01:01 -0800975 if (t->GetConnectionState() == kCsNoPerm) {
David Purselld2acbd12015-12-02 15:14:31 -0800976 *error_out = UsbNoPermissionsLongHelpText();
Mike Lockwood37d31112009-08-08 13:53:16 -0400977 continue;
978 }
Mike Lockwood0927bf92009-08-08 12:37:44 -0400979
Josh Gaob122b172017-08-16 16:57:01 -0700980 if (transport_id) {
981 if (t->id == transport_id) {
982 result = t;
983 break;
984 }
985 } else if (serial) {
David Pursell3f902aa2016-03-01 08:58:26 -0800986 if (t->MatchesTarget(serial)) {
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700987 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700988 *error_out = "more than one device";
Elliott Hughes8d28e192015-10-07 14:55:10 -0700989 if (is_ambiguous) *is_ambiguous = true;
990 result = nullptr;
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700991 break;
992 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800993 result = t;
Scott Andersone109d262012-04-20 11:21:14 -0700994 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800995 } else {
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700996 if (type == kTransportUsb && t->type == kTransportUsb) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800997 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700998 *error_out = "more than one device";
Elliott Hughes8d28e192015-10-07 14:55:10 -0700999 if (is_ambiguous) *is_ambiguous = true;
1000 result = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001001 break;
1002 }
1003 result = t;
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001004 } else if (type == kTransportLocal && t->type == kTransportLocal) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001005 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -07001006 *error_out = "more than one emulator";
Elliott Hughes8d28e192015-10-07 14:55:10 -07001007 if (is_ambiguous) *is_ambiguous = true;
1008 result = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001009 break;
1010 }
1011 result = t;
Elliott Hughes3bd73c12015-05-05 13:10:43 -07001012 } else if (type == kTransportAny) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001013 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -07001014 *error_out = "more than one device/emulator";
Elliott Hughes8d28e192015-10-07 14:55:10 -07001015 if (is_ambiguous) *is_ambiguous = true;
1016 result = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001017 break;
1018 }
1019 result = t;
1020 }
1021 }
1022 }
Josh Gao0cd3ae12016-09-21 12:37:10 -07001023 lock.unlock();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001024
Josh Gao704494b2018-05-04 16:04:49 -07001025 if (result && !accept_any_state) {
1026 // The caller requires an active transport.
1027 // Make sure that we're actually connected.
1028 ConnectionState state = result->GetConnectionState();
1029 switch (state) {
1030 case kCsConnecting:
1031 *error_out = "device still connecting";
1032 result = nullptr;
1033 break;
Benoit Goby77e8e582013-01-15 12:36:47 -08001034
Josh Gao704494b2018-05-04 16:04:49 -07001035 case kCsAuthorizing:
1036 *error_out = "device still authorizing";
1037 result = nullptr;
1038 break;
1039
1040 case kCsUnauthorized: {
1041 *error_out = "device unauthorized.\n";
1042 char* ADB_VENDOR_KEYS = getenv("ADB_VENDOR_KEYS");
1043 *error_out += "This adb server's $ADB_VENDOR_KEYS is ";
1044 *error_out += ADB_VENDOR_KEYS ? ADB_VENDOR_KEYS : "not set";
1045 *error_out += "\n";
1046 *error_out += "Try 'adb kill-server' if that seems wrong.\n";
1047 *error_out += "Otherwise check for a confirmation dialog on your device.";
1048 result = nullptr;
1049 break;
1050 }
1051
1052 case kCsOffline:
1053 *error_out = "device offline";
1054 result = nullptr;
1055 break;
1056
1057 default:
1058 break;
1059 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001060 }
1061
1062 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -07001063 *error_out = "success";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001064 }
1065
1066 return result;
1067}
1068
Luis Hector Chavez56fe7532018-04-17 14:25:04 -07001069bool ConnectionWaitable::WaitForConnection(std::chrono::milliseconds timeout) {
1070 std::unique_lock<std::mutex> lock(mutex_);
Josh Gao982f7bd2019-02-12 13:59:03 -08001071 ScopedLockAssertion assume_locked(mutex_);
Luis Hector Chavez56fe7532018-04-17 14:25:04 -07001072 return cv_.wait_for(lock, timeout, [&]() REQUIRES(mutex_) {
1073 return connection_established_ready_;
1074 }) && connection_established_;
1075}
1076
1077void ConnectionWaitable::SetConnectionEstablished(bool success) {
1078 {
1079 std::lock_guard<std::mutex> lock(mutex_);
1080 if (connection_established_ready_) return;
1081 connection_established_ready_ = true;
1082 connection_established_ = success;
1083 D("connection established with %d", success);
1084 }
1085 cv_.notify_one();
1086}
1087
1088atransport::~atransport() {
1089 // If the connection callback had not been run before, run it now.
1090 SetConnectionEstablished(false);
1091}
1092
Yabin Cuib5e11412017-03-10 16:01:01 -08001093int atransport::Write(apacket* p) {
Luis Hector Chavez9a388d52018-04-25 08:56:41 -07001094 return this->connection()->Write(std::unique_ptr<apacket>(p)) ? 0 : -1;
Yabin Cuib5e11412017-03-10 16:01:01 -08001095}
1096
Josh Gao3705b342019-03-28 15:47:44 -07001097void atransport::Reset() {
1098 if (!kicked_.exchange(true)) {
1099 LOG(INFO) << "resetting transport " << this << " " << this->serial;
1100 this->connection()->Reset();
1101 }
1102}
1103
Yabin Cui7f274902016-04-18 11:22:34 -07001104void atransport::Kick() {
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -07001105 if (!kicked_.exchange(true)) {
Josh Gao3705b342019-03-28 15:47:44 -07001106 LOG(INFO) << "kicking transport " << this << " " << this->serial;
Luis Hector Chavez9a388d52018-04-25 08:56:41 -07001107 this->connection()->Stop();
Yabin Cui7f274902016-04-18 11:22:34 -07001108 }
1109}
1110
Yabin Cuib5e11412017-03-10 16:01:01 -08001111ConnectionState atransport::GetConnectionState() const {
1112 return connection_state_;
1113}
1114
1115void atransport::SetConnectionState(ConnectionState state) {
1116 check_main_thread();
1117 connection_state_ = state;
1118}
1119
Luis Hector Chavez9a388d52018-04-25 08:56:41 -07001120void atransport::SetConnection(std::unique_ptr<Connection> connection) {
1121 std::lock_guard<std::mutex> lock(mutex_);
1122 connection_ = std::shared_ptr<Connection>(std::move(connection));
1123}
1124
Josh Gaoffbd3362018-02-28 14:44:23 -08001125std::string atransport::connection_state_name() const {
Yabin Cuib5e11412017-03-10 16:01:01 -08001126 ConnectionState state = GetConnectionState();
1127 switch (state) {
Josh Gao1290fbf2016-11-22 14:32:34 -08001128 case kCsOffline:
1129 return "offline";
1130 case kCsBootloader:
1131 return "bootloader";
1132 case kCsDevice:
1133 return "device";
1134 case kCsHost:
1135 return "host";
1136 case kCsRecovery:
1137 return "recovery";
Tao Bao55d407e2019-04-07 23:24:03 -07001138 case kCsRescue:
1139 return "rescue";
Josh Gao1290fbf2016-11-22 14:32:34 -08001140 case kCsNoPerm:
1141 return UsbNoPermissionsShortHelpText();
1142 case kCsSideload:
1143 return "sideload";
1144 case kCsUnauthorized:
1145 return "unauthorized";
Josh Gao704494b2018-05-04 16:04:49 -07001146 case kCsAuthorizing:
1147 return "authorizing";
1148 case kCsConnecting:
1149 return "connecting";
Josh Gao1290fbf2016-11-22 14:32:34 -08001150 default:
1151 return "unknown";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001152 }
1153}
1154
Tamas Berghammer3d2904c2015-07-13 19:12:28 +01001155void atransport::update_version(int version, size_t payload) {
1156 protocol_version = std::min(version, A_VERSION);
1157 max_payload = std::min(payload, MAX_PAYLOAD);
1158}
1159
1160int atransport::get_protocol_version() const {
1161 return protocol_version;
1162}
1163
Joshua Duong5cf78682020-01-21 13:19:42 -08001164int atransport::get_tls_version() const {
1165 return tls_version;
1166}
1167
Tamas Berghammer3d2904c2015-07-13 19:12:28 +01001168size_t atransport::get_max_payload() const {
1169 return max_payload;
1170}
1171
Dan Albert1792c232015-05-18 13:06:53 -07001172const FeatureSet& supported_features() {
Yurii Zubrytskyi6fc26df2020-03-26 18:19:28 -07001173 static const android::base::NoDestructor<FeatureSet> features([] {
1174 return FeatureSet{
1175 kFeatureShell2,
1176 kFeatureCmd,
1177 kFeatureStat2,
1178 kFeatureLs2,
1179 kFeatureFixedPushMkdir,
1180 kFeatureApex,
1181 kFeatureAbb,
1182 kFeatureFixedPushSymlinkTimestamp,
1183 kFeatureAbbExec,
1184 kFeatureRemountShell,
1185 kFeatureTrackApp,
1186 kFeatureSendRecv2,
1187 kFeatureSendRecv2Brotli,
1188 kFeatureSendRecv2LZ4,
1189 kFeatureSendRecv2DryRunSend,
1190 // Increment ADB_SERVER_VERSION when adding a feature that adbd needs
1191 // to know about. Otherwise, the client can be stuck running an old
1192 // version of the server even after upgrading their copy of adb.
1193 // (http://b/24370690)
1194 };
1195 }());
David Pursell4e2fd362015-09-22 10:43:08 -07001196
1197 return *features;
1198}
1199
1200std::string FeatureSetToString(const FeatureSet& features) {
Elliott Hughes86ab9ff2018-09-05 12:13:11 -07001201 return android::base::Join(features, ',');
David Pursell4e2fd362015-09-22 10:43:08 -07001202}
1203
1204FeatureSet StringToFeatureSet(const std::string& features_string) {
David Purselld2b588e2015-09-25 13:04:21 -07001205 if (features_string.empty()) {
1206 return FeatureSet();
1207 }
1208
Yurii Zubrytskyi6fc26df2020-03-26 18:19:28 -07001209 return android::base::Split(features_string, ",");
1210}
1211
1212template <class Range, class Value>
1213static bool contains(const Range& r, const Value& v) {
1214 return std::find(std::begin(r), std::end(r), v) != std::end(r);
Dan Albert1792c232015-05-18 13:06:53 -07001215}
1216
David Pursell70ef7b42015-09-30 13:35:42 -07001217bool CanUseFeature(const FeatureSet& feature_set, const std::string& feature) {
Yurii Zubrytskyi6fc26df2020-03-26 18:19:28 -07001218 return contains(feature_set, feature) && contains(supported_features(), feature);
David Pursell70ef7b42015-09-30 13:35:42 -07001219}
1220
Dan Albert1792c232015-05-18 13:06:53 -07001221bool atransport::has_feature(const std::string& feature) const {
Yurii Zubrytskyi6fc26df2020-03-26 18:19:28 -07001222 return contains(features_, feature);
Dan Albert1792c232015-05-18 13:06:53 -07001223}
1224
David Pursell4e2fd362015-09-22 10:43:08 -07001225void atransport::SetFeatures(const std::string& features_string) {
1226 features_ = StringToFeatureSet(features_string);
Dan Albert1792c232015-05-18 13:06:53 -07001227}
1228
Yabin Cuib3298242015-08-28 15:09:44 -07001229void atransport::AddDisconnect(adisconnect* disconnect) {
1230 disconnects_.push_back(disconnect);
1231}
1232
1233void atransport::RemoveDisconnect(adisconnect* disconnect) {
1234 disconnects_.remove(disconnect);
1235}
1236
1237void atransport::RunDisconnects() {
Elliott Hughes65fe2512015-10-07 15:59:35 -07001238 for (const auto& disconnect : disconnects_) {
Yabin Cuib3298242015-08-28 15:09:44 -07001239 disconnect->func(disconnect->opaque, this);
1240 }
1241 disconnects_.clear();
1242}
1243
David Pursell3f902aa2016-03-01 08:58:26 -08001244bool atransport::MatchesTarget(const std::string& target) const {
Luis Hector Chavez6150a372018-07-18 21:18:27 -07001245 if (!serial.empty()) {
David Pursell3f902aa2016-03-01 08:58:26 -08001246 if (target == serial) {
1247 return true;
1248 } else if (type == kTransportLocal) {
1249 // Local transports can match [tcp:|udp:]<hostname>[:port].
1250 const char* local_target_ptr = target.c_str();
1251
1252 // For fastboot compatibility, ignore protocol prefixes.
1253 if (android::base::StartsWith(target, "tcp:") ||
Josh Gao1290fbf2016-11-22 14:32:34 -08001254 android::base::StartsWith(target, "udp:")) {
David Pursell3f902aa2016-03-01 08:58:26 -08001255 local_target_ptr += 4;
1256 }
1257
1258 // Parse our |serial| and the given |target| to check if the hostnames and ports match.
1259 std::string serial_host, error;
1260 int serial_port = -1;
Josh Gao1290fbf2016-11-22 14:32:34 -08001261 if (android::base::ParseNetAddress(serial, &serial_host, &serial_port, nullptr, &error)) {
David Pursell3f902aa2016-03-01 08:58:26 -08001262 // |target| may omit the port to default to ours.
1263 std::string target_host;
1264 int target_port = serial_port;
1265 if (android::base::ParseNetAddress(local_target_ptr, &target_host, &target_port,
1266 nullptr, &error) &&
Josh Gao1290fbf2016-11-22 14:32:34 -08001267 serial_host == target_host && serial_port == target_port) {
David Pursell3f902aa2016-03-01 08:58:26 -08001268 return true;
1269 }
1270 }
1271 }
1272 }
1273
Luis Hector Chavez6150a372018-07-18 21:18:27 -07001274 return (target == devpath) || qual_match(target, "product:", product, false) ||
1275 qual_match(target, "model:", model, true) ||
1276 qual_match(target, "device:", device, false);
David Pursell3f902aa2016-03-01 08:58:26 -08001277}
1278
Luis Hector Chavez56fe7532018-04-17 14:25:04 -07001279void atransport::SetConnectionEstablished(bool success) {
1280 connection_waitable_->SetConnectionEstablished(success);
1281}
1282
Josh Gaofc2e56f2018-08-30 11:37:00 -07001283ReconnectResult atransport::Reconnect() {
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -07001284 return reconnect_(this);
1285}
1286
Elliott Hughese67f1f82015-04-30 17:32:03 -07001287#if ADB_HOST
1288
Josh Gaob122b172017-08-16 16:57:01 -07001289// We use newline as our delimiter, make sure to never output it.
1290static std::string sanitize(std::string str, bool alphanumeric) {
1291 auto pred = alphanumeric ? [](const char c) { return !isalnum(c); }
1292 : [](const char c) { return c == '\n'; };
1293 std::replace_if(str.begin(), str.end(), pred, '_');
1294 return str;
1295}
1296
Luis Hector Chavez6150a372018-07-18 21:18:27 -07001297static void append_transport_info(std::string* result, const char* key, const std::string& value,
Josh Gaob122b172017-08-16 16:57:01 -07001298 bool alphanumeric) {
Luis Hector Chavez6150a372018-07-18 21:18:27 -07001299 if (value.empty()) {
Scott Anderson2ca3e6b2012-05-30 18:11:27 -07001300 return;
Scott Anderson2ca3e6b2012-05-30 18:11:27 -07001301 }
1302
Elliott Hughese67f1f82015-04-30 17:32:03 -07001303 *result += ' ';
1304 *result += key;
Josh Gaob122b172017-08-16 16:57:01 -07001305 *result += sanitize(value, alphanumeric);
Scott Anderson2ca3e6b2012-05-30 18:11:27 -07001306}
1307
Josh Gao1290fbf2016-11-22 14:32:34 -08001308static void append_transport(const atransport* t, std::string* result, bool long_listing) {
Luis Hector Chavez6150a372018-07-18 21:18:27 -07001309 std::string serial = t->serial;
1310 if (serial.empty()) {
Dan Albertd99d9022015-05-06 16:48:52 -07001311 serial = "(no serial number)";
Elliott Hughese67f1f82015-04-30 17:32:03 -07001312 }
Scott Anderson2ca3e6b2012-05-30 18:11:27 -07001313
1314 if (!long_listing) {
Elliott Hughese67f1f82015-04-30 17:32:03 -07001315 *result += serial;
1316 *result += '\t';
1317 *result += t->connection_state_name();
Scott Anderson2ca3e6b2012-05-30 18:11:27 -07001318 } else {
Luis Hector Chavez6150a372018-07-18 21:18:27 -07001319 android::base::StringAppendF(result, "%-22s %s", serial.c_str(),
1320 t->connection_state_name().c_str());
Scott Anderson2ca3e6b2012-05-30 18:11:27 -07001321
Elliott Hughese67f1f82015-04-30 17:32:03 -07001322 append_transport_info(result, "", t->devpath, false);
1323 append_transport_info(result, "product:", t->product, false);
1324 append_transport_info(result, "model:", t->model, true);
1325 append_transport_info(result, "device:", t->device, false);
Josh Gaob122b172017-08-16 16:57:01 -07001326
1327 // Put id at the end, so that anyone parsing the output here can always find it by scanning
1328 // backwards from newlines, even with hypothetical devices named 'transport_id:1'.
1329 *result += " transport_id:";
1330 *result += std::to_string(t->id);
Scott Anderson2ca3e6b2012-05-30 18:11:27 -07001331 }
Elliott Hughese67f1f82015-04-30 17:32:03 -07001332 *result += '\n';
Scott Anderson2ca3e6b2012-05-30 18:11:27 -07001333}
1334
Elliott Hughese67f1f82015-04-30 17:32:03 -07001335std::string list_transports(bool long_listing) {
Josh Gao1db71af2017-08-17 13:50:51 -07001336 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Artem Iglikov04398a92017-12-17 10:56:07 +00001337
1338 auto sorted_transport_list = transport_list;
1339 sorted_transport_list.sort([](atransport*& x, atransport*& y) {
1340 if (x->type != y->type) {
1341 return x->type < y->type;
1342 }
Luis Hector Chavez6150a372018-07-18 21:18:27 -07001343 return x->serial < y->serial;
Artem Iglikov04398a92017-12-17 10:56:07 +00001344 });
1345
1346 std::string result;
1347 for (const auto& t : sorted_transport_list) {
Elliott Hughese67f1f82015-04-30 17:32:03 -07001348 append_transport(t, &result, long_listing);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001349 }
Elliott Hughese67f1f82015-04-30 17:32:03 -07001350 return result;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001351}
1352
Josh Gao3705b342019-03-28 15:47:44 -07001353void close_usb_devices(std::function<bool(const atransport*)> predicate, bool reset) {
Josh Gao1db71af2017-08-17 13:50:51 -07001354 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gao22d2b3e2016-10-27 14:01:08 -07001355 for (auto& t : transport_list) {
1356 if (predicate(t)) {
Josh Gao3705b342019-03-28 15:47:44 -07001357 if (reset) {
1358 t->Reset();
1359 } else {
1360 t->Kick();
1361 }
Josh Gao22d2b3e2016-10-27 14:01:08 -07001362 }
1363 }
1364}
1365
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001366/* hack for osx */
Josh Gao3705b342019-03-28 15:47:44 -07001367void close_usb_devices(bool reset) {
1368 close_usb_devices([](const atransport*) { return true; }, reset);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001369}
Josh Gao1290fbf2016-11-22 14:32:34 -08001370#endif // ADB_HOST
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001371
Josh Gao362e6962018-08-08 16:20:14 -07001372bool register_socket_transport(unique_fd s, std::string serial, int port, int local,
Joshua Duong5cf78682020-01-21 13:19:42 -08001373 atransport::ReconnectCallback reconnect, bool use_tls, int* error) {
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -07001374 atransport* t = new atransport(std::move(reconnect), kCsOffline);
Joshua Duong5cf78682020-01-21 13:19:42 -08001375 t->use_tls = use_tls;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +01001376
Josh Gao3b4de3c2018-08-02 13:58:24 -07001377 D("transport: %s init'ing for socket %d, on port %d", serial.c_str(), s.get(), port);
Josh Gao56300c92018-07-25 17:21:49 -07001378 if (init_socket_transport(t, std::move(s), port, local) < 0) {
Dan Albertc7915a32015-05-18 16:46:31 -07001379 delete t;
Josh Gao362e6962018-08-08 16:20:14 -07001380 if (error) *error = errno;
1381 return false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001382 }
Benoit Goby1c45ee92013-03-29 18:22:36 -07001383
Josh Gao1db71af2017-08-17 13:50:51 -07001384 std::unique_lock<std::recursive_mutex> lock(transport_lock);
Elliott Hughes65fe2512015-10-07 15:59:35 -07001385 for (const auto& transport : pending_list) {
Josh Gao3b4de3c2018-08-02 13:58:24 -07001386 if (serial == transport->serial) {
Yabin Cuib74c6492016-04-29 16:53:52 -07001387 VLOG(TRANSPORT) << "socket transport " << transport->serial
Josh Gao1290fbf2016-11-22 14:32:34 -08001388 << " is already in pending_list and fails to register";
Dan Albertc7915a32015-05-18 16:46:31 -07001389 delete t;
Josh Gao362e6962018-08-08 16:20:14 -07001390 if (error) *error = EALREADY;
1391 return false;
Benoit Goby1c45ee92013-03-29 18:22:36 -07001392 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001393 }
Benoit Goby1c45ee92013-03-29 18:22:36 -07001394
Elliott Hughes65fe2512015-10-07 15:59:35 -07001395 for (const auto& transport : transport_list) {
Josh Gao3b4de3c2018-08-02 13:58:24 -07001396 if (serial == transport->serial) {
Yabin Cuib74c6492016-04-29 16:53:52 -07001397 VLOG(TRANSPORT) << "socket transport " << transport->serial
Josh Gao1290fbf2016-11-22 14:32:34 -08001398 << " is already in transport_list and fails to register";
Dan Albertc7915a32015-05-18 16:46:31 -07001399 delete t;
Josh Gao362e6962018-08-08 16:20:14 -07001400 if (error) *error = EALREADY;
1401 return false;
Benoit Goby1c45ee92013-03-29 18:22:36 -07001402 }
1403 }
1404
Josh Gao3b4de3c2018-08-02 13:58:24 -07001405 t->serial = std::move(serial);
Dan Albertc7915a32015-05-18 16:46:31 -07001406 pending_list.push_front(t);
Josh Gao0cd3ae12016-09-21 12:37:10 -07001407
1408 lock.unlock();
Benoit Goby1c45ee92013-03-29 18:22:36 -07001409
Luis Hector Chavez56fe7532018-04-17 14:25:04 -07001410 auto waitable = t->connection_waitable();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001411 register_transport(t);
Luis Hector Chavez56fe7532018-04-17 14:25:04 -07001412
Luis Hector Chavezc587f022018-05-01 17:12:16 -07001413 if (local == 1) {
1414 // Do not wait for emulator transports.
Josh Gao362e6962018-08-08 16:20:14 -07001415 return true;
Luis Hector Chavezc587f022018-05-01 17:12:16 -07001416 }
1417
Josh Gao362e6962018-08-08 16:20:14 -07001418 if (!waitable->WaitForConnection(std::chrono::seconds(10))) {
1419 if (error) *error = ETIMEDOUT;
1420 return false;
1421 }
1422
1423 if (t->GetConnectionState() == kCsUnauthorized) {
1424 if (error) *error = EPERM;
1425 return false;
1426 }
1427
1428 return true;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001429}
1430
Mike Lockwood8cf0d592009-10-11 23:04:18 -04001431#if ADB_HOST
Josh Gao1290fbf2016-11-22 14:32:34 -08001432atransport* find_transport(const char* serial) {
Dan Albertc7915a32015-05-18 16:46:31 -07001433 atransport* result = nullptr;
Mike Lockwood8cf0d592009-10-11 23:04:18 -04001434
Josh Gao1db71af2017-08-17 13:50:51 -07001435 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Yabin Cuif4b99282015-08-27 12:03:11 -07001436 for (auto& t : transport_list) {
Luis Hector Chavez6150a372018-07-18 21:18:27 -07001437 if (strcmp(serial, t->serial.c_str()) == 0) {
Dan Albertc7915a32015-05-18 16:46:31 -07001438 result = t;
Mike Lockwood8cf0d592009-10-11 23:04:18 -04001439 break;
1440 }
Dan Albertc7915a32015-05-18 16:46:31 -07001441 }
Mike Lockwood8cf0d592009-10-11 23:04:18 -04001442
Dan Albertc7915a32015-05-18 16:46:31 -07001443 return result;
Mike Lockwood8cf0d592009-10-11 23:04:18 -04001444}
1445
Yabin Cuif4b99282015-08-27 12:03:11 -07001446void kick_all_tcp_devices() {
Josh Gao1db71af2017-08-17 13:50:51 -07001447 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Yabin Cuif4b99282015-08-27 12:03:11 -07001448 for (auto& t : transport_list) {
Yabin Cuib74c6492016-04-29 16:53:52 -07001449 if (t->IsTcpDevice()) {
Yabin Cuid6ab3c22015-08-31 11:50:24 -07001450 // Kicking breaks the read_transport thread of this transport out of any read, then
1451 // the read_transport thread will notify the main thread to make this transport
1452 // offline. Then the main thread will notify the write_transport thread to exit.
Yabin Cuif4b99282015-08-27 12:03:11 -07001453 // Finally, this transport will be closed and freed in the main thread.
Yabin Cui7f274902016-04-18 11:22:34 -07001454 t->Kick();
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001455 }
Dan Albertc7915a32015-05-18 16:46:31 -07001456 }
Josh Gao902dace2018-08-10 14:44:54 -07001457#if ADB_HOST
1458 reconnect_handler.CheckForKicked();
1459#endif
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -04001460}
1461
Mike Lockwood8cf0d592009-10-11 23:04:18 -04001462#endif
1463
Josh Gao08718242020-03-27 18:09:56 -07001464#if ADB_HOST
Josh Gao1290fbf2016-11-22 14:32:34 -08001465void register_usb_transport(usb_handle* usb, const char* serial, const char* devpath,
1466 unsigned writeable) {
Luis Hector Chavez454bc7c2018-04-20 10:31:29 -07001467 atransport* t = new atransport(writeable ? kCsOffline : kCsNoPerm);
Dan Albertc7915a32015-05-18 16:46:31 -07001468
Josh Gao1290fbf2016-11-22 14:32:34 -08001469 D("transport: %p init'ing for usb_handle %p (sn='%s')", t, usb, serial ? serial : "");
Yabin Cuib5e11412017-03-10 16:01:01 -08001470 init_usb_transport(t, usb);
Josh Gao1290fbf2016-11-22 14:32:34 -08001471 if (serial) {
Luis Hector Chavez6150a372018-07-18 21:18:27 -07001472 t->serial = serial;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001473 }
Dan Albertc7915a32015-05-18 16:46:31 -07001474
1475 if (devpath) {
Luis Hector Chavez6150a372018-07-18 21:18:27 -07001476 t->devpath = devpath;
Scott Andersone109d262012-04-20 11:21:14 -07001477 }
Benoit Goby1c45ee92013-03-29 18:22:36 -07001478
Josh Gao0cd3ae12016-09-21 12:37:10 -07001479 {
Josh Gao1db71af2017-08-17 13:50:51 -07001480 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gao0cd3ae12016-09-21 12:37:10 -07001481 pending_list.push_front(t);
1482 }
Benoit Goby1c45ee92013-03-29 18:22:36 -07001483
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001484 register_transport(t);
1485}
Josh Gao08718242020-03-27 18:09:56 -07001486#endif
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001487
Josh Gaoc51726c2018-10-11 16:33:05 -07001488#if ADB_HOST
Dan Albertdcd78a12015-05-18 16:43:57 -07001489// This should only be used for transports with connection_state == kCsNoPerm.
Josh Gao1290fbf2016-11-22 14:32:34 -08001490void unregister_usb_transport(usb_handle* usb) {
Josh Gao1db71af2017-08-17 13:50:51 -07001491 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gaob800d882018-01-28 20:32:46 -08001492 transport_list.remove_if([usb](atransport* t) {
Josh Gaoce5ce872018-12-11 13:11:52 -08001493 return t->GetUsbHandle() == usb && t->GetConnectionState() == kCsNoPerm;
Josh Gaob800d882018-01-28 20:32:46 -08001494 });
Mike Lockwood0927bf92009-08-08 12:37:44 -04001495}
Josh Gaoc51726c2018-10-11 16:33:05 -07001496#endif
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001497
Josh Gao36dadca2017-05-16 15:02:45 -07001498bool check_header(apacket* p, atransport* t) {
Josh Gao1290fbf2016-11-22 14:32:34 -08001499 if (p->msg.magic != (p->msg.command ^ 0xffffffff)) {
Yabin Cuib5e11412017-03-10 16:01:01 -08001500 VLOG(RWX) << "check_header(): invalid magic command = " << std::hex << p->msg.command
1501 << ", magic = " << p->msg.magic;
Josh Gao36dadca2017-05-16 15:02:45 -07001502 return false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001503 }
1504
Josh Gao1290fbf2016-11-22 14:32:34 -08001505 if (p->msg.data_length > t->get_max_payload()) {
1506 VLOG(RWX) << "check_header(): " << p->msg.data_length
1507 << " atransport::max_payload = " << t->get_max_payload();
Josh Gao36dadca2017-05-16 15:02:45 -07001508 return false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001509 }
1510
Josh Gao36dadca2017-05-16 15:02:45 -07001511 return true;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001512}
1513
Josh Gao3bd28792016-10-05 19:02:29 -07001514#if ADB_HOST
Joshua Duong5cf78682020-01-21 13:19:42 -08001515std::shared_ptr<RSA> atransport::Key() {
1516 if (keys_.empty()) {
1517 return nullptr;
1518 }
1519
1520 std::shared_ptr<RSA> result = keys_[0];
1521 return result;
1522}
1523
Josh Gao2e671202016-08-18 22:00:12 -07001524std::shared_ptr<RSA> atransport::NextKey() {
Josh Gao4414e4c2018-12-04 01:07:50 -08001525 if (keys_.empty()) {
1526 LOG(INFO) << "fetching keys for transport " << this->serial_name();
1527 keys_ = adb_auth_get_private_keys();
1528
1529 // We should have gotten at least one key: the one that's automatically generated.
1530 CHECK(!keys_.empty());
Joshua Duong5cf78682020-01-21 13:19:42 -08001531 } else {
1532 keys_.pop_front();
Josh Gao4414e4c2018-12-04 01:07:50 -08001533 }
Elliott Hughes0aeb5052016-06-29 17:42:01 -07001534
Josh Gao2e671202016-08-18 22:00:12 -07001535 std::shared_ptr<RSA> result = keys_[0];
Elliott Hughes0aeb5052016-06-29 17:42:01 -07001536 return result;
1537}
Josh Gao4414e4c2018-12-04 01:07:50 -08001538
1539void atransport::ResetKeys() {
1540 keys_.clear();
1541}
Josh Gao3bd28792016-10-05 19:02:29 -07001542#endif