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