blob: ca12eb7b6e328d2c5d85db217cbd5879193a21f8 [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
Dan Albert33134262015-03-19 15:21:08 -070017#define TRACE_TAG TRACE_ADB
18
19#include "sysdeps.h"
20#include "adb.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080021
22#include <stdio.h>
23#include <stdlib.h>
24#include <ctype.h>
25#include <stdarg.h>
26#include <errno.h>
Scott Andersonc7993af2012-05-25 13:55:46 -070027#include <stddef.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080028#include <string.h>
29#include <time.h>
Mike Lockwood1f546e62009-05-25 18:17:55 -040030#include <sys/time.h>
Ray Donnellycbb98912012-11-29 01:36:08 +000031#include <stdint.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080032
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070033#include "adb_auth.h"
Dan Albertcc731cc2015-02-24 21:26:58 -080034#include "adb_io.h"
Dan Alberte9fca142015-02-18 18:03:26 -080035#include "adb_listeners.h"
Dan Albert76649012015-02-24 15:51:19 -080036#include "transport.h"
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080037
Scott Andersone82c2db2012-05-25 14:10:02 -070038#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
39
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080040#if !ADB_HOST
Nick Kralevich893a4a42013-05-23 09:54:13 -070041#include <cutils/properties.h>
Nick Kraleviche2864bf2013-02-28 14:12:58 -080042#include <sys/capability.h>
Jeff Sharkey885342a2012-08-14 21:00:22 -070043#include <sys/mount.h>
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080044#endif
45
JP Abgrall408fa572011-03-16 15:57:42 -070046#if ADB_TRACE
47ADB_MUTEX_DEFINE( D_lock );
48#endif
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080049
50int HOST = 0;
51
Scott Andersone82c2db2012-05-25 14:10:02 -070052#if !ADB_HOST
Dan Albertbd0b7502015-02-18 18:22:45 -080053const char *adb_device_banner = "device";
Scott Andersone82c2db2012-05-25 14:10:02 -070054#endif
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080055
56void fatal(const char *fmt, ...)
57{
58 va_list ap;
59 va_start(ap, fmt);
60 fprintf(stderr, "error: ");
61 vfprintf(stderr, fmt, ap);
62 fprintf(stderr, "\n");
63 va_end(ap);
64 exit(-1);
65}
66
67void fatal_errno(const char *fmt, ...)
68{
69 va_list ap;
70 va_start(ap, fmt);
71 fprintf(stderr, "error: %s: ", strerror(errno));
72 vfprintf(stderr, fmt, ap);
73 fprintf(stderr, "\n");
74 va_end(ap);
75 exit(-1);
76}
77
78int adb_trace_mask;
79
80/* read a comma/space/colum/semi-column separated list of tags
81 * from the ADB_TRACE environment variable and build the trace
82 * mask from it. note that '1' and 'all' are special cases to
83 * enable all tracing
84 */
85void adb_trace_init(void)
86{
87 const char* p = getenv("ADB_TRACE");
88 const char* q;
89
90 static const struct {
91 const char* tag;
92 int flag;
93 } tags[] = {
94 { "1", 0 },
95 { "all", 0 },
96 { "adb", TRACE_ADB },
97 { "sockets", TRACE_SOCKETS },
98 { "packets", TRACE_PACKETS },
99 { "rwx", TRACE_RWX },
100 { "usb", TRACE_USB },
101 { "sync", TRACE_SYNC },
102 { "sysdeps", TRACE_SYSDEPS },
103 { "transport", TRACE_TRANSPORT },
104 { "jdwp", TRACE_JDWP },
JP Abgrall408fa572011-03-16 15:57:42 -0700105 { "services", TRACE_SERVICES },
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700106 { "auth", TRACE_AUTH },
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800107 { NULL, 0 }
108 };
109
110 if (p == NULL)
111 return;
112
113 /* use a comma/column/semi-colum/space separated list */
114 while (*p) {
115 int len, tagn;
116
117 q = strpbrk(p, " ,:;");
118 if (q == NULL) {
119 q = p + strlen(p);
120 }
121 len = q - p;
122
123 for (tagn = 0; tags[tagn].tag != NULL; tagn++)
124 {
125 int taglen = strlen(tags[tagn].tag);
126
127 if (len == taglen && !memcmp(tags[tagn].tag, p, len) )
128 {
129 int flag = tags[tagn].flag;
130 if (flag == 0) {
131 adb_trace_mask = ~0;
132 return;
133 }
134 adb_trace_mask |= (1 << flag);
135 break;
136 }
137 }
138 p = q;
139 if (*p)
140 p++;
141 }
142}
143
Dan Albertbac34742015-02-25 17:51:28 -0800144apacket* get_apacket(void)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800145{
Dan Albertbac34742015-02-25 17:51:28 -0800146 apacket* p = reinterpret_cast<apacket*>(malloc(sizeof(apacket)));
147 if (p == nullptr) {
148 fatal("failed to allocate an apacket");
149 }
150
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800151 memset(p, 0, sizeof(apacket) - MAX_PAYLOAD);
152 return p;
153}
154
155void put_apacket(apacket *p)
156{
157 free(p);
158}
159
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700160void handle_online(atransport *t)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800161{
162 D("adb: online\n");
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700163 t->online = 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800164}
165
166void handle_offline(atransport *t)
167{
168 D("adb: offline\n");
169 //Close the associated usb
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700170 t->online = 0;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800171 run_transport_disconnects(t);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800172}
173
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700174#if DEBUG_PACKETS
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800175#define DUMPMAX 32
176void print_packet(const char *label, apacket *p)
177{
178 char *tag;
179 char *x;
180 unsigned count;
181
182 switch(p->msg.command){
183 case A_SYNC: tag = "SYNC"; break;
184 case A_CNXN: tag = "CNXN" ; break;
185 case A_OPEN: tag = "OPEN"; break;
186 case A_OKAY: tag = "OKAY"; break;
187 case A_CLSE: tag = "CLSE"; break;
188 case A_WRTE: tag = "WRTE"; break;
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700189 case A_AUTH: tag = "AUTH"; break;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800190 default: tag = "????"; break;
191 }
192
193 fprintf(stderr, "%s: %s %08x %08x %04x \"",
194 label, tag, p->msg.arg0, p->msg.arg1, p->msg.data_length);
195 count = p->msg.data_length;
196 x = (char*) p->data;
197 if(count > DUMPMAX) {
198 count = DUMPMAX;
199 tag = "\n";
200 } else {
201 tag = "\"\n";
202 }
203 while(count-- > 0){
204 if((*x >= ' ') && (*x < 127)) {
205 fputc(*x, stderr);
206 } else {
207 fputc('.', stderr);
208 }
209 x++;
210 }
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700211 fputs(tag, stderr);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800212}
213#endif
214
215static void send_ready(unsigned local, unsigned remote, atransport *t)
216{
217 D("Calling send_ready \n");
218 apacket *p = get_apacket();
219 p->msg.command = A_OKAY;
220 p->msg.arg0 = local;
221 p->msg.arg1 = remote;
222 send_packet(p, t);
223}
224
225static void send_close(unsigned local, unsigned remote, atransport *t)
226{
227 D("Calling send_close \n");
228 apacket *p = get_apacket();
229 p->msg.command = A_CLSE;
230 p->msg.arg0 = local;
231 p->msg.arg1 = remote;
232 send_packet(p, t);
233}
234
Scott Andersone82c2db2012-05-25 14:10:02 -0700235static size_t fill_connect_data(char *buf, size_t bufsize)
236{
237#if ADB_HOST
238 return snprintf(buf, bufsize, "host::") + 1;
239#else
240 static const char *cnxn_props[] = {
241 "ro.product.name",
242 "ro.product.model",
243 "ro.product.device",
244 };
245 static const int num_cnxn_props = ARRAY_SIZE(cnxn_props);
246 int i;
247 size_t remaining = bufsize;
248 size_t len;
249
250 len = snprintf(buf, remaining, "%s::", adb_device_banner);
251 remaining -= len;
252 buf += len;
253 for (i = 0; i < num_cnxn_props; i++) {
254 char value[PROPERTY_VALUE_MAX];
255 property_get(cnxn_props[i], value, "");
256 len = snprintf(buf, remaining, "%s=%s;", cnxn_props[i], value);
257 remaining -= len;
258 buf += len;
259 }
260
261 return bufsize - remaining + 1;
262#endif
263}
264
David 'Digit' Turner25258692013-03-21 21:07:42 +0100265#if !ADB_HOST
266static void send_msg_with_header(int fd, const char* msg, size_t msglen) {
267 char header[5];
268 if (msglen > 0xffff)
269 msglen = 0xffff;
270 snprintf(header, sizeof(header), "%04x", (unsigned)msglen);
Dan Albertcc731cc2015-02-24 21:26:58 -0800271 WriteFdExactly(fd, header, 4);
272 WriteFdExactly(fd, msg, msglen);
David 'Digit' Turner25258692013-03-21 21:07:42 +0100273}
274#endif
275
Chih-Hung Hsiehf787b382014-09-05 15:38:15 -0700276#if ADB_HOST
David 'Digit' Turner25258692013-03-21 21:07:42 +0100277static void send_msg_with_okay(int fd, const char* msg, size_t msglen) {
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100278 char header[9];
279 if (msglen > 0xffff)
280 msglen = 0xffff;
281 snprintf(header, sizeof(header), "OKAY%04x", (unsigned)msglen);
Dan Albertcc731cc2015-02-24 21:26:58 -0800282 WriteFdExactly(fd, header, 8);
283 WriteFdExactly(fd, msg, msglen);
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100284}
Chih-Hung Hsiehf787b382014-09-05 15:38:15 -0700285#endif // ADB_HOST
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100286
Dan Albertba3a2512015-02-18 17:47:33 -0800287void send_connect(atransport *t)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800288{
289 D("Calling send_connect \n");
290 apacket *cp = get_apacket();
291 cp->msg.command = A_CNXN;
292 cp->msg.arg0 = A_VERSION;
293 cp->msg.arg1 = MAX_PAYLOAD;
Scott Andersone82c2db2012-05-25 14:10:02 -0700294 cp->msg.data_length = fill_connect_data((char *)cp->data,
295 sizeof(cp->data));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800296 send_packet(cp, t);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700297}
298
Chih-Hung Hsiehf787b382014-09-05 15:38:15 -0700299#if ADB_HOST
Dan Albertbac34742015-02-25 17:51:28 -0800300static const char* connection_state_name(atransport *t)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800301{
302 if (t == NULL) {
303 return "unknown";
304 }
305
306 switch(t->connection_state) {
307 case CS_BOOTLOADER:
308 return "bootloader";
309 case CS_DEVICE:
310 return "device";
trevda5ad5392013-04-17 14:34:23 +0100311 case CS_RECOVERY:
312 return "recovery";
313 case CS_SIDELOAD:
314 return "sideload";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800315 case CS_OFFLINE:
316 return "offline";
Benoit Goby77e8e582013-01-15 12:36:47 -0800317 case CS_UNAUTHORIZED:
318 return "unauthorized";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800319 default:
320 return "unknown";
321 }
322}
Chih-Hung Hsiehf787b382014-09-05 15:38:15 -0700323#endif // ADB_HOST
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800324
Scott Andersone82c2db2012-05-25 14:10:02 -0700325/* qual_overwrite is used to overwrite a qualifier string. dst is a
326 * pointer to a char pointer. It is assumed that if *dst is non-NULL, it
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700327 * was malloc'ed and needs to freed. *dst will be set to a dup of src.
Scott Andersone82c2db2012-05-25 14:10:02 -0700328 */
329static void qual_overwrite(char **dst, const char *src)
330{
331 if (!dst)
332 return;
333
334 free(*dst);
335 *dst = NULL;
336
337 if (!src || !*src)
338 return;
339
340 *dst = strdup(src);
341}
342
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800343void parse_banner(char *banner, atransport *t)
344{
Scott Andersone82c2db2012-05-25 14:10:02 -0700345 static const char *prop_seps = ";";
346 static const char key_val_sep = '=';
Scott Anderson2ca3e6b2012-05-30 18:11:27 -0700347 char *cp;
348 char *type;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800349
350 D("parse_banner: %s\n", banner);
351 type = banner;
Scott Andersone82c2db2012-05-25 14:10:02 -0700352 cp = strchr(type, ':');
353 if (cp) {
354 *cp++ = 0;
355 /* Nothing is done with second field. */
356 cp = strchr(cp, ':');
357 if (cp) {
358 char *save;
359 char *key;
Scott Anderson1b7a7e82012-06-05 17:54:27 -0700360 key = adb_strtok_r(cp + 1, prop_seps, &save);
Scott Andersone82c2db2012-05-25 14:10:02 -0700361 while (key) {
362 cp = strchr(key, key_val_sep);
363 if (cp) {
364 *cp++ = '\0';
365 if (!strcmp(key, "ro.product.name"))
366 qual_overwrite(&t->product, cp);
367 else if (!strcmp(key, "ro.product.model"))
368 qual_overwrite(&t->model, cp);
369 else if (!strcmp(key, "ro.product.device"))
370 qual_overwrite(&t->device, cp);
371 }
Scott Anderson1b7a7e82012-06-05 17:54:27 -0700372 key = adb_strtok_r(NULL, prop_seps, &save);
Scott Andersone82c2db2012-05-25 14:10:02 -0700373 }
374 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800375 }
376
377 if(!strcmp(type, "bootloader")){
378 D("setting connection_state to CS_BOOTLOADER\n");
379 t->connection_state = CS_BOOTLOADER;
380 update_transports();
381 return;
382 }
383
384 if(!strcmp(type, "device")) {
385 D("setting connection_state to CS_DEVICE\n");
386 t->connection_state = CS_DEVICE;
387 update_transports();
388 return;
389 }
390
391 if(!strcmp(type, "recovery")) {
392 D("setting connection_state to CS_RECOVERY\n");
393 t->connection_state = CS_RECOVERY;
394 update_transports();
395 return;
396 }
397
Doug Zongker447f0612012-01-09 14:54:53 -0800398 if(!strcmp(type, "sideload")) {
399 D("setting connection_state to CS_SIDELOAD\n");
400 t->connection_state = CS_SIDELOAD;
401 update_transports();
402 return;
403 }
404
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800405 t->connection_state = CS_HOST;
406}
407
408void handle_packet(apacket *p, atransport *t)
409{
410 asocket *s;
411
Viral Mehta899913f2010-06-16 18:41:28 +0530412 D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0],
413 ((char*) (&(p->msg.command)))[1],
414 ((char*) (&(p->msg.command)))[2],
415 ((char*) (&(p->msg.command)))[3]);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800416 print_packet("recv", p);
417
418 switch(p->msg.command){
419 case A_SYNC:
420 if(p->msg.arg0){
421 send_packet(p, t);
422 if(HOST) send_connect(t);
423 } else {
424 t->connection_state = CS_OFFLINE;
425 handle_offline(t);
426 send_packet(p, t);
427 }
428 return;
429
430 case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */
431 /* XXX verify version, etc */
432 if(t->connection_state != CS_OFFLINE) {
433 t->connection_state = CS_OFFLINE;
434 handle_offline(t);
435 }
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700436
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800437 parse_banner((char*) p->data, t);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700438
439 if (HOST || !auth_enabled) {
440 handle_online(t);
441 if(!HOST) send_connect(t);
442 } else {
443 send_auth_request(t);
444 }
445 break;
446
447 case A_AUTH:
448 if (p->msg.arg0 == ADB_AUTH_TOKEN) {
Benoit Goby77e8e582013-01-15 12:36:47 -0800449 t->connection_state = CS_UNAUTHORIZED;
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700450 t->key = adb_auth_nextkey(t->key);
451 if (t->key) {
452 send_auth_response(p->data, p->msg.data_length, t);
453 } else {
454 /* No more private keys to try, send the public key */
455 send_auth_publickey(t);
456 }
457 } else if (p->msg.arg0 == ADB_AUTH_SIGNATURE) {
458 if (adb_auth_verify(t->token, p->data, p->msg.data_length)) {
459 adb_auth_verified(t);
460 t->failed_auth_attempts = 0;
461 } else {
462 if (t->failed_auth_attempts++ > 10)
463 adb_sleep_ms(1000);
464 send_auth_request(t);
465 }
466 } else if (p->msg.arg0 == ADB_AUTH_RSAPUBLICKEY) {
467 adb_auth_confirm_key(p->data, p->msg.data_length, t);
468 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800469 break;
470
471 case A_OPEN: /* OPEN(local-id, 0, "destination") */
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100472 if (t->online && p->msg.arg0 != 0 && p->msg.arg1 == 0) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800473 char *name = (char*) p->data;
474 name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0;
475 s = create_local_service_socket(name);
476 if(s == 0) {
477 send_close(0, p->msg.arg0, t);
478 } else {
479 s->peer = create_remote_socket(p->msg.arg0, t);
480 s->peer->peer = s;
481 send_ready(s->id, s->peer->id, t);
482 s->ready(s);
483 }
484 }
485 break;
486
487 case A_OKAY: /* READY(local-id, remote-id, "") */
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100488 if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) {
489 if((s = find_local_socket(p->msg.arg1, 0))) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800490 if(s->peer == 0) {
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100491 /* On first READY message, create the connection. */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800492 s->peer = create_remote_socket(p->msg.arg0, t);
493 s->peer->peer = s;
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100494 s->ready(s);
495 } else if (s->peer->id == p->msg.arg0) {
496 /* Other READY messages must use the same local-id */
497 s->ready(s);
498 } else {
499 D("Invalid A_OKAY(%d,%d), expected A_OKAY(%d,%d) on transport %s\n",
500 p->msg.arg0, p->msg.arg1, s->peer->id, p->msg.arg1, t->serial);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800501 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800502 }
503 }
504 break;
505
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100506 case A_CLSE: /* CLOSE(local-id, remote-id, "") or CLOSE(0, remote-id, "") */
507 if (t->online && p->msg.arg1 != 0) {
508 if((s = find_local_socket(p->msg.arg1, p->msg.arg0))) {
509 /* According to protocol.txt, p->msg.arg0 might be 0 to indicate
510 * a failed OPEN only. However, due to a bug in previous ADB
511 * versions, CLOSE(0, remote-id, "") was also used for normal
512 * CLOSE() operations.
513 *
514 * This is bad because it means a compromised adbd could
515 * send packets to close connections between the host and
516 * other devices. To avoid this, only allow this if the local
517 * socket has a peer on the same transport.
518 */
519 if (p->msg.arg0 == 0 && s->peer && s->peer->transport != t) {
520 D("Invalid A_CLSE(0, %u) from transport %s, expected transport %s\n",
521 p->msg.arg1, t->serial, s->peer->transport->serial);
522 } else {
523 s->close(s);
524 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800525 }
526 }
527 break;
528
David 'Digit' Turner818d6412013-12-13 14:09:44 +0100529 case A_WRTE: /* WRITE(local-id, remote-id, <data>) */
530 if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) {
531 if((s = find_local_socket(p->msg.arg1, p->msg.arg0))) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800532 unsigned rid = p->msg.arg0;
533 p->len = p->msg.data_length;
534
535 if(s->enqueue(s, p) == 0) {
536 D("Enqueue the socket\n");
537 send_ready(s->id, rid, t);
538 }
539 return;
540 }
541 }
542 break;
543
544 default:
545 printf("handle_packet: what is %08x?!\n", p->msg.command);
546 }
547
548 put_apacket(p);
549}
550
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800551#if ADB_HOST
JP Abgrall571c1362012-12-06 18:18:12 -0800552
Stefan Hilzingera84a42e2010-04-19 12:21:12 +0100553int launch_server(int server_port)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800554{
Yabin Cuie77b6a02014-11-11 09:24:11 -0800555#if defined(_WIN32)
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800556 /* we need to start the server in the background */
557 /* we create a PIPE that will be used to wait for the server's "OK" */
558 /* message since the pipe handles must be inheritable, we use a */
559 /* security attribute */
560 HANDLE pipe_read, pipe_write;
Ray Donnelly267aa8b2012-11-29 01:18:50 +0000561 HANDLE stdout_handle, stderr_handle;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800562 SECURITY_ATTRIBUTES sa;
563 STARTUPINFO startup;
564 PROCESS_INFORMATION pinfo;
565 char program_path[ MAX_PATH ];
566 int ret;
567
568 sa.nLength = sizeof(sa);
569 sa.lpSecurityDescriptor = NULL;
570 sa.bInheritHandle = TRUE;
571
572 /* create pipe, and ensure its read handle isn't inheritable */
573 ret = CreatePipe( &pipe_read, &pipe_write, &sa, 0 );
574 if (!ret) {
575 fprintf(stderr, "CreatePipe() failure, error %ld\n", GetLastError() );
576 return -1;
577 }
578
579 SetHandleInformation( pipe_read, HANDLE_FLAG_INHERIT, 0 );
580
Ray Donnelly267aa8b2012-11-29 01:18:50 +0000581 /* Some programs want to launch an adb command and collect its output by
582 * calling CreateProcess with inheritable stdout/stderr handles, then
583 * using read() to get its output. When this happens, the stdout/stderr
584 * handles passed to the adb client process will also be inheritable.
585 * When starting the adb server here, care must be taken to reset them
586 * to non-inheritable.
587 * Otherwise, something bad happens: even if the adb command completes,
588 * the calling process is stuck while read()-ing from the stdout/stderr
589 * descriptors, because they're connected to corresponding handles in the
590 * adb server process (even if the latter never uses/writes to them).
591 */
592 stdout_handle = GetStdHandle( STD_OUTPUT_HANDLE );
593 stderr_handle = GetStdHandle( STD_ERROR_HANDLE );
594 if (stdout_handle != INVALID_HANDLE_VALUE) {
595 SetHandleInformation( stdout_handle, HANDLE_FLAG_INHERIT, 0 );
596 }
597 if (stderr_handle != INVALID_HANDLE_VALUE) {
598 SetHandleInformation( stderr_handle, HANDLE_FLAG_INHERIT, 0 );
599 }
600
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800601 ZeroMemory( &startup, sizeof(startup) );
602 startup.cb = sizeof(startup);
603 startup.hStdInput = GetStdHandle( STD_INPUT_HANDLE );
604 startup.hStdOutput = pipe_write;
605 startup.hStdError = GetStdHandle( STD_ERROR_HANDLE );
606 startup.dwFlags = STARTF_USESTDHANDLES;
607
608 ZeroMemory( &pinfo, sizeof(pinfo) );
609
610 /* get path of current program */
611 GetModuleFileName( NULL, program_path, sizeof(program_path) );
Wenhao Lia09558c2013-11-13 16:23:37 +0800612 char args[64];
613 snprintf(args, sizeof(args), "adb -P %d fork-server server", server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800614 ret = CreateProcess(
615 program_path, /* program path */
Wenhao Lia09558c2013-11-13 16:23:37 +0800616 args,
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800617 /* the fork-server argument will set the
618 debug = 2 in the child */
619 NULL, /* process handle is not inheritable */
620 NULL, /* thread handle is not inheritable */
621 TRUE, /* yes, inherit some handles */
622 DETACHED_PROCESS, /* the new process doesn't have a console */
623 NULL, /* use parent's environment block */
624 NULL, /* use parent's starting directory */
625 &startup, /* startup info, i.e. std handles */
626 &pinfo );
627
628 CloseHandle( pipe_write );
629
630 if (!ret) {
631 fprintf(stderr, "CreateProcess failure, error %ld\n", GetLastError() );
632 CloseHandle( pipe_read );
633 return -1;
634 }
635
636 CloseHandle( pinfo.hProcess );
637 CloseHandle( pinfo.hThread );
638
639 /* wait for the "OK\n" message */
640 {
641 char temp[3];
642 DWORD count;
643
644 ret = ReadFile( pipe_read, temp, 3, &count, NULL );
645 CloseHandle( pipe_read );
646 if ( !ret ) {
647 fprintf(stderr, "could not read ok from ADB Server, error = %ld\n", GetLastError() );
648 return -1;
649 }
650 if (count != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') {
651 fprintf(stderr, "ADB server didn't ACK\n" );
652 return -1;
653 }
654 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800655#else /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800656 char path[PATH_MAX];
657 int fd[2];
658
659 // set up a pipe so the child can tell us when it is ready.
660 // fd[0] will be parent's end, and fd[1] will get mapped to stderr in the child.
661 if (pipe(fd)) {
662 fprintf(stderr, "pipe failed in launch_server, errno: %d\n", errno);
663 return -1;
664 }
Alexey Tarasov31664102009-10-22 02:55:00 +1100665 get_my_path(path, PATH_MAX);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800666 pid_t pid = fork();
667 if(pid < 0) return -1;
668
669 if (pid == 0) {
670 // child side of the fork
671
672 // redirect stderr to the pipe
673 // we use stderr instead of stdout due to stdout's buffering behavior.
674 adb_close(fd[0]);
675 dup2(fd[1], STDERR_FILENO);
676 adb_close(fd[1]);
677
Matt Gumbeld7b33082012-11-14 10:16:17 -0800678 char str_port[30];
679 snprintf(str_port, sizeof(str_port), "%d", server_port);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800680 // child process
Matt Gumbeld7b33082012-11-14 10:16:17 -0800681 int result = execl(path, "adb", "-P", str_port, "fork-server", "server", NULL);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800682 // this should not return
683 fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno);
684 } else {
685 // parent side of the fork
686
687 char temp[3];
688
689 temp[0] = 'A'; temp[1] = 'B'; temp[2] = 'C';
690 // wait for the "OK\n" message
691 adb_close(fd[1]);
692 int ret = adb_read(fd[0], temp, 3);
JP Abgrall408fa572011-03-16 15:57:42 -0700693 int saved_errno = errno;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800694 adb_close(fd[0]);
695 if (ret < 0) {
JP Abgrall408fa572011-03-16 15:57:42 -0700696 fprintf(stderr, "could not read ok from ADB Server, errno = %d\n", saved_errno);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800697 return -1;
698 }
699 if (ret != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') {
700 fprintf(stderr, "ADB server didn't ACK\n" );
701 return -1;
702 }
703
704 setsid();
705 }
Yabin Cuie77b6a02014-11-11 09:24:11 -0800706#endif /* !defined(_WIN32) */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800707 return 0;
708}
Yabin Cuie77b6a02014-11-11 09:24:11 -0800709#endif /* ADB_HOST */
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800710
David 'Digit' Turner25258692013-03-21 21:07:42 +0100711// Try to handle a network forwarding request.
712// This returns 1 on success, 0 on failure, and -1 to indicate this is not
713// a forwarding-related request.
714int handle_forward_request(const char* service, transport_type ttype, char* serial, int reply_fd)
715{
716 if (!strcmp(service, "list-forward")) {
717 // Create the list of forward redirections.
718 int buffer_size = format_listeners(NULL, 0);
719 // Add one byte for the trailing zero.
Dan Albertbac34742015-02-25 17:51:28 -0800720 char* buffer = reinterpret_cast<char*>(malloc(buffer_size + 1));
721 if (buffer == nullptr) {
David 'Digit' Turner25258692013-03-21 21:07:42 +0100722 sendfailmsg(reply_fd, "not enough memory");
723 return 1;
724 }
725 (void) format_listeners(buffer, buffer_size + 1);
726#if ADB_HOST
727 send_msg_with_okay(reply_fd, buffer, buffer_size);
728#else
729 send_msg_with_header(reply_fd, buffer, buffer_size);
730#endif
731 free(buffer);
732 return 1;
733 }
734
735 if (!strcmp(service, "killforward-all")) {
736 remove_all_listeners();
737#if ADB_HOST
738 /* On the host: 1st OKAY is connect, 2nd OKAY is status */
739 adb_write(reply_fd, "OKAY", 4);
740#endif
741 adb_write(reply_fd, "OKAY", 4);
742 return 1;
743 }
744
745 if (!strncmp(service, "forward:",8) ||
746 !strncmp(service, "killforward:",12)) {
Dan Albertbac34742015-02-25 17:51:28 -0800747 char *local, *remote;
David 'Digit' Turner25258692013-03-21 21:07:42 +0100748 int r;
749 atransport *transport;
750
751 int createForward = strncmp(service, "kill", 4);
752 int no_rebind = 0;
753
754 local = strchr(service, ':') + 1;
755
756 // Handle forward:norebind:<local>... here
757 if (createForward && !strncmp(local, "norebind:", 9)) {
758 no_rebind = 1;
759 local = strchr(local, ':') + 1;
760 }
761
762 remote = strchr(local,';');
763
764 if (createForward) {
765 // Check forward: parameter format: '<local>;<remote>'
766 if(remote == 0) {
767 sendfailmsg(reply_fd, "malformed forward spec");
768 return 1;
769 }
770
771 *remote++ = 0;
772 if((local[0] == 0) || (remote[0] == 0) || (remote[0] == '*')) {
773 sendfailmsg(reply_fd, "malformed forward spec");
774 return 1;
775 }
776 } else {
777 // Check killforward: parameter format: '<local>'
778 if (local[0] == 0) {
779 sendfailmsg(reply_fd, "malformed forward spec");
780 return 1;
781 }
782 }
783
Dan Albertbac34742015-02-25 17:51:28 -0800784 const char* err;
David 'Digit' Turner25258692013-03-21 21:07:42 +0100785 transport = acquire_one_transport(CS_ANY, ttype, serial, &err);
786 if (!transport) {
787 sendfailmsg(reply_fd, err);
788 return 1;
789 }
790
791 if (createForward) {
792 r = install_listener(local, remote, transport, no_rebind);
793 } else {
794 r = remove_listener(local, transport);
795 }
796 if(r == 0) {
797#if ADB_HOST
798 /* On the host: 1st OKAY is connect, 2nd OKAY is status */
Dan Albertcc731cc2015-02-24 21:26:58 -0800799 WriteFdExactly(reply_fd, "OKAY", 4);
David 'Digit' Turner25258692013-03-21 21:07:42 +0100800#endif
Dan Albertcc731cc2015-02-24 21:26:58 -0800801 WriteFdExactly(reply_fd, "OKAY", 4);
David 'Digit' Turner25258692013-03-21 21:07:42 +0100802 return 1;
803 }
804
805 if (createForward) {
806 const char* message;
807 switch (r) {
808 case INSTALL_STATUS_CANNOT_BIND:
809 message = "cannot bind to socket";
810 break;
811 case INSTALL_STATUS_CANNOT_REBIND:
812 message = "cannot rebind existing socket";
813 break;
814 default:
815 message = "internal error";
816 }
817 sendfailmsg(reply_fd, message);
818 } else {
819 sendfailmsg(reply_fd, "cannot remove listener");
820 }
821 return 1;
822 }
823 return 0;
824}
825
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800826int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s)
827{
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800828 if(!strcmp(service, "kill")) {
829 fprintf(stderr,"adb server killed by remote request\n");
830 fflush(stdout);
831 adb_write(reply_fd, "OKAY", 4);
832 usb_cleanup();
833 exit(0);
834 }
835
836#if ADB_HOST
Chih-Hung Hsiehf787b382014-09-05 15:38:15 -0700837 atransport *transport = NULL;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800838 // "transport:" is used for switching transport with a specified serial number
839 // "transport-usb:" is used for switching transport to the only USB transport
840 // "transport-local:" is used for switching transport to the only local transport
841 // "transport-any:" is used for switching transport to the only transport
842 if (!strncmp(service, "transport", strlen("transport"))) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800843 transport_type type = kTransportAny;
844
845 if (!strncmp(service, "transport-usb", strlen("transport-usb"))) {
846 type = kTransportUsb;
847 } else if (!strncmp(service, "transport-local", strlen("transport-local"))) {
848 type = kTransportLocal;
849 } else if (!strncmp(service, "transport-any", strlen("transport-any"))) {
850 type = kTransportAny;
851 } else if (!strncmp(service, "transport:", strlen("transport:"))) {
852 service += strlen("transport:");
Tom Marlin3175c8e2011-07-27 12:56:14 -0500853 serial = service;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800854 }
855
Dan Albertbac34742015-02-25 17:51:28 -0800856 const char* error_string = "unknown failure";
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800857 transport = acquire_one_transport(CS_ANY, type, serial, &error_string);
858
859 if (transport) {
860 s->transport = transport;
861 adb_write(reply_fd, "OKAY", 4);
862 } else {
863 sendfailmsg(reply_fd, error_string);
864 }
865 return 1;
866 }
867
868 // return a list of all connected devices
Scott Andersone109d262012-04-20 11:21:14 -0700869 if (!strncmp(service, "devices", 7)) {
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800870 char buffer[4096];
Scott Andersone109d262012-04-20 11:21:14 -0700871 int use_long = !strcmp(service+7, "-l");
872 if (use_long || service[7] == 0) {
Scott Andersone109d262012-04-20 11:21:14 -0700873 memset(buffer, 0, sizeof(buffer));
874 D("Getting device list \n");
875 list_transports(buffer, sizeof(buffer), use_long);
Scott Andersone109d262012-04-20 11:21:14 -0700876 D("Wrote device list \n");
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100877 send_msg_with_okay(reply_fd, buffer, strlen(buffer));
Scott Andersone109d262012-04-20 11:21:14 -0700878 return 0;
879 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800880 }
881
Mike Lockwood74d7ff82009-10-11 23:04:18 -0400882 // remove TCP transport
883 if (!strncmp(service, "disconnect:", 11)) {
884 char buffer[4096];
885 memset(buffer, 0, sizeof(buffer));
886 char* serial = service + 11;
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400887 if (serial[0] == 0) {
888 // disconnect from all TCP devices
889 unregister_all_tcp_transports();
Mike Lockwood74d7ff82009-10-11 23:04:18 -0400890 } else {
Mike Lockwoodcbbe79a2010-05-24 10:44:35 -0400891 char hostbuf[100];
892 // assume port 5555 if no port is specified
893 if (!strchr(serial, ':')) {
894 snprintf(hostbuf, sizeof(hostbuf) - 1, "%s:5555", serial);
895 serial = hostbuf;
896 }
897 atransport *t = find_transport(serial);
898
899 if (t) {
900 unregister_transport(t);
901 } else {
902 snprintf(buffer, sizeof(buffer), "No such device %s", serial);
903 }
Mike Lockwood74d7ff82009-10-11 23:04:18 -0400904 }
905
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100906 send_msg_with_okay(reply_fd, buffer, strlen(buffer));
Mike Lockwood2f38b692009-08-24 15:58:40 -0700907 return 0;
908 }
909
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800910 // returns our value for ADB_SERVER_VERSION
911 if (!strcmp(service, "version")) {
912 char version[12];
913 snprintf(version, sizeof version, "%04x", ADB_SERVER_VERSION);
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100914 send_msg_with_okay(reply_fd, version, strlen(version));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800915 return 0;
916 }
917
918 if(!strncmp(service,"get-serialno",strlen("get-serialno"))) {
Dan Albertbac34742015-02-25 17:51:28 -0800919 const char *out = "unknown";
920 transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800921 if (transport && transport->serial) {
922 out = transport->serial;
923 }
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100924 send_msg_with_okay(reply_fd, out, strlen(out));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800925 return 0;
926 }
Scott Andersone109d262012-04-20 11:21:14 -0700927 if(!strncmp(service,"get-devpath",strlen("get-devpath"))) {
Dan Albertbac34742015-02-25 17:51:28 -0800928 const char *out = "unknown";
929 transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
Scott Andersone109d262012-04-20 11:21:14 -0700930 if (transport && transport->devpath) {
931 out = transport->devpath;
932 }
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100933 send_msg_with_okay(reply_fd, out, strlen(out));
Scott Andersone109d262012-04-20 11:21:14 -0700934 return 0;
935 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800936 // indicates a new emulator instance has started
937 if (!strncmp(service,"emulator:",9)) {
938 int port = atoi(service+9);
939 local_connect(port);
940 /* we don't even need to send a reply */
941 return 0;
942 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800943
944 if(!strncmp(service,"get-state",strlen("get-state"))) {
945 transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
Dan Albertbac34742015-02-25 17:51:28 -0800946 const char *state = connection_state_name(transport);
Snild Dolkow2264e7c2014-01-30 10:08:38 +0100947 send_msg_with_okay(reply_fd, state, strlen(state));
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800948 return 0;
949 }
Simon Yedc22c3c2014-07-14 17:23:06 -0700950#endif // ADB_HOST
951
952 int ret = handle_forward_request(service, ttype, serial, reply_fd);
953 if (ret >= 0)
954 return ret - 1;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800955 return -1;
956}