├── wifiPicker ├── keywords.txt ├── library.properties ├── README.md ├── examples │ └── wifiPicker │ │ └── wifiPicker.ino └── src │ ├── wifiPicker.cpp │ └── wifiPicker.h ├── arduinoWebSockets ├── examples │ ├── WebSocketClientAVR │ │ ├── .esp8266.skip │ │ └── WebSocketClientAVR.ino │ ├── ParticleWebSocketClient │ │ ├── .esp8266.skip │ │ └── application.cpp │ ├── WebSocketClient │ │ └── WebSocketClient.ino │ ├── WebSocketClientSSL │ │ └── WebSocketClientSSL.ino │ ├── WebSocketServer │ │ └── WebSocketServer.ino │ ├── WebSocketServerFragmentation │ │ └── WebSocketServerFragmentation.ino │ ├── WebSocketServerHttpHeaderValidation │ │ └── WebSocketServerHttpHeaderValidation.ino │ ├── WebSocketClientSocketIO │ │ └── WebSocketClientSocketIO.ino │ ├── Nginx │ │ └── esp8266.ssl.reverse.proxy.conf │ ├── WebSocketServer_LEDcontrol │ │ └── WebSocketServer_LEDcontrol.ino │ └── WebSocketClientSockJsAndStomp │ │ └── WebSocketClientSockJsAndStomp.ino ├── src │ ├── libb64 │ │ ├── AUTHORS │ │ ├── cdecode.h │ │ ├── cencode.h │ │ ├── LICENSE │ │ ├── cencode.c │ │ └── cdecode.c │ ├── WebSocketsClient.h │ ├── WebSocketsServer.h │ └── WebSockets.h ├── library.properties ├── .gitignore ├── travis │ └── common.sh ├── tests │ ├── webSocketServer │ │ ├── package.json │ │ └── index.js │ └── webSocket.html ├── library.json ├── .travis.yml └── README.md ├── Documents ├── PIC1.PNG └── PIC2.PNG ├── AsyncTCP ├── component.mk ├── library.properties ├── library.json ├── README.md ├── travis │ └── common.sh ├── .travis.yml ├── src │ └── AsyncTCP.h └── LICENSE ├── WebServer ├── examples │ ├── FSBrowser │ │ ├── data │ │ │ ├── edit.htm.gz │ │ │ ├── favicon.ico │ │ │ ├── graphs.js.gz │ │ │ └── index.htm │ │ └── FSBrowser.ino │ ├── SDWebServer │ │ ├── SdRoot │ │ │ ├── pins.png │ │ │ └── index.htm │ │ └── SDWebServer.ino │ ├── HttpBasicAuth │ │ └── HttpBasicAuth.ino │ ├── HelloServer │ │ └── HelloServer.ino │ ├── WebUpdate │ │ └── WebUpdate.ino │ ├── SimpleAuthentification │ │ └── SimpleAuthentification.ino │ └── AdvancedWebServer │ │ └── AdvancedWebServer.ino ├── library.properties ├── README.md ├── .gitignore ├── src │ ├── detail │ │ ├── RequestHandler.h │ │ └── RequestHandlersImpl.h │ ├── ESP8266WebServer.h │ ├── WebServer.h │ └── WebServer.cpp ├── keywords.txt └── .travis.yml ├── Hash ├── library.properties ├── README.md ├── .gitignore ├── examples │ └── sha1 │ │ └── sha1.ino └── src │ ├── sha1 │ ├── sha1.h │ └── sha1.c │ ├── Hash.h │ └── Hash.cpp ├── LICENSE └── README.md /wifiPicker/keywords.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /arduinoWebSockets/examples/WebSocketClientAVR/.esp8266.skip: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /arduinoWebSockets/examples/ParticleWebSocketClient/.esp8266.skip: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Documents/PIC1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/S-March/wifiPicker/HEAD/Documents/PIC1.PNG -------------------------------------------------------------------------------- /Documents/PIC2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/S-March/wifiPicker/HEAD/Documents/PIC2.PNG -------------------------------------------------------------------------------- /AsyncTCP/component.mk: -------------------------------------------------------------------------------- 1 | COMPONENT_ADD_INCLUDEDIRS := src 2 | COMPONENT_SRCDIRS := src 3 | CXXFLAGS += -fno-rtti 4 | -------------------------------------------------------------------------------- /WebServer/examples/FSBrowser/data/edit.htm.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/S-March/wifiPicker/HEAD/WebServer/examples/FSBrowser/data/edit.htm.gz -------------------------------------------------------------------------------- /WebServer/examples/FSBrowser/data/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/S-March/wifiPicker/HEAD/WebServer/examples/FSBrowser/data/favicon.ico -------------------------------------------------------------------------------- /WebServer/examples/FSBrowser/data/graphs.js.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/S-March/wifiPicker/HEAD/WebServer/examples/FSBrowser/data/graphs.js.gz -------------------------------------------------------------------------------- /WebServer/examples/SDWebServer/SdRoot/pins.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/S-March/wifiPicker/HEAD/WebServer/examples/SDWebServer/SdRoot/pins.png -------------------------------------------------------------------------------- /arduinoWebSockets/src/libb64/AUTHORS: -------------------------------------------------------------------------------- 1 | libb64: Base64 Encoding/Decoding Routines 2 | ====================================== 3 | 4 | Authors: 5 | ------- 6 | 7 | Chris Venter chris.venter@gmail.com http://rocketpod.blogspot.com 8 | -------------------------------------------------------------------------------- /Hash/library.properties: -------------------------------------------------------------------------------- 1 | name=Hash 2 | version=1.0 3 | author=Markus Sattler 4 | maintainer=Markus Sattler 5 | sentence=Generate Hash from data 6 | paragraph= 7 | category=Data Processing 8 | url= 9 | architectures=esp8266,esp32 10 | -------------------------------------------------------------------------------- /AsyncTCP/library.properties: -------------------------------------------------------------------------------- 1 | name=AsyncTCP 2 | version=1.0.0 3 | author=Me-No-Dev 4 | maintainer=Me-No-Dev 5 | sentence=Async TCP Library for ESP32 6 | paragraph=Async TCP Library for ESP32 7 | category=Other 8 | url=https://github.com/me-no-dev/AsyncTCP 9 | architectures=* 10 | -------------------------------------------------------------------------------- /arduinoWebSockets/library.properties: -------------------------------------------------------------------------------- 1 | name=WebSockets 2 | version=2.0.10 3 | author=Markus Sattler 4 | maintainer=Markus Sattler 5 | sentence=WebSockets for Arduino (Server + Client) 6 | paragraph=use 2.x.x for ESP and 1.3 for AVR 7 | category=Communication 8 | url=https://github.com/Links2004/arduinoWebSockets 9 | architectures=* 10 | -------------------------------------------------------------------------------- /wifiPicker/library.properties: -------------------------------------------------------------------------------- 1 | name=wifiPicker 2 | version=1.0.1 3 | author=Samson march 4 | maintainer=Samson March 5 | sentence=Wifi Provisioning Page 6 | paragraph=The library will attempt to connect to a known network, if it can't it will create an access point that allows the user to pick a network. 7 | category=Communication 8 | url= 9 | architectures=esp32 -------------------------------------------------------------------------------- /WebServer/library.properties: -------------------------------------------------------------------------------- 1 | name=WebServer 2 | version=1.0 3 | author=Ivan Grokhotkov 4 | maintainer=Ivan Grokhtkov 5 | sentence=Simple web server library 6 | paragraph=The library supports HTTP GET and POST requests, provides argument parsing, handles one client at a time. 7 | category=Communication 8 | url= 9 | architectures=esp8266,esp32 10 | -------------------------------------------------------------------------------- /Hash/README.md: -------------------------------------------------------------------------------- 1 | Port for Hash library from https://github.com/esp8266/Arduino/libraries/Hash 2 | commit d6f1f0d to ESP32. 3 | 4 | This is an experimental port that should work on ESP8266 and ESP32. This is NOT 5 | an official repo supported by Espressif. Do not depend on this code for 6 | anything important or expect it to be updated. Once the official repo is 7 | created, this repo will be deleted. 8 | -------------------------------------------------------------------------------- /WebServer/README.md: -------------------------------------------------------------------------------- 1 | # WebServer 2 | ESP8266/ESP32 WebServer library 3 | 4 | This is an experimental port of the ESP8266WebServer library that should work 5 | on ESP8266 and ESP32. This is NOT an official repo supported by Espressif. Do 6 | not depend on this code for anything important or expect it to be updated. Once 7 | the official repo is created, this repo will be deleted. 8 | 9 | Added Travis CI 10 | -------------------------------------------------------------------------------- /Hash/.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | -------------------------------------------------------------------------------- /WebServer/.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | -------------------------------------------------------------------------------- /arduinoWebSockets/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | /tests/webSocketServer/node_modules 30 | -------------------------------------------------------------------------------- /AsyncTCP/library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"AsyncTCP", 3 | "description":"Asynchronous TCP Library for ESP32", 4 | "keywords":"async,tcp", 5 | "authors": 6 | { 7 | "name": "Hristo Gochkov", 8 | "maintainer": true 9 | }, 10 | "repository": 11 | { 12 | "type": "git", 13 | "url": "https://github.com/me-no-dev/AsyncTCP.git" 14 | }, 15 | "version": "1.0.0", 16 | "license": "LGPL-3.0", 17 | "frameworks": "arduino", 18 | "platforms": ["espressif32", "espressif32_stage"] 19 | } 20 | -------------------------------------------------------------------------------- /WebServer/examples/SDWebServer/SdRoot/index.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ESP Index 6 | 12 | 17 | 18 | 19 |

ESP8266 Pin Functions

