diff --git a/apps/aqhome-storage/0BUILD b/apps/aqhome-storage/0BUILD index 66a4e77..dd8fe00 100644 --- a/apps/aqhome-storage/0BUILD +++ b/apps/aqhome-storage/0BUILD @@ -39,6 +39,8 @@ aqhomestorage.h init.h http.h + aqhomehttp.h + aqhomehttp_p.h @@ -48,6 +50,7 @@ init.c http.c main.c + aqhomehttp.c diff --git a/apps/aqhome-storage/aqhomehttp.c b/apps/aqhome-storage/aqhomehttp.c new file mode 100644 index 0000000..3253b77 --- /dev/null +++ b/apps/aqhome-storage/aqhomehttp.c @@ -0,0 +1,306 @@ +/**************************************************************************** + * 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 +#endif + + +#include "./aqhomehttp_p.h" +#include "aqhome/http/httpservice.h" +#include "aqhome/http/httpservice_http.h" + +#include +#include +#include +#include + + + +GWEN_INHERIT(AQH_SERVICE, AQHOME_HTTP) + + + +/* ------------------------------------------------------------------------------------------------ + * forward declarations + * ------------------------------------------------------------------------------------------------ + */ + +static void GWENHYWFAR_CB _freeData(void *bp, void *p); +static int _handleUrl(AQH_SERVICE *sv, AQH_HTTP_REQUEST *rq); +static int _handleUrl_login(AQH_SERVICE *sv, AQH_HTTP_REQUEST *rq); +static GWEN_MSG *_createResponseMsg(AQH_SERVICE *sv, int code, const char *text, const char *protocol, const char *page); +static void _writeDefaultResponseHeaderToBuffer(AQH_SERVICE *sv, int contentLength, GWEN_BUFFER *buf); + + + +/* ------------------------------------------------------------------------------------------------ + * implementations + * ------------------------------------------------------------------------------------------------ + */ + +void AqHomeHttpService_Extend(AQH_SERVICE *sv) +{ + AQHOME_HTTP *xsv; + + GWEN_NEW_OBJECT(AQHOME_HTTP, xsv); + GWEN_INHERIT_SETDATA(AQH_SERVICE, AQHOME_HTTP, sv, xsv, _freeData); + + AQH_HttpService_SetHandleRequestFn(sv, _handleUrl); +} + + + +void _freeData(void *bp, void *p) +{ + AQHOME_HTTP *xsv; + + xsv=(AQHOME_HTTP*) p; + + AQH_Storage_free(xsv->storage); + xsv->storage=NULL; + GWEN_MsgEndpoint_free(xsv->rootEndpoint); + xsv->rootEndpoint=NULL; + xsv->ipcdEndpoint=NULL; + xsv->mqttEndpoint=NULL; + xsv->httpdEndpoint=NULL; + GWEN_DB_Group_free(xsv->dbArgs); + xsv->dbArgs=NULL; + free(xsv->pidFile); + + GWEN_FREE_OBJECT(xsv); +} + + + +GWEN_DB_NODE *AqHomeHttpService_GetDbArgs(const AQH_SERVICE *sv) +{ + if (sv) { + AQHOME_HTTP *xsv; + + xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQHOME_HTTP, sv); + if (xsv) + return xsv->dbArgs; + } + return NULL; +} + + + +const char *AqHomeHttpService_GetPidFile(const AQH_SERVICE *sv) +{ + if (sv) { + AQHOME_HTTP *xsv; + + xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQHOME_HTTP, sv); + if (xsv) + return xsv->pidFile; + } + return NULL; +} + + + +void AqHomeHttpService_SetPidFile(AQH_SERVICE *sv, const char *s) +{ + if (sv) { + AQHOME_HTTP *xsv; + + xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQHOME_HTTP, sv); + if (xsv) { + free(xsv->pidFile); + xsv->pidFile=s?strdup(s):NULL; + } + } +} + + + + +GWEN_MSG_ENDPOINT *AqHomeHttpService_GetRootEndpoint(const AQH_SERVICE *sv) +{ + if (sv) { + AQHOME_HTTP *xsv; + + xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQHOME_HTTP, sv); + if (xsv) + return xsv->rootEndpoint; + } + return NULL; +} + + + +GWEN_MSG_ENDPOINT *AqHomeHttpService_GetIpcdEndpoint(const AQH_SERVICE *sv) +{ + if (sv) { + AQHOME_HTTP *xsv; + + xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQHOME_HTTP, sv); + if (xsv) + return xsv->ipcdEndpoint; + } + return NULL; +} + + + +GWEN_MSG_ENDPOINT *AqHomeHttpService_GetMqttEndpoint(const AQH_SERVICE *sv) +{ + if (sv) { + AQHOME_HTTP *xsv; + + xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQHOME_HTTP, sv); + if (xsv) + return xsv->mqttEndpoint; + } + return NULL; +} + + + +GWEN_MSG_ENDPOINT *AqHomeHttpService_GetHttpdEndpoint(const AQH_SERVICE *sv) +{ + if (sv) { + AQHOME_HTTP *xsv; + + xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQHOME_HTTP, sv); + if (xsv) + return xsv->httpdEndpoint; + } + return NULL; +} + + + +AQH_STORAGE *AqHomeHttpService_GetStorage(const AQH_SERVICE *sv) +{ + if (sv) { + AQHOME_HTTP *xsv; + + xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQHOME_HTTP, sv); + if (xsv) + return xsv->storage; + } + return NULL; +} + + + + + + + + +int _handleUrl(AQH_SERVICE *sv, AQH_HTTP_REQUEST *rq) +{ + + const GWEN_URL *url; + const char *sPath; + + url=AQH_HttpRequest_GetUrl(rq); + + sPath=GWEN_Url_GetPath(url); + if (strcasecmp(sPath, "/login")==0) + return _handleUrl_login(sv, rq); + else { + DBG_ERROR(NULL, "Invalid URL [%s]", sPath); + return GWEN_ERROR_INVALID; + } +} + + + +int _handleUrl_login(AQH_SERVICE *sv, AQH_HTTP_REQUEST *rq) +{ + const char *protocol; + const char *cmd; + AQH_SESSION *session; + GWEN_MSG *msgOut=NULL; + + protocol=AQH_HttpRequest_GetProtocol(rq); + session=AQH_HttpRequest_GetSession(rq); + cmd=AQH_HttpRequest_GetCommand(rq); + if (cmd && strcasecmp(cmd, "GET")==0) { + GWEN_BUFFER *pageBuf; + const char *s; + int rv; + + pageBuf=GWEN_Buffer_new(0, 256, 0, 1); + s=AQH_HttpService_GetSiteHeader(sv); + if (s) + GWEN_Buffer_AppendString(pageBuf, s); + + rv=AQH_HttpService_AddFile(sv, session, "login.html", pageBuf); + if (rv<0) { + DBG_ERROR(AQH_LOGDOMAIN, "Error reading file \"login.html\""); + GWEN_Buffer_free(pageBuf); + msgOut=_createResponseMsg(sv, 500, "Internal Error", protocol, NULL); + AQH_HttpRequest_SetResponseMsg(rq, msgOut); + return 0; + } + + s=AQH_HttpService_GetSiteFooter(sv); + if (s) + GWEN_Buffer_AppendString(pageBuf, s); + + msgOut=_createResponseMsg(sv, 200, "OK", protocol, GWEN_Buffer_GetStart(pageBuf)); + GWEN_Buffer_free(pageBuf); + AQH_HttpRequest_SetResponseMsg(rq, msgOut); + return 0; + } + else { + msgOut=_createResponseMsg(sv, 501, "Not (yet) implemented", protocol, NULL); + AQH_HttpRequest_SetResponseMsg(rq, msgOut); + return 0; + } +} + + + + + + +GWEN_MSG *_createResponseMsg(AQH_SERVICE *sv, int code, const char *text, const char *protocol, const char *page) +{ + GWEN_BUFFER *buf; + GWEN_MSG *msg; + + buf=GWEN_Buffer_new(0, 256, 0, 1); + AQH_HttpService_AddStatusLine(sv, code, text, protocol, buf); + _writeDefaultResponseHeaderToBuffer(sv, (page && *page)?strlen(page):0, buf); + if (page && *page) + GWEN_Buffer_AppendString(buf, page); + + msg=GWEN_Msg_fromBytes((const uint8_t*)GWEN_Buffer_GetStart(buf), GWEN_Buffer_GetUsedBytes(buf)); + GWEN_Buffer_free(buf); + return msg; +} + + + +void _writeDefaultResponseHeaderToBuffer(AQH_SERVICE *sv, int contentLength, GWEN_BUFFER *buf) +{ + GWEN_DB_NODE *db; + + db=GWEN_DB_Group_new("header"); + GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "Connection", "Keep-Alive"); + GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "Content-Type", "text/html; charset=utf-8"); + GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "Content-Length", contentLength); + + AQH_HttpService_AddHeader(sv, db, buf); + GWEN_DB_Group_free(db); +} + + + + + + + + diff --git a/apps/aqhome-storage/aqhomehttp.h b/apps/aqhome-storage/aqhomehttp.h new file mode 100644 index 0000000..726e020 --- /dev/null +++ b/apps/aqhome-storage/aqhomehttp.h @@ -0,0 +1,41 @@ +/**************************************************************************** + * 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_HTTP_H +#define AQHOME_HTTP_H + + +#include "aqhome/service/service.h" +#include "aqhome/data/storage.h" + +#include + + +void AqHomeHttpService_Extend(AQH_SERVICE *sv); + +GWEN_MSG_ENDPOINT *AqHomeHttpService_GetRootEndpoint(const AQH_SERVICE *sv); +GWEN_MSG_ENDPOINT *AqHomeHttpService_GetIpcdEndpoint(const AQH_SERVICE *sv); +GWEN_MSG_ENDPOINT *AqHomeHttpService_GetMqttEndpoint(const AQH_SERVICE *sv); +GWEN_MSG_ENDPOINT *AqHomeHttpService_GetHttpdEndpoint(const AQH_SERVICE *sv); + +AQH_STORAGE *AqHomeHttpService_GetStorage(const AQH_SERVICE *sv); + +GWEN_DB_NODE *AqHomeHttpService_GetDbArgs(const AQH_SERVICE *sv); +const char *AqHomeHttpService_GetPidFile(const AQH_SERVICE *sv); +void AqHomeHttpService_SetPidFile(AQH_SERVICE *sv, const char *s); + + + + + + + + +#endif + + diff --git a/apps/aqhome-storage/aqhomehttp_p.h b/apps/aqhome-storage/aqhomehttp_p.h new file mode 100644 index 0000000..e046244 --- /dev/null +++ b/apps/aqhome-storage/aqhomehttp_p.h @@ -0,0 +1,35 @@ +/**************************************************************************** + * 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_HTTP_P_H +#define AQHOME_HTTP_P_H + + +#include "./aqhomehttp.h" + + +typedef struct AQHOME_HTTP AQHOME_HTTP; +struct AQHOME_HTTP { + GWEN_MSG_ENDPOINT *rootEndpoint; + + GWEN_MSG_ENDPOINT *ipcdEndpoint; + GWEN_MSG_ENDPOINT *mqttEndpoint; + GWEN_MSG_ENDPOINT *httpdEndpoint; + + AQH_STORAGE *storage; + + GWEN_DB_NODE *dbArgs; + + char *pidFile; +}; + + + +#endif + +