Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add BearSSL client and server, support true bidir, lower memory, modern SSL #4273

Merged
merged 28 commits into from
May 15, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
9c519a0
Add BearSSL as SSL/TLS provider to ESP8266-Arduino
earlephilhower Feb 1, 2018
fb44b74
Fix crash due to chaange in WiFiClient
earlephilhower Mar 25, 2018
8f6f5df
Merge branch 'master' into bearssl_wip
d-a-v Mar 27, 2018
71b003f
Pull latest bearssl, save 160 bytes
earlephilhower Mar 27, 2018
c9c560e
Merge branch 'master' of https://github.com/esp8266/Arduino into bear…
earlephilhower Mar 28, 2018
c91995c
Use String instead of fixed char[] for SD paths
earlephilhower Mar 30, 2018
c34f564
Merge branch 'master' into bearssl_wip
earlephilhower Apr 2, 2018
2c31676
Attempt platformIO build fix for SD libs
earlephilhower Apr 2, 2018
a6f0042
More PIO build attempts
earlephilhower Apr 2, 2018
5ec2865
Merge branch 'master' into bearssl_wip
earlephilhower Apr 2, 2018
67afc48
Move axTLS code to a separate namespace
earlephilhower Apr 8, 2018
d2412d9
Move BearSSL to its own namespace, too
earlephilhower Apr 8, 2018
65103cf
BearSSL class renamed to standard Client/ServerSecure
earlephilhower Apr 8, 2018
9987019
Make BearSSLServer source compatible with axTLS code
earlephilhower Apr 8, 2018
d317be2
Add axTLS compatible wrappers to BearSSL Client
earlephilhower Apr 8, 2018
35ccf94
Update examples to hardcode BearSSL namespace
earlephilhower Apr 8, 2018
50e780a
Migrate ESP8266WebServerBearSSL to ServerSecure
earlephilhower Apr 8, 2018
6261b79
Merge branch 'master' into bearssl_wip
earlephilhower Apr 8, 2018
bac5c9c
Fix linker script to place bearssl in flash
earlephilhower Apr 8, 2018
6c94e92
Update per code review, remove old dead #if code
earlephilhower Apr 11, 2018
df612f6
Add EC public key parsing support
earlephilhower Apr 11, 2018
fc2aad0
Merge branch 'master' into bearssl_wip
devyte Apr 11, 2018
a064caa
Merge branch 'master' into bearssl_wip
earlephilhower Apr 14, 2018
569bdda
Merge branch 'master' into bearssl_wip
devyte Apr 20, 2018
e8fbc98
Merge branch 'master' into bearssl_wip
earlephilhower Apr 21, 2018
16bcc45
Merge branch 'master' of https://github.com/esp8266/Arduino into bear…
earlephilhower Apr 23, 2018
af52cb4
Merge branch 'master' into bearssl_wip
d-a-v May 11, 2018
3c5a97c
Update BearSSL lib to upstream commit 77b18d97
earlephilhower May 14, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 65 additions & 2 deletions libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,19 +60,47 @@ class TLSTraits : public TransportTraits

std::unique_ptr<WiFiClient> create() override
{
return std::unique_ptr<WiFiClient>(new WiFiClientSecure());
return std::unique_ptr<WiFiClient>(new axTLS::WiFiClientSecure());
}

bool verify(WiFiClient& client, const char* host) override
{
auto wcs = static_cast<WiFiClientSecure&>(client);
auto wcs = static_cast<axTLS::WiFiClientSecure&>(client);
return wcs.verify(_fingerprint.c_str(), host);
}

protected:
String _fingerprint;
};

class BearSSLTraits : public TransportTraits
{
public:
BearSSLTraits(const uint8_t fingerprint[20])
{
memcpy(_fingerprint, fingerprint, sizeof(_fingerprint));
}

std::unique_ptr<WiFiClient> create() override
{
BearSSL::WiFiClientSecure *client = new BearSSL::WiFiClientSecure();
client->setFingerprint(_fingerprint);
return std::unique_ptr<WiFiClient>(client);
}

bool verify(WiFiClient& client, const char* host) override
{
// No-op. BearSSL will not connect if the fingerprint doesn't match.
// So if you get to here you've already connected and it matched
(void) client;
(void) host;
return true;
}

protected:
uint8_t _fingerprint[20];
};

