• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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