diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index f64f5e2..26e1f07 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -15,7 +15,7 @@ If you don't find anything, please [open a new issue](https://github.com/khoih-p
Please ensure to specify the following:
* Arduino IDE version (e.g. 1.8.19) or Platform.io version
-* `ArduinoCore-mbed` Core Version (e.g. `ArduinoCore-mbed` mbed_portenta core v2.6.1)
+* `ArduinoCore-mbed` Core Version (e.g. `ArduinoCore-mbed` mbed_portenta core v3.3.0)
* `Portenta_H7` Board type (e.g. Portenta_H7 Rev2 ABX00042, etc.)
* Contextual information (e.g. what you were trying to achieve)
* Simplest possible steps to reproduce
@@ -28,13 +28,13 @@ Please ensure to specify the following:
```
Arduino IDE version: 1.8.19
-`ArduinoCore-mbed` mbed_portenta core v2.6.1
+`ArduinoCore-mbed` mbed_portenta core v3.3.0
Portenta_H7 Rev2 ABX00042
OS: Ubuntu 20.04 LTS
-Linux xy-Inspiron-3593 5.4.0-94-generic #106-Ubuntu SMP Thu Jan 6 23:58:14 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
+Linux xy-Inspiron-3593 5.15.0-46-generic #49~20.04.1-Ubuntu SMP Thu Aug 4 19:15:44 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
Context:
-I encountered a crash while using Ethernet Async_AdvancedWebServer.
+I encountered a crash while using this library
Steps to reproduce:
1. ...
diff --git a/Packages_Patches/arduino/hardware/mbed_portenta/3.3.0/portenta_post_install.sh b/Packages_Patches/arduino/hardware/mbed_portenta/3.3.0/portenta_post_install.sh
new file mode 100644
index 0000000..7fe71d6
--- /dev/null
+++ b/Packages_Patches/arduino/hardware/mbed_portenta/3.3.0/portenta_post_install.sh
@@ -0,0 +1,22 @@
+#!/usr/bin/env bash
+
+portenta_h7_rules () {
+ echo ""
+ echo "# Portenta H7 bootloader mode UDEV rules"
+ echo ""
+cat < /etc/udev/rules.d/49-portenta_h7.rules
+
+# reload udev rules
+echo "Reload rules..."
+udevadm trigger
+udevadm control --reload-rules
diff --git a/README.md b/README.md
index 571fda8..7382fb6 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,8 @@
[![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](#Contributing)
[![GitHub issues](https://img.shields.io/github/issues/khoih-prog/Portenta_H7_AsyncWebServer.svg)](http://github.com/khoih-prog/Portenta_H7_AsyncWebServer/issues)
-
+
+
---
@@ -166,8 +167,8 @@ to apply the better and faster **asynchronous** feature of the **powerful** [ESP
## Prerequisites
1. [`Arduino IDE 1.8.19+` for Arduino](https://github.com/arduino/Arduino). [![GitHub release](https://img.shields.io/github/release/arduino/Arduino.svg)](https://github.com/arduino/Arduino/releases/latest)
- 2. [`ArduinoCore-mbed mbed_portenta core 2.7.2+`](https://github.com/arduino/ArduinoCore-mbed) for Arduino **Portenta_H7** boards, such as **Portenta_H7 Rev2 ABX00042, etc.**. [![GitHub release](https://img.shields.io/github/release/arduino/ArduinoCore-mbed.svg)](https://github.com/arduino/ArduinoCore-mbed/releases/latest). To be used with [**Portenta_H7_AsyncTCP releases v1.3.0+**](https://github.com/khoih-prog/Portenta_H7_AsyncTCP/releases/tag/v1.3.0)
- 3. [`Portenta_H7_AsyncTCP library v1.3.0+`](https://github.com/khoih-prog/Portenta_H7_AsyncTCP) for Portenta_H7 using `Vision-shield Ethernet` or `Murata WiFi`. [To install. check [![arduino-library-badge](https://www.ardu-badge.com/badge/Portenta_H7_AsyncTCP.svg?)](https://www.ardu-badge.com/Portenta_H7_AsyncTCP)
+ 2. [`ArduinoCore-mbed mbed_portenta core 3.3.0+`](https://github.com/arduino/ArduinoCore-mbed) for Arduino **Portenta_H7** boards, such as **Portenta_H7 Rev2 ABX00042, etc.**. [![GitHub release](https://img.shields.io/github/release/arduino/ArduinoCore-mbed.svg)](https://github.com/arduino/ArduinoCore-mbed/releases/latest).
+ 3. [`Portenta_H7_AsyncTCP library v1.4.0+`](https://github.com/khoih-prog/Portenta_H7_AsyncTCP) for Portenta_H7 using `Vision-shield Ethernet` or `Murata WiFi`. [![GitHub release](https://img.shields.io/github/release/khoih-prog/Portenta_H7_AsyncTCP.svg)](https://github.com/khoih-prog/Portenta_H7_AsyncTCP/releases/latest)
---
@@ -180,15 +181,15 @@ The best and easiest way is to use `Arduino Library Manager`. Search for `Porten
### Manual Install
1. Navigate to [Portenta_H7_AsyncWebServer](https://github.com/khoih-prog/Portenta_H7_AsyncWebServer) page.
-2. Download the latest release `Portenta_H7_AsyncWebServer-master.zip`.
-3. Extract the zip file to `Portenta_H7_AsyncWebServer-master` directory
-4. Copy the whole `Portenta_H7_AsyncWebServer-master` folder to Arduino libraries' directory such as `~/Arduino/libraries/`.
+2. Download the latest release `Portenta_H7_AsyncWebServer-main.zip`.
+3. Extract the zip file to `Portenta_H7_AsyncWebServer-main` directory
+4. Copy the whole `Portenta_H7_AsyncWebServer-main` folder to Arduino libraries' directory such as `~/Arduino/libraries/`.
### VS Code & PlatformIO:
1. Install [VS Code](https://code.visualstudio.com/)
2. Install [PlatformIO](https://platformio.org/platformio-ide)
-3. Install [**Portenta_H7_AsyncWebServer** library](https://platformio.org/lib/show/12920/Portenta_H7_AsyncWebServer) by using [Library Manager](https://platformio.org/lib/show/12920/Portenta_H7_AsyncWebServer/installation). Search for **Portenta_H7_AsyncWebServer** in [Platform.io Author's Libraries](https://platformio.org/lib/search?query=author:%22Khoi%20Hoang%22)
+3. Install [**Portenta_H7_AsyncWebServer** library](https://registry.platformio.org/libraries/khoih-prog/Portenta_H7_AsyncWebServer) by using [Library Manager](https://registry.platformio.org/libraries/khoih-prog/Portenta_H7_AsyncWebServer/installation). Search for **Portenta_H7_AsyncWebServer** in [Platform.io Author's Libraries](https://platformio.org/lib/search?query=author:%22Khoi%20Hoang%22)
4. Use included [platformio.ini](platformio/platformio.ini) file from examples to ensure that all dependent libraries will installed automatically. Please visit documentation for the other options and examples at [Project Configuration File](https://docs.platformio.org/page/projectconf.html)
---
@@ -198,12 +199,12 @@ The best and easiest way is to use `Arduino Library Manager`. Search for `Porten
#### 1. For Portenta_H7 boards using Arduino IDE in Linux
- **To be able to upload firmware to Portenta_H7 using Arduino IDE in Linux (Ubuntu, etc.)**, you have to copy the file [portenta_post_install.sh](Packages_Patches/arduino/hardware/mbed_portenta/2.6.1/portenta_post_install.sh) into mbed_portenta directory (~/.arduino15/packages/arduino/hardware/mbed_portenta/2.6.1/portenta_post_install.sh).
+ **To be able to upload firmware to Portenta_H7 using Arduino IDE in Linux (Ubuntu, etc.)**, you have to copy the file [portenta_post_install.sh](Packages_Patches/arduino/hardware/mbed_portenta/3.3.0/portenta_post_install.sh) into mbed_portenta directory (~/.arduino15/packages/arduino/hardware/mbed_portenta/3.3.0/portenta_post_install.sh).
Then run the following command using `sudo`
```
-$ cd ~/.arduino15/packages/arduino/hardware/mbed_portenta/2.6.1
+$ cd ~/.arduino15/packages/arduino/hardware/mbed_portenta/3.3.0
$ chmod 755 portenta_post_install.sh
$ sudo ./portenta_post_install.sh
```
@@ -216,9 +217,9 @@ This will create the file `/etc/udev/rules.d/49-portenta_h7.rules` as follows:
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2341", ATTRS{idProduct}=="035b", GROUP="plugdev", MODE="0666"
```
-Supposing the ArduinoCore-mbed core version is 2.6.1. Now only one file must be copied into the directory:
+Supposing the ArduinoCore-mbed core version is 3.3.0. Now only one file must be copied into the directory:
-- `~/.arduino15/packages/arduino/hardware/mbed_portenta/2.6.1/portenta_post_install.sh`
+- `~/.arduino15/packages/arduino/hardware/mbed_portenta/3.3.0/portenta_post_install.sh`
Whenever a new version is installed, remember to copy this files into the new version directory. For example, new version is x.yy.zz
@@ -230,7 +231,7 @@ This file must be copied into the directory:
#### 2. To fix compile error relating to dns_gethostbyname and LwIP stack
-#### Notes: Only for cores v2.5.2-. This fix is not necessary for core v2.6.1+
+#### Notes: Only for cores v2.5.2-. This fix is not necessary for core v3.3.0+
**To be able to compile, run on Portenta_H7 boards**, you have to copy the whole [mbed_portenta Packages_Patches](Packages_Patches/arduino/hardware/mbed_portenta/2.5.2) directory into Arduino mbed_portenta directory (~/.arduino15/packages/arduino/hardware/mbed_portenta/2.5.2).
@@ -1484,248 +1485,7 @@ build_flags =
### Example [Async_AdvancedWebServer](examples/Ethernet/Async_AdvancedWebServer)
-```cpp
-#if !( defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) )
- #error For Portenta_H7 only
-#endif
-
-#define _PORTENTA_H7_AWS_LOGLEVEL_ 1
-
-#define USE_ETHERNET_PORTENTA_H7 true
-
-#include
-#include
-#warning Using Portenta_Ethernet lib for Portenta_H7.
-
-#include
-
-// Enter a MAC address and IP address for your controller below.
-#define NUMBER_OF_MAC 20
-
-byte mac[][NUMBER_OF_MAC] =
-{
- { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x01 },
- { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x02 },
- { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x03 },
- { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x04 },
- { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x05 },
- { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x06 },
- { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x07 },
- { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x08 },
- { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x09 },
- { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x0A },
- { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x0B },
- { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x0C },
- { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x0D },
- { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x0E },
- { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x0F },
- { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x10 },
- { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x11 },
- { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x12 },
- { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x13 },
- { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x14 },
-};
-// Select the IP address according to your local network
-IPAddress ip(192, 168, 2, 232);
-
-AsyncWebServer server(80);
-
-int reqCount = 0; // number of requests received
-
-#define LED_OFF HIGH
-#define LED_ON LOW
-
-
-#define BUFFER_SIZE 512
-char temp[BUFFER_SIZE];
-
-void handleRoot(AsyncWebServerRequest *request)
-{
- digitalWrite(LED_BUILTIN, LED_ON);
-
- int sec = millis() / 1000;
- int min = sec / 60;
- int hr = min / 60;
- int day = hr / 24;
-
- snprintf(temp, BUFFER_SIZE - 1,
- "\
-\
- \
-AsyncWebServer-%s \
-\
-\
-\
-AsyncWebServer_Portenta_H7! \
-running on %s \
-Uptime: %d d %02d:%02d:%02d
\
- \
-\
-", BOARD_NAME, BOARD_NAME, day, hr % 24, min % 60, sec % 60);
-
- request->send(200, "text/html", temp);
-
- digitalWrite(LED_BUILTIN, LED_OFF);
-}
-
-void handleNotFound(AsyncWebServerRequest *request)
-{
- digitalWrite(LED_BUILTIN, LED_ON);
- String message = "File Not Found\n\n";
-
- message += "URI: ";
- message += request->url();
- message += "\nMethod: ";
- message += (request->method() == HTTP_GET) ? "GET" : "POST";
- message += "\nArguments: ";
- message += request->args();
- message += "\n";
-
- for (uint8_t i = 0; i < request->args(); i++)
- {
- message += " " + request->argName(i) + ": " + request->arg(i) + "\n";
- }
-
- request->send(404, "text/plain", message);
- digitalWrite(LED_BUILTIN, LED_OFF);
-}
-
-void drawGraph(AsyncWebServerRequest *request)
-{
- String out;
-
- out.reserve(3000);
- char temp[70];
-
- out += "\n";
- out += " \n";
- out += "\n";
- int y = rand() % 130;
-
- for (int x = 10; x < 300; x += 10)
- {
- int y2 = rand() % 130;
- sprintf(temp, " \n", x, 140 - y, x + 10, 140 - y2);
- out += temp;
- y = y2;
- }
- out += " \n \n";
-
- request->send(200, "image/svg+xml", out);
-}
-
-
-void setup()
-{
- pinMode(LED_BUILTIN, OUTPUT);
- digitalWrite(LED_BUILTIN, LED_OFF);
-
- Serial.begin(115200);
- while (!Serial);
-
- delay(200);
-
- Serial.print("\nStart Async_AdvancedWebServer on "); Serial.print(BOARD_NAME);
- Serial.print(" with "); Serial.println(SHIELD_TYPE);
- Serial.println(PORTENTA_H7_ASYNC_TCP_VERSION);
- Serial.println(PORTENTA_H7_ASYNC_WEBSERVER_VERSION);
-
- ///////////////////////////////////
-
- // start the ethernet connection and the server
- // Use random mac
- uint16_t index = millis() % NUMBER_OF_MAC;
-
- // Use Static IP
- //Ethernet.begin(mac[index], ip);
- // Use DHCP dynamic IP and random mac
- Ethernet.begin(mac[index]);
-
- if (Ethernet.hardwareStatus() == EthernetNoHardware)
- {
- Serial.println("No Ethernet found. Stay here forever");
-
- while (true)
- {
- delay(1); // do nothing, no point running without Ethernet hardware
- }
- }
-
- if (Ethernet.linkStatus() == LinkOFF)
- {
- Serial.println("Not connected Ethernet cable");
- }
-
- Serial.print(F("Using mac index = "));
- Serial.println(index);
-
- Serial.print(F("Connected! IP address: "));
- Serial.println(Ethernet.localIP());
-
- ///////////////////////////////////
-
-
- server.on("/", HTTP_GET, [](AsyncWebServerRequest * request)
- {
- handleRoot(request);
- });
-
- server.on("/test.svg", HTTP_GET, [](AsyncWebServerRequest * request)
- {
- drawGraph(request);
- });
-
- server.on("/inline", [](AsyncWebServerRequest * request)
- {
- request->send(200, "text/plain", "This works as well");
- });
-
- server.onNotFound(handleNotFound);
-
- server.begin();
-
- Serial.print(F("HTTP EthernetWebServer is @ IP : "));
- Serial.println(Ethernet.localIP());
-}
-
-void heartBeatPrint()
-{
- static int num = 1;
-
- Serial.print(F("."));
-
- if (num == 80)
- {
- Serial.println();
- num = 1;
- }
- else if (num++ % 10 == 0)
- {
- Serial.print(F(" "));
- }
-}
-
-void check_status()
-{
- static unsigned long checkstatus_timeout = 0;
-
-#define STATUS_CHECK_INTERVAL 10000L
-
- // Send status report every STATUS_REPORT_INTERVAL (60) seconds: we don't need to send updates frequently if there is no status change.
- if ((millis() > checkstatus_timeout) || (checkstatus_timeout == 0))
- {
- heartBeatPrint();
- checkstatus_timeout = millis() + STATUS_CHECK_INTERVAL;
- }
-}
-
-void loop()
-{
- check_status();
-}
-```
+https://github.com/khoih-prog/Portenta_H7_AsyncWebServer/blob/f934df6aecbf814047affe39d3d0e3f23fc1fccf/examples/WiFi/Async_AdvancedWebServer/Async_AdvancedWebServer.ino#L41-L268
You can access the Async Advanced WebServer @ the server IP
@@ -1745,8 +1505,8 @@ Following is debug terminal output when running example [MQTT_ThingStream](examp
```
Start MQTT_ThingStream on PORTENTA_H7_M7 with Ethernet using Portenta_Ethernet Library
-Portenta_H7_AsyncTCP v1.3.0
-Portenta_H7_AsyncWebServer v1.2.1
+Portenta_H7_AsyncTCP v1.4.0
+Portenta_H7_AsyncWebServer v1.3.0
Using mac index = 17
Connected! IP address: 192.168.2.87
***************************************
@@ -1770,8 +1530,8 @@ Following is debug terminal output when running example [WebClient](examples/Eth
```
Start WebClientRepeating on PORTENTA_H7_M7 with Ethernet using Portenta_Ethernet Library
-Portenta_H7_AsyncTCP v1.3.0
-Portenta_H7_AsyncWebServer v1.2.1
+Portenta_H7_AsyncTCP v1.4.0
+Portenta_H7_AsyncWebServer v1.3.0
Using mac index = 16
Connected! IP address: 192.168.2.87
@@ -1838,8 +1598,8 @@ Following is debug terminal output when running example [MQTTClient_Auth](exampl
```
Start MQTTClient_Auth on PORTENTA_H7_M7 with Ethernet using Portenta_Ethernet Library
-Portenta_H7_AsyncTCP v1.3.0
-Portenta_H7_AsyncWebServer v1.2.1
+Portenta_H7_AsyncTCP v1.4.0
+Portenta_H7_AsyncWebServer v1.3.0
Using mac index = 9
Connected! IP address: 192.168.2.87
Attempting MQTT connection to broker.emqx.io...connected
@@ -1859,8 +1619,8 @@ Following is debug terminal output when running example [MQTTClient_Basic](examp
```
Start MQTTClient_Basic on PORTENTA_H7_M7 with Ethernet using Portenta_Ethernet Library
-Portenta_H7_AsyncTCP v1.3.0
-Portenta_H7_AsyncWebServer v1.2.1
+Portenta_H7_AsyncTCP v1.4.0
+Portenta_H7_AsyncWebServer v1.3.0
Using mac index = 8
Connected! IP address: 192.168.2.87
Attempting MQTT connection to broker.emqx.io...connected
@@ -1878,8 +1638,8 @@ Following is debug terminal output when running example [Async_HTTPBasicAuth](ex
```
Start Async_HTTPBasicAuth on PORTENTA_H7_M7 with Ethernet using Portenta_Ethernet Library
-Portenta_H7_AsyncTCP v1.3.0
-Portenta_H7_AsyncWebServer v1.2.1
+Portenta_H7_AsyncTCP v1.4.0
+Portenta_H7_AsyncWebServer v1.3.0
Using mac index = 16
Connected! IP address: 192.168.2.87
Async_HttpBasicAuth started @ IP : 192.168.2.87
@@ -1908,8 +1668,8 @@ Following are debug terminal output and screen shots when running example [Async
```
Start Async_AdvancedWebServer on PORTENTA_H7_M7 with Ethernet using Portenta_Ethernet Library
-Portenta_H7_AsyncTCP v1.3.0
-Portenta_H7_AsyncWebServer v1.2.1
+Portenta_H7_AsyncTCP v1.4.0
+Portenta_H7_AsyncWebServer v1.3.0
Using mac index = 4
Connected! IP address: 192.168.2.87
HTTP EthernetWebServer is @ IP : 192.168.2.87
@@ -1921,6 +1681,12 @@ You can access the Async Advanced WebServers at the displayed server IP, e.g. `1
+#### Using Firefox Browser
+
+
+
+
+
---
#### 7. Async_AdvancedWebServer on PORTENTA_H7_M7 using WiFi
@@ -1929,8 +1695,8 @@ Following is the debug terminal and screen shot when running example [Async_Adva
```
Start Async_AdvancedWebServer on PORTENTA_H7_M7 with Portenta_H7 WiFi
-Portenta_H7_AsyncTCP v1.3.0
-Portenta_H7_AsyncWebServer v1.2.1
+Portenta_H7_AsyncTCP v1.4.0
+Portenta_H7_AsyncWebServer v1.3.0
Connecting to SSID: HueNet1
SSID: HueNet1
Local IP Address: 192.168.2.94
@@ -1985,6 +1751,7 @@ Submit issues to: [Portenta_H7_AsyncWebServer issues](https://github.com/khoih-p
1. Add support to Portenta_H7 using `Vision-shield Ethernet`
2. Add Table of Contents
+ 3. Fix issue with slow browsers or network. Check [Target stops responding after variable time when using Firefox on Windows 10 #3](https://github.com/khoih-prog/AsyncWebServer_RP2040W/issues/3)
---
---
diff --git a/changelog.md b/changelog.md
index efa5f23..deb712a 100644
--- a/changelog.md
+++ b/changelog.md
@@ -11,6 +11,7 @@
## Table of Contents
* [Changelog](#changelog)
+ * [Releases v1.3.0](#Releases-v130)
* [Releases v1.2.1](#Releases-v121)
* [Releases v1.2.0](#Releases-v120)
* [Releases v1.1.1](#Releases-v111)
@@ -22,6 +23,10 @@
## Changelog
+### Releases v1.3.0
+
+1. Fix issue with slow browsers or network. Check [Target stops responding after variable time when using Firefox on Windows 10 #3](https://github.com/khoih-prog/AsyncWebServer_RP2040W/issues/3)
+
### Releases v1.2.1
1. Fix authenticate issue caused by libb64
diff --git a/library.json b/library.json
index 6934770..6e8b0c8 100644
--- a/library.json
+++ b/library.json
@@ -1,6 +1,6 @@
{
"name": "Portenta_H7_AsyncWebServer",
- "version": "1.2.1",
+ "version": "1.3.0",
"keywords": "http, async, websocket, webserver, async-webserver, async-tcp, async-udp, async-websocket, async-http, ssl, tls, mbed, mbed-portenta, portenta-h7, portentah7, portenta-h7-m7, portenta-h7-m4, portentah7-m7, portentah7-m4, stm32h7",
"description": "Asynchronous WebServer Library for STM32H7-based Portenta_H7 using mbed_portenta core. This library, which is relied on Portenta_H7_AsyncTCP, is part of a series of advanced Async libraries, such as AsyncTCP, AsyncUDP, AsyncWebSockets, AsyncHTTPRequest, AsyncHTTPSRequest, etc.",
"authors":
@@ -34,7 +34,7 @@
{
"owner": "khoih-prog",
"name": "Portenta_H7_AsyncTCP",
- "version": "^1.3.0"
+ "version": "^1.4.0"
}
],
"license": "LGPL-3.0",
diff --git a/library.properties b/library.properties
index 1967a60..9692c65 100644
--- a/library.properties
+++ b/library.properties
@@ -1,5 +1,5 @@
name=Portenta_H7_AsyncWebServer
-version=1.2.1
+version=1.3.0
author=Hristo Gochkov,Khoi Hoang
maintainer=Khoi Hoang
sentence=Asynchronous WebServer Library for STM32H7-based Portenta_H7 using mbed_portenta core.
diff --git a/pics/Async_AdvancedWebServer_Firefox.png b/pics/Async_AdvancedWebServer_Firefox.png
new file mode 100644
index 0000000..fab3f56
Binary files /dev/null and b/pics/Async_AdvancedWebServer_Firefox.png differ
diff --git a/platformio/platformio.ini b/platformio/platformio.ini
index d44d2a3..a4c6fb0 100644
--- a/platformio/platformio.ini
+++ b/platformio/platformio.ini
@@ -38,13 +38,16 @@ upload_speed = 921600
;monitor_port = COM11
; Checks for the compatibility with frameworks and dev/platforms
+; Adjust as necessary
lib_compat_mode = strict
+lib_ldf_mode = chain+
+;lib_ldf_mode = deep+
lib_deps =
; PlatformIO 4.x
-; Portenta_H7_AsyncTCP@>=1.3.0
+; Portenta_H7_AsyncTCP@>=1.4.0
; PlatformIO 5.x
- khoih-prog/Portenta_H7_AsyncTCP@>=1.3.0
+ khoih-prog/Portenta_H7_AsyncTCP@>=1.4.0
build_flags =
diff --git a/src/Portenta_H7_AsyncEventSource.cpp b/src/Portenta_H7_AsyncEventSource.cpp
index b4b8c5f..41004c3 100644
--- a/src/Portenta_H7_AsyncEventSource.cpp
+++ b/src/Portenta_H7_AsyncEventSource.cpp
@@ -9,7 +9,7 @@
Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_AsyncWebServer
Licensed under GPLv3 license
- Version: 1.2.1
+ Version: 1.3.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -18,6 +18,7 @@
1.1.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json`
1.2.0 K Hoang 07/12/2021 Fix crashing issue
1.2.1 K Hoang 12/01/2022 Fix authenticate issue caused by libb64
+ 1.3.0 K Hoang 26/09/2022 Fix issue with slow browsers or network
*****************************************************************************************************************************/
#if !defined(_PORTENTA_H7_AWS_LOGLEVEL_)
@@ -29,6 +30,8 @@
#include "Arduino.h"
#include "Portenta_H7_AsyncEventSource.h"
+/////////////////////////////////////////////////
+
static String generateEventMessage(const char *message, const char *event, uint32_t id, uint32_t reconnect)
{
String ev = "";
@@ -143,6 +146,8 @@ static String generateEventMessage(const char *message, const char *event, uint3
return ev;
}
+/////////////////////////////////////////////////
+
// Message
AsyncEventSourceMessage::AsyncEventSourceMessage(const char * data, size_t len)
@@ -161,12 +166,16 @@ AsyncEventSourceMessage::AsyncEventSourceMessage(const char * data, size_t len)
}
}
+/////////////////////////////////////////////////
+
AsyncEventSourceMessage::~AsyncEventSourceMessage()
{
if (_data != NULL)
free(_data);
}
+/////////////////////////////////////////////////
+
size_t AsyncEventSourceMessage::ack(size_t len, uint32_t time)
{
PORTENTA_H7_AWS_UNUSED(time);
@@ -187,6 +196,8 @@ size_t AsyncEventSourceMessage::ack(size_t len, uint32_t time)
return 0;
}
+/////////////////////////////////////////////////
+
size_t AsyncEventSourceMessage::send(AsyncClient *client)
{
const size_t len = _len - _sent;
@@ -206,6 +217,8 @@ size_t AsyncEventSourceMessage::send(AsyncClient *client)
return sent;
}
+/////////////////////////////////////////////////
+
// Client
AsyncEventSourceClient::AsyncEventSourceClient(AsyncWebServerRequest *request, AsyncEventSource *server)
@@ -253,12 +266,16 @@ AsyncEventSourceClient::AsyncEventSourceClient(AsyncWebServerRequest *request, A
delete request;
}
+/////////////////////////////////////////////////
+
AsyncEventSourceClient::~AsyncEventSourceClient()
{
_messageQueue.free();
close();
}
+/////////////////////////////////////////////////
+
void AsyncEventSourceClient::_queueMessage(AsyncEventSourceMessage *dataMessage)
{
if (dataMessage == NULL)
@@ -285,6 +302,8 @@ void AsyncEventSourceClient::_queueMessage(AsyncEventSourceMessage *dataMessage)
_runQueue();
}
+/////////////////////////////////////////////////
+
void AsyncEventSourceClient::_onAck(size_t len, uint32_t time)
{
AWS_LOGDEBUG("AsyncEventSourceClient::_onAck");
@@ -300,6 +319,8 @@ void AsyncEventSourceClient::_onAck(size_t len, uint32_t time)
_runQueue();
}
+/////////////////////////////////////////////////
+
void AsyncEventSourceClient::_onPoll()
{
AWS_LOGDEBUG("AsyncEventSourceClient::_onPoll");
@@ -310,6 +331,7 @@ void AsyncEventSourceClient::_onPoll()
}
}
+/////////////////////////////////////////////////
void AsyncEventSourceClient::_onTimeout(uint32_t time __attribute__((unused)))
{
@@ -318,6 +340,8 @@ void AsyncEventSourceClient::_onTimeout(uint32_t time __attribute__((unused)))
_client->close(true);
}
+/////////////////////////////////////////////////
+
void AsyncEventSourceClient::_onDisconnect()
{
AWS_LOGDEBUG("AsyncEventSourceClient::_onDisconnect");
@@ -326,6 +350,8 @@ void AsyncEventSourceClient::_onDisconnect()
_server->_handleDisconnect(this);
}
+/////////////////////////////////////////////////
+
void AsyncEventSourceClient::close()
{
AWS_LOGDEBUG("AsyncEventSourceClient::close");
@@ -334,6 +360,8 @@ void AsyncEventSourceClient::close()
_client->close();
}
+/////////////////////////////////////////////////
+
void AsyncEventSourceClient::write(const char * message, size_t len)
{
AWS_LOGDEBUG3("AsyncEventSourceClient::write: message =", message, ", len =", len);
@@ -341,6 +369,8 @@ void AsyncEventSourceClient::write(const char * message, size_t len)
_queueMessage(new AsyncEventSourceMessage(message, len));
}
+/////////////////////////////////////////////////
+
void AsyncEventSourceClient::send(const char *message, const char *event, uint32_t id, uint32_t reconnect)
{
AWS_LOGDEBUG5("AsyncEventSourceClient::send: message =", message, ", event =", event, ", id =", id);
@@ -349,6 +379,8 @@ void AsyncEventSourceClient::send(const char *message, const char *event, uint32
_queueMessage(new AsyncEventSourceMessage(ev.c_str(), ev.length()));
}
+/////////////////////////////////////////////////
+
void AsyncEventSourceClient::_runQueue()
{
while (!_messageQueue.isEmpty() && _messageQueue.front()->finished())
@@ -363,6 +395,7 @@ void AsyncEventSourceClient::_runQueue()
}
}
+/////////////////////////////////////////////////
// Handler
@@ -375,11 +408,15 @@ AsyncEventSource::AsyncEventSource(const String& url)
, _connectcb(NULL)
{}
+/////////////////////////////////////////////////
+
AsyncEventSource::~AsyncEventSource()
{
close();
}
+/////////////////////////////////////////////////
+
void AsyncEventSource::onConnect(ArEventHandlerFunction cb)
{
AWS_LOGDEBUG("AsyncEventSource::onConnect");
@@ -387,6 +424,8 @@ void AsyncEventSource::onConnect(ArEventHandlerFunction cb)
_connectcb = cb;
}
+/////////////////////////////////////////////////
+
void AsyncEventSource::_addClient(AsyncEventSourceClient * client)
{
/*char * temp = (char *)malloc(2054);
@@ -410,12 +449,16 @@ void AsyncEventSource::_addClient(AsyncEventSourceClient * client)
_connectcb(client);
}
+/////////////////////////////////////////////////
+
void AsyncEventSource::_handleDisconnect(AsyncEventSourceClient * client)
{
AWS_LOGDEBUG("AsyncEventSource::_handleDisconnect");
_clients.remove(client);
}
+/////////////////////////////////////////////////
+
void AsyncEventSource::close()
{
AWS_LOGDEBUG("AsyncEventSource::close");
@@ -427,6 +470,8 @@ void AsyncEventSource::close()
}
}
+/////////////////////////////////////////////////
+
// pmb fix
size_t AsyncEventSource::avgPacketsWaiting() const
{
@@ -449,6 +494,8 @@ size_t AsyncEventSource::avgPacketsWaiting() const
return ((aql) + (nConnectedClients / 2)) / (nConnectedClients); // round up
}
+/////////////////////////////////////////////////
+
void AsyncEventSource::send(const char *message, const char *event, uint32_t id, uint32_t reconnect)
{
String ev = generateEventMessage(message, event, id, reconnect);
@@ -462,6 +509,8 @@ void AsyncEventSource::send(const char *message, const char *event, uint32_t id,
}
}
+/////////////////////////////////////////////////
+
size_t AsyncEventSource::count() const
{
return _clients.count_if([](AsyncEventSourceClient * c)
@@ -470,6 +519,8 @@ size_t AsyncEventSource::count() const
});
}
+/////////////////////////////////////////////////
+
bool AsyncEventSource::canHandle(AsyncWebServerRequest *request)
{
if (request->method() != HTTP_GET || !request->url().equals(_url))
@@ -482,6 +533,8 @@ bool AsyncEventSource::canHandle(AsyncWebServerRequest *request)
return true;
}
+/////////////////////////////////////////////////
+
void AsyncEventSource::handleRequest(AsyncWebServerRequest *request)
{
if ((_username != "" && _password != "") && !request->authenticate(_username.c_str(), _password.c_str()))
@@ -490,6 +543,8 @@ void AsyncEventSource::handleRequest(AsyncWebServerRequest *request)
request->send(new AsyncEventSourceResponse(this));
}
+/////////////////////////////////////////////////
+
// Response
AsyncEventSourceResponse::AsyncEventSourceResponse(AsyncEventSource *server)
@@ -502,6 +557,8 @@ AsyncEventSourceResponse::AsyncEventSourceResponse(AsyncEventSource *server)
addHeader("Connection", "keep-alive");
}
+/////////////////////////////////////////////////
+
void AsyncEventSourceResponse::_respond(AsyncWebServerRequest *request)
{
String out = _assembleHead(request->version());
@@ -509,6 +566,8 @@ void AsyncEventSourceResponse::_respond(AsyncWebServerRequest *request)
_state = RESPONSE_WAIT_ACK;
}
+/////////////////////////////////////////////////
+
size_t AsyncEventSourceResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time __attribute__((unused)))
{
if (len)
@@ -519,3 +578,5 @@ size_t AsyncEventSourceResponse::_ack(AsyncWebServerRequest *request, size_t len
return 0;
}
+/////////////////////////////////////////////////
+
diff --git a/src/Portenta_H7_AsyncEventSource.h b/src/Portenta_H7_AsyncEventSource.h
index fde583b..9f51041 100644
--- a/src/Portenta_H7_AsyncEventSource.h
+++ b/src/Portenta_H7_AsyncEventSource.h
@@ -9,7 +9,7 @@
Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_AsyncWebServer
Licensed under GPLv3 license
- Version: 1.2.1
+ Version: 1.3.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -18,6 +18,7 @@
1.1.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json`
1.2.0 K Hoang 07/12/2021 Fix crashing issue
1.2.1 K Hoang 12/01/2022 Fix authenticate issue caused by libb64
+ 1.3.0 K Hoang 26/09/2022 Fix issue with slow browsers or network
*****************************************************************************************************************************/
#pragma once
@@ -40,11 +41,15 @@
#define DEFAULT_MAX_SSE_CLIENTS 8
//#define DEFAULT_MAX_SSE_CLIENTS 4
+/////////////////////////////////////////////////
+
class AsyncEventSource;
class AsyncEventSourceResponse;
class AsyncEventSourceClient;
typedef std::function ArEventHandlerFunction;
+/////////////////////////////////////////////////
+
class AsyncEventSourceMessage
{
private:
@@ -71,6 +76,8 @@ class AsyncEventSourceMessage
}
};
+/////////////////////////////////////////////////
+
class AsyncEventSourceClient
{
private:
@@ -117,6 +124,8 @@ class AsyncEventSourceClient
void _onDisconnect();
};
+/////////////////////////////////////////////////
+
class AsyncEventSource: public AsyncWebHandler
{
private:
@@ -146,6 +155,8 @@ class AsyncEventSource: public AsyncWebHandler
virtual void handleRequest(AsyncWebServerRequest *request) override final;
};
+/////////////////////////////////////////////////
+
class AsyncEventSourceResponse: public AsyncWebServerResponse
{
private:
@@ -163,4 +174,6 @@ class AsyncEventSourceResponse: public AsyncWebServerResponse
}
};
+/////////////////////////////////////////////////
+
#endif /* PORTENTA_H7_ASYNCEVENTSOURCE_H_ */
diff --git a/src/Portenta_H7_AsyncJson.h b/src/Portenta_H7_AsyncJson.h
index eed5621..83229e4 100644
--- a/src/Portenta_H7_AsyncJson.h
+++ b/src/Portenta_H7_AsyncJson.h
@@ -9,7 +9,7 @@
Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_AsyncWebServer
Licensed under GPLv3 license
- Version: 1.2.1
+ Version: 1.3.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -18,6 +18,7 @@
1.1.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json`
1.2.0 K Hoang 07/12/2021 Fix crashing issue
1.2.1 K Hoang 12/01/2022 Fix authenticate issue caused by libb64
+ 1.3.0 K Hoang 26/09/2022 Fix issue with slow browsers or network
*****************************************************************************************************************************/
/*
Async Response to use with ArduinoJson and AsyncWebServer
@@ -62,14 +63,18 @@
#include
#include
+/////////////////////////////////////////////////
+
#if ARDUINOJSON_VERSION_MAJOR == 5
-#define ARDUINOJSON_5_COMPATIBILITY
+ #define ARDUINOJSON_5_COMPATIBILITY
#else
-#define DYNAMIC_JSON_DOCUMENT_SIZE 1024
+ #define DYNAMIC_JSON_DOCUMENT_SIZE 1024
#endif
constexpr const char* JSON_MIMETYPE = "application/json";
+/////////////////////////////////////////////////
+
/*
Json Response
* */
@@ -113,6 +118,8 @@ class ChunkPrint : public Print
}
};
+/////////////////////////////////////////////////
+
class AsyncJsonResponse: public AsyncAbstractResponse
{
protected:
@@ -199,6 +206,8 @@ class AsyncJsonResponse: public AsyncAbstractResponse
}
};
+/////////////////////////////////////////////////
+
class PrettyAsyncJsonResponse: public AsyncJsonResponse
{
public:
@@ -238,6 +247,8 @@ class PrettyAsyncJsonResponse: public AsyncJsonResponse
}
};
+/////////////////////////////////////////////////
+
typedef std::function ArJsonRequestHandlerFunction;
class AsyncCallbackJsonWebHandler: public AsyncWebHandler
@@ -265,21 +276,29 @@ class AsyncCallbackJsonWebHandler: public AsyncWebHandler
: _uri(uri), _method(HTTP_POST | HTTP_PUT | HTTP_PATCH), _onRequest(onRequest), maxJsonBufferSize(maxJsonBufferSize), _maxContentLength(16384) {}
#endif
+ /////////////////////////////////////////////////
+
void setMethod(WebRequestMethodComposite method)
{
_method = method;
}
+
+ /////////////////////////////////////////////////
void setMaxContentLength(int maxContentLength)
{
_maxContentLength = maxContentLength;
}
+
+ /////////////////////////////////////////////////
void onRequest(ArJsonRequestHandlerFunction fn)
{
_onRequest = fn;
}
+ /////////////////////////////////////////////////
+
virtual bool canHandle(AsyncWebServerRequest *request) override final
{
if (!_onRequest)
@@ -299,6 +318,8 @@ class AsyncCallbackJsonWebHandler: public AsyncWebHandler
return true;
}
+ /////////////////////////////////////////////////
+
virtual void handleRequest(AsyncWebServerRequest *request) override final
{
if (_onRequest)
@@ -334,10 +355,14 @@ class AsyncCallbackJsonWebHandler: public AsyncWebHandler
request->send(500);
}
}
+
+ /////////////////////////////////////////////////
virtual void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) override final
{
}
+
+ /////////////////////////////////////////////////
virtual void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) override final
{
@@ -356,11 +381,18 @@ class AsyncCallbackJsonWebHandler: public AsyncWebHandler
}
}
}
+
+ /////////////////////////////////////////////////
virtual bool isRequestHandlerTrivial() override final
{
return _onRequest ? false : true;
}
+
+ /////////////////////////////////////////////////
+
};
+/////////////////////////////////////////////////
+
#endif // PORTENTA_H7_ASYNC_JSON_H_
diff --git a/src/Portenta_H7_AsyncWebAuthentication.cpp b/src/Portenta_H7_AsyncWebAuthentication.cpp
index 5628c31..ab7b2ab 100644
--- a/src/Portenta_H7_AsyncWebAuthentication.cpp
+++ b/src/Portenta_H7_AsyncWebAuthentication.cpp
@@ -9,7 +9,7 @@
Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_AsyncWebServer
Licensed under GPLv3 license
- Version: 1.2.1
+ Version: 1.3.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -18,6 +18,7 @@
1.1.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json`
1.2.0 K Hoang 07/12/2021 Fix crashing issue
1.2.1 K Hoang 12/01/2022 Fix authenticate issue caused by libb64
+ 1.3.0 K Hoang 26/09/2022 Fix issue with slow browsers or network
*****************************************************************************************************************************/
#if !defined(_PORTENTA_H7_AWS_LOGLEVEL_)
@@ -34,6 +35,8 @@
#include "Crypto/bearssl_hash.h"
#include "Crypto/Hash.h"
+/////////////////////////////////////////////////
+
// Basic Auth hash = base64("username:password")
bool checkBasicAuthentication(const char * hash, const char * username, const char * password)
@@ -41,6 +44,7 @@ bool checkBasicAuthentication(const char * hash, const char * username, const ch
if (username == NULL || password == NULL || hash == NULL)
{
AWS_LOGDEBUG("checkBasicAuthentication: Fail: NULL username/password/hash");
+
return false;
}
@@ -70,6 +74,7 @@ bool checkBasicAuthentication(const char * hash, const char * username, const ch
AWS_LOGDEBUG("checkBasicAuthentication: NULL encoded");
delete[] toencode;
+
return false;
}
@@ -81,6 +86,7 @@ bool checkBasicAuthentication(const char * hash, const char * username, const ch
delete[] toencode;
delete[] encoded;
+
return true;
}
@@ -88,9 +94,12 @@ bool checkBasicAuthentication(const char * hash, const char * username, const ch
delete[] toencode;
delete[] encoded;
+
return false;
}
+/////////////////////////////////////////////////
+
static bool getMD5(uint8_t * data, uint16_t len, char * output)
{
//33 bytes or more
@@ -127,9 +136,10 @@ static bool getMD5(uint8_t * data, uint16_t len, char * output)
return true;
}
+/////////////////////////////////////////////////
+
static String genRandomMD5()
{
- // For STM32
uint32_t r = rand();
char * out = (char*) malloc(33);
@@ -145,6 +155,8 @@ static String genRandomMD5()
return res;
}
+/////////////////////////////////////////////////
+
static String stringMD5(const String& in)
{
char * out = (char*) malloc(33);
@@ -160,6 +172,8 @@ static String stringMD5(const String& in)
return res;
}
+/////////////////////////////////////////////////
+
String generateDigestHash(const char * username, const char * password, const char * realm)
{
if (username == NULL || password == NULL || realm == NULL)
@@ -189,6 +203,8 @@ String generateDigestHash(const char * username, const char * password, const ch
return res;
}
+/////////////////////////////////////////////////
+
String requestDigestAuthentication(const char * realm)
{
String header = "realm=\"";
@@ -209,8 +225,10 @@ String requestDigestAuthentication(const char * realm)
return header;
}
+/////////////////////////////////////////////////
+
bool checkDigestAuthentication(const char * header, const char * method, const char * username, const char * password,
- const char * realm, bool passwordIsHash, const char * nonce, const char * opaque, const char * uri)
+ const char * realm, bool passwordIsHash, const char * nonce, const char * opaque, const char * uri)
{
if (username == NULL || password == NULL || header == NULL || method == NULL)
{
@@ -351,3 +369,6 @@ bool checkDigestAuthentication(const char * header, const char * method, const c
return false;
}
+
+/////////////////////////////////////////////////
+
diff --git a/src/Portenta_H7_AsyncWebAuthentication.h b/src/Portenta_H7_AsyncWebAuthentication.h
index 3c9766e..b8e7956 100644
--- a/src/Portenta_H7_AsyncWebAuthentication.h
+++ b/src/Portenta_H7_AsyncWebAuthentication.h
@@ -9,7 +9,7 @@
Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_AsyncWebServer
Licensed under GPLv3 license
- Version: 1.2.1
+ Version: 1.3.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -18,6 +18,7 @@
1.1.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json`
1.2.0 K Hoang 07/12/2021 Fix crashing issue
1.2.1 K Hoang 12/01/2022 Fix authenticate issue caused by libb64
+ 1.3.0 K Hoang 26/09/2022 Fix issue with slow browsers or network
*****************************************************************************************************************************/
#pragma once
@@ -28,9 +29,12 @@
#include "Arduino.h"
#include "Portenta_H7_AsyncWebServer_Debug.h"
+/////////////////////////////////////////////////
+
bool checkBasicAuthentication(const char * header, const char * username, const char * password);
String requestDigestAuthentication(const char * realm);
-bool checkDigestAuthentication(const char * header, const char * method, const char * username, const char * password, const char * realm, bool passwordIsHash, const char * nonce, const char * opaque, const char * uri);
+bool checkDigestAuthentication(const char * header, const char * method, const char * username, const char * password, const char * realm,
+ bool passwordIsHash, const char * nonce, const char * opaque, const char * uri);
//for storing hashed versions on the device that can be authenticated against
String generateDigestHash(const char * username, const char * password, const char * realm);
diff --git a/src/Portenta_H7_AsyncWebHandlerImpl.h b/src/Portenta_H7_AsyncWebHandlerImpl.h
index b3ca023..d8dc1fd 100644
--- a/src/Portenta_H7_AsyncWebHandlerImpl.h
+++ b/src/Portenta_H7_AsyncWebHandlerImpl.h
@@ -9,7 +9,7 @@
Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_AsyncWebServer
Licensed under GPLv3 license
- Version: 1.2.1
+ Version: 1.3.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -18,6 +18,7 @@
1.1.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json`
1.2.0 K Hoang 07/12/2021 Fix crashing issue
1.2.1 K Hoang 12/01/2022 Fix authenticate issue caused by libb64
+ 1.3.0 K Hoang 26/09/2022 Fix issue with slow browsers or network
*****************************************************************************************************************************/
#pragma once
@@ -34,6 +35,8 @@
#include "stddef.h"
#include
+/////////////////////////////////////////////////
+
class AsyncStaticWebHandler: public AsyncWebHandler
{
private:
@@ -61,13 +64,18 @@ class AsyncStaticWebHandler: public AsyncWebHandler
AsyncStaticWebHandler& setLastModified(time_t last_modified);
AsyncStaticWebHandler& setLastModified(); //sets to current time. Make sure sntp is runing and time is updated
+ /////////////////////////////////////////////////
+
AsyncStaticWebHandler& setTemplateProcessor(AwsTemplateProcessor newCallback)
{
_callback = newCallback;
+
return *this;
}
};
+/////////////////////////////////////////////////
+
class AsyncCallbackWebHandler: public AsyncWebHandler
{
private:
@@ -82,31 +90,44 @@ class AsyncCallbackWebHandler: public AsyncWebHandler
public:
AsyncCallbackWebHandler() : _uri(), _method(HTTP_ANY), _onRequest(NULL), _onUpload(NULL), _onBody(NULL), _isRegex(false) {}
+ /////////////////////////////////////////////////
+
void setUri(const String& uri)
{
_uri = uri;
_isRegex = uri.startsWith("^") && uri.endsWith("$");
}
+ /////////////////////////////////////////////////
+
void setMethod(WebRequestMethodComposite method)
{
_method = method;
}
+
+ /////////////////////////////////////////////////
+
void onRequest(ArRequestHandlerFunction fn)
{
_onRequest = fn;
}
+ /////////////////////////////////////////////////
+
void onUpload(ArUploadHandlerFunction fn)
{
_onUpload = fn;
}
+ /////////////////////////////////////////////////
+
void onBody(ArBodyHandlerFunction fn)
{
_onBody = fn;
}
+ /////////////////////////////////////////////////
+
virtual bool canHandle(AsyncWebServerRequest *request) override final
{
if (!_onRequest)
@@ -153,6 +174,8 @@ class AsyncCallbackWebHandler: public AsyncWebHandler
return true;
}
+ /////////////////////////////////////////////////
+
virtual void handleRequest(AsyncWebServerRequest *request) override final
{
if (_onRequest)
@@ -161,16 +184,22 @@ class AsyncCallbackWebHandler: public AsyncWebHandler
request->send(500);
}
+ /////////////////////////////////////////////////
+
virtual void handleBody(AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) override final
{
if (_onBody)
_onBody(request, data, len, index, total);
}
+ /////////////////////////////////////////////////
+
virtual bool isRequestHandlerTrivial() override final
{
return _onRequest ? false : true;
}
};
+/////////////////////////////////////////////////
+
#endif /* PORTENTA_H7_ASYNCWEBSERVERHANDLERIMPL_H_ */
diff --git a/src/Portenta_H7_AsyncWebHandlers.cpp b/src/Portenta_H7_AsyncWebHandlers.cpp
index 87a0387..90fe060 100644
--- a/src/Portenta_H7_AsyncWebHandlers.cpp
+++ b/src/Portenta_H7_AsyncWebHandlers.cpp
@@ -9,7 +9,7 @@
Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_AsyncWebServer
Licensed under GPLv3 license
- Version: 1.2.1
+ Version: 1.3.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -18,6 +18,7 @@
1.1.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json`
1.2.0 K Hoang 07/12/2021 Fix crashing issue
1.2.1 K Hoang 12/01/2022 Fix authenticate issue caused by libb64
+ 1.3.0 K Hoang 26/09/2022 Fix issue with slow browsers or network
*****************************************************************************************************************************/
#if !defined(_PORTENTA_H7_AWS_LOGLEVEL_)
@@ -29,6 +30,8 @@
#include "Portenta_H7_AsyncWebServer.h"
#include "Portenta_H7_AsyncWebHandlerImpl.h"
+/////////////////////////////////////////////////
+
AsyncStaticWebHandler::AsyncStaticWebHandler(const char* uri, /*FS& fs,*/ const char* path, const char* cache_control)
: _uri(uri), _path(path), _cache_control(cache_control), _last_modified(""), _callback(nullptr)
{
@@ -56,12 +59,17 @@ AsyncStaticWebHandler::AsyncStaticWebHandler(const char* uri, /*FS& fs,*/ const
_gzipStats = 0xF8;
}
+/////////////////////////////////////////////////
+
AsyncStaticWebHandler& AsyncStaticWebHandler::setIsDir(bool isDir)
{
_isDir = isDir;
+
return *this;
}
+/////////////////////////////////////////////////
+
AsyncStaticWebHandler& AsyncStaticWebHandler::setCacheControl(const char* cache_control)
{
_cache_control = String(cache_control);
@@ -69,6 +77,8 @@ AsyncStaticWebHandler& AsyncStaticWebHandler::setCacheControl(const char* cache_
return *this;
}
+/////////////////////////////////////////////////
+
AsyncStaticWebHandler& AsyncStaticWebHandler::setLastModified(const char* last_modified)
{
_last_modified = String(last_modified);
@@ -76,6 +86,8 @@ AsyncStaticWebHandler& AsyncStaticWebHandler::setLastModified(const char* last_m
return *this;
}
+/////////////////////////////////////////////////
+
AsyncStaticWebHandler& AsyncStaticWebHandler::setLastModified(struct tm* last_modified)
{
char result[30];
@@ -85,12 +97,15 @@ AsyncStaticWebHandler& AsyncStaticWebHandler::setLastModified(struct tm* last_mo
return setLastModified((const char *)result);
}
-// For STM32
+/////////////////////////////////////////////////
+
AsyncStaticWebHandler& AsyncStaticWebHandler::setLastModified(time_t last_modified)
{
return setLastModified((struct tm *)gmtime(&last_modified));
}
+/////////////////////////////////////////////////
+
AsyncStaticWebHandler& AsyncStaticWebHandler::setLastModified()
{
time_t last_modified;
@@ -101,6 +116,8 @@ AsyncStaticWebHandler& AsyncStaticWebHandler::setLastModified()
return setLastModified(last_modified);
}
+/////////////////////////////////////////////////
+
bool AsyncStaticWebHandler::canHandle(AsyncWebServerRequest *request)
{
if (request->method() != HTTP_GET
@@ -114,9 +131,12 @@ bool AsyncStaticWebHandler::canHandle(AsyncWebServerRequest *request)
return false;
}
-// For STM32
+/////////////////////////////////////////////////
+
#define FILE_IS_REAL(f) (f == true)
+/////////////////////////////////////////////////
+
uint8_t AsyncStaticWebHandler::_countBits(const uint8_t value) const
{
uint8_t w = value;
@@ -127,3 +147,6 @@ uint8_t AsyncStaticWebHandler::_countBits(const uint8_t value) const
return n;
}
+
+/////////////////////////////////////////////////
+
diff --git a/src/Portenta_H7_AsyncWebRequest.cpp b/src/Portenta_H7_AsyncWebRequest.cpp
index 6f5b7a7..0149d35 100644
--- a/src/Portenta_H7_AsyncWebRequest.cpp
+++ b/src/Portenta_H7_AsyncWebRequest.cpp
@@ -9,7 +9,7 @@
Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_AsyncWebServer
Licensed under GPLv3 license
- Version: 1.2.1
+ Version: 1.3.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -18,6 +18,7 @@
1.1.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json`
1.2.0 K Hoang 07/12/2021 Fix crashing issue
1.2.1 K Hoang 12/01/2022 Fix authenticate issue caused by libb64
+ 1.3.0 K Hoang 26/09/2022 Fix issue with slow browsers or network
*****************************************************************************************************************************/
#if !defined(_PORTENTA_H7_AWS_LOGLEVEL_)
@@ -32,10 +33,14 @@
//static const String SharedEmptyString = String();
+/////////////////////////////////////////////////
+
#define __is_param_char(c) ((c) && ((c) != '{') && ((c) != '[') && ((c) != '&') && ((c) != '='))
enum { PARSE_REQ_START, PARSE_REQ_HEADERS, PARSE_REQ_BODY, PARSE_REQ_END, PARSE_REQ_FAIL };
+/////////////////////////////////////////////////
+
AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer* s, AsyncClient* c)
: _client(c), _server(s), _handler(NULL), _response(NULL), _temp(), _parseState(0)
, _version(0), _method(HTTP_ANY), _url(), _host(), _contentType(), _boundary()
@@ -59,6 +64,7 @@ AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer* s, AsyncClient* c)
c->onError([](void *r, AsyncClient * c, int8_t error)
{
PORTENTA_H7_AWS_UNUSED(c);
+
AsyncWebServerRequest *req = (AsyncWebServerRequest*)r;
req->_onError(error);
}, this);
@@ -66,6 +72,7 @@ AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer* s, AsyncClient* c)
c->onAck([](void *r, AsyncClient * c, size_t len, uint32_t time)
{
PORTENTA_H7_AWS_UNUSED(c);
+
AsyncWebServerRequest *req = (AsyncWebServerRequest*)r;
req->_onAck(len, time);
}, this);
@@ -80,6 +87,7 @@ AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer* s, AsyncClient* c)
c->onTimeout([](void *r, AsyncClient * c, uint32_t time)
{
PORTENTA_H7_AWS_UNUSED(c);
+
AsyncWebServerRequest *req = (AsyncWebServerRequest*)r;
req->_onTimeout(time);
}, this);
@@ -87,6 +95,7 @@ AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer* s, AsyncClient* c)
c->onData([](void *r, AsyncClient * c, void *buf, size_t len)
{
PORTENTA_H7_AWS_UNUSED(c);
+
AsyncWebServerRequest *req = (AsyncWebServerRequest*)r;
req->_onData(buf, len);
}, this);
@@ -94,11 +103,14 @@ AsyncWebServerRequest::AsyncWebServerRequest(AsyncWebServer* s, AsyncClient* c)
c->onPoll([](void *r, AsyncClient * c)
{
PORTENTA_H7_AWS_UNUSED(c);
+
AsyncWebServerRequest *req = ( AsyncWebServerRequest*)r;
req->_onPoll();
}, this);
}
+/////////////////////////////////////////////////
+
AsyncWebServerRequest::~AsyncWebServerRequest()
{
_headers.free();
@@ -119,6 +131,8 @@ AsyncWebServerRequest::~AsyncWebServerRequest()
}
}
+/////////////////////////////////////////////////
+
void AsyncWebServerRequest::_onData(void *buf, size_t len)
{
size_t i = 0;
@@ -143,6 +157,7 @@ void AsyncWebServerRequest::_onData(void *buf, size_t len)
// No new line, just add the buffer in _temp
char ch = str[len - 1];
str[len - 1] = 0;
+
_temp.reserve(_temp.length() + len);
_temp.concat(str);
_temp.concat(ch);
@@ -151,6 +166,7 @@ void AsyncWebServerRequest::_onData(void *buf, size_t len)
{
// Found new line - extract it and parse
str[i] = 0; // Terminate the string at the end of the line.
+
_temp.concat(str);
_temp.trim();
_parseLine();
@@ -246,9 +262,12 @@ void AsyncWebServerRequest::_onData(void *buf, size_t len)
}
// KH, Important for Portenta Murata WiFi, or system will hang
- delay(0);
+ //delay(0);
+ yield();
}
+/////////////////////////////////////////////////
+
void AsyncWebServerRequest::_removeNotInterestingHeaders()
{
if (_interestingHeaders.containsIgnoreCase("ANY"))
@@ -263,6 +282,8 @@ void AsyncWebServerRequest::_removeNotInterestingHeaders()
}
}
+/////////////////////////////////////////////////
+
void AsyncWebServerRequest::_onPoll()
{
if (_response != NULL && _client != NULL && _client->canSend() && !_response->_finished())
@@ -271,9 +292,12 @@ void AsyncWebServerRequest::_onPoll()
}
// KH, Important for Portenta Murata WiFi, or system will hang
- delay(0);
+ //delay(0);
+ yield();
}
+/////////////////////////////////////////////////
+
void AsyncWebServerRequest::_onAck(size_t len, uint32_t time)
{
AWS_LOGDEBUG3("onAck: len =", len, ", time =", time);
@@ -293,31 +317,41 @@ void AsyncWebServerRequest::_onAck(size_t len, uint32_t time)
}
// KH, Important for Portenta Murata WiFi, or system will hang
- delay(0);
+ //delay(0);
+ yield();
}
+/////////////////////////////////////////////////
+
void AsyncWebServerRequest::_onError(int8_t error)
{
PORTENTA_H7_AWS_UNUSED(error);
}
+/////////////////////////////////////////////////
+
void AsyncWebServerRequest::_onTimeout(uint32_t time)
{
PORTENTA_H7_AWS_UNUSED(time);
- AWS_LOGDEBUG3("TIMEOUT: time =", time, ", state =", _client->stateToString());
+ AWS_LOGINFO3("TIMEOUT: time =", time, ", state =", _client->stateToString());
_client->close();
// KH, Important for Portenta Murata WiFi, or system will hang
- delay(0);
+ //delay(0);
+ yield();
}
+/////////////////////////////////////////////////
+
void AsyncWebServerRequest::onDisconnect (ArDisconnectHandler fn)
{
_onDisconnectfn = fn;
}
+/////////////////////////////////////////////////
+
void AsyncWebServerRequest::_onDisconnect()
{
if (_onDisconnectfn)
@@ -328,19 +362,26 @@ void AsyncWebServerRequest::_onDisconnect()
_server->_handleDisconnect(this);
// KH, Important for Portenta Murata WiFi, or system will hang
- delay(0);
+ //delay(0);
+ yield();
}
+/////////////////////////////////////////////////
+
void AsyncWebServerRequest::_addParam(AsyncWebParameter *p)
{
_params.add(p);
}
+/////////////////////////////////////////////////
+
void AsyncWebServerRequest::_addPathParam(const char *p)
{
_pathParams.add(new String(p));
}
+/////////////////////////////////////////////////
+
void AsyncWebServerRequest::_addGetParams(const String& params)
{
size_t start = 0;
@@ -364,6 +405,8 @@ void AsyncWebServerRequest::_addGetParams(const String& params)
}
}
+/////////////////////////////////////////////////
+
bool AsyncWebServerRequest::_parseReqHead()
{
// Split the head into method, url and version
@@ -422,6 +465,8 @@ bool AsyncWebServerRequest::_parseReqHead()
return true;
}
+/////////////////////////////////////////////////
+
bool strContains(String src, String find, bool mindcase = true)
{
int pos = 0, i = 0;
@@ -453,6 +498,8 @@ bool strContains(String src, String find, bool mindcase = true)
return false;
}
+/////////////////////////////////////////////////
+
bool AsyncWebServerRequest::_parseReqHeader()
{
int index = _temp.indexOf(':');
@@ -522,6 +569,8 @@ bool AsyncWebServerRequest::_parseReqHeader()
return true;
}
+/////////////////////////////////////////////////
+
void AsyncWebServerRequest::_parsePlainPostChar(uint8_t data)
{
if (data && (char)data != '&')
@@ -543,6 +592,8 @@ void AsyncWebServerRequest::_parsePlainPostChar(uint8_t data)
}
}
+/////////////////////////////////////////////////
+
void AsyncWebServerRequest::_handleUploadByte(uint8_t data, bool last)
{
_itemBuffer[_itemBufferIndex++] = data;
@@ -557,6 +608,8 @@ void AsyncWebServerRequest::_handleUploadByte(uint8_t data, bool last)
}
}
+/////////////////////////////////////////////////
+
enum
{
EXPECT_BOUNDARY,
@@ -572,6 +625,7 @@ enum
PARSE_ERROR
};
+/////////////////////////////////////////////////
void AsyncWebServerRequest::_parseMultipartPostByte(uint8_t data, bool last)
{
@@ -602,16 +656,19 @@ void AsyncWebServerRequest::_parseMultipartPostByte(uint8_t data, bool last)
if (_parsedLength < 2 && data != '-')
{
_multiParseState = PARSE_ERROR;
+
return;
}
else if (_parsedLength - 2 < _boundary.length() && _boundary.c_str()[_parsedLength - 2] != data)
{
_multiParseState = PARSE_ERROR;
+
return;
}
else if (_parsedLength - 2 == _boundary.length() && data != '\r')
{
_multiParseState = PARSE_ERROR;
+
return;
}
else if (_parsedLength - 3 == _boundary.length())
@@ -619,6 +676,7 @@ void AsyncWebServerRequest::_parseMultipartPostByte(uint8_t data, bool last)
if (data != '\n')
{
_multiParseState = PARSE_ERROR;
+
return;
}
@@ -696,6 +754,7 @@ void AsyncWebServerRequest::_parseMultipartPostByte(uint8_t data, bool last)
if (_itemBuffer == NULL)
{
_multiParseState = PARSE_ERROR;
+
return;
}
@@ -803,6 +862,7 @@ void AsyncWebServerRequest::_parseMultipartPostByte(uint8_t data, bool last)
{
AWS_LOGDEBUG1("ERROR: The parser got to the end of the POST but is expecting more bytes =", (_contentLength - _parsedLength - 4));
AWS_LOGDEBUG("Drop an issue so we can have more info on the matter!");
+
_contentLength = _parsedLength + 4;//lets close the request gracefully
}
@@ -857,6 +917,8 @@ void AsyncWebServerRequest::_parseMultipartPostByte(uint8_t data, bool last)
}
}
+/////////////////////////////////////////////////
+
void AsyncWebServerRequest::_parseLine()
{
if (_parseState == PARSE_REQ_START)
@@ -911,12 +973,15 @@ void AsyncWebServerRequest::_parseLine()
}
}
+/////////////////////////////////////////////////
size_t AsyncWebServerRequest::headers() const
{
return _headers.length();
}
+/////////////////////////////////////////////////
+
bool AsyncWebServerRequest::hasHeader(const String& name) const
{
for (const auto& h : _headers)
@@ -930,6 +995,8 @@ bool AsyncWebServerRequest::hasHeader(const String& name) const
return false;
}
+/////////////////////////////////////////////////
+
AsyncWebHeader* AsyncWebServerRequest::getHeader(const String& name) const
{
for (const auto& h : _headers)
@@ -943,6 +1010,8 @@ AsyncWebHeader* AsyncWebServerRequest::getHeader(const String& name) const
return nullptr;
}
+/////////////////////////////////////////////////
+
AsyncWebHeader* AsyncWebServerRequest::getHeader(size_t num) const
{
auto header = _headers.nth(num);
@@ -950,11 +1019,14 @@ AsyncWebHeader* AsyncWebServerRequest::getHeader(size_t num) const
return (header ? *header : nullptr);
}
+/////////////////////////////////////////////////
+
size_t AsyncWebServerRequest::params() const
{
return _params.length();
}
+/////////////////////////////////////////////////
bool AsyncWebServerRequest::hasParam(const String& name, bool post, bool file) const
{
@@ -969,6 +1041,8 @@ bool AsyncWebServerRequest::hasParam(const String& name, bool post, bool file) c
return false;
}
+/////////////////////////////////////////////////
+
AsyncWebParameter* AsyncWebServerRequest::getParam(const String& name, bool post, bool file) const
{
for (const auto& p : _params)
@@ -982,6 +1056,8 @@ AsyncWebParameter* AsyncWebServerRequest::getParam(const String& name, bool post
return nullptr;
}
+/////////////////////////////////////////////////
+
AsyncWebParameter* AsyncWebServerRequest::getParam(size_t num) const
{
auto param = _params.nth(num);
@@ -989,12 +1065,16 @@ AsyncWebParameter* AsyncWebServerRequest::getParam(size_t num) const
return (param ? *param : nullptr);
}
+/////////////////////////////////////////////////
+
void AsyncWebServerRequest::addInterestingHeader(const String& name)
{
if (!_interestingHeaders.containsIgnoreCase(name))
_interestingHeaders.add(name);
}
+/////////////////////////////////////////////////
+
void AsyncWebServerRequest::send(AsyncWebServerResponse *response)
{
_response = response;
@@ -1021,21 +1101,29 @@ void AsyncWebServerRequest::send(AsyncWebServerResponse *response)
}
}
+/////////////////////////////////////////////////
+
AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(int code, const String& contentType, const String& content)
{
return new AsyncBasicResponse(code, contentType, content);
}
+/////////////////////////////////////////////////
+
AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(Stream &stream, const String& contentType, size_t len, AwsTemplateProcessor callback)
{
return new AsyncStreamResponse(stream, contentType, len, callback);
}
+/////////////////////////////////////////////////
+
AsyncWebServerResponse * AsyncWebServerRequest::beginResponse(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback)
{
return new AsyncCallbackResponse(contentType, len, callback, templateCallback);
}
+/////////////////////////////////////////////////
+
AsyncWebServerResponse * AsyncWebServerRequest::beginChunkedResponse(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback)
{
if (_version)
@@ -1044,31 +1132,43 @@ AsyncWebServerResponse * AsyncWebServerRequest::beginChunkedResponse(const Strin
return new AsyncCallbackResponse(contentType, 0, callback, templateCallback);
}
+/////////////////////////////////////////////////
+
AsyncResponseStream * AsyncWebServerRequest::beginResponseStream(const String& contentType, size_t bufferSize)
{
return new AsyncResponseStream(contentType, bufferSize);
}
+/////////////////////////////////////////////////
+
void AsyncWebServerRequest::send(int code, const String& contentType, const String& content)
{
send(beginResponse(code, contentType, content));
}
+/////////////////////////////////////////////////
+
void AsyncWebServerRequest::send(Stream &stream, const String& contentType, size_t len, AwsTemplateProcessor callback)
{
send(beginResponse(stream, contentType, len, callback));
}
+/////////////////////////////////////////////////
+
void AsyncWebServerRequest::send(const String& contentType, size_t len, AwsResponseFiller callback, AwsTemplateProcessor templateCallback)
{
send(beginResponse(contentType, len, callback, templateCallback));
}
+/////////////////////////////////////////////////
+
void AsyncWebServerRequest::sendChunked(const String& contentType, AwsResponseFiller callback, AwsTemplateProcessor templateCallback)
{
send(beginChunkedResponse(contentType, callback, templateCallback));
}
+/////////////////////////////////////////////////
+
void AsyncWebServerRequest::redirect(const String& url)
{
AsyncWebServerResponse * response = beginResponse(302);
@@ -1076,6 +1176,8 @@ void AsyncWebServerRequest::redirect(const String& url)
send(response);
}
+/////////////////////////////////////////////////
+
bool AsyncWebServerRequest::authenticate(const char * username, const char * password, const char * realm, bool passwordIsHash)
{
AWS_LOGDEBUG1("AsyncWebServerRequest::authenticate: auth-len =", _authorization.length());
@@ -1107,6 +1209,8 @@ bool AsyncWebServerRequest::authenticate(const char * username, const char * pas
return false;
}
+/////////////////////////////////////////////////
+
bool AsyncWebServerRequest::authenticate(const char * hash)
{
if (!_authorization.length() || hash == NULL)
@@ -1136,6 +1240,8 @@ bool AsyncWebServerRequest::authenticate(const char * hash)
return (_authorization.equals(hash));
}
+/////////////////////////////////////////////////
+
void AsyncWebServerRequest::requestAuthentication(const char * realm, bool isDigest)
{
AsyncWebServerResponse * r = beginResponse(401);
@@ -1161,6 +1267,8 @@ void AsyncWebServerRequest::requestAuthentication(const char * realm, bool isDig
send(r);
}
+/////////////////////////////////////////////////
+
bool AsyncWebServerRequest::hasArg(const char* name) const
{
for (const auto& arg : _params)
@@ -1174,6 +1282,8 @@ bool AsyncWebServerRequest::hasArg(const char* name) const
return false;
}
+/////////////////////////////////////////////////
+
const String& AsyncWebServerRequest::arg(const String& name) const
{
for (const auto& arg : _params)
@@ -1187,16 +1297,22 @@ const String& AsyncWebServerRequest::arg(const String& name) const
return SharedEmptyString;
}
+/////////////////////////////////////////////////
+
const String& AsyncWebServerRequest::arg(size_t i) const
{
return getParam(i)->value();
}
+/////////////////////////////////////////////////
+
const String& AsyncWebServerRequest::argName(size_t i) const
{
return getParam(i)->name();
}
+/////////////////////////////////////////////////
+
const String& AsyncWebServerRequest::pathArg(size_t i) const
{
auto param = _pathParams.nth(i);
@@ -1204,6 +1320,8 @@ const String& AsyncWebServerRequest::pathArg(size_t i) const
return (param ? **param : SharedEmptyString);
}
+/////////////////////////////////////////////////
+
const String& AsyncWebServerRequest::header(const char* name) const
{
AsyncWebHeader* h = getHeader(String(name));
@@ -1211,6 +1329,8 @@ const String& AsyncWebServerRequest::header(const char* name) const
return (h ? h->value() : SharedEmptyString);
}
+/////////////////////////////////////////////////
+
const String& AsyncWebServerRequest::header(size_t i) const
{
AsyncWebHeader* h = getHeader(i);
@@ -1218,6 +1338,8 @@ const String& AsyncWebServerRequest::header(size_t i) const
return (h ? h->value() : SharedEmptyString);
}
+/////////////////////////////////////////////////
+
const String& AsyncWebServerRequest::headerName(size_t i) const
{
AsyncWebHeader* h = getHeader(i);
@@ -1225,6 +1347,8 @@ const String& AsyncWebServerRequest::headerName(size_t i) const
return (h ? h->name() : SharedEmptyString);
}
+/////////////////////////////////////////////////
+
String AsyncWebServerRequest::urlDecode(const String& text) const
{
char temp[] = "0x00";
@@ -1259,6 +1383,7 @@ String AsyncWebServerRequest::urlDecode(const String& text) const
return decoded;
}
+/////////////////////////////////////////////////
const char * AsyncWebServerRequest::methodToString() const
{
@@ -1282,6 +1407,8 @@ const char * AsyncWebServerRequest::methodToString() const
return "UNKNOWN";
}
+/////////////////////////////////////////////////
+
const char *AsyncWebServerRequest::requestedConnTypeToString() const
{
switch (_reqconntype)
@@ -1301,6 +1428,8 @@ const char *AsyncWebServerRequest::requestedConnTypeToString() const
}
}
+/////////////////////////////////////////////////
+
bool AsyncWebServerRequest::isExpectedRequestedConnType(RequestedConnectionType erct1, RequestedConnectionType erct2, RequestedConnectionType erct3)
{
bool res = false;
@@ -1316,3 +1445,6 @@ bool AsyncWebServerRequest::isExpectedRequestedConnType(RequestedConnectionType
return res;
}
+
+/////////////////////////////////////////////////
+
diff --git a/src/Portenta_H7_AsyncWebResponseImpl.h b/src/Portenta_H7_AsyncWebResponseImpl.h
index 32dd2b9..6e8e0e1 100644
--- a/src/Portenta_H7_AsyncWebResponseImpl.h
+++ b/src/Portenta_H7_AsyncWebResponseImpl.h
@@ -9,7 +9,7 @@
Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_AsyncWebServer
Licensed under GPLv3 license
- Version: 1.2.1
+ Version: 1.3.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -18,6 +18,7 @@
1.1.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json`
1.2.0 K Hoang 07/12/2021 Fix crashing issue
1.2.1 K Hoang 12/01/2022 Fix authenticate issue caused by libb64
+ 1.3.0 K Hoang 26/09/2022 Fix issue with slow browsers or network
*****************************************************************************************************************************/
#pragma once
@@ -25,6 +26,8 @@
#ifndef PORTENTA_H7_ASYNCWEBSERVERRESPONSEIMPL_H_
#define PORTENTA_H7_ASYNCWEBSERVERRESPONSEIMPL_H_
+/////////////////////////////////////////////////
+
#ifdef Arduino_h
// arduino is not compatible with std::vector
#undef min
@@ -34,6 +37,8 @@
#include
// It is possible to restore these defines, but one can use _min and _max instead. Or std::min, std::max.
+/////////////////////////////////////////////////
+
class AsyncBasicResponse: public AsyncWebServerResponse
{
private:
@@ -51,6 +56,8 @@ class AsyncBasicResponse: public AsyncWebServerResponse
}
};
+/////////////////////////////////////////////////
+
class AsyncAbstractResponse: public AsyncWebServerResponse
{
private:
@@ -82,12 +89,16 @@ class AsyncAbstractResponse: public AsyncWebServerResponse
}
};
+/////////////////////////////////////////////////
+
#ifndef TEMPLATE_PLACEHOLDER
#define TEMPLATE_PLACEHOLDER '%'
#endif
#define TEMPLATE_PARAM_NAME_LENGTH 32
+/////////////////////////////////////////////////
+
class AsyncStreamResponse: public AsyncAbstractResponse
{
private:
@@ -104,6 +115,8 @@ class AsyncStreamResponse: public AsyncAbstractResponse
virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override;
};
+/////////////////////////////////////////////////
+
class AsyncCallbackResponse: public AsyncAbstractResponse
{
private:
@@ -121,6 +134,8 @@ class AsyncCallbackResponse: public AsyncAbstractResponse
virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override;
};
+/////////////////////////////////////////////////
+
class AsyncChunkedResponse: public AsyncAbstractResponse
{
private:
@@ -138,8 +153,12 @@ class AsyncChunkedResponse: public AsyncAbstractResponse
virtual size_t _fillBuffer(uint8_t *buf, size_t maxLen) override;
};
+/////////////////////////////////////////////////
+
class cbuf;
+/////////////////////////////////////////////////
+
class AsyncResponseStream: public AsyncAbstractResponse, public Print
{
private:
@@ -160,4 +179,6 @@ class AsyncResponseStream: public AsyncAbstractResponse, public Print
using Print::write;
};
+/////////////////////////////////////////////////
+
#endif /* PORTENTA_H7_ASYNCWEBSERVERRESPONSEIMPL_H_ */
diff --git a/src/Portenta_H7_AsyncWebResponses.cpp b/src/Portenta_H7_AsyncWebResponses.cpp
index f57d2f6..1a88d29 100644
--- a/src/Portenta_H7_AsyncWebResponses.cpp
+++ b/src/Portenta_H7_AsyncWebResponses.cpp
@@ -9,7 +9,7 @@
Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_AsyncWebServer
Licensed under GPLv3 license
- Version: 1.2.1
+ Version: 1.3.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -18,6 +18,7 @@
1.1.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json`
1.2.0 K Hoang 07/12/2021 Fix crashing issue
1.2.1 K Hoang 12/01/2022 Fix authenticate issue caused by libb64
+ 1.3.0 K Hoang 26/09/2022 Fix issue with slow browsers or network
*****************************************************************************************************************************/
#if !defined(_PORTENTA_H7_AWS_LOGLEVEL_)
@@ -30,7 +31,8 @@
#include "Portenta_H7_AsyncWebResponseImpl.h"
#include "cbuf.h"
-// Since ESP8266 does not link memchr by default, here's its implementation.
+/////////////////////////////////////////////////
+
void* memchr(void* ptr, int ch, size_t count)
{
unsigned char* p = static_cast(ptr);
@@ -44,6 +46,8 @@ void* memchr(void* ptr, int ch, size_t count)
return nullptr;
}
+/////////////////////////////////////////////////
+
/*
Abstract Response
* */
@@ -95,6 +99,8 @@ const char* AsyncWebServerResponse::_responseCodeToString(int code)
}
}
+/////////////////////////////////////////////////
+
AsyncWebServerResponse::AsyncWebServerResponse()
: _code(0)
, _headers(LinkedList([](AsyncWebHeader * h)
@@ -110,34 +116,46 @@ AsyncWebServerResponse::AsyncWebServerResponse()
}
}
+/////////////////////////////////////////////////
+
AsyncWebServerResponse::~AsyncWebServerResponse()
{
_headers.free();
}
+/////////////////////////////////////////////////
+
void AsyncWebServerResponse::setCode(int code)
{
if (_state == RESPONSE_SETUP)
_code = code;
}
+/////////////////////////////////////////////////
+
void AsyncWebServerResponse::setContentLength(size_t len)
{
if (_state == RESPONSE_SETUP)
_contentLength = len;
}
+/////////////////////////////////////////////////
+
void AsyncWebServerResponse::setContentType(const String& type)
{
if (_state == RESPONSE_SETUP)
_contentType = type;
}
+/////////////////////////////////////////////////
+
void AsyncWebServerResponse::addHeader(const String& name, const String& value)
{
_headers.add(new AsyncWebHeader(name, value));
}
+/////////////////////////////////////////////////
+
String AsyncWebServerResponse::_assembleHead(uint8_t version)
{
if (version)
@@ -181,26 +199,36 @@ String AsyncWebServerResponse::_assembleHead(uint8_t version)
return out;
}
+/////////////////////////////////////////////////
+
bool AsyncWebServerResponse::_started() const
{
return _state > RESPONSE_SETUP;
}
+/////////////////////////////////////////////////
+
bool AsyncWebServerResponse::_finished() const
{
return _state > RESPONSE_WAIT_ACK;
}
+/////////////////////////////////////////////////
+
bool AsyncWebServerResponse::_failed() const
{
return _state == RESPONSE_FAILED;
}
+/////////////////////////////////////////////////
+
bool AsyncWebServerResponse::_sourceValid() const
{
return false;
}
+/////////////////////////////////////////////////
+
void AsyncWebServerResponse::_respond(AsyncWebServerRequest *request)
{
_state = RESPONSE_END;
@@ -208,14 +236,19 @@ void AsyncWebServerResponse::_respond(AsyncWebServerRequest *request)
request->client()->close();
}
+/////////////////////////////////////////////////
+
size_t AsyncWebServerResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time)
{
PORTENTA_H7_AWS_UNUSED(request);
PORTENTA_H7_AWS_UNUSED(len);
PORTENTA_H7_AWS_UNUSED(time);
+
return 0;
}
+/////////////////////////////////////////////////
+
/*
String/Code Response
* */
@@ -236,6 +269,8 @@ AsyncBasicResponse::AsyncBasicResponse(int code, const String& contentType, cons
addHeader("Connection", "close");
}
+/////////////////////////////////////////////////
+
void AsyncBasicResponse::_respond(AsyncWebServerRequest *request)
{
_state = RESPONSE_HEADERS;
@@ -281,9 +316,12 @@ void AsyncBasicResponse::_respond(AsyncWebServerRequest *request)
}
}
+/////////////////////////////////////////////////
+
size_t AsyncBasicResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time)
{
PORTENTA_H7_AWS_UNUSED(time);
+
_ackedLength += len;
if (_state == RESPONSE_CONTENT)
@@ -320,6 +358,7 @@ size_t AsyncBasicResponse::_ack(AsyncWebServerRequest *request, size_t len, uint
return 0;
}
+/////////////////////////////////////////////////
/*
Abstract Response
@@ -336,6 +375,8 @@ AsyncAbstractResponse::AsyncAbstractResponse(AwsTemplateProcessor callback): _ca
}
}
+/////////////////////////////////////////////////
+
void AsyncAbstractResponse::_respond(AsyncWebServerRequest *request)
{
addHeader("Connection", "close");
@@ -344,6 +385,8 @@ void AsyncAbstractResponse::_respond(AsyncWebServerRequest *request)
_ack(request, 0, 0);
}
+/////////////////////////////////////////////////
+
size_t AsyncAbstractResponse::_ack(AsyncWebServerRequest *request, size_t len, uint32_t time)
{
PORTENTA_H7_AWS_UNUSED(time);
@@ -494,6 +537,8 @@ size_t AsyncAbstractResponse::_ack(AsyncWebServerRequest *request, size_t len, u
return 0;
}
+/////////////////////////////////////////////////
+
size_t AsyncAbstractResponse::_readDataFromCacheOrContent(uint8_t* data, const size_t len)
{
// If we have something in cache, copy it to buffer
@@ -512,6 +557,8 @@ size_t AsyncAbstractResponse::_readDataFromCacheOrContent(uint8_t* data, const s
return readFromCache + readFromContent;
}
+/////////////////////////////////////////////////
+
size_t AsyncAbstractResponse::_fillBufferAndProcessTemplates(uint8_t* data, size_t len)
{
if (!_callback)
@@ -643,6 +690,8 @@ size_t AsyncAbstractResponse::_fillBufferAndProcessTemplates(uint8_t* data, size
return len;
}
+/////////////////////////////////////////////////
+
/*
Stream Response
* */
@@ -655,6 +704,8 @@ AsyncStreamResponse::AsyncStreamResponse(Stream &stream, const String& contentTy
_contentType = contentType;
}
+/////////////////////////////////////////////////
+
size_t AsyncStreamResponse::_fillBuffer(uint8_t *data, size_t len)
{
size_t available = _content->available();
@@ -667,6 +718,8 @@ size_t AsyncStreamResponse::_fillBuffer(uint8_t *data, size_t len)
return outLen;
}
+/////////////////////////////////////////////////
+
/*
Callback Response
* */
@@ -685,6 +738,8 @@ AsyncCallbackResponse::AsyncCallbackResponse(const String& contentType, size_t l
_filledLength = 0;
}
+/////////////////////////////////////////////////
+
size_t AsyncCallbackResponse::_fillBuffer(uint8_t *data, size_t len)
{
size_t ret = _content(data, len, _filledLength);
@@ -697,6 +752,8 @@ size_t AsyncCallbackResponse::_fillBuffer(uint8_t *data, size_t len)
return ret;
}
+/////////////////////////////////////////////////
+
/*
Chunked Response
* */
@@ -712,6 +769,8 @@ AsyncChunkedResponse::AsyncChunkedResponse(const String& contentType, AwsRespons
_filledLength = 0;
}
+/////////////////////////////////////////////////
+
size_t AsyncChunkedResponse::_fillBuffer(uint8_t *data, size_t len)
{
size_t ret = _content(data, len, _filledLength);
@@ -724,6 +783,8 @@ size_t AsyncChunkedResponse::_fillBuffer(uint8_t *data, size_t len)
return ret;
}
+/////////////////////////////////////////////////
+
/*
Response Stream (You can print/write/printf to it, up to the contentLen bytes)
* */
@@ -736,16 +797,22 @@ AsyncResponseStream::AsyncResponseStream(const String& contentType, size_t buffe
_content = new cbuf(bufferSize);
}
+/////////////////////////////////////////////////
+
AsyncResponseStream::~AsyncResponseStream()
{
delete _content;
}
+/////////////////////////////////////////////////
+
size_t AsyncResponseStream::_fillBuffer(uint8_t *buf, size_t maxLen)
{
return _content->read((char*)buf, maxLen);
}
+/////////////////////////////////////////////////
+
size_t AsyncResponseStream::write(const uint8_t *data, size_t len)
{
if (_started())
@@ -763,7 +830,12 @@ size_t AsyncResponseStream::write(const uint8_t *data, size_t len)
return written;
}
+/////////////////////////////////////////////////
+
size_t AsyncResponseStream::write(uint8_t data)
{
return write(&data, 1);
}
+
+/////////////////////////////////////////////////
+
diff --git a/src/Portenta_H7_AsyncWebServer.cpp b/src/Portenta_H7_AsyncWebServer.cpp
index 95d9225..d245068 100644
--- a/src/Portenta_H7_AsyncWebServer.cpp
+++ b/src/Portenta_H7_AsyncWebServer.cpp
@@ -9,7 +9,7 @@
Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_AsyncWebServer
Licensed under GPLv3 license
- Version: 1.2.1
+ Version: 1.3.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -18,6 +18,7 @@
1.1.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json`
1.2.0 K Hoang 07/12/2021 Fix crashing issue
1.2.1 K Hoang 12/01/2022 Fix authenticate issue caused by libb64
+ 1.3.0 K Hoang 26/09/2022 Fix issue with slow browsers or network
*****************************************************************************************************************************/
#if !defined(_PORTENTA_H7_AWS_LOGLEVEL_)
@@ -29,6 +30,8 @@
#include "Portenta_H7_AsyncWebServer.h"
#include "Portenta_H7_AsyncWebHandlerImpl.h"
+/////////////////////////////////////////////////
+
AsyncWebServer::AsyncWebServer(uint16_t port)
: _server(port), _rewrites(LinkedList([](AsyncWebRewrite * r)
{
@@ -49,7 +52,11 @@ AsyncWebServer::AsyncWebServer(uint16_t port)
if (c == NULL)
return;
- c->setRxTimeout(3);
+ // KH set no RxTimeout for slower Firefox / network
+ //c->setRxTimeout(3);
+ c->setRxTimeout(0);
+ //////
+
AsyncWebServerRequest *r = new AsyncWebServerRequest((AsyncWebServer*)s, c);
if (r == NULL)
@@ -61,6 +68,8 @@ AsyncWebServer::AsyncWebServer(uint16_t port)
}, this);
}
+/////////////////////////////////////////////////
+
AsyncWebServer::~AsyncWebServer()
{
reset();
@@ -70,6 +79,8 @@ AsyncWebServer::~AsyncWebServer()
delete _catchAllHandler;
}
+/////////////////////////////////////////////////
+
AsyncWebRewrite& AsyncWebServer::addRewrite(AsyncWebRewrite* rewrite)
{
_rewrites.add(rewrite);
@@ -77,55 +88,77 @@ AsyncWebRewrite& AsyncWebServer::addRewrite(AsyncWebRewrite* rewrite)
return *rewrite;
}
+/////////////////////////////////////////////////
+
bool AsyncWebServer::removeRewrite(AsyncWebRewrite *rewrite)
{
return _rewrites.remove(rewrite);
}
+/////////////////////////////////////////////////
+
AsyncWebRewrite& AsyncWebServer::rewrite(const char* from, const char* to)
{
return addRewrite(new AsyncWebRewrite(from, to));
}
+/////////////////////////////////////////////////
+
AsyncWebHandler& AsyncWebServer::addHandler(AsyncWebHandler* handler)
{
_handlers.add(handler);
return *handler;
}
+/////////////////////////////////////////////////
+
bool AsyncWebServer::removeHandler(AsyncWebHandler *handler)
{
return _handlers.remove(handler);
}
+/////////////////////////////////////////////////
+
void AsyncWebServer::begin()
{
_server.setNoDelay(true);
_server.begin();
}
+/////////////////////////////////////////////////
+
void AsyncWebServer::end()
{
_server.end();
}
+/////////////////////////////////////////////////
+
#if ASYNC_TCP_SSL_ENABLED
+
void AsyncWebServer::onSslFileRequest(AcSSlFileHandler cb, void* arg)
{
_server.onSslFileRequest(cb, arg);
}
+/////////////////////////////////////////////////
+
void AsyncWebServer::beginSecure(const char *cert, const char *key, const char *password)
{
_server.beginSecure(cert, key, password);
}
+
#endif
+/////////////////////////////////////////////////
+
void AsyncWebServer::_handleDisconnect(AsyncWebServerRequest *request)
{
delete request;
}
+/////////////////////////////////////////////////
+
void AsyncWebServer::_rewriteRequest(AsyncWebServerRequest *request)
{
for (const auto& r : _rewrites)
@@ -138,6 +171,8 @@ void AsyncWebServer::_rewriteRequest(AsyncWebServerRequest *request)
}
}
+/////////////////////////////////////////////////
+
void AsyncWebServer::_attachHandler(AsyncWebServerRequest *request)
{
for (const auto& h : _handlers)
@@ -145,17 +180,17 @@ void AsyncWebServer::_attachHandler(AsyncWebServerRequest *request)
if (h->filter(request) && h->canHandle(request))
{
request->setHandler(h);
+
return;
}
}
request->addInterestingHeader("ANY");
- // KH, fix crashing issue from v1.2.0, for Arduino-mbed core v2.6.1
- //request->setHandler(_catchAllHandler);
request->setHandler(NULL);
}
+/////////////////////////////////////////////////
AsyncCallbackWebHandler& AsyncWebServer::on(const char* uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest,
ArUploadHandlerFunction onUpload, ArBodyHandlerFunction onBody)
@@ -172,6 +207,8 @@ AsyncCallbackWebHandler& AsyncWebServer::on(const char* uri, WebRequestMethodCom
return *handler;
}
+/////////////////////////////////////////////////
+
AsyncCallbackWebHandler& AsyncWebServer::on(const char* uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest, ArUploadHandlerFunction onUpload)
{
AsyncCallbackWebHandler* handler = new AsyncCallbackWebHandler();
@@ -184,6 +221,8 @@ AsyncCallbackWebHandler& AsyncWebServer::on(const char* uri, WebRequestMethodCom
return *handler;
}
+/////////////////////////////////////////////////
+
AsyncCallbackWebHandler& AsyncWebServer::on(const char* uri, WebRequestMethodComposite method, ArRequestHandlerFunction onRequest)
{
AsyncCallbackWebHandler* handler = new AsyncCallbackWebHandler();
@@ -195,6 +234,8 @@ AsyncCallbackWebHandler& AsyncWebServer::on(const char* uri, WebRequestMethodCom
return *handler;
}
+/////////////////////////////////////////////////
+
AsyncCallbackWebHandler& AsyncWebServer::on(const char* uri, ArRequestHandlerFunction onRequest)
{
AsyncCallbackWebHandler* handler = new AsyncCallbackWebHandler();
@@ -205,16 +246,22 @@ AsyncCallbackWebHandler& AsyncWebServer::on(const char* uri, ArRequestHandlerFun
return *handler;
}
+/////////////////////////////////////////////////
+
void AsyncWebServer::onNotFound(ArRequestHandlerFunction fn)
{
_catchAllHandler->onRequest(fn);
}
+/////////////////////////////////////////////////
+
void AsyncWebServer::onRequestBody(ArBodyHandlerFunction fn)
{
_catchAllHandler->onBody(fn);
}
+/////////////////////////////////////////////////
+
void AsyncWebServer::reset()
{
_rewrites.free();
@@ -228,4 +275,6 @@ void AsyncWebServer::reset()
}
}
+/////////////////////////////////////////////////
+
diff --git a/src/Portenta_H7_AsyncWebServer.h b/src/Portenta_H7_AsyncWebServer.h
index d1fd22a..c4fc2c4 100644
--- a/src/Portenta_H7_AsyncWebServer.h
+++ b/src/Portenta_H7_AsyncWebServer.h
@@ -9,7 +9,7 @@
Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_AsyncWebServer
Licensed under GPLv3 license
- Version: 1.2.1
+ Version: 1.3.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -18,6 +18,7 @@
1.1.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json`
1.2.0 K Hoang 07/12/2021 Fix crashing issue
1.2.1 K Hoang 12/01/2022 Fix authenticate issue caused by libb64
+ 1.3.0 K Hoang 26/09/2022 Fix issue with slow browsers or network
*****************************************************************************************************************************/
#ifndef _PORTENTA_H7_ASYNC_WEBSERVER_H_
@@ -32,13 +33,13 @@
#endif
-#define PORTENTA_H7_ASYNC_WEBSERVER_VERSION "Portenta_H7_AsyncWebServer v1.2.1"
+#define PORTENTA_H7_ASYNC_WEBSERVER_VERSION "Portenta_H7_AsyncWebServer v1.3.0"
#define PORTENTA_H7_ASYNC_WEBSERVER_VERSION_MAJOR 1
-#define PORTENTA_H7_ASYNC_WEBSERVER_VERSION_MINOR 2
-#define PORTENTA_H7_ASYNC_WEBSERVER_VERSION_PATCH 1
+#define PORTENTA_H7_ASYNC_WEBSERVER_VERSION_MINOR 3
+#define PORTENTA_H7_ASYNC_WEBSERVER_VERSION_PATCH 0
-#define PORTENTA_H7_ASYNC_WEBSERVER_VERSION_INT 1002001
+#define PORTENTA_H7_ASYNC_WEBSERVER_VERSION_INT 1003000
#ifndef PORTENTA_H7_AWS_UNUSED
#define PORTENTA_H7_AWS_UNUSED(x) (void)(x)
diff --git a/src/Portenta_H7_AsyncWebServer_Debug.h b/src/Portenta_H7_AsyncWebServer_Debug.h
index da7031f..74a125c 100644
--- a/src/Portenta_H7_AsyncWebServer_Debug.h
+++ b/src/Portenta_H7_AsyncWebServer_Debug.h
@@ -9,7 +9,7 @@
Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_AsyncWebServer
Licensed under GPLv3 license
- Version: 1.2.1
+ Version: 1.3.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -18,6 +18,7 @@
1.1.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json`
1.2.0 K Hoang 07/12/2021 Fix crashing issue
1.2.1 K Hoang 12/01/2022 Fix authenticate issue caused by libb64
+ 1.3.0 K Hoang 26/09/2022 Fix issue with slow browsers or network
*****************************************************************************************************************************/
#pragma once
@@ -25,12 +26,16 @@
#ifndef PORTENTA_H7_ASYNC_WEBSERVER_DEBUG_H
#define PORTENTA_H7_ASYNC_WEBSERVER_DEBUG_H
+/////////////////////////////////////////////////
+
#ifdef PORTENTA_H7_ASYNCWEBSERVER_DEBUG_PORT
#define DBG_PORT_AWS PORTENTA_H7_ASYNCWEBSERVER_DEBUG_PORT
#else
#define DBG_PORT_AWS Serial
#endif
+/////////////////////////////////////////////////
+
// Change _PORTENTA_H7_AWS_LOGLEVEL_ to set tracing and logging verbosity
// 0: DISABLED: no logging
// 1: ERROR: errors
@@ -58,18 +63,24 @@
#define AWS_LOGERROR2(x,y,z) if(_PORTENTA_H7_AWS_LOGLEVEL_>0) { AWS_PRINT_MARK; AWS_PRINT(x); AWS_PRINT_SP; AWS_PRINT(y); AWS_PRINT_SP; AWS_PRINTLN(z); }
#define AWS_LOGERROR3(x,y,z,w) if(_PORTENTA_H7_AWS_LOGLEVEL_>0) { AWS_PRINT_MARK; AWS_PRINT(x); AWS_PRINT_SP; AWS_PRINT(y); AWS_PRINT_SP; AWS_PRINT(z); AWS_PRINT_SP; AWS_PRINTLN(w); }
+/////////////////////////////////////////////////
+
#define AWS_LOGWARN(x) if(_PORTENTA_H7_AWS_LOGLEVEL_>1) { AWS_PRINT_MARK; AWS_PRINTLN(x); }
#define AWS_LOGWARN0(x) if(_PORTENTA_H7_AWS_LOGLEVEL_>1) { AWS_PRINT(x); }
#define AWS_LOGWARN1(x,y) if(_PORTENTA_H7_AWS_LOGLEVEL_>1) { AWS_PRINT_MARK; AWS_PRINT(x); AWS_PRINT_SP; AWS_PRINTLN(y); }
#define AWS_LOGWARN2(x,y,z) if(_PORTENTA_H7_AWS_LOGLEVEL_>1) { AWS_PRINT_MARK; AWS_PRINT(x); AWS_PRINT_SP; AWS_PRINT(y); AWS_PRINT_SP; AWS_PRINTLN(z); }
#define AWS_LOGWARN3(x,y,z,w) if(_PORTENTA_H7_AWS_LOGLEVEL_>1) { AWS_PRINT_MARK; AWS_PRINT(x); AWS_PRINT_SP; AWS_PRINT(y); AWS_PRINT_SP; AWS_PRINT(z); AWS_PRINT_SP; AWS_PRINTLN(w); }
+/////////////////////////////////////////////////
+
#define AWS_LOGINFO(x) if(_PORTENTA_H7_AWS_LOGLEVEL_>2) { AWS_PRINT_MARK; AWS_PRINTLN(x); }
#define AWS_LOGINFO0(x) if(_PORTENTA_H7_AWS_LOGLEVEL_>2) { AWS_PRINT(x); }
#define AWS_LOGINFO1(x,y) if(_PORTENTA_H7_AWS_LOGLEVEL_>2) { AWS_PRINT_MARK; AWS_PRINT(x); AWS_PRINT_SP; AWS_PRINTLN(y); }
#define AWS_LOGINFO2(x,y,z) if(_PORTENTA_H7_AWS_LOGLEVEL_>2) { AWS_PRINT_MARK; AWS_PRINT(x); AWS_PRINT_SP; AWS_PRINT(y); AWS_PRINT_SP; AWS_PRINTLN(z); }
#define AWS_LOGINFO3(x,y,z,w) if(_PORTENTA_H7_AWS_LOGLEVEL_>2) { AWS_PRINT_MARK; AWS_PRINT(x); AWS_PRINT_SP; AWS_PRINT(y); AWS_PRINT_SP; AWS_PRINT(z); AWS_PRINT_SP; AWS_PRINTLN(w); }
+/////////////////////////////////////////////////
+
#define AWS_LOGDEBUG(x) if(_PORTENTA_H7_AWS_LOGLEVEL_>3) { AWS_PRINT_MARK; AWS_PRINTLN(x); }
#define AWS_LOGDEBUG0(x) if(_PORTENTA_H7_AWS_LOGLEVEL_>3) { AWS_PRINT(x); }
#define AWS_LOGDEBUG1(x,y) if(_PORTENTA_H7_AWS_LOGLEVEL_>3) { AWS_PRINT_MARK; AWS_PRINT(x); AWS_PRINT_SP; AWS_PRINTLN(y); }
@@ -77,4 +88,6 @@
#define AWS_LOGDEBUG3(x,y,z,w) if(_PORTENTA_H7_AWS_LOGLEVEL_>3) { AWS_PRINT_MARK; AWS_PRINT(x); AWS_PRINT_SP; AWS_PRINT(y); AWS_PRINT_SP; AWS_PRINT(z); AWS_PRINT_SP; AWS_PRINTLN(w); }
#define AWS_LOGDEBUG5(x,y,z,w,xx,yy) if(_PORTENTA_H7_AWS_LOGLEVEL_>3) { AWS_PRINT_MARK; AWS_PRINT(x); AWS_PRINT_SP; AWS_PRINT(y); AWS_PRINT_SP; AWS_PRINT(z); AWS_PRINT_SP; AWS_PRINT(w); AWS_PRINT_SP; AWS_PRINT(xx); AWS_PRINT_SP; AWS_PRINTLN(yy);}
+/////////////////////////////////////////////////
+
#endif //PORTENTA_H7_ASYNC_WEBSERVER_DEBUG_H
diff --git a/src/Portenta_H7_AsyncWebSocket.cpp b/src/Portenta_H7_AsyncWebSocket.cpp
index 18a86df..2f3943f 100644
--- a/src/Portenta_H7_AsyncWebSocket.cpp
+++ b/src/Portenta_H7_AsyncWebSocket.cpp
@@ -9,7 +9,7 @@
Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_AsyncWebServer
Licensed under GPLv3 license
- Version: 1.2.1
+ Version: 1.3.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -18,6 +18,7 @@
1.1.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json`
1.2.0 K Hoang 07/12/2021 Fix crashing issue
1.2.1 K Hoang 12/01/2022 Fix authenticate issue caused by libb64
+ 1.3.0 K Hoang 26/09/2022 Fix issue with slow browsers or network
*****************************************************************************************************************************/
#include "Arduino.h"
@@ -38,6 +39,8 @@
#define MAX_PRINTF_LEN 64
+/////////////////////////////////////////////////
+
size_t webSocketSendFrameWindow(AsyncClient *client)
{
if (!client->canSend())
@@ -51,6 +54,8 @@ size_t webSocketSendFrameWindow(AsyncClient *client)
return (space - 8);
}
+/////////////////////////////////////////////////
+
size_t webSocketSendFrame(AsyncClient *client, bool final, uint8_t opcode, bool mask, uint8_t *data, size_t len)
{
if (!client->canSend())
@@ -118,6 +123,7 @@ size_t webSocketSendFrame(AsyncClient *client, bool final, uint8_t opcode, bool
AWS_LOGDEBUG1("Error adding header, bytes =", headLen);
free(buf);
+
return 0;
}
@@ -144,25 +150,26 @@ size_t webSocketSendFrame(AsyncClient *client, bool final, uint8_t opcode, bool
if (!client->send())
{
AWS_LOGDEBUG1("Error sending frame: bytes =", headLen + len);
+
return 0;
}
return len;
}
+/////////////////////////////////////////////////
/*
AsyncWebSocketMessageBuffer
*/
-
-
AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer()
: _data(nullptr), _len(0), _lock(false), _count(0)
{
-
}
+/////////////////////////////////////////////////
+
AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer(uint8_t * data, size_t size)
: _data(nullptr), _len(size), _lock(false), _count(0)
{
@@ -180,6 +187,7 @@ AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer(uint8_t * data, size_t
}
}
+/////////////////////////////////////////////////
AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer(size_t size)
: _data(nullptr), _len(size), _lock(false), _count(0)
@@ -190,9 +198,10 @@ AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer(size_t size)
{
_data[_len] = 0;
}
-
}
+/////////////////////////////////////////////////
+
AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer(const AsyncWebSocketMessageBuffer & copy)
: _data(nullptr), _len(0), _lock(false), _count(0)
{
@@ -211,9 +220,10 @@ AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer(const AsyncWebSocketMes
memcpy(_data, copy._data, _len);
_data[_len] = 0;
}
-
}
+/////////////////////////////////////////////////
+
AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer(AsyncWebSocketMessageBuffer && copy)
: _data(nullptr), _len(0), _lock(false), _count(0)
{
@@ -226,9 +236,10 @@ AsyncWebSocketMessageBuffer::AsyncWebSocketMessageBuffer(AsyncWebSocketMessageBu
_data = copy._data;
copy._data = nullptr;
}
-
}
+/////////////////////////////////////////////////
+
AsyncWebSocketMessageBuffer::~AsyncWebSocketMessageBuffer()
{
if (_data)
@@ -237,6 +248,8 @@ AsyncWebSocketMessageBuffer::~AsyncWebSocketMessageBuffer()
}
}
+/////////////////////////////////////////////////
+
bool AsyncWebSocketMessageBuffer::reserve(size_t size)
{
_len = size;
@@ -259,9 +272,10 @@ bool AsyncWebSocketMessageBuffer::reserve(size_t size)
{
return false;
}
-
}
+/////////////////////////////////////////////////
+
/*
Control Frame
*/
@@ -326,6 +340,8 @@ class AsyncWebSocketControl
}
};
+/////////////////////////////////////////////////
+
/*
Basic Buffered Message
*/
@@ -349,6 +365,8 @@ AsyncWebSocketBasicMessage::AsyncWebSocketBasicMessage(const char * data, size_t
}
}
+/////////////////////////////////////////////////
+
AsyncWebSocketBasicMessage::AsyncWebSocketBasicMessage(uint8_t opcode, bool mask)
: _len(0), _sent(0), _ack(0), _acked(0), _data(NULL)
{
@@ -356,6 +374,7 @@ AsyncWebSocketBasicMessage::AsyncWebSocketBasicMessage(uint8_t opcode, bool mask
_mask = mask;
}
+/////////////////////////////////////////////////
AsyncWebSocketBasicMessage::~AsyncWebSocketBasicMessage()
{
@@ -363,6 +382,8 @@ AsyncWebSocketBasicMessage::~AsyncWebSocketBasicMessage()
free(_data);
}
+/////////////////////////////////////////////////
+
void AsyncWebSocketBasicMessage::ack(size_t len, uint32_t time)
{
PORTENTA_H7_AWS_UNUSED(time);
@@ -374,6 +395,8 @@ void AsyncWebSocketBasicMessage::ack(size_t len, uint32_t time)
}
}
+/////////////////////////////////////////////////
+
size_t AsyncWebSocketBasicMessage::send(AsyncClient *client)
{
if (_status != WS_MSG_SENDING)
@@ -426,6 +449,8 @@ size_t AsyncWebSocketBasicMessage::send(AsyncClient *client)
return sent;
}
+/////////////////////////////////////////////////
+
bool AsyncWebSocketBasicMessage::reserve(size_t size)
{
if (size)
@@ -444,6 +469,8 @@ bool AsyncWebSocketBasicMessage::reserve(size_t size)
return false;
}
+/////////////////////////////////////////////////
+
/*
AsyncWebSocketMultiMessage Message
*/
@@ -471,6 +498,7 @@ AsyncWebSocketMultiMessage::AsyncWebSocketMultiMessage(AsyncWebSocketMessageBuff
}
+/////////////////////////////////////////////////
AsyncWebSocketMultiMessage::~AsyncWebSocketMultiMessage()
{
@@ -480,6 +508,8 @@ AsyncWebSocketMultiMessage::~AsyncWebSocketMultiMessage()
}
}
+/////////////////////////////////////////////////
+
void AsyncWebSocketMultiMessage::ack(size_t len, uint32_t time)
{
PORTENTA_H7_AWS_UNUSED(time);
@@ -493,6 +523,8 @@ void AsyncWebSocketMultiMessage::ack(size_t len, uint32_t time)
AWS_LOGDEBUG1("ACK:", _len);
}
+/////////////////////////////////////////////////
+
size_t AsyncWebSocketMultiMessage::send(AsyncClient *client)
{
if (_status != WS_MSG_SENDING)
@@ -506,6 +538,7 @@ size_t AsyncWebSocketMultiMessage::send(AsyncClient *client)
if (_sent == _len)
{
_status = WS_MSG_SENT;
+
return 0;
}
@@ -548,6 +581,7 @@ size_t AsyncWebSocketMultiMessage::send(AsyncClient *client)
return sent;
}
+/////////////////////////////////////////////////
/*
Async WebSocket Client
@@ -577,12 +611,14 @@ AsyncWebSocketClient::AsyncWebSocketClient(AsyncWebServerRequest *request, Async
_client->onError([](void *r, AsyncClient * c, int8_t error)
{
PORTENTA_H7_AWS_UNUSED(c);
+
((AsyncWebSocketClient*)(r))->_onError(error);
}, this);
_client->onAck([](void *r, AsyncClient * c, size_t len, uint32_t time)
{
PORTENTA_H7_AWS_UNUSED(c);
+
((AsyncWebSocketClient*)(r))->_onAck(len, time);
}, this);
@@ -595,18 +631,21 @@ AsyncWebSocketClient::AsyncWebSocketClient(AsyncWebServerRequest *request, Async
_client->onTimeout([](void *r, AsyncClient * c, uint32_t time)
{
PORTENTA_H7_AWS_UNUSED(c);
+
((AsyncWebSocketClient*)(r))->_onTimeout(time);
}, this);
_client->onData([](void *r, AsyncClient * c, void *buf, size_t len)
{
PORTENTA_H7_AWS_UNUSED(c);
+
((AsyncWebSocketClient*)(r))->_onData(buf, len);
}, this);
_client->onPoll([](void *r, AsyncClient * c)
{
PORTENTA_H7_AWS_UNUSED(c);
+
((AsyncWebSocketClient*)(r))->_onPoll();
}, this);
@@ -616,6 +655,8 @@ AsyncWebSocketClient::AsyncWebSocketClient(AsyncWebServerRequest *request, Async
delete request;
}
+/////////////////////////////////////////////////
+
AsyncWebSocketClient::~AsyncWebSocketClient()
{
_messageQueue.free();
@@ -623,6 +664,8 @@ AsyncWebSocketClient::~AsyncWebSocketClient()
_server->_handleEvent(this, WS_EVT_DISCONNECT, NULL, NULL, 0);
}
+/////////////////////////////////////////////////
+
void AsyncWebSocketClient::_onAck(size_t len, uint32_t time)
{
_lastMessageTime = millis();
@@ -656,6 +699,8 @@ void AsyncWebSocketClient::_onAck(size_t len, uint32_t time)
_runQueue();
}
+/////////////////////////////////////////////////
+
void AsyncWebSocketClient::_onPoll()
{
if (_client->canSend() && (!_controlQueue.isEmpty() || !_messageQueue.isEmpty())) {
@@ -667,6 +712,8 @@ void AsyncWebSocketClient::_onPoll()
}
}
+/////////////////////////////////////////////////
+
void AsyncWebSocketClient::_runQueue()
{
while (!_messageQueue.isEmpty() && _messageQueue.front()->finished())
@@ -685,6 +732,8 @@ void AsyncWebSocketClient::_runQueue()
}
}
+/////////////////////////////////////////////////
+
bool AsyncWebSocketClient::queueIsFull()
{
if ((_messageQueue.length() >= WS_MAX_QUEUED_MESSAGES) || (_status != WS_CONNECTED) )
@@ -693,6 +742,8 @@ bool AsyncWebSocketClient::queueIsFull()
return false;
}
+/////////////////////////////////////////////////
+
void AsyncWebSocketClient::_queueMessage(AsyncWebSocketMessage *dataMessage)
{
if (dataMessage == NULL)
@@ -718,6 +769,8 @@ void AsyncWebSocketClient::_queueMessage(AsyncWebSocketMessage *dataMessage)
_runQueue();
}
+/////////////////////////////////////////////////
+
void AsyncWebSocketClient::_queueControl(AsyncWebSocketControl *controlMessage)
{
if (controlMessage == NULL)
@@ -729,6 +782,8 @@ void AsyncWebSocketClient::_queueControl(AsyncWebSocketControl *controlMessage)
_runQueue();
}
+/////////////////////////////////////////////////
+
void AsyncWebSocketClient::close(uint16_t code, const char * message)
{
if (_status != WS_CONNECTED)
@@ -770,26 +825,36 @@ void AsyncWebSocketClient::close(uint16_t code, const char * message)
_queueControl(new AsyncWebSocketControl(WS_DISCONNECT));
}
+/////////////////////////////////////////////////
+
void AsyncWebSocketClient::ping(uint8_t *data, size_t len)
{
if (_status == WS_CONNECTED)
_queueControl(new AsyncWebSocketControl(WS_PING, data, len));
}
+/////////////////////////////////////////////////
+
void AsyncWebSocketClient::_onError(int8_t) {}
+/////////////////////////////////////////////////
+
void AsyncWebSocketClient::_onTimeout(uint32_t time)
{
PORTENTA_H7_AWS_UNUSED(time);
_client->close(true);
}
+/////////////////////////////////////////////////
+
void AsyncWebSocketClient::_onDisconnect()
{
_client = NULL;
_server->_handleDisconnect(this);
}
+/////////////////////////////////////////////////
+
void AsyncWebSocketClient::_onData(void *pbuf, size_t plen)
{
_lastMessageTime = millis();
@@ -918,6 +983,8 @@ void AsyncWebSocketClient::_onData(void *pbuf, size_t plen)
}
}
+/////////////////////////////////////////////////
+
size_t AsyncWebSocketClient::printf(const char *format, ...)
{
va_list arg;
@@ -927,6 +994,7 @@ size_t AsyncWebSocketClient::printf(const char *format, ...)
if (!temp)
{
va_end(arg);
+
return 0;
}
@@ -941,6 +1009,7 @@ size_t AsyncWebSocketClient::printf(const char *format, ...)
if (!buffer)
{
delete[] temp;
+
return 0;
}
@@ -961,77 +1030,104 @@ size_t AsyncWebSocketClient::printf(const char *format, ...)
return len;
}
+/////////////////////////////////////////////////
+
void AsyncWebSocketClient::text(const char * message, size_t len)
{
_queueMessage(new AsyncWebSocketBasicMessage(message, len));
}
+/////////////////////////////////////////////////
+
void AsyncWebSocketClient::text(const char * message)
{
text(message, strlen(message));
}
+/////////////////////////////////////////////////
+
void AsyncWebSocketClient::text(uint8_t * message, size_t len)
{
text((const char *)message, len);
}
+/////////////////////////////////////////////////
+
void AsyncWebSocketClient::text(char * message)
{
text(message, strlen(message));
}
+/////////////////////////////////////////////////
+
void AsyncWebSocketClient::text(const String & message)
{
text(message.c_str(), message.length());
}
+/////////////////////////////////////////////////
+
void AsyncWebSocketClient::text(AsyncWebSocketMessageBuffer * buffer)
{
_queueMessage(new AsyncWebSocketMultiMessage(buffer));
}
+/////////////////////////////////////////////////
+
void AsyncWebSocketClient::binary(const char * message, size_t len)
{
_queueMessage(new AsyncWebSocketBasicMessage(message, len, WS_BINARY));
}
+/////////////////////////////////////////////////
+
void AsyncWebSocketClient::binary(const char * message)
{
binary(message, strlen(message));
}
+/////////////////////////////////////////////////
+
void AsyncWebSocketClient::binary(uint8_t * message, size_t len)
{
binary((const char *)message, len);
}
+/////////////////////////////////////////////////
+
void AsyncWebSocketClient::binary(char * message)
{
binary(message, strlen(message));
}
+/////////////////////////////////////////////////
+
void AsyncWebSocketClient::binary(const String & message)
{
binary(message.c_str(), message.length());
}
+/////////////////////////////////////////////////
+
void AsyncWebSocketClient::binary(AsyncWebSocketMessageBuffer * buffer)
{
_queueMessage(new AsyncWebSocketMultiMessage(buffer, WS_BINARY));
}
+/////////////////////////////////////////////////
+
IPAddress AsyncWebSocketClient::remoteIP()
{
if (!_client)
{
- //return IPAddress(0U);
return IPAddress(0, 0, 0, 0);
}
return _client->remoteIP();
}
+/////////////////////////////////////////////////
+
uint16_t AsyncWebSocketClient::remotePort()
{
if (!_client)
@@ -1042,6 +1138,8 @@ uint16_t AsyncWebSocketClient::remotePort()
return _client->remotePort();
}
+/////////////////////////////////////////////////
+
/*
Async Web Socket - Each separate socket location
*/
@@ -1060,8 +1158,12 @@ AsyncWebSocket::AsyncWebSocket(const String & url)
_eventHandler = NULL;
}
+/////////////////////////////////////////////////
+
AsyncWebSocket::~AsyncWebSocket() {}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::_handleEvent(AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len)
{
if (_eventHandler != NULL)
@@ -1070,11 +1172,15 @@ void AsyncWebSocket::_handleEvent(AsyncWebSocketClient * client, AwsEventType ty
}
}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::_addClient(AsyncWebSocketClient * client)
{
_clients.add(client);
}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::_handleDisconnect(AsyncWebSocketClient * client)
{
@@ -1084,6 +1190,8 @@ void AsyncWebSocket::_handleDisconnect(AsyncWebSocketClient * client)
});
}
+/////////////////////////////////////////////////
+
bool AsyncWebSocket::availableForWriteAll()
{
for (const auto& c : _clients)
@@ -1095,6 +1203,8 @@ bool AsyncWebSocket::availableForWriteAll()
return true;
}
+/////////////////////////////////////////////////
+
bool AsyncWebSocket::availableForWrite(uint32_t id)
{
for (const auto& c : _clients)
@@ -1106,6 +1216,8 @@ bool AsyncWebSocket::availableForWrite(uint32_t id)
return true;
}
+/////////////////////////////////////////////////
+
size_t AsyncWebSocket::count() const
{
return _clients.count_if([](AsyncWebSocketClient * c)
@@ -1114,6 +1226,8 @@ size_t AsyncWebSocket::count() const
});
}
+/////////////////////////////////////////////////
+
AsyncWebSocketClient * AsyncWebSocket::client(uint32_t id)
{
for (const auto &c : _clients)
@@ -1127,6 +1241,7 @@ AsyncWebSocketClient * AsyncWebSocket::client(uint32_t id)
return nullptr;
}
+/////////////////////////////////////////////////
void AsyncWebSocket::close(uint32_t id, uint16_t code, const char * message)
{
@@ -1136,6 +1251,8 @@ void AsyncWebSocket::close(uint32_t id, uint16_t code, const char * message)
c->close(code, message);
}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::closeAll(uint16_t code, const char * message)
{
for (const auto& c : _clients)
@@ -1145,6 +1262,8 @@ void AsyncWebSocket::closeAll(uint16_t code, const char * message)
}
}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::cleanupClients(uint16_t maxClients)
{
if (count() > maxClients)
@@ -1153,6 +1272,8 @@ void AsyncWebSocket::cleanupClients(uint16_t maxClients)
}
}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::ping(uint32_t id, uint8_t *data, size_t len)
{
AsyncWebSocketClient * c = client(id);
@@ -1161,6 +1282,8 @@ void AsyncWebSocket::ping(uint32_t id, uint8_t *data, size_t len)
c->ping(data, len);
}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::pingAll(uint8_t *data, size_t len)
{
for (const auto& c : _clients)
@@ -1170,6 +1293,8 @@ void AsyncWebSocket::pingAll(uint8_t *data, size_t len)
}
}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::text(uint32_t id, const char * message, size_t len)
{
AsyncWebSocketClient * c = client(id);
@@ -1178,6 +1303,8 @@ void AsyncWebSocket::text(uint32_t id, const char * message, size_t len)
c->text(message, len);
}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::textAll(AsyncWebSocketMessageBuffer * buffer)
{
if (!buffer)
@@ -1197,6 +1324,7 @@ void AsyncWebSocket::textAll(AsyncWebSocketMessageBuffer * buffer)
_cleanBuffers();
}
+/////////////////////////////////////////////////
void AsyncWebSocket::textAll(const char * message, size_t len)
{
@@ -1204,6 +1332,8 @@ void AsyncWebSocket::textAll(const char * message, size_t len)
textAll(WSBuffer);
}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::binary(uint32_t id, const char * message, size_t len)
{
AsyncWebSocketClient * c = client(id);
@@ -1212,12 +1342,16 @@ void AsyncWebSocket::binary(uint32_t id, const char * message, size_t len)
c->binary(message, len);
}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::binaryAll(const char * message, size_t len)
{
AsyncWebSocketMessageBuffer * buffer = makeBuffer((uint8_t *)message, len);
binaryAll(buffer);
}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::binaryAll(AsyncWebSocketMessageBuffer * buffer)
{
if (!buffer)
@@ -1235,6 +1369,8 @@ void AsyncWebSocket::binaryAll(AsyncWebSocketMessageBuffer * buffer)
_cleanBuffers();
}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::message(uint32_t id, AsyncWebSocketMessage * message)
{
AsyncWebSocketClient * c = client(id);
@@ -1243,6 +1379,8 @@ void AsyncWebSocket::message(uint32_t id, AsyncWebSocketMessage * message)
c->message(message);
}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::messageAll(AsyncWebSocketMultiMessage * message)
{
for (const auto& c : _clients)
@@ -1254,6 +1392,8 @@ void AsyncWebSocket::messageAll(AsyncWebSocketMultiMessage * message)
_cleanBuffers();
}
+/////////////////////////////////////////////////
+
size_t AsyncWebSocket::printf(uint32_t id, const char *format, ...)
{
AsyncWebSocketClient * c = client(id);
@@ -1270,6 +1410,8 @@ size_t AsyncWebSocket::printf(uint32_t id, const char *format, ...)
return 0;
}
+/////////////////////////////////////////////////
+
size_t AsyncWebSocket::printfAll(const char *format, ...)
{
va_list arg;
@@ -1297,64 +1439,89 @@ size_t AsyncWebSocket::printfAll(const char *format, ...)
va_end(arg);
textAll(buffer);
+
return len;
}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::text(uint32_t id, const char * message)
{
text(id, message, strlen(message));
}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::text(uint32_t id, uint8_t * message, size_t len)
{
text(id, (const char *)message, len);
}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::text(uint32_t id, char * message)
{
text(id, message, strlen(message));
}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::text(uint32_t id, const String & message)
{
text(id, message.c_str(), message.length());
}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::textAll(const char * message)
{
textAll(message, strlen(message));
}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::textAll(uint8_t * message, size_t len)
{
textAll((const char *)message, len);
}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::textAll(char * message)
{
textAll(message, strlen(message));
}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::textAll(const String & message)
{
textAll(message.c_str(), message.length());
}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::binary(uint32_t id, const char * message)
{
binary(id, message, strlen(message));
}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::binary(uint32_t id, uint8_t * message, size_t len)
{
binary(id, (const char *)message, len);
}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::binary(uint32_t id, char * message)
{
binary(id, message, strlen(message));
}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::binary(uint32_t id, const String & message)
{
binary(id, message.c_str(), message.length());
@@ -1365,21 +1532,29 @@ void AsyncWebSocket::binaryAll(const char * message)
binaryAll(message, strlen(message));
}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::binaryAll(uint8_t * message, size_t len)
{
binaryAll((const char *)message, len);
}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::binaryAll(char * message)
{
binaryAll(message, strlen(message));
}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::binaryAll(const String & message)
{
binaryAll(message.c_str(), message.length());
}
+/////////////////////////////////////////////////
+
const char * WS_STR_CONNECTION = "Connection";
const char * WS_STR_UPGRADE = "Upgrade";
const char * WS_STR_ORIGIN = "Origin";
@@ -1389,6 +1564,8 @@ const char * WS_STR_PROTOCOL = "Sec-WebSocket-Protocol";
const char * WS_STR_ACCEPT = "Sec-WebSocket-Accept";
const char * WS_STR_UUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
+/////////////////////////////////////////////////
+
bool AsyncWebSocket::canHandle(AsyncWebServerRequest * request)
{
if (!_enabled)
@@ -1407,6 +1584,8 @@ bool AsyncWebSocket::canHandle(AsyncWebServerRequest * request)
return true;
}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::handleRequest(AsyncWebServerRequest * request)
{
if (!request->hasHeader(WS_STR_VERSION) || !request->hasHeader(WS_STR_KEY))
@@ -1445,6 +1624,8 @@ void AsyncWebSocket::handleRequest(AsyncWebServerRequest * request)
request->send(response);
}
+/////////////////////////////////////////////////
+
AsyncWebSocketMessageBuffer * AsyncWebSocket::makeBuffer(size_t size)
{
AsyncWebSocketMessageBuffer * buffer = new AsyncWebSocketMessageBuffer(size);
@@ -1458,6 +1639,8 @@ AsyncWebSocketMessageBuffer * AsyncWebSocket::makeBuffer(size_t size)
return buffer;
}
+/////////////////////////////////////////////////
+
AsyncWebSocketMessageBuffer * AsyncWebSocket::makeBuffer(uint8_t * data, size_t size)
{
AsyncWebSocketMessageBuffer * buffer = new AsyncWebSocketMessageBuffer(data, size);
@@ -1471,6 +1654,8 @@ AsyncWebSocketMessageBuffer * AsyncWebSocket::makeBuffer(uint8_t * data, size_t
return buffer;
}
+/////////////////////////////////////////////////
+
void AsyncWebSocket::_cleanBuffers()
{
AsyncWebLockGuard l(_lock);
@@ -1484,11 +1669,15 @@ void AsyncWebSocket::_cleanBuffers()
}
}
+/////////////////////////////////////////////////
+
AsyncWebSocket::AsyncWebSocketClientLinkedList AsyncWebSocket::getClients() const
{
return _clients;
}
+/////////////////////////////////////////////////
+
/*
Response to Web Socket request - sends the authorization and detaches the TCP Client from the web server
Authentication code from https://github.com/Links2004/arduinoWebSockets/blob/master/src/WebSockets.cpp#L480
@@ -1505,6 +1694,7 @@ AsyncWebSocketResponse::AsyncWebSocketResponse(const String & key, AsyncWebSocke
if (hash == NULL)
{
_state = RESPONSE_FAILED;
+
return;
}
@@ -1514,6 +1704,7 @@ AsyncWebSocketResponse::AsyncWebSocketResponse(const String & key, AsyncWebSocke
{
free(hash);
_state = RESPONSE_FAILED;
+
return;
}
@@ -1540,11 +1731,14 @@ AsyncWebSocketResponse::AsyncWebSocketResponse(const String & key, AsyncWebSocke
free(hash);
}
+/////////////////////////////////////////////////
+
void AsyncWebSocketResponse::_respond(AsyncWebServerRequest * request)
{
if (_state == RESPONSE_FAILED)
{
request->client()->close(true);
+
return;
}
@@ -1553,6 +1747,8 @@ void AsyncWebSocketResponse::_respond(AsyncWebServerRequest * request)
_state = RESPONSE_WAIT_ACK;
}
+/////////////////////////////////////////////////
+
size_t AsyncWebSocketResponse::_ack(AsyncWebServerRequest * request, size_t len, uint32_t time)
{
PORTENTA_H7_AWS_UNUSED(time);
@@ -1564,3 +1760,6 @@ size_t AsyncWebSocketResponse::_ack(AsyncWebServerRequest * request, size_t len,
return 0;
}
+
+/////////////////////////////////////////////////
+
diff --git a/src/Portenta_H7_AsyncWebSocket.h b/src/Portenta_H7_AsyncWebSocket.h
index fa3faf4..8b39445 100644
--- a/src/Portenta_H7_AsyncWebSocket.h
+++ b/src/Portenta_H7_AsyncWebSocket.h
@@ -9,7 +9,7 @@
Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_AsyncWebServer
Licensed under GPLv3 license
- Version: 1.2.1
+ Version: 1.3.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -18,6 +18,7 @@
1.1.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json`
1.2.0 K Hoang 07/12/2021 Fix crashing issue
1.2.1 K Hoang 12/01/2022 Fix authenticate issue caused by libb64
+ 1.3.0 K Hoang 26/09/2022 Fix issue with slow browsers or network
*****************************************************************************************************************************/
#pragma once
@@ -38,11 +39,15 @@
#include "Portenta_H7_AsyncWebSynchronization.h"
+/////////////////////////////////////////////////
+
class AsyncWebSocket;
class AsyncWebSocketResponse;
class AsyncWebSocketClient;
class AsyncWebSocketControl;
+/////////////////////////////////////////////////
+
typedef struct
{
/** Message type as defined by enum AwsFrameType.
@@ -68,6 +73,8 @@ typedef struct
uint64_t index;
} AwsFrameInfo;
+/////////////////////////////////////////////////
+
typedef enum
{
WS_DISCONNECTED,
@@ -75,6 +82,8 @@ typedef enum
WS_DISCONNECTING
} AwsClientStatus;
+/////////////////////////////////////////////////
+
typedef enum
{
WS_CONTINUATION,
@@ -85,6 +94,8 @@ typedef enum
WS_PONG
} AwsFrameType;
+/////////////////////////////////////////////////
+
typedef enum
{
WS_MSG_SENDING,
@@ -92,6 +103,8 @@ typedef enum
WS_MSG_ERROR
} AwsMessageStatus;
+/////////////////////////////////////////////////
+
typedef enum
{
WS_EVT_CONNECT,
@@ -101,6 +114,8 @@ typedef enum
WS_EVT_DATA
} AwsEventType;
+/////////////////////////////////////////////////
+
class AsyncWebSocketMessageBuffer
{
private:
@@ -116,12 +131,16 @@ class AsyncWebSocketMessageBuffer
AsyncWebSocketMessageBuffer(const AsyncWebSocketMessageBuffer &);
AsyncWebSocketMessageBuffer(AsyncWebSocketMessageBuffer &&);
~AsyncWebSocketMessageBuffer();
+
+ /////////////////////////////////////////////////
void operator ++(int i)
{
PORTENTA_H7_AWS_UNUSED(i);
_count++;
}
+
+ /////////////////////////////////////////////////
void operator --(int i)
{
@@ -132,43 +151,61 @@ class AsyncWebSocketMessageBuffer
_count--;
} ;
}
+
+ /////////////////////////////////////////////////
bool reserve(size_t size);
+
+ /////////////////////////////////////////////////
void lock()
{
_lock = true;
}
+
+ /////////////////////////////////////////////////
void unlock()
{
_lock = false;
}
+
+ /////////////////////////////////////////////////
uint8_t * get()
{
return _data;
}
+
+ /////////////////////////////////////////////////
size_t length()
{
return _len;
}
+
+ /////////////////////////////////////////////////
uint32_t count()
{
return _count;
}
+
+ /////////////////////////////////////////////////
bool canDelete()
{
return (!_count && !_lock);
}
+ /////////////////////////////////////////////////
+
friend AsyncWebSocket;
};
+/////////////////////////////////////////////////
+
class AsyncWebSocketMessage
{
protected:
@@ -180,16 +217,22 @@ class AsyncWebSocketMessage
AsyncWebSocketMessage(): _opcode(WS_TEXT), _mask(false), _status(WS_MSG_ERROR) {}
virtual ~AsyncWebSocketMessage() {}
virtual void ack(size_t len __attribute__((unused)), uint32_t time __attribute__((unused))) {}
+
+ /////////////////////////////////////////////////
virtual size_t send(AsyncClient *client __attribute__((unused)))
{
return 0;
}
+
+ /////////////////////////////////////////////////
virtual bool finished()
{
return _status != WS_MSG_SENDING;
}
+
+ /////////////////////////////////////////////////
virtual bool betweenFrames() const
{
@@ -197,6 +240,8 @@ class AsyncWebSocketMessage
}
};
+/////////////////////////////////////////////////
+
class AsyncWebSocketBasicMessage: public AsyncWebSocketMessage
{
private:
@@ -210,11 +255,15 @@ class AsyncWebSocketBasicMessage: public AsyncWebSocketMessage
AsyncWebSocketBasicMessage(const char * data, size_t len, uint8_t opcode = WS_TEXT, bool mask = false);
AsyncWebSocketBasicMessage(uint8_t opcode = WS_TEXT, bool mask = false);
virtual ~AsyncWebSocketBasicMessage() override;
+
+ /////////////////////////////////////////////////
virtual bool betweenFrames() const override
{
return _acked == _ack;
}
+
+ /////////////////////////////////////////////////
virtual void ack(size_t len, uint32_t time) override;
virtual size_t send(AsyncClient *client) override;
@@ -222,6 +271,8 @@ class AsyncWebSocketBasicMessage: public AsyncWebSocketMessage
virtual bool reserve(size_t size);
};
+/////////////////////////////////////////////////
+
class AsyncWebSocketMultiMessage: public AsyncWebSocketMessage
{
private:
@@ -235,16 +286,22 @@ class AsyncWebSocketMultiMessage: public AsyncWebSocketMessage
public:
AsyncWebSocketMultiMessage(AsyncWebSocketMessageBuffer * buffer, uint8_t opcode = WS_TEXT, bool mask = false);
virtual ~AsyncWebSocketMultiMessage() override;
+
+ /////////////////////////////////////////////////
virtual bool betweenFrames() const override
{
return _acked == _ack;
}
+
+ /////////////////////////////////////////////////
virtual void ack(size_t len, uint32_t time) override ;
virtual size_t send(AsyncClient *client) override ;
};
+/////////////////////////////////////////////////
+
class AsyncWebSocketClient
{
private:
@@ -272,11 +329,15 @@ class AsyncWebSocketClient
AsyncWebSocketClient(AsyncWebServerRequest *request, AsyncWebSocket *server);
~AsyncWebSocketClient();
+ /////////////////////////////////////////////////
+
//client id increments for the given server
uint32_t id()
{
return _clientId;
}
+
+ /////////////////////////////////////////////////
AwsClientStatus status()
{
@@ -287,17 +348,23 @@ class AsyncWebSocketClient
{
return _client;
}
+
+ /////////////////////////////////////////////////
AsyncWebSocket *server()
{
return _server;
}
+
+ /////////////////////////////////////////////////
AwsFrameInfo const &pinfo() const
{
return _pinfo;
}
+ /////////////////////////////////////////////////
+
IPAddress remoteIP();
uint16_t remotePort();
@@ -305,22 +372,30 @@ class AsyncWebSocketClient
void close(uint16_t code = 0, const char * message = NULL);
void ping(uint8_t *data = NULL, size_t len = 0);
+ /////////////////////////////////////////////////
+
//set auto-ping period in seconds. disabled if zero (default)
void keepAlivePeriod(uint16_t seconds)
{
_keepAlivePeriod = seconds * 1000;
}
+
+ /////////////////////////////////////////////////
uint16_t keepAlivePeriod()
{
return (uint16_t)(_keepAlivePeriod / 1000);
}
+ /////////////////////////////////////////////////
+
//data packets
void message(AsyncWebSocketMessage *message)
{
_queueMessage(message);
}
+
+ /////////////////////////////////////////////////
bool queueIsFull();
@@ -340,11 +415,15 @@ class AsyncWebSocketClient
void binary(const String &message);
void binary(AsyncWebSocketMessageBuffer *buffer);
+ /////////////////////////////////////////////////
+
bool canSend()
{
return _messageQueue.length() < WS_MAX_QUEUED_MESSAGES;
}
+ /////////////////////////////////////////////////
+
//system callbacks (do not call)
void _onAck(size_t len, uint32_t time);
void _onError(int8_t);
@@ -354,8 +433,12 @@ class AsyncWebSocketClient
void _onData(void *pbuf, size_t plen);
};
+/////////////////////////////////////////////////
+
typedef std::function AwsEventHandler;
+/////////////////////////////////////////////////
+
//WebServer Handler implementation that plays the role of a socket server
class AsyncWebSocket: public AsyncWebHandler
{
@@ -373,33 +456,45 @@ class AsyncWebSocket: public AsyncWebHandler
public:
AsyncWebSocket(const String& url);
~AsyncWebSocket();
+
+ /////////////////////////////////////////////////
const char * url() const
{
return _url.c_str();
}
+
+ /////////////////////////////////////////////////
void enable(bool e)
{
_enabled = e;
}
+
+ /////////////////////////////////////////////////
bool enabled() const
{
return _enabled;
}
+
+ /////////////////////////////////////////////////
bool availableForWriteAll();
bool availableForWrite(uint32_t id);
size_t count() const;
AsyncWebSocketClient * client(uint32_t id);
+
+ /////////////////////////////////////////////////
bool hasClient(uint32_t id)
{
return client(id) != NULL;
}
+ /////////////////////////////////////////////////
+
void close(uint32_t id, uint16_t code = 0, const char * message = NULL);
void closeAll(uint16_t code = 0, const char * message = NULL);
void cleanupClients(uint16_t maxClients = DEFAULT_MAX_WS_CLIENTS);
@@ -439,17 +534,23 @@ class AsyncWebSocket: public AsyncWebHandler
size_t printf(uint32_t id, const char *format, ...) __attribute__ ((format (printf, 3, 4)));
size_t printfAll(const char *format, ...) __attribute__ ((format (printf, 2, 3)));
+ /////////////////////////////////////////////////
+
//event listener
void onEvent(AwsEventHandler handler)
{
_eventHandler = handler;
}
+ /////////////////////////////////////////////////
+
//system callbacks (do not call)
uint32_t _getNextId()
{
return _cNextId++;
}
+
+ /////////////////////////////////////////////////
void _addClient(AsyncWebSocketClient * client);
void _handleDisconnect(AsyncWebSocketClient * client);
@@ -457,7 +558,6 @@ class AsyncWebSocket: public AsyncWebHandler
virtual bool canHandle(AsyncWebServerRequest *request) override final;
virtual void handleRequest(AsyncWebServerRequest *request) override final;
-
// messagebuffer functions/objects.
AsyncWebSocketMessageBuffer * makeBuffer(size_t size = 0);
AsyncWebSocketMessageBuffer * makeBuffer(uint8_t * data, size_t size);
@@ -467,6 +567,8 @@ class AsyncWebSocket: public AsyncWebHandler
AsyncWebSocketClientLinkedList getClients() const;
};
+/////////////////////////////////////////////////
+
//WebServer response to authenticate the socket and detach the tcp client from the web server request
class AsyncWebSocketResponse: public AsyncWebServerResponse
{
@@ -478,6 +580,8 @@ class AsyncWebSocketResponse: public AsyncWebServerResponse
AsyncWebSocketResponse(const String& key, AsyncWebSocket *server);
void _respond(AsyncWebServerRequest *request);
size_t _ack(AsyncWebServerRequest *request, size_t len, uint32_t time);
+
+ /////////////////////////////////////////////////
bool _sourceValid() const
{
@@ -485,5 +589,6 @@ class AsyncWebSocketResponse: public AsyncWebServerResponse
}
};
+/////////////////////////////////////////////////
#endif /* PORTENTA_H7_ASYNCWEBSOCKET_H_ */
diff --git a/src/Portenta_H7_AsyncWebSynchronization.h b/src/Portenta_H7_AsyncWebSynchronization.h
index aee893e..7370073 100644
--- a/src/Portenta_H7_AsyncWebSynchronization.h
+++ b/src/Portenta_H7_AsyncWebSynchronization.h
@@ -9,7 +9,7 @@
Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_AsyncWebServer
Licensed under GPLv3 license
- Version: 1.2.1
+ Version: 1.3.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -18,6 +18,7 @@
1.1.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json`
1.2.0 K Hoang 07/12/2021 Fix crashing issue
1.2.1 K Hoang 12/01/2022 Fix authenticate issue caused by libb64
+ 1.3.0 K Hoang 26/09/2022 Fix issue with slow browsers or network
*****************************************************************************************************************************/
#pragma once
@@ -27,6 +28,8 @@
#include
+/////////////////////////////////////////////////
+
// This is the STM32 version of the Sync Lock which is currently unimplemented
class AsyncWebLock
{
@@ -44,6 +47,8 @@ class AsyncWebLock
void unlock() const {}
};
+/////////////////////////////////////////////////
+
class AsyncWebLockGuard
{
private:
@@ -71,4 +76,6 @@ class AsyncWebLockGuard
}
};
+/////////////////////////////////////////////////
+
#endif // PORTENTA_H7_ASYNCWEBSYNCHRONIZATION_H_
diff --git a/src/Portenta_H7_StringArray.h b/src/Portenta_H7_StringArray.h
index 1ac971e..77c5b87 100644
--- a/src/Portenta_H7_StringArray.h
+++ b/src/Portenta_H7_StringArray.h
@@ -9,7 +9,7 @@
Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_AsyncWebServer
Licensed under GPLv3 license
- Version: 1.2.1
+ Version: 1.3.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -18,6 +18,7 @@
1.1.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json`
1.2.0 K Hoang 07/12/2021 Fix crashing issue
1.2.1 K Hoang 12/01/2022 Fix authenticate issue caused by libb64
+ 1.3.0 K Hoang 26/09/2022 Fix issue with slow browsers or network
*****************************************************************************************************************************/
#pragma once
@@ -28,6 +29,8 @@
#include "stddef.h"
#include "WString.h"
+/////////////////////////////////////////////////
+
template
class LinkedListNode
{
@@ -38,17 +41,23 @@ class LinkedListNode
LinkedListNode(const T val): _value(val), next(nullptr) {}
~LinkedListNode() {}
+ /////////////////////////////////////////////////
+
const T& value() const
{
return _value;
};
+ /////////////////////////////////////////////////
+
T& value()
{
return _value;
}
};
+/////////////////////////////////////////////////
+
template class Item = LinkedListNode>
class LinkedList
{
@@ -69,22 +78,30 @@ class LinkedList
Iterator(ItemType* current = nullptr) : _node(current) {}
Iterator(const Iterator& i) : _node(i._node) {}
+ /////////////////////////////////////////////////
+
Iterator& operator ++()
{
_node = _node->next;
return *this;
}
+ /////////////////////////////////////////////////
+
bool operator != (const Iterator& i) const
{
return _node != i._node;
}
+ /////////////////////////////////////////////////
+
const T& operator * () const
{
return _node->value();
}
+ /////////////////////////////////////////////////
+
const T* operator -> () const
{
return &_node->value();
@@ -94,19 +111,27 @@ class LinkedList
public:
typedef const Iterator ConstIterator;
+ /////////////////////////////////////////////////
+
ConstIterator begin() const
{
return ConstIterator(_root);
}
+ /////////////////////////////////////////////////
+
ConstIterator end() const
{
return ConstIterator(nullptr);
}
+ /////////////////////////////////////////////////
+
LinkedList(OnRemove onRemove) : _root(nullptr), _onRemove(onRemove) {}
~LinkedList() {}
+ /////////////////////////////////////////////////
+
void add(const T& t)
{
auto it = new ItemType(t);
@@ -126,16 +151,22 @@ class LinkedList
}
}
+ /////////////////////////////////////////////////
+
T& front() const
{
return _root->value();
}
+ /////////////////////////////////////////////////
+
bool isEmpty() const
{
return _root == nullptr;
}
+ /////////////////////////////////////////////////
+
size_t length() const
{
size_t i = 0;
@@ -150,6 +181,8 @@ class LinkedList
return i;
}
+ /////////////////////////////////////////////////
+
size_t count_if(Predicate predicate) const
{
size_t i = 0;
@@ -172,6 +205,8 @@ class LinkedList
return i;
}
+ /////////////////////////////////////////////////
+
const T* nth(size_t N) const
{
size_t i = 0;
@@ -188,6 +223,8 @@ class LinkedList
return nullptr;
}
+ /////////////////////////////////////////////////
+
bool remove(const T& t)
{
auto it = _root;
@@ -212,6 +249,7 @@ class LinkedList
}
delete it;
+
return true;
}
@@ -222,6 +260,8 @@ class LinkedList
return false;
}
+ /////////////////////////////////////////////////
+
bool remove_first(Predicate predicate)
{
auto it = _root;
@@ -246,6 +286,7 @@ class LinkedList
}
delete it;
+
return true;
}
@@ -256,6 +297,8 @@ class LinkedList
return false;
}
+ /////////////////////////////////////////////////
+
void free()
{
while (_root != nullptr)
@@ -275,6 +318,7 @@ class LinkedList
}
};
+/////////////////////////////////////////////////
class StringArray : public LinkedList
{
@@ -282,6 +326,8 @@ class StringArray : public LinkedList
StringArray() : LinkedList(nullptr) {}
+ /////////////////////////////////////////////////
+
bool containsIgnoreCase(const String& str)
{
for (const auto& s : *this)
@@ -296,4 +342,6 @@ class StringArray : public LinkedList
}
};
+/////////////////////////////////////////////////
+
#endif /* PORTENTA_H7_STRINGARRAY_H_ */
diff --git a/src/libb64/cdecode.c b/src/libb64/cdecode.c
index 7adf7e8..fd567f1 100644
--- a/src/libb64/cdecode.c
+++ b/src/libb64/cdecode.c
@@ -12,7 +12,7 @@
Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_AsyncWebServer
Licensed under GPLv3 license
- Version: 1.2.1
+ Version: 1.3.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -21,6 +21,7 @@
1.1.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json`
1.2.0 K Hoang 07/12/2021 Fix crashing issue
1.2.1 K Hoang 12/01/2022 Fix authenticate issue caused by libb64
+ 1.3.0 K Hoang 26/09/2022 Fix issue with slow browsers or network
*****************************************************************************************************************************/
#include "cdecode.h"
diff --git a/src/libb64/cdecode.h b/src/libb64/cdecode.h
index 80e911e..9cc60e5 100644
--- a/src/libb64/cdecode.h
+++ b/src/libb64/cdecode.h
@@ -12,7 +12,7 @@
Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_AsyncWebServer
Licensed under GPLv3 license
- Version: 1.2.1
+ Version: 1.3.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -21,6 +21,7 @@
1.1.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json`
1.2.0 K Hoang 07/12/2021 Fix crashing issue
1.2.1 K Hoang 12/01/2022 Fix authenticate issue caused by libb64
+ 1.3.0 K Hoang 26/09/2022 Fix issue with slow browsers or network
*****************************************************************************************************************************/
#pragma once
diff --git a/src/libb64/cencode.c b/src/libb64/cencode.c
index cba5665..bf0fcb0 100644
--- a/src/libb64/cencode.c
+++ b/src/libb64/cencode.c
@@ -12,7 +12,7 @@
Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_AsyncWebServer
Licensed under GPLv3 license
- Version: 1.2.1
+ Version: 1.3.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -21,6 +21,7 @@
1.1.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json`
1.2.0 K Hoang 07/12/2021 Fix crashing issue
1.2.1 K Hoang 12/01/2022 Fix authenticate issue caused by libb64
+ 1.3.0 K Hoang 26/09/2022 Fix issue with slow browsers or network
*****************************************************************************************************************************/
#include "cencode.h"
diff --git a/src/libb64/cencode.h b/src/libb64/cencode.h
index c9d4f27..288e1d0 100644
--- a/src/libb64/cencode.h
+++ b/src/libb64/cencode.h
@@ -12,7 +12,7 @@
Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_AsyncWebServer
Licensed under GPLv3 license
- Version: 1.2.1
+ Version: 1.3.0
Version Modified By Date Comments
------- ----------- ---------- -----------
@@ -21,6 +21,7 @@
1.1.1 K Hoang 12/10/2021 Update `platform.ini` and `library.json`
1.2.0 K Hoang 07/12/2021 Fix crashing issue
1.2.1 K Hoang 12/01/2022 Fix authenticate issue caused by libb64
+ 1.3.0 K Hoang 26/09/2022 Fix issue with slow browsers or network
*****************************************************************************************************************************/
#pragma once