Compare commits

...

69 Commits

Author SHA1 Message Date
32dd01b91b bump version to 2.1.1 2018-08-08 18:11:32 +02:00
388683d4cd fix compiler warnings for ESP32 - #319 2018-08-07 18:10:48 +02:00
38c401b8af adapt to ESP32 repo changes
4e5cbdaa7f
2018-08-07 18:06:32 +02:00
f7a7ab6ab4 wrap reasonCode in define
see #343
2018-07-04 16:29:28 +02:00
bdee8b9744 call end for ESP8266_ASYNC TCP Server 2018-06-21 09:30:11 +02:00
7ddcdc2bd3 add info for AVR usage with version 2.x.x 2018-05-12 12:40:56 +02:00
bde97179bf fix unused parameter warnings
fix switch warinings

part of #319
2018-05-12 11:39:59 +02:00
9ce044e550 code style 2018-05-12 11:34:12 +02:00
a796079b0c fix code style 2018-05-12 11:27:03 +02:00
e8c0d775fb fix #146 HTTP Header handler 2018-05-12 11:22:16 +02:00
5636b02b46 add WebSocketServerAllFunctionsDemo (WIP) 2018-05-10 20:47:05 +02:00
4b33575af1 add connectedClients see #242 2018-05-10 20:43:08 +02:00
486a612693 allow usage of IPAddress #230 2018-05-10 20:12:48 +02:00
ea8e81c6ce add close #322 2018-05-10 18:56:31 +02:00
8a187b523b Merge pull request #323 from chemicstry/printf_fix
Fix format specifiers
2018-05-10 18:48:43 +02:00
ac8d806085 Fix format specifiers 2018-05-10 01:16:39 +03:00
02e0128802 Update index.js
fix port
2018-04-17 19:42:47 +02:00
01e1fdfb50 Merge pull request #304 from CarlosRDomin/master
Allow custom WEBSOCKETS_SERVER_CLIENT_MAX definition
2018-04-03 19:21:22 +02:00
d02932ef21 Allow custom WEBSOCKETS_SERVER_CLIENT_MAX definition 2018-04-02 22:17:34 -07:00
5bf8b2407e Merge pull request #296 from getbyte/master
fix undefined virtual methods
2018-03-18 07:34:57 +01:00
50d9a8d6e5 fix undefined virtual methods 2018-03-18 01:25:49 +03:00
7443f9b1dc Merge pull request #292 from ivankravets/patch-2
Update supported platforms, allow PIO to detect examples automatically
2018-03-07 18:49:05 +01:00
4b04f6fa53 Update supported platforms, allow PIO to detect examples automatically 2018-03-07 10:33:33 +02:00
a67a8dd0e0 Merge pull request #265 from Links2004/esp32
ESP32 support
improved test
sorted examples
2018-02-07 18:32:49 +01:00
4759a66a62 Arduino 1.8.5 is very peaky with the board parameters 2018-02-07 18:15:50 +01:00
48e690a42a bump version to 2.1.0
travis arduino 1.8.5
2018-02-07 18:11:08 +01:00
b059d0711c sort examples by platform
rework the travis tests
create ESP32 examples
2018-02-07 17:28:17 +01:00
a09b8c48ee ide version 2018-02-06 21:58:26 +01:00
94eb4b12e5 IDE version 2018-02-06 21:52:13 +01:00
2df62558f1 more verbose verify step 2018-02-06 21:48:49 +01:00
86074c90ae update IDE test 2018-02-06 21:41:47 +01:00
d73e3ecc9c skip some test for ESP32 2018-02-06 21:37:24 +01:00
f62aa6478d more ESP32 stuff 2018-02-06 21:36:44 +01:00
d340c89b09 ... 2018-02-06 21:26:06 +01:00
05f4cfd7bf fix includes for WebSocketClient.ino 2018-02-06 21:17:14 +01:00
46cff38287 fix ESP32 sha1 problem 2018-02-06 21:12:39 +01:00
0b35e32b2a examples for ESP32 2018-02-06 21:10:29 +01:00
255f40eaa7 travis.yml 2018-02-06 20:46:17 +01:00
5e1f9b1c26 CORE_HAS_LIBB64 for ESP32 2018-02-06 20:44:10 +01:00
30b6deedd2 use travis matrix 2018-02-06 20:41:36 +01:00
0e6e1c76ee Merge pull request #281 from baggior/esp32 2018-02-06 20:24:40 +01:00
887683fabb Merge branch 'master' into esp32 2018-02-06 20:24:03 +01:00
0b10299549 travis builds for ESP32 2018-02-06 20:22:29 +01:00
1d300084e0 fix 2018-02-06 09:57:04 +01:00
d9e1e97cf6 Merge branch 'master' into esp32 2018-01-23 12:40:10 +01:00
642750e232 Merge pull request #245 from PeterEmbedded/patch-1
Added some missing comments to WebSockets.cpp
2017-10-16 19:04:40 +02:00
a0c714bf10 Update WebSockets.cpp
Added some missing comments
2017-10-16 13:01:00 +02:00
c5461d5779 memset zero _clients struct for server
fixes #244
2017-10-06 18:30:05 +02:00
b87bce4466 add virtual to destructor #243 2017-10-04 19:17:21 +02:00
9608c2d210 Merge pull request #240 from mgbckr/master
Add example for plain STOMP connection
2017-09-25 21:31:24 +02:00
4baf4896cc Add missing Hash.h library 2017-09-25 17:20:07 +02:00
4fd2e9d993 Add example for plain STOMP connection 2017-09-25 15:04:56 +02:00
fa580a568f Merge pull request #223 from robokoding/master
Add ESP32 support from @robokoding
2017-09-20 18:53:55 +02:00
a93a845780 add: ESP32 support 2017-09-03 10:06:00 +02:00
83a1539e1e fix: ESP32 new client connection 2017-09-03 09:55:15 +02:00
1bd4638621 bump version to 2.0.10 2017-08-21 21:44:30 +02:00
f40a390ab1 workaround windows gcc Template issue (#228, #229) 2017-08-21 21:39:14 +02:00
b6c27f74cd bump version to 2.0.9 2017-08-19 22:05:33 +02:00
c64a082270 Merge branch 'write_big_data' 2017-08-19 21:36:10 +02:00
522a67bc1b add setReconnectInterval for the Client 2017-08-19 21:16:07 +02:00
29df9c30f7 bump version to 2.0.8 2017-08-18 17:16:51 +02:00
4c1c5378cb esp32 no hasClient function 2017-07-30 01:40:36 +02:00
dbabc1025b added esp32 support 2017-07-30 00:58:15 +02:00
1d40160d99 added esp32 support 2017-07-30 00:54:17 +02:00
a388676b40 added remoteIP for esp32 2017-07-30 00:22:23 +02:00
8c19d7ba48 Update WebSockets.cpp
added esp32 hwcrypto for sha1
2017-07-30 00:21:13 +02:00
4fc80871a6 Update WebSockets.h 2017-07-30 00:18:37 +02:00
c911776860 add virtual to write
fix some naming
2017-04-10 17:49:42 +02:00
adb52b11e9 handle cases when not all data can be written to TCP stack #187 2017-04-09 17:58:23 +02:00
33 changed files with 1080 additions and 253 deletions

View File

@ -2,28 +2,31 @@ sudo: false
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="esp32" BOARD="espressif:esp32:esp32:FlashFreq=80" IDE_VERSION=1.8.5
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
- wget http://downloads.arduino.cc/arduino-1.6.5-linux64.tar.xz
- tar xf arduino-1.6.5-linux64.tar.xz
- mv arduino-1.6.5 $HOME/arduino_ide
- 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
- cp -r $TRAVIS_BUILD_DIR $HOME/Arduino/libraries/arduinoWebSockets
- cd $HOME/arduino_ide/hardware
- mkdir esp8266com
- cd esp8266com
- git clone https://github.com/esp8266/Arduino.git esp8266
- cd esp8266/tools
- python get.py
- source $TRAVIS_BUILD_DIR/travis/common.sh
- arduino --board esp8266com:esp8266:generic --save-prefs
- get_core $CPU
- cd $TRAVIS_BUILD_DIR
- arduino --board $BOARD --save-prefs
- arduino --get-pref sketchbook.path
- build_sketches arduino $HOME/Arduino/libraries/arduinoWebSockets esp8266
- build_sketches arduino $HOME/Arduino/libraries/arduinoWebSockets/examples/$CPU $CPU
notifications:
email:

View File

@ -23,7 +23,8 @@ a WebSocket Server and Client for Arduino based on RFC6455.
- wss / SSL is not possible.
##### Supported Hardware #####
- ESP8266 [Arduino for ESP8266](https://github.com/Links2004/Arduino)
- ESP8266 [Arduino for ESP8266](https://github.com/esp8266/Arduino/)
- ESP32 [Arduino for ESP32](https://github.com/espressif/arduino-esp32)
- ESP31B
- Particle with STM32 ARM Cortex M3
- ATmega328 with Ethernet Shield (ATmega branch)

View File

@ -0,0 +1,110 @@
/*
* WebSocketClient.ino
*
* Created on: 24.05.2015
*
*/
#include <Arduino.h>
#include <WiFi.h>
#include <WiFiMulti.h>
#include <WiFiClientSecure.h>
#include <WebSocketsClient.h>
WiFiMulti WiFiMulti;
WebSocketsClient webSocket;
#define USE_SERIAL Serial1
void hexdump(const void *mem, uint32_t len, uint8_t cols = 16) {
const uint8_t* src = (const uint8_t*) mem;
USE_SERIAL.printf("\n[HEXDUMP] Address: 0x%08X len: 0x%X (%d)", (ptrdiff_t)src, len, len);
for(uint32_t i = 0; i < len; i++) {
if(i % cols == 0) {
USE_SERIAL.printf("\n[0x%08X] 0x%08X: ", (ptrdiff_t)src, i);
}
USE_SERIAL.printf("%02X ", *src);
src++;
}
USE_SERIAL.printf("\n");
}
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;
case WStype_ERROR:
case WStype_FRAGMENT_TEXT_START:
case WStype_FRAGMENT_BIN_START:
case WStype_FRAGMENT:
case WStype_FRAGMENT_FIN:
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);
}
WiFiMulti.addAP("SSID", "passpasspass");
//WiFi.disconnect();
while(WiFiMulti.run() != WL_CONNECTED) {
delay(100);
}
// server address, port and URL
webSocket.begin("192.168.0.123", 81, "/");
// event handler
webSocket.onEvent(webSocketEvent);
// use HTTP Basic Authorization this is optional remove if not needed
webSocket.setAuthorization("user", "Password");
// try ever 5000 again if connection has failed
webSocket.setReconnectInterval(5000);
}
void loop() {
webSocket.loop();
}

View File

@ -1,25 +1,39 @@
/*
* WebSocketClient.ino
* WebSocketClientSSL.ino
*
* Created on: 24.05.2015
* Created on: 10.12.2015
*
* note SSL is only possible with the ESP8266
*
*/
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <WiFi.h>
#include <WiFiMulti.h>
#include <WiFiClientSecure.h>
#include <WebSocketsClient.h>
#include <Hash.h>
ESP8266WiFiMulti WiFiMulti;
WiFiMulti WiFiMulti;
WebSocketsClient webSocket;
#define USE_SERIAL Serial1
void hexdump(const void *mem, uint32_t len, uint8_t cols = 16) {
const uint8_t* src = (const uint8_t*) mem;
USE_SERIAL.printf("\n[HEXDUMP] Address: 0x%08X len: 0x%X (%d)", (ptrdiff_t)src, len, len);
for(uint32_t i = 0; i < len; i++) {
if(i % cols == 0) {
USE_SERIAL.printf("\n[0x%08X] 0x%08X: ", (ptrdiff_t)src, i);
}
USE_SERIAL.printf("%02X ", *src);
src++;
}
USE_SERIAL.printf("\n");
}
void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {
@ -30,7 +44,7 @@ void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {
case WStype_CONNECTED:
{
USE_SERIAL.printf("[WSc] Connected to url: %s\n", payload);
// send message to server when Connected
webSocket.sendTXT("Connected");
}
@ -48,6 +62,12 @@ void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {
// send data to server
// webSocket.sendBIN(payload, length);
break;
case WStype_ERROR:
case WStype_FRAGMENT_TEXT_START:
case WStype_FRAGMENT_BIN_START:
case WStype_FRAGMENT:
case WStype_FRAGMENT_FIN:
break;
}
}
@ -76,8 +96,7 @@ void setup() {
delay(100);
}
webSocket.begin("192.168.0.123", 81);
//webSocket.setAuthorization("user", "Password"); // HTTP Basic Authorization
webSocket.beginSSL("192.168.0.123", 81);
webSocket.onEvent(webSocketEvent);
}

View File

@ -0,0 +1,104 @@
/*
* WebSocketServer.ino
*
* Created on: 22.05.2015
*
*/
#include <Arduino.h>
#include <WiFi.h>
#include <WiFiMulti.h>
#include <WiFiClientSecure.h>
#include <WebSocketsServer.h>
WiFiMulti WiFiMulti;
WebSocketsServer webSocket = WebSocketsServer(81);
#define USE_SERIAL Serial1
void hexdump(const void *mem, uint32_t len, uint8_t cols = 16) {
const uint8_t* src = (const uint8_t*) mem;
USE_SERIAL.printf("\n[HEXDUMP] Address: 0x%08X len: 0x%X (%d)", (ptrdiff_t)src, len, len);
for(uint32_t i = 0; i < len; i++) {
if(i % cols == 0) {
USE_SERIAL.printf("\n[0x%08X] 0x%08X: ", (ptrdiff_t)src, i);
}
USE_SERIAL.printf("%02X ", *src);
src++;
}
USE_SERIAL.printf("\n");
}
void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) {
switch(type) {
case WStype_DISCONNECTED:
USE_SERIAL.printf("[%u] Disconnected!\n", num);
break;
case WStype_CONNECTED:
{
IPAddress ip = webSocket.remoteIP(num);
USE_SERIAL.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload);
// send message to client
webSocket.sendTXT(num, "Connected");
}
break;
case WStype_TEXT:
USE_SERIAL.printf("[%u] get Text: %s\n", num, payload);
// send message to client
// webSocket.sendTXT(num, "message here");
// send data to all connected clients
// webSocket.broadcastTXT("message here");
break;
case WStype_BIN:
USE_SERIAL.printf("[%u] get binary length: %u\n", num, length);
hexdump(payload, length);
// send message to client
// webSocket.sendBIN(num, payload, length);
break;
case WStype_ERROR:
case WStype_FRAGMENT_TEXT_START:
case WStype_FRAGMENT_BIN_START:
case WStype_FRAGMENT:
case WStype_FRAGMENT_FIN:
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);
}
WiFiMulti.addAP("SSID", "passpasspass");
while(WiFiMulti.run() != WL_CONNECTED) {
delay(100);
}
webSocket.begin();
webSocket.onEvent(webSocketEvent);
}
void loop() {
webSocket.loop();
}

