diff --git a/src/ebusd/mainloop.cpp b/src/ebusd/mainloop.cpp index 3cee7bb6..03ae9651 100644 --- a/src/ebusd/mainloop.cpp +++ b/src/ebusd/mainloop.cpp @@ -379,8 +379,10 @@ void MainLoop::run() { m_busHandler->formatUpdateInfo(&ostr); ostr << "}"; string response; - if (!m_httpClient.post("/", ostr.str(), &response)) { + bool repeat = false; + if (!m_httpClient.post("/", ostr.str(), &response, &repeat)) { logError(lf_main, "update check error: %s", response.c_str()); + nextCheckRun = now + (repeat ? CHECK_INITIAL_DELAY : CHECK_DELAY); } else { m_updateCheck = response.empty() ? "unknown" : response; logNotice(lf_main, "update check: %s", response.c_str()); @@ -389,8 +391,8 @@ void MainLoop::run() { dataSink->notifyUpdateCheckResult(response == "OK" ? "" : m_updateCheck); } } + nextCheckRun = now + CHECK_DELAY; } - nextCheckRun = now + CHECK_DELAY; } } time(&lastTaskRun); diff --git a/src/ebusd/scan.cpp b/src/ebusd/scan.cpp index cb1cf184..2c42450f 100644 --- a/src/ebusd/scan.cpp +++ b/src/ebusd/scan.cpp @@ -57,6 +57,9 @@ ScanHelper::~ScanHelper() { } } +// the time slice to sleep when repeating an HTTP request +#define REPEAT_NANOS 1000000 + result_t ScanHelper::collectConfigFiles(const string& relPath, const string& prefix, const string& extension, vector* files, bool ignoreAddressPrefix, const string& query, @@ -66,8 +69,19 @@ result_t ScanHelper::collectConfigFiles(const string& relPath, const string& pre string uri = m_configUriPrefix + relPathWithSlash + m_configLangQuery + (m_configLangQuery.empty() ? "?" : "&") + "t=" + extension.substr(1) + query; string names; - if (!m_configHttpClient->get(uri, "", &names)) { - return RESULT_ERR_NOTFOUND; + bool repeat = false; + if (!m_configHttpClient->get(uri, "", &names, &repeat)) { + if (!names.empty()) { + logError(lf_main, "HTTP failure%s: %s", repeat ? ", repeating" : "", names.c_str()); + names = ""; + } + if (!repeat) { + return RESULT_ERR_NOTFOUND; + } + usleep(REPEAT_NANOS); + if (!m_configHttpClient->get(uri, "", &names)) { + return RESULT_ERR_NOTFOUND; + } } istringstream stream(names); string name; @@ -261,11 +275,23 @@ result_t ScanHelper::loadDefinitionsFromConfigPath(FileReader* reader, const str time_t mtime = 0; if (m_configUriPrefix.empty()) { stream = FileReader::openFile(m_configLocalPrefix + filename, errorDescription, &mtime); - } else { + } else if (m_configHttpClient) { + string uri = m_configUriPrefix + filename + m_configLangQuery; string content; - if (m_configHttpClient - && m_configHttpClient->get(m_configUriPrefix + filename + m_configLangQuery, "", &content, &mtime)) { + bool repeat = false; + if (m_configHttpClient->get(uri, "", &content, &repeat, &mtime)) { stream = new istringstream(content); + } else { + if (!content.empty()) { + logError(lf_main, "HTTP failure%s: %s", repeat ? ", repeating" : "", content.c_str()); + content = ""; + } + if (repeat) { + usleep(REPEAT_NANOS); + if (m_configHttpClient->get(uri, "", &content, nullptr, &mtime)) { + stream = new istringstream(content); + } + } } } result_t result; diff --git a/src/lib/utils/httpclient.cpp b/src/lib/utils/httpclient.cpp index 35b05e20..50440491 100755 --- a/src/lib/utils/httpclient.cpp +++ b/src/lib/utils/httpclient.cpp @@ -431,12 +431,12 @@ void HttpClient::disconnect() { } } -bool HttpClient::get(const string& uri, const string& body, string* response, time_t* time) { - return request("GET", uri, body, response, time); +bool HttpClient::get(const string& uri, const string& body, string* response, bool* repeatable, time_t* time) { + return request("GET", uri, body, response, repeatable, time); } -bool HttpClient::post(const string& uri, const string& body, string* response) { - return request("POST", uri, body, response); +bool HttpClient::post(const string& uri, const string& body, string* response, bool* repeatable) { + return request("POST", uri, body, response, repeatable); } const int indexToMonth[] = { @@ -446,9 +446,13 @@ const int indexToMonth[] = { -1, -1, 4, -1, -1, -1, -1, -1, // 24-31 }; -bool HttpClient::request(const string& method, const string& uri, const string& body, string* response, time_t* time) { +bool HttpClient::request(const string& method, const string& uri, const string& body, string* response, +bool* repeatable, time_t* time) { if (!ensureConnected()) { *response = "not connected"; + if (repeatable) { + *repeatable = true; + } return false; } ostringstream ostr; @@ -473,6 +477,9 @@ bool HttpClient::request(const string& method, const string& uri, const string& if (sent < 0) { disconnect(); *response = "send error"; + if (repeatable) { + *repeatable = true; + } return false; } pos += sent; diff --git a/src/lib/utils/httpclient.h b/src/lib/utils/httpclient.h index fcfcddeb..7bd3cf1f 100755 --- a/src/lib/utils/httpclient.h +++ b/src/lib/utils/httpclient.h @@ -188,19 +188,24 @@ class HttpClient { * @param uri the URI string. * @param body the optional body to send. * @param response the response body from the server (or the HTTP header on error). + * @param repeatable optional pointer to a bool in which to store whether the request should be repeated later on + * (e.g. due to temporary connectivity issues). * @param time optional pointer to a @a time_t value for storing the modification time of the file, or nullptr. * @return true on success, false on error. */ - bool get(const string& uri, const string& body, string* response, time_t* time = nullptr); + bool get(const string& uri, const string& body, string* response, bool* repeatable = nullptr, + time_t* time = nullptr); /** * Execute a POST request. * @param uri the URI string. * @param body the optional body to send. * @param response the response body from the server (or the HTTP header on error). + * @param repeatable optional pointer to a bool in which to store whether the request should be repeated later on + * (e.g. due to temporary connectivity issues). * @return true on success, false on error. */ - bool post(const string& uri, const string& body, string* response); + bool post(const string& uri, const string& body, string* response, bool* repeatable = nullptr); /** * Execute an arbitrary request. @@ -208,10 +213,13 @@ class HttpClient { * @param uri the URI string. * @param body the optional body to send. * @param response the response body from the server (or the HTTP header on error). + * @param repeatable optional pointer to a bool in which to store whether the request should be repeated later on + * (e.g. due to temporary connectivity issues). * @param time optional pointer to a @a time_t value for storing the modification time of the file, or nullptr. * @return true on success, false on error. */ - bool request(const string& method, const string& uri, const string& body, string* response, time_t* time = nullptr); + bool request(const string& method, const string& uri, const string& body, string* response, + bool* repeatable = nullptr, time_t* time = nullptr); private: /**