using namespace NHttpEnums;
ScanResult NHttpStartCutter::cut(const uint8_t* buffer, uint32_t length,
- NHttpInfractions& infractions, NHttpEventGen& events)
+ NHttpInfractions& infractions, NHttpEventGen& events, uint32_t, uint32_t)
{
for (uint32_t k = 0; k < length; k++)
{
}
ScanResult NHttpHeaderCutter::cut(const uint8_t* buffer, uint32_t length,
- NHttpInfractions& infractions, NHttpEventGen& events)
+ NHttpInfractions& infractions, NHttpEventGen& events, uint32_t, uint32_t)
{
// Header separators: leading \r\n, leading \n, nonleading \r\n\r\n, nonleading \n\r\n,
// nonleading \r\n\n, and nonleading \n\n. The separator itself becomes num_excess which is
return SCAN_NOTFOUND;
}
-ScanResult NHttpBodyCutter::cut(const uint8_t*, uint32_t, NHttpInfractions&, NHttpEventGen&)
+ScanResult NHttpBodyCutter::cut(const uint8_t*, uint32_t, NHttpInfractions&, NHttpEventGen&,
+ uint32_t flow_target, uint32_t flow_max)
{
assert(remaining > 0);
- // The normal body section size is about 16K. But if there are only 24K or less remaining we
- // take the whole thing rather than leave a small final section.
- if (remaining <= FINAL_BLOCK_SIZE)
+ // The normal body section size is flow_target. But if there are only flow_max or less
+ // remaining we take the whole thing rather than leave a small final section.
+ if (remaining <= flow_max)
{
num_flush = remaining;
remaining = 0;
else
{
// FIXIT-M need to implement random increments
- num_flush = DATA_BLOCK_SIZE;
+ num_flush = flow_target;
remaining -= num_flush;
return SCAN_FOUND_PIECE;
}
}
ScanResult NHttpChunkCutter::cut(const uint8_t* buffer, uint32_t length,
- NHttpInfractions& infractions, NHttpEventGen& events)
+ NHttpInfractions& infractions, NHttpEventGen& events, uint32_t flow_target, uint32_t)
{
if (new_section)
{
case CHUNK_DATA:
{
uint32_t skip_amount = (length-k <= expected) ? length-k : expected;
- skip_amount = (skip_amount <= DATA_BLOCK_SIZE-data_seen) ? skip_amount :
- DATA_BLOCK_SIZE-data_seen;
+ skip_amount = (skip_amount <= flow_target-data_seen) ? skip_amount :
+ flow_target-data_seen;
k += skip_amount - 1;
if ((expected -= skip_amount) == 0)
{
curr_state = CHUNK_DCRLF1;
}
- if ((data_seen += skip_amount) == DATA_BLOCK_SIZE)
+ if ((data_seen += skip_amount) == flow_target)
{
// FIXIT-M need to randomize slice point
data_seen = 0;
break;
case CHUNK_BAD:
uint32_t skip_amount = length-k;
- skip_amount = (skip_amount <= DATA_BLOCK_SIZE-data_seen) ? skip_amount :
- DATA_BLOCK_SIZE-data_seen;
+ skip_amount = (skip_amount <= flow_target-data_seen) ? skip_amount :
+ flow_target-data_seen;
k += skip_amount - 1;
- if ((data_seen += skip_amount) == DATA_BLOCK_SIZE)
+ if ((data_seen += skip_amount) == flow_target)
{
// FIXIT-M need to randomize slice point
data_seen = 0;
public:
virtual ~NHttpCutter() = default;
virtual NHttpEnums::ScanResult cut(const uint8_t* buffer, uint32_t length,
- NHttpInfractions& infractions, NHttpEventGen& events) = 0;
+ NHttpInfractions& infractions, NHttpEventGen& events, uint32_t flow_target,
+ uint32_t flow_max) = 0;
uint32_t get_num_flush() const { return num_flush; }
uint32_t get_octets_seen() const { return octets_seen; }
virtual uint32_t get_num_excess() const { return 0; }
{
public:
NHttpEnums::ScanResult cut(const uint8_t* buffer, uint32_t length,
- NHttpInfractions& infractions, NHttpEventGen& events) override;
+ NHttpInfractions& infractions, NHttpEventGen& events, uint32_t, uint32_t) override;
uint32_t get_num_excess() const override { return (num_flush > 0) ? num_crlf : 0; }
protected:
{
public:
NHttpEnums::ScanResult cut(const uint8_t* buffer, uint32_t length,
- NHttpInfractions& infractions, NHttpEventGen& events) override;
+ NHttpInfractions& infractions, NHttpEventGen& events, uint32_t, uint32_t) override;
uint32_t get_num_excess() const override { return (num_flush > 0) ? num_crlf : 0; }
uint32_t get_num_head_lines() const override { return num_head_lines; }
public:
explicit NHttpBodyCutter(int64_t expected_length) : remaining(expected_length)
{ assert(remaining > 0); }
- NHttpEnums::ScanResult cut(const uint8_t*, uint32_t, NHttpInfractions&, NHttpEventGen&)
- override;
+ NHttpEnums::ScanResult cut(const uint8_t*, uint32_t, NHttpInfractions&, NHttpEventGen&,
+ uint32_t flow_target, uint32_t flow_max) override;
private:
int64_t remaining;
{
public:
NHttpEnums::ScanResult cut(const uint8_t* buffer, uint32_t length,
- NHttpInfractions& infractions, NHttpEventGen& events) override;
+ NHttpInfractions& infractions, NHttpEventGen& events, uint32_t flow_target, uint32_t)
+ override;
bool get_is_broken_chunk() const { return curr_state == NHttpEnums::CHUNK_BAD; }
uint32_t get_num_good_chunks() const { return num_good_chunks; }
}
data_length[source_id] = STAT_NOTPRESENT;
body_octets[source_id] = STAT_NOTPRESENT;
+ section_size_target[source_id] = 0;
+ section_size_max[source_id] = 0;
infractions[source_id].reset();
events[source_id].reset();
}
// 0 element refers to client request, 1 element refers to server response
- // StreamSplitter internal data - scan()
+ // *** StreamSplitter internal data - scan()
NHttpCutter* cutter[2] = { nullptr, nullptr };
- // StreamSplitter internal data - reassemble()
+ // *** StreamSplitter internal data - reassemble()
uint8_t* section_buffer[2] = { nullptr, nullptr };
uint32_t chunk_offset[2] = { 0, 0 };
NHttpEnums::ChunkState chunk_state[2] = { NHttpEnums::CHUNK_NUMBER, NHttpEnums::CHUNK_NUMBER };
uint32_t chunk_expected_length[2] = { 0, 0 };
- // StreamSplitter internal data - scan() => reassemble()
+ // *** StreamSplitter internal data - scan() => reassemble()
uint32_t num_excess[2] = { 0, 0 };
bool is_broken_chunk[2] = { false, false };
uint32_t num_good_chunks[2] = { 0, 0 };
- // StreamSplitter => Inspector (facts about the most recent message section)
+ // *** StreamSplitter => Inspector (facts about the most recent message section)
NHttpEnums::SectionType section_type[2] = { NHttpEnums::SEC__NOTCOMPUTE,
NHttpEnums::SEC__NOTCOMPUTE };
bool tcp_close[2] = { false, false };
int32_t num_head_lines[2] = { NHttpEnums::STAT_NOTPRESENT, NHttpEnums::STAT_NOTPRESENT };
uint32_t flush_size[2] = { 0, 0 };
- // Inspector => StreamSplitter (facts about the message section that is coming next)
+ // *** Inspector => StreamSplitter (facts about the message section that is coming next)
NHttpEnums::SectionType type_expected[2] = { NHttpEnums::SEC_REQUEST, NHttpEnums::SEC_STATUS };
-
// length of the data from Content-Length field
int64_t data_length[2] = { NHttpEnums::STAT_NOTPRESENT, NHttpEnums::STAT_NOTPRESENT };
+ uint32_t section_size_target[2] = { 0, 0 };
+ uint32_t section_size_max[2] = { 0, 0 };
- // Inspector's internal data about the current message
+ // *** Inspector's internal data about the current message
NHttpEnums::VersionId version_id[2] = { NHttpEnums::VERS__NOTPRESENT,
NHttpEnums::VERS__NOTPRESENT };
NHttpEnums::MethodId method_id = NHttpEnums::METH__NOTPRESENT;
{
// More body coming
session_data->body_octets[source_id] = body_octets;
+ session_data->section_size_target[source_id] = DATA_BLOCK_SIZE;
+ session_data->section_size_max[source_id] = FINAL_BLOCK_SIZE;
session_data->infractions[source_id] = infractions;
session_data->events[source_id] = events;
}
else
{
session_data->body_octets[source_id] = body_octets;
+ session_data->section_size_target[source_id] = DATA_BLOCK_SIZE;
session_data->infractions[source_id] = infractions;
session_data->events[source_id] = events;
}
// Chunked body
session_data->type_expected[source_id] = SEC_CHUNK;
session_data->body_octets[source_id] = 0;
+ session_data->section_size_target[source_id] = DATA_BLOCK_SIZE;
session_data->infractions[source_id].reset();
session_data->events[source_id].reset();
}
session_data->data_length[source_id] = *(int64_t*)get_header_value_norm(
HEAD_CONTENT_LENGTH).start;
session_data->body_octets[source_id] = 0;
+ session_data->section_size_target[source_id] = DATA_BLOCK_SIZE;
+ session_data->section_size_max[source_id] = FINAL_BLOCK_SIZE;
session_data->infractions[source_id].reset();
session_data->events[source_id].reset();
}
}
const uint32_t max_length = MAX_OCTETS - cutter->get_octets_seen();
const ScanResult cut_result = cutter->cut(data, (length <= max_length) ? length :
- max_length, session_data->infractions[source_id], session_data->events[source_id]);
+ max_length, session_data->infractions[source_id], session_data->events[source_id],
+ session_data->section_size_target[source_id], session_data->section_size_max[source_id]);
switch (cut_result)
{
case SCAN_NOTFOUND: