mirror of
https://github.com/Links2004/arduinoWebSockets.git
synced 2025-06-25 23:11:36 +02:00
Compare commits
98 Commits
2.1.1
...
Links2004-
Author | SHA1 | Date | |
---|---|---|---|
906530e38f | |||
5caff59f7f | |||
b90fe4c1d7 | |||
a086303c87 | |||
217c7ce4ea | |||
13a304a8c9 | |||
9b873978ba | |||
ca52afeec0 | |||
beba0f88e3 | |||
f2265118b4 | |||
9982818cfa | |||
91b02341ba | |||
a00d3edcb7 | |||
c73c77e988 | |||
e1ddbfe1a5 | |||
f65e8d9062 | |||
508e0fb691 | |||
083683425f | |||
05ec18e49b | |||
e185668a97 | |||
7e34a8b246 | |||
4acc7eff8a | |||
b3c5348e9b | |||
19c39d5ea0 | |||
ebdc8def4a | |||
44fb41e3b7 | |||
cadbd6458f | |||
f244741caa | |||
3f1cedb21c | |||
ba6275e7fe | |||
a71a480676 | |||
1e271b5e12 | |||
0c3b15c5e7 | |||
7a4160814c | |||
784088d9cc | |||
9048ef9ee4 | |||
80b0867786 | |||
b9e1336826 | |||
ac9b2ccdf6 | |||
12684582aa | |||
420cc55960 | |||
64296cced7 | |||
c3f01e43fc | |||
04e4be03fe | |||
ebd7a528ac | |||
516911900b | |||
674a6e98c9 | |||
4ee0ba5630 | |||
370f217a30 | |||
c038f100d6 | |||
0444a78441 | |||
8cc20b6e4b | |||
40152be197 | |||
e2669c1c5e | |||
771831c57e | |||
06a7bb177b | |||
bd158c9c5c | |||
9a803e1fb3 | |||
c64f2b81e5 | |||
4ef8d733dc | |||
7816bb3fa4 | |||
adf2b07f3b | |||
d3fde2ba34 | |||
c164c47f08 | |||
6a76efa791 | |||
5d26a65df4 | |||
007b5ba9a8 | |||
dbca2ab420 | |||
dfa35fa9ae | |||
794163cec9 | |||
294436840c | |||
b1b21d188f | |||
3063ad27ae | |||
e8df841b7f | |||
0aa07421a6 | |||
df3ef524b6 | |||
8ec27b0468 | |||
c361895a4b | |||
31bade1530 | |||
4223a9e41f | |||
72731beb10 | |||
1b6b42b877 | |||
d6dd7be987 | |||
d325bd338e | |||
d693437908 | |||
9b6ce7563a | |||
68800e2e7a | |||
eaef4f0801 | |||
4db22fe5e4 | |||
50e2e366cc | |||
e8249f76e6 | |||
a70d644f5d | |||
a3079f5645 | |||
38a881a86a | |||
50903cd410 | |||
f95c014342 | |||
8967356af3 | |||
d2043bf8ef |
63
.clang-format
Normal file
63
.clang-format
Normal file
@ -0,0 +1,63 @@
|
||||
---
|
||||
BasedOnStyle: Google
|
||||
AccessModifierOffset: '-2'
|
||||
AlignAfterOpenBracket: DontAlign
|
||||
AlignConsecutiveAssignments: 'true'
|
||||
AlignConsecutiveDeclarations: 'false'
|
||||
AlignEscapedNewlines: Left
|
||||
AlignTrailingComments: 'true'
|
||||
AllowAllParametersOfDeclarationOnNextLine: 'false'
|
||||
AllowShortBlocksOnASingleLine: 'false'
|
||||
AllowShortCaseLabelsOnASingleLine: 'false'
|
||||
AllowShortFunctionsOnASingleLine: InlineOnly
|
||||
AllowShortIfStatementsOnASingleLine: 'true'
|
||||
AllowShortLoopsOnASingleLine: 'true'
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: 'true'
|
||||
AlwaysBreakTemplateDeclarations: 'false'
|
||||
BinPackParameters: 'true'
|
||||
BreakAfterJavaFieldAnnotations: 'false'
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInheritanceComma: 'false'
|
||||
BreakBeforeTernaryOperators: 'false'
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
BreakStringLiterals: 'false'
|
||||
ColumnLimit: '0'
|
||||
CompactNamespaces: 'true'
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: 'true'
|
||||
ConstructorInitializerIndentWidth: '4'
|
||||
ContinuationIndentWidth: '4'
|
||||
Cpp11BracedListStyle: 'false'
|
||||
DerivePointerAlignment: 'false'
|
||||
FixNamespaceComments: 'true'
|
||||
IndentCaseLabels: 'true'
|
||||
IndentWidth: '4'
|
||||
IndentWrappedFunctionNames: 'false'
|
||||
JavaScriptQuotes: Single
|
||||
JavaScriptWrapImports: 'false'
|
||||
KeepEmptyLinesAtTheStartOfBlocks: 'false'
|
||||
MaxEmptyLinesToKeep: '1'
|
||||
NamespaceIndentation: All
|
||||
ObjCBlockIndentWidth: '4'
|
||||
ObjCSpaceAfterProperty: 'false'
|
||||
ObjCSpaceBeforeProtocolList: 'false'
|
||||
PointerAlignment: Middle
|
||||
SortIncludes: 'false'
|
||||
SortUsingDeclarations: 'true'
|
||||
SpaceAfterCStyleCast: 'false'
|
||||
SpaceAfterTemplateKeyword: 'false'
|
||||
SpaceBeforeAssignmentOperators: 'true'
|
||||
SpaceBeforeParens: Never
|
||||
SpaceInEmptyParentheses: 'false'
|
||||
SpacesBeforeTrailingComments: '4'
|
||||
SpacesInAngles: 'false'
|
||||
SpacesInCStyleCastParentheses: 'false'
|
||||
SpacesInContainerLiterals: 'false'
|
||||
SpacesInParentheses: 'false'
|
||||
SpacesInSquareBrackets: 'false'
|
||||
TabWidth: '4'
|
||||
UseTab: Never
|
||||
|
||||
...
|
8
.gitignore
vendored
8
.gitignore
vendored
@ -27,3 +27,11 @@
|
||||
*.out
|
||||
*.app
|
||||
/tests/webSocketServer/node_modules
|
||||
|
||||
# IDE
|
||||
.vscode
|
||||
.cproject
|
||||
.project
|
||||
.settings
|
||||
*.swp
|
||||
|
||||
|
23
.travis.yml
23
.travis.yml
@ -1,31 +1,42 @@
|
||||
sudo: false
|
||||
dist:
|
||||
- xenial
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- xvfb
|
||||
language: bash
|
||||
os:
|
||||
- linux
|
||||
env:
|
||||
matrix:
|
||||
- CPU="esp8266" BOARD="esp8266com:esp8266:generic:CpuFrequency=80" IDE_VERSION=1.6.5
|
||||
- CPU="esp8266" BOARD="esp8266com:esp8266:generic:CpuFrequency=80,FlashSize=1M0,FlashMode=qio,FlashFreq=80" IDE_VERSION=1.8.5
|
||||
- CPU="esp8266" BOARD="esp8266com:esp8266:generic:CpuFrequency=80,Debug=Serial1" IDE_VERSION=1.6.5
|
||||
- CPU="esp32" BOARD="espressif:esp32:esp32:FlashFreq=80" IDE_VERSION=1.6.5
|
||||
- CPU="esp8266" BOARD="esp8266com:esp8266:generic:xtal=80" IDE_VERSION=1.6.13
|
||||
- CPU="esp8266" BOARD="esp8266com:esp8266:generic:xtal=80,dbg=Serial1" IDE_VERSION=1.6.13
|
||||
- CPU="esp8266" BOARD="esp8266com:esp8266:generic:xtal=80,eesz=1M,FlashMode=qio,FlashFreq=80" IDE_VERSION=1.8.13
|
||||
- CPU="esp32" BOARD="espressif:esp32:esp32:FlashFreq=80" IDE_VERSION=1.8.5
|
||||
|
||||
- CPU="esp32" BOARD="espressif:esp32:esp32:FlashFreq=80" IDE_VERSION=1.8.9
|
||||
- CPU="esp32" BOARD="espressif:esp32:esp32:FlashFreq=80" IDE_VERSION=1.8.13
|
||||
script:
|
||||
- /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16
|
||||
- sleep 3
|
||||
- export DISPLAY=:1.0
|
||||
- sleep 3
|
||||
- wget http://downloads.arduino.cc/arduino-$IDE_VERSION-linux64.tar.xz
|
||||
- tar xf arduino-$IDE_VERSION-linux64.tar.xz
|
||||
- mv arduino-$IDE_VERSION $HOME/arduino_ide
|
||||
- export PATH="$HOME/arduino_ide:$PATH"
|
||||
- which arduino
|
||||
- mkdir -p $HOME/Arduino/libraries
|
||||
|
||||
- wget https://github.com/bblanchon/ArduinoJson/archive/6.x.zip
|
||||
- unzip 6.x.zip
|
||||
- mv ArduinoJson-6.x $HOME/Arduino/libraries/ArduinoJson
|
||||
- cp -r $TRAVIS_BUILD_DIR $HOME/Arduino/libraries/arduinoWebSockets
|
||||
- source $TRAVIS_BUILD_DIR/travis/common.sh
|
||||
- get_core $CPU
|
||||
- cd $TRAVIS_BUILD_DIR
|
||||
- arduino --board $BOARD --save-prefs
|
||||
- arduino --get-pref sketchbook.path
|
||||
- arduino --pref update.check=false
|
||||
- build_sketches arduino $HOME/Arduino/libraries/arduinoWebSockets/examples/$CPU $CPU
|
||||
|
||||
notifications:
|
||||
|
18
README.md
18
README.md
@ -1,4 +1,4 @@
|
||||
WebSocket Server and Client for Arduino [](https://travis-ci.org/Links2004/arduinoWebSockets)
|
||||
WebSocket Server and Client for Arduino [](https://travis-ci.com/Links2004/arduinoWebSockets)
|
||||
===========================================
|
||||
|
||||
a WebSocket Server and Client for Arduino based on RFC6455.
|
||||
@ -34,7 +34,9 @@ a WebSocket Server and Client for Arduino based on RFC6455.
|
||||
|
||||
###### Note: ######
|
||||
|
||||
version 2.0 and up is not compatible with AVR/ATmega, check ATmega branch.
|
||||
version 2.0.0 and up is not compatible with AVR/ATmega, check ATmega branch.
|
||||
|
||||
version 2.3.0 has API changes for the ESP8266 BareSSL (may brakes existing code)
|
||||
|
||||
Arduino for AVR not supports std namespace of c++.
|
||||
|
||||
@ -57,22 +59,22 @@ The mode can be activated in the ```WebSockets.h``` (see WEBSOCKETS_NETWORK_TYPE
|
||||
### High Level Client API ###
|
||||
|
||||
- `begin` : Initiate connection sequence to the websocket host.
|
||||
```
|
||||
```c++
|
||||
void begin(const char *host, uint16_t port, const char * url = "/", const char * protocol = "arduino");
|
||||
void begin(String host, uint16_t port, String url = "/", String protocol = "arduino");
|
||||
```
|
||||
- `onEvent`: Callback to handle for websocket events
|
||||
|
||||
```
|
||||
```c++
|
||||
void onEvent(WebSocketClientEvent cbEvent);
|
||||
```
|
||||
|
||||
- `WebSocketClientEvent`: Handler for websocket events
|
||||
```
|
||||
```c++
|
||||
void (*WebSocketClientEvent)(WStype_t type, uint8_t * payload, size_t length)
|
||||
```
|
||||
Where `WStype_t type` is defined as:
|
||||
```
|
||||
```c++
|
||||
typedef enum {
|
||||
WStype_ERROR,
|
||||
WStype_DISCONNECTED,
|
||||
@ -83,6 +85,8 @@ Where `WStype_t type` is defined as:
|
||||
WStype_FRAGMENT_BIN_START,
|
||||
WStype_FRAGMENT,
|
||||
WStype_FRAGMENT_FIN,
|
||||
WStype_PING,
|
||||
WStype_PONG,
|
||||
} WStype_t;
|
||||
```
|
||||
|
||||
@ -96,3 +100,5 @@ Submit issues to: https://github.com/Links2004/arduinoWebSockets/issues
|
||||
The library is licensed under [LGPLv2.1](https://github.com/Links2004/arduinoWebSockets/blob/master/LICENSE)
|
||||
|
||||
[libb64](http://libb64.sourceforge.net/) written by Chris Venter. It is distributed under Public Domain see [LICENSE](https://github.com/Links2004/arduinoWebSockets/blob/master/src/libb64/LICENSE).
|
||||
|
||||
|
||||
|
@ -45,6 +45,14 @@ void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {
|
||||
// send data to server
|
||||
// webSocket.sendBIN(payload, length);
|
||||
break;
|
||||
case WStype_PING:
|
||||
// pong will be send automatically
|
||||
USE_SERIAL.printf("[WSc] get ping\n");
|
||||
break;
|
||||
case WStype_PONG:
|
||||
// answer to a ping we send
|
||||
USE_SERIAL.printf("[WSc] get pong\n");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
@ -85,6 +93,12 @@ void setup() {
|
||||
// try ever 5000 again if connection has failed
|
||||
webSocket.setReconnectInterval(5000);
|
||||
|
||||
// start heartbeat (optional)
|
||||
// ping server every 15000 ms
|
||||
// expect pong from server within 3000 ms
|
||||
// consider connection disconnected if pong is not received 2 times
|
||||
webSocket.enableHeartbeat(15000, 3000, 2);
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* WebSocketClientSSLWithCA.ino
|
||||
*
|
||||
* Created on: 27.10.2019
|
||||
*
|
||||
* note SSL is only possible with the ESP8266
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266WiFiMulti.h>
|
||||
|
||||
#include <WebSocketsClient.h>
|
||||
|
||||
ESP8266WiFiMulti WiFiMulti;
|
||||
WebSocketsClient webSocket;
|
||||
|
||||
#define USE_SERIAL Serial1
|
||||
|
||||
|
||||
// Can be obtained with:
|
||||
// openssl s_client -showcerts -connect echo.websocket.org:443 </dev/null
|
||||
const char ENDPOINT_CA_CERT[] PROGMEM = R"EOF(
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
|
||||
DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0NlowSjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT
|
||||
GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF
|
||||
q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0
|
||||
Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWAa6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj
|
||||
/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG
|
||||
CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNvbTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k
|
||||
c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAwVAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
|
||||
ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAzMDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu
|
||||
Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsFAAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo
|
||||
uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu
|
||||
X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlGPfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6
|
||||
KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
|
||||
-----END CERTIFICATE-----
|
||||
)EOF";
|
||||
|
||||
void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {
|
||||
switch(type) {
|
||||
case WStype_DISCONNECTED:
|
||||
USE_SERIAL.printf("[WSc] Disconnected!\n");
|
||||
break;
|
||||
case WStype_CONNECTED:
|
||||
{
|
||||
USE_SERIAL.printf("[WSc] Connected to url: %s\n", payload);
|
||||
|
||||
// send message to server when Connected
|
||||
webSocket.sendTXT("Connected");
|
||||
}
|
||||
break;
|
||||
case WStype_TEXT:
|
||||
USE_SERIAL.printf("[WSc] get text: %s\n", payload);
|
||||
|
||||
// send message to server
|
||||
// webSocket.sendTXT("message here");
|
||||
break;
|
||||
case WStype_BIN:
|
||||
USE_SERIAL.printf("[WSc] get binary length: %u\n", length);
|
||||
hexdump(payload, length);
|
||||
|
||||
// send data to server
|
||||
// webSocket.sendBIN(payload, length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
USE_SERIAL.begin(115200);
|
||||
|
||||
USE_SERIAL.setDebugOutput(true);
|
||||
|
||||
USE_SERIAL.println();
|
||||
USE_SERIAL.println();
|
||||
USE_SERIAL.println();
|
||||
|
||||
for(uint8_t t = 4; t > 0; t--) {
|
||||
USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t);
|
||||
USE_SERIAL.flush();
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
WiFiMulti.addAP("SSID", "passpasspass");
|
||||
|
||||
while(WiFiMulti.run() != WL_CONNECTED) {
|
||||
delay(100);
|
||||
}
|
||||
|
||||
webSocket.beginSslWithCA("echo.websocket.org", 443, "/", ENDPOINT_CA_CERT);
|
||||
webSocket.onEvent(webSocketEvent);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
webSocket.loop();
|
||||
}
|
@ -10,56 +10,46 @@
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266WiFiMulti.h>
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
#include <WebSocketsClient.h>
|
||||
#include <SocketIOclient.h>
|
||||
|
||||
#include <Hash.h>
|
||||
|
||||
ESP8266WiFiMulti WiFiMulti;
|
||||
WebSocketsClient webSocket;
|
||||
|
||||
SocketIOclient socketIO;
|
||||
|
||||
#define USE_SERIAL Serial1
|
||||
|
||||
#define MESSAGE_INTERVAL 30000
|
||||
#define HEARTBEAT_INTERVAL 25000
|
||||
|
||||
uint64_t messageTimestamp = 0;
|
||||
uint64_t heartbeatTimestamp = 0;
|
||||
bool isConnected = false;
|
||||
|
||||
void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {
|
||||
|
||||
|
||||
void socketIOEvent(socketIOmessageType_t type, uint8_t * payload, size_t length) {
|
||||
switch(type) {
|
||||
case WStype_DISCONNECTED:
|
||||
USE_SERIAL.printf("[WSc] Disconnected!\n");
|
||||
isConnected = false;
|
||||
case sIOtype_DISCONNECT:
|
||||
USE_SERIAL.printf("[IOc] Disconnected!\n");
|
||||
break;
|
||||
case WStype_CONNECTED:
|
||||
{
|
||||
USE_SERIAL.printf("[WSc] Connected to url: %s\n", payload);
|
||||
isConnected = true;
|
||||
|
||||
// send message to server when Connected
|
||||
// socket.io upgrade confirmation message (required)
|
||||
webSocket.sendTXT("5");
|
||||
}
|
||||
case sIOtype_CONNECT:
|
||||
USE_SERIAL.printf("[IOc] Connected to url: %s\n", payload);
|
||||
break;
|
||||
case WStype_TEXT:
|
||||
USE_SERIAL.printf("[WSc] get text: %s\n", payload);
|
||||
|
||||
// send message to server
|
||||
// webSocket.sendTXT("message here");
|
||||
case sIOtype_EVENT:
|
||||
USE_SERIAL.printf("[IOc] get event: %s\n", payload);
|
||||
break;
|
||||
case WStype_BIN:
|
||||
USE_SERIAL.printf("[WSc] get binary length: %u\n", length);
|
||||
case sIOtype_ACK:
|
||||
USE_SERIAL.printf("[IOc] get ack: %u\n", length);
|
||||
hexdump(payload, length);
|
||||
break;
|
||||
case sIOtype_ERROR:
|
||||
USE_SERIAL.printf("[IOc] get error: %u\n", length);
|
||||
hexdump(payload, length);
|
||||
break;
|
||||
case sIOtype_BINARY_EVENT:
|
||||
USE_SERIAL.printf("[IOc] get binary: %u\n", length);
|
||||
hexdump(payload, length);
|
||||
break;
|
||||
case sIOtype_BINARY_ACK:
|
||||
USE_SERIAL.printf("[IOc] get binary ack: %u\n", length);
|
||||
hexdump(payload, length);
|
||||
|
||||
// send data to server
|
||||
// webSocket.sendBIN(payload, length);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void setup() {
|
||||
@ -79,6 +69,11 @@ void setup() {
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
// disable AP
|
||||
if(WiFi.getMode() & WIFI_AP) {
|
||||
WiFi.softAPdisconnect(true);
|
||||
}
|
||||
|
||||
WiFiMulti.addAP("SSID", "passpasspass");
|
||||
|
||||
//WiFi.disconnect();
|
||||
@ -86,28 +81,45 @@ void setup() {
|
||||
delay(100);
|
||||
}
|
||||
|
||||
webSocket.beginSocketIO("192.168.0.123", 81);
|
||||
//webSocket.setAuthorization("user", "Password"); // HTTP Basic Authorization
|
||||
webSocket.onEvent(webSocketEvent);
|
||||
String ip = WiFi.localIP().toString();
|
||||
USE_SERIAL.printf("[SETUP] WiFi Connected %s\n", ip.c_str());
|
||||
|
||||
// server address, port and URL
|
||||
socketIO.begin("10.11.100.100", 8880);
|
||||
|
||||
// event handler
|
||||
socketIO.onEvent(socketIOEvent);
|
||||
}
|
||||
|
||||
unsigned long messageTimestamp = 0;
|
||||
void loop() {
|
||||
webSocket.loop();
|
||||
|
||||
if(isConnected) {
|
||||
socketIO.loop();
|
||||
|
||||
uint64_t now = millis();
|
||||
|
||||
if(now - messageTimestamp > MESSAGE_INTERVAL) {
|
||||
if(now - messageTimestamp > 2000) {
|
||||
messageTimestamp = now;
|
||||
// example socket.io message with type "messageType" and JSON payload
|
||||
webSocket.sendTXT("42[\"messageType\",{\"greeting\":\"hello\"}]");
|
||||
}
|
||||
if((now - heartbeatTimestamp) > HEARTBEAT_INTERVAL) {
|
||||
heartbeatTimestamp = now;
|
||||
// socket.io heartbeat message
|
||||
webSocket.sendTXT("2");
|
||||
}
|
||||
|
||||
// creat JSON message for Socket.IO (event)
|
||||
DynamicJsonDocument doc(1024);
|
||||
JsonArray array = doc.to<JsonArray>();
|
||||
|
||||
// add evnet name
|
||||
// Hint: socket.on('event_name', ....
|
||||
array.add("event_name");
|
||||
|
||||
// add payload (parameters) for the event
|
||||
JsonObject param1 = array.createNestedObject();
|
||||
param1["now"] = (uint32_t) now;
|
||||
|
||||
// JSON to String (serializion)
|
||||
String output;
|
||||
serializeJson(doc, output);
|
||||
|
||||
// Send event
|
||||
socketIO.sendEVENT(output);
|
||||
|
||||
// Print JSON for debugging
|
||||
USE_SERIAL.println(output);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,162 @@
|
||||
/*
|
||||
* WebSocketClientSocketIOack.ino
|
||||
*
|
||||
* Created on: 20.07.2019
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266WiFiMulti.h>
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
#include <WebSocketsClient.h>
|
||||
#include <SocketIOclient.h>
|
||||
|
||||
#include <Hash.h>
|
||||
|
||||
ESP8266WiFiMulti WiFiMulti;
|
||||
SocketIOclient socketIO;
|
||||
|
||||
#define USE_SERIAL Serial
|
||||
|
||||
|
||||
void socketIOEvent(socketIOmessageType_t type, uint8_t * payload, size_t length) {
|
||||
switch(type) {
|
||||
case sIOtype_DISCONNECT:
|
||||
USE_SERIAL.printf("[IOc] Disconnected!\n");
|
||||
break;
|
||||
case sIOtype_CONNECT:
|
||||
USE_SERIAL.printf("[IOc] Connected to url: %s\n", payload);
|
||||
break;
|
||||
case sIOtype_EVENT:
|
||||
{
|
||||
char * sptr = NULL;
|
||||
int id = strtol((char *)payload, &sptr, 10);
|
||||
USE_SERIAL.printf("[IOc] get event: %s id: %d\n", payload, id);
|
||||
if(id) {
|
||||
payload = (uint8_t *)sptr;
|
||||
}
|
||||
DynamicJsonDocument doc(1024);
|
||||
DeserializationError error = deserializeJson(doc, payload, length);
|
||||
if(error) {
|
||||
USE_SERIAL.print(F("deserializeJson() failed: "));
|
||||
USE_SERIAL.println(error.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
String eventName = doc[0];
|
||||
USE_SERIAL.printf("[IOc] event name: %s\n", eventName.c_str());
|
||||
|
||||
// Message Includes a ID for a ACK (callback)
|
||||
if(id) {
|
||||
// creat JSON message for Socket.IO (ack)
|
||||
DynamicJsonDocument docOut(1024);
|
||||
JsonArray array = docOut.to<JsonArray>();
|
||||
|
||||
// add payload (parameters) for the ack (callback function)
|
||||
JsonObject param1 = array.createNestedObject();
|
||||
param1["now"] = millis();
|
||||
|
||||
// JSON to String (serializion)
|
||||
String output;
|
||||
output += id;
|
||||
serializeJson(docOut, output);
|
||||
|
||||
// Send event
|
||||
socketIO.send(sIOtype_ACK, output);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case sIOtype_ACK:
|
||||
USE_SERIAL.printf("[IOc] get ack: %u\n", length);
|
||||
hexdump(payload, length);
|
||||
break;
|
||||
case sIOtype_ERROR:
|
||||
USE_SERIAL.printf("[IOc] get error: %u\n", length);
|
||||
hexdump(payload, length);
|
||||
break;
|
||||
case sIOtype_BINARY_EVENT:
|
||||
USE_SERIAL.printf("[IOc] get binary: %u\n", length);
|
||||
hexdump(payload, length);
|
||||
break;
|
||||
case sIOtype_BINARY_ACK:
|
||||
USE_SERIAL.printf("[IOc] get binary ack: %u\n", length);
|
||||
hexdump(payload, length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
//USE_SERIAL.begin(921600);
|
||||
USE_SERIAL.begin(115200);
|
||||
|
||||
//Serial.setDebugOutput(true);
|
||||
USE_SERIAL.setDebugOutput(true);
|
||||
|
||||
USE_SERIAL.println();
|
||||
USE_SERIAL.println();
|
||||
USE_SERIAL.println();
|
||||
|
||||
for(uint8_t t = 4; t > 0; t--) {
|
||||
USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t);
|
||||
USE_SERIAL.flush();
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
// disable AP
|
||||
if(WiFi.getMode() & WIFI_AP) {
|
||||
WiFi.softAPdisconnect(true);
|
||||
}
|
||||
|
||||
WiFiMulti.addAP("SSID", "passpasspass");
|
||||
|
||||
//WiFi.disconnect();
|
||||
while(WiFiMulti.run() != WL_CONNECTED) {
|
||||
delay(100);
|
||||
}
|
||||
|
||||
String ip = WiFi.localIP().toString();
|
||||
USE_SERIAL.printf("[SETUP] WiFi Connected %s\n", ip.c_str());
|
||||
|
||||
// server address, port and URL
|
||||
socketIO.begin("10.11.100.100", 8880);
|
||||
|
||||
// event handler
|
||||
socketIO.onEvent(socketIOEvent);
|
||||
}
|
||||
|
||||
unsigned long messageTimestamp = 0;
|
||||
void loop() {
|
||||
socketIO.loop();
|
||||
|
||||
uint64_t now = millis();
|
||||
|
||||
if(now - messageTimestamp > 2000) {
|
||||
messageTimestamp = now;
|
||||
|
||||
// creat JSON message for Socket.IO (event)
|
||||
DynamicJsonDocument doc(1024);
|
||||
JsonArray array = doc.to<JsonArray>();
|
||||
|
||||
// add evnet name
|
||||
// Hint: socket.on('event_name', ....
|
||||
array.add("event_name");
|
||||
|
||||
// add payload (parameters) for the event
|
||||
JsonObject param1 = array.createNestedObject();
|
||||
param1["now"] = (uint32_t) now;
|
||||
|
||||
// JSON to String (serializion)
|
||||
String output;
|
||||
serializeJson(doc, output);
|
||||
|
||||
// Send event
|
||||
socketIO.sendEVENT(output);
|
||||
|
||||
// Print JSON for debugging
|
||||
USE_SERIAL.println(output);
|
||||
}
|
||||
}
|
@ -13,7 +13,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/Links2004/arduinoWebSockets.git"
|
||||
},
|
||||
"version": "2.1.1",
|
||||
"version": "2.3.1",
|
||||
"license": "LGPL-2.1",
|
||||
"export": {
|
||||
"exclude": [
|
||||
|
@ -1,5 +1,5 @@
|
||||
name=WebSockets
|
||||
version=2.1.1
|
||||
version=2.3.1
|
||||
author=Markus Sattler
|
||||
maintainer=Markus Sattler
|
||||
sentence=WebSockets for Arduino (Server + Client)
|
||||
|
201
src/SocketIOclient.cpp
Normal file
201
src/SocketIOclient.cpp
Normal file
@ -0,0 +1,201 @@
|
||||
/*
|
||||
* SocketIOclient.cpp
|
||||
*
|
||||
* Created on: May 12, 2018
|
||||
* Author: links
|
||||
*/
|
||||
|
||||
#include "WebSockets.h"
|
||||
#include "WebSocketsClient.h"
|
||||
#include "SocketIOclient.h"
|
||||
|
||||
SocketIOclient::SocketIOclient() {
|
||||
}
|
||||
|
||||
SocketIOclient::~SocketIOclient() {
|
||||
}
|
||||
|
||||
void SocketIOclient::begin(const char * host, uint16_t port, const char * url, const char * protocol) {
|
||||
WebSocketsClient::beginSocketIO(host, port, url, protocol);
|
||||
WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
|
||||
}
|
||||
|
||||
void SocketIOclient::begin(String host, uint16_t port, String url, String protocol) {
|
||||
WebSocketsClient::beginSocketIO(host, port, url, protocol);
|
||||
WebSocketsClient::enableHeartbeat(60 * 1000, 90 * 1000, 5);
|
||||
}
|
||||
|
||||
/**
|
||||
* set callback function
|
||||
* @param cbEvent SocketIOclientEvent
|
||||
*/
|
||||
void SocketIOclient::onEvent(SocketIOclientEvent cbEvent) {
|
||||
_cbEvent = cbEvent;
|
||||
}
|
||||
|
||||
bool SocketIOclient::isConnected(void) {
|
||||
return WebSocketsClient::isConnected();
|
||||
}
|
||||
|
||||
/**
|
||||
* send text data to client
|
||||
* @param num uint8_t client id
|
||||
* @param type socketIOmessageType_t
|
||||
* @param payload uint8_t *
|
||||
* @param length size_t
|
||||
* @param headerToPayload bool (see sendFrame for more details)
|
||||
* @return true if ok
|
||||
*/
|
||||
bool SocketIOclient::send(socketIOmessageType_t type, uint8_t * payload, size_t length, bool headerToPayload) {
|
||||
bool ret = false;
|
||||
if(length == 0) {
|
||||
length = strlen((const char *)payload);
|
||||
}
|
||||
if(clientIsConnected(&_client)) {
|
||||
if(!headerToPayload) {
|
||||
// webSocket Header
|
||||
ret = WebSocketsClient::sendFrameHeader(&_client, WSop_text, length + 2, true);
|
||||
// Engine.IO / Socket.IO Header
|
||||
if(ret) {
|
||||
uint8_t buf[3] = { eIOtype_MESSAGE, type, 0x00 };
|
||||
ret = WebSocketsClient::write(&_client, buf, 2);
|
||||
}
|
||||
if(ret && payload && length > 0) {
|
||||
ret = WebSocketsClient::write(&_client, payload, length);
|
||||
}
|
||||
return ret;
|
||||
} else {
|
||||
// TODO implement
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SocketIOclient::send(socketIOmessageType_t type, const uint8_t * payload, size_t length) {
|
||||
return send(type, (uint8_t *)payload, length);
|
||||
}
|
||||
|
||||
bool SocketIOclient::send(socketIOmessageType_t type, char * payload, size_t length, bool headerToPayload) {
|
||||
return send(type, (uint8_t *)payload, length, headerToPayload);
|
||||
}
|
||||
|
||||
bool SocketIOclient::send(socketIOmessageType_t type, const char * payload, size_t length) {
|
||||
return send(type, (uint8_t *)payload, length);
|
||||
}
|
||||
|
||||
bool SocketIOclient::send(socketIOmessageType_t type, String & payload) {
|
||||
return send(type, (uint8_t *)payload.c_str(), payload.length());
|
||||
}
|
||||
|
||||
/**
|
||||
* send text data to client
|
||||
* @param num uint8_t client id
|
||||
* @param payload uint8_t *
|
||||
* @param length size_t
|
||||
* @param headerToPayload bool (see sendFrame for more details)
|
||||
* @return true if ok
|
||||
*/
|
||||
bool SocketIOclient::sendEVENT(uint8_t * payload, size_t length, bool headerToPayload) {
|
||||
return send(sIOtype_EVENT, payload, length, headerToPayload);
|
||||
}
|
||||
|
||||
bool SocketIOclient::sendEVENT(const uint8_t * payload, size_t length) {
|
||||
return sendEVENT((uint8_t *)payload, length);
|
||||
}
|
||||
|
||||
bool SocketIOclient::sendEVENT(char * payload, size_t length, bool headerToPayload) {
|
||||
return sendEVENT((uint8_t *)payload, length, headerToPayload);
|
||||
}
|
||||
|
||||
bool SocketIOclient::sendEVENT(const char * payload, size_t length) {
|
||||
return sendEVENT((uint8_t *)payload, length);
|
||||
}
|
||||
|
||||
bool SocketIOclient::sendEVENT(String & payload) {
|
||||
return sendEVENT((uint8_t *)payload.c_str(), payload.length());
|
||||
}
|
||||
|
||||
void SocketIOclient::loop(void) {
|
||||
WebSocketsClient::loop();
|
||||
unsigned long t = millis();
|
||||
if((t - _lastConnectionFail) > EIO_HEARTBEAT_INTERVAL) {
|
||||
_lastConnectionFail = t;
|
||||
DEBUG_WEBSOCKETS("[wsIOc] send ping\n");
|
||||
WebSocketsClient::sendTXT(eIOtype_PING);
|
||||
}
|
||||
}
|
||||
|
||||
void SocketIOclient::handleCbEvent(WStype_t type, uint8_t * payload, size_t length) {
|
||||
switch(type) {
|
||||
case WStype_DISCONNECTED:
|
||||
runIOCbEvent(sIOtype_DISCONNECT, NULL, 0);
|
||||
DEBUG_WEBSOCKETS("[wsIOc] Disconnected!\n");
|
||||
break;
|
||||
case WStype_CONNECTED: {
|
||||
DEBUG_WEBSOCKETS("[wsIOc] Connected to url: %s\n", payload);
|
||||
// send message to server when Connected
|
||||
// Engine.io upgrade confirmation message (required)
|
||||
WebSocketsClient::sendTXT(eIOtype_UPGRADE);
|
||||
runIOCbEvent(sIOtype_CONNECT, payload, length);
|
||||
} break;
|
||||
case WStype_TEXT: {
|
||||
if(length < 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
engineIOmessageType_t eType = (engineIOmessageType_t)payload[0];
|
||||
switch(eType) {
|
||||
case eIOtype_PING:
|
||||
payload[0] = eIOtype_PONG;
|
||||
DEBUG_WEBSOCKETS("[wsIOc] get ping send pong (%s)\n", payload);
|
||||
WebSocketsClient::sendTXT(payload, length, false);
|
||||
break;
|
||||
case eIOtype_PONG:
|
||||
DEBUG_WEBSOCKETS("[wsIOc] get pong\n");
|
||||
break;
|
||||
case eIOtype_MESSAGE: {
|
||||
if(length < 2) {
|
||||
break;
|
||||
}
|
||||
socketIOmessageType_t ioType = (socketIOmessageType_t)payload[1];
|
||||
uint8_t * data = &payload[2];
|
||||
size_t lData = length - 2;
|
||||
switch(ioType) {
|
||||
case sIOtype_EVENT:
|
||||
DEBUG_WEBSOCKETS("[wsIOc] get event (%d): %s\n", lData, data);
|
||||
break;
|
||||
case sIOtype_CONNECT:
|
||||
case sIOtype_DISCONNECT:
|
||||
case sIOtype_ACK:
|
||||
case sIOtype_ERROR:
|
||||
case sIOtype_BINARY_EVENT:
|
||||
case sIOtype_BINARY_ACK:
|
||||
default:
|
||||
DEBUG_WEBSOCKETS("[wsIOc] Socket.IO Message Type %c (%02X) is not implemented\n", ioType, ioType);
|
||||
DEBUG_WEBSOCKETS("[wsIOc] get text: %s\n", payload);
|
||||
break;
|
||||
}
|
||||
|
||||
runIOCbEvent(ioType, data, lData);
|
||||
} break;
|
||||
case eIOtype_OPEN:
|
||||
case eIOtype_CLOSE:
|
||||
case eIOtype_UPGRADE:
|
||||
case eIOtype_NOOP:
|
||||
default:
|
||||
DEBUG_WEBSOCKETS("[wsIOc] Engine.IO Message Type %c (%02X) is not implemented\n", eType, eType);
|
||||
DEBUG_WEBSOCKETS("[wsIOc] get text: %s\n", payload);
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
case WStype_ERROR:
|
||||
case WStype_BIN:
|
||||
case WStype_FRAGMENT_TEXT_START:
|
||||
case WStype_FRAGMENT_BIN_START:
|
||||
case WStype_FRAGMENT:
|
||||
case WStype_FRAGMENT_FIN:
|
||||
case WStype_PING:
|
||||
case WStype_PONG:
|
||||
break;
|
||||
}
|
||||
}
|
86
src/SocketIOclient.h
Normal file
86
src/SocketIOclient.h
Normal file
@ -0,0 +1,86 @@
|
||||
/**
|
||||
* SocketIOclient.h
|
||||
*
|
||||
* Created on: May 12, 2018
|
||||
* Author: links
|
||||
*/
|
||||
|
||||
#ifndef SOCKETIOCLIENT_H_
|
||||
#define SOCKETIOCLIENT_H_
|
||||
|
||||
#include "WebSockets.h"
|
||||
|
||||
#define EIO_HEARTBEAT_INTERVAL 20000
|
||||
|
||||
#define EIO_MAX_HEADER_SIZE (WEBSOCKETS_MAX_HEADER_SIZE + 1)
|
||||
#define SIO_MAX_HEADER_SIZE (EIO_MAX_HEADER_SIZE + 1)
|
||||
|
||||
typedef enum {
|
||||
eIOtype_OPEN = '0', ///< Sent from the server when a new transport is opened (recheck)
|
||||
eIOtype_CLOSE = '1', ///< Request the close of this transport but does not shutdown the connection itself.
|
||||
eIOtype_PING = '2', ///< Sent by the client. Server should answer with a pong packet containing the same data
|
||||
eIOtype_PONG = '3', ///< Sent by the server to respond to ping packets.
|
||||
eIOtype_MESSAGE = '4', ///< actual message, client and server should call their callbacks with the data
|
||||
eIOtype_UPGRADE = '5', ///< Before engine.io switches a transport, it tests, if server and client can communicate over this transport. If this test succeed, the client sends an upgrade packets which requests the server to flush its cache on the old transport and switch to the new transport.
|
||||
eIOtype_NOOP = '6', ///< A noop packet. Used primarily to force a poll cycle when an incoming websocket connection is received.
|
||||
} engineIOmessageType_t;
|
||||
|
||||
typedef enum {
|
||||
sIOtype_CONNECT = '0',
|
||||
sIOtype_DISCONNECT = '1',
|
||||
sIOtype_EVENT = '2',
|
||||
sIOtype_ACK = '3',
|
||||
sIOtype_ERROR = '4',
|
||||
sIOtype_BINARY_EVENT = '5',
|
||||
sIOtype_BINARY_ACK = '6',
|
||||
} socketIOmessageType_t;
|
||||
|
||||
class SocketIOclient : protected WebSocketsClient {
|
||||
public:
|
||||
#ifdef __AVR__
|
||||
typedef void (*SocketIOclientEvent)(socketIOmessageType_t type, uint8_t * payload, size_t length);
|
||||
#else
|
||||
typedef std::function<void(socketIOmessageType_t type, uint8_t * payload, size_t length)> SocketIOclientEvent;
|
||||
#endif
|
||||
|
||||
SocketIOclient(void);
|
||||
virtual ~SocketIOclient(void);
|
||||
|
||||
void begin(const char * host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * protocol = "arduino");
|
||||
void begin(String host, uint16_t port, String url = "/socket.io/?EIO=3", String protocol = "arduino");
|
||||
|
||||
bool isConnected(void);
|
||||
|
||||
void onEvent(SocketIOclientEvent cbEvent);
|
||||
|
||||
bool sendEVENT(uint8_t * payload, size_t length = 0, bool headerToPayload = false);
|
||||
bool sendEVENT(const uint8_t * payload, size_t length = 0);
|
||||
bool sendEVENT(char * payload, size_t length = 0, bool headerToPayload = false);
|
||||
bool sendEVENT(const char * payload, size_t length = 0);
|
||||
bool sendEVENT(String & payload);
|
||||
|
||||
bool send(socketIOmessageType_t type, uint8_t * payload, size_t length = 0, bool headerToPayload = false);
|
||||
bool send(socketIOmessageType_t type, const uint8_t * payload, size_t length = 0);
|
||||
bool send(socketIOmessageType_t type, char * payload, size_t length = 0, bool headerToPayload = false);
|
||||
bool send(socketIOmessageType_t type, const char * payload, size_t length = 0);
|
||||
bool send(socketIOmessageType_t type, String & payload);
|
||||
|
||||
void loop(void);
|
||||
|
||||
protected:
|
||||
uint64_t _lastHeartbeat = 0;
|
||||
SocketIOclientEvent _cbEvent;
|
||||
virtual void runIOCbEvent(socketIOmessageType_t type, uint8_t * payload, size_t length) {
|
||||
if(_cbEvent) {
|
||||
_cbEvent(type, payload, length);
|
||||
}
|
||||
}
|
||||
|
||||
// Handeling events from websocket layer
|
||||
virtual void runCbEvent(WStype_t type, uint8_t * payload, size_t length) {
|
||||
handleCbEvent(type, payload, length);
|
||||
}
|
||||
void handleCbEvent(WStype_t type, uint8_t * payload, size_t length);
|
||||
};
|
||||
|
||||
#endif /* SOCKETIOCLIENT_H_ */
|
@ -39,7 +39,14 @@ extern "C" {
|
||||
#ifdef ESP8266
|
||||
#include <Hash.h>
|
||||
#elif defined(ESP32)
|
||||
#include <esp_system.h>
|
||||
|
||||
#if ESP_IDF_VERSION_MAJOR >= 4
|
||||
#include <esp32/sha.h>
|
||||
#else
|
||||
#include <hwcrypto/sha.h>
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
extern "C" {
|
||||
@ -48,7 +55,6 @@ extern "C" {
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param client WSclient_t * ptr to the client struct
|
||||
@ -60,7 +66,7 @@ void WebSockets::clientDisconnect(WSclient_t * client, uint16_t code, char * rea
|
||||
DEBUG_WEBSOCKETS("[WS][%d][handleWebsocket] clientDisconnect code: %u\n", client->num, code);
|
||||
if(client->status == WSC_CONNECTED && code) {
|
||||
if(reason) {
|
||||
sendFrame(client, WSop_close, (uint8_t *) reason, reasonLen);
|
||||
sendFrame(client, WSop_close, (uint8_t *)reason, reasonLen);
|
||||
} else {
|
||||
uint8_t buffer[2];
|
||||
buffer[0] = ((code >> 8) & 0xFF);
|
||||
@ -73,43 +79,15 @@ void WebSockets::clientDisconnect(WSclient_t * client, uint16_t code, char * rea
|
||||
|
||||
/**
|
||||
*
|
||||
* @param client WSclient_t * ptr to the client struct
|
||||
* @param buf uint8_t * ptr to the buffer for writing
|
||||
* @param opcode WSopcode_t
|
||||
* @param payload uint8_t * ptr to the payload
|
||||
* @param length size_t length of the payload
|
||||
* @param mask bool add dummy mask to the frame (needed for web browser)
|
||||
* @param maskkey uint8_t[4] key used for payload
|
||||
* @param fin bool can be used to send data in more then one frame (set fin on the last frame)
|
||||
* @param headerToPayload bool set true if the payload has reserved 14 Byte at the beginning to dynamically add the Header (payload neet to be in RAM!)
|
||||
* @return true if ok
|
||||
*/
|
||||
bool WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool mask, bool fin, bool headerToPayload) {
|
||||
|
||||
if(client->tcp && !client->tcp->connected()) {
|
||||
DEBUG_WEBSOCKETS("[WS][%d][sendFrame] not Connected!?\n", client->num);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(client->status != WSC_CONNECTED) {
|
||||
DEBUG_WEBSOCKETS("[WS][%d][sendFrame] not in WSC_CONNECTED state!?\n", client->num);
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG_WEBSOCKETS("[WS][%d][sendFrame] ------- send message frame -------\n", client->num);
|
||||
DEBUG_WEBSOCKETS("[WS][%d][sendFrame] fin: %u opCode: %u mask: %u length: %u headerToPayload: %u\n", client->num, fin, opcode, mask, length, headerToPayload);
|
||||
|
||||
if(opcode == WSop_text) {
|
||||
DEBUG_WEBSOCKETS("[WS][%d][sendFrame] text: %s\n", client->num, (payload + (headerToPayload ? 14 : 0)));
|
||||
}
|
||||
|
||||
uint8_t maskKey[4] = { 0x00, 0x00, 0x00, 0x00 };
|
||||
uint8_t buffer[WEBSOCKETS_MAX_HEADER_SIZE] = { 0 };
|
||||
|
||||
uint8_t WebSockets::createHeader(uint8_t * headerPtr, WSopcode_t opcode, size_t length, bool mask, uint8_t maskKey[4], bool fin) {
|
||||
uint8_t headerSize;
|
||||
uint8_t * headerPtr;
|
||||
uint8_t * payloadPtr = payload;
|
||||
bool useInternBuffer = false;
|
||||
bool ret = true;
|
||||
|
||||
// calculate header Size
|
||||
if(length < 126) {
|
||||
headerSize = 2;
|
||||
@ -123,29 +101,6 @@ bool WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * pay
|
||||
headerSize += 4;
|
||||
}
|
||||
|
||||
#ifdef WEBSOCKETS_USE_BIG_MEM
|
||||
// only for ESP since AVR has less HEAP
|
||||
// try to send data in one TCP package (only if some free Heap is there)
|
||||
if(!headerToPayload && ((length > 0) && (length < 1400)) && (GET_FREE_HEAP > 6000)) {
|
||||
DEBUG_WEBSOCKETS("[WS][%d][sendFrame] pack to one TCP package...\n", client->num);
|
||||
uint8_t * dataPtr = (uint8_t *) malloc(length + WEBSOCKETS_MAX_HEADER_SIZE);
|
||||
if(dataPtr) {
|
||||
memcpy((dataPtr + WEBSOCKETS_MAX_HEADER_SIZE), payload, length);
|
||||
headerToPayload = true;
|
||||
useInternBuffer = true;
|
||||
payloadPtr = dataPtr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// set Header Pointer
|
||||
if(headerToPayload) {
|
||||
// calculate offset in payload
|
||||
headerPtr = (payloadPtr + (WEBSOCKETS_MAX_HEADER_SIZE - headerSize));
|
||||
} else {
|
||||
headerPtr = &buffer[0];
|
||||
}
|
||||
|
||||
// create header
|
||||
|
||||
// byte 0
|
||||
@ -195,15 +150,123 @@ bool WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * pay
|
||||
}
|
||||
|
||||
if(mask) {
|
||||
if(useInternBuffer) {
|
||||
*headerPtr = maskKey[0];
|
||||
headerPtr++;
|
||||
*headerPtr = maskKey[1];
|
||||
headerPtr++;
|
||||
*headerPtr = maskKey[2];
|
||||
headerPtr++;
|
||||
*headerPtr = maskKey[3];
|
||||
headerPtr++;
|
||||
}
|
||||
return headerSize;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param client WSclient_t * ptr to the client struct
|
||||
* @param opcode WSopcode_t
|
||||
* @param length size_t length of the payload
|
||||
* @param fin bool can be used to send data in more then one frame (set fin on the last frame)
|
||||
* @return true if ok
|
||||
*/
|
||||
bool WebSockets::sendFrameHeader(WSclient_t * client, WSopcode_t opcode, size_t length, bool fin) {
|
||||
uint8_t maskKey[4] = { 0x00, 0x00, 0x00, 0x00 };
|
||||
uint8_t buffer[WEBSOCKETS_MAX_HEADER_SIZE] = { 0 };
|
||||
|
||||
uint8_t headerSize = createHeader(&buffer[0], opcode, length, client->cIsClient, maskKey, fin);
|
||||
|
||||
if(write(client, &buffer[0], headerSize) != headerSize) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param client WSclient_t * ptr to the client struct
|
||||
* @param opcode WSopcode_t
|
||||
* @param payload uint8_t * ptr to the payload
|
||||
* @param length size_t length of the payload
|
||||
* @param fin bool can be used to send data in more then one frame (set fin on the last frame)
|
||||
* @param headerToPayload bool set true if the payload has reserved 14 Byte at the beginning to dynamically add the Header (payload neet to be in RAM!)
|
||||
* @return true if ok
|
||||
*/
|
||||
bool WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin, bool headerToPayload) {
|
||||
if(client->tcp && !client->tcp->connected()) {
|
||||
DEBUG_WEBSOCKETS("[WS][%d][sendFrame] not Connected!?\n", client->num);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(client->status != WSC_CONNECTED) {
|
||||
DEBUG_WEBSOCKETS("[WS][%d][sendFrame] not in WSC_CONNECTED state!?\n", client->num);
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG_WEBSOCKETS("[WS][%d][sendFrame] ------- send message frame -------\n", client->num);
|
||||
DEBUG_WEBSOCKETS("[WS][%d][sendFrame] fin: %u opCode: %u mask: %u length: %u headerToPayload: %u\n", client->num, fin, opcode, client->cIsClient, length, headerToPayload);
|
||||
|
||||
if(opcode == WSop_text) {
|
||||
DEBUG_WEBSOCKETS("[WS][%d][sendFrame] text: %s\n", client->num, (payload + (headerToPayload ? 14 : 0)));
|
||||
}
|
||||
|
||||
uint8_t maskKey[4] = { 0x00, 0x00, 0x00, 0x00 };
|
||||
uint8_t buffer[WEBSOCKETS_MAX_HEADER_SIZE] = { 0 };
|
||||
|
||||
uint8_t headerSize;
|
||||
uint8_t * headerPtr;
|
||||
uint8_t * payloadPtr = payload;
|
||||
bool useInternBuffer = false;
|
||||
bool ret = true;
|
||||
|
||||
// calculate header Size
|
||||
if(length < 126) {
|
||||
headerSize = 2;
|
||||
} else if(length < 0xFFFF) {
|
||||
headerSize = 4;
|
||||
} else {
|
||||
headerSize = 10;
|
||||
}
|
||||
|
||||
if(client->cIsClient) {
|
||||
headerSize += 4;
|
||||
}
|
||||
|
||||
#ifdef WEBSOCKETS_USE_BIG_MEM
|
||||
// only for ESP since AVR has less HEAP
|
||||
// try to send data in one TCP package (only if some free Heap is there)
|
||||
if(!headerToPayload && ((length > 0) && (length < 1400)) && (GET_FREE_HEAP > 6000)) {
|
||||
DEBUG_WEBSOCKETS("[WS][%d][sendFrame] pack to one TCP package...\n", client->num);
|
||||
uint8_t * dataPtr = (uint8_t *)malloc(length + WEBSOCKETS_MAX_HEADER_SIZE);
|
||||
if(dataPtr) {
|
||||
memcpy((dataPtr + WEBSOCKETS_MAX_HEADER_SIZE), payload, length);
|
||||
headerToPayload = true;
|
||||
useInternBuffer = true;
|
||||
payloadPtr = dataPtr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// set Header Pointer
|
||||
if(headerToPayload) {
|
||||
// calculate offset in payload
|
||||
headerPtr = (payloadPtr + (WEBSOCKETS_MAX_HEADER_SIZE - headerSize));
|
||||
} else {
|
||||
headerPtr = &buffer[0];
|
||||
}
|
||||
|
||||
if(client->cIsClient && useInternBuffer) {
|
||||
// if we use a Intern Buffer we can modify the data
|
||||
// by this fact its possible the do the masking
|
||||
for(uint8_t x = 0; x < sizeof(maskKey); x++) {
|
||||
maskKey[x] = random(0xFF);
|
||||
*headerPtr = maskKey[x];
|
||||
headerPtr++;
|
||||
}
|
||||
}
|
||||
|
||||
createHeader(headerPtr, opcode, length, client->cIsClient, maskKey, fin);
|
||||
|
||||
if(client->cIsClient && useInternBuffer) {
|
||||
uint8_t * dataMaskPtr;
|
||||
|
||||
if(headerToPayload) {
|
||||
@ -215,17 +278,6 @@ bool WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * pay
|
||||
for(size_t x = 0; x < length; x++) {
|
||||
dataMaskPtr[x] = (dataMaskPtr[x] ^ maskKey[x % 4]);
|
||||
}
|
||||
|
||||
} else {
|
||||
*headerPtr = maskKey[0];
|
||||
headerPtr++;
|
||||
*headerPtr = maskKey[1];
|
||||
headerPtr++;
|
||||
*headerPtr = maskKey[2];
|
||||
headerPtr++;
|
||||
*headerPtr = maskKey[3];
|
||||
headerPtr++;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NODEBUG_WEBSOCKETS
|
||||
@ -272,7 +324,7 @@ void WebSockets::headerDone(WSclient_t * client) {
|
||||
client->status = WSC_CONNECTED;
|
||||
client->cWsRXsize = 0;
|
||||
DEBUG_WEBSOCKETS("[WS][%d][headerDone] Header Handling Done.\n", client->num);
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
client->cHttpLine = "";
|
||||
handleWebsocket(client);
|
||||
#endif
|
||||
@ -319,12 +371,12 @@ bool WebSockets::handleWebsocketWaitFor(WSclient_t * client, size_t size) {
|
||||
// timeout or error
|
||||
server->clientDisconnect(client, 1002);
|
||||
}
|
||||
}, this, size, std::placeholders::_1, std::placeholders::_2));
|
||||
},
|
||||
this, size, std::placeholders::_1, std::placeholders::_2));
|
||||
return false;
|
||||
}
|
||||
|
||||
void WebSockets::handleWebsocketCb(WSclient_t * client) {
|
||||
|
||||
if(!client->tcp || !client->tcp->connected()) {
|
||||
return;
|
||||
}
|
||||
@ -345,11 +397,11 @@ void WebSockets::handleWebsocketCb(WSclient_t * client) {
|
||||
header->rsv1 = ((*buffer >> 6) & 0x01);
|
||||
header->rsv2 = ((*buffer >> 5) & 0x01);
|
||||
header->rsv3 = ((*buffer >> 4) & 0x01);
|
||||
header->opCode = (WSopcode_t) (*buffer & 0x0F);
|
||||
header->opCode = (WSopcode_t)(*buffer & 0x0F);
|
||||
buffer++;
|
||||
|
||||
header->mask = ((*buffer >> 7) & 0x01);
|
||||
header->payloadLen = (WSopcode_t) (*buffer & 0x7F);
|
||||
header->payloadLen = (WSopcode_t)(*buffer & 0x7F);
|
||||
buffer++;
|
||||
|
||||
if(header->payloadLen == 126) {
|
||||
@ -396,7 +448,7 @@ void WebSockets::handleWebsocketCb(WSclient_t * client) {
|
||||
|
||||
if(header->payloadLen > 0) {
|
||||
// if text data we need one more
|
||||
payload = (uint8_t *) malloc(header->payloadLen + 1);
|
||||
payload = (uint8_t *)malloc(header->payloadLen + 1);
|
||||
|
||||
if(!payload) {
|
||||
DEBUG_WEBSOCKETS("[WS][%d][handleWebsocket] to less memory to handle payload %d!\n", client->num, header->payloadLen);
|
||||
@ -410,7 +462,6 @@ void WebSockets::handleWebsocketCb(WSclient_t * client) {
|
||||
}
|
||||
|
||||
void WebSockets::handleWebsocketPayloadCb(WSclient_t * client, bool ok, uint8_t * payload) {
|
||||
|
||||
WSMessageHeader_t * header = &client->cWsHeaderDecode;
|
||||
if(ok) {
|
||||
if(header->payloadLen > 0) {
|
||||
@ -434,28 +485,32 @@ void WebSockets::handleWebsocketPayloadCb(WSclient_t * client, bool ok, uint8_t
|
||||
break;
|
||||
case WSop_ping:
|
||||
// send pong back
|
||||
sendFrame(client, WSop_pong, payload, header->payloadLen, true);
|
||||
DEBUG_WEBSOCKETS("[WS][%d][handleWebsocket] ping received (%s)\n", client->num, payload ? (const char *)payload : "");
|
||||
sendFrame(client, WSop_pong, payload, header->payloadLen);
|
||||
messageReceived(client, header->opCode, payload, header->payloadLen, header->fin);
|
||||
break;
|
||||
case WSop_pong:
|
||||
DEBUG_WEBSOCKETS("[WS][%d][handleWebsocket] get pong (%s)\n", client->num, payload ? (const char*)payload : "");
|
||||
DEBUG_WEBSOCKETS("[WS][%d][handleWebsocket] get pong (%s)\n", client->num, payload ? (const char *)payload : "");
|
||||
client->pongReceived = true;
|
||||
messageReceived(client, header->opCode, payload, header->payloadLen, header->fin);
|
||||
break;
|
||||
case WSop_close: {
|
||||
#ifndef NODEBUG_WEBSOCKETS
|
||||
#ifndef NODEBUG_WEBSOCKETS
|
||||
uint16_t reasonCode = 1000;
|
||||
if(header->payloadLen >= 2) {
|
||||
reasonCode = payload[0] << 8 | payload[1];
|
||||
}
|
||||
#endif
|
||||
DEBUG_WEBSOCKETS("[WS][%d][handleWebsocket] get ask for close. Code: %d", client->num, reasonCode);
|
||||
#endif
|
||||
DEBUG_WEBSOCKETS("[WS][%d][handleWebsocket] get ask for close. Code: %d\n", client->num, reasonCode);
|
||||
if(header->payloadLen > 2) {
|
||||
DEBUG_WEBSOCKETS(" (%s)\n", (payload + 2));
|
||||
} else {
|
||||
DEBUG_WEBSOCKETS("\n");
|
||||
}
|
||||
clientDisconnect(client, 1000);
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
default:
|
||||
DEBUG_WEBSOCKETS("[WS][%d][handleWebsocket] got unknown opcode: %d\n", client->num, header->opCode);
|
||||
clientDisconnect(client, 1002);
|
||||
break;
|
||||
}
|
||||
@ -466,7 +521,7 @@ void WebSockets::handleWebsocketPayloadCb(WSclient_t * client, bool ok, uint8_t
|
||||
|
||||
// reset input
|
||||
client->cWsRXsize = 0;
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
//register callback for next message
|
||||
handleWebsocketWaitFor(client, 2);
|
||||
#endif
|
||||
@ -489,12 +544,12 @@ String WebSockets::acceptKey(String & clientKey) {
|
||||
sha1(clientKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", &sha1HashBin[0]);
|
||||
#elif defined(ESP32)
|
||||
String data = clientKey + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
|
||||
esp_sha(SHA1, (unsigned char*)data.c_str(), data.length(), &sha1HashBin[0]);
|
||||
esp_sha(SHA1, (unsigned char *)data.c_str(), data.length(), &sha1HashBin[0]);
|
||||
#else
|
||||
clientKey += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
|
||||
SHA1_CTX ctx;
|
||||
SHA1Init(&ctx);
|
||||
SHA1Update(&ctx, (const unsigned char*)clientKey.c_str(), clientKey.length());
|
||||
SHA1Update(&ctx, (const unsigned char *)clientKey.c_str(), clientKey.length());
|
||||
SHA1Final(&sha1HashBin[0], &ctx);
|
||||
#endif
|
||||
|
||||
@ -512,11 +567,11 @@ String WebSockets::acceptKey(String & clientKey) {
|
||||
*/
|
||||
String WebSockets::base64_encode(uint8_t * data, size_t length) {
|
||||
size_t size = ((length * 1.6f) + 1);
|
||||
char * buffer = (char *) malloc(size);
|
||||
char * buffer = (char *)malloc(size);
|
||||
if(buffer) {
|
||||
base64_encodestate _state;
|
||||
base64_init_encodestate(&_state);
|
||||
int len = base64_encode_block((const char *) &data[0], length, &buffer[0], &_state);
|
||||
int len = base64_encode_block((const char *)&data[0], length, &buffer[0], &_state);
|
||||
len = base64_encode_blockend((buffer + len), &_state);
|
||||
|
||||
String base64 = String(buffer);
|
||||
@ -534,7 +589,7 @@ String WebSockets::base64_encode(uint8_t * data, size_t length) {
|
||||
* @return true if ok
|
||||
*/
|
||||
bool WebSockets::readCb(WSclient_t * client, uint8_t * out, size_t n, WSreadWaitCb cb) {
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
if(!client->tcp || !client->tcp->connected()) {
|
||||
return false;
|
||||
}
|
||||
@ -543,11 +598,12 @@ bool WebSockets::readCb(WSclient_t * client, uint8_t * out, size_t n, WSreadWait
|
||||
if(cb) {
|
||||
cb(client, ok);
|
||||
}
|
||||
}, client, std::placeholders::_1, cb));
|
||||
},
|
||||
client, std::placeholders::_1, cb));
|
||||
|
||||
#else
|
||||
unsigned long t = millis();
|
||||
size_t len;
|
||||
ssize_t len;
|
||||
DEBUG_WEBSOCKETS("[readCb] n: %zu t: %lu\n", n, t);
|
||||
while(n > 0) {
|
||||
if(client->tcp == NULL) {
|
||||
@ -575,14 +631,12 @@ bool WebSockets::readCb(WSclient_t * client, uint8_t * out, size_t n, WSreadWait
|
||||
}
|
||||
|
||||
if(!client->tcp->available()) {
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
|
||||
delay(0);
|
||||
#endif
|
||||
WEBSOCKETS_YIELD_MORE();
|
||||
continue;
|
||||
}
|
||||
|
||||
len = client->tcp->read((uint8_t*) out, n);
|
||||
if(len) {
|
||||
len = client->tcp->read((uint8_t *)out, n);
|
||||
if(len > 0) {
|
||||
t = millis();
|
||||
out += len;
|
||||
n -= len;
|
||||
@ -590,13 +644,14 @@ bool WebSockets::readCb(WSclient_t * client, uint8_t * out, size_t n, WSreadWait
|
||||
} else {
|
||||
//DEBUG_WEBSOCKETS("Receive %d left %d!\n", len, n);
|
||||
}
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
|
||||
delay(0);
|
||||
#endif
|
||||
if (n > 0) {
|
||||
WEBSOCKETS_YIELD();
|
||||
}
|
||||
}
|
||||
if(cb) {
|
||||
cb(client, true);
|
||||
}
|
||||
WEBSOCKETS_YIELD();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
@ -608,9 +663,11 @@ bool WebSockets::readCb(WSclient_t * client, uint8_t * out, size_t n, WSreadWait
|
||||
* @param n size_t byte count
|
||||
* @return bytes send
|
||||
*/
|
||||
size_t WebSockets::write(WSclient_t * client, uint8_t *out, size_t n) {
|
||||
if(out == NULL) return 0;
|
||||
if(client == NULL) return 0;
|
||||
size_t WebSockets::write(WSclient_t * client, uint8_t * out, size_t n) {
|
||||
if(out == NULL)
|
||||
return 0;
|
||||
if(client == NULL)
|
||||
return 0;
|
||||
unsigned long t = millis();
|
||||
size_t len = 0;
|
||||
size_t total = 0;
|
||||
@ -631,7 +688,7 @@ size_t WebSockets::write(WSclient_t * client, uint8_t *out, size_t n) {
|
||||
break;
|
||||
}
|
||||
|
||||
len = client->tcp->write((const uint8_t*)out, n);
|
||||
len = client->tcp->write((const uint8_t *)out, n);
|
||||
if(len) {
|
||||
t = millis();
|
||||
out += len;
|
||||
@ -639,17 +696,62 @@ size_t WebSockets::write(WSclient_t * client, uint8_t *out, size_t n) {
|
||||
total += len;
|
||||
//DEBUG_WEBSOCKETS("write %d left %d!\n", len, n);
|
||||
} else {
|
||||
//DEBUG_WEBSOCKETS("write %d failed left %d!\n", len, n);
|
||||
DEBUG_WEBSOCKETS("WS write %d failed left %d!\n", len, n);
|
||||
}
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
|
||||
delay(0);
|
||||
#endif
|
||||
if (n > 0) {
|
||||
WEBSOCKETS_YIELD();
|
||||
}
|
||||
}
|
||||
WEBSOCKETS_YIELD();
|
||||
return total;
|
||||
}
|
||||
|
||||
size_t WebSockets::write(WSclient_t * client, const char *out) {
|
||||
if(client == NULL) return 0;
|
||||
if(out == NULL) return 0;
|
||||
return write(client, (uint8_t*)out, strlen(out));
|
||||
size_t WebSockets::write(WSclient_t * client, const char * out) {
|
||||
if(client == NULL)
|
||||
return 0;
|
||||
if(out == NULL)
|
||||
return 0;
|
||||
return write(client, (uint8_t *)out, strlen(out));
|
||||
}
|
||||
|
||||
/**
|
||||
* enable ping/pong heartbeat process
|
||||
* @param client WSclient_t *
|
||||
* @param pingInterval uint32_t how often ping will be sent
|
||||
* @param pongTimeout uint32_t millis after which pong should timout if not received
|
||||
* @param disconnectTimeoutCount uint8_t how many timeouts before disconnect, 0=> do not disconnect
|
||||
*/
|
||||
void WebSockets::enableHeartbeat(WSclient_t * client, uint32_t pingInterval, uint32_t pongTimeout, uint8_t disconnectTimeoutCount) {
|
||||
if(client == NULL)
|
||||
return;
|
||||
client->pingInterval = pingInterval;
|
||||
client->pongTimeout = pongTimeout;
|
||||
client->disconnectTimeoutCount = disconnectTimeoutCount;
|
||||
client->pongReceived = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* handle ping/pong heartbeat timeout process
|
||||
* @param client WSclient_t *
|
||||
*/
|
||||
void WebSockets::handleHBTimeout(WSclient_t * client) {
|
||||
if(client->pingInterval) { // if heartbeat is enabled
|
||||
uint32_t pi = millis() - client->lastPing;
|
||||
|
||||
if(client->pongReceived) {
|
||||
client->pongTimeoutCount = 0;
|
||||
} else {
|
||||
if(pi > client->pongTimeout) { // pong not received in time
|
||||
client->pongTimeoutCount++;
|
||||
client->lastPing = millis() - client->pingInterval - 500; // force ping on the next run
|
||||
|
||||
DEBUG_WEBSOCKETS("[HBtimeout] pong TIMEOUT! lp=%d millis=%d pi=%d count=%d\n", client->lastPing, millis(), pi, client->pongTimeoutCount);
|
||||
|
||||
if(client->disconnectTimeoutCount && client->pongTimeoutCount >= client->disconnectTimeoutCount) {
|
||||
DEBUG_WEBSOCKETS("[HBtimeout] count=%d, DISCONNECTING\n", client->pongTimeoutCount);
|
||||
clientDisconnect(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -40,52 +40,62 @@
|
||||
#include <functional>
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef NODEBUG_WEBSOCKETS
|
||||
#ifdef DEBUG_ESP_PORT
|
||||
#define DEBUG_WEBSOCKETS(...) DEBUG_ESP_PORT.printf( __VA_ARGS__ )
|
||||
#define DEBUG_WEBSOCKETS(...) DEBUG_ESP_PORT.printf(__VA_ARGS__)
|
||||
#else
|
||||
//#define DEBUG_WEBSOCKETS(...) os_printf( __VA_ARGS__ )
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef DEBUG_WEBSOCKETS
|
||||
#define DEBUG_WEBSOCKETS(...)
|
||||
#ifndef NODEBUG_WEBSOCKETS
|
||||
#define NODEBUG_WEBSOCKETS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
|
||||
#define WEBSOCKETS_MAX_DATA_SIZE (15*1024)
|
||||
#define WEBSOCKETS_MAX_DATA_SIZE (15 * 1024)
|
||||
#define WEBSOCKETS_USE_BIG_MEM
|
||||
#define GET_FREE_HEAP ESP.getFreeHeap()
|
||||
// moves all Header strings to Flash (~300 Byte)
|
||||
//#define WEBSOCKETS_SAVE_RAM
|
||||
|
||||
#if defined(ESP8266)
|
||||
#define WEBSOCKETS_YIELD() delay(0)
|
||||
#define WEBSOCKETS_YIELD_MORE() delay(1)
|
||||
#elif defined(ESP32)
|
||||
#define WEBSOCKETS_YIELD() yield()
|
||||
#define WEBSOCKETS_YIELD_MORE() delay(1)
|
||||
#endif
|
||||
|
||||
#elif defined(STM32_DEVICE)
|
||||
|
||||
#define WEBSOCKETS_MAX_DATA_SIZE (15*1024)
|
||||
#define WEBSOCKETS_MAX_DATA_SIZE (15 * 1024)
|
||||
#define WEBSOCKETS_USE_BIG_MEM
|
||||
#define GET_FREE_HEAP System.freeMemory()
|
||||
|
||||
#define WEBSOCKETS_YIELD()
|
||||
#define WEBSOCKETS_YIELD_MORE()
|
||||
#else
|
||||
|
||||
//atmega328p has only 2KB ram!
|
||||
#define WEBSOCKETS_MAX_DATA_SIZE (1024)
|
||||
// moves all Header strings to Flash
|
||||
#define WEBSOCKETS_SAVE_RAM
|
||||
|
||||
#define WEBSOCKETS_YIELD()
|
||||
#define WEBSOCKETS_YIELD_MORE()
|
||||
#endif
|
||||
|
||||
|
||||
#define WEBSOCKETS_TCP_TIMEOUT (2000)
|
||||
#define WEBSOCKETS_TCP_TIMEOUT (5000)
|
||||
|
||||
#define NETWORK_ESP8266_ASYNC (0)
|
||||
#define NETWORK_ESP8266 (1)
|
||||
#define NETWORK_W5100 (2)
|
||||
#define NETWORK_ENC28J60 (3)
|
||||
#define NETWORK_ESP32 (4)
|
||||
#define NETWORK_ESP32_ETH (5)
|
||||
|
||||
// max size of the WS Message Header
|
||||
#define WEBSOCKETS_MAX_HEADER_SIZE (14)
|
||||
@ -99,7 +109,7 @@
|
||||
|
||||
#elif defined(ESP32)
|
||||
#define WEBSOCKETS_NETWORK_TYPE NETWORK_ESP32
|
||||
|
||||
//#define WEBSOCKETS_NETWORK_TYPE NETWORK_ESP32_ETH
|
||||
#else
|
||||
#define WEBSOCKETS_NETWORK_TYPE NETWORK_W5100
|
||||
|
||||
@ -107,18 +117,18 @@
|
||||
#endif
|
||||
|
||||
// Includes and defined based on Network Type
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
|
||||
// Note:
|
||||
// No SSL/WSS support for client in Async mode
|
||||
// TLS lib need a sync interface!
|
||||
|
||||
|
||||
#if defined(ESP8266)
|
||||
#include <ESP8266WiFi.h>
|
||||
#elif defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#include <WiFiClientSecure.h>
|
||||
#define SSL_AXTLS
|
||||
#elif defined(ESP31B)
|
||||
#include <ESP31BWiFi.h>
|
||||
#else
|
||||
@ -130,7 +140,7 @@
|
||||
#define WEBSOCKETS_NETWORK_CLASS AsyncTCPbuffer
|
||||
#define WEBSOCKETS_NETWORK_SERVER_CLASS AsyncServer
|
||||
|
||||
#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
|
||||
#elif(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
|
||||
|
||||
#if !defined(ESP8266) && !defined(ESP31B)
|
||||
#error "network type ESP8266 only possible on the ESP mcu!"
|
||||
@ -138,13 +148,19 @@
|
||||
|
||||
#ifdef ESP8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#if defined(wificlientbearssl_h) && !defined(USING_AXTLS) && !defined(wificlientsecure_h)
|
||||
#define SSL_BARESSL
|
||||
#else
|
||||
#define SSL_AXTLS
|
||||
#endif
|
||||
#else
|
||||
#include <ESP31BWiFi.h>
|
||||
#endif
|
||||
#define WEBSOCKETS_NETWORK_CLASS WiFiClient
|
||||
#define WEBSOCKETS_NETWORK_SSL_CLASS WiFiClientSecure
|
||||
#define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer
|
||||
|
||||
#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_W5100)
|
||||
#elif(WEBSOCKETS_NETWORK_TYPE == NETWORK_W5100)
|
||||
|
||||
#ifdef STM32_DEVICE
|
||||
#define WEBSOCKETS_NETWORK_CLASS TCPClient
|
||||
@ -156,16 +172,24 @@
|
||||
#define WEBSOCKETS_NETWORK_SERVER_CLASS EthernetServer
|
||||
#endif
|
||||
|
||||
#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_ENC28J60)
|
||||
#elif(WEBSOCKETS_NETWORK_TYPE == NETWORK_ENC28J60)
|
||||
|
||||
#include <UIPEthernet.h>
|
||||
#define WEBSOCKETS_NETWORK_CLASS UIPClient
|
||||
#define WEBSOCKETS_NETWORK_SERVER_CLASS UIPServer
|
||||
|
||||
#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
#elif(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
|
||||
#include <WiFi.h>
|
||||
#include <WiFiClientSecure.h>
|
||||
#define SSL_AXTLS
|
||||
#define WEBSOCKETS_NETWORK_CLASS WiFiClient
|
||||
#define WEBSOCKETS_NETWORK_SSL_CLASS WiFiClientSecure
|
||||
#define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer
|
||||
|
||||
#elif(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32_ETH)
|
||||
|
||||
#include <ETH.h>
|
||||
#define WEBSOCKETS_NETWORK_CLASS WiFiClient
|
||||
#define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer
|
||||
|
||||
@ -173,6 +197,10 @@
|
||||
#error "no network type selected!"
|
||||
#endif
|
||||
|
||||
#ifdef WEBSOCKETS_NETWORK_SSL_CLASS
|
||||
#define HAS_SSL
|
||||
#endif
|
||||
|
||||
// moves all Header strings to Flash (~300 Byte)
|
||||
#ifdef WEBSOCKETS_SAVE_RAM
|
||||
#define WEBSOCKETS_STRING(var) F(var)
|
||||
@ -196,6 +224,8 @@ typedef enum {
|
||||
WStype_FRAGMENT_BIN_START,
|
||||
WStype_FRAGMENT,
|
||||
WStype_FRAGMENT_FIN,
|
||||
WStype_PING,
|
||||
WStype_PONG,
|
||||
} WStype_t;
|
||||
|
||||
typedef enum {
|
||||
@ -210,7 +240,6 @@ typedef enum {
|
||||
} WSopcode_t;
|
||||
|
||||
typedef struct {
|
||||
|
||||
bool fin;
|
||||
bool rsv1;
|
||||
bool rsv2;
|
||||
@ -233,14 +262,15 @@ typedef struct {
|
||||
|
||||
bool isSocketIO; ///< client for socket.io server
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
#if defined(HAS_SSL)
|
||||
bool isSSL; ///< run in ssl mode
|
||||
WiFiClientSecure * ssl;
|
||||
WEBSOCKETS_NETWORK_SSL_CLASS * ssl;
|
||||
#endif
|
||||
|
||||
String cUrl; ///< http url
|
||||
uint16_t cCode; ///< http code
|
||||
|
||||
bool cIsClient = false; ///< will be used for masking
|
||||
bool cIsUpgrade; ///< Connection == Upgrade
|
||||
bool cIsWebsocket; ///< Upgrade == websocket
|
||||
|
||||
@ -263,14 +293,19 @@ typedef struct {
|
||||
bool cHttpHeadersValid; ///< non-websocket http header validity indicator
|
||||
size_t cMandatoryHeadersCount; ///< non-websocket mandatory http headers present count
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
bool pongReceived;
|
||||
uint32_t pingInterval; // how often ping will be sent, 0 means "heartbeat is not active"
|
||||
uint32_t lastPing; // millis when last pong has been received
|
||||
uint32_t pongTimeout; // interval in millis after which pong is considered to timeout
|
||||
uint8_t disconnectTimeoutCount; // after how many subsequent pong timeouts discconnect will happen, 0 means "do not disconnect"
|
||||
uint8_t pongTimeoutCount; // current pong timeout count
|
||||
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
String cHttpLine; ///< HTTP header lines
|
||||
#endif
|
||||
|
||||
} WSclient_t;
|
||||
|
||||
|
||||
|
||||
class WebSockets {
|
||||
protected:
|
||||
#ifdef __AVR__
|
||||
@ -282,10 +317,13 @@ class WebSockets {
|
||||
virtual void clientDisconnect(WSclient_t * client) = 0;
|
||||
virtual bool clientIsConnected(WSclient_t * client) = 0;
|
||||
|
||||
void clientDisconnect(WSclient_t * client, uint16_t code, char * reason = NULL, size_t reasonLen = 0);
|
||||
|
||||
virtual void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin) = 0;
|
||||
|
||||
void clientDisconnect(WSclient_t * client, uint16_t code, char * reason = NULL, size_t reasonLen = 0);
|
||||
bool sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * payload = NULL, size_t length = 0, bool mask = false, bool fin = true, bool headerToPayload = false);
|
||||
uint8_t createHeader(uint8_t * buf, WSopcode_t opcode, size_t length, bool mask, uint8_t maskKey[4], bool fin);
|
||||
bool sendFrameHeader(WSclient_t * client, WSopcode_t opcode, size_t length = 0, bool fin = true);
|
||||
bool sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * payload = NULL, size_t length = 0, bool fin = true, bool headerToPayload = false);
|
||||
|
||||
void headerDone(WSclient_t * client);
|
||||
|
||||
@ -298,11 +336,12 @@ class WebSockets {
|
||||
String acceptKey(String & clientKey);
|
||||
String base64_encode(uint8_t * data, size_t length);
|
||||
|
||||
bool readCb(WSclient_t * client, uint8_t *out, size_t n, WSreadWaitCb cb);
|
||||
virtual size_t write(WSclient_t * client, uint8_t *out, size_t n);
|
||||
size_t write(WSclient_t * client, const char *out);
|
||||
|
||||
bool readCb(WSclient_t * client, uint8_t * out, size_t n, WSreadWaitCb cb);
|
||||
virtual size_t write(WSclient_t * client, uint8_t * out, size_t n);
|
||||
size_t write(WSclient_t * client, const char * out);
|
||||
|
||||
void enableHeartbeat(WSclient_t * client, uint32_t pingInterval, uint32_t pongTimeout, uint8_t disconnectTimeoutCount);
|
||||
void handleHBTimeout(WSclient_t * client);
|
||||
};
|
||||
|
||||
#ifndef UNUSED
|
||||
|
@ -28,7 +28,11 @@
|
||||
WebSocketsClient::WebSocketsClient() {
|
||||
_cbEvent = NULL;
|
||||
_client.num = 0;
|
||||
_client.cIsClient = true;
|
||||
_client.extraHeaders = WEBSOCKETS_STRING("Origin: file://");
|
||||
_reconnectInterval = 500;
|
||||
_port = 0;
|
||||
_host = "";
|
||||
}
|
||||
|
||||
WebSocketsClient::~WebSocketsClient() {
|
||||
@ -38,17 +42,18 @@ WebSocketsClient::~WebSocketsClient() {
|
||||
/**
|
||||
* calles to init the Websockets server
|
||||
*/
|
||||
void WebSocketsClient::begin(const char *host, uint16_t port, const char * url, const char * protocol) {
|
||||
void WebSocketsClient::begin(const char * host, uint16_t port, const char * url, const char * protocol) {
|
||||
_host = host;
|
||||
_port = port;
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
_fingerprint = "";
|
||||
#if defined(HAS_SSL)
|
||||
_fingerprint = SSL_FINGERPRINT_NULL;
|
||||
_CA_cert = NULL;
|
||||
#endif
|
||||
|
||||
_client.num = 0;
|
||||
_client.status = WSC_NOT_CONNECTED;
|
||||
_client.tcp = NULL;
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
#if defined(HAS_SSL)
|
||||
_client.isSSL = false;
|
||||
_client.ssl = NULL;
|
||||
#endif
|
||||
@ -65,18 +70,22 @@ void WebSocketsClient::begin(const char *host, uint16_t port, const char * url,
|
||||
_client.plainAuthorization = "";
|
||||
_client.isSocketIO = false;
|
||||
|
||||
_client.lastPing = 0;
|
||||
_client.pongReceived = false;
|
||||
_client.pongTimeoutCount = 0;
|
||||
|
||||
#ifdef ESP8266
|
||||
randomSeed(RANDOM_REG32);
|
||||
#else
|
||||
// todo find better seed
|
||||
randomSeed(millis());
|
||||
#endif
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
asyncConnect();
|
||||
#endif
|
||||
|
||||
_lastConnectionFail = 0;
|
||||
_reconnectInterval = 500;
|
||||
_lastHeaderSent = 0;
|
||||
}
|
||||
|
||||
void WebSocketsClient::begin(String host, uint16_t port, String url, String protocol) {
|
||||
@ -87,19 +96,49 @@ void WebSocketsClient::begin(IPAddress host, uint16_t port, const char * url, co
|
||||
return begin(host.toString().c_str(), port, url, protocol);
|
||||
}
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
void WebSocketsClient::beginSSL(const char *host, uint16_t port, const char * url, const char * fingerprint, const char * protocol) {
|
||||
#if defined(HAS_SSL)
|
||||
#if defined(SSL_AXTLS)
|
||||
void WebSocketsClient::beginSSL(const char * host, uint16_t port, const char * url, const char * fingerprint, const char * protocol) {
|
||||
begin(host, port, url, protocol);
|
||||
_client.isSSL = true;
|
||||
_fingerprint = fingerprint;
|
||||
_CA_cert = NULL;
|
||||
}
|
||||
|
||||
void WebSocketsClient::beginSSL(String host, uint16_t port, String url, String fingerprint, String protocol) {
|
||||
beginSSL(host.c_str(), port, url.c_str(), fingerprint.c_str(), protocol.c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
void WebSocketsClient::beginSocketIO(const char *host, uint16_t port, const char * url, const char * protocol) {
|
||||
void WebSocketsClient::beginSslWithCA(const char * host, uint16_t port, const char * url, const char * CA_cert, const char * protocol) {
|
||||
begin(host, port, url, protocol);
|
||||
_client.isSSL = true;
|
||||
_fingerprint = SSL_FINGERPRINT_NULL;
|
||||
_CA_cert = CA_cert;
|
||||
}
|
||||
#else
|
||||
void WebSocketsClient::beginSSL(const char * host, uint16_t port, const char * url, const uint8_t * fingerprint, const char * protocol) {
|
||||
begin(host, port, url, protocol);
|
||||
_client.isSSL = true;
|
||||
_fingerprint = fingerprint;
|
||||
_CA_cert = NULL;
|
||||
}
|
||||
void WebSocketsClient::beginSslWithCA(const char * host, uint16_t port, const char * url, const char * CA_cert, const char * protocol) {
|
||||
begin(host, port, url, protocol);
|
||||
_client.isSSL = true;
|
||||
_fingerprint = SSL_FINGERPRINT_NULL;
|
||||
_CA_cert = new BearSSL::X509List(CA_cert);
|
||||
}
|
||||
|
||||
void WebSocketsClient::beginSslWithCA(const char * host, uint16_t port, const char * url, BearSSL::X509List * CA_cert, const char * protocol) {
|
||||
begin(host, port, url, protocol);
|
||||
_client.isSSL = true;
|
||||
_fingerprint = SSL_FINGERPRINT_NULL;
|
||||
_CA_cert = CA_cert;
|
||||
}
|
||||
#endif // SSL_AXTLS
|
||||
#endif // HAS_SSL
|
||||
|
||||
void WebSocketsClient::beginSocketIO(const char * host, uint16_t port, const char * url, const char * protocol) {
|
||||
begin(host, port, url, protocol);
|
||||
_client.isSocketIO = true;
|
||||
}
|
||||
@ -108,31 +147,47 @@ void WebSocketsClient::beginSocketIO(String host, uint16_t port, String url, Str
|
||||
beginSocketIO(host.c_str(), port, url.c_str(), protocol.c_str());
|
||||
}
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
void WebSocketsClient::beginSocketIOSSL(const char *host, uint16_t port, const char * url, const char * protocol) {
|
||||
#if defined(HAS_SSL)
|
||||
void WebSocketsClient::beginSocketIOSSL(const char * host, uint16_t port, const char * url, const char * protocol) {
|
||||
begin(host, port, url, protocol);
|
||||
_client.isSocketIO = true;
|
||||
_client.isSSL = true;
|
||||
_fingerprint = "";
|
||||
_fingerprint = SSL_FINGERPRINT_NULL;
|
||||
}
|
||||
|
||||
void WebSocketsClient::beginSocketIOSSL(String host, uint16_t port, String url, String protocol) {
|
||||
beginSocketIOSSL(host.c_str(), port, url.c_str(), protocol.c_str());
|
||||
}
|
||||
|
||||
void WebSocketsClient::beginSocketIOSSLWithCA(const char * host, uint16_t port, const char * url, const char * CA_cert, const char * protocol) {
|
||||
begin(host, port, url, protocol);
|
||||
_client.isSocketIO = true;
|
||||
_client.isSSL = true;
|
||||
_fingerprint = SSL_FINGERPRINT_NULL;
|
||||
#if defined(SSL_AXTLS)
|
||||
_CA_cert = CA_cert;
|
||||
#else
|
||||
_CA_cert = new BearSSL::X509List(CA_cert);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||
/**
|
||||
* called in arduino loop
|
||||
*/
|
||||
void WebSocketsClient::loop(void) {
|
||||
if(_port == 0) {
|
||||
return;
|
||||
}
|
||||
WEBSOCKETS_YIELD();
|
||||
if(!clientIsConnected(&_client)) {
|
||||
// do not flood the server
|
||||
if((millis() - _lastConnectionFail) < _reconnectInterval) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
#if defined(HAS_SSL)
|
||||
if(_client.isSSL) {
|
||||
DEBUG_WEBSOCKETS("[WS-Client] connect wss...\n");
|
||||
if(_client.ssl) {
|
||||
@ -140,15 +195,33 @@ void WebSocketsClient::loop(void) {
|
||||
_client.ssl = NULL;
|
||||
_client.tcp = NULL;
|
||||
}
|
||||
_client.ssl = new WiFiClientSecure();
|
||||
_client.ssl = new WEBSOCKETS_NETWORK_SSL_CLASS();
|
||||
_client.tcp = _client.ssl;
|
||||
if(_CA_cert) {
|
||||
DEBUG_WEBSOCKETS("[WS-Client] setting CA certificate");
|
||||
#if defined(ESP32)
|
||||
_client.ssl->setCACert(_CA_cert);
|
||||
#elif defined(ESP8266) && defined(SSL_AXTLS)
|
||||
_client.ssl->setCACert((const uint8_t *)_CA_cert, strlen(_CA_cert) + 1);
|
||||
#elif defined(ESP8266) && defined(SSL_BARESSL)
|
||||
_client.ssl->setTrustAnchors(_CA_cert);
|
||||
#else
|
||||
#error setCACert not implemented
|
||||
#endif
|
||||
#if defined(SSL_BARESSL)
|
||||
} else if(_fingerprint) {
|
||||
_client.ssl->setFingerprint(_fingerprint);
|
||||
} else {
|
||||
_client.ssl->setInsecure();
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
DEBUG_WEBSOCKETS("[WS-Client] connect ws...\n");
|
||||
if(_client.tcp) {
|
||||
delete _client.tcp;
|
||||
_client.tcp = NULL;
|
||||
}
|
||||
_client.tcp = new WiFiClient();
|
||||
_client.tcp = new WEBSOCKETS_NETWORK_CLASS();
|
||||
}
|
||||
#else
|
||||
_client.tcp = new WEBSOCKETS_NETWORK_CLASS();
|
||||
@ -158,17 +231,25 @@ void WebSocketsClient::loop(void) {
|
||||
DEBUG_WEBSOCKETS("[WS-Client] creating Network class failed!");
|
||||
return;
|
||||
}
|
||||
|
||||
WEBSOCKETS_YIELD();
|
||||
#if defined(ESP32)
|
||||
if(_client.tcp->connect(_host.c_str(), _port, WEBSOCKETS_TCP_TIMEOUT)) {
|
||||
#else
|
||||
if(_client.tcp->connect(_host.c_str(), _port)) {
|
||||
#endif
|
||||
connectedCb();
|
||||
_lastConnectionFail = 0;
|
||||
} else {
|
||||
connectFailedCb();
|
||||
_lastConnectionFail = millis();
|
||||
|
||||
}
|
||||
} else {
|
||||
handleClientData();
|
||||
WEBSOCKETS_YIELD();
|
||||
if(_client.status == WSC_CONNECTED) {
|
||||
handleHBPing();
|
||||
handleHBTimeout(&_client);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -191,28 +272,34 @@ void WebSocketsClient::onEvent(WebSocketClientEvent cbEvent) {
|
||||
*/
|
||||
bool WebSocketsClient::sendTXT(uint8_t * payload, size_t length, bool headerToPayload) {
|
||||
if(length == 0) {
|
||||
length = strlen((const char *) payload);
|
||||
length = strlen((const char *)payload);
|
||||
}
|
||||
if(clientIsConnected(&_client)) {
|
||||
return sendFrame(&_client, WSop_text, payload, length, true, true, headerToPayload);
|
||||
return sendFrame(&_client, WSop_text, payload, length, true, headerToPayload);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WebSocketsClient::sendTXT(const uint8_t * payload, size_t length) {
|
||||
return sendTXT((uint8_t *) payload, length);
|
||||
return sendTXT((uint8_t *)payload, length);
|
||||
}
|
||||
|
||||
bool WebSocketsClient::sendTXT(char * payload, size_t length, bool headerToPayload) {
|
||||
return sendTXT((uint8_t *) payload, length, headerToPayload);
|
||||
return sendTXT((uint8_t *)payload, length, headerToPayload);
|
||||
}
|
||||
|
||||
bool WebSocketsClient::sendTXT(const char * payload, size_t length) {
|
||||
return sendTXT((uint8_t *) payload, length);
|
||||
return sendTXT((uint8_t *)payload, length);
|
||||
}
|
||||
|
||||
bool WebSocketsClient::sendTXT(String & payload) {
|
||||
return sendTXT((uint8_t *) payload.c_str(), payload.length());
|
||||
return sendTXT((uint8_t *)payload.c_str(), payload.length());
|
||||
}
|
||||
|
||||
bool WebSocketsClient::sendTXT(char payload) {
|
||||
uint8_t buf[WEBSOCKETS_MAX_HEADER_SIZE + 2] = { 0x00 };
|
||||
buf[WEBSOCKETS_MAX_HEADER_SIZE] = payload;
|
||||
return sendTXT(buf, 1, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -225,13 +312,13 @@ bool WebSocketsClient::sendTXT(String & payload) {
|
||||
*/
|
||||
bool WebSocketsClient::sendBIN(uint8_t * payload, size_t length, bool headerToPayload) {
|
||||
if(clientIsConnected(&_client)) {
|
||||
return sendFrame(&_client, WSop_binary, payload, length, true, true, headerToPayload);
|
||||
return sendFrame(&_client, WSop_binary, payload, length, true, headerToPayload);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WebSocketsClient::sendBIN(const uint8_t * payload, size_t length) {
|
||||
return sendBIN((uint8_t *) payload, length);
|
||||
return sendBIN((uint8_t *)payload, length);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -242,13 +329,16 @@ bool WebSocketsClient::sendBIN(const uint8_t * payload, size_t length) {
|
||||
*/
|
||||
bool WebSocketsClient::sendPing(uint8_t * payload, size_t length) {
|
||||
if(clientIsConnected(&_client)) {
|
||||
return sendFrame(&_client, WSop_ping, payload, length, true);
|
||||
bool sent = sendFrame(&_client, WSop_ping, payload, length);
|
||||
if(sent)
|
||||
_client.lastPing = millis();
|
||||
return sent;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WebSocketsClient::sendPing(String & payload) {
|
||||
return sendPing((uint8_t *) payload.c_str(), payload.length());
|
||||
return sendPing((uint8_t *)payload.c_str(), payload.length());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -271,7 +361,7 @@ void WebSocketsClient::setAuthorization(const char * user, const char * password
|
||||
String auth = user;
|
||||
auth += ":";
|
||||
auth += password;
|
||||
_client.base64Authorization = base64_encode((uint8_t *) auth.c_str(), auth.length());
|
||||
_client.base64Authorization = base64_encode((uint8_t *)auth.c_str(), auth.length());
|
||||
}
|
||||
}
|
||||
|
||||
@ -304,6 +394,10 @@ void WebSocketsClient::setReconnectInterval(unsigned long time) {
|
||||
_reconnectInterval = time;
|
||||
}
|
||||
|
||||
bool WebSocketsClient::isConnected(void) {
|
||||
return (_client.status == WSC_CONNECTED);
|
||||
}
|
||||
|
||||
//#################################################################################
|
||||
//#################################################################################
|
||||
//#################################################################################
|
||||
@ -330,15 +424,18 @@ void WebSocketsClient::messageReceived(WSclient_t * client, WSopcode_t opcode, u
|
||||
case WSop_continuation:
|
||||
type = fin ? WStype_FRAGMENT_FIN : WStype_FRAGMENT;
|
||||
break;
|
||||
case WSop_close:
|
||||
case WSop_ping:
|
||||
type = WStype_PING;
|
||||
break;
|
||||
case WSop_pong:
|
||||
type = WStype_PONG;
|
||||
break;
|
||||
case WSop_close:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
runCbEvent(type, payload, length);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -346,10 +443,9 @@ void WebSocketsClient::messageReceived(WSclient_t * client, WSopcode_t opcode, u
|
||||
* @param client WSclient_t * ptr to the client struct
|
||||
*/
|
||||
void WebSocketsClient::clientDisconnect(WSclient_t * client) {
|
||||
|
||||
bool event = false;
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
if(client->isSSL && client->ssl) {
|
||||
if(client->ssl->connected()) {
|
||||
client->ssl->flush();
|
||||
@ -364,13 +460,13 @@ void WebSocketsClient::clientDisconnect(WSclient_t * client) {
|
||||
|
||||
if(client->tcp) {
|
||||
if(client->tcp->connected()) {
|
||||
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||
client->tcp->flush();
|
||||
#endif
|
||||
client->tcp->stop();
|
||||
}
|
||||
event = true;
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
client->status = WSC_NOT_CONNECTED;
|
||||
#else
|
||||
delete client->tcp;
|
||||
@ -400,7 +496,6 @@ void WebSocketsClient::clientDisconnect(WSclient_t * client) {
|
||||
* @return true = conneted
|
||||
*/
|
||||
bool WebSocketsClient::clientIsConnected(WSclient_t * client) {
|
||||
|
||||
if(!client->tcp) {
|
||||
return false;
|
||||
}
|
||||
@ -425,19 +520,24 @@ bool WebSocketsClient::clientIsConnected(WSclient_t * client) {
|
||||
|
||||
return false;
|
||||
}
|
||||
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||
/**
|
||||
* Handel incomming data from Client
|
||||
*/
|
||||
void WebSocketsClient::handleClientData(void) {
|
||||
if(_client.status == WSC_HEADER && _lastHeaderSent + WEBSOCKETS_TCP_TIMEOUT < millis()) {
|
||||
DEBUG_WEBSOCKETS("[WS-Client][handleClientData] header response timeout.. disconnecting!\n");
|
||||
clientDisconnect(&_client);
|
||||
WEBSOCKETS_YIELD();
|
||||
return;
|
||||
}
|
||||
int len = _client.tcp->available();
|
||||
if(len > 0) {
|
||||
switch(_client.status) {
|
||||
case WSC_HEADER: {
|
||||
String headerLine = _client.tcp->readStringUntil('\n');
|
||||
handleHeader(&_client, &headerLine);
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
case WSC_CONNECTED:
|
||||
WebSockets::handleWebsocket(&_client);
|
||||
break;
|
||||
@ -446,9 +546,7 @@ void WebSocketsClient::handleClientData(void) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
delay(0);
|
||||
#endif
|
||||
WEBSOCKETS_YIELD();
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -457,7 +555,6 @@ void WebSocketsClient::handleClientData(void) {
|
||||
* @param client WSclient_t * ptr to the client struct
|
||||
*/
|
||||
void WebSocketsClient::sendHeader(WSclient_t * client) {
|
||||
|
||||
static const char * NEW_LINE = "\r\n";
|
||||
|
||||
DEBUG_WEBSOCKETS("[WS-Client][sendHeader] sending header...\n");
|
||||
@ -489,12 +586,14 @@ void WebSocketsClient::sendHeader(WSclient_t * client) {
|
||||
}
|
||||
|
||||
handshake = WEBSOCKETS_STRING("GET ");
|
||||
handshake += url + WEBSOCKETS_STRING(" HTTP/1.1\r\n"
|
||||
handshake += url + WEBSOCKETS_STRING(
|
||||
" HTTP/1.1\r\n"
|
||||
"Host: ");
|
||||
handshake += _host + ":" + _port + NEW_LINE;
|
||||
|
||||
if(ws_header) {
|
||||
handshake += WEBSOCKETS_STRING("Connection: Upgrade\r\n"
|
||||
handshake += WEBSOCKETS_STRING(
|
||||
"Connection: Upgrade\r\n"
|
||||
"Upgrade: websocket\r\n"
|
||||
"Sec-WebSocket-Version: 13\r\n"
|
||||
"Sec-WebSocket-Key: ");
|
||||
@ -532,15 +631,15 @@ void WebSocketsClient::sendHeader(WSclient_t * client) {
|
||||
|
||||
handshake += NEW_LINE;
|
||||
|
||||
DEBUG_WEBSOCKETS("[WS-Client][sendHeader] handshake %s", (uint8_t* )handshake.c_str());
|
||||
write(client, (uint8_t*) handshake.c_str(), handshake.length());
|
||||
DEBUG_WEBSOCKETS("[WS-Client][sendHeader] handshake %s", (uint8_t *)handshake.c_str());
|
||||
write(client, (uint8_t *)handshake.c_str(), handshake.length());
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
client->tcp->readStringUntil('\n', &(client->cHttpLine), std::bind(&WebSocketsClient::handleHeader, this, client, &(client->cHttpLine)));
|
||||
#endif
|
||||
|
||||
DEBUG_WEBSOCKETS("[WS-Client][sendHeader] sending header... Done (%luus).\n", (micros() - start));
|
||||
|
||||
_lastHeaderSent = millis();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -548,7 +647,6 @@ void WebSocketsClient::sendHeader(WSclient_t * client) {
|
||||
* @param client WSclient_t * ptr to the client struct
|
||||
*/
|
||||
void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) {
|
||||
|
||||
headerLine->trim(); // remove \r
|
||||
|
||||
if(headerLine->length() > 0) {
|
||||
@ -557,7 +655,7 @@ void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) {
|
||||
if(headerLine->startsWith(WEBSOCKETS_STRING("HTTP/1."))) {
|
||||
// "HTTP/1.1 101 Switching Protocols"
|
||||
client->cCode = headerLine->substring(9, headerLine->indexOf(' ', 9)).toInt();
|
||||
} else if(headerLine->indexOf(':')) {
|
||||
} else if(headerLine->indexOf(':') >= 0) {
|
||||
String headerName = headerLine->substring(0, headerLine->indexOf(':'));
|
||||
String headerValue = headerLine->substring(headerLine->indexOf(':') + 1);
|
||||
|
||||
@ -595,10 +693,9 @@ void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) {
|
||||
}
|
||||
|
||||
(*headerLine) = "";
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
client->tcp->readStringUntil('\n', &(client->cHttpLine), std::bind(&WebSocketsClient::handleHeader, this, client, &(client->cHttpLine)));
|
||||
#endif
|
||||
|
||||
} else {
|
||||
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] Header read fin.\n");
|
||||
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] Client settings:\n");
|
||||
@ -639,7 +736,6 @@ void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) {
|
||||
}
|
||||
|
||||
if(ok) {
|
||||
|
||||
if(client->cAccept.length() == 0) {
|
||||
ok = false;
|
||||
} else {
|
||||
@ -653,14 +749,21 @@ void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) {
|
||||
}
|
||||
|
||||
if(ok) {
|
||||
|
||||
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] Websocket connection init done.\n");
|
||||
headerDone(client);
|
||||
|
||||
runCbEvent(WStype_CONNECTED, (uint8_t *) client->cUrl.c_str(), client->cUrl.length());
|
||||
|
||||
runCbEvent(WStype_CONNECTED, (uint8_t *)client->cUrl.c_str(), client->cUrl.length());
|
||||
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||
} else if(clientIsConnected(client) && client->isSocketIO && client->cSessionId.length() > 0) {
|
||||
if(_client.tcp->available()) {
|
||||
// read not needed data
|
||||
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] still data in buffer (%d), clean up.\n", _client.tcp->available());
|
||||
while(_client.tcp->available() > 0) {
|
||||
_client.tcp->read();
|
||||
}
|
||||
}
|
||||
sendHeader(client);
|
||||
#endif
|
||||
} else {
|
||||
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] no Websocket connection close.\n");
|
||||
_lastConnectionFail = millis();
|
||||
@ -673,10 +776,9 @@ void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) {
|
||||
}
|
||||
|
||||
void WebSocketsClient::connectedCb() {
|
||||
|
||||
DEBUG_WEBSOCKETS("[WS-Client] connected to %s:%u.\n", _host.c_str(), _port);
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
_client.tcp->onDisconnect(std::bind([](WebSocketsClient * c, AsyncTCPbuffer * obj, WSclient_t * client) -> bool {
|
||||
DEBUG_WEBSOCKETS("[WS-Server][%d] Disconnect client\n", client->num);
|
||||
client->status = WSC_NOT_CONNECTED;
|
||||
@ -686,41 +788,50 @@ void WebSocketsClient::connectedCb() {
|
||||
c->asyncConnect();
|
||||
|
||||
return true;
|
||||
}, this, std::placeholders::_1, &_client));
|
||||
},
|
||||
this, std::placeholders::_1, &_client));
|
||||
#endif
|
||||
|
||||
_client.status = WSC_HEADER;
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||
// set Timeout for readBytesUntil and readStringUntil
|
||||
_client.tcp->setTimeout(WEBSOCKETS_TCP_TIMEOUT);
|
||||
#endif
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
_client.tcp->setNoDelay(true);
|
||||
#endif
|
||||
|
||||
#if defined(HAS_SSL)
|
||||
#if defined(SSL_AXTLS) || defined(ESP32)
|
||||
if(_client.isSSL && _fingerprint.length()) {
|
||||
if(!_client.ssl->verify(_fingerprint.c_str(), _host.c_str())) {
|
||||
DEBUG_WEBSOCKETS("[WS-Client] certificate mismatch\n");
|
||||
WebSockets::clientDisconnect(&_client, 1000);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if(_client.isSSL && _fingerprint) {
|
||||
#endif
|
||||
} else if(_client.isSSL && !_CA_cert) {
|
||||
#if defined(SSL_BARESSL)
|
||||
_client.ssl->setInsecure();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
// send Header to Server
|
||||
sendHeader(&_client);
|
||||
|
||||
}
|
||||
|
||||
void WebSocketsClient::connectFailedCb() {
|
||||
DEBUG_WEBSOCKETS("[WS-Client] connection to %s:%u Faild\n", _host.c_str(), _port);
|
||||
DEBUG_WEBSOCKETS("[WS-Client] connection to %s:%u Failed\n", _host.c_str(), _port);
|
||||
}
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
|
||||
void WebSocketsClient::asyncConnect() {
|
||||
|
||||
DEBUG_WEBSOCKETS("[WS-Client] asyncConnect...\n");
|
||||
|
||||
AsyncClient * tcpclient = new AsyncClient();
|
||||
@ -730,12 +841,12 @@ void WebSocketsClient::asyncConnect() {
|
||||
return;
|
||||
}
|
||||
|
||||
tcpclient->onDisconnect([](void *obj, AsyncClient* c) {
|
||||
tcpclient->onDisconnect([](void * obj, AsyncClient * c) {
|
||||
c->free();
|
||||
delete c;
|
||||
});
|
||||
|
||||
tcpclient->onConnect(std::bind([](WebSocketsClient * ws , AsyncClient * tcp) {
|
||||
tcpclient->onConnect(std::bind([](WebSocketsClient * ws, AsyncClient * tcp) {
|
||||
ws->_client.tcp = new AsyncTCPbuffer(tcp);
|
||||
if(!ws->_client.tcp) {
|
||||
DEBUG_WEBSOCKETS("[WS-Client] creating Network class failed!\n");
|
||||
@ -743,20 +854,54 @@ void WebSocketsClient::asyncConnect() {
|
||||
return;
|
||||
}
|
||||
ws->connectedCb();
|
||||
}, this, std::placeholders::_2));
|
||||
},
|
||||
this, std::placeholders::_2));
|
||||
|
||||
tcpclient->onError(std::bind([](WebSocketsClient * ws , AsyncClient * tcp) {
|
||||
tcpclient->onError(std::bind([](WebSocketsClient * ws, AsyncClient * tcp) {
|
||||
ws->connectFailedCb();
|
||||
|
||||
// reconnect
|
||||
ws->asyncConnect();
|
||||
}, this, std::placeholders::_2));
|
||||
},
|
||||
this, std::placeholders::_2));
|
||||
|
||||
if(!tcpclient->connect(_host.c_str(), _port)) {
|
||||
connectFailedCb();
|
||||
delete tcpclient;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* send heartbeat ping to server in set intervals
|
||||
*/
|
||||
void WebSocketsClient::handleHBPing() {
|
||||
if(_client.pingInterval == 0)
|
||||
return;
|
||||
uint32_t pi = millis() - _client.lastPing;
|
||||
if(pi > _client.pingInterval) {
|
||||
DEBUG_WEBSOCKETS("[WS-Client] sending HB ping\n");
|
||||
if(sendPing()) {
|
||||
_client.lastPing = millis();
|
||||
_client.pongReceived = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* enable ping/pong heartbeat process
|
||||
* @param pingInterval uint32_t how often ping will be sent
|
||||
* @param pongTimeout uint32_t millis after which pong should timout if not received
|
||||
* @param disconnectTimeoutCount uint8_t how many timeouts before disconnect, 0=> do not disconnect
|
||||
*/
|
||||
void WebSocketsClient::enableHeartbeat(uint32_t pingInterval, uint32_t pongTimeout, uint8_t disconnectTimeoutCount) {
|
||||
WebSockets::enableHeartbeat(&_client, pingInterval, pongTimeout, disconnectTimeoutCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* disable ping/pong heartbeat process
|
||||
*/
|
||||
void WebSocketsClient::disableHeartbeat() {
|
||||
_client.pingInterval = 0;
|
||||
}
|
||||
|
@ -27,40 +27,46 @@
|
||||
|
||||
#include "WebSockets.h"
|
||||
|
||||
class WebSocketsClient: private WebSockets {
|
||||
class WebSocketsClient : protected WebSockets {
|
||||
public:
|
||||
#ifdef __AVR__
|
||||
typedef void (*WebSocketClientEvent)(WStype_t type, uint8_t * payload, size_t length);
|
||||
#else
|
||||
typedef std::function<void (WStype_t type, uint8_t * payload, size_t length)> WebSocketClientEvent;
|
||||
typedef std::function<void(WStype_t type, uint8_t * payload, size_t length)> WebSocketClientEvent;
|
||||
#endif
|
||||
|
||||
|
||||
WebSocketsClient(void);
|
||||
virtual ~WebSocketsClient(void);
|
||||
|
||||
void begin(const char *host, uint16_t port, const char * url = "/", const char * protocol = "arduino");
|
||||
void begin(const char * host, uint16_t port, const char * url = "/", const char * protocol = "arduino");
|
||||
void begin(String host, uint16_t port, String url = "/", String protocol = "arduino");
|
||||
void begin(IPAddress host, uint16_t port, const char * url = "/", const char * protocol = "arduino");
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
void beginSSL(const char *host, uint16_t port, const char * url = "/", const char * = "", const char * protocol = "arduino");
|
||||
#if defined(HAS_SSL)
|
||||
#ifdef SSL_AXTLS
|
||||
void beginSSL(const char * host, uint16_t port, const char * url = "/", const char * fingerprint = "", const char * protocol = "arduino");
|
||||
void beginSSL(String host, uint16_t port, String url = "/", String fingerprint = "", String protocol = "arduino");
|
||||
#else
|
||||
void beginSSL(const char * host, uint16_t port, const char * url = "/", const uint8_t * fingerprint = NULL, const char * protocol = "arduino");
|
||||
void beginSslWithCA(const char * host, uint16_t port, const char * url = "/", BearSSL::X509List * CA_cert = NULL, const char * protocol = "arduino");
|
||||
#endif
|
||||
void beginSslWithCA(const char * host, uint16_t port, const char * url = "/", const char * CA_cert = NULL, const char * protocol = "arduino");
|
||||
#endif
|
||||
|
||||
void beginSocketIO(const char *host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * protocol = "arduino");
|
||||
void beginSocketIO(const char * host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * protocol = "arduino");
|
||||
void beginSocketIO(String host, uint16_t port, String url = "/socket.io/?EIO=3", String protocol = "arduino");
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
void beginSocketIOSSL(const char *host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * protocol = "arduino");
|
||||
#if defined(HAS_SSL)
|
||||
void beginSocketIOSSL(const char * host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * protocol = "arduino");
|
||||
void beginSocketIOSSL(String host, uint16_t port, String url = "/socket.io/?EIO=3", String protocol = "arduino");
|
||||
void beginSocketIOSSLWithCA(const char * host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * CA_cert = NULL, const char * protocol = "arduino");
|
||||
#endif
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||
void loop(void);
|
||||
#else
|
||||
// Async interface not need a loop call
|
||||
void loop(void) __attribute__ ((deprecated)) {}
|
||||
void loop(void) __attribute__((deprecated)) {}
|
||||
#endif
|
||||
|
||||
void onEvent(WebSocketClientEvent cbEvent);
|
||||
@ -70,6 +76,7 @@ class WebSocketsClient: private WebSockets {
|
||||
bool sendTXT(char * payload, size_t length = 0, bool headerToPayload = false);
|
||||
bool sendTXT(const char * payload, size_t length = 0);
|
||||
bool sendTXT(String & payload);
|
||||
bool sendTXT(char payload);
|
||||
|
||||
bool sendBIN(uint8_t * payload, size_t length, bool headerToPayload = false);
|
||||
bool sendBIN(const uint8_t * payload, size_t length);
|
||||
@ -86,12 +93,26 @@ class WebSocketsClient: private WebSockets {
|
||||
|
||||
void setReconnectInterval(unsigned long time);
|
||||
|
||||
void enableHeartbeat(uint32_t pingInterval, uint32_t pongTimeout, uint8_t disconnectTimeoutCount);
|
||||
void disableHeartbeat();
|
||||
|
||||
bool isConnected(void);
|
||||
|
||||
protected:
|
||||
String _host;
|
||||
uint16_t _port;
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
#if defined(HAS_SSL)
|
||||
#ifdef SSL_AXTLS
|
||||
String _fingerprint;
|
||||
const char * _CA_cert;
|
||||
#define SSL_FINGERPRINT_NULL ""
|
||||
#else
|
||||
const uint8_t * _fingerprint;
|
||||
BearSSL::X509List * _CA_cert;
|
||||
#define SSL_FINGERPRINT_NULL NULL
|
||||
#endif
|
||||
|
||||
#endif
|
||||
WSclient_t _client;
|
||||
|
||||
@ -99,13 +120,14 @@ class WebSocketsClient: private WebSockets {
|
||||
|
||||
unsigned long _lastConnectionFail;
|
||||
unsigned long _reconnectInterval;
|
||||
unsigned long _lastHeaderSent;
|
||||
|
||||
void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin);
|
||||
|
||||
void clientDisconnect(WSclient_t * client);
|
||||
bool clientIsConnected(WSclient_t * client);
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||
void handleClientData(void);
|
||||
#endif
|
||||
|
||||
@ -115,7 +137,9 @@ class WebSocketsClient: private WebSockets {
|
||||
void connectedCb();
|
||||
void connectFailedCb();
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
void handleHBPing(); // send ping in specified intervals
|
||||
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
void asyncConnect();
|
||||
#endif
|
||||
|
||||
@ -130,7 +154,6 @@ class WebSocketsClient: private WebSockets {
|
||||
_cbEvent(type, payload, length);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif /* WEBSOCKETSCLIENT_H_ */
|
||||
|
@ -30,13 +30,17 @@ WebSocketsServer::WebSocketsServer(uint16_t port, String origin, String protocol
|
||||
_origin = origin;
|
||||
_protocol = protocol;
|
||||
_runnning = false;
|
||||
_pingInterval = 0;
|
||||
_pongTimeout = 0;
|
||||
_disconnectTimeoutCount = 0;
|
||||
|
||||
_server = new WEBSOCKETS_NETWORK_SERVER_CLASS(port);
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
_server->onClient([](void *s, AsyncClient* c){
|
||||
((WebSocketsServer*)s)->newClient(new AsyncTCPbuffer(c));
|
||||
}, this);
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
_server->onClient([](void * s, AsyncClient * c) {
|
||||
((WebSocketsServer *)s)->newClient(new AsyncTCPbuffer(c));
|
||||
},
|
||||
this);
|
||||
#endif
|
||||
|
||||
_cbEvent = NULL;
|
||||
@ -48,12 +52,11 @@ WebSocketsServer::WebSocketsServer(uint16_t port, String origin, String protocol
|
||||
memset(&_clients[0], 0x00, (sizeof(WSclient_t) * WEBSOCKETS_SERVER_CLIENT_MAX));
|
||||
}
|
||||
|
||||
|
||||
WebSocketsServer::~WebSocketsServer() {
|
||||
// disconnect all clients
|
||||
close();
|
||||
|
||||
if (_mandatoryHttpHeaders)
|
||||
if(_mandatoryHttpHeaders)
|
||||
delete[] _mandatoryHttpHeaders;
|
||||
|
||||
_mandatoryHttpHeaderCount = 0;
|
||||
@ -72,7 +75,7 @@ void WebSocketsServer::begin(void) {
|
||||
client->num = i;
|
||||
client->status = WSC_NOT_CONNECTED;
|
||||
client->tcp = NULL;
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
client->isSSL = false;
|
||||
client->ssl = NULL;
|
||||
#endif
|
||||
@ -88,15 +91,19 @@ void WebSocketsServer::begin(void) {
|
||||
|
||||
client->cWsRXsize = 0;
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
client->cHttpLine = "";
|
||||
#endif
|
||||
|
||||
client->pingInterval = _pingInterval;
|
||||
client->pongTimeout = _pongTimeout;
|
||||
client->disconnectTimeoutCount = _disconnectTimeoutCount;
|
||||
}
|
||||
|
||||
#ifdef ESP8266
|
||||
randomSeed(RANDOM_REG32);
|
||||
#elif defined(ESP32)
|
||||
#define DR_REG_RNG_BASE 0x3ff75144
|
||||
#define DR_REG_RNG_BASE 0x3ff75144
|
||||
randomSeed(READ_PERI_REG(DR_REG_RNG_BASE));
|
||||
#else
|
||||
// TODO find better seed
|
||||
@ -113,23 +120,24 @@ void WebSocketsServer::close(void) {
|
||||
_runnning = false;
|
||||
disconnect();
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
|
||||
_server->close();
|
||||
#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
#elif(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
_server->end();
|
||||
#else
|
||||
// TODO how to close server?
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||
/**
|
||||
* called in arduino loop
|
||||
*/
|
||||
void WebSocketsServer::loop(void) {
|
||||
if(_runnning) {
|
||||
WEBSOCKETS_YIELD();
|
||||
handleNewClients();
|
||||
WEBSOCKETS_YIELD();
|
||||
handleClientData();
|
||||
}
|
||||
}
|
||||
@ -151,18 +159,17 @@ void WebSocketsServer::onEvent(WebSocketServerEvent cbEvent) {
|
||||
*/
|
||||
void WebSocketsServer::onValidateHttpHeader(
|
||||
WebSocketServerHttpHeaderValFunc validationFunc,
|
||||
const char* mandatoryHttpHeaders[],
|
||||
size_t mandatoryHttpHeaderCount)
|
||||
{
|
||||
const char * mandatoryHttpHeaders[],
|
||||
size_t mandatoryHttpHeaderCount) {
|
||||
_httpHeaderValidationFunc = validationFunc;
|
||||
|
||||
if (_mandatoryHttpHeaders)
|
||||
if(_mandatoryHttpHeaders)
|
||||
delete[] _mandatoryHttpHeaders;
|
||||
|
||||
_mandatoryHttpHeaderCount = mandatoryHttpHeaderCount;
|
||||
_mandatoryHttpHeaders = new String[_mandatoryHttpHeaderCount];
|
||||
|
||||
for (size_t i = 0; i < _mandatoryHttpHeaderCount; i++) {
|
||||
for(size_t i = 0; i < _mandatoryHttpHeaderCount; i++) {
|
||||
_mandatoryHttpHeaders[i] = mandatoryHttpHeaders[i];
|
||||
}
|
||||
}
|
||||
@ -180,29 +187,29 @@ bool WebSocketsServer::sendTXT(uint8_t num, uint8_t * payload, size_t length, bo
|
||||
return false;
|
||||
}
|
||||
if(length == 0) {
|
||||
length = strlen((const char *) payload);
|
||||
length = strlen((const char *)payload);
|
||||
}
|
||||
WSclient_t * client = &_clients[num];
|
||||
if(clientIsConnected(client)) {
|
||||
return sendFrame(client, WSop_text, payload, length, false, true, headerToPayload);
|
||||
return sendFrame(client, WSop_text, payload, length, true, headerToPayload);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WebSocketsServer::sendTXT(uint8_t num, const uint8_t * payload, size_t length) {
|
||||
return sendTXT(num, (uint8_t *) payload, length);
|
||||
return sendTXT(num, (uint8_t *)payload, length);
|
||||
}
|
||||
|
||||
bool WebSocketsServer::sendTXT(uint8_t num, char * payload, size_t length, bool headerToPayload) {
|
||||
return sendTXT(num, (uint8_t *) payload, length, headerToPayload);
|
||||
return sendTXT(num, (uint8_t *)payload, length, headerToPayload);
|
||||
}
|
||||
|
||||
bool WebSocketsServer::sendTXT(uint8_t num, const char * payload, size_t length) {
|
||||
return sendTXT(num, (uint8_t *) payload, length);
|
||||
return sendTXT(num, (uint8_t *)payload, length);
|
||||
}
|
||||
|
||||
bool WebSocketsServer::sendTXT(uint8_t num, String & payload) {
|
||||
return sendTXT(num, (uint8_t *) payload.c_str(), payload.length());
|
||||
return sendTXT(num, (uint8_t *)payload.c_str(), payload.length());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -216,37 +223,35 @@ bool WebSocketsServer::broadcastTXT(uint8_t * payload, size_t length, bool heade
|
||||
WSclient_t * client;
|
||||
bool ret = true;
|
||||
if(length == 0) {
|
||||
length = strlen((const char *) payload);
|
||||
length = strlen((const char *)payload);
|
||||
}
|
||||
|
||||
for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
|
||||
client = &_clients[i];
|
||||
if(clientIsConnected(client)) {
|
||||
if(!sendFrame(client, WSop_text, payload, length, false, true, headerToPayload)) {
|
||||
if(!sendFrame(client, WSop_text, payload, length, true, headerToPayload)) {
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
|
||||
delay(0);
|
||||
#endif
|
||||
WEBSOCKETS_YIELD();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool WebSocketsServer::broadcastTXT(const uint8_t * payload, size_t length) {
|
||||
return broadcastTXT((uint8_t *) payload, length);
|
||||
return broadcastTXT((uint8_t *)payload, length);
|
||||
}
|
||||
|
||||
bool WebSocketsServer::broadcastTXT(char * payload, size_t length, bool headerToPayload) {
|
||||
return broadcastTXT((uint8_t *) payload, length, headerToPayload);
|
||||
return broadcastTXT((uint8_t *)payload, length, headerToPayload);
|
||||
}
|
||||
|
||||
bool WebSocketsServer::broadcastTXT(const char * payload, size_t length) {
|
||||
return broadcastTXT((uint8_t *) payload, length);
|
||||
return broadcastTXT((uint8_t *)payload, length);
|
||||
}
|
||||
|
||||
bool WebSocketsServer::broadcastTXT(String & payload) {
|
||||
return broadcastTXT((uint8_t *) payload.c_str(), payload.length());
|
||||
return broadcastTXT((uint8_t *)payload.c_str(), payload.length());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -263,13 +268,13 @@ bool WebSocketsServer::sendBIN(uint8_t num, uint8_t * payload, size_t length, bo
|
||||
}
|
||||
WSclient_t * client = &_clients[num];
|
||||
if(clientIsConnected(client)) {
|
||||
return sendFrame(client, WSop_binary, payload, length, false, true, headerToPayload);
|
||||
return sendFrame(client, WSop_binary, payload, length, true, headerToPayload);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WebSocketsServer::sendBIN(uint8_t num, const uint8_t * payload, size_t length) {
|
||||
return sendBIN(num, (uint8_t *) payload, length);
|
||||
return sendBIN(num, (uint8_t *)payload, length);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -285,22 +290,19 @@ bool WebSocketsServer::broadcastBIN(uint8_t * payload, size_t length, bool heade
|
||||
for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
|
||||
client = &_clients[i];
|
||||
if(clientIsConnected(client)) {
|
||||
if(!sendFrame(client, WSop_binary, payload, length, false, true, headerToPayload)) {
|
||||
if(!sendFrame(client, WSop_binary, payload, length, true, headerToPayload)) {
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
|
||||
delay(0);
|
||||
#endif
|
||||
WEBSOCKETS_YIELD();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool WebSocketsServer::broadcastBIN(const uint8_t * payload, size_t length) {
|
||||
return broadcastBIN((uint8_t *) payload, length);
|
||||
return broadcastBIN((uint8_t *)payload, length);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* sends a WS ping to Client
|
||||
* @param num uint8_t client id
|
||||
@ -320,7 +322,7 @@ bool WebSocketsServer::sendPing(uint8_t num, uint8_t * payload, size_t length) {
|
||||
}
|
||||
|
||||
bool WebSocketsServer::sendPing(uint8_t num, String & payload) {
|
||||
return sendPing(num, (uint8_t *) payload.c_str(), payload.length());
|
||||
return sendPing(num, (uint8_t *)payload.c_str(), payload.length());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -339,18 +341,15 @@ bool WebSocketsServer::broadcastPing(uint8_t * payload, size_t length) {
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
|
||||
delay(0);
|
||||
#endif
|
||||
WEBSOCKETS_YIELD();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool WebSocketsServer::broadcastPing(String & payload) {
|
||||
return broadcastPing((uint8_t *) payload.c_str(), payload.length());
|
||||
return broadcastPing((uint8_t *)payload.c_str(), payload.length());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* disconnect all clients
|
||||
*/
|
||||
@ -378,7 +377,6 @@ void WebSocketsServer::disconnect(uint8_t num) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* set the Authorization for the http request
|
||||
* @param user const char *
|
||||
@ -421,7 +419,19 @@ int WebSocketsServer::connectedClients(bool ping) {
|
||||
return count;
|
||||
}
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
/**
|
||||
* see if one client is connected
|
||||
* @param num uint8_t client id
|
||||
*/
|
||||
bool WebSocketsServer::clientIsConnected(uint8_t num) {
|
||||
if(num >= WEBSOCKETS_SERVER_CLIENT_MAX) {
|
||||
return false;
|
||||
}
|
||||
WSclient_t * client = &_clients[num];
|
||||
return clientIsConnected(client);
|
||||
}
|
||||
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
/**
|
||||
* get an IP for a client
|
||||
* @param num uint8_t client id
|
||||
@ -455,27 +465,27 @@ bool WebSocketsServer::newClient(WEBSOCKETS_NETWORK_CLASS * TCPclient) {
|
||||
|
||||
// state is not connected or tcp connection is lost
|
||||
if(!clientIsConnected(client)) {
|
||||
|
||||
client->tcp = TCPclient;
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
client->isSSL = false;
|
||||
client->tcp->setNoDelay(true);
|
||||
#endif
|
||||
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||
// set Timeout for readBytesUntil and readStringUntil
|
||||
client->tcp->setTimeout(WEBSOCKETS_TCP_TIMEOUT);
|
||||
#endif
|
||||
client->status = WSC_HEADER;
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
#ifndef NODEBUG_WEBSOCKETS
|
||||
IPAddress ip = client->tcp->remoteIP();
|
||||
#endif
|
||||
DEBUG_WEBSOCKETS("[WS-Server][%d] new client from %d.%d.%d.%d\n", client->num, ip[0], ip[1], ip[2], ip[3]);
|
||||
#else
|
||||
DEBUG_WEBSOCKETS("[WS-Server][%d] new client\n", client->num);
|
||||
#endif
|
||||
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
client->tcp->onDisconnect(std::bind([](WebSocketsServer * server, AsyncTCPbuffer * obj, WSclient_t * client) -> bool {
|
||||
DEBUG_WEBSOCKETS("[WS-Server][%d] Disconnect client\n", client->num);
|
||||
|
||||
@ -485,12 +495,18 @@ bool WebSocketsServer::newClient(WEBSOCKETS_NETWORK_CLASS * TCPclient) {
|
||||
*sl = NULL;
|
||||
}
|
||||
return true;
|
||||
}, this, std::placeholders::_1, client));
|
||||
|
||||
},
|
||||
this, std::placeholders::_1, client));
|
||||
|
||||
client->tcp->readStringUntil('\n', &(client->cHttpLine), std::bind(&WebSocketsServer::handleHeader, this, client, &(client->cHttpLine)));
|
||||
#endif
|
||||
|
||||
client->pingInterval = _pingInterval;
|
||||
client->pongTimeout = _pongTimeout;
|
||||
client->disconnectTimeoutCount = _disconnectTimeoutCount;
|
||||
client->lastPing = millis();
|
||||
client->pongReceived = false;
|
||||
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
@ -518,15 +534,18 @@ void WebSocketsServer::messageReceived(WSclient_t * client, WSopcode_t opcode, u
|
||||
case WSop_continuation:
|
||||
type = fin ? WStype_FRAGMENT_FIN : WStype_FRAGMENT;
|
||||
break;
|
||||
case WSop_close:
|
||||
case WSop_ping:
|
||||
type = WStype_PING;
|
||||
break;
|
||||
case WSop_pong:
|
||||
type = WStype_PONG;
|
||||
break;
|
||||
case WSop_close:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
runCbEvent(client->num, type, payload, length);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -534,9 +553,7 @@ void WebSocketsServer::messageReceived(WSclient_t * client, WSopcode_t opcode, u
|
||||
* @param client WSclient_t * ptr to the client struct
|
||||
*/
|
||||
void WebSocketsServer::clientDisconnect(WSclient_t * client) {
|
||||
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
if(client->isSSL && client->ssl) {
|
||||
if(client->ssl->connected()) {
|
||||
client->ssl->flush();
|
||||
@ -550,12 +567,12 @@ void WebSocketsServer::clientDisconnect(WSclient_t * client) {
|
||||
|
||||
if(client->tcp) {
|
||||
if(client->tcp->connected()) {
|
||||
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) && (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP32)
|
||||
client->tcp->flush();
|
||||
#endif
|
||||
client->tcp->stop();
|
||||
}
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
client->status = WSC_NOT_CONNECTED;
|
||||
#else
|
||||
delete client->tcp;
|
||||
@ -572,7 +589,7 @@ void WebSocketsServer::clientDisconnect(WSclient_t * client) {
|
||||
|
||||
client->cWsRXsize = 0;
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
client->cHttpLine = "";
|
||||
#endif
|
||||
|
||||
@ -581,7 +598,6 @@ void WebSocketsServer::clientDisconnect(WSclient_t * client) {
|
||||
DEBUG_WEBSOCKETS("[WS-Server][%d] client disconnected.\n", client->num);
|
||||
|
||||
runCbEvent(client->num, WStype_DISCONNECTED, NULL, 0);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -590,7 +606,6 @@ void WebSocketsServer::clientDisconnect(WSclient_t * client) {
|
||||
* @return true = connected
|
||||
*/
|
||||
bool WebSocketsServer::clientIsConnected(WSclient_t * client) {
|
||||
|
||||
if(!client->tcp) {
|
||||
return false;
|
||||
}
|
||||
@ -616,18 +631,17 @@ bool WebSocketsServer::clientIsConnected(WSclient_t * client) {
|
||||
|
||||
return false;
|
||||
}
|
||||
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||
/**
|
||||
* Handle incoming Connection Request
|
||||
*/
|
||||
void WebSocketsServer::handleNewClients(void) {
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
while(_server->hasClient()) {
|
||||
#endif
|
||||
bool ok = false;
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
// store new connection
|
||||
WEBSOCKETS_NETWORK_CLASS * tcpClient = new WEBSOCKETS_NETWORK_CLASS(_server->available());
|
||||
#else
|
||||
@ -643,8 +657,10 @@ void WebSocketsServer::handleNewClients(void) {
|
||||
|
||||
if(!ok) {
|
||||
// no free space to handle client
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
#ifndef NODEBUG_WEBSOCKETS
|
||||
IPAddress ip = tcpClient->remoteIP();
|
||||
#endif
|
||||
DEBUG_WEBSOCKETS("[WS-Server] no free space new client from %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
|
||||
#else
|
||||
DEBUG_WEBSOCKETS("[WS-Server] no free space new client\n");
|
||||
@ -652,19 +668,16 @@ void WebSocketsServer::handleNewClients(void) {
|
||||
tcpClient->stop();
|
||||
}
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
delay(0);
|
||||
WEBSOCKETS_YIELD();
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handel incomming data from Client
|
||||
*/
|
||||
void WebSocketsServer::handleClientData(void) {
|
||||
|
||||
WSclient_t * client;
|
||||
for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
|
||||
client = &_clients[i];
|
||||
@ -673,24 +686,24 @@ void WebSocketsServer::handleClientData(void) {
|
||||
if(len > 0) {
|
||||
//DEBUG_WEBSOCKETS("[WS-Server][%d][handleClientData] len: %d\n", client->num, len);
|
||||
switch(client->status) {
|
||||
case WSC_HEADER:
|
||||
{
|
||||
case WSC_HEADER: {
|
||||
String headerLine = client->tcp->readStringUntil('\n');
|
||||
handleHeader(client, &headerLine);
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
case WSC_CONNECTED:
|
||||
WebSockets::handleWebsocket(client);
|
||||
break;
|
||||
default:
|
||||
DEBUG_WEBSOCKETS("[WS-Server][%d][handleClientData] unknown client status %d\n", client->num, client->status);
|
||||
WebSockets::clientDisconnect(client, 1002);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
handleHBPing(client);
|
||||
handleHBTimeout(client);
|
||||
}
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
|
||||
delay(0);
|
||||
#endif
|
||||
WEBSOCKETS_YIELD();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -700,21 +713,19 @@ void WebSocketsServer::handleClientData(void) {
|
||||
* @param headerName String ///< the name of the header being checked
|
||||
*/
|
||||
bool WebSocketsServer::hasMandatoryHeader(String headerName) {
|
||||
for (size_t i = 0; i < _mandatoryHttpHeaderCount; i++) {
|
||||
if (_mandatoryHttpHeaders[i].equalsIgnoreCase(headerName))
|
||||
for(size_t i = 0; i < _mandatoryHttpHeaderCount; i++) {
|
||||
if(_mandatoryHttpHeaders[i].equalsIgnoreCase(headerName))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* handles http header reading for WebSocket upgrade
|
||||
* @param client WSclient_t * ///< pointer to the client struct
|
||||
* @param headerLine String ///< the header being read / processed
|
||||
*/
|
||||
void WebSocketsServer::handleHeader(WSclient_t * client, String * headerLine) {
|
||||
|
||||
static const char * NEW_LINE = "\r\n";
|
||||
|
||||
headerLine->trim(); // remove \r
|
||||
@ -724,7 +735,6 @@ void WebSocketsServer::handleHeader(WSclient_t * client, String * headerLine) {
|
||||
|
||||
// websocket requests always start with GET see rfc6455
|
||||
if(headerLine->startsWith("GET ")) {
|
||||
|
||||
// cut URL out
|
||||
client->cUrl = headerLine->substring(4, headerLine->indexOf(' ', 4));
|
||||
|
||||
@ -732,7 +742,7 @@ void WebSocketsServer::handleHeader(WSclient_t * client, String * headerLine) {
|
||||
client->cHttpHeadersValid = true;
|
||||
client->cMandatoryHeadersCount = 0;
|
||||
|
||||
} else if(headerLine->indexOf(':')) {
|
||||
} else if(headerLine->indexOf(':') >= 0) {
|
||||
String headerName = headerLine->substring(0, headerLine->indexOf(':'));
|
||||
String headerValue = headerLine->substring(headerLine->indexOf(':') + 1);
|
||||
|
||||
@ -773,11 +783,10 @@ void WebSocketsServer::handleHeader(WSclient_t * client, String * headerLine) {
|
||||
}
|
||||
|
||||
(*headerLine) = "";
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
|
||||
client->tcp->readStringUntil('\n', &(client->cHttpLine), std::bind(&WebSocketsServer::handleHeader, this, client, &(client->cHttpLine)));
|
||||
#endif
|
||||
} else {
|
||||
|
||||
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] Header read fin.\n", client->num);
|
||||
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] - cURL: %s\n", client->num, client->cUrl.c_str());
|
||||
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] - cIsUpgrade: %d\n", client->num, client->cIsUpgrade);
|
||||
@ -805,7 +814,7 @@ void WebSocketsServer::handleHeader(WSclient_t * client, String * headerLine) {
|
||||
if(!client->cHttpHeadersValid) {
|
||||
ok = false;
|
||||
}
|
||||
if (client->cMandatoryHeadersCount != _mandatoryHttpHeaderCount) {
|
||||
if(client->cMandatoryHeadersCount != _mandatoryHttpHeaderCount) {
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
@ -821,7 +830,6 @@ void WebSocketsServer::handleHeader(WSclient_t * client, String * headerLine) {
|
||||
}
|
||||
|
||||
if(ok) {
|
||||
|
||||
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] Websocket connection incoming.\n", client->num);
|
||||
|
||||
// generate Sec-WebSocket-Accept key
|
||||
@ -831,7 +839,8 @@ void WebSocketsServer::handleHeader(WSclient_t * client, String * headerLine) {
|
||||
|
||||
client->status = WSC_CONNECTED;
|
||||
|
||||
String handshake = WEBSOCKETS_STRING("HTTP/1.1 101 Switching Protocols\r\n"
|
||||
String handshake = WEBSOCKETS_STRING(
|
||||
"HTTP/1.1 101 Switching Protocols\r\n"
|
||||
"Server: arduino-WebSocketsServer\r\n"
|
||||
"Upgrade: websocket\r\n"
|
||||
"Connection: Upgrade\r\n"
|
||||
@ -841,27 +850,27 @@ void WebSocketsServer::handleHeader(WSclient_t * client, String * headerLine) {
|
||||
|
||||
if(_origin.length() > 0) {
|
||||
handshake += WEBSOCKETS_STRING("Access-Control-Allow-Origin: ");
|
||||
handshake +=_origin + NEW_LINE;
|
||||
handshake += _origin + NEW_LINE;
|
||||
}
|
||||
|
||||
if(client->cProtocol.length() > 0) {
|
||||
handshake += WEBSOCKETS_STRING("Sec-WebSocket-Protocol: ");
|
||||
handshake +=_protocol + NEW_LINE;
|
||||
handshake += _protocol + NEW_LINE;
|
||||
}
|
||||
|
||||
// header end
|
||||
handshake += NEW_LINE;
|
||||
|
||||
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] handshake %s", client->num, (uint8_t*)handshake.c_str());
|
||||
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] handshake %s", client->num, (uint8_t *)handshake.c_str());
|
||||
|
||||
write(client, (uint8_t*)handshake.c_str(), handshake.length());
|
||||
write(client, (uint8_t *)handshake.c_str(), handshake.length());
|
||||
|
||||
headerDone(client);
|
||||
|
||||
// send ping
|
||||
WebSockets::sendFrame(client, WSop_ping);
|
||||
|
||||
runCbEvent(client->num, WStype_CONNECTED, (uint8_t *) client->cUrl.c_str(), client->cUrl.length());
|
||||
runCbEvent(client->num, WStype_CONNECTED, (uint8_t *)client->cUrl.c_str(), client->cUrl.length());
|
||||
|
||||
} else {
|
||||
handleNonWebsocketConnection(client);
|
||||
@ -869,5 +878,49 @@ void WebSocketsServer::handleHeader(WSclient_t * client, String * headerLine) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* send heartbeat ping to server in set intervals
|
||||
*/
|
||||
void WebSocketsServer::handleHBPing(WSclient_t * client) {
|
||||
if(client->pingInterval == 0)
|
||||
return;
|
||||
uint32_t pi = millis() - client->lastPing;
|
||||
if(pi > client->pingInterval) {
|
||||
DEBUG_WEBSOCKETS("[WS-Server][%d] sending HB ping\n", client->num);
|
||||
if(sendPing(client->num)) {
|
||||
client->lastPing = millis();
|
||||
client->pongReceived = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* enable ping/pong heartbeat process
|
||||
* @param pingInterval uint32_t how often ping will be sent
|
||||
* @param pongTimeout uint32_t millis after which pong should timout if not received
|
||||
* @param disconnectTimeoutCount uint8_t how many timeouts before disconnect, 0=> do not disconnect
|
||||
*/
|
||||
void WebSocketsServer::enableHeartbeat(uint32_t pingInterval, uint32_t pongTimeout, uint8_t disconnectTimeoutCount) {
|
||||
_pingInterval = pingInterval;
|
||||
_pongTimeout = pongTimeout;
|
||||
_disconnectTimeoutCount = disconnectTimeoutCount;
|
||||
|
||||
WSclient_t * client;
|
||||
for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
|
||||
client = &_clients[i];
|
||||
WebSockets::enableHeartbeat(client, pingInterval, pongTimeout, disconnectTimeoutCount);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* disable ping/pong heartbeat process
|
||||
*/
|
||||
void WebSocketsServer::disableHeartbeat() {
|
||||
_pingInterval = 0;
|
||||
|
||||
WSclient_t * client;
|
||||
for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
|
||||
client = &_clients[i];
|
||||
client->pingInterval = 0;
|
||||
}
|
||||
}
|
@ -31,18 +31,14 @@
|
||||
#define WEBSOCKETS_SERVER_CLIENT_MAX (5)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
class WebSocketsServer: protected WebSockets {
|
||||
public:
|
||||
|
||||
class WebSocketsServer : protected WebSockets {
|
||||
public:
|
||||
#ifdef __AVR__
|
||||
typedef void (*WebSocketServerEvent)(uint8_t num, WStype_t type, uint8_t * payload, size_t length);
|
||||
typedef bool (*WebSocketServerHttpHeaderValFunc)(String headerName, String headerValue);
|
||||
#else
|
||||
typedef std::function<void (uint8_t num, WStype_t type, uint8_t * payload, size_t length)> WebSocketServerEvent;
|
||||
typedef std::function<bool (String headerName, String headerValue)> WebSocketServerHttpHeaderValFunc;
|
||||
typedef std::function<void(uint8_t num, WStype_t type, uint8_t * payload, size_t length)> WebSocketServerEvent;
|
||||
typedef std::function<bool(String headerName, String headerValue)> WebSocketServerHttpHeaderValFunc;
|
||||
#endif
|
||||
|
||||
WebSocketsServer(uint16_t port, String origin = "", String protocol = "arduino");
|
||||
@ -51,20 +47,19 @@ public:
|
||||
void begin(void);
|
||||
void close(void);
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||
void loop(void);
|
||||
#else
|
||||
// Async interface not need a loop call
|
||||
void loop(void) __attribute__ ((deprecated)) {}
|
||||
void loop(void) __attribute__((deprecated)) {}
|
||||
#endif
|
||||
|
||||
void onEvent(WebSocketServerEvent cbEvent);
|
||||
void onValidateHttpHeader(
|
||||
WebSocketServerHttpHeaderValFunc validationFunc,
|
||||
const char* mandatoryHttpHeaders[],
|
||||
const char * mandatoryHttpHeaders[],
|
||||
size_t mandatoryHttpHeaderCount);
|
||||
|
||||
|
||||
bool sendTXT(uint8_t num, uint8_t * payload, size_t length = 0, bool headerToPayload = false);
|
||||
bool sendTXT(uint8_t num, const uint8_t * payload, size_t length = 0);
|
||||
bool sendTXT(uint8_t num, char * payload, size_t length = 0, bool headerToPayload = false);
|
||||
@ -97,11 +92,16 @@ public:
|
||||
|
||||
int connectedClients(bool ping = false);
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
bool clientIsConnected(uint8_t num);
|
||||
|
||||
void enableHeartbeat(uint32_t pingInterval, uint32_t pongTimeout, uint8_t disconnectTimeoutCount);
|
||||
void disableHeartbeat();
|
||||
|
||||
#if(WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
|
||||
IPAddress remoteIP(uint8_t num);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
protected:
|
||||
uint16_t _port;
|
||||
String _origin;
|
||||
String _protocol;
|
||||
@ -118,6 +118,10 @@ protected:
|
||||
|
||||
bool _runnning;
|
||||
|
||||
uint32_t _pingInterval;
|
||||
uint32_t _pongTimeout;
|
||||
uint8_t _disconnectTimeoutCount;
|
||||
|
||||
bool newClient(WEBSOCKETS_NETWORK_CLASS * TCPclient);
|
||||
|
||||
void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin);
|
||||
@ -125,13 +129,15 @@ protected:
|
||||
void clientDisconnect(WSclient_t * client);
|
||||
bool clientIsConnected(WSclient_t * client);
|
||||
|
||||
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||
#if(WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
|
||||
void handleNewClients(void);
|
||||
void handleClientData(void);
|
||||
#endif
|
||||
|
||||
void handleHeader(WSclient_t * client, String * headerLine);
|
||||
|
||||
void handleHBPing(WSclient_t * client); // send ping in specified intervals
|
||||
|
||||
/**
|
||||
* called if a non Websocket connection is coming in.
|
||||
* Note: can be override
|
||||
@ -139,7 +145,8 @@ protected:
|
||||
*/
|
||||
virtual void handleNonWebsocketConnection(WSclient_t * client) {
|
||||
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] no Websocket connection close.\n", client->num);
|
||||
client->tcp->write("HTTP/1.1 400 Bad Request\r\n"
|
||||
client->tcp->write(
|
||||
"HTTP/1.1 400 Bad Request\r\n"
|
||||
"Server: arduino-WebSocket-Server\r\n"
|
||||
"Content-Type: text/plain\r\n"
|
||||
"Content-Length: 32\r\n"
|
||||
@ -155,8 +162,9 @@ protected:
|
||||
* Note: can be override
|
||||
* @param client WSclient_t * ptr to the client struct
|
||||
*/
|
||||
virtual void handleAuthorizationFailed(WSclient_t *client) {
|
||||
client->tcp->write("HTTP/1.1 401 Unauthorized\r\n"
|
||||
virtual void handleAuthorizationFailed(WSclient_t * client) {
|
||||
client->tcp->write(
|
||||
"HTTP/1.1 401 Unauthorized\r\n"
|
||||
"Server: arduino-WebSocket-Server\r\n"
|
||||
"Content-Type: text/plain\r\n"
|
||||
"Content-Length: 45\r\n"
|
||||
@ -198,15 +206,12 @@ protected:
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
/*
|
||||
* returns an indicator whether the given named header exists in the configured _mandatoryHttpHeaders collection
|
||||
* @param headerName String ///< the name of the header being checked
|
||||
*/
|
||||
bool hasMandatoryHeader(String headerName);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* WEBSOCKETSSERVER_H_ */
|
||||
|
Reference in New Issue
Block a user