fixed memory leaks, added cleanup code, added valgrind scripts to test binaries

This commit is contained in:
Martin Preuss
2023-08-09 17:24:44 +02:00
parent 4701a71986
commit b5916acf79
41 changed files with 991 additions and 170 deletions

View File

@@ -48,7 +48,7 @@
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>with_getbymember</flags>
<flags>own with_getbymember</flags>
</member>
<member name="mqttDataType" type="int" maxlen="8">

View File

@@ -41,14 +41,14 @@
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>with_getbymember</flags>
<flags>own with_getbymember</flags>
</member>
<member name="description" type="char_ptr" maxlen="256">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags></flags>
<flags>own</flags>
</member>
<member name="colour" type="uint32_t" maxlen="8">

View File

@@ -204,6 +204,37 @@ AQH_VALUE *AQH_Storage_GetValueById(const AQH_STORAGE *sto, uint64_t id)
uint32_t AQH_Storage_GetRuntimeFlags(const AQH_STORAGE *sto)
{
return sto?sto->runtimeFlags:0;
}
void AQH_Storage_SetRuntimeFlags(AQH_STORAGE *sto, uint32_t flags)
{
if (sto)
sto->runtimeFlags=flags;
}
void AQH_Storage_AddRuntimeFlags(AQH_STORAGE *sto, uint32_t flags)
{
if (sto)
sto->runtimeFlags|=flags;
}
void AQH_Storage_SubRuntimeFlags(AQH_STORAGE *sto, uint32_t flags)
{
if (sto)
sto->runtimeFlags&=~flags;
}
void AQH_Storage_HandleMqttPublish(AQH_STORAGE *sto, const char *topic, const char *value)
{
/* TODO */
@@ -216,7 +247,10 @@ int AQH_Storage_Init(AQH_STORAGE *sto)
int rv;
rv=GWEN_Directory_GetPath(sto->stateFile,
GWEN_PATH_FLAGS_CHECKROOT | GWEN_PATH_FLAGS_PATHMUSTEXIST | GWEN_PATH_FLAGS_NAMEMUSTEXIST);
GWEN_PATH_FLAGS_CHECKROOT |
GWEN_PATH_FLAGS_PATHMUSTEXIST |
GWEN_PATH_FLAGS_NAMEMUSTEXIST |
GWEN_PATH_FLAGS_VARIABLE);
if (rv==0) {
rv=AQH_Storage_ReadStateFile(sto, sto->stateFile);
if (rv<0) {
@@ -225,7 +259,7 @@ int AQH_Storage_Init(AQH_STORAGE *sto)
}
}
else {
DBG_WARN(AQH_LOGDOMAIN, "State file \"%s\" not available, will try to create it later", sto->stateFile);
DBG_WARN(AQH_LOGDOMAIN, "State file \"%s\" not available, will try to create it later (%d)", sto->stateFile, rv);
}
return 0;
@@ -242,7 +276,7 @@ int AQH_Storage_WriteState(AQH_STORAGE *sto)
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
return rv;
}
sto->runtimeFlags&=~AQH_STORAGE_RTFLAGS_MODIFIED;
return 0;
}

View File

