From f76639745f89bfeb44fa678ea4de8af0a4a78cfc Mon Sep 17 00:00:00 2001 From: Th3maz1ng Date: Tue, 14 Jul 2020 11:48:43 +0200 Subject: [PATCH] Corrected the isReplyAvailable methode --- src/app/HttpClient.cpp | 197 +++++++++++++++++++++++++---------------- src/app/HttpClient.h | 16 ++-- 2 files changed, 129 insertions(+), 84 deletions(-) diff --git a/src/app/HttpClient.cpp b/src/app/HttpClient.cpp index 095291a..3ca82ac 100644 --- a/src/app/HttpClient.cpp +++ b/src/app/HttpClient.cpp @@ -7,20 +7,8 @@ * End of HttpClientHelper */ -HttpClient::HttpClient() : WiFiClient(), _connectionStatus(NO_ATTEMPT), _resource(NULL), _address(NULL), _port(0), _keepAlive(false), _maxRetries(-1), _retries(0), _httpCode(HTTP_CODE::UNDEFINED_CODE), _bodyReadyToRead(false) +HttpClient::HttpClient(const char *address, uint16_t port) : WiFiClient(), _connectionStatus(NO_ATTEMPT), _resource(NULL), _pAddress(address), _port(0), _keepAlive(false), _maxRetries(-1), _retries(0), _isIp(false), _httpCode(HTTP_CODE::UNDEFINED_CODE), _httpCodeParsed(false) { - -} - -HttpClient::HttpClient(const char *address, uint16_t port) : HttpClient() -{ - - if(address != NULL) - { - _address = (char *)malloc(strlen(address) * sizeof(char) + 1); - strcpy(_address, address); - } - _port = port; connectByHostOrIp(); @@ -44,35 +32,28 @@ HttpClient::HttpClient(const HttpClient &object) } else _resource = NULL; - - if(object._address != NULL) - { - _address = (char *)malloc(strlen(object._address) * sizeof(char) + 1); - strcpy(_address, object._address); - } - else - _address = NULL; + _pAddress = object._pAddress; _connectionStatus = object._connectionStatus; _keepAlive = object._keepAlive; _maxRetries = object._maxRetries; _retries = object._retries; _port = object._port; _httpCode = object._httpCode; - _bodyReadyToRead = object._bodyReadyToRead; + _httpCodeParsed = object._httpCodeParsed; } HttpClient::~HttpClient() { if(_resource != NULL)free(_resource); - if(_address != NULL)free(_address); } boolean HttpClient::connectByHostOrIp() { IPAddress ipAddress; - if(ipAddress.fromString(_address)) + if(ipAddress.fromString(_pAddress)) { + _isIp = true; _connectionStatus = connect(ipAddress, _port) == 1 ? SUCCESSFUL : FAILED; #ifdef DEBUG_HTTP_CLIENT Serial.printf("Correct ip address. Connection status : %d\n", _connectionStatus); @@ -80,7 +61,8 @@ boolean HttpClient::connectByHostOrIp() } else { - _connectionStatus = connect(_address, _port) == 1 ? SUCCESSFUL : FAILED; + _isIp = false; + _connectionStatus = connect(_pAddress, _port) == 1 ? SUCCESSFUL : FAILED; #ifdef DEBUG_HTTP_CLIENT Serial.printf("Probably a hostname. Connection status : %d\n", _connectionStatus); #endif @@ -108,7 +90,7 @@ boolean HttpClient::sendHttpQuery(HttpRequestMethod method, Dictionary 99 ? 99 : bytesAvailable; - peekBytes(readBuffer, safeSize); - readBuffer[safeSize] = '\0'; + return _httpCode; + } + #ifdef DEBUG_HTTP_CLIENT + Serial.println("Before timeout"); + #endif - #ifdef DEBUG_HTTP_CLIENT - Serial.printf("Data chunk from server size -> %u - %u : %s\n", safeSize, bytesAvailable, readBuffer); - #endif - - //We try to extract the http return code: - if(_httpCode == HTTP_CODE::UNDEFINED_CODE) + //This is the loop where we parse the data + while(available() || millis() - ts < timeout) + { + if(available()) { - char *code = strchr((char *)readBuffer, ' '), *endP; - - if(code != NULL) + //If we do not have the HTTP response code yet, we parse it + if(_httpCode == HTTP_CODE::UNDEFINED_CODE) { - endP = strchr(code + 1, ' '); - if(endP != NULL) + uint8_t bytesRed = buffer[peekBytes((uint8_t*)buffer,99)] = '\0'; + //We look for the end of the first line ie : HTTP/1.1 200 OK\r\n + char *pNewLine = strstr(buffer, "\r\n"); + //If we found the new line, we can retrieve the code + if(pNewLine) { - *endP = '\0'; - #ifdef DEBUG_HTTP_CLIENT - Serial.printf("Http code : %s\n", code + 1); + Serial.println("New line found"); #endif - - - _httpCode = numberToHTTP_CODE(strtoul(code+1, NULL, 10)); - read(readBuffer, safeSize - 4); //To remove the peek bytes + //We extract the code + char *code = strchr((char *)buffer, ' '), *endP; + if(code) + { + endP = strchr(code + 1, ' '); + if(endP != NULL) + { + *endP = '\0'; + + #ifdef DEBUG_HTTP_CLIENT + Serial.printf("Http code : %s\n", code + 1); + #endif + + + _httpCode = numberToHTTP_CODE(strtoul(code+1, NULL, 10)); + //We can now discard the first line + #ifdef DEBUG_HTTP_CLIENT + Serial.printf("First line length : %u\n",(pNewLine - buffer) + 2); + #endif + read((uint8_t *)buffer, (pNewLine - buffer) + 2); + #ifdef DEBUG_HTTP_CLIENT + buffer[peekBytes((uint8_t*)buffer,99)] = '\0'; + Serial.printf("Next chunk is : %s\n",buffer); + #endif + } + } + else + { + #ifdef DEBUG_HTTP_CLIENT + Serial.println("Code delimiter NOT found, leaving"); + #endif + break; + } + } + else if(millis() - ts >= timeout)//Time out is over, received data is probably junk. + { + //we leave the loop; + #ifdef DEBUG_HTTP_CLIENT + Serial.println("New line NOT found, leaving"); + #endif + break; } } + else//We found the HTTP code, now we discard all the header data + { + char *bodyDelimiter(NULL); + char *newLineDelimiter; + do + { + buffer[peekBytes((uint8_t*)buffer,99)] = '\0'; + bodyDelimiter = strstr(buffer, "\r\n\r\n"); + newLineDelimiter = strstr(buffer, "\r\n"); + if(!bodyDelimiter) + { + if(newLineDelimiter) + { + read((uint8_t *)buffer, (newLineDelimiter - buffer) + 2); + } + else + { + read((uint8_t *)buffer, strlen(buffer)); + } + } + else + { + #ifdef DEBUG_HTTP_CLIENT + Serial.println("We found the body delimiter"); + #endif + read((uint8_t *)buffer, (bodyDelimiter - buffer) + 4); + #ifdef DEBUG_HTTP_CLIENT + buffer[peekBytes((uint8_t*)buffer,99)] = '\0'; + Serial.printf("Body chunk is : %s\n",buffer); + #endif + } + }while(!bodyDelimiter); + break; + } } - - if(!_bodyReadyToRead) - { - char *endP = strstr((char *)readBuffer, "\r\n\r\n"); - - if(endP != NULL) - { - #ifdef DEBUG_HTTP_CLIENT - Serial.printf("Body found, bytes to discard : %u\n", (uint8_t *)endP - readBuffer + 4); - #endif - read(readBuffer, (uint8_t *)endP - readBuffer + 4); - _bodyReadyToRead = true; - } - else - { - read(readBuffer, safeSize - 3); - } - } } - if(_httpCode != HTTP_CODE::UNDEFINED_CODE && _bodyReadyToRead) - return _httpCode; + #ifdef DEBUG_HTTP_CLIENT + Serial.println("\nAfter timeout or all data is received"); + #endif - return HTTP_CODE::UNDEFINED_CODE; + return _httpCode; } -uint16_t HttpClient::readHttpReply(uint8_t *buffer, uint32_t size) +uint16_t HttpClient::readHttpBody(uint8_t *buffer, uint32_t size) { uint32_t bytesAvailable(available()); uint8_t safeSize(0); @@ -310,7 +346,12 @@ void HttpClient::keepAlive(boolean enabled) void HttpClient::sendHeader(HttpMIMEType contentType, uint64_t contentLength, HttpVersion httpVersion) { char mime[255] = "", httpVer[15] = ""; - printf(" %s\r\nHost: %u.%u.%u.%u:%u\r\nConnection: %s\r\n", httpVersionToString(httpVersion, httpVer), remoteIP()[0], remoteIP()[1], remoteIP()[2], remoteIP()[3], remotePort(), _keepAlive ? "keep-alive" : "close"); + //Host could be an IP address or a host name + if(_isIp) + printf(" %s\r\nHost: %u.%u.%u.%u:%u\r\nConnection: %s\r\n", httpVersionToString(httpVersion, httpVer), remoteIP()[0], remoteIP()[1], remoteIP()[2], remoteIP()[3], remotePort(), _keepAlive ? "keep-alive" : "close"); + else + printf(" %s\r\nHost: %s\r\nConnection: %s\r\n", httpVersionToString(httpVersion, httpVer), _pAddress, _keepAlive ? "keep-alive" : "close"); + if(contentLength > 0) { printf("Content-Length: %u\r\n", contentLength); diff --git a/src/app/HttpClient.h b/src/app/HttpClient.h index e0ea07c..85c1318 100644 --- a/src/app/HttpClient.h +++ b/src/app/HttpClient.h @@ -1,3 +1,7 @@ +/** + * Anatole SCHRAMM-HENRY + * Updated on 12/07/2020 + */ #ifndef HTTPCLIENT_H #define HTTPCLIENT_H @@ -15,7 +19,6 @@ class HttpClient : public WiFiClient, public HttpConstants public: enum ConnectionStatus { NO_ATTEMPT = 0, SUCCESSFUL, FAILED }; - HttpClient(); HttpClient(const char *address, uint16_t port = 80); HttpClient(const char *address, const char *resource, uint16_t port = 80); @@ -26,10 +29,10 @@ class HttpClient : public WiFiClient, public HttpConstants boolean sendHttpQuery(HttpRequestMethod method = HttpRequestMethod::GET, Dictionary *getData = NULL, Dictionary *postData = NULL); void keepAlive(boolean enabled); void setMaxRetries(int16_t retries); - - HTTP_CODE isReplyAvailable(); + //100 ms is the default timeout + HTTP_CODE isReplyAvailable(uint16_t timeout = 100); - uint16_t readHttpReply(uint8_t *buffer, uint32_t size); + uint16_t readHttpBody(uint8_t *buffer, uint32_t size); protected: private: boolean connectByHostOrIp(); @@ -40,13 +43,14 @@ class HttpClient : public WiFiClient, public HttpConstants ConnectionStatus _connectionStatus; char *_resource; - char *_address; + const char *_pAddress; uint16_t _port; boolean _keepAlive; int16_t _maxRetries; uint16_t _retries; + boolean _isIp; HTTP_CODE _httpCode; - boolean _bodyReadyToRead; + boolean _httpCodeParsed; }; #endif //HTTPCLIENT_H