Skip to content
This repository was archived by the owner on Feb 4, 2023. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,21 @@
---
---


*****
Added a destructive C string interface to send

if called with
request->send(200, textPlainStr, ArduinoStr); // no difference
request->send(200, textPlainStr, cStr); // no differfence
request->send(200, textPlainStr, cStr, false); // this will have to be a cString with enough space to fit the header, it will be memmoved as required, header added, and sent, without creating any large arduino Strings that consume heap

in my application max heap size went from 375k to 66k (which is the lowest possible wit the variables and otehr data I am using)

Seems to work, let me know what you think



## Table of contents

* [Table of contents](#table-of-contents)
Expand Down
18 changes: 18 additions & 0 deletions src/Portenta_H7_AsyncWebRequest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1101,6 +1101,13 @@ void AsyncWebServerRequest::send(AsyncWebServerResponse *response)
}
}

//RSMOD///////////////////////////////////////////////

AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(int code, const String& contentType, const char * content)
{
return new AsyncBasicResponse(code, contentType, content);
}

/////////////////////////////////////////////////

AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(int code, const String& contentType, const String& content)
Expand Down Expand Up @@ -1139,6 +1146,17 @@ AsyncResponseStream * AsyncWebServerRequest::beginResponseStream(const String& c
return new AsyncResponseStream(contentType, bufferSize);
}

//RSMOD///////////////////////////////////////////////

void AsyncWebServerRequest::send(int code, const String& contentType, const char *content, bool nonDetructiveSend)
{
if (nonDetructiveSend == true) {
send(beginResponse(code, contentType, String(content))); // for backwards compatibility
} else {
send(beginResponse(code, contentType, content));
}
}

/////////////////////////////////////////////////

void AsyncWebServerRequest::send(int code, const String& contentType, const String& content)
Expand Down
2 changes: 2 additions & 0 deletions src/Portenta_H7_AsyncWebResponseImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,11 @@ class AsyncBasicResponse: public AsyncWebServerResponse
{
private:
String _content;
char *_contentCstr; // RSMOD

public:
AsyncBasicResponse(int code, const String& contentType = String(), const String& content = String());
AsyncBasicResponse(int code, const String& contentType, const char *content); // RSMOD
void _respond(AsyncWebServerRequest *request);

size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time);
Expand Down
173 changes: 152 additions & 21 deletions src/Portenta_H7_AsyncWebResponses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,31 @@ size_t AsyncWebServerResponse::_ack(AsyncWebServerRequest *request, size_t len,
return 0;
}


//RSMOD///////////////////////////////////////////////

/*
String/Code Response
* */
AsyncBasicResponse::AsyncBasicResponse(int code, const String& contentType, const char *content)
{
_code = code;
_content = String("");
_contentCstr = (char *)content;
_contentType = contentType;
int iLen;

if ((iLen = strlen(_contentCstr)))
{
_contentLength = iLen;

if (!_contentType.length())
_contentType = "text/plain";
}

addHeader("Connection", "close");
}

/////////////////////////////////////////////////

