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));
}
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();

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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];

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
```c++

View File

@ -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;

View File

@ -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

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
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

View File

@ -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;

View File

@ -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:

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);
/**
* @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.