Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Honor timeout in HTTPClient #6056

Merged
merged 5 commits into from
May 6, 2019
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -63,31 +63,35 @@ void loop() {
// create buffer for read
uint8_t buff[128] = { 0 };

#if 0
// with API
Serial.println(http.getString());
#else
// or "by hand"

// get tcp stream
WiFiClient * stream = &client;

// read all data from server
while (http.connected() && (len > 0 || len == -1)) {
// get available data size
size_t size = stream->available();

if (size) {
// read up to 128 byte
int c = stream->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size));
// read up to 128 byte
int c = stream->readBytes(buff, std::min((size_t)len, sizeof(buff)));
Serial.printf("readBytes: %d\n", c);
if (!c) {
Serial.println("read timeout");
}

// write it to Serial
Serial.write(buff, c);
// write it to Serial
Serial.write(buff, c);

if (len > 0) {
len -= c;
}
if (len > 0) {
len -= c;
}
delay(1);
}
#endif

Serial.println();
Serial.print("[HTTP] connection closed or file end.\n");

}
} else {
Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
Expand All @@ -96,5 +100,5 @@ void loop() {
http.end();
}

delay(10000);
delay(60000);
}
136 changes: 64 additions & 72 deletions libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -847,7 +847,7 @@ int HTTPClient::sendRequest(const char * type, Stream * stream, size_t size)
}

} else {
DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] too less ram! need %d\n", HTTP_TCP_BUFFER_SIZE);
DEBUG_HTTPCLIENT("[HTTP-Client][sendRequest] not enough ram! need %d\n", HTTP_TCP_BUFFER_SIZE);
return returnError(HTTPC_ERROR_TOO_LESS_RAM);
}

