19d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine/* 29d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * Copyright (C) 2011 The Android Open Source Project 39d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * 49d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * Licensed under the Apache License, Version 2.0 (the "License"); 59d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * you may not use this file except in compliance with the License. 69d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * You may obtain a copy of the License at 79d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * 89d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * http://www.apache.org/licenses/LICENSE-2.0 99d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * 109d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * Unless required by applicable law or agreed to in writing, software 119d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * distributed under the License is distributed on an "AS IS" BASIS, 129d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * See the License for the specific language governing permissions and 149d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * limitations under the License. 159d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine */ 169d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 179d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine/* 189d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * Encapsulates exchange protocol between the emulator, and an Android device 199d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * that is connected to the host via USB. The communication is established over 209d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * a TCP port forwarding, enabled by ADB. 219d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine */ 229d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 239d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine#include "android/utils/debug.h" 249d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine#include "android/async-socket-connector.h" 259d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine#include "utils/panic.h" 269d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine#include "iolooper.h" 279d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 289d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine#define E(...) derror(__VA_ARGS__) 299d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine#define W(...) dwarning(__VA_ARGS__) 309d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine#define D(...) VERBOSE_PRINT(asconnector,__VA_ARGS__) 319d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine#define D_ACTIVE VERBOSE_CHECK(asconnector) 329d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 33c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#define TRACE_ON 0 34c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 35c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#if TRACE_ON 36c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#define T(...) VERBOSE_PRINT(asconnector,__VA_ARGS__) 37c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#else 38c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#define T(...) 39c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#endif 40c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 419d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine/******************************************************************************** 429d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * Internals 439d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine *******************************************************************************/ 449d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 459d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkinestruct AsyncSocketConnector { 469d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine /* TCP address for the connection. */ 479d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine SockAddress address; 489d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine /* I/O looper for asynchronous I/O. */ 499d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine Looper* looper; 509d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine /* I/O port for asynchronous connection. */ 519d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine LoopIo connector_io[1]; 529d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine /* Timer that is used to retry asynchronous connections. */ 539d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine LoopTimer connector_timer[1]; 549d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine /* Asynchronous connector to the socket. */ 559d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine AsyncConnector connector[1]; 566dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine /* Callback to invoke on connection events. */ 579d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine asc_event_cb on_connected_cb; 589d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine /* An opaque parameter to pass to the connection callback. */ 599d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine void* on_connected_cb_opaque; 609d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine /* Retry timeout in milliseconds. */ 619d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine int retry_to; 629d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine /* Socket descriptor for the connection. */ 639d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine int fd; 64ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine /* Number of outstanding references to the connector. */ 65ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine int ref_count; 66c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Flags whether (1) or not (0) connector owns the looper. */ 67c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine int owns_looper; 689d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine}; 699d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 709d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine/* Asynchronous I/O looper callback invoked by the connector. 719d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * Param: 729d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * opaque - AsyncSocketConnector instance. 739d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * fd, events - Standard I/O callback parameters. 749d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine */ 759d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkinestatic void _on_async_socket_connector_io(void* opaque, int fd, unsigned events); 769d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 779d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine/* Gets socket's address string. */ 789d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir ChtchetkineAINLINED const char* 799d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine_asc_socket_string(AsyncSocketConnector* connector) 809d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine{ 819d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine return sock_address_to_string(&connector->address); 829d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine} 839d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 849d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine/* Destroys AsyncSocketConnector instance. 859d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * Param: 869d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * connector - Initialized AsyncSocketConnector instance. 879d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine */ 889d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkinestatic void 899d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine_async_socket_connector_free(AsyncSocketConnector* connector) 909d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine{ 919d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine if (connector != NULL) { 92c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("ASC %s: Connector is destroying...", _asc_socket_string(connector)); 93c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 94c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Stop all activities. */ 95ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine if (asyncConnector_stop(connector->connector) == 0) { 96ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine /* Connection was in progress. We need to destroy I/O descriptor for 97ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine * that connection. */ 98c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine D("ASC %s: Stopped async connection in progress.", 99ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine _asc_socket_string(connector)); 100ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine loopIo_done(connector->connector_io); 101ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine } 1029d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 103c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Free allocated resources. */ 1049d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine if (connector->looper != NULL) { 1059d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine loopTimer_done(connector->connector_timer); 106c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (connector->owns_looper) { 107c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine looper_free(connector->looper); 108c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1099d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine } 1109d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 111c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (connector->fd >= 0) { 112c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine socket_close(connector->fd); 113c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 114c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 115c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("ASC %s: Connector is destroyed", _asc_socket_string(connector)); 116c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1179d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine sock_address_done(&connector->address); 1189d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 1199d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine AFREE(connector); 1209d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine } 1219d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine} 1229d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 1239d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine/* Opens connection socket. 1249d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * Param: 1259d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * connector - Initialized AsyncSocketConnector instance. 1269d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * Return: 1279d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * 0 on success, or -1 on failure. 1289d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine */ 1299d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkinestatic int 1309d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine_async_socket_connector_open_socket(AsyncSocketConnector* connector) 1319d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine{ 1329d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine /* Open socket. */ 1339d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine connector->fd = socket_create_inet(SOCKET_STREAM); 1349d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine if (connector->fd < 0) { 135c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine D("ASC %s: Unable to create socket: %d -> %s", 1366dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine _asc_socket_string(connector), errno, strerror(errno)); 1379d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine return -1; 1389d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine } 1399d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 1409d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine /* Prepare for async I/O on the connector. */ 1419d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine socket_set_nonblock(connector->fd); 1429d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 143c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("ASC %s: Connector socket is opened with FD = %d", 144c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _asc_socket_string(connector), connector->fd); 145c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1469d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine return 0; 1479d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine} 1489d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 1499d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine/* Closes connection socket. 1509d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * Param: 1519d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * connector - Initialized AsyncSocketConnector instance. 1529d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * Return: 1539d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * 0 on success, or -1 on failure. 1549d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine */ 1559d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkinestatic void 1569d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine_async_socket_connector_close_socket(AsyncSocketConnector* connector) 1579d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine{ 1589d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine if (connector->fd >= 0) { 1599d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine socket_close(connector->fd); 160c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("ASC %s: Connector socket FD = %d is closed.", 161c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _asc_socket_string(connector), connector->fd); 1629d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine connector->fd = -1; 1639d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine } 1649d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine} 1659d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 1669d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine/* Asynchronous connector (AsyncConnector instance) has completed connection 1679d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * attempt. 1689d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * Param: 169ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine * connector - Initialized AsyncSocketConnector instance. Note: When this 170ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine * callback is called, the caller has referenced passed connector object, 171ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine * So, it's guaranteed that this connector is not going to be destroyed 172ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine * while this routine executes. 1739d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * status - Status of the connection attempt. 1749d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine */ 1759d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkinestatic void 1769d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine_on_async_socket_connector_connecting(AsyncSocketConnector* connector, 1779d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine AsyncStatus status) 1789d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine{ 1796dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine AsyncIOAction action = ASIO_ACTION_DONE; 1809d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 1819d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine switch (status) { 1829d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine case ASYNC_COMPLETE: 1839d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine loopIo_done(connector->connector_io); 1846dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine D("Socket '%s' is connected", _asc_socket_string(connector)); 1859d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine /* Invoke "on connected" callback */ 1869d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine action = connector->on_connected_cb(connector->on_connected_cb_opaque, 1876dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine connector, ASIO_STATE_SUCCEEDED); 1889d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine break; 1899d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 1909d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine case ASYNC_ERROR: 1919d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine loopIo_done(connector->connector_io); 1926dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine D("Error while connecting to socket '%s': %d -> %s", 1936dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine _asc_socket_string(connector), errno, strerror(errno)); 1949d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine /* Invoke "on connected" callback */ 1959d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine action = connector->on_connected_cb(connector->on_connected_cb_opaque, 1966dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine connector, ASIO_STATE_FAILED); 1979d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine break; 1989d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 1999d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine case ASYNC_NEED_MORE: 200c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("ASC %s: Waiting on connection to complete. Connector FD = %d", 201c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _asc_socket_string(connector), connector->fd); 2029d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine return; 2039d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine } 2049d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 2056dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine if (action == ASIO_ACTION_RETRY) { 206c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine D("ASC %s: Retrying connection. Connector FD = %d", 207c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _asc_socket_string(connector), connector->fd); 2089d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine loopTimer_startRelative(connector->connector_timer, connector->retry_to); 209ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine } else if (action == ASIO_ACTION_ABORT) { 210c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine D("ASC %s: Client has aborted connection. Connector FD = %d", 211c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _asc_socket_string(connector), connector->fd); 2129d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine } 2139d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine} 2149d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 2159d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkinestatic void 2169d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine_on_async_socket_connector_io(void* opaque, int fd, unsigned events) 2179d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine{ 2189d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine AsyncSocketConnector* const connector = (AsyncSocketConnector*)opaque; 2199d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 220ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine /* Reference the connector while we're handing I/O. */ 221ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine async_socket_connector_reference(connector); 222ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine 2236dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine /* Notify the client that another connection attempt is about to start. */ 2246dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine const AsyncIOAction action = 2256dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine connector->on_connected_cb(connector->on_connected_cb_opaque, 2266dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine connector, ASIO_STATE_CONTINUES); 2276dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine if (action != ASIO_ACTION_ABORT) { 2286dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine /* Complete socket connection. */ 2296dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine const AsyncStatus status = asyncConnector_run(connector->connector); 2306dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine _on_async_socket_connector_connecting(connector, status); 2316dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine } else { 232c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine D("ASC %s: Client has aborted connection. Connector FD = %d", 233c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _asc_socket_string(connector), connector->fd); 2346dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine } 235ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine 236ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine /* Release the connector after we're done with handing I/O. */ 237ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine async_socket_connector_release(connector); 2389d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine} 2399d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 2409d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine/* Retry connection timer callback. 2419d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * Param: 2429d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * opaque - AsyncSocketConnector instance. 2439d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine */ 2449d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkinestatic void 2459d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine_on_async_socket_connector_retry(void* opaque) 2469d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine{ 2476dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine AsyncStatus status; 2489d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine AsyncSocketConnector* const connector = (AsyncSocketConnector*)opaque; 2499d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 250c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("ASC %s: Reconnect timer expired. Connector FD = %d", 251c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _asc_socket_string(connector), connector->fd); 252c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 253ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine /* Reference the connector while we're in callback. */ 254ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine async_socket_connector_reference(connector); 255ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine 2569d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine /* Invoke the callback to notify about a connection retry attempt. */ 2576dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine AsyncIOAction action = 2589d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine connector->on_connected_cb(connector->on_connected_cb_opaque, 2596dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine connector, ASIO_STATE_RETRYING); 2609d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 261ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine if (action != ASIO_ACTION_ABORT) { 262ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine /* Close handle opened for the previous (failed) attempt. */ 263ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine _async_socket_connector_close_socket(connector); 2649d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 265ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine /* Retry connection attempt. */ 266ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine if (_async_socket_connector_open_socket(connector) == 0) { 267ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine loopIo_init(connector->connector_io, connector->looper, 268ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine connector->fd, _on_async_socket_connector_io, connector); 269ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine status = asyncConnector_init(connector->connector, 270ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine &connector->address, 271ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine connector->connector_io); 272ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine } else { 273ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine status = ASYNC_ERROR; 274ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine } 2759d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 276ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine _on_async_socket_connector_connecting(connector, status); 2779d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine } else { 278c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine D("ASC %s: Client has aborted connection. Connector FD = %d", 279c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _asc_socket_string(connector), connector->fd); 2809d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine } 2816dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine 282ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine /* Release the connector after we're done with the callback. */ 283ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine async_socket_connector_release(connector); 2849d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine} 2859d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 2869d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine/******************************************************************************** 2879d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine * Async connector implementation 2889d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine *******************************************************************************/ 2899d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 2909d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir ChtchetkineAsyncSocketConnector* 2919d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkineasync_socket_connector_new(const SockAddress* address, 2929d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine int retry_to, 2939d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine asc_event_cb cb, 294c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine void* cb_opaque, 295c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine Looper* looper) 2969d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine{ 2979d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine AsyncSocketConnector* connector; 2989d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 2999d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine if (cb == NULL) { 3006dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine W("No callback for AsyncSocketConnector for socket '%s'", 3019d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine sock_address_to_string(address)); 3029d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine errno = EINVAL; 3039d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine return NULL; 3049d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine } 3059d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 3069d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine ANEW0(connector); 3079d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 3089d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine connector->fd = -1; 3099d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine connector->retry_to = retry_to; 3109d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine connector->on_connected_cb = cb; 3119d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine connector->on_connected_cb_opaque = cb_opaque; 312ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine connector->ref_count = 1; 3139d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 3149d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine /* Copy socket address. */ 3154732aee0622005bc612f75d0319e6e3a057301b4Vladimir Chtchetkine#ifdef _WIN32 3164732aee0622005bc612f75d0319e6e3a057301b4Vladimir Chtchetkine connector->address = *address; 3174732aee0622005bc612f75d0319e6e3a057301b4Vladimir Chtchetkine#else 3189d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine if (sock_address_get_family(address) == SOCKET_UNIX) { 3199d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine sock_address_init_unix(&connector->address, sock_address_get_path(address)); 3209d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine } else { 3219d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine connector->address = *address; 3229d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine } 3234732aee0622005bc612f75d0319e6e3a057301b4Vladimir Chtchetkine#endif 3249d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 3259d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine /* Create a looper for asynchronous I/O. */ 326c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (looper == NULL) { 327c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine connector->looper = looper_newCore(); 328c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (connector->looper == NULL) { 329c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine E("Unable to create I/O looper for AsyncSocketConnector for socket '%s'", 330c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _asc_socket_string(connector)); 331c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine cb(cb_opaque, connector, ASIO_STATE_FAILED); 332c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _async_socket_connector_free(connector); 333c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return NULL; 334c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 335c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine connector->owns_looper = 1; 336c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } else { 337c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine connector->looper = looper; 338c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine connector->owns_looper = 0; 3399d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine } 3409d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 341ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine /* Create a timer that will be used for connection retries. */ 342ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine loopTimer_init(connector->connector_timer, connector->looper, 343ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine _on_async_socket_connector_retry, connector); 344ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine 345c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("ASC %s: New connector object", _asc_socket_string(connector)); 346c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 3479d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine return connector; 3489d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine} 3499d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 350ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkineint 351ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkineasync_socket_connector_reference(AsyncSocketConnector* connector) 352ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine{ 353ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine assert(connector->ref_count > 0); 354ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine connector->ref_count++; 355ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine return connector->ref_count; 356ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine} 357ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine 358ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkineint 359ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkineasync_socket_connector_release(AsyncSocketConnector* connector) 360ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine{ 361ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine assert(connector->ref_count > 0); 362ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine connector->ref_count--; 363ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine if (connector->ref_count == 0) { 364ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine /* Last reference has been dropped. Destroy this object. */ 365ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine _async_socket_connector_free(connector); 366ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine return 0; 367ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine } 368ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine return connector->ref_count; 369ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine} 370ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine 3716dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkinevoid 3729d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkineasync_socket_connector_connect(AsyncSocketConnector* connector) 3739d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine{ 3749d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine AsyncStatus status; 3759d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 376c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("ASC %s: Handling connect request. Connector FD = %d", 377c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _asc_socket_string(connector), connector->fd); 378c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 3799d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine if (_async_socket_connector_open_socket(connector) == 0) { 3806dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine const AsyncIOAction action = 3816dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine connector->on_connected_cb(connector->on_connected_cb_opaque, 3826dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine connector, ASIO_STATE_STARTED); 3836dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine if (action == ASIO_ACTION_ABORT) { 384c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine D("ASC %s: Client has aborted connection. Connector FD = %d", 385c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _asc_socket_string(connector), connector->fd); 3866dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine return; 3876dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine } else { 388ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine loopIo_init(connector->connector_io, connector->looper, 389ef4ccd385650612a830a098f4b1eac48482b65b3Vladimir Chtchetkine connector->fd, _on_async_socket_connector_io, connector); 3906dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine status = asyncConnector_init(connector->connector, 3916dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine &connector->address, 3926dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine connector->connector_io); 3936dc5c2cef91004488f04fc6e9c0946f6d3a29705Vladimir Chtchetkine } 3949d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine } else { 3959d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine status = ASYNC_ERROR; 3969d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine } 3979d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 3989d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine _on_async_socket_connector_connecting(connector, status); 3999d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine} 4009d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine 4019d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkineint 4029d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkineasync_socket_connector_pull_fd(AsyncSocketConnector* connector) 4039d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine{ 4049d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine const int fd = connector->fd; 4059d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine if (fd >= 0) { 4069d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine connector->fd = -1; 4079d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine } 408c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 409c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("ASC %s: Client has pulled connector FD %d", _asc_socket_string(connector), fd); 410c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 4119d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine return fd; 4129d36fe7e6f0c5ece4de1b29ec78a15c37c158b1dVladimir Chtchetkine} 413