Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Move HTTP strings into flash and provide suitable functions #1459

Merged
merged 3 commits into from
Oct 5, 2018
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions Sming/SmingCore/Network/Http/HttpCommon.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/****
* Sming Framework Project - Open Source framework for high efficiency native ESP8266 development.
* Created 2015 by Skurydin Alexey
* http://github.com/SmingHub/Sming
* All files of the Sming Core are provided under the LGPL v3 license.
*
* @author: 2018 - Mikee47 <[email protected]>
*
* httpGetErrnoName() and httpGetStatusText() functions added
*
****/

#include "HttpCommon.h"

// Define flash strings and lookup table for HTTP error names
#define XX(_n, _s) static DEFINE_FSTR(hpename_##_n, "HPE_" #_n);
HTTP_ERRNO_MAP(XX)
#undef XX

static FSTR_TABLE(hpeNames) = {
#define XX(_n, _s) FSTR_PTR(hpename_##_n),
HTTP_ERRNO_MAP(XX)
#undef XX
};

String httpGetErrorName(enum http_errno err)
{
if(err > HPE_UNKNOWN)
return F("HPE_#") + String(err);

return *hpeNames[err];
}

// Define flash strings and lookup table for HTTP error descriptions
#define XX(_n, _s) static DEFINE_FSTR(hpedesc_##_n, _s);
HTTP_ERRNO_MAP(XX)
#undef XX

static FSTR_TABLE(hpeDescriptions) = {
#define XX(_n, _s) FSTR_PTR(hpedesc_##_n),
HTTP_ERRNO_MAP(XX)
#undef XX
};

String httpGetErrorDescription(enum http_errno err)
{
if(err > HPE_UNKNOWN)
return F("HPE_#") + String(err);

return *hpeDescriptions[err];
}

// Define flash strings for HTTP status codes
#define XX(_num, _name, _string) static DEFINE_FSTR(hpsText_##_num, #_string);
HTTP_STATUS_MAP(XX)
#undef XX

String httpGetStatusText(enum http_status code)
{
switch(code) {
#define XX(_num, _name, _string) \
case _num: \
return hpsText_##_num;
HTTP_STATUS_MAP(XX)
#undef XX
default:
return F("<unknown_") + String(code) + '>';
}
}
32 changes: 32 additions & 0 deletions Sming/SmingCore/Network/Http/HttpCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,36 @@ enum HttpConnectionState {
eHCS_Sent
};

/**
* @brief Return a string name of the given error
* @param err
* @retval String
* @note This replaces the one in http_parser module which uses a load of RAM
*/
String httpGetErrorName(enum http_errno err);

/**
* @brief Return a descriptive string for the given error
* @param err
* @retval String
*/
String httpGetErrorDescription(enum http_errno err);

/**
* @brief Return a descriptive string for an HTTP status code
* @param code
* @retval String
*/
String httpGetStatusText(enum http_status code);

/**
* @brief Return a descriptive string for an HTTP status code
* @param code
* @retval String
*/
static inline String httpGetStatusText(unsigned code)
{
return httpGetStatusText((enum http_status)code);
}

#endif /* _SMING_CORE_HTTP_COMMON_H_ */
2 changes: 1 addition & 1 deletion Sming/SmingCore/Network/Http/HttpConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,7 @@ err_t HttpConnection::onReceive(pbuf* buf)
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
debug_e("HTTP parser error: %s", http_errno_name(HTTP_PARSER_ERRNO(&parser)));
debug_e("HTTP parser error: %s", httpGetErrorName(HTTP_PARSER_ERRNO(&parser)).c_str());
cleanup();
TcpConnection::onReceive(NULL);
return ERR_ABRT;
Expand Down
24 changes: 5 additions & 19 deletions Sming/SmingCore/Network/Http/HttpServerConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ int HttpServerConnection::staticOnMessageComplete(http_parser* parser)
// we are finished with this request
int hasError = 0;
if(HTTP_PARSER_ERRNO(parser) != HPE_OK) {
connection->sendError(http_errno_name(HTTP_PARSER_ERRNO(parser)));
connection->sendError(httpGetErrorName(HTTP_PARSER_ERRNO(parser)));
return 0;
}

Expand Down Expand Up @@ -320,7 +320,7 @@ err_t HttpServerConnection::onReceive(pbuf* buf)
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
debug_e("HTTP parser error: %s", http_errno_name(HTTP_PARSER_ERRNO(&parser)));
debug_e("HTTP parser error: %s", httpGetErrorName(HTTP_PARSER_ERRNO(&parser)).c_str());
sendError();

