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

SoftAP HTTP fixes #1362

Merged
merged 6 commits into from
Aug 9, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions crypto/inc/mbedtls_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -1331,6 +1331,14 @@
*/
//#define MBEDTLS_X509_RSASSA_PSS_SUPPORT

/**
* \def MBEDTLS_X509_INFO_SUPPORT
*
* Enable mbedtls_x509_crt_info and mbedtls_x509_crt_verify_info functions
*
*/
// #define MBEDTLS_X509_INFO_SUPPORT

/**
* \def MBEDTLS_SSL_RAW_PUBLIC_KEY_SUPPORT
*
Expand Down
8 changes: 8 additions & 0 deletions crypto/inc/mbedtls_config_photon.h
Original file line number Diff line number Diff line change
Expand Up @@ -1359,6 +1359,14 @@
*/
// #define MBEDTLS_X509_RSASSA_PSS_SUPPORT

/**
* \def MBEDTLS_X509_INFO_SUPPORT
*
* Enable mbedtls_x509_crt_info and mbedtls_x509_crt_verify_info functions
*
*/
// #define MBEDTLS_X509_INFO_SUPPORT

/**
* \def MBEDTLS_ZLIB_SUPPORT
*
Expand Down
8 changes: 6 additions & 2 deletions crypto/mbedtls/include/mbedtls/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,12 @@
#endif

#if defined(MBEDTLS_X509_CRT_PARSE_C)
#define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) \
# if defined(MBEDTLS_X509_INFO_SUPPORT)
# define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) \
mbedtls_debug_print_crt( ssl, level, __FILE__, __LINE__, text, crt )
# else
# define MBEDTLS_SSL_DEBUG_CRT( level, text, crt )
# endif /* MBEDTLS_X509_INFO_SUPPORT */
#endif

#else /* MBEDTLS_DEBUG_C */
Expand Down Expand Up @@ -199,7 +203,7 @@ void mbedtls_debug_print_ecp( const mbedtls_ssl_context *ssl, int level,
const char *text, const mbedtls_ecp_point *X );
#endif

#if defined(MBEDTLS_X509_CRT_PARSE_C)
#if defined(MBEDTLS_X509_CRT_PARSE_C) && defined(MBEDTLS_X509_INFO_SUPPORT)
/**
* \brief Print a X.509 certificate structure to the debug output. This
* function is always used through the MBEDTLS_SSL_DEBUG_CRT() macro,
Expand Down
4 changes: 2 additions & 2 deletions crypto/mbedtls/library/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ void mbedtls_debug_print_mpi( const mbedtls_ssl_context *ssl, int level,
}
#endif /* MBEDTLS_BIGNUM_C */

#if defined(MBEDTLS_X509_CRT_PARSE_C)
#if defined(MBEDTLS_X509_CRT_PARSE_C) && defined(MBEDTLS_X509_INFO_SUPPORT)
static void debug_print_pk( const mbedtls_ssl_context *ssl, int level,
const char *file, int line,
const char *text, const mbedtls_pk_context *pk )
Expand Down Expand Up @@ -364,6 +364,6 @@ void mbedtls_debug_print_crt( const mbedtls_ssl_context *ssl, int level,
crt = crt->next;
}
}
#endif /* MBEDTLS_X509_CRT_PARSE_C */
#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_X509_INFO_SUPPORT */

#endif /* MBEDTLS_DEBUG_C */
3 changes: 3 additions & 0 deletions crypto/mbedtls/library/x509_crt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,7 @@ int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path )
}
#endif /* MBEDTLS_FS_IO */

#if defined(MBEDTLS_X509_INFO_SUPPORT)
static int x509_info_subject_alt_name( char **buf, size_t *size,
const mbedtls_x509_sequence *subject_alt_name )
{
Expand Down Expand Up @@ -1557,6 +1558,8 @@ int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix,
return( (int) ( size - n ) );
}

#endif /* MBEDTLS_X509_INFO_SUPPORT */

#if defined(MBEDTLS_X509_CHECK_KEY_USAGE)
int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt,
unsigned int usage )
Expand Down
Binary file modified hal/src/photon/lib/Lib_HTTP_Server.a
Binary file not shown.
225 changes: 200 additions & 25 deletions hal/src/photon/softap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,14 @@
#include "device_code.h"

#if SOFTAP_HTTP
#include "http_server.h"
#endif
# include "http_server.h"

# ifndef SOFTAP_HTTP_MAXIMUM_CONNECTIONS
# define SOFTAP_HTTP_MAXIMUM_CONNECTIONS 5
# endif // SOFTAP_HTTP_MAXIMUM_CONNECTIONS

# define SOFTAP_HTTP_MAXIMUM_URL_LENGTH 255
#endif // SOFTAP_HTTP

