1 /*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /*
18 * Encapsulates exchange protocol between the emulator, and an Android device
19 * that is connected to the host via USB. The communication is established over
20 * a TCP port forwarding, enabled by ADB.
21 */
22
23 #include "qemu-common.h"
24 #include "android/async-utils.h"
25 #include "android/utils/debug.h"
26 #include "android/async-socket-connector.h"
27 #include "utils/panic.h"
28 #include "iolooper.h"
29
30 #define E(...) derror(__VA_ARGS__)
31 #define W(...) dwarning(__VA_ARGS__)
32 #define D(...) VERBOSE_PRINT(asconnector,__VA_ARGS__)
33 #define D_ACTIVE VERBOSE_CHECK(asconnector)
34
35 #define TRACE_ON 0
36
37 #if TRACE_ON
38 #define T(...) VERBOSE_PRINT(asconnector,__VA_ARGS__)
39 #else
40 #define T(...)
41 #endif
42
43 /********************************************************************************
44 * Internals
45 *******************************************************************************/
46
47 struct AsyncSocketConnector {
48 /* TCP address for the connection. */
49 SockAddress address;
50 /* I/O looper for asynchronous I/O. */
51 Looper* looper;
52 /* I/O port for asynchronous connection. */
53 LoopIo connector_io[1];
54 /* Timer that is used to retry asynchronous connections. */
55 LoopTimer connector_timer[1];
56 /* Asynchronous connector to the socket. */
57 AsyncConnector connector[1];
58 /* Callback to invoke on connection events. */
59 asc_event_cb on_connected_cb;
60 /* An opaque parameter to pass to the connection callback. */
61 void* on_connected_cb_opaque;
62 /* Retry timeout in milliseconds. */
63 int retry_to;
64 /* Socket descriptor for the connection. */
65 int fd;
66 /* Number of outstanding references to the connector. */
67 int ref_count;
68 /* Flags whether (1) or not (0) connector owns the looper. */
69 int owns_looper;
70 };
71
72 /* Asynchronous I/O looper callback invoked by the connector.
73 * Param:
74 * opaque - AsyncSocketConnector instance.
75 * fd, events - Standard I/O callback parameters.
76 */
77 static void _on_async_socket_connector_io(void* opaque, int fd, unsigned events);
78
79 /* Gets socket's address string. */
80 AINLINED const char*
_asc_socket_string(AsyncSocketConnector * connector)81 _asc_socket_string(AsyncSocketConnector* connector)
82 {
83 return sock_address_to_string(&connector->address);
84 }
85
86 /* Destroys AsyncSocketConnector instance.
87 * Param:
88 * connector - Initialized AsyncSocketConnector instance.
89 */
90 static void
_async_socket_connector_free(AsyncSocketConnector * connector)91 _async_socket_connector_free(AsyncSocketConnector* connector)
92 {
93 if (connector != NULL) {
94 T("ASC %s: Connector is destroying...", _asc_socket_string(connector));
95
96 /* Stop all activities. */
97 if (asyncConnector_stop(connector->connector) == 0) {
98 /* Connection was in progress. We need to destroy I/O descriptor for
99 * that connection. */
100 D("ASC %s: Stopped async connection in progress.",
101 _asc_socket_string(connector));
102 loopIo_done(connector->connector_io);
103 }
104
105 /* Free allocated resources. */
106 if (connector->looper != NULL) {
107 loopTimer_done(connector->connector_timer);
108 if (connector->owns_looper) {
109 looper_free(connector->looper);
110 }
111 }
112
113 if (connector->fd >= 0) {
114 socket_close(connector->fd);
115 }
116
117 T("ASC %s: Connector is destroyed", _asc_socket_string(connector));
118
119 sock_address_done(&connector->address);
120
121 AFREE(connector);
122 }
123 }
124
125 /* Opens connection socket.
126 * Param:
127 * connector - Initialized AsyncSocketConnector instance.
128 * Return:
129 * 0 on success, or -1 on failure.
130 */
131 static int
_async_socket_connector_open_socket(AsyncSocketConnector * connector)132 _async_socket_connector_open_socket(AsyncSocketConnector* connector)
133 {
134 /* Open socket. */
135 connector->fd = socket_create_inet(SOCKET_STREAM);
136 if (connector->fd < 0) {
137 D("ASC %s: Unable to create socket: %d -> %s",
138 _asc_socket_string(connector), errno, strerror(errno));
139 return -1;
140 }
141
142 /* Prepare for async I/O on the connector. */
143 socket_set_nonblock(connector->fd);
144
145 T("ASC %s: Connector socket is opened with FD = %d",
146 _asc_socket_string(connector), connector->fd);
147
148 return 0;
149 }
150
151 /* Closes connection socket.
152 * Param:
153 * connector - Initialized AsyncSocketConnector instance.
154 * Return:
155 * 0 on success, or -1 on failure.
156 */
157 static void
_async_socket_connector_close_socket(AsyncSocketConnector * connector)158 _async_socket_connector_close_socket(AsyncSocketConnector* connector)
159 {
160 if (connector->fd >= 0) {
161 socket_close(connector->fd);
162 T("ASC %s: Connector socket FD = %d is closed.",
163 _asc_socket_string(connector), connector->fd);
164 connector->fd = -1;
165 }
166 }
167
168 /* Asynchronous connector (AsyncConnector instance) has completed connection
169 * attempt.
170 * Param:
171 * connector - Initialized AsyncSocketConnector instance. Note: When this
172 * callback is called, the caller has referenced passed connector object,
173 * So, it's guaranteed that this connector is not going to be destroyed
174 * while this routine executes.
175 * status - Status of the connection attempt.
176 */
177 static void
_on_async_socket_connector_connecting(AsyncSocketConnector * connector,AsyncStatus status)178 _on_async_socket_connector_connecting(AsyncSocketConnector* connector,
179 AsyncStatus status)
180 {
181 AsyncIOAction action = ASIO_ACTION_DONE;
182
183 switch (status) {
184 case ASYNC_COMPLETE:
185 loopIo_done(connector->connector_io);
186 D("Socket '%s' is connected", _asc_socket_string(connector));
187 /* Invoke "on connected" callback */
188 action = connector->on_connected_cb(connector->on_connected_cb_opaque,
189 connector, ASIO_STATE_SUCCEEDED);
190 break;
191
192 case ASYNC_ERROR:
193 loopIo_done(connector->connector_io);
194 D("Error while connecting to socket '%s': %d -> %s",
195 _asc_socket_string(connector), errno, strerror(errno));
196 /* Invoke "on connected" callback */
197 action = connector->on_connected_cb(connector->on_connected_cb_opaque,
198 connector, ASIO_STATE_FAILED);
199 break;
200
201 case ASYNC_NEED_MORE:
202 T("ASC %s: Waiting on connection to complete. Connector FD = %d",
203 _asc_socket_string(connector), connector->fd);
204 return;
205 }
206
207 if (action == ASIO_ACTION_RETRY) {
208 D("ASC %s: Retrying connection. Connector FD = %d",
209 _asc_socket_string(connector), connector->fd);
210 loopTimer_startRelative(connector->connector_timer, connector->retry_to);
211 } else if (action == ASIO_ACTION_ABORT) {
212 D("ASC %s: Client has aborted connection. Connector FD = %d",
213 _asc_socket_string(connector), connector->fd);
214 }
215 }
216
217 static void
_on_async_socket_connector_io(void * opaque,int fd,unsigned events)218 _on_async_socket_connector_io(void* opaque, int fd, unsigned events)
219 {
220 AsyncSocketConnector* const connector = (AsyncSocketConnector*)opaque;
221
222 /* Reference the connector while we're handing I/O. */
223 async_socket_connector_reference(connector);
224
225 /* Notify the client that another connection attempt is about to start. */
226 const AsyncIOAction action =
227 connector->on_connected_cb(connector->on_connected_cb_opaque,
228 connector, ASIO_STATE_CONTINUES);
229 if (action != ASIO_ACTION_ABORT) {
230 /* Complete socket connection. */
231 const AsyncStatus status = asyncConnector_run(connector->connector);
232 _on_async_socket_connector_connecting(connector, status);
233 } else {
234 D("ASC %s: Client has aborted connection. Connector FD = %d",
235 _asc_socket_string(connector), connector->fd);
236 }
237
238 /* Release the connector after we're done with handing I/O. */
239 async_socket_connector_release(connector);
240 }
241
242 /* Retry connection timer callback.
243 * Param:
244 * opaque - AsyncSocketConnector instance.
245 */
246 static void
_on_async_socket_connector_retry(void * opaque)247 _on_async_socket_connector_retry(void* opaque)
248 {
249 AsyncStatus status;
250 AsyncSocketConnector* const connector = (AsyncSocketConnector*)opaque;
251
252 T("ASC %s: Reconnect timer expired. Connector FD = %d",
253 _asc_socket_string(connector), connector->fd);
254
255 /* Reference the connector while we're in callback. */
256 async_socket_connector_reference(connector);
257
258 /* Invoke the callback to notify about a connection retry attempt. */
259 AsyncIOAction action =
260 connector->on_connected_cb(connector->on_connected_cb_opaque,
261 connector, ASIO_STATE_RETRYING);
262
263 if (action != ASIO_ACTION_ABORT) {
264 /* Close handle opened for the previous (failed) attempt. */
265 _async_socket_connector_close_socket(connector);
266
267 /* Retry connection attempt. */
268 if (_async_socket_connector_open_socket(connector) == 0) {
269 loopIo_init(connector->connector_io, connector->looper,
270 connector->fd, _on_async_socket_connector_io, connector);
271 status = asyncConnector_init(connector->connector,
272 &connector->address,
273 connector->connector_io);
274 } else {
275 status = ASYNC_ERROR;
276 }
277
278 _on_async_socket_connector_connecting(connector, status);
279 } else {
280 D("ASC %s: Client has aborted connection. Connector FD = %d",
281 _asc_socket_string(connector), connector->fd);
282 }
283
284 /* Release the connector after we're done with the callback. */
285 async_socket_connector_release(connector);
286 }
287
288 /********************************************************************************
289 * Async connector implementation
290 *******************************************************************************/
291
292 AsyncSocketConnector*
async_socket_connector_new(const SockAddress * address,int retry_to,asc_event_cb cb,void * cb_opaque,Looper * looper)293 async_socket_connector_new(const SockAddress* address,
294 int retry_to,
295 asc_event_cb cb,
296 void* cb_opaque,
297 Looper* looper)
298 {
299 AsyncSocketConnector* connector;
300
301 if (cb == NULL) {
302 W("No callback for AsyncSocketConnector for socket '%s'",
303 sock_address_to_string(address));
304 errno = EINVAL;
305 return NULL;
306 }
307
308 ANEW0(connector);
309
310 connector->fd = -1;
311 connector->retry_to = retry_to;
312 connector->on_connected_cb = cb;
313 connector->on_connected_cb_opaque = cb_opaque;
314 connector->ref_count = 1;
315
316 /* Copy socket address. */
317 if (sock_address_get_family(address) == SOCKET_UNIX) {
318 sock_address_init_unix(&connector->address, sock_address_get_path(address));
319 } else {
320 connector->address = *address;
321 }
322
323 /* Create a looper for asynchronous I/O. */
324 if (looper == NULL) {
325 connector->looper = looper_newCore();
326 if (connector->looper == NULL) {
327 E("Unable to create I/O looper for AsyncSocketConnector for socket '%s'",
328 _asc_socket_string(connector));
329 cb(cb_opaque, connector, ASIO_STATE_FAILED);
330 _async_socket_connector_free(connector);
331 return NULL;
332 }
333 connector->owns_looper = 1;
334 } else {
335 connector->looper = looper;
336 connector->owns_looper = 0;
337 }
338
339 /* Create a timer that will be used for connection retries. */
340 loopTimer_init(connector->connector_timer, connector->looper,
341 _on_async_socket_connector_retry, connector);
342
343 T("ASC %s: New connector object", _asc_socket_string(connector));
344
345 return connector;
346 }
347
348 int
async_socket_connector_reference(AsyncSocketConnector * connector)349 async_socket_connector_reference(AsyncSocketConnector* connector)
350 {
351 assert(connector->ref_count > 0);
352 connector->ref_count++;
353 return connector->ref_count;
354 }
355
356 int
async_socket_connector_release(AsyncSocketConnector * connector)357 async_socket_connector_release(AsyncSocketConnector* connector)
358 {
359 assert(connector->ref_count > 0);
360 connector->ref_count--;
361 if (connector->ref_count == 0) {
362 /* Last reference has been dropped. Destroy this object. */
363 _async_socket_connector_free(connector);
364 return 0;
365 }
366 return connector->ref_count;
367 }
368
369 void
async_socket_connector_connect(AsyncSocketConnector * connector)370 async_socket_connector_connect(AsyncSocketConnector* connector)
371 {
372 AsyncStatus status;
373
374 T("ASC %s: Handling connect request. Connector FD = %d",
375 _asc_socket_string(connector), connector->fd);
376
377 if (_async_socket_connector_open_socket(connector) == 0) {
378 const AsyncIOAction action =
379 connector->on_connected_cb(connector->on_connected_cb_opaque,
380 connector, ASIO_STATE_STARTED);
381 if (action == ASIO_ACTION_ABORT) {
382 D("ASC %s: Client has aborted connection. Connector FD = %d",
383 _asc_socket_string(connector), connector->fd);
384 return;
385 } else {
386 loopIo_init(connector->connector_io, connector->looper,
387 connector->fd, _on_async_socket_connector_io, connector);
388 status = asyncConnector_init(connector->connector,
389 &connector->address,
390 connector->connector_io);
391 }
392 } else {
393 status = ASYNC_ERROR;
394 }
395
396 _on_async_socket_connector_connecting(connector, status);
397 }
398
399 int
async_socket_connector_pull_fd(AsyncSocketConnector * connector)400 async_socket_connector_pull_fd(AsyncSocketConnector* connector)
401 {
402 const int fd = connector->fd;
403 if (fd >= 0) {
404 connector->fd = -1;
405 }
406
407 T("ASC %s: Client has pulled connector FD %d", _asc_socket_string(connector), fd);
408
409 return fd;
410 }
411