More work on node/pc interface.
- added AQH_MSG_ENDPOINT - added AQH_MsgEndpointLog - added AQH_MsgEndpointTcp - added AQH_MsgEndpointTty - added AQH_MsgEndpointMgr
This commit is contained in:
@@ -57,6 +57,16 @@
|
||||
msg_haveaddr.h
|
||||
msg_claimaddr.h
|
||||
msg_denyaddr.h
|
||||
msg_setaccmsggrps.h
|
||||
msgendpoint.h
|
||||
msgendpoint_p.h
|
||||
msgendpointtcp.h
|
||||
msgendpointtty.h
|
||||
msgendpointtty_p.h
|
||||
msgendpointlog.h
|
||||
msgendpointlog_p.h
|
||||
msgendpointmanager.h
|
||||
msgendpointmanager_p.h
|
||||
</headers>
|
||||
|
||||
|
||||
@@ -72,6 +82,12 @@
|
||||
msg_haveaddr.c
|
||||
msg_claimaddr.c
|
||||
msg_denyaddr.c
|
||||
msg_setaccmsggrps.c
|
||||
msgendpoint.c
|
||||
msgendpointtcp.c
|
||||
msgendpointtty.c
|
||||
msgendpointlog.c
|
||||
msgendpointmanager.c
|
||||
</sources>
|
||||
|
||||
<useTargets>
|
||||
|
||||
@@ -32,7 +32,7 @@ int testRecv()
|
||||
|
||||
fprintf(stdout, "Opening device...\n");
|
||||
sr=AQH_Serial_new("/dev/ttyUSB0", 240);
|
||||
rv=AQH_Serial_Open(sr);
|
||||
rv=AQH_Serial_Open(sr, AQH_SerialReadWriteMode_ReadOnly);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "ERROR opening device (%d)", rv);
|
||||
AQH_Serial_free(sr);
|
||||
@@ -77,7 +77,7 @@ int testSend()
|
||||
|
||||
fprintf(stdout, "Opening device...\n");
|
||||
sr=AQH_Serial_new("/dev/ttyUSB0", 240);
|
||||
rv=AQH_Serial_Open(sr);
|
||||
rv=AQH_Serial_Open(sr, AQH_SerialReadWriteMode_ReadWrite);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "ERROR opening device (%d)", rv);
|
||||
AQH_Serial_free(sr);
|
||||
@@ -268,7 +268,7 @@ int testLoop()
|
||||
|
||||
fprintf(stdout, "Opening device...\n");
|
||||
sr=AQH_Serial_new("/dev/ttyUSB0", 240);
|
||||
rv=AQH_Serial_Open(sr);
|
||||
rv=AQH_Serial_Open(sr, AQH_SerialReadWriteMode_ReadWrite);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "ERROR opening device (%d)", rv);
|
||||
AQH_Serial_free(sr);
|
||||
@@ -335,10 +335,60 @@ int testLoop()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int main(void)
|
||||
int testReadLoop()
|
||||
{
|
||||
AQH_SERIAL *sr;
|
||||
int rv;
|
||||
int i;
|
||||
GWEN_BUFFER *dbuf;
|
||||
time_t tLast;
|
||||
|
||||
fprintf(stdout, "Opening device...\n");
|
||||
sr=AQH_Serial_new("/dev/ttyUSB0", 240);
|
||||
rv=AQH_Serial_Open(sr, AQH_SerialReadWriteMode_ReadOnly);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "ERROR opening device (%d)", rv);
|
||||
AQH_Serial_free(sr);
|
||||
return 2;
|
||||
}
|
||||
fprintf(stdout, "Device open, waiting for packets\n");
|
||||
AQH_Serial_SetPacketReceivedFn(sr, _packetReceived);
|
||||
|
||||
tLast=time(NULL);
|
||||
for (;;) {
|
||||
time_t t;
|
||||
|
||||
rv=AQH_Serial_ReadOnlyLoop(sr);
|
||||
if (rv<0) {
|
||||
AQH_Serial_Close(sr);
|
||||
AQH_Serial_free(sr);
|
||||
break;
|
||||
}
|
||||
t=time(NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *cmd;
|
||||
|
||||
if (argc<2)
|
||||
return testLoop();
|
||||
|
||||
cmd=argv[1];
|
||||
if (strcasecmp(cmd, "monitor")==0 || strcasecmp(cmd, "mon")==0)
|
||||
return testReadLoop();
|
||||
else if (strcasecmp(cmd, "pingtest")==0) {
|
||||
}
|
||||
else if (strcasecmp(cmd, "rwtest")==0) {
|
||||
return testLoop();
|
||||
}
|
||||
//return testRecv();
|
||||
//return testSend();
|
||||
return testLoop();
|
||||
|
||||
26
aqhome/msg.c
26
aqhome/msg.c
@@ -51,6 +51,20 @@ void AQH_Msg_free(AQH_MSG *msg)
|
||||
|
||||
|
||||
|
||||
AQH_MSG *AQH_Msg_dup(const AQH_MSG *srcMsg)
|
||||
{
|
||||
AQH_MSG *msg;
|
||||
|
||||
msg=AQH_Msg_new();
|
||||
memmove(msg->buffer, srcMsg->buffer, AQH_MAXMSGSIZE);
|
||||
msg->bytesInBuffer=srcMsg->bytesInBuffer;
|
||||
msg->currentPos=srcMsg->currentPos;
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint8_t *AQH_Msg_GetBuffer(AQH_MSG *msg)
|
||||
{
|
||||
if (msg)
|
||||
@@ -230,6 +244,18 @@ int AQH_Msg_AddChecksum(AQH_MSG *msg)
|
||||
|
||||
|
||||
|
||||
void AQH_Msg_DumpToBuffer(const AQH_MSG *msg, GWEN_BUFFER *dbuf, const char *sText)
|
||||
{
|
||||
GWEN_Buffer_AppendArgs(dbuf,
|
||||
"0x%02x->0x%02x: %d %s\n",
|
||||
AQH_Msg_GetSourceAddress(msg),
|
||||
AQH_Msg_GetDestAddress(msg),
|
||||
AQH_Msg_GetMsgType(msg),
|
||||
sText);
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint8_t _calcChecksum(const uint8_t *ptr, uint8_t len)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <aqhome/api.h>
|
||||
|
||||
#include <gwenhywfar/list.h>
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
|
||||
@@ -39,6 +40,9 @@
|
||||
#define AQH_MSG_TYPE_DENY_ADDRESS 63
|
||||
#define AQH_MSG_TYPE_ADDRESS_RANGE 64
|
||||
|
||||
/* internal msg types via NET interface */
|
||||
#define AQH_MSG_TYPE_NET_SET_ACCEPTED_MSGGROUPS 200
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -49,6 +53,7 @@ GWEN_LIST_FUNCTION_LIB_DEFS(AQH_MSG, AQH_Msg, AQHOME_API)
|
||||
|
||||
AQHOME_API AQH_MSG *AQH_Msg_new();
|
||||
AQHOME_API void AQH_Msg_free(AQH_MSG *msg);
|
||||
AQHOME_API AQH_MSG *AQH_Msg_dup(const AQH_MSG *srcMsg);
|
||||
|
||||
AQHOME_API uint8_t *AQH_Msg_GetBuffer(AQH_MSG *msg);
|
||||
AQHOME_API const uint8_t *AQH_Msg_GetConstBuffer(const AQH_MSG *msg);
|
||||
@@ -69,6 +74,8 @@ AQHOME_API int AQH_Msg_IsMsgComplete(const AQH_MSG *msg);
|
||||
AQHOME_API int AQH_Msg_IsChecksumValid(const AQH_MSG *msg);
|
||||
AQHOME_API int AQH_Msg_AddChecksum(AQH_MSG *msg);
|
||||
|
||||
AQHOME_API void AQH_Msg_DumpToBuffer(const AQH_MSG *msg, GWEN_BUFFER *dbuf, const char *sText);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
73
aqhome/msg_setaccmsggrps.c
Normal file
73
aqhome/msg_setaccmsggrps.c
Normal file
@@ -0,0 +1,73 @@
|
||||
/****************************************************************************
|
||||
* 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/msg_setaccmsggrps.h"
|
||||
|
||||
#include <gwenhywfar/misc.h>
|
||||
#include <gwenhywfar/list.h>
|
||||
#include <gwenhywfar/error.h>
|
||||
#include <gwenhywfar/debug.h>
|
||||
|
||||
|
||||
|
||||
|
||||
AQH_MSG *AQH_MsgSetAcceptedMsgGroups_new(uint8_t destAddr, uint32_t groups)
|
||||
{
|
||||
AQH_MSG *msg;
|
||||
|
||||
msg=AQH_Msg_new();
|
||||
AQH_Msg_AddByte(msg, destAddr); /* DESTADDR */
|
||||
AQH_Msg_AddByte(msg, 2+4); /* MSGLEN: srcAddr(1), msgType(1), groups (4) */
|
||||
AQH_Msg_AddByte(msg, AQH_MSG_TYPE_NET_SET_ACCEPTED_MSGGROUPS); /* MSGTYPE */
|
||||
AQH_Msg_AddByte(msg, 0); /* SRCADDR (admin, no src address needed) */
|
||||
AQH_Msg_AddByte(msg, groups & 0xff); /* 4 bytes remaining payload */
|
||||
AQH_Msg_AddByte(msg, (groups>>8) & 0xff);
|
||||
AQH_Msg_AddByte(msg, (groups>>16) & 0xff);
|
||||
AQH_Msg_AddByte(msg, (groups>>24) & 0xff);
|
||||
AQH_Msg_AddChecksum(msg);
|
||||
AQH_Msg_RewindCurrentPos(msg);
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint32_t AQH_MsgSetAcceptedMsgGroups_GetMsgGroups(const AQH_MSG *msg)
|
||||
{
|
||||
if ((AQH_Msg_GetMsgType(msg)==AQH_MSG_TYPE_NET_SET_ACCEPTED_MSGGROUPS) &&
|
||||
(AQH_Msg_GetBytesInBuffer(msg)>=AQH_MSG_SETACCMSGGRPS_MINSIZE)) {
|
||||
const uint8_t *ptr;
|
||||
|
||||
ptr=AQH_Msg_GetConstBuffer(msg)+AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_SETACCMSGGRPS_GRPS;
|
||||
return (uint32_t)(ptr[0])+(ptr[1]<<8)+(ptr[2]<<16)+(ptr[3]<<24);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_MsgSetAcceptedMsgGroups_DumpToBuffer(const AQH_MSG *msg, GWEN_BUFFER *dbuf, const char *sText)
|
||||
{
|
||||
if ((AQH_Msg_GetMsgType(msg)==AQH_MSG_TYPE_NET_SET_ACCEPTED_MSGGROUPS) &&
|
||||
(AQH_Msg_GetBytesInBuffer(msg)>=AQH_MSG_SETACCMSGGRPS_MINSIZE)) {
|
||||
GWEN_Buffer_AppendArgs(dbuf,
|
||||
"0x%02x->0x%02x: ACCEPTED_MSG_GROUPS %s (groups=0x%08x)\n",
|
||||
AQH_Msg_GetSourceAddress(msg),
|
||||
AQH_Msg_GetDestAddress(msg),
|
||||
sText,
|
||||
(unsigned int) AQH_MsgSetAcceptedMsgGroups_GetMsgGroups(msg));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
37
aqhome/msg_setaccmsggrps.h
Normal file
37
aqhome/msg_setaccmsggrps.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/****************************************************************************
|
||||
* 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.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQH_MSG_SETACCMSGGRPS_H
|
||||
#define AQH_MSG_SETACCMSGGRPS_H
|
||||
|
||||
|
||||
#include <aqhome/api.h>
|
||||
|
||||
#include "aqhome/msg.h"
|
||||
|
||||
#include <gwenhywfar/list.h>
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
|
||||
#define AQH_MSG_OFFS_SETACCMSGGRPS_GRPS 0
|
||||
|
||||
#define AQH_MSG_SETACCMSGGRPS_MINSIZE (AQH_MSG_OFFS_ALL_DATA_BEGIN+AQH_MSG_OFFS_SETACCMSGGRPS_GRPS+4)
|
||||
|
||||
|
||||
|
||||
AQHOME_API AQH_MSG *AQH_MsgSetAcceptedMsgGroups_new(uint8_t destAddr, uint32_t groups);
|
||||
|
||||
AQHOME_API uint32_t AQH_MsgSetAcceptedMsgGroups_GetMsgGroups(const AQH_MSG *msg);
|
||||
AQHOME_API void AQH_MsgSetAcceptedMsgGroups_DumpToBuffer(const AQH_MSG *msg, GWEN_BUFFER *dbuf, const char *sText);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
555
aqhome/msgendpoint.c
Normal file
555
aqhome/msgendpoint.c
Normal file
@@ -0,0 +1,555 @@
|
||||
/****************************************************************************
|
||||
* 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/msgendpoint_p.h"
|
||||
|
||||
|
||||
#include <gwenhywfar/misc.h>
|
||||
#include <gwenhywfar/list.h>
|
||||
#include <gwenhywfar/error.h>
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/text.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
# include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
|
||||
#define AQH_MSG_ENDPOINT_BUFFERSIZE 32
|
||||
|
||||
|
||||
GWEN_LIST_FUNCTIONS(AQH_MSG_ENDPOINT, AQH_MsgEndpoint)
|
||||
GWEN_INHERIT_FUNCTIONS(AQH_MSG_ENDPOINT)
|
||||
|
||||
|
||||
static int _internalHandleReadable(AQH_MSG_ENDPOINT *ep);
|
||||
static int _internalHandleWritable(AQH_MSG_ENDPOINT *ep, AQH_MSG_ENDPOINT_MGR *emgr);
|
||||
static int _setSocketNonBlocking(int fd);
|
||||
|
||||
|
||||
|
||||
|
||||
AQH_MSG_ENDPOINT *AQH_MsgEndpoint_new(int fd, int groupId)
|
||||
{
|
||||
AQH_MSG_ENDPOINT *ep;
|
||||
|
||||
GWEN_NEW_OBJECT(AQH_MSG_ENDPOINT, ep);
|
||||
GWEN_INHERIT_INIT(AQH_MSG_ENDPOINT, ep);
|
||||
GWEN_LIST_INIT(AQH_MSG_ENDPOINT, ep);
|
||||
ep->fd=fd;
|
||||
ep->groupId=groupId;
|
||||
ep->receivedMessageList=AQH_Msg_List_new();
|
||||
ep->sendMessageList=AQH_Msg_List_new();
|
||||
|
||||
return ep;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_MsgEndpoint_free(AQH_MSG_ENDPOINT *ep)
|
||||
{
|
||||
if (ep) {
|
||||
GWEN_LIST_FINI(AQH_MSG_ENDPOINT, ep);
|
||||
GWEN_INHERIT_FINI(AQH_MSG_ENDPOINT, ep);
|
||||
if (ep->fd>=0)
|
||||
close(ep->fd);
|
||||
AQH_Msg_free(ep->currentlyReceivedMsg);
|
||||
AQH_Msg_List_free(ep->receivedMessageList);
|
||||
AQH_Msg_List_free(ep->sendMessageList);
|
||||
GWEN_FREE_OBJECT(ep);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_MsgEndpoint_GetFd(const AQH_MSG_ENDPOINT *ep)
|
||||
{
|
||||
return ep->fd;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint32_t AQH_MsgEndpoint_GetGroupId(const AQH_MSG_ENDPOINT *ep)
|
||||
{
|
||||
return ep->groupId;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint32_t AQH_MsgEndpoint_GetAcceptedMsgGroups(const AQH_MSG_ENDPOINT *ep)
|
||||
{
|
||||
return ep->acceptedMsgGroups;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_MsgEndpoint_SetAcceptedMsgGroups(AQH_MSG_ENDPOINT *ep, uint32_t f)
|
||||
{
|
||||
ep->acceptedMsgGroups=f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_MsgEndpoint_AddAcceptedMsgGroups(AQH_MSG_ENDPOINT *ep, uint32_t f)
|
||||
{
|
||||
ep->acceptedMsgGroups|=f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_MsgEndpoint_DelAcceptedMsgGroups(AQH_MSG_ENDPOINT *ep, uint32_t f)
|
||||
{
|
||||
ep->acceptedMsgGroups&=~f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint32_t AQH_MsgEndpoint_GetAcceptedEndpointGroups(const AQH_MSG_ENDPOINT *ep)
|
||||
{
|
||||
return ep->acceptedEndpointGroups;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_MsgEndpoint_SetAcceptedEndpointGroups(AQH_MSG_ENDPOINT *ep, uint32_t f)
|
||||
{
|
||||
ep->acceptedEndpointGroups=f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_MsgEndpoint_AddAcceptedEndpointGroups(AQH_MSG_ENDPOINT *ep, uint32_t f)
|
||||
{
|
||||
ep->acceptedEndpointGroups|=f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_MsgEndpoint_DelAcceptedEndpointGroups(AQH_MSG_ENDPOINT *ep, uint32_t f)
|
||||
{
|
||||
ep->acceptedEndpointGroups&=~f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint32_t AQH_MsgEndpoint_GetFlags(const AQH_MSG_ENDPOINT *ep)
|
||||
{
|
||||
return ep->flags;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_MsgEndpoint_SetFlags(AQH_MSG_ENDPOINT *ep, uint32_t f)
|
||||
{
|
||||
ep->flags=f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_MsgEndpoint_AddFlags(AQH_MSG_ENDPOINT *ep, uint32_t f)
|
||||
{
|
||||
ep->flags|=f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_MsgEndpoint_SubFlags(AQH_MSG_ENDPOINT *ep, uint32_t f)
|
||||
{
|
||||
ep->flags&=~f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
AQH_MSG_LIST *AQH_MsgEndpoint_GetReceivedMessageList(const AQH_MSG_ENDPOINT *ep)
|
||||
{
|
||||
return ep->receivedMessageList;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_MSG *AQH_MsgEndpoint_TakeFirstReceivedMessage(AQH_MSG_ENDPOINT *ep)
|
||||
{
|
||||
AQH_MSG *msg;
|
||||
|
||||
msg=AQH_Msg_List_First(ep->receivedMessageList);
|
||||
if (msg)
|
||||
AQH_Msg_List_Del(msg);
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_MSG_LIST *AQH_MsgEndpoint_GetSendMessageList(const AQH_MSG_ENDPOINT *ep)
|
||||
{
|
||||
return ep->sendMessageList;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_MsgEndpoint_AddReceivedMessage(AQH_MSG_ENDPOINT *ep, AQH_MSG *m)
|
||||
{
|
||||
AQH_Msg_List_Add(m, ep->receivedMessageList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_MsgEndpoint_AddSendMessage(AQH_MSG_ENDPOINT *ep, AQH_MSG *m)
|
||||
{
|
||||
AQH_Msg_List_Add(m, ep->sendMessageList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_MSG *AQH_MsgEndpoint_GetCurrentlyReceivedMsg(const AQH_MSG_ENDPOINT *ep)
|
||||
{
|
||||
return ep->currentlyReceivedMsg;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_MsgEndpoint_SetCurrentlyReceivedMsg(AQH_MSG_ENDPOINT *ep, AQH_MSG *m)
|
||||
{
|
||||
AQH_Msg_free(ep->currentlyReceivedMsg);
|
||||
ep->currentlyReceivedMsg=m;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_MsgEndpoint_HandleReadable(AQH_MSG_ENDPOINT *ep, AQH_MSG_ENDPOINT_MGR *emgr)
|
||||
{
|
||||
return (ep->handleReadableFn)?(ep->handleReadableFn(ep, emgr)):_internalHandleReadable(ep);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_MsgEndpoint_HandleWritable(AQH_MSG_ENDPOINT *ep, AQH_MSG_ENDPOINT_MGR *emgr)
|
||||
{
|
||||
return (ep->handleWritableFn)?(ep->handleWritableFn(ep, emgr)):_internalHandleWritable(ep, emgr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_MsgEndpoint_Run(AQH_MSG_ENDPOINT *ep)
|
||||
{
|
||||
if (ep->runFn)
|
||||
ep->runFn(ep);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_MsgEndpoint_StartMsg(AQH_MSG_ENDPOINT *ep)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv=(ep->startMsgFn)?(ep->startMsgFn(ep)):0;
|
||||
if (rv==0)
|
||||
ep->sendingMessage=1;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_MsgEndpoint_EndMsg(AQH_MSG_ENDPOINT *ep)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv=(ep->endMsgFn)?(ep->endMsgFn(ep)):0;
|
||||
if (rv==0)
|
||||
ep->sendingMessage=0;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_MsgEndpoint_CheckMsg(AQH_MSG_ENDPOINT *ep)
|
||||
{
|
||||
return (ep->checkMsgFn)?(ep->checkMsgFn(ep)):1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_MSG_ENDPOINT_HANDLEREADABLE_FN AQH_MsgEndpoint_SetHandleReadableFn(AQH_MSG_ENDPOINT *ep,
|
||||
AQH_MSG_ENDPOINT_HANDLEREADABLE_FN f)
|
||||
{
|
||||
AQH_MSG_ENDPOINT_HANDLEREADABLE_FN oldFn;
|
||||
|
||||
oldFn=ep->handleReadableFn;
|
||||
ep->handleReadableFn=f;
|
||||
return oldFn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_MSG_ENDPOINT_HANDLEWRITABLE_FN AQH_MsgEndpoint_SetHandleWritableFn(AQH_MSG_ENDPOINT *ep,
|
||||
AQH_MSG_ENDPOINT_HANDLEWRITABLE_FN f)
|
||||
{
|
||||
AQH_MSG_ENDPOINT_HANDLEWRITABLE_FN oldFn;
|
||||
|
||||
oldFn=ep->handleWritableFn;
|
||||
ep->handleWritableFn=f;
|
||||
return oldFn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_MSG_ENDPOINT_GET_READFD_FN AQH_MsgEndpoint_SetGetReadFdFn(AQH_MSG_ENDPOINT *ep,
|
||||
AQH_MSG_ENDPOINT_GET_READFD_FN f)
|
||||
{
|
||||
AQH_MSG_ENDPOINT_GET_READFD_FN oldFn;
|
||||
|
||||
oldFn=ep->getReadFdFn;
|
||||
ep->getReadFdFn=f;
|
||||
return oldFn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_MSG_ENDPOINT_GET_WRITEFD_FN AQH_MsgEndpoint_SetGetWriteFdFn(AQH_MSG_ENDPOINT *ep,
|
||||
AQH_MSG_ENDPOINT_GET_WRITEFD_FN f)
|
||||
{
|
||||
AQH_MSG_ENDPOINT_GET_WRITEFD_FN oldFn;
|
||||
|
||||
oldFn=ep->getWriteFdFn;
|
||||
ep->getWriteFdFn=f;
|
||||
return oldFn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_MSG_ENDPOINT_RUN_FN AQH_MsgEndpoint_SetRunFn(AQH_MSG_ENDPOINT *ep, AQH_MSG_ENDPOINT_RUN_FN f)
|
||||
{
|
||||
AQH_MSG_ENDPOINT_RUN_FN oldFn;
|
||||
|
||||
oldFn=ep->runFn;
|
||||
ep->runFn=f;
|
||||
return oldFn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_MSG_ENDPOINT_STARTMSG_FN AQH_MsgEndpoint_SetStartMsgFn(AQH_MSG_ENDPOINT *ep, AQH_MSG_ENDPOINT_STARTMSG_FN f)
|
||||
{
|
||||
AQH_MSG_ENDPOINT_STARTMSG_FN oldFn;
|
||||
|
||||
oldFn=ep->startMsgFn;
|
||||
ep->startMsgFn=f;
|
||||
return oldFn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_MSG_ENDPOINT_ENDMSG_FN AQH_MsgEndpoint_SetEndMsgFn(AQH_MSG_ENDPOINT *ep, AQH_MSG_ENDPOINT_ENDMSG_FN f)
|
||||
{
|
||||
AQH_MSG_ENDPOINT_ENDMSG_FN oldFn;
|
||||
|
||||
oldFn=ep->endMsgFn;
|
||||
ep->endMsgFn=f;
|
||||
return oldFn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_MSG_ENDPOINT_CHECKMSG_FN AQH_MsgEndpoint_SetCheckMsgFn(AQH_MSG_ENDPOINT *ep, AQH_MSG_ENDPOINT_CHECKMSG_FN f)
|
||||
{
|
||||
AQH_MSG_ENDPOINT_CHECKMSG_FN oldFn;
|
||||
|
||||
oldFn=ep->checkMsgFn;
|
||||
ep->checkMsgFn=f;
|
||||
return oldFn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_MsgEndpoint_GetReadFd(AQH_MSG_ENDPOINT *ep)
|
||||
{
|
||||
return (ep->getReadFdFn)?(ep->getReadFdFn(ep)):(ep->fd);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_MsgEndpoint_GetWriteFd(AQH_MSG_ENDPOINT *ep)
|
||||
{
|
||||
if (ep->getWriteFdFn)
|
||||
return ep->getWriteFdFn(ep);
|
||||
else {
|
||||
int somethingToWrite;
|
||||
|
||||
somethingToWrite=(AQH_Msg_List_First(ep->sendMessageList)!=NULL)?1:0;
|
||||
if (somethingToWrite)
|
||||
return ep->fd;
|
||||
}
|
||||
return GWEN_ERROR_NO_DATA;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int AQH_MsgEndpoint_DiscardInput(AQH_MSG_ENDPOINT *ep)
|
||||
{
|
||||
int rv;
|
||||
uint8_t buffer[AQH_MSG_ENDPOINT_BUFFERSIZE];
|
||||
|
||||
do {
|
||||
rv=read(ep->fd, buffer, sizeof(buffer));
|
||||
} while( (rv>0 || (rv<0) && errno==EINTR));
|
||||
if (rv<0 && errno!=EAGAIN && errno!=EWOULDBLOCK) {
|
||||
DBG_ERROR(NULL, "Error on read(): %s (%d)", strerror(errno), errno);
|
||||
return GWEN_ERROR_IO;
|
||||
}
|
||||
else if (rv==0) {
|
||||
DBG_ERROR(NULL, "EOF met on read()");
|
||||
return GWEN_ERROR_IO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _internalHandleReadable(AQH_MSG_ENDPOINT *ep)
|
||||
{
|
||||
int rv;
|
||||
uint8_t buffer[AQH_MSG_ENDPOINT_BUFFERSIZE*2];
|
||||
int len;
|
||||
int i;
|
||||
|
||||
do {
|
||||
rv=read(ep->fd, buffer, sizeof(buffer));
|
||||
} while( (rv<0) && errno==EINTR);
|
||||
if (rv<0) {
|
||||
if (errno==EAGAIN || errno==EWOULDBLOCK)
|
||||
return GWEN_ERROR_TRY_AGAIN;
|
||||
DBG_ERROR(NULL, "Error on read(): %s (%d)", strerror(errno), errno);
|
||||
return GWEN_ERROR_IO;
|
||||
}
|
||||
else if (rv==0) {
|
||||
DBG_ERROR(NULL, "EOF met on read()");
|
||||
return GWEN_ERROR_IO;
|
||||
}
|
||||
len=rv;
|
||||
|
||||
for (i=0; i<len; i++) {
|
||||
if (ep->currentlyReceivedMsg==NULL)
|
||||
ep->currentlyReceivedMsg=AQH_Msg_new();
|
||||
rv=AQH_Msg_AddByte(ep->currentlyReceivedMsg, buffer[i]);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
rv=AQH_Msg_IsMsgComplete(ep->currentlyReceivedMsg);
|
||||
if (rv<0) {
|
||||
/* invalid message */
|
||||
DBG_ERROR(NULL, "Invalid message, discarding");
|
||||
AQH_Msg_free(ep->currentlyReceivedMsg);
|
||||
ep->currentlyReceivedMsg=NULL;
|
||||
rv=AQH_MsgEndpoint_DiscardInput(ep);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
else if (rv>0) {
|
||||
if (!AQH_Msg_IsChecksumValid(ep->currentlyReceivedMsg)) {
|
||||
DBG_ERROR(NULL, "Invalid checksum, discarding message");
|
||||
GWEN_Text_DumpString(AQH_Msg_GetBuffer(ep->currentlyReceivedMsg), AQH_Msg_GetBytesInBuffer(ep->currentlyReceivedMsg), 6);
|
||||
AQH_Msg_free(ep->currentlyReceivedMsg);
|
||||
ep->currentlyReceivedMsg=NULL;
|
||||
rv=AQH_MsgEndpoint_DiscardInput(ep);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* valid msg received, add to list */
|
||||
AQH_Msg_List_Add(ep->currentlyReceivedMsg, ep->receivedMessageList);
|
||||
ep->currentlyReceivedMsg=NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _internalHandleWritable(AQH_MSG_ENDPOINT *ep, AQH_MSG_ENDPOINT_MGR *emgr)
|
||||
{
|
||||
AQH_MSG *msg;
|
||||
|
||||
msg=AQH_Msg_List_First(ep->sendMessageList);
|
||||
if (msg) {
|
||||
uint8_t pos;
|
||||
int len;
|
||||
int remaining;
|
||||
int rv;
|
||||
|
||||
rv=AQH_MsgEndpoint_CheckMsg(ep);
|
||||
if (rv<0 || rv==1) {
|
||||
DBG_ERROR(NULL, "Line busy, not sending");
|
||||
usleep(100);
|
||||
return 0;
|
||||
}
|
||||
pos=AQH_Msg_GetCurrentPos(msg);
|
||||
remaining=AQH_Msg_GetRemainingBytes(msg);
|
||||
if (remaining>0) {
|
||||
const uint8_t *buf;
|
||||
|
||||
rv=AQH_MsgEndpoint_StartMsg(ep);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
buf=AQH_Msg_GetBuffer(msg)+pos;
|
||||
do {
|
||||
rv=write(ep->fd, buf, remaining);
|
||||
} while(rv<0 && errno==EINTR);
|
||||
if (rv<0) {
|
||||
if (errno==EAGAIN || errno==EWOULDBLOCK)
|
||||
return GWEN_ERROR_TRY_AGAIN;
|
||||
DBG_ERROR(NULL, "Error on write(): %s (%d)", strerror(errno), errno);
|
||||
return GWEN_ERROR_IO;
|
||||
}
|
||||
AQH_Msg_IncCurrentPos(msg, rv);
|
||||
if (rv==remaining) {
|
||||
rv=AQH_MsgEndpoint_EndMsg(ep);
|
||||
// TODO: callback msg sent
|
||||
AQH_Msg_List_Del(msg);
|
||||
AQH_Msg_free(msg);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
125
aqhome/msgendpoint.h
Normal file
125
aqhome/msgendpoint.h
Normal file
@@ -0,0 +1,125 @@
|
||||
/****************************************************************************
|
||||
* 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.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQH_MSGENDPOINT_H
|
||||
#define AQH_MSGENDPOINT_H
|
||||
|
||||
|
||||
#include <aqhome/api.h>
|
||||
|
||||
#include "aqhome/msg.h"
|
||||
|
||||
#include <gwenhywfar/list.h>
|
||||
#include <gwenhywfar/inherit.h>
|
||||
|
||||
|
||||
typedef struct AQH_MSG_ENDPOINT AQH_MSG_ENDPOINT;
|
||||
GWEN_LIST_FUNCTION_LIB_DEFS(AQH_MSG_ENDPOINT, AQH_MsgEndpoint, AQHOME_API)
|
||||
GWEN_INHERIT_FUNCTION_LIB_DEFS(AQH_MSG_ENDPOINT, AQHOME_API)
|
||||
|
||||
|
||||
#include "aqhome/msgendpointmanager.h"
|
||||
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
|
||||
|
||||
#define AQH_MSG_ENDPOINT_ENDPOINTGROUP_BUS 0x0001
|
||||
#define AQH_MSG_ENDPOINT_ENDPOINTGROUP_NET 0x0002
|
||||
|
||||
|
||||
#define AQH_MSG_ENDPOINT_MSGGROUP_INFO 0x00000001
|
||||
#define AQH_MSG_ENDPOINT_MSGGROUP_VALUES 0x00000002
|
||||
#define AQH_MSG_ENDPOINT_MSGGROUP_ADDRESS 0x00000004
|
||||
#define AQH_MSG_ENDPOINT_MSGGROUP_FLASH 0x00000008
|
||||
#define AQH_MSG_ENDPOINT_MSGGROUP_ADMIN 0x00000010
|
||||
#define AQH_MSG_ENDPOINT_MSGGROUP_ALL 0xffffffff
|
||||
|
||||
#define AQH_MSG_ENDPOINT_FLAGS_NOMESSAGES 0x0001
|
||||
#define AQH_MSG_ENDPOINT_FLAGS_NOIO 0x0002
|
||||
|
||||
|
||||
|
||||
typedef int (*AQH_MSG_ENDPOINT_HANDLEREADABLE_FN)(AQH_MSG_ENDPOINT *ep, AQH_MSG_ENDPOINT_MGR *emgr);
|
||||
typedef int (*AQH_MSG_ENDPOINT_HANDLEWRITABLE_FN)(AQH_MSG_ENDPOINT *ep, AQH_MSG_ENDPOINT_MGR *emgr);
|
||||
typedef void (*AQH_MSG_ENDPOINT_RUN_FN)(AQH_MSG_ENDPOINT *ep);
|
||||
typedef int (*AQH_MSG_ENDPOINT_GET_READFD_FN)(AQH_MSG_ENDPOINT *ep);
|
||||
typedef int (*AQH_MSG_ENDPOINT_GET_WRITEFD_FN)(AQH_MSG_ENDPOINT *ep);
|
||||
|
||||
typedef int (*AQH_MSG_ENDPOINT_STARTMSG_FN)(AQH_MSG_ENDPOINT *ep);
|
||||
typedef int (*AQH_MSG_ENDPOINT_ENDMSG_FN)(AQH_MSG_ENDPOINT *ep);
|
||||
typedef int (*AQH_MSG_ENDPOINT_CHECKMSG_FN)(AQH_MSG_ENDPOINT *ep);
|
||||
|
||||
|
||||
|
||||
AQHOME_API AQH_MSG_ENDPOINT *AQH_MsgEndpoint_new(int fd, int groupId);
|
||||
AQHOME_API void AQH_MsgEndpoint_free(AQH_MSG_ENDPOINT *ep);
|
||||
|
||||
AQHOME_API int AQH_MsgEndpoint_GetFd(const AQH_MSG_ENDPOINT *ep);
|
||||
|
||||
AQHOME_API uint32_t AQH_MsgEndpoint_GetGroupId(const AQH_MSG_ENDPOINT *ep);
|
||||
|
||||
AQHOME_API uint32_t AQH_MsgEndpoint_GetAcceptedMsgGroups(const AQH_MSG_ENDPOINT *ep);
|
||||
AQHOME_API void AQH_MsgEndpoint_SetAcceptedMsgGroups(AQH_MSG_ENDPOINT *ep, uint32_t f);
|
||||
AQHOME_API void AQH_MsgEndpoint_AddAcceptedMsgGroups(AQH_MSG_ENDPOINT *ep, uint32_t f);
|
||||
AQHOME_API void AQH_MsgEndpoint_DelAcceptedMsgGroups(AQH_MSG_ENDPOINT *ep, uint32_t f);
|
||||
|
||||
AQHOME_API uint32_t AQH_MsgEndpoint_GetAcceptedEndpointGroups(const AQH_MSG_ENDPOINT *ep);
|
||||
AQHOME_API void AQH_MsgEndpoint_SetAcceptedEndpointGroups(AQH_MSG_ENDPOINT *ep, uint32_t f);
|
||||
AQHOME_API void AQH_MsgEndpoint_AddAcceptedEndpointGroups(AQH_MSG_ENDPOINT *ep, uint32_t f);
|
||||
AQHOME_API void AQH_MsgEndpoint_DelAcceptedEndpointGroups(AQH_MSG_ENDPOINT *ep, uint32_t f);
|
||||
|
||||
AQHOME_API uint32_t AQH_MsgEndpoint_GetFlags(const AQH_MSG_ENDPOINT *ep);
|
||||
AQHOME_API void AQH_MsgEndpoint_SetFlags(AQH_MSG_ENDPOINT *ep, uint32_t f);
|
||||
AQHOME_API void AQH_MsgEndpoint_AddFlags(AQH_MSG_ENDPOINT *ep, uint32_t f);
|
||||
AQHOME_API void AQH_MsgEndpoint_SubFlags(AQH_MSG_ENDPOINT *ep, uint32_t f);
|
||||
|
||||
AQHOME_API AQH_MSG_LIST *AQH_MsgEndpoint_GetReceivedMessageList(const AQH_MSG_ENDPOINT *ep);
|
||||
AQHOME_API AQH_MSG_LIST *AQH_MsgEndpoint_GetSendMessageList(const AQH_MSG_ENDPOINT *ep);
|
||||
|
||||
AQHOME_API void AQH_MsgEndpoint_AddReceivedMessage(AQH_MSG_ENDPOINT *ep, AQH_MSG *m);
|
||||
AQHOME_API AQH_MSG *AQH_MsgEndpoint_TakeFirstReceivedMessage(AQH_MSG_ENDPOINT *ep);
|
||||
AQHOME_API void AQH_MsgEndpoint_AddSendMessage(AQH_MSG_ENDPOINT *ep, AQH_MSG *m);
|
||||
|
||||
AQHOME_API AQH_MSG *AQH_MsgEndpoint_GetCurrentlyReceivedMsg(const AQH_MSG_ENDPOINT *ep);
|
||||
AQHOME_API void AQH_MsgEndpoint_SetCurrentlyReceivedMsg(AQH_MSG_ENDPOINT *ep, AQH_MSG *m);
|
||||
|
||||
|
||||
AQHOME_API int AQH_MsgEndpoint_GetReadFd(AQH_MSG_ENDPOINT *ep);
|
||||
AQHOME_API int AQH_MsgEndpoint_GetWriteFd(AQH_MSG_ENDPOINT *ep);
|
||||
|
||||
AQHOME_API int AQH_MsgEndpoint_HandleReadable(AQH_MSG_ENDPOINT *ep, AQH_MSG_ENDPOINT_MGR *emgr);
|
||||
AQHOME_API int AQH_MsgEndpoint_HandleWritable(AQH_MSG_ENDPOINT *ep, AQH_MSG_ENDPOINT_MGR *emgr);
|
||||
AQHOME_API void AQH_MsgEndpoint_Run(AQH_MSG_ENDPOINT *ep);
|
||||
|
||||
AQHOME_API int AQH_MsgEndpoint_DiscardInput(AQH_MSG_ENDPOINT *ep);
|
||||
|
||||
AQHOME_API int AQH_MsgEndpoint_StartMsg(AQH_MSG_ENDPOINT *ep);
|
||||
AQHOME_API int AQH_MsgEndpoint_EndMsg(AQH_MSG_ENDPOINT *ep);
|
||||
AQHOME_API int AQH_MsgEndpoint_CheckMsg(AQH_MSG_ENDPOINT *ep);
|
||||
|
||||
|
||||
AQHOME_API AQH_MSG_ENDPOINT_HANDLEREADABLE_FN AQH_MsgEndpoint_SetHandleReadableFn(AQH_MSG_ENDPOINT *ep,
|
||||
AQH_MSG_ENDPOINT_HANDLEREADABLE_FN f);
|
||||
AQHOME_API AQH_MSG_ENDPOINT_HANDLEWRITABLE_FN AQH_MsgEndpoint_SetHandleWritableFn(AQH_MSG_ENDPOINT *ep,
|
||||
AQH_MSG_ENDPOINT_HANDLEWRITABLE_FN f);
|
||||
AQHOME_API AQH_MSG_ENDPOINT_GET_READFD_FN AQH_MsgEndpoint_SetGetReadFdFn(AQH_MSG_ENDPOINT *ep,
|
||||
AQH_MSG_ENDPOINT_GET_READFD_FN f);
|
||||
AQHOME_API AQH_MSG_ENDPOINT_GET_WRITEFD_FN AQH_MsgEndpoint_SetGetWriteFdFn(AQH_MSG_ENDPOINT *ep,
|
||||
AQH_MSG_ENDPOINT_GET_WRITEFD_FN f);
|
||||
|
||||
AQHOME_API AQH_MSG_ENDPOINT_RUN_FN AQH_MsgEndpoint_SetRunFn(AQH_MSG_ENDPOINT *ep, AQH_MSG_ENDPOINT_RUN_FN f);
|
||||
AQHOME_API AQH_MSG_ENDPOINT_STARTMSG_FN AQH_MsgEndpoint_SetStartMsgFn(AQH_MSG_ENDPOINT *ep, AQH_MSG_ENDPOINT_STARTMSG_FN f);
|
||||
AQHOME_API AQH_MSG_ENDPOINT_ENDMSG_FN AQH_MsgEndpoint_SetEndMsgFn(AQH_MSG_ENDPOINT *ep, AQH_MSG_ENDPOINT_ENDMSG_FN f);
|
||||
AQHOME_API AQH_MSG_ENDPOINT_CHECKMSG_FN AQH_MsgEndpoint_SetCheckMsgFn(AQH_MSG_ENDPOINT *ep, AQH_MSG_ENDPOINT_CHECKMSG_FN f);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
51
aqhome/msgendpoint_p.h
Normal file
51
aqhome/msgendpoint_p.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/****************************************************************************
|
||||
* 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.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQH_MSGENDPOINT_P_H
|
||||
#define AQH_MSGENDPOINT_P_H
|
||||
|
||||
|
||||
#include <aqhome/api.h>
|
||||
|
||||
#include "aqhome/msgendpoint.h"
|
||||
|
||||
#include <gwenhywfar/list.h>
|
||||
#include <gwenhywfar/buffer.h>
|
||||
|
||||
|
||||
struct AQH_MSG_ENDPOINT {
|
||||
GWEN_INHERIT_ELEMENT(AQH_MSG_ENDPOINT)
|
||||
GWEN_LIST_ELEMENT(AQH_MSG_ENDPOINT)
|
||||
|
||||
int fd;
|
||||
AQH_MSG_LIST *receivedMessageList;
|
||||
AQH_MSG_LIST *sendMessageList;
|
||||
AQH_MSG *currentlyReceivedMsg;
|
||||
|
||||
AQH_MSG_ENDPOINT_HANDLEREADABLE_FN handleReadableFn;
|
||||
AQH_MSG_ENDPOINT_HANDLEWRITABLE_FN handleWritableFn;
|
||||
AQH_MSG_ENDPOINT_GET_READFD_FN getReadFdFn;
|
||||
AQH_MSG_ENDPOINT_GET_WRITEFD_FN getWriteFdFn;
|
||||
AQH_MSG_ENDPOINT_RUN_FN runFn;
|
||||
AQH_MSG_ENDPOINT_STARTMSG_FN startMsgFn;
|
||||
AQH_MSG_ENDPOINT_ENDMSG_FN endMsgFn;
|
||||
AQH_MSG_ENDPOINT_CHECKMSG_FN checkMsgFn;
|
||||
|
||||
uint32_t flags;
|
||||
uint32_t groupId;
|
||||
uint32_t acceptedEndpointGroups;
|
||||
uint32_t acceptedMsgGroups;
|
||||
|
||||
int sendingMessage;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
155
aqhome/msgendpointlog.c
Normal file
155
aqhome/msgendpointlog.c
Normal file
@@ -0,0 +1,155 @@
|
||||
/****************************************************************************
|
||||
* 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/msgendpointlog_p.h"
|
||||
|
||||
#include "aqhome/msg_value.h"
|
||||
#include "aqhome/msg_sendstats.h"
|
||||
#include "aqhome/msg_ping.h"
|
||||
#include "aqhome/msg_pong.h"
|
||||
#include "aqhome/msg_needaddr.h"
|
||||
#include "aqhome/msg_claimaddr.h"
|
||||
#include "aqhome/msg_haveaddr.h"
|
||||
#include "aqhome/msg_denyaddr.h"
|
||||
|
||||
#include <gwenhywfar/list.h>
|
||||
#include <gwenhywfar/inherit.h>
|
||||
#include <gwenhywfar/debug.h>
|
||||
#include <gwenhywfar/gwentime.h>
|
||||
|
||||
|
||||
|
||||
GWEN_INHERIT(AQH_MSG_ENDPOINT, AQH_MSG_ENDPOINT_LOG)
|
||||
|
||||
|
||||
static void GWENHYWFAR_CB _freeData(void *bp, void *p);
|
||||
static void _run(AQH_MSG_ENDPOINT *ep);
|
||||
static void _logMessage(AQH_MSG_ENDPOINT *ep, const AQH_MSG *msg);
|
||||
static void _writeToLogFile(const char *filename, const char *txt);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
AQH_MSG_ENDPOINT *AQH_MsgEndpointLog_new(const char *filename)
|
||||
{
|
||||
int fd;
|
||||
AQH_MSG_ENDPOINT *ep;
|
||||
AQH_MSG_ENDPOINT_LOG *xep;
|
||||
|
||||
ep=AQH_MsgEndpoint_new(-1, AQH_MSG_ENDPOINT_ENDPOINTGROUP_NET);
|
||||
GWEN_NEW_OBJECT(AQH_MSG_ENDPOINT_LOG, xep);
|
||||
xep->filename=strdup(filename);
|
||||
GWEN_INHERIT_SETDATA(AQH_MSG_ENDPOINT, AQH_MSG_ENDPOINT_LOG, ep, xep, _freeData);
|
||||
AQH_MsgEndpoint_SetAcceptedEndpointGroups(ep, AQH_MSG_ENDPOINT_ENDPOINTGROUP_BUS);
|
||||
AQH_MsgEndpoint_SetAcceptedMsgGroups(ep, AQH_MSG_ENDPOINT_MSGGROUP_ALL);
|
||||
AQH_MsgEndpoint_AddFlags(ep, AQH_MSG_ENDPOINT_FLAGS_NOIO);
|
||||
AQH_MsgEndpoint_SetRunFn(ep, _run);
|
||||
|
||||
return ep;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _freeData(void *bp, void *p)
|
||||
{
|
||||
AQH_MSG_ENDPOINT_LOG *xep;
|
||||
|
||||
xep=(AQH_MSG_ENDPOINT_LOG*) p;
|
||||
free(xep->filename);
|
||||
GWEN_FREE_OBJECT(xep);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _run(AQH_MSG_ENDPOINT *ep)
|
||||
{
|
||||
AQH_MSG_LIST *msgList;
|
||||
|
||||
msgList=AQH_MsgEndpoint_GetSendMessageList(ep);
|
||||
if (msgList && AQH_Msg_List_GetCount(msgList)) {
|
||||
AQH_MSG *msg;
|
||||
|
||||
msg=AQH_Msg_List_First(msgList);
|
||||
while(msg) {
|
||||
AQH_MSG *next;
|
||||
|
||||
next=AQH_Msg_List_Next(msg);
|
||||
_logMessage(ep, msg);
|
||||
AQH_Msg_free(msg);
|
||||
msg=next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _logMessage(AQH_MSG_ENDPOINT *ep, const AQH_MSG *msg)
|
||||
{
|
||||
AQH_MSG_ENDPOINT_LOG *xep;
|
||||
const uint8_t *ptr;
|
||||
uint8_t len;
|
||||
uint8_t msgType;
|
||||
int msgIsValid;
|
||||
GWEN_BUFFER *dbuf;
|
||||
GWEN_TIME *ti;
|
||||
|
||||
xep=GWEN_INHERIT_GETDATA(AQH_MSG_ENDPOINT, AQH_MSG_ENDPOINT_LOG, ep);
|
||||
dbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
ti=GWEN_CurrentTime();
|
||||
GWEN_Time_toString(ti, "YYYY-MM-DD hh:mm:ss ", dbuf);
|
||||
GWEN_Time_free(ti);
|
||||
ti=NULL;
|
||||
|
||||
msgIsValid=(AQH_Msg_IsChecksumValid(msg) && AQH_Msg_IsMsgComplete(msg));
|
||||
ptr=AQH_Msg_GetConstBuffer(msg);
|
||||
len=AQH_Msg_GetBytesInBuffer(msg);
|
||||
msgType=AQH_Msg_GetMsgType(msg);
|
||||
|
||||
switch(msgType) {
|
||||
case AQH_MSG_TYPE_PING: AQH_MsgPing_DumpToBuffer(msg, dbuf, "received"); break;
|
||||
case AQH_MSG_TYPE_PONG: AQH_MsgPong_DumpToBuffer(msg, dbuf, "received"); break;
|
||||
case AQH_MSG_TYPE_COMSENDSTATS: AQH_MsgSendStats_DumpToBuffer(msg, dbuf, "received"); break;
|
||||
case AQH_MSG_TYPE_TWIBUSMEMBER: AQH_Msg_DumpToBuffer(msg, dbuf, "received"); break;
|
||||
case AQH_MSG_TYPE_DEBUG: AQH_Msg_DumpToBuffer(msg, dbuf, "received"); break;
|
||||
case AQH_MSG_TYPE_VALUE: AQH_MsgValue_DumpToBuffer(msg, dbuf, "received"); break;
|
||||
case AQH_MSG_TYPE_NEED_ADDRESS: AQH_MsgNeedAddr_DumpToBuffer(msg, dbuf, "received"); break;
|
||||
case AQH_MSG_TYPE_CLAIM_ADDRESS: AQH_MsgClaimAddr_DumpToBuffer(msg, dbuf, "received"); break;
|
||||
case AQH_MSG_TYPE_HAVE_ADDRESS: AQH_MsgHaveAddr_DumpToBuffer(msg, dbuf, "received"); break;
|
||||
case AQH_MSG_TYPE_DENY_ADDRESS: AQH_MsgDenyAddr_DumpToBuffer(msg, dbuf, "received"); break;
|
||||
default: AQH_MsgValue_DumpToBuffer(msg, dbuf, "received"); break;
|
||||
}
|
||||
_writeToLogFile(xep->filename, GWEN_Buffer_GetStart(dbuf));
|
||||
GWEN_Buffer_free(dbuf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _writeToLogFile(const char *filename, const char *txt)
|
||||
{
|
||||
if (txt && *txt) {
|
||||
FILE *f;
|
||||
|
||||
f=fopen(filename, "a+");
|
||||
if (f) {
|
||||
if (1!=fwrite(txt, strlen(txt), 1, f)) {
|
||||
DBG_ERROR(NULL, "Error logging.");
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
27
aqhome/msgendpointlog.h
Normal file
27
aqhome/msgendpointlog.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/****************************************************************************
|
||||
* 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.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQH_MSGENDPOINT_LOG_H
|
||||
#define AQH_MSGENDPOINT_LOG_H
|
||||
|
||||
|
||||
#include <aqhome/api.h>
|
||||
|
||||
#include "aqhome/msgendpoint.h"
|
||||
|
||||
#include <gwenhywfar/list.h>
|
||||
#include <gwenhywfar/inherit.h>
|
||||
|
||||
|
||||
AQHOME_API AQH_MSG_ENDPOINT *AQH_MsgEndpointLog_new(const char *filename);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
25
aqhome/msgendpointlog_p.h
Normal file
25
aqhome/msgendpointlog_p.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/****************************************************************************
|
||||
* 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.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQH_MSGENDPOINT_LOG_P_H
|
||||
#define AQH_MSGENDPOINT_LOG_P_H
|
||||
|
||||
|
||||
#include "aqhome/msgendpointlog.h"
|
||||
|
||||
|
||||
typedef struct AQH_MSG_ENDPOINT_LOG AQH_MSG_ENDPOINT_LOG;
|
||||
struct AQH_MSG_ENDPOINT_LOG {
|
||||
char *filename;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
307
aqhome/msgendpointmanager.c
Normal file
307
aqhome/msgendpointmanager.c
Normal file
@@ -0,0 +1,307 @@
|
||||
/****************************************************************************
|
||||
* 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/msgendpointmanager_p.h"
|
||||
#include "aqhome/msg_setaccmsggrps.h"
|
||||
|
||||
#include <gwenhywfar/misc.h>
|
||||
#include <gwenhywfar/list.h>
|
||||
#include <gwenhywfar/error.h>
|
||||
#include <gwenhywfar/debug.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
|
||||
static int _ioLoopOnce(AQH_MSG_ENDPOINT_MGR *emgr);
|
||||
static void _msgLoopOnce(AQH_MSG_ENDPOINT_MGR *emgr);
|
||||
static void _runAllEndpoints(AQH_MSG_ENDPOINT_MGR *emgr);
|
||||
static void _distributeMsg(AQH_MSG_ENDPOINT_MGR *emgr, AQH_MSG_ENDPOINT *ep, const AQH_MSG *msg);
|
||||
static void _handleAdminMsg(AQH_MSG_ENDPOINT_MGR *emgr, AQH_MSG_ENDPOINT *ep, const AQH_MSG *msg);
|
||||
static void _handleMsgSetAcceptedMsgGroups(AQH_MSG_ENDPOINT_MGR *emgr, AQH_MSG_ENDPOINT *ep, const AQH_MSG *msg);
|
||||
static uint32_t _getMsgGroup(uint8_t msgType);
|
||||
|
||||
|
||||
|
||||
|
||||
AQH_MSG_ENDPOINT_MGR *AQH_MsgEndpointMgr_new(uint8_t busAddr)
|
||||
{
|
||||
AQH_MSG_ENDPOINT_MGR *emgr;
|
||||
|
||||
GWEN_NEW_OBJECT(AQH_MSG_ENDPOINT_MGR, emgr);
|
||||
emgr->endpointList=AQH_MsgEndpoint_List_new();
|
||||
emgr->busAddr=busAddr;
|
||||
return emgr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_MsgEndpointMgr_free(AQH_MSG_ENDPOINT_MGR *emgr)
|
||||
{
|
||||
if (emgr) {
|
||||
AQH_MsgEndpoint_List_free(emgr->endpointList);
|
||||
GWEN_FREE_OBJECT(emgr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint8_t AQH_MsgEndpointMgr_GetBusAddr(const AQH_MSG_ENDPOINT_MGR *emgr)
|
||||
{
|
||||
return emgr->busAddr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
AQH_MSG_ENDPOINT_LIST *AQH_MsgEndpointMgr_GetEndpointList(const AQH_MSG_ENDPOINT_MGR *emgr)
|
||||
{
|
||||
return emgr->endpointList;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_MsgEndpointMgr_AddEndpoint(AQH_MSG_ENDPOINT_MGR *emgr, AQH_MSG_ENDPOINT *ep)
|
||||
{
|
||||
AQH_MsgEndpoint_List_Add(ep, emgr->endpointList);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_MsgEndpointMgr_DelEndpoint(AQH_MSG_ENDPOINT_MGR *emgr, AQH_MSG_ENDPOINT *ep)
|
||||
{
|
||||
AQH_MsgEndpoint_List_Del(ep);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_MsgEndpointMgr_LoopOnce(AQH_MSG_ENDPOINT_MGR *emgr)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv=_ioLoopOnce(emgr);
|
||||
_msgLoopOnce(emgr);
|
||||
_runAllEndpoints(emgr);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _ioLoopOnce(AQH_MSG_ENDPOINT_MGR *emgr)
|
||||
{
|
||||
AQH_MSG_ENDPOINT *ep;
|
||||
fd_set readSet;
|
||||
fd_set writeSet;
|
||||
int highestRdFd=-1;
|
||||
int highestWrFd=-1;
|
||||
struct timeval tv;
|
||||
int rv;
|
||||
|
||||
FD_ZERO(&readSet);
|
||||
FD_ZERO(&writeSet);
|
||||
tv.tv_sec=2;
|
||||
tv.tv_usec=0;
|
||||
|
||||
ep=AQH_MsgEndpoint_List_First(emgr->endpointList);
|
||||
while(ep) {
|
||||
if (!(AQH_MsgEndpoint_GetFlags(ep) & AQH_MSG_ENDPOINT_FLAGS_NOIO)) {
|
||||
int fd;
|
||||
|
||||
fd=AQH_MsgEndpoint_GetReadFd(ep);
|
||||
if (fd!=-1) {
|
||||
FD_SET(fd, &readSet);
|
||||
highestRdFd=(fd>highestRdFd)?fd:highestRdFd;
|
||||
}
|
||||
|
||||
fd=AQH_MsgEndpoint_GetWriteFd(ep);
|
||||
if (fd!=-1) {
|
||||
FD_SET(fd, &writeSet);
|
||||
highestWrFd=(fd>highestWrFd)?fd:highestWrFd;
|
||||
}
|
||||
}
|
||||
ep=AQH_MsgEndpoint_List_Next(ep);
|
||||
}
|
||||
|
||||
rv=select(((highestRdFd>highestWrFd)?highestRdFd:highestWrFd)+1,
|
||||
(highestRdFd<0)?NULL:&readSet,
|
||||
(highestWrFd<0)?NULL:&writeSet,
|
||||
NULL,
|
||||
&tv);
|
||||
if (rv<0) {
|
||||
if (errno!=EINTR) {
|
||||
DBG_ERROR(NULL, "Error on select");
|
||||
return GWEN_ERROR_IO;
|
||||
}
|
||||
}
|
||||
else if (rv==0) {
|
||||
/* timeout */
|
||||
return GWEN_ERROR_TRY_AGAIN;
|
||||
}
|
||||
else if (rv) {
|
||||
ep=AQH_MsgEndpoint_List_First(emgr->endpointList);
|
||||
while(ep) {
|
||||
AQH_MSG_ENDPOINT *epNext;
|
||||
int fd;
|
||||
int rv;
|
||||
|
||||
epNext=AQH_MsgEndpoint_List_Next(ep);
|
||||
fd=AQH_MsgEndpoint_GetFd(ep);
|
||||
if (fd!=-1 && FD_ISSET(fd, &readSet)) {
|
||||
rv=AQH_MsgEndpoint_HandleReadable(ep, emgr);
|
||||
if (rv<0 && rv!=GWEN_ERROR_TRY_AGAIN) {
|
||||
fd=-1;
|
||||
AQH_MsgEndpointMgr_DelEndpoint(emgr, ep);
|
||||
}
|
||||
}
|
||||
if (fd!=-1 && FD_ISSET(fd, &writeSet)) {
|
||||
rv=AQH_MsgEndpoint_HandleWritable(ep, emgr);
|
||||
if (rv<0 && rv!=GWEN_ERROR_TRY_AGAIN) {
|
||||
fd=-1;
|
||||
AQH_MsgEndpointMgr_DelEndpoint(emgr, ep);
|
||||
}
|
||||
}
|
||||
ep=epNext;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _msgLoopOnce(AQH_MSG_ENDPOINT_MGR *emgr)
|
||||
{
|
||||
AQH_MSG_ENDPOINT *ep;
|
||||
|
||||
ep=AQH_MsgEndpoint_List_First(emgr->endpointList);
|
||||
while(ep) {
|
||||
AQH_MSG *msg;
|
||||
|
||||
while( (msg=AQH_MsgEndpoint_TakeFirstReceivedMessage(ep)) ) {
|
||||
uint32_t msgGroup;
|
||||
|
||||
msgGroup=_getMsgGroup(AQH_Msg_GetMsgType(msg));
|
||||
if (msgGroup & AQH_MSG_ENDPOINT_MSGGROUP_ADMIN) {
|
||||
if (!(AQH_MsgEndpoint_GetGroupId(ep) & AQH_MSG_ENDPOINT_ENDPOINTGROUP_BUS))
|
||||
/* only handle admin messages not from nodes */
|
||||
_handleAdminMsg(emgr, ep, msg);
|
||||
}
|
||||
else
|
||||
_distributeMsg(emgr, ep, msg);
|
||||
AQH_Msg_free(msg);
|
||||
}
|
||||
|
||||
ep=AQH_MsgEndpoint_List_Next(ep);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _runAllEndpoints(AQH_MSG_ENDPOINT_MGR *emgr)
|
||||
{
|
||||
AQH_MSG_ENDPOINT *ep;
|
||||
|
||||
ep=AQH_MsgEndpoint_List_First(emgr->endpointList);
|
||||
while(ep) {
|
||||
AQH_MSG_ENDPOINT *next;
|
||||
|
||||
next=AQH_MsgEndpoint_List_Next(ep);
|
||||
AQH_MsgEndpoint_Run(ep);
|
||||
ep=next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _distributeMsg(AQH_MSG_ENDPOINT_MGR *emgr, AQH_MSG_ENDPOINT *srcEp, const AQH_MSG *msg)
|
||||
{
|
||||
AQH_MSG_ENDPOINT *ep;
|
||||
int srcGroupId;
|
||||
uint32_t msgGroup;
|
||||
|
||||
msgGroup=_getMsgGroup(AQH_Msg_GetMsgType(msg));
|
||||
srcGroupId=AQH_MsgEndpoint_GetGroupId(srcEp);
|
||||
|
||||
ep=AQH_MsgEndpoint_List_First(emgr->endpointList);
|
||||
while(ep) {
|
||||
uint32_t acceptedGroupIds;
|
||||
uint32_t acceptedMsgGroups;
|
||||
|
||||
acceptedGroupIds=AQH_MsgEndpoint_GetAcceptedMsgGroups(ep);
|
||||
acceptedMsgGroups=AQH_MsgEndpoint_GetAcceptedMsgGroups(ep);
|
||||
|
||||
if (
|
||||
!(AQH_MsgEndpoint_GetFlags(ep) & AQH_MSG_ENDPOINT_FLAGS_NOMESSAGES) &&
|
||||
(acceptedMsgGroups & msgGroup) &&
|
||||
(acceptedGroupIds & srcGroupId)
|
||||
) {
|
||||
/* endpoint accepts this message */
|
||||
AQH_MsgEndpoint_AddSendMessage(ep, AQH_Msg_dup(msg));
|
||||
}
|
||||
ep=AQH_MsgEndpoint_List_Next(ep);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleAdminMsg(AQH_MSG_ENDPOINT_MGR *emgr, AQH_MSG_ENDPOINT *ep, const AQH_MSG *msg)
|
||||
{
|
||||
uint8_t mt;
|
||||
|
||||
mt=AQH_Msg_GetMsgType(msg);
|
||||
switch(mt) {
|
||||
case AQH_MSG_TYPE_NET_SET_ACCEPTED_MSGGROUPS:
|
||||
_handleMsgSetAcceptedMsgGroups(emgr, ep, msg);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _handleMsgSetAcceptedMsgGroups(AQH_MSG_ENDPOINT_MGR *emgr, AQH_MSG_ENDPOINT *ep, const AQH_MSG *msg)
|
||||
{
|
||||
AQH_MsgEndpoint_SetAcceptedMsgGroups(ep, AQH_MsgSetAcceptedMsgGroups_GetMsgGroups(msg));
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint32_t _getMsgGroup(uint8_t msgType)
|
||||
{
|
||||
switch(msgType) {
|
||||
case AQH_MSG_TYPE_PING:
|
||||
case AQH_MSG_TYPE_PONG:
|
||||
case AQH_MSG_TYPE_COMSENDSTATS:
|
||||
case AQH_MSG_TYPE_COMRECVSTATS:
|
||||
case AQH_MSG_TYPE_TWIBUSMEMBER:
|
||||
case AQH_MSG_TYPE_DEBUG:
|
||||
return AQH_MSG_ENDPOINT_MSGGROUP_INFO;
|
||||
case AQH_MSG_TYPE_VALUE:
|
||||
return AQH_MSG_ENDPOINT_MSGGROUP_VALUES;
|
||||
case AQH_MSG_TYPE_NEED_ADDRESS:
|
||||
case AQH_MSG_TYPE_HAVE_ADDRESS:
|
||||
case AQH_MSG_TYPE_CLAIM_ADDRESS:
|
||||
case AQH_MSG_TYPE_DENY_ADDRESS:
|
||||
case AQH_MSG_TYPE_ADDRESS_RANGE:
|
||||
return AQH_MSG_ENDPOINT_MSGGROUP_ADDRESS;
|
||||
case AQH_MSG_TYPE_NET_SET_ACCEPTED_MSGGROUPS:
|
||||
return AQH_MSG_ENDPOINT_MSGGROUP_ADMIN;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
41
aqhome/msgendpointmanager.h
Normal file
41
aqhome/msgendpointmanager.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/****************************************************************************
|
||||
* 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.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQH_MSGENDPOINT_MGR_H
|
||||
#define AQH_MSGENDPOINT_MGR_H
|
||||
|
||||
|
||||
typedef struct AQH_MSG_ENDPOINT_MGR AQH_MSG_ENDPOINT_MGR;
|
||||
|
||||
|
||||
#include <aqhome/api.h>
|
||||
|
||||
#include "aqhome/msg.h"
|
||||
#include "aqhome/msgendpoint.h"
|
||||
|
||||
#include <gwenhywfar/list.h>
|
||||
|
||||
|
||||
|
||||
AQHOME_API AQH_MSG_ENDPOINT_MGR *AQH_MsgEndpointMgr_new(uint8_t busAddr);
|
||||
AQHOME_API void AQH_MsgEndpointMgr_free(AQH_MSG_ENDPOINT_MGR *emgr);
|
||||
|
||||
AQHOME_API uint8_t AQH_MsgEndpointMgr_GetBusAddr(const AQH_MSG_ENDPOINT_MGR *emgr);
|
||||
|
||||
AQHOME_API AQH_MSG_ENDPOINT_LIST *AQH_MsgEndpointMgr_GetEndpointList(const AQH_MSG_ENDPOINT_MGR *emgr);
|
||||
|
||||
AQHOME_API void AQH_MsgEndpointMgr_AddEndpoint(AQH_MSG_ENDPOINT_MGR *emgr, AQH_MSG_ENDPOINT *ep);
|
||||
AQHOME_API void AQH_MsgEndpointMgr_DelEndpoint(AQH_MSG_ENDPOINT_MGR *emgr, AQH_MSG_ENDPOINT *ep);
|
||||
|
||||
AQHOME_API int AQH_MsgEndpointMgr_LoopOnce(AQH_MSG_ENDPOINT_MGR *emgr);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
27
aqhome/msgendpointmanager_p.h
Normal file
27
aqhome/msgendpointmanager_p.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/****************************************************************************
|
||||
* 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.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQH_MSGENDPOINT_MGR_P_H
|
||||
#define AQH_MSGENDPOINT_MGR_P_H
|
||||
|
||||
|
||||
#include "aqhome/msgendpointmanager.h"
|
||||
|
||||
|
||||
|
||||
|
||||
struct AQH_MSG_ENDPOINT_MGR {
|
||||
uint8_t busAddr;
|
||||
AQH_MSG_ENDPOINT_LIST *endpointList;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
222
aqhome/msgendpointtcp.c
Normal file
222
aqhome/msgendpointtcp.c
Normal file
@@ -0,0 +1,222 @@
|
||||
/****************************************************************************
|
||||
* 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/msgendpointtcp.h"
|
||||
|
||||
#include <gwenhywfar/list.h>
|
||||
#include <gwenhywfar/inherit.h>
|
||||
#include <gwenhywfar/debug.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
|
||||
#define AQH_MSG_ENDPOINTTCP_BACKLOG 10
|
||||
|
||||
|
||||
|
||||
static int _setupListeningSocket(const char *host, int port);
|
||||
static int _setSocketNonBlocking(int fd);
|
||||
static int _getReadFd(AQH_MSG_ENDPOINT *ep);
|
||||
static int _getWriteFd(AQH_MSG_ENDPOINT *ep);
|
||||
static int _handleReadable(AQH_MSG_ENDPOINT *ep, AQH_MSG_ENDPOINT_MGR *emgr);
|
||||
static int _handleWritable(AQH_MSG_ENDPOINT *ep, AQH_MSG_ENDPOINT_MGR *emgr);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
AQH_MSG_ENDPOINT *AQH_MsgEndpointTcp_new(const char *host, int port)
|
||||
{
|
||||
int fd;
|
||||
AQH_MSG_ENDPOINT *ep;
|
||||
|
||||
fd=_setupListeningSocket(host, port);
|
||||
if (fd<0) {
|
||||
DBG_INFO(NULL, "here");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ep=AQH_MsgEndpoint_new(fd, AQH_MSG_ENDPOINT_ENDPOINTGROUP_NET);
|
||||
AQH_MsgEndpoint_SetAcceptedEndpointGroups(ep, AQH_MSG_ENDPOINT_ENDPOINTGROUP_BUS);
|
||||
AQH_MsgEndpoint_AddFlags(ep, AQH_MSG_ENDPOINT_FLAGS_NOMESSAGES);
|
||||
|
||||
AQH_MsgEndpoint_SetHandleReadableFn(ep, _handleReadable);
|
||||
AQH_MsgEndpoint_SetHandleWritableFn(ep, _handleWritable);
|
||||
AQH_MsgEndpoint_SetGetReadFdFn(ep, _getReadFd);
|
||||
AQH_MsgEndpoint_SetGetWriteFdFn(ep, _getWriteFd);
|
||||
|
||||
return ep;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _setupListeningSocket(const char *host, int port)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
int rv;
|
||||
int sk;
|
||||
int i;
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_port=htons(port);
|
||||
addr.sin_family=AF_INET;
|
||||
|
||||
if (inet_aton(host, &(addr.sin_addr))==0) {
|
||||
/* bad address */
|
||||
}
|
||||
|
||||
sk=socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sk<0) {
|
||||
/* socket error */
|
||||
DBG_ERROR(NULL, "socket(): %s", strerror(errno));
|
||||
}
|
||||
|
||||
i=1;
|
||||
rv=setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "setsockopt(): %s", strerror(errno));
|
||||
close(sk);
|
||||
return GWEN_ERROR_IO;
|
||||
}
|
||||
|
||||
rv=_setSocketNonBlocking(sk);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
close(sk);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
rv=bind(sk, (struct sockaddr*) &addr, sizeof(addr));
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "bind(): %s", strerror(errno));
|
||||
close(sk);
|
||||
return GWEN_ERROR_IO;
|
||||
}
|
||||
|
||||
rv=listen(sk, AQH_MSG_ENDPOINTTCP_BACKLOG);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "listen(): %s", strerror(errno));
|
||||
close(sk);
|
||||
return GWEN_ERROR_IO;
|
||||
}
|
||||
|
||||
return sk;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _setSocketNonBlocking(int fd)
|
||||
{
|
||||
int prevFlags;
|
||||
int newFlags;
|
||||
|
||||
/* get current socket flags */
|
||||
prevFlags=fcntl(fd, F_GETFL);
|
||||
if (prevFlags==-1) {
|
||||
DBG_ERROR(NULL, "fcntl(): %s", strerror(errno));
|
||||
return GWEN_ERROR_IO;
|
||||
}
|
||||
|
||||
/* set nonblocking/blocking */
|
||||
newFlags=prevFlags|O_NONBLOCK;
|
||||
|
||||
if (-1==fcntl(fd, F_SETFL, newFlags)) {
|
||||
DBG_ERROR(NULL, "fcntl(): %s", strerror(errno));
|
||||
return GWEN_ERROR_IO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int _getReadFd(AQH_MSG_ENDPOINT *ep)
|
||||
{
|
||||
return AQH_MsgEndpoint_GetFd(ep);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _getWriteFd(AQH_MSG_ENDPOINT *ep)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _handleReadable(AQH_MSG_ENDPOINT *ep, AQH_MSG_ENDPOINT_MGR *emgr)
|
||||
{
|
||||
int fd;
|
||||
int newSock;
|
||||
int rv;
|
||||
struct sockaddr_in clientAddr;
|
||||
socklen_t len;
|
||||
AQH_MSG_ENDPOINT *newEp;
|
||||
|
||||
fd=AQH_MsgEndpoint_GetFd(ep);
|
||||
memset(&clientAddr, 0, sizeof(clientAddr));
|
||||
do {
|
||||
len=sizeof(clientAddr);
|
||||
rv=accept(fd, (struct sockaddr*) &clientAddr, &len);
|
||||
} while(rv<0 && errno==EINTR);
|
||||
if (rv<0) {
|
||||
if (errno==EAGAIN || errno==EWOULDBLOCK)
|
||||
return GWEN_ERROR_TRY_AGAIN;
|
||||
DBG_ERROR(NULL, "Error on accept(): %s (%d)", strerror(errno), errno);
|
||||
return GWEN_ERROR_IO;
|
||||
}
|
||||
newSock=rv;
|
||||
|
||||
rv=_setSocketNonBlocking(newSock);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
close(newSock);
|
||||
return rv;
|
||||
}
|
||||
|
||||
newEp=AQH_MsgEndpoint_new(newSock, AQH_MsgEndpoint_GetGroupId(ep));
|
||||
AQH_MsgEndpoint_SetFlags(newEp, AQH_MsgEndpoint_GetFlags(ep));
|
||||
AQH_MsgEndpoint_SubFlags(newEp, AQH_MSG_ENDPOINT_FLAGS_NOMESSAGES);
|
||||
AQH_MsgEndpoint_SetAcceptedMsgGroups(newEp, AQH_MsgEndpoint_GetAcceptedMsgGroups(ep));
|
||||
AQH_MsgEndpoint_SetAcceptedEndpointGroups(newEp, AQH_MsgEndpoint_GetAcceptedEndpointGroups(ep));
|
||||
|
||||
AQH_MsgEndpointMgr_AddEndpoint(emgr, newEp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _handleWritable(AQH_MSG_ENDPOINT *ep, AQH_MSG_ENDPOINT_MGR *emgr)
|
||||
{
|
||||
/* should not get called */
|
||||
return GWEN_ERROR_INVALID;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
27
aqhome/msgendpointtcp.h
Normal file
27
aqhome/msgendpointtcp.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/****************************************************************************
|
||||
* 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.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQH_MSGENDPOINT_TCP_H
|
||||
#define AQH_MSGENDPOINT_TCP_H
|
||||
|
||||
|
||||
#include <aqhome/api.h>
|
||||
|
||||
#include "aqhome/msgendpoint.h"
|
||||
|
||||
#include <gwenhywfar/list.h>
|
||||
#include <gwenhywfar/inherit.h>
|
||||
|
||||
|
||||
AQHOME_API AQH_MSG_ENDPOINT *AQH_MsgEndpointTcp_new(const char *host, int port);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
270
aqhome/msgendpointtty.c
Normal file
270
aqhome/msgendpointtty.c
Normal file
@@ -0,0 +1,270 @@
|
||||
/****************************************************************************
|
||||
* 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/msgendpointtty_p.h"
|
||||
|
||||
#include <gwenhywfar/list.h>
|
||||
#include <gwenhywfar/inherit.h>
|
||||
#include <gwenhywfar/debug.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
#include <errno.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
#define AQH_MSG_ENDPOINT_TTY_BAUDRATE B19200
|
||||
#define AQH_MSG_ENDPOINT_TTY_BYTE_MICROSECS 520
|
||||
|
||||
|
||||
|
||||
GWEN_INHERIT(AQH_MSG_ENDPOINT, AQH_MSG_ENDPOINT_TTY)
|
||||
|
||||
|
||||
static void GWENHYWFAR_CB _freeData(void *bp, void *p);
|
||||
|
||||
static int _startMsg(AQH_MSG_ENDPOINT *ep);
|
||||
static int _endMsg(AQH_MSG_ENDPOINT *ep);
|
||||
static int _checkMsg(AQH_MSG_ENDPOINT *ep);
|
||||
|
||||
static int _setupDevice(AQH_MSG_ENDPOINT *ep);
|
||||
static int _attnLow(AQH_MSG_ENDPOINT *ep);
|
||||
static int _attnHigh(AQH_MSG_ENDPOINT *ep);
|
||||
static int _isAttnLow(AQH_MSG_ENDPOINT *ep);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
AQH_MSG_ENDPOINT *AQH_MsgEndpointTty_new(const char *deviceName)
|
||||
{
|
||||
AQH_MSG_ENDPOINT *ep;
|
||||
AQH_MSG_ENDPOINT_TTY *xep;
|
||||
int fd;
|
||||
int rv;
|
||||
|
||||
fd=open(deviceName, O_NOCTTY | O_NDELAY | O_RDWR);
|
||||
if (fd<0) {
|
||||
DBG_ERROR(NULL, "Error on open(%s): %s (%d)", deviceName, strerror(errno), errno);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ep=AQH_MsgEndpoint_new(fd, AQH_MSG_ENDPOINT_ENDPOINTGROUP_BUS);
|
||||
AQH_MsgEndpoint_SetAcceptedEndpointGroups(ep, AQH_MSG_ENDPOINT_ENDPOINTGROUP_NET);
|
||||
|
||||
GWEN_NEW_OBJECT(AQH_MSG_ENDPOINT_TTY, xep);
|
||||
GWEN_INHERIT_SETDATA(AQH_MSG_ENDPOINT, AQH_MSG_ENDPOINT_TTY, ep, xep, _freeData);
|
||||
xep->deviceName=strdup(deviceName);
|
||||
_attnHigh(ep);
|
||||
|
||||
AQH_MsgEndpoint_SetStartMsgFn(ep, _startMsg);
|
||||
AQH_MsgEndpoint_SetEndMsgFn(ep, _endMsg);
|
||||
AQH_MsgEndpoint_SetCheckMsgFn(ep, _checkMsg);
|
||||
|
||||
rv=_setupDevice(ep);
|
||||
if (rv<0) {
|
||||
DBG_INFO(NULL, "here (%d)", rv);
|
||||
AQH_MsgEndpoint_free(ep);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ep;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _freeData(void *bp, void *p)
|
||||
{
|
||||
AQH_MSG_ENDPOINT *ep;
|
||||
AQH_MSG_ENDPOINT_TTY *xep;
|
||||
int fd;
|
||||
|
||||
ep=(AQH_MSG_ENDPOINT*) bp;
|
||||
xep=(AQH_MSG_ENDPOINT_TTY*) p;
|
||||
fd=AQH_MsgEndpoint_GetFd(ep);
|
||||
if (fd>=0)
|
||||
tcsetattr(fd, TCSANOW, &xep->previousOptions);
|
||||
free(xep->deviceName);
|
||||
GWEN_FREE_OBJECT(xep);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _startMsg(AQH_MSG_ENDPOINT *ep)
|
||||
{
|
||||
AQH_MSG_ENDPOINT_TTY *xep;
|
||||
|
||||
xep=GWEN_INHERIT_GETDATA(AQH_MSG_ENDPOINT, AQH_MSG_ENDPOINT_TTY, ep);
|
||||
if (xep->intendedAttnState==1) {
|
||||
int rv;
|
||||
|
||||
rv=_attnLow(ep);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "here (%d)", rv);
|
||||
return rv;
|
||||
}
|
||||
usleep(AQH_MSG_ENDPOINT_TTY_BYTE_MICROSECS/5);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _endMsg(AQH_MSG_ENDPOINT *ep)
|
||||
{
|
||||
_attnHigh(ep);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _checkMsg(AQH_MSG_ENDPOINT *ep)
|
||||
{
|
||||
return _isAttnLow(ep);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _setupDevice(AQH_MSG_ENDPOINT *ep)
|
||||
{
|
||||
AQH_MSG_ENDPOINT_TTY *xep;
|
||||
int fd;
|
||||
int status;
|
||||
int i;
|
||||
struct termios options;
|
||||
int rv;
|
||||
int m;
|
||||
|
||||
xep=GWEN_INHERIT_GETDATA(AQH_MSG_ENDPOINT, AQH_MSG_ENDPOINT_TTY, ep);
|
||||
fd=AQH_MsgEndpoint_GetFd(ep);
|
||||
rv=tcgetattr(fd, &(xep->previousOptions));
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error on tcgetattr(%s): %s (%d)", xep->deviceName, strerror(errno), errno);
|
||||
return GWEN_ERROR_IO;
|
||||
}
|
||||
memset(&options, 0, sizeof(options)); /* preset */
|
||||
|
||||
options.c_cflag=CLOCAL | CREAD | CS8;
|
||||
options.c_iflag=IGNPAR | IGNBRK;
|
||||
options.c_oflag=0;
|
||||
options.c_lflag=0;
|
||||
cfmakeraw(&options);
|
||||
options.c_cc[VTIME]=0; /* read timeout in deciseconds */
|
||||
options.c_cc[VMIN]=0; /* no minimum number of receive bytes */
|
||||
|
||||
rv=cfsetispeed(&options, AQH_MSG_ENDPOINT_TTY_BAUDRATE);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error on cfsetispeed(%s): %s (%d)", xep->deviceName, strerror(errno), errno);
|
||||
return GWEN_ERROR_IO;
|
||||
}
|
||||
rv=cfsetospeed(&options, AQH_MSG_ENDPOINT_TTY_BAUDRATE);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error on cfsetospeed(%s): %s (%d)", xep->deviceName, strerror(errno), errno);
|
||||
return GWEN_ERROR_IO;
|
||||
}
|
||||
|
||||
rv=tcflush(fd, TCIOFLUSH);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error on tcflush(%s): %s (%d)", xep->deviceName, strerror(errno), errno);
|
||||
return GWEN_ERROR_IO;
|
||||
}
|
||||
|
||||
rv=tcsetattr(fd, TCSANOW, &options);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error on tcsetattr(%s): %s (%d)", xep->deviceName, strerror(errno), errno);
|
||||
return GWEN_ERROR_IO;
|
||||
}
|
||||
|
||||
_attnHigh(ep);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _attnLow(AQH_MSG_ENDPOINT *ep)
|
||||
{
|
||||
AQH_MSG_ENDPOINT_TTY *xep;
|
||||
int status;
|
||||
int rv;
|
||||
int fd;
|
||||
|
||||
xep=GWEN_INHERIT_GETDATA(AQH_MSG_ENDPOINT, AQH_MSG_ENDPOINT_TTY, ep);
|
||||
fd=AQH_MsgEndpoint_GetFd(ep);
|
||||
rv=ioctl(fd, TIOCMGET, &status); /* GET the State of MODEM bits in Status */
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error on ioctl(%s): %s (%d)", xep->deviceName, strerror(errno), errno);
|
||||
return GWEN_ERROR_IO;
|
||||
}
|
||||
status |= TIOCM_DTR | TIOCM_RTS; /* clear the DTR pin (cave: signals inverted!) */
|
||||
rv=ioctl(fd, TIOCMSET, &status);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error on ioctl(%s): %s (%d)", xep->deviceName, strerror(errno), errno);
|
||||
return GWEN_ERROR_IO;
|
||||
}
|
||||
xep->intendedAttnState=0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _attnHigh(AQH_MSG_ENDPOINT *ep)
|
||||
{
|
||||
AQH_MSG_ENDPOINT_TTY *xep;
|
||||
int status;
|
||||
int rv;
|
||||
int fd;
|
||||
|
||||
xep=GWEN_INHERIT_GETDATA(AQH_MSG_ENDPOINT, AQH_MSG_ENDPOINT_TTY, ep);
|
||||
fd=AQH_MsgEndpoint_GetFd(ep);
|
||||
rv=ioctl(fd, TIOCMGET, &status);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error on ioctl(%s): %s (%d)", xep->deviceName, strerror(errno), errno);
|
||||
return GWEN_ERROR_IO;
|
||||
}
|
||||
status |= TIOCM_DTR; /* Set the DTR pin */
|
||||
status &= ~ (TIOCM_DTR | TIOCM_RTS); /* clear the DTR pin (cave: signals inverted!) */
|
||||
rv=ioctl(fd, TIOCMSET, &status);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error on ioctl(%s): %s (%d)", xep->deviceName, strerror(errno), errno);
|
||||
return GWEN_ERROR_IO;
|
||||
}
|
||||
|
||||
xep->intendedAttnState=1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _isAttnLow(AQH_MSG_ENDPOINT *ep)
|
||||
{
|
||||
AQH_MSG_ENDPOINT_TTY *xep;
|
||||
int status;
|
||||
int rv;
|
||||
int fd;
|
||||
|
||||
xep=GWEN_INHERIT_GETDATA(AQH_MSG_ENDPOINT, AQH_MSG_ENDPOINT_TTY, ep);
|
||||
fd=AQH_MsgEndpoint_GetFd(ep);
|
||||
rv=ioctl(fd, TIOCMGET, &status);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(NULL, "Error on ioctl(%s): %s (%d)", xep->deviceName, strerror(errno), errno);
|
||||
return GWEN_ERROR_IO;
|
||||
}
|
||||
//return (status & TIOCM_CTS)?1:0;
|
||||
return (status & TIOCM_CTS)?1:0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
27
aqhome/msgendpointtty.h
Normal file
27
aqhome/msgendpointtty.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/****************************************************************************
|
||||
* 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.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQH_MSGENDPOINT_TTY_H
|
||||
#define AQH_MSGENDPOINT_TTY_H
|
||||
|
||||
|
||||
#include <aqhome/api.h>
|
||||
|
||||
#include "aqhome/msgendpoint.h"
|
||||
|
||||
#include <gwenhywfar/list.h>
|
||||
#include <gwenhywfar/inherit.h>
|
||||
|
||||
|
||||
AQHOME_API AQH_MSG_ENDPOINT *AQH_MsgEndpointTty_new(const char *devName);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
30
aqhome/msgendpointtty_p.h
Normal file
30
aqhome/msgendpointtty_p.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/****************************************************************************
|
||||
* 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.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef AQH_MSGENDPOINT_TTY_P_H
|
||||
#define AQH_MSGENDPOINT_TTY_P_H
|
||||
|
||||
|
||||
#include "aqhome/msgendpointtty.h"
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
|
||||
|
||||
typedef struct AQH_MSG_ENDPOINT_TTY AQH_MSG_ENDPOINT_TTY;
|
||||
struct AQH_MSG_ENDPOINT_TTY {
|
||||
char *deviceName;
|
||||
struct termios previousOptions;
|
||||
int intendedAttnState;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user