20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Hash/examples/sha1/sha1.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * simple demo to show sha1 calculation 3 | */ 4 | #include 5 | #include 6 | 7 | void setup() { 8 | Serial.begin(921600); 9 | } 10 | 11 | void loop() { 12 | 13 | // usage as String 14 | // SHA1:a94a8fe5ccb19ba61c4c0873d391e987982fbbd3 15 | 16 | Serial.print("SHA1:"); 17 | Serial.println(sha1("abc")); 18 | 19 | // usage as ptr 20 | // SHA1:a94a8fe5ccb19ba61c4c0873d391e987982fbbd3 21 | uint8_t hash[20]; 22 | sha1("abc", &hash[0]); 23 | 24 | Serial.print("SHA1:"); 25 | for(uint16_t i = 0; i < 20; i++) { 26 | Serial.printf("%02x", hash[i]); 27 | } 28 | Serial.println(); 29 | 30 | delay(1000); 31 | } 32 | 33 | -------------------------------------------------------------------------------- /AsyncTCP/README.md: -------------------------------------------------------------------------------- 1 | # AsyncTCP 2 | Async TCP Library for ESP32 Arduino 3 | 4 | [![Join the chat at https://gitter.im/me-no-dev/ESPAsyncWebServer](https://badges.gitter.im/me-no-dev/ESPAsyncWebServer.svg)](https://gitter.im/me-no-dev/ESPAsyncWebServer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 5 | 6 | This is a fully asynchronous TCP library, aimed at enabling trouble-free, multi-connection network environment for Espressif's ESP32 MCUs. 7 | 8 | This library is the base for [ESPAsyncWebServer](https://github.com/me-no-dev/ESPAsyncWebServer) 9 | 10 | ## AsyncClient and AsyncServer 11 | The base classes on which everything else is built. They expose all possible scenarios, but are really raw and require more skills to use. 12 | -------------------------------------------------------------------------------- /AsyncTCP/travis/common.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function build_sketches() 4 | { 5 | local arduino=$1 6 | local srcpath=$2 7 | local platform=$3 8 | local sketches=$(find $srcpath -name *.ino) 9 | for sketch in $sketches; do 10 | local sketchdir=$(dirname $sketch) 11 | if [[ -f "$sketchdir/.$platform.skip" ]]; then 12 | echo -e "\n\n ------------ Skipping $sketch ------------ \n\n"; 13 | continue 14 | fi 15 | echo -e "\n\n ------------ Building $sketch ------------ \n\n"; 16 | $arduino --verify $sketch; 17 | local result=$? 18 | if [ $result -ne 0 ]; then 19 | echo "Build failed ($1)" 20 | return $result 21 | fi 22 | done 23 | } 24 | -------------------------------------------------------------------------------- /arduinoWebSockets/travis/common.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function build_sketches() 4 | { 5 | local arduino=$1 6 | local srcpath=$2 7 | local platform=$3 8 | local sketches=$(find $srcpath -name *.ino) 9 | for sketch in $sketches; do 10 | local sketchdir=$(dirname $sketch) 11 | if [[ -f "$sketchdir/.$platform.skip" ]]; then 12 | echo -e "\n\n ------------ Skipping $sketch ------------ \n\n"; 13 | continue 14 | fi 15 | echo -e "\n\n ------------ Building $sketch ------------ \n\n"; 16 | $arduino --verify $sketch; 17 | local result=$? 18 | if [ $result -ne 0 ]; then 19 | echo "Build failed ($1)" 20 | return $result 21 | fi 22 | done 23 | } 24 | 25 | -------------------------------------------------------------------------------- /arduinoWebSockets/tests/webSocketServer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webSocketServer", 3 | "version": "1.0.0", 4 | "description": "WebSocketServer for testing", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/Links2004/arduinoWebSockets" 12 | }, 13 | "keywords": [ 14 | "esp8266", 15 | "websocket", 16 | "arduino" 17 | ], 18 | "author": "Markus Sattler", 19 | "license": "LGPLv2", 20 | "bugs": { 21 | "url": "https://github.com/Links2004/arduinoWebSockets/issues" 22 | }, 23 | "homepage": "https://github.com/Links2004/arduinoWebSockets", 24 | "dependencies": { 25 | "websocket": "^1.0.18" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /arduinoWebSockets/library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "WebSockets", 3 | "description": "WebSocket Server and Client for Arduino based on RFC6455", 4 | "keywords": "wifi, http, web, server, client, websocket", 5 | "authors": [ 6 | { 7 | "name": "Markus Sattler", 8 | "url": "https://github.com/Links2004", 9 | "maintainer": true 10 | } 11 | ], 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/Links2004/arduinoWebSockets.git" 15 | }, 16 | "version": "2.0.10", 17 | "license": "LGPL-2.1", 18 | "export": { 19 | "exclude": [ 20 | "tests" 21 | ] 22 | }, 23 | "frameworks": "arduino", 24 | "platforms": "*", 25 | "examples": [ 26 | "examples/*/*.ino" 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /WebServer/src/detail/RequestHandler.h: -------------------------------------------------------------------------------- 1 | #ifndef REQUESTHANDLER_H 2 | #define REQUESTHANDLER_H 3 | 4 | class RequestHandler { 5 | public: 6 | virtual ~RequestHandler() { } 7 | virtual bool canHandle(HTTPMethod method, String uri) { (void) method; (void) uri; return false; } 8 | virtual bool canUpload(String uri) { (void) uri; return false; } 9 | virtual bool handle(WebServer& server, HTTPMethod requestMethod, String requestUri) { (void) server; (void) requestMethod; (void) requestUri; return false; } 10 | virtual void upload(WebServer& server, String requestUri, HTTPUpload& upload) { (void) server; (void) requestUri; (void) upload; } 11 | 12 | RequestHandler* next() { return _next; } 13 | void next(RequestHandler* r) { _next = r; } 14 | 15 | private: 16 | RequestHandler* _next = nullptr; 17 | }; 18 | 19 | #endif //REQUESTHANDLER_H 20 | -------------------------------------------------------------------------------- /WebServer/keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For Ultrasound 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | ESP8266WebServer KEYWORD1 10 | HTTPMethod KEYWORD1 11 | 12 | ####################################### 13 | # Methods and Functions (KEYWORD2) 14 | ####################################### 15 | 16 | begin KEYWORD2 17 | handleClient KEYWORD2 18 | on KEYWORD2 19 | addHandler KEYWORD2 20 | uri KEYWORD2 21 | method KEYWORD2 22 | client KEYWORD2 23 | send KEYWORD2 24 | arg KEYWORD2 25 | argName KEYWORD2 26 | args KEYWORD2 27 | hasArg KEYWORD2 28 | onNotFound KEYWORD2 29 | 30 | ####################################### 31 | # Constants (LITERAL1) 32 | ####################################### 33 | 34 | HTTP_GET LITERAL1 35 | HTTP_POST LITERAL1 36 | HTTP_ANY LITERAL1 37 | -------------------------------------------------------------------------------- /Hash/src/sha1/sha1.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file sha1.h 3 | * @date 20.05.2015 4 | * @author Steve Reid 5 | * 6 | * from: http://www.virtualbox.org/svn/vbox/trunk/src/recompiler/tests/sha1.c 7 | */ 8 | 9 | /* ================ sha1.h ================ */ 10 | /* 11 | SHA-1 in C 12 | By Steve Reid 13 | 100% Public Domain 14 | */ 15 | 16 | #ifndef SHA1_H_ 17 | #define SHA1_H_ 18 | 19 | #ifdef ESP32 20 | #define ICACHE_FLASH_ATTR 21 | #define STATIC static 22 | #else 23 | #define STATIC 24 | #endif 25 | 26 | typedef struct { 27 | uint32_t state[5]; 28 | uint32_t count[2]; 29 | unsigned char buffer[64]; 30 | } SHA1_CTX; 31 | 32 | STATIC void SHA1Transform(uint32_t state[5], uint8_t buffer[64]); 33 | STATIC void SHA1Init(SHA1_CTX* context); 34 | STATIC void SHA1Update(SHA1_CTX* context, uint8_t* data, uint32_t len); 35 | STATIC void SHA1Final(unsigned char digest[20], SHA1_CTX* context); 36 | 37 | #endif /* SHA1_H_ */ 38 | 39 | /* ================ end of sha1.h ================ */ 40 | -------------------------------------------------------------------------------- /arduinoWebSockets/src/libb64/cdecode.h: -------------------------------------------------------------------------------- 1 | /* 2 | cdecode.h - c header for a base64 decoding algorithm 3 | 4 | This is part of the libb64 project, and has been placed in the public domain. 5 | For details, see http://sourceforge.net/projects/libb64 6 | */ 7 | 8 | #ifndef BASE64_CDECODE_H 9 | #define BASE64_CDECODE_H 10 | 11 | #define base64_decode_expected_len(n) ((n * 3) / 4) 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | typedef enum { 18 | step_a, step_b, step_c, step_d 19 | } base64_decodestep; 20 | 21 | typedef struct { 22 | base64_decodestep step; 23 | char plainchar; 24 | } base64_decodestate; 25 | 26 | void base64_init_decodestate(base64_decodestate* state_in); 27 | 28 | int base64_decode_value(char value_in); 29 | 30 | int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in); 31 | 32 | int base64_decode_chars(const char* code_in, const int length_in, char* plaintext_out); 33 | 34 | #ifdef __cplusplus 35 | } // extern "C" 36 | #endif 37 | 38 | #endif /* BASE64_CDECODE_H */ 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 S-March 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /arduinoWebSockets/src/libb64/cencode.h: -------------------------------------------------------------------------------- 1 | /* 2 | cencode.h - c header for a base64 encoding algorithm 3 | 4 | This is part of the libb64 project, and has been placed in the public domain. 5 | For details, see http://sourceforge.net/projects/libb64 6 | */ 7 | 8 | #ifndef BASE64_CENCODE_H 9 | #define BASE64_CENCODE_H 10 | 11 | #define base64_encode_expected_len(n) ((((4 * n) / 3) + 3) & ~3) 12 | 13 | #ifdef __cplusplus 14 | extern "C" { 15 | #endif 16 | 17 | typedef enum { 18 | step_A, step_B, step_C 19 | } base64_encodestep; 20 | 21 | typedef struct { 22 | base64_encodestep step; 23 | char result; 24 | int stepcount; 25 | } base64_encodestate; 26 | 27 | void base64_init_encodestate(base64_encodestate* state_in); 28 | 29 | char base64_encode_value(char value_in); 30 | 31 | int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in); 32 | 33 | int base64_encode_blockend(char* code_out, base64_encodestate* state_in); 34 | 35 | int base64_encode_chars(const char* plaintext_in, int length_in, char* code_out); 36 | 37 | #ifdef __cplusplus 38 | } // extern "C" 39 | #endif 40 | 41 | #endif /* BASE64_CENCODE_H */ 42 | -------------------------------------------------------------------------------- /WebServer/src/ESP8266WebServer.h: -------------------------------------------------------------------------------- 1 | /* 2 | ESP8266WebServer.h - Dead simple web-server. 3 | Supports only one simultaneous client, knows how to handle GET and POST. 4 | 5 | Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. 6 | 7 | This library is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU Lesser General Public 9 | License as published by the Free Software Foundation; either 10 | version 2.1 of the License, or (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public 18 | License along with this library; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling) 21 | */ 22 | 23 | 24 | #ifndef ESP8266WEBSERVER_H 25 | #define ESP8266WEBSERVER_H 26 | 27 | #include 28 | 29 | #endif //ESP8266WEBSERVER_H 30 | -------------------------------------------------------------------------------- /WebServer/examples/HttpBasicAuth/HttpBasicAuth.ino: -------------------------------------------------------------------------------- 1 | #ifdef ESP8266 2 | #include 3 | #include 4 | #include 5 | #include 6 | ESP8266WebServer server(80); 7 | #else 8 | #include 9 | #include 10 | #include 11 | #include 12 | WebServer server(80); 13 | #endif 14 | 15 | const char* ssid = "........"; 16 | const char* password = "........"; 17 | 18 | const char* www_username = "admin"; 19 | const char* www_password = "esp8266esp32"; 20 | 21 | void setup() { 22 | Serial.begin(115200); 23 | WiFi.mode(WIFI_STA); 24 | WiFi.begin(ssid, password); 25 | if(WiFi.waitForConnectResult() != WL_CONNECTED) { 26 | Serial.println("WiFi Connect Failed! Rebooting..."); 27 | delay(1000); 28 | ESP.restart(); 29 | } 30 | ArduinoOTA.begin(); 31 | 32 | server.on("/", [](){ 33 | if(!server.authenticate(www_username, www_password)) 34 | return server.requestAuthentication(); 35 | server.send(200, "text/plain", "Login OK"); 36 | }); 37 | server.begin(); 38 | 39 | Serial.print("Open http://"); 40 | Serial.print(WiFi.localIP()); 41 | Serial.println("/ in your browser to see it working"); 42 | } 43 | 44 | void loop() { 45 | ArduinoOTA.handle(); 46 | server.handleClient(); 47 | } 48 | -------------------------------------------------------------------------------- /arduinoWebSockets/examples/ParticleWebSocketClient/application.cpp: -------------------------------------------------------------------------------- 1 | /* To compile using make CLI, create a folder under \firmware\user\applications and copy application.cpp there. 2 | * Then, copy src files under particleWebSocket folder. 3 | */ 4 | 5 | #include "application.h" 6 | #include "particleWebSocket/WebSocketsClient.h" 7 | 8 | WebSocketsClient webSocket; 9 | 10 | void webSocketEvent(WStype_t type, uint8_t* payload, size_t length) 11 | { 12 | switch (type) 13 | { 14 | case WStype_DISCONNECTED: 15 | Serial.printlnf("[WSc] Disconnected!"); 16 | break; 17 | case WStype_CONNECTED: 18 | Serial.printlnf("[WSc] Connected to URL: %s", payload); 19 | webSocket.sendTXT("Connected\r\n"); 20 | break; 21 | case WStype_TEXT: 22 | Serial.printlnf("[WSc] get text: %s", payload); 23 | break; 24 | case WStype_BIN: 25 | Serial.printlnf("[WSc] get binary length: %u", length); 26 | break; 27 | } 28 | } 29 | 30 | void setup() 31 | { 32 | Serial.begin(9600); 33 | 34 | WiFi.setCredentials("[SSID]", "[PASSWORD]", WPA2, WLAN_CIPHER_AES_TKIP); 35 | WiFi.connect(); 36 | 37 | webSocket.begin("192.168.1.153", 85, "/ClientService/?variable=Test1212"); 38 | webSocket.onEvent(webSocketEvent); 39 | } 40 | 41 | void loop() 42 | { 43 | webSocket.sendTXT("Hello world!"); 44 | delay(500); 45 | webSocket.loop(); 46 | } 47 | -------------------------------------------------------------------------------- /AsyncTCP/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: bash 3 | os: 4 | - linux 5 | 6 | script: 7 | - /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16 8 | - sleep 3 9 | - export DISPLAY=:1.0 10 | - wget http://downloads.arduino.cc/arduino-1.6.5-linux64.tar.xz 11 | - tar xf arduino-1.6.5-linux64.tar.xz 12 | - mv arduino-1.6.5 $HOME/arduino_ide 13 | - export PATH="$HOME/arduino_ide:$PATH" 14 | - which arduino 15 | - mkdir -p $HOME/Arduino/libraries 16 | - cp -r $TRAVIS_BUILD_DIR $HOME/Arduino/libraries/ESPAsyncTCP 17 | - cd $HOME/arduino_ide/hardware 18 | - mkdir esp8266com 19 | - cd esp8266com 20 | - git clone https://github.com/esp8266/Arduino.git esp8266 21 | - cd esp8266/tools 22 | - python get.py 23 | - source $TRAVIS_BUILD_DIR/travis/common.sh 24 | - arduino --board esp8266com:esp8266:generic --save-prefs 25 | - arduino --get-pref sketchbook.path 26 | - build_sketches arduino $HOME/Arduino/libraries/ESPAsyncTCP esp8266 27 | 28 | notifications: 29 | email: 30 | on_success: change 31 | on_failure: change 32 | webhooks: 33 | urls: 34 | - https://webhooks.gitter.im/e/60e65d0c78ea0a920347 35 | on_success: change # options: [always|never|change] default: always 36 | on_failure: always # options: [always|never|change] default: always 37 | on_start: false # default: false 38 | -------------------------------------------------------------------------------- /arduinoWebSockets/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: bash 3 | os: 4 | - linux 5 | 6 | script: 7 | - /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16 8 | - sleep 3 9 | - export DISPLAY=:1.0 10 | - wget http://downloads.arduino.cc/arduino-1.6.5-linux64.tar.xz 11 | - tar xf arduino-1.6.5-linux64.tar.xz 12 | - mv arduino-1.6.5 $HOME/arduino_ide 13 | - export PATH="$HOME/arduino_ide:$PATH" 14 | - which arduino 15 | - mkdir -p $HOME/Arduino/libraries 16 | - cp -r $TRAVIS_BUILD_DIR $HOME/Arduino/libraries/arduinoWebSockets 17 | - cd $HOME/arduino_ide/hardware 18 | - mkdir esp8266com 19 | - cd esp8266com 20 | - git clone https://github.com/esp8266/Arduino.git esp8266 21 | - cd esp8266/tools 22 | - python get.py 23 | - source $TRAVIS_BUILD_DIR/travis/common.sh 24 | - arduino --board esp8266com:esp8266:generic --save-prefs 25 | - arduino --get-pref sketchbook.path 26 | - build_sketches arduino $HOME/Arduino/libraries/arduinoWebSockets esp8266 27 | 28 | notifications: 29 | email: 30 | on_success: change 31 | on_failure: change 32 | webhooks: 33 | urls: 34 | - https://webhooks.gitter.im/e/1aa78fbe15080b0c2e37 35 | on_success: change # options: [always|never|change] default: always 36 | on_failure: always # options: [always|never|change] default: always 37 | on_start: false # default: false 38 | -------------------------------------------------------------------------------- /arduinoWebSockets/tests/webSocket.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 40 | 41 | 42 | 43 | LED Control:
44 |
45 | R:
46 | G:
47 | B:
48 | 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wifiPicker 2 | #### A WiFi provisioning library for the ESP32 3 | wifiPicker is a library meant to make connecting an ESP32 easy. The library will first check if any known networks are around, if so, it will connect to that. If there is no known network, it will create one for you. Once connected, navigate to 192.168.4.1 to select a network from a list. Enter in the password and your ESP32 will connect to it. 4 | 5 | If you power off the ESP32, it will remember the credentials for the next time it comes on. In other words, you will only need to set up the network once. 6 | 7 | ![Main page](Documents/PIC1.PNG) 8 | 9 | ## To Install: 10 | Download the zip and extract all the contents into your libraries folder. Make sure that the following libraries are all added: 11 | 12 | * arduinoWebSockets modified from [Links2004](https://github.com/Links2004) 13 | * AsyncTCP from [me-no-dev](https://github.com/me-no-dev) 14 | * Hash modified from [esp8266](https://github.com/esp8266) 15 | * WebServer modified from [esp8266](https://github.com/esp8266) 16 | * wifiPicker 17 | 18 | ## To Use: 19 | Add the wifiPicker library to your project: 20 | 21 | ~~~~ 22 | #include "wifiPicker.h" 23 | ~~~~ 24 | 25 | Add the following lines to the top of your code: 26 | ~~~~ 27 | const char* AP_SSID = "ACCESS_POINT_SSID"; 28 | const char* AP_PW = "ACCESS_POINT_PW"; 29 | ~~~~ 30 | 31 | And then lastly, add this in your setup: 32 | ~~~~ 33 | wifiPicker(AP_SSID,AP_PW); 34 | ~~~~ 35 | 36 | It is possible to change the syling by going into wifiPicker.h and modifying the content there. 37 | 38 | ## Password page 39 | ![Password Page](Documents/PIC2.PNG) -------------------------------------------------------------------------------- /wifiPicker/README.md: -------------------------------------------------------------------------------- 1 | # wifiPicker 2 | #### A WiFi provisioning library for the ESP32 3 | wifiPicker is a library meant to make connecting an ESP32 easy. The library will first check if any known networks are around, if so, it will connect to that. If there is no known network, it will create one for you. Once connected, navigate to 192.168.4.1 to select a network from a list. Enter in the password and your ESP32 will connect to it. 4 | 5 | If you power off the ESP32, it will remember the credentials for the next time it comes on. In other words, you will only need to set up the network once. 6 | 7 | ![Main page](Documents/PIC1.PNG) 8 | 9 | ## To Install: 10 | Download the zip and extract all the contents into your libraries folder. Make sure that the following libraries are all added: 11 | 12 | * arduinoWebSockets modified from [Links2004](https://github.com/Links2004) 13 | * AsyncTCP from [me-no-dev](https://github.com/me-no-dev) 14 | * Hash modified from [esp8266](https://github.com/esp8266) 15 | * WebServer modified from [esp8266](https://github.com/esp8266) 16 | * wifiPicker 17 | 18 | ## To Use: 19 | Add the wifiPicker library to your project: 20 | 21 | ~~~~ 22 | #include "wifiPicker.h" 23 | ~~~~ 24 | 25 | Add the following lines to the top of your code: 26 | ~~~~ 27 | const char* AP_SSID = "ACCESS_POINT_SSID"; 28 | const char* AP_PW = "ACCESS_POINT_PW"; 29 | ~~~~ 30 | 31 | And then lastly, add this in your setup: 32 | ~~~~ 33 | wifiPicker(AP_SSID,AP_PW); 34 | ~~~~ 35 | 36 | It is possible to change the syling by going into wifiPicker.h and modifying the content there. 37 | 38 | ## Password page 39 | ![Password Page](Documents/PIC2.PNG) -------------------------------------------------------------------------------- /wifiPicker/examples/wifiPicker/wifiPicker.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /**************************************************************** 5 | SSID and PW for new network if no previously known network is 6 | available. 7 | ****************************************************************/ 8 | const char* AP_SSID = "ACCESS_POINT_SSID"; 9 | const char* AP_PW = "ACCESS_POINT_PW"; 10 | 11 | void setup() 12 | { 13 | /**************************************************************** 14 | Start serial communications 15 | ****************************************************************/ 16 | Serial.begin(115200); 17 | Serial.println(); 18 | 19 | /**************************************************************** 20 | Turn debug information on 21 | ****************************************************************/ 22 | setDebugPrint(true); 23 | 24 | /**************************************************************** 25 | Attempt to connect to a known network. If no known network is 26 | available, create a network with name AP_SSID and password AP_PW. 27 | Connect to the network and navigate to 192.168.4.1 28 | Select your network and enter in password to connect 29 | ****************************************************************/ 30 | wifiPicker(AP_SSID,AP_PW); 31 | 32 | /**************************************************************** 33 | If connection is successful, display IP address of ESP32 34 | ****************************************************************/ 35 | Serial.println("IP ADDRESS IS:"); 36 | Serial.println(WiFi.localIP()); 37 | } 38 | void loop() 39 | { 40 | } 41 | -------------------------------------------------------------------------------- /Hash/src/Hash.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Hash.h 3 | * @date 20.05.2015 4 | * @author Markus Sattler 5 | * 6 | * Copyright (c) 2015 Markus Sattler. All rights reserved. 7 | * This file is part of the esp8266 core for Arduino environment. 8 | * 9 | * This library is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU Lesser General Public 11 | * License as published by the Free Software Foundation; either 12 | * version 2.1 of the License, or (at your option) any later version. 13 | * 14 | * This library is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | * Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public 20 | * License along with this library; if not, write to the Free Software 21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 | * 23 | */ 24 | 25 | #ifndef HASH_H_ 26 | #define HASH_H_ 27 | 28 | //#define DEBUG_SHA1 29 | 30 | void sha1(uint8_t * data, uint32_t size, uint8_t hash[20]); 31 | void sha1(char * data, uint32_t size, uint8_t hash[20]); 32 | void sha1(const uint8_t * data, uint32_t size, uint8_t hash[20]); 33 | void sha1(const char * data, uint32_t size, uint8_t hash[20]); 34 | void sha1(String data, uint8_t hash[20]); 35 | 36 | String sha1(uint8_t* data, uint32_t size); 37 | String sha1(char* data, uint32_t size); 38 | String sha1(const uint8_t* data, uint32_t size); 39 | String sha1(const char* data, uint32_t size); 40 | String sha1(String data); 41 | 42 | #endif /* HASH_H_ */ 43 | -------------------------------------------------------------------------------- /arduinoWebSockets/src/libb64/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright-Only Dedication (based on United States law) 2 | or Public Domain Certification 3 | 4 | The person or persons who have associated work with this document (the 5 | "Dedicator" or "Certifier") hereby either (a) certifies that, to the best of 6 | his knowledge, the work of authorship identified is in the public domain of the 7 | country from which the work is published, or (b) hereby dedicates whatever 8 | copyright the dedicators holds in the work of authorship identified below (the 9 | "Work") to the public domain. A certifier, moreover, dedicates any copyright 10 | interest he may have in the associated work, and for these purposes, is 11 | described as a "dedicator" below. 12 | 13 | A certifier has taken reasonable steps to verify the copyright status of this 14 | work. Certifier recognizes that his good faith efforts may not shield him from 15 | liability if in fact the work certified is not in the public domain. 16 | 17 | Dedicator makes this dedication for the benefit of the public at large and to 18 | the detriment of the Dedicator's heirs and successors. Dedicator intends this 19 | dedication to be an overt act of relinquishment in perpetuity of all present 20 | and future rights under copyright law, whether vested or contingent, in the 21 | Work. Dedicator understands that such relinquishment of all rights includes 22 | the relinquishment of all rights to enforce (by lawsuit or otherwise) those 23 | copyrights in the Work. 24 | 25 | Dedicator recognizes that, once placed in the public domain, the Work may be 26 | freely reproduced, distributed, transmitted, used, modified, built upon, or 27 | otherwise exploited by anyone for any purpose, commercial or non-commercial, 28 | and in any way, including by methods that have not yet been invented or 29 | conceived. -------------------------------------------------------------------------------- /arduinoWebSockets/tests/webSocketServer/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | var WebSocketServer = require('websocket').server; 3 | var http = require('http'); 4 | 5 | var server = http.createServer(function(request, response) { 6 | console.log((new Date()) + ' Received request for ' + request.url); 7 | response.writeHead(404); 8 | response.end(); 9 | }); 10 | server.listen(81, function() { 11 | console.log((new Date()) + ' Server is listening on port 8011'); 12 | }); 13 | 14 | wsServer = new WebSocketServer({ 15 | httpServer: server, 16 | // You should not use autoAcceptConnections for production 17 | // applications, as it defeats all standard cross-origin protection 18 | // facilities built into the protocol and the browser. You should 19 | // *always* verify the connection's origin and decide whether or not 20 | // to accept it. 21 | autoAcceptConnections: false 22 | }); 23 | 24 | function originIsAllowed(origin) { 25 | // put logic here to detect whether the specified origin is allowed. 26 | return true; 27 | } 28 | 29 | wsServer.on('request', function(request) { 30 | 31 | if (!originIsAllowed(request.origin)) { 32 | // Make sure we only accept requests from an allowed origin 33 | request.reject(); 34 | console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.'); 35 | return; 36 | } 37 | 38 | var connection = request.accept('arduino', request.origin); 39 | console.log((new Date()) + ' Connection accepted.'); 40 | 41 | connection.on('message', function(message) { 42 | if (message.type === 'utf8') { 43 | console.log('Received Message: ' + message.utf8Data); 44 | // connection.sendUTF(message.utf8Data); 45 | } 46 | else if (message.type === 'binary') { 47 | console.log('Received Binary Message of ' + message.binaryData.length + ' bytes'); 48 | //connection.sendBytes(message.binaryData); 49 | } 50 | }); 51 | 52 | connection.on('close', function(reasonCode, description) { 53 | console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.'); 54 | }); 55 | 56 | connection.sendUTF("Hallo Client!"); 57 | }); -------------------------------------------------------------------------------- /arduinoWebSockets/examples/WebSocketClient/WebSocketClient.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * WebSocketClient.ino 3 | * 4 | * Created on: 24.05.2015 5 | * 6 | */ 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #include 16 | 17 | ESP8266WiFiMulti WiFiMulti; 18 | WebSocketsClient webSocket; 19 | 20 | #define USE_SERIAL Serial1 21 | 22 | void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) { 23 | 24 | switch(type) { 25 | case WStype_DISCONNECTED: 26 | USE_SERIAL.printf("[WSc] Disconnected!\n"); 27 | break; 28 | case WStype_CONNECTED: { 29 | USE_SERIAL.printf("[WSc] Connected to url: %s\n", payload); 30 | 31 | // send message to server when Connected 32 | webSocket.sendTXT("Connected"); 33 | } 34 | break; 35 | case WStype_TEXT: 36 | USE_SERIAL.printf("[WSc] get text: %s\n", payload); 37 | 38 | // send message to server 39 | // webSocket.sendTXT("message here"); 40 | break; 41 | case WStype_BIN: 42 | USE_SERIAL.printf("[WSc] get binary length: %u\n", length); 43 | hexdump(payload, length); 44 | 45 | // send data to server 46 | // webSocket.sendBIN(payload, length); 47 | break; 48 | } 49 | 50 | } 51 | 52 | void setup() { 53 | // USE_SERIAL.begin(921600); 54 | USE_SERIAL.begin(115200); 55 | 56 | //Serial.setDebugOutput(true); 57 | USE_SERIAL.setDebugOutput(true); 58 | 59 | USE_SERIAL.println(); 60 | USE_SERIAL.println(); 61 | USE_SERIAL.println(); 62 | 63 | for(uint8_t t = 4; t > 0; t--) { 64 | USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t); 65 | USE_SERIAL.flush(); 66 | delay(1000); 67 | } 68 | 69 | WiFiMulti.addAP("SSID", "passpasspass"); 70 | 71 | //WiFi.disconnect(); 72 | while(WiFiMulti.run() != WL_CONNECTED) { 73 | delay(100); 74 | } 75 | 76 | // server address, port and URL 77 | webSocket.begin("192.168.0.123", 81, "/"); 78 | 79 | // event handler 80 | webSocket.onEvent(webSocketEvent); 81 | 82 | // use HTTP Basic Authorization this is optional remove if not needed 83 | webSocket.setAuthorization("user", "Password"); 84 | 85 | // try ever 5000 again if connection has failed 86 | webSocket.setReconnectInterval(5000); 87 | 88 | } 89 | 90 | void loop() { 91 | webSocket.loop(); 92 | } 93 | -------------------------------------------------------------------------------- /arduinoWebSockets/examples/WebSocketClientSSL/WebSocketClientSSL.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * WebSocketClientSSL.ino 3 | * 4 | * Created on: 10.12.2015 5 | * 6 | * note SSL is only possible with the ESP8266 7 | * 8 | */ 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | #include 18 | 19 | ESP8266WiFiMulti WiFiMulti; 20 | WebSocketsClient webSocket; 21 | 22 | 23 | #define USE_SERIAL Serial1 24 | 25 | void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) { 26 | 27 | 28 | switch(type) { 29 | case WStype_DISCONNECTED: 30 | USE_SERIAL.printf("[WSc] Disconnected!\n"); 31 | break; 32 | case WStype_CONNECTED: 33 | { 34 | USE_SERIAL.printf("[WSc] Connected to url: %s\n", payload); 35 | 36 | // send message to server when Connected 37 | webSocket.sendTXT("Connected"); 38 | } 39 | break; 40 | case WStype_TEXT: 41 | USE_SERIAL.printf("[WSc] get text: %s\n", payload); 42 | 43 | // send message to server 44 | // webSocket.sendTXT("message here"); 45 | break; 46 | case WStype_BIN: 47 | USE_SERIAL.printf("[WSc] get binary length: %u\n", length); 48 | hexdump(payload, length); 49 | 50 | // send data to server 51 | // webSocket.sendBIN(payload, length); 52 | break; 53 | } 54 | 55 | } 56 | 57 | void setup() { 58 | // USE_SERIAL.begin(921600); 59 | USE_SERIAL.begin(115200); 60 | 61 | //Serial.setDebugOutput(true); 62 | USE_SERIAL.setDebugOutput(true); 63 | 64 | USE_SERIAL.println(); 65 | USE_SERIAL.println(); 66 | USE_SERIAL.println(); 67 | 68 | for(uint8_t t = 4; t > 0; t--) { 69 | USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t); 70 | USE_SERIAL.flush(); 71 | delay(1000); 72 | } 73 | 74 | WiFiMulti.addAP("SSID", "passpasspass"); 75 | 76 | //WiFi.disconnect(); 77 | while(WiFiMulti.run() != WL_CONNECTED) { 78 | delay(100); 79 | } 80 | 81 | webSocket.beginSSL("192.168.0.123", 81); 82 | webSocket.onEvent(webSocketEvent); 83 | 84 | } 85 | 86 | void loop() { 87 | webSocket.loop(); 88 | } 89 | -------------------------------------------------------------------------------- /WebServer/examples/HelloServer/HelloServer.ino: -------------------------------------------------------------------------------- 1 | #ifdef ESP8266 2 | #include 3 | #include 4 | #include 5 | #include 6 | ESP8266WebServer server(80); 7 | #else 8 | #include 9 | #include 10 | #include 11 | #include 12 | WebServer server(80); 13 | #endif 14 | 15 | const char* ssid = "........"; 16 | const char* password = "........"; 17 | 18 | #ifdef LED_BUILTIN 19 | const int led = LED_BUILTIN; 20 | #else 21 | const int led = 13; 22 | #endif 23 | 24 | void handleRoot() { 25 | digitalWrite(led, 1); 26 | #ifdef ESP8266 27 | server.send(200, "text/plain", "hello from esp8266!"); 28 | #else 29 | server.send(200, "text/plain", "hello from esp32!"); 30 | #endif 31 | digitalWrite(led, 0); 32 | } 33 | 34 | void handleNotFound(){ 35 | digitalWrite(led, 1); 36 | String message = "File Not Found\n\n"; 37 | message += "URI: "; 38 | message += server.uri(); 39 | message += "\nMethod: "; 40 | message += (server.method() == HTTP_GET)?"GET":"POST"; 41 | message += "\nArguments: "; 42 | message += server.args(); 43 | message += "\n"; 44 | for (uint8_t i=0; i 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | 16 | 17 | // Enter a MAC address for your controller below. 18 | // Newer Ethernet shields have a MAC address printed on a sticker on the shield 19 | byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; 20 | 21 | // Set the static IP address to use if the DHCP fails to assign 22 | IPAddress ip(192, 168, 0, 177); 23 | 24 | WebSocketsClient webSocket; 25 | 26 | 27 | 28 | void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) { 29 | 30 | 31 | switch(type) { 32 | case WStype_DISCONNECTED: 33 | Serial.println("[WSc] Disconnected!\n"); 34 | break; 35 | case WStype_CONNECTED: 36 | { 37 | Serial.print("[WSc] Connected to url: "); 38 | Serial.println((char *)payload); 39 | // send message to server when Connected 40 | webSocket.sendTXT("Connected"); 41 | } 42 | break; 43 | case WStype_TEXT: 44 | Serial.print("[WSc] get text: "); 45 | Serial.println((char *)payload); 46 | // send message to server 47 | // webSocket.sendTXT("message here"); 48 | break; 49 | case WStype_BIN: 50 | Serial.print("[WSc] get binary length: "); 51 | Serial.println(length); 52 | // hexdump(payload, length); 53 | 54 | // send data to server 55 | // webSocket.sendBIN(payload, length); 56 | break; 57 | } 58 | 59 | } 60 | 61 | void setup() 62 | { 63 | // Open serial communications and wait for port to open: 64 | Serial.begin(115200); 65 | while (!Serial) {} 66 | 67 | // start the Ethernet connection: 68 | if (Ethernet.begin(mac) == 0) { 69 | Serial.println("Failed to configure Ethernet using DHCP"); 70 | // no point in carrying on, so do nothing forevermore: 71 | // try to congifure using IP address instead of DHCP: 72 | Ethernet.begin(mac, ip); 73 | } 74 | 75 | webSocket.begin("192.168.0.123", 8011); 76 | webSocket.onEvent(webSocketEvent); 77 | 78 | } 79 | 80 | 81 | void loop() 82 | { 83 | webSocket.loop(); 84 | } 85 | -------------------------------------------------------------------------------- /arduinoWebSockets/examples/WebSocketServer/WebSocketServer.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * WebSocketServer.ino 3 | * 4 | * Created on: 22.05.2015 5 | * 6 | */ 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | ESP8266WiFiMulti WiFiMulti; 16 | 17 | WebSocketsServer webSocket = WebSocketsServer(81); 18 | 19 | #define USE_SERIAL Serial1 20 | 21 | void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) { 22 | 23 | switch(type) { 24 | case WStype_DISCONNECTED: 25 | USE_SERIAL.printf("[%u] Disconnected!\n", num); 26 | break; 27 | case WStype_CONNECTED: 28 | { 29 | IPAddress ip = webSocket.remoteIP(num); 30 | USE_SERIAL.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload); 31 | 32 | // send message to client 33 | webSocket.sendTXT(num, "Connected"); 34 | } 35 | break; 36 | case WStype_TEXT: 37 | USE_SERIAL.printf("[%u] get Text: %s\n", num, payload); 38 | 39 | // send message to client 40 | // webSocket.sendTXT(num, "message here"); 41 | 42 | // send data to all connected clients 43 | // webSocket.broadcastTXT("message here"); 44 | break; 45 | case WStype_BIN: 46 | USE_SERIAL.printf("[%u] get binary length: %u\n", num, length); 47 | hexdump(payload, length); 48 | 49 | // send message to client 50 | // webSocket.sendBIN(num, payload, length); 51 | break; 52 | } 53 | 54 | } 55 | 56 | void setup() { 57 | // USE_SERIAL.begin(921600); 58 | USE_SERIAL.begin(115200); 59 | 60 | //Serial.setDebugOutput(true); 61 | USE_SERIAL.setDebugOutput(true); 62 | 63 | USE_SERIAL.println(); 64 | USE_SERIAL.println(); 65 | USE_SERIAL.println(); 66 | 67 | for(uint8_t t = 4; t > 0; t--) { 68 | USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t); 69 | USE_SERIAL.flush(); 70 | delay(1000); 71 | } 72 | 73 | WiFiMulti.addAP("SSID", "passpasspass"); 74 | 75 | while(WiFiMulti.run() != WL_CONNECTED) { 76 | delay(100); 77 | } 78 | 79 | webSocket.begin(); 80 | webSocket.onEvent(webSocketEvent); 81 | } 82 | 83 | void loop() { 84 | webSocket.loop(); 85 | } 86 | 87 | -------------------------------------------------------------------------------- /arduinoWebSockets/examples/WebSocketServerFragmentation/WebSocketServerFragmentation.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * WebSocketServer.ino 3 | * 4 | * Created on: 22.05.2015 5 | * 6 | */ 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | ESP8266WiFiMulti WiFiMulti; 16 | 17 | WebSocketsServer webSocket = WebSocketsServer(81); 18 | 19 | #define USE_SERIAL Serial 20 | 21 | String fragmentBuffer = ""; 22 | 23 | void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) { 24 | 25 | switch(type) { 26 | case WStype_DISCONNECTED: 27 | USE_SERIAL.printf("[%u] Disconnected!\n", num); 28 | break; 29 | case WStype_CONNECTED: { 30 | IPAddress ip = webSocket.remoteIP(num); 31 | USE_SERIAL.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload); 32 | 33 | // send message to client 34 | webSocket.sendTXT(num, "Connected"); 35 | } 36 | break; 37 | case WStype_TEXT: 38 | USE_SERIAL.printf("[%u] get Text: %s\n", num, payload); 39 | break; 40 | case WStype_BIN: 41 | USE_SERIAL.printf("[%u] get binary length: %u\n", num, length); 42 | hexdump(payload, length); 43 | break; 44 | 45 | // Fragmentation / continuation opcode handling 46 | // case WStype_FRAGMENT_BIN_START: 47 | case WStype_FRAGMENT_TEXT_START: 48 | fragmentBuffer = (char*)payload; 49 | USE_SERIAL.printf("[%u] get start start of Textfragment: %s\n", num, payload); 50 | break; 51 | case WStype_FRAGMENT: 52 | fragmentBuffer += (char*)payload; 53 | USE_SERIAL.printf("[%u] get Textfragment : %s\n", num, payload); 54 | break; 55 | case WStype_FRAGMENT_FIN: 56 | fragmentBuffer += (char*)payload; 57 | USE_SERIAL.printf("[%u] get end of Textfragment: %s\n", num, payload); 58 | USE_SERIAL.printf("[%u] full frame: %s\n", num, fragmentBuffer.c_str()); 59 | break; 60 | } 61 | 62 | } 63 | 64 | void setup() { 65 | // USE_SERIAL.begin(921600); 66 | USE_SERIAL.begin(115200); 67 | 68 | //Serial.setDebugOutput(true); 69 | USE_SERIAL.setDebugOutput(true); 70 | 71 | USE_SERIAL.println(); 72 | USE_SERIAL.println(); 73 | USE_SERIAL.println(); 74 | 75 | for(uint8_t t = 4; t > 0; t--) { 76 | USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t); 77 | USE_SERIAL.flush(); 78 | delay(1000); 79 | } 80 | 81 | WiFiMulti.addAP("SSID", "passpasspass"); 82 | 83 | while(WiFiMulti.run() != WL_CONNECTED) { 84 | delay(100); 85 | } 86 | 87 | webSocket.begin(); 88 | webSocket.onEvent(webSocketEvent); 89 | } 90 | 91 | void loop() { 92 | webSocket.loop(); 93 | } 94 | 95 | -------------------------------------------------------------------------------- /WebServer/examples/WebUpdate/WebUpdate.ino: -------------------------------------------------------------------------------- 1 | /* 2 | To upload through terminal you can use: curl -F "image=@firmware.bin" esp8266-webupdate.local/update 3 | */ 4 | 5 | #ifdef ESP8266 6 | #include 7 | #include 8 | #include 9 | #include 10 | ESP8266WebServer server(80); 11 | const char* host = "esp8266-webupdate"; 12 | #else 13 | #include 14 | #include 15 | #include 16 | #include 17 | WebServer server(80); 18 | const char* host = "esp32-webupdate"; 19 | #endif 20 | 21 | const char* ssid = "........"; 22 | const char* password = "........"; 23 | 24 | const char* serverIndex = "
"; 25 | 26 | void setup(void){ 27 | Serial.begin(115200); 28 | Serial.println(); 29 | Serial.println("Booting Sketch..."); 30 | WiFi.mode(WIFI_AP_STA); 31 | WiFi.begin(ssid, password); 32 | if(WiFi.waitForConnectResult() == WL_CONNECTED){ 33 | MDNS.begin(host); 34 | server.on("/", HTTP_GET, [](){ 35 | server.sendHeader("Connection", "close"); 36 | server.send(200, "text/html", serverIndex); 37 | }); 38 | server.on("/update", HTTP_POST, [](){ 39 | server.sendHeader("Connection", "close"); 40 | server.send(200, "text/plain", (Update.hasError())?"FAIL":"OK"); 41 | ESP.restart(); 42 | },[](){ 43 | HTTPUpload& upload = server.upload(); 44 | if(upload.status == UPLOAD_FILE_START){ 45 | Serial.setDebugOutput(true); 46 | WiFiUDP::stopAll(); 47 | Serial.printf("Update: %s\n", upload.filename.c_str()); 48 | uint32_t maxSketchSpace = (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000; 49 | if(!Update.begin(maxSketchSpace)){//start with max available size 50 | Update.printError(Serial); 51 | } 52 | } else if(upload.status == UPLOAD_FILE_WRITE){ 53 | if(Update.write(upload.buf, upload.currentSize) != upload.currentSize){ 54 | Update.printError(Serial); 55 | } 56 | } else if(upload.status == UPLOAD_FILE_END){ 57 | if(Update.end(true)){ //true to set the size to the current progress 58 | Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize); 59 | } else { 60 | Update.printError(Serial); 61 | } 62 | Serial.setDebugOutput(false); 63 | } 64 | yield(); 65 | }); 66 | server.begin(); 67 | MDNS.addService("http", "tcp", 80); 68 | 69 | Serial.printf("Ready! Open http://%s.local in your browser\n", host); 70 | } else { 71 | Serial.println("WiFi Failed"); 72 | } 73 | } 74 | 75 | void loop(void){ 76 | server.handleClient(); 77 | delay(1); 78 | } 79 | -------------------------------------------------------------------------------- /arduinoWebSockets/examples/WebSocketServerHttpHeaderValidation/WebSocketServerHttpHeaderValidation.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * WebSocketServerHttpHeaderValidation.ino 3 | * 4 | * Created on: 08.06.2016 5 | * 6 | */ 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | ESP8266WiFiMulti WiFiMulti; 16 | 17 | WebSocketsServer webSocket = WebSocketsServer(81); 18 | 19 | #define USE_SERIAL Serial1 20 | 21 | const unsigned long int validSessionId = 12345; //some arbitrary value to act as a valid sessionId 22 | 23 | /* 24 | * Returns a bool value as an indicator to describe whether a user is allowed to initiate a websocket upgrade 25 | * based on the value of a cookie. This function expects the rawCookieHeaderValue to look like this "sessionId=|" 26 | */ 27 | bool isCookieValid(String rawCookieHeaderValue) { 28 | 29 | if (rawCookieHeaderValue.indexOf("sessionId") != -1) { 30 | String sessionIdStr = rawCookieHeaderValue.substring(rawCookieHeaderValue.indexOf("sessionId=") + 10, rawCookieHeaderValue.indexOf("|")); 31 | unsigned long int sessionId = strtoul(sessionIdStr.c_str(), NULL, 10); 32 | return sessionId == validSessionId; 33 | } 34 | return false; 35 | } 36 | 37 | /* 38 | * The WebSocketServerHttpHeaderValFunc delegate passed to webSocket.onValidateHttpHeader 39 | */ 40 | bool validateHttpHeader(String headerName, String headerValue) { 41 | 42 | //assume a true response for any headers not handled by this validator 43 | bool valid = true; 44 | 45 | if(headerName.equalsIgnoreCase("Cookie")) { 46 | //if the header passed is the Cookie header, validate it according to the rules in 'isCookieValid' function 47 | valid = isCookieValid(headerValue); 48 | } 49 | 50 | return valid; 51 | } 52 | 53 | void setup() { 54 | // USE_SERIAL.begin(921600); 55 | USE_SERIAL.begin(115200); 56 | 57 | //Serial.setDebugOutput(true); 58 | USE_SERIAL.setDebugOutput(true); 59 | 60 | USE_SERIAL.println(); 61 | USE_SERIAL.println(); 62 | USE_SERIAL.println(); 63 | 64 | for(uint8_t t = 4; t > 0; t--) { 65 | USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t); 66 | USE_SERIAL.flush(); 67 | delay(1000); 68 | } 69 | 70 | WiFiMulti.addAP("SSID", "passpasspass"); 71 | 72 | while(WiFiMulti.run() != WL_CONNECTED) { 73 | delay(100); 74 | } 75 | 76 | //connecting clients must supply a valid session cookie at websocket upgrade handshake negotiation time 77 | const char * headerkeys[] = { "Cookie" }; 78 | size_t headerKeyCount = sizeof(headerkeys) / sizeof(char*); 79 | webSocket.onValidateHttpHeader(validateHttpHeader, headerkeys, headerKeyCount); 80 | webSocket.begin(); 81 | } 82 | 83 | void loop() { 84 | webSocket.loop(); 85 | } 86 | 87 | -------------------------------------------------------------------------------- /arduinoWebSockets/examples/WebSocketClientSocketIO/WebSocketClientSocketIO.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * WebSocketClientSocketIO.ino 3 | * 4 | * Created on: 06.06.2016 5 | * 6 | */ 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #include 16 | 17 | ESP8266WiFiMulti WiFiMulti; 18 | WebSocketsClient webSocket; 19 | 20 | 21 | #define USE_SERIAL Serial1 22 | 23 | #define MESSAGE_INTERVAL 30000 24 | #define HEARTBEAT_INTERVAL 25000 25 | 26 | uint64_t messageTimestamp = 0; 27 | uint64_t heartbeatTimestamp = 0; 28 | bool isConnected = false; 29 | 30 | void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) { 31 | 32 | 33 | switch(type) { 34 | case WStype_DISCONNECTED: 35 | USE_SERIAL.printf("[WSc] Disconnected!\n"); 36 | isConnected = false; 37 | break; 38 | case WStype_CONNECTED: 39 | { 40 | USE_SERIAL.printf("[WSc] Connected to url: %s\n", payload); 41 | isConnected = true; 42 | 43 | // send message to server when Connected 44 | // socket.io upgrade confirmation message (required) 45 | webSocket.sendTXT("5"); 46 | } 47 | break; 48 | case WStype_TEXT: 49 | USE_SERIAL.printf("[WSc] get text: %s\n", payload); 50 | 51 | // send message to server 52 | // webSocket.sendTXT("message here"); 53 | break; 54 | case WStype_BIN: 55 | USE_SERIAL.printf("[WSc] get binary length: %u\n", length); 56 | hexdump(payload, length); 57 | 58 | // send data to server 59 | // webSocket.sendBIN(payload, length); 60 | break; 61 | } 62 | 63 | } 64 | 65 | void setup() { 66 | // USE_SERIAL.begin(921600); 67 | USE_SERIAL.begin(115200); 68 | 69 | //Serial.setDebugOutput(true); 70 | USE_SERIAL.setDebugOutput(true); 71 | 72 | USE_SERIAL.println(); 73 | USE_SERIAL.println(); 74 | USE_SERIAL.println(); 75 | 76 | for(uint8_t t = 4; t > 0; t--) { 77 | USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t); 78 | USE_SERIAL.flush(); 79 | delay(1000); 80 | } 81 | 82 | WiFiMulti.addAP("SSID", "passpasspass"); 83 | 84 | //WiFi.disconnect(); 85 | while(WiFiMulti.run() != WL_CONNECTED) { 86 | delay(100); 87 | } 88 | 89 | webSocket.beginSocketIO("192.168.0.123", 81); 90 | //webSocket.setAuthorization("user", "Password"); // HTTP Basic Authorization 91 | webSocket.onEvent(webSocketEvent); 92 | 93 | } 94 | 95 | void loop() { 96 | webSocket.loop(); 97 | 98 | if(isConnected) { 99 | 100 | uint64_t now = millis(); 101 | 102 | if(now - messageTimestamp > MESSAGE_INTERVAL) { 103 | messageTimestamp = now; 104 | // example socket.io message with type "messageType" and JSON payload 105 | webSocket.sendTXT("42[\"messageType\",{\"greeting\":\"hello\"}]"); 106 | } 107 | if((now - heartbeatTimestamp) > HEARTBEAT_INTERVAL) { 108 | heartbeatTimestamp = now; 109 | // socket.io heartbeat message 110 | webSocket.sendTXT("2"); 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /Hash/src/Hash.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Hash.cpp 3 | * @date 20.05.2015 4 | * @author Markus Sattler 5 | * 6 | * Copyright (c) 2015 Markus Sattler. All rights reserved. 7 | * This file is part of the esp8266 core for Arduino environment. 8 | * 9 | * This library is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU Lesser General Public 11 | * License as published by the Free Software Foundation; either 12 | * version 2.1 of the License, or (at your option) any later version. 13 | * 14 | * This library is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | * Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public 20 | * License along with this library; if not, write to the Free Software 21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 | * 23 | */ 24 | 25 | #include 26 | 27 | #include "Hash.h" 28 | 29 | extern "C" { 30 | #include "sha1/sha1.h" 31 | #include "sha1/sha1.c" 32 | } 33 | 34 | /** 35 | * create a sha1 hash from data 36 | * @param data uint8_t * 37 | * @param size uint32_t 38 | * @param hash uint8_t[20] 39 | */ 40 | void sha1(uint8_t * data, uint32_t size, uint8_t hash[20]) { 41 | 42 | SHA1_CTX ctx; 43 | 44 | #ifdef DEBUG_SHA1 45 | os_printf("DATA:"); 46 | for(uint16_t i = 0; i < size; i++) { 47 | os_printf("%02X", data[i]); 48 | } 49 | os_printf("\n"); 50 | os_printf("DATA:"); 51 | for(uint16_t i = 0; i < size; i++) { 52 | os_printf("%c", data[i]); 53 | } 54 | os_printf("\n"); 55 | #endif 56 | 57 | SHA1Init(&ctx); 58 | SHA1Update(&ctx, data, size); 59 | SHA1Final(hash, &ctx); 60 | 61 | #ifdef DEBUG_SHA1 62 | os_printf("SHA1:"); 63 | for(uint16_t i = 0; i < 20; i++) { 64 | os_printf("%02X", hash[i]); 65 | } 66 | os_printf("\n\n"); 67 | #endif 68 | } 69 | 70 | void sha1(char * data, uint32_t size, uint8_t hash[20]) { 71 | sha1((uint8_t *) data, size, hash); 72 | } 73 | 74 | void sha1(const uint8_t * data, uint32_t size, uint8_t hash[20]) { 75 | sha1((uint8_t *) data, size, hash); 76 | } 77 | 78 | void sha1(const char * data, uint32_t size, uint8_t hash[20]) { 79 | sha1((uint8_t *) data, size, hash); 80 | } 81 | 82 | void sha1(String data, uint8_t hash[20]) { 83 | sha1(data.c_str(), data.length(), hash); 84 | } 85 | 86 | String sha1(uint8_t* data, uint32_t size) { 87 | uint8_t hash[20]; 88 | String hashStr = ""; 89 | 90 | sha1(&data[0], size, &hash[0]); 91 | 92 | for(uint16_t i = 0; i < 20; i++) { 93 | String hex = String(hash[i], HEX); 94 | if(hex.length() < 2) { 95 | hex = "0" + hex; 96 | } 97 | hashStr += hex; 98 | } 99 | 100 | return hashStr; 101 | } 102 | 103 | String sha1(char* data, uint32_t size) { 104 | return sha1((uint8_t*) data, size); 105 | } 106 | 107 | String sha1(const uint8_t* data, uint32_t size) { 108 | return sha1((uint8_t*) data, size); 109 | } 110 | 111 | String sha1(const char* data, uint32_t size) { 112 | return sha1((uint8_t*) data, size); 113 | } 114 | 115 | String sha1(String data) { 116 | return sha1(data.c_str(), data.length()); 117 | } 118 | 119 | -------------------------------------------------------------------------------- /arduinoWebSockets/examples/Nginx/esp8266.ssl.reverse.proxy.conf: -------------------------------------------------------------------------------- 1 | # ESP8266 nginx SSL reverse proxy configuration file (tested and working on nginx v1.10.0) 2 | 3 | # proxy cache location 4 | proxy_cache_path /opt/etc/nginx/cache levels=1:2 keys_zone=ESP8266_cache:10m max_size=10g inactive=5m use_temp_path=off; 5 | 6 | # webserver proxy 7 | server { 8 | 9 | # general server parameters 10 | listen 50080; 11 | server_name myDomain.net; 12 | access_log /opt/var/log/nginx/myDomain.net.access.log; 13 | 14 | # SSL configuration 15 | ssl on; 16 | ssl_certificate /usr/builtin/etc/certificate/lets-encrypt/myDomain.net/fullchain.pem; 17 | ssl_certificate_key /usr/builtin/etc/certificate/lets-encrypt/myDomain.net/privkey.pem; 18 | ssl_session_cache builtin:1000 shared:SSL:10m; 19 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 20 | ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4; 21 | ssl_prefer_server_ciphers on; 22 | 23 | location / { 24 | 25 | # proxy caching configuration 26 | proxy_cache ESP8266_cache; 27 | proxy_cache_revalidate on; 28 | proxy_cache_min_uses 1; 29 | proxy_cache_use_stale off; 30 | proxy_cache_lock on; 31 | # proxy_cache_bypass $http_cache_control; 32 | # include the sessionId cookie value as part of the cache key - keeps the cache per user 33 | # proxy_cache_key $proxy_host$request_uri$cookie_sessionId; 34 | 35 | # header pass through configuration 36 | proxy_set_header Host $host; 37 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 38 | proxy_set_header X-Forwarded-Proto $scheme; 39 | 40 | # ESP8266 custom headers which identify to the device that it's running through an SSL proxy 41 | proxy_set_header X-SSL On; 42 | proxy_set_header X-SSL-WebserverPort 50080; 43 | proxy_set_header X-SSL-WebsocketPort 50081; 44 | 45 | # extra debug headers 46 | add_header X-Proxy-Cache $upstream_cache_status; 47 | add_header X-Forwarded-For $proxy_add_x_forwarded_for; 48 | 49 | # actual proxying configuration 50 | proxy_ssl_session_reuse on; 51 | # target the IP address of the device with proxy_pass 52 | proxy_pass http://192.168.0.20; 53 | proxy_read_timeout 90; 54 | } 55 | } 56 | 57 | # websocket proxy 58 | server { 59 | 60 | # general server parameters 61 | listen 50081; 62 | server_name myDomain.net; 63 | access_log /opt/var/log/nginx/myDomain.net.wss.access.log; 64 | 65 | # SSL configuration 66 | ssl on; 67 | ssl_certificate /usr/builtin/etc/certificate/lets-encrypt/myDomain.net/fullchain.pem; 68 | ssl_certificate_key /usr/builtin/etc/certificate/lets-encrypt/myDomain.net/privkey.pem; 69 | ssl_session_cache builtin:1000 shared:SSL:10m; 70 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 71 | ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4; 72 | ssl_prefer_server_ciphers on; 73 | 74 | location / { 75 | 76 | # websocket upgrade tunnel configuration 77 | proxy_pass http://192.168.0.20:81; 78 | proxy_http_version 1.1; 79 | proxy_set_header Upgrade $http_upgrade; 80 | proxy_set_header Connection "Upgrade"; 81 | proxy_read_timeout 86400; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /arduinoWebSockets/src/libb64/cencode.c: -------------------------------------------------------------------------------- 1 | /* 2 | cencoder.c - c source to a base64 encoding algorithm implementation 3 | 4 | This is part of the libb64 project, and has been placed in the public domain. 5 | For details, see http://sourceforge.net/projects/libb64 6 | */ 7 | 8 | #include "cencode.h" 9 | 10 | const int CHARS_PER_LINE = 72; 11 | 12 | void base64_init_encodestate(base64_encodestate* state_in) 13 | { 14 | state_in->step = step_A; 15 | state_in->result = 0; 16 | state_in->stepcount = 0; 17 | } 18 | 19 | char base64_encode_value(char value_in) 20 | { 21 | static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 22 | if (value_in > 63) { 23 | return '='; 24 | } 25 | return encoding[(int)value_in]; 26 | } 27 | 28 | int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in) 29 | { 30 | const char* plainchar = plaintext_in; 31 | const char* const plaintextend = plaintext_in + length_in; 32 | char* codechar = code_out; 33 | char result; 34 | char fragment; 35 | 36 | result = state_in->result; 37 | 38 | switch (state_in->step) { 39 | while (1) { 40 | case step_A: 41 | if (plainchar == plaintextend) { 42 | state_in->result = result; 43 | state_in->step = step_A; 44 | return codechar - code_out; 45 | } 46 | fragment = *plainchar++; 47 | result = (fragment & 0x0fc) >> 2; 48 | *codechar++ = base64_encode_value(result); 49 | result = (fragment & 0x003) << 4; 50 | case step_B: 51 | if (plainchar == plaintextend) { 52 | state_in->result = result; 53 | state_in->step = step_B; 54 | return codechar - code_out; 55 | } 56 | fragment = *plainchar++; 57 | result |= (fragment & 0x0f0) >> 4; 58 | *codechar++ = base64_encode_value(result); 59 | result = (fragment & 0x00f) << 2; 60 | case step_C: 61 | if (plainchar == plaintextend) { 62 | state_in->result = result; 63 | state_in->step = step_C; 64 | return codechar - code_out; 65 | } 66 | fragment = *plainchar++; 67 | result |= (fragment & 0x0c0) >> 6; 68 | *codechar++ = base64_encode_value(result); 69 | result = (fragment & 0x03f) >> 0; 70 | *codechar++ = base64_encode_value(result); 71 | 72 | ++(state_in->stepcount); 73 | if (state_in->stepcount == CHARS_PER_LINE/4) { 74 | *codechar++ = '\n'; 75 | state_in->stepcount = 0; 76 | } 77 | } 78 | } 79 | /* control should not reach here */ 80 | return codechar - code_out; 81 | } 82 | 83 | int base64_encode_blockend(char* code_out, base64_encodestate* state_in) 84 | { 85 | char* codechar = code_out; 86 | 87 | switch (state_in->step) { 88 | case step_B: 89 | *codechar++ = base64_encode_value(state_in->result); 90 | *codechar++ = '='; 91 | *codechar++ = '='; 92 | break; 93 | case step_C: 94 | *codechar++ = base64_encode_value(state_in->result); 95 | *codechar++ = '='; 96 | break; 97 | case step_A: 98 | break; 99 | } 100 | *codechar = 0x00; 101 | 102 | return codechar - code_out; 103 | } 104 | 105 | int base64_encode_chars(const char* plaintext_in, int length_in, char* code_out) 106 | { 107 | base64_encodestate _state; 108 | base64_init_encodestate(&_state); 109 | int len = base64_encode_block(plaintext_in, length_in, code_out, &_state); 110 | return len + base64_encode_blockend((code_out + len), &_state); 111 | } 112 | -------------------------------------------------------------------------------- /arduinoWebSockets/README.md: -------------------------------------------------------------------------------- 1 | WebSocket Server and Client for Arduino [![Build Status](https://travis-ci.org/Links2004/arduinoWebSockets.svg?branch=master)](https://travis-ci.org/Links2004/arduinoWebSockets) 2 | =========================================== 3 | 4 | a WebSocket Server and Client for Arduino based on RFC6455. 5 | 6 | 7 | ##### Supported features of RFC6455 ##### 8 | - text frame 9 | - binary frame 10 | - connection close 11 | - ping 12 | - pong 13 | - continuation frame 14 | 15 | ##### Limitations ##### 16 | - max input length is limited to the ram size and the ```WEBSOCKETS_MAX_DATA_SIZE``` define 17 | - max output length has no limit (the hardware is the limit) 18 | - Client send big frames with mask 0x00000000 (on AVR all frames) 19 | - continuation frame reassembly need to be handled in the application code 20 | 21 | ##### Limitations for Async ##### 22 | - Functions called from within the context of the websocket event might not honor `yield()` and/or `delay()`. See [this issue](https://github.com/Links2004/arduinoWebSockets/issues/58#issuecomment-192376395) for more info and a potential workaround. 23 | - wss / SSL is not possible. 24 | 25 | ##### Supported Hardware ##### 26 | - ESP8266 [Arduino for ESP8266](https://github.com/Links2004/Arduino) 27 | - ESP31B 28 | - Particle with STM32 ARM Cortex M3 29 | - ATmega328 with Ethernet Shield (ATmega branch) 30 | - ATmega328 with enc28j60 (ATmega branch) 31 | - ATmega2560 with Ethernet Shield (ATmega branch) 32 | - ATmega2560 with enc28j60 (ATmega branch) 33 | 34 | ###### Note: ###### 35 | 36 | version 2.0 and up is not compatible with AVR/ATmega, check ATmega branch. 37 | 38 | Arduino for AVR not supports std namespace of c++. 39 | 40 | ### wss / SSL ### 41 | supported for: 42 | - wss client on the ESP8266 43 | - wss / SSL is not natively supported in WebSocketsServer however it is possible to achieve secure websockets 44 | by running the device behind an SSL proxy. See [Nginx](examples/Nginx/esp8266.ssl.reverse.proxy.conf) for a 45 | sample Nginx server configuration file to enable this. 46 | 47 | ### ESP Async TCP ### 48 | 49 | This libary can run in Async TCP mode on the ESP. 50 | 51 | The mode can be activated in the ```WebSockets.h``` (see WEBSOCKETS_NETWORK_TYPE define). 52 | 53 | [ESPAsyncTCP](https://github.com/me-no-dev/ESPAsyncTCP) libary is required. 54 | 55 | 56 | ### High Level Client API ### 57 | 58 | - `begin` : Initiate connection sequence to the websocket host. 59 | ``` 60 | void begin(const char *host, uint16_t port, const char * url = "/", const char * protocol = "arduino"); 61 | void begin(String host, uint16_t port, String url = "/", String protocol = "arduino"); 62 | ``` 63 | - `onEvent`: Callback to handle for websocket events 64 | 65 | ``` 66 | void onEvent(WebSocketClientEvent cbEvent); 67 | ``` 68 | 69 | - `WebSocketClientEvent`: Handler for websocket events 70 | ``` 71 | void (*WebSocketClientEvent)(WStype_t type, uint8_t * payload, size_t length) 72 | ``` 73 | Where `WStype_t type` is defined as: 74 | ``` 75 | typedef enum { 76 | WStype_ERROR, 77 | WStype_DISCONNECTED, 78 | WStype_CONNECTED, 79 | WStype_TEXT, 80 | WStype_BIN, 81 | WStype_FRAGMENT_TEXT_START, 82 | WStype_FRAGMENT_BIN_START, 83 | WStype_FRAGMENT, 84 | WStype_FRAGMENT_FIN, 85 | } WStype_t; 86 | ``` 87 | 88 | ### Issues ### 89 | Submit issues to: https://github.com/Links2004/arduinoWebSockets/issues 90 | 91 | [![Join the chat at https://gitter.im/Links2004/arduinoWebSockets](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Links2004/arduinoWebSockets?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 92 | 93 | ### License and credits ### 94 | 95 | The library is licensed under [LGPLv2.1](https://github.com/Links2004/arduinoWebSockets/blob/master/LICENSE) 96 | 97 | [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). 98 | -------------------------------------------------------------------------------- /WebServer/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: python 4 | python: 5 | - "2.7" 6 | 7 | os: 8 | - linux 9 | 10 | env: 11 | - TESTCASE="1.8.3|esp8266|stable|esp8266:esp8266:nodemcuv2:CpuFrequency=80,FlashSize=4M3M" 12 | - TESTCASE="1.8.3|esp8266|devel|esp8266com:esp8266:nodemcuv2:CpuFrequency=80,FlashSize=4M3M" 13 | - TESTCASE="1.8.3|esp32|devel|espressif:esp32:esp32:FlashFreq=40" 14 | 15 | script: 16 | - echo -e "travis_fold:start:sketch_test_env_prepare" 17 | - pip install pyserial 18 | - IFS='|' read -r -a array <<< "${TESTCASE}" 19 | - | 20 | for index in "${!array[@]}" 21 | do 22 | case $index in 23 | 0) IDEVER="${array[index]}" ;; 24 | 1) PLATFORM="${array[index]}" ;; 25 | 2) RELEASE="${array[index]}" ;; 26 | 3) BOARD="${array[index]}" ;; 27 | esac 28 | done 29 | - cd $HOME 30 | - wget -O arduino.tar.xz https://downloads.arduino.cc/arduino-${IDEVER}-linux64.tar.xz 31 | - tar xf arduino.tar.xz 32 | - mv arduino-${IDEVER} $HOME/arduino_ide 33 | - mkdir -p $HOME/Arduino/libraries 34 | - IDEDIR="${HOME}/arduino_ide" 35 | - export PATH="$IDEDIR:$PATH" 36 | - cd ${IDEDIR} 37 | - which arduino 38 | - | 39 | if [[ $PLATFORM == "esp8266" ]] && [[ $RELEASE == "stable" ]] 40 | then 41 | arduino --pref "boardsmanager.additional.urls=http://arduino.esp8266.com/stable/package_esp8266com_index.json" --save-prefs 42 | arduino --install-boards "esp8266:esp8266" 43 | fi 44 | - | 45 | if [[ $PLATFORM == "esp8266" ]] && [[ $RELEASE == "devel" ]] 46 | then 47 | mkdir -p hardware/esp8266com 48 | cd hardware/esp8266com 49 | git clone https://github.com/esp8266/Arduino.git esp8266 50 | cd esp8266/tools 51 | python get.py 52 | fi 53 | - | 54 | if [[ $PLATFORM == "esp32" ]] && [[ $RELEASE == "devel" ]] 55 | then 56 | mkdir -p hardware/espressif 57 | cd hardware/espressif 58 | git clone https://github.com/espressif/arduino-esp32.git esp32 59 | cd esp32/tools/ 60 | python get.py 61 | fi 62 | - arduino --pref "compiler.warning_level=all" --save-prefs 63 | - echo -e "travis_fold:end:sketch_test_env_prepare" 64 | - echo -e "travis_fold:start:install_library" 65 | - cd $HOME/Arduino/libraries 66 | - git clone https://github.com/bbx10/WebServer_tng ${HOME}/Arduino/libraries/WebServer 67 | - echo -e "travis_fold:end:install_library" 68 | - echo -e "travis_fold:start:AdvancedWebServer" 69 | - cd ${HOME}/Arduino/libraries/WebServer/examples 70 | - arduino --verbose-build --verify --board ${BOARD} AdvancedWebServer/AdvancedWebServer.ino 71 | - echo -e "travis_fold:end:AdvancedWebServer" 72 | - echo -e "travis_fold:start:HelloServer" 73 | - arduino --verbose-build --verify --board ${BOARD} HelloServer/HelloServer.ino 74 | - echo -e "travis_fold:end:HelloServer" 75 | - echo -e "travis_fold:start:HttpBasicAuth" 76 | - arduino --verbose-build --verify --board ${BOARD} HttpBasicAuth/HttpBasicAuth.ino 77 | - echo -e "travis_fold:end:HttpBasicAuth" 78 | - echo -e "travis_fold:start:SDWebServer" 79 | - arduino --verbose-build --verify --board ${BOARD} SDWebServer/SDWebServer.ino 80 | - echo -e "travis_fold:end:SDWebServer" 81 | - echo -e "travis_fold:start:SimpleAuthentification" 82 | - arduino --verbose-build --verify --board ${BOARD} SimpleAuthentification/SimpleAuthentification.ino 83 | - echo -e "travis_fold:end:SimpleAuthentification" 84 | - | 85 | if [[ $PLATFORM == "esp8266" ]] 86 | then 87 | echo -e "travis_fold:start:FSBrowser" 88 | arduino --verbose-build --verify --board ${BOARD} FSBrowser/FSBrowser.ino 89 | echo -e "travis_fold:end:FSBrowser" 90 | echo -e "travis_fold:start:WebUpdate" 91 | arduino --verbose-build --verify --board ${BOARD} WebUpdate/WebUpdate.ino 92 | echo -e "travis_fold:end:WebUpdate" 93 | fi 94 | 95 | notifications: 96 | email: 97 | on_success: change 98 | on_failure: change 99 | 100 | -------------------------------------------------------------------------------- /WebServer/examples/FSBrowser/data/index.htm: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 21 | 22 | ESP Monitor 23 | 24 | 85 | 86 | 87 |
88 | 89 | 90 | 91 | 92 |
93 |
94 |
95 |
96 | 97 | -------------------------------------------------------------------------------- /arduinoWebSockets/src/libb64/cdecode.c: -------------------------------------------------------------------------------- 1 | /* 2 | cdecoder.c - c source to a base64 decoding algorithm implementation 3 | 4 | This is part of the libb64 project, and has been placed in the public domain. 5 | For details, see http://sourceforge.net/projects/libb64 6 | */ 7 | 8 | #include "cdecode.h" 9 | #include 10 | 11 | static int base64_decode_value_signed(int8_t value_in){ 12 | static const int8_t decoding[] = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51}; 13 | static const int8_t decoding_size = sizeof(decoding); 14 | value_in -= 43; 15 | if (value_in < 0 || value_in > decoding_size) return -1; 16 | return decoding[(int)value_in]; 17 | } 18 | 19 | void base64_init_decodestate(base64_decodestate* state_in){ 20 | state_in->step = step_a; 21 | state_in->plainchar = 0; 22 | } 23 | 24 | static int base64_decode_block_signed(const int8_t* code_in, const int length_in, int8_t* plaintext_out, base64_decodestate* state_in){ 25 | const int8_t* codechar = code_in; 26 | int8_t* plainchar = plaintext_out; 27 | int8_t fragment; 28 | 29 | *plainchar = state_in->plainchar; 30 | 31 | switch (state_in->step){ 32 | while (1){ 33 | case step_a: 34 | do { 35 | if (codechar == code_in+length_in){ 36 | state_in->step = step_a; 37 | state_in->plainchar = *plainchar; 38 | return plainchar - plaintext_out; 39 | } 40 | fragment = (int8_t)base64_decode_value_signed(*codechar++); 41 | } while (fragment < 0); 42 | *plainchar = (fragment & 0x03f) << 2; 43 | case step_b: 44 | do { 45 | if (codechar == code_in+length_in){ 46 | state_in->step = step_b; 47 | state_in->plainchar = *plainchar; 48 | return plainchar - plaintext_out; 49 | } 50 | fragment = (int8_t)base64_decode_value_signed(*codechar++); 51 | } while (fragment < 0); 52 | *plainchar++ |= (fragment & 0x030) >> 4; 53 | *plainchar = (fragment & 0x00f) << 4; 54 | case step_c: 55 | do { 56 | if (codechar == code_in+length_in){ 57 | state_in->step = step_c; 58 | state_in->plainchar = *plainchar; 59 | return plainchar - plaintext_out; 60 | } 61 | fragment = (int8_t)base64_decode_value_signed(*codechar++); 62 | } while (fragment < 0); 63 | *plainchar++ |= (fragment & 0x03c) >> 2; 64 | *plainchar = (fragment & 0x003) << 6; 65 | case step_d: 66 | do { 67 | if (codechar == code_in+length_in){ 68 | state_in->step = step_d; 69 | state_in->plainchar = *plainchar; 70 | return plainchar - plaintext_out; 71 | } 72 | fragment = (int8_t)base64_decode_value_signed(*codechar++); 73 | } while (fragment < 0); 74 | *plainchar++ |= (fragment & 0x03f); 75 | } 76 | } 77 | /* control should not reach here */ 78 | return plainchar - plaintext_out; 79 | } 80 | 81 | static int base64_decode_chars_signed(const int8_t* code_in, const int length_in, int8_t* plaintext_out){ 82 | base64_decodestate _state; 83 | base64_init_decodestate(&_state); 84 | int len = base64_decode_block_signed(code_in, length_in, plaintext_out, &_state); 85 | if(len > 0) plaintext_out[len] = 0; 86 | return len; 87 | } 88 | 89 | int base64_decode_value(char value_in){ 90 | return base64_decode_value_signed(*((int8_t *) &value_in)); 91 | } 92 | 93 | int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in){ 94 | return base64_decode_block_signed((int8_t *) code_in, length_in, (int8_t *) plaintext_out, state_in); 95 | } 96 | 97 | int base64_decode_chars(const char* code_in, const int length_in, char* plaintext_out){ 98 | return base64_decode_chars_signed((int8_t *) code_in, length_in, (int8_t *) plaintext_out); 99 | } 100 | -------------------------------------------------------------------------------- /arduinoWebSockets/examples/WebSocketServer_LEDcontrol/WebSocketServer_LEDcontrol.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * WebSocketServer_LEDcontrol.ino 3 | * 4 | * Created on: 26.11.2015 5 | * 6 | */ 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define LED_RED 15 18 | #define LED_GREEN 12 19 | #define LED_BLUE 13 20 | 21 | #define USE_SERIAL Serial 22 | 23 | 24 | ESP8266WiFiMulti WiFiMulti; 25 | 26 | ESP8266WebServer server = ESP8266WebServer(80); 27 | WebSocketsServer webSocket = WebSocketsServer(81); 28 | 29 | void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) { 30 | 31 | switch(type) { 32 | case WStype_DISCONNECTED: 33 | USE_SERIAL.printf("[%u] Disconnected!\n", num); 34 | break; 35 | case WStype_CONNECTED: { 36 | IPAddress ip = webSocket.remoteIP(num); 37 | USE_SERIAL.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload); 38 | 39 | // send message to client 40 | webSocket.sendTXT(num, "Connected"); 41 | } 42 | break; 43 | case WStype_TEXT: 44 | USE_SERIAL.printf("[%u] get Text: %s\n", num, payload); 45 | 46 | if(payload[0] == '#') { 47 | // we get RGB data 48 | 49 | // decode rgb data 50 | uint32_t rgb = (uint32_t) strtol((const char *) &payload[1], NULL, 16); 51 | 52 | analogWrite(LED_RED, ((rgb >> 16) & 0xFF)); 53 | analogWrite(LED_GREEN, ((rgb >> 8) & 0xFF)); 54 | analogWrite(LED_BLUE, ((rgb >> 0) & 0xFF)); 55 | } 56 | 57 | break; 58 | } 59 | 60 | } 61 | 62 | void setup() { 63 | //USE_SERIAL.begin(921600); 64 | USE_SERIAL.begin(115200); 65 | 66 | //USE_SERIAL.setDebugOutput(true); 67 | 68 | USE_SERIAL.println(); 69 | USE_SERIAL.println(); 70 | USE_SERIAL.println(); 71 | 72 | for(uint8_t t = 4; t > 0; t--) { 73 | USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t); 74 | USE_SERIAL.flush(); 75 | delay(1000); 76 | } 77 | 78 | pinMode(LED_RED, OUTPUT); 79 | pinMode(LED_GREEN, OUTPUT); 80 | pinMode(LED_BLUE, OUTPUT); 81 | 82 | digitalWrite(LED_RED, 1); 83 | digitalWrite(LED_GREEN, 1); 84 | digitalWrite(LED_BLUE, 1); 85 | 86 | WiFiMulti.addAP("SSID", "passpasspass"); 87 | 88 | while(WiFiMulti.run() != WL_CONNECTED) { 89 | delay(100); 90 | } 91 | 92 | // start webSocket server 93 | webSocket.begin(); 94 | webSocket.onEvent(webSocketEvent); 95 | 96 | if(MDNS.begin("esp8266")) { 97 | USE_SERIAL.println("MDNS responder started"); 98 | } 99 | 100 | // handle index 101 | server.on("/", []() { 102 | // send index.html 103 | server.send(200, "text/html", "LED Control:

