blob: f15902b2db146e1b8fcc4663ccf8c7971baa6dd5 [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 Alberte9fca142015-02-18 18:03:26 -080033#include "adb_listeners.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080034
Scott Andersone82c2db2012-05-25 14:10:02 -070035#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
36
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080037#if !ADB_HOST
Nick Kralevich893a4a42013-05-23 09:54:13 -070038#include <cutils/properties.h>
Nick Kraleviche2864bf2013-02-28 14:12:58 -080039#include <sys/capability.h>
Jeff Sharkey885342a2012-08-14 21:00:22 -070040#include <sys/mount.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080041#endif
42
JP Abgrall408fa572011-03-16 15:57:42 -070043#if ADB_TRACE
44ADB_MUTEX_DEFINE( D_lock );
45#endif
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080046
47int HOST = 0;
48
Scott Andersone82c2db2012-05-25 14:10:02 -070049#if !ADB_HOST
Dan Albertbd0b7502015-02-18 18:22:45 -080050const char *adb_device_banner = "device";
Scott Andersone82c2db2012-05-25 14:10:02 -070051#endif
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080052
53void fatal(const char *fmt, ...)
54{
55 va_list ap;
56 va_start(ap, fmt);
57 fprintf(stderr, "error: ");
58 vfprintf(stderr, fmt, ap);
59 fprintf(stderr, "\n");
60 va_end(ap);
61 exit(-1);
62}
63
64void fatal_errno(const char *fmt, ...)
65{
66 va_list ap;
67 va_start(ap, fmt);
68 fprintf(stderr, "error: %s: ", strerror(errno));
69 vfprintf(stderr, fmt, ap);
70 fprintf(stderr, "\n");
71 va_end(ap);
72 exit(-1);
73}
74
75int adb_trace_mask;
76
77/* read a comma/space/colum/semi-column separated list of tags
78 * from the ADB_TRACE environment variable and build the trace
79 * mask from it. note that '1' and 'all' are special cases to
80 * enable all tracing
81 */
82void adb_trace_init(void)
83{
84 const char* p = getenv("ADB_TRACE");
85 const char* q;
86
87 static const struct {
88 const char* tag;
89 int flag;
90 } tags[] = {
91 { "1", 0 },
92 { "all", 0 },
93 { "adb", TRACE_ADB },
94 { "sockets", TRACE_SOCKETS },
95 { "packets", TRACE_PACKETS },
96 { "rwx", TRACE_RWX },
97 { "usb", TRACE_USB },
98 { "sync", TRACE_SYNC },
99 { "sysdeps", TRACE_SYSDEPS },
100 { "transport", TRACE_TRANSPORT },
101 { "jdwp", TRACE_JDWP },
JP Abgrall408fa572011-03-16 15:57:42 -0700102 { "services", TRACE_SERVICES },
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700103 { "auth", TRACE_AUTH },
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800104 { NULL, 0 }
105 };
106
107 if (p == NULL)
108 return;
109
110 /* use a comma/column/semi-colum/space separated list */
111 while (*p) {
112 int len, tagn;
113
114 q = strpbrk(p, " ,:;");
115 if (q == NULL) {
116 q = p + strlen(p);
117 }
118 len = q - p;
119
120 for (tagn = 0; tags[tagn].tag != NULL; tagn++)
121 {
122 int taglen = strlen(tags[tagn].tag);
123
124 if (len == taglen && !memcmp(tags[tagn].tag, p, len) )
125 {
126 int flag = tags[tagn].flag;
127 if (flag == 0) {
128 adb_trace_mask = ~0;
129 return;
130 }
131 adb_trace_mask |= (1 << flag);
132 break;
133 }
134 }
135 p = q;
136 if (*p)
137 p++;
138 }
139}
140
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800141apacket *get_apacket(void)
142{
143 apacket *p = malloc(sizeof(apacket));
144 if(p == 0) fatal("failed to allocate an apacket");
145 memset(p, 0, sizeof(apacket) - MAX_PAYLOAD);
146 return p;
147}
148
149void put_apacket(apacket *p)
150{
151 free(p);
152}
153
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700154void handle_online(atransport *t)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800155{
156 D("adb: online\n");
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700157 t->online = 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800158}
159
160void handle_offline(atransport *t)
161{
162 D("adb: offline\n");
163 //Close the associated usb
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700164 t->online = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800165 run_transport_disconnects(t);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800166}
167
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700168#if DEBUG_PACKETS
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800169#define DUMPMAX 32
170void print_packet(const char *label, apacket *p)
171{
172 char *tag;
173 char *x;
174 unsigned count;
175
176 switch(p->msg.command){
177 case A_SYNC: tag = "SYNC"; break;
178 case A_CNXN: tag = "CNXN" ; break;
179 case A_OPEN: tag = "OPEN"; break;
180 case A_OKAY: tag = "OKAY"; break;
181 case A_CLSE: tag = "CLSE"; break;
182 case A_WRTE: tag = "WRTE"; break;
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700183 case A_AUTH: tag = "AUTH"; break;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800184 default: tag = "????"; break;
185 }
186
187 fprintf(stderr, "%s: %s %08x %08x %04x \"",
188 label, tag, p->msg.arg0, p->msg.arg1, p->msg.data_length);
189 count = p->msg.data_length;
190 x = (char*) p->data;
191 if(count > DUMPMAX) {
192 count = DUMPMAX;
193 tag = "\n";
194 } else {
195 tag = "\"\n";
196 }
197 while(count-- > 0){
198 if((*x >= ' ') && (*x < 127)) {
199 fputc(*x, stderr);
200 } else {
201 fputc('.', stderr);
202 }
203 x++;
204 }
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700205 fputs(tag, stderr);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800206}
207#endif
208
209static void send_ready(unsigned local, unsigned remote, atransport *t)
210{
211 D("Calling send_ready \n");
212 apacket *p = get_apacket();
213 p->msg.command = A_OKAY;
214 p->msg.arg0 = local;
215 p->msg.arg1 = remote;
216 send_packet(p, t);
217}
218
219static void send_close(unsigned local, unsigned remote, atransport *t)
220{
221 D("Calling send_close \n");
222 apacket *p = get_apacket();
223 p->msg.command = A_CLSE;
224 p->msg.arg0 = local;
225 p->msg.arg1 = remote;
226 send_packet(p, t);
227}
228
Scott Andersone82c2db2012-05-25 14:10:02 -0700229static size_t fill_connect_data(char *buf, size_t bufsize)
230{
231#if ADB_HOST
232 return snprintf(buf, bufsize, "host::") + 1;
233#else
234 static const char *cnxn_props[] = {
235 "ro.product.name",
236 "ro.product.model",
237 "ro.product.device",
238 };
239 static const int num_cnxn_props = ARRAY_SIZE(cnxn_props);
240 int i;
241 size_t remaining = bufsize;
242 size_t len;
243
244 len = snprintf(buf, remaining, "%s::", adb_device_banner);
245 remaining -= len;
246 buf += len;
247 for (i = 0; i < num_cnxn_props; i++) {
248 char value[PROPERTY_VALUE_MAX];
249 property_get(cnxn_props[i], value, "");
250 len = snprintf(buf, remaining, "%s=%s;", cnxn_props[i], value);
251 remaining -= len;
252 buf += len;
253 }
254
255 return bufsize - remaining + 1;
256#endif
257}
258
David 'Digit' Turner25258692013-03-21 21:07:42 +0100259#if !ADB_HOST
260static void send_msg_with_header(int fd, const char* msg, size_t msglen) {
261 char header[5];
262 if (msglen > 0xffff)
263 msglen = 0xffff;
264 snprintf(header, sizeof(header), "%04x", (unsigned)msglen);
265 writex(fd, header, 4);
266 writex(fd, msg, msglen);
267}
268#endif
269
Chih-Hung Hsiehf787b382014-09-05 15:38:15 -0700270#if ADB_HOST
David 'Digit' Turner25258692013-03-21 21:07:42 +0100271static void send_msg_with_okay(int fd, const char* msg, size_t msglen) {
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100272 char header[9];
273 if (msglen > 0xffff)
274 msglen = 0xffff;
275 snprintf(header, sizeof(header), "OKAY%04x", (unsigned)msglen);
276 writex(fd, header, 8);
277 writex(fd, msg, msglen);
278}
Chih-Hung Hsiehf787b382014-09-05 15:38:15 -0700279#endif // ADB_HOST
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100280
Dan Albertba3a2512015-02-18 17:47:33 -0800281void send_connect(atransport *t)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800282{
283 D("Calling send_connect \n");
284 apacket *cp = get_apacket();
285 cp->msg.command = A_CNXN;
286 cp->msg.arg0 = A_VERSION;
287 cp->msg.arg1 = MAX_PAYLOAD;
Scott Andersone82c2db2012-05-25 14:10:02 -0700288 cp->msg.data_length = fill_connect_data((char *)cp->data,
289 sizeof(cp->data));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800290 send_packet(cp, t);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700291}
292
Chih-Hung Hsiehf787b382014-09-05 15:38:15 -0700293#if ADB_HOST
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800294static char *connection_state_name(atransport *t)
295{
296 if (t == NULL) {
297 return "unknown";
298 }
299
300 switch(t->connection_state) {
301 case CS_BOOTLOADER:
302 return "bootloader";
303 case CS_DEVICE:
304 return "device";
trevda5ad5392013-04-17 14:34:23 +0100305 case CS_RECOVERY:
306 return "recovery";
307 case CS_SIDELOAD:
308 return "sideload";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800309 case CS_OFFLINE:
310 return "offline";
Benoit Goby77e8e582013-01-15 12:36:47 -0800311 case CS_UNAUTHORIZED:
312 return "unauthorized";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800313 default:
314 return "unknown";
315 }
316}
Chih-Hung Hsiehf787b382014-09-05 15:38:15 -0700317#endif // ADB_HOST
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800318
Scott Andersone82c2db2012-05-25 14:10:02 -0700319/* qual_overwrite is used to overwrite a qualifier string. dst is a
320 * pointer to a char pointer. It is assumed that if *dst is non-NULL, it
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700321 * was malloc'ed and needs to freed. *dst will be set to a dup of src.
Scott Andersone82c2db2012-05-25 14:10:02 -0700322 */
323static void qual_overwrite(char **dst, const char *src)
324{
325 if (!dst)
326 return;
327
328 free(*dst);
329 *dst = NULL;
330
331 if (!src || !*src)
332 return;
333
334 *dst = strdup(src);
335}
336
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800337void parse_banner(char *banner, atransport *t)
338{
Scott Andersone82c2db2012-05-25 14:10:02 -0700339 static const char *prop_seps = ";";
340 static const char key_val_sep = '=';
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700341 char *cp;
342 char *type;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800343
344 D("parse_banner: %s\n", banner);
345 type = banner;
Scott Andersone82c2db2012-05-25 14:10:02 -0700346 cp = strchr(type, ':');
347 if (cp) {
348 *cp++ = 0;
349 /* Nothing is done with second field. */
350 cp = strchr(cp, ':');
351 if (cp) {
352 char *save;
353 char *key;
Scott Anderson1b7a7e82012-06-05 17:54:27 -0700354 key = adb_strtok_r(cp + 1, prop_seps, &save);
Scott Andersone82c2db2012-05-25 14:10:02 -0700355 while (key) {
356 cp = strchr(key, key_val_sep);
357 if (cp) {
358 *cp++ = '\0';
359 if (!strcmp(key, "ro.product.name"))
360 qual_overwrite(&t->product, cp);
361 else if (!strcmp(key, "ro.product.model"))
362 qual_overwrite(&t->model, cp);
363 else if (!strcmp(key, "ro.product.device"))
364 qual_overwrite(&t->device, cp);
365 }
Scott Anderson1b7a7e82012-06-05 17:54:27 -0700366 key = adb_strtok_r(NULL, prop_seps, &save);
Scott Andersone82c2db2012-05-25 14:10:02 -0700367 }
368 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800369 }
370
371 if(!strcmp(type, "bootloader")){
372 D("setting connection_state to CS_BOOTLOADER\n");
373 t->connection_state = CS_BOOTLOADER;
374 update_transports();
375 return;
376 }
377
378 if(!strcmp(type, "device")) {
379 D("setting connection_state to CS_DEVICE\n");
380 t->connection_state = CS_DEVICE;
381 update_transports();
382 return;
383 }
384
385 if(!strcmp(type, "recovery")) {
386 D("setting connection_state to CS_RECOVERY\n");
387 t->connection_state = CS_RECOVERY;
388 update_transports();
389 return;
390 }
391
Doug Zongker447f0612012-01-09 14:54:53 -0800392 if(!strcmp(type, "sideload")) {
393 D("setting connection_state to CS_SIDELOAD\n");
394 t->connection_state = CS_SIDELOAD;
395 update_transports();
396 return;
397 }
398
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800399 t->connection_state = CS_HOST;
400}
401
402void handle_packet(apacket *p, atransport *t)
403{
404 asocket *s;
405
Viral Mehta899913f2010-06-16 18:41:28 +0530406 D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0],
407 ((char*) (&(p->msg.command)))[1],
408 ((char*) (&(p->msg.command)))[2],
409 ((char*) (&(p->msg.command)))[3]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800410 print_packet("recv", p);
411
412 switch(p->msg.command){
413 case A_SYNC:
414 if(p->msg.arg0){
415 send_packet(p, t);
416 if(HOST) send_connect(t);
417 } else {
418 t->connection_state = CS_OFFLINE;
419 handle_offline(t);
420 send_packet(p, t);
421 }
422 return;
423
424 case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */
425 /* XXX verify version, etc */
426 if(t->connection_state != CS_OFFLINE) {
427 t->connection_state = CS_OFFLINE;
428 handle_offline(t);
429 }
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700430
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800431 parse_banner((char*) p->data, t);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700432
433 if (HOST || !auth_enabled) {
434 handle_online(t);
435 if(!HOST) send_connect(t);
436 } else {
437 send_auth_request(t);
438 }
439 break;
440
441 case A_AUTH:
442 if (p->msg.arg0 == ADB_AUTH_TOKEN) {
Benoit Goby77e8e582013-01-15 12:36:47 -0800443 t->connection_state = CS_UNAUTHORIZED;
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700444 t->key = adb_auth_nextkey(t->key);
445 if (t->key) {
446 send_auth_response(p->data, p->msg.data_length, t);
447 } else {
448 /* No more private keys to try, send the public key */
449 send_auth_publickey(t);
450 }
451 } else if (p->msg.arg0 == ADB_AUTH_SIGNATURE) {
452 if (adb_auth_verify(t->token, p->data, p->msg.data_length)) {
453 adb_auth_verified(t);
454 t->failed_auth_attempts = 0;
455 } else {
456 if (t->failed_auth_attempts++ > 10)
457 adb_sleep_ms(1000);
458 send_auth_request(t);
459 }
460 } else if (p->msg.arg0 == ADB_AUTH_RSAPUBLICKEY) {
461 adb_auth_confirm_key(p->data, p->msg.data_length, t);
462 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800463 break;
464
465 case A_OPEN: /* OPEN(local-id, 0, "destination") */
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100466 if (t->online && p->msg.arg0 != 0 && p->msg.arg1 == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800467 char *name = (char*) p->data;
468 name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0;
469 s = create_local_service_socket(name);
470 if(s == 0) {
471 send_close(0, p->msg.arg0, t);
472 } else {
473 s->peer = create_remote_socket(p->msg.arg0, t);
474 s->peer->peer = s;
475 send_ready(s->id, s->peer->id, t);
476 s->ready(s);
477 }
478 }
479 break;
480
481 case A_OKAY: /* READY(local-id, remote-id, "") */
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100482 if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) {
483 if((s = find_local_socket(p->msg.arg1, 0))) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800484 if(s->peer == 0) {
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100485 /* On first READY message, create the connection. */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800486 s->peer = create_remote_socket(p->msg.arg0, t);
487 s->peer->peer = s;
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100488 s->ready(s);
489 } else if (s->peer->id == p->msg.arg0) {
490 /* Other READY messages must use the same local-id */
491 s->ready(s);
492 } else {
493 D("Invalid A_OKAY(%d,%d), expected A_OKAY(%d,%d) on transport %s\n",
494 p->msg.arg0, p->msg.arg1, s->peer->id, p->msg.arg1, t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800495 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800496 }
497 }
498 break;
499
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100500 case A_CLSE: /* CLOSE(local-id, remote-id, "") or CLOSE(0, remote-id, "") */
501 if (t->online && p->msg.arg1 != 0) {
502 if((s = find_local_socket(p->msg.arg1, p->msg.arg0))) {
503 /* According to protocol.txt, p->msg.arg0 might be 0 to indicate
504 * a failed OPEN only. However, due to a bug in previous ADB
505 * versions, CLOSE(0, remote-id, "") was also used for normal
506 * CLOSE() operations.
507 *
508 * This is bad because it means a compromised adbd could
509 * send packets to close connections between the host and
510 * other devices. To avoid this, only allow this if the local
511 * socket has a peer on the same transport.
512 */
513 if (p->msg.arg0 == 0 && s->peer && s->peer->transport != t) {
514 D("Invalid A_CLSE(0, %u) from transport %s, expected transport %s\n",
515 p->msg.arg1, t->serial, s->peer->transport->serial);
516 } else {
517 s->close(s);
518 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800519 }
520 }
521 break;
522
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100523 case A_WRTE: /* WRITE(local-id, remote-id, <data>) */
524 if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) {
525 if((s = find_local_socket(p->msg.arg1, p->msg.arg0))) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800526 unsigned rid = p->msg.arg0;
527 p->len = p->msg.data_length;
528
529 if(s->enqueue(s, p) == 0) {
530 D("Enqueue the socket\n");
531 send_ready(s->id, rid, t);
532 }
533 return;
534 }
535 }
536 break;
537
538 default:
539 printf("handle_packet: what is %08x?!\n", p->msg.command);
540 }
541
542 put_apacket(p);
543}
544
Yabin Cuie77b6a02014-11-11 09:24:11 -0800545#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800546static BOOL WINAPI ctrlc_handler(DWORD type)
547{
548 exit(STATUS_CONTROL_C_EXIT);
549 return TRUE;
550}
551#endif
552
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800553#if ADB_HOST
JP Abgrall571c1362012-12-06 18:18:12 -0800554
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100555int launch_server(int server_port)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800556{
Yabin Cuie77b6a02014-11-11 09:24:11 -0800557#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800558 /* we need to start the server in the background */
559 /* we create a PIPE that will be used to wait for the server's "OK" */
560 /* message since the pipe handles must be inheritable, we use a */
561 /* security attribute */
562 HANDLE pipe_read, pipe_write;
Ray Donnelly267aa8b2012-11-29 01:18:50 +0000563 HANDLE stdout_handle, stderr_handle;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800564 SECURITY_ATTRIBUTES sa;
565 STARTUPINFO startup;
566 PROCESS_INFORMATION pinfo;
567 char program_path[ MAX_PATH ];
568 int ret;
569
570 sa.nLength = sizeof(sa);
571 sa.lpSecurityDescriptor = NULL;
572 sa.bInheritHandle = TRUE;
573
574 /* create pipe, and ensure its read handle isn't inheritable */
575 ret = CreatePipe( &pipe_read, &pipe_write, &sa, 0 );
576 if (!ret) {
577 fprintf(stderr, "CreatePipe() failure, error %ld\n", GetLastError() );
578 return -1;
579 }
580
581 SetHandleInformation( pipe_read, HANDLE_FLAG_INHERIT, 0 );
582
Ray Donnelly267aa8b2012-11-29 01:18:50 +0000583 /* Some programs want to launch an adb command and collect its output by
584 * calling CreateProcess with inheritable stdout/stderr handles, then
585 * using read() to get its output. When this happens, the stdout/stderr
586 * handles passed to the adb client process will also be inheritable.
587 * When starting the adb server here, care must be taken to reset them
588 * to non-inheritable.
589 * Otherwise, something bad happens: even if the adb command completes,
590 * the calling process is stuck while read()-ing from the stdout/stderr
591 * descriptors, because they're connected to corresponding handles in the
592 * adb server process (even if the latter never uses/writes to them).
593 */
594 stdout_handle = GetStdHandle( STD_OUTPUT_HANDLE );
595 stderr_handle = GetStdHandle( STD_ERROR_HANDLE );
596 if (stdout_handle != INVALID_HANDLE_VALUE) {
597 SetHandleInformation( stdout_handle, HANDLE_FLAG_INHERIT, 0 );
598 }
599 if (stderr_handle != INVALID_HANDLE_VALUE) {
600 SetHandleInformation( stderr_handle, HANDLE_FLAG_INHERIT, 0 );
601 }
602
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800603 ZeroMemory( &startup, sizeof(startup) );
604 startup.cb = sizeof(startup);
605 startup.hStdInput = GetStdHandle( STD_INPUT_HANDLE );
606 startup.hStdOutput = pipe_write;
607 startup.hStdError = GetStdHandle( STD_ERROR_HANDLE );
608 startup.dwFlags = STARTF_USESTDHANDLES;
609
610 ZeroMemory( &pinfo, sizeof(pinfo) );
611
612 /* get path of current program */
613 GetModuleFileName( NULL, program_path, sizeof(program_path) );
Wenhao Lia09558c2013-11-13 16:23:37 +0800614 char args[64];
615 snprintf(args, sizeof(args), "adb -P %d fork-server server", server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800616 ret = CreateProcess(
617 program_path, /* program path */
Wenhao Lia09558c2013-11-13 16:23:37 +0800618 args,
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800619 /* the fork-server argument will set the
620 debug = 2 in the child */
621 NULL, /* process handle is not inheritable */
622 NULL, /* thread handle is not inheritable */
623 TRUE, /* yes, inherit some handles */
624 DETACHED_PROCESS, /* the new process doesn't have a console */
625 NULL, /* use parent's environment block */
626 NULL, /* use parent's starting directory */
627 &startup, /* startup info, i.e. std handles */
628 &pinfo );
629
630 CloseHandle( pipe_write );
631
632 if (!ret) {
633 fprintf(stderr, "CreateProcess failure, error %ld\n", GetLastError() );
634 CloseHandle( pipe_read );
635 return -1;
636 }
637
638 CloseHandle( pinfo.hProcess );
639 CloseHandle( pinfo.hThread );
640
641 /* wait for the "OK\n" message */
642 {
643 char temp[3];
644 DWORD count;
645
646 ret = ReadFile( pipe_read, temp, 3, &count, NULL );
647 CloseHandle( pipe_read );
648 if ( !ret ) {
649 fprintf(stderr, "could not read ok from ADB Server, error = %ld\n", GetLastError() );
650 return -1;
651 }
652 if (count != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') {
653 fprintf(stderr, "ADB server didn't ACK\n" );
654 return -1;
655 }
656 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800657#else /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800658 char path[PATH_MAX];
659 int fd[2];
660
661 // set up a pipe so the child can tell us when it is ready.
662 // fd[0] will be parent's end, and fd[1] will get mapped to stderr in the child.
663 if (pipe(fd)) {
664 fprintf(stderr, "pipe failed in launch_server, errno: %d\n", errno);
665 return -1;
666 }
Alexey Tarasov31664102009-10-22 02:55:00 +1100667 get_my_path(path, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800668 pid_t pid = fork();
669 if(pid < 0) return -1;
670
671 if (pid == 0) {
672 // child side of the fork
673
674 // redirect stderr to the pipe
675 // we use stderr instead of stdout due to stdout's buffering behavior.
676 adb_close(fd[0]);
677 dup2(fd[1], STDERR_FILENO);
678 adb_close(fd[1]);
679
Matt Gumbeld7b33082012-11-14 10:16:17 -0800680 char str_port[30];
681 snprintf(str_port, sizeof(str_port), "%d", server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800682 // child process
Matt Gumbeld7b33082012-11-14 10:16:17 -0800683 int result = execl(path, "adb", "-P", str_port, "fork-server", "server", NULL);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800684 // this should not return
685 fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno);
686 } else {
687 // parent side of the fork
688
689 char temp[3];
690
691 temp[0] = 'A'; temp[1] = 'B'; temp[2] = 'C';
692 // wait for the "OK\n" message
693 adb_close(fd[1]);
694 int ret = adb_read(fd[0], temp, 3);
JP Abgrall408fa572011-03-16 15:57:42 -0700695 int saved_errno = errno;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800696 adb_close(fd[0]);
697 if (ret < 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700698 fprintf(stderr, "could not read ok from ADB Server, errno = %d\n", saved_errno);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800699 return -1;
700 }
701 if (ret != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') {
702 fprintf(stderr, "ADB server didn't ACK\n" );
703 return -1;
704 }
705
706 setsid();
707 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800708#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800709 return 0;
710}
Yabin Cuie77b6a02014-11-11 09:24:11 -0800711#endif /* ADB_HOST */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800712
David 'Digit' Turner25258692013-03-21 21:07:42 +0100713// Try to handle a network forwarding request.
714// This returns 1 on success, 0 on failure, and -1 to indicate this is not
715// a forwarding-related request.
716int handle_forward_request(const char* service, transport_type ttype, char* serial, int reply_fd)
717{
718 if (!strcmp(service, "list-forward")) {
719 // Create the list of forward redirections.
720 int buffer_size = format_listeners(NULL, 0);
721 // Add one byte for the trailing zero.
722 char* buffer = malloc(buffer_size + 1);
723 if (buffer == NULL) {
724 sendfailmsg(reply_fd, "not enough memory");
725 return 1;
726 }
727 (void) format_listeners(buffer, buffer_size + 1);
728#if ADB_HOST
729 send_msg_with_okay(reply_fd, buffer, buffer_size);
730#else
731 send_msg_with_header(reply_fd, buffer, buffer_size);
732#endif
733 free(buffer);
734 return 1;
735 }
736
737 if (!strcmp(service, "killforward-all")) {
738 remove_all_listeners();
739#if ADB_HOST
740 /* On the host: 1st OKAY is connect, 2nd OKAY is status */
741 adb_write(reply_fd, "OKAY", 4);
742#endif
743 adb_write(reply_fd, "OKAY", 4);
744 return 1;
745 }
746
747 if (!strncmp(service, "forward:",8) ||
748 !strncmp(service, "killforward:",12)) {
749 char *local, *remote, *err;
750 int r;
751 atransport *transport;
752
753 int createForward = strncmp(service, "kill", 4);
754 int no_rebind = 0;
755
756 local = strchr(service, ':') + 1;
757
758 // Handle forward:norebind:<local>... here
759 if (createForward && !strncmp(local, "norebind:", 9)) {
760 no_rebind = 1;
761 local = strchr(local, ':') + 1;
762 }
763
764 remote = strchr(local,';');
765
766 if (createForward) {
767 // Check forward: parameter format: '<local>;<remote>'
768 if(remote == 0) {
769 sendfailmsg(reply_fd, "malformed forward spec");
770 return 1;
771 }
772
773 *remote++ = 0;
774 if((local[0] == 0) || (remote[0] == 0) || (remote[0] == '*')) {
775 sendfailmsg(reply_fd, "malformed forward spec");
776 return 1;
777 }
778 } else {
779 // Check killforward: parameter format: '<local>'
780 if (local[0] == 0) {
781 sendfailmsg(reply_fd, "malformed forward spec");
782 return 1;
783 }
784 }
785
786 transport = acquire_one_transport(CS_ANY, ttype, serial, &err);
787 if (!transport) {
788 sendfailmsg(reply_fd, err);
789 return 1;
790 }
791
792 if (createForward) {
793 r = install_listener(local, remote, transport, no_rebind);
794 } else {
795 r = remove_listener(local, transport);
796 }
797 if(r == 0) {
798#if ADB_HOST
799 /* On the host: 1st OKAY is connect, 2nd OKAY is status */
800 writex(reply_fd, "OKAY", 4);
801#endif
802 writex(reply_fd, "OKAY", 4);
803 return 1;
804 }
805
806 if (createForward) {
807 const char* message;
808 switch (r) {
809 case INSTALL_STATUS_CANNOT_BIND:
810 message = "cannot bind to socket";
811 break;
812 case INSTALL_STATUS_CANNOT_REBIND:
813 message = "cannot rebind existing socket";
814 break;
815 default:
816 message = "internal error";
817 }
818 sendfailmsg(reply_fd, message);
819 } else {
820 sendfailmsg(reply_fd, "cannot remove listener");
821 }
822 return 1;
823 }
824 return 0;
825}
826
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800827int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s)
828{
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800829 if(!strcmp(service, "kill")) {
830 fprintf(stderr,"adb server killed by remote request\n");
831 fflush(stdout);
832 adb_write(reply_fd, "OKAY", 4);
833 usb_cleanup();
834 exit(0);
835 }
836
837#if ADB_HOST
Chih-Hung Hsiehf787b382014-09-05 15:38:15 -0700838 atransport *transport = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800839 // "transport:" is used for switching transport with a specified serial number
840 // "transport-usb:" is used for switching transport to the only USB transport
841 // "transport-local:" is used for switching transport to the only local transport
842 // "transport-any:" is used for switching transport to the only transport
843 if (!strncmp(service, "transport", strlen("transport"))) {
844 char* error_string = "unknown failure";
845 transport_type type = kTransportAny;
846
847 if (!strncmp(service, "transport-usb", strlen("transport-usb"))) {
848 type = kTransportUsb;
849 } else if (!strncmp(service, "transport-local", strlen("transport-local"))) {
850 type = kTransportLocal;
851 } else if (!strncmp(service, "transport-any", strlen("transport-any"))) {
852 type = kTransportAny;
853 } else if (!strncmp(service, "transport:", strlen("transport:"))) {
854 service += strlen("transport:");
Tom Marlin3175c8e2011-07-27 12:56:14 -0500855 serial = service;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800856 }
857
858 transport = acquire_one_transport(CS_ANY, type, serial, &error_string);
859
860 if (transport) {
861 s->transport = transport;
862 adb_write(reply_fd, "OKAY", 4);
863 } else {
864 sendfailmsg(reply_fd, error_string);
865 }
866 return 1;
867 }
868
869 // return a list of all connected devices
Scott Andersone109d262012-04-20 11:21:14 -0700870 if (!strncmp(service, "devices", 7)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800871 char buffer[4096];
Scott Andersone109d262012-04-20 11:21:14 -0700872 int use_long = !strcmp(service+7, "-l");
873 if (use_long || service[7] == 0) {
Scott Andersone109d262012-04-20 11:21:14 -0700874 memset(buffer, 0, sizeof(buffer));
875 D("Getting device list \n");
876 list_transports(buffer, sizeof(buffer), use_long);
Scott Andersone109d262012-04-20 11:21:14 -0700877 D("Wrote device list \n");
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100878 send_msg_with_okay(reply_fd, buffer, strlen(buffer));
Scott Andersone109d262012-04-20 11:21:14 -0700879 return 0;
880 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800881 }
882
Mike Lockwood74d7ff82009-10-11 23:04:18 -0400883 // remove TCP transport
884 if (!strncmp(service, "disconnect:", 11)) {
885 char buffer[4096];
886 memset(buffer, 0, sizeof(buffer));
887 char* serial = service + 11;
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400888 if (serial[0] == 0) {
889 // disconnect from all TCP devices
890 unregister_all_tcp_transports();
Mike Lockwood74d7ff82009-10-11 23:04:18 -0400891 } else {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400892 char hostbuf[100];
893 // assume port 5555 if no port is specified
894 if (!strchr(serial, ':')) {
895 snprintf(hostbuf, sizeof(hostbuf) - 1, "%s:5555", serial);
896 serial = hostbuf;
897 }
898 atransport *t = find_transport(serial);
899
900 if (t) {
901 unregister_transport(t);
902 } else {
903 snprintf(buffer, sizeof(buffer), "No such device %s", serial);
904 }
Mike Lockwood74d7ff82009-10-11 23:04:18 -0400905 }
906
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100907 send_msg_with_okay(reply_fd, buffer, strlen(buffer));
Mike Lockwood2f38b692009-08-24 15:58:40 -0700908 return 0;
909 }
910
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800911 // returns our value for ADB_SERVER_VERSION
912 if (!strcmp(service, "version")) {
913 char version[12];
914 snprintf(version, sizeof version, "%04x", ADB_SERVER_VERSION);
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100915 send_msg_with_okay(reply_fd, version, strlen(version));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800916 return 0;
917 }
918
919 if(!strncmp(service,"get-serialno",strlen("get-serialno"))) {
920 char *out = "unknown";
921 transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
922 if (transport && transport->serial) {
923 out = transport->serial;
924 }
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100925 send_msg_with_okay(reply_fd, out, strlen(out));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800926 return 0;
927 }
Scott Andersone109d262012-04-20 11:21:14 -0700928 if(!strncmp(service,"get-devpath",strlen("get-devpath"))) {
929 char *out = "unknown";
930 transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
931 if (transport && transport->devpath) {
932 out = transport->devpath;
933 }
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100934 send_msg_with_okay(reply_fd, out, strlen(out));
Scott Andersone109d262012-04-20 11:21:14 -0700935 return 0;
936 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800937 // indicates a new emulator instance has started
938 if (!strncmp(service,"emulator:",9)) {
939 int port = atoi(service+9);
940 local_connect(port);
941 /* we don't even need to send a reply */
942 return 0;
943 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800944
945 if(!strncmp(service,"get-state",strlen("get-state"))) {
946 transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
947 char *state = connection_state_name(transport);
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100948 send_msg_with_okay(reply_fd, state, strlen(state));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800949 return 0;
950 }
Simon Yedc22c3c2014-07-14 17:23:06 -0700951#endif // ADB_HOST
952
953 int ret = handle_forward_request(service, ttype, serial, reply_fd);
954 if (ret >= 0)
955 return ret - 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800956 return -1;
957}