/**
* constructor
*/
Expand Down Expand Up @@ -116,6 +144,24 @@ bool HTTPClient::begin(String url, String httpsFingerprint)
return true;
}


bool HTTPClient::begin(String url, const uint8_t httpsFingerprint[20])
{
_transportTraits.reset(nullptr);
_port = 443;
if (!beginInternal(url, "https")) {
return false;
}
_transportTraits = TransportTraitsPtr(new BearSSLTraits(httpsFingerprint));
DEBUG_HTTPCLIENT("[HTTP-Client][begin] BearSSL-httpsFingerprint:");
for (size_t i=0; i < 20; i++) {
DEBUG_HTTPCLIENT(" %02x", httpsFingerprint[i]);
}
DEBUG_HTTPCLIENT("\n");
return true;
}


/**
* parsing the url for all needed parameters
* @param url String
Expand Down Expand Up @@ -213,6 +259,23 @@ bool HTTPClient::begin(String host, uint16_t port, String uri, String httpsFinge
return true;
}

bool HTTPClient::begin(String host, uint16_t port, String uri, const uint8_t httpsFingerprint[20])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code duplication is increasing with all these begin() methods. But let's fix that later as a cleanup step.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One suggestion voiced elsewhere was to change the way HTTPClient works to be similar to PubSubClient. That is, HTTPClient receives a prepared Client object (which can be WiFiClient or WiFiClientSecure or any other client). This object already has fingerprint set if necessary. If you think this is a good idea, i can prepare a PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then we would have HTTPClient::begin(Client& client, String hostname) and would do something like

WiFiClientSecure tlsClient;
tlsClient.setFingerprint(fp);
if (!tlsClient.connect(host, port)) {
  // could not connect
}
HTTPClient httpClient;
httpClient.begin(tlsClient, hostname);
int res = httpClient.GET();

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@igrr That's a good idea. Maybe for this immediate round we can shelve it and then migrate to that way afterwards? I'm already at 71 updated files here, and I'd rather not boil any more of the ocean in this pot than necessary.

We'd need to change axTLS::WiFiClientSecure to allow this setFingerprint() call and, when used, do an immediate check on connect(). Then only one TLSClient class in HTTPClient would be needed and we can decorate the older ones as deprecated.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure sure, no need to do anything in this PR. Once this is merged, I will prepare a PR about HTTPClient.

{
clear();
_host = host;
_port = port;
_uri = uri;

_transportTraits = TransportTraitsPtr(new BearSSLTraits(httpsFingerprint));
DEBUG_HTTPCLIENT("[HTTP-Client][begin] host: %s port: %d url: %s BearSSL-httpsFingerprint:", host.c_str(), port, uri.c_str());
for (size_t i=0; i < 20; i++) {
DEBUG_HTTPCLIENT(" %02x", httpsFingerprint[i]);
}
DEBUG_HTTPCLIENT("\n");
return true;
}


/**
* end
* called after the payload is handled
Expand Down
7 changes: 6 additions & 1 deletion libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,15 @@ class HTTPClient
HTTPClient();
~HTTPClient();

// Plain HTTP connection, unencrypted
bool begin(String url);
bool begin(String url, String httpsFingerprint);
bool begin(String host, uint16_t port, String uri = "/");
// Use axTLS for secure HTTPS connection
bool begin(String url, String httpsFingerprint);
bool begin(String host, uint16_t port, String uri, String httpsFingerprint);
// Use BearSSL for secure HTTPS connection
bool begin(String url, const uint8_t httpsFingerprint[20]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why can't we pass the fingerprint as String? If the intention is to disambiguate between two implementations of TLS, then it's a really non-obvious way to do this. Introducing a function with different name (beginBearSSL?) and keeping the argument type might be an option.

bool begin(String host, uint16_t port, String uri, const uint8_t httpsFingerprint[20]);
// deprecated, use the overload above instead
bool begin(String host, uint16_t port, String uri, bool https, String httpsFingerprint) __attribute__ ((deprecated));

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
SecureBearSSLUpdater - SSL encrypted, password-protected firmware update

This example starts a HTTPS server on the ESP8266 to allow firmware updates
to be performed. All communication, including the username and password,
is encrypted via SSL. Be sure to update the SSID and PASSWORD before running
to allow connection to your WiFi network.

To upload through terminal you can use:
curl -u admin:admin -F "image=@firmware.bin" esp8266-webupdate.local/firmware

Adapted by Earle F. Philhower, III, from the SecureWebUpdater.ino example.
This example is released into the public domain.
*/

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServerSecure.h>
#include <ESP8266mDNS.h>
#include <ESP8266HTTPUpdateServer.h>

