/**************************************************************************** * This file is part of the project AqHome. * AqHome (c) by 2023 Martin Preuss, all rights reserved. * * The license for this file can be found in the file COPYING which you * should have received along with this file. ****************************************************************************/ #ifdef HAVE_CONFIG_H # include #endif #include "aqhome/ipc/endpoint_ipcclient.h" #include "aqhome/ipc/data/ipc_data.h" #include "aqhome/ipc/endpoint_ipc.h" #include "aqhome/ipc/data/msg_data_connect.h" #include "aqhome/ipc/msg_ipc_result.h" #include #include #include #include #define AQH_MSG_ENDPOINT_IPCCLIENT_NAME "ipc-client" /* ------------------------------------------------------------------------------------------------ * forward declarations * ------------------------------------------------------------------------------------------------ */ static int _startConnect(GWEN_MSG_ENDPOINT *ep, GWEN_MSG_ENDPOINT *epChild); static void _checkSockets(GWEN_MSG_ENDPOINT *ep, GWEN_MSG_ENDPOINT *epChild, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet); /* ------------------------------------------------------------------------------------------------ * implementations * ------------------------------------------------------------------------------------------------ */ GWEN_MSG_ENDPOINT *AQH_ClientIpcEndpoint_new(const char *name, int groupId) { GWEN_MSG_ENDPOINT *ep; ep=GWEN_MultilayerEndpoint_new(name?name:AQH_MSG_ENDPOINT_IPCCLIENT_NAME, groupId); GWEN_MultilayerEndpoint_SetStartConnectFn(ep, _startConnect); GWEN_MultilayerEndpoint_SetCheckSocketsFn(ep, _checkSockets); return ep; } int _startConnect(GWEN_MSG_ENDPOINT *ep, GWEN_MSG_ENDPOINT *epChild) { if (epChild) { int rv; GWEN_MSG *msg; uint32_t flagsForConnectMsg; flagsForConnectMsg=(GWEN_MsgEndpoint_GetFlags(ep) & AQH_ENDPOINT_IPCCLIENT_FLAGS_WANTUPDATES)?AQH_IPCENDPOINT_FLAGS_WANTUPDATES:0; rv=GWEN_TcpcEndpoint_StartConnect(epChild); if (rv<0 && rv!=GWEN_ERROR_IN_PROGRESS) { DBG_INFO(AQH_LOGDOMAIN, "Error starting to connect child layer (%d)", rv); return rv; } msg=AQH_ConnectDataIpcMsg_new(AQH_MSGTYPE_IPC_DATA_CONNECT_REQ, AQH_IpcEndpoint_GetServiceName(epChild), AQH_IpcEndpoint_GetUserName(epChild), AQH_IpcEndpoint_GetPassword(epChild), flagsForConnectMsg); GWEN_MsgEndpoint_AddSendMessage(epChild, msg); GWEN_MsgEndpoint_SetState(ep, GWEN_MSG_ENDPOINT_STATE_CONNECTING); return rv; /* result from GWEN_TcpcEndpoint_StartConnect() above */ } return GWEN_ERROR_GENERIC; } void _checkSockets(GWEN_MSG_ENDPOINT *ep, GWEN_MSG_ENDPOINT *epChild, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET *writeSet, GWEN_SOCKETSET *xSet) { GWEN_MSG *msg; GWEN_MsgEndpoint_CheckSockets(epChild, readSet, writeSet, xSet); /* let base layer work */ msg=GWEN_MsgEndpoint_GetFirstReceivedMessage(epChild); while(msg) { GWEN_MSG *msgNext; uint16_t code; msgNext=GWEN_Msg_List_Next(msg); code=GWEN_IpcMsg_GetCode(msg); if (code==AQH_MSGTYPE_IPC_DATA_RESULT) { uint32_t resultCode; GWEN_Msg_List_Del(msg); /* remove from list */ resultCode=AQH_ResultIpcMsg_GetResultCode(msg); if (resultCode==AQH_MSG_IPC_SUCCESS) { DBG_INFO(AQH_LOGDOMAIN, "Positive CONNECT response, connected"); GWEN_MsgEndpoint_SetState(ep, GWEN_MSG_ENDPOINT_STATE_CONNECTED); } else { DBG_ERROR(AQH_LOGDOMAIN, "Negative CONNECT response (%d)", code); GWEN_MsgEndpoint_Disconnect(epChild); GWEN_MsgEndpoint_Disconnect(ep); } GWEN_Msg_free(msg); break; } else { DBG_ERROR(AQH_LOGDOMAIN, "Ignoring response (%u)", code); GWEN_Msg_free(msg); } msg=msgNext; } /* while */ }