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