1db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* 2db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Copyright (C) 2011 The Android Open Source Project 3db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * 4db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Licensed under the Apache License, Version 2.0 (the "License"); 5db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * you may not use this file except in compliance with the License. 6db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * You may obtain a copy of the License at 7db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * 8db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * http://www.apache.org/licenses/LICENSE-2.0 9db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * 10db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Unless required by applicable law or agreed to in writing, software 11db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * distributed under the License is distributed on an "AS IS" BASIS, 12db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * See the License for the specific language governing permissions and 14db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * limitations under the License. 15db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine */ 16db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 17db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* 18db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Encapsulates exchange protocol between the emulator, and an Android device 19db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * that is connected to the host via USB. The communication is established over 20db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * a TCP port forwarding, enabled by ADB. 21db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine */ 22db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 23db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine#include "android/android-device.h" 2434f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine#include "utils/panic.h" 25db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine#include "iolooper.h" 26db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 27db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine#define E(...) derror(__VA_ARGS__) 28db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine#define W(...) dwarning(__VA_ARGS__) 29db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine#define D(...) VERBOSE_PRINT(adevice,__VA_ARGS__) 30db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine#define D_ACTIVE VERBOSE_CHECK(adevice) 31db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 32db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/******************************************************************************** 33db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Common android device socket 34db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine *******************************************************************************/ 35db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 36db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Milliseconds between retrying asynchronous connections to the device. */ 37db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine#define ADS_RETRY_CONNECTION_TIMEOUT 3000 38db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 39db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Socket type. */ 40db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinetypedef enum ADSType { 41db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Query socket. */ 42db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ADS_TYPE_QUERY = 0, 43db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Events socket. */ 44db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ADS_TYPE_EVENT = 1 45db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} ADSType; 46db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 47db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Status of the socket. */ 48db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinetypedef enum ADSStatus { 49db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Socket is disconnected. */ 50db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ADS_DISCONNECTED, 51db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Connection process has been started. */ 52db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ADS_CONNECTING, 53db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Connection has been established. */ 54db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ADS_CONNECTED, 55db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Socket has been registered with the server. */ 56db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ADS_REGISTERED, 57db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} ADSStatus; 58db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 59db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Identifies socket as a "query" socket with the server. */ 60db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic const char* _ads_query_socket_id = "query"; 61db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Identifies socket as an "event" socket with the server. */ 62db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic const char* _ads_event_socket_id = "event"; 63db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 64db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Android device socket descriptor. */ 65db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinetypedef struct AndroidDevSocket AndroidDevSocket; 66db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 67db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* 68db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Callback routines. 69db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine */ 70db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 71db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Callback routine that is called when a socket is connected. 72db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Param: 73db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * opaque - Opaque pointer associated with the socket. Typicaly it's the same 74db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * pointer that is associated with AndroidDevice instance. 75db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * ads - Connection socket. 76db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * failure - If zero, indicates that socket has been successuly connected. If a 77db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * connection error has occured, this parameter contains the error code (as 78db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * in 'errno). 79db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine */ 80db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinetypedef void (*ads_socket_connected_cb)(void* opaque, 81db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine struct AndroidDevSocket* ads, 82db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int failure); 83db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 84db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Android device socket descriptor. */ 85db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestruct AndroidDevSocket { 86db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Socket type. */ 87db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ADSType type; 88db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Socket status. */ 89db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ADSStatus socket_status; 90db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* TCP address for the socket. */ 91db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine SockAddress address; 92db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Android device descriptor that owns the socket. */ 93db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine AndroidDevice* ad; 94db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Opaque pointer associated with the socket. Typicaly it's the same 95db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * pointer that is associated with AndroidDevice instance.*/ 96db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine void* opaque; 97db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Deadline for current I/O performed on the socket. */ 98db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine Duration deadline; 99db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Socket's file descriptor. */ 100db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int fd; 101db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine}; 102db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 103db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Query socket descriptor. */ 104db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinetypedef struct AndroidQuerySocket { 105db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Common device socket. */ 106db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine AndroidDevSocket dev_socket; 107db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} AndroidQuerySocket; 108db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 10934f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine/* Describes data to send via an asynchronous socket. */ 11034f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkinetypedef struct AsyncSendBuffer { 11134f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine /* Next buffer to send. */ 11234f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine struct AsyncSendBuffer* next; 11334f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine /* Callback to invoke when data transfer is completed. */ 11434f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine async_send_cb complete_cb; 11534f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine /* An opaque pointer to pass to the transfer completion callback. */ 11634f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine void* complete_opaque; 11734f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine /* Data to send. */ 11834f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine uint8_t* data; 11934f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine /* Size of the entire data buffer. */ 12034f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine int data_size; 12134f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine /* Remaining bytes to send. */ 12234f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine int data_remaining; 12334f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine /* Boolean flag indicating whether to free data buffer upon completion. */ 12434f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine int free_on_completion; 12534f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine} AsyncSendBuffer; 12634f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine 127db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Event socket descriptor. */ 128db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinetypedef struct AndroidEventSocket { 129db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Common socket descriptor. */ 130db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine AndroidDevSocket dev_socket; 131db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Asynchronous connector to the device. */ 132db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine AsyncConnector connector[1]; 133db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* I/O port for asynchronous I/O on this socket. */ 134db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine LoopIo io[1]; 135db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Asynchronous string reader. */ 136db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine AsyncLineReader alr; 137db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Callback to call at the end of the asynchronous connection to this socket. 138db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Can be NULL. */ 139db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ads_socket_connected_cb on_connected; 140db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Callback to call when an event is received on this socket. Can be NULL. */ 141db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine event_cb on_event; 14234f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine /* Lists buffers that are pending to be sent. */ 14334f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine AsyncSendBuffer* send_pending; 144db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} AndroidEventSocket; 145db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 146db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Android device descriptor. */ 147db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestruct AndroidDevice { 148db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Query socket for the device. */ 149db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine AndroidQuerySocket query_socket; 150db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Event socket for the device. */ 151db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine AndroidEventSocket event_socket; 152db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* An opaque pointer associated with this descriptor. */ 153db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine void* opaque; 154db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* I/O looper for synchronous I/O on the sockets for this device. */ 155db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine IoLooper* io_looper; 156db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Timer that is used to retry asynchronous connections. */ 157db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine LoopTimer timer[1]; 158db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* I/O looper for asynchronous I/O. */ 159db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine Looper* looper; 160db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Callback to call when device is fully connected. */ 161db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine device_connected_cb on_connected; 162db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* I/O failure callback .*/ 163db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine io_failure_cb on_io_failure; 164db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine}; 165db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 16634f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine/* Creates descriptor for a buffer to send asynchronously. 16734f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine * Param: 16834f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine * data, size - Buffer to send. 16934f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine * free_on_close - Boolean flag indicating whether to free data buffer upon 17034f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine * completion. 17134f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine * cb - Callback to invoke when data transfer is completed. 17234f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine * opaque - An opaque pointer to pass to the transfer completion callback. 17334f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine */ 17434f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkinestatic AsyncSendBuffer* 17534f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine_async_send_buffer_create(void* data, 17634f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine int size, 17734f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine int free_on_close, 17834f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine async_send_cb cb, 17934f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine void* opaque) 18034f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine{ 18134f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine AsyncSendBuffer* desc = malloc(sizeof(AsyncSendBuffer)); 18234f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine if (desc == NULL) { 18334f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine APANIC("Unable to allocate %d bytes for AsyncSendBuffer", 18434f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine sizeof(AsyncSendBuffer)); 18534f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine } 18634f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine desc->next = NULL; 18734f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine desc->data = (uint8_t*)data; 18834f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine desc->data_size = desc->data_remaining = size; 18934f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine desc->free_on_completion = free_on_close; 19034f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine desc->complete_cb = cb; 19134f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine desc->complete_opaque = opaque; 19234f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine 19334f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine return desc; 19434f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine} 19534f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine 19634f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine/* Completes data transfer for the given descriptor. 19734f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine * Note that this routine will free the descriptor. 19834f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine * Param: 19934f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine * desc - Asynchronous data transfer descriptor. Will be freed upon the exit 20034f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine * from this routine. 20134f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine * res - Data transfer result. 20234f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine */ 20334f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkinestatic void 20434f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine_async_send_buffer_complete(AsyncSendBuffer* desc, ATResult res) 20534f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine{ 20634f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine /* Invoke completion callback (if present) */ 20734f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine if (desc->complete_cb) { 20834f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine desc->complete_cb(desc->complete_opaque, res, desc->data, desc->data_size, 20934f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine desc->data_size - desc->data_remaining); 21034f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine } 21134f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine 21234f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine /* Free data buffer (if required) */ 21334f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine if (desc->free_on_completion) { 21434f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine free(desc->data); 21534f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine } 21634f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine 21734f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine /* Free the descriptor itself. */ 21834f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine free(desc); 21934f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine} 22034f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine 221db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/******************************************************************************** 222db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Common socket declarations 223db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine *******************************************************************************/ 224db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 225db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Initializes common device socket. 226db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Param: 227db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * ads - Socket descriptor to initialize. 228db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * opaque - An opaque pointer to associate with the socket. Typicaly it's the 229db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * same pointer that is associated with AndroidDevice instance. 230db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * ad - Android device descriptor that owns the socket. 231db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * port - Socket's TCP port. 232db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * type - Socket type (query, or event). 233db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine */ 234db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic int _android_dev_socket_init(AndroidDevSocket* ads, 235db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine void* opaque, 236db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine AndroidDevice* ad, 237db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int port, 238db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ADSType type); 239db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 240db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Destroys socket descriptor. */ 241db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic void _android_dev_socket_destroy(AndroidDevSocket* ads); 242db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 243417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine/* Callback that is ivoked from _android_dev_socket_connect when a file 244417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine * descriptor has been created for a socket. 245417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine * Param: 246417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine * ads - Socket descritor. 247417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine * opaque - An opaque pointer associated with the callback. 248417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine */ 249417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkinetypedef void (*on_socked_fd_created)(AndroidDevSocket* ads, void* opaque); 250417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine 251db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Synchronously connects to the socket, and registers it with the server. 252db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Param: 253db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * ads - Socket to connect. Must have 'deadline' field properly setup. 254417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine * cb, opaque - A callback to invoke (and opaque parameters to pass to the 255417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine * callback) when a file descriptor has been created for a socket. These 256417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine * parameters are optional and can be NULL. 257db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Return: 258db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * 0 on success, -1 on failure with errno containing the reason for failure. 259db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine */ 260417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkinestatic int _android_dev_socket_connect(AndroidDevSocket* ads, 261417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine on_socked_fd_created cb, 262417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine void* opaque); 263db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 264db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Synchronously registers a connected socket with the server. 265db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Param: 266db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * ads - Socket to register. Must be connected, and must have 'deadline' field 267db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * properly setup. 268db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Return: 269db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * 0 on success, -1 on failure with errno containing the reason for failure. 270db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine */ 271db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic int _android_dev_socket_register(AndroidDevSocket* ads); 272db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 273db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Disconnects the socket (if it was connected) */ 274db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic void _android_dev_socket_disconnect(AndroidDevSocket* ads); 275db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 276db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Synchronously sends data to the socket. 277db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Param: 278db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * ads - Socket to send the data to. Must be connected, and must have 'deadline' 279db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * field properly setup. 280db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * buff, buffsize - Buffer to send. 281db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Return: 282db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Number of bytes sent on success, or -1 on failure with errno containing the 283db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * reason for failure. 284db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine */ 285db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic int _android_dev_socket_send(AndroidDevSocket* ads, 286db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine const char* buff, 287db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int buffsize); 288db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 289db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Synchronously receives data from the socket. 290db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Param: 291db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * ads - Socket to receive the data from. Must be connected, and must have 292db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * 'deadline' field properly setup. 293db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * buff, buffsize - Buffer where to receive data. 294db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Return: 295db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Number of bytes received on success, or -1 on failure with errno containing 296db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * the reason for failure. 297db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine */ 298db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic int _android_dev_socket_recv(AndroidDevSocket* ads, 299db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine char* buf, 300db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int bufsize); 301db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 302db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Synchronously reads zero-terminated string from the socket. 303db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Param: 304db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * ads - Socket to read the string from. Must be connected, and must have 305db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * 'deadline' field properly setup. 306db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * str, strsize - Buffer where to read the string. 307db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Return: 308db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Number of charactes read into the string buffer (including zero-terminator) 309db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * on success, or -1 on failure with 'errno' containing the reason for failure. 310db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * If this routine returns -1, and errno contains ENOMEM, this is an indicator 311db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * that supplied string buffer was too small for the receiving string. 312db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine */ 313db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic int _android_dev_socket_read_string(AndroidDevSocket* ads, 314db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine char* str, 315db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int strsize); 316db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 317db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Synchronously reads zero-terminated query response from the socket. 318db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * All queries respond with an 'ok', or 'ko' prefix, indicating a success, or 319db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * failure. Prefix can be followed by more query response data, separated from 320db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * the prefix with a ':' character. This routine helps separating prefix from the 321db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * data, by placing only the query response data into provided buffer. 'ko' or 322db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * 'ok' will be encoded in the return value. 323db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Param: 324db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * ads - Socket to read the response from. Must be connected, and must have 325db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * 'deadline' field properly setup. 326db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * data, datasize - Buffer where to read the query response data. 327db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Return: 328db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Number of charactes read into the data buffer (including zero-terminator) on 329db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * success, or -1 on failure with errno containing the reason for failure. 330db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * If the query has been completed with 'ko', this routine will return -1, with 331db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * errno set to 0. If this routine returned -1, and errno is set to EINVAL, this 332db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * indicates that reply string didn't match expected query reply format. 333db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine */ 334db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic int _android_dev_socket_read_response(AndroidDevSocket* ads, 335db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine char* str, 336db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int strsize); 337db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 338db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Gets ID string for the channel. */ 339db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir ChtchetkineAINLINED const char* 340db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine_ads_id_str(AndroidDevSocket* ads) 341db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 342db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return (ads->type == ADS_TYPE_QUERY) ? _ads_query_socket_id : 343db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _ads_event_socket_id; 344db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 345db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 346db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Gets socket's TCP port. */ 347db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir ChtchetkineAINLINED int 348db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine_ads_port(AndroidDevSocket* ads) 349db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 350db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return sock_address_get_port(&ads->address); 351db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 352db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 353db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Gets synchronous I/O looper for the socket. */ 354db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir ChtchetkineAINLINED IoLooper* 355db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine_ads_io_looper(AndroidDevSocket* ads) 356db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 357db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return ads->ad->io_looper; 358db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 359db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 360db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Sets deadline on a socket operation, given relative timeout. 361db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Param: 362db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * ads - Socket descriptor to set deadline for. 363db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * to - Relative timeout (in millisec) for the operation. 364db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * AD_INFINITE_WAIT passed in this parameter means "no deadline". 365db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine */ 366db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir ChtchetkineAINLINED void 367db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine_ads_set_deadline(AndroidDevSocket* ads, int to) 368db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 369db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ads->deadline = (to == AD_INFINITE_WAIT) ? DURATION_INFINITE : 370db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine iolooper_now() + to; 371db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 372db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 373db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/******************************************************************************** 374db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Common socket implementation 375db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine *******************************************************************************/ 376db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 377db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic int 378db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine_android_dev_socket_init(AndroidDevSocket* ads, 379db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine void* opaque, 380db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine AndroidDevice* ad, 381db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int port, 382db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ADSType type) 383db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 384db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ads->type = type; 385db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ads->socket_status = ADS_DISCONNECTED; 386db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ads->opaque = opaque; 387db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ads->ad = ad; 388db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ads->fd = -1; 389db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine sock_address_init_inet(&ads->address, SOCK_ADDRESS_INET_LOOPBACK, port); 390db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 391db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return 0; 392db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 393db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 394db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic void 395db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine_android_dev_socket_destroy(AndroidDevSocket* ads) 396db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 397db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Make sure it's disconnected. */ 398db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _android_dev_socket_disconnect(ads); 399db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 400db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Finalize socket address. */ 401db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine sock_address_done(&ads->address); 402db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine memset(&ads->address, 0, sizeof(ads->address)); 403db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 404db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 405db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic int 406417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine_android_dev_socket_connect(AndroidDevSocket* ads, 407417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine on_socked_fd_created cb, 408417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine void* opaque) 409db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 410db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int res; 411db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 412db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Create communication socket. */ 413db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ads->fd = socket_create_inet(SOCKET_STREAM); 414db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (ads->fd < 0) { 415db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine D("Unable to create socket for channel '%s'@%d: %s", 416db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _ads_id_str(ads), _ads_port(ads), strerror(errno)); 417db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return -1; 418db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 419db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine socket_set_nonblock(ads->fd); 420db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 421417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine /* Invoke FD creation callback (if required) */ 422417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine if (cb != NULL) { 423417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine cb(ads, opaque); 42446ff3eaff40952df50ee14056cae88a3e7396a81Vladimir Chtchetkine } 42546ff3eaff40952df50ee14056cae88a3e7396a81Vladimir Chtchetkine 426db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Synchronously connect to it. */ 427db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ads->socket_status = ADS_CONNECTING; 428db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine iolooper_add_write(_ads_io_looper(ads), ads->fd); 429db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine res = socket_connect(ads->fd, &ads->address); 430db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine while (res < 0 && errno == EINTR) { 431db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine res = socket_connect(ads->fd, &ads->address); 432db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 433db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 434db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (res && (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN)) { 435db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Connection is delayed. Wait for it until timeout expires. */ 436db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine res = iolooper_wait_absolute(_ads_io_looper(ads), ads->deadline); 437db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (res > 0) { 438db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Pick up on possible connection error. */ 439db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine errno = socket_get_error(ads->fd); 440db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine res = (errno == 0) ? 0 : -1; 441db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } else { 442db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine res = -1; 443db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 444db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 445db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine iolooper_del_write(_ads_io_looper(ads), ads->fd); 446db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 447db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (res == 0) { 448db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine D("Channel '%s'@%d is connected", _ads_id_str(ads), _ads_port(ads)); 449db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Socket is connected. Now register it with the server. */ 450db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ads->socket_status = ADS_CONNECTED; 451db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine res = _android_dev_socket_register(ads); 452db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } else { 453db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine D("Unable to connect channel '%s' to port %d: %s", 454db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _ads_id_str(ads), _ads_port(ads), strerror(errno)); 455db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 456db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 457db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (res) { 458db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _android_dev_socket_disconnect(ads); 459db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 460db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 461db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return res; 462db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 463db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 464db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic int 465db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine_android_dev_socket_register(AndroidDevSocket* ads) 466db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 467db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Make sure that socket is connected. */ 468db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (ads->socket_status < ADS_CONNECTED) { 469db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine D("Attempt to register a disconnected channel '%s'@%d", 470db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _ads_id_str(ads), _ads_port(ads)); 471db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine errno = ECONNRESET; 472db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return -1; 473db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 474db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 475db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Register this socket accordingly to its type. */ 476db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine const char* reg_str = _ads_id_str(ads); 477db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int res = _android_dev_socket_send(ads, reg_str, strlen(reg_str) + 1); 478db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (res > 0) { 479db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Receive reply. Note that according to the protocol, the server should 480db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * reply to channel registration with 'ok', or 'ko' (just like with queries), 481db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * so we can use query reply reader here. */ 482db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine char reply[256]; 483db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine res = _android_dev_socket_read_response(ads, reply, sizeof(reply)); 484db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (res >= 0) { 485db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Socket is now registered. */ 486db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ads->socket_status = ADS_REGISTERED; 487db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine D("Channel '%s'@%d is registered", _ads_id_str(ads), _ads_port(ads)); 488db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine res = 0; 489db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } else { 490db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (errno == 0) { 491db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* 'ko' condition */ 492db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine D("Device failed registration of channel '%s'@%d: %s", 493db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _ads_id_str(ads), _ads_port(ads), reply); 494db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine errno = EINVAL; 495db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } else { 496db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine D("I/O failure while registering channel '%s'@%d: %s", 497db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _ads_id_str(ads), _ads_port(ads), strerror(errno)); 498db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 499db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine res = -1; 500db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 501db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } else { 502db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine D("Unable to send registration query for channel '%s'@%d: %s", 503db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _ads_id_str(ads), _ads_port(ads), strerror(errno)); 504db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine res = -1; 505db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 506db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 507db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return res; 508db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 509db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 510db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic void 511db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine_android_dev_socket_disconnect(AndroidDevSocket* ads) 512db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 513db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Preserve errno */ 514db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine const int save_error = errno; 515db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (ads->socket_status != ADS_DISCONNECTED) { 516db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Reset I/O looper for this socket. */ 517db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine iolooper_modify(_ads_io_looper(ads), ads->fd, 518db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine IOLOOPER_READ | IOLOOPER_WRITE, 0); 519db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 520db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Mark as disconnected. */ 521db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ads->socket_status = ADS_DISCONNECTED; 522db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 523db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Close socket. */ 524db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (ads->fd >= 0) { 525db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine socket_close(ads->fd); 526db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ads->fd = -1; 527db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 528db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 529db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine errno = save_error; 530db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 531db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 532db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic int 533db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine_android_dev_socket_send(AndroidDevSocket* ads, const char* buff, int to_send) 534db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 535db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int sent = 0; 536db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 537db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Make sure that socket is connected. */ 538db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (ads->socket_status < ADS_CONNECTED) { 539db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine D("Attempt to send via disconnected channel '%s'@%d", 540db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _ads_id_str(ads), _ads_port(ads)); 541db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine errno = ECONNRESET; 542db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return -1; 543db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 544db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 545db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine iolooper_add_write(_ads_io_looper(ads), ads->fd); 546db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine do { 547db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int res = socket_send(ads->fd, buff + sent, to_send - sent); 548db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (res == 0) { 549db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Disconnection. */ 550db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine errno = ECONNRESET; 551db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine sent = -1; 552db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine break; 553db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 554db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 555db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (res < 0) { 556db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (errno == EINTR) { 557db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* loop on EINTR */ 558db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine continue; 559db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 560db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 561db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (errno == EWOULDBLOCK || errno == EAGAIN) { 562db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine res = iolooper_wait_absolute(_ads_io_looper(ads), ads->deadline); 563db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (res > 0) { 564db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Ready to write. */ 565db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine continue; 566db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 567db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 568db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine sent = -1; 569db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine break; 570db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 571db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine sent += res; 572db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } while (sent < to_send); 573db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine iolooper_del_write(_ads_io_looper(ads), ads->fd); 574db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 575db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* In case of an I/O failure we have to invoke failure callback. Note that we 576db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * report I/O failures only on registered sockets. */ 577db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (sent < 0) { 578db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine D("I/O error while sending data via channel '%s'@%d: %s", 579db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _ads_id_str(ads), _ads_port(ads), strerror(errno)); 580db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 581db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (ads->ad->on_io_failure != NULL && ads->socket_status > ADS_CONNECTED) { 582db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine const char save_error = errno; 583db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ads->ad->on_io_failure(ads->opaque, ads->ad, save_error); 584db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine errno = save_error; 585db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 586db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 587db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 588db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return sent; 589db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 590db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 591db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic int 592db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine_android_dev_socket_recv(AndroidDevSocket* ads, char* buf, int bufsize) 593db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 594db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int recvd = 0; 595db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 596db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Make sure that socket is connected. */ 597db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (ads->socket_status < ADS_CONNECTED) { 598db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine D("Attempt to receive from disconnected channel '%s'@%d", 599db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _ads_id_str(ads), _ads_port(ads)); 600db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine errno = ECONNRESET; 601db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return -1; 602db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 603db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 60410bc04fd968d7f80258bf1eec665babf28e9e47dVladimir Chtchetkine iolooper_add_read(_ads_io_looper(ads), ads->fd); 60510bc04fd968d7f80258bf1eec665babf28e9e47dVladimir Chtchetkine do { 60610bc04fd968d7f80258bf1eec665babf28e9e47dVladimir Chtchetkine int res = socket_recv(ads->fd, buf + recvd, bufsize - recvd); 60710bc04fd968d7f80258bf1eec665babf28e9e47dVladimir Chtchetkine if (res == 0) { 60810bc04fd968d7f80258bf1eec665babf28e9e47dVladimir Chtchetkine /* Disconnection. */ 60910bc04fd968d7f80258bf1eec665babf28e9e47dVladimir Chtchetkine errno = ECONNRESET; 61010bc04fd968d7f80258bf1eec665babf28e9e47dVladimir Chtchetkine recvd = -1; 61110bc04fd968d7f80258bf1eec665babf28e9e47dVladimir Chtchetkine break; 612db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 61310bc04fd968d7f80258bf1eec665babf28e9e47dVladimir Chtchetkine 61410bc04fd968d7f80258bf1eec665babf28e9e47dVladimir Chtchetkine if (res < 0) { 61510bc04fd968d7f80258bf1eec665babf28e9e47dVladimir Chtchetkine if (errno == EINTR) { 61610bc04fd968d7f80258bf1eec665babf28e9e47dVladimir Chtchetkine /* loop on EINTR */ 61710bc04fd968d7f80258bf1eec665babf28e9e47dVladimir Chtchetkine continue; 618db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 619db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 62010bc04fd968d7f80258bf1eec665babf28e9e47dVladimir Chtchetkine if (errno == EWOULDBLOCK || errno == EAGAIN) { 62110bc04fd968d7f80258bf1eec665babf28e9e47dVladimir Chtchetkine res = iolooper_wait_absolute(_ads_io_looper(ads), ads->deadline); 62210bc04fd968d7f80258bf1eec665babf28e9e47dVladimir Chtchetkine if (res > 0) { 62310bc04fd968d7f80258bf1eec665babf28e9e47dVladimir Chtchetkine /* Ready to read. */ 624db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine continue; 625db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 626db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 62710bc04fd968d7f80258bf1eec665babf28e9e47dVladimir Chtchetkine recvd = -1; 62810bc04fd968d7f80258bf1eec665babf28e9e47dVladimir Chtchetkine break; 62910bc04fd968d7f80258bf1eec665babf28e9e47dVladimir Chtchetkine } 63010bc04fd968d7f80258bf1eec665babf28e9e47dVladimir Chtchetkine recvd += res; 63110bc04fd968d7f80258bf1eec665babf28e9e47dVladimir Chtchetkine } while (recvd < bufsize); 63210bc04fd968d7f80258bf1eec665babf28e9e47dVladimir Chtchetkine iolooper_del_read(_ads_io_looper(ads), ads->fd); 633db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 634db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* In case of an I/O failure we have to invoke failure callback. Note that we 635db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * report I/O failures only on registered sockets. */ 636db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (recvd < 0) { 637db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine D("I/O error while receiving from channel '%s'@%d: %s", 638db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _ads_id_str(ads), _ads_port(ads), strerror(errno)); 639db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 640db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (ads->ad->on_io_failure != NULL && ads->socket_status > ADS_CONNECTED) { 641db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine const char save_error = errno; 642db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ads->ad->on_io_failure(ads->opaque, ads->ad, save_error); 643db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine errno = save_error; 644db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 645db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 646db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 647db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return recvd; 648db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 649db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 650db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic int 651db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine_android_dev_socket_read_string(AndroidDevSocket* ads, char* str, int strsize) 652db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 653db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int n; 654db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 655db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Char by char read from the socket, until zero-terminator is read. */ 656db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine for (n = 0; n < strsize; n++) { 657db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (_android_dev_socket_recv(ads, str + n, 1) > 0) { 658db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (str[n] == '\0') { 659db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Done. */ 660db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return n + 1; /* Including zero-terminator. */ 661db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 662db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } else { 663db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* I/O error. */ 664db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return -1; 665db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 666db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 667db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 668db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Buffer was too small. Report that by setting errno to ENOMEM. */ 669db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine D("Buffer %d is too small to receive a string from channel '%s'@%d", 670db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine strsize, _ads_id_str(ads), _ads_port(ads)); 671db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine errno = ENOMEM; 672db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return -1; 673db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 674db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 675db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic int 676db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine_android_dev_socket_read_response(AndroidDevSocket* ads, char* data, int datasize) 677db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 678db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int n, res; 679db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int success = 0; 680db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int failure = 0; 681db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int bad_format = 0; 682db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine char ok[4]; 683db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 684db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine *data = '\0'; 685db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 686db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Char by char read from the socket, until ok/ko is read. */ 687db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine for (n = 0; n < 2; n++) { 688db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine res = _android_dev_socket_recv(ads, ok + n, 1); 689db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (res > 0) { 690db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (ok[n] == '\0') { 691db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* EOS is unexpected here! */ 692db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine D("Bad query reply format on channel '%s'@%d: '%s' is too short.", 693db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _ads_id_str(ads), _ads_port(ads), ok); 694db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine errno = EINVAL; 695db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return -1; 696db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 697db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } else { 698db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* I/O error. */ 699db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return -1; 700db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 701db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 702db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 703db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Next character must be either ':', or '\0' */ 704db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine res = _android_dev_socket_recv(ads, ok + n, 1); 705db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (res <= 0) { 706db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* I/O error. */ 707db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return -1; 708db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 709db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 710db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* 711db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Verify format. 712db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine */ 713db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 714db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Check ok / ko */ 715db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine success = memcmp(ok, "ok", 2) == 0; 716db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine failure = memcmp(ok, "ko", 2) == 0; 717db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 718db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Check the prefix: 'ok'|'ko' & ':'|'\0' */ 719db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if ((success || failure) && (ok[n] == '\0' || ok[n] == ':')) { 720db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Format is good. */ 721db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (ok[n] == '\0') { 722db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* We're done: no extra data in response. */ 723db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine errno = 0; 724db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return success ? 0 : -1; 725db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 726db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Reset buffer offset, so we will start to read the remaining query 727db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * data to the beginning of the supplied buffer. */ 728db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine n = 0; 729db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } else { 730db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Bad format. Lets move what we've read to the main buffer, and 731db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * continue filling it in. */ 732db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine bad_format = 1; 733db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine n++; 734db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine memcpy(data, ok, n); 735db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 736db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 737db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Read the remainder of reply to the supplied data buffer. */ 738db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine res = _android_dev_socket_read_string(ads, data + n, datasize - n); 739db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (res < 0) { 740db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return res; 741db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 742db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 743db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Lets see if format was bad */ 744db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (bad_format) { 745db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine D("Bad query reply format on channel '%s'@%d: %s.", 746db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _ads_id_str(ads), _ads_port(ads), data); 747db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine errno = EINVAL; 748db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return -1; 749db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } else { 750db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine errno = 0; 751db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return success ? n : -1; 752db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 753db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 754db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 755db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/******************************************************************************** 756db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Query socket declarations 757db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine *******************************************************************************/ 758db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 759db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Initializes query socket descriptor. 760db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Param: 761db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * adsquery - Socket descriptor to initialize. 762db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * opaque - An opaque pointer to associate with the socket. Typicaly it's the 763db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * same pointer that is associated with AndroidDevice instance. 764db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * ad - Android device descriptor that owns the socket. 765db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * port - TCP socket port. 766db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine */ 767db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic int _android_query_socket_init(AndroidQuerySocket* adsquery, 768db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine void* opaque, 769db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine AndroidDevice* ad, 770db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int port); 771db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 772db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Destroys query socket descriptor. */ 773db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic void _android_query_socket_destroy(AndroidQuerySocket* adsquery); 774db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 775db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Synchronously connects the query socket, and registers it with the server. 776db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Param: 777db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * adsquery - Descriptor for the query socket to connect. Must have 'deadline' 778db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * field properly setup. 779db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * cb - Callback to invoke when socket connection is completed. Can be NULL. 780db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Return: 781db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Zero on success, or non-zero on failure. 782db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine */ 783db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic int _android_query_socket_connect(AndroidQuerySocket* adsquery); 784db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 785db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Disconnects the query socket. */ 786db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic void _android_query_socket_disconnect(AndroidQuerySocket* adsquery); 787db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 788db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/******************************************************************************** 789db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Query socket implementation 790db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine *******************************************************************************/ 791db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 792db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic int 793db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine_android_query_socket_init(AndroidQuerySocket* adsquery, 794db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine void* opaque, 795db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine AndroidDevice* ad, 796db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int port) 797db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 798db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return _android_dev_socket_init(&adsquery->dev_socket, opaque, ad, port, 799db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ADS_TYPE_QUERY); 800db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 801db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 802db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic void 803db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine_android_query_socket_destroy(AndroidQuerySocket* adsquery) 804db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 805db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _android_query_socket_disconnect(adsquery); 806db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _android_dev_socket_destroy(&adsquery->dev_socket); 807db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 808db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 809db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic int 810db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine_android_query_socket_connect(AndroidQuerySocket* adsquery) 811db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 812417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine return _android_dev_socket_connect(&adsquery->dev_socket, NULL, NULL); 813db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 814db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 815db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic void 816db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine_android_query_socket_disconnect(AndroidQuerySocket* adsquery) 817db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 818db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _android_dev_socket_disconnect(&adsquery->dev_socket); 819db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 820db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 821db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/******************************************************************************** 822db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Events socket declarations 823db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine *******************************************************************************/ 824db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 825db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Initializes event socket descriptor. 826db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Param: 827db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * adsevent - Socket descriptor to initialize. 828db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * opaque - An opaque pointer to associate with the socket. Typicaly it's the 829db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * same pointer that is associated with AndroidDevice instance. 830db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * ad - Android device descriptor that owns the socket. 831db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * port - TCP socket port. 832db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine */ 833db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic int _android_event_socket_init(AndroidEventSocket* adsevent, 834db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine void* opaque, 835db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine AndroidDevice* ad, 836db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int port); 837db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 838db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Destroys the event socket descriptor. */ 839db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic void _android_event_socket_destroy(AndroidEventSocket* adsevent); 840db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 841db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Synchronously connects event socket. 842db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Param: 843db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * adsevent - Descriptor for the event socket to connect. Must have 'deadline' 844db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * field properly setup. 845db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Return: 846db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Zero on success, or non-zero on failure. 847db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine */ 848db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic int _android_event_socket_connect_sync(AndroidEventSocket* adsevent); 849db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 850db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Initiates asynchronous event socket connection. 851db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Param: 852db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * adsevent - Descriptor for the event socket to connect. Must have 'deadline' 853db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * field properly setup. 854db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * cb - Callback to invoke when socket connection is completed. Can be NULL. 855db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Return: 856db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Zero on success, or non-zero on failure. 857db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine */ 858db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic int _android_event_socket_connect_async(AndroidEventSocket* adsevent, 859db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ads_socket_connected_cb cb); 860db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 861db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Disconnects the event socket. */ 862db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic void _android_event_socket_disconnect(AndroidEventSocket* adsevent); 863db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 864db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Initiates listening on the event socket. 865db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Param: 866db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * adsevent - Descriptor for the event socket to listen on. 867db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * str, strsize - Buffer where to read the string. 868db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * cb - A callback to call when the event string is read. Can be NULL. 869db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Return: 870db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Zero on success, or non-zero on failure. 871db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine */ 872db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic int _android_event_socket_listen(AndroidEventSocket* adsevent, 873db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine char* str, 874db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int strsize, 875db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine event_cb cb); 876db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 87734f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine/* Asynchronously sends data via event socket. 87834f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine * Param: 87934f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine * adsevent - Descriptor for the event socket to send data to. 88034f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine * data, size - Buffer containing data to send. 88134f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine * free_on_close - A boolean flag indicating whether the data buffer should be 88234f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine * freed upon data transfer completion. 88334f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine * cb - Callback to invoke when data transfer is completed. 88434f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine * opaque - An opaque pointer to pass to the transfer completion callback. 88534f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine */ 88634f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkinestatic int _android_event_socket_send(AndroidEventSocket* adsevent, 88734f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine void* data, 88834f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine int size, 88934f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine int free_on_close, 89034f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine async_send_cb cb, 89134f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine void* opaque); 89234f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine 89334f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine/* Cancels all asynchronous data transfers on the event socket. 89434f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine * Param: 89534f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine * adsevent - Descriptor for the event socket to cancel data transfer. 89634f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine * reason - Reason for the cancellation. 89734f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine */ 89834f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkinestatic void _android_event_socket_cancel_send(AndroidEventSocket* adsevent, 89934f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine ATResult reason); 90034f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine 901db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Event socket's asynchronous I/O looper callback. 902db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Param: 903db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * opaque - AndroidEventSocket instance. 904db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * fd - Socket's FD. 905db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * events - I/O type bitsmask (read | write). 906db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine */ 907db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic void _on_event_socket_io(void* opaque, int fd, unsigned events); 908db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 909db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Callback that is invoked when asynchronous event socket connection is 910db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * completed. */ 911db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic void _on_event_socket_connected(AndroidEventSocket* adsevent, int failure); 912db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 913db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Callback that is invoked when an event is received from the device. */ 914db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic void _on_event_received(AndroidEventSocket* adsevent); 915db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 916db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Gets I/O looper for asynchronous I/O on event socket. */ 917db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir ChtchetkineAINLINED Looper* 918db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine_aes_looper(AndroidEventSocket* adsevent) 919db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 920db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return adsevent->dev_socket.ad->looper; 921db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 922db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 923db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/******************************************************************************** 924db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Events socket implementation 925db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine *******************************************************************************/ 926db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 927db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic int 928db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine_android_event_socket_init(AndroidEventSocket* adsevent, 929db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine void* opaque, 930db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine AndroidDevice* ad, 931db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int port) 932db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 933db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return _android_dev_socket_init(&adsevent->dev_socket, opaque, ad, port, 934db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ADS_TYPE_EVENT); 935db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 936db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 937db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic void 938db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine_android_event_socket_destroy(AndroidEventSocket* adsevent) 939db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 940db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _android_event_socket_disconnect(adsevent); 941db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _android_dev_socket_destroy(&adsevent->dev_socket); 942db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 943db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 944417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine/* A callback invoked when file descriptor is created for the event socket. 945417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine * We use this callback to initialize the event socket for async I/O right after 946417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine * the FD has been created. 947417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine */ 948417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkinestatic void 949417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine_on_event_fd_created(AndroidDevSocket* ads, void* opaque) 950417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine{ 951417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine AndroidEventSocket* adsevent = (AndroidEventSocket*)opaque; 952417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine /* Prepare for async I/O on the event socket. */ 953417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine loopIo_init(adsevent->io, _aes_looper(adsevent), ads->fd, 954417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine _on_event_socket_io, adsevent); 955417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine} 956db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 957db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic int 958db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine_android_event_socket_connect_sync(AndroidEventSocket* adsevent) 959db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 960417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine return _android_dev_socket_connect(&adsevent->dev_socket, 961417c67d3c58c82d000b103070abf241c9de414b6Vladimir Chtchetkine _on_event_fd_created, adsevent); 962db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 963db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 964db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic int 965db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine_android_event_socket_connect_async(AndroidEventSocket* adsevent, 966db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ads_socket_connected_cb cb) 967db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 968db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine AsyncStatus status; 969db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine AndroidDevSocket* ads = &adsevent->dev_socket; 970db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 971db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Create asynchronous socket. */ 972db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ads->fd = socket_create_inet(SOCKET_STREAM); 973db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (ads->fd < 0) { 974db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine D("Unable to create socket for channel '%s'@%d: %s", 975db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _ads_id_str(ads), _ads_port(ads), strerror(errno)); 976db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (cb != NULL) { 977db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine cb(ads->opaque, ads, errno); 978db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 979db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return -1; 980db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 981db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine socket_set_nonblock(ads->fd); 982db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 983db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Prepare for async I/O on the event socket. */ 984db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine loopIo_init(adsevent->io, _aes_looper(adsevent), ads->fd, 985db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _on_event_socket_io, adsevent); 986db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 987db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Try to connect. */ 988db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ads->socket_status = ADS_CONNECTING; 989db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine adsevent->on_connected = cb; 990db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine status = asyncConnector_init(adsevent->connector, &ads->address, adsevent->io); 991db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine switch (status) { 992db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine case ASYNC_COMPLETE: 993db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* We're connected to the device socket. */ 994db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ads->socket_status = ADS_CONNECTED; 995db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _on_event_socket_connected(adsevent, 0); 996db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine break; 997db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine case ASYNC_ERROR: 998db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _on_event_socket_connected(adsevent, errno); 999db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine break; 1000db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine case ASYNC_NEED_MORE: 1001db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Attempt to connect would block, so connection competion is 1002db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * delegates to the looper's I/O routine. */ 1003db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine default: 1004db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine break; 1005db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1006db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1007db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return 0; 1008db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 1009db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1010db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic void 1011db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine_android_event_socket_disconnect(AndroidEventSocket* adsevent) 1012db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 1013db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine AndroidDevSocket* ads = &adsevent->dev_socket; 1014db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1015db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (ads->socket_status != ADS_DISCONNECTED) { 101634f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine /* Cancel data transfer. */ 101734f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine _android_event_socket_cancel_send(adsevent, ATR_DISCONNECT); 101834f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine 1019db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Stop all async I/O. */ 1020db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine loopIo_done(adsevent->io); 1021db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1022db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Disconnect common socket. */ 1023db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _android_dev_socket_disconnect(ads); 1024db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1025db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 1026db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1027db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic int 1028db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine_android_event_socket_listen(AndroidEventSocket* adsevent, 1029db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine char* str, 1030db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int strsize, 1031db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine event_cb cb) 1032db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 1033db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine AsyncStatus status; 1034db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine AndroidDevSocket* ads = &adsevent->dev_socket; 1035db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1036db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Make sure that device is connected. */ 1037db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (ads->socket_status < ADS_CONNECTED) { 1038db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine D("Attempt to listen on a disconnected channel '%s'@%d", 1039db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _ads_id_str(ads), _ads_port(ads)); 1040db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine errno = ECONNRESET; 1041db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return -1; 1042db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1043db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1044db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* NOTE: only one reader at any given time! */ 1045db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine adsevent->on_event = cb; 1046db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine asyncLineReader_init(&adsevent->alr, str, strsize, adsevent->io); 1047db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Default EOL for the line reader was '\n'. */ 1048db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine asyncLineReader_setEOL(&adsevent->alr, '\0'); 1049db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine status = asyncLineReader_read(&adsevent->alr); 1050db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (status == ASYNC_COMPLETE) { 1051db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Data has been transferred immediately. Do the callback here. */ 1052db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _on_event_received(adsevent); 1053db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } else if (status == ASYNC_ERROR) { 1054db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine D("Error while listening on channel '%s'@%d: %s", 1055db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _ads_id_str(ads), _ads_port(ads), strerror(errno)); 1056db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* There is one special failure here, when buffer was too small to 1057db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * contain the entire string. This is not an I/O, but rather a 1058db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * protocol error. So we don't report it to the I/O failure 1059db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * callback. */ 1060db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (errno == ENOMEM) { 1061db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _on_event_received(adsevent); 1062db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } else { 1063db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (ads->ad->on_io_failure != NULL) { 1064db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ads->ad->on_io_failure(ads->ad->opaque, ads->ad, errno); 1065db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1066db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1067db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return -1; 1068db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1069db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return 0; 1070db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 1071db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 107234f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkinestatic int 107334f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine_android_event_socket_send(AndroidEventSocket* adsevent, 107434f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine void* data, 107534f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine int size, 107634f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine int free_on_close, 107734f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine async_send_cb cb, 107834f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine void* opaque) 107934f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine{ 108034f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine /* Create data transfer descriptor, and place it at the end of the list. */ 108134f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine AsyncSendBuffer* const desc = 108234f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine _async_send_buffer_create(data, size, free_on_close, cb, opaque); 108334f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine AsyncSendBuffer** place = &adsevent->send_pending; 108434f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine while (*place != NULL) { 108534f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine place = &((*place)->next); 108634f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine } 108734f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine *place = desc; 108834f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine 108934f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine /* We're ready to transfer data. */ 109034f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine loopIo_wantWrite(adsevent->io); 109134f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine 109234f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine return 0; 109334f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine} 109434f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine 109534f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkinestatic void 109634f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine_android_event_socket_cancel_send(AndroidEventSocket* adsevent, ATResult reason) 109734f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine{ 109834f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine while (adsevent->send_pending != NULL) { 109934f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine AsyncSendBuffer* const to_cancel = adsevent->send_pending; 110034f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine adsevent->send_pending = to_cancel->next; 110134f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine _async_send_buffer_complete(to_cancel, reason); 110234f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine } 110334f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine loopIo_dontWantWrite(adsevent->io); 110434f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine} 110534f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine 1106db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic void 1107db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine_on_event_socket_io(void* opaque, int fd, unsigned events) 1108db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 1109db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine AsyncStatus status; 1110db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine AndroidEventSocket* adsevent = (AndroidEventSocket*)opaque; 1111db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine AndroidDevSocket* ads = &adsevent->dev_socket; 1112db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1113db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Lets see if we're still wating on a connection to occur. */ 1114db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (ads->socket_status == ADS_CONNECTING) { 1115db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Complete socket connection. */ 1116db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine status = asyncConnector_run(adsevent->connector); 1117db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (status == ASYNC_COMPLETE) { 1118db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* We're connected to the device socket. */ 1119db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ads->socket_status = ADS_CONNECTED; 1120db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine D("Channel '%s'@%d is connected asynchronously", 1121db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _ads_id_str(ads), _ads_port(ads)); 1122db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _on_event_socket_connected(adsevent, 0); 1123db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } else if (status == ASYNC_ERROR) { 1124db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _on_event_socket_connected(adsevent, adsevent->connector->error); 1125db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1126db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return; 1127db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1128db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1129db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* 113034f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine * Device is connected. Continue with the data transfer. 1131db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine */ 1132db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1133db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if ((events & LOOP_IO_READ) != 0) { 1134db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Continue reading data. */ 1135db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine status = asyncLineReader_read(&adsevent->alr); 1136db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (status == ASYNC_COMPLETE) { 11378dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine errno = 0; 1138db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _on_event_received(adsevent); 1139db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } else if (status == ASYNC_ERROR) { 1140db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine D("I/O failure while reading from channel '%s'@%d: %s", 1141db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _ads_id_str(ads), _ads_port(ads), strerror(errno)); 1142db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* There is one special failure here, when buffer was too small to 1143db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * contain the entire string. This is not an I/O, but rather a 1144db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * protocol error. So we don't report it to the I/O failure 1145db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * callback. */ 1146db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (errno == ENOMEM) { 1147db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _on_event_received(adsevent); 1148db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } else { 1149db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (ads->ad->on_io_failure != NULL) { 1150db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ads->ad->on_io_failure(ads->ad->opaque, ads->ad, errno); 1151db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1152db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1153db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1154db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 115534f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine 115634f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine if ((events & LOOP_IO_WRITE) != 0) { 115734f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine while (adsevent->send_pending != NULL) { 115834f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine AsyncSendBuffer* to_send = adsevent->send_pending; 115934f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine const int offset = to_send->data_size - to_send->data_remaining; 116034f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine const int sent = socket_send(ads->fd, to_send->data + offset, 116134f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine to_send->data_remaining); 116234f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine if (sent < 0) { 116334f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine if (errno == EWOULDBLOCK) { 116434f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine /* Try again later. */ 116534f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine return; 116634f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine } else { 116734f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine /* An error has occured. */ 116834f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine _android_event_socket_cancel_send(adsevent, ATR_IO_ERROR); 116934f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine if (ads->ad->on_io_failure != NULL) { 117034f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine ads->ad->on_io_failure(ads->ad->opaque, ads->ad, errno); 117134f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine } 117234f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine return; 117334f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine } 117434f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine } else if (sent == 0) { 117534f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine /* Disconnect condition. */ 117634f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine _android_event_socket_cancel_send(adsevent, ATR_DISCONNECT); 117734f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine if (ads->ad->on_io_failure != NULL) { 117834f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine ads->ad->on_io_failure(ads->ad->opaque, ads->ad, errno); 117934f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine } 118034f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine return; 118134f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine } else if (sent == to_send->data_remaining) { 118234f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine /* All data is sent. */ 11838dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine errno = 0; 118434f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine adsevent->send_pending = to_send->next; 118534f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine _async_send_buffer_complete(to_send, ATR_SUCCESS); 118634f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine } else { 118734f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine /* Chunk is sent. */ 118834f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine to_send->data_remaining -= sent; 118934f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine return; 119034f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine } 119134f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine } 119234f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine loopIo_dontWantWrite(adsevent->io); 119334f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine } 1194db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 1195db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1196db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic void 1197db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine_on_event_socket_connected(AndroidEventSocket* adsevent, int failure) 1198db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 1199db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int res; 1200db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine AndroidDevSocket* ads = &adsevent->dev_socket; 1201db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1202db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (failure) { 1203db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _android_event_socket_disconnect(adsevent); 1204db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (adsevent->on_connected != NULL) { 1205db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine adsevent->on_connected(ads->opaque, ads, failure); 1206db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1207db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return; 1208db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1209db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1210db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Complete event socket connection by identifying it as "event" socket with 1211db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * the application. */ 121246ff3eaff40952df50ee14056cae88a3e7396a81Vladimir Chtchetkine ads->socket_status = ADS_CONNECTED; 1213db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine res = _android_dev_socket_register(ads); 12148dd31e8e10fc3ca10192368acf19d2345eeddde7Vladimir Chtchetkine 1215db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (res) { 1216db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine const int save_error = errno; 1217db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _android_event_socket_disconnect(adsevent); 1218db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine errno = save_error; 1219db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1220db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1221db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Notify callback about connection completion. */ 1222db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (adsevent->on_connected != NULL) { 1223db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (res) { 1224db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine adsevent->on_connected(ads->opaque, ads, errno); 1225db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } else { 1226db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine adsevent->on_connected(ads->opaque, ads, 0); 1227db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1228db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1229db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 1230db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1231db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic void 1232db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine_on_event_received(AndroidEventSocket* adsevent) 1233db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 1234db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (adsevent->on_event != NULL) { 1235db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine AndroidDevice* ad = adsevent->dev_socket.ad; 1236db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine adsevent->on_event(ad->opaque, ad, (char*)adsevent->alr.buffer, 1237db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine adsevent->alr.pos); 1238db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1239db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 1240db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1241db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/******************************************************************************** 1242db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Android device connection 1243db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine *******************************************************************************/ 1244db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1245db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Callback that is invoked when event socket is connected and registered as part 1246db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * of the _android_device_connect_async API. 1247db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Param: 1248db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * opaque - Opaque pointer associated with AndroidDevice instance. 1249db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * ads - Common socket descriptor for the event socket. 1250db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * failure - If zero connection has succeeded, otherwise contains 'errno'-reason 1251db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * for connection failure. 1252db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine */ 1253db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic void 1254db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine_on_android_device_connected_async(void* opaque, 1255db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine AndroidDevSocket* ads, 1256db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int failure) 1257db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 1258db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int res; 1259db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine AndroidDevice* ad = ads->ad; 1260db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1261db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (failure) { 1262db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Depending on the failure code we will either retry, or bail out. */ 1263db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine switch (failure) { 1264db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine case EPIPE: 1265db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine case EAGAIN: 1266db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine case EINPROGRESS: 1267db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine case EALREADY: 1268db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine case EHOSTUNREACH: 1269db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine case EHOSTDOWN: 1270db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine case ECONNREFUSED: 1271db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine case ESHUTDOWN: 1272db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine case ENOTCONN: 1273db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine case ECONNRESET: 1274db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine case ECONNABORTED: 1275db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine case ENETRESET: 1276db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine case ENETUNREACH: 1277db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine case ENETDOWN: 1278db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine case EBUSY: 1279e857adfa4de0c143f3327d1e2b2dde827891064fVladimir Chtchetkine#if !defined(_DARWIN_C_SOURCE) && !defined(_WIN32) 1280db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine case ERESTART: 1281db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine case ECOMM: 1282db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine case ENONET: 1283e857adfa4de0c143f3327d1e2b2dde827891064fVladimir Chtchetkine#endif /* !_DARWIN_C_SOURCE && !_WIN32 */ 1284db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Device is not available / reachable at the moment. 1285db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Retry connection later. */ 1286db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine loopTimer_startRelative(ad->timer, ADS_RETRY_CONNECTION_TIMEOUT); 1287db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return; 1288db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine default: 1289db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine D("Failed to asynchronously connect channel '%s':%d %s", 1290db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _ads_id_str(ads), _ads_port(ads), strerror(errno)); 1291db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (ad->on_connected != NULL) { 1292db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ad->on_connected(ad->opaque, ad, failure); 1293db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1294db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine break; 1295db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1296db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return; 1297db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1298db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1299db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Event socket is connected. Connect the query socket now. Give it 5 1300db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * seconds to connect. */ 1301db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _ads_set_deadline(&ad->query_socket.dev_socket, 5000); 1302db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine res = _android_query_socket_connect(&ad->query_socket); 1303db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (res == 0) { 1304db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Query socket is connected. */ 1305db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (ad->on_connected != NULL) { 1306db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ad->on_connected(ad->opaque, ad, 0); 1307db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1308db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } else { 1309db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* If connection completion has failed - disconnect the sockets. */ 1310db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _android_event_socket_disconnect(&ad->event_socket); 1311db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _android_query_socket_disconnect(&ad->query_socket); 1312db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1313db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (ad->on_connected != NULL) { 1314db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ad->on_connected(ad->opaque, ad, errno); 1315db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1316db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1317db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 1318db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1319db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic void 1320db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine_on_timer(void* opaque) 1321db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 1322db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Retry the connection. */ 1323db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine AndroidDevice* ad = (AndroidDevice*)opaque; 1324db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine android_device_connect_async(ad, ad->on_connected); 1325db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 1326db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1327db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/* Destroys and frees the descriptor. */ 1328db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinestatic void 1329db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine_android_device_free(AndroidDevice* ad) 1330db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 1331db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (ad != NULL) { 1332db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _android_event_socket_destroy(&ad->event_socket); 1333db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _android_query_socket_destroy(&ad->query_socket); 1334db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1335db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Delete asynchronous I/O looper. */ 1336db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (ad->looper != NULL ) { 1337db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine loopTimer_done(ad->timer); 1338db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine looper_free(ad->looper); 1339db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1340db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1341db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Delete synchronous I/O looper. */ 1342db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (ad->io_looper != NULL) { 1343db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine iolooper_reset(ad->io_looper); 1344db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine iolooper_free(ad->io_looper); 1345db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1346db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1347db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine AFREE(ad); 1348db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1349db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 1350db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1351db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine/******************************************************************************** 1352db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * Android device API 1353db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine *******************************************************************************/ 1354db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1355db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir ChtchetkineAndroidDevice* 1356db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkineandroid_device_init(void* opaque, int port, io_failure_cb on_io_failure) 1357db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 1358db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int res; 1359db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine AndroidDevice* ad; 1360db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1361db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ANEW0(ad); 1362db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1363db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ad->opaque = opaque; 1364db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ad->on_io_failure = on_io_failure; 1365db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1366db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Create I/O looper for synchronous I/O on the device. */ 1367db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ad->io_looper = iolooper_new(); 1368db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (ad->io_looper == NULL) { 1369db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine E("Unable to create synchronous I/O looper for android device."); 1370db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _android_device_free(ad); 1371db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return NULL; 1372db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1373db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1374db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Create a looper for asynchronous I/O on the device. */ 1375db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ad->looper = looper_newCore(); 1376db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (ad->looper != NULL) { 1377db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Create a timer that will be used for connection retries. */ 1378db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine loopTimer_init(ad->timer, ad->looper, _on_timer, ad); 1379db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } else { 1380db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine E("Unable to create asynchronous I/O looper for android device."); 1381db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _android_device_free(ad); 1382db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return NULL; 1383db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1384db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1385db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Init query socket. */ 1386db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine res = _android_query_socket_init(&ad->query_socket, opaque, ad, port); 1387db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (res) { 1388db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _android_device_free(ad); 1389db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return NULL; 1390db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1391db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1392db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Init event socket. */ 1393db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine res = _android_event_socket_init(&ad->event_socket, opaque, ad, port); 1394db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (res) { 1395db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _android_device_free(ad); 1396db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return NULL; 1397db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1398db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1399db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return ad; 1400db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 1401db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1402db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinevoid 1403db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkineandroid_device_destroy(AndroidDevice* ad) 1404db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 1405db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (ad != NULL) { 1406db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _android_device_free(ad); 1407db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1408db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 1409db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1410db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkineint 1411db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkineandroid_device_connect_sync(AndroidDevice* ad, int to) 1412db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 1413db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int res; 1414db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1415db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Setup deadline for the connections. */ 1416db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _ads_set_deadline(&ad->query_socket.dev_socket, to); 1417db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ad->event_socket.dev_socket.deadline = ad->query_socket.dev_socket.deadline; 1418db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1419db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Connect the query socket first. */ 1420db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine res = _android_query_socket_connect(&ad->query_socket); 1421db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (!res) { 1422db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Connect to the event socket next. */ 1423db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine res = _android_event_socket_connect_sync(&ad->event_socket); 1424db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1425db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1426db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return res; 1427db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 1428db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1429db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkineint 1430db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkineandroid_device_connect_async(AndroidDevice* ad, device_connected_cb on_connected) 1431db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 1432db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* No deadline for async connections. */ 1433db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ad->query_socket.dev_socket.deadline = DURATION_INFINITE; 1434db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ad->event_socket.dev_socket.deadline = DURATION_INFINITE; 1435db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1436db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Connect to the event socket first, and delegate query socket connection 1437db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * into callback invoked when event socket is connected. NOTE: In case of 1438db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * failure 'on_connected' callback has already been called from 1439db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine * _on_android_device_connected_async routine. */ 1440db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine ad->on_connected = on_connected; 1441db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return _android_event_socket_connect_async(&ad->event_socket, 1442db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _on_android_device_connected_async); 1443db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 1444db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1445db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkinevoid 1446db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkineandroid_device_disconnect(AndroidDevice* ad) 1447db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 1448db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _android_event_socket_disconnect(&ad->event_socket); 1449db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _android_query_socket_disconnect(&ad->query_socket); 1450db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 1451db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1452db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkineint 1453db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkineandroid_device_query(AndroidDevice* ad, 1454db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine const char* query, 1455db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine char* buff, 1456db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine size_t buffsize, 1457db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int to) 1458db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 1459db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int res; 1460db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1461db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Setup deadline for the query. */ 1462db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine _ads_set_deadline(&ad->query_socket.dev_socket, to); 1463db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1464db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Send the query. */ 1465db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine res = _android_dev_socket_send(&ad->query_socket.dev_socket, query, 1466db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine strlen(query) + 1); 1467db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine if (res > 0) { 1468db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine /* Receive the response. */ 1469db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine res = _android_dev_socket_read_response(&ad->query_socket.dev_socket, 1470db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine buff, buffsize); 1471db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return (res >= 0) ? 0 : -1; 1472db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine } 1473db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1474db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return -1; 1475db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 1476db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine 1477db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkineint 1478720d4ae010c7b2dac83ac61b96a9bf7e6f02f440Vladimir Chtchetkineandroid_device_start_query(AndroidDevice* ad, const char* query, int to) 1479720d4ae010c7b2dac83ac61b96a9bf7e6f02f440Vladimir Chtchetkine{ 1480720d4ae010c7b2dac83ac61b96a9bf7e6f02f440Vladimir Chtchetkine int res; 1481720d4ae010c7b2dac83ac61b96a9bf7e6f02f440Vladimir Chtchetkine 1482720d4ae010c7b2dac83ac61b96a9bf7e6f02f440Vladimir Chtchetkine /* Setup deadline for the query. */ 1483720d4ae010c7b2dac83ac61b96a9bf7e6f02f440Vladimir Chtchetkine _ads_set_deadline(&ad->query_socket.dev_socket, to); 1484720d4ae010c7b2dac83ac61b96a9bf7e6f02f440Vladimir Chtchetkine 1485720d4ae010c7b2dac83ac61b96a9bf7e6f02f440Vladimir Chtchetkine /* Send the query header. */ 1486720d4ae010c7b2dac83ac61b96a9bf7e6f02f440Vladimir Chtchetkine res = _android_dev_socket_send(&ad->query_socket.dev_socket, query, 1487720d4ae010c7b2dac83ac61b96a9bf7e6f02f440Vladimir Chtchetkine strlen(query) + 1); 1488720d4ae010c7b2dac83ac61b96a9bf7e6f02f440Vladimir Chtchetkine return (res > 0) ? 0 : -1; 1489720d4ae010c7b2dac83ac61b96a9bf7e6f02f440Vladimir Chtchetkine} 1490720d4ae010c7b2dac83ac61b96a9bf7e6f02f440Vladimir Chtchetkine 1491720d4ae010c7b2dac83ac61b96a9bf7e6f02f440Vladimir Chtchetkineint 1492720d4ae010c7b2dac83ac61b96a9bf7e6f02f440Vladimir Chtchetkineandroid_device_send_query_data(AndroidDevice* ad, const void* data, int size) 1493720d4ae010c7b2dac83ac61b96a9bf7e6f02f440Vladimir Chtchetkine{ 1494720d4ae010c7b2dac83ac61b96a9bf7e6f02f440Vladimir Chtchetkine return _android_dev_socket_send(&ad->query_socket.dev_socket, data, size); 1495720d4ae010c7b2dac83ac61b96a9bf7e6f02f440Vladimir Chtchetkine} 1496720d4ae010c7b2dac83ac61b96a9bf7e6f02f440Vladimir Chtchetkine 1497720d4ae010c7b2dac83ac61b96a9bf7e6f02f440Vladimir Chtchetkineint 1498720d4ae010c7b2dac83ac61b96a9bf7e6f02f440Vladimir Chtchetkineandroid_device_complete_query(AndroidDevice* ad, char* buff, size_t buffsize) 1499720d4ae010c7b2dac83ac61b96a9bf7e6f02f440Vladimir Chtchetkine{ 1500720d4ae010c7b2dac83ac61b96a9bf7e6f02f440Vladimir Chtchetkine /* Receive the response to the query. */ 1501720d4ae010c7b2dac83ac61b96a9bf7e6f02f440Vladimir Chtchetkine const int res = _android_dev_socket_read_response(&ad->query_socket.dev_socket, 1502720d4ae010c7b2dac83ac61b96a9bf7e6f02f440Vladimir Chtchetkine buff, buffsize); 1503720d4ae010c7b2dac83ac61b96a9bf7e6f02f440Vladimir Chtchetkine return (res >= 0) ? 0 : -1; 1504720d4ae010c7b2dac83ac61b96a9bf7e6f02f440Vladimir Chtchetkine} 1505720d4ae010c7b2dac83ac61b96a9bf7e6f02f440Vladimir Chtchetkine 1506720d4ae010c7b2dac83ac61b96a9bf7e6f02f440Vladimir Chtchetkineint 1507db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkineandroid_device_listen(AndroidDevice* ad, 1508db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine char* buff, 1509db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine int buffsize, 1510db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine event_cb on_event) 1511db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine{ 1512db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine return _android_event_socket_listen(&ad->event_socket, buff, buffsize, 1513db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine on_event); 1514db611d57e0da9acd7ecf2a4a9b2a63e7620fe54dVladimir Chtchetkine} 151534f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine 151634f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkineint 151734f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkineandroid_device_send_async(AndroidDevice* ad, 151834f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine void* data, 151934f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine int size, 152034f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine int free_on_close, 152134f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine async_send_cb cb, 152234f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine void* opaque) 152334f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine{ 152434f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine return _android_event_socket_send(&ad->event_socket, data, size, 152534f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine free_on_close, cb, opaque); 152634f234393256163101b05c41ee4676bc68b57c65Vladimir Chtchetkine} 1527