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

fix for WICED HTTP server only reading one packet #694

Merged
merged 2 commits into from Oct 19, 2015
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Binary file modified hal/src/photon/lib/Lib_HTTP_Server.a
Binary file not shown.
2 changes: 2 additions & 0 deletions hal/src/photon/libraries/daemons/HTTP_server/http_server.h
Expand Up @@ -244,6 +244,8 @@ typedef struct
wiced_bool_t chunked_transfer; /* chunked data format */
wiced_packet_mime_type_t mime_type; /* mime type */
wiced_http_request_type_t request_type; /* GET, POST or PUT request */
wiced_tcp_socket_t* socket; /* The socket to retrieve additional packets from */
void* user; /* additional storage. */
} wiced_http_message_body_t;

/**
Expand Down
112 changes: 109 additions & 3 deletions hal/src/photon/softap.cpp
Expand Up @@ -2,6 +2,7 @@
#include <cstdlib>
#include <algorithm>
#include "wiced.h"
#include "http_server.h"
#include "static_assert.h"
#include "dns_redirect.h"
#include "wiced_security.h"
Expand Down Expand Up @@ -901,16 +902,121 @@ static void tcp_stream_reader(Reader& r, wiced_tcp_stream_t* stream) {

int read_from_buffer(Reader* r, uint8_t* target, size_t length) {
memcpy(target, r->state, length);
r->state = ((uint8_t*)r->state)+length;
return length;
}

void reader_from_buffer(Reader* r, const uint8_t* buffer, size_t length) {
void reader_from_buffer(Reader* r, const uint8_t* buffer, size_t length)
{
r->bytes_left = length;
r->callback = read_from_buffer;
r->state = (void*)buffer;
}


void cleanup_http_body(wiced_http_message_body_t* body)
{
if (body->user)
{
wiced_packet_delete((wiced_packet_t*)body->user);
body->user = NULL;
}
}

int read_from_http_body_part(wiced_http_message_body_t* body, uint8_t* target, size_t length)
{
// first read from the data already read in the body
if (body->message_data_length)
{
if (length>body->message_data_length)
length = body->message_data_length;

memcpy(target, body->data, length);
body->message_data_length -= length;
body->data += length;
return length;
}
else if (body->total_message_data_remaining)
{
cleanup_http_body(body);

// fetch the next packet - we assume length is large enough to hold the packet content
// which is the case since we are retrieving the entire content in Reader::fetch_as_string())
wiced_packet_t* packet = NULL;
wiced_result_t result = wiced_tcp_receive(body->socket, &packet, 3000);
if (result)
return -1;

body->user = packet; // ensure we clean up the packet
uint16_t packet_length;
uint16_t available_data_length;
uint32_t offset =0;
uint8_t* data;

if (length>available_data_length)

Choose a reason for hiding this comment

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

@m-mcgowan comparing uninitialised variable available_data_length

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks!

length = available_data_length;
else
available_data_length = length;

do
{
result = wiced_packet_get_data(packet, offset, &data, &packet_length, &available_data_length);
if (result)
return -1;

uint32_t tocopy = std::min(length, size_t(packet_length));
memcpy(target, data, tocopy);
length -= tocopy;
target += tocopy;
offset += packet_length;
}
while (length && offset < available_data_length);

body->total_message_data_remaining -= available_data_length;
return available_data_length;
}
else
return -1;
}

/**
* This implementation takes some shortcuts since it's just a placeholder until
* WICED implements http based on streams rather than packets.
* This function relies upon the Reader::fetch_as_string() call that reads
* the entire content in one call.
* @param r
* @param target
* @param length
* @return
*/
int read_from_http_body(Reader* r, uint8_t* target, size_t length) {
size_t read = 0;
wiced_http_message_body_t* body = (wiced_http_message_body_t*)r->state;
while (read<length)
{
int block = read_from_http_body_part(body, target, length-read);
if (block<0)
break;
target += block;
read += block;
}
return read;
}

void reader_from_http_body(Reader* r, wiced_http_message_body_t* body)
{
if (body->total_message_data_remaining==0)
{
reader_from_buffer(r, (uint8_t*)body->data, body->message_data_length);
}
else
{
r->bytes_left = body->message_data_length + body->total_message_data_remaining;
r->callback = read_from_http_body;
r->state = body;
}
}

#if SOFTAP_HTTP
extern "C" wiced_http_page_t soft_ap_http_pages[];

Expand Down Expand Up @@ -959,14 +1065,14 @@ class HTTPDispatcher {
static int32_t handle_command(const char* url, wiced_http_response_stream_t* stream, void* arg, wiced_http_message_body_t* http_data) {
Command* cmd = (Command*)arg;
Reader r;
reader_from_buffer(&r, (uint8_t*)http_data->data, http_data->message_data_length);

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 );
Writer w;
http_stream_writer(w, stream);
int result = cmd->execute(r, w);
cleanup_http_body(http_data);
return result;
}

Expand Down