diff --git a/src/httpserver/http_tcp_server.c b/src/httpserver/http_tcp_server.c index 8cc83d4a0..91ee5da44 100644 --- a/src/httpserver/http_tcp_server.c +++ b/src/httpserver/http_tcp_server.c @@ -39,7 +39,6 @@ static void tcp_client_thread( beken_thread_arg_t arg ) { OSStatus err = kNoErr; int fd = (int) arg; - int lenrx = 0; //fd_set readfds, errfds, readfds2; char *buf = NULL; char *reply = NULL; @@ -50,37 +49,34 @@ static void tcp_client_thread( beken_thread_arg_t arg ) //my_fd = fd; reply = (char*) os_malloc( replyBufferSize ); - buf = (char*) os_malloc( 1024 ); + buf = (char*) os_malloc( 1026 ); ASSERT(buf); - while ( 1 ) + http_request_t request; + os_memset(&request, 0, sizeof(request)); + + request.fd = fd; + request.received = buf; + request.receivedLen = recv( fd, request.received, 1024, 0 ); + + request.reply = reply; + reply[0] = '\0'; + request.replymaxlen = replyBufferSize - 1; + + if ( request.receivedLen <= 0 ) { - lenrx = recv( fd, buf, 1024, 0 ); - - if ( lenrx <= 0 ) - { - os_printf( "TCP Client is disconnected, fd: %d", fd ); - goto exit; - } - - //addLog( "TCP received string %s\n",buf ); - // returns length to be sent if any - buf[lenrx] = 0; - int lenret = HTTP_ProcessPacket(buf, reply, replyBufferSize, sendfn, fd); - addLog( "TCP sending reply len %i\n",lenret ); - while(lenret){ - int len = lenret; - if (len > 1024) len = 1024; - send( fd, reply, len, 0 ); - reply += len; - lenret -= len; - } - - rtos_delay_milliseconds(10); - close(fd); - break; + os_printf( "TCP Client is disconnected, fd: %d", fd ); + goto exit; } + //addLog( "TCP received string %s\n",buf ); + // returns length to be sent if any + request.received[request.receivedLen] = 0; + int lenret = HTTP_ProcessPacket(&request); + addLog( "TCP sending reply len %i\n",lenret ); + send( fd, reply, lenret, 0 ); + + rtos_delay_milliseconds(10); exit: if ( err != kNoErr ) diff --git a/src/httpserver/new_http.c b/src/httpserver/new_http.c index c1c378141..3020a957f 100644 --- a/src/httpserver/new_http.c +++ b/src/httpserver/new_http.c @@ -3,7 +3,12 @@ #include "../new_common.h" #include "ctype.h" #ifndef WINDOWS +#include "lwip/sockets.h" #include "str_pub.h" +#else +//#include +#include +//#include #endif #include "new_http.h" #include "../new_pins.h" @@ -44,21 +49,34 @@ Connection: keep-alive #define DEFAULT_OTA_URL "http://raspberrypi:1880/firmware" const char httpHeader[] = "HTTP/1.1 200 OK\nContent-type: " ; // HTTP header -const char httpMimeTypeHTML[] = "text/html\n\n" ; // HTML MIME type -const char httpMimeTypeText[] = "text/plain\n\n" ; // TEXT MIME type +const char httpMimeTypeHTML[] = "text/html" ; // HTML MIME type +const char httpMimeTypeText[] = "text/plain" ; // TEXT MIME type const char htmlHeader[] = "" ; const char htmlEnd[] = "" ; const char htmlReturnToMenu[] = "Return to menu";; const char htmlReturnToCfg[] = "Return to cfg";; const char *g_build_str = "Build on " __DATE__ " " __TIME__; +const char httpCorsHeaders[] = "Access-Control-Allow-Origin: *\r\nAccess-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept" ; // TEXT MIME type + +const char *methodNames[] = { + "GET", + "POST", + "PUT", + "OPTIONS" +}; + + #if WINDOWS #define os_free free #define os_malloc malloc #endif + + typedef struct http_callback_tag { char *url; + int method; http_callback_fn callback; } http_callback_t; @@ -66,7 +84,7 @@ typedef struct http_callback_tag { static http_callback_t *callbacks[MAX_HTTP_CALLBACKS]; static int numCallbacks = 0; -int HTTP_RegisterCallback( const char *url, http_callback_fn callback){ +int HTTP_RegisterCallback( const char *url, int method, http_callback_fn callback){ if (!url || !callback){ return -1; } @@ -84,6 +102,8 @@ int HTTP_RegisterCallback( const char *url, http_callback_fn callback){ } strcpy(callbacks[numCallbacks]->url, url); callbacks[numCallbacks]->callback = callback; + callbacks[numCallbacks]->method = method; + numCallbacks++; // success @@ -116,10 +136,15 @@ bool http_checkUrlBase(const char *base, const char *fileName) { return true; } -void http_setup(char *o, const char *type){ - strcpy(o,httpHeader); - strcat(o,type); +void http_setup(http_request_t *request, const char *type){ + poststr(request,httpHeader); + poststr(request,type); + poststr(request,"\r\n"); // next header + poststr(request,httpCorsHeaders); + poststr(request,"\r\n"); // end headers with double CRLF + poststr(request,"\r\n"); } + const char *http_checkArg(const char *p, const char *n) { while(1) { if(*n == 0 && (*p == 0 || *p == '=')) @@ -267,186 +292,305 @@ int g_total_templates = sizeof(g_templates)/sizeof(g_templates[0]); const char *g_header = "

OpenBK7231

[Read more][Support project]

"; -void HTTP_AddBuildFooter(char *outbuf, int outBufSize) { - strcat_safe(outbuf,"
",outBufSize); - strcat_safe(outbuf,g_build_str,outBufSize); +void HTTP_AddBuildFooter(http_request_t *request) { + poststr(request,"
"); + poststr(request,g_build_str); } -int HTTP_ProcessPacket(const char *recvbuf, char *outbuf, int outBufSize, http_send_fn sendpart, int socket) { + + +// add some more output safely, sending if necessary. +// call with str == NULL to force send. +int poststr(http_request_t *request, const char *str){ + if (NULL == str){ + send(request->fd, request->reply, strlen(request->reply), 0); + request->reply[0] = 0; + return 0; + } + + int currentlen = strlen(request->reply); + int addlen = strlen(str); + if (currentlen + addlen >= request->replymaxlen){ + send(request->fd, request->reply, strlen(request->reply), 0); + request->reply[0] = 0; + currentlen = 0; + } + if (addlen > request->replymaxlen){ + printf("won't fit"); + } else { + strcat(request->reply, str ); + } + return (currentlen + addlen); +} + +int HTTP_ProcessPacket(http_request_t *request) { int i, j; char tmpA[128]; char tmpB[64]; char tmpC[64]; //int bChanged = 0; - const char *urlStr; + const char *urlStr = ""; - *outbuf = '\0'; + char *recvbuf = request->received; + for (int i = 0; i < sizeof(methodNames)/sizeof(*methodNames); i++){ + if (http_startsWith(recvbuf, methodNames[i])){ + urlStr = recvbuf + strlen(methodNames[i]) + 2; // skip method name plus space, plus slash + request->method = i; + break; + } + } + if (request->method == -1){ + printf("unsupported method %7s", recvbuf); + return 0; + } - urlStr = recvbuf + 5; - if(http_startsWith(recvbuf,"GET")) { + if (request->method == HTTP_GET) { printf("HTTP request\n"); } else { printf("Other request\n"); } + + // if OPTIONS, return now - for CORS + if (request->method == HTTP_OPTIONS) { + http_setup(request, httpMimeTypeHTML); + i = strlen(request->reply); + return i; + } + + // chop URL at space + char *p = strchr(urlStr, ' '); + if (*p) { + *p = '\0'; + p++; // past space + } + else { + printf("invalid request\n"); + return 0; + } + // protocol is next, termed by \r\n + char *protocol = p; + p = strchr(protocol, '\r'); + if (*p) { + *p = '\0'; + p++; // past \r + p++; // past \n + } else { + printf("invalid request\n"); + return 0; + } + p++; + char *headers = p; + do { + p = strchr(headers, '\r'); + if (p != headers){ + if (p){ + if (request->numheaders < 16){ + request->headers[request->numheaders] = headers; + request->numheaders++; + } + // pick out contentLength + if (!strcmp(headers, "Content-Length:")){ + request->contentLength = atoi(headers + 15); + } + + *p = 0; + p++; // past \r + p++; // past \n + headers = p; + } else { + break; + } + } + if (*p == '\r'){ + // end of headers + *p = 0; + p++; + p++; + break; + } + } while(1); + + request->bodystart = p; + + // we will make this more general http_getArg(urlStr,"a",tmpA,sizeof(tmpA)); http_getArg(urlStr,"b",tmpB,sizeof(tmpB)); http_getArg(urlStr,"c",tmpC,sizeof(tmpC)); + if (*tmpA){ + request->querynames[request->numqueryitems] = "a"; + request->queryvalues[request->numqueryitems] = tmpA; + request->numqueryitems++; + } + if (*tmpB){ + request->querynames[request->numqueryitems] = "b"; + request->queryvalues[request->numqueryitems] = tmpB; + request->numqueryitems++; + } + if (*tmpC){ + request->querynames[request->numqueryitems] = "c"; + request->queryvalues[request->numqueryitems] = tmpC; + request->numqueryitems++; + } + // look for a callback with this URL and method, or HTTP_ANY for (i = 0; i < numCallbacks; i++){ char *url = callbacks[i]->url; if (http_checkUrlBase(urlStr, &url[1])){ - return callbacks[i]->callback(recvbuf, outbuf, outBufSize); + int method = callbacks[i]->method; + if(method == HTTP_ANY || method == request->method){ + return callbacks[i]->callback(request); + } } } if(http_checkUrlBase(urlStr,"about")) { - http_setup(outbuf, httpMimeTypeHTML); - strcat_safe(outbuf,htmlHeader,outBufSize); - strcat_safe(outbuf,g_header,outBufSize); - strcat_safe(outbuf,"About us page.",outBufSize); - strcat_safe(outbuf,htmlReturnToMenu,outBufSize); - HTTP_AddBuildFooter(outbuf,outBufSize); - strcat_safe(outbuf,htmlEnd,outBufSize); + poststr(request, httpMimeTypeHTML); + poststr(request,htmlHeader); + poststr(request,g_header); + poststr(request,"About us page."); + poststr(request,htmlReturnToMenu); + HTTP_AddBuildFooter(request); + poststr(request,htmlEnd); } else if(http_checkUrlBase(urlStr,"cfg_mqtt")) { - http_setup(outbuf, httpMimeTypeHTML); - strcat_safe(outbuf,htmlHeader,outBufSize); - strcat_safe(outbuf,g_header,outBufSize); - strcat_safe(outbuf,"

Use this to connect to your MQTT

",outBufSize); - strcat_safe(outbuf,"
\ + http_setup(request, httpMimeTypeHTML); + poststr(request,htmlHeader); + poststr(request,g_header); + poststr(request,"

Use this to connect to your MQTT

"); + poststr(request,"\
\ -
\ + poststr(request,CFG_GetMQTTHost()); + poststr(request,"\">
\
\ -

\ + poststr(request,tmpA); + poststr(request,"\">

\
\ -
\ + poststr(request,CFG_GetMQTTBrokerName()); + poststr(request,"\">
\
\ -
\ +
\
\ -
\ +
\ \ -
",outBufSize); - strcat_safe(outbuf,htmlReturnToCfg,outBufSize); - HTTP_AddBuildFooter(outbuf,outBufSize); - strcat_safe(outbuf,htmlEnd,outBufSize); + "); + poststr(request,htmlReturnToCfg); + HTTP_AddBuildFooter(request); + poststr(request,htmlEnd); } else if(http_checkUrlBase(urlStr,"cfg_mqtt_set")) { - http_setup(outbuf, httpMimeTypeHTML); - strcat_safe(outbuf,htmlHeader,outBufSize); - strcat_safe(outbuf,g_header,outBufSize); + http_setup(request, httpMimeTypeHTML); + poststr(request,htmlHeader); + poststr(request,g_header); - if(http_getArg(recvbuf,"host",tmpA,sizeof(tmpA))) { + if(http_getArg(urlStr,"host",tmpA,sizeof(tmpA))) { CFG_SetMQTTHost(tmpA); } - if(http_getArg(recvbuf,"port",tmpA,sizeof(tmpA))) { + if(http_getArg(urlStr,"port",tmpA,sizeof(tmpA))) { CFG_SetMQTTPort(atoi(tmpA)); } - if(http_getArg(recvbuf,"user",tmpA,sizeof(tmpA))) { + if(http_getArg(urlStr,"user",tmpA,sizeof(tmpA))) { CFG_SetMQTTUserName(tmpA); } - if(http_getArg(recvbuf,"password",tmpA,sizeof(tmpA))) { + if(http_getArg(urlStr,"password",tmpA,sizeof(tmpA))) { CFG_SetMQTTPass(tmpA); } - if(http_getArg(recvbuf,"client",tmpA,sizeof(tmpA))) { + if(http_getArg(urlStr,"client",tmpA,sizeof(tmpA))) { CFG_SetMQTTBrokerName(tmpA); } - strcat_safe(outbuf,"MQTT mode set!",outBufSize); + poststr(request,"MQTT mode set!"); CFG_SaveMQTT(); - strcat_safe(outbuf,"Please wait for module to connect... if there is problem, restart it...",outBufSize); + poststr(request,"Please wait for module to connect... if there is problem, restart it..."); - strcat_safe(outbuf,"
",outBufSize); - strcat_safe(outbuf,"Return to MQTT settings",outBufSize); - strcat_safe(outbuf,"
",outBufSize); - strcat_safe(outbuf,htmlReturnToCfg,outBufSize); - HTTP_AddBuildFooter(outbuf,outBufSize); - strcat_safe(outbuf,htmlEnd,outBufSize); + poststr(request,"
"); + poststr(request,"Return to MQTT settings"); + poststr(request,"
"); + poststr(request,htmlReturnToCfg); + HTTP_AddBuildFooter(request); + poststr(request,htmlEnd); } else if(http_checkUrlBase(urlStr,"cfg_wifi_set")) { - http_setup(outbuf, httpMimeTypeHTML); - strcat_safe(outbuf,htmlHeader,outBufSize); - strcat_safe(outbuf,g_header,outBufSize); + http_setup(request, httpMimeTypeHTML); + poststr(request,htmlHeader); + poststr(request,g_header); if(http_getArg(recvbuf,"open",tmpA,sizeof(tmpA))) { CFG_SetWiFiSSID(""); CFG_SetWiFiPass(""); - strcat_safe(outbuf,"WiFi mode set: open access point.",outBufSize); + poststr(request,"WiFi mode set: open access point."); } else { - if(http_getArg(recvbuf,"ssid",tmpA,sizeof(tmpA))) { + if(http_getArg(urlStr,"ssid",tmpA,sizeof(tmpA))) { CFG_SetWiFiSSID(tmpA); } - if(http_getArg(recvbuf,"pass",tmpA,sizeof(tmpA))) { + if(http_getArg(urlStr,"pass",tmpA,sizeof(tmpA))) { CFG_SetWiFiPass(tmpA); } - strcat_safe(outbuf,"WiFi mode set: connect to WLAN.",outBufSize); + poststr(request,"WiFi mode set: connect to WLAN."); } CFG_SaveWiFi(); - strcat_safe(outbuf,"Please wait for module to reset...",outBufSize); + poststr(request,"Please wait for module to reset..."); - strcat_safe(outbuf,"
",outBufSize); - strcat_safe(outbuf,"Return to WiFi settings",outBufSize); - strcat_safe(outbuf,"
",outBufSize); - strcat_safe(outbuf,htmlReturnToCfg,outBufSize); - HTTP_AddBuildFooter(outbuf,outBufSize); - strcat_safe(outbuf,htmlEnd,outBufSize); + poststr(request,"
"); + poststr(request,"Return to WiFi settings"); + poststr(request,"
"); + poststr(request,htmlReturnToCfg); + HTTP_AddBuildFooter(request); + poststr(request,htmlEnd); } else if(http_checkUrlBase(urlStr,"cfg_wifi")) { // for a test, show password as well... const char *cur_ssid, *cur_pass; - http_setup(outbuf, httpMimeTypeHTML); - strcat_safe(outbuf,htmlHeader,outBufSize); - strcat_safe(outbuf,g_header,outBufSize); + http_setup(request, httpMimeTypeHTML); + poststr(request,htmlHeader); + poststr(request,g_header); /*bChanged = 0; if(http_getArg(recvbuf,"ssid",tmpA,sizeof(tmpA))) { CFG_SetWiFiSSID(tmpA); - strcat_safe(outbuf,"

WiFi SSID set!

",outBufSize); + poststr(request,"

WiFi SSID set!

"); bChanged = 1; } if(http_getArg(recvbuf,"pass",tmpA,sizeof(tmpA))) { CFG_SetWiFiPass(tmpA); - strcat_safe(outbuf,"

WiFi Password set!

",outBufSize); + poststr(request,"

WiFi Password set!

"); bChanged = 1; } if(bChanged) { - strcat_safe(outbuf,"

Device will reconnect after restarting

",outBufSize); + poststr(request,"

Device will reconnect after restarting

"); }*/ - strcat_safe(outbuf,"

Use this to disconnect from your WiFi

",outBufSize); - strcat_safe(outbuf,"
\ + poststr(request,"

Use this to disconnect from your WiFi

"); + poststr(request,"\ \ \ -
",outBufSize); - strcat_safe(outbuf,"

Use this to connect to your WiFi

",outBufSize); - strcat_safe(outbuf,"
\ +
"); + poststr(request,"

Use this to connect to your WiFi

"); + poststr(request,"
\
\ -
\ + poststr(request, "\">
\
\ -

\ + poststr(request,"\">

\ \ -
",outBufSize); - strcat_safe(outbuf,htmlReturnToCfg,outBufSize); - HTTP_AddBuildFooter(outbuf,outBufSize); - strcat_safe(outbuf,htmlEnd,outBufSize); + "); + poststr(request,htmlReturnToCfg); + HTTP_AddBuildFooter(request); + poststr(request,htmlEnd); } else if(http_checkUrlBase(urlStr,"flash_read_tool")) { int len = 16; int ofs = 1970176; @@ -454,18 +598,19 @@ int HTTP_ProcessPacket(const char *recvbuf, char *outbuf, int outBufSize, http_s int rem; int now; int nowOfs; - http_setup(outbuf, httpMimeTypeHTML); - strcat_safe(outbuf,htmlHeader,outBufSize); - strcat_safe(outbuf,g_header,outBufSize); - strcat_safe(outbuf,"

Flash Read Tool

",outBufSize); + http_setup(request, httpMimeTypeHTML); + poststr(request,htmlHeader); + poststr(request,g_header); + poststr(request,"

Flash Read Tool

"); - if(http_getArg(recvbuf,"offset",tmpA,sizeof(tmpA))&&http_getArg(recvbuf,"len",tmpB,sizeof(tmpB))) { + if( http_getArg(urlStr,"offset",tmpA,sizeof(tmpA)) && + http_getArg(urlStr,"len",tmpB,sizeof(tmpB))) { u8 buffer[128]; len = atoi(tmpB); ofs = atoi(tmpA); sprintf(tmpA,"Memory at %i with len %i reads: ",ofs,len); - strcat_safe(outbuf,tmpA,outBufSize); - strcat_safe(outbuf,"
",outBufSize); + poststr(request,tmpA); + poststr(request,"
"); ///res = tuya_hal_flash_read (ofs, buffer,len); //sprintf(tmpA,"Result %i",res); @@ -483,7 +628,7 @@ int HTTP_ProcessPacket(const char *recvbuf, char *outbuf, int outBufSize, http_s res = tuya_hal_flash_read (nowOfs, buffer,now); for(i = 0; i < now; i++) { sprintf(tmpA,"%02X ",buffer[i]); - strcat_safe(outbuf,tmpA,outBufSize); + poststr(request,tmpA); } rem -= now; nowOfs += now; @@ -492,51 +637,51 @@ int HTTP_ProcessPacket(const char *recvbuf, char *outbuf, int outBufSize, http_s } } - strcat_safe(outbuf,"
",outBufSize); + poststr(request,"
"); } - strcat_safe(outbuf,"
\ + poststr(request,"\
\ -
",ofs); - strcat_safe(outbuf,tmpA,outBufSize); - strcat_safe(outbuf,"
\ - lenght:
\ + ",len); - strcat_safe(outbuf,tmpA,outBufSize); - strcat_safe(outbuf,"

\ + poststr(request,tmpA); + poststr(request,"

\ \ -
",outBufSize); + "); - strcat_safe(outbuf,htmlReturnToCfg,outBufSize); - HTTP_AddBuildFooter(outbuf,outBufSize); - strcat_safe(outbuf,htmlEnd,outBufSize); + poststr(request,htmlReturnToCfg); + HTTP_AddBuildFooter(request); + poststr(request,htmlEnd); } else if(http_checkUrlBase(urlStr,"cfg_quick")) { - http_setup(outbuf, httpMimeTypeHTML); - strcat_safe(outbuf,htmlHeader,outBufSize); - strcat_safe(outbuf,g_header,outBufSize); - strcat_safe(outbuf,"

Quick Config

",outBufSize); + http_setup(request, httpMimeTypeHTML); + poststr(request,htmlHeader); + poststr(request,g_header); + poststr(request,"

Quick Config

"); if(http_getArg(urlStr,"dev",tmpA,sizeof(tmpA))) { j = atoi(tmpA); sprintf(tmpA,"

Set dev %i!

",j); - strcat(outbuf,tmpA); + poststr(request,tmpA); g_templates[j].setter(); } - strcat_safe(outbuf,"
",outBufSize); + poststr(request,""); sprintf(tmpA, ""); - strcat_safe(outbuf,"
",outBufSize); + poststr(request,""); + poststr(request,""); - strcat_safe(outbuf,htmlReturnToCfg,outBufSize); - HTTP_AddBuildFooter(outbuf,outBufSize); - strcat_safe(outbuf,htmlEnd,outBufSize); + poststr(request,htmlReturnToCfg); + HTTP_AddBuildFooter(request); + poststr(request,htmlEnd); } else if(http_checkUrlBase(urlStr,"cfg_ha")) { @@ -548,13 +693,13 @@ int HTTP_ProcessPacket(const char *recvbuf, char *outbuf, int outBufSize, http_s baseName = CFG_GetShortDeviceName(); - http_setup(outbuf, httpMimeTypeHTML); - strcat_safe(outbuf,htmlHeader,outBufSize); - strcat_safe(outbuf,g_header,outBufSize); - strcat_safe(outbuf,"

Home Assistant Cfg

",outBufSize); - strcat_safe(outbuf,"

Paste this to configuration yaml

",outBufSize); + http_setup(request, httpMimeTypeHTML); + poststr(request,htmlHeader); + poststr(request,g_header); + poststr(request,"

Home Assistant Cfg

"); + poststr(request,"

Paste this to configuration yaml

"); - strcat_safe(outbuf,"",outBufSize); + poststr(request,""); - strcat_safe(outbuf,htmlReturnToCfg,outBufSize); - HTTP_AddBuildFooter(outbuf,outBufSize); - strcat_safe(outbuf,htmlEnd,outBufSize); + poststr(request,htmlReturnToCfg); + HTTP_AddBuildFooter(request); + poststr(request,htmlEnd); } else if(http_checkUrlBase(urlStr,"cfg")) { - http_setup(outbuf, httpMimeTypeHTML); - strcat_safe(outbuf,htmlHeader,outBufSize); - strcat_safe(outbuf,g_header,outBufSize); - strcat_safe(outbuf,"
",outBufSize); - strcat_safe(outbuf,"
",outBufSize); - strcat_safe(outbuf,"
",outBufSize); - strcat_safe(outbuf,"
",outBufSize); - strcat_safe(outbuf,"
",outBufSize); - strcat_safe(outbuf,"
",outBufSize); - strcat_safe(outbuf,"
",outBufSize); - strcat_safe(outbuf,"
",outBufSize); + http_setup(request, httpMimeTypeHTML); + poststr(request,htmlHeader); + poststr(request,g_header); + poststr(request,"
"); + poststr(request,"
"); + poststr(request,"
"); + poststr(request,"
"); + poststr(request,"
"); + poststr(request,"
"); + poststr(request,"
"); + poststr(request,"
"); - strcat_safe(outbuf,htmlReturnToMenu,outBufSize); - HTTP_AddBuildFooter(outbuf,outBufSize); - strcat_safe(outbuf,htmlEnd,outBufSize); + poststr(request,htmlReturnToMenu); + HTTP_AddBuildFooter(request); + poststr(request,htmlEnd); //} else if(http_checkUrlBase(urlStr,"setWB2SInputs")) { // http_setup(outbuf, httpMimeTypeHTML); - // strcat_safe(outbuf,htmlHeader,outBufSize); + // poststr(request,htmlHeader); // setupAllWB2SPinsAsButtons(); // http_setup(outbuf, httpMimeTypeHTML); - // strcat_safe(outbuf,"Set all inputs for dbg .",outBufSize); - // strcat_safe(outbuf,htmlReturnToMenu,outBufSize); - // HTTP_AddBuildFooter(outbuf,outBufSize); - // strcat_safe(outbuf,htmlEnd,outBufSize); + // poststr(request,"Set all inputs for dbg ."); + // poststr(request,htmlReturnToMenu); + // HTTP_AddBuildFooter(outbuf); + // poststr(request,htmlEnd); //} else if(http_checkUrlBase(urlStr,"setAllInputs")) { // http_setup(outbuf, httpMimeTypeHTML); - // strcat_safe(outbuf,htmlHeader,outBufSize); + // poststr(request,htmlHeader); // // it breaks UART pins as well, omg! // for(i = 0; i < GPIO_MAX; i++) { // PIN_SetPinRoleForPinIndex(i,IOR_Button); // PIN_SetPinChannelForPinIndex(i,1); // } // http_setup(outbuf, httpMimeTypeHTML); - // strcat_safe(outbuf,"Set all inputs for dbg .",outBufSize); - // strcat_safe(outbuf,htmlReturnToMenu,outBufSize); - // HTTP_AddBuildFooter(outbuf,outBufSize); - // strcat_safe(outbuf,htmlEnd,outBufSize); + // poststr(request,"Set all inputs for dbg ."); + // poststr(request,htmlReturnToMenu); + // HTTP_AddBuildFooter(outbuf); + // poststr(request,htmlEnd); } else if(http_checkUrlBase(urlStr,"cfg_pins")) { int iChanged = 0; int iChangedRequested = 0; - http_setup(outbuf, httpMimeTypeHTML); - strcat(outbuf,htmlHeader); - strcat_safe(outbuf,g_header,outBufSize); + http_setup(request, httpMimeTypeHTML); + poststr(request,htmlHeader); + poststr(request,g_header); for(i = 0; i < GPIO_MAX; i++) { sprintf(tmpA, "%i",i); if(http_getArg(recvbuf,tmpA,tmpB,sizeof(tmpB))) { @@ -682,7 +827,7 @@ int HTTP_ProcessPacket(const char *recvbuf, char *outbuf, int outBufSize, http_s } } sprintf(tmpA, "r%i",i); - if(http_getArg(recvbuf,tmpA,tmpB,sizeof(tmpB))) { + if(http_getArg(urlStr,tmpA,tmpB,sizeof(tmpB))) { int rel; int prevRel; @@ -697,60 +842,44 @@ int HTTP_ProcessPacket(const char *recvbuf, char *outbuf, int outBufSize, http_s } } } - if (sendpart){ - sendpart(socket, outbuf, strlen(outbuf)); - outbuf[0] = 0; - } if(iChangedRequested>0) { PIN_SaveToFlash(); sprintf(tmpA, "Pins update - %i reqs, %i changed!

",iChangedRequested,iChanged); - strcat(outbuf,tmpA); + poststr(request,tmpA); } // strcat(outbuf,""); - strcat(outbuf,"
"); + poststr(request,""); for( i = 0; i < GPIO_MAX; i++) { int si, ch; si = PIN_GetPinRoleForPinIndex(i); ch = PIN_GetPinChannelForPinIndex(i); sprintf(tmpA, "P%i ",i); - strcat(outbuf,tmpA); + poststr(request,tmpA); sprintf(tmpA, ""); + poststr(request, ""); if(ch == 0) { tmpB[0] = 0; } else { sprintf(tmpB,"%i",ch); } sprintf(tmpA, "",i,tmpB); - strcat(outbuf,tmpA); - strcat(outbuf,"
"); - if (sendpart){ - sendpart(socket, outbuf, strlen(outbuf)); - outbuf[0] = 0; - } + poststr(request,tmpA); + poststr(request,"
"); } - strcat(outbuf,"
"); + poststr(request,""); - strcat(outbuf,htmlReturnToCfg); - HTTP_AddBuildFooter(outbuf,outBufSize); - strcat(outbuf,htmlEnd); + poststr(request,htmlReturnToCfg); + HTTP_AddBuildFooter(request); + poststr(request,htmlEnd); } else if(http_checkUrlBase(urlStr,"index")) { int relayFlags; int pwmFlags; @@ -758,26 +887,26 @@ int HTTP_ProcessPacket(const char *recvbuf, char *outbuf, int outBufSize, http_s relayFlags = 0; pwmFlags = 0; - http_setup(outbuf, httpMimeTypeHTML); - strcat(outbuf,htmlHeader); - strcat(outbuf,""); - strcat_safe(outbuf,g_header,outBufSize); + http_setup(request, httpMimeTypeHTML); + poststr(request,htmlHeader); + poststr(request,""); + poststr(request,g_header); if(http_getArg(urlStr,"tgl",tmpA,sizeof(tmpA))) { j = atoi(tmpA); sprintf(tmpA,"

Toggled %i!

",j); - strcat(outbuf,tmpA); + poststr(request,tmpA); CHANNEL_Toggle(j); } if(http_getArg(urlStr,"on",tmpA,sizeof(tmpA))) { j = atoi(tmpA); sprintf(tmpA,"

Enabled %i!

",j); - strcat(outbuf,tmpA); + poststr(request,tmpA); CHANNEL_Set(j,255,1); } if(http_getArg(urlStr,"off",tmpA,sizeof(tmpA))) { j = atoi(tmpA); sprintf(tmpA,"

Disabled %i!

",j); - strcat(outbuf,tmpA); + poststr(request,tmpA); CHANNEL_Set(j,0,1); } if(http_getArg(urlStr,"pwm",tmpA,sizeof(tmpA))) { @@ -785,7 +914,7 @@ int HTTP_ProcessPacket(const char *recvbuf, char *outbuf, int outBufSize, http_s http_getArg(urlStr,"pwmIndex",tmpA,sizeof(tmpA)); j = atoi(tmpA); sprintf(tmpA,"

Changed pwm %i to %i!

",j,newPWMValue); - strcat(outbuf,tmpA); + poststr(request,tmpA); CHANNEL_Set(j,newPWMValue,1); } @@ -807,92 +936,84 @@ int HTTP_ProcessPacket(const char *recvbuf, char *outbuf, int outBufSize, http_s } else { c = "g"; } - strcat(outbuf,"
"); + poststr(request,""); sprintf(tmpA,"",i); - strcat(outbuf,tmpA); + poststr(request,tmpA); sprintf(tmpA,"
",c,i); - strcat(outbuf,tmpA); + poststr(request,tmpA); } if(BIT_CHECK(pwmFlags,i)) { int pwmValue; pwmValue = CHANNEL_Get(i); sprintf(tmpA,"
",i); - strcat(outbuf,tmpA); + poststr(request,tmpA); sprintf(tmpA,"",i,pwmValue); - strcat(outbuf,tmpA); + poststr(request,tmpA); sprintf(tmpA,"",i); - strcat(outbuf,tmpA); + poststr(request,tmpA); sprintf(tmpA,"
",i); - strcat(outbuf,tmpA); + poststr(request,tmpA); - strcat(outbuf,""); + poststr(request,tmpA); + poststr(request,"}\n"); + poststr(request,""); } } // strcat(outbuf,""); - strcat(outbuf,"
"); - strcat(outbuf,"
"); + poststr(request,"
"); + poststr(request,"
"); - strcat(outbuf,htmlReturnToMenu); - HTTP_AddBuildFooter(outbuf,outBufSize); - strcat(outbuf,htmlEnd); + poststr(request,htmlReturnToMenu); + HTTP_AddBuildFooter(request); + poststr(request,htmlEnd); } else if(http_checkUrlBase(urlStr,"ota_exec")) { - http_setup(outbuf, httpMimeTypeHTML); - strcat(outbuf,htmlHeader); + http_setup(request, httpMimeTypeHTML); + poststr(request,htmlHeader); if(http_getArg(urlStr,"host",tmpA,sizeof(tmpA))) { sprintf(tmpB,"

OTA requested for %s!

",tmpA); - strcat(outbuf,tmpB); + poststr(request,tmpB); #if WINDOWS #else otarequest(tmpA); #endif } - strcat(outbuf,htmlReturnToMenu); - HTTP_AddBuildFooter(outbuf,outBufSize); - strcat(outbuf,htmlEnd); + poststr(request,htmlReturnToMenu); + HTTP_AddBuildFooter(request); + poststr(request,htmlEnd); } else if(http_checkUrlBase(urlStr,"ota")) { - http_setup(outbuf, httpMimeTypeHTML); - strcat(outbuf,htmlHeader); - strcat_safe(outbuf,"
\ + http_setup(request, httpMimeTypeHTML); + poststr(request,htmlHeader); + poststr(request,"\
\ -
\ +
\ \ -
",outBufSize); - strcat(outbuf,htmlReturnToMenu); - HTTP_AddBuildFooter(outbuf,outBufSize); - strcat(outbuf,htmlEnd); + "); + poststr(request,htmlReturnToMenu); + HTTP_AddBuildFooter(request); + poststr(request,htmlEnd); } else { - http_setup(outbuf, httpMimeTypeHTML); - strcat(outbuf,htmlHeader); - strcat_safe(outbuf,g_header,outBufSize); - strcat(outbuf,"Not found."); - strcat(outbuf,htmlReturnToMenu); - HTTP_AddBuildFooter(outbuf,outBufSize); - strcat(outbuf,htmlEnd); + http_setup(request, httpMimeTypeHTML); + poststr(request,htmlHeader); + poststr(request,g_header); + poststr(request,"Not found."); + poststr(request,htmlReturnToMenu); + HTTP_AddBuildFooter(request); + poststr(request,htmlEnd); } - i = strlen(outbuf); - if(i >= outBufSize-1) { - // Rewrite all to allow user to know that something went wrong - http_setup(outbuf, httpMimeTypeHTML); - strcat(outbuf,htmlHeader); - strcat_safe(outbuf,g_header,outBufSize); - sprintf(tmpA, "Buffer overflow occured while trying to process your request.
"); - strcat(outbuf,tmpA); - strcat(outbuf,htmlReturnToMenu); - HTTP_AddBuildFooter(outbuf,outBufSize); - strcat(outbuf,htmlEnd); - } - i = strlen(outbuf); - return i; + + + // force send remaining + poststr(request, NULL); + // nothing more to send + return 0; } \ No newline at end of file diff --git a/src/httpserver/new_http.h b/src/httpserver/new_http.h index 4806fc90b..8f45f4787 100644 --- a/src/httpserver/new_http.h +++ b/src/httpserver/new_http.h @@ -7,14 +7,44 @@ extern const char htmlHeader[]; extern const char htmlEnd[]; extern const char htmlReturnToMenu[]; -typedef int (*http_send_fn)(int fd, const char *payload, int len); +#define MAX_QUERY 16 +#define MAX_HEADERS 16 +typedef struct http_request_tag { + char *received; // partial or whole received data, up to 1024 + int receivedLen; -int HTTP_ProcessPacket(const char *recvbuf, char *outbuf, int outBufSize, http_send_fn send, int socket); -void http_setup(char *o, const char *type); + // filled by HTTP_ProcessPacket + int method; + char *url; + int numqueryitems; + char *querynames[MAX_QUERY]; + char *queryvalues[MAX_QUERY]; + int numheaders; + char *headers[MAX_HEADERS]; + char *bodystart; /// start start of the body (maybe all of it) + int contentLength; + // used to respond + char *reply; + int replymaxlen; + int fd; +} http_request_t; + + +int HTTP_ProcessPacket(http_request_t *request); +void http_setup(http_request_t *request, const char *type); +int poststr(http_request_t *request, const char *str); + +enum { + HTTP_ANY = -1, + HTTP_GET = 0, + HTTP_PUT = 1, + HTTP_POST = 2, + HTTP_OPTIONS = 3 +} METHODS; // callback function for http -typedef int (*http_callback_fn)(const char *payload, char *outbuf, int outBufSize); +typedef int (*http_callback_fn)(http_request_t *request); // url MUST start with '/' // urls must be unique (i.e. you can't have /about and /aboutme or /about/me) -int HTTP_RegisterCallback( const char *url, http_callback_fn callback); \ No newline at end of file +int HTTP_RegisterCallback( const char *url, int method, http_callback_fn callback); \ No newline at end of file diff --git a/src/logging/logging.c b/src/logging/logging.c index 78db380ae..1df9e101c 100644 --- a/src/logging/logging.c +++ b/src/logging/logging.c @@ -4,7 +4,7 @@ #include "../httpserver/new_http.h" #include "str_pub.h" -static int http_getlog(const char *payload, char *outbuf, int outBufSize); +static int http_getlog(http_request_t *request); static void log_server_thread( beken_thread_arg_t arg ); static void log_client_thread( beken_thread_arg_t arg ); @@ -38,7 +38,7 @@ static void initLog() { initialised = 1; startSerialLog(); startLogServer(); - HTTP_RegisterCallback( "/logs", http_getlog); + HTTP_RegisterCallback( "/logs", HTTP_GET, http_getlog); } // adds a log to the log memory @@ -255,29 +255,31 @@ static void log_serial_thread( beken_thread_arg_t arg ) -static int http_getlog(const char *payload, char *outbuf, int outBufSize){ - http_setup(outbuf, httpMimeTypeHTML); - strcat_safe(outbuf,htmlHeader,outBufSize); - strcat_safe(outbuf,htmlReturnToMenu,outBufSize); +static int http_getlog(http_request_t *request){ + http_setup(request, httpMimeTypeHTML); + poststr(request,htmlHeader); + poststr(request,htmlReturnToMenu); - strcat_safe(outbuf, "
",outBufSize);
+    poststr(request, "
");
     char *post = "
"; - char *b = outbuf; + int len = 0; - int len = strlen(b); - b += len; - outBufSize -= len; + // get log in small chunks, posting on http + do { + char buf[128]; + len = getHttp(buf, 127); + buf[len] = '\0'; + if (len){ + poststr(request, buf); + } + } while (len); - int trailsize = strlen(htmlEnd) + strlen(post); - len = getHttp(b, outBufSize - trailsize - 1); - b += len; - outBufSize -= len; + poststr(request, post); + poststr(request, htmlEnd); + poststr(request, NULL); - strcat_safe(outbuf, post, outBufSize); - strcat_safe(outbuf,htmlEnd,outBufSize); - - return strlen(outbuf); + return 0; } diff --git a/src/win_main.c b/src/win_main.c index 68aa50d72..3e350e208 100644 --- a/src/win_main.c +++ b/src/win_main.c @@ -138,13 +138,23 @@ int __cdecl main(void) iResult = recv(ClientSocket, recvbuf, recvbuflen, 0); if (iResult > 0) { int leen; - HTTP_ProcessPacket(recvbuf,outbuf,sizeof(outbuf)); - printf("Bytes received: %d\n", iResult); - printf("%s\n",outbuf); + http_request_t request; + memset(&request, 0, sizeof(request)); + + request.fd = ClientSocket; + request.received = recvbuf; + request.receivedLen = iResult; + request.reply = outbuf; + request.replymaxlen = DEFAULT_BUFLEN; + + int len = HTTP_ProcessPacket(&request); + + printf("Bytes received: %d tosend %d\n", iResult, len); + //printf("%s\n",outbuf); // Echo the buffer back to the sender - leen = strlen(outbuf); - iSendResult = send( ClientSocket, outbuf,leen, 0 ); + //leen = strlen(request.reply); + iSendResult = send( ClientSocket, outbuf,len, 0 ); if (iSendResult == SOCKET_ERROR) { printf("send failed with error: %d\n", WSAGetLastError()); closesocket(ClientSocket);