269 lines
5.6 KiB
C
269 lines
5.6 KiB
C
/****************************************************************************
|
|
* This file is part of the project AqHome.
|
|
* AqHome (c) by 2023 Martin Preuss, all rights reserved.
|
|
*
|
|
* The license for this file can be found in the file COPYING which you
|
|
* should have received along with this file.
|
|
****************************************************************************/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#endif
|
|
|
|
#include <aqhome/api.h>
|
|
#include <aqhome/aqhome.h>
|
|
|
|
#include "./server.h"
|
|
|
|
#include <gwenhywfar/gwenhywfar.h>
|
|
#include <gwenhywfar/logger.h>
|
|
#include <gwenhywfar/cgui.h>
|
|
#include <gwenhywfar/debug.h>
|
|
|
|
#ifdef HAVE_SIGNAL_H
|
|
# include <signal.h>
|
|
#endif
|
|
|
|
|
|
#define DISABLE_DEBUGLOG
|
|
|
|
|
|
//#define WRITE_INTERVAL_IN_SECS (5*60)
|
|
|
|
#define WRITE_INTERVAL_IN_SECS 60
|
|
#define PING_INTERVAL 120
|
|
#define CONNCLEAN_INTERVAL_IN_SECS 10
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------
|
|
* defines
|
|
* ------------------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------
|
|
* forward declarations
|
|
* ------------------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
#ifdef HAVE_SIGNAL_H
|
|
static int _setSignalHandlers(void);
|
|
static int _setupSigAction(struct sigaction *sa, int sig);
|
|
static void _signalHandler(int s);
|
|
#endif
|
|
|
|
static void _runService(AQH_OBJECT *aqh, AQH_EVENT_LOOP *eventLoop);
|
|
static void _writeCurrentState(AQH_OBJECT *aqh);
|
|
static int _diffInSeconds(time_t t1, time_t t0);
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------
|
|
* static vars
|
|
* ------------------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
#ifdef HAVE_SIGNAL_H
|
|
static struct sigaction saINT,saTERM, saHUP, saTSTP, saCONT, saPIPE;
|
|
#endif
|
|
|
|
static int stopService=0;
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------
|
|
* implementations
|
|
* ------------------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
int rv;
|
|
AQH_EVENT_LOOP *eventLoop;
|
|
AQH_OBJECT *aqh;
|
|
GWEN_GUI *gui;
|
|
|
|
rv=GWEN_Init();
|
|
if (rv) {
|
|
fprintf(stderr, "ERROR: Unable to init Gwen.\n");
|
|
return 2;
|
|
}
|
|
|
|
GWEN_Logger_Open(0, "aqhome-data", 0, GWEN_LoggerType_Console, GWEN_LoggerFacility_User);
|
|
GWEN_Logger_SetLevel(0, GWEN_LoggerLevel_Warning);
|
|
|
|
rv=_setSignalHandlers();
|
|
if (rv<0) {
|
|
DBG_INFO(NULL, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
|
|
rv=AQH_Init();
|
|
if (rv<0) {
|
|
DBG_INFO(NULL, "here (%d)", rv);
|
|
return 2;
|
|
}
|
|
|
|
gui=GWEN_Gui_CGui_new();
|
|
GWEN_Gui_SetGui(gui);
|
|
|
|
eventLoop=AQH_EventLoop_new();
|
|
aqh=AqHomeDataServer_new(eventLoop);
|
|
rv=AqHomeDataServer_Init(aqh, argc, argv);
|
|
if (rv<0) {
|
|
DBG_INFO(NULL, "here (%d)", rv);
|
|
return 2;
|
|
}
|
|
|
|
_runService(aqh, eventLoop);
|
|
|
|
AqHomeDataServer_Fini(aqh);
|
|
AQH_Object_free(aqh);
|
|
AQH_EventLoop_free(eventLoop);
|
|
|
|
GWEN_Gui_SetGui(NULL);
|
|
GWEN_Gui_free(gui);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
void _runService(AQH_OBJECT *aqh, AQH_EVENT_LOOP *eventLoop)
|
|
{
|
|
time_t timeStart;
|
|
time_t timeLastWrite;
|
|
time_t timeLastConnectionCleanup;
|
|
int timeout;
|
|
|
|
timeout=AqHomeDataServer_GetTimeout(aqh);
|
|
timeStart=time(NULL);
|
|
timeLastWrite=time(NULL);
|
|
timeLastConnectionCleanup=time(NULL);
|
|
|
|
while(!stopService) {
|
|
time_t now;
|
|
|
|
DBG_INFO(NULL, "Next loop (%d clients)", AqHomeDataServer_GetClientNum(aqh));
|
|
AQH_EventLoop_Run(eventLoop, 2000);
|
|
AqHomeDataServer_HandleClientMsgs(aqh);
|
|
|
|
now=time(NULL);
|
|
|
|
if (_diffInSeconds(now, timeLastConnectionCleanup)>CONNCLEAN_INTERVAL_IN_SECS) {
|
|
DBG_INFO(NULL, "Cleanup connections");
|
|
AqHomeDataServer_CleanupClients(aqh);
|
|
timeLastConnectionCleanup=now;
|
|
}
|
|
|
|
if (_diffInSeconds(now, timeLastWrite)>WRITE_INTERVAL_IN_SECS) {
|
|
DBG_INFO(NULL, "Write time");
|
|
_writeCurrentState(aqh);
|
|
timeLastWrite=now;
|
|
}
|
|
|
|
if (timeout && (_diffInSeconds(now, timeStart)>timeout)) {
|
|
DBG_ERROR(NULL, "Timeout");
|
|
_writeCurrentState(aqh);
|
|
break;
|
|
}
|
|
} /* while */
|
|
}
|
|
|
|
|
|
|
|
int _diffInSeconds(time_t t1, time_t t0)
|
|
{
|
|
return t1-t0;
|
|
}
|
|
|
|
|
|
void _writeCurrentState(AQH_OBJECT *aqh)
|
|
{
|
|
int rv;
|
|
|
|
rv=AqHomeDataServer_WriteStorageIfChanged(aqh);
|
|
if (rv<0) {
|
|
DBG_ERROR(NULL, "ATTENTION: Could not write storage statefile (%d)", rv);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
int _setSignalHandlers(void)
|
|
{
|
|
#ifdef HAVE_SIGNAL_H
|
|
int rv;
|
|
|
|
rv=_setupSigAction(&saINT, SIGINT);
|
|
if (rv)
|
|
return rv;
|
|
|
|
rv=_setupSigAction(&saTERM, SIGTERM);
|
|
if (rv)
|
|
return rv;
|
|
|
|
rv=_setupSigAction(&saHUP, SIGHUP);
|
|
if (rv)
|
|
return rv;
|
|
|
|
rv=_setupSigAction(&saPIPE, SIGPIPE);
|
|
if (rv)
|
|
return rv;
|
|
|
|
# ifdef SIGTSTP
|
|
rv=_setupSigAction(&saTSTP, SIGTSTP);
|
|
if (rv)
|
|
return rv;
|
|
# endif
|
|
|
|
# ifdef SIGCONT
|
|
rv=_setupSigAction(&saCONT, SIGCONT);
|
|
if (rv)
|
|
return rv;
|
|
# endif
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int _setupSigAction(struct sigaction *sa, int sig)
|
|
{
|
|
sa->sa_handler=_signalHandler;
|
|
sigemptyset(&sa->sa_mask);
|
|
sa->sa_flags=0;
|
|
if (sigaction(sig, sa, 0)) {
|
|
DBG_ERROR(NULL, "Could not setup signal handler for signal %d", sig);
|
|
return GWEN_ERROR_IO;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
void _signalHandler(int s)
|
|
{
|
|
switch(s) {
|
|
case SIGINT:
|
|
case SIGTERM:
|
|
case SIGHUP:
|
|
DBG_WARN(0, "Received signal %d, stopping service in next loop.",s);
|
|
stopService=1;
|
|
break;
|
|
case SIGPIPE:
|
|
DBG_WARN(0, "Received PIPE signal");
|
|
break;
|
|
default:
|
|
DBG_WARN(0, "Unknown signal %d",s);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|