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 "android/utils/debug.h" 24c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#include "android/async-socket-connector.h" 25c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#include "android/async-socket.h" 26c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#include "android/sdk-controller-socket.h" 27c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#include "utils/panic.h" 28d413fa5f2916a2a46494edb320340486b262644cDavid 'Digit' Turner#include "android/iolooper.h" 29c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 30c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#define E(...) derror(__VA_ARGS__) 31c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#define W(...) dwarning(__VA_ARGS__) 32c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#define D(...) VERBOSE_PRINT(sdkctlsocket,__VA_ARGS__) 33c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#define D_ACTIVE VERBOSE_CHECK(sdkctlsocket) 34c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 357136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine#define TRACE_ON 0 36c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 37c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#if TRACE_ON 38c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#define T(...) VERBOSE_PRINT(sdkctlsocket,__VA_ARGS__) 39c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#else 40c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#define T(...) 41c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#endif 42c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 43c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Recycling memory descriptor. */ 44c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinetypedef struct SDKCtlRecycled SDKCtlRecycled; 45c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestruct SDKCtlRecycled { 46c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine union { 47c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Next recycled descriptor (while listed in recycler). */ 48c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlRecycled* next; 49c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Allocated memory size (while outside of the recycler). */ 50c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine uint32_t size; 51c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine }; 52c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine}; 53c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 54c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* 557136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * Types of the data packets sent via SDK controller socket. 56c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 57c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 58c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* The packet is a message. */ 59c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#define SDKCTL_PACKET_MESSAGE 1 60c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* The packet is a query. */ 61c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#define SDKCTL_PACKET_QUERY 2 62c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* The packet is a response to a query. */ 63c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#define SDKCTL_PACKET_QUERY_RESPONSE 3 64c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 657136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/* 667136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * Types of intenal port messages sent via SDK controller socket. 677136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine */ 687136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 697136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/* Port is connected. 707136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * This message is sent by SDK controller when the service connects a socket with 717136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * a port that provides requested emulation functionality. 727136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine */ 737136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine#define SDKCTL_MSG_PORT_CONNECTED -1 747136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/* Port is disconnected. 757136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * This message is sent by SDK controller when a port that provides requested 767136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * emulation functionality disconnects from the socket. 777136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine */ 787136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine#define SDKCTL_MSG_PORT_DISCONNECTED -2 797136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/* Port is enabled. 807136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * This message is sent by SDK controller when a port that provides requested 817136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * emulation functionality is ready to do the emulation. 827136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine */ 837136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine#define SDKCTL_MSG_PORT_ENABLED -3 847136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/* Port is disabled. 857136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * This message is sent by SDK controller when a port that provides requested 867136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * emulation functionality is not ready to do the emulation. 877136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine */ 887136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine#define SDKCTL_MSG_PORT_DISABLED -4 897136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 907136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/* 917136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * Types of internal queries sent via SDK controller socket. 927136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine */ 937136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 947136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/* Handshake query. 957136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * This query is sent to SDK controller service as part of the connection 967136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * protocol implementation. 977136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine */ 987136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine#define SDKCTL_QUERY_HANDSHAKE -1 997136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 1007136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/******************************************************************************** 1017136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * SDKCtlPacket declarations 1027136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine *******************************************************************************/ 1037136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 1047136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/* Packet signature value ('SDKC'). */ 1057136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkinestatic const int _sdkctl_packet_sig = 0x53444B43; 1067136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 107c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Data packet descriptor. 108c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * 109c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * All packets, sent and received via SDK controller socket begin with this 110c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * header, with packet data immediately following this header. 111c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 112c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinetypedef struct SDKCtlPacketHeader { 1137136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Signature. */ 1147136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine int signature; 115c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Total size of the data to transfer with this packet, including this 116c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * header. The transferring data should immediatelly follow this header. */ 117c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine int size; 118c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Encodes packet type. See SDKCTL_PACKET_XXX for the list of packet types 119c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * used by SDK controller. */ 120c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine int type; 121c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} SDKCtlPacketHeader; 122c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 123c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Packet descriptor, allocated by this API for data packets to be sent to SDK 1247136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * controller. 125c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * 126c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * When packet descriptors are allocated by this API, they are allocated large 127c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * enough to contain this header, and packet data to send to the service, 128c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * immediately following this descriptor. 129c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 1307136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkinetypedef struct SDKCtlPacket { 131c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Supports recycling. Don't put anything in front: recycler expects this 132c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * to be the first field in recyclable descriptor. */ 1337136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCtlRecycled recycling; 134c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 135c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* SDK controller socket that transmits this packet. */ 1367136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCtlSocket* sdkctl; 137c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Number of outstanding references to the packet. */ 1387136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine int ref_count; 139c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 140c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Common packet header. Packet data immediately follows this header, so it 1417136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * must be the last field in SDKCtlPacket descriptor. */ 1427136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCtlPacketHeader header; 1437136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine} SDKCtlPacket; 144c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 145c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/******************************************************************************** 1467136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * SDKCtlDirectPacket declarations 147c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *******************************************************************************/ 148c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1497136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/* Direct packet descriptor, allocated by this API for direct data packets to be 1507136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * sent to SDK controller service on the device. 1517136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * 1527136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * Direct packet (unlike SDKCtlPacket) don't contain data buffer, but rather 1537136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * reference data allocated by the client. This is useful when client sends large 1547136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * amount of data (such as framebuffer updates sent my multi-touch port), and 1557136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * regular packet descriptors for such large transfer cannot be obtained from the 1567136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * recycler. 157c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 1587136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkinestruct SDKCtlDirectPacket { 1597136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Supports recycling. Don't put anything in front: recycler expects this 1607136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * to be the first field in recyclable descriptor. */ 1617136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCtlRecycled recycling; 162c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1637136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* SDKCtlSocket that owns this packet. */ 1647136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCtlSocket* sdkctl; 1657136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Packet to send. */ 1667136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCtlPacketHeader* packet; 1677136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Callback to invoke on packet transmission events. */ 1687136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine on_sdkctl_direct_cb on_sent; 1697136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* An opaque pointer to pass to on_sent callback. */ 1707136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine void* on_sent_opaque; 1717136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Number of outstanding references to the packet. */ 1727136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine int ref_count; 1737136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine}; 1747136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 1757136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/******************************************************************************** 1767136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * SDKCtlQuery declarations 1777136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine *******************************************************************************/ 178c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 179c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Query packet descriptor. 180c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * 181c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * All queries, sent and received via SDK controller socket begin with this 182c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * header, with query data immediately following this header. 183c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 184c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinetypedef struct SDKCtlQueryHeader { 185c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Data packet header for this query. */ 186c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlPacketHeader packet; 187c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* A unique query identifier. This ID is used to track the query in the 188c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * asynchronous environment in whcih SDK controller socket operates. */ 189c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine int query_id; 1907136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Query type. */ 191c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine int query_type; 192c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} SDKCtlQueryHeader; 193c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 194c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Query descriptor, allocated by this API for queries to be sent to SDK 195c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * controller service on the device. 196c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * 197c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * When query descriptors are allocated by this API, they are allocated large 198c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * enough to contain this header, and query data to send to the service, 199c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * immediately following this descriptor. 200c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 201c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestruct SDKCtlQuery { 202c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Supports recycling. Don't put anything in front: recycler expects this 203c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * to be the first field in recyclable descriptor. */ 204c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlRecycled recycling; 205c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 2067136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Next query in the list of active queries. */ 207c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* next; 208c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* A timer to run time out on this query after it has been sent. */ 209c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine LoopTimer timer[1]; 210c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Absolute time for this query's deadline. This is the value that query's 2117136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * timer is set to after query has been transmitted to the service. */ 212c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine Duration deadline; 213c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* SDK controller socket that owns the query. */ 214c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* sdkctl; 215c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* A callback to invoke on query state changes. */ 216c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine on_sdkctl_query_cb query_cb; 217c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* An opaque pointer associated with this query. */ 218c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine void* query_opaque; 219c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Points to an address of a buffer where to save query response. */ 220c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine void** response_buffer; 2217136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Points to a variable containing size of the response buffer (on the way 2227136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * in), or actual query response size (when query is completed). */ 223c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine uint32_t* response_size; 224c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Internal response buffer, allocated if query creator didn't provide its 225c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * own. This field is valid only if response_buffer field is NULL, or is 226c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * pointing to this field. */ 227c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine void* internal_resp_buffer; 2287136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Internal response buffer size used if query creator didn't provide its 2297136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * own. This field is valid only if response_size field is NULL, or is 2307136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * pointing to this field. */ 231c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine uint32_t internal_resp_size; 232c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Number of outstanding references to the query. */ 233c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine int ref_count; 234c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 2357136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Common query header. Query data immediately follows this header, so it 236c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * must be last field in SDKCtlQuery descriptor. */ 237c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQueryHeader header; 238c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine}; 239c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 240c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Query reply descriptor. 241c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * 242c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * All replies to a query, sent and received via SDK controller socket begin with 243c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * this header, with query reply data immediately following this header. 244c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 245c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinetypedef struct SDKCtlQueryReplyHeader { 246c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Data packet header for this reply. */ 247c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlPacketHeader packet; 248c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 249c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* An identifier for the query that is addressed with this reply. */ 250c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine int query_id; 251c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} SDKCtlQueryReplyHeader; 252c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 253c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/******************************************************************************** 2547136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * SDKCtlMessage declarations 2557136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine *******************************************************************************/ 2567136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 2577136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/* Message packet descriptor. 2587136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * 2597136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * All messages, sent and received via SDK controller socket begin with this 2607136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * header, with message data immediately following this header. 2617136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine */ 2627136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkinetypedef struct SDKCtlMessageHeader { 2637136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Data packet header for this query. */ 2647136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCtlPacketHeader packet; 2657136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Message type. */ 2667136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine int msg_type; 2677136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine} SDKCtlMessageHeader; 2687136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 2697136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/* Message packet descriptor. 2707136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * 2717136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * All messages, sent and received via SDK controller socket begin with this 2727136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * header, with message data immediately following this header. 2737136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine */ 2744732aee0622005bc612f75d0319e6e3a057301b4Vladimir Chtchetkinestruct SDKCtlMessage { 2757136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Data packet descriptor for this message. */ 2767136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCtlPacket packet; 2777136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Message type. */ 2787136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine int msg_type; 2794732aee0622005bc612f75d0319e6e3a057301b4Vladimir Chtchetkine}; 2807136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 2817136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/******************************************************************************** 282c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * SDK Control Socket declarations 283c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *******************************************************************************/ 284c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 285c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Enumerates SDKCtlSocket states. */ 286c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinetypedef enum SDKCtlSocketState { 287c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Socket is disconnected from SDK controller. */ 288c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCTL_SOCKET_DISCONNECTED, 289c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Connection to SDK controller is in progress. */ 290c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCTL_SOCKET_CONNECTING, 291c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Socket is connected to an SDK controller service. */ 292c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCTL_SOCKET_CONNECTED 293c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} SDKCtlSocketState; 294c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 295c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Enumerates SDKCtlSocket I/O dispatcher states. */ 296c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinetypedef enum SDKCtlIODispatcherState { 297c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* I/O dispatcher expects a packet header. */ 298c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCTL_IODISP_EXPECT_HEADER, 299c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* I/O dispatcher expects packet data. */ 300c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCTL_IODISP_EXPECT_DATA, 301c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* I/O dispatcher expects query response header. */ 302c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCTL_IODISP_EXPECT_QUERY_REPLY_HEADER, 303c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* I/O dispatcher expects query response data. */ 304c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCTL_IODISP_EXPECT_QUERY_REPLY_DATA, 305c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} SDKCtlIODispatcherState; 306c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 307c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* SDKCtlSocket I/O dispatcher descriptor. */ 308c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinetypedef struct SDKCtlIODispatcher { 309c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* SDKCtlSocket instance for this dispatcher. */ 310c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* sdkctl; 311c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Dispatcher state. */ 312c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlIODispatcherState state; 313c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Unites all types of headers used in SDK controller data exchange. */ 314c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine union { 315c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Common packet header. */ 3167136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCtlPacketHeader packet_header; 317c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Header for a query packet. */ 318c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQueryHeader query_header; 3197136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Header for a message packet. */ 3207136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCtlMessageHeader message_header; 321c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Header for a query response packet. */ 322c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQueryReplyHeader query_reply_header; 323c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine }; 3247136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Descriptor of a packet that is being received from SDK controller. */ 325c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlPacket* packet; 326c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* A query for which a reply is currently being received. */ 327c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* current_query; 328c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} SDKCtlIODispatcher; 329c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 330c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* SDK controller socket descriptor. */ 331c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestruct SDKCtlSocket { 332c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* SDK controller socket state */ 3337136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCtlSocketState state; 3347136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* SDK controller port status */ 3357136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SdkCtlPortStatus port_status; 336c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* I/O dispatcher for the socket. */ 3377136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCtlIODispatcher io_dispatcher; 338c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Asynchronous socket connected to SDK Controller on the device. */ 3397136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine AsyncSocket* as; 340c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Client callback that monitors this socket connection. */ 3417136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine on_sdkctl_socket_connection_cb on_socket_connection; 3427136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Client callback that monitors SDK controller prt connection. */ 3437136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine on_sdkctl_port_connection_cb on_port_connection; 344c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* A callback to invoke when a message is received from the SDK controller. */ 3457136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine on_sdkctl_message_cb on_message; 346c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* An opaque pointer associated with this socket. */ 3477136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine void* opaque; 3487136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Name of an SDK controller port this socket is connected to. */ 3497136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine char* service_name; 350c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* I/O looper for timers. */ 3517136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine Looper* looper; 352c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Head of the active query list. */ 3537136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCtlQuery* query_head; 354c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Tail of the active query list. */ 3557136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCtlQuery* query_tail; 356c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Query ID generator that gets incremented for each new query. */ 3577136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine int next_query_id; 358c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Timeout before trying to reconnect after disconnection. */ 3597136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine int reconnect_to; 360c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Number of outstanding references to this descriptor. */ 3617136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine int ref_count; 362c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Head of the recycled memory */ 3637136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCtlRecycled* recycler; 364c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Recyclable block size. */ 3657136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine uint32_t recycler_block_size; 366c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Maximum number of blocks to recycle. */ 3677136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine int recycler_max; 368c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Number of blocs in the recycler. */ 3697136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine int recycler_count; 370c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine}; 371c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 372c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/******************************************************************************** 373c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * SDKCtlSocket recycling management 374c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *******************************************************************************/ 375c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 376c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Gets a recycled block for a given SDKCtlSocket, or allocates new memory 377c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * block. */ 378c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void* 379c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_socket_alloc_recycler(SDKCtlSocket* sdkctl, uint32_t size) 380c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 381c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlRecycled* block = NULL; 382c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 383c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->recycler != NULL && size <= sdkctl->recycler_block_size) { 3847136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine assert(sdkctl->recycler_count > 0); 385c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* There are blocks in the recycler, and requested size fits. */ 386c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine block = sdkctl->recycler; 387c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->recycler = block->next; 388c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine block->size = sdkctl->recycler_block_size; 389c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->recycler_count--; 390c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } else if (size <= sdkctl->recycler_block_size) { 3917136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* There are no blocks in the recycler, but requested size fits. Lets 3927136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * allocate block that we can later recycle. */ 393c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine block = malloc(sdkctl->recycler_block_size); 394c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (block == NULL) { 3957136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine APANIC("SDKCtl %s: Unable to allocate %d bytes block.", 396c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name, sdkctl->recycler_block_size); 397c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 398c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine block->size = sdkctl->recycler_block_size; 399c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } else { 400c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Requested size doesn't fit the recycler. */ 401c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine block = malloc(size); 402c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (block == NULL) { 403c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine APANIC("SDKCtl %s: Unable to allocate %d bytes block", 404c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name, size); 405c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 406c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine block->size = size; 407c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 408c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 409c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return block; 410c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 411c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 412c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Recycles, or frees a block of memory for a given SDKCtlSocket. */ 413c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 414c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_socket_free_recycler(SDKCtlSocket* sdkctl, void* mem) 415c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 4167136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCtlRecycled* const block = (SDKCtlRecycled*)mem; 417c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 4187136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine if (block->size != sdkctl->recycler_block_size || 4197136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->recycler_count == sdkctl->recycler_max) { 4207136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Recycler is full, or block cannot be recycled. Just free the memory. */ 421c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine free(mem); 4227136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine } else { 4237136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Add that block to the recycler. */ 4247136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine assert(sdkctl->recycler_count >= 0); 4257136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine block->next = sdkctl->recycler; 4267136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->recycler = block; 4277136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->recycler_count++; 428c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 429c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 430c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 431c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Empties the recycler for a given SDKCtlSocket. */ 432c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 433c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_socket_empty_recycler(SDKCtlSocket* sdkctl) 434c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 435c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlRecycled* block = sdkctl->recycler; 436c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine while (block != NULL) { 4377136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine void* const to_free = block; 438c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine block = block->next; 439c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine free(to_free); 440c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 441c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->recycler = NULL; 442c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->recycler_count = 0; 443c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 444c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 445c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/******************************************************************************** 446c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * SDKCtlSocket query list management 447c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *******************************************************************************/ 448c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 449c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Adds a query to the list of active queries. 450c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Param: 451c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * sdkctl - SDKCtlSocket instance for the query. 452c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * query - Query to add to the list. 453c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 454c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 455c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_socket_add_query(SDKCtlQuery* query) 456c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 457c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* const sdkctl = query->sdkctl; 458c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->query_head == NULL) { 4597136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine assert(sdkctl->query_tail == NULL); 460c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->query_head = sdkctl->query_tail = query; 461c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } else { 462c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->query_tail->next = query; 463c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->query_tail = query; 464c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 465c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 466c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Keep the query referenced while it's in the list. */ 467c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_reference(query); 468c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 469c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 470c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Removes a query from the list of active queries. 471c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Param: 4727136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * query - Query to remove from the list of active queries. If query has been 4737136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * removed from the list, it will be dereferenced to offset the reference 4747136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * that wad made when the query has been added to the list. 475c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Return: 476c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Boolean: 1 if query has been removed, or 0 if query has not been found in the 477c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * list of active queries. 478c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 479c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic int 480c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_socket_remove_query(SDKCtlQuery* query) 481c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 482c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* const sdkctl = query->sdkctl; 483c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* prev = NULL; 484c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* head = sdkctl->query_head; 485c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 4867136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Quick check: the query could be currently handled by the dispatcher. */ 487c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->io_dispatcher.current_query == query) { 488c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Release the query from dispatcher. */ 489c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->io_dispatcher.current_query = NULL; 4907136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl_query_release(query); 491c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return 1; 492c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 493c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 494c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Remove query from the list. */ 495c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine while (head != NULL && query != head) { 496c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine prev = head; 497c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine head = head->next; 498c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 4997136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine if (head == NULL) { 5007136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine D("SDKCtl %s: Query %p is not found in the list.", 5017136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->service_name, query); 5027136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine return 0; 5037136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine } 504c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 5057136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine if (prev == NULL) { 5067136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Query is at the head of the list. */ 5077136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine assert(query == sdkctl->query_head); 5087136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->query_head = query->next; 509c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } else { 5107136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Query is in the middle / at the end of the list. */ 5117136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine assert(query != sdkctl->query_head); 5127136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine prev->next = query->next; 513c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 5147136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine if (sdkctl->query_tail == query) { 5157136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Query is at the tail of the list. */ 5167136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine assert(query->next == NULL); 5177136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->query_tail = prev; 5187136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine } 5197136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine query->next = NULL; 5207136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 5217136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Release query that is now removed from the list. Note that query 5227136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * passed to this routine should hold an extra reference, owned by the 5237136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * caller. */ 5247136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl_query_release(query); 5257136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 5267136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine return 1; 527c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 528c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 529c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Removes a query (based on query ID) from the list of active queries. 530c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Param: 531c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * sdkctl - SDKCtlSocket instance that owns the query. 532c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * query_id - Identifies the query to remove. 533c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Return: 534c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * A query removed from the list of active queries, or NULL if query with the 5357136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * given ID has not been found in the list. Note that query returned from this 5367136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * routine still holds the reference made when the query has been added to the 5377136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * list. 538c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 539c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic SDKCtlQuery* 540c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_socket_remove_query_id(SDKCtlSocket* sdkctl, int query_id) 541c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 5427136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCtlQuery* query = NULL; 543c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* prev = NULL; 544c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* head = sdkctl->query_head; 545c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 546c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Quick check: the query could be currently handled by dispatcher. */ 547c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->io_dispatcher.current_query != NULL && 548c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->io_dispatcher.current_query->header.query_id == query_id) { 549c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Release the query from dispatcher. */ 5507136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine query = sdkctl->io_dispatcher.current_query; 551c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->io_dispatcher.current_query = NULL; 552c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return query; 553c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 554c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 555c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Remove query from the list. */ 556c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine while (head != NULL && head->header.query_id != query_id) { 557c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine prev = head; 558c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine head = head->next; 559c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 5607136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine if (head == NULL) { 5617136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine D("SDKCtl %s: Query ID %d is not found in the list.", 562c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name, query_id); 563c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return NULL; 564c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 5657136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 5667136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Query is found in the list. */ 5677136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine query = head; 5687136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine if (prev == NULL) { 5697136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Query is at the head of the list. */ 5707136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine assert(query == sdkctl->query_head); 5717136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->query_head = query->next; 5727136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine } else { 5737136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Query is in the middle, or at the end of the list. */ 5747136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine assert(query != sdkctl->query_head); 5757136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine prev->next = query->next; 5767136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine } 5777136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine if (sdkctl->query_tail == query) { 5787136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Query is at the tail of the list. */ 5797136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine assert(query->next == NULL); 5807136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->query_tail = prev; 5817136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine } 5827136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine query->next = NULL; 5837136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 5847136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine return query; 585c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 586c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 587c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Pulls the first query from the list of active queries. 588c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Param: 589c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * sdkctl - SDKCtlSocket instance that owns the query. 590c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Return: 5917136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * A query removed from the head of the list of active queries, or NULL if query 592c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * list is empty. 593c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 594c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic SDKCtlQuery* 595c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_socket_pull_first_query(SDKCtlSocket* sdkctl) 596c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 597c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* const query = sdkctl->query_head; 598c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 599c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (query != NULL) { 600c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->query_head = query->next; 601c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->query_head == NULL) { 602c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->query_tail = NULL; 603c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 604c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 605c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return query; 606c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 607c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 608c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Generates new query ID for the given SDKCtl. */ 609c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic int 610c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_socket_next_query_id(SDKCtlSocket* sdkctl) 611c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 612c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return ++sdkctl->next_query_id; 613c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 614c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 615c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/******************************************************************************** 616c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * SDKCtlPacket implementation 617c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *******************************************************************************/ 618c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 619c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Alocates a packet. */ 620c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic SDKCtlPacket* 6217136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine_sdkctl_packet_new(SDKCtlSocket* sdkctl, uint32_t size, int type) 622c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 6237136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Allocate packet descriptor large enough to contain packet data. */ 6247136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCtlPacket* const packet = 6257136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine _sdkctl_socket_alloc_recycler(sdkctl, sizeof(SDKCtlPacket) + size); 626c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 6277136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine packet->sdkctl = sdkctl; 6287136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine packet->ref_count = 1; 6297136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine packet->header.signature = _sdkctl_packet_sig; 6307136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine packet->header.size = size; 6317136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine packet->header.type = type; 632c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 633c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Refence SDKCTlSocket that owns this packet. */ 634c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_socket_reference(sdkctl); 635c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 6367136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine T("SDKCtl %s: Packet %p of type %d is allocated for %d bytes transfer.", 6377136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->service_name, packet, type, size); 6387136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 639c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return packet; 640c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 641c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 642c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Frees a packet. */ 643c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 644c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_packet_free(SDKCtlPacket* packet) 645c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 646c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* const sdkctl = packet->sdkctl; 647c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 6487136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Recycle packet. */ 649c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_free_recycler(packet->sdkctl, packet); 650c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 6517136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine T("SDKCtl %s: Packet %p is freed.", sdkctl->service_name, packet); 6527136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 653c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Release SDKCTlSocket that owned this packet. */ 654c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_socket_release(sdkctl); 655c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 656c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 6577136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/* References a packet. */ 658c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkineint 6597136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine_sdkctl_packet_reference(SDKCtlPacket* packet) 660c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 661c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine assert(packet->ref_count > 0); 662c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine packet->ref_count++; 663c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return packet->ref_count; 664c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 665c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 6667136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/* Releases a packet. */ 667c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkineint 6687136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine_sdkctl_packet_release(SDKCtlPacket* packet) 669c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 670c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine assert(packet->ref_count > 0); 671c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine packet->ref_count--; 672c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (packet->ref_count == 0) { 673c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Last reference has been dropped. Destroy this object. */ 674c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_packet_free(packet); 675c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return 0; 676c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 677c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return packet->ref_count; 678c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 679c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 6807136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/* An I/O callback invoked on packet transmission. 6817136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * Param: 6827136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * io_opaque SDKCtlPacket instance of the packet that's being sent with this I/O. 6837136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * asio - Write I/O descriptor. 6847136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * status - I/O status. 6857136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine */ 6867136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkinestatic AsyncIOAction 6877136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine_on_sdkctl_packet_send_io(void* io_opaque, 6887136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine AsyncSocketIO* asio, 6897136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine AsyncIOState status) 6907136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine{ 6917136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCtlPacket* const packet = (SDKCtlPacket*)io_opaque; 6927136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine AsyncIOAction action = ASIO_ACTION_DONE; 6937136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 6947136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Reference the packet while we're in this callback. */ 6957136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine _sdkctl_packet_reference(packet); 6967136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 6977136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Lets see what's going on with query transmission. */ 6987136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine switch (status) { 6997136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine case ASIO_STATE_SUCCEEDED: 7007136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Packet has been sent to the service. */ 7017136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine T("SDKCtl %s: Packet %p transmission has succeeded.", 7027136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine packet->sdkctl->service_name, packet); 7037136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine break; 7047136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 7057136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine case ASIO_STATE_CANCELLED: 7067136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine T("SDKCtl %s: Packet %p is cancelled.", 7077136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine packet->sdkctl->service_name, packet); 7087136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine break; 7097136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 7107136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine case ASIO_STATE_FAILED: 7117136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine T("SDKCtl %s: Packet %p has failed: %d -> %s", 7127136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine packet->sdkctl->service_name, packet, errno, strerror(errno)); 7137136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine break; 7147136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 7157136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine case ASIO_STATE_FINISHED: 7167136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Time to disassociate the packet with the I/O. */ 7177136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine _sdkctl_packet_release(packet); 7187136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine break; 7197136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 7207136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine default: 7217136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Transitional state. */ 7227136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine break; 7237136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine } 7247136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 7257136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine _sdkctl_packet_release(packet); 7267136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 7277136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine return action; 7287136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine} 7297136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 7307136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/* Transmits a packet to SDK Controller. 7317136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * Param: 7327136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * packet - Packet to transmit. 7337136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine */ 7347136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkinestatic void 7357136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine_sdkctl_packet_transmit(SDKCtlPacket* packet) 7367136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine{ 7377136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine assert(packet->header.signature == _sdkctl_packet_sig); 7387136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 7397136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Reference to associate with the I/O */ 7407136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine _sdkctl_packet_reference(packet); 7417136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 7427136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Transmit the packet to SDK controller. */ 7437136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine async_socket_write_rel(packet->sdkctl->as, &packet->header, packet->header.size, 7447136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine _on_sdkctl_packet_send_io, packet, -1); 7457136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 7467136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine T("SDKCtl %s: Packet %p size %d is being sent.", 7477136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine packet->sdkctl->service_name, packet, packet->header.size); 7487136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine} 7497136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 7507136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/******************************************************************************** 7517136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * SDKCtlDirectPacket implementation 7527136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine ********************************************************************************/ 7537136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 7547136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir ChtchetkineSDKCtlDirectPacket* 7557136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkinesdkctl_direct_packet_new(SDKCtlSocket* sdkctl) 7567136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine{ 7577136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCtlDirectPacket* const packet = 7587136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine _sdkctl_socket_alloc_recycler(sdkctl, sizeof(SDKCtlDirectPacket)); 7597136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 7607136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine packet->sdkctl = sdkctl; 7617136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine packet->ref_count = 1; 7627136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 7637136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Refence SDKCTlSocket that owns this packet. */ 7647136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl_socket_reference(packet->sdkctl); 7657136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 7667136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine T("SDKCtl %s: Direct packet %p is allocated.", sdkctl->service_name, packet); 7677136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 7687136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine return packet; 7697136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine} 7707136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 7717136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/* Frees a direct packet. */ 7727136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkinestatic void 7737136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine_sdkctl_direct_packet_free(SDKCtlDirectPacket* packet) 7747136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine{ 7757136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCtlSocket* const sdkctl = packet->sdkctl; 7767136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 7777136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Free allocated resources. */ 7787136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine _sdkctl_socket_free_recycler(packet->sdkctl, packet); 7797136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 7807136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine T("SDKCtl %s: Direct packet %p is freed.", sdkctl->service_name, packet); 7817136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 7827136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Release SDKCTlSocket that owned this packet. */ 7837136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl_socket_release(sdkctl); 7847136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine} 7857136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 7867136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/* References a packet. */ 7877136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkineint 7887136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkinesdkctl_direct_packet_reference(SDKCtlDirectPacket* packet) 7897136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine{ 7907136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine assert(packet->ref_count > 0); 7917136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine packet->ref_count++; 7927136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine return packet->ref_count; 7937136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine} 7947136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 7957136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/* Releases a packet. */ 7967136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkineint 7977136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkinesdkctl_direct_packet_release(SDKCtlDirectPacket* packet) 7987136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine{ 7997136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine assert(packet->ref_count > 0); 8007136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine packet->ref_count--; 8017136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine if (packet->ref_count == 0) { 8027136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Last reference has been dropped. Destroy this object. */ 8037136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine _sdkctl_direct_packet_free(packet); 8047136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine return 0; 8057136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine } 8067136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine return packet->ref_count; 8077136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine} 8087136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 8097136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/* An I/O callback invoked on direct packet transmission. 8107136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * Param: 8117136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * io_opaque SDKCtlDirectPacket instance of the packet that's being sent with 8127136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * this I/O. 8137136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * asio - Write I/O descriptor. 8147136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * status - I/O status. 8157136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine */ 8167136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkinestatic AsyncIOAction 8177136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine_on_sdkctl_direct_packet_send_io(void* io_opaque, 8187136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine AsyncSocketIO* asio, 8197136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine AsyncIOState status) 8207136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine{ 8217136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCtlDirectPacket* const packet = (SDKCtlDirectPacket*)io_opaque; 8227136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine AsyncIOAction action = ASIO_ACTION_DONE; 8237136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 8247136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Reference the packet while we're in this callback. */ 8257136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl_direct_packet_reference(packet); 8267136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 8277136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Lets see what's going on with query transmission. */ 8287136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine switch (status) { 8297136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine case ASIO_STATE_SUCCEEDED: 8307136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Packet has been sent to the service. */ 8317136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine T("SDKCtl %s: Direct packet %p transmission has succeeded.", 8327136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine packet->sdkctl->service_name, packet); 8337136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine packet->on_sent(packet->on_sent_opaque, packet, status); 8347136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine break; 8357136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 8367136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine case ASIO_STATE_CANCELLED: 8377136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine T("SDKCtl %s: Direct packet %p is cancelled.", 8387136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine packet->sdkctl->service_name, packet); 8397136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine packet->on_sent(packet->on_sent_opaque, packet, status); 8407136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine break; 8417136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 8427136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine case ASIO_STATE_FAILED: 8437136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine T("SDKCtl %s: Direct packet %p has failed: %d -> %s", 8447136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine packet->sdkctl->service_name, packet, errno, strerror(errno)); 8457136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine packet->on_sent(packet->on_sent_opaque, packet, status); 8467136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine break; 8477136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 8487136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine case ASIO_STATE_FINISHED: 8497136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Time to disassociate with the I/O. */ 8507136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl_direct_packet_release(packet); 8517136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine break; 8527136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 8537136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine default: 8547136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Transitional state. */ 8557136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine break; 8567136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine } 8577136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 8587136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl_direct_packet_release(packet); 8597136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 8607136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine return action; 8617136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine} 8627136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 8637136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkinevoid 8647136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkinesdkctl_direct_packet_send(SDKCtlDirectPacket* packet, 8657136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine void* data, 8667136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine on_sdkctl_direct_cb cb, 8677136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine void* cb_opaque) 8687136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine{ 8697136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine packet->packet = (SDKCtlPacketHeader*)data; 8707136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine packet->on_sent = cb; 8717136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine packet->on_sent_opaque = cb_opaque; 8727136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine assert(packet->packet->signature == _sdkctl_packet_sig); 8737136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 8747136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Reference for I/O */ 8757136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl_direct_packet_reference(packet); 8767136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 8777136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Transmit the packet to SDK controller. */ 8787136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine async_socket_write_rel(packet->sdkctl->as, packet->packet, packet->packet->size, 8797136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine _on_sdkctl_direct_packet_send_io, packet, -1); 8807136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 8817136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine T("SDKCtl %s: Direct packet %p size %d is being sent", 8827136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine packet->sdkctl->service_name, packet, packet->packet->size); 8837136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine} 8847136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 8857136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/******************************************************************************** 8867136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * SDKCtlMessage implementation 8877136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine *******************************************************************************/ 8887136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 8897136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/* Alocates a message descriptor. */ 8907136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkinestatic SDKCtlMessage* 8917136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine_sdkctl_message_new(SDKCtlSocket* sdkctl, uint32_t msg_size, int msg_type) 8927136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine{ 8937136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCtlMessage* const msg = 8947136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine (SDKCtlMessage*)_sdkctl_packet_new(sdkctl, 8957136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sizeof(SDKCtlMessageHeader) + msg_size, 8967136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCTL_PACKET_MESSAGE); 8977136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine msg->msg_type = msg_type; 8987136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 8997136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine return msg; 9007136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine} 9017136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 9027136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkineint 9037136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkinesdkctl_message_reference(SDKCtlMessage* msg) 9047136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine{ 9057136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine return _sdkctl_packet_reference(&msg->packet); 9067136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine} 9077136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 9087136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkineint 9097136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkinesdkctl_message_release(SDKCtlMessage* msg) 9107136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine{ 9117136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine return _sdkctl_packet_release(&msg->packet); 9127136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine} 9137136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 9147136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir ChtchetkineSDKCtlMessage* 9157136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkinesdkctl_message_send(SDKCtlSocket* sdkctl, 9167136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine int msg_type, 9177136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine const void* data, 9187136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine uint32_t size) 9197136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine{ 9207136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCtlMessage* const msg = _sdkctl_message_new(sdkctl, size, msg_type); 9217136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine if (size != 0 && data != NULL) { 9227136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine memcpy(msg + 1, data, size); 9237136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine } 9247136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine _sdkctl_packet_transmit(&msg->packet); 9257136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 9267136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine return msg; 9277136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine} 9287136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 9297136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkineint 9307136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkinesdkctl_message_get_header_size(void) 9317136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine{ 9327136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine return sizeof(SDKCtlMessageHeader); 9337136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine} 9347136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 9357136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkinevoid 9367136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkinesdkctl_init_message_header(void* msg, int msg_type, int msg_size) 9377136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine{ 9387136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCtlMessageHeader* const msg_header = (SDKCtlMessageHeader*)msg; 9397136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 9407136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine msg_header->packet.signature = _sdkctl_packet_sig; 9417136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine msg_header->packet.size = sizeof(SDKCtlMessageHeader) + msg_size; 9427136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine msg_header->packet.type = SDKCTL_PACKET_MESSAGE; 9437136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine msg_header->msg_type = msg_type; 9447136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine} 9457136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 946c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/******************************************************************************** 947c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * SDKCtlQuery implementation 948c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *******************************************************************************/ 949c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 950c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Frees query descriptor. */ 951c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 952c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_query_free(SDKCtlQuery* query) 953c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 954c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (query != NULL) { 955c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* const sdkctl = query->sdkctl; 956c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (query->internal_resp_buffer != NULL && 957c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine (query->response_buffer == NULL || 958c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->response_buffer == &query->internal_resp_buffer)) { 9597136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* This query used its internal buffer to receive the response. 9607136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * Free it. */ 961c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine free(query->internal_resp_buffer); 962c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 963c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 964c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine loopTimer_done(query->timer); 9657136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 9667136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Recyle the descriptor. */ 967c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_free_recycler(sdkctl, query); 968c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 9697136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine T("SDKCtl %s: Query %p is freed.", sdkctl->service_name, query); 9707136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 971c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Release socket that owned this query. */ 972c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_socket_release(sdkctl); 973c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 974c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 975c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 976c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Cancels timeout for the query. 977c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * 978c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * For the simplicity of implementation, the dispatcher will cancel query timer 979c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * when query response data begins to flow in. If we let the timer to expire at 980c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * that stage, we will end up with data flowing in without real place to 981c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * accomodate it. 982c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 983c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 984c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_query_cancel_timeout(SDKCtlQuery* query) 985c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 986c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine loopTimer_stop(query->timer); 987c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 9887136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine T("SDKCtl %s: Query %p ID %d deadline %lld is cancelled.", 9897136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine query->sdkctl->service_name, query, query->header.query_id, query->deadline); 990c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 991c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 992c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* 993c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Query I/O callbacks. 994c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 995c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 996c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Callback that is invoked by the I/O dispatcher when query is successfuly 997c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * completed (i.e. response to the query is received). 998c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 999c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 1000c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_sdkctl_query_completed(SDKCtlQuery* query) 1001c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1002c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("SDKCtl %s: Query %p ID %d is completed.", 1003c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->sdkctl->service_name, query, query->header.query_id); 1004c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1005c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Cancel deadline, and inform the client about query completion. */ 1006c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_query_cancel_timeout(query); 1007c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->query_cb(query->query_opaque, query, ASIO_STATE_SUCCEEDED); 1008c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1009c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1010c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* A callback that is invoked on query cancellation. */ 1011c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 1012c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_sdkctl_query_cancelled(SDKCtlQuery* query) 1013c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1014c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* 1015c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Query cancellation means that SDK controller is disconnected. In turn, 1016c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * this means that SDK controller socket will handle disconnection in its 1017c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * connection callback. So, at this point all we need to do here is to inform 10187136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * the client about query cancellation. 1019c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 1020c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1021c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Cancel deadline, and inform the client about query cancellation. */ 1022c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_query_cancel_timeout(query); 1023c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->query_cb(query->query_opaque, query, ASIO_STATE_CANCELLED); 1024c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1025c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1026c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* A timer callback that is invoked on query timeout. 1027c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Param: 1028c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * opaque - SDKCtlQuery instance. 1029c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 1030c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 1031c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_skdctl_query_timeout(void* opaque) 1032c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1033c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* const query = (SDKCtlQuery*)opaque; 1034c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1035c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine D("SDKCtl %s: Query %p ID %d with deadline %lld has timed out at %lld", 1036c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->sdkctl->service_name, query, query->header.query_id, 1037c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->deadline, async_socket_deadline(query->sdkctl->as, 0)); 1038c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1039c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Reference the query while we're in this callback. */ 1040c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_reference(query); 1041c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1042c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Inform the client about deadline expiration. Note that client may 1043c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * extend the deadline, and retry the query. */ 1044c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine const AsyncIOAction action = 1045c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->query_cb(query->query_opaque, query, ASIO_STATE_TIMED_OUT); 1046c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1047c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* For actions other than retry we will destroy the query. */ 1048c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (action != ASIO_ACTION_RETRY) { 1049c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_remove_query(query); 1050c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1051c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1052c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_release(query); 1053c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1054c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 10557136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/* A callback that is invoked when query has been sent to the SDK controller. */ 1056c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 1057c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_sdkctl_query_sent(SDKCtlQuery* query) 1058c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 10597136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine T("SDKCtl %s: Sent %d bytes of query %p ID %d of type %d", 1060c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->sdkctl->service_name, query->header.packet.size, query, 1061c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->header.query_id, query->header.query_type); 1062c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1063c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Inform the client about the event. */ 1064c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->query_cb(query->query_opaque, query, ASIO_STATE_CONTINUES); 1065c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1066c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Set a timer to expire at query's deadline, and let the response to come 1067c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * through the dispatcher loop. */ 1068c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine loopTimer_startAbsolute(query->timer, query->deadline); 1069c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1070c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1071c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* An I/O callback invoked on query transmission. 1072c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Param: 1073c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * io_opaque SDKCtlQuery instance of the query that's being sent with this I/O. 1074c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * asio - Write I/O descriptor. 1075c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * status - I/O status. 1076c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 1077c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic AsyncIOAction 1078c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_sdkctl_query_send_io(void* io_opaque, 1079c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncSocketIO* asio, 1080c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncIOState status) 1081c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1082c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* const query = (SDKCtlQuery*)io_opaque; 1083c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncIOAction action = ASIO_ACTION_DONE; 1084c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1085c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Reference the query while we're in this callback. */ 1086c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_reference(query); 1087c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1088c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Lets see what's going on with query transmission. */ 1089c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine switch (status) { 10907136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine case ASIO_STATE_SUCCEEDED: 10917136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Query has been sent to the service. */ 10927136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine _on_sdkctl_query_sent(query); 10937136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine break; 10947136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 1095c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_CANCELLED: 10967136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine T("SDKCtl %s: Query %p ID %d is cancelled in transmission.", 10977136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine query->sdkctl->service_name, query, query->header.query_id); 1098c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Remove the query from the list of active queries. */ 1099c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_remove_query(query); 1100c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_sdkctl_query_cancelled(query); 1101c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1102c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1103c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_TIMED_OUT: 11047136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine D("SDKCtl %s: Query %p ID %d with deadline %lld has timed out in transmission at %lld", 1105c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->sdkctl->service_name, query, query->header.query_id, 11067136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine query->deadline, async_socket_deadline(query->sdkctl->as, 0)); 1107c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Invoke query's callback. */ 1108c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine action = query->query_cb(query->query_opaque, query, status); 1109c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* For actions other than retry we need to stop the query. */ 1110c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (action != ASIO_ACTION_RETRY) { 1111c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_remove_query(query); 1112c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1113c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1114c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1115c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_FAILED: 11167136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine T("SDKCtl %s: Query %p ID %d failed in transmission: %d -> %s", 1117c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->sdkctl->service_name, query, query->header.query_id, 1118c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine errno, strerror(errno)); 1119c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Invoke query's callback. Note that we will let the client to 1120c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * decide what to do on I/O failure. */ 1121c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine action = query->query_cb(query->query_opaque, query, status); 1122c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* For actions other than retry we need to stop the query. */ 1123c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (action != ASIO_ACTION_RETRY) { 1124c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_remove_query(query); 1125c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1126c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1127c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1128c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_FINISHED: 1129c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Time to disassociate with the I/O. */ 1130c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_release(query); 1131c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1132c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1133c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine default: 1134c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Transitional state. */ 1135c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1136c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1137c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1138c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_release(query); 1139c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1140c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return action; 1141c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1142c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1143c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/******************************************************************************** 1144c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * SDKCtlQuery public API implementation 1145c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine ********************************************************************************/ 1146c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1147c8aa2c570d30098da59f1967d5158024ed28570dVladimir ChtchetkineSDKCtlQuery* 1148c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinesdkctl_query_new(SDKCtlSocket* sdkctl, int query_type, uint32_t in_data_size) 1149c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 11507136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCtlQuery* const query = 11517136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine _sdkctl_socket_alloc_recycler(sdkctl, sizeof(SDKCtlQuery) + in_data_size); 11527136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine query->next = NULL; 11537136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine query->sdkctl = sdkctl; 11547136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine query->response_buffer = NULL; 11557136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine query->response_size = NULL; 11567136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine query->internal_resp_buffer = NULL; 11577136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine query->internal_resp_size = 0; 11587136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine query->query_cb = NULL; 11597136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine query->query_opaque = NULL; 11607136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine query->deadline = DURATION_INFINITE; 11617136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine query->ref_count = 1; 11627136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine query->header.packet.signature = _sdkctl_packet_sig; 11637136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine query->header.packet.size = sizeof(SDKCtlQueryHeader) + in_data_size; 11647136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine query->header.packet.type = SDKCTL_PACKET_QUERY; 11657136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine query->header.query_id = _sdkctl_socket_next_query_id(sdkctl); 11667136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine query->header.query_type = query_type; 1167c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1168c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Initialize timer to fire up on query deadline expiration. */ 1169c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine loopTimer_init(query->timer, sdkctl->looper, _on_skdctl_query_timeout, query); 1170c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1171c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Reference socket that owns this query. */ 1172c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_socket_reference(sdkctl); 1173c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1174c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("SDKCtl %s: Query %p ID %d type %d is created for %d bytes of data.", 1175c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->sdkctl->service_name, query, query->header.query_id, 1176c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query_type, in_data_size); 1177c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1178c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return query; 1179c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1180c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1181c8aa2c570d30098da59f1967d5158024ed28570dVladimir ChtchetkineSDKCtlQuery* 1182c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinesdkctl_query_new_ex(SDKCtlSocket* sdkctl, 1183c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine int query_type, 1184c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine uint32_t in_data_size, 1185c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine const void* in_data, 1186c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine void** response_buffer, 1187c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine uint32_t* response_size, 1188c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine on_sdkctl_query_cb query_cb, 1189c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine void* query_opaque) 1190c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1191c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* const query = sdkctl_query_new(sdkctl, query_type, in_data_size); 1192c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 11937136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine query->response_buffer = response_buffer; 1194c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (query->response_buffer == NULL) { 1195c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Creator didn't supply a buffer. Use internal one instead. */ 1196c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->response_buffer = &query->internal_resp_buffer; 1197c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 11987136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine query->response_size = response_size; 1199c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (query->response_size == NULL) { 1200c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Creator didn't supply a buffer for response size. Use internal one 1201c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * instead. */ 1202c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->response_size = &query->internal_resp_size; 1203c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 12047136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine query->query_cb = query_cb; 12057136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine query->query_opaque = query_opaque; 1206c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Init query's input buffer. */ 1207c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (in_data_size != 0 && in_data != NULL) { 1208c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine memcpy(query + 1, in_data, in_data_size); 1209c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1210c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1211c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return query; 1212c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1213c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1214c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinevoid 1215c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinesdkctl_query_send(SDKCtlQuery* query, int to) 1216c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1217c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* const sdkctl = query->sdkctl; 1218c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1219c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Initialize the deadline. */ 1220c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->deadline = async_socket_deadline(query->sdkctl->as, to); 1221c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1222c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* List the query in the list of active queries. */ 1223c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_add_query(query); 1224c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1225c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Reference query associated with write I/O. */ 1226c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_reference(query); 1227c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 12287136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine assert(query->header.packet.signature == _sdkctl_packet_sig); 1229c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Transmit the query to SDK controller. */ 1230c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine async_socket_write_abs(sdkctl->as, &query->header, query->header.packet.size, 1231c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_sdkctl_query_send_io, query, query->deadline); 1232c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 12337136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine T("SDKCtl %s: Query %p ID %d type %d is being sent with deadline at %lld", 1234c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->sdkctl->service_name, query, query->header.query_id, 1235c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->header.query_type, query->deadline); 1236c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1237c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1238c8aa2c570d30098da59f1967d5158024ed28570dVladimir ChtchetkineSDKCtlQuery* 1239c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinesdkctl_query_build_and_send(SDKCtlSocket* sdkctl, 1240c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine int query_type, 1241c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine uint32_t in_data_size, 1242c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine const void* in_data, 1243c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine void** response_buffer, 1244c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine uint32_t* response_size, 1245c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine on_sdkctl_query_cb query_cb, 1246c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine void* query_opaque, 1247c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine int to) 1248c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1249c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* const query = 1250c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_new_ex(sdkctl, query_type, in_data_size, in_data, 1251c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine response_buffer, response_size, query_cb, 1252c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query_opaque); 1253c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_send(query, to); 1254c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return query; 1255c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1256c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1257c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkineint 1258c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinesdkctl_query_reference(SDKCtlQuery* query) 1259c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1260c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine assert(query->ref_count > 0); 1261c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->ref_count++; 1262c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return query->ref_count; 1263c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1264c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1265c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkineint 1266c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinesdkctl_query_release(SDKCtlQuery* query) 1267c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1268c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine assert(query->ref_count > 0); 1269c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->ref_count--; 1270c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (query->ref_count == 0) { 1271c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Last reference has been dropped. Destroy this object. */ 1272c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_query_free(query); 1273c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return 0; 1274c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1275c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return query->ref_count; 1276c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1277c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 12787136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkinevoid* 12797136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkinesdkctl_query_get_buffer_in(SDKCtlQuery* query) 12807136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine{ 12817136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Query buffer starts right after the header. */ 12827136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine return query + 1; 12837136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine} 12847136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 12857136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkinevoid* 12867136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkinesdkctl_query_get_buffer_out(SDKCtlQuery* query) 12877136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine{ 12887136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine return query->response_buffer != NULL ? *query->response_buffer : 12897136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine query->internal_resp_buffer; 12907136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine} 12917136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 1292c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/******************************************************************************** 1293c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * SDKCtlPacket implementation 1294c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *******************************************************************************/ 1295c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 12967136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/* A packet has been received from SDK controller. 12977136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * Note that we expect the packet to be a message, since queries, and query 12987136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * replies are handled separately. */ 1299c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 1300c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_sdkctl_packet_received(SDKCtlSocket* sdkctl, SDKCtlPacket* packet) 1301c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1302c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("SDKCtl %s: Received packet size: %d, type: %d", 1303c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name, packet->header.size, packet->header.type); 1304c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 13057136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine assert(packet->header.signature == _sdkctl_packet_sig); 13067136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine if (packet->header.type == SDKCTL_PACKET_MESSAGE) { 13077136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCtlMessage* const msg = (SDKCtlMessage*)packet; 13087136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Lets see if this is an internal protocol message. */ 13097136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine switch (msg->msg_type) { 13107136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine case SDKCTL_MSG_PORT_CONNECTED: 13117136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->port_status = SDKCTL_PORT_CONNECTED; 13127136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->on_port_connection(sdkctl->opaque, sdkctl, 13137136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCTL_PORT_CONNECTED); 13147136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine break; 13157136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 13167136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine case SDKCTL_MSG_PORT_DISCONNECTED: 13177136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->port_status = SDKCTL_PORT_DISCONNECTED; 13187136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->on_port_connection(sdkctl->opaque, sdkctl, 13197136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCTL_PORT_DISCONNECTED); 13207136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine break; 13217136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 13227136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine case SDKCTL_MSG_PORT_ENABLED: 13237136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->port_status = SDKCTL_PORT_ENABLED; 13247136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->on_port_connection(sdkctl->opaque, sdkctl, 13257136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCTL_PORT_ENABLED); 13267136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine break; 13277136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 13287136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine case SDKCTL_MSG_PORT_DISABLED: 13297136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->port_status = SDKCTL_PORT_DISABLED; 13307136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->on_port_connection(sdkctl->opaque, sdkctl, 13317136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCTL_PORT_DISABLED); 13327136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine break; 13337136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 13347136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine default: 13357136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* This is a higher-level message. Dispatch the message to the 13367136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * client. */ 13377136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->on_message(sdkctl->opaque, sdkctl, msg, msg->msg_type, msg + 1, 13387136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine packet->header.size - sizeof(SDKCtlMessageHeader)); 13397136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine break; 13407136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine } 13417136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine } else { 13427136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine E("SDKCtl %s: Received unknown packet type %d size %d", 13437136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->service_name, packet->header.type, packet->header.size); 13447136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine } 1345c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1346c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1347c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/******************************************************************************** 1348c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * SDKCtlIODispatcher implementation 1349c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *******************************************************************************/ 1350c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1351c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* An I/O callback invoked when data gets received from the socket. 1352c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Param: 1353c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * io_opaque SDKCtlIODispatcher instance associated with the reader. 1354c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * asio - Read I/O descriptor. 1355c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * status - I/O status. 1356c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 1357c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic AsyncIOAction _on_sdkctl_io_dispatcher_io(void* io_opaque, 1358c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncSocketIO* asio, 1359c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncIOState status); 1360c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1361c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Starts I/O dispatcher for SDK controller socket. */ 1362c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 1363c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_io_dispatcher_start(SDKCtlSocket* sdkctl) { 1364c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlIODispatcher* const dispatcher = &sdkctl->io_dispatcher; 1365c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1366c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->state = SDKCTL_IODISP_EXPECT_HEADER; 1367c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->sdkctl = sdkctl; 1368c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->packet = NULL; 1369c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->current_query = NULL; 1370c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1371c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Register a packet header reader with the socket. */ 13727136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine async_socket_read_rel(dispatcher->sdkctl->as, &dispatcher->packet_header, 1373c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sizeof(SDKCtlPacketHeader), _on_sdkctl_io_dispatcher_io, 1374c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher, -1); 1375c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1376c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1377c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Resets I/O dispatcher for SDK controller socket. */ 1378c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 1379c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_io_dispatcher_reset(SDKCtlSocket* sdkctl) { 1380c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlIODispatcher* const dispatcher = &sdkctl->io_dispatcher; 1381c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1382c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Cancel current query. */ 1383c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (dispatcher->current_query != NULL) { 1384c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* const query = dispatcher->current_query; 1385c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->current_query = NULL; 1386c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_sdkctl_query_cancelled(query); 1387c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_release(query); 1388c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1389c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1390c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Free packet data buffer. */ 1391c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (dispatcher->packet != NULL) { 13927136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine _sdkctl_packet_release(dispatcher->packet); 1393c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->packet = NULL; 1394c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1395c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1396c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Reset dispatcher state. */ 1397c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->state = SDKCTL_IODISP_EXPECT_HEADER; 13987136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 13997136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine T("SDKCtl %s: I/O Dispatcher is reset", sdkctl->service_name); 1400c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1401c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1402c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* 1403c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * I/O dispatcher callbacks. 1404c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 1405c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1406c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* A callback that is invoked when a failure occurred while dispatcher was 1407c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * reading data from the socket. 1408c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 1409c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 1410c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_io_dispatcher_io_failure(SDKCtlIODispatcher* dispatcher, 1411c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncSocketIO* asio) 1412c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1413c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* const sdkctl = dispatcher->sdkctl; 1414c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1415c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine D("SDKCtl %s: Dispatcher I/O failure: %d -> %s", 1416c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name, errno, strerror(errno)); 1417c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1418c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* We treat all I/O failures same way we treat disconnection. Just cancel 1419c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * everything, disconnect, and let the client to decide what to do next. */ 1420c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_socket_disconnect(sdkctl); 1421c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1422c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Report disconnection to the client, and let it restore connection in this 1423c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * callback. */ 14247136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->on_socket_connection(sdkctl->opaque, sdkctl, ASIO_STATE_FAILED); 1425c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1426c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1427c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* A callback that is invoked when dispatcher's reader has been cancelled. */ 1428c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 1429c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_io_dispatcher_io_cancelled(SDKCtlIODispatcher* dispatcher, 1430c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncSocketIO* asio) 1431c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1432c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("SDKCtl %s: Dispatcher I/O cancelled.", dispatcher->sdkctl->service_name); 1433c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1434c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* If we're in the middle of receiving query reply we need to cancel the 1435c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * query. */ 1436c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (dispatcher->current_query != NULL) { 1437c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* const query = dispatcher->current_query; 1438c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->current_query = NULL; 1439c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_sdkctl_query_cancelled(query); 1440c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_release(query); 1441c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1442c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1443c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Discard packet data we've received so far. */ 1444c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (dispatcher->packet != NULL) { 14457136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine _sdkctl_packet_release(dispatcher->packet); 1446c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->packet = NULL; 1447c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1448c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1449c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1450c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* A generic packet header has been received by I/O dispatcher. */ 1451c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic AsyncIOAction 1452c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_io_dispatcher_packet_header(SDKCtlIODispatcher* dispatcher, 1453c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncSocketIO* asio) 1454c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1455c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* const sdkctl = dispatcher->sdkctl; 1456c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1457c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("SDKCtl %s: Packet header type %d, size %d is received.", 14587136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine dispatcher->sdkctl->service_name, dispatcher->packet_header.type, 14597136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine dispatcher->packet_header.size); 14607136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 14617136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* Make sure we have a valid packet header. */ 14627136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine if (dispatcher->packet_header.signature != _sdkctl_packet_sig) { 14637136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine E("SDKCtl %s: Invalid packet signature %x for packet type %d, size %d", 14647136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->service_name, dispatcher->packet_header.signature, 14657136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine dispatcher->packet_header.type, dispatcher->packet_header.size); 14667136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine /* This is a protocol failure. Treat it as I/O failure: disconnect, and 14677136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * let the client to decide what to do next. */ 14687136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine errno = EINVAL; 14697136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine _on_io_dispatcher_io_failure(dispatcher, asio); 14707136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine return ASIO_ACTION_DONE; 14717136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine } 1472c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1473c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Here we have three choices for the packet, that define the rest of 1474c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * the data that follow it: 1475c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * - Regular packet, 1476c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * - Response to a query that has been sent to SDK controller, 1477c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * - A query from SDK controller. 1478c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Update the state accordingly, and initiate reading of the 1479c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * remaining of the packet. 1480c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 14817136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine if (dispatcher->packet_header.type == SDKCTL_PACKET_QUERY_RESPONSE) { 1482c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* This is a response to the query. Before receiving response data we 1483c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * need to locate the relevant query, and use its response buffer to read 1484c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * the data. For that we need to obtain query ID firts. So, initiate 1485c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * reading of the remaining part of SDKCtlQueryReplyHeader. */ 1486c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->state = SDKCTL_IODISP_EXPECT_QUERY_REPLY_HEADER; 1487c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine async_socket_read_rel(sdkctl->as, &dispatcher->query_reply_header.query_id, 1488c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sizeof(SDKCtlQueryReplyHeader) - sizeof(SDKCtlPacketHeader), 1489c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_sdkctl_io_dispatcher_io, dispatcher, -1); 1490c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } else { 1491c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* For regular packets, as well as queries, we simply allocate buffer, 1492c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * that fits the entire packet, and read the remainder of the data in 1493c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * there. */ 1494c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->state = SDKCTL_IODISP_EXPECT_DATA; 1495c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->packet = 14967136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine _sdkctl_packet_new(sdkctl, dispatcher->packet_header.size, 14977136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine dispatcher->packet_header.type); 1498c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Initiate reading of the packet data. */ 1499c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine async_socket_read_rel(sdkctl->as, dispatcher->packet + 1, 15007136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine dispatcher->packet_header.size - sizeof(SDKCtlPacketHeader), 1501c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_sdkctl_io_dispatcher_io, dispatcher, -1); 1502c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1503c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1504c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return ASIO_ACTION_DONE; 1505c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1506c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1507c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* A generic packet has been received by I/O dispatcher. */ 1508c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic AsyncIOAction 1509c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_io_dispatcher_packet(SDKCtlIODispatcher* dispatcher, AsyncSocketIO* asio) 1510c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1511c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* const sdkctl = dispatcher->sdkctl; 15127136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SDKCtlPacket* const packet = dispatcher->packet; 15137136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine dispatcher->packet = NULL; 1514c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1515c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("SDKCtl %s: Packet type %d, size %d is received.", 15167136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine dispatcher->sdkctl->service_name, dispatcher->packet_header.type, 15177136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine dispatcher->packet_header.size); 1518c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 15197136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine _on_sdkctl_packet_received(sdkctl, packet); 15207136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine _sdkctl_packet_release(packet); 1521c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1522c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Get ready for the next I/O cycle. */ 1523c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->state = SDKCTL_IODISP_EXPECT_HEADER; 15247136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine async_socket_read_rel(sdkctl->as, &dispatcher->packet_header, sizeof(SDKCtlPacketHeader), 1525c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_sdkctl_io_dispatcher_io, dispatcher, -1); 1526c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return ASIO_ACTION_DONE; 1527c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1528c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1529c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* A query reply header has been received by I/O dispatcher. */ 1530c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic AsyncIOAction 1531c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_io_dispatcher_query_reply_header(SDKCtlIODispatcher* dispatcher, 1532c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncSocketIO* asio) 1533c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1534c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* const sdkctl = dispatcher->sdkctl; 1535c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* query; 1536c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1537c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("SDKCtl %s: Query reply header is received for query ID %d", 1538c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->sdkctl->service_name, dispatcher->query_reply_header.query_id); 1539c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1540c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Pull the query out of the list of active queries. It's the dispatcher that 1541c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * owns this query now. */ 1542c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->current_query = 1543c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_remove_query_id(sdkctl, dispatcher->query_reply_header.query_id); 1544c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query = dispatcher->current_query; 15457136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine const uint32_t query_data_size = 15467136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine dispatcher->packet_header.size - sizeof(SDKCtlQueryReplyHeader); 15477136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine dispatcher->state = SDKCTL_IODISP_EXPECT_QUERY_REPLY_DATA; 1548c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1549c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (query == NULL) { 1550c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine D("%s: Query #%d is not found by dispatcher", 1551c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->sdkctl->service_name, dispatcher->query_reply_header.query_id); 1552c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1553c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Query is not found. Just read the remainder of reply up in the air, 1554c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * and then discard when it's over. */ 1555c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->state = SDKCTL_IODISP_EXPECT_QUERY_REPLY_DATA; 1556c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->packet = 15577136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine _sdkctl_packet_new(sdkctl, dispatcher->packet_header.size, 15587136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine dispatcher->packet_header.type); 1559c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Copy query reply info to the packet. */ 1560c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine memcpy(&dispatcher->packet->header, &dispatcher->query_reply_header, 1561c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sizeof(SDKCtlQueryReplyHeader)); 15627136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine async_socket_read_rel(sdkctl->as, dispatcher->packet + 1, query_data_size, 1563c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_sdkctl_io_dispatcher_io, dispatcher, -1); 1564c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } else { 1565c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Prepare to receive query reply. For the simplicity sake, cancel query 1566c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * time out, so it doesn't expire on us while we're in the middle of 1567c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * receiving query's reply. */ 1568c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_query_cancel_timeout(query); 1569c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1570c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (*query->response_size < query_data_size) { 1571c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *query->response_buffer = malloc(query_data_size); 1572c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (*query->response_buffer == NULL) { 1573c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine APANIC("%s: Unable to allocate %d bytes for query response", 1574c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name, query_data_size); 1575c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1576c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1577c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Save the actual query response size. */ 1578c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *query->response_size = query_data_size; 1579c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1580c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Start reading query response. */ 1581c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine async_socket_read_rel(sdkctl->as, *query->response_buffer, 1582c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *query->response_size, _on_sdkctl_io_dispatcher_io, 1583c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher, -1); 1584c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1585c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1586c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return ASIO_ACTION_DONE; 1587c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1588c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1589c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* A query reply header has been received by I/O dispatcher. */ 1590c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic AsyncIOAction 1591c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_io_dispatcher_query_reply(SDKCtlIODispatcher* dispatcher, AsyncSocketIO* asio) 1592c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1593c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* const sdkctl = dispatcher->sdkctl; 1594c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* const query = dispatcher->current_query; 1595c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->current_query = NULL; 1596c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1597c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (query != NULL) { 1598c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _ANDROID_ASSERT(query->header.query_id == dispatcher->query_reply_header.query_id, 1599c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine "SDKCtl %s: Query ID mismatch in I/O dispatcher", 1600c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name); 1601c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("SDKCtl %s: Query reply is received for query %p ID %d. Reply size is %d", 1602c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->sdkctl->service_name, query, query->header.query_id, 1603c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *query->response_size); 1604c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1605c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Complete the query, and release it from the dispatcher. */ 1606c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_sdkctl_query_completed(query); 1607c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_release(query); 1608c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } else { 1609c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* This was "read up in the air" for a cancelled query. Just discard the 1610c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * read data. */ 1611c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (dispatcher->packet != NULL) { 16127136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine _sdkctl_packet_release(dispatcher->packet); 1613c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->packet = NULL; 1614c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1615c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1616c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1617c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Get ready for the next I/O cycle. */ 1618c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->state = SDKCTL_IODISP_EXPECT_HEADER; 16197136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine async_socket_read_rel(sdkctl->as, &dispatcher->packet_header, sizeof(SDKCtlPacketHeader), 1620c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_sdkctl_io_dispatcher_io, dispatcher, -1); 1621c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return ASIO_ACTION_DONE; 1622c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1623c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1624c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* An I/O callback invoked when data gets received from the socket. 1625c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * This is main I/O dispatcher loop. 1626c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Param: 1627c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * io_opaque SDKCtlIODispatcher instance associated with the reader. 1628c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * asio - Read I/O descriptor. 1629c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * status - I/O status. 1630c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 1631c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic AsyncIOAction 1632c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_sdkctl_io_dispatcher_io(void* io_opaque, 1633c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncSocketIO* asio, 1634c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncIOState status) 1635c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1636c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncIOAction action = ASIO_ACTION_DONE; 1637c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlIODispatcher* const dispatcher = (SDKCtlIODispatcher*)io_opaque; 1638c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* const sdkctl = dispatcher->sdkctl; 1639c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1640c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Reference SDKCtlSocket while we're in this callback. */ 1641c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_socket_reference(sdkctl); 1642c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1643c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (status != ASIO_STATE_SUCCEEDED) { 1644c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Something going on with I/O other than receiving data.. */ 1645c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine switch (status) { 1646c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_STARTED: 1647c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Data has started flowing in. Cancel timeout on I/O that has 1648c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * started, so we can complete the current state of the 1649c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * dispatcher without interruptions other than I/O failures. */ 1650c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine async_socket_io_cancel_time_out(asio); 1651c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1652c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1653c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_FAILED: 1654c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* I/O failure has occurred. Handle the failure. */ 1655c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_io_dispatcher_io_failure(dispatcher, asio); 1656c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1657c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1658c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_TIMED_OUT: 1659c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* The way I/O dispatcher is implemented, this should never 1660c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * happen, because dispatcher doesn't set I/O expiration time 1661c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * when registering its readers. */ 1662c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _ANDROID_ASSERT(0, 1663c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine "SDKCtl %s: We should never receive ASIO_STATE_TIMED_OUT in SDKCtl I/O dispatcher.", 1664c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name); 1665c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1666c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1667c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_CANCELLED: 1668c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Cancellation means that we're in the middle of handling 1669c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * disconnection. Sooner or later, this dispatcher will be reset, 1670c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * so we don't really care about keeping its state at this point. 1671c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 1672c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_io_dispatcher_io_cancelled(dispatcher, asio); 1673c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1674c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1675c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_FINISHED: 1676c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1677c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1678c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine default: 1679c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _ANDROID_ASSERT(0, "SDKCtl %s: Unexpected I/O status %d in the dispatcher", 1680c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name, status); 1681c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Handle this as protocol failure. */ 1682c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine errno = EINVAL; 1683c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_io_dispatcher_io_failure(dispatcher, asio); 1684c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine action = ASIO_ACTION_ABORT; 1685c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1686c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1687c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1688c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_socket_release(sdkctl); 1689c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1690c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return action; 1691c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1692c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1693c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Requested data has been read. Handle the chunk depending on dispatcher's 1694c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * state. */ 1695c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine switch (dispatcher->state) { 1696c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case SDKCTL_IODISP_EXPECT_HEADER: 1697c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* A generic packet header is received. */ 1698c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine action = _on_io_dispatcher_packet_header(dispatcher, asio); 1699c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1700c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1701c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case SDKCTL_IODISP_EXPECT_QUERY_REPLY_HEADER: 1702c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Query reply header is received. */ 1703c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine action = _on_io_dispatcher_query_reply_header(dispatcher, asio); 1704c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1705c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1706c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case SDKCTL_IODISP_EXPECT_QUERY_REPLY_DATA: 1707c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Query reply is received. Complete the query. */ 1708c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine action = _on_io_dispatcher_query_reply(dispatcher, asio); 1709c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1710c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1711c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case SDKCTL_IODISP_EXPECT_DATA: 1712c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* A generic packet is received. */ 1713c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine action = _on_io_dispatcher_packet(dispatcher, asio); 1714c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1715c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1716c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine default: 1717c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _ANDROID_ASSERT(0, "SDKCtl %s: Unexpected I/O dispacher state %d", 1718c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name, dispatcher->state); 1719c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1720c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1721c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1722c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_socket_release(sdkctl); 1723c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1724c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return action; 1725c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1726c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1727c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/******************************************************************************** 1728c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * SDKCtlSocket internals. 1729c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *******************************************************************************/ 1730c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1731c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Cancels all queries that is active on this socket. */ 1732c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 1733c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_socket_cancel_all_queries(SDKCtlSocket* sdkctl) 1734c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1735c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlIODispatcher* const dispatcher = &sdkctl->io_dispatcher; 1736c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* query; 1737c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1738c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Cancel query that is being completed in dispatcher. */ 1739c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (dispatcher->current_query != NULL) { 1740c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* const query = dispatcher->current_query; 1741c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine dispatcher->current_query = NULL; 1742c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_sdkctl_query_cancelled(query); 1743c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_release(query); 1744c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1745c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1746c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* One by one empty query list cancelling pulled queries. */ 1747c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query = _sdkctl_socket_pull_first_query(sdkctl); 1748c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine while (query != NULL) { 1749c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_query_cancel_timeout(query); 1750c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query->query_cb(query->query_opaque, query, ASIO_STATE_CANCELLED); 1751c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_release(query); 1752c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine query = _sdkctl_socket_pull_first_query(sdkctl); 1753c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1754c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1755c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1756c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Cancels all packets that is active on this socket. */ 1757c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 1758c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_socket_cancel_all_packets(SDKCtlSocket* sdkctl) 1759c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1760c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1761c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1762c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Cancels all I/O that is active on this socket. */ 1763c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 1764c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_socket_cancel_all_io(SDKCtlSocket* sdkctl) 1765c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1766c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Cancel all queries, and packets that are active for this I/O. */ 1767c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_cancel_all_queries(sdkctl); 1768c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_cancel_all_packets(sdkctl); 1769c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1770c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1771c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Disconnects AsyncSocket for SDKCtlSocket. */ 1772c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 1773c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_socket_disconnect_socket(SDKCtlSocket* sdkctl) 1774c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1775c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->as != NULL) { 1776c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Disconnect the socket. This will trigger I/O cancellation callbacks. */ 1777c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine async_socket_disconnect(sdkctl->as); 1778c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1779c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Cancel all I/O that is active on this socket. */ 1780c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_cancel_all_io(sdkctl); 1781c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1782c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Reset I/O dispatcher. */ 1783c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_io_dispatcher_reset(sdkctl); 1784c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1785c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1786c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->state = SDKCTL_SOCKET_DISCONNECTED; 17877136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->port_status = SDKCTL_PORT_DISCONNECTED; 1788c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1789c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1790c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Frees SDKCtlSocket instance. */ 1791c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 1792c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_socket_free(SDKCtlSocket* sdkctl) 1793c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1794c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl != NULL) { 17957136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine T("SDKCtl %s: descriptor is destroing.", sdkctl->service_name); 17967136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 1797c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Disconnect, and release the socket. */ 1798c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->as != NULL) { 1799c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine async_socket_disconnect(sdkctl->as); 1800c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine async_socket_release(sdkctl->as); 1801c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1802c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1803c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Free allocated resources. */ 1804c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->looper != NULL) { 1805c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine looper_free(sdkctl->looper); 1806c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1807c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->service_name != NULL) { 1808c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine free(sdkctl->service_name); 1809c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1810c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_empty_recycler(sdkctl); 1811c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1812c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AFREE(sdkctl); 1813c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1814c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1815c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1816c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/******************************************************************************** 1817c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * SDK Control Socket connection callbacks. 1818c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *******************************************************************************/ 1819c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1820c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Initiates handshake query when SDK controller socket is connected. */ 1821c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void _sdkctl_do_handshake(SDKCtlSocket* sdkctl); 1822c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1823c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* A socket connection is established. 1824c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Here we will start I/O dispatcher, and will initiate a handshake with 1825c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * the SdkController service for this socket. */ 1826c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic AsyncIOAction 1827c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_async_socket_connected(SDKCtlSocket* sdkctl) 1828c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1829c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine D("SDKCtl %s: Socket is connected.", sdkctl->service_name); 1830c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1831c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Notify the client that connection is established. */ 1832c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine const AsyncIOAction action = 18337136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->on_socket_connection(sdkctl->opaque, sdkctl, ASIO_STATE_SUCCEEDED); 1834c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1835c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (action == ASIO_ACTION_DONE) { 1836c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Initialize, and start main I/O dispatcher. */ 1837c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_io_dispatcher_start(sdkctl); 1838c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1839c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Initiate handshake. */ 1840c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_do_handshake(sdkctl); 1841c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1842c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return action; 1843c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } else { 1844c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Client didn't like something about this connection. */ 1845c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return action; 1846c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1847c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1848c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1849c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* Handles lost connection with SdkController service. */ 1850c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic AsyncIOAction 1851c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_async_socket_disconnected(SDKCtlSocket* sdkctl) 1852c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1853c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine D("SDKCtl %s: Socket has been disconnected.", sdkctl->service_name); 1854c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1855c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_disconnect_socket(sdkctl); 1856c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 18577136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine AsyncIOAction action = sdkctl->on_socket_connection(sdkctl->opaque, sdkctl, 18587136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine ASIO_STATE_FAILED); 1859c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (action == ASIO_ACTION_DONE) { 1860c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Default action for disconnect is to reestablish the connection. */ 1861c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine action = ASIO_ACTION_RETRY; 1862c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1863c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (action == ASIO_ACTION_RETRY) { 1864c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->state = SDKCTL_SOCKET_CONNECTING; 1865c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1866c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return action; 1867c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1868c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1869c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* An entry point for all socket connection events. 1870c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Here we will dispatch connection events to appropriate handlers. 1871c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Param: 1872c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * client_opaque - SDKCtlSocket isntance. 1873c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine */ 1874c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic AsyncIOAction 1875c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_async_socket_connection(void* client_opaque, 1876c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncSocket* as, 1877c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncIOState status) 1878c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1879c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncIOAction action = ASIO_ACTION_DONE; 1880c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* const sdkctl = (SDKCtlSocket*)client_opaque; 1881c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1882c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Reference the socket while in this callback. */ 1883c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_socket_reference(sdkctl); 1884c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1885c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine switch (status) { 1886c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_SUCCEEDED: 1887c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->state = SDKCTL_SOCKET_CONNECTED; 1888c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_async_socket_connected(sdkctl); 1889c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1890c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1891c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_FAILED: 1892c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->state == SDKCTL_SOCKET_CONNECTED) { 1893c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* This is disconnection condition. */ 1894c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine action = _on_async_socket_disconnected(sdkctl); 1895c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } else { 1896c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* An error has occurred while attempting to connect to socket. 1897c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Lets try again... */ 1898c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine action = ASIO_ACTION_RETRY; 1899c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1900c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1901c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1902c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_RETRYING: 1903c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine default: 1904c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine action = ASIO_ACTION_RETRY; 1905c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 1906c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1907c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1908c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_socket_release(sdkctl); 1909c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1910c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return action; 1911c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1912c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1913c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/******************************************************************************** 1914c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * SDK Control Socket public API 1915c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *******************************************************************************/ 1916c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1917c8aa2c570d30098da59f1967d5158024ed28570dVladimir ChtchetkineSDKCtlSocket* 1918c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinesdkctl_socket_new(int reconnect_to, 1919c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine const char* service_name, 19207136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine on_sdkctl_socket_connection_cb on_socket_connection, 19217136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine on_sdkctl_port_connection_cb on_port_connection, 1922c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine on_sdkctl_message_cb on_message, 1923c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine void* opaque) 1924c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1925c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* sdkctl; 1926c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine ANEW0(sdkctl); 1927c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 19287136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->state = SDKCTL_SOCKET_DISCONNECTED; 19297136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->port_status = SDKCTL_PORT_DISCONNECTED; 19307136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->opaque = opaque; 19317136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->service_name = ASTRDUP(service_name); 19327136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->on_socket_connection = on_socket_connection; 19337136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->on_port_connection = on_port_connection; 19347136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->on_message = on_message; 19357136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->reconnect_to = reconnect_to; 19367136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->as = NULL; 19377136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->next_query_id = 0; 19387136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->query_head = sdkctl->query_tail = NULL; 19397136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->ref_count = 1; 19407136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->recycler = NULL; 19417136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->recycler_block_size = 0; 19427136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->recycler_max = 0; 19437136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->recycler_count = 0; 19447136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 19457136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine T("SDKCtl %s: descriptor is created.", sdkctl->service_name); 1946c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1947c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->looper = looper_newCore(); 1948c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->looper == NULL) { 1949c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine E("Unable to create I/O looper for SDKCtl socket '%s'", 1950c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine service_name); 19517136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine on_socket_connection(opaque, sdkctl, ASIO_STATE_FAILED); 1952c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_free(sdkctl); 1953c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return NULL; 1954c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1955c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1956c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return sdkctl; 1957c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1958c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1959c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkineint sdkctl_socket_reference(SDKCtlSocket* sdkctl) 1960c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1961c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine assert(sdkctl->ref_count > 0); 1962c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->ref_count++; 1963c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return sdkctl->ref_count; 1964c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1965c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1966c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkineint 1967c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinesdkctl_socket_release(SDKCtlSocket* sdkctl) 1968c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1969c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine assert(sdkctl->ref_count > 0); 1970c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->ref_count--; 1971c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->ref_count == 0) { 1972c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Last reference has been dropped. Destroy this object. */ 1973c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_free(sdkctl); 1974c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return 0; 1975c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1976c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return sdkctl->ref_count; 1977c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1978c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1979c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinevoid 1980c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinesdkctl_init_recycler(SDKCtlSocket* sdkctl, 1981c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine uint32_t data_size, 1982c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine int max_recycled_num) 1983c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 1984c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->recycler != NULL) { 1985c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine D("SDKCtl %s: Recycler is already initialized. Ignoring recycler init.", 1986c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name); 1987c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return; 1988c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 1989c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1990c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* SDKCtlQuery is max descriptor sizeof. */ 1991c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine data_size += sizeof(SDKCtlQuery); 1992c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1993c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->recycler_block_size = data_size; 1994c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->recycler_max = max_recycled_num; 1995c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->recycler_count = 0; 1996c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 1997c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 1998c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinevoid 1999c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinesdkctl_socket_connect(SDKCtlSocket* sdkctl, int port, int retry_to) 2000c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 2001c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("SDKCtl %s: Handling connect request to port %d, retrying in %dms...", 2002c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name, port, retry_to); 2003c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 2004c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->state = SDKCTL_SOCKET_CONNECTING; 2005c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->as = async_socket_new(port, sdkctl->reconnect_to, 2006c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_async_socket_connection, sdkctl, 2007c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->looper); 2008c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->as == NULL) { 2009c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine E("Unable to allocate AsyncSocket for SDKCtl socket '%s'", 2010c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name); 20117136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->on_socket_connection(sdkctl->opaque, sdkctl, ASIO_STATE_FAILED); 2012c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } else { 2013c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine async_socket_connect(sdkctl->as, retry_to); 2014c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 2015c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 2016c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 2017c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinevoid 2018c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinesdkctl_socket_reconnect(SDKCtlSocket* sdkctl, int port, int retry_to) 2019c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 2020c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("SDKCtl %s: Handling reconnection request to port %d, retrying in %dms...", 2021c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name, port, retry_to); 2022c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 2023c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_disconnect_socket(sdkctl); 2024c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 2025c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (sdkctl->as == NULL) { 2026c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_socket_connect(sdkctl, port, retry_to); 2027c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } else { 2028c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->state = SDKCTL_SOCKET_CONNECTING; 2029c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine async_socket_reconnect(sdkctl->as, retry_to); 2030c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 2031c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 2032c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 2033c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinevoid 2034c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinesdkctl_socket_disconnect(SDKCtlSocket* sdkctl) 2035c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 2036c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine T("SDKCtl %s: Handling disconnect request.", sdkctl->service_name); 2037c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 2038c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _sdkctl_socket_disconnect_socket(sdkctl); 2039c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 2040c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 20417136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkineint 20427136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkinesdkctl_socket_is_connected(SDKCtlSocket* sdkctl) 20437136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine{ 20447136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine return (sdkctl->state == SDKCTL_SOCKET_CONNECTED) ? 1 : 0; 20457136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine} 20467136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 20477136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkineint 20487136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkinesdkctl_socket_is_port_ready(SDKCtlSocket* sdkctl) 20497136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine{ 20507136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine return (sdkctl->port_status == SDKCTL_PORT_ENABLED) ? 1 : 0; 20517136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine} 20527136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 20537136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir ChtchetkineSdkCtlPortStatus 20547136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkinesdkctl_socket_get_port_status(SDKCtlSocket* sdkctl) 20557136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine{ 20567136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine return sdkctl->port_status; 20577136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine} 20587136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 20597136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkineint 20607136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkinesdkctl_socket_is_handshake_ok(SDKCtlSocket* sdkctl) 20617136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine{ 20627136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine switch (sdkctl->port_status) { 20637136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine case SDKCTL_HANDSHAKE_DUP: 20647136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine case SDKCTL_HANDSHAKE_UNKNOWN_QUERY: 20657136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine case SDKCTL_HANDSHAKE_UNKNOWN_RESPONSE: 20667136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine return 0; 20677136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine default: 20687136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine return 1; 20697136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine } 20707136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine} 2071c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 2072c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/******************************************************************************** 2073c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * Handshake query 2074c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine *******************************************************************************/ 2075c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 20767136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/* 20777136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine * Handshake result values. 20787136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine */ 20797136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 20807136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/* Handshake has succeeded completed, and service-side port is connected. */ 20817136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine#define SDKCTL_HANDSHAKE_RESP_CONNECTED 0 20827136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/* Handshake has succeeded completed, but service-side port is not connected. */ 20837136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine#define SDKCTL_HANDSHAKE_RESP_NOPORT 1 20847136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/* Handshake has failed due to duplicate connection request. */ 20857136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine#define SDKCTL_HANDSHAKE_RESP_DUP -1 20867136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine/* Handshake has failed due to unknown query. */ 20877136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine#define SDKCTL_HANDSHAKE_RESP_QUERY_UNKNOWN -2 20887136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 2089c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine/* A callback that is ivoked on handshake I/O events. */ 2090c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic AsyncIOAction 2091c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_handshake_io(void* query_opaque, 2092c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* query, 2093c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncIOState status) 2094c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 2095c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* const sdkctl = (SDKCtlSocket*)query_opaque; 2096c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 2097c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (status == ASIO_STATE_SUCCEEDED) { 20987136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine const int* res = (const int*)(*query->response_buffer); 20997136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine SdkCtlPortStatus handshake_status; 21007136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine switch (*res) { 21017136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine case SDKCTL_HANDSHAKE_RESP_CONNECTED: 21027136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine D("SDKCtl %s: Handshake succeeded. Port is connected", 21037136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->service_name); 21047136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine handshake_status = SDKCTL_HANDSHAKE_CONNECTED; 21057136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine break; 21067136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 21077136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine case SDKCTL_HANDSHAKE_RESP_NOPORT: 21087136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine D("SDKCtl %s: Handshake succeeded. Port is not connected", 21097136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->service_name); 21107136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine handshake_status = SDKCTL_HANDSHAKE_NO_PORT; 21117136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine break; 21127136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 21137136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine case SDKCTL_HANDSHAKE_RESP_DUP: 21147136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine D("SDKCtl %s: Handshake failed: duplicate connection.", 21157136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->service_name); 21167136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine handshake_status = SDKCTL_HANDSHAKE_DUP; 21177136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine break; 2118c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 21197136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine case SDKCTL_HANDSHAKE_RESP_QUERY_UNKNOWN: 21207136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine D("SDKCtl %s: Handshake failed: unknown query.", 21217136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->service_name); 21227136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine handshake_status = SDKCTL_HANDSHAKE_UNKNOWN_QUERY; 21237136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine break; 21247136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine 21257136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine default: 21267136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine E("SDKCtl %s: Unknown handshake response: %d", 21277136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->service_name, *res); 21287136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine handshake_status = SDKCTL_HANDSHAKE_UNKNOWN_RESPONSE; 21297136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine break; 21307136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine } 21317136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->port_status = handshake_status; 21327136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->on_port_connection(sdkctl->opaque, sdkctl, handshake_status); 2133c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } else { 2134c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Something is going on with the handshake... */ 2135c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine switch (status) { 2136c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_FAILED: 2137c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_TIMED_OUT: 2138c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_CANCELLED: 2139c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine D("SDKCtl %s: Handshake failed: I/O state %d. Error: %d -> %s", 2140c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name, status, errno, strerror(errno)); 21417136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->on_socket_connection(sdkctl->opaque, sdkctl, 21427136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine ASIO_STATE_FAILED); 2143c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 2144c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 2145c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine default: 2146c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 2147c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 2148c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 2149c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return ASIO_ACTION_DONE; 2150c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 2151c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 2152c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic AsyncIOAction 2153c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_on_sdkctl_endianness_io(void* io_opaque, 2154c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncSocketIO* asio, 2155c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine AsyncIOState status) { 2156c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlSocket* const sdkctl = (SDKCtlSocket*)io_opaque; 2157c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 2158c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine if (status == ASIO_STATE_SUCCEEDED) { 2159c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Now it's time to initiate handshake message. */ 2160c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine D("SDKCtl %s: Sending handshake query...", sdkctl->service_name); 2161c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine SDKCtlQuery* query = 2162c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_build_and_send(sdkctl, SDKCTL_QUERY_HANDSHAKE, 2163c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine strlen(sdkctl->service_name), 2164c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name, NULL, NULL, 2165c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_handshake_io, sdkctl, 3000); 2166c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl_query_release(query); 2167c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return ASIO_ACTION_DONE; 2168c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } else { 2169c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Something is going on with the endianness... */ 2170c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine switch (status) { 2171c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_FAILED: 2172c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_TIMED_OUT: 2173c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine case ASIO_STATE_CANCELLED: 2174c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine D("SDKCtl %s: endianness failed: I/O state %d. Error: %d -> %s", 2175c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine sdkctl->service_name, status, errno, strerror(errno)); 21767136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine sdkctl->on_socket_connection(sdkctl->opaque, sdkctl, ASIO_STATE_FAILED); 2177c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 2178c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 2179c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine default: 2180c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine break; 2181c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 2182c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine } 2183c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine return ASIO_ACTION_DONE; 2184c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 2185c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 2186c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic void 2187c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine_sdkctl_do_handshake(SDKCtlSocket* sdkctl) 2188c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine{ 2189c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#ifndef HOST_WORDS_BIGENDIAN 2190c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic const char _host_end = 0; 2191c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#else 2192c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkinestatic const char _host_end = 1; 2193c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine#endif 2194c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 21957136b053b7fc7840ec64e01d1d19ab822e1f949aVladimir Chtchetkine D("SDKCtl %s: Sending endianness: %d", sdkctl->service_name, _host_end); 2196c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine 2197c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine /* Before we can send any structured data to the SDK controller we need to 2198c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine * report endianness of the host. */ 2199c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine async_socket_write_rel(sdkctl->as, &_host_end, 1, 2200c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine _on_sdkctl_endianness_io, sdkctl, 3000); 2201c8aa2c570d30098da59f1967d5158024ed28570dVladimir Chtchetkine} 2202