From fffcc2dd2dd1ee2a659948b664ad243502791cf1 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 26 Jun 2024 14:58:39 +0700 Subject: [PATCH] Prevent auth task handler from running when downloading/uploading file --- FAQ.md | 18 ++++++------- README.md | 13 +++++----- .../StreamConcurentcy/StreamConcurentcy.ino | 6 +++++ library.json | 2 +- library.properties | 2 +- resources/docs/async_client.md | 21 +++++++++++++--- resources/docs/realtime_database_result.md | 4 +-- src/Config.h | 4 --- src/core/AsyncClient/AsyncClient.h | 25 ++++++++++++------- src/core/AsyncClient/RequestHandler.h | 2 ++ src/core/Core.h | 2 +- src/core/Error.h | 6 ++--- src/core/Options.h | 4 --- 13 files changed, 64 insertions(+), 45 deletions(-) diff --git a/FAQ.md b/FAQ.md index e0287a44..d690bca0 100644 --- a/FAQ.md +++ b/FAQ.md @@ -1,5 +1,5 @@ -Revision `2024-06-11T01:14:40Z` +Revision `2024-06-26T07:53:25Z` # Async Firebase Client library for Arduino Frequently Asked Questions. @@ -7,7 +7,7 @@ Revision `2024-06-11T01:14:40Z` - [Q1: Why I get an error `"TCP connection failed"`?](#q1-why-i-get-an-error-tcp-connection-failed) - [Q2: Why I get an error `"TCP send failed"`?](#q1-why-i-get-an-error-tcp-connection-failed) -- [Q3: Why I get an error `"TCP receive time out"`?](#q3-why-i-get-an-error-tcp-receive-time-out) +- [Q3: Why I get an error `"TCP receive timed out"`?](#q3-why-i-get-an-error-tcp-receive-time-out) - [Q4: Why I get an error `"TCP disconnected"`?](#q4-why-i-get-an-error-tcp-disconnected) - [Q5: What should I do when I get the error `"error opening file"`?](#q5-what-should-i-do-when-i-get-the-error-error-opening-file) - [Q6: What should I do when I get the error `"error reading file"` or `"error writng file"`?](#q6-what-should-i-do-when-i-get-the-error-error-reading-file-or-error-writng-file) @@ -17,12 +17,12 @@ Revision `2024-06-11T01:14:40Z` - [Q10: What should I do when I get the error `"JWT, token signing fail"`?](#q10-what-should-i-do-when-i-get-the-error-jwt-token-signing-fail) - [Q11: What should I do when I get the error `"too low sketch space"`?](#q11-what-should-i-do-when-i-get-the-error-too-low-sketch-space) - [Q12: What should I do when I get the error `"firmware write failed"` or `"firmware end failed"`?](#q12-what-should-i-do-when-i-get-the-error-firmware-write-failed-or-firmware-end-failed) -- [Q13: What should I do when I get the error `"stream time out"`?](#q13-what-should-i-do-when-i-get-the-error-stream-time-out) +- [Q13: What should I do when I get the error `"stream connection timed out"`?](#q13-what-should-i-do-when-i-get-the-error-stream-connection-timed-out) - [Q14: What should I do when I get the error `"auth revoked"`?](#q14-what-should-i-do-when-i-get-the-error-auth-revoked) - [Q15: Why I get the error `"app was not assigned"`?](#q15-why-i-get-the-error-app-was-not-assigned) - [Q16: Why I get the error `"operation was cancelled"`?](#q16-why-i-get-the-error-operation-was-cancelled) - [Q17: Why I get the error `"JWT, time was not set or not valid"`?](#q17-why-i-get-the-error-jwt-time-was-not-set-or-not-valid) -- [Q18: Why sometimes the Reltime Database Stream does not work when WiFi was disconnected and reconnected and I get the error `"stream time out"`?](#q18-why-sometimes-the-reltime-database-stream-does-not-work-when-wifi-was-disconnected-and-reconnected-and-i-get-the-error-stream-time-out) +- [Q18: Why sometimes the Reltime Database Stream does not work when WiFi was disconnected and reconnected and I get the error `"stream connection timed out"`?](#q18-why-sometimes-the-reltime-database-stream-does-not-work-when-wifi-was-disconnected-and-reconnected-and-i-get-the-error-stream-time-out) - [Q19: Can I use delay in this library?](#q19-can-i-use-delay-in-this-library) - [Q20: Can I change the send timeout?](#q20-can-i-change-the-send-timeout) - [Q21: Can I change the read timeout?](#q21-can-i-change-the-read-timeout) @@ -122,7 +122,7 @@ Then there are many possible causes of connection issue that cause the SSL clien - The send timeout is too small. In case sync task, the send timeout can be set via `AsyncClientClass::setSyncSendTimeout`. The async task send timeout is 30 seconds and cannot be changed and you have to fix the possible issues instead of increasing the send timeout. -### Q3: Why I get an error `"TCP receive time out"`? +### Q3: Why I get an error `"TCP receive timed out"`? #### A3: The time that used while processing the server response (header or payload) is greater than the read timeout. @@ -221,7 +221,7 @@ In case download process interrupted, see [Q1: Why I get an error `"TCP connecti In case unkbown error, please verify your free flash and do not write any file to the filesytem that decreased the free flash space. -### Q13: What should I do when I get the error `"stream time out"`? +### Q13: What should I do when I get the error `"stream connection timed out"`? #### A13: The error can be occured when no keep-alive event received during the stream timeout period. @@ -259,7 +259,7 @@ When no more memory to be allocated for new task. You have to reduce the memory The timestamp that you set in the uint32_t variable of time status callback function is not valid or it was not set. -### Q18: Why sometimes the Reltime Database Stream does not work when WiFi was disconnected and reconnected and I get the error `"stream time out"`? +### Q18: Why sometimes the Reltime Database Stream does not work when WiFi was disconnected and reconnected and I get the error `"stream connection timed out"`? #### A18: The problem is due to the WiFi reconnection interferences. @@ -269,7 +269,7 @@ Please read [Possible WiFi issues](#possible-wifi-issues). #### A19: Yes, but it's not recommend. -If the delay was used in the loop it causes many errors e.g. read and send time out and stream time out. +If the delay was used in the loop it causes many errors e.g. read and send timed out and stream connection timed out. ### Q20: Can I change the send timeout? @@ -306,7 +306,7 @@ The memory allocation failure due to out of memory can cause the dangling pointe If network disconnected and re-connected, network connected but internet access was missing, and no events included keep-alive event received within 40 seconds, the Stream will be closed and restarted automatically as long as the async client's queue was running. -The `stream time out`error will show in case time out (no events received within 40 seconds). +The `stream connection timed out`error will show in case timed out (no events received within 40 seconds). If you are intend to totally remove the steam task from the queue, and stream is running, use `AsyncClientClass::stopAsync()`. If you are not sure that stream was running or stopped because of other tasks, use `AsyncClientClass::stopAsync(true)` to cancell all tasks and remove all tasks from the queue. diff --git a/README.md b/README.md index 81ea33ac..0ef70c1d 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,11 @@ ![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/mobizt/FirebaseClient/.github%2Fworkflows%2Fcompile_library.yml?logo=github&label=compile) [![Github Stars](https://img.shields.io/github/stars/mobizt/FirebaseClient?logo=github)](https://github.com/mobizt/FirebaseClient/stargazers) ![Github Issues](https://img.shields.io/github/issues/mobizt/FirebaseClient?logo=github) -![GitHub Release](https://img.shields.io/github/v/release/mobizt/FirebaseClient) ![Arduino](https://img.shields.io/badge/Arduino-v1.2.17-57C207?logo=arduino) ![PlatformIO](https://badges.registry.platformio.org/packages/mobizt/library/FirebaseClient.svg) ![GitHub Release Date](https://img.shields.io/github/release-date/mobizt/FirebaseClient) +![GitHub Release](https://img.shields.io/github/v/release/mobizt/FirebaseClient) ![Arduino](https://img.shields.io/badge/Arduino-v1.2.18-57C207?logo=arduino) ![PlatformIO](https://badges.registry.platformio.org/packages/mobizt/library/FirebaseClient.svg) ![GitHub Release Date](https://img.shields.io/github/release-date/mobizt/FirebaseClient) [![GitHub Sponsors](https://img.shields.io/github/sponsors/mobizt?logo=github)](https://github.com/sponsors/mobizt) -Revision `2024-06-25T23:50:45Z` +Revision `2024-06-26T07:53:25Z` ## Table of Contents @@ -479,7 +479,7 @@ To run multiple `SSE mode (HTTP Streaming)` tasks, you have to run each task in The async task handler will kepp the async tasks running as long as it places in the main `loop` function. > [!IMPORTANT] -> Do not underestimate the important the async task handler location and usage. The non-async third-party library and user blocking code, `delay` function and placing the async task handler in the `millis` code blocks, will cause the async task to run slowly and the time out can of operation will be occurred. The `SSE mode (HTTP Streaming)` task will not update in realtime. +> Do not underestimate the important the async task handler location and usage. The non-async third-party library and user blocking code, `delay` function and placing the async task handler in the `millis` code blocks, will cause the async task to run slowly and the timed out will be occurred. The `SSE mode (HTTP Streaming)` task will not update in realtime. > The async task handler i.e. `FirebaseApp::loop()`, `RealtimeDatabase::loop()`, `Storage::loop()`, `Messaging::loop()`, `CloudStorage::loop()` and `CloudFunctions` should be placed inside the main `loop` function, at the top most of the `loop`. > [!NOTE] @@ -507,7 +507,7 @@ In case using ESP8266 without `PSRAM` and you want to reduce the memory usage, y Note that, because the receive buffer size was set to minimum safe value, 1024, the large server response may not be able to handle. > [!WARNING] -> In ESP32, `WiFiClient` and `WiFiClientSecure` classes are unable to detect the server disconnection in case server session time out and the TCP session was kept alive for reuse in most tasks this library. The server session timed out will not happen if data was sent or received within the server time out period. The TCP session timeout in seconds in this library can be set via macro or build flag `FIREBASE_SESSION_TIMEOUT`. +> In ESP32, when using `WiFiClient` with `ESP_SSLClient` classes, `WiFiClient` was unable to detect the server disconnection in case server session timed out and the TCP session was kept alive for reuse in most tasks in this library. The TCP session timeout in seconds (equal to or greater than 150 seconds) in this library can be set via `AsyncClientClass::setSessionTimeout`. - ### Async Client @@ -2953,7 +2953,7 @@ The following options are not yet defined in [**Config.h**](src/Config.h) and ca ```cpp FIREBASE_ETHERNET_MODULE_LIB `"EthernetLibrary.h"` // For the Ethernet library to work with external Ethernet module. FIREBASE_ETHERNET_MODULE_CLASS EthernetClass // For the Ethernet class object of Ethernet library to work with external Ethernet module. -FIREBASE_ETHERNET_MODULE_TIMEOUT 2000 // For the time out in milliseconds to wait external Ethernet module to connect to network. +FIREBASE_ETHERNET_MODULE_TIMEOUT 2000 // For the timeout in milliseconds to wait external Ethernet module to connect to network. ENABLE_ESP8266_ENC28J60_ETH // For native core library ENC28J60 Ethernet module support in ESP8266. ENABLE_ESP8266_W5500_ETH // For native core library W5500 Ethernet module support in ESP8266. ENABLE_ESP8266_W5100_ETH // For native core library W5100 Ethernet module support in ESP8266. @@ -2963,7 +2963,6 @@ ENABLE_ASYNC_TCP_CLIENT // For Async TCP Client usage. FIREBASE_ASYNC_QUEUE_LIMIT // For maximum async queue limit setting for an async client. FIREBASE_PRINTF_PORT // For Firebase.printf debug port. FIREBASE_PRINTF_BUFFER // Firebase.printf buffer size. -FIREBASE_SESSION_TIMEOUT // For TCP session timeout in seconds. The default TCP session timeout is 150 seconds ``` You can assign the optional build options using one of the following methods. @@ -2985,7 +2984,7 @@ For external Ethernet module integation used with function `setEthernetClient`, `FIREBASE_ETHERNET_MODULE_CLASS` is the name of static object defined from class e.g. `Ethernet`. -`FIREBASE_ETHERNET_MODULE_TIMEOUT` is the time out in milliseconds to wait network connection. +`FIREBASE_ETHERNET_MODULE_TIMEOUT` is the timeout in milliseconds to wait for network connection. For disabling predefined options instead of editing the [**Config.h**](src/Config.h) or using `#undef` in `UserConfig.h`, you can define these build flags with these names or macros in `UserConfig.h`. diff --git a/examples/RealtimeDatabase/Async/Callback/StreamConcurentcy/StreamConcurentcy.ino b/examples/RealtimeDatabase/Async/Callback/StreamConcurentcy/StreamConcurentcy.ino index 5cbb081a..6336b867 100644 --- a/examples/RealtimeDatabase/Async/Callback/StreamConcurentcy/StreamConcurentcy.ino +++ b/examples/RealtimeDatabase/Async/Callback/StreamConcurentcy/StreamConcurentcy.ino @@ -114,6 +114,12 @@ void setup() ssl_client2.setDebugLevel(1); ssl_client3.setDebugLevel(1); + // This timeout in seconds is required for WiFiClient used with ESP_SSLClient to limit the timeout of keep-alive TCP sesssion + // as the WiFiClient does not detect the server disconnection, WiFiClient::connected returns true and write error can be occurred. + // This timeout was not applied for Stream. + aClient1.setSessionTimeout(150); + aClient2.setSessionTimeout(150); + initializeApp(aClient3, app, getAuth(user_auth), asyncCB, "authTask"); // Binding the FirebaseApp for authentication handler. diff --git a/library.json b/library.json index 415057d9..8459e18f 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "FirebaseClient", - "version": "1.2.17", + "version": "1.2.18", "keywords": "communication, REST, esp32, esp8266, arduino", "description": "Async Firebase Client library for Arduino.", "repository": { diff --git a/library.properties b/library.properties index a259f8f3..e744aa2e 100644 --- a/library.properties +++ b/library.properties @@ -1,6 +1,6 @@ name=FirebaseClient -version=1.2.17 +version=1.2.18 author=Mobizt diff --git a/resources/docs/async_client.md b/resources/docs/async_client.md index d2575d46..72d8c212 100644 --- a/resources/docs/async_client.md +++ b/resources/docs/async_client.md @@ -125,7 +125,7 @@ void setETag(const String &etag) 10. ## 🔹 void setSyncSendTimeout(uint32_t timeoutSec) -Set the sync task's send time out in seconds. +Set the sync task's send timeout in seconds. ```cpp void setSyncSendTimeout(uint32_t timeoutSec) @@ -133,12 +133,12 @@ void setSyncSendTimeout(uint32_t timeoutSec) **Params:** -- `timeoutSec` - The TCP write time out in seconds. +- `timeoutSec` - The TCP write timeout in seconds. 11. ## 🔹 void setSyncReadTimeout(uint32_t timeoutSec) -Set the sync task's read time out in seconds. +Set the sync task's read timeout in seconds. ```cpp void setSyncReadTimeout(uint32_t timeoutSec) @@ -146,5 +146,18 @@ void setSyncReadTimeout(uint32_t timeoutSec) **Params:** -- `timeoutSec` - The TCP read time out in seconds. +- `timeoutSec` - The TCP read timeout in seconds. + + +12. ## 🔹 void setSessionTimeout(uint32_t timeoutSec) + +Set the TCP session timeout in seconds. + +```cpp +void setSessionTimeout(uint32_t timeoutSec) +``` + +**Params:** + +- `timeoutSec` - The TCP session timeout in seconds. diff --git a/resources/docs/realtime_database_result.md b/resources/docs/realtime_database_result.md index 9e642f34..1d8e20cd 100644 --- a/resources/docs/realtime_database_result.md +++ b/resources/docs/realtime_database_result.md @@ -98,7 +98,7 @@ String data() 8. ## 🔹 bool eventTimeout() -Get the SSE mode (HTTP Streaming) event time out status. +Get the SSE mode (HTTP Streaming) event timed out status. ```cpp bool eventTimeout() @@ -106,7 +106,7 @@ bool eventTimeout() **Returns:** -- `bool` - The SSE mode (HTTP Streaming) event time out status. +- `bool` - The SSE mode (HTTP Streaming) event timed out status. 9. ## 🔹 realtime_database_data_type type() diff --git a/src/Config.h b/src/Config.h index 2263d0fa..3433bb24 100644 --- a/src/Config.h +++ b/src/Config.h @@ -126,10 +126,6 @@ * * * 🏷️ For Firebase.printf buffer size. * #define FIREBASE_PRINTF_BUFFER 2048 - * - * * 🏷️ For TCP session timeout in seconds. - * The default TCP session timeout is 150 seconds. - * #define FIREBASE_SESSION_TIMEOUT */ #if __has_include("UserConfig.h") diff --git a/src/core/AsyncClient/AsyncClient.h b/src/core/AsyncClient/AsyncClient.h index 6bd60fb7..93a74e6d 100644 --- a/src/core/AsyncClient/AsyncClient.h +++ b/src/core/AsyncClient/AsyncClient.h @@ -1,5 +1,5 @@ /** - * Created June 25, 2024 + * Created June 26, 2024 * * For MCU build target (CORE_ARDUINO_XXXX), see Options.h. * @@ -186,7 +186,7 @@ class AsyncClientClass : public ResultBase, RTDBResultBase uint32_t auth_ts = 0; uint32_t cvec_addr = 0; uint32_t result_addr = 0; - uint32_t sync_send_timeout_sec = 0, sync_read_timeout_sec = 0; + uint32_t sync_send_timeout_sec = 0, sync_read_timeout_sec = 0, session_timeout_sec = 0; Timer session_timer; Client *client = nullptr; #if defined(ENABLE_ASYNC_TCP_CLIENT) @@ -236,7 +236,7 @@ class AsyncClientClass : public ResultBase, RTDBResultBase void newCon(async_data_item_t *sData, const char *host, uint16_t port) { - if ((!sData->sse && session_timer.remaining() == 0) || (sse && !sData->sse) || (!sse && sData->sse) || (sData->auth_used && sData->state == async_state_undefined) || + if ((!sData->sse && session_timeout_sec >= FIREBASE_SESSION_TIMEOUT_SEC && session_timer.remaining() == 0) || (sse && !sData->sse) || (!sse && sData->sse) || (sData->auth_used && sData->state == async_state_undefined) || strcmp(this->host.c_str(), host) != 0 || this->port != port) { stop(sData); @@ -1428,8 +1428,8 @@ class AsyncClientClass : public ResultBase, RTDBResultBase this->host = host; this->port = port; - if (client && client->connected()) - session_timer.feed(FIREBASE_SESSION_TIMEOUT); + if (client && client->connected() && session_timeout_sec >= FIREBASE_SESSION_TIMEOUT_SEC) + session_timer.feed(session_timeout_sec); return sData->return_type; } @@ -2420,18 +2420,25 @@ class AsyncClientClass : public ResultBase, RTDBResultBase void setETag(const String &etag) { reqEtag = etag; } /** - * Set the sync task's send time out in seconds. + * Set the sync task's send timeout in seconds. * - * @param timeoutSec The TCP write time out in seconds. + * @param timeoutSec The TCP write timeout in seconds. */ void setSyncSendTimeout(uint32_t timeoutSec) { sync_send_timeout_sec = timeoutSec; } /** - * Set the sync task's read time out in seconds. + * Set the sync task's read timeout in seconds. * - * @param timeoutSec The TCP read time out in seconds. + * @param timeoutSec The TCP read timeout in seconds. */ void setSyncReadTimeout(uint32_t timeoutSec) { sync_read_timeout_sec = timeoutSec; } + + /** + * Set the TCP session timeout in seconds. + * + * @param timeoutSec The TCP session timeout in seconds. + */ + void setSessionTimeout(uint32_t timeoutSec) { session_timeout_sec = timeoutSec; } }; #endif \ No newline at end of file diff --git a/src/core/AsyncClient/RequestHandler.h b/src/core/AsyncClient/RequestHandler.h index 2aa74e1c..60045820 100644 --- a/src/core/AsyncClient/RequestHandler.h +++ b/src/core/AsyncClient/RequestHandler.h @@ -39,6 +39,8 @@ #define FIREBASE_RECONNECTION_TIMEOUT_MSEC 5000 +#define FIREBASE_SESSION_TIMEOUT_SEC 150 + #define FIREBASE_AUTH_PLACEHOLDER FPSTR("") #if !defined(FIREBASE_ASYNC_QUEUE_LIMIT) diff --git a/src/core/Core.h b/src/core/Core.h index f4787d0c..fc6243a7 100644 --- a/src/core/Core.h +++ b/src/core/Core.h @@ -7,7 +7,7 @@ #undef FIREBASE_CLIENT_VERSION #endif -#define FIREBASE_CLIENT_VERSION "1.2.17" +#define FIREBASE_CLIENT_VERSION "1.2.18" static void sys_idle() { diff --git a/src/core/Error.h b/src/core/Error.h index ee746f33..a646bddd 100644 --- a/src/core/Error.h +++ b/src/core/Error.h @@ -1,5 +1,5 @@ /** - * Created May 5, 2024 + * Created June 26, 2024 * * The MIT License (MIT) * Copyright (c) 2024 K. Suwatchai (Mobizt) @@ -143,7 +143,7 @@ class FirebaseError err.setError(code, FPSTR("TCP send failed")); break; case FIREBASE_ERROR_TCP_RECEIVE_TIMEOUT: - err.setError(code, FPSTR("TCP receive time out")); + err.setError(code, FPSTR("TCP receive timed out")); break; case FIREBASE_ERROR_TCP_DISCONNECTED: err.setError(code, FPSTR("TCP disconnected")); @@ -176,7 +176,7 @@ class FirebaseError err.setError(code, FPSTR("firmware end failed")); break; case FIREBASE_ERROR_STREAM_TIMEOUT: - err.setError(code, FPSTR("stream time out")); + err.setError(code, FPSTR("stream connection timed out")); break; case FIREBASE_ERROR_STREAM_AUTH_REVOKED: err.setError(code, FPSTR("auth revoked")); diff --git a/src/core/Options.h b/src/core/Options.h index a4d597cd..58ed2f50 100644 --- a/src/core/Options.h +++ b/src/core/Options.h @@ -272,8 +272,4 @@ #define FIREBASE_ASYNC_CLIENT AsyncClient #endif -#if !defined(FIREBASE_SESSION_TIMEOUT) -#define FIREBASE_SESSION_TIMEOUT 150 -#endif - #endif \ No newline at end of file