From c2682e10c314d7841a87edcec0fcfb3ddb065e90 Mon Sep 17 00:00:00 2001 From: Apollon77 Date: Mon, 14 Sep 2015 11:52:22 +0200 Subject: [PATCH 1/4] Added error handling to skipHeaders to prevent usable of httpReturnCode on invalid returns Added error handling to skipHeaders to prevent usable of httpReturnCode on invalid returns --- HTTPClient.cpp | 6 +++++- HTTPClient.h | 0 2 files changed, 5 insertions(+), 1 deletion(-) mode change 100644 => 100755 HTTPClient.cpp mode change 100644 => 100755 HTTPClient.h diff --git a/HTTPClient.cpp b/HTTPClient.cpp old mode 100644 new mode 100755 index dea3547..14223fb --- a/HTTPClient.cpp +++ b/HTTPClient.cpp @@ -400,7 +400,11 @@ int HTTPClient::skipHeader(FILE* stream) { //skip over the header - fscanf_P(stream, PSTR("HTTP/1.1 %i"), &lastReturnCode); + int httpReturnCode; + lastReturnCode = NULL; + int res=fscanf_P(stream, PSTR("HTTP/1.1 %i"), &httpReturnCode); + if ( (res!=1) || (feof(stream)) || (ferror(stream)) ) return NULL; + lastReturnCode = httpReturnCode; // only set class variable when successfully matched char inByte = '\0'; char lastByte = '\0'; while (!(inByte == '\n' && lastByte == '\n')) diff --git a/HTTPClient.h b/HTTPClient.h old mode 100644 new mode 100755 From 115b0dbdcf20516206cc0209c83345b77257227c Mon Sep 17 00:00:00 2001 From: Ingo Fischer Date: Thu, 17 Sep 2015 12:53:38 +0200 Subject: [PATCH 2/4] Simplified check Simplified check because it is only relevant if the status code could be read - all other error cases are handled by later code too --- HTTPClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/HTTPClient.cpp b/HTTPClient.cpp index 14223fb..a6e2d18 100755 --- a/HTTPClient.cpp +++ b/HTTPClient.cpp @@ -403,7 +403,7 @@ HTTPClient::skipHeader(FILE* stream) int httpReturnCode; lastReturnCode = NULL; int res=fscanf_P(stream, PSTR("HTTP/1.1 %i"), &httpReturnCode); - if ( (res!=1) || (feof(stream)) || (ferror(stream)) ) return NULL; + if (res!=1) return NULL; lastReturnCode = httpReturnCode; // only set class variable when successfully matched char inByte = '\0'; char lastByte = '\0'; From 5a2f1b51228efb50dfa7a3a638477fcd135ba468 Mon Sep 17 00:00:00 2001 From: Ingo Fischer Date: Mon, 21 Sep 2015 09:13:14 +0200 Subject: [PATCH 3/4] make sure all connections are closed properly on client side MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the server closed the connection and all data are read, the socket is in „CLOSE-WAIT“ status … but in this combination „connected“ returns false, even if the socket is not really closed on the client. This is not a real problem because normally „CLOSE_WAIT“ sockets are reused for new connections, but it may end up in problems any may cause problems. (I try to tackle down the effect that sometimes no more connections are possible …) The solution is to call „stop“ in any case when the Stream should be closed because with this the connection is closed correctly in any case. A double call is handed by „stop“ automatically so don’t worry about this. --- HTTPClient.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/HTTPClient.cpp b/HTTPClient.cpp index a6e2d18..faf1a70 100755 --- a/HTTPClient.cpp +++ b/HTTPClient.cpp @@ -431,10 +431,7 @@ HTTPClient::closeStream(FILE* stream) if (stream != NULL) { http_stream_udata* udata = (http_stream_udata*) fdev_get_udata(stream); - if (udata->client->connected()) - { - udata->client->stop(); - } + udata->client->stop(); free(udata); fclose(stream); } From ab4a0261715e331fcc9dff5859105d7392b986c2 Mon Sep 17 00:00:00 2001 From: Ingo Fischer Date: Fri, 6 Nov 2015 15:10:23 +0100 Subject: [PATCH 4/4] Checks and delay before reading header infos - Added some checks that stream variable is not NULL before using it (just to make sure) - To avoid header-read errors that happened sometimes implement a check for available data with a maximum timeout of 1000ms (configurable via defines in header file). With my default settings we wait 20 ms and then check again if at least 17 characters are available to read (which should be a normal HTTP-header first line). This is done at max 50 times before the read is tried --- HTTPClient.cpp | 21 ++++++++++++++++++++- HTTPClient.h | 9 ++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/HTTPClient.cpp b/HTTPClient.cpp index faf1a70..d21f4fd 100755 --- a/HTTPClient.cpp +++ b/HTTPClient.cpp @@ -203,6 +203,10 @@ char HTTPClient::sendUriAndHeaders(FILE* stream, char* hostName, const char* requestType, char* uri, http_client_parameter parameters[], http_client_parameter headers[]) { + if (stream == NULL) + { + return 0; + } fprintf_P(stream, requestType, uri); fprintf_P(stream, PSTR(" "), uri); //encode but use reserved characters @@ -256,6 +260,10 @@ HTTPClient::sendUriAndHeaders(FILE* stream, char* hostName, const char* requestT char HTTPClient::sendContentPayload(FILE* stream, char* data) { + if (stream == NULL) + { + return 0; + } //calculate the content length int content_length = 0; if (data != NULL) @@ -402,9 +410,20 @@ HTTPClient::skipHeader(FILE* stream) //skip over the header int httpReturnCode; lastReturnCode = NULL; + + if (stream == NULL) return NULL; + http_stream_udata* udata = (http_stream_udata*) fdev_get_udata(stream); + HTTPClient* client = udata->client; + + int delayReadHeaderCount=0; + // check if at least the first HTTP-response available, up to 1000ms=1s + while ((client->available()<17) && (delayReadHeaderCount++ -#include "EthernetClient.h" +#include + +/* With this we try a delay of 20 ms before checking again if content is available + * and we try this up to 50 times. + * So max: 20x50ms=1000ms=1s + */ +#define HTTPCLIENT_HEADER_READ_DELAY_ONCE 20 +#define HTTPCLIENT_HEADER_READ_DELAY_MAXCOUNT 50 /* This struct is used to pass parameters as URI paramters and additional HTTP headers. * normally you pass this as a array. The last entry must have the NULL-Pointer as name.