extern WLanSecurityType toSecurityType(wiced_security_t sec);

Expand Down Expand Up @@ -1181,12 +1187,125 @@ int writeHeader(void* cbArg, uint16_t flags, uint16_t responseCode, const char*
CHUNKED_CONTENT_LENGTH, HTTP_CACHE_DISABLED, http_server_get_mime_type(mimeType), header_list);
}

struct HTTPRequest {
char* url;
wiced_http_response_stream_t* stream;
uint8_t* buffer;
bool alloced;
size_t length;
size_t total_length;
// const char* url_query_string;

HTTPRequest()
: url{nullptr},
buffer{nullptr},
alloced{false} {
reset();
}

~HTTPRequest() {
reset();
}

bool init(const char* u, wiced_http_response_stream_t* s, wiced_http_message_body_t* b) {
stream = s;
if (b->message_data_length != 0 && b->total_message_data_remaining == 0) {
url = nullptr;
// Single packet
total_length = length = b->message_data_length;
buffer = (uint8_t*)b->data;
alloced = false;
} else if (b->total_message_data_remaining) {
// Multi-packet
buffer = (uint8_t*)malloc(b->total_message_data_remaining + b->message_data_length);
if (buffer == nullptr) {
reset();
return false;
}
alloced = true;
length = b->message_data_length;
total_length = length + b->total_message_data_remaining;
if (length > 0) {
memcpy(buffer, b->data, length);
}

const size_t l = strlen(u) + 1;
url = (char*)calloc(1, std::min(l, (size_t)SOFTAP_HTTP_MAXIMUM_URL_LENGTH));
if (url == nullptr) {
reset();
return false;
}
memcpy(url, u, std::min(l, (size_t)SOFTAP_HTTP_MAXIMUM_URL_LENGTH - 1));
}

return true;
}

bool append(wiced_http_message_body_t* b) {
memcpy(buffer + length, b->data, b->message_data_length);
length += b->message_data_length;
return true;
}

bool matches(const char* u, wiced_http_response_stream_t* s, wiced_http_message_body_t* b) const {
if (s == nullptr || b == nullptr) {
return false;
}

if (stream == nullptr || s != stream) {
return false;
}

if ((b->message_data_length + b->total_message_data_remaining + length) != total_length) {
return false;
}

return true;
}

bool ready() const {
return !empty() && length == total_length;
}

void reset() {
if (buffer && alloced) {
free(buffer);
}
buffer = nullptr;
alloced = false;
stream = nullptr;
length = 0;
total_length = 0;
if (url) {
free(url);
}
url = nullptr;
}

Reader reader() {
Reader r;
reader_from_buffer(&r, buffer, length);
return r;
}

Writer writer() {
Writer w;
http_stream_writer(w, stream);
return w;
}

bool empty() const {
return (url == nullptr && stream == nullptr && buffer == nullptr && length == 0 && total_length == 0);
}
};

