adb.cpp revision 571c1367682c83cb23481cc9c1028c8588a1fed0
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
17aed3c61c4437ebb05eadfb3bf85d6962c30b9935Yabin Cui#define  TRACE_TAG   TRACE_ADB
183313426fad9eaaf53017cdbde889ebcec91358ecDan Albert
193313426fad9eaaf53017cdbde889ebcec91358ecDan Albert#include <stdio.h>
203313426fad9eaaf53017cdbde889ebcec91358ecDan Albert#include <stdlib.h>
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <ctype.h>
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdarg.h>
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h>
24ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert#include <stddef.h>
25c7993af64baec271a238646bc20aaa846866c4a9Scott Anderson#include <string.h>
26ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert#include <time.h>
27ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert#include <sys/time.h>
28ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "sysdeps.h"
301f546e6d1f6ccd1964336ddf0d8e8b3b11b1e945Mike Lockwood#include "adb.h"
31ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert#include "adb_auth.h"
32ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert
33ea2175ab6bae74409620374a96fc9a0097a1845cDan Albert#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
34e246219d0c9897b1c08204d6c535d5d341c4e7eeDan Albert
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if !ADB_HOST
365f787ed2b3b9f6cc02aa5923b95d77e2a5865438David Pursell#include <private/android_filesystem_config.h>
3782ff315bb0fecb9127970e01b399be53c92ca14fElliott Hughes#include <linux/capability.h>
384f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include <linux/prctl.h>
394f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include <sys/mount.h>
40706955ff0d159d28bb6eb06dc10178624c505f4eDavid Pursell#else
414f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include "usb_vendors.h"
424f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#endif
437b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes
44d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#if ADB_TRACE
45cc731cc76786b6bdc58764aad9924c0d0c8d645fDan AlbertADB_MUTEX_DEFINE( D_lock );
46e9fca14c9e555a9d02e1d94ba6d3b290673ea26bDan Albert#endif
473d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes
487664901a355b959f312e9acff5a0fd31b7139623Dan Albertint HOST = 0;
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint gListenAll = 0;
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
51893a4a47e8c9290128b9254af0246e36f821c260Nick Kralevichstatic int auth_enabled = 0;
52e2864bf727d6a404bd871f063c03e36cc8eedeecNick Kralevich
53885342a0f2c834a6b680284047c47c9d04b32565Jeff Sharkey#if !ADB_HOST
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic const char *adb_device_banner = "device";
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
5642ae2604f43ef88be748f125e8733f2c08b83faeElliott Hughes
5742ae2604f43ef88be748f125e8733f2c08b83faeElliott Hughesvoid fatal(const char *fmt, ...)
5842ae2604f43ef88be748f125e8733f2c08b83faeElliott Hughes{
5942ae2604f43ef88be748f125e8733f2c08b83faeElliott Hughes    va_list ap;
6042ae2604f43ef88be748f125e8733f2c08b83faeElliott Hughes    va_start(ap, fmt);
6142ae2604f43ef88be748f125e8733f2c08b83faeElliott Hughes    fprintf(stderr, "error: ");
6242ae2604f43ef88be748f125e8733f2c08b83faeElliott Hughes    vfprintf(stderr, fmt, ap);
6342ae2604f43ef88be748f125e8733f2c08b83faeElliott Hughes    fprintf(stderr, "\n");
649313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albert    va_end(ap);
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    exit(-1);
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
674abdeee073aecd2130e82f301ceff03dbd27fd72Josh Gao
684abdeee073aecd2130e82f301ceff03dbd27fd72Josh Gaovoid fatal_errno(const char *fmt, ...)
694abdeee073aecd2130e82f301ceff03dbd27fd72Josh Gao{
704abdeee073aecd2130e82f301ceff03dbd27fd72Josh Gao    va_list ap;
714abdeee073aecd2130e82f301ceff03dbd27fd72Josh Gao    va_start(ap, fmt);
724abdeee073aecd2130e82f301ceff03dbd27fd72Josh Gao    fprintf(stderr, "error: %s: ", strerror(errno));
734abdeee073aecd2130e82f301ceff03dbd27fd72Josh Gao    vfprintf(stderr, fmt, ap);
744abdeee073aecd2130e82f301ceff03dbd27fd72Josh Gao    fprintf(stderr, "\n");
754abdeee073aecd2130e82f301ceff03dbd27fd72Josh Gao    va_end(ap);
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    exit(-1);
774abdeee073aecd2130e82f301ceff03dbd27fd72Josh Gao}
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint   adb_trace_mask;
809313c0df20d7cc8ea6a074a3d53022c4b3b5ea05Dan Albert
814abdeee073aecd2130e82f301ceff03dbd27fd72Josh Gao/* read a comma/space/colum/semi-column separated list of tags
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * from the ADB_TRACE environment variable and build the trace
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * mask from it. note that '1' and 'all' are special cases to
844abdeee073aecd2130e82f301ceff03dbd27fd72Josh Gao * enable all tracing
854abdeee073aecd2130e82f301ceff03dbd27fd72Josh Gao */
864abdeee073aecd2130e82f301ceff03dbd27fd72Josh Gaovoid  adb_trace_init(void)
874abdeee073aecd2130e82f301ceff03dbd27fd72Josh Gao{
884abdeee073aecd2130e82f301ceff03dbd27fd72Josh Gao    const char*  p = getenv("ADB_TRACE");
894abdeee073aecd2130e82f301ceff03dbd27fd72Josh Gao    const char*  q;
904abdeee073aecd2130e82f301ceff03dbd27fd72Josh Gao
914abdeee073aecd2130e82f301ceff03dbd27fd72Josh Gao    static const struct {
924abdeee073aecd2130e82f301ceff03dbd27fd72Josh Gao        const char*  tag;
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int           flag;
944abdeee073aecd2130e82f301ceff03dbd27fd72Josh Gao    } tags[] = {
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        { "1", 0 },
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        { "all", 0 },
97bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert        { "adb", TRACE_ADB },
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        { "sockets", TRACE_SOCKETS },
99bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert        { "packets", TRACE_PACKETS },
100bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert        { "rwx", TRACE_RWX },
101bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert        { "usb", TRACE_USB },
102bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert        { "sync", TRACE_SYNC },
103bac3474a8256cb32a29e8d46f78cad95a5502692Dan Albert        { "sysdeps", TRACE_SYSDEPS },
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        { "transport", TRACE_TRANSPORT },
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        { "jdwp", TRACE_JDWP },
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        { "services", TRACE_SERVICES },
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        { "auth", TRACE_AUTH },
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        { NULL, 0 }
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    };
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (p == NULL)
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return;
113d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* use a comma/column/semi-colum/space separated list */
1157a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    while (*p) {
116d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        int  len, tagn;
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        q = strpbrk(p, " ,:;");
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (q == NULL) {
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            q = p + strlen(p);
1217a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui        }
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        len = q - p;
123d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
12434f45c566365c966c78264e8a4dc0cf69957b6faYabin Cui        for (tagn = 0; tags[tagn].tag != NULL; tagn++)
125b329824e6c5373ae303269dca285d835ce57e514Yabin Cui        {
12634f45c566365c966c78264e8a4dc0cf69957b6faYabin Cui            int  taglen = strlen(tags[tagn].tag);
12734f45c566365c966c78264e8a4dc0cf69957b6faYabin Cui
12834f45c566365c966c78264e8a4dc0cf69957b6faYabin Cui            if (len == taglen && !memcmp(tags[tagn].tag, p, len) )
129b329824e6c5373ae303269dca285d835ce57e514Yabin Cui            {
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                int  flag = tags[tagn].flag;
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (flag == 0) {
132d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby                    adb_trace_mask = ~0;
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    return;
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                adb_trace_mask |= (1 << flag);
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                break;
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        p = q;
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (*p)
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            p++;
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if !ADB_HOST
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
147d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * Implements ADB tracing inside the emulator.
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdarg.h>
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Redefine open and write for qemu_pipe.h that contains inlined references
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * to those routines. We will redifine them back after qemu_pipe.h inclusion.
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#undef open
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#undef write
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define open    adb_open
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define write   adb_write
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <hardware/qemu_pipe.h>
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#undef open
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#undef write
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define open    ___xxx_open
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define write   ___xxx_write
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* A handle to adb-debug qemud service in the emulator. */
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint   adb_debug_qemu = -1;
169d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* Initializes connection with the adb-debug qemud service in the emulator. */
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int adb_qemu_trace_init(void)
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char con_name[32];
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1757a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    if (adb_debug_qemu >= 0) {
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* adb debugging QEMUD service connection request. */
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    snprintf(con_name, sizeof(con_name), "qemud:adb-debug");
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    adb_debug_qemu = qemu_pipe_open(con_name);
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return (adb_debug_qemu >= 0) ? 0 : -1;
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1857a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cuivoid adb_qemu_trace(const char* fmt, ...)
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_list args;
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_start(args, fmt);
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char msg[1024];
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (adb_debug_qemu >= 0) {
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        vsnprintf(msg, sizeof(msg), fmt, args);
1931792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert        adb_write(adb_debug_qemu, msg, strlen(msg));
1941792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    }
1951792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert}
1961792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert#endif  /* !ADB_HOST */
1971792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert
198e82c2db05cae70a0490a1f84b7211ef42c329671Scott Andersonapacket *get_apacket(void)
199e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson{
200e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson    apacket *p = malloc(sizeof(apacket));
201e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson    if(p == 0) fatal("failed to allocate an apacket");
2021792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    memset(p, 0, sizeof(apacket) - MAX_PAYLOAD);
2031792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    return p;
204e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson}
2051792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert
2061792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albertvoid put_apacket(apacket *p)
2071792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert{
208e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson    free(p);
209e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson}
2101792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert
2111792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albertvoid handle_online(atransport *t)
2124e2fd36bc8c16147cab323b0418a7666812d3bc7David Pursell{
2131792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    D("adb: online\n");
2141792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    t->online = 1;
2151792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert}
2161792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert
217e82c2db05cae70a0490a1f84b7211ef42c329671Scott Andersonvoid handle_offline(atransport *t)
218e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson{
2191792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    D("adb: offline\n");
2207a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    //Close the associated usb
2211792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    t->online = 0;
222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    run_transport_disconnects(t);
2233d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer}
2243d2904cdf2371e26c0465184436bd063979a5d97Tamas Berghammer
2251792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert#if DEBUG_PACKETS
2261792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert#define DUMPMAX 32
2271792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albertvoid print_packet(const char *label, apacket *p)
2281792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert{
2291792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    char *tag;
2301792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    char *x;
2311792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    unsigned count;
2321792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert
2331792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    switch(p->msg.command){
2341792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    case A_SYNC: tag = "SYNC"; break;
2351792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    case A_CNXN: tag = "CNXN" ; break;
2361792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    case A_OPEN: tag = "OPEN"; break;
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case A_OKAY: tag = "OKAY"; break;
238d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    case A_CLSE: tag = "CLSE"; break;
239d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    case A_WRTE: tag = "WRTE"; break;
2408d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    case A_AUTH: tag = "AUTH"; break;
2418d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    default: tag = "????"; break;
2428d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    }
2438d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes
2448d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    fprintf(stderr, "%s: %s %08x %08x %04x \"",
245e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson            label, tag, p->msg.arg0, p->msg.arg1, p->msg.data_length);
2468d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    count = p->msg.data_length;
247e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson    x = (char*) p->data;
248e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson    if(count > DUMPMAX) {
2491792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert        count = DUMPMAX;
2507a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui        tag = "\n";
2518d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    } else {
2528d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes        tag = "\"\n";
2538d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    }
2548d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    while(count-- > 0){
2558d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes        if((*x >= ' ') && (*x < 127)) {
256d2b588e23901538f4b459a71fefdac6fc2748f7eDavid Pursell            fputc(*x, stderr);
257d2b588e23901538f4b459a71fefdac6fc2748f7eDavid Pursell        } else {
258d2b588e23901538f4b459a71fefdac6fc2748f7eDavid Pursell            fputc('.', stderr);
259d2b588e23901538f4b459a71fefdac6fc2748f7eDavid Pursell        }
2608d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes        x++;
2618d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    }
26265fe2516b402ed8903f2ce39a86fa0bdc2b263a6Elliott Hughes    fputs(tag, stderr);
2638d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes}
2648d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes#endif
2658d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes
2668d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughesstatic void send_ready(unsigned local, unsigned remote, atransport *t)
2678d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes{
2688d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    D("Calling send_ready \n");
2698d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    apacket *p = get_apacket();
2708d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    p->msg.command = A_OKAY;
2718d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    p->msg.arg0 = local;
2728d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    p->msg.arg1 = remote;
2738d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    send_packet(p, t);
2748d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes}
2758d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes
2768d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughesstatic void send_close(unsigned local, unsigned remote, atransport *t)
2771792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert{
2784e2fd36bc8c16147cab323b0418a7666812d3bc7David Pursell    D("Calling send_close \n");
279e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson    apacket *p = get_apacket();
280e82c2db05cae70a0490a1f84b7211ef42c329671Scott Anderson    p->msg.command = A_CLSE;
281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.arg0 = local;
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.arg1 = remote;
2838d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    send_packet(p, t);
2848d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes}
2857a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui
286dcd78a15d0be143d48fc93af6a9fa5748dbf9790Dan Albertstatic size_t fill_connect_data(char *buf, size_t bufsize)
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
2888d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes#if ADB_HOST
2897a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    return snprintf(buf, bufsize, "host::") + 1;
290dcd78a15d0be143d48fc93af6a9fa5748dbf9790Dan Albert#else
291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    static const char *cnxn_props[] = {
2928d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes        "ro.product.name",
2937a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui        "ro.product.model",
294dcd78a15d0be143d48fc93af6a9fa5748dbf9790Dan Albert        "ro.product.device",
295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    };
2968d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    static const int num_cnxn_props = ARRAY_SIZE(cnxn_props);
2977a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    int i;
298dcd78a15d0be143d48fc93af6a9fa5748dbf9790Dan Albert    size_t remaining = bufsize;
299447f061da19fe46bae35f1cdd93eeb16bc225463Doug Zongker    size_t len;
3003ce9575af76fa6dc110506080434303b9459abf4Elliott Hughes
3017a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    len = snprintf(buf, remaining, "%s::", adb_device_banner);
302dcd78a15d0be143d48fc93af6a9fa5748dbf9790Dan Albert    remaining -= len;
303447f061da19fe46bae35f1cdd93eeb16bc225463Doug Zongker    buf += len;
304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (i = 0; i < num_cnxn_props; i++) {
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char value[PROPERTY_VALUE_MAX];
3061792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert        property_get(cnxn_props[i], value, "");
3071792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert        len = snprintf(buf, remaining, "%s=%s;", cnxn_props[i], value);
3081792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert        remaining -= len;
3091792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert        buf += len;
3101792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    }
3111792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert
3121792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    return bufsize - remaining + 1;
3131792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert#endif
3141792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert}
3151792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert
3161792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albertstatic void send_connect(atransport *t)
3171792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert{
3181792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    D("Calling send_connect \n");
3191792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    apacket *cp = get_apacket();
3201792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    cp->msg.command = A_CNXN;
3211792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    cp->msg.arg0 = A_VERSION;
3221792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    cp->msg.arg1 = MAX_PAYLOAD;
3231792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    cp->msg.data_length = fill_connect_data((char *)cp->data,
3241792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert                                            sizeof(cp->data));
3251792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    send_packet(cp, t);
3261792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert}
3271792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert
3281792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albertstatic void send_auth_request(atransport *t)
329dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("Calling send_auth_request\n");
3317a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    apacket *p;
332899913f8168b54e00971c0e8d4ae16d06a4651feViral Mehta    int ret;
333899913f8168b54e00971c0e8d4ae16d06a4651feViral Mehta
334899913f8168b54e00971c0e8d4ae16d06a4651feViral Mehta    ret = adb_auth_generate_token(t->token, sizeof(t->token));
335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (ret != sizeof(t->token)) {
336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D("Error generating token ret=%d\n", ret);
337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return;
338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
339ffc73a39fd813c8823ca0e4cdc52b79521ce84daElliott Hughes
340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p = get_apacket();
341661327e8e40f95076e0e8abe86193da16b061bd8Yabin Cui    memcpy(p->data, t->token, ret);
342661327e8e40f95076e0e8abe86193da16b061bd8Yabin Cui    p->msg.command = A_AUTH;
343661327e8e40f95076e0e8abe86193da16b061bd8Yabin Cui    p->msg.arg0 = ADB_AUTH_TOKEN;
344dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.data_length = ret;
345dcd78a15d0be143d48fc93af6a9fa5748dbf9790Dan Albert    send_packet(p, t);
346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void send_auth_response(uint8_t *token, size_t token_size, atransport *t)
349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
350dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("Calling send_auth_response\n");
3511792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    apacket *p = get_apacket();
3521792c23cb892ab58590b2cdfce0d0ece30c21787Dan Albert    int ret;
353d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
354d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    ret = adb_auth_sign(t->key, token, token_size, p->data);
355d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    if (!ret) {
356d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        D("Error signing the token\n");
357dcd78a15d0be143d48fc93af6a9fa5748dbf9790Dan Albert        put_apacket(p);
3580aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes        return;
359d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    }
3600aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes
361d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    p->msg.command = A_AUTH;
362d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    p->msg.arg0 = ADB_AUTH_SIGNATURE;
363d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    p->msg.data_length = ret;
364c8cb38803af20e922419760663ed1627e865fad2Josh Gao    send_packet(p, t);
365d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby}
366d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
367d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobystatic void send_auth_publickey(atransport *t)
368d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby{
369d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    D("Calling send_auth_publickey\n");
370dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    apacket *p = get_apacket();
371dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int ret;
372dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
373818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    ret = adb_auth_get_userkey(p->data, sizeof(p->data));
374dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!ret) {
375dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D("Failed to get user public key\n");
376ffc73a39fd813c8823ca0e4cdc52b79521ce84daElliott Hughes        put_apacket(p);
377ffc73a39fd813c8823ca0e4cdc52b79521ce84daElliott Hughes        return;
378dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
379dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
380dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.command = A_AUTH;
381dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.arg0 = ADB_AUTH_RSAPUBLICKEY;
382dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p->msg.data_length = ret;
383dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    send_packet(p, t);
384dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
385dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
386dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid adb_auth_verified(atransport *t)
387dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
388dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    handle_online(t);
389818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    send_connect(t);
390ffc73a39fd813c8823ca0e4cdc52b79521ce84daElliott Hughes}
391ffc73a39fd813c8823ca0e4cdc52b79521ce84daElliott Hughes
392dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic char *connection_state_name(atransport *t)
393818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner{
394dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (t == NULL) {
395dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return "unknown";
396818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    }
397818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner
398818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    switch(t->connection_state) {
399818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    case CS_BOOTLOADER:
400818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner        return "bootloader";
4017a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    case CS_DEVICE:
402818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner        return "device";
403dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case CS_OFFLINE:
404aa77e22d7384a97757e2d2194f4e265f7ad3b71aYabin Cui        return "offline";
405aa77e22d7384a97757e2d2194f4e265f7ad3b71aYabin Cui    default:
406aa77e22d7384a97757e2d2194f4e265f7ad3b71aYabin Cui        return "unknown";
407aa77e22d7384a97757e2d2194f4e265f7ad3b71aYabin Cui    }
408aa77e22d7384a97757e2d2194f4e265f7ad3b71aYabin Cui}
409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* qual_overwrite is used to overwrite a qualifier string.  dst is a
411dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * pointer to a char pointer.  It is assumed that if *dst is non-NULL, it
412dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * was malloc'ed and needs to freed.  *dst will be set to a dup of src.
413818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner */
414818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turnerstatic void qual_overwrite(char **dst, const char *src)
415ffc73a39fd813c8823ca0e4cdc52b79521ce84daElliott Hughes{
416ffc73a39fd813c8823ca0e4cdc52b79521ce84daElliott Hughes    if (!dst)
417818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner        return;
418818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner
419818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    free(*dst);
420818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    *dst = NULL;
421818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner
422818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    if (!src || !*src)
423818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner        return;
424818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner
425818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    *dst = strdup(src);
426818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner}
427818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner
4287a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cuivoid parse_banner(char *banner, atransport *t)
429818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner{
430818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    static const char *prop_seps = ";";
431818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    static const char key_val_sep = '=';
432818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    char *cp;
433dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *type;
434dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
435dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D("parse_banner: %s\n", banner);
436dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    type = banner;
437818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    cp = strchr(type, ':');
438818d641c420f5d4f35f4e8706937c17b974146d1David 'Digit' Turner    if (cp) {
439ffc73a39fd813c8823ca0e4cdc52b79521ce84daElliott Hughes        *cp++ = 0;
440ffc73a39fd813c8823ca0e4cdc52b79521ce84daElliott Hughes        /* Nothing is done with second field. */
441dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        cp = strchr(cp, ':');
442dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (cp) {
443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            char *save;
444ffc73a39fd813c8823ca0e4cdc52b79521ce84daElliott Hughes            char *key;
4457a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui            key = adb_strtok_r(cp + 1, prop_seps, &save);
446dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            while (key) {
447dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                cp = strchr(key, key_val_sep);
448dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (cp) {
449dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    *cp++ = '\0';
450dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    if (!strcmp(key, "ro.product.name"))
451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        qual_overwrite(&t->product, cp);
452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    else if (!strcmp(key, "ro.product.model"))
453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        qual_overwrite(&t->model, cp);
454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    else if (!strcmp(key, "ro.product.device"))
455dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        qual_overwrite(&t->device, cp);
456dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                key = adb_strtok_r(NULL, prop_seps, &save);
458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
461571c1367682c83cb23481cc9c1028c8588a1fed0JP Abgrall
4622122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    if(!strcmp(type, "bootloader")){
4632122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        D("setting connection_state to CS_BOOTLOADER\n");
464bc36bdbdc8bb64011bc573a14d54576946fa1006Spencer Low        t->connection_state = CS_BOOTLOADER;
465bc36bdbdc8bb64011bc573a14d54576946fa1006Spencer Low        update_transports();
466bc36bdbdc8bb64011bc573a14d54576946fa1006Spencer Low        return;
467bc36bdbdc8bb64011bc573a14d54576946fa1006Spencer Low    }
468bc36bdbdc8bb64011bc573a14d54576946fa1006Spencer Low
4692122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    if(!strcmp(type, "device")) {
470bc36bdbdc8bb64011bc573a14d54576946fa1006Spencer Low        D("setting connection_state to CS_DEVICE\n");
471bc36bdbdc8bb64011bc573a14d54576946fa1006Spencer Low        t->connection_state = CS_DEVICE;
472bc36bdbdc8bb64011bc573a14d54576946fa1006Spencer Low        update_transports();
473bc36bdbdc8bb64011bc573a14d54576946fa1006Spencer Low        return;
474bc36bdbdc8bb64011bc573a14d54576946fa1006Spencer Low    }
475bc36bdbdc8bb64011bc573a14d54576946fa1006Spencer Low
476bc36bdbdc8bb64011bc573a14d54576946fa1006Spencer Low    if(!strcmp(type, "recovery")) {
477bc36bdbdc8bb64011bc573a14d54576946fa1006Spencer Low        D("setting connection_state to CS_RECOVERY\n");
478bc36bdbdc8bb64011bc573a14d54576946fa1006Spencer Low        t->connection_state = CS_RECOVERY;
479bc36bdbdc8bb64011bc573a14d54576946fa1006Spencer Low        update_transports();
480bc36bdbdc8bb64011bc573a14d54576946fa1006Spencer Low        return;
481bc36bdbdc8bb64011bc573a14d54576946fa1006Spencer Low    }
482bc36bdbdc8bb64011bc573a14d54576946fa1006Spencer Low
4835f787ed2b3b9f6cc02aa5923b95d77e2a5865438David Pursell    if(!strcmp(type, "sideload")) {
484bc36bdbdc8bb64011bc573a14d54576946fa1006Spencer Low        D("setting connection_state to CS_SIDELOAD\n");
4852122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        t->connection_state = CS_SIDELOAD;
4862122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        update_transports();
4872122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        return;
4882122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    }
4892122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
4902122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    t->connection_state = CS_HOST;
4912122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low}
4922122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
4932122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Lowvoid handle_packet(apacket *p, atransport *t)
4942122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low{
4952122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    asocket *s;
4962122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
4972122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0],
4982122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            ((char*) (&(p->msg.command)))[1],
4995f787ed2b3b9f6cc02aa5923b95d77e2a5865438David Pursell            ((char*) (&(p->msg.command)))[2],
5002122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            ((char*) (&(p->msg.command)))[3]);
5012122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    print_packet("recv", p);
5022122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
5032122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    switch(p->msg.command){
5042122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    case A_SYNC:
5052122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        if(p->msg.arg0){
5062122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            send_packet(p, t);
5072122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            if(HOST) send_connect(t);
5082122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        } else {
5092122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            t->connection_state = CS_OFFLINE;
5102122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            handle_offline(t);
5112122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            send_packet(p, t);
5122122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        }
5132122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        return;
5142122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
5152122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */
5162122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            /* XXX verify version, etc */
5172122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        if(t->connection_state != CS_OFFLINE) {
51853a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low            t->connection_state = CS_OFFLINE;
51953a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low            handle_offline(t);
52053a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low        }
5212122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
5222122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        parse_banner((char*) p->data, t);
5232122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
52453a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low        if (HOST || !auth_enabled) {
52553a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low            handle_online(t);
52653a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low            if(!HOST) send_connect(t);
52753a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low        } else {
52853a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low            send_auth_request(t);
52953a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low        }
53053a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low        break;
53153a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low
53253a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low    case A_AUTH:
53353a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low        if (p->msg.arg0 == ADB_AUTH_TOKEN) {
53453a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low            t->key = adb_auth_nextkey(t->key);
53553a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low            if (t->key) {
53653a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low                send_auth_response(p->data, p->msg.data_length, t);
53753a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low            } else {
53853a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low                /* No more private keys to try, send the public key */
53953a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low                send_auth_publickey(t);
54053a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low            }
54153a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low        } else if (p->msg.arg0 == ADB_AUTH_SIGNATURE) {
54253a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low            if (adb_auth_verify(t->token, p->data, p->msg.data_length)) {
54353a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low                adb_auth_verified(t);
54453a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low                t->failed_auth_attempts = 0;
54553a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low            } else {
54653a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low                if (t->failed_auth_attempts++ > 10)
54753a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low                    adb_sleep_ms(1000);
54853a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low                send_auth_request(t);
54953a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low            }
55053a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low        } else if (p->msg.arg0 == ADB_AUTH_RSAPUBLICKEY) {
55153a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low            adb_auth_confirm_key(p->data, p->msg.data_length, t);
55253a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low        }
55353a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low        break;
55453a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low
55553a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low    case A_OPEN: /* OPEN(local-id, 0, "destination") */
55653a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low        if (t->online) {
55753a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low            char *name = (char*) p->data;
55853a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low            name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0;
55953a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low            s = create_local_service_socket(name);
56053a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low            if(s == 0) {
56153a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low                send_close(0, p->msg.arg0, t);
56253a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low            } else {
56353a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low                s->peer = create_remote_socket(p->msg.arg0, t);
56453a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low                s->peer->peer = s;
56553a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low                send_ready(s->id, s->peer->id, t);
56653a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low                s->ready(s);
56753a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low            }
56853a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low        }
56953a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low        break;
57053a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low
57153a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low    case A_OKAY: /* READY(local-id, remote-id, "") */
5722122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        if (t->online) {
5732122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            if((s = find_local_socket(p->msg.arg1))) {
5742122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                if(s->peer == 0) {
5752122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                    s->peer = create_remote_socket(p->msg.arg0, t);
5762122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                    s->peer->peer = s;
5772122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                }
5782122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                s->ready(s);
5792122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            }
5802122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        }
5812122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        break;
5822122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
5832122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    case A_CLSE: /* CLOSE(local-id, remote-id, "") */
5845f787ed2b3b9f6cc02aa5923b95d77e2a5865438David Pursell        if (t->online) {
5852122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            if((s = find_local_socket(p->msg.arg1))) {
5862122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                s->close(s);
5872122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            }
5882122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        }
58953a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low        break;
59053a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low
59153a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low    case A_WRTE:
59253a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low        if (t->online) {
5932122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            if((s = find_local_socket(p->msg.arg1))) {
59453a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low                unsigned rid = p->msg.arg0;
59553a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low                p->len = p->msg.data_length;
5962122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
5972122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                if(s->enqueue(s, p) == 0) {
5982122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                    D("Enqueue the socket\n");
5992122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                    send_ready(s->id, rid, t);
6002122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                }
6012122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                return;
6022122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            }
60349ee7cf9a10f66ffa9a3490c69db5fa46e0a966bSiva Velusamy        }
6042122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        break;
6052122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
6062122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    default:
6072122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        printf("handle_packet: what is %08x?!\n", p->msg.command);
60849ee7cf9a10f66ffa9a3490c69db5fa46e0a966bSiva Velusamy    }
6092122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
6102122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    put_apacket(p);
6112122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low}
6122122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
6132122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Lowalistener listener_list = {
614a84a42eb20d43ffa2695a69d583a6e09532b49d9Stefan Hilzinger    .next = &listener_list,
615dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    .prev = &listener_list,
616e77b6a08623bba383ce55cd6653bec76cdf57792Yabin Cui};
617dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
618dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void ss_listener_event_func(int _fd, unsigned ev, void *_l)
619dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
620dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    asocket *s;
621dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
622dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if(ev & FDE_READ) {
623dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        struct sockaddr addr;
624dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        socklen_t alen;
625dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int fd;
6262122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
6272122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        alen = sizeof(addr);
6282122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        fd = adb_socket_accept(_fd, &addr, &alen);
6292122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        if(fd < 0) return;
6302122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
6312122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        adb_socket_setbufsize(fd, CHUNK_SIZE);
6322122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
6332122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        s = create_local_socket(fd);
6342122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        if(s) {
6352122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            connect_to_smartsocket(s);
6362122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            return;
6372122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        }
6382122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
6392122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        adb_close(fd);
6405f787ed2b3b9f6cc02aa5923b95d77e2a5865438David Pursell    }
641d0f66c361641dc30162877ee3e4b4690d6833442Spencer Low}
642d0f66c361641dc30162877ee3e4b4690d6833442Spencer Low
643d0f66c361641dc30162877ee3e4b4690d6833442Spencer Lowstatic void listener_event_func(int _fd, unsigned ev, void *_l)
64453a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low{
64553a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low    alistener *l = _l;
64653a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low    asocket *s;
64753a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low
6482122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    if(ev & FDE_READ) {
6492122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        struct sockaddr addr;
650d0f66c361641dc30162877ee3e4b4690d6833442Spencer Low        socklen_t alen;
651d0f66c361641dc30162877ee3e4b4690d6833442Spencer Low        int fd;
6522122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
6532122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        alen = sizeof(addr);
6542122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        fd = adb_socket_accept(_fd, &addr, &alen);
6552122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        if(fd < 0) return;
6562122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
6572122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        s = create_local_socket(fd);
658dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if(s) {
659dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            s->transport = l->transport;
660dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            connect_to_remote(s, l->connect_to);
661267aa8b00eadf273321e492026af74b7baad890eRay Donnelly            return;
662267aa8b00eadf273321e492026af74b7baad890eRay Donnelly        }
663267aa8b00eadf273321e492026af74b7baad890eRay Donnelly
664267aa8b00eadf273321e492026af74b7baad890eRay Donnelly        adb_close(fd);
665267aa8b00eadf273321e492026af74b7baad890eRay Donnelly    }
666267aa8b00eadf273321e492026af74b7baad890eRay Donnelly}
667267aa8b00eadf273321e492026af74b7baad890eRay Donnelly
668267aa8b00eadf273321e492026af74b7baad890eRay Donnellystatic void  free_listener(alistener*  l)
669267aa8b00eadf273321e492026af74b7baad890eRay Donnelly{
670267aa8b00eadf273321e492026af74b7baad890eRay Donnelly    if (l->next) {
6712122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        l->next->prev = l->prev;
6722122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        l->prev->next = l->next;
6732122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        l->next = l->prev = l;
6742122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    }
6752122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
6762122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // closes the corresponding fd
6772122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    fdevent_remove(&l->fde);
678bc36bdbdc8bb64011bc573a14d54576946fa1006Spencer Low
679bc36bdbdc8bb64011bc573a14d54576946fa1006Spencer Low    if (l->local_name)
680bc36bdbdc8bb64011bc573a14d54576946fa1006Spencer Low        free((char*)l->local_name);
681267aa8b00eadf273321e492026af74b7baad890eRay Donnelly
682bc36bdbdc8bb64011bc573a14d54576946fa1006Spencer Low    if (l->connect_to)
683bc36bdbdc8bb64011bc573a14d54576946fa1006Spencer Low        free((char*)l->connect_to);
684bc36bdbdc8bb64011bc573a14d54576946fa1006Spencer Low
685267aa8b00eadf273321e492026af74b7baad890eRay Donnelly    if (l->transport) {
6862122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        remove_transport_disconnect(l->transport, &l->disconnect);
687dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
688dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    free(l);
6892122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low}
6902122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
6912122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Lowstatic void listener_disconnect(void*  _l, atransport*  t)
692dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
693dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    alistener*  l = _l;
6945c398d2ce96150e94e596e959bfe2246b94de660Spencer Low
6955c398d2ce96150e94e596e959bfe2246b94de660Spencer Low    free_listener(l);
6962122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low}
6972122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
6985c398d2ce96150e94e596e959bfe2246b94de660Spencer Lowint local_name_to_fd(const char *name)
6995c398d2ce96150e94e596e959bfe2246b94de660Spencer Low{
7005c398d2ce96150e94e596e959bfe2246b94de660Spencer Low    int port;
7012122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
7022122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    if(!strncmp("tcp:", name, 4)){
7035c398d2ce96150e94e596e959bfe2246b94de660Spencer Low        int  ret;
7045c398d2ce96150e94e596e959bfe2246b94de660Spencer Low        port = atoi(name + 4);
7055c398d2ce96150e94e596e959bfe2246b94de660Spencer Low
7062122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        if (gListenAll > 0) {
7072122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            ret = socket_inaddr_any_server(port, SOCK_STREAM);
7082122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        } else {
7092122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            ret = socket_loopback_server(port, SOCK_STREAM);
7102122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        }
7112122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
7122122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        return ret;
7135f787ed2b3b9f6cc02aa5923b95d77e2a5865438David Pursell    }
7142122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low#ifndef HAVE_WIN32_IPC  /* no Unix-domain sockets on Win32 */
7152122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // It's non-sensical to support the "reserved" space on the adb host side
7162122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    if(!strncmp(name, "local:", 6)) {
7172122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        return socket_local_server(name + 6,
718cf4ff64f2d3cdc4ffa2f06e594d18a965f591a82Spencer Low                ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
7195c398d2ce96150e94e596e959bfe2246b94de660Spencer Low    } else if(!strncmp(name, "localabstract:", 14)) {
7202122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        return socket_local_server(name + 14,
7212122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
7222122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    } else if(!strncmp(name, "localfilesystem:", 16)) {
7232122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        return socket_local_server(name + 16,
7242122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
7252122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    }
726dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
727a09558c2e205771e6830eeb6241c5c0e3b1cf4ceWenhao Li#endif
728dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    printf("unknown local portname '%s'\n", name);
729dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
730dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
731dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
732dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// Write a single line describing a listener to a user-provided buffer.
733dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// Appends a trailing zero, even in case of truncation, but the function
734dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// returns the full line length.
735dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project// If |buffer| is NULL, does not write but returns required size.
736dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int format_listener(alistener* l, char* buffer, size_t buffer_len) {
7372122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // Format is simply:
7382122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    //
7395f787ed2b3b9f6cc02aa5923b95d77e2a5865438David Pursell    //  <device-serial> " " <local-name> " " <remote-name> "\n"
7402122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    //
7412122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    int local_len = strlen(l->local_name);
742dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int connect_len = strlen(l->connect_to);
7432122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    int serial_len = strlen(l->transport->serial);
7442122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
7452122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    if (buffer != NULL) {
7462122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        snprintf(buffer, buffer_len, "%s %s %s\n",
7472122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                l->transport->serial, l->local_name, l->connect_to);
7482122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    }
7492122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // NOTE: snprintf() on Windows returns -1 in case of truncation, so
7502122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    // return the computed line length instead.
7512122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    return local_len + connect_len + serial_len + 3;
7522122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low}
7532122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
7542122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low// Write the list of current listeners (network redirections) into a
75553a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low// user-provided buffer. Appends a trailing zero, even in case of
75653a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low// trunctaion, but return the full size in bytes.
75753a0a99fe8197984acd5ed6324e945c09772a73eSpencer Low// If |buffer| is NULL, does not write but returns required size.
7582122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Lowstatic int format_listeners(char* buf, size_t buflen)
7592122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low{
7602122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    alistener* l;
7612122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    int result = 0;
7622122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    for (l = listener_list.next; l != &listener_list; l = l->next) {
7632122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        // Ignore special listeners like those for *smartsocket*
7642122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        if (l->connect_to[0] == '*')
7652122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low          continue;
7662122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        int len = format_listener(l, buf, buflen);
7672122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        // Ensure there is space for the trailing zero.
7682122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        result += len;
7692122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        if (buf != NULL) {
7702122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low          buf += len;
7712122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low          buflen -= len;
772dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project          if (buflen <= 0)
7732122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low              break;
7742122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        }
7752122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    }
7762122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    return result;
7772122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low}
778dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
779dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int remove_listener(const char *local_name, atransport* transport)
7802122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low{
781dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    alistener *l;
7822122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
783dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (l = listener_list.next; l != &listener_list; l = l->next) {
7842122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        if (!strcmp(local_name, l->local_name)) {
785dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            listener_disconnect(l, l->transport);
7862122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            return 0;
7872122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        }
7882122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    }
7892122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    return -1;
7902122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low}
7912122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
7922122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Lowstatic void remove_all_listeners(void)
7932122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low{
7942122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    alistener *l, *l_next;
7952122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    for (l = listener_list.next; l != &listener_list; l = l_next) {
7962122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        l_next = l->next;
7972122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        // Never remove smart sockets.
7982122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        if (l->connect_to[0] == '*')
7992122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            continue;
8002122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        listener_disconnect(l, l->transport);
8012122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    }
8022122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low}
8032122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
8042122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low// error/status codes for install_listener.
8052122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Lowtypedef enum {
8065f787ed2b3b9f6cc02aa5923b95d77e2a5865438David Pursell  INSTALL_STATUS_OK = 0,
807dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project  INSTALL_STATUS_INTERNAL_ERROR = -1,
8082122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low  INSTALL_STATUS_CANNOT_BIND = -2,
8092122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low  INSTALL_STATUS_CANNOT_REBIND = -3,
8102122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low} install_status_t;
8112122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
8122122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Lowstatic install_status_t install_listener(const char *local_name,
8132122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                                         const char *connect_to,
8142122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                                         atransport* transport,
8152122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                                         int no_rebind)
8162122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low{
8172122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    alistener *l;
8182122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
8192122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    //printf("install_listener('%s','%s')\n", local_name, connect_to);
8202122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
8212122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low    for(l = listener_list.next; l != &listener_list; l = l->next){
8222122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low        if(strcmp(local_name, l->local_name) == 0) {
8232122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            char *cto;
8242122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
8252122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                /* can't repurpose a smartsocket */
8262122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            if(l->connect_to[0] == '*') {
8272122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                return INSTALL_STATUS_INTERNAL_ERROR;
8282122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            }
8292122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
8302122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                /* can't repurpose a listener if 'no_rebind' is true */
831dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (no_rebind) {
8322122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                return INSTALL_STATUS_CANNOT_REBIND;
8332122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            }
8342122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
8352122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            cto = strdup(connect_to);
8362122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            if(cto == 0) {
8375f787ed2b3b9f6cc02aa5923b95d77e2a5865438David Pursell                return INSTALL_STATUS_INTERNAL_ERROR;
8382122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            }
8392122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low
8402122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            //printf("rebinding '%s' to '%s'\n", local_name, connect_to);
8412122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            free((void*) l->connect_to);
8422122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            l->connect_to = cto;
8432122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low            if (l->transport != transport) {
8442122c7a1483dc6050b33f58fad4a15d5acd79fddSpencer Low                remove_transport_disconnect(l->transport, &l->disconnect);
845dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                l->transport = transport;
846e77b6a08623bba383ce55cd6653bec76cdf57792Yabin Cui                add_transport_disconnect(l->transport, &l->disconnect);
847dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
8489f2d1a9cfc04e1d5970823da1878097288a9a9cdSiva Velusamy            return INSTALL_STATUS_OK;
84982ff315bb0fecb9127970e01b399be53c92ca14fElliott Hughes        }
850dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
851dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
852dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if((l = calloc(1, sizeof(alistener))) == 0) goto nomem;
853dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if((l->local_name = strdup(local_name)) == 0) goto nomem;
85482ff315bb0fecb9127970e01b399be53c92ca14fElliott Hughes    if((l->connect_to = strdup(connect_to)) == 0) goto nomem;
85582ff315bb0fecb9127970e01b399be53c92ca14fElliott Hughes
85682ff315bb0fecb9127970e01b399be53c92ca14fElliott Hughes
857dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    l->fd = local_name_to_fd(local_name);
85882ff315bb0fecb9127970e01b399be53c92ca14fElliott Hughes    if(l->fd < 0) {
859dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        free((void*) l->local_name);
860dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        free((void*) l->connect_to);
861dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        free(l);
862dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        printf("cannot bind '%s'\n", local_name);
863dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -2;
864dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
865d7b33085117ccbb908a883f624cb1fe5495ee92aMatt Gumbel
8669f2d1a9cfc04e1d5970823da1878097288a9a9cdSiva Velusamy    close_on_exec(l->fd);
8679f2d1a9cfc04e1d5970823da1878097288a9a9cdSiva Velusamy    if(!strcmp(l->connect_to, "*smartsocket*")) {
8689f2d1a9cfc04e1d5970823da1878097288a9a9cdSiva Velusamy        fdevent_install(&l->fde, l->fd, ss_listener_event_func, l);
869dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
87082ff315bb0fecb9127970e01b399be53c92ca14fElliott Hughes        fdevent_install(&l->fde, l->fd, listener_event_func, l);
871dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
872dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fdevent_set(&l->fde, FDE_READ);
873dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
874dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    l->next = &listener_list;
875dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    l->prev = listener_list.prev;
876dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    l->next->prev = l;
877dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    l->prev->next = l;
878dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    l->transport = transport;
879dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
880dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (transport) {
881dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        l->disconnect.opaque = l;
882408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall        l->disconnect.func   = listener_disconnect;
883dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        add_transport_disconnect(transport, &l->disconnect);
884dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
885408fa57864c01113deaa213e5c1848a9c594ae92JP Abgrall    return INSTALL_STATUS_OK;
886dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
887dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectnomem:
888dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fatal("cannot allocate listener");
889dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return INSTALL_STATUS_INTERNAL_ERROR;
890dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
891dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
892dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifdef HAVE_WIN32_PROC
893e77b6a08623bba383ce55cd6653bec76cdf57792Yabin Cuistatic BOOL WINAPI ctrlc_handler(DWORD type)
894dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
895dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    exit(STATUS_CONTROL_C_EXIT);
896e77b6a08623bba383ce55cd6653bec76cdf57792Yabin Cui    return TRUE;
897dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
898252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner#endif
899252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
900252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turnerstatic void adb_cleanup(void)
901aee80fb67bcc3fc5209050c40bd8efc1bbcc0610Elliott Hughes{
902252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    usb_cleanup();
903252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner}
904252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
905e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughesvoid start_logging(void)
906252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner{
907e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes#ifdef HAVE_WIN32_PROC
908252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    char    temp[ MAX_PATH ];
9097e6683ce40ba79c94ccc1e3b984cd39e63651dd5Josh Gao    FILE*   fnul;
910252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    FILE*   flog;
911252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
912252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    GetTempPath( sizeof(temp) - 8, temp );
913252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    strcat( temp, "adb.log" );
914252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
915252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    /* Win32 specific redirections */
916e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes    fnul = fopen( "NUL", "rt" );
917252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    if (fnul != NULL)
918e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes        stdin[0] = fnul[0];
919252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
920252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    flog = fopen( temp, "at" );
921252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    if (flog == NULL)
922424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes        flog = fnul;
923424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes
924424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes    setvbuf( flog, NULL, _IONBF, 0 );
925424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes
926424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes    stdout[0] = flog[0];
927424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes    stderr[0] = flog[0];
928424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes    fprintf(stderr,"--- adb starting (pid %d) ---\n", getpid());
929424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes#else
930a6b340af123b82e3aaa33cb2a0d45f637eeb4759Spencer Low    int fd;
931a6b340af123b82e3aaa33cb2a0d45f637eeb4759Spencer Low
932424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes    fd = unix_open("/dev/null", O_RDONLY);
933424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes    dup2(fd, 0);
934424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes    adb_close(fd);
935424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes
936252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    fd = unix_open("/tmp/adb.log", O_WRONLY | O_CREAT | O_APPEND, 0640);
937252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    if(fd < 0) {
938424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes        fd = unix_open("/dev/null", O_WRONLY);
939252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    }
940424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes    dup2(fd, 1);
941424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes    dup2(fd, 2);
942424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes    adb_close(fd);
943424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes    fprintf(stderr,"--- adb starting (pid %d) ---\n", getpid());
944252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner#endif
945252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner}
946252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
947424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes#if !ADB_HOST
948424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughesvoid start_device_log(void)
949424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes{
950252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    int fd;
951252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    char    path[PATH_MAX];
952252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    struct tm now;
953252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    time_t t;
9547be29c819b4fb8bf9b1d4b69a4333f8765de0281Elliott Hughes    char value[PROPERTY_VALUE_MAX];
9558d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes
956252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    // read the trace mask from persistent property persist.adb.trace_mask
957e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes    // give up if the property is not set or cannot be parsed
958252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    property_get("persist.adb.trace_mask", value, "");
959252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    if (sscanf(value, "%x", &adb_trace_mask) != 1)
960252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        return;
9615200c6670f041550c23821fec8e8e49b30ef6d29Spencer Low
9623bd73c12c07dcefc965abeef535ac53c4754d682Elliott Hughes    adb_mkdir("/data/adb", 0775);
963eaae97e127717750b4264d9b6617b845f9bc701fDavid Pursell    tzset();
964424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes    time(&t);
965424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes    localtime_r(&t, &now);
966252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    strftime(path, sizeof(path),
967eaae97e127717750b4264d9b6617b845f9bc701fDavid Pursell                "/data/adb/adb-%Y-%m-%d-%H-%M-%S.txt",
968eaae97e127717750b4264d9b6617b845f9bc701fDavid Pursell                &now);
969252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    fd = unix_open(path, O_WRONLY | O_CREAT | O_TRUNC, 0640);
9707b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes    if (fd < 0)
971252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner        return;
972eaae97e127717750b4264d9b6617b845f9bc701fDavid Pursell
973e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes    // redirect stdout and stderr to the log file
974252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner    dup2(fd, 1);
975e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes    dup2(fd, 2);
976eaae97e127717750b4264d9b6617b845f9bc701fDavid Pursell    fprintf(stderr,"--- adb starting (pid %d) ---\n", getpid());
977eaae97e127717750b4264d9b6617b845f9bc701fDavid Pursell    adb_close(fd);
978eaae97e127717750b4264d9b6617b845f9bc701fDavid Pursell
979eaae97e127717750b4264d9b6617b845f9bc701fDavid Pursell    fd = unix_open("/dev/null", O_RDONLY);
980eaae97e127717750b4264d9b6617b845f9bc701fDavid Pursell    dup2(fd, 0);
981eaae97e127717750b4264d9b6617b845f9bc701fDavid Pursell    adb_close(fd);
982252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner}
983252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner#endif
984252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
9857b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes#if ADB_HOST
9867b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes
987424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes#ifdef WORKAROUND_BUG6558362
9887b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes#include <sched.h>
9897b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes#define AFFINITY_ENVVAR "ADB_CPU_AFFINITY_BUG6558362"
990bf7c605d87f87c03066c384cecb0f0c91aa31403Spencer Lowvoid adb_set_affinity(void)
9915200c6670f041550c23821fec8e8e49b30ef6d29Spencer Low{
9927b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes   cpu_set_t cpu_set;
9937b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes   const char* cpunum_str = getenv(AFFINITY_ENVVAR);
994a6b340af123b82e3aaa33cb2a0d45f637eeb4759Spencer Low   char* strtol_res;
9957b506090e1ac51f4990f17621c6e33847b0632a2Elliott Hughes   int cpu_num;
996424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes
997424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes   if (!cpunum_str || !*cpunum_str)
998424af02f363a305a349ff99e1cc253ac5bc642c9Elliott Hughes       return;
999252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner   cpu_num = strtol(cpunum_str, &strtol_res, 0);
1000e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes   if (*strtol_res != '\0')
1001252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner     fatal("bad number (%s) in env var %s. Expecting 0..n.\n", cpunum_str, AFFINITY_ENVVAR);
1002252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner
1003252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner   sched_getaffinity(0, sizeof(cpu_set), &cpu_set);
1004252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner   D("orig cpu_set[0]=0x%08lx\n", cpu_set.__bits[0]);
1005252586941934d23073a8d167ec240b221062505fDavid 'Digit' Turner   CPU_ZERO(&cpu_set);
1006e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes   CPU_SET(cpu_num, &cpu_set);
1007e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes   sched_setaffinity(0, sizeof(cpu_set), &cpu_set);
1008e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes   sched_getaffinity(0, sizeof(cpu_set), &cpu_set);
1009e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes   D("new cpu_set[0]=0x%08lx\n", cpu_set.__bits[0]);
1010e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes}
1011e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes#endif
1012e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes
1013e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughesint launch_server(int server_port)
1014c89e0ccd40624e8b2ce30d425e8bed0264fae548Dan Albert{
1015c89e0ccd40624e8b2ce30d425e8bed0264fae548Dan Albert#ifdef HAVE_WIN32_PROC
1016c89e0ccd40624e8b2ce30d425e8bed0264fae548Dan Albert    /* we need to start the server in the background                    */
1017c89e0ccd40624e8b2ce30d425e8bed0264fae548Dan Albert    /* we create a PIPE that will be used to wait for the server's "OK" */
1018dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* message since the pipe handles must be inheritable, we use a     */
1019e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes    /* security attribute                                               */
1020f18fc0879be9cd506be6b1e051feb543b0746bdbSpencer Low    HANDLE                pipe_read, pipe_write;
1021351ecd15b29f0ce528ffac119640b9c01874562bSpencer Low    SECURITY_ATTRIBUTES   sa;
1022351ecd15b29f0ce528ffac119640b9c01874562bSpencer Low    STARTUPINFO           startup;
1023351ecd15b29f0ce528ffac119640b9c01874562bSpencer Low    PROCESS_INFORMATION   pinfo;
1024351ecd15b29f0ce528ffac119640b9c01874562bSpencer Low    char                  program_path[ MAX_PATH ];
1025351ecd15b29f0ce528ffac119640b9c01874562bSpencer Low    int                   ret;
1026f18fc0879be9cd506be6b1e051feb543b0746bdbSpencer Low
1027f18fc0879be9cd506be6b1e051feb543b0746bdbSpencer Low    sa.nLength = sizeof(sa);
1028dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sa.lpSecurityDescriptor = NULL;
1029dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    sa.bInheritHandle = TRUE;
1030dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1031dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* create pipe, and ensure its read handle isn't inheritable */
1032dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ret = CreatePipe( &pipe_read, &pipe_write, &sa, 0 );
1033dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!ret) {
1034dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fprintf(stderr, "CreatePipe() failure, error %ld\n", GetLastError() );
1035dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
1036dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
10373bd73c12c07dcefc965abeef535ac53c4754d682Elliott Hughes
1038dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SetHandleInformation( pipe_read, HANDLE_FLAG_INHERIT, 0 );
1039dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1040dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ZeroMemory( &startup, sizeof(startup) );
1041dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    startup.cb = sizeof(startup);
1042dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    startup.hStdInput  = GetStdHandle( STD_INPUT_HANDLE );
1043dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    startup.hStdOutput = pipe_write;
1044dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    startup.hStdError  = GetStdHandle( STD_ERROR_HANDLE );
1045dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    startup.dwFlags    = STARTF_USESTDHANDLES;
1046dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
10473175c8e9bfcb01f181d7300755da15a999e5461cTom Marlin    ZeroMemory( &pinfo, sizeof(pinfo) );
1048dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
1049dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    /* get path of current program */
10508d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes    GetModuleFileName( NULL, program_path, sizeof(program_path) );
10518d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes
1052e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes    ret = CreateProcess(
1053e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes            program_path,                              /* program path  */
1054e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes            "adb fork-server server",
1055dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                                    /* the fork-server argument will set the
10568d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes                                       debug = 2 in the child           */
1057dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            NULL,                   /* process handle is not inheritable */
1058dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            NULL,                    /* thread handle is not inheritable */
1059dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            TRUE,                          /* yes, inherit some handles */
1060dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            DETACHED_PROCESS, /* the new process doesn't have a console */
1061dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            NULL,                     /* use parent's environment block */
1062e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson            NULL,                    /* use parent's starting directory */
1063e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes            &startup,                 /* startup info, i.e. std handles */
1064e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes            &pinfo );
10657a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui
1066e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes    CloseHandle( pipe_write );
10677a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui
1068e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes    if (!ret) {
1069e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson        fprintf(stderr, "CreateProcess failure, error %ld\n", GetLastError() );
1070e67f1f87d9b1188ec8617035db7006c37ee7b21eElliott Hughes        CloseHandle( pipe_read );
1071dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
1072dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
107390d4b739ab94fded63086de1261e70a3d39ceb1dDan Albert
10748d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes    CloseHandle( pinfo.hProcess );
10758d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes    CloseHandle( pinfo.hThread );
1076880be434a9ec197100fe5c6f0b299353d13b916bDavid Pursell
10774e2fd36bc8c16147cab323b0418a7666812d3bc7David Pursell    /* wait for the "OK\n" message */
1078880be434a9ec197100fe5c6f0b299353d13b916bDavid Pursell    {
10798d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes        char  temp[3];
1080880be434a9ec197100fe5c6f0b299353d13b916bDavid Pursell        DWORD  count;
1081880be434a9ec197100fe5c6f0b299353d13b916bDavid Pursell
1082880be434a9ec197100fe5c6f0b299353d13b916bDavid Pursell        ret = ReadFile( pipe_read, temp, 3, &count, NULL );
1083880be434a9ec197100fe5c6f0b299353d13b916bDavid Pursell        CloseHandle( pipe_read );
108474d7ff8cfd490852d3df1c4b9d8a21beed619caaMike Lockwood        if ( !ret ) {
108574d7ff8cfd490852d3df1c4b9d8a21beed619caaMike Lockwood            fprintf(stderr, "could not read ok from ADB Server, error = %ld\n", GetLastError() );
10863d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes            return -1;
10873d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes        }
1088f4b9928563e97620fc1d9bd5c2efdaa0ded96488Yabin Cui        if (count != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') {
10893d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes            fprintf(stderr, "ADB server didn't ACK\n" );
109074d7ff8cfd490852d3df1c4b9d8a21beed619caaMike Lockwood            return -1;
109174d7ff8cfd490852d3df1c4b9d8a21beed619caaMike Lockwood        }
10923d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes    }
10933d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes#elif defined(HAVE_FORKEXEC)
10943d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes    char    path[PATH_MAX];
10953d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes    int     fd[2];
1096706955ff0d159d28bb6eb06dc10178624c505f4eDavid Pursell
10973d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes    // set up a pipe so the child can tell us when it is ready.
10983d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes    // fd[0] will be parent's end, and fd[1] will get mapped to stderr in the child.
10993d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes    if (pipe(fd)) {
11003d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes        fprintf(stderr, "pipe failed in launch_server, errno: %d\n", errno);
11013d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes        return -1;
11023d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes    }
11033d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes    get_my_path(path, PATH_MAX);
11043d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes    pid_t pid = fork();
1105f4b9928563e97620fc1d9bd5c2efdaa0ded96488Yabin Cui    if(pid < 0) return -1;
11063d5f60dbba3bc0feabc05457d181547b295bb3b2Elliott Hughes
11072f38b699713dc2587a771bd5d4c6a47329728f5eMike Lockwood    if (pid == 0) {
11082f38b699713dc2587a771bd5d4c6a47329728f5eMike Lockwood        // child side of the fork
11098d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes
1110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // redirect stderr to the pipe
1111e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes        // we use stderr instead of stdout due to stdout's buffering behavior.
1112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        adb_close(fd[0]);
1113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        dup2(fd[1], STDERR_FILENO);
1114e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes        adb_close(fd[1]);
1115e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes
11168d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes        char str_port[30];
11178d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes        snprintf(str_port, sizeof(str_port), "%d",  server_port);
11188d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes        // child process
11198d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes        int result = execl(path, "adb", "-P", str_port, "fork-server", "server", NULL);
11208d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes        // this should not return
11218d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes        fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno);
11228d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes    } else  {
1123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // parent side of the fork
1124e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes
11258d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes        char  temp[3];
11268d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes
11278d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes        temp[0] = 'A'; temp[1] = 'B'; temp[2] = 'C';
11288d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes        // wait for the "OK\n" message
11298d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes        adb_close(fd[1]);
11308d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes        int ret = adb_read(fd[0], temp, 3);
11318d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes        int saved_errno = errno;
1132e109d266c12c5f537d429ca4b892f2719e02c2daScott Anderson        adb_close(fd[0]);
1133e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes        if (ret < 0) {
11348d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes            fprintf(stderr, "could not read ok from ADB Server, errno = %d\n", saved_errno);
11358d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes            return -1;
11368d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes        }
11378d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes        if (ret != 3 || temp[0] != 'O' || temp[1] != 'K' || temp[2] != '\n') {
11388d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes            fprintf(stderr, "ADB server didn't ACK\n" );
11398d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes            return -1;
11408d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes        }
1141e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes
1142e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes        setsid();
11438d28e191c5ba81b82e51e3fd120d03851e1d905fElliott Hughes    }
1144e2d3677cc2239a8530d33e3c5e24e65fff096801Elliott Hughes#else
1145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#error "cannot implement background server start on this platform"
1146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
1147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
1148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
1149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
11501f4ec19e499ba981e4117f647d191603c2713e79Yabin Cui
11511f4ec19e499ba981e4117f647d191603c2713e79Yabin Cui/* Constructs a local name of form tcp:port.
11521f4ec19e499ba981e4117f647d191603c2713e79Yabin Cui * target_str points to the target string, it's content will be overwritten.
11531f4ec19e499ba981e4117f647d191603c2713e79Yabin Cui * target_size is the capacity of the target string.
11541f4ec19e499ba981e4117f647d191603c2713e79Yabin Cui * server_port is the port number to use for the local name.
11551f4ec19e499ba981e4117f647d191603c2713e79Yabin Cui */
11561f4ec19e499ba981e4117f647d191603c2713e79Yabin Cuivoid build_local_name(char* target_str, size_t target_size, int server_port)
1157dc22c3c7a82ad1919c52dc4d00c601ad7210c61bSimon Ye{
1158dc22c3c7a82ad1919c52dc4d00c601ad7210c61bSimon Ye  snprintf(target_str, target_size, "tcp:%d", server_port);
11593bd73c12c07dcefc965abeef535ac53c4754d682Elliott Hughes}
1160dc22c3c7a82ad1919c52dc4d00c601ad7210c61bSimon Ye
1161dc22c3c7a82ad1919c52dc4d00c601ad7210c61bSimon Ye#if !ADB_HOST
1162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int should_drop_privileges() {
1163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifndef ALLOW_ADBD_ROOT
1164    return 1;
1165#else /* ALLOW_ADBD_ROOT */
1166    int secure = 0;
1167    char value[PROPERTY_VALUE_MAX];
1168
1169   /* run adbd in secure mode if ro.secure is set and
1170    ** we are not in the emulator
1171    */
1172    property_get("ro.kernel.qemu", value, "");
1173    if (strcmp(value, "1") != 0) {
1174        property_get("ro.secure", value, "1");
1175        if (strcmp(value, "1") == 0) {
1176            // don't run as root if ro.secure is set...
1177            secure = 1;
1178
1179            // ... except we allow running as root in userdebug builds if the
1180            // service.adb.root property has been set by the "adb root" command
1181            property_get("ro.debuggable", value, "");
1182            if (strcmp(value, "1") == 0) {
1183                property_get("service.adb.root", value, "");
1184                if (strcmp(value, "1") == 0) {
1185                    secure = 0;
1186                }
1187            }
1188        }
1189    }
1190    return secure;
1191#endif /* ALLOW_ADBD_ROOT */
1192}
1193#endif /* !ADB_HOST */
1194
1195int adb_main(int is_daemon, int server_port)
1196{
1197#if !ADB_HOST
1198    int port;
1199    char value[PROPERTY_VALUE_MAX];
1200
1201    umask(000);
1202#endif
1203
1204    atexit(adb_cleanup);
1205#ifdef HAVE_WIN32_PROC
1206    SetConsoleCtrlHandler( ctrlc_handler, TRUE );
1207#elif defined(HAVE_FORKEXEC)
1208    // No SIGCHLD. Let the service subproc handle its children.
1209    signal(SIGPIPE, SIG_IGN);
1210#endif
1211
1212    init_transport_registration();
1213
1214#if ADB_HOST
1215    HOST = 1;
1216
1217#ifdef WORKAROUND_BUG6558362
1218    if(is_daemon) adb_set_affinity();
1219#endif
1220    usb_vendors_init();
1221    usb_init();
1222    local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
1223    adb_auth_init();
1224
1225    char local_name[30];
1226    build_local_name(local_name, sizeof(local_name), server_port);
1227    if(install_listener(local_name, "*smartsocket*", NULL, 0)) {
1228        exit(1);
1229    }
1230#else
1231    property_get("ro.adb.secure", value, "0");
1232    auth_enabled = !strcmp(value, "1");
1233    if (auth_enabled)
1234        adb_auth_init();
1235
1236    // Our external storage path may be different than apps, since
1237    // we aren't able to bind mount after dropping root.
1238    const char* adb_external_storage = getenv("ADB_EXTERNAL_STORAGE");
1239    if (NULL != adb_external_storage) {
1240        setenv("EXTERNAL_STORAGE", adb_external_storage, 1);
1241    } else {
1242        D("Warning: ADB_EXTERNAL_STORAGE is not set.  Leaving EXTERNAL_STORAGE"
1243          " unchanged.\n");
1244    }
1245
1246    /* don't listen on a port (default 5037) if running in secure mode */
1247    /* don't run as root if we are running in secure mode */
1248    if (should_drop_privileges()) {
1249        struct __user_cap_header_struct header;
1250        struct __user_cap_data_struct cap;
1251
1252        if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0) {
1253            exit(1);
1254        }
1255
1256        /* add extra groups:
1257        ** AID_ADB to access the USB driver
1258        ** AID_LOG to read system logs (adb logcat)
1259        ** AID_INPUT to diagnose input issues (getevent)
1260        ** AID_INET to diagnose network issues (netcfg, ping)
1261        ** AID_GRAPHICS to access the frame buffer
1262        ** AID_NET_BT and AID_NET_BT_ADMIN to diagnose bluetooth (hcidump)
1263        ** AID_SDCARD_R to allow reading from the SD card
1264        ** AID_SDCARD_RW to allow writing to the SD card
1265        ** AID_MOUNT to allow unmounting the SD card before rebooting
1266        ** AID_NET_BW_STATS to read out qtaguid statistics
1267        */
1268        gid_t groups[] = { AID_ADB, AID_LOG, AID_INPUT, AID_INET, AID_GRAPHICS,
1269                           AID_NET_BT, AID_NET_BT_ADMIN, AID_SDCARD_R, AID_SDCARD_RW,
1270                           AID_MOUNT, AID_NET_BW_STATS };
1271        if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) {
1272            exit(1);
1273        }
1274
1275        /* then switch user and group to "shell" */
1276        if (setgid(AID_SHELL) != 0) {
1277            exit(1);
1278        }
1279        if (setuid(AID_SHELL) != 0) {
1280            exit(1);
1281        }
1282
1283        /* set CAP_SYS_BOOT capability, so "adb reboot" will succeed */
1284        header.version = _LINUX_CAPABILITY_VERSION;
1285        header.pid = 0;
1286        cap.effective = cap.permitted = (1 << CAP_SYS_BOOT);
1287        cap.inheritable = 0;
1288        capset(&header, &cap);
1289
1290        D("Local port disabled\n");
1291    } else {
1292        char local_name[30];
1293        build_local_name(local_name, sizeof(local_name), server_port);
1294        if(install_listener(local_name, "*smartsocket*", NULL, 0)) {
1295            exit(1);
1296        }
1297    }
1298
1299    int usb = 0;
1300    if (access(USB_ADB_PATH, F_OK) == 0 || access(USB_FFS_ADB_EP0, F_OK) == 0) {
1301        // listen on USB
1302        usb_init();
1303        usb = 1;
1304    }
1305
1306    // If one of these properties is set, also listen on that port
1307    // If one of the properties isn't set and we couldn't listen on usb,
1308    // listen on the default port.
1309    property_get("service.adb.tcp.port", value, "");
1310    if (!value[0]) {
1311        property_get("persist.adb.tcp.port", value, "");
1312    }
1313    if (sscanf(value, "%d", &port) == 1 && port > 0) {
1314        printf("using port=%d\n", port);
1315        // listen on TCP port specified by service.adb.tcp.port property
1316        local_init(port);
1317    } else if (!usb) {
1318        // listen on default port
1319        local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
1320    }
1321
1322    D("adb_main(): pre init_jdwp()\n");
1323    init_jdwp();
1324    D("adb_main(): post init_jdwp()\n");
1325#endif
1326
1327    if (is_daemon)
1328    {
1329        // inform our parent that we are up and running.
1330#ifdef HAVE_WIN32_PROC
1331        DWORD  count;
1332        WriteFile( GetStdHandle( STD_OUTPUT_HANDLE ), "OK\n", 3, &count, NULL );
1333#elif defined(HAVE_FORKEXEC)
1334        fprintf(stderr, "OK\n");
1335#endif
1336        start_logging();
1337    }
1338    D("Event loop starting\n");
1339
1340    fdevent_loop();
1341
1342    usb_cleanup();
1343
1344    return 0;
1345}
1346
1347#if ADB_HOST
1348void connect_device(char* host, char* buffer, int buffer_size)
1349{
1350    int port, fd;
1351    char* portstr = strchr(host, ':');
1352    char hostbuf[100];
1353    char serial[100];
1354
1355    strncpy(hostbuf, host, sizeof(hostbuf) - 1);
1356    if (portstr) {
1357        if (portstr - host >= (ptrdiff_t)sizeof(hostbuf)) {
1358            snprintf(buffer, buffer_size, "bad host name %s", host);
1359            return;
1360        }
1361        // zero terminate the host at the point we found the colon
1362        hostbuf[portstr - host] = 0;
1363        if (sscanf(portstr + 1, "%d", &port) == 0) {
1364            snprintf(buffer, buffer_size, "bad port number %s", portstr);
1365            return;
1366        }
1367    } else {
1368        port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
1369    }
1370
1371    snprintf(serial, sizeof(serial), "%s:%d", hostbuf, port);
1372    if (find_transport(serial)) {
1373        snprintf(buffer, buffer_size, "already connected to %s", serial);
1374        return;
1375    }
1376
1377    fd = socket_network_client(hostbuf, port, SOCK_STREAM);
1378    if (fd < 0) {
1379        snprintf(buffer, buffer_size, "unable to connect to %s:%d", host, port);
1380        return;
1381    }
1382
1383    D("client: connected on remote on fd %d\n", fd);
1384    close_on_exec(fd);
1385    disable_tcp_nagle(fd);
1386    register_socket_transport(fd, serial, port, 0);
1387    snprintf(buffer, buffer_size, "connected to %s", serial);
1388}
1389
1390void connect_emulator(char* port_spec, char* buffer, int buffer_size)
1391{
1392    char* port_separator = strchr(port_spec, ',');
1393    if (!port_separator) {
1394        snprintf(buffer, buffer_size,
1395                "unable to parse '%s' as <console port>,<adb port>",
1396                port_spec);
1397        return;
1398    }
1399
1400    // Zero-terminate console port and make port_separator point to 2nd port.
1401    *port_separator++ = 0;
1402    int console_port = strtol(port_spec, NULL, 0);
1403    int adb_port = strtol(port_separator, NULL, 0);
1404    if (!(console_port > 0 && adb_port > 0)) {
1405        *(port_separator - 1) = ',';
1406        snprintf(buffer, buffer_size,
1407                "Invalid port numbers: Expected positive numbers, got '%s'",
1408                port_spec);
1409        return;
1410    }
1411
1412    /* Check if the emulator is already known.
1413     * Note: There's a small but harmless race condition here: An emulator not
1414     * present just yet could be registered by another invocation right
1415     * after doing this check here. However, local_connect protects
1416     * against double-registration too. From here, a better error message
1417     * can be produced. In the case of the race condition, the very specific
1418     * error message won't be shown, but the data doesn't get corrupted. */
1419    atransport* known_emulator = find_emulator_transport_by_adb_port(adb_port);
1420    if (known_emulator != NULL) {
1421        snprintf(buffer, buffer_size,
1422                "Emulator on port %d already registered.", adb_port);
1423        return;
1424    }
1425
1426    /* Check if more emulators can be registered. Similar unproblematic
1427     * race condition as above. */
1428    int candidate_slot = get_available_local_transport_index();
1429    if (candidate_slot < 0) {
1430        snprintf(buffer, buffer_size, "Cannot accept more emulators.");
1431        return;
1432    }
1433
1434    /* Preconditions met, try to connect to the emulator. */
1435    if (!local_connect_arbitrary_ports(console_port, adb_port)) {
1436        snprintf(buffer, buffer_size,
1437                "Connected to emulator on ports %d,%d", console_port, adb_port);
1438    } else {
1439        snprintf(buffer, buffer_size,
1440                "Could not connect to emulator on ports %d,%d",
1441                console_port, adb_port);
1442    }
1443}
1444#endif
1445
1446int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s)
1447{
1448    atransport *transport = NULL;
1449    char buf[4096];
1450
1451    if(!strcmp(service, "kill")) {
1452        fprintf(stderr,"adb server killed by remote request\n");
1453        fflush(stdout);
1454        adb_write(reply_fd, "OKAY", 4);
1455        usb_cleanup();
1456        exit(0);
1457    }
1458
1459#if ADB_HOST
1460    // "transport:" is used for switching transport with a specified serial number
1461    // "transport-usb:" is used for switching transport to the only USB transport
1462    // "transport-local:" is used for switching transport to the only local transport
1463    // "transport-any:" is used for switching transport to the only transport
1464    if (!strncmp(service, "transport", strlen("transport"))) {
1465        char* error_string = "unknown failure";
1466        transport_type type = kTransportAny;
1467
1468        if (!strncmp(service, "transport-usb", strlen("transport-usb"))) {
1469            type = kTransportUsb;
1470        } else if (!strncmp(service, "transport-local", strlen("transport-local"))) {
1471            type = kTransportLocal;
1472        } else if (!strncmp(service, "transport-any", strlen("transport-any"))) {
1473            type = kTransportAny;
1474        } else if (!strncmp(service, "transport:", strlen("transport:"))) {
1475            service += strlen("transport:");
1476            serial = service;
1477        }
1478
1479        transport = acquire_one_transport(CS_ANY, type, serial, &error_string);
1480
1481        if (transport) {
1482            s->transport = transport;
1483            adb_write(reply_fd, "OKAY", 4);
1484        } else {
1485            sendfailmsg(reply_fd, error_string);
1486        }
1487        return 1;
1488    }
1489
1490    // return a list of all connected devices
1491    if (!strncmp(service, "devices", 7)) {
1492        char buffer[4096];
1493        int use_long = !strcmp(service+7, "-l");
1494        if (use_long || service[7] == 0) {
1495            memset(buf, 0, sizeof(buf));
1496            memset(buffer, 0, sizeof(buffer));
1497            D("Getting device list \n");
1498            list_transports(buffer, sizeof(buffer), use_long);
1499            snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer),buffer);
1500            D("Wrote device list \n");
1501            writex(reply_fd, buf, strlen(buf));
1502            return 0;
1503        }
1504    }
1505
1506    // add a new TCP transport, device or emulator
1507    if (!strncmp(service, "connect:", 8)) {
1508        char buffer[4096];
1509        char* host = service + 8;
1510        if (!strncmp(host, "emu:", 4)) {
1511            connect_emulator(host + 4, buffer, sizeof(buffer));
1512        } else {
1513            connect_device(host, buffer, sizeof(buffer));
1514        }
1515        // Send response for emulator and device
1516        snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer), buffer);
1517        writex(reply_fd, buf, strlen(buf));
1518        return 0;
1519    }
1520
1521    // remove TCP transport
1522    if (!strncmp(service, "disconnect:", 11)) {
1523        char buffer[4096];
1524        memset(buffer, 0, sizeof(buffer));
1525        char* serial = service + 11;
1526        if (serial[0] == 0) {
1527            // disconnect from all TCP devices
1528            unregister_all_tcp_transports();
1529        } else {
1530            char hostbuf[100];
1531            // assume port 5555 if no port is specified
1532            if (!strchr(serial, ':')) {
1533                snprintf(hostbuf, sizeof(hostbuf) - 1, "%s:5555", serial);
1534                serial = hostbuf;
1535            }
1536            atransport *t = find_transport(serial);
1537
1538            if (t) {
1539                unregister_transport(t);
1540            } else {
1541                snprintf(buffer, sizeof(buffer), "No such device %s", serial);
1542            }
1543        }
1544
1545        snprintf(buf, sizeof(buf), "OKAY%04x%s",(unsigned)strlen(buffer), buffer);
1546        writex(reply_fd, buf, strlen(buf));
1547        return 0;
1548    }
1549
1550    // returns our value for ADB_SERVER_VERSION
1551    if (!strcmp(service, "version")) {
1552        char version[12];
1553        snprintf(version, sizeof version, "%04x", ADB_SERVER_VERSION);
1554        snprintf(buf, sizeof buf, "OKAY%04x%s", (unsigned)strlen(version), version);
1555        writex(reply_fd, buf, strlen(buf));
1556        return 0;
1557    }
1558
1559    if(!strncmp(service,"get-serialno",strlen("get-serialno"))) {
1560        char *out = "unknown";
1561         transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
1562       if (transport && transport->serial) {
1563            out = transport->serial;
1564        }
1565        snprintf(buf, sizeof buf, "OKAY%04x%s",(unsigned)strlen(out),out);
1566        writex(reply_fd, buf, strlen(buf));
1567        return 0;
1568    }
1569    if(!strncmp(service,"get-devpath",strlen("get-devpath"))) {
1570        char *out = "unknown";
1571         transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
1572       if (transport && transport->devpath) {
1573            out = transport->devpath;
1574        }
1575        snprintf(buf, sizeof buf, "OKAY%04x%s",(unsigned)strlen(out),out);
1576        writex(reply_fd, buf, strlen(buf));
1577        return 0;
1578    }
1579    // indicates a new emulator instance has started
1580    if (!strncmp(service,"emulator:",9)) {
1581        int  port = atoi(service+9);
1582        local_connect(port);
1583        /* we don't even need to send a reply */
1584        return 0;
1585    }
1586#endif // ADB_HOST
1587
1588    if(!strcmp(service,"list-forward")) {
1589        // Create the list of forward redirections.
1590        char header[9];
1591        int buffer_size = format_listeners(NULL, 0);
1592        // Add one byte for the trailing zero.
1593        char* buffer = malloc(buffer_size+1);
1594        (void) format_listeners(buffer, buffer_size+1);
1595        snprintf(header, sizeof header, "OKAY%04x", buffer_size);
1596        writex(reply_fd, header, 8);
1597        writex(reply_fd, buffer, buffer_size);
1598        free(buffer);
1599        return 0;
1600    }
1601
1602    if (!strcmp(service,"killforward-all")) {
1603        remove_all_listeners();
1604        adb_write(reply_fd, "OKAYOKAY", 8);
1605        return 0;
1606    }
1607
1608    if(!strncmp(service,"forward:",8) ||
1609       !strncmp(service,"killforward:",12)) {
1610        char *local, *remote, *err;
1611        int r;
1612        atransport *transport;
1613
1614        int createForward = strncmp(service,"kill",4);
1615        int no_rebind = 0;
1616
1617        local = strchr(service, ':') + 1;
1618
1619        // Handle forward:norebind:<local>... here
1620        if (createForward && !strncmp(local, "norebind:", 9)) {
1621            no_rebind = 1;
1622            local = strchr(local, ':') + 1;
1623        }
1624
1625        remote = strchr(local,';');
1626
1627        if (createForward) {
1628            // Check forward: parameter format: '<local>;<remote>'
1629            if(remote == 0) {
1630                sendfailmsg(reply_fd, "malformed forward spec");
1631                return 0;
1632            }
1633
1634            *remote++ = 0;
1635            if((local[0] == 0) || (remote[0] == 0) || (remote[0] == '*')){
1636                sendfailmsg(reply_fd, "malformed forward spec");
1637                return 0;
1638            }
1639        } else {
1640            // Check killforward: parameter format: '<local>'
1641            if (local[0] == 0) {
1642                sendfailmsg(reply_fd, "malformed forward spec");
1643                return 0;
1644            }
1645        }
1646
1647        transport = acquire_one_transport(CS_ANY, ttype, serial, &err);
1648        if (!transport) {
1649            sendfailmsg(reply_fd, err);
1650            return 0;
1651        }
1652
1653        if (createForward) {
1654            r = install_listener(local, remote, transport, no_rebind);
1655        } else {
1656            r = remove_listener(local, transport);
1657        }
1658        if(r == 0) {
1659                /* 1st OKAY is connect, 2nd OKAY is status */
1660            writex(reply_fd, "OKAYOKAY", 8);
1661            return 0;
1662        }
1663
1664        if (createForward) {
1665            const char* message;
1666            switch (r) {
1667              case INSTALL_STATUS_CANNOT_BIND:
1668                message = "cannot bind to socket";
1669                break;
1670              case INSTALL_STATUS_CANNOT_REBIND:
1671                message = "cannot rebind existing socket";
1672                break;
1673              default:
1674                message = "internal error";
1675            }
1676            sendfailmsg(reply_fd, message);
1677        } else {
1678            sendfailmsg(reply_fd, "cannot remove listener");
1679        }
1680        return 0;
1681    }
1682
1683    if(!strncmp(service,"get-state",strlen("get-state"))) {
1684        transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
1685        char *state = connection_state_name(transport);
1686        snprintf(buf, sizeof buf, "OKAY%04x%s",(unsigned)strlen(state),state);
1687        writex(reply_fd, buf, strlen(buf));
1688        return 0;
1689    }
1690    return -1;
1691}
1692
1693#if !ADB_HOST
1694int recovery_mode = 0;
1695#endif
1696
1697int main(int argc, char **argv)
1698{
1699#if ADB_HOST
1700    adb_sysdeps_init();
1701    adb_trace_init();
1702    D("Handling commandline()\n");
1703    return adb_commandline(argc - 1, argv + 1);
1704#else
1705    /* If adbd runs inside the emulator this will enable adb tracing via
1706     * adb-debug qemud service in the emulator. */
1707    adb_qemu_trace_init();
1708    if((argc > 1) && (!strcmp(argv[1],"recovery"))) {
1709        adb_device_banner = "recovery";
1710        recovery_mode = 1;
1711    }
1712
1713    start_device_log();
1714    D("Handling main()\n");
1715    return adb_main(0, DEFAULT_ADB_PORT);
1716#endif
1717}
1718