-- Custom LWIP:(default:ON) By default we are using custom compiled LWIP stack instead of the binary one provided from Espressif. This is increasing the free memory and decreasing the space on the flash. All espconn_* functions are turned off by default. If your application requires the use of some of the espconn_* functions then add the ENABLE_ESPCONN=1 directive. See `Makefile-user.mk` from the [Basic_SmartConfig](https://github.com/SmingHub/Sming/blob/develop/samples/Basic_SmartConfig/Makefile-user.mk#L41) application for examples. If you would like to use the binary LWIP then you should turn off the custom LWIP compilation by providing ENABLE_CUSTOM_LWIP=0.
-- SSL:(default:off) The SSL support is not built-in by default to conserve resources. If you want to enable it then take a look at the [Readme](https://github.com/SmingHub/Sming/blob/develop/samples/Basic_Ssl/README.md) in the Basic_Ssl samples.
-- Custom PWM:(default:off) If you want to use the [open PWM implementation](https://github.com/StefanBruens/ESP8266_new_pwm) then compile your application with ENABLE_CUSTOM_PWM=1. There is no need to recompile the Sming library.
-- Custom serial baud rate: (default:off) The default serial baud rate is 115200. If you want to change it to a higher baud rate you can recompile Sming and your application changing the COM_SPEED_SERIAL directive. For example COM_SPEED_SERIAL=921600
-- Custom Heap Allocation:(default:off) If your application is experiencing heap fragmentation then you can try the Umm Malloc heap allocation. To enable it compile Sming with ENABLE_CUSTOM_HEAP=1. In order to use it in your sample/application make sure to compile the sample with ENABLE_CUSTOM_HEAP=1. Avoid enabling your custom heap allocation AND -mforce-l32 compiler flag.
-- Debug information log level and format: There are four debug levels: debug=3, info=2, warn=1, error=0. Using DEBUG_VERBOSE_LEVEL you can set the desired level (0-3). For example DEBUG_VERBOSE_LEVEL=2 will show only info messages and above. Another make directive is DEBUG_PRINT_FILENAME_AND_LINE=1 which enables printing the filename and line number of every debug line. This will require extra space on flash. Note: You can compile the Sming library with a set of debug directives and your project with another settings, this way you can control debugging sepparately for sming and your application code.
-- Debug information for custom LWIP: If you use custom LWIP(see above) some debug information will be printed for critical errors and situations. You can enable debug information printing altogether using ENABLE_LWIPDEBUG=1. To increase debugging for certain areas you can modify debug options in third-party/esp-open-lwip/include/lwipopts.h
-- CommandExecutor feature disabling. This feature enables execution of certain commands by registering token handlers for text received via serial, websocket or telnet connection. If this feature is not used additional RAM/Flash can be obtained by setting ENABLE_CMD_EXECUTOR=0. This will save ~1KB RAM and ~3KB of flash memory.
+
+- Custom LWIP: (default: ON) By default we are using custom compiled LWIP stack instead of the binary one provided from Espressif. This is increasing the free memory and decreasing the space on the flash. All espconn_* functions are turned off by default. If your application requires the use of some of the espconn_* functions then add the ENABLE_ESPCONN=1 directive. See `Makefile-user.mk` from the [Basic_SmartConfig](https://github.com/SmingHub/Sming/blob/develop/samples/Basic_SmartConfig/Makefile-user.mk#L41) application for examples. If you would like to use the binary LWIP then you should turn off the custom LWIP compilation by providing `ENABLE_CUSTOM_LWIP=0`.
+- SSL: (default: OFF) The SSL support is not built-in by default to conserve resources. If you want to enable it then take a look at the [Readme](https://github.com/SmingHub/Sming/blob/develop/samples/Basic_Ssl/README.md) in the Basic_Ssl samples.
+- Custom PWM: (default: OFF) If you want to use the [open PWM implementation](https://github.com/StefanBruens/ESP8266_new_pwm) then compile your application with `ENABLE_CUSTOM_PWM=1`. There is no need to recompile the Sming library.
+- Custom serial baud rate: (default: OFF) The default serial baud rate is 115200. If you want to change it to a higher baud rate you can recompile Sming and your application changing the `COM_SPEED_SERIAL` directive. For example `COM_SPEED_SERIAL=921600`.
+- Custom heap allocation: (default: OFF) If your application is experiencing heap fragmentation then you can try the [umm_malloc](https://github.com/rhempel/umm_malloc) heap allocation. To enable it compile Sming with `ENABLE_CUSTOM_HEAP=1`. In order to use it in your sample/application make sure to compile the sample with `ENABLE_CUSTOM_HEAP=1`. **Do not enable custom heap allocation and -mforce-l32 compiler flag together**.
+- Debug information log level and format: There are four debug levels: debug=3, info=2, warn=1, error=0. Using `DEBUG_VERBOSE_LEVEL` you can set the desired level (0-3). For example `DEBUG_VERBOSE_LEVEL=2` will show only info messages and above. Another make directive is `DEBUG_PRINT_FILENAME_AND_LINE=1` which enables printing the filename and line number of every debug line. This will require extra space on flash. Note: you can compile the Sming library with a set of debug directives and your project with another settings, this way you can control debugging sepparately for sming and your application code.
+- Debug information for custom LWIP: If you use custom LWIP (see above) some debug information will be printed for critical errors and situations. You can enable debug information printing altogether using `ENABLE_LWIPDEBUG=1`. To increase debugging for certain areas you can modify debug options in `third-party/esp-open-lwip/include/lwipopts.h`.
+- CommandExecutor feature: This feature enables execution of certain commands by registering token handlers for text received via serial, websocket or telnet connection. If this feature is not used additional RAM/Flash can be obtained by setting `ENABLE_CMD_EXECUTOR=0`. This will save ~1KB RAM and ~3KB of flash memory.
+
## Compilation and flashing
From bc64de4fb5aec42976a0092a1ad9ec66143c8c55 Mon Sep 17 00:00:00 2001
From: slaff
Date: Wed, 10 May 2017 10:06:14 +0200
Subject: [PATCH 06/35] HttpServer: (#1123)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Added infrastructure for body parsers.
Form-url-encoded is default body parser for HttpServer, that can be disabled with сержер configuration setting, if needed.
---
.../SmingCore/Network/Http/HttpBodyParser.cpp | 97 +++++++++++++++++++
Sming/SmingCore/Network/Http/HttpBodyParser.h | 46 +++++++++
Sming/SmingCore/Network/Http/HttpRequest.h | 2 +
.../Network/Http/HttpServerConnection.cpp | 29 +++++-
.../Network/Http/HttpServerConnection.h | 12 ++-
Sming/SmingCore/Network/HttpServer.cpp | 11 +++
Sming/SmingCore/Network/HttpServer.h | 5 +
7 files changed, 199 insertions(+), 3 deletions(-)
create mode 100644 Sming/SmingCore/Network/Http/HttpBodyParser.cpp
create mode 100644 Sming/SmingCore/Network/Http/HttpBodyParser.h
diff --git a/Sming/SmingCore/Network/Http/HttpBodyParser.cpp b/Sming/SmingCore/Network/Http/HttpBodyParser.cpp
new file mode 100644
index 0000000000..36061047a5
--- /dev/null
+++ b/Sming/SmingCore/Network/Http/HttpBodyParser.cpp
@@ -0,0 +1,97 @@
+/****
+ * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development.
+ * Created 2015 by Skurydin Alexey
+ * http://github.com/anakod/Sming
+ * All files of the Sming Core are provided under the LGPL v3 license.
+ *
+ * HttpBodyParser
+ *
+ * @author: 2017 - Slavey Karadzhov
+ *
+ ****/
+
+#include "HttpBodyParser.h"
+#include "../WebHelpers/escape.h"
+
+void formUrlParser(HttpRequest& request, const char *at, int length)
+{
+ FormUrlParserState* state = (FormUrlParserState*)request.args;
+
+ if(length == -1) {
+ if(state != NULL) {
+ delete state;
+ }
+ state = new FormUrlParserState;
+ request.args = (void *)state;
+ return;
+ }
+
+ if(length == -2) {
+ int maxLength = 0;
+ for(int i=0; isearchChar);
+ if(pos == -1) {
+ if(state->searchChar == '=') {
+ state->postName += data;
+ }
+ else {
+ request.postParams[state->postName] += data;
+ }
+
+ return;
+ }
+
+ String buf = data.substring(0, pos);
+ if(state->searchChar == '=') {
+ state->postName += buf;
+ state->searchChar = '&';
+ }
+ else {
+ request.postParams[state->postName] += buf;
+ state->searchChar = '=';
+ state->postName = "";
+ }
+
+ data = data.substring(pos + 1);
+ }
+}
diff --git a/Sming/SmingCore/Network/Http/HttpBodyParser.h b/Sming/SmingCore/Network/Http/HttpBodyParser.h
new file mode 100644
index 0000000000..98ebb881fd
--- /dev/null
+++ b/Sming/SmingCore/Network/Http/HttpBodyParser.h
@@ -0,0 +1,46 @@
+/****
+ * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development.
+ * Created 2015 by Skurydin Alexey
+ * http://github.com/anakod/Sming
+ * All files of the Sming Core are provided under the LGPL v3 license.
+ *
+ * HttpBodyParser
+ *
+ * @author: 2017 - Slavey Karadzhov
+ *
+ ****/
+
+#ifndef _SMING_CORE_HTTP_BODY_PARSER_H_
+#define _SMING_CORE_HTTP_BODY_PARSER_H_
+
+#include "HttpCommon.h"
+#include "HttpRequest.h"
+
+typedef Delegate HttpBodyParserDelegate;
+typedef HashMap BodyParsers;
+
+typedef struct {
+ char searchChar = '=';
+ String postName = "";
+} FormUrlParserState;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Parses application/x-www-form-urlencoded body data
+ * @param HttpRequest&
+ * @param const *char
+ * @param int length Negative lengths are used to specify special cases
+ * -1 - start of incoming data
+ * -2 - end of incoming data
+ */
+void formUrlParser(HttpRequest& request, const char *at, int length);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _SMING_CORE_HTTP_BODY_PARSER_H_ */
diff --git a/Sming/SmingCore/Network/Http/HttpRequest.h b/Sming/SmingCore/Network/Http/HttpRequest.h
index 32603b6faf..5f1b079697 100644
--- a/Sming/SmingCore/Network/Http/HttpRequest.h
+++ b/Sming/SmingCore/Network/Http/HttpRequest.h
@@ -133,6 +133,8 @@ class HttpRequest {
int retries = 0; // how many times the request should be send again...
+ void *args = NULL; // Used to store data that should be valid during a single request
+
protected:
RequestHeadersCompletedDelegate headersCompletedDelegate;
RequestBodyDelegate requestBodyDelegate;
diff --git a/Sming/SmingCore/Network/Http/HttpServerConnection.cpp b/Sming/SmingCore/Network/Http/HttpServerConnection.cpp
index 1cd4b51e4a..04447b6342 100644
--- a/Sming/SmingCore/Network/Http/HttpServerConnection.cpp
+++ b/Sming/SmingCore/Network/Http/HttpServerConnection.cpp
@@ -3,6 +3,11 @@
* Created 2015 by Skurydin Alexey
* http://github.com/anakod/Sming
* All files of the Sming Core are provided under the LGPL v3 license.
+ *
+ * HttpServerConnection
+ *
+ * Modified: 2017 - Slavey Karadzhov
+ *
****/
#include "HttpServerConnection.h"
@@ -36,10 +41,16 @@ HttpServerConnection::~HttpServerConnection()
{
}
-void HttpServerConnection::setResourceTree(ResourceTree* resourceTree) {
+void HttpServerConnection::setResourceTree(ResourceTree* resourceTree)
+{
this->resourceTree = resourceTree;
}
+void HttpServerConnection::setBodyParsers(BodyParsers* bodyParsers)
+{
+ this->bodyParsers = bodyParsers;
+}
+
int HttpServerConnection::staticOnMessageBegin(http_parser* parser)
{
HttpServerConnection *connection = (HttpServerConnection*)parser->data;
@@ -65,6 +76,7 @@ int HttpServerConnection::staticOnMessageBegin(http_parser* parser)
// and temp data...
connection->requestHeaders.clear();
+ connection->bodyParser = 0;
return 0;
}
@@ -116,6 +128,10 @@ int HttpServerConnection::staticOnMessageComplete(http_parser* parser)
return 0;
}
+ if(connection->bodyParser) {
+ connection->bodyParser(connection->request, NULL, -2);
+ }
+
if(connection->resource != NULL && connection->resource->onRequestComplete) {
hasError = connection->resource->onRequestComplete(*connection, connection->request, connection->response);
}
@@ -165,6 +181,13 @@ int HttpServerConnection::staticOnHeadersComplete(http_parser* parser)
error = 1;
}
+ if(connection->request.headers.contains("Content-Type")) {
+ if(connection->bodyParsers->contains(connection->request.headers["Content-Type"])) {
+ connection->bodyParser = (*connection->bodyParsers)[connection->request.headers["Content-Type"]];
+ connection->bodyParser(connection->request, NULL, -1);
+ }
+ }
+
return error;
}
@@ -212,6 +235,10 @@ int HttpServerConnection::staticOnBody(http_parser *parser, const char *at, size
return -1;
}
+ if(connection->bodyParser) {
+ connection->bodyParser(connection->request, at, length);
+ }
+
if(connection->resource != NULL && connection->resource->onBody) {
return connection->resource->onBody(*connection, connection->request, at, length);
}
diff --git a/Sming/SmingCore/Network/Http/HttpServerConnection.h b/Sming/SmingCore/Network/Http/HttpServerConnection.h
index c84fcfdd6f..639edb9a70 100644
--- a/Sming/SmingCore/Network/Http/HttpServerConnection.h
+++ b/Sming/SmingCore/Network/Http/HttpServerConnection.h
@@ -3,6 +3,11 @@
* Created 2015 by Skurydin Alexey
* http://github.com/anakod/Sming
* All files of the Sming Core are provided under the LGPL v3 license.
+ *
+ * HttpServerConnection
+ *
+ * Modified: 2017 - Slavey Karadzhov
+ *
****/
#ifndef _SMING_CORE_HTTPSERVERCONNECTION_H_
@@ -15,6 +20,7 @@
#include "HttpResource.h"
#include "HttpRequest.h"
+#include "HttpBodyParser.h"
#ifndef HTTP_SERVER_EXPOSE_NAME
#define HTTP_SERVER_EXPOSE_NAME 1
@@ -42,13 +48,12 @@ class HttpServerConnection: public TcpClient
virtual ~HttpServerConnection();
void setResourceTree(ResourceTree* resourceTree);
+ void setBodyParsers(BodyParsers* bodyParsers);
void send();
using TcpClient::send;
-// virtual void close();
-
protected:
virtual err_t onReceive(pbuf *buf);
virtual void onReadyToSendData(TcpConnectionEvent sourceEvent);
@@ -91,6 +96,9 @@ class HttpServerConnection: public TcpClient
bool lastWasValue = true;
String lastData = "";
String currentField = "";
+
+ BodyParsers* bodyParsers;
+ HttpBodyParserDelegate bodyParser;
};
#endif /* _SMING_CORE_HTTPSERVERCONNECTION_H_ */
diff --git a/Sming/SmingCore/Network/HttpServer.cpp b/Sming/SmingCore/Network/HttpServer.cpp
index 6df1a6bec0..7e6b2a6ed5 100644
--- a/Sming/SmingCore/Network/HttpServer.cpp
+++ b/Sming/SmingCore/Network/HttpServer.cpp
@@ -31,6 +31,11 @@ void HttpServer::configure(HttpServerSettings settings) {
if(settings.minHeapSize != -1 && settings.minHeapSize > -1) {
minHeapSize = settings.minHeapSize;
}
+
+ if(settings.useDefaultBodyParsers) {
+ setBodyParser(ContentType::toString(MIME_FORM_URL_ENCODED), formUrlParser);
+ }
+
setTimeOut(settings.keepAliveSeconds);
#ifdef ENABLE_SSL
sslSessionCacheSize = settings.sslSessionCacheSize;
@@ -46,10 +51,16 @@ HttpServer::~HttpServer()
}
}
+void HttpServer::setBodyParser(const String& contentType, HttpBodyParserDelegate parser)
+{
+ bodyParsers[contentType] = parser;
+}
+
TcpConnection* HttpServer::createClient(tcp_pcb *clientTcp)
{
HttpServerConnection* con = new HttpServerConnection(clientTcp);
con->setResourceTree(&resourceTree);
+ con->setBodyParsers(&bodyParsers);
con->setCompleteDelegate(TcpClientCompleteDelegate(&HttpServer::onConnectionClose, this));
totalConnections++;
diff --git a/Sming/SmingCore/Network/HttpServer.h b/Sming/SmingCore/Network/HttpServer.h
index 56d77dfac1..573a1cc081 100644
--- a/Sming/SmingCore/Network/HttpServer.h
+++ b/Sming/SmingCore/Network/HttpServer.h
@@ -21,12 +21,14 @@
#include "Http/HttpRequest.h"
#include "Http/HttpResource.h"
#include "Http/HttpServerConnection.h"
+#include "Http/HttpBodyParser.h"
typedef struct {
int maxActiveConnections = 10; // << the maximum number of concurrent requests..
int keepAliveSeconds = 5; // << the default seconds to keep the connection alive before closing it
int minHeapSize = -1; // << defines the min heap size that is required to accept connection.
// -1 - means use server default
+ bool useDefaultBodyParsers = 1; // << if the default body parsers, as form-url-encoded, should be used
#ifdef ENABLE_SSL
int sslSessionCacheSize = 10; // << number of SSL session ids to cache. Setting this to 0 will disable SSL session resumption.
#endif
@@ -46,6 +48,8 @@ class HttpServer: public TcpServer
*/
void configure(HttpServerSettings settings);
+ void setBodyParser(const String& contentType, HttpBodyParserDelegate parser);
+
/**
* @param String path URL path.
* @note Path should start with slash. Trailing slashes will be removed.
@@ -71,6 +75,7 @@ class HttpServer: public TcpServer
private:
HttpServerSettings settings;
ResourceTree resourceTree;
+ BodyParsers bodyParsers;
};
#endif /* _SMING_CORE_HTTPSERVER_H_ */
From 277c716fb67c95e37f11d324129a0c58ac3be198 Mon Sep 17 00:00:00 2001
From: slaff
Date: Wed, 17 May 2017 15:31:29 +0200
Subject: [PATCH 07/35] HttpServer: extract the actual content-type value.
(#1129)
---
Sming/SmingCore/Network/Http/HttpServerConnection.cpp | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/Sming/SmingCore/Network/Http/HttpServerConnection.cpp b/Sming/SmingCore/Network/Http/HttpServerConnection.cpp
index 04447b6342..486bdb7154 100644
--- a/Sming/SmingCore/Network/Http/HttpServerConnection.cpp
+++ b/Sming/SmingCore/Network/Http/HttpServerConnection.cpp
@@ -182,8 +182,14 @@ int HttpServerConnection::staticOnHeadersComplete(http_parser* parser)
}
if(connection->request.headers.contains("Content-Type")) {
- if(connection->bodyParsers->contains(connection->request.headers["Content-Type"])) {
- connection->bodyParser = (*connection->bodyParsers)[connection->request.headers["Content-Type"]];
+ String contentType = connection->request.headers["Content-Type"];
+ int endPos = contentType.indexOf(';');
+ if(endPos != -1) {
+ contentType = contentType.substring(0, endPos);
+ }
+
+ if(connection->bodyParsers->contains(contentType)) {
+ connection->bodyParser = (*connection->bodyParsers)[contentType];
connection->bodyParser(connection->request, NULL, -1);
}
}
From 1168f8dd86f810feadb2f348352f8e9f0250865f Mon Sep 17 00:00:00 2001
From: slaff
Date: Thu, 1 Jun 2017 12:01:16 +0400
Subject: [PATCH 08/35] Ported support for C++11 iterators. (#1141)
See https://github.com/esp8266/Arduino/pull/2267.
---
Sming/Wiring/WString.h | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/Sming/Wiring/WString.h b/Sming/Wiring/WString.h
index f9e26b68b8..00364b068f 100644
--- a/Sming/Wiring/WString.h
+++ b/Sming/Wiring/WString.h
@@ -215,7 +215,11 @@ class String
{
getBytes((unsigned char *)buf, bufsize, index);
}
- const char * c_str() const { return buffer; }
+ const char* c_str() const { return buffer; }
+ char* begin() { return buffer; }
+ char* end() { return buffer + length(); }
+ const char* begin() const { return c_str(); }
+ const char* end() const { return c_str() + length(); }
// search
int IRAM_ATTR indexOf(char ch) const;
From fd7a20d88ceb7850980988f819b2975414d9b85b Mon Sep 17 00:00:00 2001
From: slaff
Date: Thu, 1 Jun 2017 18:06:59 +0400
Subject: [PATCH 09/35] Detect division by zero. (#1142)
See https://github.com/esp8266/Arduino/pull/2397 for details.
---
Sming/Wiring/WMath.cpp | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/Sming/Wiring/WMath.cpp b/Sming/Wiring/WMath.cpp
index 65ff351ec3..6dfd927480 100644
--- a/Sming/Wiring/WMath.cpp
+++ b/Sming/Wiring/WMath.cpp
@@ -79,9 +79,12 @@ long random(long howsmall, long howbig)
}
-long map(long x, long in_min, long in_max, long out_min, long out_max)
-{
- return (x - in_min) * (out_max - out_min + 1) / (in_max - in_min + 1) + out_min;
+long map(long x, long in_min, long in_max, long out_min, long out_max) {
+ long divisor = (in_max - in_min) + out_min;
+ if(divisor == 0){
+ return -1; //AVR returns -1, SAM returns 0
+ }
+ return (x - in_min) * (out_max - out_min) / divisor;
}
From bfccdd2991b60b117c31092e2974e9773f5b5366 Mon Sep 17 00:00:00 2001
From: slaff
Date: Tue, 13 Jun 2017 09:12:36 +0200
Subject: [PATCH 10/35] Fix/memory related (#1143)
* Prevent memory fragmentation when a lot of data is transferred.
* Fix for possible memory leaks.
* Fixed memory leak in TcpServer in SSL mode.
---
.../SmingCore/Network/FTPServerConnection.cpp | 3 +--
Sming/SmingCore/Network/TcpConnection.cpp | 19 +++++++++++++------
Sming/SmingCore/Network/TcpServer.cpp | 1 +
3 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/Sming/SmingCore/Network/FTPServerConnection.cpp b/Sming/SmingCore/Network/FTPServerConnection.cpp
index bdb715e105..492557a25a 100644
--- a/Sming/SmingCore/Network/FTPServerConnection.cpp
+++ b/Sming/SmingCore/Network/FTPServerConnection.cpp
@@ -77,10 +77,9 @@ class FTPDataRetrieve : public FTPDataStream
virtual void transferData(TcpConnectionEvent sourceEvent)
{
if (completed) return;
- char * buf = new char [1024];
+ char buf[1024];
int len = fileRead(file, buf, 1024);
write(buf, len, TCP_WRITE_FLAG_COPY);
- delete buf;
if (fileIsEOF(file))
{
completed = true;
diff --git a/Sming/SmingCore/Network/TcpConnection.cpp b/Sming/SmingCore/Network/TcpConnection.cpp
index 0e0f304292..bb4a24e943 100644
--- a/Sming/SmingCore/Network/TcpConnection.cpp
+++ b/Sming/SmingCore/Network/TcpConnection.cpp
@@ -51,13 +51,15 @@ bool TcpConnection::connect(String server, int port, bool useSsl /* = false */,
#ifdef ENABLE_SSL
this->sslOptions |= sslOptions;
- if(ssl_ext == NULL) {
- ssl_ext = ssl_ext_new();
- ssl_ext->host_name = (char *)malloc(server.length() + 1);
- strcpy(ssl_ext->host_name, server.c_str());
-
- ssl_ext->max_fragment_size = 4*1024; // 4K max size
+ if(ssl_ext != NULL) {
+ ssl_ext_free(ssl_ext);
}
+
+ ssl_ext = ssl_ext_new();
+ ssl_ext->host_name = (char *)malloc(server.length() + 1);
+ strcpy(ssl_ext->host_name, server.c_str());
+
+ ssl_ext->max_fragment_size = 4*1024; // 4K max size
#endif
debugf("connect to: %s", server.c_str());
@@ -405,6 +407,11 @@ err_t TcpConnection::staticOnConnected(void *arg, tcp_pcb *tcp, err_t err)
System.setCpuFrequency(eCF_160MHz); // For shorter waiting time, more power consumption.
#endif
debugf("SSL: handshake start (%d ms)", millis());
+
+ if(con->ssl != NULL) {
+ ssl_free(con->ssl);
+ }
+
con->sslContext = ssl_ctx_new(SSL_CONNECT_IN_PARTS | sslOptions, 1);
if (con->clientKeyCert.keyLength && con->clientKeyCert.certificateLength) {
diff --git a/Sming/SmingCore/Network/TcpServer.cpp b/Sming/SmingCore/Network/TcpServer.cpp
index 3566455811..828d725563 100644
--- a/Sming/SmingCore/Network/TcpServer.cpp
+++ b/Sming/SmingCore/Network/TcpServer.cpp
@@ -166,6 +166,7 @@ err_t TcpServer::onAccept(tcp_pcb *clientTcp, err_t err)
if(useSsl) {
int clientfd = axl_append(clientTcp);
if(clientfd == -1) {
+ delete client;
debugf("SSL: Unable to initiate tcp ");
return ERR_ABRT;
}
From a41edb7f50e203029c0053ccfea627184e835c1f Mon Sep 17 00:00:00 2001
From: slaff
Date: Tue, 13 Jun 2017 17:28:58 +0200
Subject: [PATCH 11/35] Changed the httpclient sample callbacks to return 0 on
success. (#1156)
---
samples/Basic_Ssl/app/application.cpp | 2 ++
samples/Basic_WebClient/app/application.cpp | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/samples/Basic_Ssl/app/application.cpp b/samples/Basic_Ssl/app/application.cpp
index 21bead78b8..378195ab17 100644
--- a/samples/Basic_Ssl/app/application.cpp
+++ b/samples/Basic_Ssl/app/application.cpp
@@ -86,6 +86,8 @@ int onDownload(HttpConnection& connection, bool success)
displayCipher(ssl);
displaySessionId(ssl);
}
+
+ return 0; // return 0 on success in your callbacks
}
void gotIP(IPAddress ip, IPAddress netmask, IPAddress gateway)
diff --git a/samples/Basic_WebClient/app/application.cpp b/samples/Basic_WebClient/app/application.cpp
index dbb20c6722..e501b59fc2 100644
--- a/samples/Basic_WebClient/app/application.cpp
+++ b/samples/Basic_WebClient/app/application.cpp
@@ -89,7 +89,7 @@ int onDownload(HttpConnection& connection, bool success)
displaySessionId(ssl);
}
- return 1;
+ return 0; // return 0 on success in your callbacks
}
void connectOk(IPAddress ip, IPAddress mask, IPAddress gateway)
From d6a1aaf4c95bbae0773aec7aca06c2d7d50acbb1 Mon Sep 17 00:00:00 2001
From: it-guru
Date: Wed, 14 Jun 2017 08:31:13 +0200
Subject: [PATCH 12/35] add Timer::tick() for better class derivation from
Timer class (#1135)
---
Sming/SmingCore/Timer.cpp | 29 ++++++++++++++++++-----------
Sming/SmingCore/Timer.h | 9 ++++++++-
2 files changed, 26 insertions(+), 12 deletions(-)
diff --git a/Sming/SmingCore/Timer.cpp b/Sming/SmingCore/Timer.cpp
index 85bb0fc75b..2e6ac3690b 100644
--- a/Sming/SmingCore/Timer.cpp
+++ b/Sming/SmingCore/Timer.cpp
@@ -48,8 +48,7 @@ void Timer::start(bool repeating/* = true*/)
{
this->repeating = repeating;
stop();
- if(interval == 0 || (!callback && !delegate_func))
- return;
+ if (interval == 0) return;
ets_timer_setfn(&timer, (os_timer_func_t *)processing, this);
if (interval > 10000)
@@ -182,15 +181,23 @@ void Timer::processing(void *arg)
ptimer->stop();
}
}
-
- if (ptimer->callback)
- {
- ptimer->callback();
- }
- else if (ptimer->delegate_func)
- {
- ptimer->delegate_func();
- }
+ ptimer->tick();
}
}
+
+
+void Timer::tick()
+{
+ if (callback)
+ {
+ callback();
+ }
+ else if (delegate_func)
+ {
+ delegate_func();
+ }
+ else{
+ stop();
+ }
+}
diff --git a/Sming/SmingCore/Timer.h b/Sming/SmingCore/Timer.h
index bf80996540..247c5ef6cb 100644
--- a/Sming/SmingCore/Timer.h
+++ b/Sming/SmingCore/Timer.h
@@ -126,11 +126,16 @@ class Timer
*/
void IRAM_ATTR setCallback(TimerDelegate delegateFunction);
- /** @} */
protected:
static void IRAM_ATTR processing(void *arg);
+ /** @brief virtual timer loop() method
+ * @note Can be override in class derivations. If overwriten,
+ * no classic other callbacks are working.
+ */
+ virtual void tick();
+ /** @} */
private:
os_timer_t timer;
@@ -144,6 +149,8 @@ class Timer
// was added to allow for longer timer intervals.
uint16_t long_intvl_cntr = 0;
uint16_t long_intvl_cntr_lim = 0;
+
+
};
#endif /* _SMING_CORE_Timer_H_ */
From 507410d47968719482ff2a42d7d5c4605f21ad82 Mon Sep 17 00:00:00 2001
From: slaff
Date: Wed, 14 Jun 2017 13:25:18 +0200
Subject: [PATCH 13/35] Changed the delay function to call wdt_reset for
intervals that are bigger than the max-safe-delay period. (#1154)
---
Sming/SmingCore/Clock.cpp | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/Sming/SmingCore/Clock.cpp b/Sming/SmingCore/Clock.cpp
index 77b5b9e90d..d9af135bc2 100644
--- a/Sming/SmingCore/Clock.cpp
+++ b/Sming/SmingCore/Clock.cpp
@@ -8,6 +8,8 @@
#include "../SmingCore/Clock.h"
#include "../Wiring/WiringFrameworkIncludes.h"
+#define MAX_SAFE_DELAY 1000
+
unsigned long millis(void)
{
return system_get_time() / 1000UL;
@@ -20,7 +22,18 @@ unsigned long micros(void)
void delay(uint32_t time)
{
- os_delay_us(time * 1000);
+ int quotient = time / MAX_SAFE_DELAY;
+ int remainder = time % MAX_SAFE_DELAY;
+ for(int i=0, max = quotient + 1; i < max ; i++) {
+ if(i == quotient) {
+ os_delay_us(remainder * 1000);
+ }
+ else {
+ os_delay_us(MAX_SAFE_DELAY * 1000);
+ }
+
+ system_soft_wdt_feed ();
+ }
}
void delayMicroseconds(uint32_t time)
From e4ee2b3d4b40bc60f9add12d4224c525a0d31497 Mon Sep 17 00:00:00 2001
From: Jarek Zgoda
Date: Wed, 14 Jun 2017 14:55:19 +0200
Subject: [PATCH 14/35] Cleaned up Nokia 5110 LCD sample code (#1091)
---
samples/ScreenLCD_5110/app/application.cpp | 54 +++++++++-------------
1 file changed, 22 insertions(+), 32 deletions(-)
diff --git a/samples/ScreenLCD_5110/app/application.cpp b/samples/ScreenLCD_5110/app/application.cpp
index 39518c7fa7..5a965f82d5 100644
--- a/samples/ScreenLCD_5110/app/application.cpp
+++ b/samples/ScreenLCD_5110/app/application.cpp
@@ -2,43 +2,33 @@
#include
#include
-// Software SPI (slower updates, more flexible pin options):
- // pin 7 - Serial clock out (SCLK)
- // pin 6 - Serial data out (DIN)
- // pin 5 - Data/Command select (D/C)
- // pin 4 - LCD chip select (CS)
- // pin 3 - LCD reset (RST)
-Adafruit_PCD8544 display = Adafruit_PCD8544(14, 13, 12, 5, 4);
+// GPIO13/D7 - Serial clock out (SCLK)
+// GPIO12/D6 - Serial data out (DIN)
+// GPIO14/D5 - Data/Command select (D/C)
+// GPIO5/D1 - LCD chip select (CS)
+// GPIO4/D2 - LCD reset (RST)
+Adafruit_PCD8544 display = Adafruit_PCD8544(13, 12, 14, 5, 4);
+
+
void displayTest()
{
display.begin();
- // init done
-
- // you can change the contrast around to adapt the display
- // for the best viewing!
- display.setContrast(10);
-
- display.display(); // show splashscreen
- delay(200);
- display.clearDisplay(); // clears the screen and buffer
-
- display.setRotation(4); // rotate 90 degrees counter clockwise, can also use values of 2 and 3 to go further.
- display.setTextSize(1);
- display.setTextColor(BLACK);
- display.setCursor(0,0);
- display.println("Sming");
- display.setTextSize(2);
- display.println("Example!");
- display.display();
+ display.setContrast(10);
+ display.display(); // show splashscreen
+ delay(2000);
+ display.clearDisplay(); // no changes will be visible until display() is called
+ display.setRotation(4); // rotate 90 degrees counter clockwise, can also use values of 2 and 3 to go further.
+ display.setTextSize(1);
+ display.setTextColor(BLACK);
+ display.setCursor(0, 0);
+ display.println("Sming");
+ display.setTextSize(2);
+ display.println("Example");
+ display.display();
}
+
void init()
{
- Serial.begin(SERIAL_BAUD_RATE); // 115200 by default
- Serial.systemDebugOutput(true); // Enable debug output to serial
-
- WifiStation.enable(false);
- WifiAccessPoint.enable(true);
-
+ Serial.begin(SERIAL_BAUD_RATE);
displayTest();
}
-
From 68c0df1330b1db11144c7fe9747158e40e494bc9 Mon Sep 17 00:00:00 2001
From: slaff
Date: Mon, 19 Jun 2017 09:07:23 +0200
Subject: [PATCH 15/35] WsConnection: declared broadcast as static so that it
can be called anywhere in the application. (#1160)
---
Sming/SmingCore/Network/Http/Websocket/WebSocketConnection.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Sming/SmingCore/Network/Http/Websocket/WebSocketConnection.h b/Sming/SmingCore/Network/Http/Websocket/WebSocketConnection.h
index e564bc7d08..0412fb3140 100644
--- a/Sming/SmingCore/Network/Http/Websocket/WebSocketConnection.h
+++ b/Sming/SmingCore/Network/Http/Websocket/WebSocketConnection.h
@@ -39,7 +39,7 @@ class WebSocketConnection
bool initialize(HttpRequest &request, HttpResponse &response);
virtual void send(const char* message, int length, wsFrameType type = WS_TEXT_FRAME);
- void broadcast(const char* message, int length, wsFrameType type = WS_TEXT_FRAME);
+ static void broadcast(const char* message, int length, wsFrameType type = WS_TEXT_FRAME);
void sendString(const String& message);
void sendBinary(const uint8_t* data, int size);
From f6c1199e3ff238e709ad60911b0d43fb55b7fe6d Mon Sep 17 00:00:00 2001
From: slaff
Date: Mon, 19 Jun 2017 09:20:28 +0200
Subject: [PATCH 16/35] HttpClient: memory usage fixes. (#1161)
Related to #1138.
---
.../SmingCore/Network/Http/HttpConnection.cpp | 63 +++++++++----------
Sming/SmingCore/Network/Http/HttpConnection.h | 2 +-
Sming/SmingCore/Network/HttpClient.cpp | 3 +
Sming/SmingCore/Network/HttpClient.h | 10 +++
4 files changed, 43 insertions(+), 35 deletions(-)
diff --git a/Sming/SmingCore/Network/Http/HttpConnection.cpp b/Sming/SmingCore/Network/Http/HttpConnection.cpp
index 8ef0b7463f..079ec22f7d 100644
--- a/Sming/SmingCore/Network/Http/HttpConnection.cpp
+++ b/Sming/SmingCore/Network/Http/HttpConnection.cpp
@@ -22,6 +22,26 @@
HttpConnection::HttpConnection(RequestQueue* queue): TcpClient(false), mode(eHCM_String) {
this->waitingQueue = queue;
+
+ http_parser_init(&parser, HTTP_RESPONSE);
+ parser.data = (void*)this;
+
+ memset(&parserSettings, 0, sizeof(parserSettings));
+
+ // Notification callbacks: on_message_begin, on_headers_complete, on_message_complete.
+ parserSettings.on_message_begin = staticOnMessageBegin;
+ parserSettings.on_headers_complete = staticOnHeadersComplete;
+ parserSettings.on_message_complete = staticOnMessageComplete;
+
+ parserSettings.on_chunk_header = staticOnChunkHeader;
+ parserSettings.on_chunk_complete = staticOnChunkComplete;
+
+
+ // Data callbacks: on_url, (common) on_header_field, on_header_value, on_body;
+ parserSettings.on_status = staticOnStatus;
+ parserSettings.on_header_field = staticOnHeaderField;
+ parserSettings.on_header_value = staticOnHeaderValue;
+ parserSettings.on_body = staticOnBody;
}
bool HttpConnection::connect(const String& host, int port, bool useSsl /* = false */, uint32_t sslOptions /* = 0 */) {
@@ -112,7 +132,9 @@ void HttpConnection::reset()
}
code = 0;
- responseStringData = "";
+ if(responseStringData.length()) {
+ responseStringData = "";
+ }
responseHeaders.clear();
lastWasValue = true;
@@ -324,34 +346,12 @@ int HttpConnection::staticOnChunkComplete(http_parser* parser) {
err_t HttpConnection::onConnected(err_t err) {
if (err == ERR_OK) {
- // create parser ...
- if(parser == NULL) {
- parser = new http_parser;
- http_parser_init(parser, HTTP_RESPONSE);
- parser->data = (void*)this;
-
- memset(&parserSettings, 0, sizeof(parserSettings));
- // Notification callbacks: on_message_begin, on_headers_complete, on_message_complete.
- parserSettings.on_message_begin = staticOnMessageBegin;
- parserSettings.on_headers_complete = staticOnHeadersComplete;
- parserSettings.on_message_complete = staticOnMessageComplete;
-
- parserSettings.on_chunk_header = staticOnChunkHeader;
- parserSettings.on_chunk_complete = staticOnChunkComplete;
-
-
- // Data callbacks: on_url, (common) on_header_field, on_header_value, on_body;
- parserSettings.on_status = staticOnStatus;
- parserSettings.on_header_field = staticOnHeaderField;
- parserSettings.on_header_value = staticOnHeaderValue;
- parserSettings.on_body = staticOnBody;
- }
-
debugf("HttpConnection::onConnected: waitingQueue.count: %d", waitingQueue->count());
do {
HttpRequest* request = waitingQueue->peek();
if(request == NULL) {
+ debugf("Nothing in the waiting queue");
break;
}
@@ -511,10 +511,10 @@ err_t HttpConnection::onReceive(pbuf *buf) {
pbuf *cur = buf;
int parsedBytes = 0;
while (cur != NULL && cur->len > 0) {
- parsedBytes += http_parser_execute(parser, &parserSettings, (char*) cur->payload, cur->len);
- if(HTTP_PARSER_ERRNO(parser) != HPE_OK) {
+ parsedBytes += http_parser_execute(&parser, &parserSettings, (char*) cur->payload, cur->len);
+ if(HTTP_PARSER_ERRNO(&parser) != HPE_OK) {
// we ran into trouble - abort the connection
- debugf("HTTP parser error: %s", http_errno_name(HTTP_PARSER_ERRNO(parser)));
+ debugf("HTTP parser error: %s", http_errno_name(HTTP_PARSER_ERRNO(&parser)));
cleanup();
TcpConnection::onReceive(NULL);
return ERR_ABRT;
@@ -523,8 +523,8 @@ err_t HttpConnection::onReceive(pbuf *buf) {
cur = cur->next;
}
- if (parser->upgrade) {
- return onProtocolUpgrade(parser);
+ if (parser.upgrade) {
+ return onProtocolUpgrade(&parser);
} else if (parsedBytes != buf->tot_len) {
TcpClient::onReceive(NULL);
@@ -552,11 +552,6 @@ void HttpConnection::cleanup() {
for(int i=0; i < executionQueue.count(); i++) {
waitingQueue->enqueue(executionQueue.dequeue());
}
-
- if(parser != NULL) {
- delete parser;
- parser = NULL;
- }
}
HttpConnection::~HttpConnection() {
diff --git a/Sming/SmingCore/Network/Http/HttpConnection.h b/Sming/SmingCore/Network/Http/HttpConnection.h
index 99c29b85b5..15147c7815 100644
--- a/Sming/SmingCore/Network/Http/HttpConnection.h
+++ b/Sming/SmingCore/Network/Http/HttpConnection.h
@@ -104,7 +104,7 @@ class HttpConnection : protected TcpClient {
RequestQueue* waitingQueue;
RequestQueue executionQueue;
- http_parser *parser = NULL;
+ http_parser parser;
http_parser_settings parserSettings;
HttpHeaders responseHeaders;
diff --git a/Sming/SmingCore/Network/HttpClient.cpp b/Sming/SmingCore/Network/HttpClient.cpp
index f1bc0ba84a..0ef64dc0de 100644
--- a/Sming/SmingCore/Network/HttpClient.cpp
+++ b/Sming/SmingCore/Network/HttpClient.cpp
@@ -24,6 +24,7 @@ bool HttpClient::send(HttpRequest* request) {
if(!queue[cacheKey]->enqueue(request)) {
// the queue is full and we cannot add more requests at the time.
debugf("The request queue is full at the moment");
+ delete request;
return false;
}
@@ -34,6 +35,8 @@ bool HttpClient::send(HttpRequest* request) {
debugf("Removing stale connection: State: %d, Active: %d", (int)httpConnectionPool[cacheKey]->getConnectionState(),
(httpConnectionPool[cacheKey]->isActive() ? 1: 0));
+ delete httpConnectionPool[cacheKey];
+ httpConnectionPool[cacheKey] = NULL;
httpConnectionPool.remove(cacheKey);
}
diff --git a/Sming/SmingCore/Network/HttpClient.h b/Sming/SmingCore/Network/HttpClient.h
index 173bc97c5d..da1bd1fedd 100644
--- a/Sming/SmingCore/Network/HttpClient.h
+++ b/Sming/SmingCore/Network/HttpClient.h
@@ -57,7 +57,17 @@ class HttpClient
bool downloadFile(const String& url, const String& saveFileName, RequestCompletedDelegate requestComplete = NULL);
/* Low Level Methods */
+
+ /*
+ * @brief This method queues a request and sends it, once it is connected to the remote server.
+ * @param HttpRequest* request The request object will be freed inside of the method.
+ * Do not try to reuse it outside of the send method as it will lead to unpredicted results
+ *
+ * @retval bool true if the request was queued, false otherwise.
+ *
+ */
bool send(HttpRequest* request);
+
HttpRequest* request(const String& url);
#ifdef ENABLE_SSL
From d44599d78aafac7cc7f490467bb60a269362a365 Mon Sep 17 00:00:00 2001
From: Slavey Karadzhov
Date: Tue, 20 Jun 2017 10:03:00 +0200
Subject: [PATCH 17/35] TemplateStream: the total length should be calculated
from the browser. HttpServer: The default keepalive time is set to 0.
---
Sming/SmingCore/DataSourceStream.h | 6 ++++++
Sming/SmingCore/Network/HttpServer.cpp | 2 +-
Sming/SmingCore/Network/HttpServer.h | 2 +-
3 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/Sming/SmingCore/DataSourceStream.h b/Sming/SmingCore/DataSourceStream.h
index 862b36f51f..91466b99fe 100644
--- a/Sming/SmingCore/DataSourceStream.h
+++ b/Sming/SmingCore/DataSourceStream.h
@@ -244,6 +244,12 @@ class TemplateFileStream : public FileStream
*/
inline TemplateVariables& variables() { return templateData; }
+ /**
+ * @brief Return the total length of the stream
+ * @retval int -1 is returned when the size cannot be determined
+ */
+ int length() { return -1; }
+
private:
TemplateVariables templateData;
TemplateExpandState state;
diff --git a/Sming/SmingCore/Network/HttpServer.cpp b/Sming/SmingCore/Network/HttpServer.cpp
index 7e6b2a6ed5..fa2e2b8ae5 100644
--- a/Sming/SmingCore/Network/HttpServer.cpp
+++ b/Sming/SmingCore/Network/HttpServer.cpp
@@ -17,7 +17,7 @@
HttpServer::HttpServer()
{
- settings.keepAliveSeconds = 10;
+ settings.keepAliveSeconds = 0;
configure(settings);
}
diff --git a/Sming/SmingCore/Network/HttpServer.h b/Sming/SmingCore/Network/HttpServer.h
index 573a1cc081..85b8b0516c 100644
--- a/Sming/SmingCore/Network/HttpServer.h
+++ b/Sming/SmingCore/Network/HttpServer.h
@@ -25,7 +25,7 @@
typedef struct {
int maxActiveConnections = 10; // << the maximum number of concurrent requests..
- int keepAliveSeconds = 5; // << the default seconds to keep the connection alive before closing it
+ int keepAliveSeconds = 0; // << the default seconds to keep the connection alive before closing it
int minHeapSize = -1; // << defines the min heap size that is required to accept connection.
// -1 - means use server default
bool useDefaultBodyParsers = 1; // << if the default body parsers, as form-url-encoded, should be used
From d870c27c6edd225381829f4ee0a0edf1816ac92b Mon Sep 17 00:00:00 2001
From: slaff
Date: Wed, 21 Jun 2017 09:28:27 +0200
Subject: [PATCH 18/35] Custom PWM is enabled by default. (#1164)
---
Sming/Makefile | 3 ++-
Sming/Makefile-project.mk | 3 ++-
Sming/Makefile-rboot.mk | 3 ++-
3 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/Sming/Makefile b/Sming/Makefile
index 4fbf170496..49fbf68dfa 100644
--- a/Sming/Makefile
+++ b/Sming/Makefile
@@ -215,7 +215,8 @@ endif
# libraries used in this project, mainly provided by the SDK
LIBS = microc microgcc hal phy pp net80211 $(LIBLWIP) wpa main
-# WARNING: In the next versions ENABLE_CUSTOM_PWM will be set to 1 by default
+
+ENABLE_CUSTOM_PWM ?= 1
ifeq ($(ENABLE_CUSTOM_PWM), 1)
THIRD_PARTY_DATA += third-party/pwm/pwm.c
endif
diff --git a/Sming/Makefile-project.mk b/Sming/Makefile-project.mk
index 371156d4e0..03e7b76c53 100644
--- a/Sming/Makefile-project.mk
+++ b/Sming/Makefile-project.mk
@@ -196,7 +196,8 @@ ifeq ($(ENABLE_CUSTOM_LWIP), 1)
endif
LIBPWM = pwm
-# WARNING: In the next versions ENABLE_CUSTOM_PWM will be set to 1 by default
+
+ENABLE_CUSTOM_PWM ?= 1
ifeq ($(ENABLE_CUSTOM_PWM), 1)
LIBPWM = pwm_open
CUSTOM_TARGETS += $(USER_LIBDIR)/lib$(LIBPWM).a
diff --git a/Sming/Makefile-rboot.mk b/Sming/Makefile-rboot.mk
index 3c1c2d64e8..b26f761668 100644
--- a/Sming/Makefile-rboot.mk
+++ b/Sming/Makefile-rboot.mk
@@ -244,7 +244,8 @@ ifeq ($(ENABLE_CUSTOM_LWIP), 1)
endif
LIBPWM = pwm
-# WARNING: In the next versions ENABLE_CUSTOM_PWM will be set to 1 by default
+
+ENABLE_CUSTOM_PWM ?= 1
ifeq ($(ENABLE_CUSTOM_PWM), 1)
LIBPWM = pwm_open
CUSTOM_TARGETS += $(USER_LIBDIR)/lib$(LIBPWM).a
From fab7b5bc2974e4a7a4cfcfdfef9ffeef141853ee Mon Sep 17 00:00:00 2001
From: Slavey Karadzhov
Date: Mon, 26 Jun 2017 12:11:34 +0200
Subject: [PATCH 19/35] Reset response and request data after completion.
---
Sming/SmingCore/Network/Http/HttpRequest.cpp | 10 ++++++++++
Sming/SmingCore/Network/Http/HttpRequest.h | 2 ++
Sming/SmingCore/Network/Http/HttpResponse.cpp | 8 ++++++++
Sming/SmingCore/Network/Http/HttpResponse.h | 2 ++
Sming/SmingCore/Network/Http/HttpServerConnection.cpp | 10 ++++++++++
Sming/SmingCore/Network/Http/HttpServerConnection.h | 2 +-
6 files changed, 33 insertions(+), 1 deletion(-)
diff --git a/Sming/SmingCore/Network/Http/HttpRequest.cpp b/Sming/SmingCore/Network/Http/HttpRequest.cpp
index 17ef222dfd..614c3b7f35 100644
--- a/Sming/SmingCore/Network/Http/HttpRequest.cpp
+++ b/Sming/SmingCore/Network/Http/HttpRequest.cpp
@@ -239,6 +239,16 @@ HttpRequest* HttpRequest::onRequestComplete(RequestCompletedDelegate delegateFun
return this;
}
+void HttpRequest::reset()
+{
+ headers.clear();
+ postParams.clear();
+ if(queryParams != NULL) {
+ delete queryParams;
+ queryParams = NULL;
+ }
+}
+
#ifndef SMING_RELEASE
String HttpRequest::toString() {
String content = "";
diff --git a/Sming/SmingCore/Network/Http/HttpRequest.h b/Sming/SmingCore/Network/Http/HttpRequest.h
index 5f1b079697..35f7807c1b 100644
--- a/Sming/SmingCore/Network/Http/HttpRequest.h
+++ b/Sming/SmingCore/Network/Http/HttpRequest.h
@@ -116,6 +116,8 @@ class HttpRequest {
HttpRequest* onBody(RequestBodyDelegate delegateFunction);
HttpRequest* onRequestComplete(RequestCompletedDelegate delegateFunction);
+ void reset();
+
#ifndef SMING_RELEASE
/**
* @brief Tries to present a readable version of the current request values
diff --git a/Sming/SmingCore/Network/Http/HttpResponse.cpp b/Sming/SmingCore/Network/Http/HttpResponse.cpp
index 9974cab2de..8711251aec 100644
--- a/Sming/SmingCore/Network/Http/HttpResponse.cpp
+++ b/Sming/SmingCore/Network/Http/HttpResponse.cpp
@@ -180,3 +180,11 @@ bool HttpResponse::sendDataStream( IDataSourceStream * newDataStream , String re
return true;
}
+void HttpResponse::reset()
+{
+ headers.clear();
+ if(stream != NULL) {
+ delete stream;
+ stream = NULL;
+ }
+}
diff --git a/Sming/SmingCore/Network/Http/HttpResponse.h b/Sming/SmingCore/Network/Http/HttpResponse.h
index 6b1952c18f..ec6c7e96fb 100644
--- a/Sming/SmingCore/Network/Http/HttpResponse.h
+++ b/Sming/SmingCore/Network/Http/HttpResponse.h
@@ -81,6 +81,8 @@ class HttpResponse {
// Send Datastream, can be called with Classes derived from
bool sendDataStream( IDataSourceStream * newDataStream , String reqContentType = "" );
+ void reset();
+
public:
int code;
HttpHeaders headers;
diff --git a/Sming/SmingCore/Network/Http/HttpServerConnection.cpp b/Sming/SmingCore/Network/Http/HttpServerConnection.cpp
index 486bdb7154..00d73c5f67 100644
--- a/Sming/SmingCore/Network/Http/HttpServerConnection.cpp
+++ b/Sming/SmingCore/Network/Http/HttpServerConnection.cpp
@@ -173,6 +173,11 @@ int HttpServerConnection::staticOnHeadersComplete(http_parser* parser)
int error = 0;
connection->request.setHeaders(connection->requestHeaders);
+ connection->lastWasValue = true;
+ connection->lastData = "";
+ connection->currentField = "";
+ connection->requestHeaders.clear();
+
if(connection->resource != NULL && connection->resource->onHeadersComplete) {
error = connection->resource->onHeadersComplete(*connection, connection->request, connection->response);
}
@@ -406,6 +411,11 @@ void HttpServerConnection::onReadyToSendData(TcpConnectionEvent sourceEvent)
setTimeOut(1); // decrease the timeout to 1 tick
}
+ if(state == eHCS_Sent) {
+ response.reset();
+ request.reset();
+ }
+
TcpClient::onReadyToSendData(sourceEvent);
}
diff --git a/Sming/SmingCore/Network/Http/HttpServerConnection.h b/Sming/SmingCore/Network/Http/HttpServerConnection.h
index 639edb9a70..e6d207ffce 100644
--- a/Sming/SmingCore/Network/Http/HttpServerConnection.h
+++ b/Sming/SmingCore/Network/Http/HttpServerConnection.h
@@ -97,7 +97,7 @@ class HttpServerConnection: public TcpClient
String lastData = "";
String currentField = "";
- BodyParsers* bodyParsers;
+ BodyParsers* bodyParsers = NULL;
HttpBodyParserDelegate bodyParser;
};
From 61cede030d78d71633e29499a4756b03db049cce Mon Sep 17 00:00:00 2001
From: slaff
Date: Thu, 6 Jul 2017 14:00:41 +0200
Subject: [PATCH 20/35] Small fixes to comparison and memory related issues.
(#1172)
* Fixes for possible memory leaks.
* Unsigned value cannot be negative.
---
Sming/Libraries/MCP23S17/MCP23S17.cpp | 20 ++++++++++++++-----
.../CommandProcessing/CommandHandler.cpp | 4 +++-
Sming/SmingCore/Network/Http/HttpResponse.cpp | 1 +
Sming/Wiring/Print.h | 1 +
4 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/Sming/Libraries/MCP23S17/MCP23S17.cpp b/Sming/Libraries/MCP23S17/MCP23S17.cpp
index e199ff4e37..7433c0b88d 100644
--- a/Sming/Libraries/MCP23S17/MCP23S17.cpp
+++ b/Sming/Libraries/MCP23S17/MCP23S17.cpp
@@ -107,8 +107,10 @@ void MCP::wordWrite(uint8_t reg, unsigned int word)
void MCP::pinMode(uint8_t pin, uint8_t mode)
{ // Accept the pin # and I/O mode
- if (pin < 0 | pin > 15)
+ if (pin > 15) {
return; // If the pin value is not valid (0-15) return, do nothing and return
+ }
+
if (mode == INPUT)
{ // Determine the mode before changing the bit state in the mode cache
_modeCache |= 1 << pin; // Since input = "HIGH", OR in a 1 in the appropriate place
@@ -132,8 +134,10 @@ void MCP::pinMode(unsigned int mode)
void MCP::pullupMode(uint8_t pin, uint8_t mode)
{
- if (pin < 0 | pin > 15)
+ if (pin > 15) {
return;
+ }
+
if (mode == ON)
{
_pullupCache |= 1 << pin;
@@ -155,8 +159,10 @@ void MCP::pullupMode(unsigned int mode)
void MCP::inputInvert(uint8_t pin, uint8_t mode)
{
- if (pin < 0 | pin > 15)
+ if (pin > 15) {
return;
+ }
+
if (mode == ON)
{
_invertCache |= 1 << pin;
@@ -178,8 +184,10 @@ void MCP::inputInvert(unsigned int mode)
void MCP::digitalWrite(uint8_t pin, uint8_t value)
{
- if (pin < 0 | pin > 15)
+ if (pin > 15) {
return;
+ }
+
if (value)
{
_outputCache |= 1 << pin;
@@ -240,7 +248,9 @@ uint8_t MCP::byteRead(uint8_t reg)
uint8_t MCP::digitalRead(uint8_t pin)
{ // Return a single bit value, supply the necessary bit (1-16)
- if (pin < 0 | pin > 15)
+ if (pin > 15) {
return 0x0; // If the pin value is not valid (1-16) return, do nothing and return
+ }
+
return digitalRead() & (1 << pin) ? HIGH : LOW; // Call the word reading function, extract HIGH/LOW information from the requested pin
}
diff --git a/Sming/Services/CommandProcessing/CommandHandler.cpp b/Sming/Services/CommandProcessing/CommandHandler.cpp
index c6d5191910..f7c0ad6154 100644
--- a/Sming/Services/CommandProcessing/CommandHandler.cpp
+++ b/Sming/Services/CommandProcessing/CommandHandler.cpp
@@ -15,7 +15,9 @@ CommandHandler::CommandHandler()
CommandHandler::~CommandHandler()
{
- // TODO Auto-generated destructor stub
+ if(registeredCommands != NULL) {
+ delete registeredCommands;
+ }
}
void CommandHandler::registerSystemCommands()
diff --git a/Sming/SmingCore/Network/Http/HttpResponse.cpp b/Sming/SmingCore/Network/Http/HttpResponse.cpp
index 8711251aec..262cc92a0e 100644
--- a/Sming/SmingCore/Network/Http/HttpResponse.cpp
+++ b/Sming/SmingCore/Network/Http/HttpResponse.cpp
@@ -57,6 +57,7 @@ bool HttpResponse::sendString(const String& text)
{
MemoryDataStream* memStream = new MemoryDataStream();
if (memStream->write((const uint8_t*)text.c_str(), text.length()) != text.length()) {
+ delete memStream;
return false;
}
diff --git a/Sming/Wiring/Print.h b/Sming/Wiring/Print.h
index bbde129ed0..884318fef6 100644
--- a/Sming/Wiring/Print.h
+++ b/Sming/Wiring/Print.h
@@ -32,6 +32,7 @@ class Print
{
public:
Print() : write_error(0) {}
+ virtual ~Print() {}
int getWriteError() { return write_error; }
void clearWriteError() { setWriteError(0); }
From d5d0f2527f5bc56ffa29428fc49db6254693c00e Mon Sep 17 00:00:00 2001
From: slaff
Date: Mon, 10 Jul 2017 17:54:11 +0200
Subject: [PATCH 21/35] Changes related to POST parameter unescaping. (#1177)
Related to #1176.
---
Sming/SmingCore/Network/Http/HttpBodyParser.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Sming/SmingCore/Network/Http/HttpBodyParser.cpp b/Sming/SmingCore/Network/Http/HttpBodyParser.cpp
index 36061047a5..ee13b77541 100644
--- a/Sming/SmingCore/Network/Http/HttpBodyParser.cpp
+++ b/Sming/SmingCore/Network/Http/HttpBodyParser.cpp
@@ -41,14 +41,14 @@ void formUrlParser(HttpRequest& request, const char *at, int length)
String key = request.postParams.keyAt(i);
String value = request.postParams.valueAt(i);
- uri_unescape(buffer, maxLength, key.c_str(), key.length());
+ uri_unescape(buffer, maxLength + 1, key.c_str(), key.length());
String newKey = buffer;
if(newKey != key) {
request.postParams.remove(key);
}
- uri_unescape(buffer, maxLength, value.c_str(), value.length());
+ uri_unescape(buffer, maxLength + 1, value.c_str(), value.length());
request.postParams[newKey] = buffer;
}
delete[] buffer;
From 393d51d3146fc88230ead1413a3870fd3cb711f9 Mon Sep 17 00:00:00 2001
From: slaff
Date: Wed, 12 Jul 2017 10:09:38 +0200
Subject: [PATCH 22/35] Adding fixes for issues reported by Vera++ and
CppCheck. (#1178)
* Implementing cppcheck recommendations for passing objects by reference.
* Removed unused variables.
* Fixed looping condition.
* Removed redundant assignment to itself.
* Added initialization for some variables.
---
Sming/SmingCore/DataSourceStream.cpp | 12 ++++++-----
Sming/SmingCore/DataSourceStream.h | 6 +++---
Sming/SmingCore/FileSystem.cpp | 20 +++++++++----------
Sming/SmingCore/FileSystem.h | 20 +++++++++----------
Sming/SmingCore/Network/DNSServer.cpp | 7 +++----
Sming/SmingCore/Network/DNSServer.h | 6 +++---
Sming/SmingCore/Network/FTPServer.cpp | 2 +-
Sming/SmingCore/Network/FTPServer.h | 2 +-
.../SmingCore/Network/FTPServerConnection.cpp | 8 ++++----
Sming/SmingCore/Network/Http/HttpResponse.cpp | 12 +++++------
Sming/SmingCore/Network/Http/HttpResponse.h | 12 +++++------
Sming/SmingCore/Network/MqttClient.cpp | 10 +++++-----
Sming/SmingCore/Network/MqttClient.h | 12 +++++------
Sming/SmingCore/Network/TcpClient.cpp | 2 +-
Sming/SmingCore/Network/TcpClient.h | 2 +-
Sming/SmingCore/Network/TcpConnection.cpp | 2 +-
Sming/SmingCore/Network/TcpConnection.h | 2 +-
Sming/SmingCore/Network/WebsocketClient.cpp | 2 +-
Sming/SmingCore/Network/WebsocketClient.h | 2 +-
Sming/SmingCore/Platform/AccessPoint.cpp | 2 +-
Sming/SmingCore/Platform/AccessPoint.h | 2 +-
Sming/SmingCore/Platform/Station.cpp | 4 ++--
Sming/SmingCore/Platform/Station.h | 4 ++--
23 files changed, 77 insertions(+), 76 deletions(-)
diff --git a/Sming/SmingCore/DataSourceStream.cpp b/Sming/SmingCore/DataSourceStream.cpp
index 61fe9e94ef..24d062d7ed 100644
--- a/Sming/SmingCore/DataSourceStream.cpp
+++ b/Sming/SmingCore/DataSourceStream.cpp
@@ -17,8 +17,10 @@ MemoryDataStream::MemoryDataStream()
MemoryDataStream::~MemoryDataStream()
{
- free(buf);
- buf = NULL;
+ if(buf != NULL) {
+ free(buf);
+ buf = NULL;
+ }
pos = NULL;
size = 0;
}
@@ -94,12 +96,12 @@ FileStream::FileStream()
pos = 0;
}
-FileStream::FileStream(String filename)
+FileStream::FileStream(const String& filename)
{
attach(filename, eFO_ReadOnly);
}
-bool FileStream::attach(String fileName, FileOpenFlags openFlags)
+bool FileStream::attach(const String& fileName, FileOpenFlags openFlags)
{
handle = fileOpen(fileName.c_str(), openFlags);
if (handle == -1)
@@ -178,7 +180,7 @@ bool FileStream::fileExist()
///////////////////////////////////////////////////////////////////////////
-TemplateFileStream::TemplateFileStream(String templateFileName)
+TemplateFileStream::TemplateFileStream(const String& templateFileName)
: FileStream(templateFileName)
{
state = eTES_Wait;
diff --git a/Sming/SmingCore/DataSourceStream.h b/Sming/SmingCore/DataSourceStream.h
index 91466b99fe..0ea982f69e 100644
--- a/Sming/SmingCore/DataSourceStream.h
+++ b/Sming/SmingCore/DataSourceStream.h
@@ -151,10 +151,10 @@ class FileStream : public IDataSourceStream
* @param fileName Name of file to open
*/
FileStream();
- FileStream(String fileName);
+ FileStream(const String& fileName);
virtual ~FileStream();
- virtual bool attach(String fileName, FileOpenFlags openFlags);
+ virtual bool attach(const String& fileName, FileOpenFlags openFlags);
//Use base class documentation
virtual StreamType getStreamType() { return eSST_File; }
@@ -215,7 +215,7 @@ class TemplateFileStream : public FileStream
/** @brief Create a template file stream
* @param templateFileName Template filename
*/
- TemplateFileStream(String templateFileName);
+ TemplateFileStream(const String& templateFileName);
virtual ~TemplateFileStream();
//Use base class documentation
diff --git a/Sming/SmingCore/FileSystem.cpp b/Sming/SmingCore/FileSystem.cpp
index f55e3d6677..9107fe3ea9 100644
--- a/Sming/SmingCore/FileSystem.cpp
+++ b/Sming/SmingCore/FileSystem.cpp
@@ -8,7 +8,7 @@
#include "FileSystem.h"
#include "../Wiring/WString.h"
-file_t fileOpen(const String name, FileOpenFlags flags)
+file_t fileOpen(const String& name, FileOpenFlags flags)
{
int res;
@@ -74,7 +74,7 @@ int fileFlush(file_t file)
return SPIFFS_fflush(&_filesystemStorageHandle, file);
}
-int fileStats(const String name, spiffs_stat *stat)
+int fileStats(const String& name, spiffs_stat *stat)
{
return SPIFFS_stat(&_filesystemStorageHandle, name.c_str(), stat);
}
@@ -84,7 +84,7 @@ int fileStats(file_t file, spiffs_stat *stat)
return SPIFFS_fstat(&_filesystemStorageHandle, file, stat);
}
-void fileDelete(const String name)
+void fileDelete(const String& name)
{
SPIFFS_remove(&_filesystemStorageHandle, name.c_str());
}
@@ -94,7 +94,7 @@ void fileDelete(file_t file)
SPIFFS_fremove(&_filesystemStorageHandle, file);
}
-bool fileExist(const String name)
+bool fileExist(const String& name)
{
spiffs_stat stat = {0};
if (fileStats(name.c_str(), &stat) < 0) return false;
@@ -112,19 +112,19 @@ void fileClearLastError(file_t fd)
SPIFFS_clearerr(&_filesystemStorageHandle);
}
-void fileSetContent(const String fileName, const String& content)
+void fileSetContent(const String& fileName, const String& content)
{
fileSetContent(fileName, content.c_str());
}
-void fileSetContent(const String fileName, const char *content)
+void fileSetContent(const String& fileName, const char *content)
{
file_t file = fileOpen(fileName.c_str(), eFO_CreateNewAlways | eFO_WriteOnly);
fileWrite(file, content, strlen(content));
fileClose(file);
}
-uint32_t fileGetSize(const String fileName)
+uint32_t fileGetSize(const String& fileName)
{
file_t file = fileOpen(fileName.c_str(), eFO_ReadOnly);
// Get size
@@ -134,7 +134,7 @@ uint32_t fileGetSize(const String fileName)
return size;
}
-void fileRename(const String oldName, const String newName)
+void fileRename(const String& oldName, const String& newName)
{
SPIFFS_rename(&_filesystemStorageHandle, oldName.c_str(), newName.c_str());
}
@@ -155,7 +155,7 @@ Vector fileList()
return result;
}
-String fileGetContent(const String fileName)
+String fileGetContent(const String& fileName)
{
file_t file = fileOpen(fileName.c_str(), eFO_ReadOnly);
// Get size
@@ -176,7 +176,7 @@ String fileGetContent(const String fileName)
return res;
}
-int fileGetContent(const String fileName, char* buffer, int bufSize)
+int fileGetContent(const String& fileName, char* buffer, int bufSize)
{
if (buffer == NULL || bufSize == 0) return 0;
*buffer = 0;
diff --git a/Sming/SmingCore/FileSystem.h b/Sming/SmingCore/FileSystem.h
index 8e4461fcbd..6903f3a820 100644
--- a/Sming/SmingCore/FileSystem.h
+++ b/Sming/SmingCore/FileSystem.h
@@ -48,7 +48,7 @@ typedef enum
* @param flags Mode to open file
* @retval file File ID or negative error code
*/
-file_t fileOpen(const String name, FileOpenFlags flags);
+file_t fileOpen(const String& name, FileOpenFlags flags);
/** @brief Clode file
* @param file ID of file to open
@@ -118,7 +118,7 @@ void fileClearLastError(file_t fd);
populates the file with the content of a c-string buffer.
Remember to terminate your c-string buffer with a null (0).
*/
-void fileSetContent(const String fileName, const char *content);
+void fileSetContent(const String& fileName, const char *content);
/** @brief Create or replace file with defined content
* @param fileName Name of file to create or replace
@@ -126,19 +126,19 @@ void fileSetContent(const String fileName, const char *content);
* @note This function creates a new file or replaces an existing file and
populates the file with the content of a string.
*/
-void fileSetContent(const String fileName, const String& content);
+void fileSetContent(const String& fileName, const String& content);
/** @brief Get size of file
* @param fileName Name of file
* @retval uint32_t Size of file in bytes
*/
-uint32_t fileGetSize(const String fileName);
+uint32_t fileGetSize(const String& fileName);
/** @brief Rename file
* @param oldName Original name of file to rename
* @param newName New name for file
*/
-void fileRename(const String oldName, const String newName);
+void fileRename(const String& oldName, const String& newName);
/** @brief Get list of files on file system
* @retval Vector Vector of strings.
@@ -151,7 +151,7 @@ Vector fileList();
* @retval String String variable in to which to read the file content
* @note After calling this function the content of the file is placed in to a string
*/
-String fileGetContent(const String fileName);
+String fileGetContent(const String& fileName);
/** @brief Read content of a file
* @param fileName Name of file to read from
@@ -162,7 +162,7 @@ String fileGetContent(const String fileName);
Ensure there is sufficient space in the buffer for file content
plus extra trailing null, i.e. at least bufSize + 1
*/
-int fileGetContent(const String fileName, char* buffer, int bufSize);
+int fileGetContent(const String& fileName, char* buffer, int bufSize);
/** brief Get file statistics
* @param name File name
@@ -171,7 +171,7 @@ int fileGetContent(const String fileName, char* buffer, int bufSize);
* @note Pass a pointer to an instantiated fileStats structure
* @todo Document the return value of fileStats
*/
-int fileStats(const String name, spiffs_stat *stat);
+int fileStats(const String& name, spiffs_stat *stat);
/** brief Get file statistics
* @param file File ID
@@ -185,7 +185,7 @@ int fileStats(file_t file, spiffs_stat *stat);
/** @brief Delete file
* @param name Name of file to delete
*/
-void fileDelete(const String name);
+void fileDelete(const String& name);
/** @brief Delete file
* @param file ID of file to delete
@@ -196,7 +196,7 @@ void fileDelete(file_t file);
* @param name Name of file to check for
* @retval bool True if file exists
*/
-bool fileExist(const String name);
+bool fileExist(const String& name);
/** @} */
#endif /* _SMING_CORE_FILESYSTEM_H_ */
diff --git a/Sming/SmingCore/Network/DNSServer.cpp b/Sming/SmingCore/Network/DNSServer.cpp
index 1d048de190..8f11f46432 100644
--- a/Sming/SmingCore/Network/DNSServer.cpp
+++ b/Sming/SmingCore/Network/DNSServer.cpp
@@ -73,9 +73,9 @@ bool DNSServer::requestIncludesOnlyOneQuestion()
void DNSServer::onReceive(pbuf* buf, IPAddress remoteIP, uint16_t remotePort)
{
-
-
- if (_buffer != NULL) free(_buffer);
+ if (_buffer != NULL) {
+ free(_buffer);
+ }
_buffer = (char*)malloc(buf->tot_len * sizeof(char));
if (_buffer == NULL) return;
pbuf_copy_partial(buf, _buffer, buf->tot_len, 0);
@@ -91,7 +91,6 @@ void DNSServer::onReceive(pbuf* buf, IPAddress remoteIP, uint16_t remotePort)
int idx = buf->tot_len;
_dnsHeader->QR = DNS_QR_RESPONSE;
_dnsHeader->ANCount = _dnsHeader->QDCount;
- _dnsHeader->QDCount = _dnsHeader->QDCount;
memcpy(response, _buffer, idx);
//Set a pointer to the domain name in the question section
response[idx] = 0xC0;
diff --git a/Sming/SmingCore/Network/DNSServer.h b/Sming/SmingCore/Network/DNSServer.h
index d5b74c0ec4..679ddeaa43 100644
--- a/Sming/SmingCore/Network/DNSServer.h
+++ b/Sming/SmingCore/Network/DNSServer.h
@@ -68,11 +68,11 @@ class DNSServer : public UdpConnection
void stop();
private:
- uint16_t _port;
+ uint16_t _port = 0;
String _domainName;
char _resolvedIP[4];
- char* _buffer;
- DNSHeader* _dnsHeader;
+ char* _buffer = NULL;
+ DNSHeader* _dnsHeader = NULL;
uint32_t _ttl;
DNSReplyCode _errorReplyCode;
diff --git a/Sming/SmingCore/Network/FTPServer.cpp b/Sming/SmingCore/Network/FTPServer.cpp
index f092e4393a..2fc6714b87 100644
--- a/Sming/SmingCore/Network/FTPServer.cpp
+++ b/Sming/SmingCore/Network/FTPServer.cpp
@@ -34,7 +34,7 @@ void FTPServer::addUser(String login, String pass)
users[login] = pass;
}
-bool FTPServer::checkUser(String login, String pass)
+bool FTPServer::checkUser(String login, const String& pass)
{
debugf("checkUser: %s %s", login.c_str(), pass.c_str());
if (!users.contains(login))
diff --git a/Sming/SmingCore/Network/FTPServer.h b/Sming/SmingCore/Network/FTPServer.h
index 7667c4b7fb..3b3ca17479 100644
--- a/Sming/SmingCore/Network/FTPServer.h
+++ b/Sming/SmingCore/Network/FTPServer.h
@@ -23,7 +23,7 @@ class FTPServer: public TcpServer
virtual ~FTPServer();
void addUser(String login, String pass);
- bool checkUser(String login, String pass);
+ bool checkUser(String login, const String& pass);
protected:
virtual TcpConnection* createClient(tcp_pcb *clientTcp);
diff --git a/Sming/SmingCore/Network/FTPServerConnection.cpp b/Sming/SmingCore/Network/FTPServerConnection.cpp
index 492557a25a..d57a10bb68 100644
--- a/Sming/SmingCore/Network/FTPServerConnection.cpp
+++ b/Sming/SmingCore/Network/FTPServerConnection.cpp
@@ -66,7 +66,7 @@ class FTPDataFileList : public FTPDataStream
class FTPDataRetrieve : public FTPDataStream
{
public:
- FTPDataRetrieve(FTPServerConnection* connection, String fileName) : FTPDataStream(connection)
+ FTPDataRetrieve(FTPServerConnection* connection, const String& fileName) : FTPDataStream(connection)
{
file = fileOpen(fileName, eFO_ReadOnly);
}
@@ -94,7 +94,7 @@ class FTPDataRetrieve : public FTPDataStream
class FTPDataStore : public FTPDataStream
{
public:
- FTPDataStore(FTPServerConnection* connection, String fileName) : FTPDataStream(connection)
+ FTPDataStore(FTPServerConnection* connection, const String& fileName) : FTPDataStream(connection)
{
file = fileOpen(fileName, eFO_WriteOnly | eFO_CreateNewAlways);
}
@@ -114,9 +114,9 @@ class FTPDataStore : public FTPDataStream
}
pbuf *cur = buf;
- while (cur)
+ while (cur != NULL && cur->len > 0)
{
- int len = fileWrite(file, (uint8_t *)cur->payload, cur->len);
+ fileWrite(file, (uint8_t *)cur->payload, cur->len);
cur = cur->next;
}
diff --git a/Sming/SmingCore/Network/Http/HttpResponse.cpp b/Sming/SmingCore/Network/Http/HttpResponse.cpp
index 262cc92a0e..56fcab6482 100644
--- a/Sming/SmingCore/Network/Http/HttpResponse.cpp
+++ b/Sming/SmingCore/Network/Http/HttpResponse.cpp
@@ -21,7 +21,7 @@ HttpResponse::~HttpResponse()
}
}
-HttpResponse* HttpResponse::setContentType(const String type)
+HttpResponse* HttpResponse::setContentType(const String& type)
{
return setHeader("Content-Type", type);
}
@@ -31,7 +31,7 @@ HttpResponse* HttpResponse::setContentType(enum MimeType type)
return setContentType(ContentType::toString(type));
}
-HttpResponse* HttpResponse::setCookie(const String name, const String value)
+HttpResponse* HttpResponse::setCookie(const String& name, const String& value)
{
return setHeader("Set-Cookie", name + "=" + value);
}
@@ -42,12 +42,12 @@ HttpResponse* HttpResponse::setCache(int maxAgeSeconds, bool isPublic /* = false
return setHeader("Cache-Control", chache);
}
-HttpResponse* HttpResponse::setAllowCrossDomainOrigin(String controlAllowOrigin)
+HttpResponse* HttpResponse::setAllowCrossDomainOrigin(const String& controlAllowOrigin)
{
return setHeader("Access-Control-Allow-Origin", controlAllowOrigin);
}
-HttpResponse* HttpResponse::setHeader(const String name, const String value)
+HttpResponse* HttpResponse::setHeader(const String& name, const String& value)
{
headers[name] = value;
return this;
@@ -73,7 +73,7 @@ bool HttpResponse::sendString(const String& text)
return true;
}
-bool HttpResponse::hasHeader(const String name)
+bool HttpResponse::hasHeader(const String& name)
{
return headers.contains(name);
}
@@ -164,7 +164,7 @@ bool HttpResponse::sendJsonObject(JsonObjectStream* newJsonStreamInstance)
return true;
}
-bool HttpResponse::sendDataStream( IDataSourceStream * newDataStream , String reqContentType /* = "" */)
+bool HttpResponse::sendDataStream( IDataSourceStream * newDataStream , const String& reqContentType /* = "" */)
{
if (stream != NULL)
{
diff --git a/Sming/SmingCore/Network/Http/HttpResponse.h b/Sming/SmingCore/Network/Http/HttpResponse.h
index ec6c7e96fb..c0a57def4f 100644
--- a/Sming/SmingCore/Network/Http/HttpResponse.h
+++ b/Sming/SmingCore/Network/Http/HttpResponse.h
@@ -31,7 +31,7 @@ class HttpResponse {
// @deprecated method
- bool hasHeader(const String name);
+ bool hasHeader(const String& name);
void redirect(const String& location);
@@ -49,12 +49,12 @@ class HttpResponse {
code = HTTP_STATUS_NOT_FOUND;
}
- HttpResponse* setContentType(const String type);
+ HttpResponse* setContentType(const String& type);
HttpResponse* setContentType(enum MimeType type);
- HttpResponse* setCookie(const String name, const String value);
- HttpResponse* setHeader(const String name, const String value);
+ HttpResponse* setCookie(const String& name, const String& value);
+ HttpResponse* setHeader(const String& name, const String& value);
HttpResponse* setCache(int maxAgeSeconds = 3600, bool isPublic = false);
- HttpResponse* setAllowCrossDomainOrigin(String controlAllowOrigin); // Access-Control-Allow-Origin for AJAX from a different domain
+ HttpResponse* setAllowCrossDomainOrigin(const String& controlAllowOrigin); // Access-Control-Allow-Origin for AJAX from a different domain
// Send file by name
bool sendFile(String fileName, bool allowGzipFileCheck = true);
@@ -79,7 +79,7 @@ class HttpResponse {
}
// Send Datastream, can be called with Classes derived from
- bool sendDataStream( IDataSourceStream * newDataStream , String reqContentType = "" );
+ bool sendDataStream( IDataSourceStream * newDataStream , const String& reqContentType = "" );
void reset();
diff --git a/Sming/SmingCore/Network/MqttClient.cpp b/Sming/SmingCore/Network/MqttClient.cpp
index e5497c32ce..ed35b037b6 100644
--- a/Sming/SmingCore/Network/MqttClient.cpp
+++ b/Sming/SmingCore/Network/MqttClient.cpp
@@ -51,17 +51,17 @@ void MqttClient::setPingRepeatTime(int seconds)
PingRepeatTime = seconds;
}
-bool MqttClient::setWill(String topic, String message, int QoS, bool retained /* = false*/)
+bool MqttClient::setWill(const String& topic, const String& message, int QoS, bool retained /* = false*/)
{
return mqtt_set_will(&broker, topic.c_str(), message.c_str(), QoS, retained);
}
-bool MqttClient::connect(String clientName, boolean useSsl /* = false */, uint32_t sslOptions /* = 0 */)
+bool MqttClient::connect(const String& clientName, boolean useSsl /* = false */, uint32_t sslOptions /* = 0 */)
{
return MqttClient::connect(clientName, "", "", useSsl, sslOptions);
}
-bool MqttClient::connect(String clientName, String username, String password, boolean useSsl /* = false */, uint32_t sslOptions /* = 0 */)
+bool MqttClient::connect(const String& clientName, const String& username, const String& password, boolean useSsl /* = false */, uint32_t sslOptions /* = 0 */)
{
if (getConnectionState() != eTCS_Ready)
{
@@ -119,7 +119,7 @@ int MqttClient::staticSendPacket(void* userInfo, const void* buf, unsigned int c
return sent ? count : 0;
}
-bool MqttClient::subscribe(String topic)
+bool MqttClient::subscribe(const String& topic)
{
uint16_t msgId = 0;
debugf("subscription '%s' registered", topic.c_str());
@@ -127,7 +127,7 @@ bool MqttClient::subscribe(String topic)
return res > 0;
}
-bool MqttClient::unsubscribe(String topic)
+bool MqttClient::unsubscribe(const String& topic)
{
uint16_t msgId = 0;
debugf("unsubscribing from '%s'", topic.c_str());
diff --git a/Sming/SmingCore/Network/MqttClient.h b/Sming/SmingCore/Network/MqttClient.h
index 247802fa43..3f9b1b09ea 100644
--- a/Sming/SmingCore/Network/MqttClient.h
+++ b/Sming/SmingCore/Network/MqttClient.h
@@ -33,10 +33,10 @@ class MqttClient: protected TcpClient
void setKeepAlive(int seconds); //send to broker
void setPingRepeatTime(int seconds); //used by client
// Sets Last Will and Testament
- bool setWill(String topic, String message, int QoS, bool retained = false);
+ bool setWill(const String& topic, const String& message, int QoS, bool retained = false);
- bool connect(String clientName, boolean useSsl = false, uint32_t sslOptions = 0);
- bool connect(String clientName, String username, String password, boolean useSsl = false, uint32_t sslOptions = 0);
+ bool connect(const String& clientName, boolean useSsl = false, uint32_t sslOptions = 0);
+ bool connect(const String& clientName,const String& username, const String& password, boolean useSsl = false, uint32_t sslOptions = 0);
using TcpClient::setCompleteDelegate;
@@ -46,8 +46,8 @@ class MqttClient: protected TcpClient
bool publish(String topic, String message, bool retained = false);
bool publishWithQoS(String topic, String message, int QoS, bool retained = false, MqttMessageDeliveredCallback onDelivery = NULL);
- bool subscribe(String topic);
- bool unsubscribe(String topic);
+ bool subscribe(const String& topic);
+ bool unsubscribe(const String& topic);
#ifdef ENABLE_SSL
using TcpClient::addSslOptions;
@@ -76,7 +76,7 @@ class MqttClient: protected TcpClient
MqttStringSubscriptionCallback callback;
int keepAlive = 60;
int PingRepeatTime = 20;
- unsigned long lastMessage;
+ unsigned long lastMessage = 0;
HashMap onDeliveryQueue;
};
diff --git a/Sming/SmingCore/Network/TcpClient.cpp b/Sming/SmingCore/Network/TcpClient.cpp
index df09b847b1..a70401d4e7 100644
--- a/Sming/SmingCore/Network/TcpClient.cpp
+++ b/Sming/SmingCore/Network/TcpClient.cpp
@@ -69,7 +69,7 @@ bool TcpClient::connect(IPAddress addr, uint16_t port, boolean useSsl /* = false
return TcpConnection::connect(addr, port, useSsl, sslOptions);
}
-bool TcpClient::sendString(String data, bool forceCloseAfterSent /* = false*/)
+bool TcpClient::sendString(const String& data, bool forceCloseAfterSent /* = false*/)
{
return send(data.c_str(), data.length(), forceCloseAfterSent);
}
diff --git a/Sming/SmingCore/Network/TcpClient.h b/Sming/SmingCore/Network/TcpClient.h
index 7b694066d5..30fbf3a9bc 100644
--- a/Sming/SmingCore/Network/TcpClient.h
+++ b/Sming/SmingCore/Network/TcpClient.h
@@ -58,7 +58,7 @@ class TcpClient : public TcpConnection
void setCompleteDelegate(TcpClientCompleteDelegate completeCb = NULL);
bool send(const char* data, uint16_t len, bool forceCloseAfterSent = false);
- bool sendString(String data, bool forceCloseAfterSent = false);
+ bool sendString(const String& data, bool forceCloseAfterSent = false);
__forceinline bool isProcessing() { return state == eTCS_Connected || state == eTCS_Connecting; }
__forceinline TcpClientState getConnectionState() { return state; }
diff --git a/Sming/SmingCore/Network/TcpConnection.cpp b/Sming/SmingCore/Network/TcpConnection.cpp
index bb4a24e943..ee9e2066e4 100644
--- a/Sming/SmingCore/Network/TcpConnection.cpp
+++ b/Sming/SmingCore/Network/TcpConnection.cpp
@@ -175,7 +175,7 @@ void TcpConnection::onReadyToSendData(TcpConnectionEvent sourceEvent)
if (sourceEvent != eTCE_Poll) debugf("onReadyToSendData: %d", sourceEvent);
}
-int TcpConnection::writeString(const String data, uint8_t apiflags /* = TCP_WRITE_FLAG_COPY*/)
+int TcpConnection::writeString(const String& data, uint8_t apiflags /* = TCP_WRITE_FLAG_COPY*/)
{
return writeString(data.c_str(), apiflags);
}
diff --git a/Sming/SmingCore/Network/TcpConnection.h b/Sming/SmingCore/Network/TcpConnection.h
index b1879e8ecc..3d4855a45d 100644
--- a/Sming/SmingCore/Network/TcpConnection.h
+++ b/Sming/SmingCore/Network/TcpConnection.h
@@ -83,7 +83,7 @@ class TcpConnection
// return -1 on error
int writeString(const char* data, uint8_t apiflags = TCP_WRITE_FLAG_COPY);
- int writeString(const String data, uint8_t apiflags = TCP_WRITE_FLAG_COPY);
+ int writeString(const String& data, uint8_t apiflags = TCP_WRITE_FLAG_COPY);
// return -1 on error
virtual int write(const char* data, int len, uint8_t apiflags = TCP_WRITE_FLAG_COPY); // flags: TCP_WRITE_FLAG_COPY, TCP_WRITE_FLAG_MORE
int write(IDataSourceStream* stream);
diff --git a/Sming/SmingCore/Network/WebsocketClient.cpp b/Sming/SmingCore/Network/WebsocketClient.cpp
index 874ad75ae8..30166c8172 100644
--- a/Sming/SmingCore/Network/WebsocketClient.cpp
+++ b/Sming/SmingCore/Network/WebsocketClient.cpp
@@ -204,7 +204,7 @@ void WebsocketClient::sendMessage(char* msg, uint16_t length)
_sendFrame(WSFrameType::text, (uint8_t*) msg, length);
}
-void WebsocketClient::sendMessage(String str)
+void WebsocketClient::sendMessage(const String& str)
{
_sendFrame(WSFrameType::text, (uint8_t*) str.c_str(), str.length() + 1);
}
diff --git a/Sming/SmingCore/Network/WebsocketClient.h b/Sming/SmingCore/Network/WebsocketClient.h
index 971a20474f..1ed1cdf231 100644
--- a/Sming/SmingCore/Network/WebsocketClient.h
+++ b/Sming/SmingCore/Network/WebsocketClient.h
@@ -90,7 +90,7 @@ class WebsocketClient: protected TcpClient
* @param msg Pointer to NULL-terminated string buffer to be send to websocket server
* @param length length of the NULL-terminated string buffer
*/
- void sendMessage(String str);
+ void sendMessage(const String& str);
/** @brief Send text message to websocket server
* @param C++ String to be send to websocket server
*/
diff --git a/Sming/SmingCore/Platform/AccessPoint.cpp b/Sming/SmingCore/Platform/AccessPoint.cpp
index 2bc7637a77..855f4840ec 100644
--- a/Sming/SmingCore/Platform/AccessPoint.cpp
+++ b/Sming/SmingCore/Platform/AccessPoint.cpp
@@ -35,7 +35,7 @@ bool AccessPointClass::isEnabled()
return wifi_get_opmode() & SOFTAP_MODE;
}
-bool AccessPointClass::config(String ssid, String password, AUTH_MODE mode, bool hidden /* = false*/, int channel /* = 7*/, int beaconInterval /* = 200*/)
+bool AccessPointClass::config(const String& ssid, String password, AUTH_MODE mode, bool hidden /* = false*/, int channel /* = 7*/, int beaconInterval /* = 200*/)
{
softap_config config = {0};
if (mode == AUTH_WEP) return false; // Not supported!
diff --git a/Sming/SmingCore/Platform/AccessPoint.h b/Sming/SmingCore/Platform/AccessPoint.h
index e84e6a085d..22c97de1ee 100644
--- a/Sming/SmingCore/Platform/AccessPoint.h
+++ b/Sming/SmingCore/Platform/AccessPoint.h
@@ -53,7 +53,7 @@ class AccessPointClass : protected ISystemReadyHandler
* @param beaconInterval WiFi AP beacon interval in milliseconds (Default: 200ms)
* @retval bool True on success
*/
- bool config(String ssid, String password, AUTH_MODE mode, bool hidden = false, int channel = 7, int beaconInterval = 200);
+ bool config(const String& ssid, String password, AUTH_MODE mode, bool hidden = false, int channel = 7, int beaconInterval = 200);
/** @brief Get WiFi AP IP address
* @retval IPAddress WiFi AP IP address
diff --git a/Sming/SmingCore/Platform/Station.cpp b/Sming/SmingCore/Platform/Station.cpp
index c494c740bd..2cf16d3496 100644
--- a/Sming/SmingCore/Platform/Station.cpp
+++ b/Sming/SmingCore/Platform/Station.cpp
@@ -49,7 +49,7 @@ bool StationClass::isEnabled()
return wifi_get_opmode() & STATION_MODE;
}
-bool StationClass::config(String ssid, String password, bool autoConnectOnStartup /* = true*/, bool save /* = true */)
+bool StationClass::config(const String& ssid, const String& password, bool autoConnectOnStartup /* = true*/, bool save /* = true */)
{
station_config config = {0};
@@ -142,7 +142,7 @@ void StationClass::enableDHCP(bool enable)
wifi_station_dhcpc_stop();
}
-void StationClass::setHostname(String hostname)
+void StationClass::setHostname(const String& hostname)
{
wifi_station_set_hostname((char*)hostname.c_str());
}
diff --git a/Sming/SmingCore/Platform/Station.h b/Sming/SmingCore/Platform/Station.h
index 87047741bf..670e776d76 100644
--- a/Sming/SmingCore/Platform/Station.h
+++ b/Sming/SmingCore/Platform/Station.h
@@ -101,7 +101,7 @@ class StationClass : protected ISystemReadyHandler
* @param autoConnectOnStartup True to auto connect. False for manual. (Default: True)
* @param save True to save the SSID and password in Flash. False otherwise. (Default: True)
*/
- bool config(String ssid, String password, bool autoConnectOnStartup = true, bool save = true);
+ bool config(const String& ssid, const String& password, bool autoConnectOnStartup = true, bool save = true);
/** @brief Connect WiFi station to network
*/
@@ -144,7 +144,7 @@ class StationClass : protected ISystemReadyHandler
/** @brief Set WiFi station DHCP hostname
* @param hostname - WiFi station DHCP hostname
*/
- void setHostname(String hostname);
+ void setHostname(const String& hostname);
/** @brief Set WiFi station DHCP hostname
* @retval WiFi station DHCP hostname
From bd291831dc348ed09b06d24c9b25c80aef1c1091 Mon Sep 17 00:00:00 2001
From: slaff
Date: Wed, 12 Jul 2017 11:13:47 +0200
Subject: [PATCH 23/35] Station::waitConnection method was deprecated and is
now removed. (#1171)
Use WifiEvents instead.
---
Sming/SmingCore/Platform/Station.cpp | 67 ----------------------------
Sming/SmingCore/Platform/Station.h | 24 ----------
2 files changed, 91 deletions(-)
diff --git a/Sming/SmingCore/Platform/Station.cpp b/Sming/SmingCore/Platform/Station.cpp
index 2cf16d3496..3e2c3ed84e 100644
--- a/Sming/SmingCore/Platform/Station.cpp
+++ b/Sming/SmingCore/Platform/Station.cpp
@@ -14,17 +14,10 @@ StationClass::StationClass()
{
System.onReady(this);
runScan = false;
- onConnectOk = nullptr;
- onConnectFail = nullptr;
- connectionTimeOut = 0;
- connectionTimer = NULL;
- connectionStarted = 0;
}
StationClass::~StationClass()
{
- delete connectionTimer;
- connectionTimer = NULL;
}
void StationClass::enable(bool enabled, bool save)
@@ -36,8 +29,6 @@ void StationClass::enable(bool enabled, bool save)
mode = wifi_get_opmode() & ~STATION_MODE;
if (enabled)
mode |= STATION_MODE;
- else if (connectionTimer)
- delete connectionTimer;
if (save)
wifi_set_opmode(mode);
else
@@ -288,27 +279,6 @@ bool StationClass::startScan(ScanCompletedDelegate scanCompleted)
return res;
}
-void StationClass::waitConnection(ConnectionDelegate successfulConnected)
-{
- waitConnection(successfulConnected, -1, NULL);
-}
-
-void StationClass::waitConnection(ConnectionDelegate successfulConnected, int secondsTimeOut, ConnectionDelegate connectionNotEstablished)
-{
- if (onConnectOk || onConnectFail )
- {
- SYSTEM_ERROR("WRONG CALL waitConnection method..");
- return;
- }
-
- onConnectOk = successfulConnected;
- connectionTimeOut = secondsTimeOut;
- onConnectFail = connectionNotEstablished;
- connectionTimer = new Timer();
- connectionTimer->initializeMs(50, staticCheckConnection).start();
- connectionStarted = millis();
-}
-
////////////
void StationClass::staticScanCompleted(void *arg, STATUS status)
@@ -347,43 +317,6 @@ void StationClass::onSystemReady()
}
}
-void StationClass::internalCheckConnection()
-{
- uint32 duration = millis() - connectionStarted;
- if (isConnected())
- {
- ConnectionDelegate callOk = nullptr;
- if (onConnectOk) {
- callOk = onConnectOk;
- }
-
- onConnectOk = nullptr;
- onConnectFail = nullptr;
- delete connectionTimer;
- connectionTimeOut = 0;
-
- if (callOk) {
- callOk();
- }
- }
- else if (connectionTimeOut > 0 && duration > (uint32)connectionTimeOut * 1000)
- {
- ConnectionDelegate call = onConnectFail;
- onConnectOk = nullptr;
- onConnectFail = nullptr;
- delete connectionTimer;
- connectionTimeOut = 0;
-
- if (call)
- call();
- }
-}
-
-void StationClass::staticCheckConnection()
-{
- WifiStation.internalCheckConnection();
-}
-
const char* StationClass::getConnectionStatusName()
{
switch (getConnectionStatus())
diff --git a/Sming/SmingCore/Platform/Station.h b/Sming/SmingCore/Platform/Station.h
index 670e776d76..b78484ee5f 100644
--- a/Sming/SmingCore/Platform/Station.h
+++ b/Sming/SmingCore/Platform/Station.h
@@ -208,24 +208,6 @@ class StationClass : protected ISystemReadyHandler
*/
bool startScan(ScanCompletedDelegate scanCompleted);
- /** @brief Assign handler for WiFi station connection
- * @note The handler will be cleared if the WiFi Station is disabled. If you subsequently reenable WiFi Station, another call to waitConnection must be made if you want the handler to be reinstalled.
- * @param successfulConnected Function to call when WiFi station connects to network
- */
- void waitConnection(ConnectionDelegate successfulConnected);
-
- /** @brief Assign handler for WiFi station connection with timeout
- * @note The handler will be cleared if the WiFi Station is disabled. If you subsequently reenable WiFi Station, another call to waitConnection must be made if you want the handler to be reinstalled.
- * @param successfulConnected Function to call when WiFi station connects to network
- * @param secondsTimeOut Quantity of seconds to wait for connection
- * @param connectionNotEstablished Function to call if WiFi station fails to connect to network
- *
- * @deprecated This method is deprecated and will be removed in the next versions. Use WifiEvents instead.
- * For an example of WifiEvents take a look at the Basic_Wifi sample code.
- *
- */
- void waitConnection(ConnectionDelegate successfulConnected, int secondsTimeOut, ConnectionDelegate connectionNotEstablished);
-
/** @brief Start WiFi station smart configuration
* @param sctype Smart configuration type
* @param callback Function to call on WiFi staton smart configuration complete (Default: none)
@@ -250,12 +232,6 @@ class StationClass : protected ISystemReadyHandler
ScanCompletedDelegate scanCompletedCallback;
SmartConfigDelegate smartConfigCallback = NULL;
bool runScan;
-
- ConnectionDelegate onConnectOk;
- ConnectionDelegate onConnectFail;
- int connectionTimeOut;
- uint32 connectionStarted;
- Timer* connectionTimer;
};
class BssInfo
From 3afb5ddcea1a57dc429a667bd708a5cd9ae0f7c3 Mon Sep 17 00:00:00 2001
From: slaff
Date: Thu, 13 Jul 2017 13:34:48 +0200
Subject: [PATCH 24/35] Release Candidate 1 for version 3.3.0. (#1185)
This version includes:
- Refactored HttpClient and HttpServer
- Support for SSL session resumption in TcpConnection and TcpServer.
- Removed deprecated Station::waitConnection.
- Custom PWM is enabled by default.
- Multiple fixes to issues reported from Codacy's Vera++ and CppCheck reports.
---
Readme.md | 6 +++---
Sming/SmingCore/SmingCore.h | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/Readme.md b/Readme.md
index 9448dfb424..5acd9f49d6 100644
--- a/Readme.md
+++ b/Readme.md
@@ -26,7 +26,7 @@ Sming - Open Source framework for high efficiency WiFi SoC ESP8266 native develo
* Out of the box support for HTTP, MQTT and Websocket client connections over SSL.
* Out of the box support for OTA over HTTPS.
* [SNI](https://tools.ietf.org/html/rfc6066#page-6) and [Maximum Fragment Length](https://tools.ietf.org/html/rfc6066#page-8) SSL support.
-* Optional alternative PWM support based on [Stefan Bruens PWM](https://github.com/StefanBruens/ESP8266_new_pwm.git)
+* PWM support based on [Stefan Bruens PWM](https://github.com/StefanBruens/ESP8266_new_pwm.git)
* Optional custom heap allocation based on [Umm Malloc](https://github.com/rhempel/umm_malloc.git)
* Based on Espressif NONOS SDK. Tested with versions 1.4, 1.5 and 2.0.
@@ -61,12 +61,12 @@ n/a = The selected SDK is not available on that OS
- Custom LWIP: (default: ON) By default we are using custom compiled LWIP stack instead of the binary one provided from Espressif. This is increasing the free memory and decreasing the space on the flash. All espconn_* functions are turned off by default. If your application requires the use of some of the espconn_* functions then add the ENABLE_ESPCONN=1 directive. See `Makefile-user.mk` from the [Basic_SmartConfig](https://github.com/SmingHub/Sming/blob/develop/samples/Basic_SmartConfig/Makefile-user.mk#L41) application for examples. If you would like to use the binary LWIP then you should turn off the custom LWIP compilation by providing `ENABLE_CUSTOM_LWIP=0`.
- SSL: (default: OFF) The SSL support is not built-in by default to conserve resources. If you want to enable it then take a look at the [Readme](https://github.com/SmingHub/Sming/blob/develop/samples/Basic_Ssl/README.md) in the Basic_Ssl samples.
-- Custom PWM: (default: OFF) If you want to use the [open PWM implementation](https://github.com/StefanBruens/ESP8266_new_pwm) then compile your application with `ENABLE_CUSTOM_PWM=1`. There is no need to recompile the Sming library.
+- Custom PWM: (default: ON) If you don't want to use the [open PWM implementation](https://github.com/StefanBruens/ESP8266_new_pwm) then compile your application with `ENABLE_CUSTOM_PWM=0`. There is no need to recompile the Sming library.
- Custom serial baud rate: (default: OFF) The default serial baud rate is 115200. If you want to change it to a higher baud rate you can recompile Sming and your application changing the `COM_SPEED_SERIAL` directive. For example `COM_SPEED_SERIAL=921600`.
- Custom heap allocation: (default: OFF) If your application is experiencing heap fragmentation then you can try the [umm_malloc](https://github.com/rhempel/umm_malloc) heap allocation. To enable it compile Sming with `ENABLE_CUSTOM_HEAP=1`. In order to use it in your sample/application make sure to compile the sample with `ENABLE_CUSTOM_HEAP=1`. **Do not enable custom heap allocation and -mforce-l32 compiler flag together**.
- Debug information log level and format: There are four debug levels: debug=3, info=2, warn=1, error=0. Using `DEBUG_VERBOSE_LEVEL` you can set the desired level (0-3). For example `DEBUG_VERBOSE_LEVEL=2` will show only info messages and above. Another make directive is `DEBUG_PRINT_FILENAME_AND_LINE=1` which enables printing the filename and line number of every debug line. This will require extra space on flash. Note: you can compile the Sming library with a set of debug directives and your project with another settings, this way you can control debugging sepparately for sming and your application code.
- Debug information for custom LWIP: If you use custom LWIP (see above) some debug information will be printed for critical errors and situations. You can enable debug information printing altogether using `ENABLE_LWIPDEBUG=1`. To increase debugging for certain areas you can modify debug options in `third-party/esp-open-lwip/include/lwipopts.h`.
-- CommandExecutor feature: This feature enables execution of certain commands by registering token handlers for text received via serial, websocket or telnet connection. If this feature is not used additional RAM/Flash can be obtained by setting `ENABLE_CMD_EXECUTOR=0`. This will save ~1KB RAM and ~3KB of flash memory.
+- CommandExecutor feature: (default: ON) This feature enables execution of certain commands by registering token handlers for text received via serial, websocket or telnet connection. If this feature is not used additional RAM/Flash can be obtained by setting `ENABLE_CMD_EXECUTOR=0`. This will save ~1KB RAM and ~3KB of flash memory.
diff --git a/Sming/SmingCore/SmingCore.h b/Sming/SmingCore/SmingCore.h
index ca273ff3cc..cc5de45cd6 100644
--- a/Sming/SmingCore/SmingCore.h
+++ b/Sming/SmingCore/SmingCore.h
@@ -8,7 +8,7 @@
#ifndef _NET_WIRING_
#define _NET_WIRING_
-#define SMING_VERSION "3.2.0" // Major Minor Sub
+#define SMING_VERSION "3.3.0" // Major Minor Sub
#include "../Wiring/WiringFrameworkIncludes.h"
From 32dcb952ad3535814fc2c3eb8e03a06d47f3da03 Mon Sep 17 00:00:00 2001
From: slaff
Date: Fri, 14 Jul 2017 17:24:16 +0200
Subject: [PATCH 25/35] decode-stacktrace.py: Added python3 compatability.
(#1190)
---
tools/decode-stacktrace.py | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/tools/decode-stacktrace.py b/tools/decode-stacktrace.py
index d2abc2659e..77791cbfb2 100755
--- a/tools/decode-stacktrace.py
+++ b/tools/decode-stacktrace.py
@@ -12,21 +12,21 @@
import re
def usage():
- print "Usage: \n\t%s []" % sys.argv[0]
+ print("Usage: \n\t%s []" % sys.argv[0])
def extractAddresses(data):
m = re.findall("(40[0-2](\d|[a-f]){5})", data)
if len(m) == 0:
return m
- addresses = []
+ addresses = []
for item in m:
addresses.append(item[0])
return addresses
if __name__ == "__main__":
- if len(sys.argv) not in range(2,4):
+ if len(sys.argv) not in list(range(2,4)):
usage()
sys.exit(1)
@@ -35,15 +35,15 @@ def extractAddresses(data):
if len(sys.argv) > 2:
data = open(sys.argv[2]).read()
- pipe.communicate("\n".join(extractAddresses(data)))
+ pipe.communicate("\n".join(extractAddresses(data)).encode('ascii'))
else:
while True:
- data = raw_input()
+ data = input()
addresses = extractAddresses(data)
if len(addresses) == 0:
continue
-# print "[",addresses,"]"
+# print ( "[",addresses,"]" )
line = "\r\n".join(addresses)+"\r\n"
# line = line.ljust(125," ")
From 8fe2d3aa4bac509acf8573996568aaae76ba753d Mon Sep 17 00:00:00 2001
From: slaff
Date: Mon, 17 Jul 2017 22:19:23 +0200
Subject: [PATCH 26/35] HttpServer tuning to allow serving of more requests.
(#1187)
* - Workaround for issue with incorrect size of files (Disadvantages: The loading process looks slower because the browser waits for the TIMEOUT in order to determine the size)
- TcpClient: Added reporting for condition that shouldn't happen and is still not handled correctly at the moment.
- TcpServer: Decreased the minimum required heap size.
- LWIP: Decreased the TCP_MSL to 2 seconds. That will lead to faster garbage collection of tcp connections in TIME_WAIT state and will release resources faster.
* Decrease the memory usage by sharing the same parser settings.
---
Sming/SmingCore/DataSourceStream.h | 2 +-
.../SmingCore/Network/Http/HttpConnection.cpp | 38 +++++++++++++------
Sming/SmingCore/Network/Http/HttpConnection.h | 7 +++-
.../Network/Http/HttpServerConnection.cpp | 28 ++++++++------
.../Network/Http/HttpServerConnection.h | 3 +-
Sming/SmingCore/Network/TcpClient.cpp | 5 ++-
Sming/SmingCore/Network/TcpServer.h | 2 +-
.../third-party/.patches/esp-open-lwip.patch | 13 +++++++
8 files changed, 70 insertions(+), 28 deletions(-)
diff --git a/Sming/SmingCore/DataSourceStream.h b/Sming/SmingCore/DataSourceStream.h
index 0ea982f69e..2adbcb12d3 100644
--- a/Sming/SmingCore/DataSourceStream.h
+++ b/Sming/SmingCore/DataSourceStream.h
@@ -182,7 +182,7 @@ class FileStream : public IDataSourceStream
* @brief Return the total length of the stream
* @retval int -1 is returned when the size cannot be determined
*/
- int length() { return size; }
+ int length() { return -1; }
private:
file_t handle;
diff --git a/Sming/SmingCore/Network/Http/HttpConnection.cpp b/Sming/SmingCore/Network/Http/HttpConnection.cpp
index 079ec22f7d..7d4e3c33d6 100644
--- a/Sming/SmingCore/Network/Http/HttpConnection.cpp
+++ b/Sming/SmingCore/Network/Http/HttpConnection.cpp
@@ -20,28 +20,38 @@
#include "lwip/tcp_impl.h"
#endif
+bool HttpConnection::parserSettingsInitialized = false;
+http_parser_settings HttpConnection::parserSettings;
+
HttpConnection::HttpConnection(RequestQueue* queue): TcpClient(false), mode(eHCM_String) {
this->waitingQueue = queue;
http_parser_init(&parser, HTTP_RESPONSE);
parser.data = (void*)this;
- memset(&parserSettings, 0, sizeof(parserSettings));
+ if(!parserSettingsInitialized) {
+ memset(&parserSettings, 0, sizeof(parserSettings));
- // Notification callbacks: on_message_begin, on_headers_complete, on_message_complete.
- parserSettings.on_message_begin = staticOnMessageBegin;
- parserSettings.on_headers_complete = staticOnHeadersComplete;
- parserSettings.on_message_complete = staticOnMessageComplete;
+ // Notification callbacks: on_message_begin, on_headers_complete, on_message_complete.
+ parserSettings.on_message_begin = staticOnMessageBegin;
+ parserSettings.on_headers_complete = staticOnHeadersComplete;
+ parserSettings.on_message_complete = staticOnMessageComplete;
- parserSettings.on_chunk_header = staticOnChunkHeader;
- parserSettings.on_chunk_complete = staticOnChunkComplete;
+#ifndef COMPACT_MODE
+ parserSettings.on_chunk_header = staticOnChunkHeader;
+ parserSettings.on_chunk_complete = staticOnChunkComplete;
+#endif
+ // Data callbacks: on_url, (common) on_header_field, on_header_value, on_body;
+#ifndef COMPACT_MODE
+ parserSettings.on_status = staticOnStatus;
+#endif
+ parserSettings.on_header_field = staticOnHeaderField;
+ parserSettings.on_header_value = staticOnHeaderValue;
+ parserSettings.on_body = staticOnBody;
- // Data callbacks: on_url, (common) on_header_field, on_header_value, on_body;
- parserSettings.on_status = staticOnStatus;
- parserSettings.on_header_field = staticOnHeaderField;
- parserSettings.on_header_value = staticOnHeaderValue;
- parserSettings.on_body = staticOnBody;
+ parserSettingsInitialized = true;
+ }
}
bool HttpConnection::connect(const String& host, int port, bool useSsl /* = false */, uint32_t sslOptions /* = 0 */) {
@@ -266,9 +276,11 @@ int HttpConnection::staticOnHeadersComplete(http_parser* parser)
return error;
}
+#ifndef COMPACT_MODE
int HttpConnection::staticOnStatus(http_parser *parser, const char *at, size_t length) {
return 0;
}
+#endif
int HttpConnection::staticOnHeaderField(http_parser *parser, const char *at, size_t length)
{
@@ -334,6 +346,7 @@ int HttpConnection::staticOnBody(http_parser *parser, const char *at, size_t len
return 0;
}
+#ifndef COMPACT_MODE
int HttpConnection::staticOnChunkHeader(http_parser* parser) {
debugf("On chunk header");
return 0;
@@ -343,6 +356,7 @@ int HttpConnection::staticOnChunkComplete(http_parser* parser) {
debugf("On chunk complete");
return 0;
}
+#endif
err_t HttpConnection::onConnected(err_t err) {
if (err == ERR_OK) {
diff --git a/Sming/SmingCore/Network/Http/HttpConnection.h b/Sming/SmingCore/Network/Http/HttpConnection.h
index 15147c7815..2ea81f7072 100644
--- a/Sming/SmingCore/Network/Http/HttpConnection.h
+++ b/Sming/SmingCore/Network/Http/HttpConnection.h
@@ -89,13 +89,17 @@ class HttpConnection : protected TcpClient {
private:
static int IRAM_ATTR staticOnMessageBegin(http_parser* parser);
+#ifndef COMPACT_MODE
static int IRAM_ATTR staticOnStatus(http_parser *parser, const char *at, size_t length);
+#endif
static int IRAM_ATTR staticOnHeadersComplete(http_parser* parser);
static int IRAM_ATTR staticOnHeaderField(http_parser *parser, const char *at, size_t length);
static int IRAM_ATTR staticOnHeaderValue(http_parser *parser, const char *at, size_t length);
static int IRAM_ATTR staticOnBody(http_parser *parser, const char *at, size_t length);
+#ifndef COMPACT_MODE
static int IRAM_ATTR staticOnChunkHeader(http_parser* parser);
static int IRAM_ATTR staticOnChunkComplete(http_parser* parser);
+#endif
static int IRAM_ATTR staticOnMessageComplete(http_parser* parser);
protected:
@@ -105,7 +109,8 @@ class HttpConnection : protected TcpClient {
RequestQueue* waitingQueue;
RequestQueue executionQueue;
http_parser parser;
- http_parser_settings parserSettings;
+ static http_parser_settings parserSettings;
+ static bool parserSettingsInitialized;
HttpHeaders responseHeaders;
int code = 0;
diff --git a/Sming/SmingCore/Network/Http/HttpServerConnection.cpp b/Sming/SmingCore/Network/Http/HttpServerConnection.cpp
index 00d73c5f67..4030ea7797 100644
--- a/Sming/SmingCore/Network/Http/HttpServerConnection.cpp
+++ b/Sming/SmingCore/Network/Http/HttpServerConnection.cpp
@@ -17,6 +17,9 @@
#include "../../Services/cWebsocket/websocket.h"
#include "WebConstants.h"
+bool HttpServerConnection::parserSettingsInitialized = false;
+http_parser_settings HttpServerConnection::parserSettings;
+
HttpServerConnection::HttpServerConnection(tcp_pcb *clientTcp)
: TcpClient(clientTcp, 0, 0), state(eHCS_Ready)
{
@@ -24,17 +27,20 @@ HttpServerConnection::HttpServerConnection(tcp_pcb *clientTcp)
http_parser_init(&parser, HTTP_REQUEST);
parser.data = (void*)this;
- memset(&parserSettings, 0, sizeof(parserSettings));
- // Notification callbacks: on_message_begin, on_headers_complete, on_message_complete.
- parserSettings.on_message_begin = staticOnMessageBegin;
- parserSettings.on_headers_complete = staticOnHeadersComplete;
- parserSettings.on_message_complete = staticOnMessageComplete;
-
- // Data callbacks: on_url, (common) on_header_field, on_header_value, on_body;
- parserSettings.on_url = staticOnPath;
- parserSettings.on_header_field = staticOnHeaderField;
- parserSettings.on_header_value = staticOnHeaderValue;
- parserSettings.on_body = staticOnBody;
+ if(!parserSettingsInitialized) {
+ memset(&parserSettings, 0, sizeof(parserSettings));
+ // Notification callbacks: on_message_begin, on_headers_complete, on_message_complete.
+ parserSettings.on_message_begin = staticOnMessageBegin;
+ parserSettings.on_headers_complete = staticOnHeadersComplete;
+ parserSettings.on_message_complete = staticOnMessageComplete;
+
+ // Data callbacks: on_url, (common) on_header_field, on_header_value, on_body;
+ parserSettings.on_url = staticOnPath;
+ parserSettings.on_header_field = staticOnHeaderField;
+ parserSettings.on_header_value = staticOnHeaderValue;
+ parserSettings.on_body = staticOnBody;
+ parserSettingsInitialized = true;
+ }
}
HttpServerConnection::~HttpServerConnection()
diff --git a/Sming/SmingCore/Network/Http/HttpServerConnection.h b/Sming/SmingCore/Network/Http/HttpServerConnection.h
index e6d207ffce..6a68e415fa 100644
--- a/Sming/SmingCore/Network/Http/HttpServerConnection.h
+++ b/Sming/SmingCore/Network/Http/HttpServerConnection.h
@@ -78,7 +78,8 @@ class HttpServerConnection: public TcpClient
HttpConnectionState state;
http_parser parser;
- http_parser_settings parserSettings;
+ static http_parser_settings parserSettings;
+ static bool parserSettingsInitialized;
ResourceTree* resourceTree = NULL;
HttpResource* resource = NULL;
diff --git a/Sming/SmingCore/Network/TcpClient.cpp b/Sming/SmingCore/Network/TcpClient.cpp
index a70401d4e7..b327af36eb 100644
--- a/Sming/SmingCore/Network/TcpClient.cpp
+++ b/Sming/SmingCore/Network/TcpClient.cpp
@@ -81,8 +81,11 @@ bool TcpClient::send(const char* data, uint16_t len, bool forceCloseAfterSent /*
if (stream == NULL)
stream = new MemoryDataStream();
- if (stream->write((const uint8_t*)data, len) != len)
+ if (stream->write((const uint8_t*)data, len) != len) {
+ debug_e("ERROR: Unable to store %d bytes in output stream", len);
return false;
+ }
+
debugf("Storing %d bytes in stream", len);
asyncTotalLen += len;
diff --git a/Sming/SmingCore/Network/TcpServer.h b/Sming/SmingCore/Network/TcpServer.h
index dfd7c392a9..fd3fe8f3e3 100644
--- a/Sming/SmingCore/Network/TcpServer.h
+++ b/Sming/SmingCore/Network/TcpServer.h
@@ -48,7 +48,7 @@ class TcpServer: public TcpConnection {
uint16_t activeClients = 0;
protected:
- int minHeapSize = 6500;
+ int minHeapSize = 3000;
#ifdef ENABLE_SSL
int sslSessionCacheSize = 50;
diff --git a/Sming/third-party/.patches/esp-open-lwip.patch b/Sming/third-party/.patches/esp-open-lwip.patch
index e3bde91a99..9e1875e5b6 100644
--- a/Sming/third-party/.patches/esp-open-lwip.patch
+++ b/Sming/third-party/.patches/esp-open-lwip.patch
@@ -293,3 +293,16 @@ index ddb5984..fb677c6 100644
*optptr++ = DHCP_OPTION_ROUTER;
*optptr++ = 4;
*optptr++ = ip4_addr1( &if_ip.gw);
+diff --git a/include/lwip/tcp_impl.h b/include/lwip/tcp_impl.h
+index 24ca8bb..0c20b6a 100644
+--- a/include/lwip/tcp_impl.h
++++ b/include/lwip/tcp_impl.h
+@@ -130,7 +130,7 @@ u32_t tcp_update_rcv_ann_wnd(struct tcp_pcb *pcb)ICACHE_FLASH_ATTR;
+ #define TCP_OOSEQ_TIMEOUT 6U /* x RTO */
+
+ #ifndef TCP_MSL
+-#define TCP_MSL 60000UL /* The maximum segment lifetime in milliseconds */
++#define TCP_MSL 2000UL /* The maximum segment lifetime in milliseconds */
+ #endif
+
+ /* Keepalive values, compliant with RFC 1122. Don't change this unless you know what you're doing */
From 4389a0a9a46b1b1411725bb384817ca0ed679c1c Mon Sep 17 00:00:00 2001
From: slaff
Date: Fri, 21 Jul 2017 10:13:03 +0200
Subject: [PATCH 27/35] Feature/httpserver etag caching (#1194)
* Added etag caching mechanism.
If a stream provides a unique id then the HttpServer will use it as HTTP etag.
The Etag generation can be disabled if needed.
---
Sming/SmingCore/DataSourceStream.cpp | 12 +++++++++++
Sming/SmingCore/DataSourceStream.h | 8 +++++++
Sming/SmingCore/Network/Http/HttpResponse.cpp | 4 ++--
.../Network/Http/HttpServerConnection.cpp | 21 ++++++++++++++++++-
4 files changed, 42 insertions(+), 3 deletions(-)
diff --git a/Sming/SmingCore/DataSourceStream.cpp b/Sming/SmingCore/DataSourceStream.cpp
index 24d062d7ed..760c8d1b78 100644
--- a/Sming/SmingCore/DataSourceStream.cpp
+++ b/Sming/SmingCore/DataSourceStream.cpp
@@ -178,6 +178,18 @@ bool FileStream::fileExist()
return size != -1;
}
+String FileStream::id()
+{
+ spiffs_stat stat;
+ fileStats(handle, &stat);
+
+#define ETAG_SIZE 16
+ char buf[ETAG_SIZE];
+ m_snprintf(buf, ETAG_SIZE, "00f-%x-%x0-%x", stat.obj_id, stat.size, strlen((char*)stat.name));
+
+ return String(buf);
+}
+
///////////////////////////////////////////////////////////////////////////
TemplateFileStream::TemplateFileStream(const String& templateFileName)
diff --git a/Sming/SmingCore/DataSourceStream.h b/Sming/SmingCore/DataSourceStream.h
index 2adbcb12d3..fd81116c66 100644
--- a/Sming/SmingCore/DataSourceStream.h
+++ b/Sming/SmingCore/DataSourceStream.h
@@ -81,6 +81,12 @@ class IDataSourceStream
* @retval int -1 is returned when the size cannot be determined
*/
virtual int length() { return -1; }
+
+ /**
+ * @brief Returns unique id of the resource.
+ * @retval String the unique id of the stream.
+ */
+ virtual String id() { return String(); }
};
/// Memory data stream class
@@ -184,6 +190,8 @@ class FileStream : public IDataSourceStream
*/
int length() { return -1; }
+ virtual String id();
+
private:
file_t handle;
int pos;
diff --git a/Sming/SmingCore/Network/Http/HttpResponse.cpp b/Sming/SmingCore/Network/Http/HttpResponse.cpp
index 56fcab6482..1715b23b70 100644
--- a/Sming/SmingCore/Network/Http/HttpResponse.cpp
+++ b/Sming/SmingCore/Network/Http/HttpResponse.cpp
@@ -38,8 +38,8 @@ HttpResponse* HttpResponse::setCookie(const String& name, const String& value)
HttpResponse* HttpResponse::setCache(int maxAgeSeconds, bool isPublic /* = false */)
{
- String chache = String(isPublic ? "public" : "private") +", max-age=" + String(maxAgeSeconds) + ", must-revalidate";
- return setHeader("Cache-Control", chache);
+ String cache = String(isPublic ? "public" : "private") +", max-age=" + String(maxAgeSeconds) + ", must-revalidate";
+ return setHeader("Cache-Control", cache);
}
HttpResponse* HttpResponse::setAllowCrossDomainOrigin(const String& controlAllowOrigin)
diff --git a/Sming/SmingCore/Network/Http/HttpServerConnection.cpp b/Sming/SmingCore/Network/Http/HttpServerConnection.cpp
index 4030ea7797..d672da16cd 100644
--- a/Sming/SmingCore/Network/Http/HttpServerConnection.cpp
+++ b/Sming/SmingCore/Network/Http/HttpServerConnection.cpp
@@ -352,7 +352,26 @@ void HttpServerConnection::onReadyToSendData(TcpConnectionEvent sourceEvent)
return;
}
+ bool sendContent = (request.method != HTTP_HEAD);
+
if(!headersSent) {
+#ifndef DISABLE_HTTPSRV_ETAG
+ if(response.stream != NULL && !response.headers.contains("ETag")) {
+ String tag = response.stream->id();
+ if(tag.length() > 0) {
+ response.headers["ETag"] = String('"' + tag + '"');
+ }
+ }
+
+ if(request.headers.contains("If-Match") && response.headers.contains("ETag") &&
+ request.headers["If-Match"] == response.headers["ETag"]) {
+ if(request.method == HTTP_GET || request.method == HTTP_HEAD) {
+ response.code = HTTP_STATUS_NOT_MODIFIED;
+ response.headers["Content-Length"] = "0";
+ sendContent = false;
+ }
+ }
+#endif /* DISABLE_HTTPSRV_ETAG */
String statusLine = "HTTP/1.1 "+String(response.code) + " " + getStatus((enum http_status)response.code) + "\r\n";
writeString(statusLine, TCP_WRITE_FLAG_MORE | TCP_WRITE_FLAG_COPY);
@@ -390,7 +409,7 @@ void HttpServerConnection::onReadyToSendData(TcpConnectionEvent sourceEvent)
}
do {
- if(request.method == HTTP_HEAD) {
+ if(sendContent == false) {
if(response.stream != NULL) {
delete response.stream;
response.stream = NULL;
From 08143b57ef714242ad9be14b5d073455b851d280 Mon Sep 17 00:00:00 2001
From: slaff
Date: Fri, 21 Jul 2017 10:35:02 +0200
Subject: [PATCH 28/35] Fixes for styling issues reported by Codacy (#1196)
* Fixing python related issues reported by Codacy.
* Fixed docker related issues.
---
.../RF24/tests/pingpair_blocking/runtest.py | 2 +-
.../RF24/tests/pingpair_test/runtest.py | 2 +-
docker/Dockerfile | 2 +-
tools/decode-stacktrace.py | 23 +++++++++---------
tools/memanalyzer.py | 24 +++++++++----------
5 files changed, 26 insertions(+), 27 deletions(-)
diff --git a/Sming/Libraries/RF24/tests/pingpair_blocking/runtest.py b/Sming/Libraries/RF24/tests/pingpair_blocking/runtest.py
index 0772f95053..76b41ada68 100644
--- a/Sming/Libraries/RF24/tests/pingpair_blocking/runtest.py
+++ b/Sming/Libraries/RF24/tests/pingpair_blocking/runtest.py
@@ -3,7 +3,7 @@
import sys,serial
def read_until(token):
- while 1:
+ while 1:
line = ser.readline(None)
sys.stdout.write(line)
diff --git a/Sming/Libraries/RF24/tests/pingpair_test/runtest.py b/Sming/Libraries/RF24/tests/pingpair_test/runtest.py
index 45fb65cec1..03ab9a8b37 100644
--- a/Sming/Libraries/RF24/tests/pingpair_test/runtest.py
+++ b/Sming/Libraries/RF24/tests/pingpair_test/runtest.py
@@ -3,7 +3,7 @@
import sys,serial
def read_until(token):
- while 1:
+ while 1:
line = ser.readline(None,"\r")
sys.stdout.write(line)
diff --git a/docker/Dockerfile b/docker/Dockerfile
index c148de5df6..98b53dfe02 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -8,7 +8,7 @@ MAINTAINER Slavey Karadzhov
COPY assets/welcome.html /cloud9/plugins/c9.ide.welcome/welcome.html
COPY assets/welcome.js /cloud9/plugins/c9.ide.welcome/welcome.js
-RUN cd /workspace && git clone https://github.com/SmingHub/Sming.git
+RUN git clone https://github.com/SmingHub/Sming.git /workspace/Sming
ENV SMING_HOME /workspace/Sming/Sming
diff --git a/tools/decode-stacktrace.py b/tools/decode-stacktrace.py
index 77791cbfb2..b1ac29e871 100755
--- a/tools/decode-stacktrace.py
+++ b/tools/decode-stacktrace.py
@@ -6,33 +6,32 @@
#
########################################################
import shlex
-import select
import subprocess
import sys
import re
def usage():
print("Usage: \n\t%s []" % sys.argv[0])
-
+
def extractAddresses(data):
m = re.findall("(40[0-2](\d|[a-f]){5})", data)
if len(m) == 0:
return m
-
+
addresses = []
for item in m:
- addresses.append(item[0])
-
- return addresses
-
+ addresses.append(item[0])
+
+ return addresses
+
if __name__ == "__main__":
if len(sys.argv) not in list(range(2,4)):
usage()
sys.exit(1)
-
+
command = "xtensa-lx106-elf-addr2line -aipfC -e '%s' " % sys.argv[1]
pipe = subprocess.Popen(shlex.split(command), bufsize=1, stdin=subprocess.PIPE)
-
+
if len(sys.argv) > 2:
data = open(sys.argv[2]).read()
pipe.communicate("\n".join(extractAddresses(data)).encode('ascii'))
@@ -42,12 +41,12 @@ def extractAddresses(data):
addresses = extractAddresses(data)
if len(addresses) == 0:
continue
-
+
# print ( "[",addresses,"]" )
-
+
line = "\r\n".join(addresses)+"\r\n"
# line = line.ljust(125," ")
-
+
pipe.stdin.write(line)
pipe.stdin.flush()
diff --git a/tools/memanalyzer.py b/tools/memanalyzer.py
index 715fb9d235..abfcc1c53f 100644
--- a/tools/memanalyzer.py
+++ b/tools/memanalyzer.py
@@ -20,7 +20,7 @@
("rodata", "ReadOnly Data (RAM)"),
("bss", "Uninitialized Data (RAM)"),
("text", "Cached Code (IRAM)"),
- ("irom0_text", "Uncached Code (SPI)")
+ ("irom0_text", "Uncached Code (SPI)")
])
if len(sys.argv) < 2:
@@ -35,10 +35,10 @@
sys.exit(1)
-command = "%s -t '%s' " % (sys.argv[1], sys.argv[2])
+command = "%s -t '%s' " % (sys.argv[1], sys.argv[2])
response = subprocess.check_output(shlex.split(command))
if isinstance(response, bytes):
- response = response.decode('utf-8')
+ response = response.decode('utf-8')
lines = response.split('\n')
print("{0: >10}|{1: >30}|{2: >12}|{3: >12}|{4: >8}".format("Section", "Description", "Start (hex)", "End (hex)", "Used space"));
@@ -48,32 +48,32 @@
usedIRAM = 0;
i = 0
-for (id, descr) in list(sections.items()):
- sectionStartToken = " _%s_start" % id
- sectionEndToken = " _%s_end" % id;
+for (name, descr) in list(sections.items()):
+ sectionStartToken = " _%s_start" % name
+ sectionEndToken = " _%s_end" % name
sectionStart = -1;
sectionEnd = -1;
for line in lines:
if sectionStartToken in line:
data = line.split(' ')
sectionStart = int(data[0], 16)
-
- if sectionEndToken in line:
+
+ if sectionEndToken in line:
data = line.split(' ')
sectionEnd = int(data[0], 16)
-
+
if sectionStart != -1 and sectionEnd != -1:
break
-
+
sectionLength = sectionEnd - sectionStart
if i < 3:
usedRAM += sectionLength
if i == 3:
usedIRAM = TOTAL_DRAM - sectionLength;
- print("{0: >10}|{1: >30}|{2:12X}|{3:12X}|{4:8}".format(id, descr, sectionStart, sectionEnd, sectionLength))
+ print("{0: >10}|{1: >30}|{2:12X}|{3:12X}|{4:8}".format(name, descr, sectionStart, sectionEnd, sectionLength))
i += 1
-
+
print("Total Used RAM : %d" % usedRAM)
print("Free RAM : %d" % (TOTAL_IRAM - usedRAM))
print("Free IRam : %d" % usedIRAM)
From f4c2d01834a49b10ae0d374d7feeeab38f197d95 Mon Sep 17 00:00:00 2001
From: jochenjagers
Date: Fri, 21 Jul 2017 11:21:31 +0200
Subject: [PATCH 29/35] Handle incomplete frame to prevent WebsocketClient
ending in an endless loop (#1189)
---
Sming/SmingCore/Network/WebsocketFrame.cpp | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/Sming/SmingCore/Network/WebsocketFrame.cpp b/Sming/SmingCore/Network/WebsocketFrame.cpp
index 2497787992..bb694ee873 100644
--- a/Sming/SmingCore/Network/WebsocketFrame.cpp
+++ b/Sming/SmingCore/Network/WebsocketFrame.cpp
@@ -185,6 +185,12 @@ uint8_t WebsocketFrameClass::_getFrameSizes(uint8_t* buffer, size_t length)
{
_nextReadOffset = 0; // single websocket frame in buffer
}
+ else if(length < _nextReadOffset)
+ {
+ // Frame is incomplete
+ _frameType = WSFrameType::incomplete;
+ return false;
+ }
return true;
}
@@ -197,7 +203,8 @@ uint8_t WebsocketFrameClass::decodeFrame(uint8_t * buffer, size_t length)
WSFrameType op = (WSFrameType)(buffer[0] & 0b00001111); // Extracting Opcode
uint8_t fin = buffer[0] & 0b10000000; // Extracting Fin Bit (Single Frame)
- if (op == WSFrameType::continuation || op == WSFrameType::text || op == WSFrameType::binary) //Data frames
+ // At least there must be one byte that op and fin are vaild
+ if (length > 0 && op == WSFrameType::continuation || op == WSFrameType::text || op == WSFrameType::binary) //Data frames
{
if (fin > 0)
{
From 63c447b5c7ebbc8816b2ab17487092cf6a44b5dc Mon Sep 17 00:00:00 2001
From: slaff
Date: Fri, 21 Jul 2017 20:49:19 +0200
Subject: [PATCH 30/35] Feature/auto deployment on release (#1198)
* Automated the API documentation update on new release.
* Simplified the CI process. CUSTOM_LWIP is enabled by default and there is no need for a separate check any longer.
* Updated the networking documentation.
---
.travis.yml | 23 ++++++++++++++----
.travis/deploy.sh | 29 +++++++++++++++++++++++
Sming/SmingCore/Network/DNSServer.h | 6 +++++
Sming/SmingCore/Network/FTPServer.h | 7 ++++++
Sming/SmingCore/Network/HttpClient.h | 7 ++++++
Sming/SmingCore/Network/HttpServer.h | 7 ++++++
Sming/SmingCore/Network/MqttClient.h | 7 ++++++
Sming/SmingCore/Network/NetUtils.h | 5 ++++
Sming/SmingCore/Network/NtpClient.h | 1 +
Sming/SmingCore/Network/TcpClient.h | 7 ++++++
Sming/SmingCore/Network/TcpConnection.h | 6 +++++
Sming/SmingCore/Network/TcpServer.h | 9 +++++++
Sming/SmingCore/Network/TelnetServer.h | 7 ++++++
Sming/SmingCore/Network/URL.h | 8 +++++++
Sming/SmingCore/Network/UdpConnection.h | 7 ++++++
Sming/SmingCore/Network/WebConstants.h | 8 +++++++
Sming/SmingCore/Network/WebsocketClient.h | 7 ++++++
17 files changed, 147 insertions(+), 4 deletions(-)
create mode 100644 .travis/deploy.sh
diff --git a/.travis.yml b/.travis.yml
index a428ad2054..c5cd0aa543 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,7 +4,8 @@ language: cpp
env:
global:
- SDK_BUILD=258
-
+ - secure: Db9Cnv+oOmmQMm6aIf3H5VYHaas04uGOtvJMsq7NW05oyDVGCgV5FayjFPVzNHHgv85em1u1CPqX3p7eHWLSKMjARcEpLavXM31HW0RPxvserSpXI7f49EBi6ENgCPre4NGMWpdJgvIhmAfcEMwyLUBqRDmfH4KqqE8V5ZbhvacCbaD2cEOsPDjbkpA66VYp3srTmVUR4cC0ehUdg7odxVOWHaJbA068jJjwz/ggbYMkVljcFkjVHtZAIiZDN1vBGRWGwTjM4TMXwJmw07WumBwhZw6Qm7OShGfBTyg5/6Obqk1QZ///6BQCUD+bGhLlfEleEB48YJXwLD96HXgUwu/wZ7xWStQCWW5GQRPgXaufwZcc1TySJxaDeMhk90cIbUsjXGhmhV+rpM/5PMZTvpTOJbKrz2oY2qqFEZJGEYGoH24LHp4yPpAvQCmqjeLcQj/JiHeL9nKUy+mC3yOPLR/DOTa7t7zN8vuKqm0G0Af3DXXuum2kkzBgHFCNiiLedF2/7BVe/nAbOJLpuQwfVVOqpxIpTzKg05oPmjSsFPp4u03Yso3Kc6ulJQ354mYmnZD34jah5FaWo8YkGCmAGLIaqpcV62LCTSDK58ZMpEU1fy3jANlmktDQlaCUvniUo+c0mqmlstRpzGathb4u1nNHdgB/rjzDx64ug2MmllI=
+
matrix:
include:
- os: linux
@@ -18,8 +19,15 @@ addons:
apt:
sources:
- ubuntu-toolchain-r-test
+ - sourceline: 'ppa:libreoffice/libreoffice-4-2'
packages:
- bsdtar
+ - doxygen
+ - doxygen-doc
+ - doxygen-latex
+ - doxygen-gui
+ - graphviz
+
install:
- if [ "$SDK_VERSION" != "2.0.0" ] && [ "$TRAVIS_OS_NAME" == "osx" ]; then export SDK_FILE_NAME="esp-alt-sdk-v${SDK_VERSION}.${SDK_BUILD}-macos-x86_64.zip"; fi
- if [ "$SDK_VERSION" != "2.0.0" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then export SDK_FILE_NAME="esp-alt-sdk-v${SDK_VERSION}.${SDK_BUILD}-linux-x86_64.tar.gz"; fi
@@ -27,7 +35,8 @@ install:
- if [ "$SDK_VERSION" != "2.0.0" ]; then wget https://bintray.com/artifact/download/kireevco/generic/${SDK_FILE_NAME}; fi
- if [ "$SDK_VERSION" != "2.0.0" ]; then bsdtar -xf ${SDK_FILE_NAME} -C $TRAVIS_BUILD_DIR/opt/esp-alt-sdk; fi
- if [ "$SDK_VERSION" == "2.0.0" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then wget https://github.com/nodemcu/nodemcu-firmware/raw/master/tools/esp-open-sdk.tar.xz; tar -Jxvf esp-open-sdk.tar.xz; ln -s `pwd`/esp-open-sdk/xtensa-lx106-elf $TRAVIS_BUILD_DIR/opt/esp-alt-sdk/. ; fi
- - if [ "$SDK_VERSION" == "2.0.0" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then wget http://bbs.espressif.com/download/file.php?id=1690 -O sdk.zip; unzip sdk.zip; ln -s `pwd`/ESP8266_NONOS_SDK/ $TRAVIS_BUILD_DIR/opt/esp-alt-sdk/sdk; fi
+ - if [ "$SDK_VERSION" == "2.0.0" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then wget http://bbs.espressif.com/download/file.php?id=1690 -O sdk.zip; unzip sdk.zip; ln -s `pwd`/ESP8266_NONOS_SDK/ $TRAVIS_BUILD_DIR/opt/esp-alt-sdk/sdk; export DEPLOY='true'; fi
+
script:
- export CHANGED_FILES=`git diff --diff-filter=AMD HEAD HEAD^ --name-only`
- export CHANGED_PROJECTS=`for i in $CHANGED_FILES; do echo "$i" | grep '^samples/' | cut -d'/' -f2; done | uniq`
@@ -47,5 +56,11 @@ script:
- make clean samples-clean
- make ENABLE_CUSTOM_HEAP=1
- make Basic_Blink ENABLE_CUSTOM_HEAP=1
- - make clean samples-clean
- - make ENABLE_CUSTOM_LWIP=1; make samples ENABLE_CUSTOM_LWIP=1
+
+deploy:
+ provider: script
+ script: sh $TRAVIS_BUILD_DIR/.travis/deploy.sh $TRAVIS_TAG
+ skip_cleanup: true
+ on:
+ tags: true
+ condition: $DEPLOY == true
diff --git a/.travis/deploy.sh b/.travis/deploy.sh
new file mode 100644
index 0000000000..a614d0783c
--- /dev/null
+++ b/.travis/deploy.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+set -e # exit with nonzero exit code if anything fails
+
+TAG=$1
+if [ -z $TAG ]; then
+ echo "Usage:\n\t$0 \n";
+ exit 1;
+fi
+
+
+# Get information about the release
+# TODO: ...
+
+# Update documentation
+cd $SMING_HOME
+make docs
+cd ..
+
+git fetch origin gh-pages:gh-pages
+git checkout gh-pages
+
+DOCS_DIR=$SMING_HOME/../api
+
+rm -rf $DOCS_DIR
+cp -r $SMING_HOME/../docs/api/sming/ $DOCS_DIR
+git add -A $DOCS_DIR
+git commit -m "Updated the API docs to version $TAG." || 1
+
+git push https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages
diff --git a/Sming/SmingCore/Network/DNSServer.h b/Sming/SmingCore/Network/DNSServer.h
index 679ddeaa43..aa897c9f1b 100644
--- a/Sming/SmingCore/Network/DNSServer.h
+++ b/Sming/SmingCore/Network/DNSServer.h
@@ -11,6 +11,11 @@
* Created on March 4, 2016
*/
+/** @defgroup dnsserver DNS server
+ * @brief Provides DNS server
+ * @ingroup udp
+ * @{
+ */
#ifndef DNSServer_h
#define DNSServer_h
@@ -83,4 +88,5 @@ class DNSServer : public UdpConnection
};
+/** @} */
#endif //DNSServer_h
diff --git a/Sming/SmingCore/Network/FTPServer.h b/Sming/SmingCore/Network/FTPServer.h
index 3b3ca17479..0fcee67c2b 100644
--- a/Sming/SmingCore/Network/FTPServer.h
+++ b/Sming/SmingCore/Network/FTPServer.h
@@ -5,6 +5,12 @@
* All files of the Sming Core are provided under the LGPL v3 license.
****/
+/** @defgroup ftpserver FTP server
+ * @brief Provides FTP server
+ * @ingroup tcpserver
+ * @{
+ */
+
#ifndef _SMING_CORE_FTPSERVER_H_
#define _SMING_CORE_FTPSERVER_H_
@@ -33,4 +39,5 @@ class FTPServer: public TcpServer
HashMap users;
};
+/** @} */
#endif /* _SMING_CORE_FTPServer_H_ */
diff --git a/Sming/SmingCore/Network/HttpClient.h b/Sming/SmingCore/Network/HttpClient.h
index da1bd1fedd..afca2fe1ee 100644
--- a/Sming/SmingCore/Network/HttpClient.h
+++ b/Sming/SmingCore/Network/HttpClient.h
@@ -10,6 +10,12 @@
*
****/
+/** @defgroup httpclient HTTP client
+ * @brief Provides HTTP/S client
+ * @ingroup tcpclient
+ * @{
+ */
+
#ifndef _SMING_CORE_NETWORK_HTTPCLIENT_H_
#define _SMING_CORE_NETWORK_HTTPCLIENT_H_
@@ -93,4 +99,5 @@ class HttpClient
#endif
};
+/** @} */
#endif /* _SMING_CORE_NETWORK_HTTPCLIENT_H_ */
diff --git a/Sming/SmingCore/Network/HttpServer.h b/Sming/SmingCore/Network/HttpServer.h
index 85b8b0516c..dfb68a555a 100644
--- a/Sming/SmingCore/Network/HttpServer.h
+++ b/Sming/SmingCore/Network/HttpServer.h
@@ -10,6 +10,12 @@
*
****/
+/** @defgroup httpserver HTTP server
+ * @brief Provides powerful HTTP/S + Websocket server
+ * @ingroup tcpserver
+ * @{
+ */
+
#ifndef _SMING_CORE_HTTPSERVER_H_
#define _SMING_CORE_HTTPSERVER_H_
@@ -78,4 +84,5 @@ class HttpServer: public TcpServer
BodyParsers bodyParsers;
};
+/** @} */
#endif /* _SMING_CORE_HTTPSERVER_H_ */
diff --git a/Sming/SmingCore/Network/MqttClient.h b/Sming/SmingCore/Network/MqttClient.h
index 3f9b1b09ea..3c5d424ecf 100644
--- a/Sming/SmingCore/Network/MqttClient.h
+++ b/Sming/SmingCore/Network/MqttClient.h
@@ -5,6 +5,12 @@
* All files of the Sming Core are provided under the LGPL v3 license.
****/
+/** @defgroup mqttclient MQTT client
+ * @brief Provides MQTT client
+ * @ingroup tcpclient
+ * @{
+ */
+
#ifndef _SMING_CORE_NETWORK_MqttClient_H_
#define _SMING_CORE_NETWORK_MqttClient_H_
@@ -80,4 +86,5 @@ class MqttClient: protected TcpClient
HashMap onDeliveryQueue;
};
+/** @} */
#endif /* _SMING_CORE_NETWORK_MqttClient_H_ */
diff --git a/Sming/SmingCore/Network/NetUtils.h b/Sming/SmingCore/Network/NetUtils.h
index 32108f0027..e2459a2cc5 100644
--- a/Sming/SmingCore/Network/NetUtils.h
+++ b/Sming/SmingCore/Network/NetUtils.h
@@ -5,6 +5,10 @@
* All files of the Sming Core are provided under the LGPL v3 license.
****/
+/** @defgroup networking Networking
+ * @{
+ */
+
#ifndef _SMING_CORE_NETWORK_NETUTILS_H_
#define _SMING_CORE_NETWORK_NETUTILS_H_
@@ -37,4 +41,5 @@ class NetUtils
static bool ipClientRoutingFixed;
};
+/** @} */
#endif /* _SMING_CORE_NETWORK_NETUTILS_H_ */
diff --git a/Sming/SmingCore/Network/NtpClient.h b/Sming/SmingCore/Network/NtpClient.h
index 5ca4651d7b..57357553e1 100644
--- a/Sming/SmingCore/Network/NtpClient.h
+++ b/Sming/SmingCore/Network/NtpClient.h
@@ -1,6 +1,7 @@
/** @defgroup ntp Network Time Protocol client
* @brief Provides NTP client
* @ingroup datetime
+ * @ingroup udp
* @{
*/
#ifndef APP_NTPCLIENT_H_
diff --git a/Sming/SmingCore/Network/TcpClient.h b/Sming/SmingCore/Network/TcpClient.h
index 30fbf3a9bc..4f27342ca0 100644
--- a/Sming/SmingCore/Network/TcpClient.h
+++ b/Sming/SmingCore/Network/TcpClient.h
@@ -5,6 +5,12 @@
* All files of the Sming Core are provided under the LGPL v3 license.
****/
+/** @defgroup tcpclient Clients
+ * @brief Provides base TCP client
+ * @ingroup tcp
+ * @{
+ */
+
#ifndef _SMING_CORE_TCPCLIENT_H_
#define _SMING_CORE_TCPCLIENT_H_
@@ -83,4 +89,5 @@ class TcpClient : public TcpConnection
int16_t asyncTotalLen = 0;
};
+/** @} */
#endif /* _SMING_CORE_TCPCLIENT_H_ */
diff --git a/Sming/SmingCore/Network/TcpConnection.h b/Sming/SmingCore/Network/TcpConnection.h
index 3d4855a45d..a902e3b55a 100644
--- a/Sming/SmingCore/Network/TcpConnection.h
+++ b/Sming/SmingCore/Network/TcpConnection.h
@@ -5,6 +5,11 @@
* All files of the Sming Core are provided under the LGPL v3 license.
****/
+/** @defgroup tcp TCP
+ * @ingroup networking
+ * @{
+ */
+
#ifndef _SMING_CORE_TCPCONNECTION_H_
#define _SMING_CORE_TCPCONNECTION_H_
@@ -231,4 +236,5 @@ class TcpConnection
bool useSsl = false;
};
+/** @} */
#endif /* _SMING_CORE_TCPCONNECTION_H_ */
diff --git a/Sming/SmingCore/Network/TcpServer.h b/Sming/SmingCore/Network/TcpServer.h
index fd3fe8f3e3..f70d69b171 100644
--- a/Sming/SmingCore/Network/TcpServer.h
+++ b/Sming/SmingCore/Network/TcpServer.h
@@ -5,6 +5,14 @@
* All files of the Sming Core are provided under the LGPL v3 license.
****/
+
+/** @defgroup tcpserver Servers
+ * @brief Provides the base for building TCP servers
+ * @ingroup tcp
+ *
+ * @{
+ */
+
#ifndef _SMING_CORE_TCPSERVER_H_
#define _SMING_CORE_TCPSERVER_H_
@@ -61,4 +69,5 @@ class TcpServer: public TcpConnection {
TcpClientConnectDelegate clientConnectDelegate = NULL;
};
+/** @} */
#endif /* _SMING_CORE_TCPSERVER_H_ */
diff --git a/Sming/SmingCore/Network/TelnetServer.h b/Sming/SmingCore/Network/TelnetServer.h
index 0c7582d8e2..dba4e8c60b 100644
--- a/Sming/SmingCore/Network/TelnetServer.h
+++ b/Sming/SmingCore/Network/TelnetServer.h
@@ -5,6 +5,12 @@
* Author: Herman
*/
+/** @defgroup telnetserver Telnet server
+ * @brief Provides Telnet server
+ * @ingroup tcpserver
+ * @{
+ */
+
#ifndef APP_TELNETSERVER_H_
#define APP_TELNETSERVER_H_
@@ -42,4 +48,5 @@ class TelnetServer : public TcpServer
bool telnetCommand = true;
};
+/** @} */
#endif /* APP_TELNETSERVER_H_ */
diff --git a/Sming/SmingCore/Network/URL.h b/Sming/SmingCore/Network/URL.h
index 33e16e3b2f..1912b12e08 100644
--- a/Sming/SmingCore/Network/URL.h
+++ b/Sming/SmingCore/Network/URL.h
@@ -5,6 +5,13 @@
* All files of the Sming Core are provided under the LGPL v3 license.
****/
+/** @defgroup url URL
+ * @brief Provides URL handling
+ * @ingroup httpserver
+ * @ingroup httpclient
+ * @{
+ */
+
#ifndef _SMING_CORE_NETWORK_URL_H_
#define _SMING_CORE_NETWORK_URL_H_
@@ -31,4 +38,5 @@ class URL
String Query;
};
+/** @} */
#endif /* _SMING_CORE_NETWORK_URL_H_ */
diff --git a/Sming/SmingCore/Network/UdpConnection.h b/Sming/SmingCore/Network/UdpConnection.h
index a321263d10..0123dbe135 100644
--- a/Sming/SmingCore/Network/UdpConnection.h
+++ b/Sming/SmingCore/Network/UdpConnection.h
@@ -5,6 +5,12 @@
* All files of the Sming Core are provided under the LGPL v3 license.
****/
+/** @defgroup udp UDP
+ * @brief Provides base for UDP clients or services
+ * @ingroup networking
+ * @{
+ */
+
#ifndef SMINGCORE_NETWORK_UDPCONNECTION_H_
#define SMINGCORE_NETWORK_UDPCONNECTION_H_
@@ -49,4 +55,5 @@ class UdpConnection
UdpConnectionDataDelegate onDataCallback;
};
+/** @} */
#endif /* SMINGCORE_NETWORK_UDPCONNECTION_H_ */
diff --git a/Sming/SmingCore/Network/WebConstants.h b/Sming/SmingCore/Network/WebConstants.h
index 8d43855bb9..1b8e708d26 100644
--- a/Sming/SmingCore/Network/WebConstants.h
+++ b/Sming/SmingCore/Network/WebConstants.h
@@ -5,6 +5,13 @@
* All files of the Sming Core are provided under the LGPL v3 license.
****/
+/** @defgroup httpconsts HTTP constants to be used with HTTP client or HTTP server
+ * @brief Provides HTTP constants
+ * @ingroup httpserver
+ * @ingroup httpclient
+ * @{
+ */
+
#ifndef _SMING_CORE_NETWORK_WEBCONSTANTS_H_
#define _SMING_CORE_NETWORK_WEBCONSTANTS_H_
@@ -81,4 +88,5 @@ namespace ContentType
}
};
+/** @} */
#endif /* _SMING_CORE_NETWORK_WEBCONSTANTS_H_ */
diff --git a/Sming/SmingCore/Network/WebsocketClient.h b/Sming/SmingCore/Network/WebsocketClient.h
index 1ed1cdf231..7342332ec3 100644
--- a/Sming/SmingCore/Network/WebsocketClient.h
+++ b/Sming/SmingCore/Network/WebsocketClient.h
@@ -10,6 +10,12 @@
*
*/
+/** @defgroup wsclient WebSocket client
+ * @brief Provides WebSocket client
+ * @ingroup tcpclient
+ * @{
+ */
+
#ifndef WEBSOCKETCLIENT_H
#define WEBSOCKETCLIENT_H
@@ -130,5 +136,6 @@ class WebsocketClient: protected TcpClient
String _key;
};
+/** @} */
#endif /* WEBSOCKETCLIENT_H */
From a7d3360fc9ed677d119c599e94bcf87c209e6397 Mon Sep 17 00:00:00 2001
From: Andriy Petrynchyn
Date: Tue, 25 Jul 2017 10:43:15 +0300
Subject: [PATCH 31/35] Fixed WebSocket sample HTML page (#1201)
---
samples/HttpServer_WebSockets/files/index.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/samples/HttpServer_WebSockets/files/index.html b/samples/HttpServer_WebSockets/files/index.html
index 9546122011..50ca1f54ec 100644
--- a/samples/HttpServer_WebSockets/files/index.html
+++ b/samples/HttpServer_WebSockets/files/index.html
@@ -16,7 +16,7 @@
function testWebSocket()
{
- var wsUri = "ws://" + location.host + "/";
+ var wsUri = "ws://" + location.host + "/ws";
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) { onOpen(evt) };
websocket.onclose = function(evt) { onClose(evt) };
From 6968d3eab5b82d440d9db0e6484a8c1d61b0d217 Mon Sep 17 00:00:00 2001
From: slaff
Date: Tue, 25 Jul 2017 09:56:45 +0200
Subject: [PATCH 32/35] Added example demonstrating Js and CSS combining ...
(#1200)
* Added example detailing how to optimize file delivery.
* Added Last-Modified header example.
---
samples/HttpServer_ConfigNetwork/.gitignore | 1 +
samples/HttpServer_ConfigNetwork/Makefile | 7 +
samples/HttpServer_ConfigNetwork/Readme.md | 25 ++
.../app/application.cpp | 17 +
samples/HttpServer_ConfigNetwork/gulpfile.js | 89 ++++
samples/HttpServer_ConfigNetwork/package.json | 22 +
.../web/build/.lastModified | 1 +
.../web/build/bootstrap-core.css.gz | Bin 0 -> 15861 bytes
.../web/build/bootstrap.css.gz | Bin 15615 -> 0 bytes
.../web/build/core.js.gz | Bin 0 -> 30474 bytes
.../web/build/index.html | 298 +-------------
.../web/build/jquery.js.gz | Bin 30153 -> 0 bytes
.../web/build/settings.html | 114 +-----
.../web/build/style.css | 382 ------------------
.../web/dev/index.html | 5 +
.../web/dev/settings.html | 6 +
16 files changed, 177 insertions(+), 790 deletions(-)
create mode 100644 samples/HttpServer_ConfigNetwork/.gitignore
create mode 100644 samples/HttpServer_ConfigNetwork/Readme.md
create mode 100644 samples/HttpServer_ConfigNetwork/gulpfile.js
create mode 100644 samples/HttpServer_ConfigNetwork/package.json
create mode 100644 samples/HttpServer_ConfigNetwork/web/build/.lastModified
create mode 100644 samples/HttpServer_ConfigNetwork/web/build/bootstrap-core.css.gz
delete mode 100644 samples/HttpServer_ConfigNetwork/web/build/bootstrap.css.gz
create mode 100644 samples/HttpServer_ConfigNetwork/web/build/core.js.gz
delete mode 100644 samples/HttpServer_ConfigNetwork/web/build/jquery.js.gz
delete mode 100644 samples/HttpServer_ConfigNetwork/web/build/style.css
diff --git a/samples/HttpServer_ConfigNetwork/.gitignore b/samples/HttpServer_ConfigNetwork/.gitignore
new file mode 100644
index 0000000000..3c3629e647
--- /dev/null
+++ b/samples/HttpServer_ConfigNetwork/.gitignore
@@ -0,0 +1 @@
+node_modules
diff --git a/samples/HttpServer_ConfigNetwork/Makefile b/samples/HttpServer_ConfigNetwork/Makefile
index 16d76cd676..254c343ac5 100644
--- a/samples/HttpServer_ConfigNetwork/Makefile
+++ b/samples/HttpServer_ConfigNetwork/Makefile
@@ -22,3 +22,10 @@ include $(SMING_HOME)/Makefile-rboot.mk
else
include $(SMING_HOME)/Makefile-project.mk
endif
+
+web-pack:
+ $(Q) gulp
+ $(Q) date +'%a, %d %b %Y %H:%M:%S GMT' -u > web/build/.lastModified
+
+web-upload: web-pack spiff_update
+ $(ESPTOOL) -p $(COM_PORT) -b $(COM_SPEED_ESPTOOL) write_flash $(flashimageoptions) $(SPIFF_START_OFFSET) $(SPIFF_BIN_OUT)
diff --git a/samples/HttpServer_ConfigNetwork/Readme.md b/samples/HttpServer_ConfigNetwork/Readme.md
new file mode 100644
index 0000000000..930221384e
--- /dev/null
+++ b/samples/HttpServer_ConfigNetwork/Readme.md
@@ -0,0 +1,25 @@
+# Introduction
+
+The HTTP server coming with Sming is quite powerful but it is limited from the available resources of the underlining hardware (your favorite ESP8266 microcontroller). Serving multiple files at once can be problematic. It is not the size of the files that can cause problems, but the number of simultaneous files that need to be delivered. Therefore if you serve multiple CSS or JS files you can optimize your web application before uploading it into your ESP8266 using the advice below.
+
+# Optimizing File Delivery
+
+In this example you will see how to combine CSS and JS files, compress them and deliver the optimized content via the HTTP server.
+
+## Installation
+
+The file optimization uses `gulp`. To install it and the needed gulp packages you need to install first [npm](https://www.npmjs.com/).
+Npm is the Node.JS package manager. Once you are done with the installation you can run from the command line the following:
+
+ npm install
+
+ The command above will install gulp and its dependencies.
+
+## Usage
+
+During the development of your web application you should work only in the `web/dev/` folder. Once you are ready with the application you can `pack` the resources and `upload` them to your device. The commands are
+
+ make web-pack
+ make web-upload
+
+That should be it.
\ No newline at end of file
diff --git a/samples/HttpServer_ConfigNetwork/app/application.cpp b/samples/HttpServer_ConfigNetwork/app/application.cpp
index 81e4ad4312..faf2234b5d 100644
--- a/samples/HttpServer_ConfigNetwork/app/application.cpp
+++ b/samples/HttpServer_ConfigNetwork/app/application.cpp
@@ -9,6 +9,8 @@ BssList networks;
String network, password;
Timer connectionTimer;
+String lastModified;
+
void onIndex(HttpRequest &request, HttpResponse &response)
{
TemplateFileStream *tmpl = new TemplateFileStream("index.html");
@@ -53,6 +55,11 @@ void onIpConfig(HttpRequest &request, HttpResponse &response)
void onFile(HttpRequest &request, HttpResponse &response)
{
+ if (lastModified.length() >0 && request.getHeader("If-Modified-Since").equals(lastModified)) {
+ response.code = HTTP_STATUS_NOT_MODIFIED;
+ return;
+ }
+
String file = request.getPath();
if (file[0] == '/')
file = file.substring(1);
@@ -61,6 +68,10 @@ void onFile(HttpRequest &request, HttpResponse &response)
response.forbidden();
else
{
+ if(lastModified.length() > 0) {
+ response.setHeader("Last-Modified", lastModified);
+ }
+
response.setCache(86400, true); // It's important to use cache for better performance.
response.sendFile(file);
}
@@ -193,6 +204,12 @@ void init()
{
spiffs_mount(); // Mount file system, in order to work with files
+ if(fileExist(".lastModified")) {
+ // The last modification
+ lastModified = fileGetContent(".lastModified");
+ lastModified.trim();
+ }
+
Serial.begin(SERIAL_BAUD_RATE); // 115200 by default
Serial.systemDebugOutput(true); // Enable debug output to serial
AppSettings.load();
diff --git a/samples/HttpServer_ConfigNetwork/gulpfile.js b/samples/HttpServer_ConfigNetwork/gulpfile.js
new file mode 100644
index 0000000000..ea3e869b99
--- /dev/null
+++ b/samples/HttpServer_ConfigNetwork/gulpfile.js
@@ -0,0 +1,89 @@
+/*
+
+ESP8266 file system builder with PlatformIO support
+
+Copyright (C) 2016 by Xose Pérez
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+
+*/
+
+// -----------------------------------------------------------------------------
+// File system builder
+// -----------------------------------------------------------------------------
+
+const gulp = require('gulp');
+const plumber = require('gulp-plumber');
+const htmlmin = require('gulp-htmlmin');
+const cleancss = require('gulp-clean-css');
+const uglify = require('gulp-uglify');
+const gzip = require('gulp-gzip');
+const del = require('del');
+const useref = require('gulp-useref');
+const gulpif = require('gulp-if');
+const inline = require('gulp-inline');
+
+/* Clean destination folder */
+gulp.task('clean', function() {
+ return del(['data/*']);
+});
+
+/* Copy static files */
+gulp.task('files', function() {
+ return gulp.src([
+ 'web/dev/*.{jpg,jpeg,png,ico,gif}',
+ ])
+ .pipe(gulp.dest('web/build'));
+});
+
+/* Process HTML, CSS, JS --- INLINE --- */
+gulp.task('inline', function() {
+ return gulp.src('web/dev/*.html')
+ .pipe(inline({
+ base: 'web/dev/',
+ js: uglify,
+ css: cleancss,
+ disabledTypes: ['svg', 'img']
+ }))
+ .pipe(htmlmin({
+ collapseWhitespace: true,
+ removeComments: true,
+ minifyCSS: true,
+ minifyJS: true
+ }))
+ .pipe(gzip())
+ .pipe(gulp.dest('web/build/'));
+})
+
+/* Process HTML, CSS, JS */
+gulp.task('html', function() {
+ return gulp.src('web/dev/*.html')
+ .pipe(useref())
+ .pipe(plumber())
+ .pipe(gulpif('*.css', cleancss()))
+ .pipe(gulpif('*.js', uglify()))
+ .pipe(gulpif('*.html', htmlmin({
+ collapseWhitespace: true,
+ removeComments: true,
+ minifyCSS: true,
+ minifyJS: true
+ })))
+ .pipe(gulpif(['*.css','*.js'], gzip()))
+ .pipe(gulp.dest('web/build/'));
+});
+
+/* Build file system */
+gulp.task('buildfs', ['clean', 'files', 'html']);
+gulp.task('buildfs2', ['clean', 'files', 'inline']);
+gulp.task('default', ['buildfs']);
diff --git a/samples/HttpServer_ConfigNetwork/package.json b/samples/HttpServer_ConfigNetwork/package.json
new file mode 100644
index 0000000000..2172fccfa7
--- /dev/null
+++ b/samples/HttpServer_ConfigNetwork/package.json
@@ -0,0 +1,22 @@
+{
+ "name": "esp8266-filesystem-builder",
+ "version": "0.1.0",
+ "description": "Gulp based build script for ESP8266 file system files",
+ "main": "gulpfile.js",
+ "author": "Xose Pérez ",
+ "license": "MIT",
+ "devDependencies": {
+ "del": "^2.2.1",
+ "gulp": "^3.9.1",
+ "gulp-clean-css": "^2.0.10",
+ "gulp-gzip": "^1.4.0",
+ "gulp-htmlmin": "^2.0.0",
+ "gulp-if": "^2.0.1",
+ "gulp-inline": "^0.1.1",
+ "gulp-plumber": "^1.1.0",
+ "gulp-uglify": "^1.5.3",
+ "gulp-useref": "^3.1.2",
+ "yargs": "^5.0.0"
+ },
+ "dependencies": {}
+}
diff --git a/samples/HttpServer_ConfigNetwork/web/build/.lastModified b/samples/HttpServer_ConfigNetwork/web/build/.lastModified
new file mode 100644
index 0000000000..9685abd72b
--- /dev/null
+++ b/samples/HttpServer_ConfigNetwork/web/build/.lastModified
@@ -0,0 +1 @@
+Mon, 24 Jul 2017 17:20:31 GMT
diff --git a/samples/HttpServer_ConfigNetwork/web/build/bootstrap-core.css.gz b/samples/HttpServer_ConfigNetwork/web/build/bootstrap-core.css.gz
new file mode 100644
index 0000000000000000000000000000000000000000..8483876af3e9ba369e93d223ee6c03ca8ca9f77a
GIT binary patch
literal 15861
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≺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