blob: 5f244a583a43f52d2165e793d20a52cac1784cf1 [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
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800143apacket *get_apacket(void)
144{
145 apacket *p = malloc(sizeof(apacket));
146 if(p == 0) fatal("failed to allocate an apacket");
147 memset(p, 0, sizeof(apacket) - MAX_PAYLOAD);
148 return p;
149}
150
151void put_apacket(apacket *p)
152{
153 free(p);
154}
155
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700156void handle_online(atransport *t)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800157{
158 D("adb: online\n");
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700159 t->online = 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800160}
161
162void handle_offline(atransport *t)
163{
164 D("adb: offline\n");
165 //Close the associated usb
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700166 t->online = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800167 run_transport_disconnects(t);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800168}
169
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700170#if DEBUG_PACKETS
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800171#define DUMPMAX 32
172void print_packet(const char *label, apacket *p)
173{
174 char *tag;
175 char *x;
176 unsigned count;
177
178 switch(p->msg.command){
179 case A_SYNC: tag = "SYNC"; break;
180 case A_CNXN: tag = "CNXN" ; break;
181 case A_OPEN: tag = "OPEN"; break;
182 case A_OKAY: tag = "OKAY"; break;
183 case A_CLSE: tag = "CLSE"; break;
184 case A_WRTE: tag = "WRTE"; break;
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700185 case A_AUTH: tag = "AUTH"; break;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800186 default: tag = "????"; break;
187 }
188
189 fprintf(stderr, "%s: %s %08x %08x %04x \"",
190 label, tag, p->msg.arg0, p->msg.arg1, p->msg.data_length);
191 count = p->msg.data_length;
192 x = (char*) p->data;
193 if(count > DUMPMAX) {
194 count = DUMPMAX;
195 tag = "\n";
196 } else {
197 tag = "\"\n";
198 }
199 while(count-- > 0){
200 if((*x >= ' ') && (*x < 127)) {
201 fputc(*x, stderr);
202 } else {
203 fputc('.', stderr);
204 }
205 x++;
206 }
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700207 fputs(tag, stderr);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800208}
209#endif
210
211static void send_ready(unsigned local, unsigned remote, atransport *t)
212{
213 D("Calling send_ready \n");
214 apacket *p = get_apacket();
215 p->msg.command = A_OKAY;
216 p->msg.arg0 = local;
217 p->msg.arg1 = remote;
218 send_packet(p, t);
219}
220
221static void send_close(unsigned local, unsigned remote, atransport *t)
222{
223 D("Calling send_close \n");
224 apacket *p = get_apacket();
225 p->msg.command = A_CLSE;
226 p->msg.arg0 = local;
227 p->msg.arg1 = remote;
228 send_packet(p, t);
229}
230
Scott Andersone82c2db2012-05-25 14:10:02 -0700231static size_t fill_connect_data(char *buf, size_t bufsize)
232{
233#if ADB_HOST
234 return snprintf(buf, bufsize, "host::") + 1;
235#else
236 static const char *cnxn_props[] = {
237 "ro.product.name",
238 "ro.product.model",
239 "ro.product.device",
240 };
241 static const int num_cnxn_props = ARRAY_SIZE(cnxn_props);
242 int i;
243 size_t remaining = bufsize;
244 size_t len;
245
246 len = snprintf(buf, remaining, "%s::", adb_device_banner);
247 remaining -= len;
248 buf += len;
249 for (i = 0; i < num_cnxn_props; i++) {
250 char value[PROPERTY_VALUE_MAX];
251 property_get(cnxn_props[i], value, "");
252 len = snprintf(buf, remaining, "%s=%s;", cnxn_props[i], value);
253 remaining -= len;
254 buf += len;
255 }
256
257 return bufsize - remaining + 1;
258#endif
259}
260
David 'Digit' Turner25258692013-03-21 21:07:42 +0100261#if !ADB_HOST
262static void send_msg_with_header(int fd, const char* msg, size_t msglen) {
263 char header[5];
264 if (msglen > 0xffff)
265 msglen = 0xffff;
266 snprintf(header, sizeof(header), "%04x", (unsigned)msglen);
Dan Albertcc731cc2015-02-24 21:26:58 -0800267 WriteFdExactly(fd, header, 4);
268 WriteFdExactly(fd, msg, msglen);
David 'Digit' Turner25258692013-03-21 21:07:42 +0100269}
270#endif
271
Chih-Hung Hsiehf787b382014-09-05 15:38:15 -0700272#if ADB_HOST
David 'Digit' Turner25258692013-03-21 21:07:42 +0100273static void send_msg_with_okay(int fd, const char* msg, size_t msglen) {
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100274 char header[9];
275 if (msglen > 0xffff)
276 msglen = 0xffff;
277 snprintf(header, sizeof(header), "OKAY%04x", (unsigned)msglen);
Dan Albertcc731cc2015-02-24 21:26:58 -0800278 WriteFdExactly(fd, header, 8);
279 WriteFdExactly(fd, msg, msglen);
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100280}
Chih-Hung Hsiehf787b382014-09-05 15:38:15 -0700281#endif // ADB_HOST
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100282
Dan Albertba3a2512015-02-18 17:47:33 -0800283void send_connect(atransport *t)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800284{
285 D("Calling send_connect \n");
286 apacket *cp = get_apacket();
287 cp->msg.command = A_CNXN;
288 cp->msg.arg0 = A_VERSION;
289 cp->msg.arg1 = MAX_PAYLOAD;
Scott Andersone82c2db2012-05-25 14:10:02 -0700290 cp->msg.data_length = fill_connect_data((char *)cp->data,
291 sizeof(cp->data));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800292 send_packet(cp, t);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700293}
294
Chih-Hung Hsiehf787b382014-09-05 15:38:15 -0700295#if ADB_HOST
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800296static char *connection_state_name(atransport *t)
297{
298 if (t == NULL) {
299 return "unknown";
300 }
301
302 switch(t->connection_state) {
303 case CS_BOOTLOADER:
304 return "bootloader";
305 case CS_DEVICE:
306 return "device";
trevda5ad5392013-04-17 14:34:23 +0100307 case CS_RECOVERY:
308 return "recovery";
309 case CS_SIDELOAD:
310 return "sideload";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800311 case CS_OFFLINE:
312 return "offline";
Benoit Goby77e8e582013-01-15 12:36:47 -0800313 case CS_UNAUTHORIZED:
314 return "unauthorized";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800315 default:
316 return "unknown";
317 }
318}
Chih-Hung Hsiehf787b382014-09-05 15:38:15 -0700319#endif // ADB_HOST
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800320
Scott Andersone82c2db2012-05-25 14:10:02 -0700321/* qual_overwrite is used to overwrite a qualifier string. dst is a
322 * pointer to a char pointer. It is assumed that if *dst is non-NULL, it
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700323 * was malloc'ed and needs to freed. *dst will be set to a dup of src.
Scott Andersone82c2db2012-05-25 14:10:02 -0700324 */
325static void qual_overwrite(char **dst, const char *src)
326{
327 if (!dst)
328 return;
329
330 free(*dst);
331 *dst = NULL;
332
333 if (!src || !*src)
334 return;
335
336 *dst = strdup(src);
337}
338
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800339void parse_banner(char *banner, atransport *t)
340{
Scott Andersone82c2db2012-05-25 14:10:02 -0700341 static const char *prop_seps = ";";
342 static const char key_val_sep = '=';
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700343 char *cp;
344 char *type;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800345
346 D("parse_banner: %s\n", banner);
347 type = banner;
Scott Andersone82c2db2012-05-25 14:10:02 -0700348 cp = strchr(type, ':');
349 if (cp) {
350 *cp++ = 0;
351 /* Nothing is done with second field. */
352 cp = strchr(cp, ':');
353 if (cp) {
354 char *save;
355 char *key;
Scott Anderson1b7a7e82012-06-05 17:54:27 -0700356 key = adb_strtok_r(cp + 1, prop_seps, &save);
Scott Andersone82c2db2012-05-25 14:10:02 -0700357 while (key) {
358 cp = strchr(key, key_val_sep);
359 if (cp) {
360 *cp++ = '\0';
361 if (!strcmp(key, "ro.product.name"))
362 qual_overwrite(&t->product, cp);
363 else if (!strcmp(key, "ro.product.model"))
364 qual_overwrite(&t->model, cp);
365 else if (!strcmp(key, "ro.product.device"))
366 qual_overwrite(&t->device, cp);
367 }
Scott Anderson1b7a7e82012-06-05 17:54:27 -0700368 key = adb_strtok_r(NULL, prop_seps, &save);
Scott Andersone82c2db2012-05-25 14:10:02 -0700369 }
370 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800371 }
372
373 if(!strcmp(type, "bootloader")){
374 D("setting connection_state to CS_BOOTLOADER\n");
375 t->connection_state = CS_BOOTLOADER;
376 update_transports();
377 return;
378 }
379
380 if(!strcmp(type, "device")) {
381 D("setting connection_state to CS_DEVICE\n");
382 t->connection_state = CS_DEVICE;
383 update_transports();
384 return;
385 }
386
387 if(!strcmp(type, "recovery")) {
388 D("setting connection_state to CS_RECOVERY\n");
389 t->connection_state = CS_RECOVERY;
390 update_transports();
391 return;
392 }
393
Doug Zongker447f0612012-01-09 14:54:53 -0800394 if(!strcmp(type, "sideload")) {
395 D("setting connection_state to CS_SIDELOAD\n");
396 t->connection_state = CS_SIDELOAD;
397 update_transports();
398 return;
399 }
400
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800401 t->connection_state = CS_HOST;
402}
403
404void handle_packet(apacket *p, atransport *t)
405{
406 asocket *s;
407
Viral Mehta899913f2010-06-16 18:41:28 +0530408 D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0],
409 ((char*) (&(p->msg.command)))[1],
410 ((char*) (&(p->msg.command)))[2],
411 ((char*) (&(p->msg.command)))[3]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800412 print_packet("recv", p);
413
414 switch(p->msg.command){
415 case A_SYNC:
416 if(p->msg.arg0){
417 send_packet(p, t);
418 if(HOST) send_connect(t);
419 } else {
420 t->connection_state = CS_OFFLINE;
421 handle_offline(t);
422 send_packet(p, t);
423 }
424 return;
425
426 case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */
427 /* XXX verify version, etc */
428 if(t->connection_state != CS_OFFLINE) {
429 t->connection_state = CS_OFFLINE;
430 handle_offline(t);
431 }
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700432
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800433 parse_banner((char*) p->data, t);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700434
435 if (HOST || !auth_enabled) {
436 handle_online(t);
437 if(!HOST) send_connect(t);
438 } else {
439 send_auth_request(t);
440 }
441 break;
442
443 case A_AUTH:
444 if (p->msg.arg0 == ADB_AUTH_TOKEN) {
Benoit Goby77e8e582013-01-15 12:36:47 -0800445 t->connection_state = CS_UNAUTHORIZED;
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700446 t->key = adb_auth_nextkey(t->key);
447 if (t->key) {
448 send_auth_response(p->data, p->msg.data_length, t);
449 } else {
450 /* No more private keys to try, send the public key */
451 send_auth_publickey(t);
452 }
453 } else if (p->msg.arg0 == ADB_AUTH_SIGNATURE) {
454 if (adb_auth_verify(t->token, p->data, p->msg.data_length)) {
455 adb_auth_verified(t);
456 t->failed_auth_attempts = 0;
457 } else {
458 if (t->failed_auth_attempts++ > 10)
459 adb_sleep_ms(1000);
460 send_auth_request(t);
461 }
462 } else if (p->msg.arg0 == ADB_AUTH_RSAPUBLICKEY) {
463 adb_auth_confirm_key(p->data, p->msg.data_length, t);
464 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800465 break;
466
467 case A_OPEN: /* OPEN(local-id, 0, "destination") */
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100468 if (t->online && p->msg.arg0 != 0 && p->msg.arg1 == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800469 char *name = (char*) p->data;
470 name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0;
471 s = create_local_service_socket(name);
472 if(s == 0) {
473 send_close(0, p->msg.arg0, t);
474 } else {
475 s->peer = create_remote_socket(p->msg.arg0, t);
476 s->peer->peer = s;
477 send_ready(s->id, s->peer->id, t);
478 s->ready(s);
479 }
480 }
481 break;
482
483 case A_OKAY: /* READY(local-id, remote-id, "") */
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100484 if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) {
485 if((s = find_local_socket(p->msg.arg1, 0))) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800486 if(s->peer == 0) {
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100487 /* On first READY message, create the connection. */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800488 s->peer = create_remote_socket(p->msg.arg0, t);
489 s->peer->peer = s;
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100490 s->ready(s);
491 } else if (s->peer->id == p->msg.arg0) {
492 /* Other READY messages must use the same local-id */
493 s->ready(s);
494 } else {
495 D("Invalid A_OKAY(%d,%d), expected A_OKAY(%d,%d) on transport %s\n",
496 p->msg.arg0, p->msg.arg1, s->peer->id, p->msg.arg1, t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800497 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800498 }
499 }
500 break;
501
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100502 case A_CLSE: /* CLOSE(local-id, remote-id, "") or CLOSE(0, remote-id, "") */
503 if (t->online && p->msg.arg1 != 0) {
504 if((s = find_local_socket(p->msg.arg1, p->msg.arg0))) {
505 /* According to protocol.txt, p->msg.arg0 might be 0 to indicate
506 * a failed OPEN only. However, due to a bug in previous ADB
507 * versions, CLOSE(0, remote-id, "") was also used for normal
508 * CLOSE() operations.
509 *
510 * This is bad because it means a compromised adbd could
511 * send packets to close connections between the host and
512 * other devices. To avoid this, only allow this if the local
513 * socket has a peer on the same transport.
514 */
515 if (p->msg.arg0 == 0 && s->peer && s->peer->transport != t) {
516 D("Invalid A_CLSE(0, %u) from transport %s, expected transport %s\n",
517 p->msg.arg1, t->serial, s->peer->transport->serial);
518 } else {
519 s->close(s);
520 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800521 }
522 }
523 break;
524
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100525 case A_WRTE: /* WRITE(local-id, remote-id, <data>) */
526 if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) {
527 if((s = find_local_socket(p->msg.arg1, p->msg.arg0))) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800528 unsigned rid = p->msg.arg0;
529 p->len = p->msg.data_length;
530
531 if(s->enqueue(s, p) == 0) {
532 D("Enqueue the socket\n");
533 send_ready(s->id, rid, t);
534 }
535 return;
536 }
537 }
538 break;
539
540 default:
541 printf("handle_packet: what is %08x?!\n", p->msg.command);
542 }
543
544 put_apacket(p);
545}
546
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800547#if ADB_HOST
JP Abgrall571c1362012-12-06 18:18:12 -0800548
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100549int launch_server(int server_port)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800550{
Yabin Cuie77b6a02014-11-11 09:24:11 -0800551#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800552 /* we need to start the server in the background */
553 /* we create a PIPE that will be used to wait for the server's "OK" */
554 /* message since the pipe handles must be inheritable, we use a */
555 /* security attribute */
556 HANDLE pipe_read, pipe_write;
Ray Donnelly267aa8b2012-11-29 01:18:50 +0000557 HANDLE stdout_handle, stderr_handle;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800558 SECURITY_ATTRIBUTES sa;
559 STARTUPINFO startup;
560 PROCESS_INFORMATION pinfo;
561 char program_path[ MAX_PATH ];
562 int ret;
563
564 sa.nLength = sizeof(sa);
565 sa.lpSecurityDescriptor = NULL;
566 sa.bInheritHandle = TRUE;
567
568 /* create pipe, and ensure its read handle isn't inheritable */
569 ret = CreatePipe( &pipe_read, &pipe_write, &sa, 0 );
570 if (!ret) {
571 fprintf(stderr, "CreatePipe() failure, error %ld\n", GetLastError() );
572 return -1;
573 }
574
575 SetHandleInformation( pipe_read, HANDLE_FLAG_INHERIT, 0 );
576
Ray Donnelly267aa8b2012-11-29 01:18:50 +0000577 /* Some programs want to launch an adb command and collect its output by
578 * calling CreateProcess with inheritable stdout/stderr handles, then
579 * using read() to get its output. When this happens, the stdout/stderr
580 * handles passed to the adb client process will also be inheritable.
581 * When starting the adb server here, care must be taken to reset them
582 * to non-inheritable.
583 * Otherwise, something bad happens: even if the adb command completes,
584 * the calling process is stuck while read()-ing from the stdout/stderr
585 * descriptors, because they're connected to corresponding handles in the
586 * adb server process (even if the latter never uses/writes to them).
587 */
588 stdout_handle = GetStdHandle( STD_OUTPUT_HANDLE );
589 stderr_handle = GetStdHandle( STD_ERROR_HANDLE );
590 if (stdout_handle != INVALID_HANDLE_VALUE) {
591 SetHandleInformation( stdout_handle, HANDLE_FLAG_INHERIT, 0 );
592 }
593 if (stderr_handle != INVALID_HANDLE_VALUE) {
594 SetHandleInformation( stderr_handle, HANDLE_FLAG_INHERIT, 0 );
595 }
596
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800597 ZeroMemory( &startup, sizeof(startup) );
598 startup.cb = sizeof(startup);
599 startup.hStdInput = GetStdHandle( STD_INPUT_HANDLE );
600 startup.hStdOutput = pipe_write;
601 startup.hStdError = GetStdHandle( STD_ERROR_HANDLE );
602 startup.dwFlags = STARTF_USESTDHANDLES;
603
604 ZeroMemory( &pinfo, sizeof(pinfo) );
605
606 /* get path of current program */
607 GetModuleFileName( NULL, program_path, sizeof(program_path) );
Wenhao Lia09558c2013-11-13 16:23:37 +0800608 char args[64];
609 snprintf(args, sizeof(args), "adb -P %d fork-server server", server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800610 ret = CreateProcess(
611 program_path, /* program path */
Wenhao Lia09558c2013-11-13 16:23:37 +0800612 args,
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800613 /* the fork-server argument will set the
614 debug = 2 in the child */
615 NULL, /* process handle is not inheritable */
616 NULL, /* thread handle is not inheritable */
617 TRUE, /* yes, inherit some handles */
618 DETACHED_PROCESS, /* the new process doesn't have a console */
619 NULL, /* use parent's environment block */
620 NULL, /* use parent's starting directory */
621 &startup, /* startup info, i.e. std handles */
622 &pinfo );
623
624 CloseHandle( pipe_write );
625
626 if (!ret) {
627 fprintf(stderr, "CreateProcess failure, error %ld\n", GetLastError() );
628 CloseHandle( pipe_read );
629 return -1;
630 }
631
632 CloseHandle( pinfo.hProcess );
633 CloseHandle( pinfo.hThread );
634
635 /* wait for the "OK\n" message */
636 {
637 char temp[3];
638 DWORD count;
639
640 ret = ReadFile( pipe_read, temp, 3, &count, NULL );
641 CloseHandle( pipe_read );
642 if ( !ret ) {
643 fprintf(stderr, "could not read ok from ADB Server, error = %ld\n", GetLastError() );
644 return -1;
645 }
646 if (count != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') {
647 fprintf(stderr, "ADB server didn't ACK\n" );
648 return -1;
649 }
650 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800651#else /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800652 char path[PATH_MAX];
653 int fd[2];
654
655 // set up a pipe so the child can tell us when it is ready.
656 // fd[0] will be parent's end, and fd[1] will get mapped to stderr in the child.
657 if (pipe(fd)) {
658 fprintf(stderr, "pipe failed in launch_server, errno: %d\n", errno);
659 return -1;
660 }
Alexey Tarasov31664102009-10-22 02:55:00 +1100661 get_my_path(path, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800662 pid_t pid = fork();
663 if(pid < 0) return -1;
664
665 if (pid == 0) {
666 // child side of the fork
667
668 // redirect stderr to the pipe
669 // we use stderr instead of stdout due to stdout's buffering behavior.
670 adb_close(fd[0]);
671 dup2(fd[1], STDERR_FILENO);
672 adb_close(fd[1]);
673
Matt Gumbeld7b33082012-11-14 10:16:17 -0800674 char str_port[30];
675 snprintf(str_port, sizeof(str_port), "%d", server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800676 // child process
Matt Gumbeld7b33082012-11-14 10:16:17 -0800677 int result = execl(path, "adb", "-P", str_port, "fork-server", "server", NULL);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800678 // this should not return
679 fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno);
680 } else {
681 // parent side of the fork
682
683 char temp[3];
684
685 temp[0] = 'A'; temp[1] = 'B'; temp[2] = 'C';
686 // wait for the "OK\n" message
687 adb_close(fd[1]);
688 int ret = adb_read(fd[0], temp, 3);
JP Abgrall408fa572011-03-16 15:57:42 -0700689 int saved_errno = errno;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800690 adb_close(fd[0]);
691 if (ret < 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700692 fprintf(stderr, "could not read ok from ADB Server, errno = %d\n", saved_errno);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800693 return -1;
694 }
695 if (ret != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') {
696 fprintf(stderr, "ADB server didn't ACK\n" );
697 return -1;
698 }
699
700 setsid();
701 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800702#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800703 return 0;
704}
Yabin Cuie77b6a02014-11-11 09:24:11 -0800705#endif /* ADB_HOST */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800706
David 'Digit' Turner25258692013-03-21 21:07:42 +0100707// Try to handle a network forwarding request.
708// This returns 1 on success, 0 on failure, and -1 to indicate this is not
709// a forwarding-related request.
710int handle_forward_request(const char* service, transport_type ttype, char* serial, int reply_fd)
711{
712 if (!strcmp(service, "list-forward")) {
713 // Create the list of forward redirections.
714 int buffer_size = format_listeners(NULL, 0);
715 // Add one byte for the trailing zero.
716 char* buffer = malloc(buffer_size + 1);
717 if (buffer == NULL) {
718 sendfailmsg(reply_fd, "not enough memory");
719 return 1;
720 }
721 (void) format_listeners(buffer, buffer_size + 1);
722#if ADB_HOST
723 send_msg_with_okay(reply_fd, buffer, buffer_size);
724#else
725 send_msg_with_header(reply_fd, buffer, buffer_size);
726#endif
727 free(buffer);
728 return 1;
729 }
730
731 if (!strcmp(service, "killforward-all")) {
732 remove_all_listeners();
733#if ADB_HOST
734 /* On the host: 1st OKAY is connect, 2nd OKAY is status */
735 adb_write(reply_fd, "OKAY", 4);
736#endif
737 adb_write(reply_fd, "OKAY", 4);
738 return 1;
739 }
740
741 if (!strncmp(service, "forward:",8) ||
742 !strncmp(service, "killforward:",12)) {
743 char *local, *remote, *err;
744 int r;
745 atransport *transport;
746
747 int createForward = strncmp(service, "kill", 4);
748 int no_rebind = 0;
749
750 local = strchr(service, ':') + 1;
751
752 // Handle forward:norebind:<local>... here
753 if (createForward && !strncmp(local, "norebind:", 9)) {
754 no_rebind = 1;
755 local = strchr(local, ':') + 1;
756 }
757
758 remote = strchr(local,';');
759
760 if (createForward) {
761 // Check forward: parameter format: '<local>;<remote>'
762 if(remote == 0) {
763 sendfailmsg(reply_fd, "malformed forward spec");
764 return 1;
765 }
766
767 *remote++ = 0;
768 if((local[0] == 0) || (remote[0] == 0) || (remote[0] == '*')) {
769 sendfailmsg(reply_fd, "malformed forward spec");
770 return 1;
771 }
772 } else {
773 // Check killforward: parameter format: '<local>'
774 if (local[0] == 0) {
775 sendfailmsg(reply_fd, "malformed forward spec");
776 return 1;
777 }
778 }
779
780 transport = acquire_one_transport(CS_ANY, ttype, serial, &err);
781 if (!transport) {
782 sendfailmsg(reply_fd, err);
783 return 1;
784 }
785
786 if (createForward) {
787 r = install_listener(local, remote, transport, no_rebind);
788 } else {
789 r = remove_listener(local, transport);
790 }
791 if(r == 0) {
792#if ADB_HOST
793 /* On the host: 1st OKAY is connect, 2nd OKAY is status */
Dan Albertcc731cc2015-02-24 21:26:58 -0800794 WriteFdExactly(reply_fd, "OKAY", 4);
David 'Digit' Turner25258692013-03-21 21:07:42 +0100795#endif
Dan Albertcc731cc2015-02-24 21:26:58 -0800796 WriteFdExactly(reply_fd, "OKAY", 4);
David 'Digit' Turner25258692013-03-21 21:07:42 +0100797 return 1;
798 }
799
800 if (createForward) {
801 const char* message;
802 switch (r) {
803 case INSTALL_STATUS_CANNOT_BIND:
804 message = "cannot bind to socket";
805 break;
806 case INSTALL_STATUS_CANNOT_REBIND:
807 message = "cannot rebind existing socket";
808 break;
809 default:
810 message = "internal error";
811 }
812 sendfailmsg(reply_fd, message);
813 } else {
814 sendfailmsg(reply_fd, "cannot remove listener");
815 }
816 return 1;
817 }
818 return 0;
819}
820
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800821int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s)
822{
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800823 if(!strcmp(service, "kill")) {
824 fprintf(stderr,"adb server killed by remote request\n");
825 fflush(stdout);
826 adb_write(reply_fd, "OKAY", 4);
827 usb_cleanup();
828 exit(0);
829 }
830
831#if ADB_HOST
Chih-Hung Hsiehf787b382014-09-05 15:38:15 -0700832 atransport *transport = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800833 // "transport:" is used for switching transport with a specified serial number
834 // "transport-usb:" is used for switching transport to the only USB transport
835 // "transport-local:" is used for switching transport to the only local transport
836 // "transport-any:" is used for switching transport to the only transport
837 if (!strncmp(service, "transport", strlen("transport"))) {
838 char* error_string = "unknown failure";
839 transport_type type = kTransportAny;
840
841 if (!strncmp(service, "transport-usb", strlen("transport-usb"))) {
842 type = kTransportUsb;
843 } else if (!strncmp(service, "transport-local", strlen("transport-local"))) {
844 type = kTransportLocal;
845 } else if (!strncmp(service, "transport-any", strlen("transport-any"))) {
846 type = kTransportAny;
847 } else if (!strncmp(service, "transport:", strlen("transport:"))) {
848 service += strlen("transport:");
Tom Marlin3175c8e2011-07-27 12:56:14 -0500849 serial = service;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800850 }
851
852 transport = acquire_one_transport(CS_ANY, type, serial, &error_string);
853
854 if (transport) {
855 s->transport = transport;
856 adb_write(reply_fd, "OKAY", 4);
857 } else {
858 sendfailmsg(reply_fd, error_string);
859 }
860 return 1;
861 }
862
863 // return a list of all connected devices
Scott Andersone109d262012-04-20 11:21:14 -0700864 if (!strncmp(service, "devices", 7)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800865 char buffer[4096];
Scott Andersone109d262012-04-20 11:21:14 -0700866 int use_long = !strcmp(service+7, "-l");
867 if (use_long || service[7] == 0) {
Scott Andersone109d262012-04-20 11:21:14 -0700868 memset(buffer, 0, sizeof(buffer));
869 D("Getting device list \n");
870 list_transports(buffer, sizeof(buffer), use_long);
Scott Andersone109d262012-04-20 11:21:14 -0700871 D("Wrote device list \n");
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100872 send_msg_with_okay(reply_fd, buffer, strlen(buffer));
Scott Andersone109d262012-04-20 11:21:14 -0700873 return 0;
874 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800875 }
876
Mike Lockwood74d7ff82009-10-11 23:04:18 -0400877 // remove TCP transport
878 if (!strncmp(service, "disconnect:", 11)) {
879 char buffer[4096];
880 memset(buffer, 0, sizeof(buffer));
881 char* serial = service + 11;
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400882 if (serial[0] == 0) {
883 // disconnect from all TCP devices
884 unregister_all_tcp_transports();
Mike Lockwood74d7ff82009-10-11 23:04:18 -0400885 } else {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400886 char hostbuf[100];
887 // assume port 5555 if no port is specified
888 if (!strchr(serial, ':')) {
889 snprintf(hostbuf, sizeof(hostbuf) - 1, "%s:5555", serial);
890 serial = hostbuf;
891 }
892 atransport *t = find_transport(serial);
893
894 if (t) {
895 unregister_transport(t);
896 } else {
897 snprintf(buffer, sizeof(buffer), "No such device %s", serial);
898 }
Mike Lockwood74d7ff82009-10-11 23:04:18 -0400899 }
900
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100901 send_msg_with_okay(reply_fd, buffer, strlen(buffer));
Mike Lockwood2f38b692009-08-24 15:58:40 -0700902 return 0;
903 }
904
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800905 // returns our value for ADB_SERVER_VERSION
906 if (!strcmp(service, "version")) {
907 char version[12];
908 snprintf(version, sizeof version, "%04x", ADB_SERVER_VERSION);
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100909 send_msg_with_okay(reply_fd, version, strlen(version));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800910 return 0;
911 }
912
913 if(!strncmp(service,"get-serialno",strlen("get-serialno"))) {
914 char *out = "unknown";
915 transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
916 if (transport && transport->serial) {
917 out = transport->serial;
918 }
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100919 send_msg_with_okay(reply_fd, out, strlen(out));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800920 return 0;
921 }
Scott Andersone109d262012-04-20 11:21:14 -0700922 if(!strncmp(service,"get-devpath",strlen("get-devpath"))) {
923 char *out = "unknown";
924 transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
925 if (transport && transport->devpath) {
926 out = transport->devpath;
927 }
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100928 send_msg_with_okay(reply_fd, out, strlen(out));
Scott Andersone109d262012-04-20 11:21:14 -0700929 return 0;
930 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800931 // indicates a new emulator instance has started
932 if (!strncmp(service,"emulator:",9)) {
933 int port = atoi(service+9);
934 local_connect(port);
935 /* we don't even need to send a reply */
936 return 0;
937 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800938
939 if(!strncmp(service,"get-state",strlen("get-state"))) {
940 transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
941 char *state = connection_state_name(transport);
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100942 send_msg_with_okay(reply_fd, state, strlen(state));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800943 return 0;
944 }
Simon Yedc22c3c2014-07-14 17:23:06 -0700945#endif // ADB_HOST
946
947 int ret = handle_forward_request(service, ttype, serial, reply_fd);
948 if (ret >= 0)
949 return ret - 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800950 return -1;
951}