Skip to content

Commit bd7d915

Browse files
committed
rework error handling and detection
add retry for short write remove compiler warnings
1 parent 7540f11 commit bd7d915

File tree

2 files changed

+97
-21
lines changed

2 files changed

+97
-21
lines changed

libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp

+93-18
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ int HTTPClient::POST(String payload) {
298298
int HTTPClient::sendRequest(const char * type, uint8_t * payload, size_t size) {
299299
// connect to server
300300
if(!connect()) {
301-
return HTTPC_ERROR_CONNECTION_REFUSED;
301+
return returnError(HTTPC_ERROR_CONNECTION_REFUSED);
302302
}
303303

304304
if(payload && size > 0) {
@@ -307,18 +307,18 @@ int HTTPClient::sendRequest(const char * type, uint8_t * payload, size_t size) {
307307

308308
// send Header
309309
if(!sendHeader(type)) {
310-
return HTTPC_ERROR_SEND_HEADER_FAILED;
310+
return returnError(HTTPC_ERROR_SEND_HEADER_FAILED);
311311
}
312312

313313
// send Payload if needed
314314
if(payload && size > 0) {
315315
if(_tcp->write(&payload[0], size) != size) {
316-
return HTTPC_ERROR_SEND_PAYLOAD_FAILED;
316+
return returnError(HTTPC_ERROR_SEND_PAYLOAD_FAILED);
317317
}
318318
}
319319

320320
// handle Server Response (Header)
321-
return handleHeaderResponse();
321+
return returnError(handleHeaderResponse());
322322
}
323323

324324
/**
@@ -348,7 +348,7 @@ int HTTPClient::sendRequest(const char * type, Stream * stream, size_t size) {
348348
return HTTPC_ERROR_SEND_HEADER_FAILED;
349349
}
350350

351-
size_t buff_size = HTTP_TCP_BUFFER_SIZE;
351+
int buff_size = HTTP_TCP_BUFFER_SIZE;
352352

353353
int len = size;
354354
int bytesWritten = 0;
@@ -371,7 +371,7 @@ int HTTPClient::sendRequest(const char * type, Stream * stream, size_t size) {
371371
while(connected() && (stream->available() > -1) && (len > 0 || len == -1)) {
372372

373373
// get available data size
374-
size_t s = stream->available();
374+
int s = stream->available();
375375

376376
if(len) {
377377
s = ((s > len) ? len : s);
@@ -461,11 +461,11 @@ WiFiClient * HTTPClient::getStreamPtr(void) {
461461
int HTTPClient::writeToStream(Stream * stream) {
462462

463463
if(!stream) {
464-
return HTTPC_ERROR_NO_STREAM;
464+
return returnError(HTTPC_ERROR_NO_STREAM);
465465
}
466466

467467
if(!connected()) {
468-
return HTTPC_ERROR_NOT_CONNECTED;
468+
return returnError(HTTPC_ERROR_NOT_CONNECTED);
469469
}
470470

471471
// get length of document (is -1 when Server sends no Content-Length header)
@@ -474,28 +474,56 @@ int HTTPClient::writeToStream(Stream * stream) {
474474

475475
if(_transferEncoding == HTTPC_TE_IDENTITY) {
476476
ret = writeToStreamDataBlock(stream, len);
477+
478+
// have we an error?
479+
if(ret < 0) {
480+
return returnError(ret);
481+
}
477482
} else if(_transferEncoding == HTTPC_TE_CHUNKED) {
483+
int size = 0;
478484
while(1) {
485+
if(!connected()) {
486+
return returnError(HTTPC_ERROR_CONNECTION_LOST);
487+
}
479488
String chunkHeader = _tcp->readStringUntil('\n');
489+
490+
if(chunkHeader.length() <= 0) {
491+
return returnError(HTTPC_ERROR_READ_TIMEOUT);
492+
}
493+
480494
chunkHeader.trim(); // remove \r
481495

482496
// read size of chunk
483497
len = (uint32_t) strtol((const char *) chunkHeader.c_str(), NULL, 16);
498+
size += len;
484499
DEBUG_HTTPCLIENT("[HTTP-Client] read chunk len: %d\n", len);
500+
501+
// data left?
485502
if(len > 0) {
486503
int r = writeToStreamDataBlock(stream, len);
487504
if(r < 0) {
488505
// error in writeToStreamDataBlock
489-
return r;
506+
return returnError(r);
490507
}
491508
ret += r;
492509
} else {
510+
511+
// if no length Header use global chunk size
512+
if(_size <= 0) {
513+
_size = size;
514+
}
515+
516+
// check if we have write all data out
517+
if(ret != _size) {
518+
return returnError(HTTPC_ERROR_STREAM_WRITE);
519+
}
493520
break;
494521
}
522+
495523
delay(0);
496524
}
497525
} else {
498-
return HTTPC_ERROR_ENCODING;
526+
return returnError(HTTPC_ERROR_ENCODING);
499527
}
500528

501529
end();
@@ -546,6 +574,10 @@ String HTTPClient::errorToString(int error) {
546574
return String("too less ram");
547575
case HTTPC_ERROR_ENCODING:
548576
return String("Transfer-Encoding not supported");
577+
case HTTPC_ERROR_STREAM_WRITE:
578+
return String("Stream write error");
579+
case HTTPC_ERROR_READ_TIMEOUT:
580+
return String("read Timeout");
549581
default:
550582
return String();
551583
}
@@ -829,23 +861,50 @@ int HTTPClient::writeToStreamDataBlock(Stream * stream, int size) {
829861
}
830862

831863
// read data
832-
int c = _tcp->readBytes(buff, readBytes);
864+
int bytesRead = _tcp->readBytes(buff, readBytes);
833865

834866
// write it to Stream
835-
int w = stream->write(buff, c);
836-
bytesWritten += w;
837-
if(w != c) {
838-
DEBUG_HTTPCLIENT("[HTTP-Client][writeToStreamDataBlock] short write asked for %d but got %d\n", c, w);
839-
break;
867+
int bytesWrite = stream->write(buff, bytesRead);
868+
bytesWritten += bytesWrite;
869+
870+
// are all Bytes a writen to stream ?
871+
if(bytesWrite != bytesRead) {
872+
DEBUG_HTTPCLIENT("[HTTP-Client][writeToStream] short write asked for %d but got %d retry...\n", bytesRead, bytesWrite);
873+
874+
// check for write error
875+
if(stream->getWriteError()) {
876+
DEBUG_HTTPCLIENT("[HTTP-Client][writeToStreamDataBlock] stream write error %d\n", stream->getWriteError());
877+
878+
//reset write error for retry
879+
stream->clearWriteError();
880+
}
881+
882+
// some time for the stream
883+
delay(1);
884+
885+
int leftBytes = (readBytes - bytesWrite);
886+
887+
// retry to send the missed bytes
888+
bytesWrite = stream->write((buff + bytesWrite), leftBytes);
889+
bytesWritten += bytesWrite;
890+
891+
if(bytesWrite != leftBytes) {
892+
// failed again
893+
DEBUG_HTTPCLIENT("[HTTP-Client][writeToStream] short write asked for %d but got %d failed.\n", leftBytes, bytesWrite);
894+
free(buff);
895+
return HTTPC_ERROR_STREAM_WRITE;
896+
}
840897
}
841898

899+
// check for write error
842900
if(stream->getWriteError()) {
843901
DEBUG_HTTPCLIENT("[HTTP-Client][writeToStreamDataBlock] stream write error %d\n", stream->getWriteError());
844-
break;
902+
return HTTPC_ERROR_STREAM_WRITE;
845903
}
846904

905+
// count bytes to read left
847906
if(len > 0) {
848-
len -= c;
907+
len -= readBytes;
849908
}
850909

851910
delay(0);
@@ -869,3 +928,19 @@ int HTTPClient::writeToStreamDataBlock(Stream * stream, int size) {
869928

870929
return bytesWritten;
871930
}
931+
932+
/**
933+
* called to handle error return, may disconnect the connection if still exists
934+
* @param error
935+
* @return error
936+
*/
937+
int HTTPClient::returnError(int error) {
938+
if(error < 0) {
939+
DEBUG_HTTPCLIENT("[HTTP-Client][returnError] error(%d): %s\n", error, errorToString(error).c_str());
940+
if(connected()) {
941+
DEBUG_HTTPCLIENT("[HTTP-Client][returnError] tcp stop\n");
942+
_tcp->stop();
943+
}
944+
}
945+
return error;
946+
}

libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
#ifndef ESP8266HTTPClient_H_
2626
#define ESP8266HTTPClient_H_
2727

28-
//#define DEBUG_HTTPCLIENT(...) Serial1.printf( __VA_ARGS__ )
28+
#define DEBUG_HTTPCLIENT(...) Serial1.printf( __VA_ARGS__ )
2929

3030
#ifndef DEBUG_HTTPCLIENT
3131
#define DEBUG_HTTPCLIENT(...)
@@ -43,7 +43,8 @@
4343
#define HTTPC_ERROR_NO_HTTP_SERVER (-7)
4444
#define HTTPC_ERROR_TOO_LESS_RAM (-8)
4545
#define HTTPC_ERROR_ENCODING (-9)
46-
46+
#define HTTPC_ERROR_STREAM_WRITE (-10)
47+
#define HTTPC_ERROR_READ_TIMEOUT (-11)
4748

4849
/// size for the stream handling
4950
#define HTTP_TCP_BUFFER_SIZE (1460)
@@ -197,7 +198,7 @@ class HTTPClient {
197198
bool _canReuse;
198199
transferEncoding_t _transferEncoding;
199200

200-
201+
int returnError(int error);
201202
bool connect(void);
202203
bool sendHeader(const char * type);
203204
int handleHeaderResponse();

0 commit comments

Comments
 (0)