/*
Expand All @@ -256,6 +281,7 @@ AsyncBasicResponse::AsyncBasicResponse(int code, const String& contentType, cons
{
_code = code;
_content = content;
_contentCstr = NULL; // RSMOD
_contentType = contentType;

if (_content.length())
Expand All @@ -277,43 +303,113 @@ void AsyncBasicResponse::_respond(AsyncWebServerRequest *request)
String out = _assembleHead(request->version());
size_t outLen = out.length();
size_t space = request->client()->space();

// Serial.println("");
// Serial.println("");
// Serial.println("");
// Serial.println("");;
// Serial.println("Pre _respond\n");
// Serial.print("_contentLength =");
// Serial.println(_contentLength);
// Serial.print("out=");
// Serial.println(out);
// Serial.print("outLen=");
// Serial.println(outLen);
//// Serial.println("_contentCstr=");
//// Serial.println(_contentCstr);

if (!_contentLength && space >= outLen)
{
// Serial.println("");
// Serial.println("In A ******");
// Serial.println("");
_writtenLength += request->client()->write(out.c_str(), outLen);
_state = RESPONSE_WAIT_ACK;
}
else if (_contentLength && space >= outLen + _contentLength)
{
out += _content;
outLen += _contentLength;
_writtenLength += request->client()->write(out.c_str(), outLen);
// Serial.println("");
// Serial.println("In B ******");
// Serial.println("");
if (_contentCstr) {
memmove(&_contentCstr[outLen], _contentCstr, _contentLength);
memcpy(_contentCstr, out.c_str(), outLen);
outLen += _contentLength;
// Serial.print(_contentCstr);
_writtenLength += request->client()->write(_contentCstr, outLen);
} else {
out += _content;
outLen += _contentLength;
_writtenLength += request->client()->write(out.c_str(), outLen);
}
_state = RESPONSE_WAIT_ACK;
}
else if (space && space < outLen)
{
String partial = out.substring(0, space);
_content = out.substring(space) + _content;
_contentLength += outLen - space;
_writtenLength += request->client()->write(partial.c_str(), partial.length());
String partial = out.substring(0, space);
// Serial.println("");
// Serial.println("In C ******");
// Serial.println("");
if (_contentCstr) {
int deltaLen = out.length() - partial.length();
memmove(&_contentCstr[deltaLen], _contentCstr, deltaLen);
memcpy(_contentCstr, out.substring(space).c_str(), deltaLen);
} else {
_content = out.substring(space) + _content;
}
_contentLength += outLen - space;
// Serial.print(partial);
_writtenLength += request->client()->write(partial.c_str(), partial.length());
_state = RESPONSE_CONTENT;
}
else if (space > outLen && space < (outLen + _contentLength))
{
size_t shift = space - outLen;
outLen += shift;
_sentLength += shift;
out += _content.substring(0, shift);
_content = _content.substring(shift);
_writtenLength += request->client()->write(out.c_str(), outLen);
size_t shift = space - outLen;
// Serial.println("");
// Serial.println("In D ******");
// Serial.println("");

outLen += shift;
_sentLength += shift;
if (_contentCstr) {
char *s = (char *)malloc(shift +1);
strncpy(s, _contentCstr, shift);
s[shift] = '\0';
out += String(s);
_contentCstr += shift;
free(s);
} else {
out += _content.substring(0, shift);
_content = _content.substring(shift);
}
// Serial.print(out);
_writtenLength += request->client()->write(out.c_str(), outLen);
_state = RESPONSE_CONTENT;
}
else
{
_content = out + _content;
_contentLength += outLen;
// Serial.println("");
// Serial.println("In E ******");
// Serial.println("");
if (_contentCstr) {
memmove(&_contentCstr[outLen], _contentCstr, _contentLength);
memcpy(_contentCstr, out.c_str(), outLen);
} else {
_content = out + _content;
}
_contentLength += outLen;
_state = RESPONSE_CONTENT;
}

// Serial.print("\n\n\n\n\n\n\nPost _respond\n");
// Serial.print("_contentLength =");
// Serial.println(_contentLength);
// Serial.print("out=");
// Serial.println(out);
// Serial.print("outLen=");
// Serial.println(outLen);
//// Serial.println("_contentCstr=");
//// Serial.println(_contentCstr);
}

/////////////////////////////////////////////////
Expand All @@ -322,28 +418,58 @@ size_t AsyncBasicResponse::_ack(AsyncWebServerRequest *request, size_t len, uint
{
PORTENTA_H7_AWS_UNUSED(time);

// Serial.print("\n\n\n\n\n\n\nPre _ack\n");
// Serial.print("_contentLength =");
// Serial.print(_contentLength);

_ackedLength += len;

if (_state == RESPONSE_CONTENT)
{
String out;
size_t available = _contentLength - _sentLength;
size_t space = request->client()->space();

// Serial.print(" available=");
// Serial.print(available);
// Serial.print(" space =");
// Serial.print(space);


//we can fit in this packet
if (space > available)
{
_writtenLength += request->client()->write(_content.c_str(), available);
_content = String();
// Serial.println("In space>available");
if (_contentCstr) {
// Serial.println("output=");
// Serial.println(_contentCstr);
_writtenLength += request->client()->write(_contentCstr, available);
//_contentCstr[0] = '\0';
} else {
_writtenLength += request->client()->write(_content.c_str(), available);
_content = String();
}
_state = RESPONSE_WAIT_ACK;

return available;
}

//send some data, the rest on ack
String out = _content.substring(0, space);
_content = _content.substring(space);
_sentLength += space;
_writtenLength += request->client()->write(out.c_str(), space);
if (_contentCstr) {
char *s = (char *)malloc(space +1);
strncpy(s, _contentCstr, space);
s[space] = '\0';
out = String(s);
_contentCstr += space;
free(s);
} else {
out = _content.substring(0, space);
_content = _content.substring(space);
}
_sentLength += space;
// Serial.println("output=");
// Serial.println(out);
_writtenLength += request->client()->write(out.c_str(), space);

return space;
}
Expand All @@ -354,6 +480,11 @@ size_t AsyncBasicResponse::_ack(AsyncWebServerRequest *request, size_t len, uint
_state = RESPONSE_END;
}
}

// Serial.print("\n\n\n\n\n\n\npost _ack");
// Serial.print("_contentLength =");
// Serial.print(_contentLength);
// Serial.print(_contentCstr);

return 0;
}
Expand Down
2 changes: 2 additions & 0 deletions src/Portenta_H7_AsyncWebServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -340,12 +340,14 @@ class AsyncWebServerRequest

void send(AsyncWebServerResponse *response);
void send(int code, const String& contentType = String(), const String& content = String());
void send(int code, const String& contentType, const char *content, bool nonDetructiveSend = true); // RSMOD

void send(Stream &stream, const String& contentType, size_t len, AwsTemplateProcessor callback = nullptr);
void send(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr);
void sendChunked(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr);

AsyncWebServerResponse *beginResponse(int code, const String& contentType = String(), const String& content = String());
AsyncWebServerResponse *beginResponse(int code, const String& contentType, const char * content); // RSMOD

AsyncWebServerResponse *beginResponse(Stream &stream, const String& contentType, size_t len, AwsTemplateProcessor callback = nullptr);
AsyncWebServerResponse *beginResponse(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback = nullptr);
Expand Down