1d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine/*
2d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine * Copyright (C) 2011 The Android Open Source Project
3d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine *
4d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine * Licensed under the Apache License, Version 2.0 (the "License");
5d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine * you may not use this file except in compliance with the License.
6d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine * You may obtain a copy of the License at
7d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine *
8d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine *      http://www.apache.org/licenses/LICENSE-2.0
9d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine *
10d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine * Unless required by applicable law or agreed to in writing, software
11d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine * distributed under the License is distributed on an "AS IS" BASIS,
12d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine * See the License for the specific language governing permissions and
14d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine * limitations under the License.
15d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine */
16d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
17d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine#include "qemu-common.h"
18d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine#include "sockets.h"
19d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine#include "iolooper.h"
20d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine#include "android/async-utils.h"
21d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine#include "android/utils/debug.h"
22d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine#include "android/utils/list.h"
23d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine#include "android/utils/misc.h"
24d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine#include "android/adb-server.h"
25d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
26d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine#define  E(...)    derror(__VA_ARGS__)
27d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine#define  W(...)    dwarning(__VA_ARGS__)
28d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine#define  D(...)    VERBOSE_PRINT(adbserver,__VA_ARGS__)
29d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine#define  D_ACTIVE  VERBOSE_CHECK(adbserver)
30d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine#define  QB(b, s)  quote_bytes((const char*)b, (s < 32) ? s : 32)
31d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
32d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkinetypedef struct AdbServer    AdbServer;
33d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkinetypedef struct AdbHost      AdbHost;
34d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkinetypedef struct AdbGuest     AdbGuest;
35d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
36d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine/* ADB guest connection descriptor. */
37d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkinestruct AdbGuest {
38d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* Entry in the list of pending or connected ADB guests.
39d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine     * NOTE: This must be the first entry in the descriptor! */
40d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    ACList              list_entry;
41d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* Opaque pointer associated with the guest. */
42d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    void*               opaque;
43d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* ADB server for this guest. */
44d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    AdbServer*          adb_srv;
45d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* ADB host connected with this ADB guest. */
46d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    AdbHost*            adb_host;
47d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* Callback routines for the ADB guest. */
48d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    AdbGuestRoutines*   callbacks;
49d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* ADB guest connection status. If 0 indicates that ADB guest is not yet
50d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine     * ready to receive data from the host. */
51d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    int                 is_connected;
52d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine};
53d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
54d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine/* ADB host connection descriptor. */
55d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkinestruct AdbHost {
56d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* Entry in the list of pending or connected ADB hosts.
57d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine     * NOTE: This must be the first entry in the descriptor! */
58d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    ACList      list_entry;
59d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* ADB server for this host. */
60d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    AdbServer*  adb_srv;
61d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* ADB socket connected with the host. */
62d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    int         host_so;
63d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* I/O port for asynchronous I/O on the host socket. */
64d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    LoopIo      io[1];
65d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* ADB guest connected with this ADB host. */
66d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    AdbGuest*   adb_guest;
67d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* Pending data to send to the guest when it is fully connected. */
68d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    uint8_t*    pending_data;
69d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* Size of the pending data buffer. */
70d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    int         pending_data_size;
71d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* Contains data that are pending to be sent to the host. */
72d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    uint8_t*    pending_send_buffer;
73d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* Number of bytes that are pending to be sent to the host. */
74d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    int         pending_send_data_size;
75d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* Size of the pending_send_buffer */
76d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    int         pending_send_buffer_size;
77d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine};
78d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
79d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine/* ADB server descriptor. */
80d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkinestruct AdbServer {
81d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* ADB socket address. */
82d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    SockAddress socket_address;
83d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* Looper for async I/O on ADB server socket. */
84d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    Looper*     looper;
85d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* I/O port for asynchronous I/O on ADB server socket. */
86d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    LoopIo      io[1];
87d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* ADB port. */
88d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    int         port;
89d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* Server socket. */
90d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    int         so;
91d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* List of connected ADB hosts. */
92d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    ACList      adb_hosts;
93d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* List of connected ADB guests. */
94d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    ACList      adb_guests;
95d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* List of ADB hosts pending connection with ADB guest. */
96d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    ACList      pending_hosts;
97d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* List of ADB guests pending connection with ADB host. */
98d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    ACList      pending_guests;
99d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine};
100d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
101d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine/* One and only one ADB server instance. */
102d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkinestatic AdbServer    _adb_server;
103d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine/* ADB server initialization flag. */
104d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkinestatic int          _adb_server_initialized = 0;
105d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
106d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine/********************************************************************************
107d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine *                             ADB host API
108d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine *******************************************************************************/
109d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
110d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine/* Creates and initializes a new AdbHost instance. */
111d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkinestatic AdbHost*
112d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine_adb_host_new(AdbServer* adb_srv)
113d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine{
114d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    AdbHost* adb_host;
115d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
116d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    ANEW0(adb_host);
117d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    alist_init(&adb_host->list_entry);
118d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    adb_host->adb_srv = adb_srv;
119d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    adb_host->host_so = -1;
120d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
121d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    return adb_host;
122d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine}
123d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
124d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine/* Frees AdbHost instance created with _adb_host_new routine. */
125d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkinestatic void
126d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine_adb_host_free(AdbHost* adb_host)
127d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine{
128d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    if (adb_host != NULL) {
129d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        /* At this point it must not be listed anywhere. */
130d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        assert(alist_is_empty(&adb_host->list_entry));
131d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
132d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        /* Close the host socket. */
133d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        if (adb_host->host_so >= 0) {
134d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            loopIo_done(adb_host->io);
135d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            socket_close(adb_host->host_so);
136d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        }
137d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
138d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        /* Free pending data buffers. */
139d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        if (adb_host->pending_data != NULL) {
140d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            free(adb_host->pending_data);
141d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        }
142d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        if (adb_host->pending_send_buffer != NULL) {
143d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            free(adb_host->pending_send_buffer);
144d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        }
145d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
146d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        AFREE(adb_host);
147d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    }
148d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine}
149d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
150d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkinestatic void
151d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine_adb_host_append_message(AdbHost* adb_host, const void* msg, int msglen)
152d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine{
153d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    printf("Append %d bytes to ADB host buffer.\n", msglen);
154d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
155d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* Make sure that buffer can contain the appending data. */
156d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    if (adb_host->pending_send_buffer == NULL) {
157d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        adb_host->pending_send_buffer = (uint8_t*)malloc(msglen);
158d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        adb_host->pending_send_buffer_size = msglen;
159d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    } else if ((adb_host->pending_send_data_size + msglen) >
160d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine               adb_host->pending_send_buffer_size) {
161d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        adb_host->pending_send_buffer =
162d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            (uint8_t*)realloc(adb_host->pending_send_buffer,
163d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                              adb_host->pending_send_data_size + msglen);
164d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        adb_host->pending_send_buffer_size =
165d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            adb_host->pending_send_data_size + msglen;
166d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    }
167d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
168d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    if (adb_host->pending_send_buffer == NULL) {
169d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        D("Unable to allocate %d bytes for pending ADB host data.",
170d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine          adb_host->pending_send_data_size + msglen);
171d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        adb_host->pending_send_buffer_size = adb_host->pending_send_data_size = 0;
172d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        loopIo_dontWantWrite(adb_host->io);
173d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        return;
174d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    }
175d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
176d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    memcpy(adb_host->pending_send_buffer + adb_host->pending_send_data_size,
177d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine           msg, msglen);
178d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    loopIo_wantWrite(adb_host->io);
179d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine}
180d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
181d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine/* Connects ADB host with ADB guest. */
182d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkinestatic void
183d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine_adb_connect(AdbHost* adb_host, AdbGuest* adb_guest)
184d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine{
185d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    D("Connecting ADB host %p(so=%d) with ADB guest %p(o=%p)",
186d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine      adb_host, adb_host->host_so, adb_guest, adb_guest->opaque);
187d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
188d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    adb_guest->adb_host = adb_host;
189d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    adb_host->adb_guest = adb_guest;
190d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    adb_guest->callbacks->on_connected(adb_guest->opaque, adb_guest);
191d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine}
192d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
193d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine/* Callback invoked when ADB host socket gets disconnected. */
194d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkinestatic void
195d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine_on_adb_host_disconnected(AdbHost* adb_host)
196d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine{
197d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    AdbGuest* const adb_guest = adb_host->adb_guest;
198d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
199d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* Notify the ADB guest that the host got disconnected. */
200d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    if (adb_guest != NULL) {
201d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        D("Disconnecting ADB host %p(so=%d) from ADB guest %p(o=%p)",
202d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine          adb_host, adb_host->host_so, adb_guest, adb_guest->opaque);
203d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        adb_host->adb_guest = NULL;
204d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        adb_guest->callbacks->on_disconnect(adb_guest->opaque, adb_guest);
205d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        adb_guest->adb_host = NULL;
206d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    } else {
207d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        D("Disconnecting ADB host %p(so=%d)", adb_host, adb_host->host_so);
208d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    }
209d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
210d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* Destroy the host. */
211d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    alist_remove(&adb_host->list_entry);
212d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    _adb_host_free(adb_host);
213d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
214d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* Remove the guest from the list. */
215d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    if (adb_guest != NULL) {
216d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        alist_remove(&adb_guest->list_entry);
217d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    }
218d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine}
219d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
220d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine/* Read I/O callback on ADB host socket. */
221d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkinestatic void
222d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine_on_adb_host_read(AdbHost* adb_host)
223d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine{
224d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    char buff[4096];
225d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
226d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* Read data from the socket. */
227d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    const int size = socket_recv(adb_host->host_so, buff, sizeof(buff));
228d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    if (size < 0) {
229d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        D("Error while reading from ADB host %p(so=%d). Error: %s",
230d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine          adb_host, adb_host->host_so, strerror(errno));
231d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    } else if (size == 0) {
232d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        /* This is a "disconnect" condition. */
233d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        _on_adb_host_disconnected(adb_host);
234d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    } else {
235d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        D("%s %d bytes received from ADB host %p(so=%d): %s",
236d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine           adb_host->adb_guest ? "Transfer" : "Pend", size, adb_host,
237d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine           adb_host->host_so, QB(buff, size));
238d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
239d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        /* Lets see if there is an ADB guest associated with this host, and it
240d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine         * is ready to receive host data. */
241d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        AdbGuest* const adb_guest = adb_host->adb_guest;
242d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        if (adb_guest != NULL && adb_guest->is_connected) {
243d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            /* Channel the data through... */
244d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            adb_guest->callbacks->on_read(adb_guest->opaque, adb_guest, buff, size);
245d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        } else {
246d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            /* Pend the data for the upcoming guest connection. */
247d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            if (adb_host->pending_data == NULL) {
248d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                adb_host->pending_data = malloc(size);
249d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            } else {
250d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                adb_host->pending_data = realloc(adb_host->pending_data,
251d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                                                 adb_host->pending_data_size + size);
252d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            }
253d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            if (adb_host->pending_data != NULL) {
254d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                memcpy(adb_host->pending_data + adb_host->pending_data_size,
255d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                       buff, size);
256d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                adb_host->pending_data_size += size;
257d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            } else {
258d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                D("Unable to (re)allocate %d bytes for pending ADB host data",
259d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                  adb_host->pending_data_size + size);
260d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            }
261d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        }
262d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    }
263d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine}
264d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
265d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine/* Write I/O callback on ADB host socket. */
266d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkinestatic void
267d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine_on_adb_host_write(AdbHost* adb_host)
268d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine{
269d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    while (adb_host->pending_send_data_size && adb_host->pending_send_buffer != NULL) {
270d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        const int sent = socket_send(adb_host->host_so,
271d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                                     adb_host->pending_send_buffer,
272d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                                     adb_host->pending_send_data_size);
273d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        if (sent < 0) {
274d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            if (errno == EWOULDBLOCK) {
275d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                /* Try again later. */
276d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                return;
277d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            } else {
278d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                D("Unable to send pending data to the ADB host: %s",
279d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                   strerror(errno));
280d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                free(adb_host->pending_send_buffer);
281d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                adb_host->pending_send_buffer = NULL;
282d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                adb_host->pending_send_buffer_size = 0;
283d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                adb_host->pending_send_data_size = 0;
284d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                break;
285d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            }
286d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        } else if (sent == 0) {
287d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            /* Disconnect condition. */
288d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            free(adb_host->pending_send_buffer);
289d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            adb_host->pending_send_buffer = NULL;
290d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            adb_host->pending_send_buffer_size = 0;
291d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            adb_host->pending_send_data_size = 0;
292d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            _on_adb_host_disconnected(adb_host);
293d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            break;
294d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        } else if (sent == adb_host->pending_send_data_size) {
295d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            free(adb_host->pending_send_buffer);
296d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            adb_host->pending_send_buffer = NULL;
297d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            adb_host->pending_send_buffer_size = 0;
298d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            adb_host->pending_send_data_size = 0;
299d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        } else {
300d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            adb_host->pending_send_data_size -= sent;
301d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            memmove(adb_host->pending_send_buffer,
302d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                    adb_host->pending_send_buffer + sent,
303d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                    adb_host->pending_send_data_size);
304d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            return;
305d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        }
306d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    }
307d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
308d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    loopIo_dontWantWrite(adb_host->io);
309d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine}
310d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
311d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine/* I/O callback on ADB host socket. */
312d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkinestatic void
313d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine_on_adb_host_io(void* opaque, int fd, unsigned events)
314d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine{
315d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    AdbHost* const adb_host = (AdbHost*)opaque;
316d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    assert(fd == adb_host->host_so);
317d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
318d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* Dispatch I/O to read / write handlers. */
319d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    if ((events & LOOP_IO_READ) != 0) {
320d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        _on_adb_host_read(adb_host);
321d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    }
322d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    if ((events & LOOP_IO_WRITE) != 0) {
323d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        _on_adb_host_write(adb_host);
324d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    }
325d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine}
326d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
327d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine/********************************************************************************
328d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine *                            ADB guest API
329d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine *******************************************************************************/
330d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
331d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine/* Creates and initializes a new AdbGuest instance. */
332d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkinestatic AdbGuest*
333d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine_adb_guest_new(AdbServer* adb_srv)
334d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine{
335d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    AdbGuest* adb_guest;
336d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
337d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    ANEW0(adb_guest);
338d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    alist_init(&adb_guest->list_entry);
339d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    adb_guest->adb_srv = adb_srv;
340d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
341d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    return adb_guest;
342d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine}
343d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
344d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine/* Frees AdbGuest instance created with _adb_guest_new routine. */
345d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkinestatic void
346d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine_adb_guest_free(AdbGuest* adb_guest)
347d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine{
348d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    if (adb_guest != NULL) {
349d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        /* At this poin the guest must not be in any of the lists. */
350d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        assert(alist_is_empty(&adb_guest->list_entry));
351d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        AFREE(adb_guest);
352d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    }
353d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine}
354d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
355d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine/********************************************************************************
356d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine *                            ADB server internals
357d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine *******************************************************************************/
358d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
359d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine/* I/O callback on ADB server socket. */
360d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkinestatic void
361d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine_on_server_socket_io(void* opaque, int fd, unsigned events)
362d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine{
363d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    AdbHost* adb_host;
364d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    AdbGuest* adb_guest;
365d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    AdbServer* adb_srv = (AdbServer*)opaque;
366d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    assert(adb_srv->so == fd);
367d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
368d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* Since this is a server socket, we only expect a connection I/O here. */
369d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    if ((events & LOOP_IO_READ) == 0) {
370d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        D("Unexpected write I/O on ADB server socket");
371d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        return;
372d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    }
373d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
374d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* Create AdbHost instance for the new host connection. */
375d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    adb_host = _adb_host_new(adb_srv);
376d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
377d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* Accept the connection. */
378d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    adb_host->host_so = socket_accept(fd, &adb_srv->socket_address);
379d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    if (adb_host->host_so < 0) {
380d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        D("Unable to accept ADB connection: %s", strerror(errno));
381d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        _adb_host_free(adb_host);
382d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        return;
383d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    }
384d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
385d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* Prepare for I/O on the host connection socket. */
386d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    loopIo_init(adb_host->io, adb_srv->looper, adb_host->host_so,
387d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                _on_adb_host_io, adb_host);
388d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
389d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* Lets see if there is an ADB guest waiting for a host connection. */
390d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    adb_guest = (AdbGuest*)alist_remove_head(&adb_srv->pending_guests);
391d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    if (adb_guest != NULL) {
392d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        /* Tie up ADB host with the ADB guest. */
393d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        alist_insert_tail(&adb_srv->adb_guests, &adb_guest->list_entry);
394d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        alist_insert_tail(&adb_srv->adb_hosts, &adb_host->list_entry);
395d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        _adb_connect(adb_host, adb_guest);
396d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    } else {
397d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        /* Pend this connection. */
398d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        D("Pend ADB host %p(so=%d)", adb_host, adb_host->host_so);
399d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        alist_insert_tail(&adb_srv->pending_hosts, &adb_host->list_entry);
400d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    }
401d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
402d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* Enable I/O on the host socket. */
403d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    loopIo_wantRead(adb_host->io);
404d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine}
405d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
406d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine/********************************************************************************
407d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine *                            ADB server API
408d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine *******************************************************************************/
409d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkineint
410d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkineadb_server_init(int port)
411d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine{
412d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    if (!_adb_server_initialized) {
413d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        /* Initialize the descriptor. */
414d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        memset(&_adb_server, 0, sizeof(_adb_server));
415d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        alist_init(&_adb_server.adb_hosts);
416d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        alist_init(&_adb_server.adb_guests);
417d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        alist_init(&_adb_server.pending_hosts);
418d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        alist_init(&_adb_server.pending_guests);
419d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        _adb_server.port = port;
420d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
421d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        /* Create looper for an async I/O on the server. */
422d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        _adb_server.looper = looper_newCore();
423d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        if (_adb_server.looper == NULL) {
424d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            E("Unable to create I/O looper for ADB server");
425d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            return -1;
426d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        }
427d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
428d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        /* Create loopback server socket for the ADB port. */
429d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        sock_address_init_inet(&_adb_server.socket_address,
430d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                               SOCK_ADDRESS_INET_LOOPBACK, port);
431d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        _adb_server.so = socket_loopback_server(port, SOCKET_STREAM);
432d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        if (_adb_server.so < 0) {
433d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            E("Unable to create ADB server socket: %s", strerror(errno));
434d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            return -1;
435d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        }
436d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
437d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        /* Prepare server socket for I/O */
438d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        socket_set_nonblock(_adb_server.so);
439d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        loopIo_init(_adb_server.io, _adb_server.looper, _adb_server.so,
440d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                    _on_server_socket_io, &_adb_server);
441d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        loopIo_wantRead(_adb_server.io);
442d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
443d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        D("ADB server has been initialized for port %d. Socket: %d",
444d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine          port, _adb_server.so);
445d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
446d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        _adb_server_initialized = 1;
447d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    }
448d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
449d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    return 0;
450d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine}
451d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
452d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkineint
453d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkineadb_server_is_initialized(void)
454d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine{
455d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    return _adb_server_initialized;
456d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine}
457d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
458d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkinevoid*
459d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkineadb_server_register_guest(void* opaque, AdbGuestRoutines* callbacks)
460d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine{
461d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    if (_adb_server_initialized) {
462d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        AdbHost* adb_host;
463d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
464d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        /* Create and initialize ADB guest descriptor. */
465d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        AdbGuest* const adb_guest = _adb_guest_new(&_adb_server);
466d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        adb_guest->opaque = opaque;
467d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        adb_guest->callbacks = callbacks;
468d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
469d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        /* Lets see if there is a pending ADB host for the new guest. */
470d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        adb_host = (AdbHost*)alist_remove_head(&_adb_server.pending_hosts);
471d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        if (adb_host != NULL) {
472d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            /* Tie up ADB host with the ADB guest. */
473d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            alist_insert_tail(&_adb_server.adb_guests, &adb_guest->list_entry);
474d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            alist_insert_tail(&_adb_server.adb_hosts, &adb_host->list_entry);
475d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            _adb_connect(adb_host, adb_guest);
476d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        } else {
477d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            /* Host is not available. Pend this guest. */
478d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            D("Pend ADB guest %p(o=%p)", adb_guest, adb_guest->opaque);
479d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            alist_insert_tail(&_adb_server.pending_guests, &adb_guest->list_entry);
480d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        }
481d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
482d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        return adb_guest;
483d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    } else {
484d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        D("%s is called on an uninitialized ADB server.", __FUNCTION__);
485d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        return NULL;
486d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    }
487d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine}
488d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
489d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkinevoid
490d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkineadb_server_complete_connection(void* opaque)
491d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine{
492d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    AdbGuest* const adb_guest = (AdbGuest*)opaque;
493d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    AdbHost* const adb_host = adb_guest->adb_host;
494d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
495d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* Mark the guest as fully connected and ready for the host data. */
496d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    adb_guest->is_connected = 1;
497d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
498d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* Lets see if there is a host data pending transmission to the guest. */
499d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    if (adb_host->pending_data != NULL && adb_host->pending_data_size != 0) {
500d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        /* Send the pending data to the guest. */
501d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        D("Pushing %d bytes of the pending ADB host data.",
502d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine          adb_host->pending_data_size);
503d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        adb_guest->callbacks->on_read(adb_guest->opaque, adb_guest,
504d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                                      adb_host->pending_data,
505d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                                      adb_host->pending_data_size);
506d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        free(adb_host->pending_data);
507d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        adb_host->pending_data = NULL;
508d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        adb_host->pending_data_size = 0;
509d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    }
510d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine}
511d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
512d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkinevoid
513d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkineadb_server_on_guest_message(void* opaque, const uint8_t* msg, int msglen)
514d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine{
515d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    AdbGuest* const adb_guest = (AdbGuest*)opaque;
516d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    AdbHost* const adb_host = adb_guest->adb_host;
517d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
518d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    if (adb_host != NULL) {
519d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        D("Sending %d bytes to the ADB host: %s", msglen, QB(msg, msglen));
520d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
521d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        /* Lets see if we can send the data immediatelly... */
522d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        if (adb_host->pending_send_buffer == NULL) {
523d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            /* There are no data that are pending to be sent to the host. Do the
524d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine             * direct send. */
525d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            const int sent = socket_send(adb_host->host_so, msg, msglen);
526d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            if (sent < 0) {
527d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                if (errno == EWOULDBLOCK) {
528d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                } else {
529d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                    D("Unable to send data to ADB host: %s", strerror(errno));
530d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                }
531d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            } else if (sent == 0) {
532d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                /* Disconnect condition. */
533d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                _on_adb_host_disconnected(adb_host);
534d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            } else if (sent < msglen) {
535d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                /* Couldn't send everything. Schedule write via I/O callback. */
536d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine                _adb_host_append_message(adb_host, msg + sent, msglen - sent);
537d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            }
538d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        } else {
539d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            /* There are data that are pending to be sent to the host. We need
540d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine             * to append new data to the end of the pending data buffer. */
541d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            _adb_host_append_message(adb_host, msg, msglen);
542d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        }
543d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    } else {
544d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        D("ADB host is disconneted and can't accept %d bytes in %s",
545d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine          msglen, QB(msg, msglen));
546d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    }
547d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine}
548d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
549d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkinevoid
550d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkineadb_server_on_guest_closed(void* opaque)
551d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine{
552d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    AdbGuest* const adb_guest = (AdbGuest*)opaque;
553d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    AdbHost* const adb_host = adb_guest->adb_host;
554d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
555d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* Remove the guest from the list */
556d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    if (!alist_is_empty(&adb_guest->list_entry)) {
557d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        alist_remove(&adb_guest->list_entry);
558d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    }
559d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine
560d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    /* Disassociate the host. */
561d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    if (adb_host != NULL) {
562d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        if (!alist_is_empty(&adb_host->list_entry)) {
563d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine            alist_remove(&adb_host->list_entry);
564d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        }
565d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine        _adb_host_free(adb_host);
566d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    }
567d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine    _adb_guest_free(adb_guest);
568d86c724b74e6c04a89219d87559d0b580e100445Vladimir Chtchetkine}
569