mirror of
https://github.com/zeek/zeek.git
synced 2025-10-09 10:08:20 +00:00
Revert "Move BinPAC, bifcl, af_packet, and gen_zam submodules into main zeek repo"
This commit is contained in:
parent
a10a70994e
commit
e64ec54172
146 changed files with 50 additions and 20635 deletions
|
@ -1,44 +0,0 @@
|
|||
include(TestBigEndian)
|
||||
test_big_endian(HOST_BIGENDIAN)
|
||||
|
||||
include(CheckTypeSize)
|
||||
check_type_size("unsigned int" SIZEOF_UNSIGNED_INT)
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/binpac.h.in ${CMAKE_CURRENT_BINARY_DIR}/binpac.h)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set(binpac_headers ${CMAKE_CURRENT_BINARY_DIR}/binpac.h binpac_analyzer.h binpac_buffer.h
|
||||
binpac_bytestring.h binpac_exception.h binpac_regex.h)
|
||||
|
||||
set(binpac_lib_SRCS binpac_buffer.cc binpac_bytestring.cc binpac_regex.cc)
|
||||
|
||||
if (BUILD_STATIC_BINPAC)
|
||||
add_library(binpac_static STATIC)
|
||||
target_sources(binpac_static PRIVATE ${binpac_lib_SRCS})
|
||||
set_target_properties(binpac_static PROPERTIES OUTPUT_NAME binpac)
|
||||
install(TARGETS binpac_static DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
if (MSVC)
|
||||
target_compile_options(binpac_static PRIVATE "/J")
|
||||
endif ()
|
||||
set(BinPAC_LIBRARY binpac_static CACHE STRING "BinPAC library" FORCE)
|
||||
else ()
|
||||
add_library(binpac_lib SHARED)
|
||||
target_sources(binpac_lib PRIVATE ${binpac_lib_SRCS})
|
||||
target_sources(binpac_lib INTERFACE ${binpac_headers})
|
||||
set_target_properties(binpac_lib PROPERTIES MACOSX_RPATH true OUTPUT_NAME binpac)
|
||||
if (MSVC)
|
||||
target_compile_options(binpac_lib PRIVATE "/J")
|
||||
endif ()
|
||||
install(TARGETS binpac_lib DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
set(BinPAC_LIBRARY binpac_lib CACHE STRING "BinPAC library" FORCE)
|
||||
endif ()
|
||||
|
||||
if (ZEEK_ROOT_DIR)
|
||||
# Installed in binpac subdir just for organization purposes.
|
||||
install(FILES ${binpac_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/binpac)
|
||||
else ()
|
||||
install(FILES ${binpac_headers} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
endif ()
|
||||
|
||||
set(BinPAC_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}
|
||||
CACHE STRING "BinPAC header directories" FORCE)
|
|
@ -1,3 +0,0 @@
|
|||
This directory contains a library needed by generated C++ code from
|
||||
binpac. Note that the library is not needed by the binpac compiler
|
||||
itself.
|
|
@ -1,160 +0,0 @@
|
|||
// Do not edit binpac.h, edit binpac.h.in instead!
|
||||
|
||||
#ifndef binpac_h
|
||||
#define binpac_h
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#cmakedefine HOST_BIGENDIAN
|
||||
#ifdef HOST_BIGENDIAN
|
||||
#define HOST_BYTEORDER bigendian
|
||||
#else
|
||||
#define HOST_BYTEORDER littleendian
|
||||
#endif
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdarg>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
// Expose C99 functionality from inttypes.h, which would otherwise not be
|
||||
// available in C++.
|
||||
#ifndef __STDC_FORMAT_MACROS
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#endif
|
||||
|
||||
static constexpr void BINPAC_ASSERT(bool val) { assert(val); }
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace binpac {
|
||||
|
||||
const int bigendian = 0;
|
||||
const int littleendian = 1;
|
||||
const int unspecified_byteorder = -1;
|
||||
|
||||
#ifndef pac_type_defs
|
||||
#define pac_type_defs
|
||||
|
||||
using int8 = int8_t;
|
||||
using int16 = int16_t;
|
||||
using int32 = int32_t;
|
||||
using int64 = int64_t;
|
||||
using uint8 = uint8_t;
|
||||
using uint16 = uint16_t;
|
||||
using uint32 = uint32_t;
|
||||
using uint64 = uint64_t;
|
||||
using nulptr = void*;
|
||||
using voidptr = void*;
|
||||
using byteptr = uint8*;
|
||||
using const_byteptr = const uint8*;
|
||||
using const_charptr = const char*;
|
||||
|
||||
static_assert(sizeof(unsigned int) == 4, "Unexpected size of unsigned int");
|
||||
|
||||
#endif /* pac_type_defs */
|
||||
|
||||
/* Handling byte order */
|
||||
|
||||
namespace {
|
||||
|
||||
inline uint16 pac_swap(const uint16 x) { return (x >> 8) | ((x & 0xff) << 8); }
|
||||
|
||||
inline int16 pac_swap(const int16 x) {
|
||||
// Forward to unsigned version with argument/result casted
|
||||
// appropriately.
|
||||
uint16 (*p)(const uint16) = &pac_swap;
|
||||
return (*p)(x);
|
||||
}
|
||||
|
||||
inline uint32 pac_swap(const uint32 x) {
|
||||
return (x >> 24) | ((x & 0xff0000) >> 8) | ((x & 0xff00) << 8) | ((x & 0xff) << 24);
|
||||
}
|
||||
|
||||
inline int32 pac_swap(const int32 x) {
|
||||
// Forward to unsigned version with argument/result casted
|
||||
// appropriately.
|
||||
uint32 (*p)(const uint32) = &pac_swap;
|
||||
return (*p)(x);
|
||||
}
|
||||
|
||||
inline uint64 pac_swap(const uint64 x) {
|
||||
return x >> 56 | (x & 0xff000000000000) >> 40 | (x & 0xff0000000000) >> 24 | (x & 0xff00000000) >> 8 |
|
||||
(x & 0xff000000) << 8 | (x & 0xff0000) << 24 | (x & 0xff00) << 40 | (x & 0xff) << 56;
|
||||
}
|
||||
|
||||
inline int64 pac_swap(const int64 x) {
|
||||
// Forward to unsigned version with argument/result casted
|
||||
// appropriately.
|
||||
uint64 (*p)(const uint64) = &pac_swap;
|
||||
return (*p)(x);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static constexpr T FixByteOrder(int byteorder, T x) {
|
||||
if ( byteorder == HOST_BYTEORDER )
|
||||
return x;
|
||||
|
||||
return static_cast<T>(pac_swap(x));
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline T UnMarshall(const unsigned char* data, int byteorder) {
|
||||
T result = 0;
|
||||
for ( int i = 0; i < (int)sizeof(T); ++i )
|
||||
result = (result << 8) | data[byteorder == bigendian ? i : sizeof(T) - 1 - i];
|
||||
return result;
|
||||
}
|
||||
|
||||
inline const char* do_fmt(const char* format, va_list ap) {
|
||||
static char buf[1024];
|
||||
vsnprintf(buf, sizeof(buf), format, ap);
|
||||
return buf;
|
||||
}
|
||||
|
||||
inline string strfmt(const char* format, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
const char* r = do_fmt(format, ap);
|
||||
va_end(ap);
|
||||
return {r};
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
||||
#define binpac_fmt(...) strfmt(__VA_ARGS__).c_str()
|
||||
|
||||
class RefCount {
|
||||
public:
|
||||
RefCount() { count = 1; }
|
||||
virtual ~RefCount() {}
|
||||
void Ref() { ++count; }
|
||||
int Unref() {
|
||||
BINPAC_ASSERT(count > 0);
|
||||
return --count;
|
||||
}
|
||||
|
||||
private:
|
||||
int count;
|
||||
};
|
||||
|
||||
namespace {
|
||||
inline void Unref(RefCount* x) {
|
||||
if ( x && x->Unref() <= 0 )
|
||||
delete x;
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
} // namespace binpac
|
||||
|
||||
#include "binpac_analyzer.h"
|
||||
#include "binpac_buffer.h"
|
||||
#include "binpac_bytestring.h"
|
||||
#include "binpac_exception.h"
|
||||
#include "binpac_regex.h"
|
||||
|
||||
#endif /* binpac_h */
|
|
@ -1,26 +0,0 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#ifndef binpac_an_h
|
||||
#define binpac_an_h
|
||||
|
||||
namespace binpac {
|
||||
|
||||
// TODO: Add the Done() function
|
||||
|
||||
// The interface for a connection analyzer
|
||||
class ConnectionAnalyzer {
|
||||
public:
|
||||
virtual ~ConnectionAnalyzer() = default;
|
||||
virtual void NewData(bool is_orig, const unsigned char* begin_of_data, const unsigned char* end_of_data) = 0;
|
||||
};
|
||||
|
||||
// The interface for a flow analyzer
|
||||
class FlowAnalyzer {
|
||||
public:
|
||||
virtual ~FlowAnalyzer() = default;
|
||||
virtual void NewData(const unsigned char* begin_of_data, const unsigned char* end_of_data) = 0;
|
||||
};
|
||||
|
||||
} // namespace binpac
|
||||
|
||||
#endif // binpac_an_h
|
|
@ -1,459 +0,0 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h> // for memcpy
|
||||
|
||||
#define binpac_regex_h
|
||||
|
||||
#include "binpac.h"
|
||||
#include "binpac_buffer.h"
|
||||
|
||||
namespace binpac {
|
||||
|
||||
extern double network_time();
|
||||
|
||||
namespace {
|
||||
const unsigned char CR = '\r';
|
||||
const unsigned char LF = '\n';
|
||||
} // namespace
|
||||
|
||||
binpac::FlowBuffer::Policy binpac::FlowBuffer::policy = {
|
||||
// max_capacity
|
||||
10 * 1024 * 1024,
|
||||
// min_capacity
|
||||
512,
|
||||
// contract_threshold
|
||||
2 * 1024 * 1024,
|
||||
};
|
||||
|
||||
FlowBuffer::FlowBuffer(LineBreakStyle linebreak_style) {
|
||||
buffer_length_ = 0;
|
||||
buffer_ = nullptr;
|
||||
|
||||
orig_data_begin_ = nullptr;
|
||||
orig_data_end_ = nullptr;
|
||||
|
||||
linebreak_style_ = linebreak_style;
|
||||
linebreak_style_default = linebreak_style;
|
||||
linebreaker_ = 0;
|
||||
ResetLineState();
|
||||
|
||||
mode_ = UNKNOWN_MODE;
|
||||
frame_length_ = 0;
|
||||
chunked_ = false;
|
||||
|
||||
data_seq_at_orig_data_end_ = 0;
|
||||
eof_ = false;
|
||||
have_pending_request_ = false;
|
||||
|
||||
buffer_n_ = 0;
|
||||
|
||||
NewMessage();
|
||||
}
|
||||
|
||||
FlowBuffer::~FlowBuffer() {
|
||||
if ( buffer_ )
|
||||
free(buffer_);
|
||||
}
|
||||
|
||||
void FlowBuffer::NewMessage() {
|
||||
BINPAC_ASSERT(frame_length_ >= 0);
|
||||
|
||||
int bytes_to_advance = 0;
|
||||
if ( buffer_n_ == 0 ) {
|
||||
switch ( mode_ ) {
|
||||
case LINE_MODE: bytes_to_advance = (frame_length_ + (linebreak_style_ == STRICT_CRLF ? 2 : 1)); break;
|
||||
case FRAME_MODE: bytes_to_advance = frame_length_; break;
|
||||
case UNKNOWN_MODE: break;
|
||||
}
|
||||
}
|
||||
|
||||
orig_data_begin_ += bytes_to_advance;
|
||||
BINPAC_ASSERT(orig_data_begin_ <= orig_data_end_);
|
||||
|
||||
buffer_n_ = 0;
|
||||
message_complete_ = false;
|
||||
ContractBuffer();
|
||||
}
|
||||
|
||||
void FlowBuffer::ResetLineState() {
|
||||
switch ( linebreak_style_ ) {
|
||||
case CR_OR_LF: state_ = CR_OR_LF_0; break;
|
||||
case STRICT_CRLF: state_ = STRICT_CRLF_0; break;
|
||||
case LINE_BREAKER: break; // Nothing to reset
|
||||
default: BINPAC_ASSERT(0); break;
|
||||
}
|
||||
}
|
||||
|
||||
void FlowBuffer::ExpandBuffer(int length) {
|
||||
if ( buffer_length_ >= length )
|
||||
return;
|
||||
|
||||
if ( length < policy.min_capacity )
|
||||
length = policy.min_capacity;
|
||||
|
||||
if ( length < buffer_length_ * 2 )
|
||||
length = buffer_length_ * 2;
|
||||
|
||||
if ( length > policy.max_capacity ) {
|
||||
std::string reason = strfmt("expand past max capacity %d/%d", length, policy.max_capacity);
|
||||
throw ExceptionFlowBufferAlloc(reason.c_str());
|
||||
}
|
||||
|
||||
// Allocate a new buffer and copy the existing contents
|
||||
buffer_length_ = length;
|
||||
unsigned char* new_buf = (unsigned char*)realloc(buffer_, buffer_length_);
|
||||
|
||||
if ( ! new_buf )
|
||||
throw ExceptionFlowBufferAlloc("expand realloc OOM");
|
||||
|
||||
buffer_ = new_buf;
|
||||
}
|
||||
|
||||
void FlowBuffer::ContractBuffer() {
|
||||
if ( buffer_length_ < policy.contract_threshold )
|
||||
return;
|
||||
|
||||
buffer_length_ = policy.min_capacity;
|
||||
unsigned char* new_buf = (unsigned char*)realloc(buffer_, buffer_length_);
|
||||
|
||||
if ( ! new_buf )
|
||||
throw ExceptionFlowBufferAlloc("contract realloc OOM");
|
||||
|
||||
buffer_ = new_buf;
|
||||
}
|
||||
|
||||
void FlowBuffer::SetLineBreaker(unsigned char* lbreaker) {
|
||||
linebreaker_ = *lbreaker;
|
||||
linebreak_style_default = linebreak_style_;
|
||||
linebreak_style_ = LINE_BREAKER;
|
||||
}
|
||||
|
||||
void FlowBuffer::UnsetLineBreaker() { linebreak_style_ = linebreak_style_default; }
|
||||
|
||||
void FlowBuffer::NewLine() {
|
||||
FlowBuffer::NewMessage();
|
||||
mode_ = LINE_MODE;
|
||||
frame_length_ = 0;
|
||||
chunked_ = false;
|
||||
have_pending_request_ = true;
|
||||
if ( state_ == FRAME_0 )
|
||||
ResetLineState();
|
||||
MarkOrCopyLine();
|
||||
}
|
||||
|
||||
void FlowBuffer::NewFrame(int frame_length, bool chunked) {
|
||||
FlowBuffer::NewMessage();
|
||||
mode_ = FRAME_MODE;
|
||||
frame_length_ = frame_length;
|
||||
chunked_ = chunked;
|
||||
have_pending_request_ = true;
|
||||
MarkOrCopyFrame();
|
||||
}
|
||||
|
||||
void FlowBuffer::BufferData(const_byteptr data, const_byteptr end) {
|
||||
mode_ = FRAME_MODE;
|
||||
frame_length_ += (end - data);
|
||||
MarkOrCopyFrame();
|
||||
NewData(data, end);
|
||||
}
|
||||
|
||||
void FlowBuffer::FinishBuffer() { message_complete_ = true; }
|
||||
|
||||
void FlowBuffer::GrowFrame(int length) {
|
||||
BINPAC_ASSERT(frame_length_ >= 0);
|
||||
if ( length <= frame_length_ )
|
||||
return;
|
||||
BINPAC_ASSERT(! chunked_ || frame_length_ == 0);
|
||||
mode_ = FRAME_MODE;
|
||||
frame_length_ = length;
|
||||
MarkOrCopyFrame();
|
||||
}
|
||||
|
||||
void FlowBuffer::DiscardData() {
|
||||
mode_ = UNKNOWN_MODE;
|
||||
message_complete_ = false;
|
||||
have_pending_request_ = false;
|
||||
orig_data_begin_ = orig_data_end_ = nullptr;
|
||||
|
||||
buffer_n_ = 0;
|
||||
frame_length_ = 0;
|
||||
ContractBuffer();
|
||||
}
|
||||
|
||||
void FlowBuffer::set_eof() {
|
||||
// fprintf(stderr, "EOF\n");
|
||||
eof_ = true;
|
||||
if ( chunked_ )
|
||||
frame_length_ = orig_data_end_ - orig_data_begin_;
|
||||
if ( frame_length_ < 0 )
|
||||
frame_length_ = 0;
|
||||
}
|
||||
|
||||
void FlowBuffer::NewData(const_byteptr begin, const_byteptr end) {
|
||||
BINPAC_ASSERT(begin <= end);
|
||||
|
||||
ClearPreviousData();
|
||||
|
||||
BINPAC_ASSERT((buffer_n_ == 0 && message_complete_) || orig_data_begin_ == orig_data_end_);
|
||||
|
||||
orig_data_begin_ = begin;
|
||||
orig_data_end_ = end;
|
||||
data_seq_at_orig_data_end_ += (end - begin);
|
||||
|
||||
MarkOrCopy();
|
||||
}
|
||||
|
||||
void FlowBuffer::MarkOrCopy() {
|
||||
if ( ! message_complete_ ) {
|
||||
switch ( mode_ ) {
|
||||
case LINE_MODE: MarkOrCopyLine(); break;
|
||||
|
||||
case FRAME_MODE: MarkOrCopyFrame(); break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FlowBuffer::ClearPreviousData() {
|
||||
// All previous data must have been processed or buffered already
|
||||
if ( orig_data_begin_ < orig_data_end_ ) {
|
||||
BINPAC_ASSERT(buffer_n_ == 0);
|
||||
if ( chunked_ ) {
|
||||
if ( frame_length_ > 0 ) {
|
||||
frame_length_ -= (orig_data_end_ - orig_data_begin_);
|
||||
}
|
||||
orig_data_begin_ = orig_data_end_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FlowBuffer::NewGap(int length) {
|
||||
ClearPreviousData();
|
||||
|
||||
if ( chunked_ && frame_length_ >= 0 ) {
|
||||
frame_length_ -= length;
|
||||
if ( frame_length_ < 0 )
|
||||
frame_length_ = 0;
|
||||
}
|
||||
|
||||
orig_data_begin_ = orig_data_end_ = nullptr;
|
||||
MarkOrCopy();
|
||||
}
|
||||
|
||||
void FlowBuffer::MarkOrCopyLine() {
|
||||
switch ( linebreak_style_ ) {
|
||||
case CR_OR_LF: MarkOrCopyLine_CR_OR_LF(); break;
|
||||
case STRICT_CRLF: MarkOrCopyLine_STRICT_CRLF(); break;
|
||||
case LINE_BREAKER: MarkOrCopyLine_LINEBREAK(); break;
|
||||
default: BINPAC_ASSERT(0); break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Finite state automaton for CR_OR_LF:
|
||||
(!--line is complete, *--add to buffer)
|
||||
|
||||
CR_OR_LF_0:
|
||||
CR: CR_OR_LF_1 !
|
||||
LF: CR_OR_LF_0 !
|
||||
.: CR_OR_LF_0 *
|
||||
|
||||
CR_OR_LF_1:
|
||||
CR: CR_OR_LF_1 !
|
||||
LF: CR_OR_LF_0
|
||||
.: CR_OR_LF_0 *
|
||||
*/
|
||||
|
||||
void FlowBuffer::MarkOrCopyLine_CR_OR_LF() {
|
||||
if ( ! (orig_data_begin_ && orig_data_end_) )
|
||||
return;
|
||||
|
||||
if ( state_ == CR_OR_LF_1 && orig_data_begin_ < orig_data_end_ && *orig_data_begin_ == LF ) {
|
||||
state_ = CR_OR_LF_0;
|
||||
++orig_data_begin_;
|
||||
}
|
||||
|
||||
const_byteptr data;
|
||||
for ( data = orig_data_begin_; data < orig_data_end_; ++data ) {
|
||||
switch ( *data ) {
|
||||
case CR: state_ = CR_OR_LF_1; goto found_end_of_line;
|
||||
|
||||
case LF:
|
||||
// state_ = CR_OR_LF_0;
|
||||
goto found_end_of_line;
|
||||
|
||||
default:
|
||||
// state_ = CR_OR_LF_0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
AppendToBuffer(orig_data_begin_, orig_data_end_ - orig_data_begin_);
|
||||
return;
|
||||
|
||||
found_end_of_line:
|
||||
if ( buffer_n_ == 0 ) {
|
||||
frame_length_ = data - orig_data_begin_;
|
||||
}
|
||||
else {
|
||||
AppendToBuffer(orig_data_begin_, data + 1 - orig_data_begin_);
|
||||
// But eliminate the last CR or LF
|
||||
--buffer_n_;
|
||||
}
|
||||
message_complete_ = true;
|
||||
|
||||
#if DEBUG_FLOW_BUFFER
|
||||
fprintf(stderr, "%.6f Line complete: [%s]\n", network_time(),
|
||||
string((const char*)begin(), (const char*)end()).c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
Finite state automaton and STRICT_CRLF:
|
||||
(!--line is complete, *--add to buffer)
|
||||
|
||||
STRICT_CRLF_0:
|
||||
CR: STRICT_CRLF_1 *
|
||||
LF: STRICT_CRLF_0 *
|
||||
.: STRICT_CRLF_0 *
|
||||
|
||||
STRICT_CRLF_1:
|
||||
CR: STRICT_CRLF_1 *
|
||||
LF: STRICT_CRLF_0 ! (--buffer_n_)
|
||||
.: STRICT_CRLF_0 *
|
||||
*/
|
||||
|
||||
void FlowBuffer::MarkOrCopyLine_STRICT_CRLF() {
|
||||
const_byteptr data;
|
||||
for ( data = orig_data_begin_; data < orig_data_end_; ++data ) {
|
||||
switch ( *data ) {
|
||||
case CR: state_ = STRICT_CRLF_1; break;
|
||||
|
||||
case LF:
|
||||
if ( state_ == STRICT_CRLF_1 ) {
|
||||
state_ = STRICT_CRLF_0;
|
||||
goto found_end_of_line;
|
||||
}
|
||||
break;
|
||||
|
||||
default: state_ = STRICT_CRLF_0; break;
|
||||
}
|
||||
}
|
||||
|
||||
AppendToBuffer(orig_data_begin_, orig_data_end_ - orig_data_begin_);
|
||||
return;
|
||||
|
||||
found_end_of_line:
|
||||
if ( buffer_n_ == 0 ) {
|
||||
frame_length_ = data - 1 - orig_data_begin_;
|
||||
}
|
||||
else {
|
||||
AppendToBuffer(orig_data_begin_, data + 1 - orig_data_begin_);
|
||||
// Pop the preceding CR and LF from the buffer
|
||||
buffer_n_ -= 2;
|
||||
}
|
||||
|
||||
message_complete_ = true;
|
||||
|
||||
#if DEBUG_FLOW_BUFFER
|
||||
fprintf(stderr, "%.6f Line complete: [%s]\n", network_time(),
|
||||
string((const char*)begin(), (const char*)end()).c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
void FlowBuffer::MarkOrCopyLine_LINEBREAK() {
|
||||
if ( ! (orig_data_begin_ && orig_data_end_) )
|
||||
return;
|
||||
|
||||
const_byteptr data;
|
||||
for ( data = orig_data_begin_; data < orig_data_end_; ++data ) {
|
||||
if ( *data == linebreaker_ )
|
||||
goto found_end_of_line;
|
||||
}
|
||||
|
||||
AppendToBuffer(orig_data_begin_, orig_data_end_ - orig_data_begin_);
|
||||
return;
|
||||
|
||||
found_end_of_line:
|
||||
if ( buffer_n_ == 0 ) {
|
||||
frame_length_ = data - orig_data_begin_;
|
||||
}
|
||||
else {
|
||||
AppendToBuffer(orig_data_begin_, data + 1 - orig_data_begin_);
|
||||
// But eliminate the last 'linebreaker' character
|
||||
--buffer_n_;
|
||||
}
|
||||
message_complete_ = true;
|
||||
|
||||
#if DEBUG_FLOW_BUFFER
|
||||
fprintf(stderr, "%.6f Line complete: [%s]\n", network_time(),
|
||||
string((const char*)begin(), (const char*)end()).c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
// Invariants:
|
||||
//
|
||||
// When buffer_n_ == 0:
|
||||
// Frame = [orig_data_begin_..(orig_data_begin_ + frame_length_)]
|
||||
//
|
||||
// When buffer_n_ > 0:
|
||||
// Frame = [0..buffer_n_][orig_data_begin_..]
|
||||
|
||||
void FlowBuffer::MarkOrCopyFrame() {
|
||||
if ( mode_ == FRAME_MODE && state_ == CR_OR_LF_1 && orig_data_begin_ < orig_data_end_ ) {
|
||||
// Skip the lingering LF
|
||||
if ( *orig_data_begin_ == LF ) {
|
||||
++orig_data_begin_;
|
||||
}
|
||||
state_ = FRAME_0;
|
||||
}
|
||||
|
||||
if ( buffer_n_ == 0 ) {
|
||||
// If there is enough data
|
||||
if ( frame_length_ >= 0 && orig_data_end_ - orig_data_begin_ >= frame_length_ ) {
|
||||
// Do nothing except setting the message complete flag
|
||||
message_complete_ = true;
|
||||
}
|
||||
else {
|
||||
if ( ! chunked_ ) {
|
||||
AppendToBuffer(orig_data_begin_, orig_data_end_ - orig_data_begin_);
|
||||
}
|
||||
message_complete_ = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
BINPAC_ASSERT(! chunked_);
|
||||
int bytes_to_copy = orig_data_end_ - orig_data_begin_;
|
||||
message_complete_ = false;
|
||||
if ( frame_length_ >= 0 && buffer_n_ + bytes_to_copy >= frame_length_ ) {
|
||||
bytes_to_copy = frame_length_ - buffer_n_;
|
||||
message_complete_ = true;
|
||||
}
|
||||
AppendToBuffer(orig_data_begin_, bytes_to_copy);
|
||||
}
|
||||
|
||||
#if DEBUG_FLOW_BUFFER
|
||||
if ( message_complete_ ) {
|
||||
fprintf(stderr, "%.6f frame complete: [%s]\n", network_time(),
|
||||
string((const char*)begin(), (const char*)end()).c_str());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void FlowBuffer::AppendToBuffer(const_byteptr data, int len) {
|
||||
if ( len <= 0 )
|
||||
return;
|
||||
|
||||
BINPAC_ASSERT(! chunked_);
|
||||
ExpandBuffer(buffer_n_ + len);
|
||||
memcpy(buffer_ + buffer_n_, data, len);
|
||||
buffer_n_ += len;
|
||||
|
||||
orig_data_begin_ += len;
|
||||
BINPAC_ASSERT(orig_data_begin_ <= orig_data_end_);
|
||||
}
|
||||
|
||||
} // namespace binpac
|
|
@ -1,170 +0,0 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#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 : uint8_t {
|
||||
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 : uint8_t {
|
||||
UNKNOWN_MODE,
|
||||
LINE_MODE,
|
||||
FRAME_MODE,
|
||||
} mode_;
|
||||
|
||||
enum : uint8_t {
|
||||
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;
|
||||
};
|
||||
|
||||
using flow_buffer_t = FlowBuffer*;
|
||||
|
||||
} // namespace binpac
|
||||
|
||||
#endif // binpac_buffer_h
|
|
@ -1,17 +0,0 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#define binpac_regex_h
|
||||
|
||||
#include "binpac_bytestring.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace binpac {
|
||||
|
||||
std::string std_string(bytestring const* s) { return std::string((const char*)s->begin(), (const char*)s->end()); }
|
||||
|
||||
int bytestring_to_int(bytestring const* s) { return atoi((const char*)s->begin()); }
|
||||
|
||||
double bytestring_to_double(bytestring const* s) { return atof((const char*)s->begin()); }
|
||||
|
||||
} // namespace binpac
|
|
@ -1,145 +0,0 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#ifndef binpac_bytestring_h
|
||||
#define binpac_bytestring_h
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
#include "binpac.h"
|
||||
|
||||
namespace binpac {
|
||||
|
||||
template<class T>
|
||||
class datastring;
|
||||
|
||||
template<class T>
|
||||
class const_datastring {
|
||||
public:
|
||||
const_datastring() : begin_(nullptr), end_(nullptr) {}
|
||||
|
||||
const_datastring(T const* data, int length) : begin_(data), end_(data + length) {}
|
||||
|
||||
const_datastring(const T* begin, const T* end) : begin_(begin), end_(end) {}
|
||||
|
||||
const_datastring(datastring<T> const& s) : begin_(s.begin()), end_(s.end()) {}
|
||||
|
||||
void init(const T* data, int length) {
|
||||
begin_ = data;
|
||||
end_ = data + length;
|
||||
}
|
||||
|
||||
T const* begin() const { return begin_; }
|
||||
T const* end() const { return end_; }
|
||||
int length() const { return end_ - begin_; }
|
||||
|
||||
T const& operator[](int index) const { return begin()[index]; }
|
||||
|
||||
bool operator==(const_datastring<T> const& s) {
|
||||
if ( length() != s.length() )
|
||||
return false;
|
||||
return memcmp((const void*)begin(), (const void*)s.begin(), sizeof(T) * length()) == 0;
|
||||
}
|
||||
|
||||
void set_begin(T const* begin) { begin_ = begin; }
|
||||
void set_end(T const* end) { end_ = end; }
|
||||
|
||||
private:
|
||||
T const* begin_;
|
||||
T const* end_;
|
||||
};
|
||||
|
||||
using const_bytestring = const_datastring<uint8>;
|
||||
|
||||
template<class T>
|
||||
class datastring {
|
||||
public:
|
||||
datastring() { clear(); }
|
||||
|
||||
datastring(T* data, int len) { set(data, len); }
|
||||
|
||||
datastring(T const* begin, T const* end) { set_const(begin, end - begin); }
|
||||
|
||||
datastring(datastring<T> const& x) : data_(x.data()), length_(x.length()) {}
|
||||
|
||||
explicit datastring(const_datastring<T> const& x) { set_const(x.begin(), x.length()); }
|
||||
|
||||
datastring const& operator=(datastring<T> const& x) {
|
||||
if ( this == &x )
|
||||
return *this;
|
||||
|
||||
BINPAC_ASSERT(! data_);
|
||||
set(x.data(), x.length());
|
||||
return *this;
|
||||
}
|
||||
|
||||
void init(T const* begin, int length) {
|
||||
BINPAC_ASSERT(! data_);
|
||||
set_const(begin, length);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
data_ = nullptr;
|
||||
length_ = 0;
|
||||
}
|
||||
|
||||
void free() {
|
||||
if ( data_ )
|
||||
delete[] data_;
|
||||
clear();
|
||||
}
|
||||
|
||||
void clone() { set_const(begin(), length()); }
|
||||
|
||||
datastring const& operator=(const_datastring<T> const& x) {
|
||||
BINPAC_ASSERT(! data_);
|
||||
set_const(x.begin(), x.length());
|
||||
return *this;
|
||||
}
|
||||
|
||||
T const& operator[](int index) const { return begin()[index]; }
|
||||
|
||||
T* data() const { return data_; }
|
||||
int length() const { return length_; }
|
||||
|
||||
T const* begin() const { return data_; }
|
||||
T const* end() const { return data_ + length_; }
|
||||
|
||||
private:
|
||||
void set(T* data, int len) {
|
||||
data_ = data;
|
||||
length_ = len;
|
||||
}
|
||||
|
||||
void set_const(T const* data, int len) {
|
||||
length_ = len;
|
||||
data_ = new T[len + 1];
|
||||
memcpy(data_, data, sizeof(T) * len);
|
||||
data_[len] = 0;
|
||||
}
|
||||
|
||||
T* data_;
|
||||
int length_;
|
||||
};
|
||||
|
||||
using bytestring = datastring<uint8>;
|
||||
|
||||
inline const char* c_str(bytestring const& s) { return (const char*)s.begin(); }
|
||||
|
||||
inline std::string std_str(const_bytestring const& s) { return {(const char*)s.begin(), (const char*)s.end()}; }
|
||||
|
||||
inline bool operator==(bytestring const& s1, const char* s2) { return strcmp(c_str(s1), s2) == 0; }
|
||||
|
||||
inline void get_pointers(const_bytestring const& s, uint8 const** pbegin, uint8 const** pend) {
|
||||
*pbegin = s.begin();
|
||||
*pend = s.end();
|
||||
}
|
||||
|
||||
inline void get_pointers(bytestring const* s, uint8 const** pbegin, uint8 const** pend) {
|
||||
*pbegin = s->begin();
|
||||
*pend = s->end();
|
||||
}
|
||||
|
||||
} // namespace binpac
|
||||
|
||||
#endif // binpac_bytestring_h
|
|
@ -1,98 +0,0 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#ifndef binpac_exception_h
|
||||
#define binpac_exception_h
|
||||
|
||||
#include <cinttypes>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace binpac {
|
||||
|
||||
class Exception {
|
||||
public:
|
||||
Exception(const char* m = nullptr) : msg_("binpac exception: ") {
|
||||
if ( m )
|
||||
append(m);
|
||||
// abort();
|
||||
}
|
||||
|
||||
void append(std::string m) { msg_ += m; }
|
||||
std::string msg() const { return msg_; }
|
||||
const char* c_msg() const { return msg_.c_str(); }
|
||||
|
||||
protected:
|
||||
std::string msg_;
|
||||
};
|
||||
|
||||
class ExceptionEnforceViolation : public Exception {
|
||||
public:
|
||||
ExceptionEnforceViolation(const char* where) { append(binpac_fmt("&enforce violation : %s", where)); }
|
||||
};
|
||||
|
||||
class ExceptionOutOfBound : public Exception {
|
||||
public:
|
||||
ExceptionOutOfBound(const char* where, int len_needed, int len_given) {
|
||||
append(binpac_fmt("out_of_bound: %s: %d > %d", where, len_needed, len_given));
|
||||
}
|
||||
};
|
||||
|
||||
class ExceptionInvalidCase : public Exception {
|
||||
public:
|
||||
ExceptionInvalidCase(const char* location, int64_t index, const char* expected)
|
||||
: location_(location), index_(index), expected_(expected) {
|
||||
append(binpac_fmt("invalid case: %s: %" PRIi64 " (%s)", location, index, expected));
|
||||
}
|
||||
|
||||
protected:
|
||||
const char* location_;
|
||||
int64_t index_;
|
||||
std::string expected_;
|
||||
};
|
||||
|
||||
class ExceptionInvalidCaseIndex : public Exception {
|
||||
public:
|
||||
ExceptionInvalidCaseIndex(const char* location, int64_t index) : location_(location), index_(index) {
|
||||
append(binpac_fmt("invalid index for case: %s: %" PRIi64, location, index));
|
||||
}
|
||||
|
||||
protected:
|
||||
const char* location_;
|
||||
int64_t index_;
|
||||
};
|
||||
|
||||
class ExceptionInvalidOffset : public Exception {
|
||||
public:
|
||||
ExceptionInvalidOffset(const char* location, int min_offset, int offset)
|
||||
: location_(location), min_offset_(min_offset), offset_(offset) {
|
||||
append(binpac_fmt("invalid offset: %s: min_offset = %d, offset = %d", location, min_offset, offset));
|
||||
}
|
||||
|
||||
protected:
|
||||
const char* location_;
|
||||
int min_offset_, offset_;
|
||||
};
|
||||
|
||||
class ExceptionStringMismatch : public Exception {
|
||||
public:
|
||||
ExceptionStringMismatch(const char* location, const char* expected, const char* actual_data) {
|
||||
append(binpac_fmt("string mismatch at %s: \nexpected pattern: \"%s\"\nactual data: \"%s\"", location, expected,
|
||||
actual_data));
|
||||
}
|
||||
};
|
||||
|
||||
class ExceptionInvalidStringLength : public Exception {
|
||||
public:
|
||||
ExceptionInvalidStringLength(const char* location, int len) {
|
||||
append(binpac_fmt("invalid length string: %s: %d", location, len));
|
||||
}
|
||||
};
|
||||
|
||||
class ExceptionFlowBufferAlloc : public Exception {
|
||||
public:
|
||||
ExceptionFlowBufferAlloc(const char* reason) { append(binpac_fmt("flowbuffer allocation failed: %s", reason)); }
|
||||
};
|
||||
|
||||
} // namespace binpac
|
||||
|
||||
#endif // binpac_exception_h
|
|
@ -1,13 +0,0 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace zeek {
|
||||
class RE_Matcher;
|
||||
}
|
||||
|
||||
namespace binpac {
|
||||
|
||||
std::vector<zeek::RE_Matcher*>* uncompiled_re_matchers = nullptr;
|
||||
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
// See the file "COPYING" in the main distribution directory for copyright.
|
||||
|
||||
#ifndef binpac_regex_h
|
||||
#define binpac_regex_h
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "zeek/RE.h"
|
||||
|
||||
#include "binpac.h"
|
||||
|
||||
namespace zeek {
|
||||
class RE_Matcher;
|
||||
}
|
||||
|
||||
namespace binpac {
|
||||
|
||||
// Must be called before any binpac functionality is used.
|
||||
//
|
||||
// Note, this must be declared/defined here, and inline, because the RE
|
||||
// functionality can only be used when compiling from inside Zeek.
|
||||
// A copy is made of any FlowBuffer policy struct data passed.
|
||||
inline void init(FlowBuffer::Policy* fbp = nullptr);
|
||||
|
||||
// Internal vector recording not yet compiled matchers.
|
||||
extern std::vector<zeek::RE_Matcher*>* uncompiled_re_matchers;
|
||||
|
||||
class RegExMatcher {
|
||||
public:
|
||||
RegExMatcher(const char* pattern) : pattern_(pattern) {
|
||||
if ( ! uncompiled_re_matchers )
|
||||
uncompiled_re_matchers = new std::vector<zeek::RE_Matcher*>;
|
||||
|
||||
re_matcher_ = new zeek::RE_Matcher(pattern_.c_str());
|
||||
uncompiled_re_matchers->push_back(re_matcher_);
|
||||
}
|
||||
|
||||
~RegExMatcher() { delete re_matcher_; }
|
||||
|
||||
// Returns the length of longest match, or -1 on mismatch.
|
||||
int MatchPrefix(const_byteptr data, int len) { return re_matcher_->MatchPrefix(data, len); }
|
||||
|
||||
private:
|
||||
friend void ::binpac::init(FlowBuffer::Policy*);
|
||||
|
||||
// Function, and state, for compiling matchers.
|
||||
static void init();
|
||||
|
||||
string pattern_;
|
||||
zeek::RE_Matcher* re_matcher_;
|
||||
};
|
||||
|
||||
inline void RegExMatcher::init() {
|
||||
if ( ! uncompiled_re_matchers )
|
||||
return;
|
||||
|
||||
for ( const auto& matcher : *uncompiled_re_matchers ) {
|
||||
if ( ! matcher->Compile() ) {
|
||||
fprintf(stderr, "binpac: cannot compile regular expression\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uncompiled_re_matchers->clear();
|
||||
}
|
||||
|
||||
inline void init(FlowBuffer::Policy* fbp) {
|
||||
RegExMatcher::init();
|
||||
|
||||
if ( fbp )
|
||||
FlowBuffer::init(*fbp);
|
||||
}
|
||||
|
||||
} // namespace binpac
|
||||
|
||||
#endif // binpac_regex_h
|
Loading…
Add table
Add a link
Reference in a new issue