Files
aqhomecontrol/aqhome/ipc/endpoint_ipcclient.c

136 lines
4.2 KiB
C

/****************************************************************************
* 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 <config.h>
#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 <gwenhywfar/endpoint_ipc.h>
#include <gwenhywfar/endpoint_tcpc.h>
#include <gwenhywfar/endpoint_multilayer.h>
#include <gwenhywfar/debug.h>
#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 */
}