adb.cpp revision b329824e6c5373ae303269dca285d835ce57e514
1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * you may not use this file except in compliance with the License.
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * You may obtain a copy of the License at
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * See the License for the specific language governing permissions and
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * limitations under the License.
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
173313426fad9eaaf53017cdbde889ebcec91358ecDan Albert#define TRACE_TAG TRACE_ADB
183313426fad9eaaf53017cdbde889ebcec91358ecDan Albert
193313426fad9eaaf53017cdbde889ebcec91358ecDan Albert#include "sysdeps.h"
203313426fad9eaaf53017cdbde889ebcec91358ecDan Albert#include "adb.h"
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <ctype.h>
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h>
24ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert#include <stdarg.h>
25c7993af64baec271a238646bc20aaa846866c4a9Scott Anderson#include <stddef.h>
26ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert#include <stdint.h>
27ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert#include <stdio.h>
28ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert#include <stdlib.h>
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h>
301f546e6d1f6ccd1964336ddf0d8e8b3b11b1e945Mike Lockwood#include <sys/time.h>
31ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert#include <time.h>
32ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert
33ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert#include <string>
34e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert#include <vector>
35e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert#include <unordered_map>
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
379313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albert#include <base/logging.h>
38cf4ff64f2d3cdc4ffa2f06e594d18a965f591a82Spencer Low#include <base/macros.h>
397b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes#include <base/stringprintf.h>
408d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes#include <base/strings.h>
417b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes
42d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#include "adb_auth.h"
43cc731cc76786b6bdc58764aad9924c0d0c8d645fDan Albert#include "adb_io.h"
44e9fca14c9e555a9d02e1d94ba6d3b290673ea26bDan Albert#include "adb_listeners.h"
453d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes#include "adb_utils.h"
467664901a355b959f312e9acff5a0fd31b7139623Dan Albert#include "transport.h"
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
48e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
49e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if !ADB_HOST
51893a4a47e8c9290128b9254af0246e36f821c260Nick Kralevich#include <cutils/properties.h>
52e2864bf727d6a404bd871f063c03e36cc8eedeecNick Kralevich#include <sys/capability.h>
53885342a0f2c834a6b680284047c47c9d04b32565Jeff Sharkey#include <sys/mount.h>
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
569313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan AlbertADB_MUTEX_DEFINE(D_lock);
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
58e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson#if !ADB_HOST
599313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albertconst char* adb_device_banner = "device";
609313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albertstatic android::base::LogdLogger gLogdLogger;
611792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert#else
621792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albertconst char* adb_device_banner = "host";
63e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson#endif
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
659313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albertvoid AdbLogger(android::base::LogId id, android::base::LogSeverity severity,
669313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albert               const char* tag, const char* file, unsigned int line,
679313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albert               const char* message) {
689313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albert    android::base::StderrLogger(id, severity, tag, file, line, message);
699313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albert#if !ADB_HOST
709313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albert    gLogdLogger(id, severity, tag, file, line, message);
719313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albert#endif
729313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albert}
739313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albert
7442ae2604f43ef88be748f125e8733f2c08b83faeElliott Hughesstd::string adb_version() {
7542ae2604f43ef88be748f125e8733f2c08b83faeElliott Hughes    // Don't change the format of this --- it's parsed by ddmlib.
7642ae2604f43ef88be748f125e8733f2c08b83faeElliott Hughes    return android::base::StringPrintf("Android Debug Bridge version %d.%d.%d\n"
7742ae2604f43ef88be748f125e8733f2c08b83faeElliott Hughes                                       "Revision %s\n",
7842ae2604f43ef88be748f125e8733f2c08b83faeElliott Hughes                                       ADB_VERSION_MAJOR, ADB_VERSION_MINOR, ADB_SERVER_VERSION,
7942ae2604f43ef88be748f125e8733f2c08b83faeElliott Hughes                                       ADB_REVISION);
8042ae2604f43ef88be748f125e8733f2c08b83faeElliott Hughes}
8142ae2604f43ef88be748f125e8733f2c08b83faeElliott Hughes
829313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albertvoid fatal(const char *fmt, ...) {
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_list ap;
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_start(ap, fmt);
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr, "error: ");
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    vfprintf(stderr, fmt, ap);
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr, "\n");
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_end(ap);
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    exit(-1);
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
929313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albertvoid fatal_errno(const char* fmt, ...) {
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_list ap;
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_start(ap, fmt);
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr, "error: %s: ", strerror(errno));
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    vfprintf(stderr, fmt, ap);
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr, "\n");
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_end(ap);
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    exit(-1);
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
102ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert#if !ADB_HOST
1039313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albertstatic std::string get_log_file_name() {
104ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    struct tm now;
105ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    time_t t;
106ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    tzset();
107ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    time(&t);
108ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    localtime_r(&t, &now);
109ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert
1108743ef98414b336f222327253f2cde6bf6aee386Dan Albert    char timestamp[PATH_MAX];
1118743ef98414b336f222327253f2cde6bf6aee386Dan Albert    strftime(timestamp, sizeof(timestamp), "%Y-%m-%d-%H-%M-%S", &now);
1128743ef98414b336f222327253f2cde6bf6aee386Dan Albert
1139313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albert    return android::base::StringPrintf("/data/adb/adb-%s-%d", timestamp,
1149313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albert                                       getpid());
1159313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albert}
1169313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albert
1179313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albertvoid start_device_log(void) {
1189313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albert    int fd = unix_open(get_log_file_name().c_str(),
1199313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albert                       O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0640);
120ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    if (fd == -1) {
121ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert        return;
122ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    }
123ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert
1249313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albert    // Redirect stdout and stderr to the log file.
125ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    dup2(fd, STDOUT_FILENO);
126ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    dup2(fd, STDERR_FILENO);
127ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    fprintf(stderr, "--- adb starting (pid %d) ---\n", getpid());
1286ac5d7dc56a016718d2a26803435505e983e5d80Spencer Low    unix_close(fd);
129ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert}
130ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert#endif
131ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert
132ea2175ab6bae74409620374a96fc9a0097a1845cDan Albertint adb_trace_mask;
133ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert
134ea2175ab6bae74409620374a96fc9a0097a1845cDan Albertstd::string get_trace_setting_from_env() {
135ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    const char* setting = getenv("ADB_TRACE");
136ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    if (setting == nullptr) {
137ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert        setting = "";
138ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    }
139ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert
140ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    return std::string(setting);
141ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert}
142ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert
143ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert#if !ADB_HOST
144ea2175ab6bae74409620374a96fc9a0097a1845cDan Albertstd::string get_trace_setting_from_prop() {
145ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    char buf[PROPERTY_VALUE_MAX];
146ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    property_get("persist.adb.trace_mask", buf, "");
147ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    return std::string(buf);
148ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert}
149ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert#endif
150ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert
151ea2175ab6bae74409620374a96fc9a0097a1845cDan Albertstd::string get_trace_setting() {
152ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert#if ADB_HOST
153ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    return get_trace_setting_from_env();
154ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert#else
155ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    return get_trace_setting_from_prop();
156ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert#endif
157ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert}
158ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert
159e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert// Split the space separated list of tags from the trace setting and build the
160e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert// trace mask from it. note that '1' and 'all' are special cases to enable all
161e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert// tracing.
162ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert//
163ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert// adb's trace setting comes from the ADB_TRACE environment variable, whereas
164ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert// adbd's comes from the system property persist.adb.trace_mask.
1659313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albertstatic void setup_trace_mask() {
166ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    const std::string trace_setting = get_trace_setting();
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
168e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert    std::unordered_map<std::string, int> trace_flags = {
169e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert        {"1", 0},
170e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert        {"all", 0},
171e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert        {"adb", TRACE_ADB},
172e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert        {"sockets", TRACE_SOCKETS},
173e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert        {"packets", TRACE_PACKETS},
174e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert        {"rwx", TRACE_RWX},
175e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert        {"usb", TRACE_USB},
176e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert        {"sync", TRACE_SYNC},
177e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert        {"sysdeps", TRACE_SYSDEPS},
178e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert        {"transport", TRACE_TRANSPORT},
179e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert        {"jdwp", TRACE_JDWP},
180e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert        {"services", TRACE_SERVICES},
181e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert        {"auth", TRACE_AUTH}};
182e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert
183e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert    std::vector<std::string> elements = android::base::Split(trace_setting, " ");
184e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert    for (const auto& elem : elements) {
185e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert        const auto& flag = trace_flags.find(elem);
186e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert        if (flag == trace_flags.end()) {
1878d8126a705dd3c5734a0894f88c2c758784bd469Spencer Low            D("Unknown trace flag: %s\n", flag->first.c_str());
188e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert            continue;
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
190e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert
191e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert        if (flag->second == 0) {
192e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert            // 0 is used for the special values "1" and "all" that enable all
193e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert            // tracing.
194e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert            adb_trace_mask = ~0;
195e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert            return;
196e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert        } else {
197e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert            adb_trace_mask |= 1 << flag->second;
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
2009313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albert}
201ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert
2029313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albertvoid adb_trace_init(char** argv) {
2037430916098fd264d569d398614d1d725adfca165Spencer Low#if !ADB_HOST
2046f009d9496fc060ba76f97348aa0702a62fcf927Paul Lawrence    // Don't open log file if no tracing, since this will block
2056f009d9496fc060ba76f97348aa0702a62fcf927Paul Lawrence    // the crypto unmount of /data
2067430916098fd264d569d398614d1d725adfca165Spencer Low    if (!get_trace_setting().empty()) {
2077430916098fd264d569d398614d1d725adfca165Spencer Low        if (isatty(STDOUT_FILENO) == 0) {
2087430916098fd264d569d398614d1d725adfca165Spencer Low            start_device_log();
2097430916098fd264d569d398614d1d725adfca165Spencer Low        }
2109313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albert    }
211ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert#endif
2129313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albert
2139313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albert    setup_trace_mask();
2149313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albert    android::base::InitLogging(argv, AdbLogger);
21542ae2604f43ef88be748f125e8733f2c08b83faeElliott Hughes
21642ae2604f43ef88be748f125e8733f2c08b83faeElliott Hughes    D("%s", adb_version().c_str());
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
219bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albertapacket* get_apacket(void)
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
221bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert    apacket* p = reinterpret_cast<apacket*>(malloc(sizeof(apacket)));
222bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert    if (p == nullptr) {
223bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert      fatal("failed to allocate an apacket");
224bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert    }
225bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(p, 0, sizeof(apacket) - MAX_PAYLOAD);
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return p;
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid put_apacket(apacket *p)
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    free(p);
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
235d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobyvoid handle_online(atransport *t)
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("adb: online\n");
238d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    t->online = 1;
239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid handle_offline(atransport *t)
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("adb: offline\n");
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    //Close the associated usb
245d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    t->online = 0;
24634f45c566365c966c78264e8a4dc0cf69957b6faYabin Cui
247b329824e6c5373ae303269dca285d835ce57e514Yabin Cui    // This is necessary to avoid a race condition that occurred when a transport closes
24834f45c566365c966c78264e8a4dc0cf69957b6faYabin Cui    // while a client socket is still active.
24934f45c566365c966c78264e8a4dc0cf69957b6faYabin Cui    close_all_sockets(t);
25034f45c566365c966c78264e8a4dc0cf69957b6faYabin Cui
251b329824e6c5373ae303269dca285d835ce57e514Yabin Cui    t->RunDisconnects();
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
254d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#if DEBUG_PACKETS
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define DUMPMAX 32
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid print_packet(const char *label, apacket *p)
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *tag;
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *x;
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned count;
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    switch(p->msg.command){
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case A_SYNC: tag = "SYNC"; break;
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case A_CNXN: tag = "CNXN" ; break;
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case A_OPEN: tag = "OPEN"; break;
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case A_OKAY: tag = "OKAY"; break;
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case A_CLSE: tag = "CLSE"; break;
268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case A_WRTE: tag = "WRTE"; break;
269d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    case A_AUTH: tag = "AUTH"; break;
270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    default: tag = "????"; break;
271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr, "%s: %s %08x %08x %04x \"",
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            label, tag, p->msg.arg0, p->msg.arg1, p->msg.data_length);
275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    count = p->msg.data_length;
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    x = (char*) p->data;
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(count > DUMPMAX) {
278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        count = DUMPMAX;
279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        tag = "\n";
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        tag = "\"\n";
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while(count-- > 0){
284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if((*x >= ' ') && (*x < 127)) {
285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fputc(*x, stderr);
286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fputc('.', stderr);
288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        x++;
290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
291d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    fputs(tag, stderr);
292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void send_ready(unsigned local, unsigned remote, atransport *t)
296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("Calling send_ready \n");
298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    apacket *p = get_apacket();
299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.command = A_OKAY;
300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.arg0 = local;
301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.arg1 = remote;
302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    send_packet(p, t);
303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void send_close(unsigned local, unsigned remote, atransport *t)
306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("Calling send_close \n");
308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    apacket *p = get_apacket();
309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.command = A_CLSE;
310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.arg0 = local;
311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.arg1 = remote;
312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    send_packet(p, t);
313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3151792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albertstd::string get_connection_string() {
3161792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    std::vector<std::string> connection_properties;
3171792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert
3181792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert#if !ADB_HOST
3191792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    static const char* cnxn_props[] = {
320e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson        "ro.product.name",
321e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson        "ro.product.model",
322e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson        "ro.product.device",
323e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson    };
3241792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert
3251792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    for (const auto& prop_name : cnxn_props) {
326e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson        char value[PROPERTY_VALUE_MAX];
3271792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert        property_get(prop_name, value, "");
3281792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert        connection_properties.push_back(
3291792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert            android::base::StringPrintf("%s=%s", prop_name, value));
330e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson    }
331e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson#endif
3321792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert
3331792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    connection_properties.push_back(android::base::StringPrintf(
3341792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert        "features=%s", android::base::Join(supported_features(), ',').c_str()));
3351792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert
3361792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    return android::base::StringPrintf(
3371792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert        "%s::%s", adb_device_banner,
3381792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert        android::base::Join(connection_properties, ';').c_str());
339e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson}
340e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson
3411792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albertvoid send_connect(atransport* t) {
342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("Calling send_connect \n");
3431792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    apacket* cp = get_apacket();
344dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    cp->msg.command = A_CNXN;
3453d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer    cp->msg.arg0 = t->get_protocol_version();
3463d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer    cp->msg.arg1 = t->get_max_payload();
3471792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert
3481792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    std::string connection_str = get_connection_string();
3491792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    // Connect and auth packets are limited to MAX_PAYLOAD_V1 because we don't
3501792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    // yet know how much data the other size is willing to accept.
3511792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    if (connection_str.length() > MAX_PAYLOAD_V1) {
3521792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert        LOG(FATAL) << "Connection banner is too long (length = "
3531792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert                   << connection_str.length() << ")";
3541792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    }
3551792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert
3561792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    memcpy(cp->data, connection_str.c_str(), connection_str.length());
3571792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    cp->msg.data_length = connection_str.length();
3581792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert
359dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    send_packet(cp, t);
360d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby}
361d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
3628d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes// qual_overwrite is used to overwrite a qualifier string.  dst is a
3638d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes// pointer to a char pointer.  It is assumed that if *dst is non-NULL, it
3648d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes// was malloc'ed and needs to freed.  *dst will be set to a dup of src.
3658d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes// TODO: switch to std::string for these atransport fields instead.
3668d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughesstatic void qual_overwrite(char** dst, const std::string& src) {
367e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson    free(*dst);
3688d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    *dst = strdup(src.c_str());
369e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson}
370e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson
3711792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albertvoid parse_banner(const std::string& banner, atransport* t) {
3721792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    D("parse_banner: %s\n", banner.c_str());
3738d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes
3748d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    // The format is something like:
3758d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    // "device::ro.product.name=x;ro.product.model=y;ro.product.device=z;".
3768d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    std::vector<std::string> pieces = android::base::Split(banner, ":");
3778d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes
3788d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    if (pieces.size() > 2) {
3798d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes        const std::string& props = pieces[2];
3808d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes        for (auto& prop : android::base::Split(props, ";")) {
3818d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes            // The list of properties was traditionally ;-terminated rather than ;-separated.
3828d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes            if (prop.empty()) continue;
3838d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes
3848d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes            std::vector<std::string> key_value = android::base::Split(prop, "=");
3858d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes            if (key_value.size() != 2) continue;
3868d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes
3878d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes            const std::string& key = key_value[0];
3888d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes            const std::string& value = key_value[1];
3898d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes            if (key == "ro.product.name") {
3908d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes                qual_overwrite(&t->product, value);
3918d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes            } else if (key == "ro.product.model") {
3928d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes                qual_overwrite(&t->model, value);
3938d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes            } else if (key == "ro.product.device") {
3948d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes                qual_overwrite(&t->device, value);
3951792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert            } else if (key == "features") {
3961792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert                for (const auto& feature : android::base::Split(value, ",")) {
3971792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert                    t->add_feature(feature);
3981792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert                }
399e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson            }
400e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson        }
401dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
402dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
4038d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    const std::string& type = pieces[0];
4048d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    if (type == "bootloader") {
405dcd78a15d0be143d48fc93af6a9fa5748dbf9790Dan Albert        D("setting connection_state to kCsBootloader\n");
406dcd78a15d0be143d48fc93af6a9fa5748dbf9790Dan Albert        t->connection_state = kCsBootloader;
407dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        update_transports();
4088d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    } else if (type == "device") {
409dcd78a15d0be143d48fc93af6a9fa5748dbf9790Dan Albert        D("setting connection_state to kCsDevice\n");
410dcd78a15d0be143d48fc93af6a9fa5748dbf9790Dan Albert        t->connection_state = kCsDevice;
411dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        update_transports();
4128d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    } else if (type == "recovery") {
413dcd78a15d0be143d48fc93af6a9fa5748dbf9790Dan Albert        D("setting connection_state to kCsRecovery\n");
414dcd78a15d0be143d48fc93af6a9fa5748dbf9790Dan Albert        t->connection_state = kCsRecovery;
415dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        update_transports();
4168d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    } else if (type == "sideload") {
417dcd78a15d0be143d48fc93af6a9fa5748dbf9790Dan Albert        D("setting connection_state to kCsSideload\n");
418dcd78a15d0be143d48fc93af6a9fa5748dbf9790Dan Albert        t->connection_state = kCsSideload;
419447f061da19fe46bae35f1cdd93eeb16bc225463Doug Zongker        update_transports();
4203ce9575af76fa6dc110506080434303b9459abf4Elliott Hughes    } else {
421dcd78a15d0be143d48fc93af6a9fa5748dbf9790Dan Albert        D("setting connection_state to kCsHost\n");
422dcd78a15d0be143d48fc93af6a9fa5748dbf9790Dan Albert        t->connection_state = kCsHost;
423447f061da19fe46bae35f1cdd93eeb16bc225463Doug Zongker    }
424dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
425dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
4261792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albertstatic void handle_new_connection(atransport* t, apacket* p) {
4271792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    if (t->connection_state != kCsOffline) {
4281792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert        t->connection_state = kCsOffline;
4291792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert        handle_offline(t);
4301792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    }
4311792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert
4321792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    t->update_version(p->msg.arg0, p->msg.arg1);
4331792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    std::string banner(reinterpret_cast<const char*>(p->data),
4341792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert                       p->msg.data_length);
4351792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    parse_banner(banner, t);
4361792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert
4371792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert#if ADB_HOST
4381792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    handle_online(t);
4391792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert#else
4401792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    if (!auth_required) {
4411792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert        handle_online(t);
4421792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert        send_connect(t);
4431792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    } else {
4441792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert        send_auth_request(t);
4451792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    }
4461792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert#endif
4471792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert}
4481792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert
449dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid handle_packet(apacket *p, atransport *t)
450dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asocket *s;
452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
453899913f8168b54e00971c0e8d4ae16d06a4651feViral Mehta    D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0],
454899913f8168b54e00971c0e8d4ae16d06a4651feViral Mehta            ((char*) (&(p->msg.command)))[1],
455899913f8168b54e00971c0e8d4ae16d06a4651feViral Mehta            ((char*) (&(p->msg.command)))[2],
456899913f8168b54e00971c0e8d4ae16d06a4651feViral Mehta            ((char*) (&(p->msg.command)))[3]);
457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    print_packet("recv", p);
458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    switch(p->msg.command){
460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case A_SYNC:
461dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(p->msg.arg0){
462dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            send_packet(p, t);
463661327e8e40f95076e0e8abe86193da16b061bd8Yabin Cui#if ADB_HOST
464661327e8e40f95076e0e8abe86193da16b061bd8Yabin Cui            send_connect(t);
465661327e8e40f95076e0e8abe86193da16b061bd8Yabin Cui#endif
466dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
467dcd78a15d0be143d48fc93af6a9fa5748dbf9790Dan Albert            t->connection_state = kCsOffline;
468dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            handle_offline(t);
469dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            send_packet(p, t);
470dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
471dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return;
472dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
4731792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    case A_CNXN:  // CONNECT(version, maxdata, "system-id-string")
4741792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert        handle_new_connection(t, p);
475d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        break;
476d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
477d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    case A_AUTH:
478d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        if (p->msg.arg0 == ADB_AUTH_TOKEN) {
479dcd78a15d0be143d48fc93af6a9fa5748dbf9790Dan Albert            t->connection_state = kCsUnauthorized;
480d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby            t->key = adb_auth_nextkey(t->key);
481d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby            if (t->key) {
482d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby                send_auth_response(p->data, p->msg.data_length, t);
483d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby            } else {
484d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby                /* No more private keys to try, send the public key */
485d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby                send_auth_publickey(t);
486d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby            }
487d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        } else if (p->msg.arg0 == ADB_AUTH_SIGNATURE) {
488d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby            if (adb_auth_verify(t->token, p->data, p->msg.data_length)) {
489d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby                adb_auth_verified(t);
490d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby                t->failed_auth_attempts = 0;
491d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby            } else {
492d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby                if (t->failed_auth_attempts++ > 10)
493d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby                    adb_sleep_ms(1000);
494d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby                send_auth_request(t);
495d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby            }
496d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        } else if (p->msg.arg0 == ADB_AUTH_RSAPUBLICKEY) {
497d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby            adb_auth_confirm_key(p->data, p->msg.data_length, t);
498d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        }
499dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
500dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
501dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case A_OPEN: /* OPEN(local-id, 0, "destination") */
502818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner        if (t->online && p->msg.arg0 != 0 && p->msg.arg1 == 0) {
503dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char *name = (char*) p->data;
504dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0;
505dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            s = create_local_service_socket(name);
506dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(s == 0) {
507dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                send_close(0, p->msg.arg0, t);
508dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else {
509dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                s->peer = create_remote_socket(p->msg.arg0, t);
510dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                s->peer->peer = s;
511dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                send_ready(s->id, s->peer->id, t);
512dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                s->ready(s);
513dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
514dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
515dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
516dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
517dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case A_OKAY: /* READY(local-id, remote-id, "") */
518818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner        if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) {
519818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner            if((s = find_local_socket(p->msg.arg1, 0))) {
520dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if(s->peer == 0) {
521818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                    /* On first READY message, create the connection. */
522dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    s->peer = create_remote_socket(p->msg.arg0, t);
523dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    s->peer->peer = s;
524818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                    s->ready(s);
525818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                } else if (s->peer->id == p->msg.arg0) {
526818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                    /* Other READY messages must use the same local-id */
527818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                    s->ready(s);
528818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                } else {
529818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                    D("Invalid A_OKAY(%d,%d), expected A_OKAY(%d,%d) on transport %s\n",
530818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                      p->msg.arg0, p->msg.arg1, s->peer->id, p->msg.arg1, t->serial);
531dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
532dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
533dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
534dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
535dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
536818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    case A_CLSE: /* CLOSE(local-id, remote-id, "") or CLOSE(0, remote-id, "") */
537818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner        if (t->online && p->msg.arg1 != 0) {
538818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner            if((s = find_local_socket(p->msg.arg1, p->msg.arg0))) {
539818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                /* According to protocol.txt, p->msg.arg0 might be 0 to indicate
540818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                 * a failed OPEN only. However, due to a bug in previous ADB
541818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                 * versions, CLOSE(0, remote-id, "") was also used for normal
542818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                 * CLOSE() operations.
543818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                 *
544818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                 * This is bad because it means a compromised adbd could
545818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                 * send packets to close connections between the host and
546818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                 * other devices. To avoid this, only allow this if the local
547818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                 * socket has a peer on the same transport.
548818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                 */
549818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                if (p->msg.arg0 == 0 && s->peer && s->peer->transport != t) {
550818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                    D("Invalid A_CLSE(0, %u) from transport %s, expected transport %s\n",
551818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                      p->msg.arg1, t->serial, s->peer->transport->serial);
552818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                } else {
553818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                    s->close(s);
554818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                }
555dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
556dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
557dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
558dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
559818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    case A_WRTE: /* WRITE(local-id, remote-id, <data>) */
560818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner        if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) {
561818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner            if((s = find_local_socket(p->msg.arg1, p->msg.arg0))) {
562dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                unsigned rid = p->msg.arg0;
563dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                p->len = p->msg.data_length;
564dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
565dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if(s->enqueue(s, p) == 0) {
566dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    D("Enqueue the socket\n");
567dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    send_ready(s->id, rid, t);
568dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
569dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                return;
570dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
571dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
572dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
573dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
574dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    default:
575dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        printf("handle_packet: what is %08x?!\n", p->msg.command);
576dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
577dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
578dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    put_apacket(p);
579dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
580dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
581dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if ADB_HOST
582571c1367682c83cb23481cc9c1028c8588a1fed0JP Abgrall
5832122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low#ifdef _WIN32
5842122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
5852122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Lowstatic bool _make_handle_noninheritable(HANDLE h) {
5862122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    if (h != INVALID_HANDLE_VALUE && h != NULL) {
5872122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        if (!SetHandleInformation(h, HANDLE_FLAG_INHERIT, 0)) {
5882122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            // Show the handle value to give us a clue in case we have problems
5892122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            // with pseudo-handle values.
5902122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            fprintf(stderr, "Cannot make handle 0x%p non-inheritable: %s\n",
5912122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                    h, SystemErrorCodeToString(GetLastError()).c_str());
5922122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            return false;
5932122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        }
5942122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    }
5952122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
5962122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    return true;
5972122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low}
5982122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
5992122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low// Create anonymous pipe, preventing inheritance of the read pipe and setting
6002122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low// security of the write pipe to sa.
6012122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Lowstatic bool _create_anonymous_pipe(unique_handle* pipe_read_out,
6022122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                                   unique_handle* pipe_write_out,
6032122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                                   SECURITY_ATTRIBUTES* sa) {
6042122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    HANDLE pipe_read_raw = NULL;
6052122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    HANDLE pipe_write_raw = NULL;
6062122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    if (!CreatePipe(&pipe_read_raw, &pipe_write_raw, sa, 0)) {
6072122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        fprintf(stderr, "Cannot create pipe: %s\n",
6082122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                SystemErrorCodeToString(GetLastError()).c_str());
6092122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        return false;
6102122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    }
6112122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
6122122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    unique_handle pipe_read(pipe_read_raw);
6132122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    pipe_read_raw = NULL;
6142122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    unique_handle pipe_write(pipe_write_raw);
6152122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    pipe_write_raw = NULL;
6162122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
6172122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    if (!_make_handle_noninheritable(pipe_read.get())) {
6182122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        return false;
6192122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    }
6202122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
6212122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    *pipe_read_out = std::move(pipe_read);
6222122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    *pipe_write_out = std::move(pipe_write);
6232122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
6242122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    return true;
6252122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low}
6262122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
6272122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low// Read from a pipe (that we take ownership of) and write what is returned to
6282122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low// GetStdHandle(nStdHandle). Return on error or when the pipe is closed.
6292122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Lowstatic unsigned _redirect_pipe_thread(HANDLE h, DWORD nStdHandle) {
6302122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // Take ownership of the HANDLE and close when we're done.
6312122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    unique_handle   read_pipe(h);
6322122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    const HANDLE    write_handle = GetStdHandle(nStdHandle);
6332122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    const char*     output_name = nStdHandle == STD_OUTPUT_HANDLE ?
6342122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                                      "stdout" : "stderr";
6352122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
6362122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    while (true) {
6372122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        char    buf[64 * 1024];
6382122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        DWORD   bytes_read = 0;
6392122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        if (!ReadFile(read_pipe.get(), buf, sizeof(buf), &bytes_read, NULL)) {
6402122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            const DWORD err = GetLastError();
6412122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            // ERROR_BROKEN_PIPE is expected when the subprocess closes
6422122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            // the other end of the pipe.
6432122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            if (err == ERROR_BROKEN_PIPE) {
6442122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                return EXIT_SUCCESS;
6452122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            } else {
6462122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                fprintf(stderr, "Failed to read from %s: %s\n", output_name,
6472122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                        SystemErrorCodeToString(err).c_str());
6482122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                return EXIT_FAILURE;
6492122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            }
6502122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        }
6512122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
6522122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        // Don't try to write if our stdout/stderr was not setup by the
6532122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        // parent process.
6542122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        if (write_handle != NULL && write_handle != INVALID_HANDLE_VALUE) {
6552122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            DWORD   bytes_written = 0;
6562122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            if (!WriteFile(write_handle, buf, bytes_read, &bytes_written,
6572122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                           NULL)) {
6582122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                fprintf(stderr, "Failed to write to %s: %s\n", output_name,
6592122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                        SystemErrorCodeToString(GetLastError()).c_str());
6602122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                return EXIT_FAILURE;
6612122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            }
6622122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
6632122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            if (bytes_written != bytes_read) {
6642122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                fprintf(stderr, "Only wrote %lu of %lu bytes to %s\n",
6652122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                        bytes_written, bytes_read, output_name);
6662122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                return EXIT_FAILURE;
6672122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            }
6682122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        }
6692122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    }
6702122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low}
6712122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
6722122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Lowstatic unsigned __stdcall _redirect_stdout_thread(HANDLE h) {
6732122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    return _redirect_pipe_thread(h, STD_OUTPUT_HANDLE);
6742122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low}
6752122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
6762122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Lowstatic unsigned __stdcall _redirect_stderr_thread(HANDLE h) {
6772122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    return _redirect_pipe_thread(h, STD_ERROR_HANDLE);
6782122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low}
6792122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
6802122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low#endif
6812122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
682a84a42eb20d43ffa2695a69d583a6e09532b49d9Stefan Hilzingerint launch_server(int server_port)
683dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
684e77b6a08623bba383ce55cd6653bec76cdf57792Yabin Cui#if defined(_WIN32)
685dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* we need to start the server in the background                    */
686dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* we create a PIPE that will be used to wait for the server's "OK" */
687dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* message since the pipe handles must be inheritable, we use a     */
688dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* security attribute                                               */
689dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SECURITY_ATTRIBUTES   sa;
690dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sa.nLength = sizeof(sa);
691dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sa.lpSecurityDescriptor = NULL;
692dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sa.bInheritHandle = TRUE;
693dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
6942122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // Redirect stdin to Windows /dev/null. If we instead pass an original
6952122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // stdin/stdout/stderr handle and it is a console handle, when the adb
6962122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // server starts up, the C Runtime will see a console handle for a process
6972122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // that isn't connected to a console and it will configure
6982122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // stdin/stdout/stderr to be closed. At that point, freopen() could be used
6992122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // to reopen stderr/out, but it would take more massaging to fixup the file
7002122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // descriptor number that freopen() uses. It's simplest to avoid all of this
7012122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // complexity by just redirecting stdin to `nul' and then the C Runtime acts
7022122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // as expected.
7032122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    unique_handle   nul_read(CreateFileW(L"nul", GENERIC_READ,
7042122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, OPEN_EXISTING,
7052122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            FILE_ATTRIBUTE_NORMAL, NULL));
7062122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    if (nul_read.get() == INVALID_HANDLE_VALUE) {
7072122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        fprintf(stderr, "Cannot open 'nul': %s\n",
7088df90321769c670b546a7ff0e7a14f2d7a79cc25Spencer Low                SystemErrorCodeToString(GetLastError()).c_str());
709d0f66c361641dc30162877ee3e4b4690d6833442Spencer Low        return -1;
710d0f66c361641dc30162877ee3e4b4690d6833442Spencer Low    }
711d0f66c361641dc30162877ee3e4b4690d6833442Spencer Low
7122122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // create pipes with non-inheritable read handle, inheritable write handle
7132122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    unique_handle   ack_read, ack_write;
7142122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    if (!_create_anonymous_pipe(&ack_read, &ack_write, &sa)) {
715d0f66c361641dc30162877ee3e4b4690d6833442Spencer Low        return -1;
716d0f66c361641dc30162877ee3e4b4690d6833442Spencer Low    }
7172122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    unique_handle   stdout_read, stdout_write;
7182122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    if (!_create_anonymous_pipe(&stdout_read, &stdout_write, &sa)) {
7192122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        return -1;
7202122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    }
7212122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    unique_handle   stderr_read, stderr_write;
7222122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    if (!_create_anonymous_pipe(&stderr_read, &stderr_write, &sa)) {
723dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
724dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
725dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
726267aa8b00eadf273321e492026af74b7baad890eRay Donnelly    /* Some programs want to launch an adb command and collect its output by
727267aa8b00eadf273321e492026af74b7baad890eRay Donnelly     * calling CreateProcess with inheritable stdout/stderr handles, then
728267aa8b00eadf273321e492026af74b7baad890eRay Donnelly     * using read() to get its output. When this happens, the stdout/stderr
729267aa8b00eadf273321e492026af74b7baad890eRay Donnelly     * handles passed to the adb client process will also be inheritable.
730267aa8b00eadf273321e492026af74b7baad890eRay Donnelly     * When starting the adb server here, care must be taken to reset them
731267aa8b00eadf273321e492026af74b7baad890eRay Donnelly     * to non-inheritable.
732267aa8b00eadf273321e492026af74b7baad890eRay Donnelly     * Otherwise, something bad happens: even if the adb command completes,
733267aa8b00eadf273321e492026af74b7baad890eRay Donnelly     * the calling process is stuck while read()-ing from the stdout/stderr
734267aa8b00eadf273321e492026af74b7baad890eRay Donnelly     * descriptors, because they're connected to corresponding handles in the
735267aa8b00eadf273321e492026af74b7baad890eRay Donnelly     * adb server process (even if the latter never uses/writes to them).
7362122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low     * Note that even if we don't pass these handles in the STARTUPINFO struct,
7372122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low     * if they're marked inheritable, they're still inherited, requiring us to
7382122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low     * deal with this.
7392122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low     *
7402122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low     * If we're still having problems with inheriting random handles in the
7412122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low     * future, consider using PROC_THREAD_ATTRIBUTE_HANDLE_LIST to explicitly
7422122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low     * specify which handles should be inherited: http://blogs.msdn.com/b/oldnewthing/archive/2011/12/16/10248328.aspx
743267aa8b00eadf273321e492026af74b7baad890eRay Donnelly     */
7442122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    if (!_make_handle_noninheritable(GetStdHandle(STD_INPUT_HANDLE))) {
7452122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        return -1;
746267aa8b00eadf273321e492026af74b7baad890eRay Donnelly    }
7472122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    if (!_make_handle_noninheritable(GetStdHandle(STD_OUTPUT_HANDLE))) {
7482122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        return -1;
7492122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    }
7502122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    if (!_make_handle_noninheritable(GetStdHandle(STD_ERROR_HANDLE))) {
7512122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        return -1;
752267aa8b00eadf273321e492026af74b7baad890eRay Donnelly    }
753267aa8b00eadf273321e492026af74b7baad890eRay Donnelly
7542122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    STARTUPINFOW    startup;
755dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ZeroMemory( &startup, sizeof(startup) );
756dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    startup.cb = sizeof(startup);
7572122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    startup.hStdInput  = nul_read.get();
7582122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    startup.hStdOutput = stdout_write.get();
7592122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    startup.hStdError  = stderr_write.get();
760dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    startup.dwFlags    = STARTF_USESTDHANDLES;
761dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
7625c398d2ce96150e94e596e959bfe2246b94de660Spencer Low    // Verify that the pipe_write handle value can be passed on the command line
7635c398d2ce96150e94e596e959bfe2246b94de660Spencer Low    // as %d and that the rest of adb code can pass it around in an int.
7642122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    const int ack_write_as_int = cast_handle_to_int(ack_write.get());
7652122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    if (cast_int_to_handle(ack_write_as_int) != ack_write.get()) {
7665c398d2ce96150e94e596e959bfe2246b94de660Spencer Low        // If this fires, either handle values are larger than 32-bits or else
7675c398d2ce96150e94e596e959bfe2246b94de660Spencer Low        // there is a bug in our casting.
7685c398d2ce96150e94e596e959bfe2246b94de660Spencer Low        // https://msdn.microsoft.com/en-us/library/windows/desktop/aa384203%28v=vs.85%29.aspx
7692122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        fprintf(stderr, "Cannot fit pipe handle value into 32-bits: 0x%p\n",
7702122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                ack_write.get());
7715c398d2ce96150e94e596e959bfe2246b94de660Spencer Low        return -1;
7725c398d2ce96150e94e596e959bfe2246b94de660Spencer Low    }
7735c398d2ce96150e94e596e959bfe2246b94de660Spencer Low
7742122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // get path of current program
7752122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    WCHAR       program_path[MAX_PATH];
7762122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    const DWORD module_result = GetModuleFileNameW(NULL, program_path,
7772122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                                                   arraysize(program_path));
7782122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    if ((module_result >= arraysize(program_path)) || (module_result == 0)) {
7792122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        // String truncation or some other error.
7802122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        fprintf(stderr, "Cannot get executable path: %s\n",
7812122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                SystemErrorCodeToString(GetLastError()).c_str());
7822122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        return -1;
7832122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    }
7842122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
7852122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    WCHAR   args[64];
786cf4ff64f2d3cdc4ffa2f06e594d18a965f591a82Spencer Low    snwprintf(args, arraysize(args),
7875c398d2ce96150e94e596e959bfe2246b94de660Spencer Low              L"adb -P %d fork-server server --reply-fd %d", server_port,
7882122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low              ack_write_as_int);
7892122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
7902122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    PROCESS_INFORMATION   pinfo;
7912122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    ZeroMemory(&pinfo, sizeof(pinfo));
7922122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
7932122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    if (!CreateProcessW(
794dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            program_path,                              /* program path  */
795a09558c2e205771e6830eeb6241c5c0e3b1cf4ceWenhao Li            args,
796dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                    /* the fork-server argument will set the
797dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                       debug = 2 in the child           */
798dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            NULL,                   /* process handle is not inheritable */
799dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            NULL,                    /* thread handle is not inheritable */
800dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            TRUE,                          /* yes, inherit some handles */
801dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            DETACHED_PROCESS, /* the new process doesn't have a console */
802dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            NULL,                     /* use parent's environment block */
803dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            NULL,                    /* use parent's starting directory */
804dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            &startup,                 /* startup info, i.e. std handles */
8052122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            &pinfo )) {
8062122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        fprintf(stderr, "Cannot create process: %s\n",
8072122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                SystemErrorCodeToString(GetLastError()).c_str());
8082122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        return -1;
8092122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    }
810dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
8112122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    unique_handle   process_handle(pinfo.hProcess);
8122122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    pinfo.hProcess = NULL;
8132122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
8142122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // Close handles that we no longer need to complete the rest.
8152122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    CloseHandle(pinfo.hThread);
8162122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    pinfo.hThread = NULL;
8172122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
8182122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    nul_read.reset();
8192122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    ack_write.reset();
8202122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    stdout_write.reset();
8212122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    stderr_write.reset();
8222122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
8232122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // Start threads to read from subprocess stdout/stderr and write to ours
8242122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // to make subprocess errors easier to diagnose.
8252122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
8262122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // In the past, reading from a pipe before the child process's C Runtime
8272122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // started up and called GetFileType() caused a hang: http://blogs.msdn.com/b/oldnewthing/archive/2011/12/02/10243553.aspx#10244216
8282122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // This is reportedly fixed in Windows Vista: https://support.microsoft.com/en-us/kb/2009703
8292122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // I was unable to reproduce the problem on Windows XP. It sounds like a
8302122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // Windows Update may have fixed this: https://www.duckware.com/tech/peeknamedpipe.html
8312122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    unique_handle   stdout_thread(reinterpret_cast<HANDLE>(
8322122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            _beginthreadex(NULL, 0, _redirect_stdout_thread, stdout_read.get(),
8332122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                           0, NULL)));
8342122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    if (stdout_thread.get() == nullptr) {
8352122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        fprintf(stderr, "Cannot create thread: %s\n", strerror(errno));
8362122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        return -1;
8372122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    }
8382122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    stdout_read.release();  // Transfer ownership to new thread
839dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
8402122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    unique_handle   stderr_thread(reinterpret_cast<HANDLE>(
8412122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            _beginthreadex(NULL, 0, _redirect_stderr_thread, stderr_read.get(),
8422122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                           0, NULL)));
8432122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    if (stderr_thread.get() == nullptr) {
8442122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        fprintf(stderr, "Cannot create thread: %s\n", strerror(errno));
845dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
846dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
8472122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    stderr_read.release();  // Transfer ownership to new thread
848dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
8492122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    bool    got_ack = false;
850dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
8512122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // Wait for the "OK\n" message, for the pipe to be closed, or other error.
852dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    {
8532122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        char    temp[3];
8542122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        DWORD   count = 0;
8552122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
8562122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        if (ReadFile(ack_read.get(), temp, sizeof(temp), &count, NULL)) {
8572122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            const CHAR  expected[] = "OK\n";
8582122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            const DWORD expected_length = arraysize(expected) - 1;
8592122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            if (count == expected_length &&
8602122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                memcmp(temp, expected, expected_length) == 0) {
8612122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                got_ack = true;
8622122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            } else {
8632122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                fprintf(stderr, "ADB server didn't ACK\n");
8642122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            }
8652122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        } else {
8662122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            const DWORD err = GetLastError();
8672122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            // If the ACK was not written and the process exited, GetLastError()
8682122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            // is probably ERROR_BROKEN_PIPE, in which case that info is not
8692122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            // useful to the user.
8702122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            fprintf(stderr, "could not read ok from ADB Server%s\n",
8712122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                    err == ERROR_BROKEN_PIPE ? "" :
8722122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                    android::base::StringPrintf(": %s",
8732122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                            SystemErrorCodeToString(err).c_str()).c_str());
874dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
8752122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    }
8762122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
8772122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // Always try to wait a bit for threads reading stdout/stderr to finish.
8782122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // If the process started ok, it should close the pipes causing the threads
8792122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // to finish. If the process had an error, it should exit, also causing
8802122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // the pipes to be closed. In that case we want to read all of the output
8812122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // and write it out so that the user can diagnose failures.
8822122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    const DWORD     thread_timeout_ms = 15 * 1000;
8832122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    const HANDLE    threads[] = { stdout_thread.get(), stderr_thread.get() };
8842122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    const DWORD     wait_result = WaitForMultipleObjects(arraysize(threads),
8852122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            threads, TRUE, thread_timeout_ms);
8862122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    if (wait_result == WAIT_TIMEOUT) {
8872122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        // Threads did not finish after waiting a little while. Perhaps the
8882122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        // server didn't close pipes, or it is hung.
8892122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        fprintf(stderr, "Timed-out waiting for threads to finish reading from "
8902122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                "ADB Server\n");
8912122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        // Process handles are signaled when the process exits, so if we wait
8922122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        // on the handle for 0 seconds and it returns 'timeout', that means that
8932122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        // the process is still running.
8942122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        if (WaitForSingleObject(process_handle.get(), 0) == WAIT_TIMEOUT) {
8952122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            // We could TerminateProcess(), but that seems somewhat presumptive.
8962122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            fprintf(stderr, "ADB Server is running: process id %lu\n",
8972122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                    pinfo.dwProcessId);
898dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
8992122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        return -1;
9002122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    }
9012122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
9022122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    if (wait_result != WAIT_OBJECT_0) {
9032122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        fprintf(stderr, "Unexpected result waiting for threads: %lu: %s\n",
9042122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                wait_result, SystemErrorCodeToString(GetLastError()).c_str());
9052122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        return -1;
9062122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    }
9072122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
9082122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // For now ignore the thread exit codes and assume they worked properly.
9092122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
9102122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    if (!got_ack) {
9112122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        return -1;
912dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
913e77b6a08623bba383ce55cd6653bec76cdf57792Yabin Cui#else /* !defined(_WIN32) */
914dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char    path[PATH_MAX];
915dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int     fd[2];
916dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
917dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // set up a pipe so the child can tell us when it is ready.
9189f2d1a9cfc04e1d5970823da1878097288a9a9cdSiva Velusamy    // fd[0] will be parent's end, and the child will write on fd[1]
919dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (pipe(fd)) {
920dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr, "pipe failed in launch_server, errno: %d\n", errno);
921dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
922dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
9233166410a82f43d39201be98a8d35c51baa86cb53Alexey Tarasov    get_my_path(path, PATH_MAX);
924dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    pid_t pid = fork();
925dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(pid < 0) return -1;
926dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
927dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (pid == 0) {
928dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // child side of the fork
929dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
930dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_close(fd[0]);
931dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
932d7b33085117ccbb908a883f624cb1fe5495ee92aMatt Gumbel        char str_port[30];
9339f2d1a9cfc04e1d5970823da1878097288a9a9cdSiva Velusamy        snprintf(str_port, sizeof(str_port), "%d", server_port);
9349f2d1a9cfc04e1d5970823da1878097288a9a9cdSiva Velusamy        char reply_fd[30];
9359f2d1a9cfc04e1d5970823da1878097288a9a9cdSiva Velusamy        snprintf(reply_fd, sizeof(reply_fd), "%d", fd[1]);
936dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // child process
9379f2d1a9cfc04e1d5970823da1878097288a9a9cdSiva Velusamy        int result = execl(path, "adb", "-P", str_port, "fork-server", "server", "--reply-fd", reply_fd, NULL);
938dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // this should not return
939dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno);
940dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else  {
941dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // parent side of the fork
942dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
943dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char  temp[3];
944dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
945dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        temp[0] = 'A'; temp[1] = 'B'; temp[2] = 'C';
946dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // wait for the "OK\n" message
947dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_close(fd[1]);
948dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int ret = adb_read(fd[0], temp, 3);
949408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        int saved_errno = errno;
950dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_close(fd[0]);
951dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (ret < 0) {
952408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            fprintf(stderr, "could not read ok from ADB Server, errno = %d\n", saved_errno);
953dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
954dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
955dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (ret != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') {
956dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fprintf(stderr, "ADB server didn't ACK\n" );
957dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
958dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
959dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
960dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        setsid();
961dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
962e77b6a08623bba383ce55cd6653bec76cdf57792Yabin Cui#endif /* !defined(_WIN32) */
963dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
964dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
965e77b6a08623bba383ce55cd6653bec76cdf57792Yabin Cui#endif /* ADB_HOST */
966dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
967252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner// Try to handle a network forwarding request.
968252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner// This returns 1 on success, 0 on failure, and -1 to indicate this is not
969252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner// a forwarding-related request.
970aee80fb67bcc3fc5209050c40bd8efc1bbcc0610Elliott Hughesint handle_forward_request(const char* service, TransportType type, const char* serial, int reply_fd)
971252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner{
972252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    if (!strcmp(service, "list-forward")) {
973252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        // Create the list of forward redirections.
974e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes        std::string listeners = format_listeners();
975252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner#if ADB_HOST
976e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes        SendOkay(reply_fd);
977252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner#endif
978e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes        SendProtocolString(reply_fd, listeners);
979252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        return 1;
980252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    }
981252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
982252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    if (!strcmp(service, "killforward-all")) {
983252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        remove_all_listeners();
984252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner#if ADB_HOST
985252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        /* On the host: 1st OKAY is connect, 2nd OKAY is status */
986e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes        SendOkay(reply_fd);
987252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner#endif
988e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes        SendOkay(reply_fd);
989252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        return 1;
990252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    }
991252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
992424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes    if (!strncmp(service, "forward:", 8) || !strncmp(service, "killforward:", 12)) {
993424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes        // killforward:local
994424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes        // forward:(norebind:)?local;remote
995424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes        bool kill_forward = false;
996424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes        bool no_rebind = false;
997424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes        if (android::base::StartsWith(service, "killforward:")) {
998424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes            kill_forward = true;
999424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes            service += 12;
1000a6b340af123b82e3aaa33cb2a0d45f637eeb4759Spencer Low        } else {
1001a6b340af123b82e3aaa33cb2a0d45f637eeb4759Spencer Low            service += 8;   // skip past "forward:"
1002424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes            if (android::base::StartsWith(service, "norebind:")) {
1003424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes                no_rebind = true;
1004424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes                service += 9;
1005424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes            }
1006252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        }
1007252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
1008424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes        std::vector<std::string> pieces = android::base::Split(service, ";");
1009252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
1010424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes        if (kill_forward) {
1011424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes            // Check killforward: parameter format: '<local>'
1012424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes            if (pieces.size() != 1 || pieces[0].empty()) {
1013424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes                SendFail(reply_fd, android::base::StringPrintf("bad killforward: %s", service));
1014252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner                return 1;
1015252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner            }
1016252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        } else {
1017424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes            // Check forward: parameter format: '<local>;<remote>'
1018424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes            if (pieces.size() != 2 || pieces[0].empty() || pieces[1].empty() || pieces[1][0] == '*') {
1019424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes                SendFail(reply_fd, android::base::StringPrintf("bad forward: %s", service));
1020252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner                return 1;
1021252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner            }
1022252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        }
1023252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
10247be29c819b4fb8bf9b1d4b69a4333f8765de0281Elliott Hughes        std::string error_msg;
1025424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes        atransport* transport = acquire_one_transport(kCsAny, type, serial, &error_msg);
1026252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        if (!transport) {
1027e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes            SendFail(reply_fd, error_msg);
1028252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner            return 1;
1029252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        }
1030252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
10315200c6670f041550c23821fec8e8e49b30ef6d29Spencer Low        std::string error;
10323bd73c12c07dcefc965abeef535ac53c4754d682Elliott Hughes        InstallStatus r;
1033424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes        if (kill_forward) {
1034424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes            r = remove_listener(pieces[0].c_str(), transport);
1035252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        } else {
10365200c6670f041550c23821fec8e8e49b30ef6d29Spencer Low            r = install_listener(pieces[0], pieces[1].c_str(), transport,
10375200c6670f041550c23821fec8e8e49b30ef6d29Spencer Low                                 no_rebind, &error);
1038252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        }
10397b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes        if (r == INSTALL_STATUS_OK) {
1040252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner#if ADB_HOST
1041252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner            /* On the host: 1st OKAY is connect, 2nd OKAY is status */
1042e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes            SendOkay(reply_fd);
1043252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner#endif
1044e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes            SendOkay(reply_fd);
1045252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner            return 1;
1046252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        }
1047252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
10487b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes        std::string message;
10497b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes        switch (r) {
1050424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes          case INSTALL_STATUS_OK: message = "success (!)"; break;
10517b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes          case INSTALL_STATUS_INTERNAL_ERROR: message = "internal error"; break;
10527b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes          case INSTALL_STATUS_CANNOT_BIND:
1053bf7c605d87f87c03066c384cecb0f0c91aa31403Spencer Low            message = android::base::StringPrintf("cannot bind listener: %s",
10545200c6670f041550c23821fec8e8e49b30ef6d29Spencer Low                                                  error.c_str());
10557b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes            break;
10567b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes          case INSTALL_STATUS_CANNOT_REBIND:
1057a6b340af123b82e3aaa33cb2a0d45f637eeb4759Spencer Low            message = android::base::StringPrintf("cannot rebind existing socket");
10587b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes            break;
1059424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes          case INSTALL_STATUS_LISTENER_NOT_FOUND:
1060424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes            message = android::base::StringPrintf("listener '%s' not found", service);
1061424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes            break;
1062252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        }
1063e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes        SendFail(reply_fd, message);
1064252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        return 1;
1065252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    }
1066252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    return 0;
1067252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner}
1068252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
1069e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes#if ADB_HOST
1070e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughesstatic int SendOkay(int fd, const std::string& s) {
1071e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes    SendOkay(fd);
1072e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes    SendProtocolString(fd, s);
1073e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes    return 0;
1074e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes}
1075e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes#endif
1076e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes
1077c89e0ccd40624e8b2ce30d425e8bed0264fae548Dan Albertint handle_host_request(const char* service, TransportType type,
1078c89e0ccd40624e8b2ce30d425e8bed0264fae548Dan Albert                        const char* serial, int reply_fd, asocket* s) {
1079c89e0ccd40624e8b2ce30d425e8bed0264fae548Dan Albert    if (strcmp(service, "kill") == 0) {
1080c89e0ccd40624e8b2ce30d425e8bed0264fae548Dan Albert        fprintf(stderr, "adb server killed by remote request\n");
1081dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fflush(stdout);
1082e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes        SendOkay(reply_fd);
1083f18fc0879be9cd506be6b1e051feb543b0746bdbSpencer Low
1084f18fc0879be9cd506be6b1e051feb543b0746bdbSpencer Low        // At least on Windows, if we exit() without shutdown(SD_SEND) or
1085f18fc0879be9cd506be6b1e051feb543b0746bdbSpencer Low        // closesocket(), the client's next recv() will error-out with
1086f18fc0879be9cd506be6b1e051feb543b0746bdbSpencer Low        // WSAECONNRESET and they'll never read the OKAY.
1087f18fc0879be9cd506be6b1e051feb543b0746bdbSpencer Low        adb_shutdown(reply_fd);
1088f18fc0879be9cd506be6b1e051feb543b0746bdbSpencer Low
1089dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        exit(0);
1090dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1091dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1092dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if ADB_HOST
1093dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // "transport:" is used for switching transport with a specified serial number
1094dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // "transport-usb:" is used for switching transport to the only USB transport
1095dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // "transport-local:" is used for switching transport to the only local transport
1096dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // "transport-any:" is used for switching transport to the only transport
1097dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!strncmp(service, "transport", strlen("transport"))) {
10983bd73c12c07dcefc965abeef535ac53c4754d682Elliott Hughes        TransportType type = kTransportAny;
1099dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strncmp(service, "transport-usb", strlen("transport-usb"))) {
1101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            type = kTransportUsb;
1102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if (!strncmp(service, "transport-local", strlen("transport-local"))) {
1103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            type = kTransportLocal;
1104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if (!strncmp(service, "transport-any", strlen("transport-any"))) {
1105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            type = kTransportAny;
1106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if (!strncmp(service, "transport:", strlen("transport:"))) {
1107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            service += strlen("transport:");
11083175c8e9bfcb01f181d7300755da15a999e5461cTom Marlin            serial = service;
1109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
1110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1111e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes        std::string error_msg;
1112e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes        atransport* t = acquire_one_transport(kCsAny, type, serial, &error_msg);
1113e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes        if (t != nullptr) {
1114e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes            s->transport = t;
1115e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes            SendOkay(reply_fd);
1116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
1117e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes            SendFail(reply_fd, error_msg);
1118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
1119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 1;
1120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // return a list of all connected devices
1123e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson    if (!strncmp(service, "devices", 7)) {
1124e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes        bool long_listing = (strcmp(service+7, "-l") == 0);
1125e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes        if (long_listing || service[7] == 0) {
1126e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes            D("Getting device list...\n");
1127e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes            std::string device_list = list_transports(long_listing);
1128e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes            D("Sending device list...\n");
1129e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes            return SendOkay(reply_fd, device_list);
1130e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson        }
1131e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes        return 1;
1132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
113490d4b739ab94fded63086de1261e70a3d39ceb1dDan Albert    if (!strcmp(service, "features")) {
113590d4b739ab94fded63086de1261e70a3d39ceb1dDan Albert        SendOkay(reply_fd);
113690d4b739ab94fded63086de1261e70a3d39ceb1dDan Albert        SendProtocolString(
113790d4b739ab94fded63086de1261e70a3d39ceb1dDan Albert            reply_fd, android::base::Join(supported_features(), '\n'));
113890d4b739ab94fded63086de1261e70a3d39ceb1dDan Albert        return 0;
113990d4b739ab94fded63086de1261e70a3d39ceb1dDan Albert    }
114090d4b739ab94fded63086de1261e70a3d39ceb1dDan Albert
114174d7ff8cfd490852d3df1c4b9d8a21beed619caaMike Lockwood    // remove TCP transport
114274d7ff8cfd490852d3df1c4b9d8a21beed619caaMike Lockwood    if (!strncmp(service, "disconnect:", 11)) {
11433d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes        const std::string address(service + 11);
11443d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes        if (address.empty()) {
1145f4b9928563e97620fc1d9bd5c2efdaa0ded96488Yabin Cui            kick_all_tcp_devices();
11463d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes            return SendOkay(reply_fd, "disconnected everything");
114774d7ff8cfd490852d3df1c4b9d8a21beed619caaMike Lockwood        }
114874d7ff8cfd490852d3df1c4b9d8a21beed619caaMike Lockwood
11493d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes        std::string serial;
11503d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes        std::string host;
11513d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes        int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
11523d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes        std::string error;
11533d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes        if (!parse_host_and_port(address, &serial, &host, &port, &error)) {
11543d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes            return SendFail(reply_fd, android::base::StringPrintf("couldn't parse '%s': %s",
11553d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes                                                                  address.c_str(), error.c_str()));
11563d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes        }
11573d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes        atransport* t = find_transport(serial.c_str());
11583d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes        if (t == nullptr) {
11593d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes            return SendFail(reply_fd, android::base::StringPrintf("no such device '%s'",
11603d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes                                                                  serial.c_str()));
11613d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes        }
1162f4b9928563e97620fc1d9bd5c2efdaa0ded96488Yabin Cui        kick_transport(t);
11633d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes        return SendOkay(reply_fd, android::base::StringPrintf("disconnected %s", address.c_str()));
11642f38b699713dc2587a771bd5d4c6a47329728f5eMike Lockwood    }
11652f38b699713dc2587a771bd5d4c6a47329728f5eMike Lockwood
1166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // returns our value for ADB_SERVER_VERSION
1167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!strcmp(service, "version")) {
1168e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes        return SendOkay(reply_fd, android::base::StringPrintf("%04x", ADB_SERVER_VERSION));
1169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1171e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes    // These always report "unknown" rather than the actual error, for scripts.
1172e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes    if (!strcmp(service, "get-serialno")) {
1173e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes        std::string ignored;
1174e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes        atransport* t = acquire_one_transport(kCsAny, type, serial, &ignored);
1175e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes        return SendOkay(reply_fd, (t && t->serial) ? t->serial : "unknown");
1176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1177e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes    if (!strcmp(service, "get-devpath")) {
1178e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes        std::string ignored;
1179e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes        atransport* t = acquire_one_transport(kCsAny, type, serial, &ignored);
1180e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes        return SendOkay(reply_fd, (t && t->devpath) ? t->devpath : "unknown");
1181e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson    }
1182e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes    if (!strcmp(service, "get-state")) {
1183e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes        std::string ignored;
1184e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes        atransport* t = acquire_one_transport(kCsAny, type, serial, &ignored);
1185e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes        return SendOkay(reply_fd, t ? t->connection_state_name() : "unknown");
1186e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes    }
1187e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes
1188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // indicates a new emulator instance has started
1189e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes    if (!strncmp(service, "emulator:", 9)) {
1190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int  port = atoi(service+9);
1191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        local_connect(port);
1192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* we don't even need to send a reply */
1193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
1194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
1195dc22c3c7a82ad1919c52dc4d00c601ad7210c61bSimon Ye#endif // ADB_HOST
1196dc22c3c7a82ad1919c52dc4d00c601ad7210c61bSimon Ye
11973bd73c12c07dcefc965abeef535ac53c4754d682Elliott Hughes    int ret = handle_forward_request(service, type, serial, reply_fd);
1198dc22c3c7a82ad1919c52dc4d00c601ad7210c61bSimon Ye    if (ret >= 0)
1199dc22c3c7a82ad1919c52dc4d00c601ad7210c61bSimon Ye      return ret - 1;
1200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
1201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1202