28 #define DUMP_REGIONS 0 // set to 1 to dump a visual representation of the regions list and sbb tree.
38 static void *ReallocFunc(
void *ptr,
const size_t size)
47 static void *CallocFunc(
const size_t nm,
const size_t sz)
59 #define CALLOC(cfg, n, s) (cfg)->Calloc ? (cfg)->Calloc((n), (s)) : CallocFunc((n), (s))
60 #define REALLOC(cfg, ptr, orig_s, s) \
61 (cfg)->Realloc ? (cfg)->Realloc((ptr), (orig_s), (s)) : ReallocFunc((ptr), (s))
62 #define FREE(cfg, ptr, s) \
63 (cfg)->Free ? (cfg)->Free((ptr), (s)) : SCFree((ptr))
90 const uint64_t lre = lookup->
offset + lookup->
len;
91 const uint64_t tre = intree->
offset + intree->
len;
94 else if (lookup->
offset < tre && lre <= tre)
108 const int comp = InclusiveCompare(elm, tmp);
113 }
else if (comp > 0) {
130 const uint64_t reg_o =
140 if (re >= reg_o && re <= reg_re) {
141 SCLogDebug(
"r %p is in-scope: %" PRIu64
" >= %" PRIu64
" && %" PRIu64
" <= %" PRIu64, r, re,
157 SCLogDebug(
"looking for first region matching %" PRIu64
"/%" PRIu64,
offset, data_re);
160 for (; r != NULL; r = r->
next) {
161 if (RegionsIntersect(sb, cfg, r,
offset, data_re) ==
true) {
176 SCLogDebug(
"starting at %p/%" PRIu64
", offset %" PRIu64
", data_re %" PRIu64, r,
179 for (; r != NULL; r = r->
next) {
182 SCLogDebug(
"checking: %p/%" PRIu64
"/%" PRIu64
", offset %" PRIu64
"/%" PRIu64, r,
185 if (!RegionsIntersect(sb, cfg, r,
offset, data_re))
202 for (; r != NULL; r = r->
next) {
203 if (!RegionsIntersect(sb, cfg, r,
offset, data_re)) {
229 if (aux_r->
buf == NULL) {
230 FREE(cfg, aux_r,
sizeof(*aux_r));
263 int r = InitBuffer(sb, cfg);
287 FREE(cfg, r,
sizeof(*r));
337 (void)SBB_RB_INSERT(&sb->
sbb_tree, sbb);
346 sbb2->
len = data_len;
352 if (SBB_RB_INSERT(&sb->
sbb_tree, sbb2) != NULL) {
353 FREE(cfg, sbb2,
sizeof(*sbb2));
381 (void)SBB_RB_INSERT(&sb->
sbb_tree, sbb);
399 const uint64_t tr_re = tr->
offset + tr->
len;
420 SCLogDebug(
"-> (fwd) tr %p %" PRIu64
"/%u REMOVED ECLIPSED (sa overlapped by tr)", tr,
422 SBB_RB_REMOVE(tree, tr);
432 }
else if (sa->
offset <= tr->
offset && sa_re >= tr_re) {
433 SCLogDebug(
"-> (fwd) tr %p %" PRIu64
"/%u REMOVED ECLIPSED (tr overlapped by sa)", tr,
435 SBB_RB_REMOVE(tree, tr);
439 SCLogDebug(
"-> (fwd) tr %p %" PRIu64
"/%u region %p so %" PRIu64
" bo %u sz %u", sa,
446 SCLogDebug(
"-> (fwd) tr %p %" PRIu64
"/%u region %p so %" PRIu64
447 " bo %u sz %u BUF_OFFSET UPDATED",
458 sa_re >= tr->
offset && sa_re < tr_re)
461 uint32_t combined_len = sa->
len + tr->
len;
465 SBB_RB_REMOVE(tree, tr);
469 SCLogDebug(
"-> (fwd) tr %p %" PRIu64
"/%u region %p so %" PRIu64
" bo %u sz %u", sa,
476 SCLogDebug(
"-> (fwd) tr %p %" PRIu64
"/%u region %p so %" PRIu64
477 " bo %u sz %u BUF_OFFSET UPDATED",
493 const uint64_t tr_re = tr->
offset + tr->
len;
512 SCLogDebug(
"-> (bwd) tr %p %" PRIu64
"/%u REMOVED ECLIPSED (sa overlapped by tr)", tr,
516 SBB_RB_REMOVE(tree, tr);
526 }
else if (sa->
offset <= tr->
offset && sa_re >= tr_re) {
527 SCLogDebug(
"-> (bwd) tr %p %" PRIu64
"/%u REMOVED ECLIPSED (tr overlapped by sa)", tr,
531 SBB_RB_REMOVE(tree, tr);
535 SCLogDebug(
"-> (bwd) tr %p %" PRIu64
"/%u region %p so %" PRIu64
" bo %u sz %u", sa,
543 SCLogDebug(
"-> (bwd) tr %p %" PRIu64
"/%u region %p so %" PRIu64
544 " bo %u sz %u BUF_OFFSET UPDATED",
557 uint32_t combined_len = sa->
len + tr->
len;
564 SBB_RB_REMOVE(tree, tr);
568 SCLogDebug(
"-> (bwd) tr %p %" PRIu64
"/%u region %p so %" PRIu64
" bo %u sz %u", sa,
575 SCLogDebug(
"-> (bwd) tr %p %" PRIu64
"/%u region %p so %" PRIu64
576 " bo %u sz %u BUF_OFFSET UPDATED",
603 SCLogDebug(
"* insert failed: exact match in tree with %p %" PRIu64
"/%u", res, res->
offset,
611 if (SBB_RB_PREV(sbb) == NULL) {
614 ConsolidateBackward(sb, cfg, region, tree, sbb);
616 ConsolidateFwd(sb, cfg, region, tree, sbb);
662 if (sbb->
len >= shrink_by) {
663 sbb->
len -= shrink_by;
690 static inline uint32_t ToNextMultipleOf(
const uint32_t in,
const uint32_t
m)
694 const uint32_t x = in %
m;
702 static thread_local
bool g2s_warn_once =
false;
709 if (!g2s_warn_once) {
710 SCLogWarning(
"StreamingBuffer::GrowRegionToSize() tried to alloc %u bytes, exceeds "
713 g2s_warn_once =
true;
719 const uint32_t grow = ToNextMultipleOf(size, cfg->
buf_size);
728 size_t diff = grow - region->
buf_size;
729 void *new_mem = ((
char *)ptr) + region->
buf_size;
730 memset(new_mem, 0, diff);
736 if (region->
buf_size > sb->buf_size_max) {
737 sb->buf_size_max = region->
buf_size;
746 return GrowRegionToSize(sb, cfg, &sb->
region, size);
786 static inline void StreamingBufferSlideToOffsetWithRegions(
792 SCLogDebug(
"slide_offset %" PRIu64, slide_offset);
797 const bool main_is_oow = RegionBeforeOffset(&sb->
region, slide_offset);
818 if (RegionBeforeOffset(r, slide_offset)) {
825 FREE(cfg, r,
sizeof(*r));
828 }
else if (RegionContainsOffset(r, slide_offset)) {
847 SCLogDebug(
"shift start region %p", to_shift);
854 if (to_shift != &sb->
region) {
863 FREE(cfg, to_shift,
sizeof(*to_shift));
873 const uint32_t new_data_size = to_shift->
buf_size - s;
874 uint32_t new_mem_size = ToNextMultipleOf(new_data_size, cfg->
buf_size);
885 const uint64_t next_re =
next->stream_offset +
next->buf_size;
886 const uint32_t mem_size = ToNextMultipleOf(next_re - slide_offset, cfg->
buf_size);
890 SCLogDebug(
"replace main with the next bigger region");
892 const uint32_t next_data_offset =
next->stream_offset - slide_offset;
893 const uint32_t prev_buf_size =
next->buf_size;
894 const uint32_t start_data_offset = slide_offset - start->
stream_offset;
896 if (start_data_offset > start->
buf_size) {
897 new_mem_size = new_data_size;
901 if (GrowRegionToSize(sb, cfg,
next, mem_size) != 0) {
902 new_mem_size = new_data_size;
911 memmove(
next->buf + next_data_offset,
next->buf, prev_buf_size);
918 const uint32_t start_data_size = start->
buf_size - start_data_offset;
919 memcpy(
next->buf, start->
buf + start_data_offset, start_data_size);
937 if (GrowRegionToSize(sb, cfg, start, mem_size) != 0) {
938 new_mem_size = new_data_size;
941 SCLogDebug(
"start->buf now size %u", mem_size);
946 SCLogDebug(
"s %u new_data_size %u", s, new_data_size);
947 memmove(start->
buf, start->
buf + s, new_data_size);
953 SCLogDebug(
"copy next->buf %p/%u to start->buf offset %u",
next->buf,
954 next->buf_size, new_data_size);
955 memcpy(start->
buf + new_data_size,
next->buf,
next->buf_size);
970 SCLogDebug(
"s %u new_data_size %u", s, new_data_size);
971 memmove(to_shift->
buf, to_shift->
buf + s, new_data_size);
979 if (s < to_shift->buf_offset)
1007 StreamingBufferSlideToOffsetWithRegions(sb, cfg,
offset);
1025 if (sb->
head != NULL) {
1029 SCLogDebug(
"sliding %u forward, size of original buffer left after slide %u", slide,
1045 SCLogDebug(
"sliding %u forward, size of original buffer left after slide %u", slide,
1064 #define DATA_FITS(sb, len) ((sb)->region.buf_offset + (len) <= (sb)->region.buf_size)
1067 StreamingBufferSegment *seg,
const uint8_t *data, uint32_t data_len)
1072 if (InitBuffer(sb, cfg) == -1)
1078 if (GrowToSize(sb, cfg, data_len) !=
SC_OK)
1089 seg->segment_len = data_len;
1094 return SBBUpdate(sb, cfg, &sb->
region, rel_offset, data_len);
1104 const uint8_t *data, uint32_t data_len)
1107 if (InitBuffer(sb, cfg) == -1)
1113 if (GrowToSize(sb, cfg, data_len) !=
SC_OK)
1127 return SBBUpdate(sb, cfg, &sb->
region, rel_offset, data_len);
1133 #define DATA_FITS_AT_OFFSET(region, len, offset) ((offset) + (len) <= (region)->buf_size)
1135 #if defined(DEBUG) || defined(DEBUG_VALIDATION)
1168 #if defined(DEBUG) && DUMP_REGIONS == 1
1174 snprintf(gap,
sizeof(gap),
"[ gap:%" PRIu64
" ]",
1178 printf(
"[ %s offset:%" PRIu64
" size:%u offset:%u ]%s", r == &sb->
region ?
"main" :
"aux",
1182 bool at_least_one =
false;
1187 if (last_re != sbb->
offset) {
1188 printf(
"[ gap:%" PRIu64
" ]", sbb->
offset - last_re);
1190 printf(
"[ sbb offset:%" PRIu64
" len:%u ]", sbb->
offset, sbb->
len);
1191 at_least_one =
true;
1197 #if defined(DEBUG) || defined(DEBUG_VALIDATION)
1201 const uint8_t *_data = NULL;
1202 uint32_t _data_len = 0;
1217 uint32_t dst_buf_size)
1221 const uint64_t data_re = data_offset + data_len;
1222 SCLogDebug(
"sb %p dst %p src_start %p src_end %p data_offset %" PRIu64
1223 "/data_len %u/data_re %" PRIu64,
1224 sb,
dst, src_start, src_end, data_offset, data_len, data_re);
1230 const uint32_t dst_size = dst_buf_size;
1234 const uint32_t old_size =
dst->buf_size;
1235 const uint32_t dst_copy_offset =
dst->stream_offset - dst_offset;
1237 const uint32_t old_offset =
dst->buf_offset;
1238 SCLogDebug(
"old_size %u, old_offset %u, dst_copy_offset %u", old_size, old_offset,
1241 if ((retval = GrowRegionToSize(sb, cfg,
dst, dst_size)) !=
SC_OK) {
1248 if (dst_copy_offset != 0)
1249 memmove(
dst->buf + dst_copy_offset,
dst->buf, old_size);
1250 if (dst_offset !=
dst->stream_offset) {
1251 dst->stream_offset = dst_offset;
1253 dst->buf_offset = 0;
1258 new_offset += data_len;
1261 bool start_is_main =
false;
1262 if (src_start == &sb->
region) {
1265 start_is_main =
true;
1267 if (src_start !=
dst)
1269 if (src_start == src_end) {
1270 SCLogDebug(
"src_start == src_end == main, we're done");
1275 src_start = src_start->
next;
1285 SCLogDebug(
"skipping r %p as it is 'dst'", r);
1292 const uint32_t target_offset = r->
stream_offset - dst_offset;
1293 SCLogDebug(
"r %p: target_offset %u", r, target_offset);
1300 FREE(cfg, r,
sizeof(*r));
1320 if (start_is_main &&
dst != &sb->
region) {
1322 SCLogDebug(
"start_is_main && dst != main region");
1337 SCLogDebug(
"returning dst %p stream_offset %" PRIu64
" buf_offset %u buf_size %u",
dst,
1338 dst->stream_offset,
dst->buf_offset,
dst->buf_size);
1349 FindFirstRegionForOffset(sb, cfg, &sb->
region,
offset,
len, &start_prev);
1351 const uint64_t insert_re =
offset +
len;
1353 uint64_t insert_adjusted_re = insert_re;
1371 uint32_t new_buf_size =
1372 ToNextMultipleOf(insert_adjusted_re - insert_start_offset, cfg->
buf_size);
1382 ToNextMultipleOf(insert_adjusted_re - insert_start_offset, cfg->
buf_size);
1389 sb, cfg, big, start, end,
offset,
len, start_prev, new_buf_size);
1402 SCLogDebug(
"no matching region found, append to %p (%s)", append,
1403 append == &sb->
region ?
"main" :
"aux");
1427 const uint64_t data_offset)
1429 SCLogDebug(
"data_offset %" PRIu64
", data_len %u, re %" PRIu64, data_offset, data_len,
1430 data_offset + data_len);
1433 if (RegionsIntersect(sb, cfg, &sb->
region, data_offset, data_offset + data_len)) {
1434 SCLogDebug(
"data_offset %" PRIu64
", data_len %u intersects with main region (next %p)",
1437 !RegionsIntersect(sb, cfg, sb->
region.
next, data_offset, data_offset + data_len)) {
1439 "data_offset %" PRIu64
1440 ", data_len %u intersects with main region, no next or way before next region",
1441 data_offset, data_len);
1444 if ((r = InitBuffer(sb, cfg)) !=
SC_OK) {
1458 SCLogDebug(
"created new region %p with offset %" PRIu64
", size %u", aux_r,
1475 StreamingBufferSegment *seg,
const uint8_t *data, uint32_t data_len, uint64_t
offset)
1486 if (region == NULL) {
1490 const bool region_is_main = region == &sb->
region;
1492 SCLogDebug(
"inserting %" PRIu64
"/%u using %s region %p",
offset, data_len,
1493 region == &sb->
region ?
"main" :
"aux", region);
1497 if ((r = GrowToSize(sb, cfg, (rel_offset + data_len))) !=
SC_OK)
1502 SCLogDebug(
"offset %" PRIu64
" data_len %u, rel_offset %u into region offset %" PRIu64
1503 ", buf_offset %u, buf_size %u",
1506 memcpy(region->
buf + rel_offset, data, data_len);
1507 seg->stream_offset =
offset;
1508 seg->segment_len = data_len;
1510 SCLogDebug(
"rel_offset %u region->stream_offset %" PRIu64
", buf_offset %u", rel_offset,
1516 if (region_is_main) {
1518 SCLogDebug(
"empty sbb list: block exactly what was expected, fall through");
1524 SCLogDebug(
"empty sbb list: block is within existing main data region");
1531 }
else if (rel_offset < sb->region.
buf_offset) {
1534 SCLogDebug(
"before expected offset: %u < sb->region.buf_offset %u", rel_offset,
1537 SCLogDebug(
"before expected offset, ends after: %u < sb->region.buf_offset "
1545 SCLogDebug(
"beyond expected offset: SBBInit");
1547 if ((r = SBBInit(sb, cfg, region, rel_offset, data_len)) !=
SC_OK)
1551 SCLogDebug(
"empty sbb list: invoking SBBInitLeadingGap");
1552 if ((r = SBBInitLeadingGap(sb, cfg, region,
offset, data_len)) !=
SC_OK)
1559 SCLogDebug(
"empty sbb list, no data in main: use SBBInit");
1560 if ((r = SBBInit(sb, cfg, region, rel_offset, data_len)) !=
SC_OK)
1564 SCLogDebug(
"empty sbb list: invoking SBBInitLeadingGap");
1565 if ((r = SBBInitLeadingGap(sb, cfg, region,
offset, data_len)) !=
SC_OK)
1577 if ((r = SBBUpdate(sb, cfg, region, rel_offset, data_len)) !=
SC_OK)
1591 const StreamingBufferSegment *seg)
1614 if (
offset >= r->stream_offset &&
offset < (r->stream_offset + r->buf_size)) {
1624 const uint8_t **data, uint32_t *data_len)
1627 SCLogDebug(
"first find our region (offset %" PRIu64
") -> %p", sbb->
offset, region);
1640 *data_len = sbb->
len;
1645 if (offset < sbb->
len) {
1646 *data = region->
buf;
1661 const uint8_t **data, uint32_t *data_len,
1678 *data = region->
buf + data_offset;
1679 if (data_offset + sbblen > region->
buf_size)
1680 *data_len = region->
buf_size - data_offset;
1687 if (data_offset < sbblen) {
1688 *data = region->
buf;
1689 *data_len = sbblen - data_offset;
1702 const StreamingBufferSegment *seg,
1703 const uint8_t **data, uint32_t *data_len)
1713 *data_len = seg->segment_len;
1719 *data = region->
buf;
1720 *data_len = seg->segment_len -
offset;
1736 const StreamingBufferSegment *seg,
1737 const uint8_t *rawdata, uint32_t rawdata_len)
1739 const uint8_t *segdata = NULL;
1740 uint32_t segdata_len = 0;
1742 if (segdata && segdata_len &&
1743 segdata_len == rawdata_len &&
1744 memcmp(segdata, rawdata, segdata_len) == 0)
1752 const uint8_t **data, uint32_t *data_len,
1755 if (sb != NULL && sb->
region.
buf != NULL) {
1769 const uint8_t **data, uint32_t *data_len,
1776 *data = region->
buf + skip;
1791 const uint8_t *rawdata, uint32_t rawdata_len)
1793 const uint8_t *sbdata = NULL;
1794 uint32_t sbdata_len = 0;
1798 sbdata && sbdata_len &&
1799 sbdata_len == rawdata_len &&
1800 memcmp(sbdata, rawdata, sbdata_len) == 0)
1807 printf(
"wanted:\n");
1818 static void DumpSegment(
StreamingBuffer *sb, StreamingBufferSegment *seg)
1820 const uint8_t *data = NULL;
1821 uint32_t data_len = 0;
1823 if (data && data_len) {
1828 static int StreamingBufferTest02(
void)
1834 StreamingBufferSegment seg1;
1836 StreamingBufferSegment seg2;
1840 FAIL_IF(seg1.stream_offset != 0);
1841 FAIL_IF(seg2.stream_offset != 8);
1845 DumpSegment(sb, &seg1);
1846 DumpSegment(sb, &seg2);
1854 StreamingBufferSegment seg3;
1858 FAIL_IF(seg3.stream_offset != 16);
1863 DumpSegment(sb, &seg1);
1864 DumpSegment(sb, &seg2);
1865 DumpSegment(sb, &seg3);
1874 DumpSegment(sb, &seg1);
1875 DumpSegment(sb, &seg2);
1876 DumpSegment(sb, &seg3);
1884 static int StreamingBufferTest03(
void)
1890 StreamingBufferSegment seg1;
1892 StreamingBufferSegment seg2;
1896 FAIL_IF(seg1.stream_offset != 0);
1897 FAIL_IF(seg2.stream_offset != 14);
1901 DumpSegment(sb, &seg1);
1902 DumpSegment(sb, &seg2);
1907 StreamingBufferSegment seg3;
1911 FAIL_IF(seg3.stream_offset != 8);
1916 DumpSegment(sb, &seg1);
1917 DumpSegment(sb, &seg2);
1918 DumpSegment(sb, &seg3);
1928 DumpSegment(sb, &seg1);
1929 DumpSegment(sb, &seg2);
1930 DumpSegment(sb, &seg3);
1939 static int StreamingBufferTest04(
void)
1945 StreamingBufferSegment seg1;
1948 StreamingBufferSegment seg2;
1952 FAIL_IF(seg1.stream_offset != 0);
1953 FAIL_IF(seg2.stream_offset != 14);
1968 DumpSegment(sb, &seg1);
1969 DumpSegment(sb, &seg2);
1972 StreamingBufferSegment seg3;
1976 FAIL_IF(seg3.stream_offset != 8);
1987 DumpSegment(sb, &seg1);
1988 DumpSegment(sb, &seg2);
1989 DumpSegment(sb, &seg3);
1995 StreamingBufferSegment seg4;
2000 FAIL_IF(seg4.stream_offset != 124);
2012 DumpSegment(sb, &seg1);
2013 DumpSegment(sb, &seg2);
2014 DumpSegment(sb, &seg3);
2015 DumpSegment(sb, &seg4);
2030 static int StreamingBufferTest06(
void)
2036 StreamingBufferSegment seg1;
2038 StreamingBufferSegment seg2;
2045 StreamingBufferSegment seg3;
2052 StreamingBufferSegment seg4;
2059 StreamingBufferSegment seg5;
2071 StreamingBufferSegment seg6;
2088 static int StreamingBufferTest07(
void)
2094 StreamingBufferSegment seg1;
2096 StreamingBufferSegment seg2;
2103 StreamingBufferSegment seg3;
2110 StreamingBufferSegment seg4;
2117 StreamingBufferSegment seg5;
2129 StreamingBufferSegment seg6;
2146 static int StreamingBufferTest08(
void)
2152 StreamingBufferSegment seg1;
2154 StreamingBufferSegment seg2;
2161 StreamingBufferSegment seg3;
2168 StreamingBufferSegment seg4;
2175 StreamingBufferSegment seg5;
2187 StreamingBufferSegment seg6;
2204 static int StreamingBufferTest09(
void)
2210 StreamingBufferSegment seg1;
2212 StreamingBufferSegment seg2;
2219 StreamingBufferSegment seg3;
2226 StreamingBufferSegment seg4;
2233 StreamingBufferSegment seg5;
2245 StreamingBufferSegment seg6;
2262 static int StreamingBufferTest10(
void)
2268 StreamingBufferSegment seg1;
2271 StreamingBufferSegment seg2;
2274 StreamingBufferSegment seg3;
2280 StreamingBufferSegment seg4;
2283 StreamingBufferSegment seg5;
2286 StreamingBufferSegment seg6;
2293 StreamingBufferSegment seg7;
2304 StreamingBufferSegment seg8;