blob: ffa93f4ee94a9417cbee8482583d7656a2e18e6d [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
17#define TRACE_TAG TRACE_ADB
18
19#include <stdio.h>
20#include <stdlib.h>
21#include <ctype.h>
22#include <stdarg.h>
23#include <errno.h>
Scott Andersonc7993af2012-05-25 13:55:46 -070024#include <stddef.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080025#include <string.h>
26#include <time.h>
Mike Lockwood1f546e62009-05-25 18:17:55 -040027#include <sys/time.h>
Ray Donnellycbb98912012-11-29 01:36:08 +000028#include <stdint.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080029
30#include "sysdeps.h"
31#include "adb.h"
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070032#include "adb_auth.h"
Dan Albertcc731cc2015-02-24 21:26:58 -080033#include "adb_io.h"
Dan Alberte9fca142015-02-18 18:03:26 -080034#include "adb_listeners.h"
Dan Albert76649012015-02-24 15:51:19 -080035#include "transport.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080036
Scott Andersone82c2db2012-05-25 14:10:02 -070037#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
38
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080039#if !ADB_HOST
Nick Kralevich893a4a42013-05-23 09:54:13 -070040#include <cutils/properties.h>
Nick Kraleviche2864bf2013-02-28 14:12:58 -080041#include <sys/capability.h>
Jeff Sharkey885342a2012-08-14 21:00:22 -070042#include <sys/mount.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080043#endif
44
JP Abgrall408fa572011-03-16 15:57:42 -070045#if ADB_TRACE
46ADB_MUTEX_DEFINE( D_lock );
47#endif
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080048
49int HOST = 0;
50
Scott Andersone82c2db2012-05-25 14:10:02 -070051#if !ADB_HOST
Dan Albertbd0b7502015-02-18 18:22:45 -080052const char *adb_device_banner = "device";
Scott Andersone82c2db2012-05-25 14:10:02 -070053#endif
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080054
55void fatal(const char *fmt, ...)
56{
57 va_list ap;
58 va_start(ap, fmt);
59 fprintf(stderr, "error: ");
60 vfprintf(stderr, fmt, ap);
61 fprintf(stderr, "\n");
62 va_end(ap);
63 exit(-1);
64}
65
66void fatal_errno(const char *fmt, ...)
67{
68 va_list ap;
69 va_start(ap, fmt);
70 fprintf(stderr, "error: %s: ", strerror(errno));
71 vfprintf(stderr, fmt, ap);
72 fprintf(stderr, "\n");
73 va_end(ap);
74 exit(-1);
75}
76
77int adb_trace_mask;
78
79/* read a comma/space/colum/semi-column separated list of tags
80 * from the ADB_TRACE environment variable and build the trace
81 * mask from it. note that '1' and 'all' are special cases to
82 * enable all tracing
83 */
84void adb_trace_init(void)
85{
86 const char* p = getenv("ADB_TRACE");
87 const char* q;
88
89 static const struct {
90 const char* tag;
91 int flag;
92 } tags[] = {
93 { "1", 0 },
94 { "all", 0 },
95 { "adb", TRACE_ADB },
96 { "sockets", TRACE_SOCKETS },
97 { "packets", TRACE_PACKETS },
98 { "rwx", TRACE_RWX },
99 { "usb", TRACE_USB },
100 { "sync", TRACE_SYNC },
101 { "sysdeps", TRACE_SYSDEPS },
102 { "transport", TRACE_TRANSPORT },
103 { "jdwp", TRACE_JDWP },
JP Abgrall408fa572011-03-16 15:57:42 -0700104 { "services", TRACE_SERVICES },
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700105 { "auth", TRACE_AUTH },
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800106 { NULL, 0 }
107 };
108
109 if (p == NULL)
110 return;
111
112 /* use a comma/column/semi-colum/space separated list */
113 while (*p) {
114 int len, tagn;
115
116 q = strpbrk(p, " ,:;");
117 if (q == NULL) {
118 q = p + strlen(p);
119 }
120 len = q - p;
121
122 for (tagn = 0; tags[tagn].tag != NULL; tagn++)
123 {
124 int taglen = strlen(tags[tagn].tag);
125
126 if (len == taglen && !memcmp(tags[tagn].tag, p, len) )
127 {
128 int flag = tags[tagn].flag;
129 if (flag == 0) {
130 adb_trace_mask = ~0;
131 return;
132 }
133 adb_trace_mask |= (1 << flag);
134 break;
135 }
136 }
137 p = q;
138 if (*p)
139 p++;
140 }
141}
142
Dan Albertbac34742015-02-25 17:51:28 -0800143apacket* get_apacket(void)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800144{
Dan Albertbac34742015-02-25 17:51:28 -0800145 apacket* p = reinterpret_cast<apacket*>(malloc(sizeof(apacket)));
146 if (p == nullptr) {
147 fatal("failed to allocate an apacket");
148 }
149
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800150 memset(p, 0, sizeof(apacket) - MAX_PAYLOAD);
151 return p;
152}
153
154void put_apacket(apacket *p)
155{
156 free(p);
157}
158
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700159void handle_online(atransport *t)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800160{
161 D("adb: online\n");
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700162 t->online = 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800163}
164
165void handle_offline(atransport *t)
166{
167 D("adb: offline\n");
168 //Close the associated usb
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700169 t->online = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800170 run_transport_disconnects(t);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800171}
172
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700173#if DEBUG_PACKETS
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800174#define DUMPMAX 32
175void print_packet(const char *label, apacket *p)
176{
177 char *tag;
178 char *x;
179 unsigned count;
180
181 switch(p->msg.command){
182 case A_SYNC: tag = "SYNC"; break;
183 case A_CNXN: tag = "CNXN" ; break;
184 case A_OPEN: tag = "OPEN"; break;
185 case A_OKAY: tag = "OKAY"; break;
186 case A_CLSE: tag = "CLSE"; break;
187 case A_WRTE: tag = "WRTE"; break;
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700188 case A_AUTH: tag = "AUTH"; break;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800189 default: tag = "????"; break;
190 }
191
192 fprintf(stderr, "%s: %s %08x %08x %04x \"",
193 label, tag, p->msg.arg0, p->msg.arg1, p->msg.data_length);
194 count = p->msg.data_length;
195 x = (char*) p->data;
196 if(count > DUMPMAX) {
197 count = DUMPMAX;
198 tag = "\n";
199 } else {
200 tag = "\"\n";
201 }
202 while(count-- > 0){
203 if((*x >= ' ') && (*x < 127)) {
204 fputc(*x, stderr);
205 } else {
206 fputc('.', stderr);
207 }
208 x++;
209 }
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700210 fputs(tag, stderr);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800211}
212#endif
213
214static void send_ready(unsigned local, unsigned remote, atransport *t)
215{
216 D("Calling send_ready \n");
217 apacket *p = get_apacket();
218 p->msg.command = A_OKAY;
219 p->msg.arg0 = local;
220 p->msg.arg1 = remote;
221 send_packet(p, t);
222}
223
224static void send_close(unsigned local, unsigned remote, atransport *t)
225{
226 D("Calling send_close \n");
227 apacket *p = get_apacket();
228 p->msg.command = A_CLSE;
229 p->msg.arg0 = local;
230 p->msg.arg1 = remote;
231 send_packet(p, t);
232}
233
Scott Andersone82c2db2012-05-25 14:10:02 -0700234static size_t fill_connect_data(char *buf, size_t bufsize)
235{
236#if ADB_HOST
237 return snprintf(buf, bufsize, "host::") + 1;
238#else
239 static const char *cnxn_props[] = {
240 "ro.product.name",
241 "ro.product.model",
242 "ro.product.device",
243 };
244 static const int num_cnxn_props = ARRAY_SIZE(cnxn_props);
245 int i;
246 size_t remaining = bufsize;
247 size_t len;
248
249 len = snprintf(buf, remaining, "%s::", adb_device_banner);
250 remaining -= len;
251 buf += len;
252 for (i = 0; i < num_cnxn_props; i++) {
253 char value[PROPERTY_VALUE_MAX];
254 property_get(cnxn_props[i], value, "");
255 len = snprintf(buf, remaining, "%s=%s;", cnxn_props[i], value);
256 remaining -= len;
257 buf += len;
258 }
259
260 return bufsize - remaining + 1;
261#endif
262}
263
David 'Digit' Turner25258692013-03-21 21:07:42 +0100264#if !ADB_HOST
265static void send_msg_with_header(int fd, const char* msg, size_t msglen) {
266 char header[5];
267 if (msglen > 0xffff)
268 msglen = 0xffff;
269 snprintf(header, sizeof(header), "%04x", (unsigned)msglen);
Dan Albertcc731cc2015-02-24 21:26:58 -0800270 WriteFdExactly(fd, header, 4);
271 WriteFdExactly(fd, msg, msglen);
David 'Digit' Turner25258692013-03-21 21:07:42 +0100272}
273#endif
274
Chih-Hung Hsiehf787b382014-09-05 15:38:15 -0700275#if ADB_HOST
David 'Digit' Turner25258692013-03-21 21:07:42 +0100276static void send_msg_with_okay(int fd, const char* msg, size_t msglen) {
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100277 char header[9];
278 if (msglen > 0xffff)
279 msglen = 0xffff;
280 snprintf(header, sizeof(header), "OKAY%04x", (unsigned)msglen);
Dan Albertcc731cc2015-02-24 21:26:58 -0800281 WriteFdExactly(fd, header, 8);
282 WriteFdExactly(fd, msg, msglen);
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100283}
Chih-Hung Hsiehf787b382014-09-05 15:38:15 -0700284#endif // ADB_HOST
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100285
Dan Albertba3a2512015-02-18 17:47:33 -0800286void send_connect(atransport *t)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800287{
288 D("Calling send_connect \n");
289 apacket *cp = get_apacket();
290 cp->msg.command = A_CNXN;
291 cp->msg.arg0 = A_VERSION;
292 cp->msg.arg1 = MAX_PAYLOAD;
Scott Andersone82c2db2012-05-25 14:10:02 -0700293 cp->msg.data_length = fill_connect_data((char *)cp->data,
294 sizeof(cp->data));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800295 send_packet(cp, t);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700296}
297
Chih-Hung Hsiehf787b382014-09-05 15:38:15 -0700298#if ADB_HOST
Dan Albertbac34742015-02-25 17:51:28 -0800299static const char* connection_state_name(atransport *t)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800300{
301 if (t == NULL) {
302 return "unknown";
303 }
304
305 switch(t->connection_state) {
306 case CS_BOOTLOADER:
307 return "bootloader";
308 case CS_DEVICE:
309 return "device";
trevda5ad5392013-04-17 14:34:23 +0100310 case CS_RECOVERY:
311 return "recovery";
312 case CS_SIDELOAD:
313 return "sideload";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800314 case CS_OFFLINE:
315 return "offline";
Benoit Goby77e8e582013-01-15 12:36:47 -0800316 case CS_UNAUTHORIZED:
317 return "unauthorized";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800318 default:
319 return "unknown";
320 }
321}
Chih-Hung Hsiehf787b382014-09-05 15:38:15 -0700322#endif // ADB_HOST
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800323
Scott Andersone82c2db2012-05-25 14:10:02 -0700324/* qual_overwrite is used to overwrite a qualifier string. dst is a
325 * pointer to a char pointer. It is assumed that if *dst is non-NULL, it
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700326 * was malloc'ed and needs to freed. *dst will be set to a dup of src.
Scott Andersone82c2db2012-05-25 14:10:02 -0700327 */
328static void qual_overwrite(char **dst, const char *src)
329{
330 if (!dst)
331 return;
332
333 free(*dst);
334 *dst = NULL;
335
336 if (!src || !*src)
337 return;
338
339 *dst = strdup(src);
340}
341
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800342void parse_banner(char *banner, atransport *t)
343{
Scott Andersone82c2db2012-05-25 14:10:02 -0700344 static const char *prop_seps = ";";
345 static const char key_val_sep = '=';
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700346 char *cp;
347 char *type;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800348
349 D("parse_banner: %s\n", banner);
350 type = banner;
Scott Andersone82c2db2012-05-25 14:10:02 -0700351 cp = strchr(type, ':');
352 if (cp) {
353 *cp++ = 0;
354 /* Nothing is done with second field. */
355 cp = strchr(cp, ':');
356 if (cp) {
357 char *save;
358 char *key;
Scott Anderson1b7a7e82012-06-05 17:54:27 -0700359 key = adb_strtok_r(cp + 1, prop_seps, &save);
Scott Andersone82c2db2012-05-25 14:10:02 -0700360 while (key) {
361 cp = strchr(key, key_val_sep);
362 if (cp) {
363 *cp++ = '\0';
364 if (!strcmp(key, "ro.product.name"))
365 qual_overwrite(&t->product, cp);
366 else if (!strcmp(key, "ro.product.model"))
367 qual_overwrite(&t->model, cp);
368 else if (!strcmp(key, "ro.product.device"))
369 qual_overwrite(&t->device, cp);
370 }
Scott Anderson1b7a7e82012-06-05 17:54:27 -0700371 key = adb_strtok_r(NULL, prop_seps, &save);
Scott Andersone82c2db2012-05-25 14:10:02 -0700372 }
373 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800374 }
375
376 if(!strcmp(type, "bootloader")){
377 D("setting connection_state to CS_BOOTLOADER\n");
378 t->connection_state = CS_BOOTLOADER;
379 update_transports();
380 return;
381 }
382
383 if(!strcmp(type, "device")) {
384 D("setting connection_state to CS_DEVICE\n");
385 t->connection_state = CS_DEVICE;
386 update_transports();
387 return;
388 }
389
390 if(!strcmp(type, "recovery")) {
391 D("setting connection_state to CS_RECOVERY\n");
392 t->connection_state = CS_RECOVERY;
393 update_transports();
394 return;
395 }
396
Doug Zongker447f0612012-01-09 14:54:53 -0800397 if(!strcmp(type, "sideload")) {
398 D("setting connection_state to CS_SIDELOAD\n");
399 t->connection_state = CS_SIDELOAD;
400 update_transports();
401 return;
402 }
403
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800404 t->connection_state = CS_HOST;
405}
406
407void handle_packet(apacket *p, atransport *t)
408{
409 asocket *s;
410
Viral Mehta899913f2010-06-16 18:41:28 +0530411 D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0],
412 ((char*) (&(p->msg.command)))[1],
413 ((char*) (&(p->msg.command)))[2],
414 ((char*) (&(p->msg.command)))[3]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800415 print_packet("recv", p);
416
417 switch(p->msg.command){
418 case A_SYNC:
419 if(p->msg.arg0){
420 send_packet(p, t);
421 if(HOST) send_connect(t);
422 } else {
423 t->connection_state = CS_OFFLINE;
424 handle_offline(t);
425 send_packet(p, t);
426 }
427 return;
428
429 case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */
430 /* XXX verify version, etc */
431 if(t->connection_state != CS_OFFLINE) {
432 t->connection_state = CS_OFFLINE;
433 handle_offline(t);
434 }
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700435
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800436 parse_banner((char*) p->data, t);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700437
438 if (HOST || !auth_enabled) {
439 handle_online(t);
440 if(!HOST) send_connect(t);
441 } else {
442 send_auth_request(t);
443 }
444 break;
445
446 case A_AUTH:
447 if (p->msg.arg0 == ADB_AUTH_TOKEN) {
Benoit Goby77e8e582013-01-15 12:36:47 -0800448 t->connection_state = CS_UNAUTHORIZED;
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700449 t->key = adb_auth_nextkey(t->key);
450 if (t->key) {
451 send_auth_response(p->data, p->msg.data_length, t);
452 } else {
453 /* No more private keys to try, send the public key */
454 send_auth_publickey(t);
455 }
456 } else if (p->msg.arg0 == ADB_AUTH_SIGNATURE) {
457 if (adb_auth_verify(t->token, p->data, p->msg.data_length)) {
458 adb_auth_verified(t);
459 t->failed_auth_attempts = 0;
460 } else {
461 if (t->failed_auth_attempts++ > 10)
462 adb_sleep_ms(1000);
463 send_auth_request(t);
464 }
465 } else if (p->msg.arg0 == ADB_AUTH_RSAPUBLICKEY) {
466 adb_auth_confirm_key(p->data, p->msg.data_length, t);
467 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800468 break;
469
470 case A_OPEN: /* OPEN(local-id, 0, "destination") */
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100471 if (t->online && p->msg.arg0 != 0 && p->msg.arg1 == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800472 char *name = (char*) p->data;
473 name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0;
474 s = create_local_service_socket(name);
475 if(s == 0) {
476 send_close(0, p->msg.arg0, t);
477 } else {
478 s->peer = create_remote_socket(p->msg.arg0, t);
479 s->peer->peer = s;
480 send_ready(s->id, s->peer->id, t);
481 s->ready(s);
482 }
483 }
484 break;
485
486 case A_OKAY: /* READY(local-id, remote-id, "") */
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100487 if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) {
488 if((s = find_local_socket(p->msg.arg1, 0))) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800489 if(s->peer == 0) {
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100490 /* On first READY message, create the connection. */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800491 s->peer = create_remote_socket(p->msg.arg0, t);
492 s->peer->peer = s;
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100493 s->ready(s);
494 } else if (s->peer->id == p->msg.arg0) {
495 /* Other READY messages must use the same local-id */
496 s->ready(s);
497 } else {
498 D("Invalid A_OKAY(%d,%d), expected A_OKAY(%d,%d) on transport %s\n",
499 p->msg.arg0, p->msg.arg1, s->peer->id, p->msg.arg1, t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800500 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800501 }
502 }
503 break;
504
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100505 case A_CLSE: /* CLOSE(local-id, remote-id, "") or CLOSE(0, remote-id, "") */
506 if (t->online && p->msg.arg1 != 0) {
507 if((s = find_local_socket(p->msg.arg1, p->msg.arg0))) {
508 /* According to protocol.txt, p->msg.arg0 might be 0 to indicate
509 * a failed OPEN only. However, due to a bug in previous ADB
510 * versions, CLOSE(0, remote-id, "") was also used for normal
511 * CLOSE() operations.
512 *
513 * This is bad because it means a compromised adbd could
514 * send packets to close connections between the host and
515 * other devices. To avoid this, only allow this if the local
516 * socket has a peer on the same transport.
517 */
518 if (p->msg.arg0 == 0 && s->peer && s->peer->transport != t) {
519 D("Invalid A_CLSE(0, %u) from transport %s, expected transport %s\n",
520 p->msg.arg1, t->serial, s->peer->transport->serial);
521 } else {
522 s->close(s);
523 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800524 }
525 }
526 break;
527
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100528 case A_WRTE: /* WRITE(local-id, remote-id, <data>) */
529 if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) {
530 if((s = find_local_socket(p->msg.arg1, p->msg.arg0))) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800531 unsigned rid = p->msg.arg0;
532 p->len = p->msg.data_length;
533
534 if(s->enqueue(s, p) == 0) {
535 D("Enqueue the socket\n");
536 send_ready(s->id, rid, t);
537 }
538 return;
539 }
540 }
541 break;
542
543 default:
544 printf("handle_packet: what is %08x?!\n", p->msg.command);
545 }
546
547 put_apacket(p);
548}
549
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800550#if ADB_HOST
JP Abgrall571c1362012-12-06 18:18:12 -0800551
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100552int launch_server(int server_port)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800553{
Yabin Cuie77b6a02014-11-11 09:24:11 -0800554#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800555 /* we need to start the server in the background */
556 /* we create a PIPE that will be used to wait for the server's "OK" */
557 /* message since the pipe handles must be inheritable, we use a */
558 /* security attribute */
559 HANDLE pipe_read, pipe_write;
Ray Donnelly267aa8b2012-11-29 01:18:50 +0000560 HANDLE stdout_handle, stderr_handle;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800561 SECURITY_ATTRIBUTES sa;
562 STARTUPINFO startup;
563 PROCESS_INFORMATION pinfo;
564 char program_path[ MAX_PATH ];
565 int ret;
566
567 sa.nLength = sizeof(sa);
568 sa.lpSecurityDescriptor = NULL;
569 sa.bInheritHandle = TRUE;
570
571 /* create pipe, and ensure its read handle isn't inheritable */
572 ret = CreatePipe( &pipe_read, &pipe_write, &sa, 0 );
573 if (!ret) {
574 fprintf(stderr, "CreatePipe() failure, error %ld\n", GetLastError() );
575 return -1;
576 }
577
578 SetHandleInformation( pipe_read, HANDLE_FLAG_INHERIT, 0 );
579
Ray Donnelly267aa8b2012-11-29 01:18:50 +0000580 /* Some programs want to launch an adb command and collect its output by
581 * calling CreateProcess with inheritable stdout/stderr handles, then
582 * using read() to get its output. When this happens, the stdout/stderr
583 * handles passed to the adb client process will also be inheritable.
584 * When starting the adb server here, care must be taken to reset them
585 * to non-inheritable.
586 * Otherwise, something bad happens: even if the adb command completes,
587 * the calling process is stuck while read()-ing from the stdout/stderr
588 * descriptors, because they're connected to corresponding handles in the
589 * adb server process (even if the latter never uses/writes to them).
590 */
591 stdout_handle = GetStdHandle( STD_OUTPUT_HANDLE );
592 stderr_handle = GetStdHandle( STD_ERROR_HANDLE );
593 if (stdout_handle != INVALID_HANDLE_VALUE) {
594 SetHandleInformation( stdout_handle, HANDLE_FLAG_INHERIT, 0 );
595 }
596 if (stderr_handle != INVALID_HANDLE_VALUE) {
597 SetHandleInformation( stderr_handle, HANDLE_FLAG_INHERIT, 0 );
598 }
599
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800600 ZeroMemory( &startup, sizeof(startup) );
601 startup.cb = sizeof(startup);
602 startup.hStdInput = GetStdHandle( STD_INPUT_HANDLE );
603 startup.hStdOutput = pipe_write;
604 startup.hStdError = GetStdHandle( STD_ERROR_HANDLE );
605 startup.dwFlags = STARTF_USESTDHANDLES;
606
607 ZeroMemory( &pinfo, sizeof(pinfo) );
608
609 /* get path of current program */
610 GetModuleFileName( NULL, program_path, sizeof(program_path) );
Wenhao Lia09558c2013-11-13 16:23:37 +0800611 char args[64];
612 snprintf(args, sizeof(args), "adb -P %d fork-server server", server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800613 ret = CreateProcess(
614 program_path, /* program path */
Wenhao Lia09558c2013-11-13 16:23:37 +0800615 args,
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800616 /* the fork-server argument will set the
617 debug = 2 in the child */
618 NULL, /* process handle is not inheritable */
619 NULL, /* thread handle is not inheritable */
620 TRUE, /* yes, inherit some handles */
621 DETACHED_PROCESS, /* the new process doesn't have a console */
622 NULL, /* use parent's environment block */
623 NULL, /* use parent's starting directory */
624 &startup, /* startup info, i.e. std handles */
625 &pinfo );
626
627 CloseHandle( pipe_write );
628
629 if (!ret) {
630 fprintf(stderr, "CreateProcess failure, error %ld\n", GetLastError() );
631 CloseHandle( pipe_read );
632 return -1;
633 }
634
635 CloseHandle( pinfo.hProcess );
636 CloseHandle( pinfo.hThread );
637
638 /* wait for the "OK\n" message */
639 {
640 char temp[3];
641 DWORD count;
642
643 ret = ReadFile( pipe_read, temp, 3, &count, NULL );
644 CloseHandle( pipe_read );
645 if ( !ret ) {
646 fprintf(stderr, "could not read ok from ADB Server, error = %ld\n", GetLastError() );
647 return -1;
648 }
649 if (count != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') {
650 fprintf(stderr, "ADB server didn't ACK\n" );
651 return -1;
652 }
653 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800654#else /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800655 char path[PATH_MAX];
656 int fd[2];
657
658 // set up a pipe so the child can tell us when it is ready.
659 // fd[0] will be parent's end, and fd[1] will get mapped to stderr in the child.
660 if (pipe(fd)) {
661 fprintf(stderr, "pipe failed in launch_server, errno: %d\n", errno);
662 return -1;
663 }
Alexey Tarasov31664102009-10-22 02:55:00 +1100664 get_my_path(path, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800665 pid_t pid = fork();
666 if(pid < 0) return -1;
667
668 if (pid == 0) {
669 // child side of the fork
670
671 // redirect stderr to the pipe
672 // we use stderr instead of stdout due to stdout's buffering behavior.
673 adb_close(fd[0]);
674 dup2(fd[1], STDERR_FILENO);
675 adb_close(fd[1]);
676
Matt Gumbeld7b33082012-11-14 10:16:17 -0800677 char str_port[30];
678 snprintf(str_port, sizeof(str_port), "%d", server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800679 // child process
Matt Gumbeld7b33082012-11-14 10:16:17 -0800680 int result = execl(path, "adb", "-P", str_port, "fork-server", "server", NULL);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800681 // this should not return
682 fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno);
683 } else {
684 // parent side of the fork
685
686 char temp[3];
687
688 temp[0] = 'A'; temp[1] = 'B'; temp[2] = 'C';
689 // wait for the "OK\n" message
690 adb_close(fd[1]);
691 int ret = adb_read(fd[0], temp, 3);
JP Abgrall408fa572011-03-16 15:57:42 -0700692 int saved_errno = errno;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800693 adb_close(fd[0]);
694 if (ret < 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700695 fprintf(stderr, "could not read ok from ADB Server, errno = %d\n", saved_errno);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800696 return -1;
697 }
698 if (ret != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') {
699 fprintf(stderr, "ADB server didn't ACK\n" );
700 return -1;
701 }
702
703 setsid();
704 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800705#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800706 return 0;
707}
Yabin Cuie77b6a02014-11-11 09:24:11 -0800708#endif /* ADB_HOST */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800709
David 'Digit' Turner25258692013-03-21 21:07:42 +0100710// Try to handle a network forwarding request.
711// This returns 1 on success, 0 on failure, and -1 to indicate this is not
712// a forwarding-related request.
713int handle_forward_request(const char* service, transport_type ttype, char* serial, int reply_fd)
714{
715 if (!strcmp(service, "list-forward")) {
716 // Create the list of forward redirections.
717 int buffer_size = format_listeners(NULL, 0);
718 // Add one byte for the trailing zero.
Dan Albertbac34742015-02-25 17:51:28 -0800719 char* buffer = reinterpret_cast<char*>(malloc(buffer_size + 1));
720 if (buffer == nullptr) {
David 'Digit' Turner25258692013-03-21 21:07:42 +0100721 sendfailmsg(reply_fd, "not enough memory");
722 return 1;
723 }
724 (void) format_listeners(buffer, buffer_size + 1);
725#if ADB_HOST
726 send_msg_with_okay(reply_fd, buffer, buffer_size);
727#else
728 send_msg_with_header(reply_fd, buffer, buffer_size);
729#endif
730 free(buffer);
731 return 1;
732 }
733
734 if (!strcmp(service, "killforward-all")) {
735 remove_all_listeners();
736#if ADB_HOST
737 /* On the host: 1st OKAY is connect, 2nd OKAY is status */
738 adb_write(reply_fd, "OKAY", 4);
739#endif
740 adb_write(reply_fd, "OKAY", 4);
741 return 1;
742 }
743
744 if (!strncmp(service, "forward:",8) ||
745 !strncmp(service, "killforward:",12)) {
Dan Albertbac34742015-02-25 17:51:28 -0800746 char *local, *remote;
David 'Digit' Turner25258692013-03-21 21:07:42 +0100747 int r;
748 atransport *transport;
749
750 int createForward = strncmp(service, "kill", 4);
751 int no_rebind = 0;
752
753 local = strchr(service, ':') + 1;
754
755 // Handle forward:norebind:<local>... here
756 if (createForward && !strncmp(local, "norebind:", 9)) {
757 no_rebind = 1;
758 local = strchr(local, ':') + 1;
759 }
760
761 remote = strchr(local,';');
762
763 if (createForward) {
764 // Check forward: parameter format: '<local>;<remote>'
765 if(remote == 0) {
766 sendfailmsg(reply_fd, "malformed forward spec");
767 return 1;
768 }
769
770 *remote++ = 0;
771 if((local[0] == 0) || (remote[0] == 0) || (remote[0] == '*')) {
772 sendfailmsg(reply_fd, "malformed forward spec");
773 return 1;
774 }
775 } else {
776 // Check killforward: parameter format: '<local>'
777 if (local[0] == 0) {
778 sendfailmsg(reply_fd, "malformed forward spec");
779 return 1;
780 }
781 }
782
Dan Albertbac34742015-02-25 17:51:28 -0800783 const char* err;
David 'Digit' Turner25258692013-03-21 21:07:42 +0100784 transport = acquire_one_transport(CS_ANY, ttype, serial, &err);
785 if (!transport) {
786 sendfailmsg(reply_fd, err);
787 return 1;
788 }
789
790 if (createForward) {
791 r = install_listener(local, remote, transport, no_rebind);
792 } else {
793 r = remove_listener(local, transport);
794 }
795 if(r == 0) {
796#if ADB_HOST
797 /* On the host: 1st OKAY is connect, 2nd OKAY is status */
Dan Albertcc731cc2015-02-24 21:26:58 -0800798 WriteFdExactly(reply_fd, "OKAY", 4);
David 'Digit' Turner25258692013-03-21 21:07:42 +0100799#endif
Dan Albertcc731cc2015-02-24 21:26:58 -0800800 WriteFdExactly(reply_fd, "OKAY", 4);
David 'Digit' Turner25258692013-03-21 21:07:42 +0100801 return 1;
802 }
803
804 if (createForward) {
805 const char* message;
806 switch (r) {
807 case INSTALL_STATUS_CANNOT_BIND:
808 message = "cannot bind to socket";
809 break;
810 case INSTALL_STATUS_CANNOT_REBIND:
811 message = "cannot rebind existing socket";
812 break;
813 default:
814 message = "internal error";
815 }
816 sendfailmsg(reply_fd, message);
817 } else {
818 sendfailmsg(reply_fd, "cannot remove listener");
819 }
820 return 1;
821 }
822 return 0;
823}
824
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800825int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s)
826{
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800827 if(!strcmp(service, "kill")) {
828 fprintf(stderr,"adb server killed by remote request\n");
829 fflush(stdout);
830 adb_write(reply_fd, "OKAY", 4);
831 usb_cleanup();
832 exit(0);
833 }
834
835#if ADB_HOST
Chih-Hung Hsiehf787b382014-09-05 15:38:15 -0700836 atransport *transport = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800837 // "transport:" is used for switching transport with a specified serial number
838 // "transport-usb:" is used for switching transport to the only USB transport
839 // "transport-local:" is used for switching transport to the only local transport
840 // "transport-any:" is used for switching transport to the only transport
841 if (!strncmp(service, "transport", strlen("transport"))) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800842 transport_type type = kTransportAny;
843
844 if (!strncmp(service, "transport-usb", strlen("transport-usb"))) {
845 type = kTransportUsb;
846 } else if (!strncmp(service, "transport-local", strlen("transport-local"))) {
847 type = kTransportLocal;
848 } else if (!strncmp(service, "transport-any", strlen("transport-any"))) {
849 type = kTransportAny;
850 } else if (!strncmp(service, "transport:", strlen("transport:"))) {
851 service += strlen("transport:");
Tom Marlin3175c8e2011-07-27 12:56:14 -0500852 serial = service;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800853 }
854
Dan Albertbac34742015-02-25 17:51:28 -0800855 const char* error_string = "unknown failure";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800856 transport = acquire_one_transport(CS_ANY, type, serial, &error_string);
857
858 if (transport) {
859 s->transport = transport;
860 adb_write(reply_fd, "OKAY", 4);
861 } else {
862 sendfailmsg(reply_fd, error_string);
863 }
864 return 1;
865 }
866
867 // return a list of all connected devices
Scott Andersone109d262012-04-20 11:21:14 -0700868 if (!strncmp(service, "devices", 7)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800869 char buffer[4096];
Scott Andersone109d262012-04-20 11:21:14 -0700870 int use_long = !strcmp(service+7, "-l");
871 if (use_long || service[7] == 0) {
Scott Andersone109d262012-04-20 11:21:14 -0700872 memset(buffer, 0, sizeof(buffer));
873 D("Getting device list \n");
874 list_transports(buffer, sizeof(buffer), use_long);
Scott Andersone109d262012-04-20 11:21:14 -0700875 D("Wrote device list \n");
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100876 send_msg_with_okay(reply_fd, buffer, strlen(buffer));
Scott Andersone109d262012-04-20 11:21:14 -0700877 return 0;
878 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800879 }
880
Mike Lockwood74d7ff82009-10-11 23:04:18 -0400881 // remove TCP transport
882 if (!strncmp(service, "disconnect:", 11)) {
883 char buffer[4096];
884 memset(buffer, 0, sizeof(buffer));
885 char* serial = service + 11;
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400886 if (serial[0] == 0) {
887 // disconnect from all TCP devices
888 unregister_all_tcp_transports();
Mike Lockwood74d7ff82009-10-11 23:04:18 -0400889 } else {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400890 char hostbuf[100];
891 // assume port 5555 if no port is specified
892 if (!strchr(serial, ':')) {
893 snprintf(hostbuf, sizeof(hostbuf) - 1, "%s:5555", serial);
894 serial = hostbuf;
895 }
896 atransport *t = find_transport(serial);
897
898 if (t) {
899 unregister_transport(t);
900 } else {
901 snprintf(buffer, sizeof(buffer), "No such device %s", serial);
902 }
Mike Lockwood74d7ff82009-10-11 23:04:18 -0400903 }
904
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100905 send_msg_with_okay(reply_fd, buffer, strlen(buffer));
Mike Lockwood2f38b692009-08-24 15:58:40 -0700906 return 0;
907 }
908
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800909 // returns our value for ADB_SERVER_VERSION
910 if (!strcmp(service, "version")) {
911 char version[12];
912 snprintf(version, sizeof version, "%04x", ADB_SERVER_VERSION);
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100913 send_msg_with_okay(reply_fd, version, strlen(version));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800914 return 0;
915 }
916
917 if(!strncmp(service,"get-serialno",strlen("get-serialno"))) {
Dan Albertbac34742015-02-25 17:51:28 -0800918 const char *out = "unknown";
919 transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800920 if (transport && transport->serial) {
921 out = transport->serial;
922 }
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100923 send_msg_with_okay(reply_fd, out, strlen(out));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800924 return 0;
925 }
Scott Andersone109d262012-04-20 11:21:14 -0700926 if(!strncmp(service,"get-devpath",strlen("get-devpath"))) {
Dan Albertbac34742015-02-25 17:51:28 -0800927 const char *out = "unknown";
928 transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
Scott Andersone109d262012-04-20 11:21:14 -0700929 if (transport && transport->devpath) {
930 out = transport->devpath;
931 }
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100932 send_msg_with_okay(reply_fd, out, strlen(out));
Scott Andersone109d262012-04-20 11:21:14 -0700933 return 0;
934 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800935 // indicates a new emulator instance has started
936 if (!strncmp(service,"emulator:",9)) {
937 int port = atoi(service+9);
938 local_connect(port);
939 /* we don't even need to send a reply */
940 return 0;
941 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800942
943 if(!strncmp(service,"get-state",strlen("get-state"))) {
944 transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
Dan Albertbac34742015-02-25 17:51:28 -0800945 const char *state = connection_state_name(transport);
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100946 send_msg_with_okay(reply_fd, state, strlen(state));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800947 return 0;
948 }
Simon Yedc22c3c2014-07-14 17:23:06 -0700949#endif // ADB_HOST
950
951 int ret = handle_forward_request(service, ttype, serial, reply_fd);
952 if (ret >= 0)
953 return ret - 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800954 return -1;
955}