1c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* 2c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Copyright (C) 2012 The Android Open Source Project 3c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * 4c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Licensed under the Apache License, Version 2.0 (the "License"); 5c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * you may not use this file except in compliance with the License. 6c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * You may obtain a copy of the License at 7c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * 8c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * http://www.apache.org/licenses/LICENSE-2.0 9c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * 10c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Unless required by applicable law or agreed to in writing, software 11c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * distributed under the License is distributed on an "AS IS" BASIS, 12c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * See the License for the specific language governing permissions and 14c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * limitations under the License. 15c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 16c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 17c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* 18c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Encapsulates exchange protocol between the emulator, and an Android device 19c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * that is connected to the host via USB. The communication is established over 20c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * a TCP port forwarding, enabled by ADB. 21c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 22c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 23c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#include "qemu-common.h" 24c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#include "android/async-utils.h" 25c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#include "android/utils/debug.h" 26c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#include "android/async-socket-connector.h" 27c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#include "android/async-socket.h" 28c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#include "android/sdk-controller-socket.h" 29c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#include "utils/panic.h" 30c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#include "iolooper.h" 31c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 32c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#define E(...) derror(__VA_ARGS__) 33c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#define W(...) dwarning(__VA_ARGS__) 34c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#define D(...) VERBOSE_PRINT(sdkctlsocket,__VA_ARGS__) 35c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#define D_ACTIVE VERBOSE_CHECK(sdkctlsocket) 36c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 37c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#define TRACE_ON 1 38c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 39c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#if TRACE_ON 40c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#define T(...) VERBOSE_PRINT(sdkctlsocket,__VA_ARGS__) 41c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#else 42c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#define T(...) 43c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#endif 44c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 45c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Recycling memory descriptor. */ 46c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinetypedef struct SDKCtlRecycled SDKCtlRecycled; 47c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestruct SDKCtlRecycled { 48c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine union { 49c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Next recycled descriptor (while listed in recycler). */ 50c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlRecycled* next; 51c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Allocated memory size (while outside of the recycler). */ 52c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine uint32_t size; 53c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine }; 54c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine}; 55c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 56c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/******************************************************************************** 57c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * SDKCtlPacket declarations 58c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *******************************************************************************/ 59c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 60c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* 61c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Types of the packets of data sent via SDK controller socket. 62c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 63c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 64c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* The packet is a message. */ 65c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#define SDKCTL_PACKET_MESSAGE 1 66c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* The packet is a query. */ 67c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#define SDKCTL_PACKET_QUERY 2 68c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* The packet is a response to a query. */ 69c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#define SDKCTL_PACKET_QUERY_RESPONSE 3 70c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 71c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Data packet descriptor. 72c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * 73c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * All packets, sent and received via SDK controller socket begin with this 74c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * header, with packet data immediately following this header. 75c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 76c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinetypedef struct SDKCtlPacketHeader { 77c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Total size of the data to transfer with this packet, including this 78c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * header. The transferring data should immediatelly follow this header. */ 79c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine int size; 80c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Encodes packet type. See SDKCTL_PACKET_XXX for the list of packet types 81c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * used by SDK controller. */ 82c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine int type; 83c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} SDKCtlPacketHeader; 84c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 85c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Packet descriptor, allocated by this API for data packets to be sent to SDK 86c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * controller service on the device. 87c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * 88c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * When packet descriptors are allocated by this API, they are allocated large 89c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * enough to contain this header, and packet data to send to the service, 90c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * immediately following this descriptor. 91c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 92c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestruct SDKCtlPacket { 93c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Supports recycling. Don't put anything in front: recycler expects this 94c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * to be the first field in recyclable descriptor. */ 95c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlRecycled recycling; 96c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 97c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Next packet in the list of packets to send. */ 98c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlPacket* next; 99c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* SDK controller socket that transmits this packet. */ 100c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* sdkctl; 101c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Number of outstanding references to the packet. */ 102c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine int ref_count; 103c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 104c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Common packet header. Packet data immediately follows this header, so it 105c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * must be last field in SDKCtlPacket descriptor. */ 106c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlPacketHeader header; 107c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine}; 108c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 109c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/******************************************************************************** 110c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * SDKCtlQuery declarations 111c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *******************************************************************************/ 112c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 113c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* 114c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Types of queries sent via SDK controller socket. 115c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 116c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 117c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Handshake query. 118c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * This query is sent to SDK controller service as part of the connection 119c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * protocol implementation. 120c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 121c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#define SDKCTL_QUERY_HANDSHAKE -1 122c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 123c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Query packet descriptor. 124c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * 125c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * All queries, sent and received via SDK controller socket begin with this 126c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * header, with query data immediately following this header. 127c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 128c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinetypedef struct SDKCtlQueryHeader { 129c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Data packet header for this query. */ 130c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlPacketHeader packet; 131c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* A unique query identifier. This ID is used to track the query in the 132c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * asynchronous environment in whcih SDK controller socket operates. */ 133c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine int query_id; 134c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Query type. See SDKCTL_QUERY_XXX for the list of query types used by SDK 135c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * controller. */ 136c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine int query_type; 137c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} SDKCtlQueryHeader; 138c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 139c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Query descriptor, allocated by this API for queries to be sent to SDK 140c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * controller service on the device. 141c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * 142c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * When query descriptors are allocated by this API, they are allocated large 143c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * enough to contain this header, and query data to send to the service, 144c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * immediately following this descriptor. 145c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 146c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestruct SDKCtlQuery { 147c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Supports recycling. Don't put anything in front: recycler expects this 148c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * to be the first field in recyclable descriptor. */ 149c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlRecycled recycling; 150c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 151c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Next query in the list of active, or recycled queries. */ 152c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* next; 153c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* A timer to run time out on this query after it has been sent. */ 154c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine LoopTimer timer[1]; 155c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Absolute time for this query's deadline. This is the value that query's 156c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * timer is set for after query has been transmitted to the service. */ 157c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine Duration deadline; 158c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* SDK controller socket that owns the query. */ 159c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* sdkctl; 160c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* A callback to invoke on query state changes. */ 161c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine on_sdkctl_query_cb query_cb; 162c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* An opaque pointer associated with this query. */ 163c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine void* query_opaque; 164c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Points to an address of a buffer where to save query response. */ 165c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine void** response_buffer; 166c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Points to a variable containing size of the response buffer (on the way in), 167c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * or actual query response size (when query is completed). */ 168c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine uint32_t* response_size; 169c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Internal response buffer, allocated if query creator didn't provide its 170c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * own. This field is valid only if response_buffer field is NULL, or is 171c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * pointing to this field. */ 172c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine void* internal_resp_buffer; 173c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Internal response buffer size This field is valid only if response_size 174c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * field is NULL, or is pointing to this field. */ 175c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine uint32_t internal_resp_size; 176c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Number of outstanding references to the query. */ 177c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine int ref_count; 178c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 179c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Common packet header. Query data immediately follows this header, so it 180c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * must be last field in SDKCtlQuery descriptor. */ 181c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQueryHeader header; 182c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine}; 183c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 184c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Query reply descriptor. 185c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * 186c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * All replies to a query, sent and received via SDK controller socket begin with 187c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * this header, with query reply data immediately following this header. 188c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 189c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinetypedef struct SDKCtlQueryReplyHeader { 190c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Data packet header for this reply. */ 191c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlPacketHeader packet; 192c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 193c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* An identifier for the query that is addressed with this reply. */ 194c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine int query_id; 195c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} SDKCtlQueryReplyHeader; 196c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 197c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/******************************************************************************** 198c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * SDK Control Socket declarations 199c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *******************************************************************************/ 200c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 201c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Enumerates SDKCtlSocket states. */ 202c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinetypedef enum SDKCtlSocketState { 203c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Socket is disconnected from SDK controller. */ 204c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCTL_SOCKET_DISCONNECTED, 205c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Connection to SDK controller is in progress. */ 206c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCTL_SOCKET_CONNECTING, 207c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Socket is connected to an SDK controller service. */ 208c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCTL_SOCKET_CONNECTED 209c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} SDKCtlSocketState; 210c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 211c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Enumerates SDKCtlSocket I/O dispatcher states. */ 212c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinetypedef enum SDKCtlIODispatcherState { 213c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* I/O dispatcher expects a packet header. */ 214c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCTL_IODISP_EXPECT_HEADER, 215c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* I/O dispatcher expects packet data. */ 216c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCTL_IODISP_EXPECT_DATA, 217c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* I/O dispatcher expects query response header. */ 218c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCTL_IODISP_EXPECT_QUERY_REPLY_HEADER, 219c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* I/O dispatcher expects query response data. */ 220c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCTL_IODISP_EXPECT_QUERY_REPLY_DATA, 221c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} SDKCtlIODispatcherState; 222c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 223c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* SDKCtlSocket I/O dispatcher descriptor. */ 224c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinetypedef struct SDKCtlIODispatcher { 225c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* SDKCtlSocket instance for this dispatcher. */ 226c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* sdkctl; 227c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Dispatcher state. */ 228c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlIODispatcherState state; 229c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Unites all types of headers used in SDK controller data exchange. */ 230c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine union { 231c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Common packet header. */ 232c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlPacketHeader header; 233c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Header for a query packet. */ 234c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQueryHeader query_header; 235c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Header for a query response packet. */ 236c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQueryReplyHeader query_reply_header; 237c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine }; 238c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Descriptor of a packet packet received from SDK controller. */ 239c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlPacket* packet; 240c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* A query for which a reply is currently being received. */ 241c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* current_query; 242c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} SDKCtlIODispatcher; 243c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 244c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* SDK controller socket descriptor. */ 245c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestruct SDKCtlSocket { 246c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* SDK controller socket state */ 247c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocketState state; 248c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* I/O dispatcher for the socket. */ 249c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlIODispatcher io_dispatcher; 250c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Asynchronous socket connected to SDK Controller on the device. */ 251c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncSocket* as; 252c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Client callback that monitors this socket connection. */ 253c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine on_sdkctl_connection_cb on_connection; 254c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* A callback to invoke when handshake message is received from the 255c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * SDK controller. */ 256c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine on_sdkctl_handshake_cb on_handshake; 257c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* A callback to invoke when a message is received from the SDK controller. */ 258c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine on_sdkctl_message_cb on_message; 259c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* An opaque pointer associated with this socket. */ 260c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine void* opaque; 261c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Name of an SDK controller service this socket is connected to. */ 262c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine char* service_name; 263c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* I/O looper for timers. */ 264c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine Looper* looper; 265c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Head of the active query list. */ 266c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* query_head; 267c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Tail of the active query list. */ 268c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* query_tail; 269c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Query ID generator that gets incremented for each new query. */ 270c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine int next_query_id; 271c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Timeout before trying to reconnect after disconnection. */ 272c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine int reconnect_to; 273c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Number of outstanding references to this descriptor. */ 274c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine int ref_count; 275c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Head of the recycled memory */ 276c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlRecycled* recycler; 277c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Recyclable block size. */ 278c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine uint32_t recycler_block_size; 279c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Maximum number of blocks to recycle. */ 280c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine int recycler_max; 281c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Number of blocs in the recycler. */ 282c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine int recycler_count; 283c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine}; 284c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 285c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/******************************************************************************** 286c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * SDKCtlSocket recycling management 287c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *******************************************************************************/ 288c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 289c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Gets a recycled block for a given SDKCtlSocket, or allocates new memory 290c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * block. */ 291c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void* 292c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_socket_alloc_recycler(SDKCtlSocket* sdkctl, uint32_t size) 293c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 294c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlRecycled* block = NULL; 295c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 296c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->recycler != NULL && size <= sdkctl->recycler_block_size) { 297c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* There are blocks in the recycler, and requested size fits. */ 298c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine block = sdkctl->recycler; 299c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->recycler = block->next; 300c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine block->size = sdkctl->recycler_block_size; 301c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->recycler_count--; 302c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } else if (size <= sdkctl->recycler_block_size) { 303c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* There are no blocks in the recycler, but requested size fits. */ 304c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine block = malloc(sdkctl->recycler_block_size); 305c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (block == NULL) { 306c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine APANIC("SDKCtl %s: Unable to allocate %d bytes block", 307c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name, sdkctl->recycler_block_size); 308c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 309c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine block->size = sdkctl->recycler_block_size; 310c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } else { 311c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Requested size doesn't fit the recycler. */ 312c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine block = malloc(size); 313c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (block == NULL) { 314c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine APANIC("SDKCtl %s: Unable to allocate %d bytes block", 315c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name, size); 316c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 317c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine block->size = size; 318c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 319c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 320c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return block; 321c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 322c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 323c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Recycles, or frees a block of memory for a given SDKCtlSocket. */ 324c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 325c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_socket_free_recycler(SDKCtlSocket* sdkctl, void* mem) 326c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 327c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlRecycled* block = (SDKCtlRecycled*)mem; 328c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 329c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->recycler_count == sdkctl->recycler_max || 330c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine block->size != sdkctl->recycler_block_size) { 331c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Recycler is full, or block cannot be recycled. */ 332c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine free(mem); 333c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return; 334c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 335c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 336c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine block->next = sdkctl->recycler; 337c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->recycler = block; 338c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->recycler_count++; 339c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 340c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 341c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Empties the recycler for a given SDKCtlSocket. */ 342c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 343c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_socket_empty_recycler(SDKCtlSocket* sdkctl) 344c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 345c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlRecycled* block = sdkctl->recycler; 346c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine while (block != NULL) { 347c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine void* to_free = block; 348c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine block = block->next; 349c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine free(to_free); 350c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 351c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->recycler = NULL; 352c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->recycler_count = 0; 353c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 354c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 355c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/******************************************************************************** 356c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * SDKCtlSocket query list management 357c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *******************************************************************************/ 358c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 359c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Adds a query to the list of active queries. 360c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Param: 361c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * sdkctl - SDKCtlSocket instance for the query. 362c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * query - Query to add to the list. 363c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 364c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 365c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_socket_add_query(SDKCtlQuery* query) 366c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 367c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* const sdkctl = query->sdkctl; 368c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->query_head == NULL) { 369c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->query_head = sdkctl->query_tail = query; 370c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } else { 371c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->query_tail->next = query; 372c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->query_tail = query; 373c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 374c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 375c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Keep the query referenced while it's in the list. */ 376c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_reference(query); 377c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 378c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 379c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Removes a query from the list of active queries. 380c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Param: 381c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * query - Query to remove from the list of active queries. 382c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Return: 383c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Boolean: 1 if query has been removed, or 0 if query has not been found in the 384c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * list of active queries. 385c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 386c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic int 387c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_socket_remove_query(SDKCtlQuery* query) 388c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 389c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* const sdkctl = query->sdkctl; 390c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* prev = NULL; 391c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* head = sdkctl->query_head; 392c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 393c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Quick check: the query could be currently handled by dispatcher. */ 394c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->io_dispatcher.current_query == query) { 395c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Release the query from dispatcher. */ 396c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_release(query); 397c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->io_dispatcher.current_query = NULL; 398c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return 1; 399c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 400c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 401c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Remove query from the list. */ 402c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine while (head != NULL && query != head) { 403c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine prev = head; 404c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine head = head->next; 405c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 406c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (head != NULL) { 407c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (prev == NULL) { 408c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Query is at the head of the list. */ 409c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine assert(query == sdkctl->query_head); 410c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->query_head = query->next; 411c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } else { 412c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Query is in the middle / at the end of the list. */ 413c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine assert(query != sdkctl->query_head); 414c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine prev->next = query->next; 415c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 416c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->query_tail == query) { 417c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Query is at the tail of the list. */ 418c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine assert(query->next == NULL); 419c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->query_tail = prev; 420c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 421c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->next = NULL; 422c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 423c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Release query that is now removed from the list. Note that query 424c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * passed to this routine should hold an extra reference, owned by the 425c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * caller. */ 426c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_release(query); 427c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return 1; 428c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } else { 429c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine D("%s: Query %p is not found in the list.", sdkctl->service_name, query); 430c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return 0; 431c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 432c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 433c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 434c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Removes a query (based on query ID) from the list of active queries. 435c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Param: 436c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * sdkctl - SDKCtlSocket instance that owns the query. 437c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * query_id - Identifies the query to remove. 438c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Return: 439c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * A query removed from the list of active queries, or NULL if query with the 440c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * given ID has not been found in the list. 441c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 442c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic SDKCtlQuery* 443c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_socket_remove_query_id(SDKCtlSocket* sdkctl, int query_id) 444c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 445c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* prev = NULL; 446c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* head = sdkctl->query_head; 447c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 448c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Quick check: the query could be currently handled by dispatcher. */ 449c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->io_dispatcher.current_query != NULL && 450c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->io_dispatcher.current_query->header.query_id == query_id) { 451c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Release the query from dispatcher. */ 452c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* const query = sdkctl->io_dispatcher.current_query; 453c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->io_dispatcher.current_query = NULL; 454c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return query; 455c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 456c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 457c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Remove query from the list. */ 458c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine while (head != NULL && head->header.query_id != query_id) { 459c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine prev = head; 460c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine head = head->next; 461c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 462c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (head != NULL) { 463c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Query is found in the list. */ 464c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* const query = head; 465c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (prev == NULL) { 466c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Query is at the head of the list. */ 467c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine assert(query == sdkctl->query_head); 468c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->query_head = query->next; 469c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } else { 470c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Query is in the middle, or at the end of the list. */ 471c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine assert(query != sdkctl->query_head); 472c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine prev->next = query->next; 473c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 474c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->query_tail == query) { 475c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Query is at the tail of the list. */ 476c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine assert(query->next == NULL); 477c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->query_tail = prev; 478c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 479c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->next = NULL; 480c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return query; 481c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } else { 482c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine D("%s: Query ID %d is not found in the list.", 483c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name, query_id); 484c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return NULL; 485c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 486c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 487c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 488c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Pulls the first query from the list of active queries. 489c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Param: 490c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * sdkctl - SDKCtlSocket instance that owns the query. 491c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Return: 492c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * A query removed pulled from the list of active queries, or NULL if query 493c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * list is empty. 494c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 495c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic SDKCtlQuery* 496c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_socket_pull_first_query(SDKCtlSocket* sdkctl) 497c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 498c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* const query = sdkctl->query_head; 499c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 500c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (query != NULL) { 501c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->query_head = query->next; 502c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->query_head == NULL) { 503c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->query_tail = NULL; 504c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 505c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 506c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return query; 507c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 508c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 509c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Generates new query ID for the given SDKCtl. */ 510c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic int 511c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_socket_next_query_id(SDKCtlSocket* sdkctl) 512c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 513c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return ++sdkctl->next_query_id; 514c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 515c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 516c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/******************************************************************************** 517c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * SDKCtlPacket implementation 518c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *******************************************************************************/ 519c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 520c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Alocates a packet. */ 521c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic SDKCtlPacket* 522c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_packet_new(SDKCtlSocket* sdkctl, int size, int type) 523c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 524c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine const uint32_t total_size = sizeof(SDKCtlPacket) + size; 525c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlPacket* const packet = _sdkctl_socket_alloc_recycler(sdkctl, total_size); 526c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 527c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine packet->sdkctl = sdkctl; 528c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine packet->ref_count = 1; 529c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine packet->header.size = size; 530c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine packet->header.type = type; 531c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 532c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Refence SDKCTlSocket that owns this packet. */ 533c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_socket_reference(sdkctl); 534c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 535c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return packet; 536c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 537c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 538c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Frees a packet. */ 539c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 540c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_packet_free(SDKCtlPacket* packet) 541c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 542c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* const sdkctl = packet->sdkctl; 543c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 544c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Free allocated resources. */ 545c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_free_recycler(packet->sdkctl, packet); 546c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 547c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Release SDKCTlSocket that owned this packet. */ 548c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_socket_release(sdkctl); 549c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 550c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 551c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkineint 552c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinesdkctl_packet_reference(SDKCtlPacket* packet) 553c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 554c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine assert(packet->ref_count > 0); 555c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine packet->ref_count++; 556c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return packet->ref_count; 557c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 558c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 559c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkineint 560c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinesdkctl_packet_release(SDKCtlPacket* packet) 561c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 562c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine assert(packet->ref_count > 0); 563c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine packet->ref_count--; 564c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (packet->ref_count == 0) { 565c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Last reference has been dropped. Destroy this object. */ 566c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_packet_free(packet); 567c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return 0; 568c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 569c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return packet->ref_count; 570c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 571c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 572c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/******************************************************************************** 573c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * SDKCtlQuery implementation 574c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *******************************************************************************/ 575c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 576c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Frees query descriptor. */ 577c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 578c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_query_free(SDKCtlQuery* query) 579c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 580c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (query != NULL) { 581c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* const sdkctl = query->sdkctl; 582c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("SDKCtl %s: Query %p ID %d is freed.", 583c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name, query, query->header.query_id); 584c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 585c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Free allocated resources. */ 586c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (query->internal_resp_buffer != NULL && 587c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine (query->response_buffer == NULL || 588c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->response_buffer == &query->internal_resp_buffer)) { 589c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine free(query->internal_resp_buffer); 590c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 591c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 592c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine loopTimer_done(query->timer); 593c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_free_recycler(sdkctl, query); 594c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 595c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Release socket that owned this query. */ 596c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_socket_release(sdkctl); 597c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 598c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 599c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 600c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Cancels timeout for the query. 601c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * 602c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * For the simplicity of implementation, the dispatcher will cancel query timer 603c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * when query response data begins to flow in. If we let the timer to expire at 604c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * that stage, we will end up with data flowing in without real place to 605c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * accomodate it. 606c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 607c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 608c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_query_cancel_timeout(SDKCtlQuery* query) 609c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 610c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine loopTimer_stop(query->timer); 611c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 612c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("SDKCtl %s: Query %p ID %d deadline is cancelled.", 613c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->sdkctl->service_name, query, query->header.query_id); 614c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 615c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 616c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* 617c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Query I/O callbacks. 618c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 619c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 620c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Callback that is invoked by the I/O dispatcher when query is successfuly 621c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * completed (i.e. response to the query is received). 622c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 623c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 624c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_sdkctl_query_completed(SDKCtlQuery* query) 625c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 626c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("SDKCtl %s: Query %p ID %d is completed.", 627c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->sdkctl->service_name, query, query->header.query_id); 628c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 629c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Cancel deadline, and inform the client about query completion. */ 630c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_query_cancel_timeout(query); 631c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->query_cb(query->query_opaque, query, ASIO_STATE_SUCCEEDED); 632c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 633c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 634c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* A callback that is invoked on query cancellation. */ 635c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 636c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_sdkctl_query_cancelled(SDKCtlQuery* query) 637c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 638c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* 639c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Query cancellation means that SDK controller is disconnected. In turn, 640c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * this means that SDK controller socket will handle disconnection in its 641c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * connection callback. So, at this point all we need to do here is to inform 642c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * the client, and then unlist the query. 643c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 644c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 645c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Cancel deadline, and inform the client about query cancellation. */ 646c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_query_cancel_timeout(query); 647c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->query_cb(query->query_opaque, query, ASIO_STATE_CANCELLED); 648c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 649c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 650c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* A timer callback that is invoked on query timeout. 651c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Param: 652c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * opaque - SDKCtlQuery instance. 653c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 654c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 655c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_skdctl_query_timeout(void* opaque) 656c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 657c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* const query = (SDKCtlQuery*)opaque; 658c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 659c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine D("SDKCtl %s: Query %p ID %d with deadline %lld has timed out at %lld", 660c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->sdkctl->service_name, query, query->header.query_id, 661c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->deadline, async_socket_deadline(query->sdkctl->as, 0)); 662c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 663c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Reference the query while we're in this callback. */ 664c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_reference(query); 665c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 666c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Inform the client about deadline expiration. Note that client may 667c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * extend the deadline, and retry the query. */ 668c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine const AsyncIOAction action = 669c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->query_cb(query->query_opaque, query, ASIO_STATE_TIMED_OUT); 670c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 671c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* For actions other than retry we will destroy the query. */ 672c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (action != ASIO_ACTION_RETRY) { 673c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_remove_query(query); 674c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 675c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 676c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_release(query); 677c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 678c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 679c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* A callback that is invoked when query has been sent to the SDK controller 680c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * service. */ 681c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 682c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_sdkctl_query_sent(SDKCtlQuery* query) 683c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 684c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("SDKCtl %s: sent %d bytes of query %p ID %d of type %d", 685c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->sdkctl->service_name, query->header.packet.size, query, 686c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->header.query_id, query->header.query_type); 687c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 688c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Inform the client about the event. */ 689c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->query_cb(query->query_opaque, query, ASIO_STATE_CONTINUES); 690c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 691c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Set a timer to expire at query's deadline, and let the response to come 692c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * through the dispatcher loop. */ 693c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine loopTimer_startAbsolute(query->timer, query->deadline); 694c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 695c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 696c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* An I/O callback invoked on query transmission. 697c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Param: 698c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * io_opaque SDKCtlQuery instance of the query that's being sent with this I/O. 699c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * asio - Write I/O descriptor. 700c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * status - I/O status. 701c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 702c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic AsyncIOAction 703c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_sdkctl_query_send_io(void* io_opaque, 704c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncSocketIO* asio, 705c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncIOState status) 706c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 707c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* const query = (SDKCtlQuery*)io_opaque; 708c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncIOAction action = ASIO_ACTION_DONE; 709c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 710c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Reference the query while we're in this callback. */ 711c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_reference(query); 712c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 713c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (status == ASIO_STATE_SUCCEEDED) { 714c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Query has been sent to the service. */ 715c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_sdkctl_query_sent(query); 716c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 717c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_release(query); 718c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 719c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return ASIO_ACTION_DONE; 720c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 721c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 722c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Lets see what's going on with query transmission. */ 723c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine switch (status) { 724c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_CANCELLED: 725c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("SDKCtl %s: Query %p ID %d is cancelled in %s I/O.", 726c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->sdkctl->service_name, query, query->header.query_id, 727c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine async_socket_io_is_read(asio) ? "READ" : "WRITE"); 728c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Remove the query from the list of active queries. */ 729c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_remove_query(query); 730c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_sdkctl_query_cancelled(query); 731c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 732c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 733c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_TIMED_OUT: 734c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine D("SDKCtl %s: Query %p ID %d with deadline %lld has timed out in %s I/O at %lld", 735c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->sdkctl->service_name, query, query->header.query_id, 736c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->deadline, async_socket_io_is_read(asio) ? "READ" : "WRITE", 737c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine async_socket_deadline(query->sdkctl->as, 0)); 738c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Invoke query's callback. */ 739c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine action = query->query_cb(query->query_opaque, query, status); 740c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* For actions other than retry we need to stop the query. */ 741c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (action != ASIO_ACTION_RETRY) { 742c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_remove_query(query); 743c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 744c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 745c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 746c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_FAILED: 747c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("SDKCtl %s: Query %p ID %d failed in %s I/O: %d -> %s", 748c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->sdkctl->service_name, query, query->header.query_id, 749c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine async_socket_io_is_read(asio) ? "READ" : "WRITE", 750c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine errno, strerror(errno)); 751c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Invoke query's callback. Note that we will let the client to 752c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * decide what to do on I/O failure. */ 753c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine action = query->query_cb(query->query_opaque, query, status); 754c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* For actions other than retry we need to stop the query. */ 755c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (action != ASIO_ACTION_RETRY) { 756c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_remove_query(query); 757c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 758c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 759c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 760c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_FINISHED: 761c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Time to disassociate with the I/O. */ 762c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_release(query); 763c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 764c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 765c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine default: 766c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Transitional state. */ 767c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 768c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 769c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 770c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_release(query); 771c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 772c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return action; 773c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 774c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 775c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/******************************************************************************** 776c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * SDKCtlQuery public API implementation 777c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine ********************************************************************************/ 778c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 779c8aa2c570d30098da59f1967d5158024ed28570dVladimir ChtchetkineSDKCtlQuery* 780c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinesdkctl_query_new(SDKCtlSocket* sdkctl, int query_type, uint32_t in_data_size) 781c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 782c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine const uint32_t total_size = sizeof(SDKCtlQuery) + in_data_size; 783c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 784c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* const query = _sdkctl_socket_alloc_recycler(sdkctl, total_size); 785c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->next = NULL; 786c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->sdkctl = sdkctl; 787c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->response_buffer = NULL; 788c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->response_size = NULL; 789c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->internal_resp_buffer = NULL; 790c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->internal_resp_size = 0; 791c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->query_cb = NULL; 792c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->query_opaque = NULL; 793c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->deadline = DURATION_INFINITE; 794c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->ref_count = 1; 795c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->header.packet.size = sizeof(SDKCtlQueryHeader) + in_data_size; 796c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->header.packet.type = SDKCTL_PACKET_QUERY; 797c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->header.query_id = _sdkctl_socket_next_query_id(sdkctl); 798c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->header.query_type = query_type; 799c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 800c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Initialize timer to fire up on query deadline expiration. */ 801c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine loopTimer_init(query->timer, sdkctl->looper, _on_skdctl_query_timeout, query); 802c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 803c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Reference socket that owns this query. */ 804c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_socket_reference(sdkctl); 805c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 806c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("SDKCtl %s: Query %p ID %d type %d is created for %d bytes of data.", 807c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->sdkctl->service_name, query, query->header.query_id, 808c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query_type, in_data_size); 809c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 810c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return query; 811c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 812c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 813c8aa2c570d30098da59f1967d5158024ed28570dVladimir ChtchetkineSDKCtlQuery* 814c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinesdkctl_query_new_ex(SDKCtlSocket* sdkctl, 815c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine int query_type, 816c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine uint32_t in_data_size, 817c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine const void* in_data, 818c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine void** response_buffer, 819c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine uint32_t* response_size, 820c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine on_sdkctl_query_cb query_cb, 821c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine void* query_opaque) 822c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 823c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* const query = sdkctl_query_new(sdkctl, query_type, in_data_size); 824c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 825c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->response_buffer = response_buffer; 826c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (query->response_buffer == NULL) { 827c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Creator didn't supply a buffer. Use internal one instead. */ 828c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->response_buffer = &query->internal_resp_buffer; 829c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->internal_resp_buffer = NULL; 830c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 831c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->response_size = response_size; 832c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (query->response_size == NULL) { 833c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Creator didn't supply a buffer for response size. Use internal one 834c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * instead. */ 835c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->response_size = &query->internal_resp_size; 836c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->internal_resp_size = 0; 837c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 838c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->query_cb = query_cb; 839c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->query_opaque = query_opaque; 840c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Init query's input buffer. */ 841c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (in_data_size != 0 && in_data != NULL) { 842c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine memcpy(query + 1, in_data, in_data_size); 843c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 844c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 845c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return query; 846c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 847c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 848c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinevoid 849c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinesdkctl_query_send(SDKCtlQuery* query, int to) 850c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 851c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* const sdkctl = query->sdkctl; 852c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 853c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Initialize the deadline. */ 854c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->deadline = async_socket_deadline(query->sdkctl->as, to); 855c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 856c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* List the query in the list of active queries. */ 857c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_add_query(query); 858c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 859c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Reference query associated with write I/O. */ 860c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_reference(query); 861c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 862c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Transmit the query to SDK controller. */ 863c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine async_socket_write_abs(sdkctl->as, &query->header, query->header.packet.size, 864c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_sdkctl_query_send_io, query, query->deadline); 865c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 866c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("SDKCtl %s: Query %p ID %d type %d is sent with deadline at %lld", 867c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->sdkctl->service_name, query, query->header.query_id, 868c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->header.query_type, query->deadline); 869c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 870c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 871c8aa2c570d30098da59f1967d5158024ed28570dVladimir ChtchetkineSDKCtlQuery* 872c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinesdkctl_query_build_and_send(SDKCtlSocket* sdkctl, 873c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine int query_type, 874c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine uint32_t in_data_size, 875c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine const void* in_data, 876c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine void** response_buffer, 877c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine uint32_t* response_size, 878c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine on_sdkctl_query_cb query_cb, 879c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine void* query_opaque, 880c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine int to) 881c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 882c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* const query = 883c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_new_ex(sdkctl, query_type, in_data_size, in_data, 884c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine response_buffer, response_size, query_cb, 885c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query_opaque); 886c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_send(query, to); 887c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return query; 888c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 889c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 890c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkineint 891c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinesdkctl_query_reference(SDKCtlQuery* query) 892c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 893c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine assert(query->ref_count > 0); 894c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->ref_count++; 895c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return query->ref_count; 896c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 897c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 898c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkineint 899c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinesdkctl_query_release(SDKCtlQuery* query) 900c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 901c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine assert(query->ref_count > 0); 902c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->ref_count--; 903c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (query->ref_count == 0) { 904c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Last reference has been dropped. Destroy this object. */ 905c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_query_free(query); 906c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return 0; 907c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 908c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return query->ref_count; 909c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 910c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 911c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/******************************************************************************** 912c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * SDKCtlPacket implementation 913c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *******************************************************************************/ 914c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 915c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* A packet has been received from SDK controller. */ 916c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 917c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_sdkctl_packet_received(SDKCtlSocket* sdkctl, SDKCtlPacket* packet) 918c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 919c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("SDKCtl %s: Received packet size: %d, type: %d", 920c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name, packet->header.size, packet->header.type); 921c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 922c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Dispatch received packet to the client. */ 923c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->on_message(sdkctl->opaque, sdkctl, packet, packet->header.type, 924c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine packet + 1, packet->header.size - sizeof(SDKCtlPacketHeader)); 925c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 926c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 927c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/******************************************************************************** 928c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * SDKCtlIODispatcher implementation 929c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *******************************************************************************/ 930c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 931c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* An I/O callback invoked when data gets received from the socket. 932c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Param: 933c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * io_opaque SDKCtlIODispatcher instance associated with the reader. 934c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * asio - Read I/O descriptor. 935c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * status - I/O status. 936c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 937c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic AsyncIOAction _on_sdkctl_io_dispatcher_io(void* io_opaque, 938c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncSocketIO* asio, 939c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncIOState status); 940c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 941c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Starts I/O dispatcher for SDK controller socket. */ 942c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 943c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_io_dispatcher_start(SDKCtlSocket* sdkctl) { 944c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlIODispatcher* const dispatcher = &sdkctl->io_dispatcher; 945c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 946c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->state = SDKCTL_IODISP_EXPECT_HEADER; 947c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->sdkctl = sdkctl; 948c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->packet = NULL; 949c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->current_query = NULL; 950c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 951c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Register a packet header reader with the socket. */ 952c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine async_socket_read_rel(dispatcher->sdkctl->as, &dispatcher->header, 953c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sizeof(SDKCtlPacketHeader), _on_sdkctl_io_dispatcher_io, 954c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher, -1); 955c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 956c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 957c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Resets I/O dispatcher for SDK controller socket. */ 958c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 959c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_io_dispatcher_reset(SDKCtlSocket* sdkctl) { 960c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlIODispatcher* const dispatcher = &sdkctl->io_dispatcher; 961c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 962c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Cancel current query. */ 963c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (dispatcher->current_query != NULL) { 964c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* const query = dispatcher->current_query; 965c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->current_query = NULL; 966c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_sdkctl_query_cancelled(query); 967c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_release(query); 968c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 969c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 970c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Free packet data buffer. */ 971c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (dispatcher->packet != NULL) { 972c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_packet_release(dispatcher->packet); 973c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->packet = NULL; 974c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 975c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 976c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Reset dispatcher state. */ 977c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->state = SDKCTL_IODISP_EXPECT_HEADER; 978c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 979c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 980c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* 981c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * I/O dispatcher callbacks. 982c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 983c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 984c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* A callback that is invoked when a failure occurred while dispatcher was 985c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * reading data from the socket. 986c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 987c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 988c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_io_dispatcher_io_failure(SDKCtlIODispatcher* dispatcher, 989c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncSocketIO* asio) 990c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 991c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* const sdkctl = dispatcher->sdkctl; 992c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 993c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine D("SDKCtl %s: Dispatcher I/O failure: %d -> %s", 994c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name, errno, strerror(errno)); 995c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 996c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* We treat all I/O failures same way we treat disconnection. Just cancel 997c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * everything, disconnect, and let the client to decide what to do next. */ 998c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_socket_disconnect(sdkctl); 999c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1000c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Report disconnection to the client, and let it restore connection in this 1001c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * callback. */ 1002c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->on_connection(sdkctl->opaque, sdkctl, ASIO_STATE_FAILED); 1003c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1004c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1005c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* A callback that is invoked when dispatcher's reader has been cancelled. */ 1006c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 1007c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_io_dispatcher_io_cancelled(SDKCtlIODispatcher* dispatcher, 1008c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncSocketIO* asio) 1009c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1010c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("SDKCtl %s: Dispatcher I/O cancelled.", dispatcher->sdkctl->service_name); 1011c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1012c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* If we're in the middle of receiving query reply we need to cancel the 1013c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * query. */ 1014c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (dispatcher->current_query != NULL) { 1015c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* const query = dispatcher->current_query; 1016c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->current_query = NULL; 1017c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_sdkctl_query_cancelled(query); 1018c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_release(query); 1019c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1020c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1021c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Discard packet data we've received so far. */ 1022c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (dispatcher->packet != NULL) { 1023c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_packet_release(dispatcher->packet); 1024c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->packet = NULL; 1025c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1026c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1027c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1028c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* A generic packet header has been received by I/O dispatcher. */ 1029c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic AsyncIOAction 1030c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_io_dispatcher_packet_header(SDKCtlIODispatcher* dispatcher, 1031c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncSocketIO* asio) 1032c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1033c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* const sdkctl = dispatcher->sdkctl; 1034c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1035c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("SDKCtl %s: Packet header type %d, size %d is received.", 1036c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->sdkctl->service_name, dispatcher->header.type, 1037c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->header.size); 1038c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1039c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Here we have three choices for the packet, that define the rest of 1040c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * the data that follow it: 1041c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * - Regular packet, 1042c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * - Response to a query that has been sent to SDK controller, 1043c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * - A query from SDK controller. 1044c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Update the state accordingly, and initiate reading of the 1045c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * remaining of the packet. 1046c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 1047c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (dispatcher->header.type == SDKCTL_PACKET_QUERY_RESPONSE) { 1048c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* This is a response to the query. Before receiving response data we 1049c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * need to locate the relevant query, and use its response buffer to read 1050c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * the data. For that we need to obtain query ID firts. So, initiate 1051c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * reading of the remaining part of SDKCtlQueryReplyHeader. */ 1052c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->state = SDKCTL_IODISP_EXPECT_QUERY_REPLY_HEADER; 1053c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine async_socket_read_rel(sdkctl->as, &dispatcher->query_reply_header.query_id, 1054c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sizeof(SDKCtlQueryReplyHeader) - sizeof(SDKCtlPacketHeader), 1055c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_sdkctl_io_dispatcher_io, dispatcher, -1); 1056c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } else { 1057c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* For regular packets, as well as queries, we simply allocate buffer, 1058c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * that fits the entire packet, and read the remainder of the data in 1059c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * there. */ 1060c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->state = SDKCTL_IODISP_EXPECT_DATA; 1061c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->packet = 1062c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_packet_new(sdkctl, dispatcher->header.size, 1063c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->header.type); 1064c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Initiate reading of the packet data. */ 1065c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine async_socket_read_rel(sdkctl->as, dispatcher->packet + 1, 1066c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->header.size - sizeof(SDKCtlPacketHeader), 1067c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_sdkctl_io_dispatcher_io, dispatcher, -1); 1068c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1069c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1070c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return ASIO_ACTION_DONE; 1071c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1072c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1073c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* A generic packet has been received by I/O dispatcher. */ 1074c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic AsyncIOAction 1075c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_io_dispatcher_packet(SDKCtlIODispatcher* dispatcher, AsyncSocketIO* asio) 1076c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1077c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* const sdkctl = dispatcher->sdkctl; 1078c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1079c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("SDKCtl %s: Packet type %d, size %d is received.", 1080c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->sdkctl->service_name, dispatcher->header.type, 1081c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->header.size); 1082c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1083c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_sdkctl_packet_received(sdkctl, dispatcher->packet); 1084c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_packet_release(dispatcher->packet); 1085c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->packet = NULL; 1086c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1087c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Get ready for the next I/O cycle. */ 1088c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->state = SDKCTL_IODISP_EXPECT_HEADER; 1089c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine async_socket_read_rel(sdkctl->as, &dispatcher->header, sizeof(SDKCtlPacketHeader), 1090c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_sdkctl_io_dispatcher_io, dispatcher, -1); 1091c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return ASIO_ACTION_DONE; 1092c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1093c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1094c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* A query reply header has been received by I/O dispatcher. */ 1095c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic AsyncIOAction 1096c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_io_dispatcher_query_reply_header(SDKCtlIODispatcher* dispatcher, 1097c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncSocketIO* asio) 1098c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1099c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* const sdkctl = dispatcher->sdkctl; 1100c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* query; 1101c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1102c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("SDKCtl %s: Query reply header is received for query ID %d", 1103c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->sdkctl->service_name, dispatcher->query_reply_header.query_id); 1104c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1105c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Pull the query out of the list of active queries. It's the dispatcher that 1106c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * owns this query now. */ 1107c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->current_query = 1108c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_remove_query_id(sdkctl, dispatcher->query_reply_header.query_id); 1109c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query = dispatcher->current_query; 1110c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1111c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (query == NULL) { 1112c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine D("%s: Query #%d is not found by dispatcher", 1113c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->sdkctl->service_name, dispatcher->query_reply_header.query_id); 1114c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1115c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Query is not found. Just read the remainder of reply up in the air, 1116c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * and then discard when it's over. */ 1117c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->state = SDKCTL_IODISP_EXPECT_QUERY_REPLY_DATA; 1118c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->packet = 1119c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_packet_new(sdkctl, dispatcher->header.size, 1120c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->header.type); 1121c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Copy query reply info to the packet. */ 1122c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine memcpy(&dispatcher->packet->header, &dispatcher->query_reply_header, 1123c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sizeof(SDKCtlQueryReplyHeader)); 1124c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine async_socket_read_rel(sdkctl->as, &dispatcher->query_header + 1, 1125c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->header.size - sizeof(SDKCtlQueryReplyHeader), 1126c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_sdkctl_io_dispatcher_io, dispatcher, -1); 1127c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } else { 1128c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Prepare to receive query reply. For the simplicity sake, cancel query 1129c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * time out, so it doesn't expire on us while we're in the middle of 1130c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * receiving query's reply. */ 1131c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_query_cancel_timeout(query); 1132c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1133c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Adjust the reply buffer set for the query (if needed). */ 1134c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine const uint32_t query_data_size = 1135c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->header.size - sizeof(SDKCtlQueryReplyHeader); 1136c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (*query->response_size < query_data_size) { 1137c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *query->response_buffer = malloc(query_data_size); 1138c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (*query->response_buffer == NULL) { 1139c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine APANIC("%s: Unable to allocate %d bytes for query response", 1140c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name, query_data_size); 1141c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1142c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1143c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Save the actual query response size. */ 1144c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *query->response_size = query_data_size; 1145c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1146c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Start reading query response. */ 1147c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->state = SDKCTL_IODISP_EXPECT_QUERY_REPLY_DATA; 1148c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine async_socket_read_rel(sdkctl->as, *query->response_buffer, 1149c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *query->response_size, _on_sdkctl_io_dispatcher_io, 1150c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher, -1); 1151c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1152c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1153c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return ASIO_ACTION_DONE; 1154c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1155c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1156c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* A query reply header has been received by I/O dispatcher. */ 1157c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic AsyncIOAction 1158c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_io_dispatcher_query_reply(SDKCtlIODispatcher* dispatcher, AsyncSocketIO* asio) 1159c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1160c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* const sdkctl = dispatcher->sdkctl; 1161c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* const query = dispatcher->current_query; 1162c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->current_query = NULL; 1163c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1164c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (query != NULL) { 1165c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _ANDROID_ASSERT(query->header.query_id == dispatcher->query_reply_header.query_id, 1166c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine "SDKCtl %s: Query ID mismatch in I/O dispatcher", 1167c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name); 1168c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("SDKCtl %s: Query reply is received for query %p ID %d. Reply size is %d", 1169c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->sdkctl->service_name, query, query->header.query_id, 1170c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *query->response_size); 1171c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1172c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Complete the query, and release it from the dispatcher. */ 1173c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_sdkctl_query_completed(query); 1174c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_release(query); 1175c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } else { 1176c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* This was "read up in the air" for a cancelled query. Just discard the 1177c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * read data. */ 1178c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (dispatcher->packet != NULL) { 1179c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_packet_release(dispatcher->packet); 1180c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->packet = NULL; 1181c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1182c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1183c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1184c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Get ready for the next I/O cycle. */ 1185c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->state = SDKCTL_IODISP_EXPECT_HEADER; 1186c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine async_socket_read_rel(sdkctl->as, &dispatcher->header, sizeof(SDKCtlPacketHeader), 1187c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_sdkctl_io_dispatcher_io, dispatcher, -1); 1188c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return ASIO_ACTION_DONE; 1189c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1190c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1191c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* An I/O callback invoked when data gets received from the socket. 1192c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * This is main I/O dispatcher loop. 1193c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Param: 1194c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * io_opaque SDKCtlIODispatcher instance associated with the reader. 1195c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * asio - Read I/O descriptor. 1196c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * status - I/O status. 1197c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 1198c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic AsyncIOAction 1199c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_sdkctl_io_dispatcher_io(void* io_opaque, 1200c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncSocketIO* asio, 1201c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncIOState status) 1202c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1203c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncIOAction action = ASIO_ACTION_DONE; 1204c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlIODispatcher* const dispatcher = (SDKCtlIODispatcher*)io_opaque; 1205c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* const sdkctl = dispatcher->sdkctl; 1206c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1207c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Reference SDKCtlSocket while we're in this callback. */ 1208c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_socket_reference(sdkctl); 1209c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1210c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (status != ASIO_STATE_SUCCEEDED) { 1211c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Something going on with I/O other than receiving data.. */ 1212c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine switch (status) { 1213c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_STARTED: 1214c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Data has started flowing in. Cancel timeout on I/O that has 1215c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * started, so we can complete the current state of the 1216c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * dispatcher without interruptions other than I/O failures. */ 1217c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine async_socket_io_cancel_time_out(asio); 1218c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1219c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1220c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_FAILED: 1221c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* I/O failure has occurred. Handle the failure. */ 1222c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_io_dispatcher_io_failure(dispatcher, asio); 1223c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1224c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1225c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_TIMED_OUT: 1226c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* The way I/O dispatcher is implemented, this should never 1227c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * happen, because dispatcher doesn't set I/O expiration time 1228c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * when registering its readers. */ 1229c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _ANDROID_ASSERT(0, 1230c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine "SDKCtl %s: We should never receive ASIO_STATE_TIMED_OUT in SDKCtl I/O dispatcher.", 1231c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name); 1232c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1233c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1234c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_CANCELLED: 1235c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Cancellation means that we're in the middle of handling 1236c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * disconnection. Sooner or later, this dispatcher will be reset, 1237c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * so we don't really care about keeping its state at this point. 1238c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 1239c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_io_dispatcher_io_cancelled(dispatcher, asio); 1240c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1241c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1242c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_FINISHED: 1243c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1244c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1245c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine default: 1246c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _ANDROID_ASSERT(0, "SDKCtl %s: Unexpected I/O status %d in the dispatcher", 1247c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name, status); 1248c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Handle this as protocol failure. */ 1249c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine errno = EINVAL; 1250c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_io_dispatcher_io_failure(dispatcher, asio); 1251c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine action = ASIO_ACTION_ABORT; 1252c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1253c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1254c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1255c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_socket_release(sdkctl); 1256c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1257c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return action; 1258c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1259c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1260c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Requested data has been read. Handle the chunk depending on dispatcher's 1261c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * state. */ 1262c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine switch (dispatcher->state) { 1263c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case SDKCTL_IODISP_EXPECT_HEADER: 1264c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* A generic packet header is received. */ 1265c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine action = _on_io_dispatcher_packet_header(dispatcher, asio); 1266c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1267c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1268c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case SDKCTL_IODISP_EXPECT_QUERY_REPLY_HEADER: 1269c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Query reply header is received. */ 1270c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine action = _on_io_dispatcher_query_reply_header(dispatcher, asio); 1271c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1272c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1273c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case SDKCTL_IODISP_EXPECT_QUERY_REPLY_DATA: 1274c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Query reply is received. Complete the query. */ 1275c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine action = _on_io_dispatcher_query_reply(dispatcher, asio); 1276c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1277c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1278c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case SDKCTL_IODISP_EXPECT_DATA: 1279c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* A generic packet is received. */ 1280c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine action = _on_io_dispatcher_packet(dispatcher, asio); 1281c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1282c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1283c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine default: 1284c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _ANDROID_ASSERT(0, "SDKCtl %s: Unexpected I/O dispacher state %d", 1285c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name, dispatcher->state); 1286c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1287c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1288c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1289c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_socket_release(sdkctl); 1290c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1291c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return action; 1292c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1293c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1294c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/******************************************************************************** 1295c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * SDKCtlSocket internals. 1296c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *******************************************************************************/ 1297c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1298c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Cancels all queries that is active on this socket. */ 1299c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 1300c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_socket_cancel_all_queries(SDKCtlSocket* sdkctl) 1301c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1302c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlIODispatcher* const dispatcher = &sdkctl->io_dispatcher; 1303c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* query; 1304c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1305c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Cancel query that is being completed in dispatcher. */ 1306c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (dispatcher->current_query != NULL) { 1307c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* const query = dispatcher->current_query; 1308c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->current_query = NULL; 1309c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_sdkctl_query_cancelled(query); 1310c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_release(query); 1311c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1312c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1313c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* One by one empty query list cancelling pulled queries. */ 1314c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query = _sdkctl_socket_pull_first_query(sdkctl); 1315c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine while (query != NULL) { 1316c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_query_cancel_timeout(query); 1317c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->query_cb(query->query_opaque, query, ASIO_STATE_CANCELLED); 1318c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_release(query); 1319c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query = _sdkctl_socket_pull_first_query(sdkctl); 1320c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1321c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1322c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1323c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Cancels all packets that is active on this socket. */ 1324c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 1325c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_socket_cancel_all_packets(SDKCtlSocket* sdkctl) 1326c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1327c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1328c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1329c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Cancels all I/O that is active on this socket. */ 1330c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 1331c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_socket_cancel_all_io(SDKCtlSocket* sdkctl) 1332c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1333c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Cancel all queries, and packets that are active for this I/O. */ 1334c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_cancel_all_queries(sdkctl); 1335c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_cancel_all_packets(sdkctl); 1336c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1337c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1338c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Disconnects AsyncSocket for SDKCtlSocket. */ 1339c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 1340c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_socket_disconnect_socket(SDKCtlSocket* sdkctl) 1341c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1342c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->as != NULL) { 1343c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Disconnect the socket. This will trigger I/O cancellation callbacks. */ 1344c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine async_socket_disconnect(sdkctl->as); 1345c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1346c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Cancel all I/O that is active on this socket. */ 1347c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_cancel_all_io(sdkctl); 1348c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1349c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Reset I/O dispatcher. */ 1350c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_io_dispatcher_reset(sdkctl); 1351c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1352c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1353c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->state = SDKCTL_SOCKET_DISCONNECTED; 1354c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1355c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1356c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Frees SDKCtlSocket instance. */ 1357c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 1358c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_socket_free(SDKCtlSocket* sdkctl) 1359c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1360c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl != NULL) { 1361c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Disconnect, and release the socket. */ 1362c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->as != NULL) { 1363c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine async_socket_disconnect(sdkctl->as); 1364c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine async_socket_release(sdkctl->as); 1365c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1366c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1367c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Free allocated resources. */ 1368c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->looper != NULL) { 1369c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine looper_free(sdkctl->looper); 1370c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1371c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->service_name != NULL) { 1372c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine free(sdkctl->service_name); 1373c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1374c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_empty_recycler(sdkctl); 1375c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1376c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AFREE(sdkctl); 1377c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1378c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1379c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1380c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/******************************************************************************** 1381c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * SDK Control Socket connection callbacks. 1382c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *******************************************************************************/ 1383c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1384c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Initiates handshake query when SDK controller socket is connected. */ 1385c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void _sdkctl_do_handshake(SDKCtlSocket* sdkctl); 1386c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1387c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* A socket connection is established. 1388c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Here we will start I/O dispatcher, and will initiate a handshake with 1389c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * the SdkController service for this socket. */ 1390c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic AsyncIOAction 1391c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_async_socket_connected(SDKCtlSocket* sdkctl) 1392c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1393c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine D("SDKCtl %s: Socket is connected.", sdkctl->service_name); 1394c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1395c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Notify the client that connection is established. */ 1396c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine const AsyncIOAction action = 1397c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->on_connection(sdkctl->opaque, sdkctl, ASIO_STATE_SUCCEEDED); 1398c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1399c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (action == ASIO_ACTION_DONE) { 1400c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Initialize, and start main I/O dispatcher. */ 1401c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_io_dispatcher_start(sdkctl); 1402c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1403c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Initiate handshake. */ 1404c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_do_handshake(sdkctl); 1405c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1406c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return action; 1407c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } else { 1408c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Client didn't like something about this connection. */ 1409c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return action; 1410c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1411c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1412c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1413c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Handles lost connection with SdkController service. */ 1414c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic AsyncIOAction 1415c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_async_socket_disconnected(SDKCtlSocket* sdkctl) 1416c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1417c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine D("SDKCtl %s: Socket has been disconnected.", sdkctl->service_name); 1418c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1419c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_disconnect_socket(sdkctl); 1420c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1421c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncIOAction action = sdkctl->on_connection(sdkctl->opaque, sdkctl, 1422c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine ASIO_STATE_FAILED); 1423c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (action == ASIO_ACTION_DONE) { 1424c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Default action for disconnect is to reestablish the connection. */ 1425c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine action = ASIO_ACTION_RETRY; 1426c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1427c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (action == ASIO_ACTION_RETRY) { 1428c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->state = SDKCTL_SOCKET_CONNECTING; 1429c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1430c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return action; 1431c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1432c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1433c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* An entry point for all socket connection events. 1434c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Here we will dispatch connection events to appropriate handlers. 1435c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Param: 1436c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * client_opaque - SDKCtlSocket isntance. 1437c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 1438c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic AsyncIOAction 1439c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_async_socket_connection(void* client_opaque, 1440c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncSocket* as, 1441c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncIOState status) 1442c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1443c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncIOAction action = ASIO_ACTION_DONE; 1444c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* const sdkctl = (SDKCtlSocket*)client_opaque; 1445c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1446c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Reference the socket while in this callback. */ 1447c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_socket_reference(sdkctl); 1448c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1449c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine switch (status) { 1450c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_SUCCEEDED: 1451c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->state = SDKCTL_SOCKET_CONNECTED; 1452c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_async_socket_connected(sdkctl); 1453c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1454c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1455c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_FAILED: 1456c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->state == SDKCTL_SOCKET_CONNECTED) { 1457c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* This is disconnection condition. */ 1458c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine action = _on_async_socket_disconnected(sdkctl); 1459c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } else { 1460c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* An error has occurred while attempting to connect to socket. 1461c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Lets try again... */ 1462c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine action = ASIO_ACTION_RETRY; 1463c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1464c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1465c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1466c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_RETRYING: 1467c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine default: 1468c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine action = ASIO_ACTION_RETRY; 1469c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1470c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1471c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1472c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_socket_release(sdkctl); 1473c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1474c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return action; 1475c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1476c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1477c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/******************************************************************************** 1478c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * SDK Control Socket public API 1479c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *******************************************************************************/ 1480c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1481c8aa2c570d30098da59f1967d5158024ed28570dVladimir ChtchetkineSDKCtlSocket* 1482c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinesdkctl_socket_new(int reconnect_to, 1483c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine const char* service_name, 1484c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine on_sdkctl_connection_cb on_connection, 1485c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine on_sdkctl_handshake_cb on_handshake, 1486c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine on_sdkctl_message_cb on_message, 1487c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine void* opaque) 1488c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1489c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* sdkctl; 1490c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine ANEW0(sdkctl); 1491c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1492c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->state = SDKCTL_SOCKET_DISCONNECTED; 1493c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->opaque = opaque; 1494c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name = ASTRDUP(service_name); 1495c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->on_connection = on_connection; 1496c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->on_handshake = on_handshake; 1497c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->on_message = on_message; 1498c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->reconnect_to = reconnect_to; 1499c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->as = NULL; 1500c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->next_query_id = 0; 1501c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->query_head = sdkctl->query_tail = NULL; 1502c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->ref_count = 1; 1503c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->recycler = NULL; 1504c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->recycler_block_size = 0; 1505c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->recycler_max = 0; 1506c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->recycler_count = 0; 1507c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1508c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->looper = looper_newCore(); 1509c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->looper == NULL) { 1510c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine E("Unable to create I/O looper for SDKCtl socket '%s'", 1511c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine service_name); 1512c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine on_connection(opaque, sdkctl, ASIO_STATE_FAILED); 1513c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_free(sdkctl); 1514c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return NULL; 1515c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1516c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1517c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return sdkctl; 1518c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1519c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1520c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkineint sdkctl_socket_reference(SDKCtlSocket* sdkctl) 1521c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1522c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine assert(sdkctl->ref_count > 0); 1523c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->ref_count++; 1524c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return sdkctl->ref_count; 1525c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1526c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1527c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkineint 1528c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinesdkctl_socket_release(SDKCtlSocket* sdkctl) 1529c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1530c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine assert(sdkctl->ref_count > 0); 1531c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->ref_count--; 1532c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->ref_count == 0) { 1533c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Last reference has been dropped. Destroy this object. */ 1534c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_free(sdkctl); 1535c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return 0; 1536c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1537c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return sdkctl->ref_count; 1538c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1539c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1540c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinevoid 1541c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinesdkctl_init_recycler(SDKCtlSocket* sdkctl, 1542c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine uint32_t data_size, 1543c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine int max_recycled_num) 1544c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1545c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->recycler != NULL) { 1546c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine D("SDKCtl %s: Recycler is already initialized. Ignoring recycler init.", 1547c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name); 1548c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return; 1549c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1550c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1551c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* SDKCtlQuery is max descriptor sizeof. */ 1552c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine data_size += sizeof(SDKCtlQuery); 1553c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1554c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->recycler_block_size = data_size; 1555c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->recycler_max = max_recycled_num; 1556c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->recycler_count = 0; 1557c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1558c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1559c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinevoid 1560c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinesdkctl_socket_connect(SDKCtlSocket* sdkctl, int port, int retry_to) 1561c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1562c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("SDKCtl %s: Handling connect request to port %d, retrying in %dms...", 1563c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name, port, retry_to); 1564c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1565c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->state = SDKCTL_SOCKET_CONNECTING; 1566c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->as = async_socket_new(port, sdkctl->reconnect_to, 1567c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_async_socket_connection, sdkctl, 1568c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->looper); 1569c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->as == NULL) { 1570c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine E("Unable to allocate AsyncSocket for SDKCtl socket '%s'", 1571c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name); 1572c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->on_connection(sdkctl->opaque, sdkctl, ASIO_STATE_FAILED); 1573c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } else { 1574c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine async_socket_connect(sdkctl->as, retry_to); 1575c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1576c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1577c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1578c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinevoid 1579c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinesdkctl_socket_reconnect(SDKCtlSocket* sdkctl, int port, int retry_to) 1580c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1581c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("SDKCtl %s: Handling reconnection request to port %d, retrying in %dms...", 1582c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name, port, retry_to); 1583c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1584c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_disconnect_socket(sdkctl); 1585c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1586c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->as == NULL) { 1587c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_socket_connect(sdkctl, port, retry_to); 1588c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } else { 1589c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->state = SDKCTL_SOCKET_CONNECTING; 1590c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine async_socket_reconnect(sdkctl->as, retry_to); 1591c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1592c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1593c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1594c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinevoid 1595c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinesdkctl_socket_disconnect(SDKCtlSocket* sdkctl) 1596c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1597c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("SDKCtl %s: Handling disconnect request.", sdkctl->service_name); 1598c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1599c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_disconnect_socket(sdkctl); 1600c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1601c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1602c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1603c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/******************************************************************************** 1604c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Handshake query 1605c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *******************************************************************************/ 1606c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1607c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* A callback that is ivoked on handshake I/O events. */ 1608c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic AsyncIOAction 1609c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_handshake_io(void* query_opaque, 1610c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* query, 1611c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncIOState status) 1612c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1613c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* const sdkctl = (SDKCtlSocket*)query_opaque; 1614c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1615c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (status == ASIO_STATE_SUCCEEDED) { 1616c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine D("SDKCtl %s: %d bytes of handshake reply is received.", 1617c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name, *query->response_size); 1618c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1619c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Handshake is received. Inform the client. */ 1620c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->on_handshake(sdkctl->opaque, sdkctl, *query->response_buffer, 1621c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *query->response_size, status); 1622c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } else { 1623c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Something is going on with the handshake... */ 1624c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine switch (status) { 1625c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_FAILED: 1626c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_TIMED_OUT: 1627c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_CANCELLED: 1628c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine D("SDKCtl %s: Handshake failed: I/O state %d. Error: %d -> %s", 1629c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name, status, errno, strerror(errno)); 1630c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->on_handshake(sdkctl->opaque, sdkctl, 1631c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *query->response_buffer, 1632c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *query->response_size, status); 1633c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1634c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1635c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine default: 1636c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1637c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1638c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1639c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return ASIO_ACTION_DONE; 1640c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1641c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1642c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic AsyncIOAction 1643c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_sdkctl_endianness_io(void* io_opaque, 1644c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncSocketIO* asio, 1645c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncIOState status) { 1646c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* const sdkctl = (SDKCtlSocket*)io_opaque; 1647c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1648c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (status == ASIO_STATE_SUCCEEDED) { 1649c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Now it's time to initiate handshake message. */ 1650c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine D("SDKCtl %s: Sending handshake query...", sdkctl->service_name); 1651c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* query = 1652c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_build_and_send(sdkctl, SDKCTL_QUERY_HANDSHAKE, 1653c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine strlen(sdkctl->service_name), 1654c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name, NULL, NULL, 1655c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_handshake_io, sdkctl, 3000); 1656c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_release(query); 1657c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return ASIO_ACTION_DONE; 1658c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } else { 1659c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Something is going on with the endianness... */ 1660c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine switch (status) { 1661c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_FAILED: 1662c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_TIMED_OUT: 1663c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_CANCELLED: 1664c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine D("SDKCtl %s: endianness failed: I/O state %d. Error: %d -> %s", 1665c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name, status, errno, strerror(errno)); 1666c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->on_handshake(sdkctl->opaque, sdkctl, NULL, 0, status); 1667c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1668c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1669c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine default: 1670c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1671c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1672c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1673c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return ASIO_ACTION_DONE; 1674c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1675c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1676c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 1677c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_do_handshake(SDKCtlSocket* sdkctl) 1678c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1679c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#ifndef HOST_WORDS_BIGENDIAN 1680c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic const char _host_end = 0; 1681c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#else 1682c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic const char _host_end = 1; 1683c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#endif 1684c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1685c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine D("SDKCtl %s: Sending endianness: %d...", sdkctl->service_name, _host_end); 1686c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1687c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Before we can send any structured data to the SDK controller we need to 1688c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * report endianness of the host. */ 1689c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine async_socket_write_rel(sdkctl->as, &_host_end, 1, 1690c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_sdkctl_endianness_io, sdkctl, 3000); 1691c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1692