Skip to content

Commit

Permalink
Add draft frame decode
Browse files Browse the repository at this point in the history
  • Loading branch information
halx99 committed Dec 10, 2024
1 parent 0817150 commit 9d37dff
Showing 1 changed file with 115 additions and 0 deletions.
115 changes: 115 additions & 0 deletions yasio/frame.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
#pragma once
#include "yasio/config.hpp"
#include "yasio/byte_buffer.hpp"
#include "yasio/endian_portable.hpp"
#include <limits>

namespace yasio
{
struct frame_options {
int max_frame_length = (std::numeric_limits<int>::max)();
int length_field_offset = -1; // -1: directly, >= 0: store as 1~4bytes integer
int length_field_length = 4; // 1,2,3,4
int length_adjustment = 0; // if the length field value not whole packet
int initial_bytes_to_strip = 0;
int no_bswap = 0;
};
class frame {
public:
frame(const frame_options& opts) : opts_(opts) {}

void input(const void* d, int n)
{
const uint8_t* ptr = static_cast<const uint8_t*>(d);
int avail = n;
int offset = 0;
do
{
if (frame_size_ == 0)
{
if (head_buf_.empty())
frame_size_ = decode_len(ptr, avail);
else
{
const auto max_head_size = opts_.length_field_offset + opts_.length_field_length;
int read_size = (std::min)(avail, max_head_size - static_cast<int>(head_buf_.size()));
if (read_size > 0)
consume(ptr, read_size, avail);
frame_size_ = decode_len(head_buf_.data(), static_cast<int>(head_buf_.size()));
if (frame_size_ > 0)
head_buf_.clear();
}
}

if (frame_size_ > 0)
{
int read_size = (std::min)(frame_size_ - cur_size_, avail);
if (read_size > 0)
consume(ptr, read_size, avail);
// else: wait fame data
}
else
{
if (frame_size_ == 0)
{ // head incomplete
if (avail > 0)
consume(ptr, avail, avail);
}
else
{
printf("on_frame data, invalid frame size: %d\n", frame_size_);
}
// else: no avail data
break;
}
} while (avail > 0);
}

void consume(const uint8_t*& ptr, int n, int& avail)
{
printf("on_frame data, size: %d/%d\n", cur_size_ + n, frame_size_);
cur_size_ += n;

if (frame_size_ == 0)
head_buf_.append(ptr, ptr + n);

if (cur_size_ == frame_size_)
{
frame_size_ = 0;
cur_size_ = 0;
head_buf_.clear();
}

ptr += n;
avail -= n;
}

int decode_len(const void* d, int n)
{
int loffset = opts_.length_field_offset;
int lsize = opts_.length_field_length;
if (loffset >= 0)
{
assert(lsize >= 1 && lsize <= YASIO_SSIZEOF(int));
int len = 0;
if (n >= (loffset + lsize))
{
::memcpy(&len, (uint8_t*)d + loffset, lsize);
if (!opts_.no_bswap)
len = yasio::network_to_host(len, lsize);
len += opts_.length_adjustment;
if (len > opts_.max_frame_length)
len = -1;
}
return len;
}
return n;
}

private:
const frame_options& opts_;
int frame_size_ = 0;
int cur_size_ = 0;
yasio::byte_buffer head_buf_;
};
} // namespace yasio

0 comments on commit 9d37dff

Please sign in to comment.