const char* host = "esp8266-webupdate";
const char* update_path = "/firmware";
const char* update_username = "admin";
const char* update_password = "admin";
const char* ssid = "........";
const char* password = "........";

BearSSL::ESP8266WebServerSecure httpServer(443);
ESP8266HTTPUpdateServer httpUpdater;

static const char serverCert[] PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
MIIDSzCCAjMCCQD2ahcfZAwXxDANBgkqhkiG9w0BAQsFADCBiTELMAkGA1UEBhMC
VVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU9yYW5nZSBDb3VudHkx
EDAOBgNVBAoMB1ByaXZhZG8xGjAYBgNVBAMMEXNlcnZlci56bGFiZWwuY29tMR8w
HQYJKoZIhvcNAQkBFhBlYXJsZUB6bGFiZWwuY29tMB4XDTE4MDMwNjA1NDg0NFoX
DTE5MDMwNjA1NDg0NFowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3Rh
dGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBAPVKBwbZ+KDSl40YCDkP6y8Sv4iNGvEOZg8Y
X7sGvf/xZH7UiCBWPFIRpNmDSaZ3yjsmFqm6sLiYSGSdrBCFqdt9NTp2r7hga6Sj
oASSZY4B9pf+GblDy5m10KDx90BFKXdPMCLT+o76Nx9PpCvw13A848wHNG3bpBgI
t+w/vJCX3bkRn8yEYAU6GdMbYe7v446hX3kY5UmgeJFr9xz1kq6AzYrMt/UHhNzO
S+QckJaY0OGWvmTNspY3xCbbFtIDkCdBS8CZAw+itnofvnWWKQEXlt6otPh5njwy
+O1t/Q+Z7OMDYQaH02IQx3188/kW3FzOY32knER1uzjmRO+jhA8CAwEAATANBgkq
hkiG9w0BAQsFAAOCAQEAnDrROGRETB0woIcI1+acY1yRq4yAcH2/hdq2MoM+DCyM
E8CJaOznGR9ND0ImWpTZqomHOUkOBpvu7u315blQZcLbL1LfHJGRTCHVhvVrcyEb
fWTnRtAQdlirUm/obwXIitoz64VSbIVzcqqfg9C6ZREB9JbEX98/9Wp2gVY+31oC
JfUvYadSYxh3nblvA4OL+iEZiW8NE3hbW6WPXxvS7Euge0uWMPc4uEcnsE0ZVG3m
+TGimzSdeWDvGBRWZHXczC2zD4aoE5vrl+GD2i++c6yjL/otHfYyUpzUfbI2hMAA
5tAF1D5vAAwA8nfPysumlLsIjohJZo4lgnhB++AlOg==
-----END CERTIFICATE-----
)EOF";