Expand Down Expand Up @@ -1033,7 +1033,7 @@ String HTTPClient::errorToString(int error)
case HTTPC_ERROR_NO_HTTP_SERVER:
return F("no HTTP server");
case HTTPC_ERROR_TOO_LESS_RAM:
return F("too less ram");
return F("not enough ram");
case HTTPC_ERROR_ENCODING:
return F("Transfer-Encoding not supported");
case HTTPC_ERROR_STREAM_WRITE:
Expand Down Expand Up @@ -1346,7 +1346,7 @@ int HTTPClient::handleHeaderResponse()
int HTTPClient::writeToStreamDataBlock(Stream * stream, int size)
{
int buff_size = HTTP_TCP_BUFFER_SIZE;
int len = size;
int len = size; // left size to read
int bytesWritten = 0;

// if possible create smaller buffer then HTTP_TCP_BUFFER_SIZE
Expand All @@ -1357,93 +1357,85 @@ int HTTPClient::writeToStreamDataBlock(Stream * stream, int size)
// create buffer for read
uint8_t * buff = (uint8_t *) malloc(buff_size);

if(buff) {
// read all data from server
while(connected() && (len > 0 || len == -1)) {

// get available data size
size_t sizeAvailable = _client->available();

if(sizeAvailable) {

int readBytes = sizeAvailable;

// read only the asked bytes
if(len > 0 && readBytes > len) {
readBytes = len;
}
if(!buff) {
DEBUG_HTTPCLIENT("[HTTP-Client][writeToStreamDataBlock] not enough ram! need %d\n", HTTP_TCP_BUFFER_SIZE);
return HTTPC_ERROR_TOO_LESS_RAM;
}

// not read more the buffer can handle
if(readBytes > buff_size) {
readBytes = buff_size;
}
// read all data from server
while(connected() && (len > 0 || len == -1))
{
int readBytes = len;

// read data
int bytesRead = _client->readBytes(buff, readBytes);
// not read more the buffer can handle
if(readBytes > buff_size) {
readBytes = buff_size;
}

// write it to Stream
int bytesWrite = stream->write(buff, bytesRead);
bytesWritten += bytesWrite;
// read data
int bytesRead = _client->readBytes(buff, readBytes);
if (!bytesRead)
{
DEBUG_HTTPCLIENT("[HTTP-Client][writeToStreamDataBlock] input stream timeout\n");
free(buff);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using above:

std::unique_ptr<uint8_t[]> buff(new uint8_t[buff_size]);

above instead of the malloc, and removing the three free(buff) calls

return HTTPC_ERROR_READ_TIMEOUT;
}

// are all Bytes a writen to stream ?
if(bytesWrite != bytesRead) {
DEBUG_HTTPCLIENT("[HTTP-Client][writeToStream] short write asked for %d but got %d retry...\n", bytesRead, bytesWrite);
// write it to Stream
int bytesWrite = stream->write(buff, bytesRead);
bytesWritten += bytesWrite;

// check for write error
if(stream->getWriteError()) {
DEBUG_HTTPCLIENT("[HTTP-Client][writeToStreamDataBlock] stream write error %d\n", stream->getWriteError());
// are all Bytes a writen to stream ?
if(bytesWrite != bytesRead) {
DEBUG_HTTPCLIENT("[HTTP-Client][writeToStream] short write asked for %d but got %d retry...\n", bytesRead, bytesWrite);

//reset write error for retry
stream->clearWriteError();
}
// check for write error
if(stream->getWriteError()) {
DEBUG_HTTPCLIENT("[HTTP-Client][writeToStreamDataBlock] stream write error %d\n", stream->getWriteError());

// some time for the stream
delay(1);
//reset write error for retry
stream->clearWriteError();
}

int leftBytes = (readBytes - bytesWrite);
// some time for the stream
delay(1);

// retry to send the missed bytes
bytesWrite = stream->write((buff + bytesWrite), leftBytes);
bytesWritten += bytesWrite;
int leftBytes = (bytesRead - bytesWrite);

if(bytesWrite != leftBytes) {
// failed again
DEBUG_HTTPCLIENT("[HTTP-Client][writeToStream] short write asked for %d but got %d failed.\n", leftBytes, bytesWrite);
free(buff);
return HTTPC_ERROR_STREAM_WRITE;
}
}
// retry to send the missed bytes
bytesWrite = stream->write((buff + bytesWrite), leftBytes);
bytesWritten += bytesWrite;

// check for write error
if(stream->getWriteError()) {
DEBUG_HTTPCLIENT("[HTTP-Client][writeToStreamDataBlock] stream write error %d\n", stream->getWriteError());
free(buff);
return HTTPC_ERROR_STREAM_WRITE;
}
if(bytesWrite != leftBytes) {
// failed again
DEBUG_HTTPCLIENT("[HTTP-Client][writeToStream] short write asked for %d but got %d failed.\n", leftBytes, bytesWrite);
free(buff);
return HTTPC_ERROR_STREAM_WRITE;
}
}

// count bytes to read left
if(len > 0) {
len -= readBytes;
}
// check for write error
if(stream->getWriteError()) {
DEBUG_HTTPCLIENT("[HTTP-Client][writeToStreamDataBlock] stream write error %d\n", stream->getWriteError());
free(buff);
return HTTPC_ERROR_STREAM_WRITE;
}

delay(0);
} else {
delay(1);
}
// count bytes to read left
if(len > 0) {
len -= bytesRead;
}

free(buff);
delay(0);
}

DEBUG_HTTPCLIENT("[HTTP-Client][writeToStreamDataBlock] connection closed or file end (written: %d).\n", bytesWritten);
free(buff);

if((size > 0) && (size != bytesWritten)) {
DEBUG_HTTPCLIENT("[HTTP-Client][writeToStreamDataBlock] bytesWritten %d and size %d mismatch!.\n", bytesWritten, size);
return HTTPC_ERROR_STREAM_WRITE;
}
DEBUG_HTTPCLIENT("[HTTP-Client][writeToStreamDataBlock] connection closed or file end (written: %d).\n", bytesWritten);

} else {
DEBUG_HTTPCLIENT("[HTTP-Client][writeToStreamDataBlock] too less ram! need %d\n", HTTP_TCP_BUFFER_SIZE);
return HTTPC_ERROR_TOO_LESS_RAM;
if((size > 0) && (size != bytesWritten)) {
DEBUG_HTTPCLIENT("[HTTP-Client][writeToStreamDataBlock] bytesWritten %d and size %d mismatch!.\n", bytesWritten, size);
return HTTPC_ERROR_STREAM_WRITE;
}

return bytesWritten;
Expand Down