R:
G:
B:
"); 104 | }); 105 | 106 | server.begin(); 107 | 108 | // Add service to MDNS 109 | MDNS.addService("http", "tcp", 80); 110 | MDNS.addService("ws", "tcp", 81); 111 | 112 | digitalWrite(LED_RED, 0); 113 | digitalWrite(LED_GREEN, 0); 114 | digitalWrite(LED_BLUE, 0); 115 | 116 | } 117 | 118 | void loop() { 119 | webSocket.loop(); 120 | server.handleClient(); 121 | } 122 | 123 | -------------------------------------------------------------------------------- /WebServer/examples/SimpleAuthentification/SimpleAuthentification.ino: -------------------------------------------------------------------------------- 1 | #ifdef ESP8266 2 | #include 3 | #include 4 | #include 5 | ESP8266WebServer server(80); 6 | #else 7 | #include 8 | #include 9 | #include 10 | WebServer server(80); 11 | #endif 12 | 13 | const char* ssid = "........"; 14 | const char* password = "........"; 15 | 16 | //Check if header is present and correct 17 | bool is_authentified(){ 18 | Serial.println("Enter is_authentified"); 19 | if (server.hasHeader("Cookie")){ 20 | Serial.print("Found cookie: "); 21 | String cookie = server.header("Cookie"); 22 | Serial.println(cookie); 23 | if (cookie.indexOf("ESPSESSIONID=1") != -1) { 24 | Serial.println("Authentification Successful"); 25 | return true; 26 | } 27 | } 28 | Serial.println("Authentification Failed"); 29 | return false; 30 | } 31 | 32 | //login page, also called for disconnect 33 | void handleLogin(){ 34 | String msg; 35 | if (server.hasHeader("Cookie")){ 36 | Serial.print("Found cookie: "); 37 | String cookie = server.header("Cookie"); 38 | Serial.println(cookie); 39 | } 40 | if (server.hasArg("DISCONNECT")){ 41 | Serial.println("Disconnection"); 42 | server.sendHeader("Location","/login"); 43 | server.sendHeader("Cache-Control","no-cache"); 44 | server.sendHeader("Set-Cookie","ESPSESSIONID=0"); 45 | server.send(301); 46 | return; 47 | } 48 | if (server.hasArg("USERNAME") && server.hasArg("PASSWORD")){ 49 | if (server.arg("USERNAME") == "admin" && server.arg("PASSWORD") == "admin" ){ 50 | server.sendHeader("Location","/"); 51 | server.sendHeader("Cache-Control","no-cache"); 52 | server.sendHeader("Set-Cookie","ESPSESSIONID=1"); 53 | server.send(301); 54 | Serial.println("Log in Successful"); 55 | return; 56 | } 57 | msg = "Wrong username/password! try again."; 58 | Serial.println("Log in Failed"); 59 | } 60 | String content = "
To log in, please use : admin/admin
"; 61 | content += "User:
"; 62 | content += "Password:
"; 63 | content += "
" + msg + "
"; 64 | content += "You also can go here"; 65 | server.send(200, "text/html", content); 66 | } 67 | 68 | //root page can be accessed only if authentification is ok 69 | void handleRoot(){ 70 | Serial.println("Enter handleRoot"); 71 | String header; 72 | if (!is_authentified()){ 73 | server.sendHeader("Location","/login"); 74 | server.sendHeader("Cache-Control","no-cache"); 75 | server.send(301); 76 | return; 77 | } 78 | String content = "

