blob: 7b82b197e01f65c01086f9a3532d539d621095ff [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"
Dan Albert76649012015-02-24 15:51:19 -080020#include "transport.h"
21
Dan Albert055f1aa2015-02-20 17:24:58 -080022#include <ctype.h>
Dan Albert76649012015-02-24 15:51:19 -080023#include <errno.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080024#include <stdio.h>
25#include <stdlib.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080026#include <string.h>
Dan Albert76649012015-02-24 15:51:19 -080027#include <unistd.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080028
Spencer Low363af562015-11-07 18:51:54 -080029#include <algorithm>
Dan Albertc7915a32015-05-18 16:46:31 -070030#include <list>
Josh Gao0cd3ae12016-09-21 12:37:10 -070031#include <mutex>
Dan Albertc7915a32015-05-18 16:46:31 -070032
Elliott Hughes4f713192015-12-04 22:00:26 -080033#include <android-base/logging.h>
David Pursell3f902aa2016-03-01 08:58:26 -080034#include <android-base/parsenetaddress.h>
Elliott Hughes4f713192015-12-04 22:00:26 -080035#include <android-base/stringprintf.h>
36#include <android-base/strings.h>
Elliott Hughese67f1f82015-04-30 17:32:03 -070037
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080038#include "adb.h"
Elliott Hughes0aeb5052016-06-29 17:42:01 -070039#include "adb_auth.h"
Elliott Hughese67f1f82015-04-30 17:32:03 -070040#include "adb_utils.h"
Elliott Hughes1b708d32015-12-11 19:07:01 -080041#include "diagnose_usb.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080042
43static void transport_unref(atransport *t);
44
Josh Gaob7b1edf2015-11-11 17:56:12 -080045static auto& transport_list = *new std::list<atransport*>();
46static auto& pending_list = *new std::list<atransport*>();
Benoit Goby1c45ee92013-03-29 18:22:36 -070047
Josh Gao0cd3ae12016-09-21 12:37:10 -070048static std::mutex& transport_lock = *new std::mutex();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080049
Todd Kennedy51c05ec2015-11-10 00:03:25 +000050const char* const kFeatureShell2 = "shell_v2";
51const char* const kFeatureCmd = "cmd";
Josh Gao5a1e3fd2016-12-05 17:11:34 -080052const char* const kFeatureStat2 = "stat_v2";
Todd Kennedy51c05ec2015-11-10 00:03:25 +000053
Yabin Cuiaed3c612015-09-22 15:52:57 -070054static std::string dump_packet(const char* name, const char* func, apacket* p) {
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +010055 unsigned command = p->msg.command;
56 int len = p->msg.data_length;
57 char cmd[9];
58 char arg0[12], arg1[12];
59 int n;
60
61 for (n = 0; n < 4; n++) {
62 int b = (command >> (n*8)) & 255;
63 if (b < 32 || b >= 127)
64 break;
65 cmd[n] = (char)b;
66 }
67 if (n == 4) {
68 cmd[4] = 0;
69 } else {
70 /* There is some non-ASCII name in the command, so dump
71 * the hexadecimal value instead */
72 snprintf(cmd, sizeof cmd, "%08x", command);
73 }
74
75 if (p->msg.arg0 < 256U)
76 snprintf(arg0, sizeof arg0, "%d", p->msg.arg0);
77 else
78 snprintf(arg0, sizeof arg0, "0x%x", p->msg.arg0);
79
80 if (p->msg.arg1 < 256U)
81 snprintf(arg1, sizeof arg1, "%d", p->msg.arg1);
82 else
83 snprintf(arg1, sizeof arg1, "0x%x", p->msg.arg1);
84
Yabin Cuiaed3c612015-09-22 15:52:57 -070085 std::string result = android::base::StringPrintf("%s: %s: [%s] arg0=%s arg1=%s (len=%d) ",
86 name, func, cmd, arg0, arg1, len);
87 result += dump_hex(p->data, len);
88 return result;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +010089}
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +010090
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080091static int
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +010092read_packet(int fd, const char* name, apacket** ppacket)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080093{
Yabin Cui62641292015-07-30 19:58:10 -070094 char buff[8];
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +010095 if (!name) {
96 snprintf(buff, sizeof buff, "fd=%d", fd);
97 name = buff;
98 }
Yabin Cui62641292015-07-30 19:58:10 -070099 char* p = reinterpret_cast<char*>(ppacket); /* really read a packet address */
100 int len = sizeof(apacket*);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800101 while(len > 0) {
Yabin Cui62641292015-07-30 19:58:10 -0700102 int r = adb_read(fd, p, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800103 if(r > 0) {
104 len -= r;
Yabin Cui62641292015-07-30 19:58:10 -0700105 p += r;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800106 } else {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700107 D("%s: read_packet (fd=%d), error ret=%d: %s", name, fd, r, strerror(errno));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800108 return -1;
109 }
110 }
111
Yabin Cuiaed3c612015-09-22 15:52:57 -0700112 VLOG(TRANSPORT) << dump_packet(name, "from remote", *ppacket);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800113 return 0;
114}
115
116static int
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100117write_packet(int fd, const char* name, apacket** ppacket)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800118{
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100119 char buff[8];
120 if (!name) {
121 snprintf(buff, sizeof buff, "fd=%d", fd);
122 name = buff;
123 }
Yabin Cuiaed3c612015-09-22 15:52:57 -0700124 VLOG(TRANSPORT) << dump_packet(name, "to remote", *ppacket);
Yabin Cui62641292015-07-30 19:58:10 -0700125 char* p = reinterpret_cast<char*>(ppacket); /* we really write the packet address */
126 int len = sizeof(apacket*);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800127 while(len > 0) {
Yabin Cui62641292015-07-30 19:58:10 -0700128 int r = adb_write(fd, p, len);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800129 if(r > 0) {
130 len -= r;
131 p += r;
132 } else {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700133 D("%s: write_packet (fd=%d) error ret=%d: %s", name, fd, r, strerror(errno));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800134 return -1;
135 }
136 }
137 return 0;
138}
139
140static void transport_socket_events(int fd, unsigned events, void *_t)
141{
Dan Albertbac34742015-02-25 17:51:28 -0800142 atransport *t = reinterpret_cast<atransport*>(_t);
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700143 D("transport_socket_events(fd=%d, events=%04x,...)", fd, events);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800144 if(events & FDE_READ){
145 apacket *p = 0;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100146 if(read_packet(fd, t->serial, &p)){
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700147 D("%s: failed to read packet from transport socket on fd %d", t->serial, fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800148 } else {
149 handle_packet(p, (atransport *) _t);
150 }
151 }
152}
153
Josh Gao06d61d42016-10-06 13:31:44 -0700154void send_packet(apacket* p, atransport* t) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800155 p->msg.magic = p->msg.command ^ 0xffffffff;
Josh Gao06d61d42016-10-06 13:31:44 -0700156 p->msg.data_check = calculate_apacket_checksum(p);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800157
158 print_packet("send", p);
159
160 if (t == NULL) {
Josh Gao06d61d42016-10-06 13:31:44 -0700161 fatal("Transport is null");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800162 }
163
Josh Gao06d61d42016-10-06 13:31:44 -0700164 if (write_packet(t->transport_socket, t->serial, &p)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800165 fatal_errno("cannot enqueue packet on transport socket");
166 }
167}
168
Yabin Cuid6ab3c22015-08-31 11:50:24 -0700169// The transport is opened by transport_register_func before
170// the read_transport and write_transport threads are started.
171//
172// The read_transport thread issues a SYNC(1, token) message to let
173// the write_transport thread know to start things up. In the event
174// of transport IO failure, the read_transport thread will post a
175// SYNC(0,0) message to ensure shutdown.
176//
177// The transport will not actually be closed until both threads exit, but the threads
178// will kick the transport on their way out to disconnect the underlying device.
179//
180// read_transport thread reads data from a transport (representing a usb/tcp connection),
181// and makes the main thread call handle_packet().
Josh Gaob5fea142016-02-12 14:31:15 -0800182static void read_transport_thread(void* _t) {
Dan Albertbac34742015-02-25 17:51:28 -0800183 atransport *t = reinterpret_cast<atransport*>(_t);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800184 apacket *p;
185
Yabin Cuid6ab3c22015-08-31 11:50:24 -0700186 adb_thread_setname(android::base::StringPrintf("<-%s",
187 (t->serial != nullptr ? t->serial : "transport")));
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700188 D("%s: starting read_transport thread on fd %d, SYNC online (%d)",
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100189 t->serial, t->fd, t->sync_token + 1);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800190 p = get_apacket();
191 p->msg.command = A_SYNC;
192 p->msg.arg0 = 1;
193 p->msg.arg1 = ++(t->sync_token);
194 p->msg.magic = A_SYNC ^ 0xffffffff;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100195 if(write_packet(t->fd, t->serial, &p)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800196 put_apacket(p);
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700197 D("%s: failed to write SYNC packet", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800198 goto oops;
199 }
200
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700201 D("%s: data pump started", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800202 for(;;) {
203 p = get_apacket();
204
205 if(t->read_from_remote(p, t) == 0){
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700206 D("%s: received remote packet, sending to transport",
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100207 t->serial);
208 if(write_packet(t->fd, t->serial, &p)){
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800209 put_apacket(p);
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700210 D("%s: failed to write apacket to transport", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800211 goto oops;
212 }
213 } else {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700214 D("%s: remote read failed for transport", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800215 put_apacket(p);
216 break;
217 }
218 }
219
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700220 D("%s: SYNC offline for transport", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800221 p = get_apacket();
222 p->msg.command = A_SYNC;
223 p->msg.arg0 = 0;
224 p->msg.arg1 = 0;
225 p->msg.magic = A_SYNC ^ 0xffffffff;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100226 if(write_packet(t->fd, t->serial, &p)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800227 put_apacket(p);
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700228 D("%s: failed to write SYNC apacket to transport", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800229 }
230
231oops:
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700232 D("%s: read_transport thread is exiting", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800233 kick_transport(t);
234 transport_unref(t);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800235}
236
Yabin Cuid6ab3c22015-08-31 11:50:24 -0700237// write_transport thread gets packets sent by the main thread (through send_packet()),
238// and writes to a transport (representing a usb/tcp connection).
Josh Gaob5fea142016-02-12 14:31:15 -0800239static void write_transport_thread(void* _t) {
Dan Albertbac34742015-02-25 17:51:28 -0800240 atransport *t = reinterpret_cast<atransport*>(_t);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800241 apacket *p;
242 int active = 0;
243
Yabin Cuid6ab3c22015-08-31 11:50:24 -0700244 adb_thread_setname(android::base::StringPrintf("->%s",
245 (t->serial != nullptr ? t->serial : "transport")));
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700246 D("%s: starting write_transport thread, reading from fd %d",
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100247 t->serial, t->fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800248
249 for(;;){
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100250 if(read_packet(t->fd, t->serial, &p)) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700251 D("%s: failed to read apacket from transport on fd %d",
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100252 t->serial, t->fd );
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800253 break;
254 }
255 if(p->msg.command == A_SYNC){
256 if(p->msg.arg0 == 0) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700257 D("%s: transport SYNC offline", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800258 put_apacket(p);
259 break;
260 } else {
261 if(p->msg.arg1 == t->sync_token) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700262 D("%s: transport SYNC online", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800263 active = 1;
264 } else {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700265 D("%s: transport ignoring SYNC %d != %d",
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100266 t->serial, p->msg.arg1, t->sync_token);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800267 }
268 }
269 } else {
270 if(active) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700271 D("%s: transport got packet, sending to remote", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800272 t->write_to_remote(p, t);
273 } else {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700274 D("%s: transport ignoring packet while offline", t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800275 }
276 }
277
278 put_apacket(p);
279 }
280
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700281 D("%s: write_transport thread is exiting, fd %d", t->serial, t->fd);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800282 kick_transport(t);
283 transport_unref(t);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800284}
285
Yabin Cuif4b99282015-08-27 12:03:11 -0700286void kick_transport(atransport* t) {
Josh Gao0cd3ae12016-09-21 12:37:10 -0700287 std::lock_guard<std::mutex> lock(transport_lock);
Yabin Cui1f4ec192016-04-05 13:50:44 -0700288 // As kick_transport() can be called from threads without guarantee that t is valid,
289 // check if the transport is in transport_list first.
290 if (std::find(transport_list.begin(), transport_list.end(), t) != transport_list.end()) {
Yabin Cui7f274902016-04-18 11:22:34 -0700291 t->Kick();
Yabin Cui1f4ec192016-04-05 13:50:44 -0700292 }
Yabin Cuif4b99282015-08-27 12:03:11 -0700293}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800294
295static int transport_registration_send = -1;
296static int transport_registration_recv = -1;
297static fdevent transport_registration_fde;
298
299
300#if ADB_HOST
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800301
302/* this adds support required by the 'track-devices' service.
303 * this is used to send the content of "list_transport" to any
304 * number of client connections that want it through a single
305 * live TCP connection
306 */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800307struct device_tracker {
308 asocket socket;
309 int update_needed;
310 device_tracker* next;
311};
312
313/* linked list of all device trackers */
314static device_tracker* device_tracker_list;
315
316static void
317device_tracker_remove( device_tracker* tracker )
318{
319 device_tracker** pnode = &device_tracker_list;
320 device_tracker* node = *pnode;
321
Josh Gao0cd3ae12016-09-21 12:37:10 -0700322 std::lock_guard<std::mutex> lock(transport_lock);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800323 while (node) {
324 if (node == tracker) {
325 *pnode = node->next;
326 break;
327 }
328 pnode = &node->next;
329 node = *pnode;
330 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800331}
332
333static void
334device_tracker_close( asocket* socket )
335{
336 device_tracker* tracker = (device_tracker*) socket;
337 asocket* peer = socket->peer;
338
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700339 D( "device tracker %p removed", tracker);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800340 if (peer) {
341 peer->peer = NULL;
342 peer->close(peer);
343 }
344 device_tracker_remove(tracker);
345 free(tracker);
346}
347
348static int
349device_tracker_enqueue( asocket* socket, apacket* p )
350{
351 /* you can't read from a device tracker, close immediately */
352 put_apacket(p);
353 device_tracker_close(socket);
354 return -1;
355}
356
Elliott Hughese67f1f82015-04-30 17:32:03 -0700357static int device_tracker_send(device_tracker* tracker, const std::string& string) {
358 apacket* p = get_apacket();
359 asocket* peer = tracker->socket.peer;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800360
Elliott Hughese67f1f82015-04-30 17:32:03 -0700361 snprintf(reinterpret_cast<char*>(p->data), 5, "%04x", static_cast<int>(string.size()));
362 memcpy(&p->data[4], string.data(), string.size());
363 p->len = 4 + string.size();
364 return peer->enqueue(peer, p);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800365}
366
Elliott Hughese67f1f82015-04-30 17:32:03 -0700367static void device_tracker_ready(asocket* socket) {
368 device_tracker* tracker = reinterpret_cast<device_tracker*>(socket);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800369
Elliott Hughese67f1f82015-04-30 17:32:03 -0700370 // We want to send the device list when the tracker connects
371 // for the first time, even if no update occurred.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800372 if (tracker->update_needed > 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800373 tracker->update_needed = 0;
374
Elliott Hughese67f1f82015-04-30 17:32:03 -0700375 std::string transports = list_transports(false);
376 device_tracker_send(tracker, transports);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800377 }
378}
379
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800380asocket*
381create_device_tracker(void)
382{
Elliott Hughesdc3b4592015-04-21 19:39:52 -0700383 device_tracker* tracker = reinterpret_cast<device_tracker*>(calloc(1, sizeof(*tracker)));
384 if (tracker == nullptr) fatal("cannot allocate device tracker");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800385
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700386 D( "device tracker %p created", tracker);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800387
388 tracker->socket.enqueue = device_tracker_enqueue;
389 tracker->socket.ready = device_tracker_ready;
390 tracker->socket.close = device_tracker_close;
391 tracker->update_needed = 1;
392
393 tracker->next = device_tracker_list;
394 device_tracker_list = tracker;
395
396 return &tracker->socket;
397}
398
399
Elliott Hughese67f1f82015-04-30 17:32:03 -0700400// Call this function each time the transport list has changed.
401void update_transports() {
402 std::string transports = list_transports(false);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800403
Elliott Hughese67f1f82015-04-30 17:32:03 -0700404 device_tracker* tracker = device_tracker_list;
405 while (tracker != nullptr) {
406 device_tracker* next = tracker->next;
407 // This may destroy the tracker if the connection is closed.
408 device_tracker_send(tracker, transports);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800409 tracker = next;
410 }
411}
Elliott Hughese67f1f82015-04-30 17:32:03 -0700412
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800413#else
Elliott Hughese67f1f82015-04-30 17:32:03 -0700414
415void update_transports() {
416 // Nothing to do on the device side.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800417}
Elliott Hughese67f1f82015-04-30 17:32:03 -0700418
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800419#endif // ADB_HOST
420
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800421struct tmsg
422{
423 atransport *transport;
424 int action;
425};
426
427static int
428transport_read_action(int fd, struct tmsg* m)
429{
430 char *p = (char*)m;
431 int len = sizeof(*m);
432 int r;
433
434 while(len > 0) {
435 r = adb_read(fd, p, len);
436 if(r > 0) {
437 len -= r;
438 p += r;
439 } else {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700440 D("transport_read_action: on fd %d: %s", fd, strerror(errno));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800441 return -1;
442 }
443 }
444 return 0;
445}
446
447static int
448transport_write_action(int fd, struct tmsg* m)
449{
450 char *p = (char*)m;
451 int len = sizeof(*m);
452 int r;
453
454 while(len > 0) {
455 r = adb_write(fd, p, len);
456 if(r > 0) {
457 len -= r;
458 p += r;
459 } else {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700460 D("transport_write_action: on fd %d: %s", fd, strerror(errno));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800461 return -1;
462 }
463 }
464 return 0;
465}
466
467static void transport_registration_func(int _fd, unsigned ev, void *data)
468{
469 tmsg m;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800470 int s[2];
471 atransport *t;
472
473 if(!(ev & FDE_READ)) {
474 return;
475 }
476
477 if(transport_read_action(_fd, &m)) {
478 fatal_errno("cannot read transport registration socket");
479 }
480
481 t = m.transport;
482
Dan Albert1792c232015-05-18 13:06:53 -0700483 if (m.action == 0) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700484 D("transport: %s removing and free'ing %d", t->serial, t->transport_socket);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800485
486 /* IMPORTANT: the remove closes one half of the
487 ** socket pair. The close closes the other half.
488 */
489 fdevent_remove(&(t->transport_fde));
490 adb_close(t->fd);
491
Josh Gao0cd3ae12016-09-21 12:37:10 -0700492 {
493 std::lock_guard<std::mutex> lock(transport_lock);
494 transport_list.remove(t);
495 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800496
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800497 if (t->product)
498 free(t->product);
499 if (t->serial)
500 free(t->serial);
Scott Andersone82c2db2012-05-25 14:10:02 -0700501 if (t->model)
502 free(t->model);
503 if (t->device)
504 free(t->device);
Scott Andersone109d262012-04-20 11:21:14 -0700505 if (t->devpath)
506 free(t->devpath);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800507
Dan Albertc7915a32015-05-18 16:46:31 -0700508 delete t;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800509
510 update_transports();
511 return;
512 }
513
Mike Lockwood0927bf92009-08-08 12:37:44 -0400514 /* don't create transport threads for inaccessible devices */
Dan Albertdcd78a12015-05-18 16:43:57 -0700515 if (t->connection_state != kCsNoPerm) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800516 /* initial references are the two threads */
Mike Lockwood0927bf92009-08-08 12:37:44 -0400517 t->ref_count = 2;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800518
Dan Albertc7915a32015-05-18 16:46:31 -0700519 if (adb_socketpair(s)) {
Mike Lockwood0927bf92009-08-08 12:37:44 -0400520 fatal_errno("cannot open transport socketpair");
521 }
522
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700523 D("transport: %s socketpair: (%d,%d) starting", t->serial, s[0], s[1]);
Mike Lockwood0927bf92009-08-08 12:37:44 -0400524
525 t->transport_socket = s[0];
526 t->fd = s[1];
527
Mike Lockwood0927bf92009-08-08 12:37:44 -0400528 fdevent_install(&(t->transport_fde),
529 t->transport_socket,
530 transport_socket_events,
531 t);
532
533 fdevent_set(&(t->transport_fde), FDE_READ);
534
Yabin Cuid6ab3c22015-08-31 11:50:24 -0700535 if (!adb_thread_create(write_transport_thread, t)) {
536 fatal_errno("cannot create write_transport thread");
Mike Lockwood0927bf92009-08-08 12:37:44 -0400537 }
538
Yabin Cuid6ab3c22015-08-31 11:50:24 -0700539 if (!adb_thread_create(read_transport_thread, t)) {
540 fatal_errno("cannot create read_transport thread");
Mike Lockwood0927bf92009-08-08 12:37:44 -0400541 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800542 }
543
Josh Gao0cd3ae12016-09-21 12:37:10 -0700544 {
545 std::lock_guard<std::mutex> lock(transport_lock);
546 pending_list.remove(t);
547 transport_list.push_front(t);
548 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800549
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800550 update_transports();
551}
552
553void init_transport_registration(void)
554{
555 int s[2];
556
557 if(adb_socketpair(s)){
558 fatal_errno("cannot open transport registration socketpair");
559 }
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700560 D("socketpair: (%d,%d)", s[0], s[1]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800561
562 transport_registration_send = s[0];
563 transport_registration_recv = s[1];
564
565 fdevent_install(&transport_registration_fde,
566 transport_registration_recv,
567 transport_registration_func,
568 0);
569
570 fdevent_set(&transport_registration_fde, FDE_READ);
571}
572
573/* the fdevent select pump is single threaded */
574static void register_transport(atransport *transport)
575{
576 tmsg m;
577 m.transport = transport;
578 m.action = 1;
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700579 D("transport: %s registered", transport->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800580 if(transport_write_action(transport_registration_send, &m)) {
581 fatal_errno("cannot write transport registration socket\n");
582 }
583}
584
585static void remove_transport(atransport *transport)
586{
587 tmsg m;
588 m.transport = transport;
589 m.action = 0;
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700590 D("transport: %s removed", transport->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800591 if(transport_write_action(transport_registration_send, &m)) {
592 fatal_errno("cannot write transport registration socket\n");
593 }
594}
595
596
Yabin Cuif4b99282015-08-27 12:03:11 -0700597static void transport_unref(atransport* t) {
598 CHECK(t != nullptr);
Josh Gao0cd3ae12016-09-21 12:37:10 -0700599
600 std::lock_guard<std::mutex> lock(transport_lock);
Yabin Cuif4b99282015-08-27 12:03:11 -0700601 CHECK_GT(t->ref_count, 0u);
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400602 t->ref_count--;
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400603 if (t->ref_count == 0) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700604 D("transport: %s unref (kicking and closing)", t->serial);
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400605 t->close(t);
606 remove_transport(t);
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100607 } else {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700608 D("transport: %s unref (count=%zu)", t->serial, t->ref_count);
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400609 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800610}
611
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700612static int qual_match(const char *to_test,
Elliott Hughes09a45a12015-04-03 16:12:15 -0700613 const char *prefix, const char *qual, bool sanitize_qual)
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700614{
615 if (!to_test || !*to_test)
616 /* Return true if both the qual and to_test are null strings. */
617 return !qual || !*qual;
618
619 if (!qual)
620 return 0;
621
622 if (prefix) {
623 while (*prefix) {
624 if (*prefix++ != *to_test++)
625 return 0;
626 }
627 }
628
629 while (*qual) {
630 char ch = *qual++;
Elliott Hughes09a45a12015-04-03 16:12:15 -0700631 if (sanitize_qual && !isalnum(ch))
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700632 ch = '_';
633 if (ch != *to_test++)
634 return 0;
635 }
636
637 /* Everything matched so far. Return true if *to_test is a NUL. */
638 return !*to_test;
639}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800640
Elliott Hughes8d28e192015-10-07 14:55:10 -0700641atransport* acquire_one_transport(TransportType type, const char* serial,
642 bool* is_ambiguous, std::string* error_out) {
643 atransport* result = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800644
Elliott Hughes8d28e192015-10-07 14:55:10 -0700645 if (serial) {
646 *error_out = android::base::StringPrintf("device '%s' not found", serial);
647 } else if (type == kTransportLocal) {
648 *error_out = "no emulators found";
649 } else if (type == kTransportAny) {
650 *error_out = "no devices/emulators found";
651 } else {
652 *error_out = "no devices found";
653 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800654
Josh Gao0cd3ae12016-09-21 12:37:10 -0700655 std::unique_lock<std::mutex> lock(transport_lock);
Elliott Hughes8d28e192015-10-07 14:55:10 -0700656 for (const auto& t : transport_list) {
Dan Albertdcd78a12015-05-18 16:43:57 -0700657 if (t->connection_state == kCsNoPerm) {
Elliott Hughes1b708d32015-12-11 19:07:01 -0800658#if ADB_HOST
David Purselld2acbd12015-12-02 15:14:31 -0800659 *error_out = UsbNoPermissionsLongHelpText();
Elliott Hughes1b708d32015-12-11 19:07:01 -0800660#endif
Mike Lockwood37d31112009-08-08 13:53:16 -0400661 continue;
662 }
Mike Lockwood0927bf92009-08-08 12:37:44 -0400663
Elliott Hughes8d28e192015-10-07 14:55:10 -0700664 // Check for matching serial number.
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800665 if (serial) {
David Pursell3f902aa2016-03-01 08:58:26 -0800666 if (t->MatchesTarget(serial)) {
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700667 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700668 *error_out = "more than one device";
Elliott Hughes8d28e192015-10-07 14:55:10 -0700669 if (is_ambiguous) *is_ambiguous = true;
670 result = nullptr;
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700671 break;
672 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800673 result = t;
Scott Andersone109d262012-04-20 11:21:14 -0700674 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800675 } else {
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700676 if (type == kTransportUsb && t->type == kTransportUsb) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800677 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700678 *error_out = "more than one device";
Elliott Hughes8d28e192015-10-07 14:55:10 -0700679 if (is_ambiguous) *is_ambiguous = true;
680 result = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800681 break;
682 }
683 result = t;
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700684 } else if (type == kTransportLocal && t->type == kTransportLocal) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800685 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700686 *error_out = "more than one emulator";
Elliott Hughes8d28e192015-10-07 14:55:10 -0700687 if (is_ambiguous) *is_ambiguous = true;
688 result = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800689 break;
690 }
691 result = t;
Elliott Hughes3bd73c12015-05-05 13:10:43 -0700692 } else if (type == kTransportAny) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800693 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700694 *error_out = "more than one device/emulator";
Elliott Hughes8d28e192015-10-07 14:55:10 -0700695 if (is_ambiguous) *is_ambiguous = true;
696 result = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800697 break;
698 }
699 result = t;
700 }
701 }
702 }
Josh Gao0cd3ae12016-09-21 12:37:10 -0700703 lock.unlock();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800704
Elliott Hughes8d28e192015-10-07 14:55:10 -0700705 // Don't return unauthorized devices; the caller can't do anything with them.
706 if (result && result->connection_state == kCsUnauthorized) {
707 *error_out = "device unauthorized.\n";
708 char* ADB_VENDOR_KEYS = getenv("ADB_VENDOR_KEYS");
709 *error_out += "This adb server's $ADB_VENDOR_KEYS is ";
710 *error_out += ADB_VENDOR_KEYS ? ADB_VENDOR_KEYS : "not set";
711 *error_out += "\n";
712 *error_out += "Try 'adb kill-server' if that seems wrong.\n";
713 *error_out += "Otherwise check for a confirmation dialog on your device.";
714 result = nullptr;
715 }
Benoit Goby77e8e582013-01-15 12:36:47 -0800716
Elliott Hughes8d28e192015-10-07 14:55:10 -0700717 // Don't return offline devices; the caller can't do anything with them.
718 if (result && result->connection_state == kCsOffline) {
719 *error_out = "device offline";
720 result = nullptr;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800721 }
722
723 if (result) {
Elliott Hughese2d36772015-06-23 13:00:32 -0700724 *error_out = "success";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800725 }
726
727 return result;
728}
729
Yabin Cui7f274902016-04-18 11:22:34 -0700730void atransport::Kick() {
731 if (!kicked_) {
732 kicked_ = true;
733 CHECK(kick_func_ != nullptr);
734 kick_func_(this);
735 }
736}
737
David Purselld2acbd12015-12-02 15:14:31 -0800738const std::string atransport::connection_state_name() const {
Elliott Hughese67f1f82015-04-30 17:32:03 -0700739 switch (connection_state) {
David Purselld2acbd12015-12-02 15:14:31 -0800740 case kCsOffline: return "offline";
741 case kCsBootloader: return "bootloader";
742 case kCsDevice: return "device";
743 case kCsHost: return "host";
744 case kCsRecovery: return "recovery";
Elliott Hughes1b708d32015-12-11 19:07:01 -0800745 case kCsNoPerm: return UsbNoPermissionsShortHelpText();
David Purselld2acbd12015-12-02 15:14:31 -0800746 case kCsSideload: return "sideload";
747 case kCsUnauthorized: return "unauthorized";
748 default: return "unknown";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800749 }
750}
751
Tamas Berghammer3d2904c2015-07-13 19:12:28 +0100752void atransport::update_version(int version, size_t payload) {
753 protocol_version = std::min(version, A_VERSION);
754 max_payload = std::min(payload, MAX_PAYLOAD);
755}
756
757int atransport::get_protocol_version() const {
758 return protocol_version;
759}
760
761size_t atransport::get_max_payload() const {
762 return max_payload;
763}
764
David Pursell4e2fd362015-09-22 10:43:08 -0700765namespace {
David Pursell0955c662015-08-31 10:42:13 -0700766
David Pursell4e2fd362015-09-22 10:43:08 -0700767constexpr char kFeatureStringDelimiter = ',';
768
769} // namespace
Dan Albert1792c232015-05-18 13:06:53 -0700770
771const FeatureSet& supported_features() {
David Pursell4e2fd362015-09-22 10:43:08 -0700772 // Local static allocation to avoid global non-POD variables.
773 static const FeatureSet* features = new FeatureSet{
Todd Kennedy51c05ec2015-11-10 00:03:25 +0000774 kFeatureShell2,
Josh Gao5a1e3fd2016-12-05 17:11:34 -0800775 kFeatureCmd,
776 kFeatureStat2,
David Pursellbbe3d212015-09-25 08:37:13 -0700777 // Increment ADB_SERVER_VERSION whenever the feature list changes to
778 // make sure that the adb client and server features stay in sync
779 // (http://b/24370690).
David Pursell4e2fd362015-09-22 10:43:08 -0700780 };
781
782 return *features;
783}
784
785std::string FeatureSetToString(const FeatureSet& features) {
786 return android::base::Join(features, kFeatureStringDelimiter);
787}
788
789FeatureSet StringToFeatureSet(const std::string& features_string) {
David Purselld2b588e2015-09-25 13:04:21 -0700790 if (features_string.empty()) {
791 return FeatureSet();
792 }
793
David Pursell4e2fd362015-09-22 10:43:08 -0700794 auto names = android::base::Split(features_string,
795 {kFeatureStringDelimiter});
796 return FeatureSet(names.begin(), names.end());
Dan Albert1792c232015-05-18 13:06:53 -0700797}
798
David Pursell70ef7b42015-09-30 13:35:42 -0700799bool CanUseFeature(const FeatureSet& feature_set, const std::string& feature) {
800 return feature_set.count(feature) > 0 &&
801 supported_features().count(feature) > 0;
802}
803
Dan Albert1792c232015-05-18 13:06:53 -0700804bool atransport::has_feature(const std::string& feature) const {
805 return features_.count(feature) > 0;
806}
807
David Pursell4e2fd362015-09-22 10:43:08 -0700808void atransport::SetFeatures(const std::string& features_string) {
809 features_ = StringToFeatureSet(features_string);
Dan Albert1792c232015-05-18 13:06:53 -0700810}
811
Yabin Cuib3298242015-08-28 15:09:44 -0700812void atransport::AddDisconnect(adisconnect* disconnect) {
813 disconnects_.push_back(disconnect);
814}
815
816void atransport::RemoveDisconnect(adisconnect* disconnect) {
817 disconnects_.remove(disconnect);
818}
819
820void atransport::RunDisconnects() {
Elliott Hughes65fe2512015-10-07 15:59:35 -0700821 for (const auto& disconnect : disconnects_) {
Yabin Cuib3298242015-08-28 15:09:44 -0700822 disconnect->func(disconnect->opaque, this);
823 }
824 disconnects_.clear();
825}
826
David Pursell3f902aa2016-03-01 08:58:26 -0800827bool atransport::MatchesTarget(const std::string& target) const {
828 if (serial) {
829 if (target == serial) {
830 return true;
831 } else if (type == kTransportLocal) {
832 // Local transports can match [tcp:|udp:]<hostname>[:port].
833 const char* local_target_ptr = target.c_str();
834
835 // For fastboot compatibility, ignore protocol prefixes.
836 if (android::base::StartsWith(target, "tcp:") ||
837 android::base::StartsWith(target, "udp:")) {
838 local_target_ptr += 4;
839 }
840
841 // Parse our |serial| and the given |target| to check if the hostnames and ports match.
842 std::string serial_host, error;
843 int serial_port = -1;
844 if (android::base::ParseNetAddress(serial, &serial_host, &serial_port, nullptr,
845 &error)) {
846 // |target| may omit the port to default to ours.
847 std::string target_host;
848 int target_port = serial_port;
849 if (android::base::ParseNetAddress(local_target_ptr, &target_host, &target_port,
850 nullptr, &error) &&
851 serial_host == target_host && serial_port == target_port) {
852 return true;
853 }
854 }
855 }
856 }
857
858 return (devpath && target == devpath) ||
859 qual_match(target.c_str(), "product:", product, false) ||
860 qual_match(target.c_str(), "model:", model, true) ||
861 qual_match(target.c_str(), "device:", device, false);
862}
863
Elliott Hughese67f1f82015-04-30 17:32:03 -0700864#if ADB_HOST
865
Dan Albertd99d9022015-05-06 16:48:52 -0700866static void append_transport_info(std::string* result, const char* key,
867 const char* value, bool sanitize) {
Elliott Hughese67f1f82015-04-30 17:32:03 -0700868 if (value == nullptr || *value == '\0') {
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700869 return;
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700870 }
871
Elliott Hughese67f1f82015-04-30 17:32:03 -0700872 *result += ' ';
873 *result += key;
874
875 for (const char* p = value; *p; ++p) {
876 result->push_back((!sanitize || isalnum(*p)) ? *p : '_');
877 }
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700878}
879
Dan Albertc7915a32015-05-18 16:46:31 -0700880static void append_transport(const atransport* t, std::string* result,
881 bool long_listing) {
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700882 const char* serial = t->serial;
Elliott Hughese67f1f82015-04-30 17:32:03 -0700883 if (!serial || !serial[0]) {
Dan Albertd99d9022015-05-06 16:48:52 -0700884 serial = "(no serial number)";
Elliott Hughese67f1f82015-04-30 17:32:03 -0700885 }
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700886
887 if (!long_listing) {
Elliott Hughese67f1f82015-04-30 17:32:03 -0700888 *result += serial;
889 *result += '\t';
890 *result += t->connection_state_name();
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700891 } else {
David Purselld2acbd12015-12-02 15:14:31 -0800892 android::base::StringAppendF(result, "%-22s %s", serial,
893 t->connection_state_name().c_str());
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700894
Elliott Hughese67f1f82015-04-30 17:32:03 -0700895 append_transport_info(result, "", t->devpath, false);
896 append_transport_info(result, "product:", t->product, false);
897 append_transport_info(result, "model:", t->model, true);
898 append_transport_info(result, "device:", t->device, false);
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700899 }
Elliott Hughese67f1f82015-04-30 17:32:03 -0700900 *result += '\n';
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700901}
902
Elliott Hughese67f1f82015-04-30 17:32:03 -0700903std::string list_transports(bool long_listing) {
904 std::string result;
Josh Gao0cd3ae12016-09-21 12:37:10 -0700905
906 std::lock_guard<std::mutex> lock(transport_lock);
Elliott Hughes65fe2512015-10-07 15:59:35 -0700907 for (const auto& t : transport_list) {
Elliott Hughese67f1f82015-04-30 17:32:03 -0700908 append_transport(t, &result, long_listing);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800909 }
Elliott Hughese67f1f82015-04-30 17:32:03 -0700910 return result;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800911}
912
Josh Gao22d2b3e2016-10-27 14:01:08 -0700913void close_usb_devices(std::function<bool(const atransport*)> predicate) {
914 std::lock_guard<std::mutex> lock(transport_lock);
915 for (auto& t : transport_list) {
916 if (predicate(t)) {
917 t->Kick();
918 }
919 }
920}
921
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800922/* hack for osx */
Dan Albertc7915a32015-05-18 16:46:31 -0700923void close_usb_devices() {
Josh Gao22d2b3e2016-10-27 14:01:08 -0700924 close_usb_devices([](const atransport*) { return true; });
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800925}
926#endif // ADB_HOST
927
Dan Albertc7915a32015-05-18 16:46:31 -0700928int register_socket_transport(int s, const char *serial, int port, int local) {
929 atransport* t = new atransport();
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100930
931 if (!serial) {
Dan Albertc7915a32015-05-18 16:46:31 -0700932 char buf[32];
933 snprintf(buf, sizeof(buf), "T-%p", t);
934 serial = buf;
David 'Digit' Turner730ff3b2011-01-06 14:11:07 +0100935 }
Dan Albertc7915a32015-05-18 16:46:31 -0700936
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700937 D("transport: %s init'ing for socket %d, on port %d", serial, s, port);
Benoit Goby1c45ee92013-03-29 18:22:36 -0700938 if (init_socket_transport(t, s, port, local) < 0) {
Dan Albertc7915a32015-05-18 16:46:31 -0700939 delete t;
Benoit Goby1c45ee92013-03-29 18:22:36 -0700940 return -1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800941 }
Benoit Goby1c45ee92013-03-29 18:22:36 -0700942
Josh Gao0cd3ae12016-09-21 12:37:10 -0700943 std::unique_lock<std::mutex> lock(transport_lock);
Elliott Hughes65fe2512015-10-07 15:59:35 -0700944 for (const auto& transport : pending_list) {
Dan Albertc7915a32015-05-18 16:46:31 -0700945 if (transport->serial && strcmp(serial, transport->serial) == 0) {
Yabin Cuib74c6492016-04-29 16:53:52 -0700946 VLOG(TRANSPORT) << "socket transport " << transport->serial
947 << " is already in pending_list and fails to register";
Dan Albertc7915a32015-05-18 16:46:31 -0700948 delete t;
Benoit Goby1c45ee92013-03-29 18:22:36 -0700949 return -1;
950 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800951 }
Benoit Goby1c45ee92013-03-29 18:22:36 -0700952
Elliott Hughes65fe2512015-10-07 15:59:35 -0700953 for (const auto& transport : transport_list) {
Dan Albertc7915a32015-05-18 16:46:31 -0700954 if (transport->serial && strcmp(serial, transport->serial) == 0) {
Yabin Cuib74c6492016-04-29 16:53:52 -0700955 VLOG(TRANSPORT) << "socket transport " << transport->serial
956 << " is already in transport_list and fails to register";
Dan Albertc7915a32015-05-18 16:46:31 -0700957 delete t;
Benoit Goby1c45ee92013-03-29 18:22:36 -0700958 return -1;
959 }
960 }
961
Dan Albertc7915a32015-05-18 16:46:31 -0700962 pending_list.push_front(t);
Benoit Goby1c45ee92013-03-29 18:22:36 -0700963 t->serial = strdup(serial);
Josh Gao0cd3ae12016-09-21 12:37:10 -0700964
965 lock.unlock();
Benoit Goby1c45ee92013-03-29 18:22:36 -0700966
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800967 register_transport(t);
Benoit Goby1c45ee92013-03-29 18:22:36 -0700968 return 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800969}
970
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400971#if ADB_HOST
Dan Albertc7915a32015-05-18 16:46:31 -0700972atransport *find_transport(const char *serial) {
973 atransport* result = nullptr;
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400974
Josh Gao0cd3ae12016-09-21 12:37:10 -0700975 std::lock_guard<std::mutex> lock(transport_lock);
Yabin Cuif4b99282015-08-27 12:03:11 -0700976 for (auto& t : transport_list) {
Dan Albertc7915a32015-05-18 16:46:31 -0700977 if (t->serial && strcmp(serial, t->serial) == 0) {
978 result = t;
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400979 break;
980 }
Dan Albertc7915a32015-05-18 16:46:31 -0700981 }
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400982
Dan Albertc7915a32015-05-18 16:46:31 -0700983 return result;
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400984}
985
Yabin Cuif4b99282015-08-27 12:03:11 -0700986void kick_all_tcp_devices() {
Josh Gao0cd3ae12016-09-21 12:37:10 -0700987 std::lock_guard<std::mutex> lock(transport_lock);
Yabin Cuif4b99282015-08-27 12:03:11 -0700988 for (auto& t : transport_list) {
Yabin Cuib74c6492016-04-29 16:53:52 -0700989 if (t->IsTcpDevice()) {
Yabin Cuid6ab3c22015-08-31 11:50:24 -0700990 // Kicking breaks the read_transport thread of this transport out of any read, then
991 // the read_transport thread will notify the main thread to make this transport
992 // offline. Then the main thread will notify the write_transport thread to exit.
Yabin Cuif4b99282015-08-27 12:03:11 -0700993 // Finally, this transport will be closed and freed in the main thread.
Yabin Cui7f274902016-04-18 11:22:34 -0700994 t->Kick();
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400995 }
Dan Albertc7915a32015-05-18 16:46:31 -0700996 }
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400997}
998
Mike Lockwood8cf0d592009-10-11 23:04:18 -0400999#endif
1000
Dan Albertc7915a32015-05-18 16:46:31 -07001001void register_usb_transport(usb_handle* usb, const char* serial,
1002 const char* devpath, unsigned writeable) {
1003 atransport* t = new atransport();
1004
Yabin Cui7a3f8d62015-09-02 17:44:28 -07001005 D("transport: %p init'ing for usb_handle %p (sn='%s')", t, usb,
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001006 serial ? serial : "");
Dan Albertdcd78a12015-05-18 16:43:57 -07001007 init_usb_transport(t, usb, (writeable ? kCsOffline : kCsNoPerm));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001008 if(serial) {
1009 t->serial = strdup(serial);
1010 }
Dan Albertc7915a32015-05-18 16:46:31 -07001011
1012 if (devpath) {
Scott Andersone109d262012-04-20 11:21:14 -07001013 t->devpath = strdup(devpath);
1014 }
Benoit Goby1c45ee92013-03-29 18:22:36 -07001015
Josh Gao0cd3ae12016-09-21 12:37:10 -07001016 {
1017 std::lock_guard<std::mutex> lock(transport_lock);
1018 pending_list.push_front(t);
1019 }
Benoit Goby1c45ee92013-03-29 18:22:36 -07001020
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001021 register_transport(t);
1022}
1023
Dan Albertdcd78a12015-05-18 16:43:57 -07001024// This should only be used for transports with connection_state == kCsNoPerm.
Dan Albertc7915a32015-05-18 16:46:31 -07001025void unregister_usb_transport(usb_handle *usb) {
Josh Gao0cd3ae12016-09-21 12:37:10 -07001026 std::lock_guard<std::mutex> lock(transport_lock);
Dan Albertc7915a32015-05-18 16:46:31 -07001027 transport_list.remove_if([usb](atransport* t) {
1028 return t->usb == usb && t->connection_state == kCsNoPerm;
1029 });
Mike Lockwood0927bf92009-08-08 12:37:44 -04001030}
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001031
Tamas Berghammer3d2904c2015-07-13 19:12:28 +01001032int check_header(apacket *p, atransport *t)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001033{
1034 if(p->msg.magic != (p->msg.command ^ 0xffffffff)) {
Yabin Cuiaed3c612015-09-22 15:52:57 -07001035 VLOG(RWX) << "check_header(): invalid magic";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001036 return -1;
1037 }
1038
Tamas Berghammer3d2904c2015-07-13 19:12:28 +01001039 if(p->msg.data_length > t->get_max_payload()) {
Yabin Cuiaed3c612015-09-22 15:52:57 -07001040 VLOG(RWX) << "check_header(): " << p->msg.data_length << " atransport::max_payload = "
1041 << t->get_max_payload();
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001042 return -1;
1043 }
1044
1045 return 0;
1046}
1047
Josh Gao06d61d42016-10-06 13:31:44 -07001048int check_data(apacket* p) {
1049 if (calculate_apacket_checksum(p) != p->msg.data_check) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001050 return -1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001051 }
Josh Gao06d61d42016-10-06 13:31:44 -07001052 return 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001053}
Elliott Hughes0aeb5052016-06-29 17:42:01 -07001054
Josh Gao3bd28792016-10-05 19:02:29 -07001055#if ADB_HOST
Josh Gao2e671202016-08-18 22:00:12 -07001056std::shared_ptr<RSA> atransport::NextKey() {
Elliott Hughes0aeb5052016-06-29 17:42:01 -07001057 if (keys_.empty()) keys_ = adb_auth_get_private_keys();
1058
Josh Gao2e671202016-08-18 22:00:12 -07001059 std::shared_ptr<RSA> result = keys_[0];
Elliott Hughes0aeb5052016-06-29 17:42:01 -07001060 keys_.pop_front();
1061 return result;
1062}
Josh Gao3bd28792016-10-05 19:02:29 -07001063#endif