333 lines
6.8 KiB
C
333 lines
6.8 KiB
C
/****************************************************************************
|
|
* This file is part of the project AqHome.
|
|
* AqHome (c) by 2025 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 "./message_p.h"
|
|
|
|
#include <gwenhywfar/misc.h>
|
|
#include <gwenhywfar/debug.h>
|
|
#include <gwenhywfar/endianfns.h>
|
|
|
|
|
|
|
|
GWEN_LIST_FUNCTIONS(AQH_MESSAGE, AQH_Message)
|
|
GWEN_INHERIT_FUNCTIONS(AQH_MESSAGE)
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------
|
|
* forward declarations
|
|
* ------------------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
static void _ensureSize(AQH_MESSAGE *msg, uint32_t neededSize);
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------
|
|
* implementations
|
|
* ------------------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
AQH_MESSAGE *AQH_Message_new(void)
|
|
{
|
|
AQH_MESSAGE *msg;
|
|
|
|
GWEN_NEW_OBJECT(AQH_MESSAGE, msg);
|
|
GWEN_INHERIT_INIT(AQH_MESSAGE, msg);
|
|
GWEN_LIST_INIT(AQH_MESSAGE, msg);
|
|
msg->refCount=1;
|
|
|
|
return msg;
|
|
}
|
|
|
|
|
|
|
|
AQH_MESSAGE *AQH_Message_dup(const AQH_MESSAGE *origMsg)
|
|
{
|
|
if (origMsg) {
|
|
AQH_MESSAGE *msg;
|
|
|
|
msg=AQH_Message_new();
|
|
if (origMsg->msgPointer && origMsg->msgSize) {
|
|
AQH_Message_SetData(msg, origMsg->msgPointer, origMsg->msgSize);
|
|
msg->usedSize=origMsg->usedSize;
|
|
}
|
|
return msg;
|
|
}
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
void AQH_Message_IncRef(AQH_MESSAGE *msg)
|
|
{
|
|
if (msg && msg->refCount)
|
|
msg->refCount++;
|
|
}
|
|
|
|
|
|
|
|
void AQH_Message_free(AQH_MESSAGE *msg)
|
|
{
|
|
if (msg && msg->refCount>0) {
|
|
if (msg->refCount==1) {
|
|
msg->refCount=0;
|
|
GWEN_LIST_FINI(AQH_MESSAGE, msg);
|
|
GWEN_INHERIT_FINI(AQH_MESSAGE, msg);
|
|
free(msg->msgPointer);
|
|
GWEN_FREE_OBJECT(msg);
|
|
}
|
|
else
|
|
msg->refCount--;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
AQH_OBJECT *AQH_Message_GetObject(const AQH_MESSAGE *msg)
|
|
{
|
|
return (msg && msg->refCount)?msg->object:NULL;
|
|
}
|
|
|
|
|
|
|
|
void AQH_Message_SetObject(AQH_MESSAGE *msg, AQH_OBJECT *o)
|
|
{
|
|
if (msg && msg->refCount)
|
|
msg->object=o;
|
|
}
|
|
|
|
|
|
|
|
uint8_t *AQH_Message_GetMsgPointer(const AQH_MESSAGE *msg)
|
|
{
|
|
return (msg && msg->refCount)?msg->msgPointer:NULL;
|
|
}
|
|
|
|
|
|
|
|
uint32_t AQH_Message_GetMsgSize(const AQH_MESSAGE *msg)
|
|
{
|
|
return (msg && msg->refCount)?msg->msgSize:0;
|
|
}
|
|
|
|
|
|
|
|
void AQH_Message_SetData(AQH_MESSAGE *msg, const uint8_t *msgPtr, uint32_t msgSize)
|
|
{
|
|
if (msg && msg->refCount) {
|
|
free(msg->msgPointer);
|
|
msg->msgPointer=NULL;
|
|
msg->msgSize=0;
|
|
if (msgSize) {
|
|
msg->msgPointer=(uint8_t*) malloc(msgSize);
|
|
if (msg->msgPointer) {
|
|
if (msgPtr)
|
|
memmove(msg->msgPointer, msgPtr, msgSize);
|
|
else
|
|
memset(msg->msgPointer, 0, msgSize);
|
|
msg->msgSize=msgSize;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
uint32_t AQH_Message_GetUsedSize(const AQH_MESSAGE *msg)
|
|
{
|
|
return msg?msg->usedSize:0;
|
|
}
|
|
|
|
|
|
|
|
void AQH_Message_SetUsedSize(AQH_MESSAGE *msg, uint32_t i)
|
|
{
|
|
if (msg) {
|
|
_ensureSize(msg, i);
|
|
msg->usedSize=i;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void AQH_Message_IncUsedSize(AQH_MESSAGE *msg, uint32_t i)
|
|
{
|
|
if (msg) {
|
|
_ensureSize(msg, msg->usedSize+i);
|
|
msg->usedSize+=i;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void AQH_Message_WriteUint8At(AQH_MESSAGE *msg, uint32_t pos, uint8_t d)
|
|
{
|
|
if (msg) {
|
|
_ensureSize(msg, pos+1);
|
|
msg->msgPointer[pos]=d;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
uint8_t AQH_Message_ReadUint8At(const AQH_MESSAGE *msg, uint32_t pos, uint8_t defaultValue)
|
|
{
|
|
if (msg && msg->msgPointer && msg->msgSize>=pos+1)
|
|
return msg->msgPointer[pos];
|
|
return defaultValue;
|
|
}
|
|
|
|
|
|
|
|
void AQH_Message_WriteUint16At(AQH_MESSAGE *msg, uint32_t pos, uint16_t d)
|
|
{
|
|
if (msg) {
|
|
_ensureSize(msg, pos+2);
|
|
*( (uint16_t*) (msg->msgPointer+pos) )=GWEN_ENDIAN_HTOLE16(d);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
uint16_t AQH_Message_ReadUint16At(const AQH_MESSAGE *msg, uint32_t pos, uint16_t defaultValue)
|
|
{
|
|
if (msg && msg->msgPointer && msg->msgSize>=pos+2)
|
|
return GWEN_ENDIAN_LE16TOH(*( (uint16_t*) (msg->msgPointer+pos) ));
|
|
return defaultValue;
|
|
}
|
|
|
|
|
|
|
|
void AQH_Message_WriteUint32At(AQH_MESSAGE *msg, uint32_t pos, uint32_t d)
|
|
{
|
|
if (msg) {
|
|
_ensureSize(msg, pos+4);
|
|
*( (uint32_t*) (msg->msgPointer+pos) )=GWEN_ENDIAN_HTOLE32(d);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
uint32_t AQH_Message_ReadUint32At(const AQH_MESSAGE *msg, uint32_t pos, uint32_t defaultValue)
|
|
{
|
|
if (msg && msg->msgPointer && msg->msgSize>=pos+4)
|
|
return GWEN_ENDIAN_LE32TOH(*( (uint32_t*) (msg->msgPointer+pos) ));
|
|
return defaultValue;
|
|
}
|
|
|
|
|
|
|
|
void AQH_Message_WriteUint64At(AQH_MESSAGE *msg, uint32_t pos, uint64_t d)
|
|
{
|
|
if (msg) {
|
|
_ensureSize(msg, pos+8);
|
|
*( (uint64_t*) (msg->msgPointer+pos) )=GWEN_ENDIAN_HTOLE64(d);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
uint64_t AQH_Message_ReadUint64At(const AQH_MESSAGE *msg, uint32_t pos, uint64_t defaultValue)
|
|
{
|
|
if (msg && msg->msgPointer && msg->msgSize>=pos+8)
|
|
return GWEN_ENDIAN_LE64TOH(*( (uint64_t*) (msg->msgPointer+pos) ));
|
|
return defaultValue;
|
|
}
|
|
|
|
|
|
|
|
void AQH_Message_WriteBytesAt(AQH_MESSAGE *msg, uint32_t pos, const uint8_t *bufferPtr, uint32_t bufferLen)
|
|
{
|
|
if (msg && bufferPtr && bufferLen) {
|
|
_ensureSize(msg, pos+bufferLen);
|
|
memmove(msg->msgPointer+pos, bufferPtr, bufferLen);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
int AQH_Message_WriteStringAt(AQH_MESSAGE *msg, uint32_t pos, uint32_t maxSize, int filler, const char *s)
|
|
{
|
|
if (msg && maxSize) {
|
|
uint32_t slen=0;
|
|
|
|
if (s) {
|
|
slen=strlen(s);
|
|
if (slen>maxSize) {
|
|
DBG_ERROR(AQH_LOGDOMAIN, "String too long (%d > %d)", slen, maxSize);
|
|
return GWEN_ERROR_INVALID;
|
|
}
|
|
}
|
|
_ensureSize(msg, pos+maxSize);
|
|
if (s)
|
|
memmove(msg->msgPointer+pos, s, slen);
|
|
if (slen<maxSize)
|
|
memset(msg->msgPointer+pos+slen, filler, maxSize-slen);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int AQH_Message_WriteStringWithTrailingNullAt(AQH_MESSAGE *msg, uint32_t pos, uint32_t maxSize, int filler, const char *s)
|
|
{
|
|
if (msg && maxSize) {
|
|
uint32_t slen=1;
|
|
|
|
if (s) {
|
|
slen=strlen(s)+1;
|
|
if (slen>maxSize) {
|
|
DBG_ERROR(AQH_LOGDOMAIN, "String too long (%d > %d)", slen, maxSize);
|
|
return GWEN_ERROR_INVALID;
|
|
}
|
|
}
|
|
_ensureSize(msg, pos+maxSize);
|
|
if (s)
|
|
memmove(msg->msgPointer+pos, s, slen);
|
|
if (slen<maxSize)
|
|
memset(msg->msgPointer+pos+slen, filler, maxSize-slen);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
void _ensureSize(AQH_MESSAGE *msg, uint32_t neededSize)
|
|
{
|
|
if (msg && neededSize) {
|
|
if (msg->msgPointer==0 || msg->msgSize==0) {
|
|
msg->msgPointer=(uint8_t*) malloc(neededSize);
|
|
assert(msg->msgPointer);
|
|
}
|
|
else {
|
|
if (neededSize>msg->msgSize) {
|
|
uint8_t *ptr;
|
|
|
|
ptr=realloc(msg->msgPointer, neededSize);
|
|
assert(ptr);
|
|
if (ptr) {
|
|
msg->msgPointer=ptr;
|
|
msg->msgSize=neededSize;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|