mirror of
https://github.com/esp8266/Arduino.git
synced 2025-07-21 21:22:31 +03:00
Merge branch 'esp8266' of https://github.com/esp8266/Arduino into doc_modify
This commit is contained in:
@ -193,6 +193,17 @@ File FS::open(const char* path, const char* mode) {
|
||||
return File(_impl->open(path, om, am));
|
||||
}
|
||||
|
||||
bool FS::exists(const char* path) {
|
||||
if (!_impl) {
|
||||
return false;
|
||||
}
|
||||
return _impl->exists(path);
|
||||
}
|
||||
|
||||
bool FS::exists(const String& path) {
|
||||
return exists(path.c_str());
|
||||
}
|
||||
|
||||
Dir FS::openDir(const char* path) {
|
||||
if (!_impl) {
|
||||
return Dir();
|
||||
|
@ -97,6 +97,9 @@ public:
|
||||
File open(const char* path, const char* mode);
|
||||
File open(const String& path, const char* mode);
|
||||
|
||||
bool exists(const char* path);
|
||||
bool exists(const String& path);
|
||||
|
||||
Dir openDir(const char* path);
|
||||
Dir openDir(const String& path);
|
||||
|
||||
|
@ -65,6 +65,7 @@ public:
|
||||
virtual bool begin() = 0;
|
||||
virtual bool format() = 0;
|
||||
virtual FileImplPtr open(const char* path, OpenMode openMode, AccessMode accessMode) = 0;
|
||||
virtual bool exists(const char* path) = 0;
|
||||
virtual DirImplPtr openDir(const char* path) = 0;
|
||||
virtual bool rename(const char* pathFrom, const char* pathTo) = 0;
|
||||
virtual bool remove(const char* path) = 0;
|
||||
|
@ -95,7 +95,7 @@ class cbuf {
|
||||
size_t bytes_available = room();
|
||||
size_t size_to_write = (size < bytes_available) ? size : bytes_available;
|
||||
size_t size_written = size_to_write;
|
||||
if(_end > _begin && size_to_write > (size_t)(_bufend - _end)) {
|
||||
if(_end >= _begin && size_to_write > (size_t)(_bufend - _end)) {
|
||||
size_t top_size = _bufend - _end;
|
||||
memcpy(_end, src, top_size);
|
||||
_end = _buf;
|
||||
|
@ -59,7 +59,7 @@ public:
|
||||
}
|
||||
|
||||
FileImplPtr open(const char* path, OpenMode openMode, AccessMode accessMode) override;
|
||||
|
||||
bool exists(const char* path) override;
|
||||
DirImplPtr openDir(const char* path) override;
|
||||
|
||||
bool rename(const char* pathFrom, const char* pathTo) override {
|
||||
@ -404,6 +404,14 @@ FileImplPtr SPIFFSImpl::open(const char* path, OpenMode openMode, AccessMode acc
|
||||
return std::make_shared<SPIFFSFileImpl>(this, fd);
|
||||
}
|
||||
|
||||
bool SPIFFSImpl::exists(const char* path) {
|
||||
char tmpName[SPIFFS_OBJ_NAME_LEN];
|
||||
strlcpy(tmpName, path, sizeof(tmpName));
|
||||
spiffs_stat stat;
|
||||
int rc = SPIFFS_stat(&_fs, tmpName, &stat);
|
||||
return rc == SPIFFS_OK;
|
||||
}
|
||||
|
||||
DirImplPtr SPIFFSImpl::openDir(const char* path) {
|
||||
spiffs_DIR dir;
|
||||
char tmpName[SPIFFS_OBJ_NAME_LEN];
|
||||
|
@ -231,6 +231,14 @@ if (!f) {
|
||||
}
|
||||
```
|
||||
|
||||
#### exists
|
||||
|
||||
```c++
|
||||
SPIFFS.exists(path)
|
||||
```
|
||||
|
||||
Returns *true* if a file with given path exists, *false* otherwise.
|
||||
|
||||
#### openDir
|
||||
|
||||
```c++
|
||||
|
@ -40,8 +40,7 @@ ESP8266WebServer::ESP8266WebServer(int port)
|
||||
{
|
||||
}
|
||||
|
||||
ESP8266WebServer::~ESP8266WebServer()
|
||||
{
|
||||
ESP8266WebServer::~ESP8266WebServer() {
|
||||
if (!_firstHandler)
|
||||
return;
|
||||
RequestHandler* handler = _firstHandler;
|
||||
@ -56,14 +55,11 @@ void ESP8266WebServer::begin() {
|
||||
_server.begin();
|
||||
}
|
||||
|
||||
|
||||
void ESP8266WebServer::on(const char* uri, ESP8266WebServer::THandlerFunction handler)
|
||||
{
|
||||
void ESP8266WebServer::on(const char* uri, ESP8266WebServer::THandlerFunction handler) {
|
||||
on(uri, HTTP_ANY, handler);
|
||||
}
|
||||
|
||||
void ESP8266WebServer::on(const char* uri, HTTPMethod method, ESP8266WebServer::THandlerFunction fn)
|
||||
{
|
||||
void ESP8266WebServer::on(const char* uri, HTTPMethod method, ESP8266WebServer::THandlerFunction fn) {
|
||||
_addRequestHandler(new FunctionRequestHandler(fn, uri, method));
|
||||
}
|
||||
|
||||
@ -79,11 +75,10 @@ void ESP8266WebServer::_addRequestHandler(RequestHandler* handler) {
|
||||
}
|
||||
|
||||
void ESP8266WebServer::serveStatic(const char* uri, FS& fs, const char* path) {
|
||||
_addRequestHandler(new StaticRequestHandler(fs, uri));
|
||||
_addRequestHandler(new StaticRequestHandler(fs, path, uri));
|
||||
}
|
||||
|
||||
void ESP8266WebServer::handleClient()
|
||||
{
|
||||
void ESP8266WebServer::handleClient() {
|
||||
WiFiClient client = _server.available();
|
||||
if (!client) {
|
||||
return;
|
||||
|
@ -4,8 +4,8 @@
|
||||
class RequestHandler {
|
||||
public:
|
||||
RequestHandler(const char* uri, HTTPMethod method)
|
||||
: uri(uri)
|
||||
, method(method)
|
||||
: _uri(uri)
|
||||
, _method(method)
|
||||
, next(NULL)
|
||||
{
|
||||
}
|
||||
@ -15,8 +15,8 @@ public:
|
||||
RequestHandler* next;
|
||||
|
||||
protected:
|
||||
String uri;
|
||||
HTTPMethod method;
|
||||
String _uri;
|
||||
HTTPMethod _method;
|
||||
};
|
||||
|
||||
|
||||
@ -25,47 +25,59 @@ class FunctionRequestHandler : public RequestHandler {
|
||||
|
||||
public:
|
||||
FunctionRequestHandler(ESP8266WebServer::THandlerFunction fn, const char* uri, HTTPMethod method)
|
||||
: fn(fn)
|
||||
: _fn(fn)
|
||||
, base(uri, method)
|
||||
{
|
||||
}
|
||||
|
||||
bool handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) override {
|
||||
if (method != HTTP_ANY && method != requestMethod)
|
||||
if (_method != HTTP_ANY && _method != requestMethod)
|
||||
return false;
|
||||
|
||||
if (requestUri != uri)
|
||||
if (requestUri != _uri)
|
||||
return false;
|
||||
|
||||
fn();
|
||||
_fn();
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
ESP8266WebServer::THandlerFunction fn;
|
||||
ESP8266WebServer::THandlerFunction _fn;
|
||||
};
|
||||
|
||||
class StaticRequestHandler : public RequestHandler {
|
||||
typedef RequestHandler base;
|
||||
|
||||
public:
|
||||
StaticRequestHandler(FS& fs, const char* uri)
|
||||
: fs(fs)
|
||||
StaticRequestHandler(FS& fs, const char* path, const char* uri)
|
||||
: _fs(fs)
|
||||
, base(uri, HTTP_GET)
|
||||
, _path(path)
|
||||
{
|
||||
_isFile = fs.exists(path);
|
||||
DEBUGV("StaticRequestHandler: path=%s uri=%s isFile=%d\r\n", path, uri, _isFile);
|
||||
_baseUriLength = _uri.length();
|
||||
}
|
||||
|
||||
bool handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) override {
|
||||
if (requestMethod != method)
|
||||
if (requestMethod != _method)
|
||||
return false;
|
||||
DEBUGV("StaticRequestHandler::handle: %s\r\n", requestUri.c_str());
|
||||
if (!requestUri.startsWith(uri))
|
||||
DEBUGV("StaticRequestHandler::handle: request=%s _uri=%s\r\n", requestUri.c_str(), _uri.c_str());
|
||||
if (!requestUri.startsWith(_uri))
|
||||
return false;
|
||||
|
||||
auto prefixLength = uri.length() - 1;
|
||||
String path = requestUri.substring(prefixLength);
|
||||
DEBUGV("StaticRequestHandler::handle: %d %s\r\n", prefixLength, path.c_str());
|
||||
File f = fs.open(path, "r");
|
||||
String path(_path);
|
||||
if (!_isFile) {
|
||||
// Base URI doesn't point to a file. Append whatever follows this
|
||||
// URI in request to get the file path.
|
||||
path += requestUri.substring(_baseUriLength);
|
||||
}
|
||||
else if (requestUri != _uri) {
|
||||
// Base URI points to a file but request doesn't match this URI exactly
|
||||
return false;
|
||||
}
|
||||
DEBUGV("StaticRequestHandler::handle: path=%s, isFile=%d\r\n", path.c_str(), _isFile);
|
||||
File f = _fs.open(path, "r");
|
||||
if (!f)
|
||||
return false;
|
||||
|
||||
@ -90,7 +102,10 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
FS fs;
|
||||
FS _fs;
|
||||
String _path;
|
||||
bool _isFile;
|
||||
size_t _baseUriLength;
|
||||
};
|
||||
|
||||
#endif //REQUESTHANDLER_H
|
||||
|
88
libraries/ESP8266WiFi/examples/HTTPSRequest/HTTPSRequest.ino
Normal file
88
libraries/ESP8266WiFi/examples/HTTPSRequest/HTTPSRequest.ino
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* HTTP over TLS (HTTPS) example sketch
|
||||
*
|
||||
* This example demonstrates how to use
|
||||
* WiFiClientSecure class to access HTTPS API.
|
||||
* We fetch and display the status of
|
||||
* esp8266/Arduino project continous integration
|
||||
* build.
|
||||
*
|
||||
* Created by Ivan Grokhotkov, 2015.
|
||||
* This example is in public domain.
|
||||
*/
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <WiFiClientSecure.h>
|
||||
|
||||
const char* ssid = "........";
|
||||
const char* password = "........";
|
||||
|
||||
const char* host = "api.github.com";
|
||||
const int httpsPort = 443;
|
||||
|
||||
// Use web browser to view and copy
|
||||
// SHA1 fingerprint of the certificate
|
||||
const char* fingerprint = "CF 05 98 89 CA FF 8E D8 5E 5C E0 C2 E4 F7 E6 C3 C7 50 DD 5C";
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
Serial.print("connecting to ");
|
||||
Serial.println(ssid);
|
||||
WiFi.begin(ssid, password);
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected");
|
||||
Serial.println("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
// Use WiFiClientSecure class to create TLS connection
|
||||
WiFiClientSecure client;
|
||||
Serial.print("connecting to ");
|
||||
Serial.println(host);
|
||||
if (!client.connect(host, httpsPort)) {
|
||||
Serial.println("connection failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (client.verify(fingerprint, host)) {
|
||||
Serial.println("certificate matches");
|
||||
} else {
|
||||
Serial.println("certificate doesn't match");
|
||||
}
|
||||
|
||||
String url = "/repos/esp8266/Arduino/commits/esp8266/status";
|
||||
Serial.print("requesting URL: ");
|
||||
Serial.println(url);
|
||||
|
||||
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
|
||||
"Host: " + host + "\r\n" +
|
||||
"User-Agent: BuildFailureDetectorESP8266\r\n" +
|
||||
"Connection: close\r\n\r\n");
|
||||
|
||||
Serial.println("request sent");
|
||||
while (client.connected()) {
|
||||
String line = client.readStringUntil('\n');
|
||||
if (line == "\r") {
|
||||
Serial.println("headers received");
|
||||
break;
|
||||
}
|
||||
}
|
||||
String line = client.readStringUntil('\n');
|
||||
if (line.startsWith("{\"state\":\"success\"")) {
|
||||
Serial.println("esp8266/Arduino CI successfull!");
|
||||
} else {
|
||||
Serial.println("esp8266/Arduino CI has failed");
|
||||
}
|
||||
Serial.println("reply was:");
|
||||
Serial.println("==========");
|
||||
Serial.println(line);
|
||||
Serial.println("==========");
|
||||
Serial.println("closing connection");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
}
|
@ -16,6 +16,7 @@ WiFi KEYWORD1
|
||||
WiFiClient KEYWORD1
|
||||
WiFiServer KEYWORD1
|
||||
WiFiUDP KEYWORD1
|
||||
WiFiClientSecure KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
@ -64,4 +65,3 @@ scanNetworks KEYWORD2
|
||||
WIFI_AP LITERAL1
|
||||
WIFI_STA LITERAL1
|
||||
WIFI_AP_STA LITERAL1
|
||||
|
||||
|
@ -29,6 +29,7 @@ extern "C"
|
||||
}
|
||||
#include <errno.h>
|
||||
#include "debug.h"
|
||||
#include "cbuf.h"
|
||||
#include "ESP8266WiFi.h"
|
||||
#include "WiFiClientSecure.h"
|
||||
#include "WiFiClient.h"
|
||||
@ -41,15 +42,23 @@ extern "C"
|
||||
#include "include/ClientContext.h"
|
||||
#include "c_types.h"
|
||||
|
||||
//#define DEBUG_SSL
|
||||
|
||||
#ifdef DEBUG_SSL
|
||||
#define SSL_DEBUG_OPTS SSL_DISPLAY_STATES
|
||||
#else
|
||||
#define SSL_DEBUG_OPTS 0
|
||||
#endif
|
||||
|
||||
class SSLContext {
|
||||
public:
|
||||
SSLContext() {
|
||||
if (_ssl_ctx_refcnt == 0) {
|
||||
_ssl_ctx = ssl_ctx_new(SSL_SERVER_VERIFY_LATER | SSL_DISPLAY_STATES, 0);
|
||||
_ssl_ctx = ssl_ctx_new(SSL_SERVER_VERIFY_LATER | SSL_DEBUG_OPTS, 0);
|
||||
}
|
||||
++_ssl_ctx_refcnt;
|
||||
|
||||
_rxbuf = new cbuf(1536);
|
||||
}
|
||||
|
||||
~SSLContext() {
|
||||
@ -62,6 +71,8 @@ public:
|
||||
if (_ssl_ctx_refcnt == 0) {
|
||||
ssl_ctx_free(_ssl_ctx);
|
||||
}
|
||||
|
||||
delete _rxbuf;
|
||||
}
|
||||
|
||||
void ref() {
|
||||
@ -78,27 +89,71 @@ public:
|
||||
_ssl = ssl_client_new(_ssl_ctx, reinterpret_cast<int>(ctx), nullptr, 0);
|
||||
}
|
||||
|
||||
int read(uint8_t* dst, size_t size) {
|
||||
if (size > _rxbuf->getSize()) {
|
||||
_readAll();
|
||||
}
|
||||
return _rxbuf->read(reinterpret_cast<char*>(dst), size);
|
||||
}
|
||||
|
||||
int read() {
|
||||
optimistic_yield(100);
|
||||
if (!_rxbuf->getSize()) {
|
||||
_readAll();
|
||||
}
|
||||
return _rxbuf->read();
|
||||
}
|
||||
|
||||
int peek() {
|
||||
if (!_rxbuf->getSize()) {
|
||||
_readAll();
|
||||
}
|
||||
return _rxbuf->peek();
|
||||
}
|
||||
|
||||
int available() {
|
||||
optimistic_yield(100);
|
||||
return _rxbuf->getSize();
|
||||
}
|
||||
|
||||
operator SSL*() {
|
||||
return _ssl;
|
||||
}
|
||||
|
||||
protected:
|
||||
int _readAll() {
|
||||
uint8_t* data;
|
||||
int rc = ssl_read(_ssl, &data);
|
||||
if (rc <= 0)
|
||||
return 0;
|
||||
|
||||
if (rc > _rxbuf->room()) {
|
||||
DEBUGV("WiFiClientSecure rx overflow");
|
||||
rc = _rxbuf->room();
|
||||
}
|
||||
int result = 0;
|
||||
size_t sizeBefore = _rxbuf->getSize();
|
||||
if (rc)
|
||||
result = _rxbuf->write(reinterpret_cast<const char*>(data), rc);
|
||||
DEBUGV("*** rb: %d + %d = %d\r\n", sizeBefore, rc, _rxbuf->getSize());
|
||||
return result;
|
||||
}
|
||||
|
||||
static SSL_CTX* _ssl_ctx;
|
||||
static int _ssl_ctx_refcnt;
|
||||
SSL* _ssl = nullptr;
|
||||
int _refcnt = 0;
|
||||
cbuf* _rxbuf;
|
||||
};
|
||||
|
||||
SSL_CTX* SSLContext::_ssl_ctx = nullptr;
|
||||
int SSLContext::_ssl_ctx_refcnt = 0;
|
||||
|
||||
|
||||
WiFiClientSecure::WiFiClientSecure()
|
||||
{
|
||||
WiFiClientSecure::WiFiClientSecure() {
|
||||
}
|
||||
|
||||
WiFiClientSecure::~WiFiClientSecure()
|
||||
{
|
||||
WiFiClientSecure::~WiFiClientSecure() {
|
||||
if (_ssl) {
|
||||
_ssl->unref();
|
||||
}
|
||||
@ -164,14 +219,19 @@ size_t WiFiClientSecure::write(const uint8_t *buf, size_t size) {
|
||||
}
|
||||
|
||||
int WiFiClientSecure::read(uint8_t *buf, size_t size) {
|
||||
return _ssl->read(buf, size);
|
||||
}
|
||||
|
||||
uint8_t* data;
|
||||
int rc = ssl_read(*_ssl, &data);
|
||||
if (rc <= 0)
|
||||
return 0;
|
||||
int WiFiClientSecure::read() {
|
||||
return _ssl->read();
|
||||
}
|
||||
|
||||
memcpy(buf, data, rc);
|
||||
return rc;
|
||||
int WiFiClientSecure::peek() {
|
||||
return _ssl->peek();
|
||||
}
|
||||
|
||||
int WiFiClientSecure::available() {
|
||||
return _ssl->available();
|
||||
}
|
||||
|
||||
void WiFiClientSecure::stop() {
|
||||
@ -182,6 +242,50 @@ void WiFiClientSecure::stop() {
|
||||
return WiFiClient::stop();
|
||||
}
|
||||
|
||||
static bool parseHexNibble(char pb, uint8_t* res) {
|
||||
if (pb >= '0' && pb <= '9') {
|
||||
*res = (uint8_t) (pb - '0'); return true;
|
||||
}
|
||||
else if (pb >= 'a' && pb <= 'f') {
|
||||
*res = (uint8_t) (pb - 'a' + 10); return true;
|
||||
}
|
||||
else if (pb >= 'A' && pb <= 'F') {
|
||||
*res = (uint8_t) (pb - 'A' + 10); return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WiFiClientSecure::verify(const char* fp, const char* url) {
|
||||
uint8_t sha1[20];
|
||||
int len = strlen(fp);
|
||||
int pos = 0;
|
||||
for (int i = 0; i < sizeof(sha1); ++i) {
|
||||
while (pos < len && fp[pos] == ' ') {
|
||||
++pos;
|
||||
}
|
||||
DEBUGV("pos:%d ", pos);
|
||||
if (pos > len - 2) {
|
||||
DEBUGV("fingerprint too short\r\n");
|
||||
return false;
|
||||
}
|
||||
uint8_t high, low;
|
||||
if (!parseHexNibble(fp[pos], &high) || !parseHexNibble(fp[pos+1], &low)) {
|
||||
DEBUGV("invalid hex sequence: %c%c\r\n", fp[pos], fp[pos+1]);
|
||||
return false;
|
||||
}
|
||||
pos += 2;
|
||||
sha1[i] = low | (high << 4);
|
||||
}
|
||||
if (ssl_match_fingerprint(*_ssl, sha1) != 0) {
|
||||
DEBUGV("fingerprint doesn't match\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
//TODO: check URL against certificate
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" int ax_port_read(int fd, uint8_t* buffer, size_t count) {
|
||||
ClientContext* _client = reinterpret_cast<ClientContext*>(fd);
|
||||
if (_client->state() != ESTABLISHED && !_client->getSize()) {
|
||||
@ -217,13 +321,13 @@ extern "C" int ax_get_file(const char *filename, uint8_t **buf) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG_TLS_MEM
|
||||
#define DEBUG_TLS_MEM_PRINT(...) DEBUGV(__VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_TLS_MEM_PRINT(...)
|
||||
#endif
|
||||
|
||||
|
||||
extern "C" void* ax_port_malloc(size_t size, const char* file, int line) {
|
||||
void* result = malloc(size);
|
||||
|
||||
@ -254,7 +358,6 @@ extern "C" void* ax_port_realloc(void* ptr, size_t size, const char* file, int l
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
extern "C" void ax_port_free(void* ptr) {
|
||||
free(ptr);
|
||||
uint32_t *p = (uint32_t*) ptr;
|
||||
|
@ -38,8 +38,13 @@ public:
|
||||
int connect(IPAddress ip, uint16_t port) override;
|
||||
int connect(const char* name, uint16_t port) override;
|
||||
|
||||
bool verify(const char* fingerprint, const char* url);
|
||||
|
||||
size_t write(const uint8_t *buf, size_t size) override;
|
||||
int read(uint8_t *buf, size_t size) override;
|
||||
int available() override;
|
||||
int read() override;
|
||||
int peek() override;
|
||||
void stop() override;
|
||||
|
||||
protected:
|
||||
|
@ -375,6 +375,15 @@ EXP_FUNC void STDCALL ssl_display_error(int error_code);
|
||||
*/
|
||||
EXP_FUNC int STDCALL ssl_verify_cert(const SSL *ssl);
|
||||
|
||||
/**
|
||||
* @brief Check if certificate fingerprint (SHA1) matches the one given.
|
||||
*
|
||||
* @param ssl [in] An SSL object reference.
|
||||
* @param fp [in] SHA1 fingerprint to match against
|
||||
* @return SSL_OK if the certificate is verified.
|
||||
*/
|
||||
EXP_FUNC int STDCALL ssl_match_fingerprint(const SSL *ssl, const uint8_t* fp);
|
||||
|
||||
/**
|
||||
* @brief Retrieve an X.509 distinguished name component.
|
||||
*
|
||||
|
Binary file not shown.
Reference in New Issue
Block a user