if(HTTP_PARSER_ERRNO(&parser) >= HPE_INVALID_EOF_STATE) {
Expand Down Expand Up @@ -429,7 +429,7 @@ void HttpServerConnection::sendResponseHeaders(HttpResponse* response)
}
#endif /* DISABLE_HTTPSRV_ETAG */
String statusLine =
"HTTP/1.1 " + String(response->code) + " " + getStatus((enum http_status)response->code) + "\r\n";
"HTTP/1.1 " + String(response->code) + " " + httpGetStatusText((enum http_status)response->code) + "\r\n";
sendString(statusLine.c_str());
if(response->stream != NULL && response->stream->available() != -1) {
response->headers["Content-Length"] = String(response->stream->available());
Expand Down Expand Up @@ -505,34 +505,20 @@ void HttpServerConnection::onError(err_t err)
TcpClient::onError(err);
}

const char* HttpServerConnection::getStatus(enum http_status code)
slaff marked this conversation as resolved.
Show resolved Hide resolved
{
switch(code) {
#define XX(num, name, string) \
case num: \
return #string;
HTTP_STATUS_MAP(XX)
#undef XX
default:
return "<unknown>";
}
}

void HttpServerConnection::send()
{
state = eHCS_StartSending;
onReadyToSendData(eTCE_Received);
}

