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

@@ -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;
}