diff --git a/libraries/SocketWrapper/src/SocketHelpers.cpp b/libraries/SocketWrapper/src/SocketHelpers.cpp index 2c53f1b12..691f7cbfa 100644 --- a/libraries/SocketWrapper/src/SocketHelpers.cpp +++ b/libraries/SocketWrapper/src/SocketHelpers.cpp @@ -125,29 +125,44 @@ void MbedSocketClass::feedWatchdog() { void MbedSocketClass::body_callback(const char* data, uint32_t data_len) { feedWatchdog(); - fwrite(data, 1, data_len, download_target); + fwrite(data, sizeof(data[0]), data_len, download_target); } -int MbedSocketClass::download(char* url, const char* target_file, bool const is_https) { +int MbedSocketClass::download(const char* url, const char* target_file, bool const is_https) { download_target = fopen(target_file, "wb"); + int res = this->download(url, is_https, mbed::callback(this, &MbedSocketClass::body_callback)); + + fclose(download_target); + download_target = nullptr; + + return res; +} + +int MbedSocketClass::download(const char* url, bool const is_https, mbed::Callback cbk) { + if(cbk == nullptr) { + return 0; // a call back must be set + } + HttpRequest* req_http = nullptr; HttpsRequest* req_https = nullptr; HttpResponse* rsp = nullptr; + int res=0; + std::vector header_fields; if (is_https) { - req_https = new HttpsRequest(getNetwork(), nullptr, HTTP_GET, url, mbed::callback(this, &MbedSocketClass::body_callback)); + req_https = new HttpsRequest(getNetwork(), nullptr, HTTP_GET, url, cbk); rsp = req_https->send(NULL, 0); if (rsp == NULL) { - fclose(download_target); - return req_https->get_error(); + res = req_https->get_error(); + goto exit; } } else { - req_http = new HttpRequest(getNetwork(), HTTP_GET, url, mbed::callback(this, &MbedSocketClass::body_callback)); + req_http = new HttpRequest(getNetwork(), HTTP_GET, url, cbk); rsp = req_http->send(NULL, 0); if (rsp == NULL) { - fclose(download_target); - return req_http->get_error(); + res = req_http->get_error(); + goto exit; } } @@ -155,7 +170,21 @@ int MbedSocketClass::download(char* url, const char* target_file, bool const is_ delay(10); } - int const size = ftell(download_target); - fclose(download_target); - return size; + // find the header containing the "Content-Length" value and return that + header_fields = rsp->get_headers_fields(); + for(int i=0; ic_str(), "Content-Length") == 0) { + res = std::stoi(*rsp->get_headers_values()[i]); + break; + } + } + +exit: + if(req_http) delete req_http; + if(req_https) delete req_https; + // no need to delete rsp, it is already deleted by deleting the request + // this may be harmful since it can allow dangling pointers existence + + return res; } diff --git a/libraries/SocketWrapper/src/SocketHelpers.h b/libraries/SocketWrapper/src/SocketHelpers.h index 8cfd0b601..5ab408267 100644 --- a/libraries/SocketWrapper/src/SocketHelpers.h +++ b/libraries/SocketWrapper/src/SocketHelpers.h @@ -107,8 +107,24 @@ class MbedSocketClass { IPAddress dnsIP(int n = 0); virtual NetworkInterface* getNetwork() = 0; - - int download(char* url, const char* target, bool const is_https = false); + + /* + * Download a file from an HTTP endpoint and save it in the provided `target` location on the fs + * The parameter cbk can be used to perform actions on the buffer before saving on the fs + * + * return: on success the size of the downloaded file, on error -status code + */ + int download( + const char* url, const char* target, bool const is_https = false); + /* + * Download a file from an HTTP endpoint and handle the body of the request on a callback + * passed as an argument + * + * return: on success the size of the downloaded file, on error -status code + */ + int download( + const char* url, bool const is_https = false, + mbed::Callback cbk = nullptr); int hostByName(const char* aHostname, IPAddress& aResult);