1
0
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:
Pascal Gollor
2015-09-14 19:44:23 +02:00
14 changed files with 291 additions and 45 deletions

View File

@ -193,6 +193,17 @@ File FS::open(const char* path, const char* mode) {
return File(_impl->open(path, om, am)); 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) { Dir FS::openDir(const char* path) {
if (!_impl) { if (!_impl) {
return Dir(); return Dir();

View File

@ -97,6 +97,9 @@ public:
File open(const char* path, const char* mode); File open(const char* path, const char* mode);
File open(const String& 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 char* path);
Dir openDir(const String& path); Dir openDir(const String& path);

View File

@ -65,6 +65,7 @@ public:
virtual bool begin() = 0; virtual bool begin() = 0;
virtual bool format() = 0; virtual bool format() = 0;
virtual FileImplPtr open(const char* path, OpenMode openMode, AccessMode accessMode) = 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 DirImplPtr openDir(const char* path) = 0;
virtual bool rename(const char* pathFrom, const char* pathTo) = 0; virtual bool rename(const char* pathFrom, const char* pathTo) = 0;
virtual bool remove(const char* path) = 0; virtual bool remove(const char* path) = 0;

View File

@ -95,7 +95,7 @@ class cbuf {
size_t bytes_available = room(); size_t bytes_available = room();
size_t size_to_write = (size < bytes_available) ? size : bytes_available; size_t size_to_write = (size < bytes_available) ? size : bytes_available;
size_t size_written = size_to_write; 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; size_t top_size = _bufend - _end;
memcpy(_end, src, top_size); memcpy(_end, src, top_size);
_end = _buf; _end = _buf;

View File

@ -59,7 +59,7 @@ public:
} }
FileImplPtr open(const char* path, OpenMode openMode, AccessMode accessMode) override; FileImplPtr open(const char* path, OpenMode openMode, AccessMode accessMode) override;
bool exists(const char* path) override;
DirImplPtr openDir(const char* path) override; DirImplPtr openDir(const char* path) override;
bool rename(const char* pathFrom, const char* pathTo) 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); 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) { DirImplPtr SPIFFSImpl::openDir(const char* path) {
spiffs_DIR dir; spiffs_DIR dir;
char tmpName[SPIFFS_OBJ_NAME_LEN]; char tmpName[SPIFFS_OBJ_NAME_LEN];

View File

@ -231,6 +231,14 @@ if (!f) {
} }
``` ```
#### exists
```c++
SPIFFS.exists(path)
```
Returns *true* if a file with given path exists, *false* otherwise.
#### openDir #### openDir
```c++ ```c++

View File

@ -40,8 +40,7 @@ ESP8266WebServer::ESP8266WebServer(int port)
{ {
} }
ESP8266WebServer::~ESP8266WebServer() ESP8266WebServer::~ESP8266WebServer() {
{
if (!_firstHandler) if (!_firstHandler)
return; return;
RequestHandler* handler = _firstHandler; RequestHandler* handler = _firstHandler;
@ -56,14 +55,11 @@ void ESP8266WebServer::begin() {
_server.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); 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)); _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) { 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(); WiFiClient client = _server.available();
if (!client) { if (!client) {
return; return;

View File

@ -4,8 +4,8 @@
class RequestHandler { class RequestHandler {
public: public:
RequestHandler(const char* uri, HTTPMethod method) RequestHandler(const char* uri, HTTPMethod method)
: uri(uri) : _uri(uri)
, method(method) , _method(method)
, next(NULL) , next(NULL)
{ {
} }
@ -15,8 +15,8 @@ public:
RequestHandler* next; RequestHandler* next;
protected: protected:
String uri; String _uri;
HTTPMethod method; HTTPMethod _method;
}; };
@ -25,47 +25,59 @@ class FunctionRequestHandler : public RequestHandler {
public: public:
FunctionRequestHandler(ESP8266WebServer::THandlerFunction fn, const char* uri, HTTPMethod method) FunctionRequestHandler(ESP8266WebServer::THandlerFunction fn, const char* uri, HTTPMethod method)
: fn(fn) : _fn(fn)
, base(uri, method) , base(uri, method)
{ {
} }
bool handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) override { bool handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) override {
if (method != HTTP_ANY && method != requestMethod) if (_method != HTTP_ANY && _method != requestMethod)
return false; return false;
if (requestUri != uri) if (requestUri != _uri)
return false; return false;
fn(); _fn();
return true; return true;
} }
protected: protected:
ESP8266WebServer::THandlerFunction fn; ESP8266WebServer::THandlerFunction _fn;
}; };
class StaticRequestHandler : public RequestHandler { class StaticRequestHandler : public RequestHandler {
typedef RequestHandler base; typedef RequestHandler base;
public: public:
StaticRequestHandler(FS& fs, const char* uri) StaticRequestHandler(FS& fs, const char* path, const char* uri)
: fs(fs) : _fs(fs)
, base(uri, HTTP_GET) , 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 { bool handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) override {
if (requestMethod != method) if (requestMethod != _method)
return false; return false;
DEBUGV("StaticRequestHandler::handle: %s\r\n", requestUri.c_str()); DEBUGV("StaticRequestHandler::handle: request=%s _uri=%s\r\n", requestUri.c_str(), _uri.c_str());
if (!requestUri.startsWith(uri)) if (!requestUri.startsWith(_uri))
return false; return false;
auto prefixLength = uri.length() - 1; String path(_path);
String path = requestUri.substring(prefixLength); if (!_isFile) {
DEBUGV("StaticRequestHandler::handle: %d %s\r\n", prefixLength, path.c_str()); // Base URI doesn't point to a file. Append whatever follows this
File f = fs.open(path, "r"); // 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) if (!f)
return false; return false;
@ -90,7 +102,10 @@ public:
} }
protected: protected:
FS fs; FS _fs;
String _path;
bool _isFile;
size_t _baseUriLength;
}; };
#endif //REQUESTHANDLER_H #endif //REQUESTHANDLER_H

View 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() {
}

View File

@ -16,6 +16,7 @@ WiFi KEYWORD1
WiFiClient KEYWORD1 WiFiClient KEYWORD1
WiFiServer KEYWORD1 WiFiServer KEYWORD1
WiFiUDP KEYWORD1 WiFiUDP KEYWORD1
WiFiClientSecure KEYWORD1
####################################### #######################################
# Methods and Functions (KEYWORD2) # Methods and Functions (KEYWORD2)
@ -64,4 +65,3 @@ scanNetworks KEYWORD2
WIFI_AP LITERAL1 WIFI_AP LITERAL1
WIFI_STA LITERAL1 WIFI_STA LITERAL1
WIFI_AP_STA LITERAL1 WIFI_AP_STA LITERAL1

View File

@ -29,6 +29,7 @@ extern "C"
} }
#include <errno.h> #include <errno.h>
#include "debug.h" #include "debug.h"
#include "cbuf.h"
#include "ESP8266WiFi.h" #include "ESP8266WiFi.h"
#include "WiFiClientSecure.h" #include "WiFiClientSecure.h"
#include "WiFiClient.h" #include "WiFiClient.h"
@ -41,15 +42,23 @@ extern "C"
#include "include/ClientContext.h" #include "include/ClientContext.h"
#include "c_types.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 { class SSLContext {
public: public:
SSLContext() { SSLContext() {
if (_ssl_ctx_refcnt == 0) { 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; ++_ssl_ctx_refcnt;
_rxbuf = new cbuf(1536);
} }
~SSLContext() { ~SSLContext() {
@ -62,6 +71,8 @@ public:
if (_ssl_ctx_refcnt == 0) { if (_ssl_ctx_refcnt == 0) {
ssl_ctx_free(_ssl_ctx); ssl_ctx_free(_ssl_ctx);
} }
delete _rxbuf;
} }
void ref() { void ref() {
@ -78,27 +89,71 @@ public:
_ssl = ssl_client_new(_ssl_ctx, reinterpret_cast<int>(ctx), nullptr, 0); _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*() { operator SSL*() {
return _ssl; return _ssl;
} }
protected: 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 SSL_CTX* _ssl_ctx;
static int _ssl_ctx_refcnt; static int _ssl_ctx_refcnt;
SSL* _ssl = nullptr; SSL* _ssl = nullptr;
int _refcnt = 0; int _refcnt = 0;
cbuf* _rxbuf;
}; };
SSL_CTX* SSLContext::_ssl_ctx = nullptr; SSL_CTX* SSLContext::_ssl_ctx = nullptr;
int SSLContext::_ssl_ctx_refcnt = 0; int SSLContext::_ssl_ctx_refcnt = 0;
WiFiClientSecure::WiFiClientSecure() WiFiClientSecure::WiFiClientSecure() {
{
} }
WiFiClientSecure::~WiFiClientSecure() WiFiClientSecure::~WiFiClientSecure() {
{
if (_ssl) { if (_ssl) {
_ssl->unref(); _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) { int WiFiClientSecure::read(uint8_t *buf, size_t size) {
return _ssl->read(buf, size);
}
uint8_t* data; int WiFiClientSecure::read() {
int rc = ssl_read(*_ssl, &data); return _ssl->read();
if (rc <= 0) }
return 0;
memcpy(buf, data, rc); int WiFiClientSecure::peek() {
return rc; return _ssl->peek();
}
int WiFiClientSecure::available() {
return _ssl->available();
} }
void WiFiClientSecure::stop() { void WiFiClientSecure::stop() {
@ -182,6 +242,50 @@ void WiFiClientSecure::stop() {
return WiFiClient::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) { extern "C" int ax_port_read(int fd, uint8_t* buffer, size_t count) {
ClientContext* _client = reinterpret_cast<ClientContext*>(fd); ClientContext* _client = reinterpret_cast<ClientContext*>(fd);
if (_client->state() != ESTABLISHED && !_client->getSize()) { if (_client->state() != ESTABLISHED && !_client->getSize()) {
@ -217,13 +321,13 @@ extern "C" int ax_get_file(const char *filename, uint8_t **buf) {
return 0; return 0;
} }
#ifdef DEBUG_TLS_MEM #ifdef DEBUG_TLS_MEM
#define DEBUG_TLS_MEM_PRINT(...) DEBUGV(__VA_ARGS__) #define DEBUG_TLS_MEM_PRINT(...) DEBUGV(__VA_ARGS__)
#else #else
#define DEBUG_TLS_MEM_PRINT(...) #define DEBUG_TLS_MEM_PRINT(...)
#endif #endif
extern "C" void* ax_port_malloc(size_t size, const char* file, int line) { extern "C" void* ax_port_malloc(size_t size, const char* file, int line) {
void* result = malloc(size); 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; return result;
} }
extern "C" void ax_port_free(void* ptr) { extern "C" void ax_port_free(void* ptr) {
free(ptr); free(ptr);
uint32_t *p = (uint32_t*) ptr; uint32_t *p = (uint32_t*) ptr;

View File

@ -38,8 +38,13 @@ public:
int connect(IPAddress ip, uint16_t port) override; int connect(IPAddress ip, uint16_t port) override;
int connect(const char* name, 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; size_t write(const uint8_t *buf, size_t size) override;
int read(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; void stop() override;
protected: protected:

View File

@ -375,6 +375,15 @@ EXP_FUNC void STDCALL ssl_display_error(int error_code);
*/ */
EXP_FUNC int STDCALL ssl_verify_cert(const SSL *ssl); 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. * @brief Retrieve an X.509 distinguished name component.
* *

Binary file not shown.