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:
parent
7540f11c93
commit
bd7d915bcd
@ -298,7 +298,7 @@ int HTTPClient::POST(String payload) {
|
|||||||
int HTTPClient::sendRequest(const char * type, uint8_t * payload, size_t size) {
|
int HTTPClient::sendRequest(const char * type, uint8_t * payload, size_t size) {
|
||||||
// connect to server
|
// connect to server
|
||||||
if(!connect()) {
|
if(!connect()) {
|
||||||
return HTTPC_ERROR_CONNECTION_REFUSED;
|
return returnError(HTTPC_ERROR_CONNECTION_REFUSED);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(payload && size > 0) {
|
if(payload && size > 0) {
|
||||||
@ -307,18 +307,18 @@ int HTTPClient::sendRequest(const char * type, uint8_t * payload, size_t size) {
|
|||||||
|
|
||||||
// send Header
|
// send Header
|
||||||
if(!sendHeader(type)) {
|
if(!sendHeader(type)) {
|
||||||
return HTTPC_ERROR_SEND_HEADER_FAILED;
|
return returnError(HTTPC_ERROR_SEND_HEADER_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
// send Payload if needed
|
// send Payload if needed
|
||||||
if(payload && size > 0) {
|
if(payload && size > 0) {
|
||||||
if(_tcp->write(&payload[0], size) != size) {
|
if(_tcp->write(&payload[0], size) != size) {
|
||||||
return HTTPC_ERROR_SEND_PAYLOAD_FAILED;
|
return returnError(HTTPC_ERROR_SEND_PAYLOAD_FAILED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle Server Response (Header)
|
// 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;
|
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 len = size;
|
||||||
int bytesWritten = 0;
|
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)) {
|
while(connected() && (stream->available() > -1) && (len > 0 || len == -1)) {
|
||||||
|
|
||||||
// get available data size
|
// get available data size
|
||||||
size_t s = stream->available();
|
int s = stream->available();
|
||||||
|
|
||||||
if(len) {
|
if(len) {
|
||||||
s = ((s > len) ? len : s);
|
s = ((s > len) ? len : s);
|
||||||
@ -461,11 +461,11 @@ WiFiClient * HTTPClient::getStreamPtr(void) {
|
|||||||
int HTTPClient::writeToStream(Stream * stream) {
|
int HTTPClient::writeToStream(Stream * stream) {
|
||||||
|
|
||||||
if(!stream) {
|
if(!stream) {
|
||||||
return HTTPC_ERROR_NO_STREAM;
|
return returnError(HTTPC_ERROR_NO_STREAM);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!connected()) {
|
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)
|
// 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) {
|
if(_transferEncoding == HTTPC_TE_IDENTITY) {
|
||||||
ret = writeToStreamDataBlock(stream, len);
|
ret = writeToStreamDataBlock(stream, len);
|
||||||
|
|
||||||
|
// have we an error?
|
||||||
|
if(ret < 0) {
|
||||||
|
return returnError(ret);
|
||||||
|
}
|
||||||
} else if(_transferEncoding == HTTPC_TE_CHUNKED) {
|
} else if(_transferEncoding == HTTPC_TE_CHUNKED) {
|
||||||
|
int size = 0;
|
||||||
while(1) {
|
while(1) {
|
||||||
|
if(!connected()) {
|
||||||
|
return returnError(HTTPC_ERROR_CONNECTION_LOST);
|
||||||
|
}
|
||||||
String chunkHeader = _tcp->readStringUntil('\n');
|
String chunkHeader = _tcp->readStringUntil('\n');
|
||||||
|
|
||||||
|
if(chunkHeader.length() <= 0) {
|
||||||
|
return returnError(HTTPC_ERROR_READ_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
chunkHeader.trim(); // remove \r
|
chunkHeader.trim(); // remove \r
|
||||||
|
|
||||||
// read size of chunk
|
// read size of chunk
|
||||||
len = (uint32_t) strtol((const char *) chunkHeader.c_str(), NULL, 16);
|
len = (uint32_t) strtol((const char *) chunkHeader.c_str(), NULL, 16);
|
||||||
|
size += len;
|
||||||
DEBUG_HTTPCLIENT("[HTTP-Client] read chunk len: %d\n", len);
|
DEBUG_HTTPCLIENT("[HTTP-Client] read chunk len: %d\n", len);
|
||||||
|
|
||||||
|
// data left?
|
||||||
if(len > 0) {
|
if(len > 0) {
|
||||||
int r = writeToStreamDataBlock(stream, len);
|
int r = writeToStreamDataBlock(stream, len);
|
||||||
if(r < 0) {
|
if(r < 0) {
|
||||||
// error in writeToStreamDataBlock
|
// error in writeToStreamDataBlock
|
||||||
return r;
|
return returnError(r);
|
||||||
}
|
}
|
||||||
ret += r;
|
ret += r;
|
||||||
} else {
|
} 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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
delay(0);
|
delay(0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return HTTPC_ERROR_ENCODING;
|
return returnError(HTTPC_ERROR_ENCODING);
|
||||||
}
|
}
|
||||||
|
|
||||||
end();
|
end();
|
||||||
@ -546,6 +574,10 @@ String HTTPClient::errorToString(int error) {
|
|||||||
return String("too less ram");
|
return String("too less ram");
|
||||||
case HTTPC_ERROR_ENCODING:
|
case HTTPC_ERROR_ENCODING:
|
||||||
return String("Transfer-Encoding not supported");
|
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:
|
default:
|
||||||
return String();
|
return String();
|
||||||
}
|
}
|
||||||
@ -829,23 +861,50 @@ int HTTPClient::writeToStreamDataBlock(Stream * stream, int size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// read data
|
// read data
|
||||||
int c = _tcp->readBytes(buff, readBytes);
|
int bytesRead = _tcp->readBytes(buff, readBytes);
|
||||||
|
|
||||||
// write it to Stream
|
// write it to Stream
|
||||||
int w = stream->write(buff, c);
|
int bytesWrite = stream->write(buff, bytesRead);
|
||||||
bytesWritten += w;
|
bytesWritten += bytesWrite;
|
||||||
if(w != c) {
|
|
||||||
DEBUG_HTTPCLIENT("[HTTP-Client][writeToStreamDataBlock] short write asked for %d but got %d\n", c, w);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// 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()) {
|
if(stream->getWriteError()) {
|
||||||
DEBUG_HTTPCLIENT("[HTTP-Client][writeToStreamDataBlock] stream write error %d\n", stream->getWriteError());
|
DEBUG_HTTPCLIENT("[HTTP-Client][writeToStreamDataBlock] stream write error %d\n", stream->getWriteError());
|
||||||
break;
|
|
||||||
|
//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());
|
||||||
|
return HTTPC_ERROR_STREAM_WRITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// count bytes to read left
|
||||||
if(len > 0) {
|
if(len > 0) {
|
||||||
len -= c;
|
len -= readBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
delay(0);
|
delay(0);
|
||||||
@ -869,3 +928,19 @@ int HTTPClient::writeToStreamDataBlock(Stream * stream, int size) {
|
|||||||
|
|
||||||
return bytesWritten;
|
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;
|
||||||
|
}
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
#ifndef ESP8266HTTPClient_H_
|
#ifndef ESP8266HTTPClient_H_
|
||||||
#define ESP8266HTTPClient_H_
|
#define ESP8266HTTPClient_H_
|
||||||
|
|
||||||
//#define DEBUG_HTTPCLIENT(...) Serial1.printf( __VA_ARGS__ )
|
#define DEBUG_HTTPCLIENT(...) Serial1.printf( __VA_ARGS__ )
|
||||||
|
|
||||||
#ifndef DEBUG_HTTPCLIENT
|
#ifndef DEBUG_HTTPCLIENT
|
||||||
#define DEBUG_HTTPCLIENT(...)
|
#define DEBUG_HTTPCLIENT(...)
|
||||||
@ -43,7 +43,8 @@
|
|||||||
#define HTTPC_ERROR_NO_HTTP_SERVER (-7)
|
#define HTTPC_ERROR_NO_HTTP_SERVER (-7)
|
||||||
#define HTTPC_ERROR_TOO_LESS_RAM (-8)
|
#define HTTPC_ERROR_TOO_LESS_RAM (-8)
|
||||||
#define HTTPC_ERROR_ENCODING (-9)
|
#define HTTPC_ERROR_ENCODING (-9)
|
||||||
|
#define HTTPC_ERROR_STREAM_WRITE (-10)
|
||||||
|
#define HTTPC_ERROR_READ_TIMEOUT (-11)
|
||||||
|
|
||||||
/// size for the stream handling
|
/// size for the stream handling
|
||||||
#define HTTP_TCP_BUFFER_SIZE (1460)
|
#define HTTP_TCP_BUFFER_SIZE (1460)
|
||||||
@ -197,7 +198,7 @@ class HTTPClient {
|
|||||||
bool _canReuse;
|
bool _canReuse;
|
||||||
transferEncoding_t _transferEncoding;
|
transferEncoding_t _transferEncoding;
|
||||||
|
|
||||||
|
int returnError(int error);
|
||||||
bool connect(void);
|
bool connect(void);
|
||||||
bool sendHeader(const char * type);
|
bool sendHeader(const char * type);
|
||||||
int handleHeaderResponse();
|
int handleHeaderResponse();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user