static const char serverKey[] PROGMEM = R"EOF(
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA9UoHBtn4oNKXjRgIOQ/rLxK/iI0a8Q5mDxhfuwa9//FkftSI
IFY8UhGk2YNJpnfKOyYWqbqwuJhIZJ2sEIWp2301OnavuGBrpKOgBJJljgH2l/4Z
uUPLmbXQoPH3QEUpd08wItP6jvo3H0+kK/DXcDzjzAc0bdukGAi37D+8kJfduRGf
zIRgBToZ0xth7u/jjqFfeRjlSaB4kWv3HPWSroDNisy39QeE3M5L5ByQlpjQ4Za+
ZM2yljfEJtsW0gOQJ0FLwJkDD6K2eh++dZYpAReW3qi0+HmePDL47W39D5ns4wNh
BofTYhDHfXzz+RbcXM5jfaScRHW7OOZE76OEDwIDAQABAoIBAQDKov5NFbNFQNR8
djcM1O7Is6dRaqiwLeH4ZH1pZ3d9QnFwKanPdQ5eCj9yhfhJMrr5xEyCqT0nMn7T
yEIGYDXjontfsf8WxWkH2TjvrfWBrHOIOx4LJEvFzyLsYxiMmtZXvy6YByD+Dw2M
q2GH/24rRdI2klkozIOyazluTXU8yOsSGxHr/aOa9/sZISgLmaGOOuKI/3Zqjdhr
eHeSqoQFt3xXa8jw01YubQUDw/4cv9rk2ytTdAoQUimiKtgtjsggpP1LTq4xcuqN
d4jWhTcnorWpbD2cVLxrEbnSR3VuBCJEZv5axg5ZPxLEnlcId8vMtvTRb5nzzszn
geYUWDPhAoGBAPyKVNqqwQl44oIeiuRM2FYenMt4voVaz3ExJX2JysrG0jtCPv+Y
84R6Cv3nfITz3EZDWp5sW3OwoGr77lF7Tv9tD6BptEmgBeuca3SHIdhG2MR+tLyx
/tkIAarxQcTGsZaSqra3gXOJCMz9h2P5dxpdU+0yeMmOEnAqgQ8qtNBfAoGBAPim
RAtnrd0WSlCgqVGYFCvDh1kD5QTNbZc+1PcBHbVV45EmJ2fLXnlDeplIZJdYxmzu
DMOxZBYgfeLY9exje00eZJNSj/csjJQqiRftrbvYY7m5njX1kM5K8x4HlynQTDkg
rtKO0YZJxxmjRTbFGMegh1SLlFLRIMtehNhOgipRAoGBAPnEEpJGCS9GGLfaX0HW
YqwiEK8Il12q57mqgsq7ag7NPwWOymHesxHV5mMh/Dw+NyBi4xAGWRh9mtrUmeqK
iyICik773Gxo0RIqnPgd4jJWN3N3YWeynzulOIkJnSNx5BforOCTc3uCD2s2YB5X
jx1LKoNQxLeLRN8cmpIWicf/AoGBANjRSsZTKwV9WWIDJoHyxav/vPb+8WYFp8lZ
zaRxQbGM6nn4NiZI7OF62N3uhWB/1c7IqTK/bVHqFTuJCrCNcsgld3gLZ2QWYaMV
kCPgaj1BjHw4AmB0+EcajfKilcqtSroJ6MfMJ6IclVOizkjbByeTsE4lxDmPCDSt
/9MKanBxAoGAY9xo741Pn9WUxDyRplww606ccdNf/ksHWNc/Y2B5SPwxxSnIq8nO
j01SmsCUYVFAgZVOTiiycakjYLzxlc6p8BxSVqy6LlJqn95N8OXoQ+bkwUux/ekg
gz5JWYhbD6c38khSzJb0pNXCo3EuYAVa36kDM96k1BtWuhRS10Q1VXk=
-----END RSA PRIVATE KEY-----
)EOF";


void setup()
{

Serial.begin(115200);
Serial.println();
Serial.println("Booting Sketch...");
WiFi.mode(WIFI_AP_STA);
WiFi.begin(ssid, password);

while(WiFi.waitForConnectResult() != WL_CONNECTED){
WiFi.begin(ssid, password);
Serial.println("WiFi failed, retrying.");
}

configTime(3 * 3600, 0, "pool.ntp.org", "time.nist.gov");

MDNS.begin(host);

httpServer.setRSACert(new BearSSLX509List(serverCert), new BearSSLPrivateKey(serverKey));
httpUpdater.setup(&httpServer, update_path, update_username, update_password);
httpServer.begin();

MDNS.addService("https", "tcp", 443);
Serial.printf("BearSSLUpdateServer ready!\nOpen https://%s.local%s in "\
"your browser and login with username '%s' and password "\
"'%s'\n", host, update_path, update_username, update_password);
}