View File

@ -0,0 +1,92 @@
/*
* WebSocketClient.ino
*
* Created on: 24.05.2015
*
*/
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <WebSocketsClient.h>
#include <Hash.h>
ESP8266WiFiMulti WiFiMulti;
WebSocketsClient webSocket;
#define USE_SERIAL Serial1
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(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);
}
WiFiMulti.addAP("SSID", "passpasspass");
//WiFi.disconnect();
while(WiFiMulti.run() != WL_CONNECTED) {
delay(100);
}
// server address, port and URL
webSocket.begin("192.168.0.123", 81, "/");
// event handler
webSocket.onEvent(webSocketEvent);
// use HTTP Basic Authorization this is optional remove if not needed
webSocket.setAuthorization("user", "Password");
// try ever 5000 again if connection has failed
webSocket.setReconnectInterval(5000);
}
void loop() {
webSocket.loop();
}

View File

@ -0,0 +1,149 @@
/*
WebSocketClientStomp.ino
Example for connecting and maintining a connection with a STOMP websocket connection.
In this example, we connect to a Spring application (see https://docs.spring.io/spring/docs/current/spring-framework-reference/html/websocket.html).
Created on: 25.09.2017
Author: Martin Becker <mgbckr>, Contact: becker@informatik.uni-wuerzburg.de
*/
// PRE
#define USE_SERIAL Serial
// LIBRARIES
#include <Arduino.h>
#include <Hash.h>
#include <ESP8266WiFi.h>
#include <WebSocketsClient.h>
// SETTINGS
const char* wlan_ssid = "yourssid";
const char* wlan_password = "somepassword";
const char* ws_host = "the.host.net";
const int ws_port = 80;
// URL for STOMP endpoint.
// For the default config of Spring's STOMP support, the default URL is "/socketentry/websocket".
const char* stompUrl = "/socketentry/websocket"; // don't forget the leading "/" !!!
// VARIABLES
WebSocketsClient webSocket;
// FUNCTIONS
/**
* STOMP messages need to be NULL-terminated (i.e., \0 or \u0000).
* However, when we send a String or a char[] array without specifying
* a length, the size of the message payload is derived by strlen() internally,
* thus dropping any NULL values appended to the "msg"-String.
*
* To solve this, we first convert the String to a NULL terminated char[] array
* via "c_str" and set the length of the payload to include the NULL value.
*/
void sendMessage(String & msg) {
webSocket.sendTXT(msg.c_str(), msg.length() + 1);
}
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);
String msg = "CONNECT\r\naccept-version:1.1,1.0\r\nheart-beat:10000,10000\r\n\r\n";
sendMessage(msg);
}
break;
case WStype_TEXT:
{
// #####################
// handle STOMP protocol
// #####################
String text = (char*) payload;
USE_SERIAL.printf("[WSc] get text: %s\n", payload);
if (text.startsWith("CONNECTED")) {
// subscribe to some channels
String msg = "SUBSCRIBE\nid:sub-0\ndestination:/user/queue/messages\n\n";
sendMessage(msg);
delay(1000);
// and send a message
msg = "SEND\ndestination:/app/message\n\n{\"user\":\"esp\",\"message\":\"Hello!\"}";
sendMessage(msg);
delay(1000);
} else {
// do something with messages
}
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() {
// setup serial
// USE_SERIAL.begin(921600);
USE_SERIAL.begin(115200);
// USE_SERIAL.setDebugOutput(true);
USE_SERIAL.println();
// connect to WiFi
USE_SERIAL.print("Logging into WLAN: "); Serial.print(wlan_ssid); Serial.print(" ...");
WiFi.mode(WIFI_STA);
WiFi.begin(wlan_ssid, wlan_password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
USE_SERIAL.print(".");
}
USE_SERIAL.println(" success.");
USE_SERIAL.print("IP: "); USE_SERIAL.println(WiFi.localIP());
// connect to websocket
webSocket.begin(ws_host, ws_port, stompUrl);
webSocket.setExtraHeaders(); // remove "Origin: file://" header because it breaks the connection with Spring's default websocket config
// webSocket.setExtraHeaders("foo: I am so funny\r\nbar: not"); // some headers, in case you feel funny
webSocket.onEvent(webSocketEvent);
}
void loop() {
webSocket.loop();
}

View File

@ -1,8 +1,8 @@
/*
WebSocketClientSockJsAndStomp.ino
WebSocketClientStompOverSockJs.ino
Example for connecting and maintining a connection with a SockJS+STOMP websocket connection.
In this example we connect to a Spring application (see https://docs.spring.io/spring/docs/current/spring-framework-reference/html/websocket.html).
In this example, we connect to a Spring application (see https://docs.spring.io/spring/docs/current/spring-framework-reference/html/websocket.html).
Created on: 18.07.2017
Author: Martin Becker <mgbckr>, Contact: becker@informatik.uni-wuerzburg.de
@ -33,7 +33,7 @@ const int ws_port = 80;
// base URL for SockJS (websocket) connection
// The complete URL will look something like this(cf. http://sockjs.github.io/sockjs-protocol/sockjs-protocol-0.3.3.html#section-36):
// ws://<ws_host>:<ws_port>/<ws_baseurl>/<3digits>/<randomstring>/websocket
// For the default config of Spring's SockJS/STOMP support the default base URL is "/socketentry/".
// For the default config of Spring's SockJS/STOMP support, the default base URL is "/socketentry/".
const char* ws_baseurl = "/socketentry/"; // don't forget leading and trailing "/" !!!
@ -58,7 +58,7 @@ void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {
case WStype_TEXT:
{
// #####################
// handle STOMP protocol
// handle SockJs+STOMP protocol
// #####################
String text = (char*) payload;

View File

@ -0,0 +1,132 @@
/*
* WebSocketServerAllFunctionsDemo.ino
*
* Created on: 10.05.2018
*
*/
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <WebSocketsServer.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <Hash.h>
#define LED_RED 15
#define LED_GREEN 12
#define LED_BLUE 13
#define USE_SERIAL Serial
ESP8266WiFiMulti WiFiMulti;
ESP8266WebServer server(80);
WebSocketsServer webSocket = WebSocketsServer(81);
void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) {
switch(type) {
case WStype_DISCONNECTED:
USE_SERIAL.printf("[%u] Disconnected!\n", num);
break;
case WStype_CONNECTED: {
IPAddress ip = webSocket.remoteIP(num);
USE_SERIAL.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload);
// send message to client
webSocket.sendTXT(num, "Connected");
}
break;
case WStype_TEXT:
USE_SERIAL.printf("[%u] get Text: %s\n", num, payload);
if(payload[0] == '#') {
// we get RGB data
// decode rgb data
uint32_t rgb = (uint32_t) strtol((const char *) &payload[1], NULL, 16);
analogWrite(LED_RED, ((rgb >> 16) & 0xFF));
analogWrite(LED_GREEN, ((rgb >> 8) & 0xFF));
analogWrite(LED_BLUE, ((rgb >> 0) & 0xFF));
}
break;
}
}
void setup() {
//USE_SERIAL.begin(921600);
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);
}
pinMode(LED_RED, OUTPUT);
pinMode(LED_GREEN, OUTPUT);
pinMode(LED_BLUE, OUTPUT);
digitalWrite(LED_RED, 1);
digitalWrite(LED_GREEN, 1);
digitalWrite(LED_BLUE, 1);
WiFiMulti.addAP("SSID", "passpasspass");
while(WiFiMulti.run() != WL_CONNECTED) {
delay(100);
}
// start webSocket server
webSocket.begin();
webSocket.onEvent(webSocketEvent);
if(MDNS.begin("esp8266")) {
USE_SERIAL.println("MDNS responder started");
}
// handle index
server.on("/", []() {
// send index.html
server.send(200, "text/html", "<html><head><script>var connection = new WebSocket('ws://'+location.hostname+':81/', ['arduino']);connection.onopen = function () { connection.send('Connect ' + new Date()); }; connection.onerror = function (error) { console.log('WebSocket Error ', error);};connection.onmessage = function (e) { console.log('Server: ', e.data);};function sendRGB() { var r = parseInt(document.getElementById('r').value).toString(16); var g = parseInt(document.getElementById('g').value).toString(16); var b = parseInt(document.getElementById('b').value).toString(16); if(r.length < 2) { r = '0' + r; } if(g.length < 2) { g = '0' + g; } if(b.length < 2) { b = '0' + b; } var rgb = '#'+r+g+b; console.log('RGB: ' + rgb); connection.send(rgb); }</script></head><body>LED Control:<br/><br/>R: <input id=\"r\" type=\"range\" min=\"0\" max=\"255\" step=\"1\" oninput=\"sendRGB();\" /><br/>G: <input id=\"g\" type=\"range\" min=\"0\" max=\"255\" step=\"1\" oninput=\"sendRGB();\" /><br/>B: <input id=\"b\" type=\"range\" min=\"0\" max=\"255\" step=\"1\" oninput=\"sendRGB();\" /><br/></body></html>");
});
server.begin();
// Add service to MDNS
MDNS.addService("http", "tcp", 80);
MDNS.addService("ws", "tcp", 81);
digitalWrite(LED_RED, 0);
digitalWrite(LED_GREEN, 0);
digitalWrite(LED_BLUE, 0);
}
unsigned long last_10sec = 0;
unsigned int counter = 0;
void loop() {
unsigned long t = millis();
webSocket.loop();
server.handleClient();
if((t - last_10sec) > 10 * 1000) {
counter++;
bool ping = (counter % 2);
int i = webSocket.connectedClients(ping);
USE_SERIAL.printf("%d Connected websocket clients ping: %d\n", i, ping);
last_10sec = millis();
}
}

