Home | History | Annotate | Download | only in android
      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*
     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
     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
    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
    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
    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
    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
    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*
    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
    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
    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
    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
    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