void HttpServerConnection::sendError(const char* message /* = NULL*/,
enum http_status code /* = HTTP_STATUS_BAD_REQUEST */)
void HttpServerConnection::sendError(const String& message, enum http_status code)
{
debug_d("SEND ERROR PAGE");
response.code = code;
response.setContentType(MIME_HTML);

String html = "<H2 color='#444'>";
html += message ? message : getStatus((enum http_status)response.code);
html += message ? message : httpGetStatusText((enum http_status)response.code);
html += "</H2>";
response.headers["Content-Length"] = html.length();
response.sendString(html);
Expand Down
4 changes: 1 addition & 3 deletions Sming/SmingCore/Network/Http/HttpServerConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,9 @@ class HttpServerConnection : public TcpClient
protected:
virtual err_t onReceive(pbuf* buf);
virtual void onReadyToSendData(TcpConnectionEvent sourceEvent);
virtual void sendError(const char* message = NULL, enum http_status code = HTTP_STATUS_BAD_REQUEST);
virtual void sendError(const String& message = nullptr, enum http_status code = HTTP_STATUS_BAD_REQUEST);
virtual void onError(err_t err);

const char* getStatus(enum http_status s);

private:
static int staticOnMessageBegin(http_parser* parser);
static int staticOnPath(http_parser* parser, const char* at, size_t length);
Expand Down
20 changes: 20 additions & 0 deletions Sming/Wiring/FlashString.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,26 @@
// Get a pointer to the actual FlashString, used when creating tables
#define FSTR_PTR(_struct) &_##_struct.fstr

/** @brief declare a table of FlashStrings
* @param _name name of the table
* @note Declares a lookup table stored in flash memory. Example:
*
* DEFINE_FSTR(fstr1, "Test string #1");
* DEFINE_FSTR(fstr2, "Test string #2");
*
* FSTR_TABLE(table) = {
* FSTR_PTR(fstr1),
* FSTR_PTR(fstr2),
* };
*
* Table entries may be accessed directly as they are word-aligned. Examples:
* debugf("fstr1 = '%s'", String(*table[0]).c_str());
* debugf("fstr2.length() = %u", table[1]->length());
*
*/
#define FSTR_TABLE(_name) const FlashString* const _name[] PROGMEM


/*
* Load a FlashString object into a named local (stack) buffer
*
Expand Down
87 changes: 82 additions & 5 deletions Sming/third-party/.patches/http-parser.patch
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ index 678f555..0000000
- }
-}
diff --git a/http_parser.c b/http_parser.c
index 5b5657b..ed0459a 100644
index 5b5657b..5949dc6 100644
--- a/http_parser.c
+++ b/http_parser.c
@@ -19,12 +19,22 @@
Expand Down Expand Up @@ -161,10 +161,20 @@ index 5b5657b..ed0459a 100644
#ifndef ULLONG_MAX
# define ULLONG_MAX ((uint64_t) -1) /* 2^64-1 */
#endif
@@ -217,17 +227,6 @@ static const char tokens[256] = {
@@ -182,7 +192,7 @@ static const char *method_strings[] =
* | "/" | "[" | "]" | "?" | "="
* | "{" | "}" | SP | HT
*/
-static const char tokens[256] = {
+static const char __flash_tokens[256] PROGMEM = {
/* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */
0, 0, 0, 0, 0, 0, 0, 0,
/* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */
@@ -216,18 +226,10 @@ static const char tokens[256] = {
/* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */
'x', 'y', 'z', 0, '|', 0, '~', 0 };

-
-static const int8_t unhex[256] =
- {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
- ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
Expand All @@ -176,10 +186,58 @@ index 5b5657b..ed0459a 100644
- ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
- };
-
+static inline char get_token(char c)
+{
+ return (char)pgm_read_byte(&__flash_tokens[(uint8_t)c]);
+}

#if HTTP_PARSER_STRICT
# define T(v) 0
@@ -1874,7 +1873,7 @@ reexecute:
@@ -236,7 +238,7 @@ static const int8_t unhex[256] =
#endif


-static const uint8_t normal_url_char[32] = {
+static const uint8_t normal_url_char[32] PROGMEM_L32 = {
/* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
/* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */
@@ -417,14 +419,14 @@ enum http_host_state
(c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \
(c) == '$' || (c) == ',')

-#define STRICT_TOKEN(c) (tokens[(unsigned char)c])
+#define STRICT_TOKEN(c) get_token(c)

#if HTTP_PARSER_STRICT
-#define TOKEN(c) (tokens[(unsigned char)c])
+#define TOKEN(c) get_token(c)
#define IS_URL_CHAR(c) (BIT_AT(normal_url_char, (unsigned char)c))
#define IS_HOST_CHAR(c) (IS_ALPHANUM(c) || (c) == '.' || (c) == '-')
#else
-#define TOKEN(c) ((c == ' ') ? ' ' : tokens[(unsigned char)c])
+#define TOKEN(c) ((c == ' ') ? ' ' : get_token(c)
#define IS_URL_CHAR(c) \
(BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80))
#define IS_HOST_CHAR(c) \
@@ -456,16 +458,6 @@ do { \
#endif


-/* Map errno values to strings for human-readable output */
-#define HTTP_STRERROR_GEN(n, s) { "HPE_" #n, s },
-static struct {
- const char *name;
- const char *description;
-} http_strerror_tab[] = {
- HTTP_ERRNO_MAP(HTTP_STRERROR_GEN)
-};
-#undef HTTP_STRERROR_GEN
-
int http_message_needs_eof(const http_parser *parser);

/* Our URL parser.
@@ -1874,7 +1866,7 @@ reexecute:
assert(parser->nread == 1);
assert(parser->flags & F_CHUNKED);

Expand All @@ -188,7 +246,7 @@ index 5b5657b..ed0459a 100644
if (UNLIKELY(unhex_val == -1)) {
SET_ERRNO(HPE_INVALID_CHUNK_SIZE);
goto error;
@@ -1896,7 +1895,7 @@ reexecute:
@@ -1896,7 +1888,7 @@ reexecute:
break;
}

Expand All @@ -197,6 +255,25 @@ index 5b5657b..ed0459a 100644

if (unhex_val == -1) {
if (ch == ';' || ch == ' ') {
@@ -2096,18 +2088,6 @@ http_parser_settings_init(http_parser_settings *settings)
memset(settings, 0, sizeof(*settings));
}

-const char *
-http_errno_name(enum http_errno err) {
- assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab));
- return http_strerror_tab[err].name;
-}
-
-const char *
-http_errno_description(enum http_errno err) {
- assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab));
- return http_strerror_tab[err].description;
-}
-
static enum http_host_state
http_parse_host_char(enum http_host_state s, const char ch) {
switch(s) {
diff --git a/test.c b/test.c
deleted file mode 100644
index bc4e664..0000000
Expand Down
16 changes: 16 additions & 0 deletions samples/Basic_ProgMem/app/TestProgmem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,22 @@ void testFSTR(Print& out)
TEST(demoFSTR1 == String(demoFSTR2))
#undef TEST

// FSTR table

static DEFINE_FSTR(fstr1, "Test string #1");
static DEFINE_FSTR(fstr2, "Test string #2");

static FSTR_TABLE(table) = {
FSTR_PTR(fstr1),
FSTR_PTR(fstr2),
};

// Table entries may be accessed directly as they are word-aligned
mikee47 marked this conversation as resolved.
Show resolved Hide resolved
out.println(_F("FSTR tables -"));
out.printf(_F(" fstr1 = '%s'\n"), String(*table[0]).c_str());
out.printf(_F(" fstr1.length() = %u\n"), table[0]->length());
out.printf(_F(" entries = %u\n"), ARRAY_SIZE(table));

out.println("< testFSTR() end\n");
}

Expand Down