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

1
.gitignore vendored
View File

@@ -5,3 +5,4 @@ aqhome.db
aqhome.log aqhome.log
aqhomed.vg aqhomed.vg
aqhome-mqttlog.vg aqhome-mqttlog.vg
aqhome-storage.vg

View File

@@ -42,6 +42,7 @@
fini.h fini.h
loop.h loop.h
loop_http.h loop_http.h
cleanup.h
u_login.h u_login.h
u_rooms.h u_rooms.h
aqhomehttp.h aqhomehttp.h
@@ -57,6 +58,7 @@
fini.c fini.c
loop.c loop.c
loop_http.c loop_http.c
cleanup.c
u_login.c u_login.c
u_rooms.c u_rooms.c
main.c main.c

View File

@@ -48,7 +48,7 @@ void AqHomeHttpService_Extend(AQH_SERVICE *sv)
GWEN_INHERIT_SETDATA(AQH_SERVICE, AQHOME_HTTP, sv, xsv, _freeData); GWEN_INHERIT_SETDATA(AQH_SERVICE, AQHOME_HTTP, sv, xsv, _freeData);
xsv->contentTree=AQH_HttpContent_new("root"); xsv->contentTree=AQH_HttpContent_new("root");
xsv->storageMutex=GWEN_Mutex_new();
} }
@@ -62,6 +62,7 @@ void _freeData(void *bp, void *p)
xsv->storage=NULL; xsv->storage=NULL;
AQH_HttpContent_free(xsv->contentTree); AQH_HttpContent_free(xsv->contentTree);
xsv->contentTree=NULL; xsv->contentTree=NULL;
GWEN_Mutex_free(xsv->storageMutex);
GWEN_FREE_OBJECT(xsv); GWEN_FREE_OBJECT(xsv);
} }
@@ -124,6 +125,65 @@ void AqHomeHttpService_SetContentTree(AQH_SERVICE *sv, AQH_HTTP_CONTENT *c)
void AqHomeHttpService_MarkStorageChanged(AQH_SERVICE *sv)
{
if (sv) {
AQHOME_HTTP *xsv;
xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQHOME_HTTP, sv);
if (xsv) {
AQH_Storage_AddRuntimeFlags(xsv->storage, AQH_STORAGE_RTFLAGS_MODIFIED);
}
}
}
int AqHomeHttpService_LockStorage(AQH_SERVICE *sv)
{
if (sv) {
AQHOME_HTTP *xsv;
xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQHOME_HTTP, sv);
if (xsv) {
int rv;
rv=GWEN_Mutex_Lock(xsv->storageMutex);
if (rv<0) {
DBG_ERROR(AQH_LOGDOMAIN, "Error obtaining lock on storage mutex");
return rv;
}
return 0;
}
}
return GWEN_ERROR_GENERIC;
}
int AqHomeHttpService_UnlockStorage(AQH_SERVICE *sv)
{
if (sv) {
AQHOME_HTTP *xsv;
xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQHOME_HTTP, sv);
if (xsv) {
int rv;
rv=GWEN_Mutex_Unlock(xsv->storageMutex);
if (rv<0) {
DBG_ERROR(AQH_LOGDOMAIN, "Error releasing lock on storage mutex");
return rv;
}
return 0;
}
}
return GWEN_ERROR_GENERIC;
}

View File

@@ -50,7 +50,9 @@ AQH_HTTP_CONTENT *AqHomeHttpService_GetContentTree(const AQH_SERVICE *sv);
void AqHomeHttpService_SetContentTree(AQH_SERVICE *sv, AQH_HTTP_CONTENT *c); void AqHomeHttpService_SetContentTree(AQH_SERVICE *sv, AQH_HTTP_CONTENT *c);
int AqHomeHttpService_LockStorage(AQH_SERVICE *sv);
int AqHomeHttpService_UnlockStorage(AQH_SERVICE *sv);
void AqHomeHttpService_MarkStorageChanged(AQH_SERVICE *sv);
#endif #endif

View File

@@ -12,10 +12,14 @@
#include "./aqhomehttp.h" #include "./aqhomehttp.h"
#include <gwenhywfar/mutex.h>
typedef struct AQHOME_HTTP AQHOME_HTTP; typedef struct AQHOME_HTTP AQHOME_HTTP;
struct AQHOME_HTTP { struct AQHOME_HTTP {
AQH_STORAGE *storage; /* do not release */ AQH_STORAGE *storage; /* do not release */
GWEN_MUTEX *storageMutex;
AQH_HTTP_CONTENT *contentTree; AQH_HTTP_CONTENT *contentTree;
}; };

View File