@@ -34,6 +34,9 @@ typedef struct AQH_STORAGE AQH_STORAGE;
#include "aqhome/data/datapoint.h"
#define AQH_STORAGE_RTFLAGS_MODIFIED 0x0001
#ifdef __cplusplus
extern "C" {
@@ -67,6 +70,11 @@ AQHOME_API AQH_VALUE *AQH_Storage_GetValueById(const AQH_STORAGE *sto, uint64_t
AQHOME_API const char *AQH_Storage_GetStateFile(const AQH_STORAGE *sto);
AQHOME_API void AQH_Storage_SetStateFile(AQH_STORAGE *sto, const char *s);
AQHOME_API uint32_t AQH_Storage_GetRuntimeFlags(const AQH_STORAGE *sto);
AQHOME_API void AQH_Storage_SetRuntimeFlags(AQH_STORAGE *sto, uint32_t flags);
AQHOME_API void AQH_Storage_AddRuntimeFlags(AQH_STORAGE *sto, uint32_t flags);
AQHOME_API void AQH_Storage_SubRuntimeFlags(AQH_STORAGE *sto, uint32_t flags);
AQHOME_API int AQH_Storage_Init(AQH_STORAGE *sto);
AQHOME_API int AQH_Storage_WriteState(AQH_STORAGE *sto);

View File

@@ -41,6 +41,8 @@ struct AQH_STORAGE {
uint64_t lastValueId;
char *stateFile;
uint32_t runtimeFlags;
};

View File

@@ -57,6 +57,8 @@ int AQH_Storage_ReadStateFile(AQH_STORAGE *sto, const char *sFilename)
_readTopicsFromXml(sto, rootNode);
_readValuesFromXml(sto, rootNode);
GWEN_XMLNode_free(rootNode);
return 0;
}

View File

@@ -125,7 +125,7 @@ void _writeDevicesToXml(const AQH_STORAGE *sto, GWEN_XMLNODE *rootNode)
nElems=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, AQH_STORAGE_XML_ELEMENTNAME_DEVICES);
elem=AQH_Device_List_First(sto->roomList);
elem=AQH_Device_List_First(sto->deviceList);
while(elem) {
GWEN_XMLNODE *nElem;

View File

@@ -55,14 +55,14 @@
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags></flags>
<flags>own</flags>
</member>
<member name="dataPath" type="char_ptr" maxlen="256">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags></flags>
<flags>own</flags>
</member>

View File

@@ -45,6 +45,9 @@ void AQH_HttpContent_free(AQH_HTTP_CONTENT *cp)
if (cp) {
GWEN_TREE2_FINI(AQH_HTTP_CONTENT, cp, AQH_HttpContent);
GWEN_INHERIT_FINI(AQH_HTTP_CONTENT, cp);
free(cp->name);
GWEN_FREE_OBJECT(cp);
}
}

View File

