Skip to content

Commit

Permalink
Honor timeout in HTTPClient (#6056)
Browse files Browse the repository at this point in the history
* check for timeout in ESP8266HTTPClient::writeToStreamDataBlock
  • Loading branch information
d-a-v authored May 6, 2019
1 parent ac53c29 commit e67cc90
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 86 deletions.
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);
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

0 comments on commit e67cc90

Please sign in to comment.