void loop()
{
httpServer.handleClient();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/*
HelloServerBearSSL - Simple HTTPS server example

This example demonstrates a basic ESP8266WebServerSecure HTTPS server
that can serve "/" and "/inline" and generate detailed 404 (not found)
HTTP respoinses. Be sure to update the SSID and PASSWORD before running
to allow connection to your WiFi network.

Adapted by Earle F. Philhower, III, from the HelloServer.ino example.
This example is released into the public domain.
*/
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServerSecure.h>
#include <ESP8266mDNS.h>

const char* ssid = "....";
const char* password = "....";

BearSSL::ESP8266WebServerSecure server(443);

static const char serverCert[] PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
MIIDSzCCAjMCCQD2ahcfZAwXxDANBgkqhkiG9w0BAQsFADCBiTELMAkGA1UEBhMC
VVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU9yYW5nZSBDb3VudHkx
EDAOBgNVBAoMB1ByaXZhZG8xGjAYBgNVBAMMEXNlcnZlci56bGFiZWwuY29tMR8w
HQYJKoZIhvcNAQkBFhBlYXJsZUB6bGFiZWwuY29tMB4XDTE4MDMwNjA1NDg0NFoX
DTE5MDMwNjA1NDg0NFowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3Rh
dGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBAPVKBwbZ+KDSl40YCDkP6y8Sv4iNGvEOZg8Y
X7sGvf/xZH7UiCBWPFIRpNmDSaZ3yjsmFqm6sLiYSGSdrBCFqdt9NTp2r7hga6Sj
oASSZY4B9pf+GblDy5m10KDx90BFKXdPMCLT+o76Nx9PpCvw13A848wHNG3bpBgI
t+w/vJCX3bkRn8yEYAU6GdMbYe7v446hX3kY5UmgeJFr9xz1kq6AzYrMt/UHhNzO
S+QckJaY0OGWvmTNspY3xCbbFtIDkCdBS8CZAw+itnofvnWWKQEXlt6otPh5njwy
+O1t/Q+Z7OMDYQaH02IQx3188/kW3FzOY32knER1uzjmRO+jhA8CAwEAATANBgkq
hkiG9w0BAQsFAAOCAQEAnDrROGRETB0woIcI1+acY1yRq4yAcH2/hdq2MoM+DCyM
E8CJaOznGR9ND0ImWpTZqomHOUkOBpvu7u315blQZcLbL1LfHJGRTCHVhvVrcyEb
fWTnRtAQdlirUm/obwXIitoz64VSbIVzcqqfg9C6ZREB9JbEX98/9Wp2gVY+31oC
JfUvYadSYxh3nblvA4OL+iEZiW8NE3hbW6WPXxvS7Euge0uWMPc4uEcnsE0ZVG3m
+TGimzSdeWDvGBRWZHXczC2zD4aoE5vrl+GD2i++c6yjL/otHfYyUpzUfbI2hMAA
5tAF1D5vAAwA8nfPysumlLsIjohJZo4lgnhB++AlOg==
-----END CERTIFICATE-----
)EOF";