@@ -36,16 +36,16 @@ AQHOME_STORAGE *AqHomeStorage_new()
void AqHomeStorage_free(AQHOME_STORAGE *aqh) void AqHomeStorage_free(AQHOME_STORAGE *aqh)
{ {
if (aqh) { if (aqh) {
AQH_Service_free(aqh->httpService);
aqh->httpService=NULL;
AQH_Storage_free(aqh->storage); AQH_Storage_free(aqh->storage);
GWEN_MsgEndpoint_free(aqh->rootEndpoint);
GWEN_MsgEndpoint_free(aqh->rootEndpoint);
GWEN_DB_Group_free(aqh->dbArgs);
aqh->storage=NULL; aqh->storage=NULL;
GWEN_MsgEndpoint_free(aqh->rootEndpoint);
aqh->rootEndpoint=NULL; aqh->rootEndpoint=NULL;
aqh->ipcdEndpoint=NULL; aqh->ipcdEndpoint=NULL;
aqh->mqttEndpoint=NULL; aqh->mqttEndpoint=NULL;
aqh->httpdEndpoint=NULL; aqh->httpdEndpoint=NULL;
GWEN_DB_Group_free(aqh->dbArgs);
aqh->dbArgs=NULL; aqh->dbArgs=NULL;
free(aqh->pidFile); free(aqh->pidFile);
@@ -114,6 +114,13 @@ void AqHomeStorage_SetPidFile(AQHOME_STORAGE *aqh, const char *s)
int AqHomeStorage_GetTimeout(const AQHOME_STORAGE *aqh)
{
return aqh?aqh->timeout:0;
}

View File

@@ -35,6 +35,8 @@ AQH_STORAGE *AqHomeStorage_GetStorage(const AQHOME_STORAGE *aqh);
const char *AqHomeStorage_GetPidFile(const AQHOME_STORAGE *aqh); const char *AqHomeStorage_GetPidFile(const AQHOME_STORAGE *aqh);
void AqHomeStorage_SetPidFile(AQHOME_STORAGE *aqh, const char *s); void AqHomeStorage_SetPidFile(AQHOME_STORAGE *aqh, const char *s);
int AqHomeStorage_GetTimeout(const AQHOME_STORAGE *aqh);
#endif #endif

View File

@@ -27,6 +27,8 @@
#define AQHOME_STORAGE_DEFAULT_STATEFILE "/var/lib/aqhomestorage/config/statefile" #define AQHOME_STORAGE_DEFAULT_STATEFILE "/var/lib/aqhomestorage/config/statefile"
#define AQHOME_STORAGE_DEFAULT_MAXSESSIONAGE (30*60)
#define AQHOME_STORAGE_SITEHEADER "site-header.html" #define AQHOME_STORAGE_SITEHEADER "site-header.html"
#define AQHOME_STORAGE_SITEFOOTER "site-footer.html" #define AQHOME_STORAGE_SITEFOOTER "site-footer.html"
@@ -35,9 +37,9 @@
struct AQHOME_STORAGE { struct AQHOME_STORAGE {
GWEN_MSG_ENDPOINT *rootEndpoint; GWEN_MSG_ENDPOINT *rootEndpoint;
GWEN_MSG_ENDPOINT *ipcdEndpoint; GWEN_MSG_ENDPOINT *ipcdEndpoint; /* don't release, will be released by freeing rootEndpoint! */
GWEN_MSG_ENDPOINT *mqttEndpoint; GWEN_MSG_ENDPOINT *mqttEndpoint; /* don't release, will be released by freeing rootEndpoint! */
GWEN_MSG_ENDPOINT *httpdEndpoint; GWEN_MSG_ENDPOINT *httpdEndpoint; /* don't release, will be released by freeing rootEndpoint! */
GWEN_DB_NODE *dbArgs; GWEN_DB_NODE *dbArgs;
@@ -45,6 +47,10 @@ struct AQHOME_STORAGE {
AQH_STORAGE *storage; AQH_STORAGE *storage;
char *pidFile; char *pidFile;
int maxSessionAgeInSeconds;
int timeout; /* timeout for run e.g. inside valgrind */
}; };
#endif #endif

View File

@@ -0,0 +1,61 @@
/****************************************************************************
* 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 "./cleanup.h"
#include "./aqhomehttp.h"
#include "./aqhomestorage_p.h"
#include "aqhome/http/httpservice_conf.h"
#include <gwenhywfar/gwenhywfar.h>
#include <gwenhywfar/args.h>
#include <gwenhywfar/debug.h>
#include <gwenhywfar/endpoint.h>
/* ------------------------------------------------------------------------------------------------
* defines
* ------------------------------------------------------------------------------------------------
*/
/* ------------------------------------------------------------------------------------------------
* forward declarations
* ------------------------------------------------------------------------------------------------
*/
/* ------------------------------------------------------------------------------------------------
* implementations
* ------------------------------------------------------------------------------------------------
*/
void AqHomeStorage_Cleanup(AQHOME_STORAGE *aqh)
{
int rv;
rv=AQH_HttpService_CleanupSessions(aqh->httpService, aqh->maxSessionAgeInSeconds);
if (rv<0) {
DBG_INFO(NULL, "here (%d)", rv);
}
}

View 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 AQHOME_STORAGE_CLEANUP_H
#define AQHOME_STORAGE_CLEANUP_H
#include "./aqhomestorage.h"
void AqHomeStorage_Cleanup(AQHOME_STORAGE *aqh);
#endif

View File

@@ -96,6 +96,9 @@ int AqHomeStorage_Init(AQHOME_STORAGE *aqh, int argc, char **argv)
} }
aqh->dbArgs=dbArgs; aqh->dbArgs=dbArgs;
aqh->maxSessionAgeInSeconds=GWEN_DB_GetIntValue(dbArgs, "maxSessionAge", 0, AQHOME_STORAGE_DEFAULT_MAXSESSIONAGE);
aqh->timeout=GWEN_DB_GetIntValue(dbArgs, "timeout", 0, 0);
s=GWEN_DB_GetCharValue(dbArgs, "pidfile", 0, AQHOME_STORAGE_DEFAULT_PIDFILE); s=GWEN_DB_GetCharValue(dbArgs, "pidfile", 0, AQHOME_STORAGE_DEFAULT_PIDFILE);
if (s && *s) { if (s && *s) {
AqHomeStorage_SetPidFile(aqh, s); AqHomeStorage_SetPidFile(aqh, s);
@@ -415,6 +418,17 @@ int _readArgs(int argc, char **argv, GWEN_DB_NODE *dbArgs)
I18S("Specify the port to listen on for HTTP connections"), I18S("Specify the port to listen on for HTTP connections"),
I18S("Specify the port to listen on for HTTP connections") I18S("Specify the port to listen on for HTTP connections")
}, },
{
GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */
GWEN_ArgsType_Int, /* type */
"maxSessionAge", /* name */
0, /* minnum */
1, /* maxnum */
NULL, /* short option */
"maxsessionage", /* long option */
I18S("Specify maximum session age in seconds (default: 30mins)"),
I18S("Specify maximum session age in seconds (default: 30mins)")
},
{ {
GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */ GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */
GWEN_ArgsType_Char, /* type */ GWEN_ArgsType_Char, /* type */

View File

@@ -151,7 +151,7 @@ int _setupHttpService(AQHOME_STORAGE *aqh, GWEN_DB_NODE *dbArgs)
DBG_ERROR(NULL, "Error loading config for HTTP service (%d)", rv); DBG_ERROR(NULL, "Error loading config for HTTP service (%d)", rv);
return GWEN_ERROR_GENERIC; return GWEN_ERROR_GENERIC;
} }
AQH_HttpService_LoadAllSessions(aqh->httpService);
return 0; return 0;
} }

View File

@@ -13,7 +13,9 @@
#include "./loop.h" #include "./loop.h"
#include "./loop_http.h" #include "./loop_http.h"
#include "./aqhomehttp.h"
#include "./aqhomestorage_p.h" #include "./aqhomestorage_p.h"
#include "aqhome/http/httpservice_conf.h"
#include <gwenhywfar/gwenhywfar.h> #include <gwenhywfar/gwenhywfar.h>
#include <gwenhywfar/args.h> #include <gwenhywfar/args.h>
@@ -34,6 +36,7 @@
* ------------------------------------------------------------------------------------------------ * ------------------------------------------------------------------------------------------------
*/ */
static int _writeModifiedSessions(AQHOME_STORAGE *aqh);
@@ -48,9 +51,97 @@ void AqHomeStorage_Loop(AQHOME_STORAGE *aqh, int timeoutInMsecs)
GWEN_MsgEndpoint_ChildrenIoLoop(aqh->rootEndpoint, timeoutInMsecs); GWEN_MsgEndpoint_ChildrenIoLoop(aqh->rootEndpoint, timeoutInMsecs);
AqHomeStorage_ReadAndHandleHttpMessages(aqh); AqHomeStorage_ReadAndHandleHttpMessages(aqh);
// AqHomeStorage_ReadAndHandleIpcMessages(aqh); // AqHomeStorage_ReadAndHandleIpcMessages(aqh);
} }
} }
int AqHomeStorage_WriteStorageIfChanged(AQHOME_STORAGE *aqh)
{
if (AQH_Storage_GetRuntimeFlags(aqh->storage) & AQH_STORAGE_RTFLAGS_MODIFIED) {
int rv;
DBG_INFO(NULL, "Storage modified, writing statefile");
rv=AqHomeHttpService_LockStorage(aqh->httpService);
if (rv<0) {
DBG_INFO(NULL, "Error locking storage (%d)", rv);
return rv;
}
rv=AQH_Storage_WriteState(aqh->storage);
if (rv<0) {
DBG_INFO(NULL, "Error writing state file (%d)", rv);
AqHomeHttpService_UnlockStorage(aqh->httpService);
return rv;
}
rv=AqHomeHttpService_UnlockStorage(aqh->httpService);
if (rv<0) {
DBG_INFO(NULL, "Error unlocking storage (%d)", rv);
return rv;
}
}
return 0;
}
int AqHomeStorage_WriteServiceIfChanged(AQHOME_STORAGE *aqh)
{
int rv;
rv=_writeModifiedSessions(aqh);
if (rv<0) {
DBG_INFO(NULL, "here (%d)", rv);
return rv;
}
return 0;
}
int _writeModifiedSessions(AQHOME_STORAGE *aqh)
{
AQH_SESSION_LIST *sessionList;
int rv;
rv=AQH_HttpService_LockSessions(aqh->httpService);
if (rv<0) {
DBG_INFO(NULL, "Error locking sessions (%d)", rv);
return rv;
}
sessionList=AQH_Service_GetSessionList(aqh->httpService);
if (sessionList) {
AQH_SESSION *session;
session=AQH_Session_List_First(sessionList);
while(session) {
if (AQH_Session_GetRuntimeFlags(session) & AQH_SESSION_RTFLAGS_MODIFIED) {
DBG_INFO(NULL, "Session \"%s\" modified, writing", AQH_Session_GetUid(session));
rv=AQH_HttpService_SaveSession(aqh->httpService, session);
if (rv<0) {
DBG_INFO(NULL, "Error writing session \"%s\" (%d)", AQH_Session_GetUid(session), rv);
}
else {
DBG_DEBUG(NULL, "Session \"%s\" written", AQH_Session_GetUid(session));
AQH_Session_SubRuntimeFlags(session, AQH_SESSION_RTFLAGS_MODIFIED);
}
}
session=AQH_Session_List_Next(session);
}
}
rv=AQH_HttpService_UnlockSessions(aqh->httpService);
if (rv<0) {
DBG_INFO(NULL, "Error unlocking sessions (%d)", rv);
return rv;
}
return 0;
}

