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