Skip to content

Commit

Permalink
ESP8266WebServer - StreamString parsing experiment
Browse files Browse the repository at this point in the history
impl based on esp8266#9005, but for existing Arduino methods
  • Loading branch information
mcspr committed Jul 26, 2024
1 parent c2f1365 commit 4255594
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 123 deletions.
54 changes: 33 additions & 21 deletions cores/esp8266/Stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@
parsing functions based on TextFinder library by Michael Margolis
*/

#include <Arduino.h>
#include <Stream.h>
#include "Arduino.h"
#include "Stream.h"
#include "StreamString.h"

#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait
#define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field
Expand Down Expand Up @@ -254,34 +255,45 @@ String Stream::readString() {

String Stream::readStringUntil(char terminator) {
String ret;
int c = timedRead();
while(c >= 0 && c != terminator) {
ret += (char) c;
c = timedRead();
}

S2Stream s2s(ret);
sendUntil(s2s, terminator, _timeout);

return ret;
}

String Stream::readStringUntil(const char* terminator, uint32_t untilTotalNumberOfOccurrences) {
String ret;
int c;
if (!untilTotalNumberOfOccurrences) {
return ret;
}

const size_t termLen = strlen_P(terminator);
if (!termLen) {
return ret;
}

S2Stream s2s(ret);
uint32_t occurrences = 0;
size_t termLen = strlen(terminator);
size_t termIndex = 0;
size_t index = 0;
const size_t tailLen = termLen - 1;

while ((c = timedRead()) > 0) {
ret += (char) c;
index++;
for (;;) {
sendUntil(s2s, terminator[tailLen], _timeout);
if (s2s.getLastSendReport() != Stream::Report::Success) {
break;
}

if ((ret.length() >= tailLen)
&& ((0 == tailLen) || (0 == memcmp_P(terminator, ret.end() - tailLen, tailLen))))
{
++occurrences;
}

if (terminator[termIndex] == c) {
if (++termIndex == termLen && ++occurrences == untilTotalNumberOfOccurrences) {
// don't include terminator in returned string
ret.remove(index - termIndex, termLen);
break;
if (untilTotalNumberOfOccurrences == occurrences) {
if (tailLen) {
ret.remove(ret.length() - tailLen);
}
} else {
termIndex = 0;
break;
}
}

Expand Down
26 changes: 9 additions & 17 deletions libraries/ESP8266WebServer/src/Parsing-impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,8 @@ static bool readBytesWithTimeout(typename ServerType::ClientType& client, size_t
template <typename ServerType>
typename ESP8266WebServerTemplate<ServerType>::ClientFuture ESP8266WebServerTemplate<ServerType>::_parseRequest(ClientType& client) {
// Read the first line of HTTP request
String req = client.readStringUntil('\r');
String req = client.readStringUntil("\r\n");
DBGWS("request: %s\n", req.c_str());
client.readStringUntil('\n');
//reset header value
for (int i = 0; i < _headerKeysCount; ++i) {
_currentHeaders[i].value.clear();
Expand Down Expand Up @@ -122,8 +121,7 @@ typename ESP8266WebServerTemplate<ServerType>::ClientFuture ESP8266WebServerTemp
uint32_t contentLength = 0;
//parse headers
while(1){
req = client.readStringUntil('\r');
client.readStringUntil('\n');
req = client.readStringUntil("\r\n");
if (req.isEmpty()) break; //no more headers
int headerDiv = req.indexOf(':');
if (headerDiv == -1){
Expand Down Expand Up @@ -198,8 +196,7 @@ typename ESP8266WebServerTemplate<ServerType>::ClientFuture ESP8266WebServerTemp
String headerValue;
//parse headers
while(1){
req = client.readStringUntil('\r');
client.readStringUntil('\n');
req = client.readStringUntil("\r\n");
if (req.isEmpty()) break;//no moar headers
int headerDiv = req.indexOf(':');
if (headerDiv == -1){
Expand Down Expand Up @@ -351,7 +348,7 @@ bool ESP8266WebServerTemplate<ServerType>::_parseForm(ClientType& client, const
String line;
int retry = 0;
do {
line = client.readStringUntil('\r');
line = client.readStringUntil("\r\n");
++retry;
} while (line.length() == 0 && retry < 3);

Expand All @@ -367,8 +364,7 @@ bool ESP8266WebServerTemplate<ServerType>::_parseForm(ClientType& client, const
String argFilename;
bool argIsFile = false;

line = client.readStringUntil('\r');
client.readStringUntil('\n');
line = client.readStringUntil("\r\n");
if (line.length() > 19 && line.substring(0, 19).equalsIgnoreCase(F("Content-Disposition"))){
int nameStart = line.indexOf('=');
if (nameStart != -1){
Expand All @@ -388,19 +384,16 @@ bool ESP8266WebServerTemplate<ServerType>::_parseForm(ClientType& client, const
DBGWS("PostArg Name: %s\n", argName.c_str());
using namespace mime;
argType = FPSTR(mimeTable[txt].mimeType);
line = client.readStringUntil('\r');
client.readStringUntil('\n');
line = client.readStringUntil("\r\n");
if (line.length() > 12 && line.substring(0, 12).equalsIgnoreCase(FPSTR(Content_Type))){
argType = line.substring(line.indexOf(':')+2);
//skip next line
client.readStringUntil('\r');
client.readStringUntil('\n');
client.readStringUntil("\r\n");
}
DBGWS("PostArg Type: %s\n", argType.c_str());
if (!argIsFile){
while(1){
line = client.readStringUntil('\r');
client.readStringUntil('\n');
line = client.readStringUntil("\r\n");
if (line.startsWith("--"+boundary)) break;
if (argValue.length() > 0) argValue += '\n';
argValue += line;
Expand Down Expand Up @@ -474,8 +467,7 @@ bool ESP8266WebServerTemplate<ServerType>::_parseForm(ClientType& client, const
_currentUpload->type.c_str(),
(int)_currentUpload->totalSize);
if (!client.connected()) return _parseFormUploadAborted();
line = client.readStringUntil('\r');
client.readStringUntil('\n');
line = client.readStringUntil("\r\n");
if (line == "--") { // extra two dashes mean we reached the end of all form fields
DBGWS("Done Parsing POST\n");
break;
Expand Down
26 changes: 26 additions & 0 deletions tests/host/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ GENHTML ?= genhtml
CXXFLAGS += -std=gnu++17
CFLAGS += -std=gnu17

# 32-bit mode is prefered, but not required
ifeq ($(FORCE32),1)
SIZEOFLONG = $(shell echo 'int main(){return sizeof(long);}'|$(CXX) -m32 -x c++ - -o sizeoflong 2>/dev/null && ./sizeoflong; echo $$?; rm -f sizeoflong;)
ifneq ($(SIZEOFLONG),4)
Expand All @@ -50,6 +51,7 @@ endif
OUTPUT_BINARY := $(BINDIR)/host_tests
LCOV_DIRECTORY := $(BINDIR)/../lcov

# Hide full build commands by default
ifeq ($(V), 0)
VERBC = @echo "C $@";
VERBCXX = @echo "C++ $@";
Expand All @@ -66,6 +68,30 @@ endif

$(shell mkdir -p $(BINDIR))

# Core files sometimes override libc functions, check when necessary to hide them
# TODO proper configure script / other build system?
ifeq (,$(wildcard $(BINDIR)/.have_strlcpy))
$(shell echo -e '#include <cstring>\nint main(){char a[4]{}; char b[4]{}; strlcpy(&a[0], &b[0], sizeof(a)); return 0;}' | \
$(CXX) -x c++ - -o $(BINDIR)/.have_strlcpy 2>/dev/null || ( echo -e '#!/bin/sh\nexit 1' > $(BINDIR)/.have_strlcpy ; chmod +x $(BINDIR)/.have_strlcpy; ))
endif

$(shell $(BINDIR)/.have_strlcpy)
ifeq ($(.SHELLSTATUS), 0)
FLAGS += -DHAVE_STRLCPY
endif

ifeq (,$(wildcard $(BINDIR)/.have_strlcat))
$(shell echo -e '#include <cstring>\nint main(){char a[4]{}; strlcat(&a[0], "test", sizeof(a)); return 0;}' | \
$(CXX) -x c++ - -o $(BINDIR)/.have_strlcat 2>/dev/null || ( echo -e '#!/bin/sh\nexit 1' > $(BINDIR)/.have_strlcat ; chmod +x $(BINDIR)/.have_strlcat; ))
endif

$(shell $(BINDIR)/.have_strlcat)
ifeq ($(.SHELLSTATUS), 0)
FLAGS += -DHAVE_STRLCAT
endif

# Actual build recipes

CORE_CPP_FILES := \
$(addprefix $(abspath $(CORE_PATH))/,\
debug.cpp \
Expand Down
15 changes: 10 additions & 5 deletions tests/host/common/mock.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,18 +56,23 @@
#define D8 8

#include <stddef.h>
#include <stdlib.h>
#include <string.h>

#include <stdlib_noniso.h>

#ifdef __cplusplus
extern "C"
{
#endif
// TODO: #include <stdlib_noniso.h> ?
char* itoa(int val, char* s, int radix);
char* ltoa(long val, char* s, int radix);

char* utoa(unsigned value, char* result, int base);
char* itoa(int value, char* result, int base);
#ifndef HAVE_STRLCAT
size_t strlcat(char* dst, const char* src, size_t size);
#endif
#ifndef HAVE_STRLCPY
size_t strlcpy(char* dst, const char* src, size_t size);

#endif
#ifdef __cplusplus
}
#endif
Expand Down
22 changes: 3 additions & 19 deletions tests/host/common/noniso.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@
#include <stdbool.h>
#include <stdint.h>
#include <math.h>
#include "stdlib_noniso.h"

void reverse(char* begin, char* end)
#include <stdlib_noniso.h>

static void reverse(char* begin, char* end)
{
char* is = begin;
char* ie = end - 1;
Expand Down Expand Up @@ -84,20 +85,3 @@ char* itoa(int value, char* result, int base)
utoa(uvalue, result, base);
return out;
}

int atoi(const char* s)
{
return (int)atol(s);
}

long atol(const char* s)
{
char* tmp;
return strtol(s, &tmp, 10);
}

double atof(const char* s)
{
char* tmp;
return strtod(s, &tmp);
}
Loading

0 comments on commit 4255594

Please sign in to comment.