1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-19 23:22:16 +03:00

rework error handling and detection

add retry for short write
remove compiler warnings
This commit is contained in:
Markus Sattler 2015-12-31 12:00:26 +01:00
parent 7540f11c93
commit bd7d915bcd
2 changed files with 97 additions and 21 deletions

View File

@ -298,7 +298,7 @@ int HTTPClient::POST(String payload) {
int HTTPClient::sendRequest(const char * type, uint8_t * payload, size_t size) {
// connect to server
if(!connect()) {
return HTTPC_ERROR_CONNECTION_REFUSED;
return returnError(HTTPC_ERROR_CONNECTION_REFUSED);
}
if(payload && size > 0) {
@ -307,18 +307,18 @@ int HTTPClient::sendRequest(const char * type, uint8_t * payload, size_t size) {
// send Header
if(!sendHeader(type)) {
return HTTPC_ERROR_SEND_HEADER_FAILED;
return returnError(HTTPC_ERROR_SEND_HEADER_FAILED);
}
// send Payload if needed
if(payload && size > 0) {
if(_tcp->write(&payload[0], size) != size) {
return HTTPC_ERROR_SEND_PAYLOAD_FAILED;
return returnError(HTTPC_ERROR_SEND_PAYLOAD_FAILED);
}
}
// handle Server Response (Header)
return handleHeaderResponse();
return returnError(handleHeaderResponse());
}
/**
@ -348,7 +348,7 @@ int HTTPClient::sendRequest(const char * type, Stream * stream, size_t size) {
return HTTPC_ERROR_SEND_HEADER_FAILED;
}
size_t buff_size = HTTP_TCP_BUFFER_SIZE;
int buff_size = HTTP_TCP_BUFFER_SIZE;
int len = size;
int bytesWritten = 0;
@ -371,7 +371,7 @@ int HTTPClient::sendRequest(const char * type, Stream * stream, size_t size) {
while(connected() && (stream->available() > -1) && (len > 0 || len == -1)) {
// get available data size
size_t s = stream->available();
int s = stream->available();
if(len) {
s = ((s > len) ? len : s);
@ -461,11 +461,11 @@ WiFiClient * HTTPClient::getStreamPtr(void) {
int HTTPClient::writeToStream(Stream * stream) {
if(!stream) {
return HTTPC_ERROR_NO_STREAM;
return returnError(HTTPC_ERROR_NO_STREAM);
}
if(!connected()) {
return HTTPC_ERROR_NOT_CONNECTED;
return returnError(HTTPC_ERROR_NOT_CONNECTED);
}
// get length of document (is -1 when Server sends no Content-Length header)
@ -474,28 +474,56 @@ int HTTPClient::writeToStream(Stream * stream) {
if(_transferEncoding == HTTPC_TE_IDENTITY) {
ret = writeToStreamDataBlock(stream, len);
// have we an error?
if(ret < 0) {
return returnError(ret);
}
} else if(_transferEncoding == HTTPC_TE_CHUNKED) {
int size = 0;
while(1) {
if(!connected()) {
return returnError(HTTPC_ERROR_CONNECTION_LOST);
}
String chunkHeader = _tcp->readStringUntil('\n');
if(chunkHeader.length() <= 0) {
return returnError(HTTPC_ERROR_READ_TIMEOUT);
}
chunkHeader.trim(); // remove \r
// read size of chunk
len = (uint32_t) strtol((const char *) chunkHeader.c_str(), NULL, 16);
size += len;
DEBUG_HTTPCLIENT("[HTTP-Client] read chunk len: %d\n", len);
// data left?
if(len > 0) {
int r = writeToStreamDataBlock(stream, len);
if(r < 0) {
// error in writeToStreamDataBlock
return r;
return returnError(r);
}
ret += r;
} else {
// if no length Header use global chunk size
if(_size <= 0) {
_size = size;
}
// check if we have write all data out
if(ret != _size) {
return returnError(HTTPC_ERROR_STREAM_WRITE);
}
break;
}
delay(0);
}
} else {
return HTTPC_ERROR_ENCODING;
return returnError(HTTPC_ERROR_ENCODING);
}
end();
@ -546,6 +574,10 @@ String HTTPClient::errorToString(int error) {
return String("too less ram");
case HTTPC_ERROR_ENCODING:
return String("Transfer-Encoding not supported");
case HTTPC_ERROR_STREAM_WRITE:
return String("Stream write error");
case HTTPC_ERROR_READ_TIMEOUT:
return String("read Timeout");
default:
return String();
}
@ -829,23 +861,50 @@ int HTTPClient::writeToStreamDataBlock(Stream * stream, int size) {
}
// read data
int c = _tcp->readBytes(buff, readBytes);
int bytesRead = _tcp->readBytes(buff, readBytes);
// write it to Stream
int w = stream->write(buff, c);
bytesWritten += w;
if(w != c) {
DEBUG_HTTPCLIENT("[HTTP-Client][writeToStreamDataBlock] short write asked for %d but got %d\n", c, w);
break;
int bytesWrite = stream->write(buff, bytesRead);
bytesWritten += bytesWrite;
// 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);
// check for write error
if(stream->getWriteError()) {
DEBUG_HTTPCLIENT("[HTTP-Client][writeToStreamDataBlock] stream write error %d\n", stream->getWriteError());
//reset write error for retry
stream->clearWriteError();
}
// some time for the stream
delay(1);
int leftBytes = (readBytes - bytesWrite);
// retry to send the missed bytes
bytesWrite = stream->write((buff + bytesWrite), leftBytes);
bytesWritten += 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;
}
}
// check for write error
if(stream->getWriteError()) {
DEBUG_HTTPCLIENT("[HTTP-Client][writeToStreamDataBlock] stream write error %d\n", stream->getWriteError());
break;
return HTTPC_ERROR_STREAM_WRITE;
}
// count bytes to read left
if(len > 0) {
len -= c;
len -= readBytes;
}
delay(0);
@ -869,3 +928,19 @@ int HTTPClient::writeToStreamDataBlock(Stream * stream, int size) {
return bytesWritten;
}
/**
* called to handle error return, may disconnect the connection if still exists
* @param error
* @return error
*/
int HTTPClient::returnError(int error) {
if(error < 0) {
DEBUG_HTTPCLIENT("[HTTP-Client][returnError] error(%d): %s\n", error, errorToString(error).c_str());
if(connected()) {
DEBUG_HTTPCLIENT("[HTTP-Client][returnError] tcp stop\n");
_tcp->stop();
}
}
return error;
}

View File

@ -25,7 +25,7 @@
#ifndef ESP8266HTTPClient_H_
#define ESP8266HTTPClient_H_
//#define DEBUG_HTTPCLIENT(...) Serial1.printf( __VA_ARGS__ )
#define DEBUG_HTTPCLIENT(...) Serial1.printf( __VA_ARGS__ )
#ifndef DEBUG_HTTPCLIENT
#define DEBUG_HTTPCLIENT(...)
@ -43,7 +43,8 @@
#define HTTPC_ERROR_NO_HTTP_SERVER (-7)
#define HTTPC_ERROR_TOO_LESS_RAM (-8)
#define HTTPC_ERROR_ENCODING (-9)
#define HTTPC_ERROR_STREAM_WRITE (-10)
#define HTTPC_ERROR_READ_TIMEOUT (-11)
/// size for the stream handling
#define HTTP_TCP_BUFFER_SIZE (1460)
@ -197,7 +198,7 @@ class HTTPClient {
bool _canReuse;
transferEncoding_t _transferEncoding;
int returnError(int error);
bool connect(void);
bool sendHeader(const char * type);
int handleHeaderResponse();