@@ -119,7 +119,7 @@ void _addSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSET
} /* if socket */
}
else if (xep->addSocketsFn) {
DBG_INFO(AQH_LOGDOMAIN, "Endpoint %s: Not connected, calling base function", GWEN_MsgEndpoint_GetName(ep));
DBG_DEBUG(AQH_LOGDOMAIN, "Endpoint %s: Not connected, calling base function", GWEN_MsgEndpoint_GetName(ep));
xep->addSocketsFn(ep, readSet, writeSet, xSet);
}
} /* if (xep) */
@@ -172,7 +172,7 @@ void _checkSockets(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKETSET *readSet, GWEN_SOCKETSE
}
} /* if connected */
else if (xep->checkSocketsFn) {
DBG_INFO(AQH_LOGDOMAIN, "Endpoint %s: Not connected, calling base function", GWEN_MsgEndpoint_GetName(ep));
DBG_DEBUG(AQH_LOGDOMAIN, "Endpoint %s: Not connected, calling base function", GWEN_MsgEndpoint_GetName(ep));
xep->checkSocketsFn(ep, readSet, writeSet, xSet);
}
}
@@ -208,7 +208,7 @@ int _writeCurrentMessage(GWEN_MSG_ENDPOINT *ep)
}
GWEN_Msg_IncCurrentPos(msg, rv);
if (rv==remaining) {
DBG_INFO(AQH_LOGDOMAIN, "Message completely sent");
DBG_DEBUG(AQH_LOGDOMAIN, "Message completely sent");
/* end current message */
GWEN_Msg_List_Del(msg);
GWEN_Msg_free(msg);
@@ -216,7 +216,7 @@ int _writeCurrentMessage(GWEN_MSG_ENDPOINT *ep)
}
}
else {
DBG_INFO(AQH_LOGDOMAIN, "Nothing to send");
DBG_DEBUG(AQH_LOGDOMAIN, "Nothing to send");
}
return 0;
}
@@ -309,7 +309,7 @@ int _distributeBufferInCommandMode(GWEN_MSG_ENDPOINT *ep, const uint8_t *bufferP
const char *s;
/* line complete */
DBG_INFO(AQH_LOGDOMAIN, "Command line complete");
DBG_DEBUG(AQH_LOGDOMAIN, "Command line complete");
rv=-rv;
xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, AQH_ENDPOINT_HTTP, ep);
@@ -319,21 +319,21 @@ int _distributeBufferInCommandMode(GWEN_MSG_ENDPOINT *ep, const uint8_t *bufferP
DBG_INFO(AQH_LOGDOMAIN, "Error parsing command line [%s]", GWEN_Buffer_GetStart(xep->currentReadBuffer));
return GWEN_ERROR_BAD_DATA;
}
DBG_ERROR(AQH_LOGDOMAIN, "Command line received: %s", GWEN_Buffer_GetStart(xep->currentReadBuffer));
DBG_DEBUG(AQH_LOGDOMAIN, "Command line received: %s", GWEN_Buffer_GetStart(xep->currentReadBuffer));
s=GWEN_DB_GetCharValue(xep->dbCurrentReadCommand, "protocol", 0, "HTTP/0.9");
if (s && *s && strcasecmp(s, "HTTP/0.9")==0) {
DBG_INFO(AQH_LOGDOMAIN, "HTTP 0.9, no header, message finished");
_finishMessageAndStartNext(ep);
return rv;
}
DBG_INFO(AQH_LOGDOMAIN,
DBG_DEBUG(AQH_LOGDOMAIN,
"Command line complete, advancing to header read mode (start: %d)",
GWEN_Buffer_GetPos(xep->currentReadBuffer));
xep->readMode=AQH_EndpointHttpd_ReadMode_Headers;
xep->currentHeaderPos=GWEN_Buffer_GetPos(xep->currentReadBuffer);
}
else {
DBG_INFO(AQH_LOGDOMAIN, "Line not yet finished (%d)", rv);
DBG_DEBUG(AQH_LOGDOMAIN, "Line not yet finished (%d)", rv);
}
return rv;
@@ -352,7 +352,7 @@ int _distributeBufferInStatusMode(GWEN_MSG_ENDPOINT *ep, const uint8_t *bufferPt
/* line complete, TODO: parse status/command line */
rv=-rv;
xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, AQH_ENDPOINT_HTTP, ep);
DBG_INFO(AQH_LOGDOMAIN, "Line complete, advancing to header read mode");
DBG_DEBUG(AQH_LOGDOMAIN, "Line complete, advancing to header read mode");
xep->readMode=AQH_EndpointHttpd_ReadMode_Headers;
xep->currentBodyPos=GWEN_Buffer_GetPos(xep->currentReadBuffer);
}
@@ -382,7 +382,7 @@ int _distributeBufferInHeaderMode(GWEN_MSG_ENDPOINT *ep, const uint8_t *bufferPt
int contentLength;
/* Empty line received, TODO: parse header */
DBG_INFO(AQH_LOGDOMAIN, "Empty header line received, end of header reached (header pos: %d).", xep->currentHeaderPos);
DBG_DEBUG(AQH_LOGDOMAIN, "Empty header line received, end of header reached (header pos: %d).", xep->currentHeaderPos);
copyOfHeader=strdup(GWEN_Buffer_GetStart(xep->currentReadBuffer)+xep->currentHeaderPos);
xep->dbCurrentReadHeader=GWEN_DB_Group_new("header");
if (_parseHeader(copyOfHeader, xep->dbCurrentReadHeader)<0) {
@@ -393,7 +393,7 @@ int _distributeBufferInHeaderMode(GWEN_MSG_ENDPOINT *ep, const uint8_t *bufferPt
free(copyOfHeader);
contentLength=GWEN_DB_GetIntValue(xep->dbCurrentReadHeader, "Content-Length", 0, -1);
if (contentLength==0 || contentLength==-1) {
DBG_INFO(AQH_LOGDOMAIN, "Message has no body, done");
DBG_DEBUG(AQH_LOGDOMAIN, "Message has no body, done");
_finishMessageAndStartNext(ep);
}
else {
@@ -425,7 +425,7 @@ int _distributeBufferInBodyMode(GWEN_MSG_ENDPOINT *ep, const uint8_t *bufferPtr,
GWEN_Buffer_AppendBytes(xep->currentReadBuffer, (const char*) bufferPtr, len);
xep->remainingBodySize-=len;
if (xep->remainingBodySize==0) {
DBG_INFO(AQH_LOGDOMAIN, "Body completely received");
DBG_DEBUG(AQH_LOGDOMAIN, "Body completely received");
_finishMessageAndStartNext(ep);
}
return len;
@@ -475,7 +475,7 @@ void _finishMessageAndStartNext(GWEN_MSG_ENDPOINT *ep)
GWEN_MSG *msg;
GWEN_DB_NODE *dbParsedData;
DBG_INFO(AQH_LOGDOMAIN, "Message completely received.");
DBG_DEBUG(AQH_LOGDOMAIN, "Message completely received.");
xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, AQH_ENDPOINT_HTTP, ep);
msg=GWEN_Msg_fromBytes((const uint8_t*)GWEN_Buffer_GetStart(xep->currentReadBuffer), GWEN_Buffer_GetUsedBytes(xep->currentReadBuffer));
@@ -502,11 +502,11 @@ void _finishMessageAndStartNext(GWEN_MSG_ENDPOINT *ep)
xep->dbCurrentReadHeader=NULL;
if (xep->flags & AQH_ENDPOINT_HTTP_FLAGS_PASSIVE) {
DBG_INFO(AQH_LOGDOMAIN, "Passive connection");
DBG_DEBUG(AQH_LOGDOMAIN, "Passive connection");
xep->readMode=AQH_EndpointHttpd_ReadMode_Command;
}
else {
DBG_INFO(AQH_LOGDOMAIN, "Active connection");
DBG_DEBUG(AQH_LOGDOMAIN, "Active connection");
xep->readMode=AQH_EndpointHttpd_ReadMode_Status;
}
}
@@ -517,7 +517,7 @@ void _abortMessage(GWEN_MSG_ENDPOINT *ep)
{
AQH_ENDPOINT_HTTP *xep;
DBG_INFO(AQH_LOGDOMAIN, "Message completely received.");
DBG_DEBUG(AQH_LOGDOMAIN, "Aborting message (if any).");
xep=GWEN_INHERIT_GETDATA(GWEN_MSG_ENDPOINT, AQH_ENDPOINT_HTTP, ep);
GWEN_Buffer_Reset(xep->currentReadBuffer);
@@ -587,7 +587,7 @@ int _parseHeader(char *bufferPtr, GWEN_DB_NODE *db)
while (*p && (*p==32 || *p==9))
p++;
if (*p) {
DBG_ERROR(AQH_LOGDOMAIN, "Setting header variable: [%s] = [%s]", pVarBegin, p);
DBG_DEBUG(AQH_LOGDOMAIN, "Setting header variable: [%s] = [%s]", pVarBegin, p);
GWEN_DB_SetCharValue(db, GWEN_PATH_FLAGS_CREATE_VAR, pVarBegin, p);
}
}

View File

@@ -18,6 +18,7 @@
#include <gwenhywfar/buffer.h>
#include <gwenhywfar/text.h>
#include <gwenhywfar/debug.h>
#include <gwenhywfar/directory.h>
#include <stdio.h>
#include <errno.h>
@@ -54,11 +55,15 @@ static GWEN_BUFFER *_getConfigFilePath(const AQH_SERVICE *sv, const char *fileNa
static GWEN_BUFFER *_getModuleFilePath(const AQH_SERVICE *sv, const char *modName);
static GWEN_BUFFER *_getUserFilePath(const AQH_SERVICE *sv, const char *userAlias);
static GWEN_BUFFER *_getSessionFilePath(const AQH_SERVICE *sv, const char *sessionUid);
static GWEN_BUFFER *_getSessionFolder(const AQH_SERVICE *sv);
static int _checkUser(const AQH_USER *user, int ignoreMissingId);
static int _checkSession(const AQH_SESSION *session);
static int _checkModule(const AQH_MODULE *m, int ignoreMissingId);
static int _checkRoleList(const AQH_ROLE_LIST *roleList, int ignoreMissingId);
static int _writeDbFile(const char *fname, GWEN_DB_NODE *db);
static GWEN_STRINGLIST *_getConfFileList(const char *folder, const char *mask);
static AQH_SESSION_LIST *_readAllSessionsIntoList(const AQH_SERVICE *sv);
static AQH_SESSION *_readSessionFromFile(const char *filename);
@@ -278,6 +283,141 @@ AQH_SESSION *AQH_HttpService_GetSession(AQH_SERVICE *sv, const char *sessionUid)
int AQH_HttpService_LockSessions(AQH_SERVICE *sv)
{
AQH_HTTP_SERVICE *xsv;
int rv;
xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_HTTP_SERVICE, sv);
if (xsv==NULL) {
DBG_ERROR(AQH_LOGDOMAIN, "Not a AQH_HttpService object");
return GWEN_ERROR_GENERIC;
}
rv=GWEN_Mutex_Lock(xsv->sessionMutex);
if (rv<0) {
DBG_ERROR(AQH_LOGDOMAIN, "Error obtaining lock on session mutex");
return rv;
}
return 0;
}
int AQH_HttpService_UnlockSessions(AQH_SERVICE *sv)
{
AQH_HTTP_SERVICE *xsv;
int rv;
xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_HTTP_SERVICE, sv);
if (xsv==NULL) {
DBG_ERROR(AQH_LOGDOMAIN, "Not a AQH_HttpService object");
return GWEN_ERROR_GENERIC;
}
rv=GWEN_Mutex_Unlock(xsv->sessionMutex);
if (rv<0) {
DBG_ERROR(AQH_LOGDOMAIN, "Error releasing lock on session mutex");
return rv;
}
return 0;
}
int AQH_HttpService_CleanupSessions(AQH_SERVICE *sv, int maxAgeInSecs)
{
time_t tNow;
AQH_SESSION_LIST *sessionList;
int rv;
rv=AQH_HttpService_LockSessions(sv);
if (rv<0) {
DBG_INFO(AQH_LOGDOMAIN, "Error locking sessions (%d)", rv);
return rv;
}
tNow=time(NULL);
sessionList=AQH_Service_GetSessionList(sv);
if (sessionList) {
AQH_SESSION *session;
session=AQH_Session_List_First(sessionList);
while(session) {
AQH_SESSION *next;
const GWEN_TIMESTAMP *ts;
next=AQH_Session_List_Next(session);
ts=AQH_Session_GetTimestampLastAccess(session);
if (ts==NULL)
ts=AQH_Session_GetTimestampCreation(session);
if (ts) {
time_t diff;
diff=tNow-GWEN_Timestamp_toTimeT(ts);
if (((int)diff)>maxAgeInSecs) {
DBG_INFO(AQH_LOGDOMAIN, "Session \"%s\" expired (%d secs)", AQH_Session_GetUid(session), (int) diff);
rv=AQH_HttpService_DelSession(sv, session); /* frees session!! */
if (rv<0) {
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
}
}
}
session=next;
}
}
rv=AQH_HttpService_UnlockSessions(sv);
if (rv<0) {
DBG_INFO(AQH_LOGDOMAIN, "Error unlocking sessions (%d)", rv);
return rv;
}
return 0;
}
void AQH_HttpService_LoadAllSessions(AQH_SERVICE *sv)
{
AQH_SESSION_LIST *sessionList;
sessionList=_readAllSessionsIntoList(sv);
if (sessionList) {
AQH_SESSION *session;
while( (session=AQH_Session_List_First(sessionList)) ) {
const char *sessionUid;
const char *userAlias;
AQH_Session_List_Del(session);
sessionUid=AQH_Session_GetUid(session);
userAlias=AQH_Session_GetUserAlias(session);
if (userAlias && *userAlias) {
AQH_USER *user;
user=AQH_HttpService_GetUser(sv, userAlias);
if (user==NULL) {
DBG_ERROR(AQH_LOGDOMAIN, "User \"%s\" for session \"%s\" not available", userAlias, sessionUid);
AQH_Session_free(session);
}
else {
DBG_INFO(AQH_LOGDOMAIN, "Adding session \"%s\" (user=%s)", sessionUid, userAlias);
AQH_Session_SetUser(session, user);
AQH_Service_AddSession(sv, session);
}
}
else {
DBG_ERROR(AQH_LOGDOMAIN, "Session has no user, not adding");
AQH_Session_free(session);
}
} /* while */
AQH_Session_List_free(sessionList);
}
}
@@ -518,29 +658,21 @@ AQH_SESSION *AQH_HttpService_LoadSession(const AQH_SERVICE *sv, const char *sess
{
GWEN_BUFFER *nameBuf;
int rv;
GWEN_DB_NODE *db;
AQH_SESSION *session;
db=GWEN_DB_Group_new("user");
nameBuf=_getSessionFilePath(sv, sessionUid);
rv=GWEN_DB_ReadFile(db, GWEN_Buffer_GetStart(nameBuf), GWEN_DB_FLAGS_DEFAULT);
if (rv<0) {
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
if (nameBuf==NULL) {
DBG_INFO(AQH_LOGDOMAIN, "here");
return NULL;
}
session=_readSessionFromFile(GWEN_Buffer_GetStart(nameBuf));
if (session==NULL) {
DBG_ERROR(AQH_LOGDOMAIN, "Error loading session \"%s\" from config group", sessionUid);
GWEN_Buffer_free(nameBuf);
GWEN_DB_Group_free(db);
return NULL;
}
GWEN_Buffer_free(nameBuf);
session=AQH_Session_fromDb(db);
if (session==NULL) {
DBG_ERROR(AQH_LOGDOMAIN, "Error loading session \"%s\" from config group", sessionUid);
GWEN_DB_Group_free(db);
return NULL;
}
GWEN_DB_Group_free(db);
rv=_checkSession(session);
if (rv<0) {
DBG_INFO(AQH_LOGDOMAIN, "Invalid data for session \"%s\"", sessionUid);
@@ -686,7 +818,6 @@ AQH_SESSION *_ensureSession(AQH_SERVICE *sv, const char *sessionUid)
AQH_Session_free(session);
return NULL;
}
AQH_User_Attach(user);
AQH_Session_SetUser(session, user);
AQH_Service_AddSession(sv, session);
}
@@ -773,23 +904,16 @@ GWEN_BUFFER *_getUserFilePath(const AQH_SERVICE *sv, const char *userAlias)
GWEN_BUFFER *_getSessionFilePath(const AQH_SERVICE *sv, const char *sessionUid)
{
const char *configFolder;
GWEN_BUFFER *nameBuf;
configFolder=AQH_HttpService_GetConfigFolder(sv);
if (!(configFolder && *configFolder)) {
DBG_ERROR(AQH_LOGDOMAIN, "No config folder given");
return NULL;
}
else {
GWEN_BUFFER *nameBuf;
nameBuf=GWEN_Buffer_new(0, 256, 0, 1);
GWEN_Buffer_AppendString(nameBuf, configFolder);
GWEN_Buffer_AppendString(nameBuf, GWEN_DIR_SEPARATOR_S AQH_HTTP_SERVICE_DIR_SESSIONS GWEN_DIR_SEPARATOR_S);
nameBuf=_getSessionFolder(sv);
if (nameBuf) {
GWEN_Buffer_AppendString(nameBuf, GWEN_DIR_SEPARATOR_S);
GWEN_Text_EscapeToBuffer(sessionUid, nameBuf);
GWEN_Buffer_AppendString(nameBuf, ".conf");
return nameBuf;
}
return NULL;
}
@@ -1012,6 +1136,132 @@ int _writeDbFile(const char *fname, GWEN_DB_NODE *db)
GWEN_BUFFER *_getSessionFolder(const AQH_SERVICE *sv)
{
const char *configFolder;
configFolder=AQH_HttpService_GetConfigFolder(sv);
if (!(configFolder && *configFolder)) {
DBG_ERROR(AQH_LOGDOMAIN, "No config folder given");
return NULL;
}
else {
GWEN_BUFFER *nameBuf;
nameBuf=GWEN_Buffer_new(0, 256, 0, 1);
GWEN_Buffer_AppendString(nameBuf, configFolder);
GWEN_Buffer_AppendString(nameBuf, GWEN_DIR_SEPARATOR_S AQH_HTTP_SERVICE_DIR_SESSIONS);
return nameBuf;
}
}
GWEN_STRINGLIST *_getConfFileList(const char *folder, const char *mask)
{
GWEN_STRINGLIST *sl;
int rv;
sl=GWEN_StringList_new();
rv=GWEN_Directory_GetFileEntries(folder, sl, mask);
if (rv<0) {
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
GWEN_StringList_free(sl);
return NULL;
}
if (GWEN_StringList_Count(sl)<1) {
DBG_INFO(AQH_LOGDOMAIN, "Empty string list");
GWEN_StringList_free(sl);
return NULL;
}
return sl;
}
AQH_SESSION_LIST *_readAllSessionsIntoList(const AQH_SERVICE *sv)
{
GWEN_BUFFER *folderBuf;
folderBuf=_getSessionFolder(sv);
if (folderBuf) {
GWEN_STRINGLIST *fileList;
fileList=_getConfFileList(GWEN_Buffer_GetStart(folderBuf), "*.conf");
if (fileList) {
AQH_SESSION_LIST *sessionList;
uint32_t pos;
GWEN_STRINGLISTENTRY *se;
sessionList=AQH_Session_List_new();
GWEN_Buffer_AppendString(folderBuf, GWEN_DIR_SEPARATOR_S);
pos=GWEN_Buffer_GetPos(folderBuf);
se=GWEN_StringList_FirstEntry(fileList);
while(se) {
const char *s;
s=GWEN_StringListEntry_Data(se);
if (s && *s) {
AQH_SESSION *session;
GWEN_Buffer_AppendString(folderBuf, s);
session=_readSessionFromFile(GWEN_Buffer_GetStart(folderBuf));
if (session==NULL) {
DBG_INFO(AQH_LOGDOMAIN, "here");
}
else {
AQH_Session_List_Add(session, sessionList);
}
GWEN_Buffer_Crop(folderBuf, 0, pos);
}
se=GWEN_StringListEntry_Next(se);
}
if (AQH_Session_List_GetCount(sessionList)<1) {
DBG_INFO(NULL, "Empty session list");
AQH_Session_List_free(sessionList);
GWEN_StringList_free(fileList);
GWEN_Buffer_free(folderBuf);
return NULL;
}
GWEN_StringList_free(fileList);
GWEN_Buffer_free(folderBuf);
return sessionList;
}
GWEN_Buffer_free(folderBuf);
}
return NULL;
}
AQH_SESSION *_readSessionFromFile(const char *filename)
{
int rv;
GWEN_DB_NODE *db;
AQH_SESSION *session;
db=GWEN_DB_Group_new("session");
rv=GWEN_DB_ReadFile(db, filename, GWEN_DB_FLAGS_DEFAULT);
if (rv<0) {
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
GWEN_DB_Group_free(db);
return NULL;
}
session=AQH_Session_fromDb(db);
if (session==NULL) {
DBG_ERROR(AQH_LOGDOMAIN, "Error loading session from file \"%s\"", filename);
GWEN_DB_Group_free(db);
return NULL;
}
GWEN_DB_Group_free(db);
return session;
}

View File

@@ -32,7 +32,9 @@ AQHOME_API AQH_USER *AQH_HttpService_GetUser(AQH_SERVICE *sv, const char *alias)
AQHOME_API int AQH_HttpService_WriteUser(const AQH_SERVICE *sv, const AQH_USER *user);
AQHOME_API AQH_SESSION *AQH_HttpService_GetSession(AQH_SERVICE *sv, const char *sessionUid);
AQHOME_API int AQH_HttpService_LockSessions(AQH_SERVICE *sv);
AQHOME_API int AQH_HttpService_UnlockSessions(AQH_SERVICE *sv);
AQHOME_API int AQH_HttpService_CleanupSessions(AQH_SERVICE *sv, int maxAgeInSecs);
AQHOME_API AQH_MODULE *AQH_HttpService_LoadModule(const AQH_SERVICE *sv, const char *modName);
AQHOME_API int AQH_HttpService_SaveModule(const AQH_SERVICE *sv, const AQH_MODULE *m);
@@ -47,6 +49,7 @@ AQHOME_API AQH_SESSION *AQH_HttpService_LoadSession(const AQH_SERVICE *sv, const
AQHOME_API int AQH_HttpService_SaveSession(const AQH_SERVICE *sv, const AQH_SESSION *session);
AQHOME_API int AQH_HttpService_AddSession(AQH_SERVICE *sv, AQH_SESSION *session);
AQHOME_API int AQH_HttpService_DelSession(AQH_SERVICE *sv, AQH_SESSION *session);
AQHOME_API void AQH_HttpService_LoadAllSessions(AQH_SERVICE *sv);
#endif

View File

@@ -94,7 +94,13 @@ GWEN_MSG *AQH_HttpService_HandleHttpRequest(AQH_SERVICE *sv, GWEN_MSG_ENDPOINT *
DBG_INFO(AQH_LOGDOMAIN, "Session \"%s\" not found", s);
}
else {
GWEN_TIMESTAMP *ts;
DBG_INFO(AQH_LOGDOMAIN, "Found session \"%s\"", s);
ts=GWEN_Timestamp_NowInLocalTime();
AQH_Session_SetTimestampLastAccess(session, ts);
GWEN_Timestamp_free(ts);
AQH_Session_AddRuntimeFlags(session, AQH_SESSION_RTFLAGS_MODIFIED);
AQH_HttpRequest_SetSession(rq, session);
}
}

View File

@@ -31,6 +31,7 @@
role.t2d
user.t2d
session.t2d
permdef.t2d
</setVar>
<setVar name="local/built_sources" >

View File

@@ -15,12 +15,15 @@
with_db
with_list1
with_list2
nodup
nocopy
</flags>
<headers>
<header type="sys" loc="pre">aqhome/api.h</header>
<header type="sys" loc="pre">gwenhywfar/error.h</header>
<header type="sys" loc="post">aqhome/service/role.h</header>
<header type="sys" loc="post">aqhome/service/permdef.h</header>
</headers>
<inlines>
@@ -42,14 +45,14 @@
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>with_getbymember</flags>
<flags>own with_getbymember</flags>
</member>
<member name="descr" type="char_ptr" maxlen="256">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags></flags>
<flags>own</flags>
</member>
<member name="guestPerms" type="uint32_t" maxlen="4">
@@ -68,6 +71,15 @@
<setflags>none</setflags>
</member>
<member name="permDefList" type="AQH_PERMDEF_LIST" elementName="permdef" >
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
<flags>own</flags>
<getflags>none</getflags>
<setflags>none</setflags>
</member>
</members>
</type>

View File

@@ -0,0 +1,65 @@
<?xml?>
<tm2>
<type id="AQH_PERMDEF" type="pointer">
<descr>
</descr>
<lang id="c">
<identifier>AQH_PERMDEF</identifier>
<prefix>AQH_PermDef</prefix>
<baseFileName>permdef</baseFileName>
<flags>
with_xml
with_db
with_list1
nodup
nocopy
</flags>
<headers>
<header type="sys" loc="pre">aqhome/api.h</header>
</headers>
<inlines>
</inlines>
</lang>
<members>
<member name="id" type="char_ptr" maxlen="32">
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
<flags>own with_getbymember</flags>
</member>
<member name="name" type="char_ptr" maxlen="32">
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
<flags>own with_getbymember</flags>
</member>
<member name="mask" type="uint32_t" maxlen="4">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own with_getbymember</flags>
</member>
<member name="descr" type="char_ptr" maxlen="256">
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
<flags>own</flags>
</member>
</members>
</type>
</tm2>

View File

@@ -40,7 +40,7 @@
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags></flags>
<flags>own</flags>
</member>
<member name="perms" type="uint32_t" maxlen="4">

View File

@@ -44,10 +44,12 @@ void AQH_Service_free(AQH_SERVICE *sv)
{
if (sv) {
GWEN_LIST_FINI(AQH_SERVICE, sv);
GWEN_INHERIT_FINI(AQH_SERVICE, sv);
AQH_User_List_free(sv->userList);
AQH_Module_List_free(sv->moduleList);
AQH_Session_List_free(sv->sessionList);
GWEN_INHERIT_FINI(AQH_SERVICE, sv);
GWEN_FREE_OBJECT(sv);
}
}

View File

@@ -31,13 +31,21 @@
</lang>
<defines>
<define id="AQH_SESSION_RTFLAGS" prefix="AQH_SESSION_RTFLAGS_">
<item name="MODIFIED" value="0x00000001" />
</define>
</defines>
<members>
<member name="uid" type="char_ptr" maxlen="64">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>with_getbymember</flags>
<flags>own with_getbymember</flags>
</member>
<member name="flags" type="uint32_t" maxlen="4">
@@ -51,7 +59,7 @@
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
<flags></flags>
<flags>own</flags>
</member>
<member name="state" type="int" maxlen="4">
@@ -65,7 +73,7 @@
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags></flags>
<flags>own</flags>
</member>
<member name="timestampCreation" type="gwen_timestamp" maxlen="8">
@@ -75,6 +83,13 @@
<flags>own</flags>
</member>
<member name="timestampLastAccess" type="gwen_timestamp" maxlen="8">
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
<flags>own</flags>
</member>
<member name="user" type="AQH_USER">
<default>NULL</default>
@@ -85,6 +100,15 @@
<flags>volatile nodup nocopy</flags>
</member>
<member name="runtimeFlags" type="uint32_t" maxlen="4">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>with_flags volatile</flags>
</member>
</members>
</type>

View File

@@ -86,35 +86,35 @@
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags></flags>
<flags>own</flags>
</member>
<member name="alias" type="char_ptr" maxlen="16">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>with_getbymember</flags>
<flags>own with_getbymember</flags>
</member>
<member name="hashedPassword" type="char_ptr" maxlen="128">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags></flags>
<flags>own</flags>
</member>
<member name="email" type="char_ptr" maxlen="128">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags></flags>
<flags>own</flags>
</member>
<member name="notes" type="char_ptr" maxlen="256">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags></flags>
<flags>own</flags>
</member>
<member name="timestampCreation" type="gwen_timestamp" maxlen="8">