Skip to content

Commit

Permalink
#49 - Payload write position correctly offset.
Browse files Browse the repository at this point in the history
  • Loading branch information
PerMalmberg committed Aug 6, 2019
1 parent 2177aef commit d9a262a
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,15 @@ namespace smooth::application::network::http
// How much left until we reach max header size?
amount_to_request = max_header_size - total_bytes_received;
// Make sure there is room for what he have received and what we ask for.
packet.ensure_room(total_bytes_received + amount_to_request);
packet.expand_by(amount_to_request);
}
else
{
// Never ask for more than content_chunk_size
auto remaining_of_content = incoming_content_length - total_content_bytes_received;
amount_to_request = std::min(content_chunk_size, remaining_of_content);

packet.ensure_room(content_bytes_received_in_current_part + amount_to_request);
packet.expand_by(amount_to_request);
}

return amount_to_request;
Expand Down
71 changes: 23 additions & 48 deletions lib/smooth/application/network/http/websocket/WebsocketProtocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,87 +29,73 @@ namespace smooth::application::network::http::websocket

int WebsocketProtocol::get_wanted_amount(HTTPPacket& packet)
{
int len;

if (amount_wanted_in_current_state > 0)
{
// Still waiting for data in current state.
Log::info("waiting", Format("{1}", Int32(amount_wanted_in_current_state)));
len = amount_wanted_in_current_state;
}
else
if (amount_wanted_in_current_state == 0)
{
current_offset = 0;
data_received_in_current_state = 0;

if (state == State::Header)
{
len = 2;
}
else if (state == State::ExtendedPayloadLength_2)
if (state == State::Header
|| state == State::ExtendedPayloadLength_2)
{
len = 2;
amount_wanted_in_current_state = 2;
}
else if (state == State::ExtendedPayloadLength_8)
{
len = 8;
amount_wanted_in_current_state = 8;
}
else if (state == State::MaskingKey)
{
len = sizeof(frame_data.mask_key);
amount_wanted_in_current_state = sizeof(frame_data.mask_key);
}
else
{
// Websockets can use up to 64 bits (well, 63 since MSB MUST always be 0,
// see https://tools.ietf.org/html/rfc6455#section-5.2) to specify the size.
// Since we can't handle that large data buffers, we split it into smaller parts based on content_chunk_size

auto remaining_to_read = payload_length - received_payload;
auto remaining_payload = payload_length - received_payload;

auto remaining_to_fill_current =
static_cast<decltype(received_payload_in_current_package)>(content_chunk_size) -
received_payload_in_current_package;

auto size_needed = std::min(remaining_to_read, remaining_to_fill_current);
len = static_cast<decltype(len)>(size_needed);
packet.ensure_room(
static_cast<decltype(content_chunk_size)>(received_payload_in_current_package) + len);
}
auto amount_left = std::min(remaining_payload, remaining_to_fill_current);
amount_wanted_in_current_state = static_cast<decltype(amount_wanted_in_current_state)>(amount_left);

Log::info("WA", Format("{1}", Int32(len)));
amount_wanted_in_current_state = len;
packet.expand_by(static_cast<int>(amount_left));
}
}

return len;
return amount_wanted_in_current_state;
}

uint8_t* WebsocketProtocol::get_write_pos(HTTPPacket& packet)
{
if (state == State::Header)
{
return frame_data.header + current_offset;
return frame_data.header + data_received_in_current_state;
}
else if (state == State::ExtendedPayloadLength_2 || state == State::ExtendedPayloadLength_8)
{
return reinterpret_cast<uint8_t*>(&frame_data.ext_len);
return reinterpret_cast<uint8_t*>(&frame_data.ext_len) + data_received_in_current_state;
}
else if (state == State::MaskingKey)
{
return frame_data.mask_key + current_offset;
return frame_data.mask_key + data_received_in_current_state;
}
else
{
return packet.data().data() + current_offset;
return packet.data().data() + data_received_in_current_state;
}
}

void WebsocketProtocol::data_received(HTTPPacket& packet, int length)
{
Log::info("DR", Format("{1}", Int32(length)));
current_offset += length;
amount_wanted_in_current_state -= length;
data_received_in_current_state += length;

// Have we received all the data we want yet?
if (amount_wanted_in_current_state == 0)
if(amount_wanted_in_current_state == 0)
{
// All requested data received
if (state == State::Header)
{
op_code = static_cast<OpCode>(get_opcode());
Expand Down Expand Up @@ -161,24 +147,13 @@ namespace smooth::application::network::http::websocket
// De-mask data
if (is_data_masked())
{
std::stringstream ss;
ss << static_cast<int>(frame_data.mask_key[0]) << " " << static_cast<int>(frame_data.mask_key[1])
<< " " << static_cast<int>(frame_data.mask_key[2]) << " "
<< static_cast<int>(frame_data.mask_key[3]) << " ";
Log::info("WP", ss.str());
ss.str("");
ss.clear();

Log::info("WP", Format("demask_ix: {1}", UInt64(demask_ix)));
for (decltype(packet.data().size()) i = 0; i < packet.data().size(); ++i, ++demask_ix)
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
packet.data()[i] = packet.data()[i] ^ frame_data.mask_key[demask_ix % 4];
ss << (char) packet.data()[i];
#pragma GCC diagnostic pop
}
Log::info("WP", ss.str());
}

set_message_properties(packet);
Expand Down Expand Up @@ -237,7 +212,7 @@ namespace smooth::application::network::http::websocket
// All parts received
state = State::Header;
received_payload = 0;
current_offset = 0;
data_received_in_current_state = 0;
demask_ix = 0;
amount_wanted_in_current_state = 0;
}
Expand All @@ -247,7 +222,7 @@ namespace smooth::application::network::http::websocket
{
state = State::Header;
error = false;
current_offset = 0;
data_received_in_current_state = 0;
payload_length = 0;
received_payload = 0;
received_payload_in_current_package = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,10 @@ namespace smooth::application::network::http
return content;
}

void ensure_room(int total_space)
void expand_by(int additional_space)
{
content.resize(static_cast<std::size_t>(total_space));
content.resize(static_cast<std::size_t>(content.size()
+ static_cast<decltype(content.size())>(additional_space)));
}

std::unordered_map<std::string, std::string>& headers()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ namespace smooth::application::network::http::websocket
{
uint16_t len_16;
uint64_t len_64;
} ext_len;
} ext_len{0};
uint8_t mask_key[4];
};

Expand All @@ -121,7 +121,7 @@ namespace smooth::application::network::http::websocket
IServerResponse& response;

bool error{false};
int current_offset{0};
int data_received_in_current_state{0};
uint64_t payload_length{0};
uint64_t received_payload{0};
uint64_t demask_ix{0};
Expand Down
7 changes: 3 additions & 4 deletions test/http_server_test/web_root/websocket.html
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@

function cont_send() {

const interval = 5000;
const interval = 50000;

if(document.getElementById("continuous").checked)
{
Expand All @@ -111,9 +111,7 @@
}
};

if(document.getElementById("continuous").checked) {
setTimeout(f, interval);
}
setTimeout(f, interval);
}
}

Expand All @@ -127,6 +125,7 @@
<button onclick="send_length(80*1024);">Send 80k</button>
<button onclick="send_length(1024*1024);">Send 1M</button>
<button onclick="send_length(1024*1024*10);">Send 10M</button>
<button onclick="send_length(1024*1024*100);">Send 100M</button>
<br/>
<div id="status">Disconnected</div>
<br/>
Expand Down

0 comments on commit d9a262a

Please sign in to comment.