aqhome: more work on http service.
This commit is contained in:
@@ -25,9 +25,6 @@ GWEN_INHERIT(AQH_SERVICE, AQH_HTTP_SERVICE)
|
||||
|
||||
static void GWENHYWFAR_CB _freeData(void *bp, void *p);
|
||||
|
||||
static int _parsePostBody(const char *s, int contentLength, GWEN_DB_NODE *dbBody);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -37,6 +34,10 @@ void AQH_HttpService_Extend(AQH_SERVICE *sv)
|
||||
|
||||
GWEN_NEW_OBJECT(AQH_HTTP_SERVICE, xsv);
|
||||
GWEN_INHERIT_SETDATA(AQH_SERVICE, AQH_HTTP_SERVICE, sv, xsv, _freeData);
|
||||
|
||||
xsv->moduleMutex=GWEN_Mutex_new();
|
||||
xsv->userMutex=GWEN_Mutex_new();
|
||||
xsv->sessionMutex=GWEN_Mutex_new();
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +47,12 @@ void _freeData(void *bp, void *p)
|
||||
AQH_HTTP_SERVICE *xsv;
|
||||
|
||||
xsv=(AQH_HTTP_SERVICE*) p;
|
||||
|
||||
GWEN_Mutex_free(xsv->moduleMutex);
|
||||
GWEN_Mutex_free(xsv->userMutex);
|
||||
GWEN_Mutex_free(xsv->sessionMutex);
|
||||
|
||||
free(xsv->configFolder);
|
||||
free(xsv->sourceFolder);
|
||||
free(xsv->siteHeader);
|
||||
free(xsv->siteFooter);
|
||||
@@ -54,6 +61,54 @@ void _freeData(void *bp, void *p)
|
||||
|
||||
|
||||
|
||||
AQH_HTTP_SERVICE_HANDLEREQUEST_FN AQH_HttpService_SetHandleRequestFn(AQH_SERVICE *sv, AQH_HTTP_SERVICE_HANDLEREQUEST_FN fn)
|
||||
{
|
||||
if (sv) {
|
||||
AQH_HTTP_SERVICE *xsv;
|
||||
|
||||
xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_HTTP_SERVICE, sv);
|
||||
if (xsv) {
|
||||
AQH_HTTP_SERVICE_HANDLEREQUEST_FN oldFn;
|
||||
|
||||
oldFn=xsv->handleRequestFn;
|
||||
xsv->handleRequestFn=fn;
|
||||
return oldFn;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *AQH_HttpService_GetConfigFolder(const AQH_SERVICE *sv)
|
||||
{
|
||||
if (sv) {
|
||||
AQH_HTTP_SERVICE *xsv;
|
||||
|
||||
xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_HTTP_SERVICE, sv);
|
||||
if (xsv)
|
||||
return xsv->configFolder;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_HttpService_SetConfigFolder(AQH_SERVICE *sv, const char *s)
|
||||
{
|
||||
if (sv) {
|
||||
AQH_HTTP_SERVICE *xsv;
|
||||
|
||||
xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_HTTP_SERVICE, sv);
|
||||
if (xsv) {
|
||||
free(xsv->configFolder);
|
||||
xsv->configFolder=s?strdup(s):NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *AQH_HttpService_GetSourceFolder(const AQH_SERVICE *sv)
|
||||
{
|
||||
if (sv) {
|
||||
@@ -83,6 +138,64 @@ void AQH_HttpService_SetSourceFolder(AQH_SERVICE *sv, const char *s)
|
||||
|
||||
|
||||
|
||||
uint32_t AQH_HttpService_GetNextModuleId(AQH_SERVICE *sv)
|
||||
{
|
||||
if (sv) {
|
||||
AQH_HTTP_SERVICE *xsv;
|
||||
|
||||
xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_HTTP_SERVICE, sv);
|
||||
if (xsv) {
|
||||
return ++(xsv->lastModuleId);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint32_t AQH_HttpService_GetNextUserId(AQH_SERVICE *sv)
|
||||
{
|
||||
if (sv) {
|
||||
AQH_HTTP_SERVICE *xsv;
|
||||
|
||||
xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_HTTP_SERVICE, sv);
|
||||
if (xsv) {
|
||||
return ++(xsv->lastUserId);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_HttpService_GetMaxSessionAgeInSecs(const AQH_SERVICE *sv)
|
||||
{
|
||||
if (sv) {
|
||||
AQH_HTTP_SERVICE *xsv;
|
||||
|
||||
xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_HTTP_SERVICE, sv);
|
||||
if (xsv) {
|
||||
return xsv->maxSessionAgeInSecs;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_HttpService_SetMaxSessionAgeInSecs(AQH_SERVICE *sv, int i)
|
||||
{
|
||||
if (sv) {
|
||||
AQH_HTTP_SERVICE *xsv;
|
||||
|
||||
xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_HTTP_SERVICE, sv);
|
||||
if (xsv)
|
||||
xsv->maxSessionAgeInSecs=i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const char *AQH_HttpService_GetSiteHeader(const AQH_SERVICE *sv)
|
||||
{
|
||||
if (sv) {
|
||||
@@ -141,183 +254,3 @@ void AQH_HttpService_SetSiteFooter(AQH_SERVICE *sv, const char *s)
|
||||
|
||||
|
||||
|
||||
int AQH_HttpService_AddFile(AQH_SERVICE *sv, const char *fname, GWEN_BUFFER *buf)
|
||||
{
|
||||
if (fname && *fname) {
|
||||
AQH_HTTP_SERVICE *xsv;
|
||||
|
||||
xsv=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_HTTP_SERVICE, sv);
|
||||
if (xsv) {
|
||||
int rv;
|
||||
GWEN_BUFFER *fnbuf;
|
||||
|
||||
fnbuf=GWEN_Buffer_new(0, 256, 0, 1);
|
||||
if (xsv->sourceFolder) {
|
||||
GWEN_Buffer_AppendString(fnbuf, xsv->sourceFolder);
|
||||
GWEN_Buffer_AppendString(fnbuf, GWEN_DIR_SEPARATOR_S);
|
||||
}
|
||||
GWEN_Buffer_AppendString(fnbuf, fname);
|
||||
|
||||
rv=GWEN_SyncIo_Helper_ReadFile(GWEN_Buffer_GetStart(fnbuf), buf);
|
||||
if (rv<0) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "Error reading file \"%s\": %d", GWEN_Buffer_GetStart(fnbuf), rv);
|
||||
GWEN_Buffer_free(fnbuf);
|
||||
return rv;
|
||||
}
|
||||
GWEN_Buffer_free(fnbuf);
|
||||
}
|
||||
else {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "No http service object");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_HttpService_AddStatusLine(AQH_SERVICE *sv, int code, const char *msg, const char *proto, GWEN_BUFFER *buf)
|
||||
{
|
||||
GWEN_Buffer_AppendArgs(buf, "%s %03d %s \r\n", proto?proto:"HTTP/1.1", code, msg?msg:"");
|
||||
}
|
||||
|
||||
|
||||
|
||||
void AQH_HttpService_AddHeader(AQH_SERVICE *sv, GWEN_DB_NODE *dbHeader, GWEN_BUFFER *buf)
|
||||
{
|
||||
GWEN_DB_NODE *dbVar;
|
||||
|
||||
dbVar=GWEN_DB_GetFirstVar(dbHeader);
|
||||
while (dbVar) {
|
||||
GWEN_DB_NODE *dbVal;
|
||||
|
||||
/* only handle first value */
|
||||
dbVal=GWEN_DB_GetFirstValue(dbVar);
|
||||
if (dbVal) {
|
||||
const char *sVar;
|
||||
|
||||
sVar=GWEN_DB_VariableName(dbVar);
|
||||
if (sVar && *sVar) {
|
||||
GWEN_DB_NODE_TYPE vtype;
|
||||
|
||||
vtype=GWEN_DB_GetValueType(dbVal);
|
||||
if (vtype==GWEN_DB_NodeType_ValueChar) {
|
||||
const char *sValue;
|
||||
|
||||
sValue=GWEN_DB_GetCharValueFromNode(dbVal);
|
||||
if (sValue)
|
||||
GWEN_Buffer_AppendArgs(buf, "%s:%s\r\n", sVar, sValue);
|
||||
} /* if char */
|
||||
else if (vtype==GWEN_DB_NodeType_ValueInt) {
|
||||
int i;
|
||||
|
||||
i=GWEN_DB_GetIntValueFromNode(dbVal);
|
||||
if (i!=-1 || strcasecmp(sVar, "Content-Length")==0)
|
||||
GWEN_Buffer_AppendArgs(buf, "%s:%d\r\n", sVar, i);
|
||||
} /* if int */
|
||||
else {
|
||||
DBG_INFO(AQH_LOGDOMAIN, "Variable type %d of var [%s] not supported, ignoring", vtype, sVar);
|
||||
}
|
||||
} /* if sVar */
|
||||
}
|
||||
dbVar=GWEN_DB_GetNextVar(dbVar);
|
||||
}
|
||||
|
||||
/* finalize header */
|
||||
GWEN_Buffer_AppendString(buf, "\r\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
int AQH_HttpService_ParsePostBody(AQH_SERVICE *sv, const GWEN_MSG *msgReceived, GWEN_DB_NODE *dbBody)
|
||||
{
|
||||
GWEN_DB_NODE *dbParsedInfo;
|
||||
GWEN_DB_NODE *dbHeader;
|
||||
const char *contentType;
|
||||
int contentLength;
|
||||
const char *s;
|
||||
|
||||
dbParsedInfo=GWEN_Msg_GetDbParsedInfo(msgReceived);
|
||||
if (dbParsedInfo==NULL) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "No parsed info in received message");
|
||||
return GWEN_ERROR_BAD_DATA;
|
||||
}
|
||||
dbHeader=GWEN_DB_GetGroup(dbParsedInfo, GWEN_PATH_FLAGS_PATHMUSTEXIST, "header");
|
||||
if (dbHeader==NULL) {
|
||||
DBG_ERROR(AQH_LOGDOMAIN, "No http header group in received message");
|
||||
return GWEN_ERROR_BAD_DATA;
|
||||
}
|
||||
|
||||
contentType=GWEN_DB_GetCharValue(dbHeader, "content-type", 0, NULL);
|
||||
if (!(contentType && *contentType && strcasecmp(contentType, "application/x-www-form-urlencoded")==0)) {
|
||||
DBG_ERROR(NULL, "Invalid or missing content type [%s]", contentType?contentType:"<no type>");
|
||||
return GWEN_ERROR_BAD_DATA;
|
||||
}
|
||||
|
||||
contentLength=GWEN_Msg_GetParsedPayloadSize(msgReceived);
|
||||
if (contentLength<1) {
|
||||
DBG_ERROR(NULL, "Empty message body");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (contentLength<1) {
|
||||
DBG_ERROR(NULL, "Empty message body");
|
||||
return 0;
|
||||
}
|
||||
s=(const char*)(GWEN_Msg_GetConstBuffer(msgReceived)+GWEN_Msg_GetParsedPayloadOffset(msgReceived));
|
||||
return _parsePostBody(s, contentLength, dbBody);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int _parsePostBody(const char *s, int contentLength, GWEN_DB_NODE *dbBody)
|
||||
{
|
||||
while(contentLength>0) {
|
||||
const char *sNameStart;
|
||||
int nameLen;
|
||||
|
||||
while((contentLength>0) && (*s<33)) {
|
||||
contentLength--;
|
||||
s++;
|
||||
}
|
||||
sNameStart=s;
|
||||
while((contentLength>0) && (*s!='=') && (*s!='&')) {
|
||||
contentLength--;
|
||||
s++;
|
||||
}
|
||||
nameLen=s-sNameStart;
|
||||
if ((contentLength>0) && (*s=='=')) {
|
||||
const char *sValueStart;
|
||||
int valueLen;
|
||||
|
||||
s++;
|
||||
while((contentLength>0) && (*s<33)) {
|
||||
s++;
|
||||
contentLength--;
|
||||
}
|
||||
sValueStart=s;
|
||||
while((contentLength>0) && (*s!='&')) {
|
||||
contentLength--;
|
||||
s++;
|
||||
}
|
||||
valueLen=s-sValueStart;
|
||||
if (nameLen && valueLen) {
|
||||
char sNameBuf[32];
|
||||
char sValueBuf[64];
|
||||
|
||||
if (GWEN_Text_UnescapeN(sNameStart, nameLen, sNameBuf, sizeof(sNameBuf))!=NULL &&
|
||||
GWEN_Text_UnescapeN(sValueStart, valueLen, sValueBuf, sizeof(sValueBuf))!=NULL)
|
||||
GWEN_DB_SetCharValue(dbBody, 0, sNameBuf, sValueBuf);
|
||||
else {
|
||||
DBG_ERROR(NULL, "Either name or value invalid in body, aborting");
|
||||
return GWEN_ERROR_BAD_DATA;
|
||||
}
|
||||
}
|
||||
if ((contentLength>0) && (*s=='&'))
|
||||
s++;
|
||||
}
|
||||
} /* while */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user