blob: 37b56e28f8c1ec10f59877db43a0719e09081d6b [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#include "sysdeps/memory.h"
21
Dan Albert76649012015-02-24 15:51:19 -080022#include "transport.h"
23
Dan Albert055f1aa2015-02-20 17:24:58 -080024#include <ctype.h>
Dan Albert76649012015-02-24 15:51:19 -080025#include <errno.h>
Josh Gaob122b172017-08-16 16:57:01 -070026#include <inttypes.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080027#include <stdio.h>
28#include <stdlib.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080029#include <string.h>
Dan Albert76649012015-02-24 15:51:19 -080030#include <unistd.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080031
Spencer Low363af562015-11-07 18:51:54 -080032#include <algorithm>
Josh Gao0bbf69c2018-02-16 13:24:58 -080033#include <deque>
Dan Albertc7915a32015-05-18 16:46:31 -070034#include <list>
Josh Gao0cd3ae12016-09-21 12:37:10 -070035#include <mutex>
Josh Gaoe1dacfc2017-04-12 17:00:49 -070036#include <thread>
Dan Albertc7915a32015-05-18 16:46:31 -070037
Elliott Hughes4f713192015-12-04 22:00:26 -080038#include <android-base/logging.h>
David Pursell3f902aa2016-03-01 08:58:26 -080039#include <android-base/parsenetaddress.h>
Elliott Hughes4f713192015-12-04 22:00:26 -080040#include <android-base/stringprintf.h>
41#include <android-base/strings.h>
Josh Gaob122b172017-08-16 16:57:01 -070042#include <android-base/thread_annotations.h>
Elliott Hughese67f1f82015-04-30 17:32:03 -070043
Josh Gao27768452018-01-02 12:01:43 -080044#include <diagnose_usb.h>
45
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080046#include "adb.h"
Elliott Hughes0aeb5052016-06-29 17:42:01 -070047#include "adb_auth.h"
Josh Gaob800d882018-01-28 20:32:46 -080048#include "adb_io.h"
Josh Gaocfe72e22016-11-29 09:40:29 -080049#include "adb_trace.h"
Elliott Hughese67f1f82015-04-30 17:32:03 -070050#include "adb_utils.h"
Yabin Cuib5e11412017-03-10 16:01:01 -080051#include "fdevent.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080052
53static void transport_unref(atransport *t);
54
Josh Gaob122b172017-08-16 16:57:01 -070055// TODO: unordered_map<TransportId, atransport*>
Josh Gaob7b1edf2015-11-11 17:56:12 -080056static auto& transport_list = *new std::list<atransport*>();
57static auto& pending_list = *new std::list<atransport*>();
Benoit Goby1c45ee92013-03-29 18:22:36 -070058
Josh Gao1db71af2017-08-17 13:50:51 -070059static auto& transport_lock = *new std::recursive_mutex();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080060
Todd Kennedy51c05ec2015-11-10 00:03:25 +000061const char* const kFeatureShell2 = "shell_v2";
62const char* const kFeatureCmd = "cmd";
Josh Gao5a1e3fd2016-12-05 17:11:34 -080063const char* const kFeatureStat2 = "stat_v2";
Josh Gao5d1756c2017-02-22 17:07:01 -080064const char* const kFeatureLibusb = "libusb";
Dan Albert5176df82017-05-23 14:30:00 -070065const char* const kFeaturePushSync = "push_sync";
Todd Kennedy51c05ec2015-11-10 00:03:25 +000066
Josh Gaob122b172017-08-16 16:57:01 -070067TransportId NextTransportId() {
68 static std::atomic<TransportId> next(1);
69 return next++;
70}
71
Josh Gao0bbf69c2018-02-16 13:24:58 -080072BlockingConnectionAdapter::BlockingConnectionAdapter(std::unique_ptr<BlockingConnection> connection)
73 : underlying_(std::move(connection)) {}
74
75BlockingConnectionAdapter::~BlockingConnectionAdapter() {
76 LOG(INFO) << "BlockingConnectionAdapter(" << this->transport_name_ << "): destructing";
77 Stop();
78}
79
80void BlockingConnectionAdapter::Start() {
81 read_thread_ = std::thread([this]() {
82 LOG(INFO) << this->transport_name_ << ": read thread spawning";
83 while (true) {
Josh Gao31b5be62018-03-07 16:51:08 -080084 auto packet = std::make_unique<apacket>();
Josh Gao0bbf69c2018-02-16 13:24:58 -080085 if (!underlying_->Read(packet.get())) {
86 PLOG(INFO) << this->transport_name_ << ": read failed";
87 break;
88 }
89 read_callback_(this, std::move(packet));
90 }
91 std::call_once(this->error_flag_, [this]() { this->error_callback_(this, "read failed"); });
92 });
93
94 write_thread_ = std::thread([this]() {
95 LOG(INFO) << this->transport_name_ << ": write thread spawning";
96 while (true) {
97 std::unique_lock<std::mutex> lock(mutex_);
98 cv_.wait(lock, [this]() { return this->stopped_ || !this->write_queue_.empty(); });
99
100 if (this->stopped_) {
101 return;
102 }
103
104 std::unique_ptr<apacket> packet = std::move(this->write_queue_.front());
105 this->write_queue_.pop_front();
106 lock.unlock();
107
108 if (!this->underlying_->Write(packet.get())) {
109 break;
110 }
111 }
112 std::call_once(this->error_flag_, [this]() { this->error_callback_(this, "write failed"); });
113 });
114}
115
116void BlockingConnectionAdapter::Stop() {
117 std::unique_lock<std::mutex> lock(mutex_);
118 if (stopped_) {
119 LOG(INFO) << "BlockingConnectionAdapter(" << this->transport_name_ << "): already stopped";
120 return;
121 }
122
123 stopped_ = true;
124 lock.unlock();
125
126 LOG(INFO) << "BlockingConnectionAdapter(" << this->transport_name_ << "): stopping";
127
128 this->underlying_->Close();
129
130 this->cv_.notify_one();
131 read_thread_.join();
132 write_thread_.join();
133
134 LOG(INFO) << "BlockingConnectionAdapter(" << this->transport_name_ << "): stopped";
135 std::call_once(this->error_flag_, [this]() { this->error_callback_(this, "requested stop"); });
136}
137
138bool BlockingConnectionAdapter::Write(std::unique_ptr<apacket> packet) {
139 {
140 std::unique_lock<std::mutex> lock(this->mutex_);
141 write_queue_.emplace_back(std::move(packet));
142 }
143
144 cv_.notify_one();
145 return true;
146}
147
Josh Gaob800d882018-01-28 20:32:46 -0800148bool FdConnection::Read(apacket* packet) {
149 if (!ReadFdExactly(fd_.get(), &packet->msg, sizeof(amessage))) {
150 D("remote local: read terminated (message)");
151 return false;
152 }
153
Josh Gaof571fcb2018-02-05 18:49:10 -0800154 if (packet->msg.data_length > MAX_PAYLOAD) {
Josh Gao5caaebd2018-02-02 14:38:04 -0800155 D("remote local: read overflow (data length = %" PRIu32 ")", packet->msg.data_length);
156 return false;
157 }
158
Josh Gaof571fcb2018-02-05 18:49:10 -0800159 packet->payload.resize(packet->msg.data_length);
160
161 if (!ReadFdExactly(fd_.get(), &packet->payload[0], packet->payload.size())) {
Josh Gaob800d882018-01-28 20:32:46 -0800162 D("remote local: terminated (data)");
163 return false;
164 }
165
166 return true;
167}
168
169bool FdConnection::Write(apacket* packet) {
Josh Gaof571fcb2018-02-05 18:49:10 -0800170 if (!WriteFdExactly(fd_.get(), &packet->msg, sizeof(packet->msg))) {
Josh Gaob800d882018-01-28 20:32:46 -0800171 D("remote local: write terminated");
172 return false;
173 }
174
Josh Gaof571fcb2018-02-05 18:49:10 -0800175 if (packet->msg.data_length) {
176 if (!WriteFdExactly(fd_.get(), &packet->payload[0], packet->msg.data_length)) {
177 D("remote local: write terminated");
178 return false;
179 }
180 }
181
Josh Gaob800d882018-01-28 20:32:46 -0800182 return true;
183}
184
185void FdConnection::Close() {
186 adb_shutdown(fd_.get());
187 fd_.reset();
188}
189
Yabin Cuiaed3c612015-09-22 15:52:57 -0700190static std::string dump_packet(const char* name, const char* func, apacket* p) {
Josh Gao1290fbf2016-11-22 14:32:34 -0800191 unsigned command = p->msg.command;
192 int len = p->msg.data_length;
193 char cmd[9];
194 char arg0[12], arg1[12];
195 int n;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100196
197 for (n = 0; n < 4; n++) {
Josh Gao1290fbf2016-11-22 14:32:34 -0800198 int b = (command >> (n * 8)) & 255;
199 if (b < 32 || b >= 127) break;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100200 cmd[n] = (char)b;
201 }
202 if (n == 4) {
203 cmd[4] = 0;
204 } else {
205 /* There is some non-ASCII name in the command, so dump
206 * the hexadecimal value instead */
207 snprintf(cmd, sizeof cmd, "%08x", command);
208 }
209
210 if (p->msg.arg0 < 256U)
211 snprintf(arg0, sizeof arg0, "%d", p->msg.arg0);
212 else
213 snprintf(arg0, sizeof arg0, "0x%x", p->msg.arg0);
214
215 if (p->msg.arg1 < 256U)
216 snprintf(arg1, sizeof arg1, "%d", p->msg.arg1);
217 else
218 snprintf(arg1, sizeof arg1, "0x%x", p->msg.arg1);
219
Josh Gao1290fbf2016-11-22 14:32:34 -0800220 std::string result = android::base::StringPrintf("%s: %s: [%s] arg0=%s arg1=%s (len=%d) ", name,
221 func, cmd, arg0, arg1, len);
Josh Gaof571fcb2018-02-05 18:49:10 -0800222 result += dump_hex(p->payload.data(), p->payload.size());
Yabin Cuiaed3c612015-09-22 15:52:57 -0700223 return result;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100224}
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100225
Josh Gao06d61d42016-10-06 13:31:44 -0700226void send_packet(apacket* p, atransport* t) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800227 p->msg.magic = p->msg.command ^ 0xffffffff;
Tim Murrayde471942017-12-07 11:40:00 -0800228 // compute a checksum for connection/auth packets for compatibility reasons
229 if (t->get_protocol_version() >= A_VERSION_SKIP_CHECKSUM) {
230 p->msg.data_check = 0;
231 } else {
232 p->msg.data_check = calculate_apacket_checksum(p);
233 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800234
Josh Gao0bbf69c2018-02-16 13:24:58 -0800235 VLOG(TRANSPORT) << dump_packet(t->serial, "to remote", p);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800236
237 if (t == NULL) {
Josh Gao06d61d42016-10-06 13:31:44 -0700238 fatal("Transport is null");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800239 }
240
Josh Gao0bbf69c2018-02-16 13:24:58 -0800241 if (t->Write(p) != 0) {
242 D("%s: failed to enqueue packet, closing transport", t->serial);
243 t->Kick();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800244 }
245}
246
Yabin Cuif4b99282015-08-27 12:03:11 -0700247void kick_transport(atransport* t) {
Josh Gao1db71af2017-08-17 13:50:51 -0700248 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Yabin Cui1f4ec192016-04-05 13:50:44 -0700249 // As kick_transport() can be called from threads without guarantee that t is valid,
250 // check if the transport is in transport_list first.
Josh Gaob122b172017-08-16 16:57:01 -0700251 //
252 // TODO(jmgao): WTF? Is this actually true?
Yabin Cui1f4ec192016-04-05 13:50:44 -0700253 if (std::find(transport_list.begin(), transport_list.end(), t) != transport_list.end()) {
Yabin Cui7f274902016-04-18 11:22:34 -0700254 t->Kick();
Yabin Cui1f4ec192016-04-05 13:50:44 -0700255 }
Yabin Cuif4b99282015-08-27 12:03:11 -0700256}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800257
258static int transport_registration_send = -1;
259static int transport_registration_recv = -1;
260static fdevent transport_registration_fde;
261
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800262#if ADB_HOST
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800263
264/* this adds support required by the 'track-devices' service.
265 * this is used to send the content of "list_transport" to any
266 * number of client connections that want it through a single
267 * live TCP connection
268 */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800269struct device_tracker {
Josh Gao1290fbf2016-11-22 14:32:34 -0800270 asocket socket;
Josh Gaoe0361d12018-02-12 17:24:00 -0800271 bool update_needed = false;
272 bool long_output = false;
273 device_tracker* next = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800274};
275
276/* linked list of all device trackers */
Josh Gao1290fbf2016-11-22 14:32:34 -0800277static device_tracker* device_tracker_list;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800278
Josh Gao1290fbf2016-11-22 14:32:34 -0800279static void device_tracker_remove(device_tracker* tracker) {
280 device_tracker** pnode = &device_tracker_list;
281 device_tracker* node = *pnode;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800282
Josh Gao1db71af2017-08-17 13:50:51 -0700283 std::lock_guard<std::recursive_mutex> lock(transport_lock);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800284 while (node) {
285 if (node == tracker) {
286 *pnode = node->next;
287 break;
288 }
289 pnode = &node->next;
Josh Gao1290fbf2016-11-22 14:32:34 -0800290 node = *pnode;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800291 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800292}
293
Josh Gao1290fbf2016-11-22 14:32:34 -0800294static void device_tracker_close(asocket* socket) {
295 device_tracker* tracker = (device_tracker*)socket;
296 asocket* peer = socket->peer;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800297
Josh Gao1290fbf2016-11-22 14:32:34 -0800298 D("device tracker %p removed", tracker);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800299 if (peer) {
300 peer->peer = NULL;
301 peer->close(peer);
302 }
303 device_tracker_remove(tracker);
Josh Gaoe0361d12018-02-12 17:24:00 -0800304 delete tracker;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800305}
306
Josh Gao27cb7dc2018-02-01 13:17:50 -0800307static int device_tracker_enqueue(asocket* socket, std::string) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800308 /* you can't read from a device tracker, close immediately */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800309 device_tracker_close(socket);
310 return -1;
311}
312
Elliott Hughese67f1f82015-04-30 17:32:03 -0700313static int device_tracker_send(device_tracker* tracker, const std::string& string) {
Elliott Hughese67f1f82015-04-30 17:32:03 -0700314 asocket* peer = tracker->socket.peer;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800315
Josh Gao27cb7dc2018-02-01 13:17:50 -0800316 std::string data;
317 data.resize(4 + string.size());
318 char buf[5];
319 snprintf(buf, sizeof(buf), "%04x", static_cast<int>(string.size()));
320 memcpy(&data[0], buf, 4);
321 memcpy(&data[4], string.data(), string.size());
322 return peer->enqueue(peer, std::move(data));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800323}
324
Elliott Hughese67f1f82015-04-30 17:32:03 -0700325static void device_tracker_ready(asocket* socket) {
326 device_tracker* tracker = reinterpret_cast<device_tracker*>(socket);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800327
Elliott Hughese67f1f82015-04-30 17:32:03 -0700328 // We want to send the device list when the tracker connects
329 // for the first time, even if no update occurred.
Josh Gaob0c18022017-08-14 18:57:54 -0700330 if (tracker->update_needed) {
331 tracker->update_needed = false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800332
Josh Gaob0c18022017-08-14 18:57:54 -0700333 std::string transports = list_transports(tracker->long_output);
Elliott Hughese67f1f82015-04-30 17:32:03 -0700334 device_tracker_send(tracker, transports);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800335 }
336}
337
Josh Gaob0c18022017-08-14 18:57:54 -0700338asocket* create_device_tracker(bool long_output) {
Josh Gaoe0361d12018-02-12 17:24:00 -0800339 device_tracker* tracker = new device_tracker();
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700340 if (tracker == nullptr) fatal("cannot allocate device tracker");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800341
Josh Gao1290fbf2016-11-22 14:32:34 -0800342 D("device tracker %p created", tracker);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800343
344 tracker->socket.enqueue = device_tracker_enqueue;
Josh Gao1290fbf2016-11-22 14:32:34 -0800345 tracker->socket.ready = device_tracker_ready;
346 tracker->socket.close = device_tracker_close;
Josh Gaob0c18022017-08-14 18:57:54 -0700347 tracker->update_needed = true;
348 tracker->long_output = long_output;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800349
Josh Gao1290fbf2016-11-22 14:32:34 -0800350 tracker->next = device_tracker_list;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800351 device_tracker_list = tracker;
352
353 return &tracker->socket;
354}
355
Josh Gaofd713e52017-05-03 22:37:10 -0700356// Check if all of the USB transports are connected.
357bool iterate_transports(std::function<bool(const atransport*)> fn) {
Josh Gao1db71af2017-08-17 13:50:51 -0700358 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gaofd713e52017-05-03 22:37:10 -0700359 for (const auto& t : transport_list) {
360 if (!fn(t)) {
361 return false;
362 }
363 }
364 for (const auto& t : pending_list) {
365 if (!fn(t)) {
366 return false;
367 }
368 }
369 return true;
370}
371
Elliott Hughese67f1f82015-04-30 17:32:03 -0700372// Call this function each time the transport list has changed.
373void update_transports() {
Josh Gaofd713e52017-05-03 22:37:10 -0700374 update_transport_status();
375
376 // Notify `adb track-devices` clients.
Elliott Hughese67f1f82015-04-30 17:32:03 -0700377 std::string transports = list_transports(false);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800378
Elliott Hughese67f1f82015-04-30 17:32:03 -0700379 device_tracker* tracker = device_tracker_list;
380 while (tracker != nullptr) {
381 device_tracker* next = tracker->next;
382 // This may destroy the tracker if the connection is closed.
383 device_tracker_send(tracker, transports);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800384 tracker = next;
385 }
386}
Elliott Hughese67f1f82015-04-30 17:32:03 -0700387
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800388#else
Elliott Hughese67f1f82015-04-30 17:32:03 -0700389
390void update_transports() {
391 // Nothing to do on the device side.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800392}
Elliott Hughese67f1f82015-04-30 17:32:03 -0700393
Josh Gao1290fbf2016-11-22 14:32:34 -0800394#endif // ADB_HOST
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800395
Josh Gao1290fbf2016-11-22 14:32:34 -0800396struct tmsg {
397 atransport* transport;
398 int action;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800399};
400
Josh Gao1290fbf2016-11-22 14:32:34 -0800401static int transport_read_action(int fd, struct tmsg* m) {
402 char* p = (char*)m;
403 int len = sizeof(*m);
404 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800405
Josh Gao1290fbf2016-11-22 14:32:34 -0800406 while (len > 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800407 r = adb_read(fd, p, len);
Josh Gao1290fbf2016-11-22 14:32:34 -0800408 if (r > 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800409 len -= r;
Josh Gao1290fbf2016-11-22 14:32:34 -0800410 p += r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800411 } else {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700412 D("transport_read_action: on fd %d: %s", fd, strerror(errno));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800413 return -1;
414 }
415 }
416 return 0;
417}
418
Josh Gao1290fbf2016-11-22 14:32:34 -0800419static int transport_write_action(int fd, struct tmsg* m) {
420 char* p = (char*)m;
421 int len = sizeof(*m);
422 int r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800423
Josh Gao1290fbf2016-11-22 14:32:34 -0800424 while (len > 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800425 r = adb_write(fd, p, len);
Josh Gao1290fbf2016-11-22 14:32:34 -0800426 if (r > 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800427 len -= r;
Josh Gao1290fbf2016-11-22 14:32:34 -0800428 p += r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800429 } else {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700430 D("transport_write_action: on fd %d: %s", fd, strerror(errno));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800431 return -1;
432 }
433 }
434 return 0;
435}
436
Josh Gao0bbf69c2018-02-16 13:24:58 -0800437static void remove_transport(atransport*);
438
439static void transport_registration_func(int _fd, unsigned ev, void*) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800440 tmsg m;
Josh Gao1290fbf2016-11-22 14:32:34 -0800441 atransport* t;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800442
Josh Gao1290fbf2016-11-22 14:32:34 -0800443 if (!(ev & FDE_READ)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800444 return;
445 }
446
Josh Gao1290fbf2016-11-22 14:32:34 -0800447 if (transport_read_action(_fd, &m)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800448 fatal_errno("cannot read transport registration socket");
449 }
450
451 t = m.transport;
452
Dan Albert1792c232015-05-18 13:06:53 -0700453 if (m.action == 0) {
Josh Gao0bbf69c2018-02-16 13:24:58 -0800454 D("transport: %s deleting", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800455
Josh Gao0cd3ae12016-09-21 12:37:10 -0700456 {
Josh Gao1db71af2017-08-17 13:50:51 -0700457 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gao0cd3ae12016-09-21 12:37:10 -0700458 transport_list.remove(t);
459 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800460
Josh Gao1290fbf2016-11-22 14:32:34 -0800461 if (t->product) free(t->product);
462 if (t->serial) free(t->serial);
463 if (t->model) free(t->model);
464 if (t->device) free(t->device);
465 if (t->devpath) free(t->devpath);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800466
Dan Albertc7915a32015-05-18 16:46:31 -0700467 delete t;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800468
469 update_transports();
470 return;
471 }
472
Mike Lockwood0927bf92009-08-08 12:37:44 -0400473 /* don't create transport threads for inaccessible devices */
Yabin Cuib5e11412017-03-10 16:01:01 -0800474 if (t->GetConnectionState() != kCsNoPerm) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800475 /* initial references are the two threads */
Josh Gao0bbf69c2018-02-16 13:24:58 -0800476 t->ref_count = 1;
477 t->connection->SetTransportName(t->serial_name());
478 t->connection->SetReadCallback([t](Connection*, std::unique_ptr<apacket> p) {
479 if (!check_header(p.get(), t)) {
480 D("%s: remote read: bad header", t->serial);
481 return false;
482 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800483
Josh Gao0bbf69c2018-02-16 13:24:58 -0800484 VLOG(TRANSPORT) << dump_packet(t->serial, "from remote", p.get());
485 apacket* packet = p.release();
Mike Lockwood0927bf92009-08-08 12:37:44 -0400486
Josh Gao0bbf69c2018-02-16 13:24:58 -0800487 // TODO: Does this need to run on the main thread?
488 fdevent_run_on_main_thread([packet, t]() { handle_packet(packet, t); });
489 return true;
490 });
491 t->connection->SetErrorCallback([t](Connection*, const std::string& error) {
492 D("%s: connection terminated: %s", t->serial, error.c_str());
493 fdevent_run_on_main_thread([t]() {
494 handle_offline(t);
495 transport_unref(t);
496 });
497 });
Mike Lockwood0927bf92009-08-08 12:37:44 -0400498
Josh Gao0bbf69c2018-02-16 13:24:58 -0800499 t->connection->Start();
500#if ADB_HOST
501 send_connect(t);
502#endif
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800503 }
504
Josh Gao0cd3ae12016-09-21 12:37:10 -0700505 {
Josh Gao1db71af2017-08-17 13:50:51 -0700506 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gao0cd3ae12016-09-21 12:37:10 -0700507 pending_list.remove(t);
508 transport_list.push_front(t);
509 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800510
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800511 update_transports();
512}
513
Josh Gao1290fbf2016-11-22 14:32:34 -0800514void init_transport_registration(void) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800515 int s[2];
516
Josh Gao1290fbf2016-11-22 14:32:34 -0800517 if (adb_socketpair(s)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800518 fatal_errno("cannot open transport registration socketpair");
519 }
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700520 D("socketpair: (%d,%d)", s[0], s[1]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800521
522 transport_registration_send = s[0];
523 transport_registration_recv = s[1];
524
Josh Gao1290fbf2016-11-22 14:32:34 -0800525 fdevent_install(&transport_registration_fde, transport_registration_recv,
526 transport_registration_func, 0);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800527
528 fdevent_set(&transport_registration_fde, FDE_READ);
Josh Gao01b7bc42017-05-09 13:43:35 -0700529}
530
531void kick_all_transports() {
532 // To avoid only writing part of a packet to a transport after exit, kick all transports.
Josh Gao1db71af2017-08-17 13:50:51 -0700533 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gao01b7bc42017-05-09 13:43:35 -0700534 for (auto t : transport_list) {
535 t->Kick();
536 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800537}
538
539/* the fdevent select pump is single threaded */
Josh Gao1290fbf2016-11-22 14:32:34 -0800540static void register_transport(atransport* transport) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800541 tmsg m;
542 m.transport = transport;
543 m.action = 1;
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700544 D("transport: %s registered", transport->serial);
Josh Gao1290fbf2016-11-22 14:32:34 -0800545 if (transport_write_action(transport_registration_send, &m)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800546 fatal_errno("cannot write transport registration socket\n");
547 }
548}
549
Josh Gao1290fbf2016-11-22 14:32:34 -0800550static void remove_transport(atransport* transport) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800551 tmsg m;
552 m.transport = transport;
553 m.action = 0;
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700554 D("transport: %s removed", transport->serial);
Josh Gao1290fbf2016-11-22 14:32:34 -0800555 if (transport_write_action(transport_registration_send, &m)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800556 fatal_errno("cannot write transport registration socket\n");
557 }
558}
559
Yabin Cuif4b99282015-08-27 12:03:11 -0700560static void transport_unref(atransport* t) {
561 CHECK(t != nullptr);
Josh Gao0cd3ae12016-09-21 12:37:10 -0700562
Josh Gaoe48ecce2017-09-13 13:40:57 -0700563 std::lock_guard<std::recursive_mutex> lock(transport_lock);
564 CHECK_GT(t->ref_count, 0u);
565 t->ref_count--;
566 if (t->ref_count == 0) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700567 D("transport: %s unref (kicking and closing)", t->serial);
Josh Gao0bbf69c2018-02-16 13:24:58 -0800568 t->connection->Stop();
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400569 remove_transport(t);
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100570 } else {
Josh Gaoe48ecce2017-09-13 13:40:57 -0700571 D("transport: %s unref (count=%zu)", t->serial, t->ref_count);
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400572 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800573}
574
Josh Gao1290fbf2016-11-22 14:32:34 -0800575static int qual_match(const char* to_test, const char* prefix, const char* qual,
576 bool sanitize_qual) {
577 if (!to_test || !*to_test) /* Return true if both the qual and to_test are null strings. */
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700578 return !qual || !*qual;
579
Josh Gao1290fbf2016-11-22 14:32:34 -0800580 if (!qual) return 0;
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700581
582 if (prefix) {
583 while (*prefix) {
Josh Gao1290fbf2016-11-22 14:32:34 -0800584 if (*prefix++ != *to_test++) return 0;
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700585 }
586 }
587
588 while (*qual) {
589 char ch = *qual++;
Josh Gao1290fbf2016-11-22 14:32:34 -0800590 if (sanitize_qual && !isalnum(ch)) ch = '_';
591 if (ch != *to_test++) return 0;
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700592 }
593
594 /* Everything matched so far. Return true if *to_test is a NUL. */
595 return !*to_test;
596}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800597
Josh Gaob122b172017-08-16 16:57:01 -0700598atransport* acquire_one_transport(TransportType type, const char* serial, TransportId transport_id,
599 bool* is_ambiguous, std::string* error_out,
600 bool accept_any_state) {
Elliott Hughes8d28e192015-10-07 14:55:10 -0700601 atransport* result = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800602
Josh Gaob122b172017-08-16 16:57:01 -0700603 if (transport_id != 0) {
604 *error_out =
605 android::base::StringPrintf("no device with transport id '%" PRIu64 "'", transport_id);
606 } else if (serial) {
Elliott Hughes8d28e192015-10-07 14:55:10 -0700607 *error_out = android::base::StringPrintf("device '%s' not found", serial);
608 } else if (type == kTransportLocal) {
609 *error_out = "no emulators found";
610 } else if (type == kTransportAny) {
611 *error_out = "no devices/emulators found";
612 } else {
613 *error_out = "no devices found";
614 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800615
Josh Gao1db71af2017-08-17 13:50:51 -0700616 std::unique_lock<std::recursive_mutex> lock(transport_lock);
Elliott Hughes8d28e192015-10-07 14:55:10 -0700617 for (const auto& t : transport_list) {
Yabin Cuib5e11412017-03-10 16:01:01 -0800618 if (t->GetConnectionState() == kCsNoPerm) {
David Purselld2acbd12015-12-02 15:14:31 -0800619 *error_out = UsbNoPermissionsLongHelpText();
Mike Lockwood37d31112009-08-08 13:53:16 -0400620 continue;
621 }
Mike Lockwood0927bf92009-08-08 12:37:44 -0400622
Josh Gaob122b172017-08-16 16:57:01 -0700623 if (transport_id) {
624 if (t->id == transport_id) {
625 result = t;
626 break;
627 }
628 } else if (serial) {
David Pursell3f902aa2016-03-01 08:58:26 -0800629 if (t->MatchesTarget(serial)) {
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700630 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700631 *error_out = "more than one device";
Elliott Hughes8d28e192015-10-07 14:55:10 -0700632 if (is_ambiguous) *is_ambiguous = true;
633 result = nullptr;
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700634 break;
635 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800636 result = t;
Scott Andersone109d262012-04-20 11:21:14 -0700637 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800638 } else {
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700639 if (type == kTransportUsb && t->type == kTransportUsb) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800640 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700641 *error_out = "more than one device";
Elliott Hughes8d28e192015-10-07 14:55:10 -0700642 if (is_ambiguous) *is_ambiguous = true;
643 result = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800644 break;
645 }
646 result = t;
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700647 } else if (type == kTransportLocal && t->type == kTransportLocal) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800648 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700649 *error_out = "more than one emulator";
Elliott Hughes8d28e192015-10-07 14:55:10 -0700650 if (is_ambiguous) *is_ambiguous = true;
651 result = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800652 break;
653 }
654 result = t;
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700655 } else if (type == kTransportAny) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800656 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700657 *error_out = "more than one device/emulator";
Elliott Hughes8d28e192015-10-07 14:55:10 -0700658 if (is_ambiguous) *is_ambiguous = true;
659 result = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800660 break;
661 }
662 result = t;
663 }
664 }
665 }
Josh Gao0cd3ae12016-09-21 12:37:10 -0700666 lock.unlock();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800667
Elliott Hughes8d28e192015-10-07 14:55:10 -0700668 // Don't return unauthorized devices; the caller can't do anything with them.
Yabin Cuib5e11412017-03-10 16:01:01 -0800669 if (result && result->GetConnectionState() == kCsUnauthorized && !accept_any_state) {
Elliott Hughes8d28e192015-10-07 14:55:10 -0700670 *error_out = "device unauthorized.\n";
671 char* ADB_VENDOR_KEYS = getenv("ADB_VENDOR_KEYS");
672 *error_out += "This adb server's $ADB_VENDOR_KEYS is ";
673 *error_out += ADB_VENDOR_KEYS ? ADB_VENDOR_KEYS : "not set";
674 *error_out += "\n";
675 *error_out += "Try 'adb kill-server' if that seems wrong.\n";
676 *error_out += "Otherwise check for a confirmation dialog on your device.";
677 result = nullptr;
678 }
Benoit Goby77e8e582013-01-15 12:36:47 -0800679
Elliott Hughes8d28e192015-10-07 14:55:10 -0700680 // Don't return offline devices; the caller can't do anything with them.
Yabin Cuib5e11412017-03-10 16:01:01 -0800681 if (result && result->GetConnectionState() == kCsOffline && !accept_any_state) {
Elliott Hughes8d28e192015-10-07 14:55:10 -0700682 *error_out = "device offline";
683 result = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800684 }
685
686 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700687 *error_out = "success";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800688 }
689
690 return result;
691}
692
Yabin Cuib5e11412017-03-10 16:01:01 -0800693int atransport::Write(apacket* p) {
Josh Gao0bbf69c2018-02-16 13:24:58 -0800694 return this->connection->Write(std::unique_ptr<apacket>(p)) ? 0 : -1;
Yabin Cuib5e11412017-03-10 16:01:01 -0800695}
696
Yabin Cui7f274902016-04-18 11:22:34 -0700697void atransport::Kick() {
698 if (!kicked_) {
Josh Gaob800d882018-01-28 20:32:46 -0800699 D("kicking transport %s", this->serial);
Yabin Cui7f274902016-04-18 11:22:34 -0700700 kicked_ = true;
Josh Gao0bbf69c2018-02-16 13:24:58 -0800701 this->connection->Stop();
Yabin Cui7f274902016-04-18 11:22:34 -0700702 }
703}
704
Yabin Cuib5e11412017-03-10 16:01:01 -0800705ConnectionState atransport::GetConnectionState() const {
706 return connection_state_;
707}
708
709void atransport::SetConnectionState(ConnectionState state) {
710 check_main_thread();
711 connection_state_ = state;
712}
713
Josh Gaoffbd3362018-02-28 14:44:23 -0800714std::string atransport::connection_state_name() const {
Yabin Cuib5e11412017-03-10 16:01:01 -0800715 ConnectionState state = GetConnectionState();
716 switch (state) {
Josh Gao1290fbf2016-11-22 14:32:34 -0800717 case kCsOffline:
718 return "offline";
719 case kCsBootloader:
720 return "bootloader";
721 case kCsDevice:
722 return "device";
723 case kCsHost:
724 return "host";
725 case kCsRecovery:
726 return "recovery";
727 case kCsNoPerm:
728 return UsbNoPermissionsShortHelpText();
729 case kCsSideload:
730 return "sideload";
731 case kCsUnauthorized:
732 return "unauthorized";
733 default:
734 return "unknown";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800735 }
736}
737
Tamas Berghammer3d2904c2015-07-13 19:12:28 +0100738void atransport::update_version(int version, size_t payload) {
739 protocol_version = std::min(version, A_VERSION);
740 max_payload = std::min(payload, MAX_PAYLOAD);
741}
742
743int atransport::get_protocol_version() const {
744 return protocol_version;
745}
746
747size_t atransport::get_max_payload() const {
748 return max_payload;
749}
750
David Pursell4e2fd362015-09-22 10:43:08 -0700751namespace {
David Pursell0955c662015-08-31 10:42:13 -0700752
David Pursell4e2fd362015-09-22 10:43:08 -0700753constexpr char kFeatureStringDelimiter = ',';
754
755} // namespace
Dan Albert1792c232015-05-18 13:06:53 -0700756
757const FeatureSet& supported_features() {
David Pursell4e2fd362015-09-22 10:43:08 -0700758 // Local static allocation to avoid global non-POD variables.
759 static const FeatureSet* features = new FeatureSet{
Josh Gao1290fbf2016-11-22 14:32:34 -0800760 kFeatureShell2, kFeatureCmd, kFeatureStat2,
David Pursellbbe3d212015-09-25 08:37:13 -0700761 // Increment ADB_SERVER_VERSION whenever the feature list changes to
762 // make sure that the adb client and server features stay in sync
763 // (http://b/24370690).
David Pursell4e2fd362015-09-22 10:43:08 -0700764 };
765
766 return *features;
767}
768
769std::string FeatureSetToString(const FeatureSet& features) {
770 return android::base::Join(features, kFeatureStringDelimiter);
771}
772
773FeatureSet StringToFeatureSet(const std::string& features_string) {
David Purselld2b588e2015-09-25 13:04:21 -0700774 if (features_string.empty()) {
775 return FeatureSet();
776 }
777
Josh Gao1290fbf2016-11-22 14:32:34 -0800778 auto names = android::base::Split(features_string, {kFeatureStringDelimiter});
David Pursell4e2fd362015-09-22 10:43:08 -0700779 return FeatureSet(names.begin(), names.end());
Dan Albert1792c232015-05-18 13:06:53 -0700780}
781
David Pursell70ef7b42015-09-30 13:35:42 -0700782bool CanUseFeature(const FeatureSet& feature_set, const std::string& feature) {
Josh Gao1290fbf2016-11-22 14:32:34 -0800783 return feature_set.count(feature) > 0 && supported_features().count(feature) > 0;
David Pursell70ef7b42015-09-30 13:35:42 -0700784}
785
Dan Albert1792c232015-05-18 13:06:53 -0700786bool atransport::has_feature(const std::string& feature) const {
787 return features_.count(feature) > 0;
788}
789
David Pursell4e2fd362015-09-22 10:43:08 -0700790void atransport::SetFeatures(const std::string& features_string) {
791 features_ = StringToFeatureSet(features_string);
Dan Albert1792c232015-05-18 13:06:53 -0700792}
793
Yabin Cuib3298242015-08-28 15:09:44 -0700794void atransport::AddDisconnect(adisconnect* disconnect) {
795 disconnects_.push_back(disconnect);
796}
797
798void atransport::RemoveDisconnect(adisconnect* disconnect) {
799 disconnects_.remove(disconnect);
800}
801
802void atransport::RunDisconnects() {
Elliott Hughes65fe2512015-10-07 15:59:35 -0700803 for (const auto& disconnect : disconnects_) {
Yabin Cuib3298242015-08-28 15:09:44 -0700804 disconnect->func(disconnect->opaque, this);
805 }
806 disconnects_.clear();
807}
808
David Pursell3f902aa2016-03-01 08:58:26 -0800809bool atransport::MatchesTarget(const std::string& target) const {
810 if (serial) {
811 if (target == serial) {
812 return true;
813 } else if (type == kTransportLocal) {
814 // Local transports can match [tcp:|udp:]<hostname>[:port].
815 const char* local_target_ptr = target.c_str();
816
817 // For fastboot compatibility, ignore protocol prefixes.
818 if (android::base::StartsWith(target, "tcp:") ||
Josh Gao1290fbf2016-11-22 14:32:34 -0800819 android::base::StartsWith(target, "udp:")) {
David Pursell3f902aa2016-03-01 08:58:26 -0800820 local_target_ptr += 4;
821 }
822
823 // Parse our |serial| and the given |target| to check if the hostnames and ports match.
824 std::string serial_host, error;
825 int serial_port = -1;
Josh Gao1290fbf2016-11-22 14:32:34 -0800826 if (android::base::ParseNetAddress(serial, &serial_host, &serial_port, nullptr, &error)) {
David Pursell3f902aa2016-03-01 08:58:26 -0800827 // |target| may omit the port to default to ours.
828 std::string target_host;
829 int target_port = serial_port;
830 if (android::base::ParseNetAddress(local_target_ptr, &target_host, &target_port,
831 nullptr, &error) &&
Josh Gao1290fbf2016-11-22 14:32:34 -0800832 serial_host == target_host && serial_port == target_port) {
David Pursell3f902aa2016-03-01 08:58:26 -0800833 return true;
834 }
835 }
836 }
837 }
838
839 return (devpath && target == devpath) ||
840 qual_match(target.c_str(), "product:", product, false) ||
841 qual_match(target.c_str(), "model:", model, true) ||
842 qual_match(target.c_str(), "device:", device, false);
843}
844
Elliott Hughese67f1f82015-04-30 17:32:03 -0700845#if ADB_HOST
846
Josh Gaob122b172017-08-16 16:57:01 -0700847// We use newline as our delimiter, make sure to never output it.
848static std::string sanitize(std::string str, bool alphanumeric) {
849 auto pred = alphanumeric ? [](const char c) { return !isalnum(c); }
850 : [](const char c) { return c == '\n'; };
851 std::replace_if(str.begin(), str.end(), pred, '_');
852 return str;
853}
854
Josh Gao1290fbf2016-11-22 14:32:34 -0800855static void append_transport_info(std::string* result, const char* key, const char* value,
Josh Gaob122b172017-08-16 16:57:01 -0700856 bool alphanumeric) {
Elliott Hughese67f1f82015-04-30 17:32:03 -0700857 if (value == nullptr || *value == '\0') {
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700858 return;
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700859 }
860
Elliott Hughese67f1f82015-04-30 17:32:03 -0700861 *result += ' ';
862 *result += key;
Josh Gaob122b172017-08-16 16:57:01 -0700863 *result += sanitize(value, alphanumeric);
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700864}
865
Josh Gao1290fbf2016-11-22 14:32:34 -0800866static void append_transport(const atransport* t, std::string* result, bool long_listing) {
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700867 const char* serial = t->serial;
Elliott Hughese67f1f82015-04-30 17:32:03 -0700868 if (!serial || !serial[0]) {
Dan Albertd99d9022015-05-06 16:48:52 -0700869 serial = "(no serial number)";
Elliott Hughese67f1f82015-04-30 17:32:03 -0700870 }
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700871
872 if (!long_listing) {
Elliott Hughese67f1f82015-04-30 17:32:03 -0700873 *result += serial;
874 *result += '\t';
875 *result += t->connection_state_name();
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700876 } else {
Josh Gao1290fbf2016-11-22 14:32:34 -0800877 android::base::StringAppendF(result, "%-22s %s", serial, t->connection_state_name().c_str());
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700878
Elliott Hughese67f1f82015-04-30 17:32:03 -0700879 append_transport_info(result, "", t->devpath, false);
880 append_transport_info(result, "product:", t->product, false);
881 append_transport_info(result, "model:", t->model, true);
882 append_transport_info(result, "device:", t->device, false);
Josh Gaob122b172017-08-16 16:57:01 -0700883
884 // Put id at the end, so that anyone parsing the output here can always find it by scanning
885 // backwards from newlines, even with hypothetical devices named 'transport_id:1'.
886 *result += " transport_id:";
887 *result += std::to_string(t->id);
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700888 }
Elliott Hughese67f1f82015-04-30 17:32:03 -0700889 *result += '\n';
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700890}
891
Elliott Hughese67f1f82015-04-30 17:32:03 -0700892std::string list_transports(bool long_listing) {
Josh Gao1db71af2017-08-17 13:50:51 -0700893 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Artem Iglikov04398a92017-12-17 10:56:07 +0000894
895 auto sorted_transport_list = transport_list;
896 sorted_transport_list.sort([](atransport*& x, atransport*& y) {
897 if (x->type != y->type) {
898 return x->type < y->type;
899 }
900 return strcmp(x->serial, y->serial) < 0;
901 });
902
903 std::string result;
904 for (const auto& t : sorted_transport_list) {
Elliott Hughese67f1f82015-04-30 17:32:03 -0700905 append_transport(t, &result, long_listing);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800906 }
Elliott Hughese67f1f82015-04-30 17:32:03 -0700907 return result;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800908}
909
Josh Gao22d2b3e2016-10-27 14:01:08 -0700910void close_usb_devices(std::function<bool(const atransport*)> predicate) {
Josh Gao1db71af2017-08-17 13:50:51 -0700911 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gao22d2b3e2016-10-27 14:01:08 -0700912 for (auto& t : transport_list) {
913 if (predicate(t)) {
914 t->Kick();
915 }
916 }
917}
918
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800919/* hack for osx */
Dan Albertc7915a32015-05-18 16:46:31 -0700920void close_usb_devices() {
Josh Gao22d2b3e2016-10-27 14:01:08 -0700921 close_usb_devices([](const atransport*) { return true; });
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800922}
Josh Gao1290fbf2016-11-22 14:32:34 -0800923#endif // ADB_HOST
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800924
Josh Gao1290fbf2016-11-22 14:32:34 -0800925int register_socket_transport(int s, const char* serial, int port, int local) {
Dan Albertc7915a32015-05-18 16:46:31 -0700926 atransport* t = new atransport();
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100927
928 if (!serial) {
Dan Albertc7915a32015-05-18 16:46:31 -0700929 char buf[32];
930 snprintf(buf, sizeof(buf), "T-%p", t);
931 serial = buf;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100932 }
Dan Albertc7915a32015-05-18 16:46:31 -0700933
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700934 D("transport: %s init'ing for socket %d, on port %d", serial, s, port);
Benoit Goby1c45ee92013-03-29 18:22:36 -0700935 if (init_socket_transport(t, s, port, local) < 0) {
Dan Albertc7915a32015-05-18 16:46:31 -0700936 delete t;
Benoit Goby1c45ee92013-03-29 18:22:36 -0700937 return -1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800938 }
Benoit Goby1c45ee92013-03-29 18:22:36 -0700939
Josh Gao1db71af2017-08-17 13:50:51 -0700940 std::unique_lock<std::recursive_mutex> lock(transport_lock);
Elliott Hughes65fe2512015-10-07 15:59:35 -0700941 for (const auto& transport : pending_list) {
Dan Albertc7915a32015-05-18 16:46:31 -0700942 if (transport->serial && strcmp(serial, transport->serial) == 0) {
Yabin Cuib74c6492016-04-29 16:53:52 -0700943 VLOG(TRANSPORT) << "socket transport " << transport->serial
Josh Gao1290fbf2016-11-22 14:32:34 -0800944 << " is already in pending_list and fails to register";
Dan Albertc7915a32015-05-18 16:46:31 -0700945 delete t;
Benoit Goby1c45ee92013-03-29 18:22:36 -0700946 return -1;
947 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800948 }
Benoit Goby1c45ee92013-03-29 18:22:36 -0700949
Elliott Hughes65fe2512015-10-07 15:59:35 -0700950 for (const auto& transport : transport_list) {
Dan Albertc7915a32015-05-18 16:46:31 -0700951 if (transport->serial && strcmp(serial, transport->serial) == 0) {
Yabin Cuib74c6492016-04-29 16:53:52 -0700952 VLOG(TRANSPORT) << "socket transport " << transport->serial
Josh Gao1290fbf2016-11-22 14:32:34 -0800953 << " is already in transport_list and fails to register";
Dan Albertc7915a32015-05-18 16:46:31 -0700954 delete t;
Benoit Goby1c45ee92013-03-29 18:22:36 -0700955 return -1;
956 }
957 }
958
Dan Albertc7915a32015-05-18 16:46:31 -0700959 pending_list.push_front(t);
Benoit Goby1c45ee92013-03-29 18:22:36 -0700960 t->serial = strdup(serial);
Josh Gao0cd3ae12016-09-21 12:37:10 -0700961
962 lock.unlock();
Benoit Goby1c45ee92013-03-29 18:22:36 -0700963
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800964 register_transport(t);
Benoit Goby1c45ee92013-03-29 18:22:36 -0700965 return 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800966}
967
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400968#if ADB_HOST
Josh Gao1290fbf2016-11-22 14:32:34 -0800969atransport* find_transport(const char* serial) {
Dan Albertc7915a32015-05-18 16:46:31 -0700970 atransport* result = nullptr;
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400971
Josh Gao1db71af2017-08-17 13:50:51 -0700972 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Yabin Cuif4b99282015-08-27 12:03:11 -0700973 for (auto& t : transport_list) {
Dan Albertc7915a32015-05-18 16:46:31 -0700974 if (t->serial && strcmp(serial, t->serial) == 0) {
975 result = t;
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400976 break;
977 }
Dan Albertc7915a32015-05-18 16:46:31 -0700978 }
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400979
Dan Albertc7915a32015-05-18 16:46:31 -0700980 return result;
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400981}
982
Yabin Cuif4b99282015-08-27 12:03:11 -0700983void kick_all_tcp_devices() {
Josh Gao1db71af2017-08-17 13:50:51 -0700984 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Yabin Cuif4b99282015-08-27 12:03:11 -0700985 for (auto& t : transport_list) {
Yabin Cuib74c6492016-04-29 16:53:52 -0700986 if (t->IsTcpDevice()) {
Yabin Cuid6ab3c22015-08-31 11:50:24 -0700987 // Kicking breaks the read_transport thread of this transport out of any read, then
988 // the read_transport thread will notify the main thread to make this transport
989 // offline. Then the main thread will notify the write_transport thread to exit.
Yabin Cuif4b99282015-08-27 12:03:11 -0700990 // Finally, this transport will be closed and freed in the main thread.
Yabin Cui7f274902016-04-18 11:22:34 -0700991 t->Kick();
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400992 }
Dan Albertc7915a32015-05-18 16:46:31 -0700993 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400994}
995
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400996#endif
997
Josh Gao1290fbf2016-11-22 14:32:34 -0800998void register_usb_transport(usb_handle* usb, const char* serial, const char* devpath,
999 unsigned writeable) {
Yabin Cuib5e11412017-03-10 16:01:01 -08001000 atransport* t = new atransport((writeable ? kCsOffline : kCsNoPerm));
Dan Albertc7915a32015-05-18 16:46:31 -07001001
Josh Gao1290fbf2016-11-22 14:32:34 -08001002 D("transport: %p init'ing for usb_handle %p (sn='%s')", t, usb, serial ? serial : "");
Yabin Cuib5e11412017-03-10 16:01:01 -08001003 init_usb_transport(t, usb);
Josh Gao1290fbf2016-11-22 14:32:34 -08001004 if (serial) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001005 t->serial = strdup(serial);
1006 }
Dan Albertc7915a32015-05-18 16:46:31 -07001007
1008 if (devpath) {
Scott Andersone109d262012-04-20 11:21:14 -07001009 t->devpath = strdup(devpath);
1010 }
Benoit Goby1c45ee92013-03-29 18:22:36 -07001011
Josh Gao0cd3ae12016-09-21 12:37:10 -07001012 {
Josh Gao1db71af2017-08-17 13:50:51 -07001013 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gao0cd3ae12016-09-21 12:37:10 -07001014 pending_list.push_front(t);
1015 }
Benoit Goby1c45ee92013-03-29 18:22:36 -07001016
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001017 register_transport(t);
1018}
1019
Dan Albertdcd78a12015-05-18 16:43:57 -07001020// This should only be used for transports with connection_state == kCsNoPerm.
Josh Gao1290fbf2016-11-22 14:32:34 -08001021void unregister_usb_transport(usb_handle* usb) {
Josh Gao1db71af2017-08-17 13:50:51 -07001022 std::lock_guard<std::recursive_mutex> lock(transport_lock);
Josh Gaob800d882018-01-28 20:32:46 -08001023 transport_list.remove_if([usb](atransport* t) {
1024 if (auto connection = dynamic_cast<UsbConnection*>(t->connection.get())) {
1025 return connection->handle_ == usb && t->GetConnectionState() == kCsNoPerm;
1026 }
1027 return false;
1028 });
Mike Lockwood0927bf92009-08-08 12:37:44 -04001029}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001030
Josh Gao36dadca2017-05-16 15:02:45 -07001031bool check_header(apacket* p, atransport* t) {
Josh Gao1290fbf2016-11-22 14:32:34 -08001032 if (p->msg.magic != (p->msg.command ^ 0xffffffff)) {
Yabin Cuib5e11412017-03-10 16:01:01 -08001033 VLOG(RWX) << "check_header(): invalid magic command = " << std::hex << p->msg.command
1034 << ", magic = " << p->msg.magic;
Josh Gao36dadca2017-05-16 15:02:45 -07001035 return false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001036 }
1037
Josh Gao1290fbf2016-11-22 14:32:34 -08001038 if (p->msg.data_length > t->get_max_payload()) {
1039 VLOG(RWX) << "check_header(): " << p->msg.data_length
1040 << " atransport::max_payload = " << t->get_max_payload();
Josh Gao36dadca2017-05-16 15:02:45 -07001041 return false;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001042 }
1043
Josh Gao36dadca2017-05-16 15:02:45 -07001044 return true;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001045}
1046
Josh Gao3bd28792016-10-05 19:02:29 -07001047#if ADB_HOST
Josh Gao2e671202016-08-18 22:00:12 -07001048std::shared_ptr<RSA> atransport::NextKey() {
Elliott Hughes0aeb5052016-06-29 17:42:01 -07001049 if (keys_.empty()) keys_ = adb_auth_get_private_keys();
1050
Josh Gao2e671202016-08-18 22:00:12 -07001051 std::shared_ptr<RSA> result = keys_[0];
Elliott Hughes0aeb5052016-06-29 17:42:01 -07001052 keys_.pop_front();
1053 return result;
1054}
Josh Gao3bd28792016-10-05 19:02:29 -07001055#endif