adb.cpp revision 8d5fa6da44d56511b3e173bc463cbc65ff221b4a
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>
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
357b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes#include <base/stringprintf.h>
368d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes#include <base/strings.h>
377b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes
38d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#include "adb_auth.h"
39cc731cc76786b6bdc58764aad9924c0d0c8d645fDan Albert#include "adb_io.h"
40e9fca14c9e555a9d02e1d94ba6d3b290673ea26bDan Albert#include "adb_listeners.h"
417664901a355b959f312e9acff5a0fd31b7139623Dan Albert#include "transport.h"
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
43e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
44e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if !ADB_HOST
46893a4a47e8c9290128b9254af0246e36f821c260Nick Kralevich#include <cutils/properties.h>
47e2864bf727d6a404bd871f063c03e36cc8eedeecNick Kralevich#include <sys/capability.h>
48885342a0f2c834a6b680284047c47c9d04b32565Jeff Sharkey#include <sys/mount.h>
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
51408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#if ADB_TRACE
52408fa57864c01113deaa213e5c1848a9c594ae92JP AbgrallADB_MUTEX_DEFINE( D_lock );
53408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall#endif
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint HOST = 0;
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
57e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson#if !ADB_HOST
58bd0b750897bebaa10e16507fdd08dbc746cd228dDan Albertconst char *adb_device_banner = "device";
59e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson#endif
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fatal(const char *fmt, ...)
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_list ap;
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_start(ap, fmt);
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr, "error: ");
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    vfprintf(stderr, fmt, ap);
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr, "\n");
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_end(ap);
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    exit(-1);
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid fatal_errno(const char *fmt, ...)
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_list ap;
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_start(ap, fmt);
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr, "error: %s: ", strerror(errno));
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    vfprintf(stderr, fmt, ap);
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr, "\n");
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_end(ap);
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    exit(-1);
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
83ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert#if !ADB_HOST
84ea2175ab6bae74409620374a96fc9a0097a1845cDan Albertvoid start_device_log(void) {
85ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    struct tm now;
86ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    time_t t;
87ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    tzset();
88ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    time(&t);
89ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    localtime_r(&t, &now);
90ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert
918743ef98414b336f222327253f2cde6bf6aee386Dan Albert    char timestamp[PATH_MAX];
928743ef98414b336f222327253f2cde6bf6aee386Dan Albert    strftime(timestamp, sizeof(timestamp), "%Y-%m-%d-%H-%M-%S", &now);
938743ef98414b336f222327253f2cde6bf6aee386Dan Albert
94ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    char path[PATH_MAX];
958743ef98414b336f222327253f2cde6bf6aee386Dan Albert    snprintf(path, sizeof(path), "/data/adb/adb-%s-%d", timestamp, getpid());
96ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert
978743ef98414b336f222327253f2cde6bf6aee386Dan Albert    int fd = unix_open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0640);
98ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    if (fd == -1) {
99ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert        return;
100ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    }
101ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert
102ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    // redirect stdout and stderr to the log file
103ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    dup2(fd, STDOUT_FILENO);
104ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    dup2(fd, STDERR_FILENO);
105ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    fprintf(stderr, "--- adb starting (pid %d) ---\n", getpid());
106ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    adb_close(fd);
107ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert}
108ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert#endif
109ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert
110ea2175ab6bae74409620374a96fc9a0097a1845cDan Albertint adb_trace_mask;
111ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert
112ea2175ab6bae74409620374a96fc9a0097a1845cDan Albertstd::string get_trace_setting_from_env() {
113ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    const char* setting = getenv("ADB_TRACE");
114ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    if (setting == nullptr) {
115ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert        setting = "";
116ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    }
117ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert
118ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    return std::string(setting);
119ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert}
120ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert
121ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert#if !ADB_HOST
122ea2175ab6bae74409620374a96fc9a0097a1845cDan Albertstd::string get_trace_setting_from_prop() {
123ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    char buf[PROPERTY_VALUE_MAX];
124ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    property_get("persist.adb.trace_mask", buf, "");
125ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    return std::string(buf);
126ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert}
127ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert#endif
128ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert
129ea2175ab6bae74409620374a96fc9a0097a1845cDan Albertstd::string get_trace_setting() {
130ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert#if ADB_HOST
131ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    return get_trace_setting_from_env();
132ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert#else
133ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    return get_trace_setting_from_prop();
134ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert#endif
135ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert}
136ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert
137ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert// Split the comma/space/colum/semi-column separated list of tags from the trace
138ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert// setting and build the trace mask from it. note that '1' and 'all' are special
139ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert// cases to enable all tracing.
140ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert//
141ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert// adb's trace setting comes from the ADB_TRACE environment variable, whereas
142ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert// adbd's comes from the system property persist.adb.trace_mask.
143ea2175ab6bae74409620374a96fc9a0097a1845cDan Albertvoid adb_trace_init() {
144ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    const std::string trace_setting = get_trace_setting();
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    static const struct {
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const char*  tag;
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int           flag;
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } tags[] = {
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        { "1", 0 },
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        { "all", 0 },
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        { "adb", TRACE_ADB },
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        { "sockets", TRACE_SOCKETS },
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        { "packets", TRACE_PACKETS },
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        { "rwx", TRACE_RWX },
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        { "usb", TRACE_USB },
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        { "sync", TRACE_SYNC },
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        { "sysdeps", TRACE_SYSDEPS },
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        { "transport", TRACE_TRANSPORT },
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        { "jdwp", TRACE_JDWP },
161408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        { "services", TRACE_SERVICES },
162d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        { "auth", TRACE_AUTH },
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        { NULL, 0 }
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    };
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
166ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    if (trace_setting.empty()) {
167ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert        return;
168ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    }
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
170ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    // Use a comma/colon/semi-colon/space separated list
171ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    const char* p = trace_setting.c_str();
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while (*p) {
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int  len, tagn;
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
175ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert        const char* q = strpbrk(p, " ,:;");
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (q == NULL) {
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            q = p + strlen(p);
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        len = q - p;
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
181ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert        for (tagn = 0; tags[tagn].tag != NULL; tagn++) {
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int  taglen = strlen(tags[tagn].tag);
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
184ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert            if (len == taglen && !memcmp(tags[tagn].tag, p, len)) {
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                int  flag = tags[tagn].flag;
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (flag == 0) {
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    adb_trace_mask = ~0;
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    return;
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                adb_trace_mask |= (1 << flag);
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                break;
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        p = q;
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (*p)
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            p++;
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
198ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert
199ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert#if !ADB_HOST
200ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert    start_device_log();
201ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert#endif
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
204bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albertapacket* get_apacket(void)
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
206bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert    apacket* p = reinterpret_cast<apacket*>(malloc(sizeof(apacket)));
207bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert    if (p == nullptr) {
208bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert      fatal("failed to allocate an apacket");
209bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert    }
210bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(p, 0, sizeof(apacket) - MAX_PAYLOAD);
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return p;
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid put_apacket(apacket *p)
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    free(p);
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
220d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobyvoid handle_online(atransport *t)
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("adb: online\n");
223d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    t->online = 1;
224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid handle_offline(atransport *t)
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("adb: offline\n");
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    //Close the associated usb
230d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    t->online = 0;
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    run_transport_disconnects(t);
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
234d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#if DEBUG_PACKETS
235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define DUMPMAX 32
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid print_packet(const char *label, apacket *p)
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *tag;
239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *x;
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned count;
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    switch(p->msg.command){
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case A_SYNC: tag = "SYNC"; break;
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case A_CNXN: tag = "CNXN" ; break;
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case A_OPEN: tag = "OPEN"; break;
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case A_OKAY: tag = "OKAY"; break;
247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case A_CLSE: tag = "CLSE"; break;
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case A_WRTE: tag = "WRTE"; break;
249d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    case A_AUTH: tag = "AUTH"; break;
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    default: tag = "????"; break;
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fprintf(stderr, "%s: %s %08x %08x %04x \"",
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            label, tag, p->msg.arg0, p->msg.arg1, p->msg.data_length);
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    count = p->msg.data_length;
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    x = (char*) p->data;
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(count > DUMPMAX) {
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        count = DUMPMAX;
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        tag = "\n";
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        tag = "\"\n";
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while(count-- > 0){
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if((*x >= ' ') && (*x < 127)) {
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fputc(*x, stderr);
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fputc('.', stderr);
268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        x++;
270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
271d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    fputs(tag, stderr);
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void send_ready(unsigned local, unsigned remote, atransport *t)
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("Calling send_ready \n");
278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    apacket *p = get_apacket();
279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.command = A_OKAY;
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.arg0 = local;
281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.arg1 = remote;
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    send_packet(p, t);
283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void send_close(unsigned local, unsigned remote, atransport *t)
286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("Calling send_close \n");
288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    apacket *p = get_apacket();
289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.command = A_CLSE;
290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.arg0 = local;
291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.arg1 = remote;
292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    send_packet(p, t);
293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
295e82c2db05cae70a0490a1f84b7211ef42c329671Scott Andersonstatic size_t fill_connect_data(char *buf, size_t bufsize)
296e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson{
297e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson#if ADB_HOST
298e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson    return snprintf(buf, bufsize, "host::") + 1;
299e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson#else
300e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson    static const char *cnxn_props[] = {
301e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson        "ro.product.name",
302e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson        "ro.product.model",
303e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson        "ro.product.device",
304e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson    };
305e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson    static const int num_cnxn_props = ARRAY_SIZE(cnxn_props);
306e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson    int i;
307e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson    size_t remaining = bufsize;
308e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson    size_t len;
309e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson
310e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson    len = snprintf(buf, remaining, "%s::", adb_device_banner);
311e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson    remaining -= len;
312e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson    buf += len;
313e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson    for (i = 0; i < num_cnxn_props; i++) {
314e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson        char value[PROPERTY_VALUE_MAX];
315e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson        property_get(cnxn_props[i], value, "");
316e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson        len = snprintf(buf, remaining, "%s=%s;", cnxn_props[i], value);
317e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson        remaining -= len;
318e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson        buf += len;
319e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson    }
320e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson
321e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson    return bufsize - remaining + 1;
322e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson#endif
323e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson}
324e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson
325252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner#if !ADB_HOST
326252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turnerstatic void send_msg_with_header(int fd, const char* msg, size_t msglen) {
327252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    char header[5];
328252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    if (msglen > 0xffff)
329252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        msglen = 0xffff;
330252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    snprintf(header, sizeof(header), "%04x", (unsigned)msglen);
331cc731cc76786b6bdc58764aad9924c0d0c8d645fDan Albert    WriteFdExactly(fd, header, 4);
332cc731cc76786b6bdc58764aad9924c0d0c8d645fDan Albert    WriteFdExactly(fd, msg, msglen);
333252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner}
334252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner#endif
335252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
336f787b381b6a304415030ed54bdba6ca482763e4cChih-Hung Hsieh#if ADB_HOST
337252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turnerstatic void send_msg_with_okay(int fd, const char* msg, size_t msglen) {
3382264e7cfef6b1236a90a13b1d99abb4aadcb0b93Snild Dolkow    char header[9];
3392264e7cfef6b1236a90a13b1d99abb4aadcb0b93Snild Dolkow    if (msglen > 0xffff)
3402264e7cfef6b1236a90a13b1d99abb4aadcb0b93Snild Dolkow        msglen = 0xffff;
3412264e7cfef6b1236a90a13b1d99abb4aadcb0b93Snild Dolkow    snprintf(header, sizeof(header), "OKAY%04x", (unsigned)msglen);
342cc731cc76786b6bdc58764aad9924c0d0c8d645fDan Albert    WriteFdExactly(fd, header, 8);
343cc731cc76786b6bdc58764aad9924c0d0c8d645fDan Albert    WriteFdExactly(fd, msg, msglen);
3442264e7cfef6b1236a90a13b1d99abb4aadcb0b93Snild Dolkow}
345f787b381b6a304415030ed54bdba6ca482763e4cChih-Hung Hsieh#endif // ADB_HOST
3462264e7cfef6b1236a90a13b1d99abb4aadcb0b93Snild Dolkow
347ba3a251749c88210949008ae26f8bc04812084c1Dan Albertvoid send_connect(atransport *t)
348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("Calling send_connect \n");
350dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    apacket *cp = get_apacket();
351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    cp->msg.command = A_CNXN;
352dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    cp->msg.arg0 = A_VERSION;
353dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    cp->msg.arg1 = MAX_PAYLOAD;
354e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson    cp->msg.data_length = fill_connect_data((char *)cp->data,
355e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson                                            sizeof(cp->data));
356dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    send_packet(cp, t);
357d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby}
358d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
359f787b381b6a304415030ed54bdba6ca482763e4cChih-Hung Hsieh#if ADB_HOST
360bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albertstatic const char* connection_state_name(atransport *t)
361dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
362dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (t == NULL) {
363dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return "unknown";
364dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
365dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
366dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    switch(t->connection_state) {
367dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case CS_BOOTLOADER:
368dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return "bootloader";
369dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case CS_DEVICE:
370dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return "device";
371a5ad539cff9dba92650425b8bec79c071ef5993btrevd    case CS_RECOVERY:
372a5ad539cff9dba92650425b8bec79c071ef5993btrevd        return "recovery";
373a5ad539cff9dba92650425b8bec79c071ef5993btrevd    case CS_SIDELOAD:
374a5ad539cff9dba92650425b8bec79c071ef5993btrevd        return "sideload";
375dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case CS_OFFLINE:
376dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return "offline";
37777e8e5851d3b951b5382663bd50f1f83cb531eb2Benoit Goby    case CS_UNAUTHORIZED:
37877e8e5851d3b951b5382663bd50f1f83cb531eb2Benoit Goby        return "unauthorized";
379dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    default:
380dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return "unknown";
381dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
382dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
383f787b381b6a304415030ed54bdba6ca482763e4cChih-Hung Hsieh#endif // ADB_HOST
384dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
3858d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes// qual_overwrite is used to overwrite a qualifier string.  dst is a
3868d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes// pointer to a char pointer.  It is assumed that if *dst is non-NULL, it
3878d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes// was malloc'ed and needs to freed.  *dst will be set to a dup of src.
3888d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes// TODO: switch to std::string for these atransport fields instead.
3898d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughesstatic void qual_overwrite(char** dst, const std::string& src) {
390e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson    free(*dst);
3918d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    *dst = strdup(src.c_str());
392e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson}
393e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson
3948d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughesvoid parse_banner(const char* banner, atransport* t) {
395dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("parse_banner: %s\n", banner);
3968d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes
3978d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    // The format is something like:
3988d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    // "device::ro.product.name=x;ro.product.model=y;ro.product.device=z;".
3998d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    std::vector<std::string> pieces = android::base::Split(banner, ":");
4008d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes
4018d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    if (pieces.size() > 2) {
4028d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes        const std::string& props = pieces[2];
4038d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes        for (auto& prop : android::base::Split(props, ";")) {
4048d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes            // The list of properties was traditionally ;-terminated rather than ;-separated.
4058d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes            if (prop.empty()) continue;
4068d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes
4078d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes            std::vector<std::string> key_value = android::base::Split(prop, "=");
4088d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes            if (key_value.size() != 2) continue;
4098d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes
4108d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes            const std::string& key = key_value[0];
4118d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes            const std::string& value = key_value[1];
4128d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes            if (key == "ro.product.name") {
4138d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes                qual_overwrite(&t->product, value);
4148d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes            } else if (key == "ro.product.model") {
4158d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes                qual_overwrite(&t->model, value);
4168d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes            } else if (key == "ro.product.device") {
4178d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes                qual_overwrite(&t->device, value);
418e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson            }
419e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson        }
420dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
421dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
4228d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    const std::string& type = pieces[0];
4238d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    if (type == "bootloader") {
424dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D("setting connection_state to CS_BOOTLOADER\n");
425dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        t->connection_state = CS_BOOTLOADER;
426dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        update_transports();
4278d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    } else if (type == "device") {
428dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D("setting connection_state to CS_DEVICE\n");
429dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        t->connection_state = CS_DEVICE;
430dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        update_transports();
4318d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    } else if (type == "recovery") {
432dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D("setting connection_state to CS_RECOVERY\n");
433dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        t->connection_state = CS_RECOVERY;
434dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        update_transports();
4358d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    } else if (type == "sideload") {
436447f061da19fe46bae35f1cdd93eeb16bc225463Doug Zongker        D("setting connection_state to CS_SIDELOAD\n");
437447f061da19fe46bae35f1cdd93eeb16bc225463Doug Zongker        t->connection_state = CS_SIDELOAD;
438447f061da19fe46bae35f1cdd93eeb16bc225463Doug Zongker        update_transports();
439447f061da19fe46bae35f1cdd93eeb16bc225463Doug Zongker    }
440447f061da19fe46bae35f1cdd93eeb16bc225463Doug Zongker
441dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    t->connection_state = CS_HOST;
442dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
444dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid handle_packet(apacket *p, atransport *t)
445dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
446dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asocket *s;
447dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
448899913f8168b54e00971c0e8d4ae16d06a4651feViral Mehta    D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0],
449899913f8168b54e00971c0e8d4ae16d06a4651feViral Mehta            ((char*) (&(p->msg.command)))[1],
450899913f8168b54e00971c0e8d4ae16d06a4651feViral Mehta            ((char*) (&(p->msg.command)))[2],
451899913f8168b54e00971c0e8d4ae16d06a4651feViral Mehta            ((char*) (&(p->msg.command)))[3]);
452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    print_packet("recv", p);
453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    switch(p->msg.command){
455dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case A_SYNC:
456dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(p->msg.arg0){
457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            send_packet(p, t);
458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(HOST) send_connect(t);
459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            t->connection_state = CS_OFFLINE;
461dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            handle_offline(t);
462dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            send_packet(p, t);
463dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
464dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return;
465dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
466dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */
467dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* XXX verify version, etc */
468dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(t->connection_state != CS_OFFLINE) {
469dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            t->connection_state = CS_OFFLINE;
470dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            handle_offline(t);
471dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
472d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
4738d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes        parse_banner(reinterpret_cast<const char*>(p->data), t);
474d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
475d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        if (HOST || !auth_enabled) {
476d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby            handle_online(t);
477d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby            if(!HOST) send_connect(t);
478d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        } else {
479d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby            send_auth_request(t);
480d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        }
481d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        break;
482d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
483d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    case A_AUTH:
484d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        if (p->msg.arg0 == ADB_AUTH_TOKEN) {
48577e8e5851d3b951b5382663bd50f1f83cb531eb2Benoit Goby            t->connection_state = CS_UNAUTHORIZED;
486d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby            t->key = adb_auth_nextkey(t->key);
487d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby            if (t->key) {
488d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby                send_auth_response(p->data, p->msg.data_length, t);
489d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby            } else {
490d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby                /* No more private keys to try, send the public key */
491d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby                send_auth_publickey(t);
492d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby            }
493d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        } else if (p->msg.arg0 == ADB_AUTH_SIGNATURE) {
494d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby            if (adb_auth_verify(t->token, p->data, p->msg.data_length)) {
495d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby                adb_auth_verified(t);
496d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby                t->failed_auth_attempts = 0;
497d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby            } else {
498d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby                if (t->failed_auth_attempts++ > 10)
499d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby                    adb_sleep_ms(1000);
500d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby                send_auth_request(t);
501d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby            }
502d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        } else if (p->msg.arg0 == ADB_AUTH_RSAPUBLICKEY) {
503d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby            adb_auth_confirm_key(p->data, p->msg.data_length, t);
504d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        }
505dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
506dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
507dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case A_OPEN: /* OPEN(local-id, 0, "destination") */
508818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner        if (t->online && p->msg.arg0 != 0 && p->msg.arg1 == 0) {
509dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char *name = (char*) p->data;
510dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0;
511dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            s = create_local_service_socket(name);
512dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if(s == 0) {
513dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                send_close(0, p->msg.arg0, t);
514dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else {
515dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                s->peer = create_remote_socket(p->msg.arg0, t);
516dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                s->peer->peer = s;
517dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                send_ready(s->id, s->peer->id, t);
518dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                s->ready(s);
519dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
520dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
521dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
522dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
523dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case A_OKAY: /* READY(local-id, remote-id, "") */
524818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner        if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) {
525818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner            if((s = find_local_socket(p->msg.arg1, 0))) {
526dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if(s->peer == 0) {
527818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                    /* On first READY message, create the connection. */
528dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    s->peer = create_remote_socket(p->msg.arg0, t);
529dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    s->peer->peer = s;
530818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                    s->ready(s);
531818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                } else if (s->peer->id == p->msg.arg0) {
532818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                    /* Other READY messages must use the same local-id */
533818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                    s->ready(s);
534818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                } else {
535818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                    D("Invalid A_OKAY(%d,%d), expected A_OKAY(%d,%d) on transport %s\n",
536818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                      p->msg.arg0, p->msg.arg1, s->peer->id, p->msg.arg1, t->serial);
537dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
538dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
539dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
540dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
541dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
542818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    case A_CLSE: /* CLOSE(local-id, remote-id, "") or CLOSE(0, remote-id, "") */
543818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner        if (t->online && p->msg.arg1 != 0) {
544818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner            if((s = find_local_socket(p->msg.arg1, p->msg.arg0))) {
545818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                /* According to protocol.txt, p->msg.arg0 might be 0 to indicate
546818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                 * a failed OPEN only. However, due to a bug in previous ADB
547818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                 * versions, CLOSE(0, remote-id, "") was also used for normal
548818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                 * CLOSE() operations.
549818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                 *
550818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                 * This is bad because it means a compromised adbd could
551818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                 * send packets to close connections between the host and
552818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                 * other devices. To avoid this, only allow this if the local
553818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                 * socket has a peer on the same transport.
554818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                 */
555818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                if (p->msg.arg0 == 0 && s->peer && s->peer->transport != t) {
556818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                    D("Invalid A_CLSE(0, %u) from transport %s, expected transport %s\n",
557818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                      p->msg.arg1, t->serial, s->peer->transport->serial);
558818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                } else {
559818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                    s->close(s);
560818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner                }
561dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
562dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
563dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
564dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
565818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    case A_WRTE: /* WRITE(local-id, remote-id, <data>) */
566818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner        if (t->online && p->msg.arg0 != 0 && p->msg.arg1 != 0) {
567818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner            if((s = find_local_socket(p->msg.arg1, p->msg.arg0))) {
568dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                unsigned rid = p->msg.arg0;
569dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                p->len = p->msg.data_length;
570dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
571dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if(s->enqueue(s, p) == 0) {
572dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    D("Enqueue the socket\n");
573dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    send_ready(s->id, rid, t);
574dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
575dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                return;
576dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
577dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
578dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
579dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
580dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    default:
581dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        printf("handle_packet: what is %08x?!\n", p->msg.command);
582dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
583dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
584dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    put_apacket(p);
585dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
586dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
587dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if ADB_HOST
588571c1367682c83cb23481cc9c1028c8588a1fed0JP Abgrall
589a84a42eb20d43ffa2695a69d583a6e09532b49d9Stefan Hilzingerint launch_server(int server_port)
590dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
591e77b6a08623bba383ce55cd6653bec76cdf57792Yabin Cui#if defined(_WIN32)
592dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* we need to start the server in the background                    */
593dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* we create a PIPE that will be used to wait for the server's "OK" */
594dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* message since the pipe handles must be inheritable, we use a     */
595dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* security attribute                                               */
596dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    HANDLE                pipe_read, pipe_write;
597267aa8b00eadf273321e492026af74b7baad890eRay Donnelly    HANDLE                stdout_handle, stderr_handle;
598dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SECURITY_ATTRIBUTES   sa;
599dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    STARTUPINFO           startup;
600dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    PROCESS_INFORMATION   pinfo;
601dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char                  program_path[ MAX_PATH ];
602dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int                   ret;
603dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
604dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sa.nLength = sizeof(sa);
605dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sa.lpSecurityDescriptor = NULL;
606dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sa.bInheritHandle = TRUE;
607dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
608dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* create pipe, and ensure its read handle isn't inheritable */
609dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ret = CreatePipe( &pipe_read, &pipe_write, &sa, 0 );
610dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!ret) {
611dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr, "CreatePipe() failure, error %ld\n", GetLastError() );
612dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
613dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
614dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
615dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SetHandleInformation( pipe_read, HANDLE_FLAG_INHERIT, 0 );
616dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
617267aa8b00eadf273321e492026af74b7baad890eRay Donnelly    /* Some programs want to launch an adb command and collect its output by
618267aa8b00eadf273321e492026af74b7baad890eRay Donnelly     * calling CreateProcess with inheritable stdout/stderr handles, then
619267aa8b00eadf273321e492026af74b7baad890eRay Donnelly     * using read() to get its output. When this happens, the stdout/stderr
620267aa8b00eadf273321e492026af74b7baad890eRay Donnelly     * handles passed to the adb client process will also be inheritable.
621267aa8b00eadf273321e492026af74b7baad890eRay Donnelly     * When starting the adb server here, care must be taken to reset them
622267aa8b00eadf273321e492026af74b7baad890eRay Donnelly     * to non-inheritable.
623267aa8b00eadf273321e492026af74b7baad890eRay Donnelly     * Otherwise, something bad happens: even if the adb command completes,
624267aa8b00eadf273321e492026af74b7baad890eRay Donnelly     * the calling process is stuck while read()-ing from the stdout/stderr
625267aa8b00eadf273321e492026af74b7baad890eRay Donnelly     * descriptors, because they're connected to corresponding handles in the
626267aa8b00eadf273321e492026af74b7baad890eRay Donnelly     * adb server process (even if the latter never uses/writes to them).
627267aa8b00eadf273321e492026af74b7baad890eRay Donnelly     */
628267aa8b00eadf273321e492026af74b7baad890eRay Donnelly    stdout_handle = GetStdHandle( STD_OUTPUT_HANDLE );
629267aa8b00eadf273321e492026af74b7baad890eRay Donnelly    stderr_handle = GetStdHandle( STD_ERROR_HANDLE );
630267aa8b00eadf273321e492026af74b7baad890eRay Donnelly    if (stdout_handle != INVALID_HANDLE_VALUE) {
631267aa8b00eadf273321e492026af74b7baad890eRay Donnelly        SetHandleInformation( stdout_handle, HANDLE_FLAG_INHERIT, 0 );
632267aa8b00eadf273321e492026af74b7baad890eRay Donnelly    }
633267aa8b00eadf273321e492026af74b7baad890eRay Donnelly    if (stderr_handle != INVALID_HANDLE_VALUE) {
634267aa8b00eadf273321e492026af74b7baad890eRay Donnelly        SetHandleInformation( stderr_handle, HANDLE_FLAG_INHERIT, 0 );
635267aa8b00eadf273321e492026af74b7baad890eRay Donnelly    }
636267aa8b00eadf273321e492026af74b7baad890eRay Donnelly
637dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ZeroMemory( &startup, sizeof(startup) );
638dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    startup.cb = sizeof(startup);
639dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    startup.hStdInput  = GetStdHandle( STD_INPUT_HANDLE );
640dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    startup.hStdOutput = pipe_write;
641dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    startup.hStdError  = GetStdHandle( STD_ERROR_HANDLE );
642dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    startup.dwFlags    = STARTF_USESTDHANDLES;
643dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
644dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ZeroMemory( &pinfo, sizeof(pinfo) );
645dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
646dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* get path of current program */
647dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    GetModuleFileName( NULL, program_path, sizeof(program_path) );
648a09558c2e205771e6830eeb6241c5c0e3b1cf4ceWenhao Li    char args[64];
649a09558c2e205771e6830eeb6241c5c0e3b1cf4ceWenhao Li    snprintf(args, sizeof(args), "adb -P %d fork-server server",  server_port);
650dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ret = CreateProcess(
651dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            program_path,                              /* program path  */
652a09558c2e205771e6830eeb6241c5c0e3b1cf4ceWenhao Li            args,
653dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                    /* the fork-server argument will set the
654dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                       debug = 2 in the child           */
655dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            NULL,                   /* process handle is not inheritable */
656dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            NULL,                    /* thread handle is not inheritable */
657dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            TRUE,                          /* yes, inherit some handles */
658dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            DETACHED_PROCESS, /* the new process doesn't have a console */
659dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            NULL,                     /* use parent's environment block */
660dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            NULL,                    /* use parent's starting directory */
661dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            &startup,                 /* startup info, i.e. std handles */
662dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            &pinfo );
663dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
664dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    CloseHandle( pipe_write );
665dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
666dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!ret) {
667dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr, "CreateProcess failure, error %ld\n", GetLastError() );
668dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        CloseHandle( pipe_read );
669dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
670dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
671dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
672dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    CloseHandle( pinfo.hProcess );
673dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    CloseHandle( pinfo.hThread );
674dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
675dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* wait for the "OK\n" message */
676dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    {
677dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char  temp[3];
678dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        DWORD  count;
679dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
680dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ret = ReadFile( pipe_read, temp, 3, &count, NULL );
681dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        CloseHandle( pipe_read );
682dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if ( !ret ) {
683dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fprintf(stderr, "could not read ok from ADB Server, error = %ld\n", GetLastError() );
684dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
685dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
686dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (count != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') {
687dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fprintf(stderr, "ADB server didn't ACK\n" );
688dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
689dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
690dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
691e77b6a08623bba383ce55cd6653bec76cdf57792Yabin Cui#else /* !defined(_WIN32) */
692dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char    path[PATH_MAX];
693dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int     fd[2];
694dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
695dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // set up a pipe so the child can tell us when it is ready.
696dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // fd[0] will be parent's end, and fd[1] will get mapped to stderr in the child.
697dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (pipe(fd)) {
698dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr, "pipe failed in launch_server, errno: %d\n", errno);
699dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
700dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
7013166410a82f43d39201be98a8d35c51baa86cb53Alexey Tarasov    get_my_path(path, PATH_MAX);
702dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    pid_t pid = fork();
703dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(pid < 0) return -1;
704dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
705dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (pid == 0) {
706dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // child side of the fork
707dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
708dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // redirect stderr to the pipe
709dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // we use stderr instead of stdout due to stdout's buffering behavior.
710dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_close(fd[0]);
711dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        dup2(fd[1], STDERR_FILENO);
712dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_close(fd[1]);
713dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
714d7b33085117ccbb908a883f624cb1fe5495ee92aMatt Gumbel        char str_port[30];
715d7b33085117ccbb908a883f624cb1fe5495ee92aMatt Gumbel        snprintf(str_port, sizeof(str_port), "%d",  server_port);
716dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // child process
717d7b33085117ccbb908a883f624cb1fe5495ee92aMatt Gumbel        int result = execl(path, "adb", "-P", str_port, "fork-server", "server", NULL);
718dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // this should not return
719dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno);
720dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else  {
721dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // parent side of the fork
722dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
723dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char  temp[3];
724dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
725dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        temp[0] = 'A'; temp[1] = 'B'; temp[2] = 'C';
726dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // wait for the "OK\n" message
727dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_close(fd[1]);
728dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int ret = adb_read(fd[0], temp, 3);
729408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        int saved_errno = errno;
730dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_close(fd[0]);
731dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (ret < 0) {
732408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall            fprintf(stderr, "could not read ok from ADB Server, errno = %d\n", saved_errno);
733dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
734dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
735dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (ret != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') {
736dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            fprintf(stderr, "ADB server didn't ACK\n" );
737dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
738dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
739dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
740dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        setsid();
741dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
742e77b6a08623bba383ce55cd6653bec76cdf57792Yabin Cui#endif /* !defined(_WIN32) */
743dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
744dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
745e77b6a08623bba383ce55cd6653bec76cdf57792Yabin Cui#endif /* ADB_HOST */
746dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
747252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner// Try to handle a network forwarding request.
748252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner// This returns 1 on success, 0 on failure, and -1 to indicate this is not
749252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner// a forwarding-related request.
750252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turnerint handle_forward_request(const char* service, transport_type ttype, char* serial, int reply_fd)
751252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner{
752252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    if (!strcmp(service, "list-forward")) {
753252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        // Create the list of forward redirections.
754252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        int buffer_size = format_listeners(NULL, 0);
755252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        // Add one byte for the trailing zero.
756bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert        char* buffer = reinterpret_cast<char*>(malloc(buffer_size + 1));
757bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert        if (buffer == nullptr) {
758252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner            sendfailmsg(reply_fd, "not enough memory");
759252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner            return 1;
760252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        }
761252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        (void) format_listeners(buffer, buffer_size + 1);
762252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner#if ADB_HOST
763252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        send_msg_with_okay(reply_fd, buffer, buffer_size);
764252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner#else
765252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        send_msg_with_header(reply_fd, buffer, buffer_size);
766252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner#endif
767252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        free(buffer);
768252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        return 1;
769252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    }
770252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
771252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    if (!strcmp(service, "killforward-all")) {
772252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        remove_all_listeners();
773252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner#if ADB_HOST
774252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        /* On the host: 1st OKAY is connect, 2nd OKAY is status */
775252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        adb_write(reply_fd, "OKAY", 4);
776252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner#endif
777252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        adb_write(reply_fd, "OKAY", 4);
778252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        return 1;
779252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    }
780252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
781252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    if (!strncmp(service, "forward:",8) ||
782252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        !strncmp(service, "killforward:",12)) {
783bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert        char *local, *remote;
784252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        atransport *transport;
785252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
786252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        int createForward = strncmp(service, "kill", 4);
787252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        int no_rebind = 0;
788252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
789252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        local = strchr(service, ':') + 1;
790252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
791252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        // Handle forward:norebind:<local>... here
792252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        if (createForward && !strncmp(local, "norebind:", 9)) {
793252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner            no_rebind = 1;
794252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner            local = strchr(local, ':') + 1;
795252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        }
796252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
797252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        remote = strchr(local,';');
798252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
799252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        if (createForward) {
800252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner            // Check forward: parameter format: '<local>;<remote>'
801252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner            if(remote == 0) {
802252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner                sendfailmsg(reply_fd, "malformed forward spec");
803252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner                return 1;
804252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner            }
805252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
806252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner            *remote++ = 0;
807252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner            if((local[0] == 0) || (remote[0] == 0) || (remote[0] == '*')) {
808252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner                sendfailmsg(reply_fd, "malformed forward spec");
809252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner                return 1;
810252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner            }
811252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        } else {
812252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner            // Check killforward: parameter format: '<local>'
813252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner            if (local[0] == 0) {
814252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner                sendfailmsg(reply_fd, "malformed forward spec");
815252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner                return 1;
816252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner            }
817252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        }
818252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
8197be29c819b4fb8bf9b1d4b69a4333f8765de0281Elliott Hughes        std::string error_msg;
8207be29c819b4fb8bf9b1d4b69a4333f8765de0281Elliott Hughes        transport = acquire_one_transport(CS_ANY, ttype, serial, &error_msg);
821252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        if (!transport) {
8227be29c819b4fb8bf9b1d4b69a4333f8765de0281Elliott Hughes            sendfailmsg(reply_fd, error_msg.c_str());
823252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner            return 1;
824252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        }
825252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
8267b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes        install_status_t r;
827252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        if (createForward) {
828252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner            r = install_listener(local, remote, transport, no_rebind);
829252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        } else {
830252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner            r = remove_listener(local, transport);
831252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        }
8327b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes        if (r == INSTALL_STATUS_OK) {
833252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner#if ADB_HOST
834252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner            /* On the host: 1st OKAY is connect, 2nd OKAY is status */
835cc731cc76786b6bdc58764aad9924c0d0c8d645fDan Albert            WriteFdExactly(reply_fd, "OKAY", 4);
836252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner#endif
837cc731cc76786b6bdc58764aad9924c0d0c8d645fDan Albert            WriteFdExactly(reply_fd, "OKAY", 4);
838252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner            return 1;
839252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        }
840252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
8417b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes        std::string message;
8427b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes        switch (r) {
8437b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes          case INSTALL_STATUS_OK: message = " "; break;
8447b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes          case INSTALL_STATUS_INTERNAL_ERROR: message = "internal error"; break;
8457b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes          case INSTALL_STATUS_CANNOT_BIND:
8467b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes            message = android::base::StringPrintf("cannot bind to socket: %s", strerror(errno));
8477b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes            break;
8487b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes          case INSTALL_STATUS_CANNOT_REBIND:
8497b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes            message = android::base::StringPrintf("cannot rebind existing socket: %s", strerror(errno));
8507b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes            break;
8517b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes          case INSTALL_STATUS_LISTENER_NOT_FOUND: message = "listener not found"; break;
852252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        }
8537b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes        sendfailmsg(reply_fd, message.c_str());
854252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        return 1;
855252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    }
856252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    return 0;
857252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner}
858252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
859dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s)
860dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
861dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(!strcmp(service, "kill")) {
862dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr,"adb server killed by remote request\n");
863dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fflush(stdout);
864dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_write(reply_fd, "OKAY", 4);
865dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        usb_cleanup();
866dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        exit(0);
867dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
868dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
869dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if ADB_HOST
870f787b381b6a304415030ed54bdba6ca482763e4cChih-Hung Hsieh    atransport *transport = NULL;
871dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // "transport:" is used for switching transport with a specified serial number
872dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // "transport-usb:" is used for switching transport to the only USB transport
873dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // "transport-local:" is used for switching transport to the only local transport
874dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // "transport-any:" is used for switching transport to the only transport
875dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!strncmp(service, "transport", strlen("transport"))) {
876dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        transport_type type = kTransportAny;
877dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
878dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strncmp(service, "transport-usb", strlen("transport-usb"))) {
879dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            type = kTransportUsb;
880dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if (!strncmp(service, "transport-local", strlen("transport-local"))) {
881dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            type = kTransportLocal;
882dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if (!strncmp(service, "transport-any", strlen("transport-any"))) {
883dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            type = kTransportAny;
884dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if (!strncmp(service, "transport:", strlen("transport:"))) {
885dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            service += strlen("transport:");
8863175c8e9bfcb01f181d7300755da15a999e5461cTom Marlin            serial = service;
887dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
888dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
8897be29c819b4fb8bf9b1d4b69a4333f8765de0281Elliott Hughes        std::string error_msg = "unknown failure";
8907be29c819b4fb8bf9b1d4b69a4333f8765de0281Elliott Hughes        transport = acquire_one_transport(CS_ANY, type, serial, &error_msg);
891dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
892dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (transport) {
893dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            s->transport = transport;
894dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            adb_write(reply_fd, "OKAY", 4);
895dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
8967be29c819b4fb8bf9b1d4b69a4333f8765de0281Elliott Hughes            sendfailmsg(reply_fd, error_msg.c_str());
897dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
898dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 1;
899dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
900dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
901dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // return a list of all connected devices
902e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson    if (!strncmp(service, "devices", 7)) {
903dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char buffer[4096];
904e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson        int use_long = !strcmp(service+7, "-l");
905e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson        if (use_long || service[7] == 0) {
906e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson            memset(buffer, 0, sizeof(buffer));
907e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson            D("Getting device list \n");
908e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson            list_transports(buffer, sizeof(buffer), use_long);
909e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson            D("Wrote device list \n");
9102264e7cfef6b1236a90a13b1d99abb4aadcb0b93Snild Dolkow            send_msg_with_okay(reply_fd, buffer, strlen(buffer));
911e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson            return 0;
912e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson        }
913dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
914dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
91574d7ff8cfd490852d3df1c4b9d8a21beed619caaMike Lockwood    // remove TCP transport
91674d7ff8cfd490852d3df1c4b9d8a21beed619caaMike Lockwood    if (!strncmp(service, "disconnect:", 11)) {
91774d7ff8cfd490852d3df1c4b9d8a21beed619caaMike Lockwood        char buffer[4096];
91874d7ff8cfd490852d3df1c4b9d8a21beed619caaMike Lockwood        memset(buffer, 0, sizeof(buffer));
91974d7ff8cfd490852d3df1c4b9d8a21beed619caaMike Lockwood        char* serial = service + 11;
920cbbe79add1410b53ec65936cfb1b74cac68467f0Mike Lockwood        if (serial[0] == 0) {
921cbbe79add1410b53ec65936cfb1b74cac68467f0Mike Lockwood            // disconnect from all TCP devices
922cbbe79add1410b53ec65936cfb1b74cac68467f0Mike Lockwood            unregister_all_tcp_transports();
92374d7ff8cfd490852d3df1c4b9d8a21beed619caaMike Lockwood        } else {
924cbbe79add1410b53ec65936cfb1b74cac68467f0Mike Lockwood            char hostbuf[100];
925cbbe79add1410b53ec65936cfb1b74cac68467f0Mike Lockwood            // assume port 5555 if no port is specified
926cbbe79add1410b53ec65936cfb1b74cac68467f0Mike Lockwood            if (!strchr(serial, ':')) {
927cbbe79add1410b53ec65936cfb1b74cac68467f0Mike Lockwood                snprintf(hostbuf, sizeof(hostbuf) - 1, "%s:5555", serial);
928cbbe79add1410b53ec65936cfb1b74cac68467f0Mike Lockwood                serial = hostbuf;
929cbbe79add1410b53ec65936cfb1b74cac68467f0Mike Lockwood            }
930cbbe79add1410b53ec65936cfb1b74cac68467f0Mike Lockwood            atransport *t = find_transport(serial);
931cbbe79add1410b53ec65936cfb1b74cac68467f0Mike Lockwood
932cbbe79add1410b53ec65936cfb1b74cac68467f0Mike Lockwood            if (t) {
933cbbe79add1410b53ec65936cfb1b74cac68467f0Mike Lockwood                unregister_transport(t);
934cbbe79add1410b53ec65936cfb1b74cac68467f0Mike Lockwood            } else {
935cbbe79add1410b53ec65936cfb1b74cac68467f0Mike Lockwood                snprintf(buffer, sizeof(buffer), "No such device %s", serial);
936cbbe79add1410b53ec65936cfb1b74cac68467f0Mike Lockwood            }
93774d7ff8cfd490852d3df1c4b9d8a21beed619caaMike Lockwood        }
93874d7ff8cfd490852d3df1c4b9d8a21beed619caaMike Lockwood
9392264e7cfef6b1236a90a13b1d99abb4aadcb0b93Snild Dolkow        send_msg_with_okay(reply_fd, buffer, strlen(buffer));
9402f38b699713dc2587a771bd5d4c6a47329728f5eMike Lockwood        return 0;
9412f38b699713dc2587a771bd5d4c6a47329728f5eMike Lockwood    }
9422f38b699713dc2587a771bd5d4c6a47329728f5eMike Lockwood
943dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // returns our value for ADB_SERVER_VERSION
944dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!strcmp(service, "version")) {
945dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char version[12];
946dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        snprintf(version, sizeof version, "%04x", ADB_SERVER_VERSION);
9472264e7cfef6b1236a90a13b1d99abb4aadcb0b93Snild Dolkow        send_msg_with_okay(reply_fd, version, strlen(version));
948dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
949dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
950dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
951dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(!strncmp(service,"get-serialno",strlen("get-serialno"))) {
952bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert        const char *out = "unknown";
953bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert        transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
9547be29c819b4fb8bf9b1d4b69a4333f8765de0281Elliott Hughes        if (transport && transport->serial) {
955dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            out = transport->serial;
956dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
9572264e7cfef6b1236a90a13b1d99abb4aadcb0b93Snild Dolkow        send_msg_with_okay(reply_fd, out, strlen(out));
958dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
959dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
960e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson    if(!strncmp(service,"get-devpath",strlen("get-devpath"))) {
961bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert        const char *out = "unknown";
962bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert        transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
9637be29c819b4fb8bf9b1d4b69a4333f8765de0281Elliott Hughes        if (transport && transport->devpath) {
964e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson            out = transport->devpath;
965e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson        }
9662264e7cfef6b1236a90a13b1d99abb4aadcb0b93Snild Dolkow        send_msg_with_okay(reply_fd, out, strlen(out));
967e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson        return 0;
968e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson    }
969dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // indicates a new emulator instance has started
970dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!strncmp(service,"emulator:",9)) {
971dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int  port = atoi(service+9);
972dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        local_connect(port);
973dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* we don't even need to send a reply */
974dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
975dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
976dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
977dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(!strncmp(service,"get-state",strlen("get-state"))) {
978dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
979bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert        const char *state = connection_state_name(transport);
9802264e7cfef6b1236a90a13b1d99abb4aadcb0b93Snild Dolkow        send_msg_with_okay(reply_fd, state, strlen(state));
981dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
982dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
983dc22c3c7a82ad1919c52dc4d00c601ad7210c61bSimon Ye#endif // ADB_HOST
984dc22c3c7a82ad1919c52dc4d00c601ad7210c61bSimon Ye
985dc22c3c7a82ad1919c52dc4d00c601ad7210c61bSimon Ye    int ret = handle_forward_request(service, ttype, serial, reply_fd);
986dc22c3c7a82ad1919c52dc4d00c601ad7210c61bSimon Ye    if (ret >= 0)
987dc22c3c7a82ad1919c52dc4d00c601ad7210c61bSimon Ye      return ret - 1;
988dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
989dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
990