Skip to content

WIP - Rewrite ESP8266WebServer using templates #4912

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

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
33 changes: 29 additions & 4 deletions cores/esp8266/pgmspace.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,35 @@
#include "ets_sys.h"
#include "osapi.h"

#define PROGMEM ICACHE_RODATA_ATTR
#define PGM_P const char *
#define PGM_VOID_P const void *
#define PSTR(s) (__extension__({static const char __c[] PROGMEM = (s); &__c[0];}))

#ifndef ICACHE_RODATA_ATTR
#define ICACHE_RODATA_ATTR __attribute__((section(".irom.text")))
#endif
#ifndef PROGMEM
// The following two macros cause a parameter to be enclosed in quotes
// by the preopressor (i.e. for concatenating ints to strings)
#define __STRINGIZE_NX(A) #A
#define __STRINGIZE(A) __STRINGIZE_NX(A)
// Since __section__ is supposed to be only use for global variables,
// there could be conflicts when a static/inlined function has them in the
// same file as a non-static PROGMEM object.
// Ref: https://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Variable-Attributes.html
// Place each progmem object into its own named section, avoiding conflicts
#define PROGMEM __attribute__((section( "\".irom.text." __FILE__ "." __STRINGIZE(__LINE__) "." __STRINGIZE(__COUNTER__) "\"")))
#endif
#ifndef PGM_P
#define PGM_P const char *
#endif
#ifndef PGM_VOID_P
#define PGM_VOID_P const void *
#endif

// PSTR() macro modified to start on a 32-bit boundary. This adds on average
// 1.5 bytes/string, but in return memcpy_P and strcpy_P will work 4~8x faster
#ifndef PSTR
#define PSTR(s) (__extension__({static const char __c[] __attribute__((__aligned__(4))) PROGMEM = (s); &__c[0];}))
#endif

#else //__ets__
#define PROGMEM
#define PGM_P const char *
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const char* ssid = "........";
const char* password = "........";

BearSSL::ESP8266WebServerSecure httpServer(443);
ESP8266HTTPUpdateServer httpUpdater;
ESP8266HTTPUpdateServerTemplate<BearSSL::WiFiServerSecure, BearSSL::WiFiClientSecure> httpUpdater;

static const char serverCert[] PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const char* ssid = "........";
const char* password = "........";

ESP8266WebServerSecure httpServer(443);
ESP8266HTTPUpdateServer httpUpdater;
ESP8266HTTPUpdateServerTemplate<axTLS::WiFiServerSecure, axTLS::WiFiClientSecure> httpUpdater;

// The certificate is stored in PMEM
static const uint8_t x509[] PROGMEM = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@
#include "StreamString.h"
#include "ESP8266HTTPUpdateServer.h"


static const char serverIndex[] PROGMEM =
static const char serverIndex[] =
R"(<html><body><form method='POST' action='' enctype='multipart/form-data'>
<input type='file' name='update'>
<input type='submit' value='Update'>
</form>
</body></html>)";
static const char successResponse[] PROGMEM =
static const char successResponse[] =
"<META http-equiv=\"refresh\" content=\"15;URL=/\">Update Success! Rebooting...\n";

ESP8266HTTPUpdateServer::ESP8266HTTPUpdateServer(bool serial_debug)
template <class ServerClass, class ClientClass>
ESP8266HTTPUpdateServerTemplate<ServerClass, ClientClass>::ESP8266HTTPUpdateServerTemplate(bool serial_debug)
{
_serial_output = serial_debug;
_server = NULL;
Expand All @@ -25,7 +25,8 @@ ESP8266HTTPUpdateServer::ESP8266HTTPUpdateServer(bool serial_debug)
_authenticated = false;
}

void ESP8266HTTPUpdateServer::setup(ESP8266WebServer *server, const char * path, const char * username, const char * password)
template <class ServerClass, class ClientClass>
void ESP8266HTTPUpdateServerTemplate<ServerClass, ClientClass>::setup(ESP8266WebServerTemplate<ServerClass, ClientClass> *server, const char * path, const char * username, const char * password)
{
_server = server;
_username = (char *)username;
Expand All @@ -35,18 +36,18 @@ void ESP8266HTTPUpdateServer::setup(ESP8266WebServer *server, const char * path,
_server->on(path, HTTP_GET, [&](){
if(_username != NULL && _password != NULL && !_server->authenticate(_username, _password))
return _server->requestAuthentication();
_server->send_P(200, PSTR("text/html"), serverIndex);
_server->send_P(200, ("text/html"), serverIndex);
});

// handler for the /update form POST (once file upload finishes)
_server->on(path, HTTP_POST, [&](){
if(!_authenticated)
return _server->requestAuthentication();
if (Update.hasError()) {
_server->send(200, F("text/html"), String(F("Update error: ")) + _updaterError);
_server->send(200, ("text/html"), String(("Update error: ")) + _updaterError);
} else {
_server->client().setNoDelay(true);
_server->send_P(200, PSTR("text/html"), successResponse);
_server->send_P(200, ("text/html"), successResponse);
delay(100);
_server->client().stop();
ESP.restart();
Expand Down Expand Up @@ -95,7 +96,8 @@ void ESP8266HTTPUpdateServer::setup(ESP8266WebServer *server, const char * path,
});
}

void ESP8266HTTPUpdateServer::_setUpdaterError()
template <class ServerClass, class ClientClass>
void ESP8266HTTPUpdateServerTemplate<ServerClass, ClientClass>::_setUpdaterError()
{
if (_serial_output) Update.printError(Serial);
StreamString str;
Expand Down
20 changes: 12 additions & 8 deletions libraries/ESP8266HTTPUpdateServer/src/ESP8266HTTPUpdateServer.h
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
#ifndef __HTTP_UPDATE_SERVER_H
#define __HTTP_UPDATE_SERVER_H

class ESP8266WebServer;
#include <ESP8266WebServer.h>

class ESP8266HTTPUpdateServer
template<class ServerClass, class ClientClass>
class ESP8266HTTPUpdateServerTemplate
{
public:
ESP8266HTTPUpdateServer(bool serial_debug=false);
ESP8266HTTPUpdateServerTemplate(bool serial_debug=false);

void setup(ESP8266WebServer *server)
void setup(ESP8266WebServerTemplate<ServerClass, ClientClass> *server)
{
setup(server, NULL, NULL);
}

void setup(ESP8266WebServer *server, const char * path)
void setup(ESP8266WebServerTemplate<ServerClass, ClientClass> *server, const char * path)
{
setup(server, path, NULL, NULL);
}

void setup(ESP8266WebServer *server, const char * username, const char * password)
void setup(ESP8266WebServerTemplate<ServerClass, ClientClass> *server, const char * username, const char * password)
{
setup(server, "/update", username, password);
}

void setup(ESP8266WebServer *server, const char * path, const char * username, const char * password);
void setup(ESP8266WebServerTemplate<ServerClass, ClientClass> *server, const char * path, const char * username, const char * password);

void updateCredentials(const char * username, const char * password)
{
Expand All @@ -36,12 +37,15 @@ class ESP8266HTTPUpdateServer

private:
bool _serial_output;
ESP8266WebServer *_server;
ESP8266WebServerTemplate<ServerClass, ClientClass> *_server;
char * _username;
char * _password;
bool _authenticated;
String _updaterError;
};

#include "ESP8266HTTPUpdateServer-impl.h"

typedef ESP8266HTTPUpdateServerTemplate<WiFiServer, WiFiClient> ESP8266HTTPUpdateServer;

#endif
Loading