class HTTPDispatcher {
wiced_http_server_t server;

wiced_http_page_t page[10];

static HTTPRequest* reqs;

void setCommand(unsigned index, Command& cmd) {
page[index].url_content.dynamic_data.generator = handle_command;
page[index].url_content.dynamic_data.arg = &cmd;
Expand All @@ -1208,42 +1327,98 @@ class HTTPDispatcher {
}

void start() {
wiced_http_server_start(&server, 80, 1, page, WICED_AP_INTERFACE, 1024*4);
reqs = new HTTPRequest[SOFTAP_HTTP_MAXIMUM_CONNECTIONS];
wiced_http_server_start(&server, 80, SOFTAP_HTTP_MAXIMUM_CONNECTIONS, page, WICED_AP_INTERFACE, 1024*4);
}

void stop() {
wiced_http_server_stop(&server);
delete[] reqs;
reqs = nullptr;
}

static int32_t handle_command(const char* url, const char* url_query_string, wiced_http_response_stream_t* stream, void* arg, wiced_http_message_body_t* http_data) {
Command* cmd = (Command*)arg;
Reader r;
reader_from_http_body(&r, http_data);
wiced_http_response_stream_enable_chunked_transfer( stream );
stream->cross_host_requests_enabled = WICED_TRUE;
wiced_http_response_stream_write_header( stream, HTTP_200_TYPE, CHUNKED_CONTENT_LENGTH, HTTP_CACHE_DISABLED, MIME_TYPE_JSON, nullptr);
Writer w;
http_stream_writer(w, stream);
int result = cmd->execute(r, w);
cleanup_http_body(http_data);
template <typename F>
static HTTPRequest* for_request(F&& f) {
if (reqs == nullptr) {
return nullptr;
}

for(HTTPRequest* r = reqs; r < reqs + SOFTAP_HTTP_MAXIMUM_CONNECTIONS; r++) {
if (f(r) == true) {
return r;
}
}

return nullptr;
}

static int32_t handle_request(const char* url, const char* url_query_string, wiced_http_response_stream_t* stream, void* arg, wiced_http_message_body_t* http_data, bool isCmd) {
int result = WICED_SUCCESS;
HTTPRequest* req = for_request([&](HTTPRequest* r) {
return r->matches(url, stream, http_data);
});
if (req == nullptr) {
req = for_request([&](HTTPRequest* r) {
if (r->empty()) {
if (r->init(url, stream, http_data)) {
return true;
}
}
return false;
});
if (req == nullptr) {
// Try to match stream only
req = for_request([&](HTTPRequest* r) {
return r->stream == stream;
});
if (req == nullptr) {
// Error
wiced_http_response_stream_write_header(stream, HTTP_500_TYPE, NO_CONTENT_LENGTH, HTTP_CACHE_DISABLED, MIME_TYPE_TEXT_HTML, nullptr);
return WICED_ERROR;
}
// There shouldn't be two active connections with the same response stream, reuse
req->reset();
}
} else {
req->append(http_data);
}

if (req->ready()) {
// Process request
wiced_http_response_stream_enable_chunked_transfer(req->stream);
stream->cross_host_requests_enabled = WICED_TRUE;

Reader r = req->reader();
Writer w = req->writer();
if (isCmd) {
Command* cmd = (Command*)arg;
wiced_http_response_stream_write_header(req->stream, HTTP_200_TYPE, CHUNKED_CONTENT_LENGTH, HTTP_CACHE_DISABLED, MIME_TYPE_JSON, nullptr);
result = cmd->execute(r, w);
} else {
PageProvider* p = (PageProvider*)arg;
if (p) {
p(req->url ? req->url : url, &writeHeader, req->stream, &r, &w, nullptr);
}
}
// We need to deactivate chunked transfer mode here
// in order to signal to client that there'll be no more data: "0\r\n\r\n"
wiced_http_response_stream_disable_chunked_transfer(req->stream);
req->reset();
}
return result;
}

static int32_t handle_command(const char* url, const char* url_query_string, wiced_http_response_stream_t* stream, void* arg, wiced_http_message_body_t* http_data) {
return handle_request(url, url_query_string, stream, arg, http_data, true);
}

static int32_t handle_app_renderer(const char* url, const char* url_query_string, wiced_http_response_stream_t* stream, void* arg, wiced_http_message_body_t* http_data) {
PageProvider* p = (PageProvider*)arg;
Reader r;
reader_from_http_body(&r, http_data);
wiced_http_response_stream_enable_chunked_transfer( stream );
stream->cross_host_requests_enabled = WICED_TRUE;
Writer w;
http_stream_writer(w, stream);
if (p)
p(url, &writeHeader, stream, &r, &w, nullptr);
cleanup_http_body(http_data);
return 0;
return handle_request(url, url_query_string, stream, arg, http_data, false);
}

};

HTTPRequest* HTTPDispatcher::reqs = nullptr;
#endif


Expand Down
2 changes: 1 addition & 1 deletion hal/src/photon/softap_ip.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ START_OF_HTTP_PAGE_DATABASE(soft_ap_http_pages)
{ "/connect-ap", "application/octet-stream", WICED_RAW_DYNAMIC_URL_CONTENT },
{ "/public-key", "application/octet-stream", WICED_RAW_DYNAMIC_URL_CONTENT },
{ "/set", "application/octet-stream", WICED_RAW_DYNAMIC_URL_CONTENT },
{ "/", "application/octet-stream", .url_content_type = WICED_RAW_DYNAMIC_URL_CONTENT },
{ "/*", "application/octet-stream", .url_content_type = WICED_RAW_DYNAMIC_URL_CONTENT },
END_OF_HTTP_PAGE_DATABASE();

extern void default_page_handler(const char* url, ResponseCallback* cb, void* cbArg, Reader* body, Writer* result, void* reserved);
Expand Down
10 changes: 10 additions & 0 deletions user/tests/app/softap_http/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Flash softap application to the device:
$ cd ~/firmware/modules
$ make -s all program-dfu PLATFORM=photon TEST=app/softap_http

Install client dependencies:
$ cd ~/firmware/user/tests/app/softap_http/client
$ npm install

Run client:
$ ./client
16 changes: 16 additions & 0 deletions user/tests/app/softap_http/client/client
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/bash

set -e

if [ ! $PLATFORM ]; then
echo 'PLATFORM is not defined, assuming Photon'
export PLATFORM=photon
fi

this_dir=$(cd $(dirname "$0") && pwd)
test_dir=$(cd "$this_dir/../../../accept" && pwd)

PATH="$test_dir/tools:$PATH"
source "$test_dir/init_env"

node "$this_dir/main.js"
Loading