mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
168 lines
4.7 KiB
C++
168 lines
4.7 KiB
C++
#ifndef binpac_buffer_h
|
|
#define binpac_buffer_h
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include "binpac.h"
|
|
|
|
namespace binpac {
|
|
|
|
class FlowBuffer {
|
|
public:
|
|
struct Policy {
|
|
int max_capacity;
|
|
int min_capacity;
|
|
int contract_threshold;
|
|
};
|
|
|
|
enum LineBreakStyle {
|
|
CR_OR_LF, // CR or LF or CRLF
|
|
STRICT_CRLF, // CR followed by LF
|
|
CR_LF_NUL, // CR or LF or CR-LF or CR-NUL
|
|
LINE_BREAKER, // User specified linebreaker
|
|
};
|
|
|
|
FlowBuffer(LineBreakStyle linebreak_style = CR_OR_LF);
|
|
virtual ~FlowBuffer();
|
|
|
|
void NewData(const_byteptr begin, const_byteptr end);
|
|
void NewGap(int length);
|
|
|
|
// Interface for delayed parsing. Sometimes BinPAC doesn't get the
|
|
// buffering right and then one can use these to feed parts
|
|
// individually and assemble them internally. After calling
|
|
// FinishBuffer(), one can send the upper-layer flow an FlowEOF() to
|
|
// trigger parsing.
|
|
void BufferData(const_byteptr data, const_byteptr end);
|
|
void FinishBuffer();
|
|
|
|
// Discard unprocessed data
|
|
void DiscardData();
|
|
|
|
// Whether there is enough data for the frame
|
|
bool ready() const { return message_complete_ || mode_ == UNKNOWN_MODE; }
|
|
|
|
inline const_byteptr begin() const {
|
|
BINPAC_ASSERT(ready());
|
|
return (buffer_n_ == 0) ? orig_data_begin_ : buffer_;
|
|
}
|
|
|
|
inline const_byteptr end() const {
|
|
BINPAC_ASSERT(ready());
|
|
if ( buffer_n_ == 0 ) {
|
|
BINPAC_ASSERT(frame_length_ >= 0);
|
|
const_byteptr end = orig_data_begin_ + frame_length_;
|
|
BINPAC_ASSERT(end <= orig_data_end_);
|
|
return end;
|
|
}
|
|
else
|
|
return buffer_ + buffer_n_;
|
|
}
|
|
|
|
inline int data_length() const {
|
|
if ( buffer_n_ > 0 )
|
|
return buffer_n_;
|
|
|
|
if ( frame_length_ < 0 || orig_data_begin_ + frame_length_ > orig_data_end_ )
|
|
return orig_data_end_ - orig_data_begin_;
|
|
else
|
|
return frame_length_;
|
|
}
|
|
|
|
inline bool data_available() const { return buffer_n_ > 0 || orig_data_end_ > orig_data_begin_; }
|
|
|
|
void SetLineBreaker(unsigned char* lbreaker);
|
|
void UnsetLineBreaker();
|
|
void NewLine();
|
|
// A negative frame_length represents a frame till EOF
|
|
void NewFrame(int frame_length, bool chunked_);
|
|
void GrowFrame(int new_frame_length);
|
|
|
|
int data_seq() const {
|
|
int data_seq_at_orig_data_begin = data_seq_at_orig_data_end_ - (orig_data_end_ - orig_data_begin_);
|
|
if ( buffer_n_ > 0 )
|
|
return data_seq_at_orig_data_begin;
|
|
else
|
|
return data_seq_at_orig_data_begin + data_length();
|
|
}
|
|
bool eof() const { return eof_; }
|
|
void set_eof();
|
|
|
|
bool have_pending_request() const { return have_pending_request_; }
|
|
|
|
static void init(Policy p) { policy = p; }
|
|
|
|
protected:
|
|
// Reset the buffer for a new message
|
|
void NewMessage();
|
|
|
|
void ClearPreviousData();
|
|
|
|
// Expand the buffer to at least <length> bytes. If there
|
|
// are contents in the existing buffer, copy them to the new
|
|
// buffer.
|
|
void ExpandBuffer(int length);
|
|
|
|
// Contract the buffer to some minimum capacity.
|
|
// Existing contents in the buffer are preserved (but only usage
|
|
// at the time of creation this function is when the contents
|
|
// are being discarded due to parsing exception or have already been
|
|
// copied out after parsing a complete unit).
|
|
void ContractBuffer();
|
|
|
|
// Reset line state when transit from frame mode to line mode.
|
|
void ResetLineState();
|
|
|
|
void AppendToBuffer(const_byteptr data, int len);
|
|
|
|
// MarkOrCopy{Line,Frame} sets message_complete_ and
|
|
// marks begin/end pointers if a line/frame is complete,
|
|
// otherwise it clears message_complete_ and copies all
|
|
// the original data to the buffer.
|
|
//
|
|
void MarkOrCopy();
|
|
void MarkOrCopyLine();
|
|
void MarkOrCopyFrame();
|
|
|
|
void MarkOrCopyLine_CR_OR_LF();
|
|
void MarkOrCopyLine_STRICT_CRLF();
|
|
void MarkOrCopyLine_LINEBREAK();
|
|
|
|
int buffer_n_; // number of bytes in the buffer
|
|
int buffer_length_; // size of the buffer
|
|
unsigned char* buffer_;
|
|
bool message_complete_;
|
|
int frame_length_;
|
|
bool chunked_;
|
|
const_byteptr orig_data_begin_, orig_data_end_;
|
|
|
|
LineBreakStyle linebreak_style_;
|
|
LineBreakStyle linebreak_style_default;
|
|
unsigned char linebreaker_;
|
|
|
|
enum {
|
|
UNKNOWN_MODE,
|
|
LINE_MODE,
|
|
FRAME_MODE,
|
|
} mode_;
|
|
|
|
enum {
|
|
CR_OR_LF_0,
|
|
CR_OR_LF_1,
|
|
STRICT_CRLF_0,
|
|
STRICT_CRLF_1,
|
|
FRAME_0,
|
|
} state_;
|
|
|
|
int data_seq_at_orig_data_end_;
|
|
bool eof_;
|
|
bool have_pending_request_;
|
|
|
|
static Policy policy;
|
|
};
|
|
|
|
typedef FlowBuffer* flow_buffer_t;
|
|
|
|
} // namespace binpac
|
|
|
|
#endif // binpac_buffer_h
|