diff options
Diffstat (limited to 'src/util-streaming-buffer.h')
-rw-r--r-- | src/util-streaming-buffer.h | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/src/util-streaming-buffer.h b/src/util-streaming-buffer.h new file mode 100644 index 0000000..98ee6f6 --- /dev/null +++ b/src/util-streaming-buffer.h @@ -0,0 +1,203 @@ +/* Copyright (C) 2015-2016 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/* + * This API is meant to be used with streaming data. A single memory + * block is used to store the data. StreamingBufferSegment points to + * chunk of data in the single StreamingBuffer. It points by offset + * and length, so no pointers. The buffer is resized on demand and + * slides forward, either automatically or manually. + * + * When a segment needs it's data it uses StreamingBufferSegmentGetData + * which takes care of checking if the segment still has a valid offset + * and length. + * + * The StreamingBuffer::stream_offset is an absolute offset since the + * start of the data streaming. + * + * Similarly, StreamingBufferSegment::stream_offset is also an absolute + * offset. + * + * Using the segments is optional. + * + * + * stream_offset buf_offset stream_offset + buf_size + * ^ ^ ^ + * | | | + * | | | + * +--------------------------------------------+ + * | data | empty | + * | xxxxxxxxxx | | + * +------^--------^--------+-------------------+ + * | | + * | | + * | | + * | | + * | | + * +------+--------+-------+ + * | StreamingBufferSegment| + * +-----------+-----------+ + * | offset | len | + * +-----------+-----------+ + */ + + +#ifndef __UTIL_STREAMING_BUFFER_H__ +#define __UTIL_STREAMING_BUFFER_H__ + +#include "tree.h" + +#define STREAMING_BUFFER_REGION_GAP_DEFAULT 262144 + +typedef struct StreamingBufferConfig_ { + uint32_t buf_size; + uint16_t max_regions; /**< max concurrent memory regions. 0 means no limit. */ + uint32_t region_gap; /**< max gap size before a new region will be created. */ + void *(*Calloc)(size_t n, size_t size); + void *(*Realloc)(void *ptr, size_t orig_size, size_t size); + void (*Free)(void *ptr, size_t size); +} StreamingBufferConfig; + +#define STREAMING_BUFFER_CONFIG_INITIALIZER \ + { \ + 2048, 8, STREAMING_BUFFER_REGION_GAP_DEFAULT, NULL, NULL, NULL, \ + } + +#define STREAMING_BUFFER_REGION_INIT \ + { \ + NULL, 0, 0, 0ULL, NULL, \ + } + +typedef struct StreamingBufferRegion_ { + uint8_t *buf; /**< memory block for reassembly */ + uint32_t buf_size; /**< size of memory block */ + uint32_t buf_offset; /**< how far we are in buf_size */ + uint64_t stream_offset; /**< stream offset of this region */ + struct StreamingBufferRegion_ *next; +} StreamingBufferRegion; + +/** + * \brief block of continues data + */ +typedef struct StreamingBufferBlock { + uint64_t offset; + RB_ENTRY(StreamingBufferBlock) rb; + uint32_t len; +} __attribute__((__packed__)) StreamingBufferBlock; + +int SBBCompare(struct StreamingBufferBlock *a, struct StreamingBufferBlock *b); + +/* red-black tree prototype for SACK records */ +RB_HEAD(SBB, StreamingBufferBlock); +RB_PROTOTYPE(SBB, StreamingBufferBlock, rb, SBBCompare); +StreamingBufferBlock *SBB_RB_FIND_INCLUSIVE(struct SBB *head, StreamingBufferBlock *elm); + +typedef struct StreamingBuffer_ { + StreamingBufferRegion region; + struct SBB sbb_tree; /**< red black tree of Stream Buffer Blocks */ + StreamingBufferBlock *head; /**< head, should always be the same as RB_MIN */ + uint32_t sbb_size; /**< data size covered by sbbs */ + uint16_t regions; + uint16_t max_regions; +#ifdef DEBUG + uint32_t buf_size_max; +#endif +} StreamingBuffer; + +static inline bool StreamingBufferHasData(const StreamingBuffer *sb) +{ + return (sb->region.stream_offset || sb->region.buf_offset || sb->region.next != NULL || + !RB_EMPTY(&sb->sbb_tree)); +} + +static inline uint64_t StreamingBufferGetConsecutiveDataRightEdge(const StreamingBuffer *sb) +{ + return sb->region.stream_offset + sb->region.buf_offset; +} + +static inline uint64_t StreamingBufferGetOffset(const StreamingBuffer *sb) +{ + return sb->region.stream_offset; +} + +#ifndef DEBUG +#define STREAMING_BUFFER_INITIALIZER \ + { \ + STREAMING_BUFFER_REGION_INIT, \ + { NULL }, \ + NULL, \ + 0, \ + 1, \ + 1, \ + }; +#else +#define STREAMING_BUFFER_INITIALIZER { STREAMING_BUFFER_REGION_INIT, { NULL }, NULL, 0, 1, 1, 0 }; +#endif + +typedef struct StreamingBufferSegment_ { + uint32_t segment_len; + uint64_t stream_offset; +} __attribute__((__packed__)) StreamingBufferSegment; + +StreamingBuffer *StreamingBufferInit(const StreamingBufferConfig *cfg); +void StreamingBufferClear(StreamingBuffer *sb, const StreamingBufferConfig *cfg); +void StreamingBufferFree(StreamingBuffer *sb, const StreamingBufferConfig *cfg); + +void StreamingBufferSlideToOffset( + StreamingBuffer *sb, const StreamingBufferConfig *cfg, uint64_t offset); + +int StreamingBufferAppend(StreamingBuffer *sb, const StreamingBufferConfig *cfg, + StreamingBufferSegment *seg, const uint8_t *data, uint32_t data_len) WARN_UNUSED; +int StreamingBufferAppendNoTrack(StreamingBuffer *sb, const StreamingBufferConfig *cfg, + const uint8_t *data, uint32_t data_len) WARN_UNUSED; +int StreamingBufferInsertAt(StreamingBuffer *sb, const StreamingBufferConfig *cfg, + StreamingBufferSegment *seg, const uint8_t *data, uint32_t data_len, + uint64_t offset) WARN_UNUSED; + +void StreamingBufferSegmentGetData(const StreamingBuffer *sb, + const StreamingBufferSegment *seg, + const uint8_t **data, uint32_t *data_len); + +void StreamingBufferSBBGetData(const StreamingBuffer *sb, + const StreamingBufferBlock *sbb, + const uint8_t **data, uint32_t *data_len); + +void StreamingBufferSBBGetDataAtOffset(const StreamingBuffer *sb, + const StreamingBufferBlock *sbb, + const uint8_t **data, uint32_t *data_len, + uint64_t offset); + +int StreamingBufferSegmentCompareRawData(const StreamingBuffer *sb, + const StreamingBufferSegment *seg, + const uint8_t *rawdata, uint32_t rawdata_len); +int StreamingBufferCompareRawData(const StreamingBuffer *sb, + const uint8_t *rawdata, uint32_t rawdata_len); + +int StreamingBufferGetData(const StreamingBuffer *sb, + const uint8_t **data, uint32_t *data_len, + uint64_t *stream_offset); + +int StreamingBufferGetDataAtOffset (const StreamingBuffer *sb, + const uint8_t **data, uint32_t *data_len, + uint64_t offset); + +int StreamingBufferSegmentIsBeforeWindow(const StreamingBuffer *sb, + const StreamingBufferSegment *seg); + +void StreamingBufferRegisterTests(void); + +#endif /* __UTIL_STREAMING_BUFFER_H__ */ |