View File

@@ -15,6 +15,9 @@
void AqHomeStorage_Loop(AQHOME_STORAGE *aqh, int timeoutInMsecs); void AqHomeStorage_Loop(AQHOME_STORAGE *aqh, int timeoutInMsecs);
int AqHomeStorage_WriteStorageIfChanged(AQHOME_STORAGE *aqh);
int AqHomeStorage_WriteServiceIfChanged(AQHOME_STORAGE *aqh);
#endif #endif

View File

@@ -17,6 +17,7 @@
#include "./init.h" #include "./init.h"
#include "./fini.h" #include "./fini.h"
#include "./loop.h" #include "./loop.h"
#include "./cleanup.h"
#include <gwenhywfar/gwenhywfar.h> #include <gwenhywfar/gwenhywfar.h>
#include <gwenhywfar/logger.h> #include <gwenhywfar/logger.h>
@@ -29,6 +30,14 @@
//#define CLEANUP_INTERVAL_IN_SECS (5*60)
//#define WRITE_INTERVAL_IN_SECS (5*60)
#define CLEANUP_INTERVAL_IN_SECS (60)
#define WRITE_INTERVAL_IN_SECS (60)
/* ------------------------------------------------------------------------------------------------ /* ------------------------------------------------------------------------------------------------
* defines * defines
* ------------------------------------------------------------------------------------------------ * ------------------------------------------------------------------------------------------------
@@ -48,6 +57,9 @@ static int _setupSigAction(struct sigaction *sa, int sig);
static void _signalHandler(int s); static void _signalHandler(int s);
#endif #endif
static void _runService(AQHOME_STORAGE *aqh);
static void _writeCurrentState(AQHOME_STORAGE *aqh);
/* ------------------------------------------------------------------------------------------------ /* ------------------------------------------------------------------------------------------------
@@ -106,10 +118,7 @@ int main(int argc, char **argv)
return 2; return 2;
} }
while(!stopService) { _runService(aqh);
DBG_DEBUG(NULL, "Next loop");
AqHomeStorage_Loop(aqh, 2000);
}
AqHomeStorage_Fini(aqh); AqHomeStorage_Fini(aqh);
AqHomeStorage_free(aqh); AqHomeStorage_free(aqh);
@@ -122,6 +131,67 @@ int main(int argc, char **argv)
void _runService(AQHOME_STORAGE *aqh)
{
time_t timeStart;
time_t timeLastCleanup;
time_t timeLastWrite;
int timeout;
timeout=AqHomeStorage_GetTimeout(aqh);
timeStart=time(NULL);
timeLastCleanup=time(NULL);
timeLastWrite=time(NULL);
while(!stopService) {
time_t now;
DBG_DEBUG(NULL, "Next loop");
AqHomeStorage_Loop(aqh, 2000);
now=time(NULL);
if (((int)difftime(now, timeLastCleanup))>CLEANUP_INTERVAL_IN_SECS) {
DBG_INFO(NULL, "Cleanup time");
AqHomeStorage_Cleanup(aqh);
timeLastCleanup=now;
}
if (((int)difftime(now, timeLastWrite))>WRITE_INTERVAL_IN_SECS) {
DBG_INFO(NULL, "Write time");
_writeCurrentState(aqh);
timeLastWrite=now;
}
if (timeout && ((int)difftime(now, timeStart))>timeout) {
DBG_INFO(NULL, "Timeout");
_writeCurrentState(aqh);
break;
}
} /* while */
}
void _writeCurrentState(AQHOME_STORAGE *aqh)
{
int rv;
rv=AqHomeStorage_WriteStorageIfChanged(aqh);
if (rv<0) {
DBG_ERROR(NULL, "ATTENTION: Could not write storage statefile (%d)", rv);
}
rv=AqHomeStorage_WriteServiceIfChanged(aqh);
if (rv<0) {
DBG_ERROR(NULL, "ATTENTION: Could not write current config (%d)", rv);
}
}
int _setSignalHandlers(void) int _setSignalHandlers(void)
{ {
#ifdef HAVE_SIGNAL_H #ifdef HAVE_SIGNAL_H

View File

@@ -308,8 +308,9 @@ AQH_SESSION *_generateSessionForUser(AQH_SERVICE *sv, AQH_USER *u)
session=AQH_Session_new(); session=AQH_Session_new();
AQH_Session_SetUid(session, GWEN_Buffer_GetStart(buf)); AQH_Session_SetUid(session, GWEN_Buffer_GetStart(buf));
ts=GWEN_Timestamp_NowInGmTime(); ts=GWEN_Timestamp_NowInLocalTime();
AQH_Session_SetTimestampCreation(session, ts); AQH_Session_SetTimestampCreation(session, ts);
AQH_Session_SetTimestampLastAccess(session, ts);
GWEN_Timestamp_free(ts); GWEN_Timestamp_free(ts);
AQH_Session_SetUserAlias(session, AQH_User_GetAlias(u)); AQH_Session_SetUserAlias(session, AQH_User_GetAlias(u));

View File

@@ -36,14 +36,15 @@
*/ */
static int _handleUrl(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq); static int _handleUrl(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq);
static int _handleGet(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq); static GWEN_MSG *_handleGet(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq);
static int _handlePost(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq); static GWEN_MSG *_handlePost(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq);
static void _handleGetList(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_BUFFER *pageBuf); static void _handleGetList(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_BUFFER *pageBuf);
static void _handleGetAdd(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_BUFFER *pageBuf); static void _handleGetAdd(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_BUFFER *pageBuf);
static int _handlePostAdd(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq); static GWEN_MSG *_handlePostAdd(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq);
static int _writeAddPage(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_DB_NODE *dbValues, GWEN_BUFFER *pageBuf); static int _writeAddPage(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_DB_NODE *dbValues, GWEN_BUFFER *pageBuf);
static GWEN_MSG *_addRoomCreateResponse(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq);
@@ -68,7 +69,7 @@ int _handleUrl(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq)
{ {
const char *protocol; const char *protocol;
const char *cmd; const char *cmd;
GWEN_MSG *msgOut=NULL; GWEN_MSG *msgOut;
AQH_HttpService_SetupModuleAndPerms(AQH_HttpUrlHandler_GetHttpService(uh), rq, "aqhome"); AQH_HttpService_SetupModuleAndPerms(AQH_HttpUrlHandler_GetHttpService(uh), rq, "aqhome");
AQH_HttpRequest_SetupUrlPathMembers(rq); AQH_HttpRequest_SetupUrlPathMembers(rq);
@@ -76,26 +77,14 @@ int _handleUrl(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq)
protocol=AQH_HttpRequest_GetProtocol(rq); protocol=AQH_HttpRequest_GetProtocol(rq);
cmd=AQH_HttpRequest_GetCommand(rq); cmd=AQH_HttpRequest_GetCommand(rq);
if (cmd && *cmd) { if (cmd && *cmd) {
int rv; if (strcasecmp(cmd, "GET")==0)
msgOut=_handleGet(uh, rq);
if (strcasecmp(cmd, "GET")==0) { else if (strcasecmp(cmd, "POST")==0)
rv=_handleGet(uh, rq); msgOut=_handlePost(uh, rq);
if (rv<0) {
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
return rv;
}
}
else if (strcasecmp(cmd, "POST")==0) {
rv=_handlePost(uh, rq);
if (rv<0) {
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
return rv;
}
}
else { else {
msgOut=AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 405, "Method not allowed", protocol, NULL); msgOut=AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 405, "Method not allowed", protocol, NULL);
AQH_HttpRequest_SetResponseMsg(rq, msgOut);
} }
AQH_HttpRequest_SetResponseMsg(rq, msgOut);
return 0; return 0;
} }
else { else {
@@ -106,7 +95,7 @@ int _handleUrl(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq)
int _handleGet(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq) GWEN_MSG *_handleGet(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq)
{ {
GWEN_BUFFER *pageBuf; GWEN_BUFFER *pageBuf;
int rv; int rv;
@@ -120,9 +109,7 @@ int _handleGet(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq)
if (rv<0) { if (rv<0) {
DBG_ERROR(AQH_LOGDOMAIN, "Error adding headers"); DBG_ERROR(AQH_LOGDOMAIN, "Error adding headers");
GWEN_Buffer_free(pageBuf); GWEN_Buffer_free(pageBuf);
msgOut=AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 500, "Internal Error", protocol, NULL); return AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 500, "Internal Error", protocol, NULL);
AQH_HttpRequest_SetResponseMsg(rq, msgOut);
return 0;
} }
/* handle middle part (header - middle - footer) */ /* handle middle part (header - middle - footer) */
@@ -140,38 +127,35 @@ int _handleGet(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq)
_handleGetAdd(uh, rq, pageBuf); _handleGetAdd(uh, rq, pageBuf);
else { else {
DBG_ERROR(NULL, "Invalid url (2nd member is [%s])", s); DBG_ERROR(NULL, "Invalid url (2nd member is [%s])", s);
msgOut=AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 500, "Internal Error", protocol, NULL);
AQH_HttpRequest_SetResponseMsg(rq, msgOut);
GWEN_Buffer_free(pageBuf); GWEN_Buffer_free(pageBuf);
return 0; return AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 404, "Not found", protocol, NULL);
} }
} }
else {
DBG_ERROR(NULL, "No list of url members");
GWEN_Buffer_free(pageBuf);
return AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 500, "Internal Error", protocol, NULL);
}
rv=AQH_HttpUrlHandler_AddContentFooters(uh, AQH_HTTP_CONTENT_MODE_DESKTOP, pageBuf); rv=AQH_HttpUrlHandler_AddContentFooters(uh, AQH_HTTP_CONTENT_MODE_DESKTOP, pageBuf);
if (rv<0) { if (rv<0) {
DBG_ERROR(AQH_LOGDOMAIN, "Error adding footers"); DBG_ERROR(AQH_LOGDOMAIN, "Error adding footers");
msgOut=AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 500, "Internal Error", protocol, NULL);
AQH_HttpRequest_SetResponseMsg(rq, msgOut);
GWEN_Buffer_free(pageBuf); GWEN_Buffer_free(pageBuf);
return rv; return AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 500, "Internal Error", protocol, NULL);
} }
msgOut=AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 200, "OK", protocol, GWEN_Buffer_GetStart(pageBuf)); msgOut=AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 200, "OK", protocol, GWEN_Buffer_GetStart(pageBuf));
GWEN_Buffer_free(pageBuf); GWEN_Buffer_free(pageBuf);
AQH_HttpRequest_SetResponseMsg(rq, msgOut); return msgOut;
return 0;
} }
int _handlePost(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq) GWEN_MSG *_handlePost(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq)
{ {
GWEN_DB_NODE *db; GWEN_DB_NODE *db;
const GWEN_STRINGLIST *sl; const GWEN_STRINGLIST *sl;
const char *protocol; const char *protocol;
GWEN_MSG *msgOut=NULL;
int rv;
DBG_ERROR(NULL, "POST:"); DBG_ERROR(NULL, "POST:");
db=AQH_HttpRequest_GetDbPostBody(rq); db=AQH_HttpRequest_GetDbPostBody(rq);
@@ -185,24 +169,21 @@ int _handlePost(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq)
s=GWEN_StringList_StringAt(sl, 1); s=GWEN_StringList_StringAt(sl, 1);
if (s && *s) { if (s && *s) {
if (strcasecmp(s, "add")==0) if (strcasecmp(s, "add")==0)
rv=_handlePostAdd(uh, rq); return _handlePostAdd(uh, rq);
else { else {
DBG_ERROR(NULL, "Invalid url (2nd member is [%s])", s); DBG_ERROR(NULL, "Invalid url (2nd member is [%s])", s);
msgOut=AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 404, "Not found", protocol, NULL); return AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 404, "Not found", protocol, NULL);
AQH_HttpRequest_SetResponseMsg(rq, msgOut);
return 0;
} }
return rv;
} }
else { else {
DBG_ERROR(NULL, "Invalid url (2nd member missing)"); DBG_ERROR(NULL, "Invalid url (2nd member missing)");
msgOut=AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 404, "Not found", protocol, NULL); return AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 404, "Not found", protocol, NULL);
AQH_HttpRequest_SetResponseMsg(rq, msgOut);
return 0;
} }
} }
else {
return 0; DBG_ERROR(NULL, "No list of url members");
return AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 404, "Not found", protocol, NULL);
}
} }
@@ -316,65 +297,89 @@ int _writeAddPage(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_DB_NODE *d
int _handlePostAdd(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq) GWEN_MSG *_handlePostAdd(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq)
{ {
const char *protocol; const char *protocol;
AQH_SERVICE *sv; AQH_SERVICE *sv;
uint32_t perms; uint32_t perms;
GWEN_MSG *msgOut=NULL;
protocol=AQH_HttpRequest_GetProtocol(rq); protocol=AQH_HttpRequest_GetProtocol(rq);
sv=AQH_HttpUrlHandler_GetHttpService(uh); sv=AQH_HttpUrlHandler_GetHttpService(uh);
perms=AQH_HttpRequest_GetModulePerms(rq); perms=AQH_HttpRequest_GetModulePerms(rq);
if (perms & AQHOME_HTTP_PERMS_ADD_ROOM) { if (perms & AQHOME_HTTP_PERMS_ADD_ROOM) {
GWEN_DB_NODE *db;
const char *roomName;
const char *roomDescr;
AQH_STORAGE *sto; AQH_STORAGE *sto;
db=AQH_HttpRequest_GetDbPostBody(rq);
roomName=GWEN_DB_GetCharValue(db, "name", 0, NULL);
roomDescr=GWEN_DB_GetCharValue(db, "description", 0, NULL);
if (!(roomName && *roomName)) {
msgOut=AQH_HttpUrlHandler_CreatePageMessage(uh, rq, "red", I18N("Missing room name"), 1, db, _writeAddPage);
AQH_HttpRequest_SetResponseMsg(rq, msgOut);
return 0;
}
sto=AqHomeHttpService_GetStorage(sv); sto=AqHomeHttpService_GetStorage(sv);
if (sto) { if (sto) {
AQH_ROOM *r; return _addRoomCreateResponse(uh, rq);
r=AQH_Room_new();
AQH_Room_SetName(r, roomName);
if (roomDescr && *roomDescr)
AQH_Room_SetDescription(r, roomDescr);
if (AQH_Storage_GetRoomByName(sto, roomName)!=NULL) {
msgOut=AQH_HttpUrlHandler_CreatePageMessage(uh, rq, "red", I18N("Room already exists"), 1, db, _writeAddPage);
AQH_HttpRequest_SetResponseMsg(rq, msgOut);
return 0;
}
AQH_Storage_AddRoom(sto, r);
msgOut=AQH_HttpService_CreateRedirectingResponseMsg(sv, protocol, "/rooms/list");
AQH_HttpRequest_SetResponseMsg(rq, msgOut);
return 0;
} }
else { else {
DBG_ERROR(NULL, "No storage"); DBG_ERROR(NULL, "No storage");
msgOut=AQH_HttpService_CreateResponseMsg(sv, 500, "Internal error", protocol, NULL); return AQH_HttpService_CreateResponseMsg(sv, 500, "Internal error", protocol, NULL);
AQH_HttpRequest_SetResponseMsg(rq, msgOut);
return 0;
} }
} }
else { else {
msgOut=AQH_HttpService_CreateResponseMsg(sv, 403, "Forbidden", protocol, NULL); return AQH_HttpService_CreateResponseMsg(sv, 403, "Forbidden", protocol, NULL);
AQH_HttpRequest_SetResponseMsg(rq, msgOut);
return 0;
} }
} }
GWEN_MSG *_addRoomCreateResponse(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq)
{
AQH_SERVICE *sv;
const char *protocol;
GWEN_DB_NODE *db;
const char *roomName;
const char *roomDescr;
AQH_STORAGE *sto;
sv=AQH_HttpUrlHandler_GetHttpService(uh);
protocol=AQH_HttpRequest_GetProtocol(rq);
db=AQH_HttpRequest_GetDbPostBody(rq);
roomName=GWEN_DB_GetCharValue(db, "name", 0, NULL);
roomDescr=GWEN_DB_GetCharValue(db, "description", 0, NULL);
if (!(roomName && *roomName)) {
DBG_INFO(NULL, "Missing room name");
return AQH_HttpUrlHandler_CreatePageMessage(uh, rq, "red", I18N("Missing room name"), 1, db, _writeAddPage);
}
sto=AqHomeHttpService_GetStorage(sv);
if (sto) {
AQH_ROOM *r;
int rv;
r=AQH_Room_new();
AQH_Room_SetName(r, roomName);
if (roomDescr && *roomDescr)
AQH_Room_SetDescription(r, roomDescr);
rv=AqHomeHttpService_LockStorage(sv);
if (rv<0) {
DBG_ERROR(NULL, "Error locking storage");
return AQH_HttpService_CreateResponseMsg(sv, 500, "Internal error", protocol, NULL);
}
if (AQH_Storage_GetRoomByName(sto, roomName)!=NULL) {
DBG_INFO(NULL, "Room \"%s\" already exists", roomName);
AqHomeHttpService_UnlockStorage(sv);
return AQH_HttpUrlHandler_CreatePageMessage(uh, rq, "red", I18N("Room already exists"), 1, db, _writeAddPage);
}
AQH_Storage_AddRoom(sto, r);
AQH_Storage_AddRuntimeFlags(sto, AQH_STORAGE_RTFLAGS_MODIFIED);
rv=AqHomeHttpService_UnlockStorage(sv);
if (rv<0) {
DBG_ERROR(NULL, "Error unlocking storage");
return AQH_HttpService_CreateResponseMsg(sv, 500, "Internal error", protocol, NULL);
}
return AQH_HttpService_CreateRedirectingResponseMsg(sv, protocol, "/rooms/list");
}
else
return AQH_HttpService_CreateResponseMsg(sv, 500, "Internal error", protocol, NULL);
}

View File

@@ -11,5 +11,5 @@ export LD_LIBRARY_PATH="0-build/aqhome/:$LD_LIBRARY_PATH"
--statefile=apps/aqhome-storage/test/config/state \ --statefile=apps/aqhome-storage/test/config/state \
-ma 192.168.117.192 -mp 1883 --mqttclientid=AQHOMESTORAGETEST \ -ma 192.168.117.192 -mp 1883 --mqttclientid=AQHOMESTORAGETEST \
-ha 127.0.0.1 -hp 1884 \ -ha 127.0.0.1 -hp 1884 \
-p ./aqhome-storage.pid -p ./aqhome-storage.pid \
$*

View File

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

View File

@@ -41,14 +41,14 @@
<default>0</default> <default>0</default>
<preset>0</preset> <preset>0</preset>
<access>public</access> <access>public</access>
<flags>with_getbymember</flags> <flags>own with_getbymember</flags>
</member> </member>
<member name="description" type="char_ptr" maxlen="256"> <member name="description" type="char_ptr" maxlen="256">
<default>0</default> <default>0</default>
<preset>0</preset> <preset>0</preset>
<access>public</access> <access>public</access>
<flags></flags> <flags>own</flags>
</member> </member>
<member name="colour" type="uint32_t" maxlen="8"> <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) void AQH_Storage_HandleMqttPublish(AQH_STORAGE *sto, const char *topic, const char *value)
{ {
/* TODO */ /* TODO */
@@ -216,7 +247,10 @@ int AQH_Storage_Init(AQH_STORAGE *sto)
int rv; int rv;
rv=GWEN_Directory_GetPath(sto->stateFile, 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) { if (rv==0) {
rv=AQH_Storage_ReadStateFile(sto, sto->stateFile); rv=AQH_Storage_ReadStateFile(sto, sto->stateFile);
if (rv<0) { if (rv<0) {
@@ -225,7 +259,7 @@ int AQH_Storage_Init(AQH_STORAGE *sto)
} }
} }
else { 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; return 0;
@@ -242,7 +276,7 @@ int AQH_Storage_WriteState(AQH_STORAGE *sto)
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv); DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
return rv; return rv;
} }
sto->runtimeFlags&=~AQH_STORAGE_RTFLAGS_MODIFIED;
return 0; return 0;
} }

