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_haveaddr.h
|
||||||
msg_claimaddr.h
|
msg_claimaddr.h
|
||||||
msg_denyaddr.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>
|
</headers>
|
||||||
|
|
||||||
|
|
||||||
@@ -72,6 +82,12 @@
|
|||||||
msg_haveaddr.c
|
msg_haveaddr.c
|
||||||
msg_claimaddr.c
|
msg_claimaddr.c
|
||||||
msg_denyaddr.c
|
msg_denyaddr.c
|
||||||
|
msg_setaccmsggrps.c
|
||||||
|
msgendpoint.c
|
||||||
|
msgendpointtcp.c
|
||||||
|
msgendpointtty.c
|
||||||
|
msgendpointlog.c
|
||||||
|
msgendpointmanager.c
|
||||||
</sources>
|
</sources>
|
||||||
|
|
||||||
<useTargets>
|
<useTargets>
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ int testRecv()
|
|||||||
|
|
||||||
fprintf(stdout, "Opening device...\n");
|
fprintf(stdout, "Opening device...\n");
|
||||||
sr=AQH_Serial_new("/dev/ttyUSB0", 240);
|
sr=AQH_Serial_new("/dev/ttyUSB0", 240);
|
||||||
rv=AQH_Serial_Open(sr);
|
rv=AQH_Serial_Open(sr, AQH_SerialReadWriteMode_ReadOnly);
|
||||||
if (rv<0) {
|
if (rv<0) {
|
||||||
DBG_ERROR(NULL, "ERROR opening device (%d)", rv);
|
DBG_ERROR(NULL, "ERROR opening device (%d)", rv);
|
||||||
AQH_Serial_free(sr);
|
AQH_Serial_free(sr);
|
||||||
@@ -77,7 +77,7 @@ int testSend()
|
|||||||
|
|
||||||
fprintf(stdout, "Opening device...\n");
|
fprintf(stdout, "Opening device...\n");
|
||||||
sr=AQH_Serial_new("/dev/ttyUSB0", 240);
|
sr=AQH_Serial_new("/dev/ttyUSB0", 240);
|
||||||
rv=AQH_Serial_Open(sr);
|
rv=AQH_Serial_Open(sr, AQH_SerialReadWriteMode_ReadWrite);
|
||||||
if (rv<0) {
|
if (rv<0) {
|
||||||
DBG_ERROR(NULL, "ERROR opening device (%d)", rv);
|
DBG_ERROR(NULL, "ERROR opening device (%d)", rv);
|
||||||
AQH_Serial_free(sr);
|
AQH_Serial_free(sr);
|
||||||
@@ -268,7 +268,7 @@ int testLoop()
|
|||||||
|
|
||||||
fprintf(stdout, "Opening device...\n");
|
fprintf(stdout, "Opening device...\n");
|
||||||
sr=AQH_Serial_new("/dev/ttyUSB0", 240);
|
sr=AQH_Serial_new("/dev/ttyUSB0", 240);
|
||||||
rv=AQH_Serial_Open(sr);
|
rv=AQH_Serial_Open(sr, AQH_SerialReadWriteMode_ReadWrite);
|
||||||
if (rv<0) {
|
if (rv<0) {
|
||||||
DBG_ERROR(NULL, "ERROR opening device (%d)", rv);
|
DBG_ERROR(NULL, "ERROR opening device (%d)", rv);
|
||||||
AQH_Serial_free(sr);
|
AQH_Serial_free(sr);
|
||||||
@@ -335,10 +335,60 @@ int testLoop()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int testReadLoop()
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
{
|
||||||
|
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 testRecv();
|
||||||
//return testSend();
|
//return testSend();
|
||||||
return testLoop();
|
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)
|
uint8_t *AQH_Msg_GetBuffer(AQH_MSG *msg)
|
||||||
{
|
{
|
||||||
if (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)
|
uint8_t _calcChecksum(const uint8_t *ptr, uint8_t len)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#include <aqhome/api.h>
|
#include <aqhome/api.h>
|
||||||
|
|
||||||
#include <gwenhywfar/list.h>
|
#include <gwenhywfar/list.h>
|
||||||
|
#include <gwenhywfar/buffer.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -39,6 +40,9 @@
|
|||||||
#define AQH_MSG_TYPE_DENY_ADDRESS 63
|
#define AQH_MSG_TYPE_DENY_ADDRESS 63
|
||||||
#define AQH_MSG_TYPE_ADDRESS_RANGE 64
|
#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 AQH_MSG *AQH_Msg_new();
|
||||||
AQHOME_API void AQH_Msg_free(AQH_MSG *msg);
|
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 uint8_t *AQH_Msg_GetBuffer(AQH_MSG *msg);
|
||||||
AQHOME_API const uint8_t *AQH_Msg_GetConstBuffer(const 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_IsChecksumValid(const AQH_MSG *msg);
|
||||||
AQHOME_API int AQH_Msg_AddChecksum(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
|
#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