static const char serverKey[] PROGMEM = R"EOF(
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA9UoHBtn4oNKXjRgIOQ/rLxK/iI0a8Q5mDxhfuwa9//FkftSI
IFY8UhGk2YNJpnfKOyYWqbqwuJhIZJ2sEIWp2301OnavuGBrpKOgBJJljgH2l/4Z
uUPLmbXQoPH3QEUpd08wItP6jvo3H0+kK/DXcDzjzAc0bdukGAi37D+8kJfduRGf
zIRgBToZ0xth7u/jjqFfeRjlSaB4kWv3HPWSroDNisy39QeE3M5L5ByQlpjQ4Za+
ZM2yljfEJtsW0gOQJ0FLwJkDD6K2eh++dZYpAReW3qi0+HmePDL47W39D5ns4wNh
BofTYhDHfXzz+RbcXM5jfaScRHW7OOZE76OEDwIDAQABAoIBAQDKov5NFbNFQNR8
djcM1O7Is6dRaqiwLeH4ZH1pZ3d9QnFwKanPdQ5eCj9yhfhJMrr5xEyCqT0nMn7T
yEIGYDXjontfsf8WxWkH2TjvrfWBrHOIOx4LJEvFzyLsYxiMmtZXvy6YByD+Dw2M
q2GH/24rRdI2klkozIOyazluTXU8yOsSGxHr/aOa9/sZISgLmaGOOuKI/3Zqjdhr
eHeSqoQFt3xXa8jw01YubQUDw/4cv9rk2ytTdAoQUimiKtgtjsggpP1LTq4xcuqN
d4jWhTcnorWpbD2cVLxrEbnSR3VuBCJEZv5axg5ZPxLEnlcId8vMtvTRb5nzzszn
geYUWDPhAoGBAPyKVNqqwQl44oIeiuRM2FYenMt4voVaz3ExJX2JysrG0jtCPv+Y
84R6Cv3nfITz3EZDWp5sW3OwoGr77lF7Tv9tD6BptEmgBeuca3SHIdhG2MR+tLyx
/tkIAarxQcTGsZaSqra3gXOJCMz9h2P5dxpdU+0yeMmOEnAqgQ8qtNBfAoGBAPim
RAtnrd0WSlCgqVGYFCvDh1kD5QTNbZc+1PcBHbVV45EmJ2fLXnlDeplIZJdYxmzu
DMOxZBYgfeLY9exje00eZJNSj/csjJQqiRftrbvYY7m5njX1kM5K8x4HlynQTDkg
rtKO0YZJxxmjRTbFGMegh1SLlFLRIMtehNhOgipRAoGBAPnEEpJGCS9GGLfaX0HW
YqwiEK8Il12q57mqgsq7ag7NPwWOymHesxHV5mMh/Dw+NyBi4xAGWRh9mtrUmeqK
iyICik773Gxo0RIqnPgd4jJWN3N3YWeynzulOIkJnSNx5BforOCTc3uCD2s2YB5X
jx1LKoNQxLeLRN8cmpIWicf/AoGBANjRSsZTKwV9WWIDJoHyxav/vPb+8WYFp8lZ
zaRxQbGM6nn4NiZI7OF62N3uhWB/1c7IqTK/bVHqFTuJCrCNcsgld3gLZ2QWYaMV
kCPgaj1BjHw4AmB0+EcajfKilcqtSroJ6MfMJ6IclVOizkjbByeTsE4lxDmPCDSt
/9MKanBxAoGAY9xo741Pn9WUxDyRplww606ccdNf/ksHWNc/Y2B5SPwxxSnIq8nO
j01SmsCUYVFAgZVOTiiycakjYLzxlc6p8BxSVqy6LlJqn95N8OXoQ+bkwUux/ekg
gz5JWYhbD6c38khSzJb0pNXCo3EuYAVa36kDM96k1BtWuhRS10Q1VXk=
-----END RSA PRIVATE KEY-----
)EOF";


const int led = 13;

void handleRoot() {
digitalWrite(led, 1);
server.send(200, "text/plain", "Hello from esp8266 over HTTPS!");
digitalWrite(led, 0);
}

void handleNotFound(){
digitalWrite(led, 1);
String message = "File Not Found\n\n";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Series of concats like this should be avoided (causes mem fragmentation). While this is an example, many users will base off of it, so let's set a good one. Can you calculate the string lenght beforehand and use ::reserve()?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say that if you need to calculate the length before using String that defeats String's purpose as a crutch for new users. If I (easily) knew how long the buffer would be, I'd just use a temp on the stack or malloc() it and sprintf().

In this sample I'd need to sum up the constant bits and then replicate the for(all args) { len += argname[i].len + arg[i].len } loop just to get that length.

Also, I believe umm_allocator will attempt to extend the existing block if there's unused heap after it, not make a new one, so we're not necessarily making as big of a mess as we might be in this case.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've seen at least one user project stop crashing when a String::reserve() call was added before the concat sequence. But let's leave it as it is for now, we can always revisit later.

message += "URI: ";
message += server.uri();
message += "\nMethod: ";
message += (server.method() == HTTP_GET)?"GET":"POST";
message += "\nArguments: ";
message += server.args();
message += "\n";
for (uint8_t i=0; i<server.args(); i++){
message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
}
server.send(404, "text/plain", message);
digitalWrite(led, 0);
}

void setup(void){
pinMode(led, OUTPUT);
digitalWrite(led, 0);
Serial.begin(115200);
WiFi.begin(ssid, password);
Serial.println("");

// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}

configTime(3 * 3600, 0, "pool.ntp.org", "time.nist.gov");

Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());

if (MDNS.begin("esp8266")) {
Serial.println("MDNS responder started");
}

server.setRSACert(new BearSSLX509List(serverCert), new BearSSLPrivateKey(serverKey));

server.on("/", handleRoot);

server.on("/inline", [](){
server.send(200, "text/plain", "this works as well");
});

server.onNotFound(handleNotFound);

server.begin();
Serial.println("HTTPS server started");
}

void loop(void){
server.handleClient();
}
Loading