View File

@@ -34,6 +34,9 @@ typedef struct AQH_STORAGE AQH_STORAGE;
#include "aqhome/data/datapoint.h" #include "aqhome/data/datapoint.h"
#define AQH_STORAGE_RTFLAGS_MODIFIED 0x0001
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { 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 const char *AQH_Storage_GetStateFile(const AQH_STORAGE *sto);
AQHOME_API void AQH_Storage_SetStateFile(AQH_STORAGE *sto, const char *s); 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_Init(AQH_STORAGE *sto);
AQHOME_API int AQH_Storage_WriteState(AQH_STORAGE *sto); AQHOME_API int AQH_Storage_WriteState(AQH_STORAGE *sto);

View File

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

View File

@@ -57,6 +57,8 @@ int AQH_Storage_ReadStateFile(AQH_STORAGE *sto, const char *sFilename)
_readTopicsFromXml(sto, rootNode); _readTopicsFromXml(sto, rootNode);
_readValuesFromXml(sto, rootNode); _readValuesFromXml(sto, rootNode);
GWEN_XMLNode_free(rootNode);
return 0; 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); 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) { while(elem) {
GWEN_XMLNODE *nElem; GWEN_XMLNODE *nElem;

View File

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

View File

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

View File

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

View File

@@ -18,6 +18,7 @@
#include <gwenhywfar/buffer.h> #include <gwenhywfar/buffer.h>
#include <gwenhywfar/text.h> #include <gwenhywfar/text.h>
#include <gwenhywfar/debug.h> #include <gwenhywfar/debug.h>
#include <gwenhywfar/directory.h>
#include <stdio.h> #include <stdio.h>
#include <errno.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 *_getModuleFilePath(const AQH_SERVICE *sv, const char *modName);
static GWEN_BUFFER *_getUserFilePath(const AQH_SERVICE *sv, const char *userAlias); 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 *_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 _checkUser(const AQH_USER *user, int ignoreMissingId);
static int _checkSession(const AQH_SESSION *session); static int _checkSession(const AQH_SESSION *session);
static int _checkModule(const AQH_MODULE *m, int ignoreMissingId); static int _checkModule(const AQH_MODULE *m, int ignoreMissingId);
static int _checkRoleList(const AQH_ROLE_LIST *roleList, int ignoreMissingId); static int _checkRoleList(const AQH_ROLE_LIST *roleList, int ignoreMissingId);
static int _writeDbFile(const char *fname, GWEN_DB_NODE *db); 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; GWEN_BUFFER *nameBuf;
int rv; int rv;
GWEN_DB_NODE *db;
AQH_SESSION *session; AQH_SESSION *session;
db=GWEN_DB_Group_new("user");
nameBuf=_getSessionFilePath(sv, sessionUid); nameBuf=_getSessionFilePath(sv, sessionUid);
rv=GWEN_DB_ReadFile(db, GWEN_Buffer_GetStart(nameBuf), GWEN_DB_FLAGS_DEFAULT); if (nameBuf==NULL) {
if (rv<0) { DBG_INFO(AQH_LOGDOMAIN, "here");
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv); 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_Buffer_free(nameBuf);
GWEN_DB_Group_free(db);
return NULL; return NULL;
} }
GWEN_Buffer_free(nameBuf); 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); rv=_checkSession(session);
if (rv<0) { if (rv<0) {
DBG_INFO(AQH_LOGDOMAIN, "Invalid data for session \"%s\"", sessionUid); 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); AQH_Session_free(session);
return NULL; return NULL;
} }
AQH_User_Attach(user);
AQH_Session_SetUser(session, user); AQH_Session_SetUser(session, user);
AQH_Service_AddSession(sv, session); 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) GWEN_BUFFER *_getSessionFilePath(const AQH_SERVICE *sv, const char *sessionUid)
{ {
const char *configFolder; GWEN_BUFFER *nameBuf;
configFolder=AQH_HttpService_GetConfigFolder(sv); nameBuf=_getSessionFolder(sv);
if (!(configFolder && *configFolder)) { if (nameBuf) {
DBG_ERROR(AQH_LOGDOMAIN, "No config folder given"); GWEN_Buffer_AppendString(nameBuf, GWEN_DIR_SEPARATOR_S);
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);
GWEN_Text_EscapeToBuffer(sessionUid, nameBuf); GWEN_Text_EscapeToBuffer(sessionUid, nameBuf);
GWEN_Buffer_AppendString(nameBuf, ".conf"); GWEN_Buffer_AppendString(nameBuf, ".conf");
return nameBuf; 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 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 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 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); 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_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_AddSession(AQH_SERVICE *sv, AQH_SESSION *session);
AQHOME_API int AQH_HttpService_DelSession(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 #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); DBG_INFO(AQH_LOGDOMAIN, "Session \"%s\" not found", s);
} }
else { else {
GWEN_TIMESTAMP *ts;
DBG_INFO(AQH_LOGDOMAIN, "Found session \"%s\"", s); 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); AQH_HttpRequest_SetSession(rq, session);
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

16
vg_aqhomed.sh Executable file
View File

@@ -0,0 +1,16 @@
#!/bin/bash
export AQHOME_LOGLEVEL=info
export LD_LIBRARY_PATH="0-build/aqhome/:$LD_LIBRARY_PATH"
valgrind \
--tool=memcheck --trace-children=yes -v --log-file=aqhomed.vg --leak-check=full --show-reachable=yes \
--track-origins=yes --num-callers=50 --keep-stacktraces=alloc-and-free \
0-build/apps/aqhomed/aqhomed \
-l aqhome.log \
-db aqhome.db \
-ma 192.168.117.192 -mp 1883 --mqttclientid=AQHOMELOGTEST \
-t 127.0.0.1 \
--pidfile=./aqhomed.pid \
-T 300

18
vg_mqttlog.sh Executable file
View File

@@ -0,0 +1,18 @@
#!/bin/bash
export AQHOME_LOGLEVEL=info
export LD_LIBRARY_PATH="0-build/aqhome/:$LD_LIBRARY_PATH"
# valgrind --tool=memcheck --trace-children=yes -v --log-file=aqf15 --leak-check=full --show-reachable=yes --track-origins=yes --num-callers=50 --keep-stacktraces=alloc-and-free --suppressions=../../../../debug/valgrind.supp /usr/local/bin/aqfinance
# valgrind --tool=memcheck --trace-children=yes -v --log-file=aqhomed.vg --leak-check=full --show-reachable=yes --track-origins=yes --num-callers=50 --keep-stacktraces=alloc-and-free 0-build/apps/aqhomed/aqhomed -l aqhome.log -db aqhome.db -ma 192.168.117.192 -mp 1883 -t 127.0.0.1 -T 300
valgrind \
--tool=memcheck --trace-children=yes -v --log-file=aqhome-mqttlog.vg --leak-check=full --show-reachable=yes \
--track-origins=yes --num-callers=50 --keep-stacktraces=alloc-and-free \
0-build/apps/aqhome-mqttlog/aqhome-mqttlog \
-ma 192.168.117.192 -mp 1883 --mqttclientid=AQHOMEMQTTLOGTEST \
-W /tmp/aqhome/mqttlog \
-i apps/aqhome-mqttlog/mqttlog.conf \
-T 30

21
vg_storage.sh Executable file
View File

@@ -0,0 +1,21 @@
#!/bin/bash
export AQHOME_LOGLEVEL=info
export LD_LIBRARY_PATH="0-build/aqhome/:$LD_LIBRARY_PATH"
# valgrind --tool=memcheck --trace-children=yes -v --log-file=aqf15 --leak-check=full --show-reachable=yes --track-origins=yes --num-callers=50 --keep-stacktraces=alloc-and-free --suppressions=../../../../debug/valgrind.supp /usr/local/bin/aqfinance
# valgrind --tool=memcheck --trace-children=yes -v --log-file=aqhomed.vg --leak-check=full --show-reachable=yes --track-origins=yes --num-callers=50 --keep-stacktraces=alloc-and-free 0-build/apps/aqhomed/aqhomed -l aqhome.log -db aqhome.db -ma 192.168.117.192 -mp 1883 -t 127.0.0.1 -T 300
valgrind \
--tool=memcheck --trace-children=yes -v --log-file=aqhome-storage.vg --leak-check=full --show-reachable=yes \
--track-origins=yes --num-callers=50 --keep-stacktraces=alloc-and-free \
0-build/apps/aqhome-storage/aqhome-storage \
--sourcefolder=apps/aqhome-storage/test/html \
-D apps/aqhome-storage/test/config \
--statefile=apps/aqhome-storage/test/config/state \
-ma 192.168.117.192 -mp 1883 --mqttclientid=AQHOMESTORAGEVG \
-ha 127.0.0.1 -hp 1884 \
-p ./aqhome-storage.pid \
-T 90