From b8769bf5ebee82a957dfe08f828cef4ca4c4ac81 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Wed, 16 Dec 2015 00:32:17 +0100 Subject: [PATCH 1/2] HTTP Client move buffer (1460 Byte) from stack to heap. --- .../ReuseConnection/ReuseConnection.ino | 1 - .../src/ESP8266HTTPClient.cpp | 105 ++++++++++-------- .../ESP8266HTTPClient/src/ESP8266HTTPClient.h | 4 + 3 files changed, 63 insertions(+), 47 deletions(-) diff --git a/libraries/ESP8266HTTPClient/examples/ReuseConnection/ReuseConnection.ino b/libraries/ESP8266HTTPClient/examples/ReuseConnection/ReuseConnection.ino index 35babdc33..631b9494d 100644 --- a/libraries/ESP8266HTTPClient/examples/ReuseConnection/ReuseConnection.ino +++ b/libraries/ESP8266HTTPClient/examples/ReuseConnection/ReuseConnection.ino @@ -60,7 +60,6 @@ void loop() { } http.end(); - } delay(1000); diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp index 6a8d010e1..3a96e4327 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp @@ -30,7 +30,6 @@ #include "ESP8266HTTPClient.h" - /** * constractor */ @@ -117,7 +116,7 @@ void HTTPClient::begin(String url, String httpsFingerprint) { if(index >= 0) { // auth info String auth = host.substring(0, index); - host.remove(0, index +1); // remove auth part including @ + host.remove(0, index + 1); // remove auth part including @ _base64Authorization = base64::encode(auth); } @@ -336,7 +335,7 @@ int HTTPClient::sendRequest(const char * type, Stream * stream, size_t size) { } // create buffer for read - uint8_t buff[1460] = { 0 }; + uint8_t * buff = (uint8_t *) malloc(HTTP_TCP_BUFFER_SIZE); int len = size; int bytesWritten = 0; @@ -345,34 +344,40 @@ int HTTPClient::sendRequest(const char * type, Stream * stream, size_t size) { len = -1; } - // read all data from stream and send it to server - while(connected() && stream->available() && (len > 0 || len == -1)) { + if(buff) { + // read all data from stream and send it to server + while(connected() && stream->available() && (len > 0 || len == -1)) { - // get available data size - size_t s = stream->available(); + // get available data size + size_t s = stream->available(); - if(s) { - int c = stream->readBytes(buff, ((s > sizeof(buff)) ? sizeof(buff) : s)); + if(s) { + int c = stream->readBytes(buff, ((s > HTTP_TCP_BUFFER_SIZE) ? HTTP_TCP_BUFFER_SIZE : s)); - // write it to Stream - bytesWritten += _tcp->write((const uint8_t *)buff, c); + // write it to Stream + bytesWritten += _tcp->write((const uint8_t *) buff, c); - if(len > 0) { - len -= c; + if(len > 0) { + len -= c; + } + + delay(0); + } else { + delay(1); } - - delay(0); - } else { - delay(1); } - } - if(size && (int)size != bytesWritten) { - DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] Stream payload bytesWritten %d and size %d mismatch!.\n", bytesWritten, _size); - DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] ERROR SEND PAYLOAD FAILED!"); - return HTTPC_ERROR_SEND_PAYLOAD_FAILED; + if(size && (int) size != bytesWritten) { + DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] Stream payload bytesWritten %d and size %d mismatch!.\n", bytesWritten, _size); DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] ERROR SEND PAYLOAD FAILED!"); + free(buff); + return HTTPC_ERROR_SEND_PAYLOAD_FAILED; + } else { + DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] Stream payload written: %d\n", bytesWritten); + } + free(buff); } else { - DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] Stream payload written: %d\n", bytesWritten); + DEBUG_HTTPCLIENT("[HTTP-Client][writeToStream] too less ram! need " HTTP_TCP_BUFFER_SIZE); + return HTTPC_ERROR_TOO_LESS_RAM; } // handle Server Response (Header) @@ -434,37 +439,44 @@ int HTTPClient::writeToStream(Stream * stream) { int len = _size; int bytesWritten = 0; + // create buffer for read - uint8_t buff[1460] = { 0 }; + uint8_t * buff = (uint8_t *) malloc(HTTP_TCP_BUFFER_SIZE); - // read all data from server - while(connected() && (len > 0 || len == -1)) { + if(buff) { + // read all data from server + while(connected() && (len > 0 || len == -1)) { - // get available data size - size_t size = _tcp->available(); + // get available data size + size_t size = _tcp->available(); - if(size) { - int c = _tcp->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size)); + if(size) { + int c = _tcp->readBytes(buff, ((size > HTTP_TCP_BUFFER_SIZE) ? HTTP_TCP_BUFFER_SIZE : size)); - // write it to Stream - bytesWritten += stream->write(buff, c); + // write it to Stream + bytesWritten += stream->write(buff, c); - if(len > 0) { - len -= c; + if(len > 0) { + len -= c; + } + + delay(0); + } else { + delay(1); } - - delay(0); - } else { - delay(1); } + + free(buff); + + DEBUG_HTTPCLIENT("[HTTP-Client][writeToStream] connection closed or file end (written: %d).\n", bytesWritten); + + if(_size && _size != bytesWritten) { + DEBUG_HTTPCLIENT("[HTTP-Client][writeToStream] bytesWritten %d and size %d mismatch!.\n", bytesWritten, _size); + } + + } else { + DEBUG_HTTPCLIENT("[HTTP-Client][writeToStream] too less ram! need " HTTP_TCP_BUFFER_SIZE); } - - DEBUG_HTTPCLIENT("[HTTP-Client][writeToStream] connection closed or file end (written: %d).\n", bytesWritten); - - if(_size && _size != bytesWritten) { - DEBUG_HTTPCLIENT("[HTTP-Client][writeToStream] bytesWritten %d and size %d mismatch!.\n", bytesWritten, _size); - } - end(); return bytesWritten; } @@ -509,12 +521,13 @@ String HTTPClient::errorToString(int error) { return String("no stream"); case HTTPC_ERROR_NO_HTTP_SERVER: return String("no HTTP server"); + case HTTPC_ERROR_TOO_LESS_RAM: + return String("too less ram"); default: return String(); } } - /** * adds Header to the request * @param name diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h index 2bf6d0565..5f7490f86 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h @@ -41,6 +41,10 @@ #define HTTPC_ERROR_CONNECTION_LOST (-5) #define HTTPC_ERROR_NO_STREAM (-6) #define HTTPC_ERROR_NO_HTTP_SERVER (-7) +#define HTTPC_ERROR_TOO_LESS_RAM (-8) + +/// size for the stream handling +#define HTTP_TCP_BUFFER_SIZE (1460) /// HTTP codes see RFC7231 typedef enum { From b9d0807a56a924a83d63bab57f2919bb5730c2b3 Mon Sep 17 00:00:00 2001 From: Markus Sattler Date: Wed, 16 Dec 2015 00:48:35 +0100 Subject: [PATCH 2/2] only malloc needed ram if we know the response size and its less then 1460 --- .../src/ESP8266HTTPClient.cpp | 34 ++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp index 3a96e4327..5cddaf616 100644 --- a/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp +++ b/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp @@ -334,8 +334,7 @@ int HTTPClient::sendRequest(const char * type, Stream * stream, size_t size) { return HTTPC_ERROR_SEND_HEADER_FAILED; } - // create buffer for read - uint8_t * buff = (uint8_t *) malloc(HTTP_TCP_BUFFER_SIZE); + size_t buff_size = HTTP_TCP_BUFFER_SIZE; int len = size; int bytesWritten = 0; @@ -344,6 +343,15 @@ int HTTPClient::sendRequest(const char * type, Stream * stream, size_t size) { len = -1; } + // if possible create smaller buffer then HTTP_TCP_BUFFER_SIZE + if((len > 0) && (len < HTTP_TCP_BUFFER_SIZE)) { + buff_size = len; + } + + // create buffer for read + uint8_t * buff = (uint8_t *) malloc(buff_size); + + if(buff) { // read all data from stream and send it to server while(connected() && stream->available() && (len > 0 || len == -1)) { @@ -352,7 +360,7 @@ int HTTPClient::sendRequest(const char * type, Stream * stream, size_t size) { size_t s = stream->available(); if(s) { - int c = stream->readBytes(buff, ((s > HTTP_TCP_BUFFER_SIZE) ? HTTP_TCP_BUFFER_SIZE : s)); + int c = stream->readBytes(buff, ((s > buff_size) ? buff_size : s)); // write it to Stream bytesWritten += _tcp->write((const uint8_t *) buff, c); @@ -367,14 +375,16 @@ int HTTPClient::sendRequest(const char * type, Stream * stream, size_t size) { } } + free(buff); + if(size && (int) size != bytesWritten) { - DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] Stream payload bytesWritten %d and size %d mismatch!.\n", bytesWritten, _size); DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] ERROR SEND PAYLOAD FAILED!"); - free(buff); + DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] Stream payload bytesWritten %d and size %d mismatch!.\n", bytesWritten, _size); + DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] ERROR SEND PAYLOAD FAILED!"); return HTTPC_ERROR_SEND_PAYLOAD_FAILED; } else { DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] Stream payload written: %d\n", bytesWritten); } - free(buff); + } else { DEBUG_HTTPCLIENT("[HTTP-Client][writeToStream] too less ram! need " HTTP_TCP_BUFFER_SIZE); return HTTPC_ERROR_TOO_LESS_RAM; @@ -439,9 +449,15 @@ int HTTPClient::writeToStream(Stream * stream) { int len = _size; int bytesWritten = 0; + size_t buff_size = HTTP_TCP_BUFFER_SIZE; + + // if possible create smaller buffer then HTTP_TCP_BUFFER_SIZE + if((len > 0) && (len < HTTP_TCP_BUFFER_SIZE)) { + buff_size = len; + } // create buffer for read - uint8_t * buff = (uint8_t *) malloc(HTTP_TCP_BUFFER_SIZE); + uint8_t * buff = (uint8_t *) malloc(buff_size); if(buff) { // read all data from server @@ -451,7 +467,7 @@ int HTTPClient::writeToStream(Stream * stream) { size_t size = _tcp->available(); if(size) { - int c = _tcp->readBytes(buff, ((size > HTTP_TCP_BUFFER_SIZE) ? HTTP_TCP_BUFFER_SIZE : size)); + int c = _tcp->readBytes(buff, ((size > buff_size) ? buff_size : size)); // write it to Stream bytesWritten += stream->write(buff, c); @@ -476,7 +492,9 @@ int HTTPClient::writeToStream(Stream * stream) { } else { DEBUG_HTTPCLIENT("[HTTP-Client][writeToStream] too less ram! need " HTTP_TCP_BUFFER_SIZE); + return HTTPC_ERROR_TOO_LESS_RAM; } + end(); return bytesWritten; }