View File

@ -23,7 +23,7 @@
ESP8266WiFiMulti WiFiMulti;
ESP8266WebServer server = ESP8266WebServer(80);
ESP8266WebServer server(80);
WebSocketsServer webSocket = WebSocketsServer(81);
void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) {
@ -119,4 +119,3 @@ void loop() {
webSocket.loop();
server.handleClient();
}

View File

@ -13,7 +13,7 @@
"type": "git",
"url": "https://github.com/Links2004/arduinoWebSockets.git"
},
"version": "2.0.7",
"version": "2.1.1",
"license": "LGPL-2.1",
"export": {
"exclude": [
@ -21,8 +21,5 @@
]
},
"frameworks": "arduino",
"platforms": "*",
"examples": [
"examples/*/*.ino"
]
"platforms": "atmelavr, espressif8266, espressif32"
}

View File

@ -1,7 +1,7 @@
name=WebSockets
version=2.0.7
version=2.1.1
author=Markus Sattler
maintainer=Markus Sattler
maintainer=Markus Sattler
sentence=WebSockets for Arduino (Server + Client)
paragraph=use 2.x.x for ESP and 1.3 for AVR
category=Communication

View File

@ -38,6 +38,8 @@ extern "C" {
#ifdef ESP8266
#include <Hash.h>
#elif defined(ESP32)
#include <hwcrypto/sha.h>
#else
extern "C" {
@ -46,12 +48,13 @@ extern "C" {
#endif
/**
*
* @param client WSclient_t * ptr to the client struct
* @param code uint16_t see RFC
* @param reason
* @param reasonLen
* @param reason ptr to the disconnect reason message
* @param reasonLen length of the disconnect reason message
*/
void WebSockets::clientDisconnect(WSclient_t * client, uint16_t code, char * reason, size_t reasonLen) {
DEBUG_WEBSOCKETS("[WS][%d][handleWebsocket] clientDisconnect code: %u\n", client->num, code);
@ -72,8 +75,8 @@ void WebSockets::clientDisconnect(WSclient_t * client, uint16_t code, char * rea
*
* @param client WSclient_t * ptr to the client struct
* @param opcode WSopcode_t
* @param payload uint8_t *
* @param length size_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 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!)
@ -91,7 +94,7 @@ bool WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * pay
return false;
}
DEBUG_WEBSOCKETS("[WS][%d][sendFrame] ------- send massage frame -------\n", client->num);
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) {
@ -233,24 +236,24 @@ bool WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * pay
// header has be added to payload
// payload is forced to reserved 14 Byte but we may not need all based on the length and mask settings
// offset in payload is calculatetd 14 - headerSize
if(client->tcp->write(&payloadPtr[(WEBSOCKETS_MAX_HEADER_SIZE - headerSize)], (length + headerSize)) != (length + headerSize)) {
if(write(client, &payloadPtr[(WEBSOCKETS_MAX_HEADER_SIZE - headerSize)], (length + headerSize)) != (length + headerSize)) {
ret = false;
}
} else {
// send header
if(client->tcp->write(&buffer[0], headerSize) != headerSize) {
if(write(client, &buffer[0], headerSize) != headerSize) {
ret = false;
}
if(payloadPtr && length > 0) {
// send payload
if(client->tcp->write(&payloadPtr[0], length) != length) {
if(write(client, &payloadPtr[0], length) != length) {
ret = false;
}
}
}
DEBUG_WEBSOCKETS("[WS][%d][sendFrame] sending Frame Done (%uus).\n", client->num, (micros() - start));
DEBUG_WEBSOCKETS("[WS][%d][sendFrame] sending Frame Done (%luus).\n", client->num, (micros() - start));
#ifdef WEBSOCKETS_USE_BIG_MEM
if(useInternBuffer && payloadPtr) {
@ -268,7 +271,7 @@ bool WebSockets::sendFrame(WSclient_t * client, WSopcode_t opcode, uint8_t * pay
void WebSockets::headerDone(WSclient_t * client) {
client->status = WSC_CONNECTED;
client->cWsRXsize = 0;
DEBUG_WEBSOCKETS("[WS][%d][headerDone] Header Handling Done (%uus).\n", client->num);
DEBUG_WEBSOCKETS("[WS][%d][headerDone] Header Handling Done.\n", client->num);
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
client->cHttpLine = "";
handleWebsocket(client);
@ -437,11 +440,12 @@ void WebSockets::handleWebsocketPayloadCb(WSclient_t * client, bool ok, uint8_t
DEBUG_WEBSOCKETS("[WS][%d][handleWebsocket] get pong (%s)\n", client->num, payload ? (const char*)payload : "");
break;
case WSop_close: {
uint16_t reasonCode = 1000;
if(header->payloadLen >= 2) {
reasonCode = payload[0] << 8 | payload[1];
}
#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);
if(header->payloadLen > 2) {
DEBUG_WEBSOCKETS(" (%s)\n", (payload + 2));
@ -483,6 +487,9 @@ String WebSockets::acceptKey(String & clientKey) {
uint8_t sha1HashBin[20] = { 0 };
#ifdef ESP8266
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]);
#else
clientKey += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
SHA1_CTX ctx;
@ -541,7 +548,7 @@ bool WebSockets::readCb(WSclient_t * client, uint8_t * out, size_t n, WSreadWait
#else
unsigned long t = millis();
size_t len;
DEBUG_WEBSOCKETS("[readCb] n: %d t: %d\n", n, t);
DEBUG_WEBSOCKETS("[readCb] n: %zu t: %lu\n", n, t);
while(n > 0) {
if(client->tcp == NULL) {
DEBUG_WEBSOCKETS("[readCb] tcp is null!\n");
@ -560,7 +567,7 @@ bool WebSockets::readCb(WSclient_t * client, uint8_t * out, size_t n, WSreadWait
}
if((millis() - t) > WEBSOCKETS_TCP_TIMEOUT) {
DEBUG_WEBSOCKETS("[readCb] receive TIMEOUT! %d\n", (millis() - t));
DEBUG_WEBSOCKETS("[readCb] receive TIMEOUT! %lu\n", (millis() - t));
if(cb) {
cb(client, false);
}
@ -593,3 +600,56 @@ bool WebSockets::readCb(WSclient_t * client, uint8_t * out, size_t n, WSreadWait
#endif
return true;
}
/**
* write x byte to tcp or get timeout
* @param client WSclient_t *
* @param out uint8_t * data buffer
* @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;
unsigned long t = millis();
size_t len = 0;
size_t total = 0;
DEBUG_WEBSOCKETS("[write] n: %zu t: %lu\n", n, t);
while(n > 0) {
if(client->tcp == NULL) {
DEBUG_WEBSOCKETS("[write] tcp is null!\n");
break;
}
if(!client->tcp->connected()) {
DEBUG_WEBSOCKETS("[write] not connected!\n");
break;
}
if((millis() - t) > WEBSOCKETS_TCP_TIMEOUT) {
DEBUG_WEBSOCKETS("[write] write TIMEOUT! %lu\n", (millis() - t));
break;
}
len = client->tcp->write((const uint8_t*)out, n);
if(len) {
t = millis();
out += len;
n -= len;
total += len;
//DEBUG_WEBSOCKETS("write %d left %d!\n", len, n);
} else {
//DEBUG_WEBSOCKETS("write %d failed left %d!\n", len, n);
}
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
delay(0);
#endif
}
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));
}

View File

@ -30,39 +30,54 @@
#define bit(b) (1UL << (b)) // Taken directly from Arduino.h
#else
#include <Arduino.h>
#include <IPAddress.h>
#endif
#ifdef ARDUINO_ARCH_AVR
#error Version 2.x.x currently does not support Arduino with AVR since there is no support for std namespace of c++.
#error Use Version 1.x.x. (ATmega branch)
#else
#include <functional>
#endif
#ifndef NODEBUG_WEBSOCKETS
#ifdef DEBUG_ESP_PORT
#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(...)
#define NODEBUG_WEBSOCKETS
#endif
#ifdef ESP8266
#if defined(ESP8266) || defined(ESP32)
#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
#else
#ifdef STM32_DEVICE
#elif defined(STM32_DEVICE)
#define WEBSOCKETS_MAX_DATA_SIZE (15*1024)
#define WEBSOCKETS_USE_BIG_MEM
#define GET_FREE_HEAP System.freeMemory()
#else
//atmega328p has only 2KB ram!
#define WEBSOCKETS_MAX_DATA_SIZE (1024)
// moves all Header strings to Flash
#define WEBSOCKETS_SAVE_RAM
#endif
#endif
#define WEBSOCKETS_TCP_TIMEOUT (2000)
@ -70,36 +85,46 @@
#define NETWORK_ESP8266 (1)
#define NETWORK_W5100 (2)
#define NETWORK_ENC28J60 (3)
#define NETWORK_ESP32 (4)
// max size of the WS Message Header
#define WEBSOCKETS_MAX_HEADER_SIZE (14)
#if !defined(WEBSOCKETS_NETWORK_TYPE)
#if !defined(WEBSOCKETS_NETWORK_TYPE)
// select Network type based
#if defined(ESP8266) || defined(ESP31B)
#define WEBSOCKETS_NETWORK_TYPE NETWORK_ESP8266
//#define WEBSOCKETS_NETWORK_TYPE NETWORK_ESP8266_ASYNC
//#define WEBSOCKETS_NETWORK_TYPE NETWORK_W5100
#elif defined(ESP32)
#define WEBSOCKETS_NETWORK_TYPE NETWORK_ESP32
#else
#define WEBSOCKETS_NETWORK_TYPE NETWORK_W5100
#endif
#endif
// Includes and defined based on Network Type
#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) && !defined(ESP31B)
#if defined(ESP8266)
#include <ESP8266WiFi.h>
#elif defined(ESP32)
#include <WiFi.h>
#include <WiFiClientSecure.h>
#elif defined(ESP31B)
#include <ESP31BWiFi.h>
#else
#error "network type ESP8266 ASYNC only possible on the ESP mcu!"
#endif
#ifdef ESP8266
#include <ESP8266WiFi.h>
#else
#include <ESP31BWiFi.h>
#endif
#include <ESPAsyncTCP.h>
#include <ESPAsyncTCPbuffer.h>
#define WEBSOCKETS_NETWORK_CLASS AsyncTCPbuffer
@ -137,6 +162,13 @@
#define WEBSOCKETS_NETWORK_CLASS UIPClient
#define WEBSOCKETS_NETWORK_SERVER_CLASS UIPServer
#elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
#include <WiFi.h>
#include <WiFiClientSecure.h>
#define WEBSOCKETS_NETWORK_CLASS WiFiClient
#define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer
#else
#error "no network type selected!"
#endif
@ -201,7 +233,7 @@ typedef struct {
bool isSocketIO; ///< client for socket.io server
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
bool isSSL; ///< run in ssl mode
WiFiClientSecure * ssl;
#endif
@ -247,10 +279,10 @@ class WebSockets {
typedef std::function<void(WSclient_t * client, bool ok)> WSreadWaitCb;
#endif
virtual void clientDisconnect(WSclient_t * client);
virtual bool clientIsConnected(WSclient_t * client);
virtual void clientDisconnect(WSclient_t * client) = 0;
virtual bool clientIsConnected(WSclient_t * client) = 0;
virtual void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin);
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);
@ -267,8 +299,13 @@ class WebSockets {
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);
};
#ifndef UNUSED
#define UNUSED(var) (void)(var)
#endif
#endif /* WEBSOCKETS_H_ */

View File

@ -25,7 +25,6 @@
#include "WebSockets.h"
#include "WebSocketsClient.h"
WebSocketsClient::WebSocketsClient() {
_cbEvent = NULL;
_client.num = 0;
@ -42,14 +41,14 @@ WebSocketsClient::~WebSocketsClient() {
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)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
_fingerprint = "";
#endif
_client.num = 0;
_client.status = WSC_NOT_CONNECTED;
_client.tcp = NULL;
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
_client.isSSL = false;
_client.ssl = NULL;
#endif
@ -75,13 +74,20 @@ void WebSocketsClient::begin(const char *host, uint16_t port, const char * url,
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
asyncConnect();
#endif
_lastConnectionFail = 0;
_reconnectInterval = 500;
}
void WebSocketsClient::begin(String host, uint16_t port, String url, String protocol) {
begin(host.c_str(), port, url.c_str(), protocol.c_str());
}
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
void WebSocketsClient::begin(IPAddress host, uint16_t port, const char * url, const char * protocol) {
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) {
begin(host, port, url, protocol);
_client.isSSL = true;
@ -102,7 +108,7 @@ 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)
#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) {
begin(host, port, url, protocol);
_client.isSocketIO = true;
@ -121,8 +127,12 @@ void WebSocketsClient::beginSocketIOSSL(String host, uint16_t port, String url,
*/
void WebSocketsClient::loop(void) {
if(!clientIsConnected(&_client)) {
// do not flood the server
if((millis() - _lastConnectionFail) < _reconnectInterval) {
return;
}
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
if(_client.isSSL) {
DEBUG_WEBSOCKETS("[WS-Client] connect wss...\n");
if(_client.ssl) {
@ -151,9 +161,11 @@ void WebSocketsClient::loop(void) {
if(_client.tcp->connect(_host.c_str(), _port)) {
connectedCb();
_lastConnectionFail = 0;
} else {
connectFailedCb();
delay(10); //some little delay to not flood the server
_lastConnectionFail = millis();
}
} else {
handleClientData();
@ -239,7 +251,6 @@ bool WebSocketsClient::sendPing(String & payload) {
return sendPing((uint8_t *) payload.c_str(), payload.length());
}
/**
* disconnect one client
* @param num uint8_t client id
@ -260,7 +271,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());
}
}
@ -284,6 +295,15 @@ void WebSocketsClient::setExtraHeaders(const char * extraHeaders) {
_client.extraHeaders = extraHeaders;
}
/**
* set the reconnect Interval
* how long to wait after a connection initiate failed
* @param time in ms
*/
void WebSocketsClient::setReconnectInterval(unsigned long time) {
_reconnectInterval = time;
}
//#################################################################################
//#################################################################################
//#################################################################################
@ -298,6 +318,8 @@ void WebSocketsClient::setExtraHeaders(const char * extraHeaders) {
void WebSocketsClient::messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin) {
WStype_t type = WStype_ERROR;
UNUSED(client);
switch(opcode) {
case WSop_text:
type = fin ? WStype_TEXT : WStype_FRAGMENT_TEXT_START;
@ -305,9 +327,14 @@ void WebSocketsClient::messageReceived(WSclient_t * client, WSopcode_t opcode, u
case WSop_binary:
type = fin ? WStype_BIN : WStype_FRAGMENT_BIN_START;
break;
case WSop_continuation:
type = fin ? WStype_FRAGMENT_FIN : WStype_FRAGMENT;
break;
case WSop_continuation:
type = fin ? WStype_FRAGMENT_FIN : WStype_FRAGMENT;
break;
case WSop_close:
case WSop_ping:
case WSop_pong:
default:
break;
}
runCbEvent(type, payload, length);
@ -322,7 +349,7 @@ void WebSocketsClient::clientDisconnect(WSclient_t * client) {
bool event = false;
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
if(client->isSSL && client->ssl) {
if(client->ssl->connected()) {
client->ssl->flush();
@ -354,7 +381,6 @@ void WebSocketsClient::clientDisconnect(WSclient_t * client) {
client->cCode = 0;
client->cKey = "";
client->cAccept = "";
client->cProtocol = "";
client->cVersion = 0;
client->cIsUpgrade = false;
client->cIsWebsocket = false;
@ -407,8 +433,7 @@ void WebSocketsClient::handleClientData(void) {
int len = _client.tcp->available();
if(len > 0) {
switch(_client.status) {
case WSC_HEADER:
{
case WSC_HEADER: {
String headerLine = _client.tcp->readStringUntil('\n');
handleHeader(&_client, &headerLine);
}
@ -421,20 +446,19 @@ void WebSocketsClient::handleClientData(void) {
break;
}
}
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
delay(0);
#endif
}
#endif
/**
* send the WebSocket header to Server
* @param client WSclient_t * ptr to the client struct
*/
void WebSocketsClient::sendHeader(WSclient_t * client) {
static const char * NEW_LINE = "\r\n";
static const char * NEW_LINE = "\r\n";
DEBUG_WEBSOCKETS("[WS-Client][sendHeader] sending header...\n");
@ -455,67 +479,67 @@ void WebSocketsClient::sendHeader(WSclient_t * client) {
String url = client->cUrl;
if(client->isSocketIO) {
if(client->cSessionId.length() == 0) {
url += WEBSOCKETS_STRING("&transport=polling");
ws_header = false;
} else {
url += WEBSOCKETS_STRING("&transport=websocket&sid=");
url += client->cSessionId;
}
if(client->cSessionId.length() == 0) {
url += WEBSOCKETS_STRING("&transport=polling");
ws_header = false;
} else {
url += WEBSOCKETS_STRING("&transport=websocket&sid=");
url += client->cSessionId;
}
}
handshake = WEBSOCKETS_STRING("GET ");
handshake += url + WEBSOCKETS_STRING(" HTTP/1.1\r\n"
"Host: ");
handshake += _host + ":" + _port + NEW_LINE;
handshake = WEBSOCKETS_STRING("GET ");
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"
"Upgrade: websocket\r\n"
"Sec-WebSocket-Version: 13\r\n"
"Sec-WebSocket-Key: ");
handshake += client->cKey + NEW_LINE;
if(ws_header) {
handshake += WEBSOCKETS_STRING("Connection: Upgrade\r\n"
"Upgrade: websocket\r\n"
"Sec-WebSocket-Version: 13\r\n"
"Sec-WebSocket-Key: ");
handshake += client->cKey + NEW_LINE;
if(client->cProtocol.length() > 0) {
handshake += WEBSOCKETS_STRING("Sec-WebSocket-Protocol: ");
handshake +=client->cProtocol + NEW_LINE;
}
if(client->cProtocol.length() > 0) {
handshake += WEBSOCKETS_STRING("Sec-WebSocket-Protocol: ");
handshake += client->cProtocol + NEW_LINE;
}
if(client->cExtensions.length() > 0) {
handshake += WEBSOCKETS_STRING("Sec-WebSocket-Extensions: ");
handshake +=client->cExtensions + NEW_LINE;
}
} else {
handshake += WEBSOCKETS_STRING("Connection: keep-alive\r\n");
}
if(client->cExtensions.length() > 0) {
handshake += WEBSOCKETS_STRING("Sec-WebSocket-Extensions: ");
handshake += client->cExtensions + NEW_LINE;
}
} else {
handshake += WEBSOCKETS_STRING("Connection: keep-alive\r\n");
}
// add extra headers; by default this includes "Origin: file://"
if (client->extraHeaders) {
handshake += client->extraHeaders + NEW_LINE;
}
// add extra headers; by default this includes "Origin: file://"
if(client->extraHeaders) {
handshake += client->extraHeaders + NEW_LINE;
}
handshake += WEBSOCKETS_STRING("User-Agent: arduino-WebSocket-Client\r\n");
handshake += WEBSOCKETS_STRING("User-Agent: arduino-WebSocket-Client\r\n");
if(client->base64Authorization.length() > 0) {
handshake += WEBSOCKETS_STRING("Authorization: Basic ");
handshake += client->base64Authorization + NEW_LINE;
}
if(client->base64Authorization.length() > 0) {
handshake += WEBSOCKETS_STRING("Authorization: Basic ");
handshake += client->base64Authorization + NEW_LINE;
}
if(client->plainAuthorization.length() > 0) {
handshake += WEBSOCKETS_STRING("Authorization: ");
handshake += client->plainAuthorization + NEW_LINE;
}
if(client->plainAuthorization.length() > 0) {
handshake += WEBSOCKETS_STRING("Authorization: ");
handshake += client->plainAuthorization + NEW_LINE;
}
handshake += NEW_LINE;
handshake += NEW_LINE;
DEBUG_WEBSOCKETS("[WS-Client][sendHeader] handshake %s", (uint8_t*)handshake.c_str());
client->tcp->write((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)
client->tcp->readStringUntil('\n', &(client->cHttpLine), std::bind(&WebSocketsClient::handleHeader, this, client, &(client->cHttpLine)));
client->tcp->readStringUntil('\n', &(client->cHttpLine), std::bind(&WebSocketsClient::handleHeader, this, client, &(client->cHttpLine)));
#endif
DEBUG_WEBSOCKETS("[WS-Client][sendHeader] sending header... Done (%uus).\n", (micros() - start));
DEBUG_WEBSOCKETS("[WS-Client][sendHeader] sending header... Done (%luus).\n", (micros() - start));
}
@ -535,7 +559,12 @@ void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) {
client->cCode = headerLine->substring(9, headerLine->indexOf(' ', 9)).toInt();
} else if(headerLine->indexOf(':')) {
String headerName = headerLine->substring(0, headerLine->indexOf(':'));
String headerValue = headerLine->substring(headerLine->indexOf(':') + 2);
String headerValue = headerLine->substring(headerLine->indexOf(':') + 1);
// remove space in the beginning (RFC2616)
if(headerValue[0] == ' ') {
headerValue.remove(0, 1);
}
if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Connection"))) {
if(headerValue.equalsIgnoreCase(WEBSOCKETS_STRING("upgrade"))) {
@ -555,10 +584,10 @@ void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) {
} else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Version"))) {
client->cVersion = headerValue.toInt();
} else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Set-Cookie"))) {
if (headerValue.indexOf(WEBSOCKETS_STRING("HttpOnly")) > -1) {
if(headerValue.indexOf(WEBSOCKETS_STRING("HttpOnly")) > -1) {
client->cSessionId = headerValue.substring(headerValue.indexOf('=') + 1, headerValue.indexOf(";"));
} else {
client->cSessionId = headerValue.substring(headerValue.indexOf('=') + 1);
} else {
client->cSessionId = headerValue.substring(headerValue.indexOf('=') + 1);
}
}
} else {
@ -604,6 +633,7 @@ void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) {
ok = false;
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] serverCode is not 101 (%d)\n", client->cCode);
clientDisconnect(client);
_lastConnectionFail = millis();
break;
}
}
@ -627,19 +657,19 @@ void WebSocketsClient::handleHeader(WSclient_t * client, String * headerLine) {
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] Websocket connection init done.\n");
headerDone(client);
runCbEvent(WStype_CONNECTED, (uint8_t *) client->cUrl.c_str(), client->cUrl.length());
} else if(clientIsConnected(client) && client->isSocketIO && client->cSessionId.length() > 0) {
sendHeader(client);
} else {
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] no Websocket connection close.\n");
if(clientIsConnected(client)) {
client->tcp->write("This is a webSocket client!");
}
clientDisconnect(client);
}
}
} else if(clientIsConnected(client) && client->isSocketIO && client->cSessionId.length() > 0) {
sendHeader(client);
} else {
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] no Websocket connection close.\n");
_lastConnectionFail = millis();
if(clientIsConnected(client)) {
write(client, "This is a webSocket client!");
}
clientDisconnect(client);
}
}
}
void WebSocketsClient::connectedCb() {
@ -648,15 +678,15 @@ void WebSocketsClient::connectedCb() {
#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;
client->tcp = NULL;
DEBUG_WEBSOCKETS("[WS-Server][%d] Disconnect client\n", client->num);
client->status = WSC_NOT_CONNECTED;
client->tcp = NULL;
// reconnect
c->asyncConnect();
// reconnect
c->asyncConnect();
return true;
}, this, std::placeholders::_1, &_client));
return true;
}, this, std::placeholders::_1, &_client));
#endif
_client.status = WSC_HEADER;
@ -683,7 +713,6 @@ void WebSocketsClient::connectedCb() {
}
void WebSocketsClient::connectFailedCb() {
DEBUG_WEBSOCKETS("[WS-Client] connection to %s:%u Faild\n", _host.c_str(), _port);
}
@ -702,26 +731,26 @@ void WebSocketsClient::asyncConnect() {
}
tcpclient->onDisconnect([](void *obj, AsyncClient* c) {
c->free();
delete c;
});
c->free();
delete c;
});
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");
ws->connectFailedCb();
return;
}
ws->connectedCb();
}, this, std::placeholders::_2));
ws->_client.tcp = new AsyncTCPbuffer(tcp);
if(!ws->_client.tcp) {
DEBUG_WEBSOCKETS("[WS-Client] creating Network class failed!\n");
ws->connectFailedCb();
return;
}
ws->connectedCb();
}, this, std::placeholders::_2));
tcpclient->onError(std::bind([](WebSocketsClient * ws , AsyncClient * tcp) {
ws->connectFailedCb();
ws->connectFailedCb();
// reconnect
ws->asyncConnect();
}, this, std::placeholders::_2));
// reconnect
ws->asyncConnect();
}, this, std::placeholders::_2));
if(!tcpclient->connect(_host.c_str(), _port)) {
connectFailedCb();

View File

@ -37,12 +37,13 @@ class WebSocketsClient: private WebSockets {
WebSocketsClient(void);
~WebSocketsClient(void);
virtual ~WebSocketsClient(void);
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)
#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");
void beginSSL(String host, uint16_t port, String url = "/", String fingerprint = "", String protocol = "arduino");
#endif
@ -50,7 +51,7 @@ class WebSocketsClient: private WebSockets {
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)
#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");
void beginSocketIOSSL(String host, uint16_t port, String url = "/socket.io/?EIO=3", String protocol = "arduino");
#endif
@ -83,17 +84,22 @@ class WebSocketsClient: private WebSockets {
void setExtraHeaders(const char * extraHeaders = NULL);
void setReconnectInterval(unsigned long time);
protected:
String _host;
uint16_t _port;
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
String _fingerprint;
#endif
WSclient_t _client;
WebSocketClientEvent _cbEvent;
unsigned long _lastConnectionFail;
unsigned long _reconnectInterval;
void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin);
void clientDisconnect(WSclient_t * client);

View File

@ -29,6 +29,7 @@ WebSocketsServer::WebSocketsServer(uint16_t port, String origin, String protocol
_port = port;
_origin = origin;
_protocol = protocol;
_runnning = false;
_server = new WEBSOCKETS_NETWORK_SERVER_CLASS(port);
@ -43,18 +44,14 @@ WebSocketsServer::WebSocketsServer(uint16_t port, String origin, String protocol
_httpHeaderValidationFunc = NULL;
_mandatoryHttpHeaders = NULL;
_mandatoryHttpHeaderCount = 0;
memset(&_clients[0], 0x00, (sizeof(WSclient_t) * WEBSOCKETS_SERVER_CLIENT_MAX));
}
WebSocketsServer::~WebSocketsServer() {
// disconnect all clients
disconnect();
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
_server->close();
#else
// TODO how to close server?
#endif
close();
if (_mandatoryHttpHeaders)
delete[] _mandatoryHttpHeaders;
@ -75,7 +72,7 @@ void WebSocketsServer::begin(void) {
client->num = i;
client->status = WSC_NOT_CONNECTED;
client->tcp = NULL;
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
client->isSSL = false;
client->ssl = NULL;
#endif
@ -98,23 +95,43 @@ void WebSocketsServer::begin(void) {
#ifdef ESP8266
randomSeed(RANDOM_REG32);
#elif defined(ESP32)
#define DR_REG_RNG_BASE 0x3ff75144
randomSeed(READ_PERI_REG(DR_REG_RNG_BASE));
#else
// TODO find better seed
randomSeed(millis());
#endif
_runnning = true;
_server->begin();
DEBUG_WEBSOCKETS("[WS-Server] Server Started.\n");
}
void WebSocketsServer::close(void) {
_runnning = false;
disconnect();
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
_server->close();
#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)
/**
* called in arduino loop
*/
void WebSocketsServer::loop(void) {
handleNewClients();
handleClientData();
if(_runnning) {
handleNewClients();
handleClientData();
}
}
#endif
@ -386,7 +403,25 @@ void WebSocketsServer::setAuthorization(const char * auth) {
}
}
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
/**
* count the connected clients (optional ping them)
* @param ping bool ping the connected clients
*/
int WebSocketsServer::connectedClients(bool ping) {
WSclient_t * client;
int count = 0;
for(uint8_t i = 0; i < WEBSOCKETS_SERVER_CLIENT_MAX; i++) {
client = &_clients[i];
if(client->status == WSC_CONNECTED) {
if(ping != true || sendPing(i)) {
count++;
}
}
}
return count;
}
#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
@ -423,7 +458,7 @@ bool WebSocketsServer::newClient(WEBSOCKETS_NETWORK_CLASS * TCPclient) {
client->tcp = TCPclient;
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
client->isSSL = false;
client->tcp->setNoDelay(true);
#endif
@ -432,7 +467,7 @@ bool WebSocketsServer::newClient(WEBSOCKETS_NETWORK_CLASS * TCPclient) {
client->tcp->setTimeout(WEBSOCKETS_TCP_TIMEOUT);
#endif
client->status = WSC_HEADER;
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
IPAddress ip = client->tcp->remoteIP();
DEBUG_WEBSOCKETS("[WS-Server][%d] new client from %d.%d.%d.%d\n", client->num, ip[0], ip[1], ip[2], ip[3]);
#else
@ -483,6 +518,11 @@ 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:
case WSop_pong:
default:
break;
}
runCbEvent(client->num, type, payload, length);
@ -496,7 +536,7 @@ void WebSocketsServer::messageReceived(WSclient_t * client, WSopcode_t opcode, u
void WebSocketsServer::clientDisconnect(WSclient_t * client) {
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
if(client->isSSL && client->ssl) {
if(client->ssl->connected()) {
client->ssl->flush();
@ -582,12 +622,12 @@ bool WebSocketsServer::clientIsConnected(WSclient_t * client) {
*/
void WebSocketsServer::handleNewClients(void) {
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
while(_server->hasClient()) {
#endif
bool ok = false;
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
#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
@ -603,7 +643,7 @@ void WebSocketsServer::handleNewClients(void) {
if(!ok) {
// no free space to handle client
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
IPAddress ip = tcpClient->remoteIP();
DEBUG_WEBSOCKETS("[WS-Server] no free space new client from %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
#else
@ -612,7 +652,7 @@ void WebSocketsServer::handleNewClients(void) {
tcpClient->stop();
}
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266)
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
delay(0);
}
#endif
@ -677,55 +717,60 @@ void WebSocketsServer::handleHeader(WSclient_t * client, String * headerLine) {
static const char * NEW_LINE = "\r\n";
headerLine->trim(); // remove \r
headerLine->trim(); // remove \r
if(headerLine->length() > 0) {
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] RX: %s\n", client->num, headerLine->c_str());
if(headerLine->length() > 0) {
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] RX: %s\n", client->num, headerLine->c_str());
// websocket requests always start with GET see rfc6455
if(headerLine->startsWith("GET ")) {
// websocket requests always start with GET see rfc6455
if(headerLine->startsWith("GET ")) {
// cut URL out
client->cUrl = headerLine->substring(4, headerLine->indexOf(' ', 4));
// cut URL out
client->cUrl = headerLine->substring(4, headerLine->indexOf(' ', 4));
//reset non-websocket http header validation state for this client
//reset non-websocket http header validation state for this client
client->cHttpHeadersValid = true;
client->cMandatoryHeadersCount = 0;
} else if(headerLine->indexOf(':')) {
String headerName = headerLine->substring(0, headerLine->indexOf(':'));
String headerValue = headerLine->substring(headerLine->indexOf(':') + 2);
} else if(headerLine->indexOf(':')) {
String headerName = headerLine->substring(0, headerLine->indexOf(':'));
String headerValue = headerLine->substring(headerLine->indexOf(':') + 1);
if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Connection"))) {
headerValue.toLowerCase();
if(headerValue.indexOf(WEBSOCKETS_STRING("upgrade")) >= 0) {
client->cIsUpgrade = true;
}
} else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Upgrade"))) {
if(headerValue.equalsIgnoreCase(WEBSOCKETS_STRING("websocket"))) {
client->cIsWebsocket = true;
}
} else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Version"))) {
client->cVersion = headerValue.toInt();
} else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Key"))) {
client->cKey = headerValue;
client->cKey.trim(); // see rfc6455
} else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Protocol"))) {
client->cProtocol = headerValue;
} else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Extensions"))) {
client->cExtensions = headerValue;
} else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Authorization"))) {
client->base64Authorization = headerValue;
} else {
client->cHttpHeadersValid &= execHttpHeaderValidation(headerName, headerValue);
if (_mandatoryHttpHeaderCount > 0 && hasMandatoryHeader(headerName)) {
client->cMandatoryHeadersCount++;
}
}
// remove space in the beginning (RFC2616)
if(headerValue[0] == ' ') {
headerValue.remove(0, 1);
}
} else {
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] Header error (%s)\n", headerLine->c_str());
}
if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Connection"))) {
headerValue.toLowerCase();
if(headerValue.indexOf(WEBSOCKETS_STRING("upgrade")) >= 0) {
client->cIsUpgrade = true;
}
} else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Upgrade"))) {
if(headerValue.equalsIgnoreCase(WEBSOCKETS_STRING("websocket"))) {
client->cIsWebsocket = true;
}
} else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Version"))) {
client->cVersion = headerValue.toInt();
} else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Key"))) {
client->cKey = headerValue;
client->cKey.trim(); // see rfc6455
} else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Protocol"))) {
client->cProtocol = headerValue;
} else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Sec-WebSocket-Extensions"))) {
client->cExtensions = headerValue;
} else if(headerName.equalsIgnoreCase(WEBSOCKETS_STRING("Authorization"))) {
client->base64Authorization = headerValue;
} else {
client->cHttpHeadersValid &= execHttpHeaderValidation(headerName, headerValue);
if(_mandatoryHttpHeaderCount > 0 && hasMandatoryHeader(headerName)) {
client->cMandatoryHeadersCount++;
}
}
} else {
DEBUG_WEBSOCKETS("[WS-Client][handleHeader] Header error (%s)\n", headerLine->c_str());
}
(*headerLine) = "";
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
@ -747,11 +792,11 @@ void WebSocketsServer::handleHeader(WSclient_t * client, String * headerLine) {
bool ok = (client->cIsUpgrade && client->cIsWebsocket);
if(ok) {
if(client->cUrl.length() == 0) {
ok = false;
}
if(client->cKey.length() == 0) {
if(ok) {
if(client->cUrl.length() == 0) {
ok = false;
}
if(client->cKey.length() == 0) {
ok = false;
}
if(client->cVersion != 13) {
@ -809,7 +854,7 @@ void WebSocketsServer::handleHeader(WSclient_t * client, String * headerLine) {
DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] handshake %s", client->num, (uint8_t*)handshake.c_str());
client->tcp->write((uint8_t*)handshake.c_str(), handshake.length());
write(client, (uint8_t*)handshake.c_str(), handshake.length());
headerDone(client);

View File

@ -27,7 +27,9 @@
#include "WebSockets.h"
#ifndef WEBSOCKETS_SERVER_CLIENT_MAX
#define WEBSOCKETS_SERVER_CLIENT_MAX (5)
#endif
@ -44,9 +46,10 @@ public:
#endif
WebSocketsServer(uint16_t port, String origin = "", String protocol = "arduino");
~WebSocketsServer(void);
virtual ~WebSocketsServer(void);
void begin(void);
void close(void);
#if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC)
void loop(void);
@ -92,7 +95,9 @@ public:
void setAuthorization(const char * user, const char * password);
void setAuthorization(const char * auth);
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC)
int connectedClients(bool ping = false);
#if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32)
IPAddress remoteIP(uint8_t num);
#endif
@ -111,6 +116,8 @@ protected:
WebSocketServerEvent _cbEvent;
WebSocketServerHttpHeaderValFunc _httpHeaderValidationFunc;
bool _runnning;
bool newClient(WEBSOCKETS_NETWORK_CLASS * TCPclient);
void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin);

View File

@ -9,6 +9,10 @@ For details, see http://sourceforge.net/projects/libb64
#include <core_esp8266_features.h>
#endif
#if defined(ESP32)
#define CORE_HAS_LIBB64
#endif
#ifndef CORE_HAS_LIBB64
#include "cdecode_inc.h"
@ -32,9 +36,9 @@ int base64_decode_block(const char* code_in, const int length_in, char* plaintex
const char* codechar = code_in;
char* plainchar = plaintext_out;
char fragment;
*plainchar = state_in->plainchar;
switch (state_in->step)
{
while (1)

View File

@ -9,6 +9,10 @@ For details, see http://sourceforge.net/projects/libb64
#include <core_esp8266_features.h>
#endif
#if defined(ESP32)
#define CORE_HAS_LIBB64
#endif
#ifndef CORE_HAS_LIBB64
#include "cencode_inc.h"
@ -35,9 +39,9 @@ int base64_encode_block(const char* plaintext_in, int length_in, char* code_out,
char* codechar = code_out;
char result;
char fragment;
result = state_in->result;
switch (state_in->step)
{
while (1)
@ -76,7 +80,7 @@ int base64_encode_block(const char* plaintext_in, int length_in, char* code_out,
*codechar++ = base64_encode_value(result);
result = (fragment & 0x03f) >> 0;
*codechar++ = base64_encode_value(result);
++(state_in->stepcount);
if (state_in->stepcount == CHARS_PER_LINE/4)
{
@ -92,7 +96,7 @@ int base64_encode_block(const char* plaintext_in, int length_in, char* code_out,
int base64_encode_blockend(char* code_out, base64_encodestate* state_in)
{
char* codechar = code_out;
switch (state_in->step)
{
case step_B:
@ -108,7 +112,7 @@ int base64_encode_blockend(char* code_out, base64_encodestate* state_in)
break;
}
*codechar++ = 0x00;
return codechar - code_out;
}

View File

@ -18,7 +18,7 @@ A million repetitions of "a"
/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */
/* #define SHA1HANDSOFF * Copies data before messing with it. */
#ifndef ESP8266
#if !defined(ESP8266) && !defined(ESP32)
#define SHA1HANDSOFF

View File

@ -5,7 +5,7 @@ By Steve Reid <steve@edmweb.com>
100% Public Domain
*/
#ifndef ESP8266
#if !defined(ESP8266) && !defined(ESP32)
typedef struct {
uint32_t state[5];
@ -18,4 +18,4 @@ void SHA1Init(SHA1_CTX* context);
void SHA1Update(SHA1_CTX* context, const unsigned char* data, uint32_t len);
void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
#endif
#endif

View File

@ -7,7 +7,7 @@ var server = http.createServer(function(request, response) {
response.writeHead(404);
response.end();
});
server.listen(81, function() {
server.listen(8011, function() {
console.log((new Date()) + ' Server is listening on port 8011');
});
@ -54,4 +54,4 @@ wsServer.on('request', function(request) {
});
connection.sendUTF("Hallo Client!");
});
});

View File

@ -16,9 +16,38 @@ function build_sketches()
$arduino --verify $sketch;
local result=$?
if [ $result -ne 0 ]; then
echo "Build failed ($1)"
echo "Build failed ($sketch) build verbose..."
$arduino --verify --verbose --preserve-temp-files $sketch
result=$?
fi
if [ $result -ne 0 ]; then
echo "Build failed ($1) $sketch"
return $result
fi
done
}
function get_core()
{
echo Setup core for $1
cd $HOME/arduino_ide/hardware
if [ "$1" = "esp8266" ] ; then
mkdir esp8266com
cd esp8266com
git clone https://github.com/esp8266/Arduino.git esp8266
cd esp8266/tools
python get.py
fi
if [ "$1" = "esp32" ] ; then
mkdir espressif
cd espressif
git clone https://github.com/espressif/arduino-esp32.git esp32
cd esp32/tools
python get.py
fi
}