/**************************************************************************** * 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 "./init_http.h" #include "./aqhomestorage_p.h" #include "./aqhomehttp.h" #include "./u_login.h" #include "./u_rooms.h" #include "./u_devices.h" #include "./u_mqtttopics.h" #include "./u_values.h" #include "./u_static.h" #include "aqhome/msg/endpoint_tty.h" #include "aqhome/ipc/endpoint_ipc.h" #include "aqhome/mqtt/endpoint_mqttc.h" #include "aqhome/http/endpoint_http.h" #include "aqhome/http/httpservice_conf.h" #include "aqhome/http/httpservice_http.h" #include "aqhome/http/httpservice.h" #include "aqhome/http/content_files.h" #include #include #include #include #include #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #include #include #include #include #include #include /* ------------------------------------------------------------------------------------------------ * defines * ------------------------------------------------------------------------------------------------ */ //#define I18N(msg) msg #define I18S(msg) msg /* ------------------------------------------------------------------------------------------------ * forward declarations * ------------------------------------------------------------------------------------------------ */ static void _setupEndpoint(AQHOME_STORAGE *aqh, const char *tcpAddress, int tcpPort); static int _setupHttpService(AQHOME_STORAGE *aqh, GWEN_DB_NODE *dbArgs); static int _createContentRoot(AQHOME_STORAGE *aqh); static GWEN_MSG_ENDPOINT *_acceptHttpFn(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKET *sk, const GWEN_INETADDRESS *addr, void *data); static int _createUrlHandler_login(AQHOME_STORAGE *aqh); static int _createUrlHandler_rooms(AQHOME_STORAGE *aqh); static int _createUrlHandler_devices(AQHOME_STORAGE *aqh); static int _createUrlHandler_topics(AQHOME_STORAGE *aqh); static int _createUrlHandler_values(AQHOME_STORAGE *aqh); static int _createUrlHandler_static(AQHOME_STORAGE *aqh); /* ------------------------------------------------------------------------------------------------ * implementations * ------------------------------------------------------------------------------------------------ */ int AqHomeStorage_SetupHttp(AQHOME_STORAGE *aqh, GWEN_DB_NODE *dbArgs) { const char *tcpAddress; int tcpPort; tcpAddress=GWEN_DB_GetCharValue(dbArgs, "httpAddress", 0, NULL); tcpPort=GWEN_DB_GetIntValue(dbArgs, "httpPort", 0, AQHOME_STORAGE_DEFAULT_HTTP_PORT); if (tcpAddress && *tcpAddress && tcpPort) { int rv; _setupEndpoint(aqh, tcpAddress, tcpPort); rv=_setupHttpService(aqh, dbArgs); if (rv<0) { DBG_INFO(NULL, "here (%d)", rv); return rv; } rv=_createContentRoot(aqh); if (rv<0) { DBG_INFO(NULL, "here (%d)", rv); return rv; } rv=_createUrlHandler_login(aqh); if (rv<0) { DBG_INFO(NULL, "here (%d)", rv); return rv; } rv=_createUrlHandler_rooms(aqh); if (rv<0) { DBG_INFO(NULL, "here (%d)", rv); return rv; } rv=_createUrlHandler_devices(aqh); if (rv<0) { DBG_INFO(NULL, "here (%d)", rv); return rv; } rv=_createUrlHandler_topics(aqh); if (rv<0) { DBG_INFO(NULL, "here (%d)", rv); return rv; } rv=_createUrlHandler_values(aqh); if (rv<0) { DBG_INFO(NULL, "here (%d)", rv); return rv; } rv=_createUrlHandler_static(aqh); if (rv<0) { DBG_INFO(NULL, "here (%d)", rv); return rv; } } return 0; } void _setupEndpoint(AQHOME_STORAGE *aqh, const char *tcpAddress, int tcpPort) { GWEN_MSG_ENDPOINT *ep; ep=GWEN_TcpdEndpoint_new(tcpAddress, tcpPort, NULL, 0); GWEN_TcpdEndpoint_SetAcceptFn(ep, _acceptHttpFn, aqh); GWEN_MsgEndpoint_Tree2_AddChild(aqh->rootEndpoint, ep); aqh->httpdEndpoint=ep; } int _setupHttpService(AQHOME_STORAGE *aqh, GWEN_DB_NODE *dbArgs) { const char *configFolder; const char *sourceFolder; int rv; configFolder=GWEN_DB_GetCharValue(dbArgs, "cfgdir", 0, AQHOME_STORAGE_DEFAULT_CONFIGDIR); sourceFolder=GWEN_DB_GetCharValue(dbArgs, "sourceFolder", 0, AQHOME_STORAGE_DEFAULT_HTTP_SOURCEDIR); aqh->httpService=AQH_HttpService_new(configFolder, sourceFolder); AqHomeHttpService_Extend(aqh->httpService); AqHomeHttpService_SetStorage(aqh->httpService, aqh->storage); rv=AQH_HttpService_LoadConfig(aqh->httpService); if (rv<0) { DBG_ERROR(NULL, "Error loading config for HTTP service (%d)", rv); return GWEN_ERROR_GENERIC; } AQH_HttpService_LoadAllSessions(aqh->httpService); return 0; } GWEN_MSG_ENDPOINT *_acceptHttpFn(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKET *sk, const GWEN_INETADDRESS *addr, GWEN_UNUSED void *data) { GWEN_MSG_ENDPOINT *epIncoming; /* AQHOME_STORAGE *aqh; * * aqh=(AQHOME_STORAGE*) data; */ DBG_INFO(NULL, "Incoming HTTP connection"); epIncoming=GWEN_MsgEndpoint_new("http", 0); GWEN_MsgEndpoint_SetSocket(epIncoming, sk); GWEN_MsgIoEndpoint_Extend(epIncoming); AQH_HttpEndpoint_Extend(epIncoming, AQH_ENDPOINT_HTTP_FLAGS_PASSIVE); return epIncoming; } int _createContentRoot(AQHOME_STORAGE *aqh) { const char *sourceFolder; GWEN_BUFFER *nbuf1; GWEN_BUFFER *nbuf2; AQH_HTTP_CONTENT *c; sourceFolder=AQH_HttpService_GetSourceFolder(aqh->httpService); nbuf1=GWEN_Buffer_new(0, 256, 0, 1); nbuf2=GWEN_Buffer_new(0, 256, 0, 1); GWEN_Buffer_AppendString(nbuf1, sourceFolder); GWEN_Buffer_AppendString(nbuf1, GWEN_DIR_SEPARATOR_S AQHOME_STORAGE_SITEHEADER); GWEN_Buffer_AppendString(nbuf2, sourceFolder); GWEN_Buffer_AppendString(nbuf2, GWEN_DIR_SEPARATOR_S AQHOME_STORAGE_SITEFOOTER); c=AQH_HttpContentFiles_new("root", GWEN_Buffer_GetStart(nbuf1), GWEN_Buffer_GetStart(nbuf2)); if (c==NULL) { DBG_INFO(NULL, "Unable to create content for root (header=[%s], footer=[%s])", GWEN_Buffer_GetStart(nbuf1), GWEN_Buffer_GetStart(nbuf2)); GWEN_Buffer_free(nbuf2); GWEN_Buffer_free(nbuf1); return GWEN_ERROR_GENERIC; } AqHomeHttpService_SetContentTree(aqh->httpService, c); GWEN_Buffer_free(nbuf2); GWEN_Buffer_free(nbuf1); return 0; } int _createUrlHandler_login(AQHOME_STORAGE *aqh) { AQH_HTTP_URLHANDLER *uh; uh=AQH_LoginHttpUrlHandler_new(aqh->httpService); AQH_HttpUrlHandler_SetContentProvider(uh, AqHomeHttpService_GetContentTree(aqh->httpService)); AQH_HttpUrlHandler_AddUrlPattern(uh, "/login"); AQH_HttpService_AddUrlHandler(aqh->httpService, uh); return 0; } int _createUrlHandler_rooms(AQHOME_STORAGE *aqh) { AQH_HTTP_URLHANDLER *uh; uh=AQH_RoomsHttpUrlHandler_new(aqh->httpService); AQH_HttpUrlHandler_SetContentProvider(uh, AqHomeHttpService_GetContentTree(aqh->httpService)); AQH_HttpUrlHandler_AddUrlPattern(uh, "/rooms/*"); AQH_HttpService_AddUrlHandler(aqh->httpService, uh); return 0; } int _createUrlHandler_devices(AQHOME_STORAGE *aqh) { AQH_HTTP_URLHANDLER *uh; uh=AQH_DevicesHttpUrlHandler_new(aqh->httpService); AQH_HttpUrlHandler_SetContentProvider(uh, AqHomeHttpService_GetContentTree(aqh->httpService)); AQH_HttpUrlHandler_AddUrlPattern(uh, "/devices/*"); AQH_HttpService_AddUrlHandler(aqh->httpService, uh); return 0; } int _createUrlHandler_topics(AQHOME_STORAGE *aqh) { AQH_HTTP_URLHANDLER *uh; uh=AQH_MqttTopicsHttpUrlHandler_new(aqh->httpService); AQH_HttpUrlHandler_SetContentProvider(uh, AqHomeHttpService_GetContentTree(aqh->httpService)); AQH_HttpUrlHandler_AddUrlPattern(uh, "/mqtttopics/*"); AQH_HttpService_AddUrlHandler(aqh->httpService, uh); return 0; } int _createUrlHandler_values(AQHOME_STORAGE *aqh) { AQH_HTTP_URLHANDLER *uh; uh=AQH_ValuesHttpUrlHandler_new(aqh->httpService); AQH_HttpUrlHandler_SetContentProvider(uh, AqHomeHttpService_GetContentTree(aqh->httpService)); AQH_HttpUrlHandler_AddUrlPattern(uh, "/values/*"); AQH_HttpService_AddUrlHandler(aqh->httpService, uh); return 0; } int _createUrlHandler_static(AQHOME_STORAGE *aqh) { AQH_HTTP_URLHANDLER *uh; GWEN_BUFFER *nameBuf; const char *sourceFolder; sourceFolder=AQH_HttpService_GetSourceFolder(aqh->httpService); nameBuf=GWEN_Buffer_new(0, 256, 0, 1); GWEN_Buffer_AppendString(nameBuf, sourceFolder); GWEN_Buffer_AppendString(nameBuf, GWEN_DIR_SEPARATOR_S AQHOME_STORAGE_STATIC_RELFOLDER GWEN_DIR_SEPARATOR_S "pics"); uh=AQH_StaticHttpUrlHandler_new(aqh->httpService, GWEN_Buffer_GetStart(nameBuf)); GWEN_Buffer_free(nameBuf); AQH_HttpUrlHandler_AddUrlPattern(uh, "/pics/*"); AQH_HttpService_AddUrlHandler(aqh->httpService, uh); return 0; }