hello, you successfully connected to esp8266/esp32!


"; 79 | if (server.hasHeader("User-Agent")){ 80 | content += "the user agent used is : " + server.header("User-Agent") + "

"; 81 | } 82 | content += "You can access this page until you disconnect"; 83 | server.send(200, "text/html", content); 84 | } 85 | 86 | //no need authentification 87 | void handleNotFound(){ 88 | String message = "File Not Found\n\n"; 89 | message += "URI: "; 90 | message += server.uri(); 91 | message += "\nMethod: "; 92 | message += (server.method() == HTTP_GET)?"GET":"POST"; 93 | message += "\nArguments: "; 94 | message += server.args(); 95 | message += "\n"; 96 | for (uint8_t i=0; i, Contact: becker@informatik.uni-wuerzburg.de 9 | */ 10 | 11 | // PRE 12 | 13 | #define USE_SERIAL Serial 14 | 15 | 16 | // LIBRARIES 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | #include 23 | 24 | 25 | // SETTINGS 26 | 27 | const char* wlan_ssid = "yourssid"; 28 | const char* wlan_password = "somepassword"; 29 | 30 | const char* ws_host = "the.host.net"; 31 | const int ws_port = 80; 32 | 33 | // base URL for SockJS (websocket) connection 34 | // The complete URL will look something like this(cf. http://sockjs.github.io/sockjs-protocol/sockjs-protocol-0.3.3.html#section-36): 35 | // ws://://<3digits>//websocket 36 | // For the default config of Spring's SockJS/STOMP support the default base URL is "/socketentry/". 37 | const char* ws_baseurl = "/socketentry/"; // don't forget leading and trailing "/" !!! 38 | 39 | 40 | // VARIABLES 41 | 42 | WebSocketsClient webSocket; 43 | 44 | 45 | // FUNCTIONS 46 | 47 | void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) { 48 | 49 | switch (type) { 50 | case WStype_DISCONNECTED: 51 | USE_SERIAL.printf("[WSc] Disconnected!\n"); 52 | break; 53 | case WStype_CONNECTED: 54 | { 55 | USE_SERIAL.printf("[WSc] Connected to url: %s\n", payload); 56 | } 57 | break; 58 | case WStype_TEXT: 59 | { 60 | // ##################### 61 | // handle STOMP protocol 62 | // ##################### 63 | 64 | String text = (char*) payload; 65 | 66 | USE_SERIAL.printf("[WSc] get text: %s\n", payload); 67 | 68 | if (payload[0] == 'h') { 69 | 70 | USE_SERIAL.println("Heartbeat!"); 71 | 72 | } else if (payload[0] == 'o') { 73 | 74 | // on open connection 75 | char *msg = "[\"CONNECT\\naccept-version:1.1,1.0\\nheart-beat:10000,10000\\n\\n\\u0000\"]"; 76 | webSocket.sendTXT(msg); 77 | 78 | } else if (text.startsWith("a[\"CONNECTED")) { 79 | 80 | // subscribe to some channels 81 | 82 | char *msg = "[\"SUBSCRIBE\\nid:sub-0\\ndestination:/user/queue/messages\\n\\n\\u0000\"]"; 83 | webSocket.sendTXT(msg); 84 | delay(1000); 85 | 86 | // and send a message 87 | 88 | msg = "[\"SEND\\ndestination:/app/message\\n\\n{\\\"user\\\":\\\"esp\\\",\\\"message\\\":\\\"Hello!\\\"}\\u0000\"]"; 89 | webSocket.sendTXT(msg); 90 | delay(1000); 91 | } 92 | 93 | break; 94 | } 95 | case WStype_BIN: 96 | USE_SERIAL.printf("[WSc] get binary length: %u\n", length); 97 | hexdump(payload, length); 98 | 99 | // send data to server 100 | // webSocket.sendBIN(payload, length); 101 | break; 102 | } 103 | 104 | } 105 | 106 | void setup() { 107 | 108 | // setup serial 109 | 110 | // USE_SERIAL.begin(921600); 111 | USE_SERIAL.begin(115200); 112 | 113 | // USE_SERIAL.setDebugOutput(true); 114 | 115 | USE_SERIAL.println(); 116 | 117 | 118 | // connect to WiFi 119 | 120 | USE_SERIAL.print("Logging into WLAN: "); Serial.print(wlan_ssid); Serial.print(" ..."); 121 | WiFi.mode(WIFI_STA); 122 | WiFi.begin(wlan_ssid, wlan_password); 123 | 124 | while (WiFi.status() != WL_CONNECTED) { 125 | delay(500); 126 | USE_SERIAL.print("."); 127 | } 128 | USE_SERIAL.println(" success."); 129 | USE_SERIAL.print("IP: "); USE_SERIAL.println(WiFi.localIP()); 130 | 131 | 132 | // ##################### 133 | // create socket url according to SockJS protocol (cf. http://sockjs.github.io/sockjs-protocol/sockjs-protocol-0.3.3.html#section-36) 134 | // ##################### 135 | String socketUrl = ws_baseurl; 136 | socketUrl += random(0, 999); 137 | socketUrl += "/"; 138 | socketUrl += random(0, 999999); // should be a random string, but this works (see ) 139 | socketUrl += "/websocket"; 140 | 141 | // connect to websocket 142 | webSocket.begin(ws_host, ws_port, socketUrl); 143 | webSocket.setExtraHeaders(); // remove "Origin: file://" header because it breaks the connection with Spring's default websocket config 144 | // webSocket.setExtraHeaders("foo: I am so funny\r\nbar: not"); // some headers, in case you feel funny 145 | webSocket.onEvent(webSocketEvent); 146 | } 147 | 148 | void loop() { 149 | webSocket.loop(); 150 | } 151 | -------------------------------------------------------------------------------- /WebServer/examples/AdvancedWebServer/AdvancedWebServer.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Majenko Technologies 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, 6 | * are permitted provided that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this 9 | * list of conditions and the following disclaimer. 10 | * 11 | * * Redistributions in binary form must reproduce the above copyright notice, this 12 | * list of conditions and the following disclaimer in the documentation and/or 13 | * other materials provided with the distribution. 14 | * 15 | * * Neither the name of Majenko Technologies nor the names of its 16 | * contributors may be used to endorse or promote products derived from 17 | * this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 23 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 26 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #ifdef ESP8266 32 | #include 33 | #include 34 | #include 35 | #include 36 | ESP8266WebServer server ( 80 ); 37 | #else 38 | #include 39 | #include 40 | #include 41 | #include 42 | WebServer server ( 80 ); 43 | #endif 44 | 45 | const char *ssid = "YourSSIDHere"; 46 | const char *password = "YourPSKHere"; 47 | 48 | #ifdef LED_BUILTIN 49 | const int led = LED_BUILTIN; 50 | #else 51 | const int led = 13; 52 | #endif 53 | 54 | void handleRoot() { 55 | digitalWrite ( led, 1 ); 56 | char temp[400]; 57 | int sec = millis() / 1000; 58 | int min = sec / 60; 59 | int hr = min / 60; 60 | 61 | snprintf ( temp, 400, 62 | 63 | "\ 64 | \ 65 | \ 66 | ESP8266/ESP32 Demo\ 67 | \ 70 | \ 71 | \ 72 |

Hello from ESP8266/ESP32!

\ 73 |

Uptime: %02d:%02d:%02d

\ 74 | \ 75 | \ 76 | ", 77 | 78 | hr, min % 60, sec % 60 79 | ); 80 | server.send ( 200, "text/html", temp ); 81 | digitalWrite ( led, 0 ); 82 | } 83 | 84 | void handleNotFound() { 85 | digitalWrite ( led, 1 ); 86 | String message = "File Not Found\n\n"; 87 | message += "URI: "; 88 | message += server.uri(); 89 | message += "\nMethod: "; 90 | message += ( server.method() == HTTP_GET ) ? "GET" : "POST"; 91 | message += "\nArguments: "; 92 | message += server.args(); 93 | message += "\n"; 94 | 95 | for ( uint8_t i = 0; i < server.args(); i++ ) { 96 | message += " " + server.argName ( i ) + ": " + server.arg ( i ) + "\n"; 97 | } 98 | 99 | server.send ( 404, "text/plain", message ); 100 | digitalWrite ( led, 0 ); 101 | } 102 | 103 | void setup ( void ) { 104 | pinMode ( led, OUTPUT ); 105 | digitalWrite ( led, 0 ); 106 | Serial.begin ( 115200 ); 107 | WiFi.begin ( ssid, password ); 108 | Serial.println ( "" ); 109 | 110 | // Wait for connection 111 | while ( WiFi.status() != WL_CONNECTED ) { 112 | delay ( 500 ); 113 | Serial.print ( "." ); 114 | } 115 | 116 | Serial.println ( "" ); 117 | Serial.print ( "Connected to " ); 118 | Serial.println ( ssid ); 119 | Serial.print ( "IP address: " ); 120 | Serial.println ( WiFi.localIP() ); 121 | 122 | #ifdef ESP8266 123 | if ( MDNS.begin ( "esp8266" ) ) { 124 | #else 125 | if ( MDNS.begin ( "esp32" ) ) { 126 | #endif 127 | Serial.println ( "MDNS responder started" ); 128 | } 129 | 130 | server.on ( "/", handleRoot ); 131 | server.on ( "/test.svg", drawGraph ); 132 | server.on ( "/inline", []() { 133 | server.send ( 200, "text/plain", "this works as well" ); 134 | } ); 135 | server.onNotFound ( handleNotFound ); 136 | server.begin(); 137 | Serial.println ( "HTTP server started" ); 138 | } 139 | 140 | void loop ( void ) { 141 | server.handleClient(); 142 | } 143 | 144 | void drawGraph() { 145 | String out = ""; 146 | char temp[100]; 147 | out += "\n"; 148 | out += "\n"; 149 | out += "\n"; 150 | int y = rand() % 130; 151 | for (int x = 10; x < 390; x+= 10) { 152 | int y2 = rand() % 130; 153 | sprintf(temp, "\n", x, 140 - y, x + 10, 140 - y2); 154 | out += temp; 155 | y = y2; 156 | } 157 | out += "\n\n"; 158 | 159 | server.send ( 200, "image/svg+xml", out); 160 | } 161 | -------------------------------------------------------------------------------- /arduinoWebSockets/src/WebSocketsClient.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file WebSocketsClient.h 3 | * @date 20.05.2015 4 | * @author Markus Sattler 5 | * 6 | * Copyright (c) 2015 Markus Sattler. All rights reserved. 7 | * This file is part of the WebSockets for Arduino. 8 | * 9 | * This library is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU Lesser General Public 11 | * License as published by the Free Software Foundation; either 12 | * version 2.1 of the License, or (at your option) any later version. 13 | * 14 | * This library is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | * Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public 20 | * License along with this library; if not, write to the Free Software 21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 | * 23 | */ 24 | 25 | #ifndef WEBSOCKETSCLIENT_H_ 26 | #define WEBSOCKETSCLIENT_H_ 27 | 28 | #include "WebSockets.h" 29 | 30 | class WebSocketsClient: private WebSockets { 31 | public: 32 | #ifdef __AVR__ 33 | typedef void (*WebSocketClientEvent)(WStype_t type, uint8_t * payload, size_t length); 34 | #else 35 | typedef std::function WebSocketClientEvent; 36 | #endif 37 | 38 | 39 | WebSocketsClient(void); 40 | ~WebSocketsClient(void); 41 | 42 | void begin(const char *host, uint16_t port, const char * url = "/", const char * protocol = "arduino"); 43 | void begin(String host, uint16_t port, String url = "/", String protocol = "arduino"); 44 | 45 | #if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) 46 | void beginSSL(const char *host, uint16_t port, const char * url = "/", const char * = "", const char * protocol = "arduino"); 47 | void beginSSL(String host, uint16_t port, String url = "/", String fingerprint = "", String protocol = "arduino"); 48 | #endif 49 | 50 | void beginSocketIO(const char *host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * protocol = "arduino"); 51 | void beginSocketIO(String host, uint16_t port, String url = "/socket.io/?EIO=3", String protocol = "arduino"); 52 | 53 | #if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) 54 | void beginSocketIOSSL(const char *host, uint16_t port, const char * url = "/socket.io/?EIO=3", const char * protocol = "arduino"); 55 | void beginSocketIOSSL(String host, uint16_t port, String url = "/socket.io/?EIO=3", String protocol = "arduino"); 56 | #endif 57 | 58 | #if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) 59 | void loop(void); 60 | #else 61 | // Async interface not need a loop call 62 | void loop(void) __attribute__ ((deprecated)) {} 63 | #endif 64 | 65 | void onEvent(WebSocketClientEvent cbEvent); 66 | 67 | bool sendTXT(uint8_t * payload, size_t length = 0, bool headerToPayload = false); 68 | bool sendTXT(const uint8_t * payload, size_t length = 0); 69 | bool sendTXT(char * payload, size_t length = 0, bool headerToPayload = false); 70 | bool sendTXT(const char * payload, size_t length = 0); 71 | bool sendTXT(String & payload); 72 | 73 | bool sendBIN(uint8_t * payload, size_t length, bool headerToPayload = false); 74 | bool sendBIN(const uint8_t * payload, size_t length); 75 | 76 | bool sendPing(uint8_t * payload = NULL, size_t length = 0); 77 | bool sendPing(String & payload); 78 | 79 | void disconnect(void); 80 | 81 | void setAuthorization(const char * user, const char * password); 82 | void setAuthorization(const char * auth); 83 | 84 | void setExtraHeaders(const char * extraHeaders = NULL); 85 | 86 | void setReconnectInterval(unsigned long time); 87 | 88 | protected: 89 | String _host; 90 | uint16_t _port; 91 | 92 | #if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) 93 | String _fingerprint; 94 | #endif 95 | WSclient_t _client; 96 | 97 | WebSocketClientEvent _cbEvent; 98 | 99 | unsigned long _lastConnectionFail; 100 | unsigned long _reconnectInterval; 101 | 102 | void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin); 103 | 104 | void clientDisconnect(WSclient_t * client); 105 | bool clientIsConnected(WSclient_t * client); 106 | 107 | #if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) 108 | void handleClientData(void); 109 | #endif 110 | 111 | void sendHeader(WSclient_t * client); 112 | void handleHeader(WSclient_t * client, String * headerLine); 113 | 114 | void connectedCb(); 115 | void connectFailedCb(); 116 | 117 | #if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) 118 | void asyncConnect(); 119 | #endif 120 | 121 | /** 122 | * called for sending a Event to the app 123 | * @param type WStype_t 124 | * @param payload uint8_t * 125 | * @param length size_t 126 | */ 127 | virtual void runCbEvent(WStype_t type, uint8_t * payload, size_t length) { 128 | if(_cbEvent) { 129 | _cbEvent(type, payload, length); 130 | } 131 | } 132 | 133 | }; 134 | 135 | #endif /* WEBSOCKETSCLIENT_H_ */ 136 | -------------------------------------------------------------------------------- /wifiPicker/src/wifiPicker.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "wifiPicker.h" 9 | 10 | WiFiMulti WiFiMulti; 11 | WebServer wifiPickerServer(80); 12 | WebSocketsServer wifiPickerWebSocket = WebSocketsServer(81); 13 | 14 | bool DEBUG_PRINT = false; 15 | bool IS_SETUP_DONE = false; 16 | String NEW_SSID_STRING; 17 | String NEW_PW_STRING; 18 | String NETWORK_LIST; 19 | 20 | void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) { 21 | 22 | switch(type) { 23 | case WStype_DISCONNECTED: 24 | break; 25 | case WStype_CONNECTED: 26 | break; 27 | case WStype_TEXT: 28 | if(String((const char *)payload).startsWith("READYFORNETWORKS")) 29 | { 30 | wifiPickerWebSocket.sendTXT(num, NETWORK_LIST); 31 | } 32 | break; 33 | } 34 | } 35 | 36 | void setDebugPrint(bool ONOFF) 37 | { 38 | DEBUG_PRINT = ONOFF; 39 | } 40 | void debugPrint(String PRINT) 41 | { 42 | if(DEBUG_PRINT) 43 | { 44 | Serial.println(PRINT); 45 | } 46 | } 47 | bool attemptAutoConnect(void) 48 | { 49 | int counter = 0; 50 | bool WAS_ABLE_TO_CONNNECT_TO_NETWORK = true; 51 | bool BOOT_INTO_AP_MODE_FLAG = false; 52 | 53 | WiFi.begin(); 54 | // TODO: If AP mode flag is false, attempt to 55 | // connect known network. 56 | if(!BOOT_INTO_AP_MODE_FLAG) 57 | { 58 | while (WiFi.status() != WL_CONNECTED) 59 | { 60 | delay(500); 61 | counter++; 62 | if(counter>=20) 63 | { 64 | debugPrint("CAN NOT CONNECT TO NETWORK"); 65 | WAS_ABLE_TO_CONNNECT_TO_NETWORK = false; 66 | break; 67 | } 68 | } 69 | } 70 | return WAS_ABLE_TO_CONNNECT_TO_NETWORK?1:0; 71 | } 72 | bool attemptManualConnect(const char* NEW_SSID, const char* NEW_PW) 73 | { 74 | int counter = 0; 75 | bool WAS_ABLE_TO_CONNNECT_TO_NETWORK = true; 76 | bool BOOT_INTO_AP_MODE_FLAG = false; 77 | 78 | WiFi.begin(NEW_SSID,NEW_PW); 79 | debugPrint("ATTEMPTING TO CONNECT TO NEW NETWORK WITH SSID:"+String(NEW_SSID)+" AND PW:"+String(NEW_PW)); 80 | while (WiFi.status() != WL_CONNECTED) 81 | { 82 | delay(500); 83 | counter++; 84 | if(counter>=20) 85 | { 86 | debugPrint("CAN NOT CONNECT TO NETWORK"); 87 | debugPrint("RESETTING"); 88 | ESP.restart(); 89 | break; 90 | } 91 | } 92 | debugPrint("CONNNECTION ESTABLISHED"); 93 | return 1; 94 | } 95 | String wifiScan(void) 96 | { 97 | String wifiNetworkList; 98 | WiFi.mode(WIFI_STA); 99 | WiFi.disconnect(); 100 | delay(100); 101 | debugPrint("SCANNING NETWORKS"); 102 | int NUMBER_OF_NETWORKS = WiFi.scanNetworks(); 103 | if (NUMBER_OF_NETWORKS == 0) 104 | { 105 | debugPrint("NO NETWORKS FOUND"); 106 | } 107 | else 108 | { 109 | debugPrint(String(NUMBER_OF_NETWORKS)+" NETWORKS FOUND"); 110 | for (int NETWORK_ID = 0; NETWORK_ID < NUMBER_OF_NETWORKS; ++NETWORK_ID) 111 | { 112 | wifiNetworkList += String(WiFi.SSID(NETWORK_ID)); 113 | wifiNetworkList += "\n"; 114 | delay(10); 115 | } 116 | } 117 | 118 | return wifiNetworkList; 119 | } 120 | void handleWifiPickerRoot() 121 | { 122 | wifiPickerServer.send_P(200, "text/html", WIFIPICKER_HTML); 123 | } 124 | void handleWifiPickerDone() 125 | { 126 | wifiPickerServer.send(200, "text/plain", "DONE!"); 127 | 128 | NEW_SSID_STRING = wifiPickerServer.arg("SSID"); 129 | NEW_PW_STRING = wifiPickerServer.arg("PW"); 130 | 131 | debugPrint("NEW SSID: "+NEW_SSID_STRING); 132 | debugPrint("NEW PW: "+NEW_PW_STRING); 133 | IS_SETUP_DONE = true; 134 | } 135 | void handleWifiPickerNotFound() 136 | { 137 | String message = "File Not Found\n\n"; 138 | message += "URI: "; 139 | message += wifiPickerServer.uri(); 140 | message += "\nMethod: "; 141 | message += (wifiPickerServer.method() == HTTP_GET)?"GET":"POST"; 142 | message += "\nArguments: "; 143 | message += wifiPickerServer.args(); 144 | message += "\n"; 145 | for (uint8_t i=0; iMIME strings stored in PROGMEM, needs to be global due to GCC section typing rules 8 | static const struct {const char endsWith[16]; const char mimeType[32];} mimeTable[] ICACHE_RODATA_ATTR = { 9 | #else 10 | static const struct {const char endsWith[16]; const char mimeType[32];} mimeTable[] = { 11 | #endif 12 | { ".html", "text/html" }, 13 | { ".htm", "text/html" }, 14 | { ".css", "text/css" }, 15 | { ".txt", "text/plain" }, 16 | { ".js", "application/javascript" }, 17 | { ".json", "application/json" }, 18 | { ".png", "image/png" }, 19 | { ".gif", "image/gif" }, 20 | { ".jpg", "image/jpeg" }, 21 | { ".ico", "image/x-icon" }, 22 | { ".svg", "image/svg+xml" }, 23 | { ".ttf", "application/x-font-ttf" }, 24 | { ".otf", "application/x-font-opentype" }, 25 | { ".woff", "application/font-woff" }, 26 | { ".woff2", "application/font-woff2" }, 27 | { ".eot", "application/vnd.ms-fontobject" }, 28 | { ".sfnt", "application/font-sfnt" }, 29 | { ".xml", "text/xml" }, 30 | { ".pdf", "application/pdf" }, 31 | { ".zip", "application/zip" }, 32 | { ".gz", "application/x-gzip" }, 33 | { ".appcache", "text/cache-manifest" }, 34 | { "", "application/octet-stream" } }; 35 | 36 | class FunctionRequestHandler : public RequestHandler { 37 | public: 38 | FunctionRequestHandler(WebServer::THandlerFunction fn, WebServer::THandlerFunction ufn, const String &uri, HTTPMethod method) 39 | : _fn(fn) 40 | , _ufn(ufn) 41 | , _uri(uri) 42 | , _method(method) 43 | { 44 | } 45 | 46 | bool canHandle(HTTPMethod requestMethod, String requestUri) override { 47 | if (_method != HTTP_ANY && _method != requestMethod) 48 | return false; 49 | 50 | if (requestUri != _uri) 51 | return false; 52 | 53 | return true; 54 | } 55 | 56 | bool canUpload(String requestUri) override { 57 | if (!_ufn || !canHandle(HTTP_POST, requestUri)) 58 | return false; 59 | 60 | return true; 61 | } 62 | 63 | bool handle(WebServer& server, HTTPMethod requestMethod, String requestUri) override { 64 | (void) server; 65 | if (!canHandle(requestMethod, requestUri)) 66 | return false; 67 | 68 | _fn(); 69 | return true; 70 | } 71 | 72 | void upload(WebServer& server, String requestUri, HTTPUpload& upload) override { 73 | (void) server; 74 | (void) upload; 75 | if (canUpload(requestUri)) 76 | _ufn(); 77 | } 78 | 79 | protected: 80 | WebServer::THandlerFunction _fn; 81 | WebServer::THandlerFunction _ufn; 82 | String _uri; 83 | HTTPMethod _method; 84 | }; 85 | 86 | class StaticRequestHandler : public RequestHandler { 87 | public: 88 | StaticRequestHandler(FS& fs, const char* path, const char* uri, const char* cache_header) 89 | : _fs(fs) 90 | , _uri(uri) 91 | , _path(path) 92 | , _cache_header(cache_header) 93 | { 94 | _isFile = fs.exists(path); 95 | #ifdef ESP8266 96 | DEBUGV("StaticRequestHandler: path=%s uri=%s isFile=%d, cache_header=%s\r\n", path, uri, _isFile, cache_header); 97 | #else 98 | #ifdef DEBUG_ESP_HTTP_SERVER 99 | DEBUG_OUTPUT.printf("StaticRequestHandler: path=%s uri=%s isFile=%d, cache_header=%s\r\n", path, uri, _isFile, cache_header); 100 | #endif 101 | #endif 102 | _baseUriLength = _uri.length(); 103 | } 104 | 105 | bool canHandle(HTTPMethod requestMethod, String requestUri) override { 106 | if (requestMethod != HTTP_GET) 107 | return false; 108 | 109 | if ((_isFile && requestUri != _uri) || !requestUri.startsWith(_uri)) 110 | return false; 111 | 112 | return true; 113 | } 114 | 115 | bool handle(WebServer& server, HTTPMethod requestMethod, String requestUri) override { 116 | if (!canHandle(requestMethod, requestUri)) 117 | return false; 118 | 119 | #ifdef ESP8266 120 | DEBUGV("StaticRequestHandler::handle: request=%s _uri=%s\r\n", requestUri.c_str(), _uri.c_str()); 121 | #else 122 | #ifdef DEBUG_ESP_HTTP_SERVER 123 | DEBUG_OUTPUT.printf("StaticRequestHandler::handle: request=%s _uri=%s\r\n", requestUri.c_str(), _uri.c_str()); 124 | #endif 125 | #endif 126 | 127 | String path(_path); 128 | 129 | if (!_isFile) { 130 | // Base URI doesn't point to a file. 131 | // If a directory is requested, look for index file. 132 | if (requestUri.endsWith("/")) requestUri += "index.htm"; 133 | 134 | // Append whatever follows this URI in request to get the file path. 135 | path += requestUri.substring(_baseUriLength); 136 | } 137 | #ifdef ESP8266 138 | DEBUGV("StaticRequestHandler::handle: path=%s, isFile=%d\r\n", path.c_str(), _isFile); 139 | #else 140 | #ifdef DEBUG_ESP_HTTP_SERVER 141 | DEBUG_OUTPUT.printf("StaticRequestHandler::handle: path=%s, isFile=%d\r\n", path.c_str(), _isFile); 142 | #endif 143 | #endif 144 | 145 | String contentType = getContentType(path); 146 | 147 | // look for gz file, only if the original specified path is not a gz. So part only works to send gzip via content encoding when a non compressed is asked for 148 | // if you point the the path to gzip you will serve the gzip as content type "application/x-gzip", not text or javascript etc... 149 | if (!path.endsWith(".gz") && !_fs.exists(path)) { 150 | String pathWithGz = path + ".gz"; 151 | if(_fs.exists(pathWithGz)) 152 | path += ".gz"; 153 | } 154 | 155 | File f = _fs.open(path, "r"); 156 | if (!f) 157 | return false; 158 | 159 | if (_cache_header.length() != 0) 160 | server.sendHeader("Cache-Control", _cache_header); 161 | 162 | server.streamFile(f, contentType); 163 | return true; 164 | } 165 | 166 | static String getContentType(const String& path) { 167 | char buff[sizeof(mimeTable[0].mimeType)]; 168 | // Check all entries but last one for match, return if found 169 | for (size_t i=0; i < sizeof(mimeTable)/sizeof(mimeTable[0])-1; i++) { 170 | strcpy_P(buff, mimeTable[i].endsWith); 171 | if (path.endsWith(buff)) { 172 | strcpy_P(buff, mimeTable[i].mimeType); 173 | return String(buff); 174 | } 175 | } 176 | // Fall-through and just return default type 177 | strcpy_P(buff, mimeTable[sizeof(mimeTable)/sizeof(mimeTable[0])-1].mimeType); 178 | return String(buff); 179 | } 180 | 181 | protected: 182 | FS _fs; 183 | String _uri; 184 | String _path; 185 | String _cache_header; 186 | bool _isFile; 187 | size_t _baseUriLength; 188 | }; 189 | 190 | 191 | #endif //REQUESTHANDLERSIMPL_H 192 | -------------------------------------------------------------------------------- /AsyncTCP/src/AsyncTCP.h: -------------------------------------------------------------------------------- 1 | /* 2 | Asynchronous TCP library for Espressif MCUs 3 | 4 | Copyright (c) 2016 Hristo Gochkov. All rights reserved. 5 | This file is part of the esp8266 core for Arduino environment. 6 | 7 | This library is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU Lesser General Public 9 | License as published by the Free Software Foundation; either 10 | version 2.1 of the License, or (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public 18 | License along with this library; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | */ 21 | 22 | #ifndef ASYNCTCP_H_ 23 | #define ASYNCTCP_H_ 24 | 25 | #include "IPAddress.h" 26 | #include 27 | extern "C" { 28 | #include "freertos/semphr.h" 29 | } 30 | 31 | class AsyncClient; 32 | 33 | #define ASYNC_MAX_ACK_TIME 5000 34 | #define ASYNC_WRITE_FLAG_COPY 0x01 //will allocate new buffer to hold the data while sending (else will hold reference to the data given) 35 | #define ASYNC_WRITE_FLAG_MORE 0x02 //will not send PSH flag, meaning that there should be more data to be sent before the application should react. 36 | 37 | typedef std::function AcConnectHandler; 38 | typedef std::function AcAckHandler; 39 | typedef std::function AcErrorHandler; 40 | typedef std::function AcDataHandler; 41 | typedef std::function AcTimeoutHandler; 42 | 43 | struct tcp_pcb; 44 | struct pbuf; 45 | struct _ip_addr; 46 | 47 | class AsyncClient { 48 | protected: 49 | tcp_pcb* _pcb; 50 | 51 | AcConnectHandler _connect_cb; 52 | void* _connect_cb_arg; 53 | AcConnectHandler _discard_cb; 54 | void* _discard_cb_arg; 55 | AcAckHandler _sent_cb; 56 | void* _sent_cb_arg; 57 | AcErrorHandler _error_cb; 58 | void* _error_cb_arg; 59 | AcDataHandler _recv_cb; 60 | void* _recv_cb_arg; 61 | AcTimeoutHandler _timeout_cb; 62 | void* _timeout_cb_arg; 63 | AcConnectHandler _poll_cb; 64 | void* _poll_cb_arg; 65 | 66 | bool _pcb_busy; 67 | uint32_t _pcb_sent_at; 68 | bool _close_pcb; 69 | bool _ack_pcb; 70 | uint32_t _rx_ack_len; 71 | uint32_t _rx_last_packet; 72 | uint32_t _rx_since_timeout; 73 | uint32_t _ack_timeout; 74 | uint16_t _connect_port; 75 | 76 | int8_t _close(); 77 | int8_t _connected(void* pcb, int8_t err); 78 | void _error(int8_t err); 79 | int8_t _poll(tcp_pcb* pcb); 80 | int8_t _sent(tcp_pcb* pcb, uint16_t len); 81 | void _dns_found(struct _ip_addr *ipaddr); 82 | 83 | 84 | public: 85 | AsyncClient* prev; 86 | AsyncClient* next; 87 | 88 | AsyncClient(tcp_pcb* pcb = 0); 89 | ~AsyncClient(); 90 | 91 | AsyncClient & operator=(const AsyncClient &other); 92 | AsyncClient & operator+=(const AsyncClient &other); 93 | 94 | bool operator==(const AsyncClient &other); 95 | 96 | bool operator!=(const AsyncClient &other) { 97 | return !(*this == other); 98 | } 99 | bool connect(IPAddress ip, uint16_t port); 100 | bool connect(const char* host, uint16_t port); 101 | void close(bool now = false); 102 | void stop(); 103 | int8_t abort(); 104 | bool free(); 105 | 106 | bool canSend();//ack is not pending 107 | size_t space(); 108 | size_t add(const char* data, size_t size, uint8_t apiflags=0);//add for sending 109 | bool send();//send all data added with the method above 110 | size_t ack(size_t len); //ack data that you have not acked using the method below 111 | void ackLater(){ _ack_pcb = false; } //will not ack the current packet. Call from onData 112 | 113 | size_t write(const char* data); 114 | size_t write(const char* data, size_t size, uint8_t apiflags=0); //only when canSend() == true 115 | 116 | uint8_t state(); 117 | bool connecting(); 118 | bool connected(); 119 | bool disconnecting(); 120 | bool disconnected(); 121 | bool freeable();//disconnected or disconnecting 122 | 123 | uint16_t getMss(); 124 | uint32_t getRxTimeout(); 125 | void setRxTimeout(uint32_t timeout);//no RX data timeout for the connection in seconds 126 | uint32_t getAckTimeout(); 127 | void setAckTimeout(uint32_t timeout);//no ACK timeout for the last sent packet in milliseconds 128 | void setNoDelay(bool nodelay); 129 | bool getNoDelay(); 130 | uint32_t getRemoteAddress(); 131 | uint16_t getRemotePort(); 132 | uint32_t getLocalAddress(); 133 | uint16_t getLocalPort(); 134 | 135 | IPAddress remoteIP(); 136 | uint16_t remotePort(); 137 | IPAddress localIP(); 138 | uint16_t localPort(); 139 | 140 | void onConnect(AcConnectHandler cb, void* arg = 0); //on successful connect 141 | void onDisconnect(AcConnectHandler cb, void* arg = 0); //disconnected 142 | void onAck(AcAckHandler cb, void* arg = 0); //ack received 143 | void onError(AcErrorHandler cb, void* arg = 0); //unsuccessful connect or error 144 | void onData(AcDataHandler cb, void* arg = 0); //data received 145 | void onTimeout(AcTimeoutHandler cb, void* arg = 0); //ack timeout 146 | void onPoll(AcConnectHandler cb, void* arg = 0); //every 125ms when connected 147 | 148 | const char * errorToString(int8_t error); 149 | const char * stateToString(); 150 | 151 | int8_t _recv(tcp_pcb* pcb, pbuf* pb, int8_t err); 152 | 153 | static int8_t _s_poll(void *arg, struct tcp_pcb *tpcb); 154 | static int8_t _s_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *pb, int8_t err); 155 | static void _s_error(void *arg, int8_t err); 156 | static int8_t _s_sent(void *arg, struct tcp_pcb *tpcb, uint16_t len); 157 | static int8_t _s_connected(void* arg, void* tpcb, int8_t err); 158 | static void _s_dns_found(const char *name, struct _ip_addr *ipaddr, void *arg); 159 | 160 | bool _in_lwip_thread; 161 | }; 162 | 163 | class AsyncServer { 164 | protected: 165 | uint16_t _port; 166 | IPAddress _addr; 167 | bool _noDelay; 168 | bool _in_lwip_thread; 169 | tcp_pcb* _pcb; 170 | AcConnectHandler _connect_cb; 171 | void* _connect_cb_arg; 172 | 173 | public: 174 | 175 | AsyncServer(IPAddress addr, uint16_t port); 176 | AsyncServer(uint16_t port); 177 | ~AsyncServer(); 178 | void onClient(AcConnectHandler cb, void* arg); 179 | void begin(); 180 | void end(); 181 | void setNoDelay(bool nodelay); 182 | bool getNoDelay(); 183 | uint8_t status(); 184 | 185 | static int8_t _s_accept(void *arg, tcp_pcb* newpcb, int8_t err); 186 | protected: 187 | int8_t _accept(tcp_pcb* newpcb, int8_t err); 188 | }; 189 | 190 | 191 | #endif /* ASYNCTCP_H_ */ 192 | -------------------------------------------------------------------------------- /wifiPicker/src/wifiPicker.h: -------------------------------------------------------------------------------- 1 | void setDebugPrint(bool ONOFF); 2 | void debugPrint(String PRINT); 3 | bool attemptAutoConnect(void); 4 | bool attemptManualConnect(const char* NEW_SSID, const char* NEW_PW); 5 | bool wifiPicker(const char* AP_SSID, const char* AP_PW); 6 | void handleWifiPickerRoot(); 7 | void handleWifiPickerDone(); 8 | void handleWifiPickerNotFound(); 9 | String wifiScan(void); 10 | 11 | static const char PROGMEM WIFIPICKER_HTML[] = R"rawliteral( 12 | 13 | 14 | 15 | 16 | 17 | 18 | 172 | 227 | 228 | 229 | 230 |
231 |
232 |
233 |
234 |
235 |

236 | WiFi Picker 237 |

238 |
239 |
240 |

241 | Select your desired network from below 242 |

243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 | 251 | 252 | 253 | )rawliteral"; 254 | -------------------------------------------------------------------------------- /Hash/src/sha1/sha1.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file sha1.c 3 | * @date 20.05.2015 4 | * @author Steve Reid 5 | * 6 | * from: http://www.virtualbox.org/svn/vbox/trunk/src/recompiler/tests/sha1.c 7 | */ 8 | 9 | /* from valgrind tests */ 10 | 11 | /* ================ sha1.c ================ */ 12 | /* 13 | SHA-1 in C 14 | By Steve Reid 15 | 100% Public Domain 16 | 17 | Test Vectors (from FIPS PUB 180-1) 18 | "abc" 19 | A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D 20 | "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" 21 | 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 22 | A million repetitions of "a" 23 | 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F 24 | */ 25 | 26 | /* #define LITTLE_ENDIAN * This should be #define'd already, if true. */ 27 | /* #define SHA1HANDSOFF * Copies data before messing with it. */ 28 | 29 | #define SHA1HANDSOFF 30 | 31 | #include 32 | #include 33 | #include 34 | #ifndef ESP32 35 | #include 36 | #endif 37 | 38 | #include "sha1.h" 39 | 40 | //#include 41 | 42 | #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) 43 | 44 | /* blk0() and blk() perform the initial expand. */ 45 | /* I got the idea of expanding during the round function from SSLeay */ 46 | #if BYTE_ORDER == LITTLE_ENDIAN 47 | #define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ 48 | |(rol(block->l[i],8)&0x00FF00FF)) 49 | #elif BYTE_ORDER == BIG_ENDIAN 50 | #define blk0(i) block->l[i] 51 | #else 52 | #error "Endianness not defined!" 53 | #endif 54 | #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ 55 | ^block->l[(i+2)&15]^block->l[i&15],1)) 56 | 57 | /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ 58 | #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); 59 | #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); 60 | #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); 61 | #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); 62 | #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); 63 | 64 | 65 | /* Hash a single 512-bit block. This is the core of the algorithm. */ 66 | STATIC void ICACHE_FLASH_ATTR SHA1Transform(uint32_t state[5], uint8_t buffer[64]) 67 | { 68 | uint32_t a, b, c, d, e; 69 | typedef union { 70 | unsigned char c[64]; 71 | uint32_t l[16]; 72 | } CHAR64LONG16; 73 | #ifdef SHA1HANDSOFF 74 | CHAR64LONG16 block[1]; /* use array to appear as a pointer */ 75 | memcpy(block, buffer, 64); 76 | #else 77 | /* The following had better never be used because it causes the 78 | * pointer-to-const buffer to be cast into a pointer to non-const. 79 | * And the result is written through. I threw a "const" in, hoping 80 | * this will cause a diagnostic. 81 | */ 82 | CHAR64LONG16* block = (const CHAR64LONG16*)buffer; 83 | #endif 84 | /* Copy context->state[] to working vars */ 85 | a = state[0]; 86 | b = state[1]; 87 | c = state[2]; 88 | d = state[3]; 89 | e = state[4]; 90 | /* 4 rounds of 20 operations each. Loop unrolled. */ 91 | R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); 92 | R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); 93 | R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); 94 | R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); 95 | R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); 96 | R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); 97 | R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); 98 | R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); 99 | R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); 100 | R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); 101 | R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); 102 | R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); 103 | R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); 104 | R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); 105 | R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); 106 | R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); 107 | R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); 108 | R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); 109 | R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); 110 | R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); 111 | /* Add the working vars back into context.state[] */ 112 | state[0] += a; 113 | state[1] += b; 114 | state[2] += c; 115 | state[3] += d; 116 | state[4] += e; 117 | /* Wipe variables */ 118 | a = b = c = d = e = 0; 119 | #ifdef SHA1HANDSOFF 120 | memset(block, '\0', sizeof(block)); 121 | #endif 122 | } 123 | 124 | 125 | /* SHA1Init - Initialize new context */ 126 | 127 | STATIC void ICACHE_FLASH_ATTR SHA1Init(SHA1_CTX* context) 128 | { 129 | /* SHA1 initialization constants */ 130 | context->state[0] = 0x67452301; 131 | context->state[1] = 0xEFCDAB89; 132 | context->state[2] = 0x98BADCFE; 133 | context->state[3] = 0x10325476; 134 | context->state[4] = 0xC3D2E1F0; 135 | context->count[0] = context->count[1] = 0; 136 | } 137 | 138 | 139 | /* Run your data through this. */ 140 | 141 | STATIC void ICACHE_FLASH_ATTR SHA1Update(SHA1_CTX* context, uint8_t* data, uint32_t len) 142 | { 143 | uint32_t i; 144 | uint32_t j; 145 | 146 | j = context->count[0]; 147 | if ((context->count[0] += len << 3) < j) 148 | context->count[1]++; 149 | context->count[1] += (len>>29); 150 | j = (j >> 3) & 63; 151 | if ((j + len) > 63) { 152 | memcpy(&context->buffer[j], data, (i = 64-j)); 153 | SHA1Transform(context->state, context->buffer); 154 | for ( ; i + 63 < len; i += 64) { 155 | SHA1Transform(context->state, &data[i]); 156 | } 157 | j = 0; 158 | } 159 | else i = 0; 160 | memcpy(&context->buffer[j], &data[i], len - i); 161 | } 162 | 163 | 164 | /* Add padding and return the message digest. */ 165 | 166 | STATIC void ICACHE_FLASH_ATTR SHA1Final(unsigned char digest[20], SHA1_CTX* context) 167 | { 168 | unsigned i; 169 | unsigned char finalcount[8]; 170 | unsigned char c; 171 | 172 | #if 0 /* untested "improvement" by DHR */ 173 | /* Convert context->count to a sequence of bytes 174 | * in finalcount. Second element first, but 175 | * big-endian order within element. 176 | * But we do it all backwards. 177 | */ 178 | unsigned char *fcp = &finalcount[8]; 179 | 180 | for (i = 0; i < 2; i++) 181 | { 182 | uint32_t t = context->count[i]; 183 | int j; 184 | 185 | for (j = 0; j < 4; t >>= 8, j++) 186 | *--fcp = (unsigned char) t; 187 | } 188 | #else 189 | for (i = 0; i < 8; i++) { 190 | finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] 191 | >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ 192 | } 193 | #endif 194 | c = 0200; 195 | SHA1Update(context, &c, 1); 196 | while ((context->count[0] & 504) != 448) { 197 | c = 0000; 198 | SHA1Update(context, &c, 1); 199 | } 200 | SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ 201 | for (i = 0; i < 20; i++) { 202 | digest[i] = (unsigned char) 203 | ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); 204 | } 205 | /* Wipe variables */ 206 | memset(context, '\0', sizeof(*context)); 207 | memset(&finalcount, '\0', sizeof(finalcount)); 208 | } 209 | /* ================ end of sha1.c ================ */ 210 | -------------------------------------------------------------------------------- /AsyncTCP/LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /arduinoWebSockets/src/WebSocketsServer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file WebSocketsServer.h 3 | * @date 20.05.2015 4 | * @author Markus Sattler 5 | * 6 | * Copyright (c) 2015 Markus Sattler. All rights reserved. 7 | * This file is part of the WebSockets for Arduino. 8 | * 9 | * This library is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU Lesser General Public 11 | * License as published by the Free Software Foundation; either 12 | * version 2.1 of the License, or (at your option) any later version. 13 | * 14 | * This library is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | * Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public 20 | * License along with this library; if not, write to the Free Software 21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 | * 23 | */ 24 | 25 | #ifndef WEBSOCKETSSERVER_H_ 26 | #define WEBSOCKETSSERVER_H_ 27 | 28 | #include "WebSockets.h" 29 | 30 | #define WEBSOCKETS_SERVER_CLIENT_MAX (5) 31 | 32 | 33 | 34 | 35 | class WebSocketsServer: protected WebSockets { 36 | public: 37 | 38 | #ifdef __AVR__ 39 | typedef void (*WebSocketServerEvent)(uint8_t num, WStype_t type, uint8_t * payload, size_t length); 40 | typedef bool (*WebSocketServerHttpHeaderValFunc)(String headerName, String headerValue); 41 | #else 42 | typedef std::function WebSocketServerEvent; 43 | typedef std::function WebSocketServerHttpHeaderValFunc; 44 | #endif 45 | 46 | WebSocketsServer(uint16_t port, String origin = "", String protocol = "arduino"); 47 | ~WebSocketsServer(void); 48 | 49 | void begin(void); 50 | 51 | #if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) 52 | void loop(void); 53 | #else 54 | // Async interface not need a loop call 55 | void loop(void) __attribute__ ((deprecated)) {} 56 | #endif 57 | 58 | void onEvent(WebSocketServerEvent cbEvent); 59 | void onValidateHttpHeader( 60 | WebSocketServerHttpHeaderValFunc validationFunc, 61 | const char* mandatoryHttpHeaders[], 62 | size_t mandatoryHttpHeaderCount); 63 | 64 | 65 | bool sendTXT(uint8_t num, uint8_t * payload, size_t length = 0, bool headerToPayload = false); 66 | bool sendTXT(uint8_t num, const uint8_t * payload, size_t length = 0); 67 | bool sendTXT(uint8_t num, char * payload, size_t length = 0, bool headerToPayload = false); 68 | bool sendTXT(uint8_t num, const char * payload, size_t length = 0); 69 | bool sendTXT(uint8_t num, String & payload); 70 | 71 | bool broadcastTXT(uint8_t * payload, size_t length = 0, bool headerToPayload = false); 72 | bool broadcastTXT(const uint8_t * payload, size_t length = 0); 73 | bool broadcastTXT(char * payload, size_t length = 0, bool headerToPayload = false); 74 | bool broadcastTXT(const char * payload, size_t length = 0); 75 | bool broadcastTXT(String & payload); 76 | 77 | bool sendBIN(uint8_t num, uint8_t * payload, size_t length, bool headerToPayload = false); 78 | bool sendBIN(uint8_t num, const uint8_t * payload, size_t length); 79 | 80 | bool broadcastBIN(uint8_t * payload, size_t length, bool headerToPayload = false); 81 | bool broadcastBIN(const uint8_t * payload, size_t length); 82 | 83 | bool sendPing(uint8_t num, uint8_t * payload = NULL, size_t length = 0); 84 | bool sendPing(uint8_t num, String & payload); 85 | 86 | bool broadcastPing(uint8_t * payload = NULL, size_t length = 0); 87 | bool broadcastPing(String & payload); 88 | 89 | void disconnect(void); 90 | void disconnect(uint8_t num); 91 | 92 | void setAuthorization(const char * user, const char * password); 93 | void setAuthorization(const char * auth); 94 | 95 | #if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) 96 | IPAddress remoteIP(uint8_t num); 97 | #endif 98 | 99 | protected: 100 | uint16_t _port; 101 | String _origin; 102 | String _protocol; 103 | String _base64Authorization; ///< Base64 encoded Auth request 104 | String * _mandatoryHttpHeaders; 105 | size_t _mandatoryHttpHeaderCount; 106 | 107 | WEBSOCKETS_NETWORK_SERVER_CLASS * _server; 108 | 109 | WSclient_t _clients[WEBSOCKETS_SERVER_CLIENT_MAX]; 110 | 111 | WebSocketServerEvent _cbEvent; 112 | WebSocketServerHttpHeaderValFunc _httpHeaderValidationFunc; 113 | 114 | bool newClient(WEBSOCKETS_NETWORK_CLASS * TCPclient); 115 | 116 | void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin); 117 | 118 | void clientDisconnect(WSclient_t * client); 119 | bool clientIsConnected(WSclient_t * client); 120 | 121 | #if (WEBSOCKETS_NETWORK_TYPE != NETWORK_ESP8266_ASYNC) 122 | void handleNewClients(void); 123 | void handleClientData(void); 124 | #endif 125 | 126 | void handleHeader(WSclient_t * client, String * headerLine); 127 | 128 | /** 129 | * called if a non Websocket connection is coming in. 130 | * Note: can be override 131 | * @param client WSclient_t * ptr to the client struct 132 | */ 133 | virtual void handleNonWebsocketConnection(WSclient_t * client) { 134 | DEBUG_WEBSOCKETS("[WS-Server][%d][handleHeader] no Websocket connection close.\n", client->num); 135 | client->tcp->write("HTTP/1.1 400 Bad Request\r\n" 136 | "Server: arduino-WebSocket-Server\r\n" 137 | "Content-Type: text/plain\r\n" 138 | "Content-Length: 32\r\n" 139 | "Connection: close\r\n" 140 | "Sec-WebSocket-Version: 13\r\n" 141 | "\r\n" 142 | "This is a Websocket server only!"); 143 | clientDisconnect(client); 144 | } 145 | 146 | /** 147 | * called if a non Authorization connection is coming in. 148 | * Note: can be override 149 | * @param client WSclient_t * ptr to the client struct 150 | */ 151 | virtual void handleAuthorizationFailed(WSclient_t *client) { 152 | client->tcp->write("HTTP/1.1 401 Unauthorized\r\n" 153 | "Server: arduino-WebSocket-Server\r\n" 154 | "Content-Type: text/plain\r\n" 155 | "Content-Length: 45\r\n" 156 | "Connection: close\r\n" 157 | "Sec-WebSocket-Version: 13\r\n" 158 | "WWW-Authenticate: Basic realm=\"WebSocket Server\"" 159 | "\r\n" 160 | "This Websocket server requires Authorization!"); 161 | clientDisconnect(client); 162 | } 163 | 164 | /** 165 | * called for sending a Event to the app 166 | * @param num uint8_t 167 | * @param type WStype_t 168 | * @param payload uint8_t * 169 | * @param length size_t 170 | */ 171 | virtual void runCbEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) { 172 | if(_cbEvent) { 173 | _cbEvent(num, type, payload, length); 174 | } 175 | } 176 | 177 | /* 178 | * Called at client socket connect handshake negotiation time for each http header that is not 179 | * a websocket specific http header (not Connection, Upgrade, Sec-WebSocket-*) 180 | * If the custom httpHeaderValidationFunc returns false for any headerName / headerValue passed, the 181 | * socket negotiation is considered invalid and the upgrade to websockets request is denied / rejected 182 | * This mechanism can be used to enable custom authentication schemes e.g. test the value 183 | * of a session cookie to determine if a user is logged on / authenticated 184 | */ 185 | virtual bool execHttpHeaderValidation(String headerName, String headerValue) { 186 | if(_httpHeaderValidationFunc) { 187 | //return the value of the custom http header validation function 188 | return _httpHeaderValidationFunc(headerName, headerValue); 189 | } 190 | //no custom http header validation so just assume all is good 191 | return true; 192 | } 193 | 194 | private: 195 | /* 196 | * returns an indicator whether the given named header exists in the configured _mandatoryHttpHeaders collection 197 | * @param headerName String ///< the name of the header being checked 198 | */ 199 | bool hasMandatoryHeader(String headerName); 200 | 201 | }; 202 | 203 | 204 | 205 | #endif /* WEBSOCKETSSERVER_H_ */ 206 | -------------------------------------------------------------------------------- /WebServer/src/WebServer.h: -------------------------------------------------------------------------------- 1 | /* 2 | WebServer.h - Dead simple web-server. 3 | Supports only one simultaneous client, knows how to handle GET and POST. 4 | 5 | Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. 6 | 7 | This library is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU Lesser General Public 9 | License as published by the Free Software Foundation; either 10 | version 2.1 of the License, or (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public 18 | License along with this library; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling) 21 | */ 22 | 23 | 24 | #ifndef WEBSERVER_H 25 | #define WEBSERVER_H 26 | 27 | #include 28 | #ifdef ESP8266 29 | #define WebServer ESP8266WebServer 30 | #include 31 | #else 32 | #include 33 | #define write_P write 34 | #endif 35 | 36 | enum HTTPMethod { HTTP_ANY, HTTP_GET, HTTP_POST, HTTP_PUT, HTTP_PATCH, HTTP_DELETE, HTTP_OPTIONS }; 37 | enum HTTPUploadStatus { UPLOAD_FILE_START, UPLOAD_FILE_WRITE, UPLOAD_FILE_END, 38 | UPLOAD_FILE_ABORTED }; 39 | enum HTTPClientStatus { HC_NONE, HC_WAIT_READ, HC_WAIT_CLOSE }; 40 | 41 | #define HTTP_DOWNLOAD_UNIT_SIZE 1460 42 | 43 | #ifndef HTTP_UPLOAD_BUFLEN 44 | #define HTTP_UPLOAD_BUFLEN 2048 45 | #endif 46 | 47 | #define HTTP_MAX_DATA_WAIT 1000 //ms to wait for the client to send the request 48 | #define HTTP_MAX_POST_WAIT 1000 //ms to wait for POST data to arrive 49 | #define HTTP_MAX_SEND_WAIT 5000 //ms to wait for data chunk to be ACKed 50 | #define HTTP_MAX_CLOSE_WAIT 2000 //ms to wait for the client to close the connection 51 | 52 | #define CONTENT_LENGTH_UNKNOWN ((size_t) -1) 53 | #define CONTENT_LENGTH_NOT_SET ((size_t) -2) 54 | 55 | class WebServer; 56 | 57 | typedef struct { 58 | HTTPUploadStatus status; 59 | String filename; 60 | String name; 61 | String type; 62 | size_t totalSize; // file size 63 | size_t currentSize; // size of data currently in buf 64 | uint8_t buf[HTTP_UPLOAD_BUFLEN]; 65 | } HTTPUpload; 66 | 67 | #include "detail/RequestHandler.h" 68 | 69 | namespace fs { 70 | class FS; 71 | } 72 | 73 | class WebServer 74 | { 75 | public: 76 | WebServer(IPAddress addr, int port = 80); 77 | WebServer(int port = 80); 78 | ~WebServer(); 79 | 80 | void begin(); 81 | void handleClient(); 82 | 83 | void close(); 84 | void stop(); 85 | 86 | bool authenticate(const char * username, const char * password); 87 | void requestAuthentication(); 88 | 89 | typedef std::function THandlerFunction; 90 | void on(const String &uri, THandlerFunction handler); 91 | void on(const String &uri, HTTPMethod method, THandlerFunction fn); 92 | void on(const String &uri, HTTPMethod method, THandlerFunction fn, THandlerFunction ufn); 93 | void addHandler(RequestHandler* handler); 94 | void serveStatic(const char* uri, fs::FS& fs, const char* path, const char* cache_header = NULL ); 95 | void onNotFound(THandlerFunction fn); //called when handler is not assigned 96 | void onFileUpload(THandlerFunction fn); //handle file uploads 97 | 98 | String uri() { return _currentUri; } 99 | HTTPMethod method() { return _currentMethod; } 100 | WiFiClient client() { return _currentClient; } 101 | HTTPUpload& upload() { return _currentUpload; } 102 | 103 | String arg(String name); // get request argument value by name 104 | String arg(int i); // get request argument value by number 105 | String argName(int i); // get request argument name by number 106 | int args(); // get arguments count 107 | bool hasArg(String name); // check if argument exists 108 | void collectHeaders(const char* headerKeys[], const size_t headerKeysCount); // set the request headers to collect 109 | String header(String name); // get request header value by name 110 | String header(int i); // get request header value by number 111 | String headerName(int i); // get request header name by number 112 | int headers(); // get header count 113 | bool hasHeader(String name); // check if header exists 114 | 115 | String hostHeader(); // get request host header if available or empty String if not 116 | 117 | // send response to the client 118 | // code - HTTP response code, can be 200 or 404 119 | // content_type - HTTP content type, like "text/plain" or "image/png" 120 | // content - actual content body 121 | void send(int code, const char* content_type = NULL, const String& content = String("")); 122 | void send(int code, char* content_type, const String& content); 123 | void send(int code, const String& content_type, const String& content); 124 | void send_P(int code, PGM_P content_type, PGM_P content); 125 | void send_P(int code, PGM_P content_type, PGM_P content, size_t contentLength); 126 | 127 | void setContentLength(size_t contentLength); 128 | void sendHeader(const String& name, const String& value, bool first = false); 129 | void sendContent(const String& content); 130 | void sendContent_P(PGM_P content); 131 | void sendContent_P(PGM_P content, size_t size); 132 | 133 | static String urlDecode(const String& text); 134 | 135 | #ifdef ESP8266 136 | template size_t streamFile(T &file, const String& contentType){ 137 | setContentLength(file.size()); 138 | if (String(file.name()).endsWith(".gz") && 139 | contentType != "application/x-gzip" && 140 | contentType != "application/octet-stream"){ 141 | sendHeader("Content-Encoding", "gzip"); 142 | } 143 | send(200, contentType, ""); 144 | return _currentClient.write(file); 145 | } 146 | #else 147 | template size_t streamFile(T &file, const String& contentType){ 148 | #define STREAMFILE_BUFSIZE 2*1460 149 | setContentLength(file.size()); 150 | if (String(file.name()).endsWith(".gz") && 151 | contentType != "application/x-gzip" && 152 | contentType != "application/octet-stream") { 153 | sendHeader("Content-Encoding", "gzip"); 154 | } 155 | send(200, contentType, ""); 156 | uint8_t *buf = (uint8_t *)malloc(STREAMFILE_BUFSIZE); 157 | if (buf == NULL) { 158 | //DBG_OUTPUT_PORT.printf("streamFile malloc failed"); 159 | return 0; 160 | } 161 | size_t totalBytesOut = 0; 162 | while (client().connected() && (file.available() > 0)) { 163 | int bytesOut; 164 | int bytesIn = file.read(buf, STREAMFILE_BUFSIZE); 165 | if (bytesIn <= 0) break; 166 | while (1) { 167 | bytesOut = 0; 168 | if (!client().connected()) break; 169 | bytesOut = client().write(buf, bytesIn); 170 | if (bytesIn == bytesOut) break; 171 | 172 | //DBG_OUTPUT_PORT.printf("bytesIn %d != bytesOut %d\r\n", 173 | //bytesIn, bytesOut); 174 | delay(1); 175 | } 176 | totalBytesOut += bytesOut; 177 | yield(); 178 | } 179 | if (totalBytesOut != file.size()) { 180 | //DBG_OUTPUT_PORT.printf("file size %d bytes out %d\r\n", 181 | // file.size(), totalBytesOut); 182 | } 183 | free(buf); 184 | return totalBytesOut; 185 | } 186 | #endif 187 | 188 | protected: 189 | void _addRequestHandler(RequestHandler* handler); 190 | void _handleRequest(); 191 | bool _parseRequest(WiFiClient& client); 192 | void _parseArguments(String data); 193 | static String _responseCodeToString(int code); 194 | bool _parseForm(WiFiClient& client, String boundary, uint32_t len); 195 | bool _parseFormUploadAborted(); 196 | void _uploadWriteByte(uint8_t b); 197 | uint8_t _uploadReadByte(WiFiClient& client); 198 | void _prepareHeader(String& response, int code, const char* content_type, size_t contentLength); 199 | bool _collectHeader(const char* headerName, const char* headerValue); 200 | 201 | struct RequestArgument { 202 | String key; 203 | String value; 204 | }; 205 | 206 | WiFiServer _server; 207 | 208 | WiFiClient _currentClient; 209 | HTTPMethod _currentMethod; 210 | String _currentUri; 211 | uint8_t _currentVersion; 212 | HTTPClientStatus _currentStatus; 213 | unsigned long _statusChange; 214 | 215 | RequestHandler* _currentHandler; 216 | RequestHandler* _firstHandler; 217 | RequestHandler* _lastHandler; 218 | THandlerFunction _notFoundHandler; 219 | THandlerFunction _fileUploadHandler; 220 | 221 | int _currentArgCount; 222 | RequestArgument* _currentArgs; 223 | HTTPUpload _currentUpload; 224 | 225 | int _headerKeysCount; 226 | RequestArgument* _currentHeaders; 227 | size_t _contentLength; 228 | String _responseHeaders; 229 | 230 | String _hostHeader; 231 | bool _chunked; 232 | 233 | }; 234 | 235 | 236 | #endif //WEBSERVER_H 237 | -------------------------------------------------------------------------------- /WebServer/examples/SDWebServer/SDWebServer.ino: -------------------------------------------------------------------------------- 1 | /* 2 | SDWebServer - Example WebServer with SD Card backend for esp8266/esp32 3 | 4 | Copyright (c) 2015 Hristo Gochkov. All rights reserved. 5 | This file is part of the ESP8266/ESP32 WebServer library for Arduino environment. 6 | 7 | This library is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU Lesser General Public 9 | License as published by the Free Software Foundation; either 10 | version 2.1 of the License, or (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public 18 | License along with this library; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | 21 | Have a FAT Formatted SD Card connected to the SPI port of the ESP8266 22 | The web root is the SD Card root folder 23 | File extensions with more than 3 charecters are not supported by the SD Library 24 | File Names longer than 8 charecters will be truncated by the SD library, so keep filenames shorter 25 | index.htm is the default index (works on subfolders as well) 26 | 27 | upload the contents of SdRoot to the root of the SDcard and access the editor by going to http://esp8266sd.local/edit 28 | 29 | */ 30 | #ifdef ESP8266 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | ESP8266WebServer server(80); 38 | #else 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | WebServer server(80); 46 | #endif 47 | 48 | #define DBG_OUTPUT_PORT Serial 49 | 50 | const char* ssid = "**********"; 51 | const char* password = "**********"; 52 | const char* host = "esp8266sd"; 53 | 54 | static bool hasSD = false; 55 | File uploadFile; 56 | 57 | 58 | void returnOK() { 59 | server.send(200, "text/plain", ""); 60 | } 61 | 62 | void returnFail(String msg) { 63 | server.send(500, "text/plain", msg + "\r\n"); 64 | } 65 | 66 | bool loadFromSdCard(String path){ 67 | String dataType = "text/plain"; 68 | if(path.endsWith("/")) path += "index.htm"; 69 | 70 | if(path.endsWith(".src")) path = path.substring(0, path.lastIndexOf(".")); 71 | else if(path.endsWith(".htm")) dataType = "text/html"; 72 | else if(path.endsWith(".css")) dataType = "text/css"; 73 | else if(path.endsWith(".js")) dataType = "application/javascript"; 74 | else if(path.endsWith(".png")) dataType = "image/png"; 75 | else if(path.endsWith(".gif")) dataType = "image/gif"; 76 | else if(path.endsWith(".jpg")) dataType = "image/jpeg"; 77 | else if(path.endsWith(".ico")) dataType = "image/x-icon"; 78 | else if(path.endsWith(".xml")) dataType = "text/xml"; 79 | else if(path.endsWith(".pdf")) dataType = "application/pdf"; 80 | else if(path.endsWith(".zip")) dataType = "application/zip"; 81 | 82 | File dataFile = SD.open(path.c_str()); 83 | if(dataFile.isDirectory()){ 84 | path += "/index.htm"; 85 | dataType = "text/html"; 86 | dataFile = SD.open(path.c_str()); 87 | } 88 | 89 | if (!dataFile) 90 | return false; 91 | 92 | if (server.hasArg("download")) dataType = "application/octet-stream"; 93 | 94 | if (server.streamFile(dataFile, dataType) != dataFile.size()) { 95 | DBG_OUTPUT_PORT.println("Sent less data than expected!"); 96 | } 97 | 98 | dataFile.close(); 99 | return true; 100 | } 101 | 102 | void handleFileUpload(){ 103 | if(server.uri() != "/edit") return; 104 | HTTPUpload& upload = server.upload(); 105 | if(upload.status == UPLOAD_FILE_START){ 106 | if(SD.exists((char *)upload.filename.c_str())) SD.remove((char *)upload.filename.c_str()); 107 | uploadFile = SD.open(upload.filename.c_str(), FILE_WRITE); 108 | DBG_OUTPUT_PORT.print("Upload: START, filename: "); DBG_OUTPUT_PORT.println(upload.filename); 109 | } else if(upload.status == UPLOAD_FILE_WRITE){ 110 | if(uploadFile) uploadFile.write(upload.buf, upload.currentSize); 111 | DBG_OUTPUT_PORT.print("Upload: WRITE, Bytes: "); DBG_OUTPUT_PORT.println(upload.currentSize); 112 | } else if(upload.status == UPLOAD_FILE_END){ 113 | if(uploadFile) uploadFile.close(); 114 | DBG_OUTPUT_PORT.print("Upload: END, Size: "); DBG_OUTPUT_PORT.println(upload.totalSize); 115 | } 116 | } 117 | 118 | void deleteRecursive(String path){ 119 | File file = SD.open((char *)path.c_str()); 120 | if(!file.isDirectory()){ 121 | file.close(); 122 | SD.remove((char *)path.c_str()); 123 | return; 124 | } 125 | 126 | file.rewindDirectory(); 127 | while(true) { 128 | File entry = file.openNextFile(); 129 | if (!entry) break; 130 | String entryPath = path + "/" +entry.name(); 131 | if(entry.isDirectory()){ 132 | entry.close(); 133 | deleteRecursive(entryPath); 134 | } else { 135 | entry.close(); 136 | SD.remove((char *)entryPath.c_str()); 137 | } 138 | yield(); 139 | } 140 | 141 | SD.rmdir((char *)path.c_str()); 142 | file.close(); 143 | } 144 | 145 | void handleDelete(){ 146 | if(server.args() == 0) return returnFail("BAD ARGS"); 147 | String path = server.arg(0); 148 | if(path == "/" || !SD.exists((char *)path.c_str())) { 149 | returnFail("BAD PATH"); 150 | return; 151 | } 152 | deleteRecursive(path); 153 | returnOK(); 154 | } 155 | 156 | void handleCreate(){ 157 | if(server.args() == 0) return returnFail("BAD ARGS"); 158 | String path = server.arg(0); 159 | if(path == "/" || SD.exists((char *)path.c_str())) { 160 | returnFail("BAD PATH"); 161 | return; 162 | } 163 | 164 | if(path.indexOf('.') > 0){ 165 | File file = SD.open((char *)path.c_str(), FILE_WRITE); 166 | if(file){ 167 | #ifdef ESP8266 168 | file.write((const char *)0); 169 | #else 170 | // TODO Create file with 0 bytes??? 171 | file.write(NULL, 0); 172 | #endif 173 | file.close(); 174 | } 175 | } else { 176 | SD.mkdir((char *)path.c_str()); 177 | } 178 | returnOK(); 179 | } 180 | 181 | void printDirectory() { 182 | if(!server.hasArg("dir")) return returnFail("BAD ARGS"); 183 | String path = server.arg("dir"); 184 | if(path != "/" && !SD.exists((char *)path.c_str())) return returnFail("BAD PATH"); 185 | File dir = SD.open((char *)path.c_str()); 186 | path = String(); 187 | if(!dir.isDirectory()){ 188 | dir.close(); 189 | return returnFail("NOT DIR"); 190 | } 191 | dir.rewindDirectory(); 192 | server.setContentLength(CONTENT_LENGTH_UNKNOWN); 193 | server.send(200, "text/json", ""); 194 | WiFiClient client = server.client(); 195 | 196 | server.sendContent("["); 197 | for (int cnt = 0; true; ++cnt) { 198 | File entry = dir.openNextFile(); 199 | if (!entry) 200 | break; 201 | 202 | String output; 203 | if (cnt > 0) 204 | output = ','; 205 | 206 | output += "{\"type\":\""; 207 | output += (entry.isDirectory()) ? "dir" : "file"; 208 | output += "\",\"name\":\""; 209 | #ifdef ESP8266 210 | output += entry.name(); 211 | #else 212 | // Ignore '/' prefix 213 | output += entry.name()+1; 214 | #endif 215 | output += "\""; 216 | output += "}"; 217 | server.sendContent(output); 218 | entry.close(); 219 | } 220 | server.sendContent("]"); 221 | // Send zero length chunk to terminate the HTTP body 222 | server.sendContent(""); 223 | dir.close(); 224 | } 225 | 226 | void handleNotFound(){ 227 | if(hasSD && loadFromSdCard(server.uri())) return; 228 | String message = "SDCARD Not Detected\n\n"; 229 | message += "URI: "; 230 | message += server.uri(); 231 | message += "\nMethod: "; 232 | message += (server.method() == HTTP_GET)?"GET":"POST"; 233 | message += "\nArguments: "; 234 | message += server.args(); 235 | message += "\n"; 236 | for (uint8_t i=0; i 30 | #define bit(b) (1UL << (b)) // Taken directly from Arduino.h 31 | #else 32 | #include 33 | #endif 34 | 35 | #include 36 | 37 | #ifndef NODEBUG_WEBSOCKETS 38 | #ifdef DEBUG_ESP_PORT 39 | #define DEBUG_WEBSOCKETS(...) DEBUG_ESP_PORT.printf( __VA_ARGS__ ) 40 | #else 41 | //#define DEBUG_WEBSOCKETS(...) os_printf( __VA_ARGS__ ) 42 | #endif 43 | #endif 44 | 45 | 46 | #ifndef DEBUG_WEBSOCKETS 47 | #define DEBUG_WEBSOCKETS(...) 48 | #define NODEBUG_WEBSOCKETS 49 | #endif 50 | 51 | #ifdef ESP8266 52 | #define WEBSOCKETS_MAX_DATA_SIZE (15*1024) 53 | #define WEBSOCKETS_USE_BIG_MEM 54 | #define GET_FREE_HEAP ESP.getFreeHeap() 55 | // moves all Header strings to Flash (~300 Byte) 56 | //#define WEBSOCKETS_SAVE_RAM 57 | #else 58 | #ifdef STM32_DEVICE 59 | #define WEBSOCKETS_MAX_DATA_SIZE (15*1024) 60 | #define WEBSOCKETS_USE_BIG_MEM 61 | #define GET_FREE_HEAP System.freeMemory() 62 | #else 63 | //atmega328p has only 2KB ram! 64 | #define WEBSOCKETS_MAX_DATA_SIZE (1024) 65 | // moves all Header strings to Flash 66 | #define WEBSOCKETS_SAVE_RAM 67 | #endif 68 | #endif 69 | 70 | #define WEBSOCKETS_TCP_TIMEOUT (2000) 71 | 72 | #define NETWORK_ESP8266_ASYNC (0) 73 | #define NETWORK_ESP8266 (1) 74 | #define NETWORK_W5100 (2) 75 | #define NETWORK_ENC28J60 (3) 76 | #define NETWORK_ESP32 (4) 77 | 78 | // max size of the WS Message Header 79 | #define WEBSOCKETS_MAX_HEADER_SIZE (14) 80 | 81 | #if !defined(WEBSOCKETS_NETWORK_TYPE) 82 | // select Network type based 83 | #if defined(ESP8266) || defined(ESP31B) 84 | #define WEBSOCKETS_NETWORK_TYPE NETWORK_ESP8266 85 | //#define WEBSOCKETS_NETWORK_TYPE NETWORK_ESP8266_ASYNC 86 | //#define WEBSOCKETS_NETWORK_TYPE NETWORK_W5100 87 | #elif defined(ESP32) 88 | #define WEBSOCKETS_NETWORK_TYPE NETWORK_ESP32 89 | #else 90 | #define WEBSOCKETS_NETWORK_TYPE NETWORK_W5100 91 | #endif 92 | #endif 93 | 94 | #if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) 95 | 96 | // Note: 97 | // No SSL/WSS support for client in Async mode 98 | // TLS lib need a sync interface! 99 | 100 | #if !defined(ESP8266) && !defined(ESP31B) 101 | #error "network type ESP8266 ASYNC only possible on the ESP mcu!" 102 | #endif 103 | 104 | #ifdef ESP8266 105 | #include 106 | #else 107 | #include 108 | #endif 109 | #include 110 | #include 111 | #define WEBSOCKETS_NETWORK_CLASS AsyncTCPbuffer 112 | #define WEBSOCKETS_NETWORK_SERVER_CLASS AsyncServer 113 | 114 | #elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) 115 | 116 | #if !defined(ESP8266) && !defined(ESP31B) 117 | #error "network type ESP8266 only possible on the ESP mcu!" 118 | #endif 119 | 120 | #ifdef ESP8266 121 | #include 122 | #else 123 | #include 124 | #endif 125 | #define WEBSOCKETS_NETWORK_CLASS WiFiClient 126 | #define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer 127 | 128 | #elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_W5100) 129 | 130 | #ifdef STM32_DEVICE 131 | #define WEBSOCKETS_NETWORK_CLASS TCPClient 132 | #define WEBSOCKETS_NETWORK_SERVER_CLASS TCPServer 133 | #else 134 | #include 135 | #include 136 | #define WEBSOCKETS_NETWORK_CLASS EthernetClient 137 | #define WEBSOCKETS_NETWORK_SERVER_CLASS EthernetServer 138 | #endif 139 | 140 | #elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_ENC28J60) 141 | 142 | #include 143 | #define WEBSOCKETS_NETWORK_CLASS UIPClient 144 | #define WEBSOCKETS_NETWORK_SERVER_CLASS UIPServer 145 | 146 | #elif (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) 147 | 148 | #include 149 | #include 150 | #define WEBSOCKETS_NETWORK_CLASS WiFiClient 151 | #define WEBSOCKETS_NETWORK_SERVER_CLASS WiFiServer 152 | 153 | #else 154 | #error "no network type selected!" 155 | #endif 156 | 157 | // moves all Header strings to Flash (~300 Byte) 158 | #ifdef WEBSOCKETS_SAVE_RAM 159 | #define WEBSOCKETS_STRING(var) F(var) 160 | #else 161 | #define WEBSOCKETS_STRING(var) var 162 | #endif 163 | 164 | typedef enum { 165 | WSC_NOT_CONNECTED, 166 | WSC_HEADER, 167 | WSC_CONNECTED 168 | } WSclientsStatus_t; 169 | 170 | typedef enum { 171 | WStype_ERROR, 172 | WStype_DISCONNECTED, 173 | WStype_CONNECTED, 174 | WStype_TEXT, 175 | WStype_BIN, 176 | WStype_FRAGMENT_TEXT_START, 177 | WStype_FRAGMENT_BIN_START, 178 | WStype_FRAGMENT, 179 | WStype_FRAGMENT_FIN, 180 | } WStype_t; 181 | 182 | typedef enum { 183 | WSop_continuation = 0x00, ///< %x0 denotes a continuation frame 184 | WSop_text = 0x01, ///< %x1 denotes a text frame 185 | WSop_binary = 0x02, ///< %x2 denotes a binary frame 186 | ///< %x3-7 are reserved for further non-control frames 187 | WSop_close = 0x08, ///< %x8 denotes a connection close 188 | WSop_ping = 0x09, ///< %x9 denotes a ping 189 | WSop_pong = 0x0A ///< %xA denotes a pong 190 | ///< %xB-F are reserved for further control frames 191 | } WSopcode_t; 192 | 193 | typedef struct { 194 | 195 | bool fin; 196 | bool rsv1; 197 | bool rsv2; 198 | bool rsv3; 199 | 200 | WSopcode_t opCode; 201 | bool mask; 202 | 203 | size_t payloadLen; 204 | 205 | uint8_t * maskKey; 206 | } WSMessageHeader_t; 207 | 208 | typedef struct { 209 | uint8_t num; ///< connection number 210 | 211 | WSclientsStatus_t status; 212 | 213 | WEBSOCKETS_NETWORK_CLASS * tcp; 214 | 215 | bool isSocketIO; ///< client for socket.io server 216 | 217 | #if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266) || (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP32) 218 | bool isSSL; ///< run in ssl mode 219 | WiFiClientSecure * ssl; 220 | #endif 221 | 222 | String cUrl; ///< http url 223 | uint16_t cCode; ///< http code 224 | 225 | bool cIsUpgrade; ///< Connection == Upgrade 226 | bool cIsWebsocket; ///< Upgrade == websocket 227 | 228 | String cSessionId; ///< client Set-Cookie (session id) 229 | String cKey; ///< client Sec-WebSocket-Key 230 | String cAccept; ///< client Sec-WebSocket-Accept 231 | String cProtocol; ///< client Sec-WebSocket-Protocol 232 | String cExtensions; ///< client Sec-WebSocket-Extensions 233 | uint16_t cVersion; ///< client Sec-WebSocket-Version 234 | 235 | uint8_t cWsRXsize; ///< State of the RX 236 | uint8_t cWsHeader[WEBSOCKETS_MAX_HEADER_SIZE]; ///< RX WS Message buffer 237 | WSMessageHeader_t cWsHeaderDecode; 238 | 239 | String base64Authorization; ///< Base64 encoded Auth request 240 | String plainAuthorization; ///< Base64 encoded Auth request 241 | 242 | String extraHeaders; 243 | 244 | bool cHttpHeadersValid; ///< non-websocket http header validity indicator 245 | size_t cMandatoryHeadersCount; ///< non-websocket mandatory http headers present count 246 | 247 | #if (WEBSOCKETS_NETWORK_TYPE == NETWORK_ESP8266_ASYNC) 248 | String cHttpLine; ///< HTTP header lines 249 | #endif 250 | 251 | } WSclient_t; 252 | 253 | 254 | 255 | class WebSockets { 256 | protected: 257 | #ifdef __AVR__ 258 | typedef void (*WSreadWaitCb)(WSclient_t * client, bool ok); 259 | #else 260 | typedef std::function WSreadWaitCb; 261 | #endif 262 | 263 | virtual void clientDisconnect(WSclient_t * client); 264 | virtual bool clientIsConnected(WSclient_t * client); 265 | 266 | virtual void messageReceived(WSclient_t * client, WSopcode_t opcode, uint8_t * payload, size_t length, bool fin); 267 | 268 | void clientDisconnect(WSclient_t * client, uint16_t code, char * reason = NULL, size_t reasonLen = 0); 269 | 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); 270 | 271 | void headerDone(WSclient_t * client); 272 | 273 | void handleWebsocket(WSclient_t * client); 274 | 275 | bool handleWebsocketWaitFor(WSclient_t * client, size_t size); 276 | void handleWebsocketCb(WSclient_t * client); 277 | void handleWebsocketPayloadCb(WSclient_t * client, bool ok, uint8_t * payload); 278 | 279 | String acceptKey(String & clientKey); 280 | String base64_encode(uint8_t * data, size_t length); 281 | 282 | bool readCb(WSclient_t * client, uint8_t *out, size_t n, WSreadWaitCb cb); 283 | virtual size_t write(WSclient_t * client, uint8_t *out, size_t n); 284 | size_t write(WSclient_t * client, const char *out); 285 | 286 | 287 | }; 288 | 289 | #endif /* WEBSOCKETS_H_ */ 290 | -------------------------------------------------------------------------------- /WebServer/examples/FSBrowser/FSBrowser.ino: -------------------------------------------------------------------------------- 1 | /* 2 | FSWebServer - Example WebServer with SPIFFS backend for esp8266 3 | Copyright (c) 2015 Hristo Gochkov. All rights reserved. 4 | This file is part of the ESP8266/ESP32 WebServer library for Arduino environment. 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | You should have received a copy of the GNU Lesser General Public 15 | License along with this library; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 | 18 | upload the contents of the data folder with MkSPIFFS Tool ("ESP8266 Sketch Data Upload" in Tools menu in Arduino IDE) 19 | or you can upload the contents of a folder if you CD in that folder and run the following command: 20 | for file in `ls -A1`; do curl -F "file=@$PWD/$file" esp8266fs.local/edit; done 21 | 22 | access the sample web page at http://esp8266fs.local 23 | edit the page by going to http://esp8266fs.local/edit 24 | */ 25 | /* 26 | * Uploading html, css, javascript, etc. 27 | * Use curl to upload the files from the SPIFFS data directory. 28 | * cd data/ 29 | * curl -X POST -F "data=@index.htm" http:///edit >/dev/null 30 | * curl -X POST -F "data=@graphs.js.gz" http:///edit >/dev/null 31 | * curl -X POST -F "data=@favicon.ico" http:///edit >/dev/null 32 | * curl -X POST -F "data=@edit.htm.gz" http:///edit >/dev/null 33 | */ 34 | #ifdef ESP8266 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | ESP8266WebServer server(80); 41 | #else 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | WebServer server(80); 48 | #endif 49 | 50 | #define DBG_OUTPUT_PORT Serial 51 | 52 | const char* ssid = "wifi-ssid"; 53 | const char* password = "wifi-password"; 54 | const char* host = "esp8266fs"; 55 | 56 | //holds the current upload 57 | File fsUploadFile; 58 | 59 | //format bytes 60 | String formatBytes(size_t bytes){ 61 | if (bytes < 1024){ 62 | return String(bytes)+"B"; 63 | } else if(bytes < (1024 * 1024)){ 64 | return String(bytes/1024.0)+"KB"; 65 | } else if(bytes < (1024 * 1024 * 1024)){ 66 | return String(bytes/1024.0/1024.0)+"MB"; 67 | } else { 68 | return String(bytes/1024.0/1024.0/1024.0)+"GB"; 69 | } 70 | } 71 | 72 | String getContentType(String filename){ 73 | if(server.hasArg("download")) return "application/octet-stream"; 74 | else if(filename.endsWith(".htm")) return "text/html"; 75 | else if(filename.endsWith(".html")) return "text/html"; 76 | else if(filename.endsWith(".css")) return "text/css"; 77 | else if(filename.endsWith(".js")) return "application/javascript"; 78 | else if(filename.endsWith(".png")) return "image/png"; 79 | else if(filename.endsWith(".gif")) return "image/gif"; 80 | else if(filename.endsWith(".jpg")) return "image/jpeg"; 81 | else if(filename.endsWith(".ico")) return "image/x-icon"; 82 | else if(filename.endsWith(".xml")) return "text/xml"; 83 | else if(filename.endsWith(".pdf")) return "application/x-pdf"; 84 | else if(filename.endsWith(".zip")) return "application/x-zip"; 85 | else if(filename.endsWith(".gz")) return "application/x-gzip"; 86 | return "text/plain"; 87 | } 88 | 89 | bool handleFileRead(String path){ 90 | DBG_OUTPUT_PORT.println("handleFileRead: " + path); 91 | if(path.endsWith("/")) path += "index.htm"; 92 | String contentType = getContentType(path); 93 | String pathWithGz = path + ".gz"; 94 | if(SPIFFS.exists(pathWithGz) || SPIFFS.exists(path)){ 95 | if(SPIFFS.exists(pathWithGz)) 96 | path += ".gz"; 97 | File file = SPIFFS.open(path, "r"); 98 | size_t sent = server.streamFile(file, contentType); 99 | file.close(); 100 | return true; 101 | } 102 | return false; 103 | } 104 | 105 | void handleFileUpload(){ 106 | if(server.uri() != "/edit") return; 107 | HTTPUpload& upload = server.upload(); 108 | if(upload.status == UPLOAD_FILE_START){ 109 | String filename = upload.filename; 110 | if(!filename.startsWith("/")) filename = "/"+filename; 111 | DBG_OUTPUT_PORT.print("handleFileUpload Name: "); DBG_OUTPUT_PORT.println(filename); 112 | fsUploadFile = SPIFFS.open(filename, "w"); 113 | filename = String(); 114 | } else if(upload.status == UPLOAD_FILE_WRITE){ 115 | //DBG_OUTPUT_PORT.print("handleFileUpload Data: "); DBG_OUTPUT_PORT.println(upload.currentSize); 116 | if(fsUploadFile) 117 | fsUploadFile.write(upload.buf, upload.currentSize); 118 | } else if(upload.status == UPLOAD_FILE_END){ 119 | if(fsUploadFile) 120 | fsUploadFile.close(); 121 | DBG_OUTPUT_PORT.print("handleFileUpload Size: "); DBG_OUTPUT_PORT.println(upload.totalSize); 122 | } 123 | } 124 | 125 | void handleFileDelete(){ 126 | if(server.args() == 0) return server.send(500, "text/plain", "BAD ARGS"); 127 | String path = server.arg(0); 128 | DBG_OUTPUT_PORT.println("handleFileDelete: " + path); 129 | if(path == "/") 130 | return server.send(500, "text/plain", "BAD PATH"); 131 | if(!SPIFFS.exists(path)) 132 | return server.send(404, "text/plain", "FileNotFound"); 133 | SPIFFS.remove(path); 134 | server.send(200, "text/plain", ""); 135 | path = String(); 136 | } 137 | 138 | void handleFileCreate(){ 139 | if(server.args() == 0) 140 | return server.send(500, "text/plain", "BAD ARGS"); 141 | String path = server.arg(0); 142 | DBG_OUTPUT_PORT.println("handleFileCreate: " + path); 143 | if(path == "/") 144 | return server.send(500, "text/plain", "BAD PATH"); 145 | if(SPIFFS.exists(path)) 146 | return server.send(500, "text/plain", "FILE EXISTS"); 147 | File file = SPIFFS.open(path, "w"); 148 | if(file) 149 | file.close(); 150 | else 151 | return server.send(500, "text/plain", "CREATE FAILED"); 152 | server.send(200, "text/plain", ""); 153 | path = String(); 154 | } 155 | 156 | void returnFail(String msg) { 157 | server.send(500, "text/plain", msg + "\r\n"); 158 | } 159 | 160 | #ifdef ESP8266 161 | void handleFileList() { 162 | if(!server.hasArg("dir")) { 163 | returnFail("BAD ARGS"); 164 | return; 165 | } 166 | 167 | String path = server.arg("dir"); 168 | DBG_OUTPUT_PORT.println("handleFileList: " + path); 169 | Dir dir = SPIFFS.openDir(path); 170 | path = String(); 171 | 172 | String output = "["; 173 | while(dir.next()){ 174 | File entry = dir.openFile("r"); 175 | if (output != "[") output += ','; 176 | bool isDir = false; 177 | output += "{\"type\":\""; 178 | output += (isDir)?"dir":"file"; 179 | output += "\",\"name\":\""; 180 | output += String(entry.name()).substring(1); 181 | output += "\"}"; 182 | entry.close(); 183 | } 184 | 185 | output += "]"; 186 | server.send(200, "text/json", output); 187 | } 188 | #else 189 | void handleFileList() { 190 | if(!server.hasArg("dir")) { 191 | returnFail("BAD ARGS"); 192 | return; 193 | } 194 | String path = server.arg("dir"); 195 | if(path != "/" && !SPIFFS.exists((char *)path.c_str())) { 196 | returnFail("BAD PATH"); 197 | return; 198 | } 199 | File dir = SPIFFS.open((char *)path.c_str()); 200 | path = String(); 201 | if(!dir.isDirectory()){ 202 | dir.close(); 203 | returnFail("NOT DIR"); 204 | return; 205 | } 206 | dir.rewindDirectory(); 207 | 208 | String output = "["; 209 | for (int cnt = 0; true; ++cnt) { 210 | File entry = dir.openNextFile(); 211 | if (!entry) 212 | break; 213 | 214 | if (cnt > 0) 215 | output += ','; 216 | 217 | output += "{\"type\":\""; 218 | output += (entry.isDirectory()) ? "dir" : "file"; 219 | output += "\",\"name\":\""; 220 | // Ignore '/' prefix 221 | output += entry.name()+1; 222 | output += "\""; 223 | output += "}"; 224 | entry.close(); 225 | } 226 | output += "]"; 227 | server.send(200, "text/json", output); 228 | dir.close(); 229 | } 230 | 231 | void listDir(fs::FS &fs, const char * dirname, uint8_t levels) { 232 | DBG_OUTPUT_PORT.printf("Listing directory: %s\n", dirname); 233 | 234 | File root = fs.open(dirname); 235 | if (!root) { 236 | DBG_OUTPUT_PORT.println("Failed to open directory"); 237 | return; 238 | } 239 | if (!root.isDirectory()) { 240 | DBG_OUTPUT_PORT.println("Not a directory"); 241 | return; 242 | } 243 | 244 | File file = root.openNextFile(); 245 | while (file) { 246 | if (file.isDirectory()) { 247 | DBG_OUTPUT_PORT.print(" DIR : "); 248 | DBG_OUTPUT_PORT.println(file.name()); 249 | if (levels) { 250 | listDir(fs, file.name(), levels - 1); 251 | } 252 | } else { 253 | DBG_OUTPUT_PORT.print(" FILE: "); 254 | DBG_OUTPUT_PORT.print(file.name()); 255 | DBG_OUTPUT_PORT.print(" SIZE: "); 256 | DBG_OUTPUT_PORT.println(file.size()); 257 | } 258 | file = root.openNextFile(); 259 | } 260 | } 261 | #endif 262 | 263 | 264 | void setup(void){ 265 | DBG_OUTPUT_PORT.begin(115200); 266 | DBG_OUTPUT_PORT.print("\n"); 267 | DBG_OUTPUT_PORT.setDebugOutput(true); 268 | SPIFFS.begin(); 269 | { 270 | #ifdef ESP8266 271 | Dir dir = SPIFFS.openDir("/"); 272 | while (dir.next()) { 273 | String fileName = dir.fileName(); 274 | size_t fileSize = dir.fileSize(); 275 | DBG_OUTPUT_PORT.printf("FS File: %s, size: %s\n", fileName.c_str(), formatBytes(fileSize).c_str()); 276 | } 277 | #else 278 | listDir(SPIFFS, "/", 0); 279 | #endif 280 | DBG_OUTPUT_PORT.printf("\n"); 281 | } 282 | 283 | 284 | //WIFI INIT 285 | DBG_OUTPUT_PORT.printf("Connecting to %s\n", ssid); 286 | if (String(WiFi.SSID()) != String(ssid)) { 287 | WiFi.begin(ssid, password); 288 | } 289 | 290 | while (WiFi.status() != WL_CONNECTED) { 291 | delay(500); 292 | DBG_OUTPUT_PORT.print("."); 293 | } 294 | DBG_OUTPUT_PORT.println(""); 295 | DBG_OUTPUT_PORT.print("Connected! IP address: "); 296 | DBG_OUTPUT_PORT.println(WiFi.localIP()); 297 | 298 | MDNS.begin(host); 299 | DBG_OUTPUT_PORT.print("Open http://"); 300 | DBG_OUTPUT_PORT.print(host); 301 | DBG_OUTPUT_PORT.println(".local/edit to see the file browser"); 302 | 303 | 304 | //SERVER INIT 305 | //list directory 306 | server.on("/list", HTTP_GET, handleFileList); 307 | //load editor 308 | server.on("/edit", HTTP_GET, [](){ 309 | if(!handleFileRead("/edit.htm")) server.send(404, "text/plain", "FileNotFound"); 310 | }); 311 | //create file 312 | server.on("/edit", HTTP_PUT, handleFileCreate); 313 | //delete file 314 | server.on("/edit", HTTP_DELETE, handleFileDelete); 315 | //first callback is called after the request has ended with all parsed arguments 316 | //second callback handles file uploads at that location 317 | server.on("/edit", HTTP_POST, [](){ server.send(200, "text/plain", ""); }, handleFileUpload); 318 | 319 | //called when the url is not defined here 320 | //use it to load content from SPIFFS 321 | server.onNotFound([](){ 322 | if(!handleFileRead(server.uri())) 323 | server.send(404, "text/plain", "FileNotFound"); 324 | }); 325 | 326 | //get heap status, analog input value and all GPIO statuses in one json call 327 | server.on("/all", HTTP_GET, [](){ 328 | String json = "{"; 329 | json += "\"heap\":"+String(ESP.getFreeHeap()); 330 | json += ", \"analog\":"+String(analogRead(A0)); 331 | #ifdef ESP8266 332 | json += ", \"gpio\":"+String((uint32_t)(((GPI | GPO) & 0xFFFF) | ((GP16I & 0x01) << 16))); 333 | #endif 334 | json += "}"; 335 | server.send(200, "text/json", json); 336 | json = String(); 337 | }); 338 | server.begin(); 339 | DBG_OUTPUT_PORT.println("HTTP server started"); 340 | 341 | } 342 | 343 | void loop(void){ 344 | server.handleClient(); 345 | } 346 | -------------------------------------------------------------------------------- /WebServer/src/WebServer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | WebServer.cpp - Dead simple web-server. 3 | Supports only one simultaneous client, knows how to handle GET and POST. 4 | 5 | Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. 6 | 7 | This library is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU Lesser General Public 9 | License as published by the Free Software Foundation; either 10 | version 2.1 of the License, or (at your option) any later version. 11 | 12 | This library is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public 18 | License along with this library; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | Modified 8 May 2015 by Hristo Gochkov (proper post and file upload handling) 21 | */ 22 | 23 | 24 | #include 25 | #include 26 | #include "WiFiServer.h" 27 | #include "WiFiClient.h" 28 | #include "WebServer.h" 29 | #include "FS.h" 30 | #include "detail/RequestHandlersImpl.h" 31 | 32 | //#define DEBUG_ESP_HTTP_SERVER 33 | #ifdef DEBUG_ESP_PORT 34 | #define DEBUG_OUTPUT DEBUG_ESP_PORT 35 | #else 36 | #define DEBUG_OUTPUT Serial 37 | #endif 38 | 39 | const char * AUTHORIZATION_HEADER = "Authorization"; 40 | 41 | WebServer::WebServer(IPAddress addr, int port) 42 | : _server(addr, port) 43 | , _currentMethod(HTTP_ANY) 44 | , _currentVersion(0) 45 | , _currentStatus(HC_NONE) 46 | , _statusChange(0) 47 | , _currentHandler(0) 48 | , _firstHandler(0) 49 | , _lastHandler(0) 50 | , _currentArgCount(0) 51 | , _currentArgs(0) 52 | , _headerKeysCount(0) 53 | , _currentHeaders(0) 54 | , _contentLength(0) 55 | , _chunked(false) 56 | { 57 | } 58 | 59 | WebServer::WebServer(int port) 60 | : _server(port) 61 | , _currentMethod(HTTP_ANY) 62 | , _currentVersion(0) 63 | , _currentStatus(HC_NONE) 64 | , _statusChange(0) 65 | , _currentHandler(0) 66 | , _firstHandler(0) 67 | , _lastHandler(0) 68 | , _currentArgCount(0) 69 | , _currentArgs(0) 70 | , _headerKeysCount(0) 71 | , _currentHeaders(0) 72 | , _contentLength(0) 73 | , _chunked(false) 74 | { 75 | } 76 | 77 | WebServer::~WebServer() { 78 | if (_currentHeaders) 79 | delete[]_currentHeaders; 80 | _headerKeysCount = 0; 81 | RequestHandler* handler = _firstHandler; 82 | while (handler) { 83 | RequestHandler* next = handler->next(); 84 | delete handler; 85 | handler = next; 86 | } 87 | close(); 88 | } 89 | 90 | void WebServer::begin() { 91 | _currentStatus = HC_NONE; 92 | _server.begin(); 93 | if(!_headerKeysCount) 94 | collectHeaders(0, 0); 95 | } 96 | 97 | bool WebServer::authenticate(const char * username, const char * password){ 98 | if(hasHeader(AUTHORIZATION_HEADER)){ 99 | String authReq = header(AUTHORIZATION_HEADER); 100 | if(authReq.startsWith("Basic")){ 101 | authReq = authReq.substring(6); 102 | authReq.trim(); 103 | char toencodeLen = strlen(username)+strlen(password)+1; 104 | char *toencode = new char[toencodeLen + 1]; 105 | if(toencode == NULL){ 106 | authReq = String(); 107 | return false; 108 | } 109 | char *encoded = new char[base64_encode_expected_len(toencodeLen)+1]; 110 | if(encoded == NULL){ 111 | authReq = String(); 112 | delete[] toencode; 113 | return false; 114 | } 115 | sprintf(toencode, "%s:%s", username, password); 116 | if(base64_encode_chars(toencode, toencodeLen, encoded) > 0 && authReq.equals(encoded)){ 117 | authReq = String(); 118 | delete[] toencode; 119 | delete[] encoded; 120 | return true; 121 | } 122 | delete[] toencode; 123 | delete[] encoded; 124 | } 125 | authReq = String(); 126 | } 127 | return false; 128 | } 129 | 130 | void WebServer::requestAuthentication(){ 131 | sendHeader("WWW-Authenticate", "Basic realm=\"Login Required\""); 132 | send(401); 133 | } 134 | 135 | void WebServer::on(const String &uri, WebServer::THandlerFunction handler) { 136 | on(uri, HTTP_ANY, handler); 137 | } 138 | 139 | void WebServer::on(const String &uri, HTTPMethod method, WebServer::THandlerFunction fn) { 140 | on(uri, method, fn, _fileUploadHandler); 141 | } 142 | 143 | void WebServer::on(const String &uri, HTTPMethod method, WebServer::THandlerFunction fn, WebServer::THandlerFunction ufn) { 144 | _addRequestHandler(new FunctionRequestHandler(fn, ufn, uri, method)); 145 | } 146 | 147 | void WebServer::addHandler(RequestHandler* handler) { 148 | _addRequestHandler(handler); 149 | } 150 | 151 | void WebServer::_addRequestHandler(RequestHandler* handler) { 152 | if (!_lastHandler) { 153 | _firstHandler = handler; 154 | _lastHandler = handler; 155 | } 156 | else { 157 | _lastHandler->next(handler); 158 | _lastHandler = handler; 159 | } 160 | } 161 | 162 | void WebServer::serveStatic(const char* uri, FS& fs, const char* path, const char* cache_header) { 163 | _addRequestHandler(new StaticRequestHandler(fs, path, uri, cache_header)); 164 | } 165 | 166 | void WebServer::handleClient() { 167 | if (_currentStatus == HC_NONE) { 168 | WiFiClient client = _server.available(); 169 | if (!client) { 170 | return; 171 | } 172 | 173 | #ifdef DEBUG_ESP_HTTP_SERVER 174 | DEBUG_OUTPUT.println("New client"); 175 | #endif 176 | 177 | _currentClient = client; 178 | _currentStatus = HC_WAIT_READ; 179 | _statusChange = millis(); 180 | } 181 | 182 | if (!_currentClient.connected()) { 183 | _currentClient = WiFiClient(); 184 | _currentStatus = HC_NONE; 185 | return; 186 | } 187 | 188 | // Wait for data from client to become available 189 | if (_currentStatus == HC_WAIT_READ) { 190 | if (!_currentClient.available()) { 191 | if (millis() - _statusChange > HTTP_MAX_DATA_WAIT) { 192 | _currentClient = WiFiClient(); 193 | _currentStatus = HC_NONE; 194 | } 195 | yield(); 196 | return; 197 | } 198 | 199 | if (!_parseRequest(_currentClient)) { 200 | _currentClient = WiFiClient(); 201 | _currentStatus = HC_NONE; 202 | return; 203 | } 204 | _currentClient.setTimeout(HTTP_MAX_SEND_WAIT); 205 | _contentLength = CONTENT_LENGTH_NOT_SET; 206 | _handleRequest(); 207 | 208 | if (!_currentClient.connected()) { 209 | _currentClient = WiFiClient(); 210 | _currentStatus = HC_NONE; 211 | return; 212 | } else { 213 | _currentStatus = HC_WAIT_CLOSE; 214 | _statusChange = millis(); 215 | return; 216 | } 217 | } 218 | 219 | if (_currentStatus == HC_WAIT_CLOSE) { 220 | if (millis() - _statusChange > HTTP_MAX_CLOSE_WAIT) { 221 | _currentClient = WiFiClient(); 222 | _currentStatus = HC_NONE; 223 | } else { 224 | yield(); 225 | return; 226 | } 227 | } 228 | } 229 | 230 | void WebServer::close() { 231 | #ifdef ESP8266 232 | _server.stop(); 233 | #else 234 | // TODO add ESP32 WiFiServer::stop() 235 | _server.end(); 236 | #endif 237 | } 238 | 239 | void WebServer::stop() { 240 | close(); 241 | } 242 | 243 | void WebServer::sendHeader(const String& name, const String& value, bool first) { 244 | String headerLine = name; 245 | headerLine += ": "; 246 | headerLine += value; 247 | headerLine += "\r\n"; 248 | 249 | if (first) { 250 | _responseHeaders = headerLine + _responseHeaders; 251 | } 252 | else { 253 | _responseHeaders += headerLine; 254 | } 255 | } 256 | 257 | void WebServer::setContentLength(size_t contentLength) { 258 | _contentLength = contentLength; 259 | } 260 | 261 | void WebServer::_prepareHeader(String& response, int code, const char* content_type, size_t contentLength) { 262 | response = "HTTP/1."+String(_currentVersion)+" "; 263 | response += String(code); 264 | response += " "; 265 | response += _responseCodeToString(code); 266 | response += "\r\n"; 267 | 268 | if (!content_type) 269 | content_type = "text/html"; 270 | 271 | sendHeader("Content-Type", content_type, true); 272 | if (_contentLength == CONTENT_LENGTH_NOT_SET) { 273 | sendHeader("Content-Length", String(contentLength)); 274 | } else if (_contentLength != CONTENT_LENGTH_UNKNOWN) { 275 | sendHeader("Content-Length", String(_contentLength)); 276 | } else if(_contentLength == CONTENT_LENGTH_UNKNOWN && _currentVersion){ //HTTP/1.1 or above client 277 | //let's do chunked 278 | _chunked = true; 279 | sendHeader("Accept-Ranges","none"); 280 | sendHeader("Transfer-Encoding","chunked"); 281 | } 282 | sendHeader("Connection", "close"); 283 | 284 | response += _responseHeaders; 285 | response += "\r\n"; 286 | _responseHeaders = String(); 287 | } 288 | 289 | void WebServer::send(int code, const char* content_type, const String& content) { 290 | String header; 291 | // Can we asume the following? 292 | //if(code == 200 && content.length() == 0 && _contentLength == CONTENT_LENGTH_NOT_SET) 293 | // _contentLength = CONTENT_LENGTH_UNKNOWN; 294 | _prepareHeader(header, code, content_type, content.length()); 295 | _currentClient.write(header.c_str(), header.length()); 296 | if(content.length()) 297 | sendContent(content); 298 | } 299 | 300 | void WebServer::send_P(int code, PGM_P content_type, PGM_P content) { 301 | size_t contentLength = 0; 302 | 303 | if (content != NULL) { 304 | contentLength = strlen_P(content); 305 | } 306 | 307 | String header; 308 | char type[64]; 309 | memccpy_P((void*)type, (PGM_VOID_P)content_type, 0, sizeof(type)); 310 | _prepareHeader(header, code, (const char* )type, contentLength); 311 | _currentClient.write(header.c_str(), header.length()); 312 | sendContent_P(content); 313 | } 314 | 315 | void WebServer::send_P(int code, PGM_P content_type, PGM_P content, size_t contentLength) { 316 | String header; 317 | char type[64]; 318 | memccpy_P((void*)type, (PGM_VOID_P)content_type, 0, sizeof(type)); 319 | _prepareHeader(header, code, (const char* )type, contentLength); 320 | sendContent(header); 321 | sendContent_P(content, contentLength); 322 | } 323 | 324 | void WebServer::send(int code, char* content_type, const String& content) { 325 | send(code, (const char*)content_type, content); 326 | } 327 | 328 | void WebServer::send(int code, const String& content_type, const String& content) { 329 | send(code, (const char*)content_type.c_str(), content); 330 | } 331 | 332 | void WebServer::sendContent(const String& content) { 333 | const char * footer = "\r\n"; 334 | size_t len = content.length(); 335 | if(_chunked) { 336 | char * chunkSize = (char *)malloc(11); 337 | if(chunkSize){ 338 | sprintf(chunkSize, "%x%s", len, footer); 339 | _currentClient.write(chunkSize, strlen(chunkSize)); 340 | free(chunkSize); 341 | } 342 | } 343 | _currentClient.write(content.c_str(), len); 344 | if(_chunked){ 345 | _currentClient.write(footer, 2); 346 | } 347 | } 348 | 349 | void WebServer::sendContent_P(PGM_P content) { 350 | sendContent_P(content, strlen_P(content)); 351 | } 352 | 353 | void WebServer::sendContent_P(PGM_P content, size_t size) { 354 | const char * footer = "\r\n"; 355 | if(_chunked) { 356 | char * chunkSize = (char *)malloc(11); 357 | if(chunkSize){ 358 | sprintf(chunkSize, "%x%s", size, footer); 359 | _currentClient.write(chunkSize, strlen(chunkSize)); 360 | free(chunkSize); 361 | } 362 | } 363 | _currentClient.write_P(content, size); 364 | if(_chunked){ 365 | _currentClient.write(footer, 2); 366 | } 367 | } 368 | 369 | 370 | String WebServer::arg(String name) { 371 | for (int i = 0; i < _currentArgCount; ++i) { 372 | if ( _currentArgs[i].key == name ) 373 | return _currentArgs[i].value; 374 | } 375 | return String(); 376 | } 377 | 378 | String WebServer::arg(int i) { 379 | if (i < _currentArgCount) 380 | return _currentArgs[i].value; 381 | return String(); 382 | } 383 | 384 | String WebServer::argName(int i) { 385 | if (i < _currentArgCount) 386 | return _currentArgs[i].key; 387 | return String(); 388 | } 389 | 390 | int WebServer::args() { 391 | return _currentArgCount; 392 | } 393 | 394 | bool WebServer::hasArg(String name) { 395 | for (int i = 0; i < _currentArgCount; ++i) { 396 | if (_currentArgs[i].key == name) 397 | return true; 398 | } 399 | return false; 400 | } 401 | 402 | 403 | String WebServer::header(String name) { 404 | for (int i = 0; i < _headerKeysCount; ++i) { 405 | if (_currentHeaders[i].key.equalsIgnoreCase(name)) 406 | return _currentHeaders[i].value; 407 | } 408 | return String(); 409 | } 410 | 411 | void WebServer::collectHeaders(const char* headerKeys[], const size_t headerKeysCount) { 412 | _headerKeysCount = headerKeysCount + 1; 413 | if (_currentHeaders) 414 | delete[]_currentHeaders; 415 | _currentHeaders = new RequestArgument[_headerKeysCount]; 416 | _currentHeaders[0].key = AUTHORIZATION_HEADER; 417 | for (int i = 1; i < _headerKeysCount; i++){ 418 | _currentHeaders[i].key = headerKeys[i-1]; 419 | } 420 | } 421 | 422 | String WebServer::header(int i) { 423 | if (i < _headerKeysCount) 424 | return _currentHeaders[i].value; 425 | return String(); 426 | } 427 | 428 | String WebServer::headerName(int i) { 429 | if (i < _headerKeysCount) 430 | return _currentHeaders[i].key; 431 | return String(); 432 | } 433 | 434 | int WebServer::headers() { 435 | return _headerKeysCount; 436 | } 437 | 438 | bool WebServer::hasHeader(String name) { 439 | for (int i = 0; i < _headerKeysCount; ++i) { 440 | if ((_currentHeaders[i].key.equalsIgnoreCase(name)) && (_currentHeaders[i].value.length() > 0)) 441 | return true; 442 | } 443 | return false; 444 | } 445 | 446 | String WebServer::hostHeader() { 447 | return _hostHeader; 448 | } 449 | 450 | void WebServer::onFileUpload(THandlerFunction fn) { 451 | _fileUploadHandler = fn; 452 | } 453 | 454 | void WebServer::onNotFound(THandlerFunction fn) { 455 | _notFoundHandler = fn; 456 | } 457 | 458 | void WebServer::_handleRequest() { 459 | bool handled = false; 460 | if (!_currentHandler){ 461 | #ifdef DEBUG_ESP_HTTP_SERVER 462 | DEBUG_OUTPUT.println("request handler not found"); 463 | #endif 464 | } 465 | else { 466 | handled = _currentHandler->handle(*this, _currentMethod, _currentUri); 467 | #ifdef DEBUG_ESP_HTTP_SERVER 468 | if (!handled) { 469 | DEBUG_OUTPUT.println("request handler failed to handle request"); 470 | } 471 | #endif 472 | } 473 | 474 | if (!handled) { 475 | if(_notFoundHandler) { 476 | _notFoundHandler(); 477 | } 478 | else { 479 | send(404, "text/plain", String("Not found: ") + _currentUri); 480 | } 481 | } 482 | 483 | _currentUri = String(); 484 | } 485 | 486 | String WebServer::_responseCodeToString(int code) { 487 | switch (code) { 488 | case 100: return F("Continue"); 489 | case 101: return F("Switching Protocols"); 490 | case 200: return F("OK"); 491 | case 201: return F("Created"); 492 | case 202: return F("Accepted"); 493 | case 203: return F("Non-Authoritative Information"); 494 | case 204: return F("No Content"); 495 | case 205: return F("Reset Content"); 496 | case 206: return F("Partial Content"); 497 | case 300: return F("Multiple Choices"); 498 | case 301: return F("Moved Permanently"); 499 | case 302: return F("Found"); 500 | case 303: return F("See Other"); 501 | case 304: return F("Not Modified"); 502 | case 305: return F("Use Proxy"); 503 | case 307: return F("Temporary Redirect"); 504 | case 400: return F("Bad Request"); 505 | case 401: return F("Unauthorized"); 506 | case 402: return F("Payment Required"); 507 | case 403: return F("Forbidden"); 508 | case 404: return F("Not Found"); 509 | case 405: return F("Method Not Allowed"); 510 | case 406: return F("Not Acceptable"); 511 | case 407: return F("Proxy Authentication Required"); 512 | case 408: return F("Request Time-out"); 513 | case 409: return F("Conflict"); 514 | case 410: return F("Gone"); 515 | case 411: return F("Length Required"); 516 | case 412: return F("Precondition Failed"); 517 | case 413: return F("Request Entity Too Large"); 518 | case 414: return F("Request-URI Too Large"); 519 | case 415: return F("Unsupported Media Type"); 520 | case 416: return F("Requested range not satisfiable"); 521 | case 417: return F("Expectation Failed"); 522 | case 500: return F("Internal Server Error"); 523 | case 501: return F("Not Implemented"); 524 | case 502: return F("Bad Gateway"); 525 | case 503: return F("Service Unavailable"); 526 | case 504: return F("Gateway Time-out"); 527 | case 505: return F("HTTP Version not supported"); 528 | default: return ""; 529 | } 530 | } 531 | --------------------------------------------------------------------------------