suricata
util-streaming-buffer.c
Go to the documentation of this file.
1 /* Copyright (C) 2015-2016 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 #include "suricata-common.h"
19 #include "util-streaming-buffer.h"
20 #include "util-unittest.h"
21 #include "util-print.h"
22 #include "util-validate.h"
23 
24 /**
25  * \file
26  *
27  * \author Victor Julien <victor@inliniac.net>
28  *
29  * \brief Streaming Buffer API
30  */
31 
32 /* memory handling wrappers. If config doesn't define it's own set of
33  * functions, use the defaults */
34 #define MALLOC(cfg, s) \
35  (cfg)->Malloc ? (cfg)->Malloc((s)) : SCMalloc((s))
36 #define CALLOC(cfg, n, s) \
37  (cfg)->Calloc ? (cfg)->Calloc((n), (s)) : SCCalloc((n), (s))
38 #define REALLOC(cfg, ptr, orig_s, s) \
39  (cfg)->Realloc ? (cfg)->Realloc((ptr), (orig_s), (s)) : SCRealloc((ptr), (s))
40 #define FREE(cfg, ptr, s) \
41  (cfg)->Free ? (cfg)->Free((ptr), (s)) : SCFree((ptr))
42 
43 static void SBBFree(StreamingBuffer *sb);
44 
46 
48 {
49  SCLogDebug("a %"PRIu64" len %u, b %"PRIu64" len %u",
50  a->offset, a->len, b->offset, b->len);
51 
52  if (a->offset > b->offset)
53  SCReturnInt(1);
54  else if (a->offset < b->offset)
55  SCReturnInt(-1);
56  else {
57  if (a->len == 0 || b->len == 0 || a->len == b->len)
58  SCReturnInt(0);
59  else if (a->len > b->len)
60  SCReturnInt(1);
61  else
62  SCReturnInt(-1);
63  }
64 }
65 
66 /* inclusive compare function that also considers the right edge,
67  * not just the offset. */
68 static inline int InclusiveCompare(StreamingBufferBlock *lookup, StreamingBufferBlock *intree) {
69  const uint64_t lre = lookup->offset + lookup->len;
70  const uint64_t tre = intree->offset + intree->len;
71  if (lre <= intree->offset) // entirely before
72  return -1;
73  else if (lre >= intree->offset && lookup->offset < tre && lre <= tre) // (some) overlap
74  return 0;
75  else
76  return 1; // entirely after
77 }
78 
80 {
81  SCLogDebug("looking up %"PRIu64, elm->offset);
82 
83  struct StreamingBufferBlock *tmp = RB_ROOT(head);
84  struct StreamingBufferBlock *res = NULL;
85  while (tmp) {
86  SCLogDebug("compare with %"PRIu64"/%u", tmp->offset, tmp->len);
87  const int comp = InclusiveCompare(elm, tmp);
88  SCLogDebug("compare result: %d", comp);
89  if (comp < 0) {
90  res = tmp;
91  tmp = RB_LEFT(tmp, rb);
92  } else if (comp > 0) {
93  tmp = RB_RIGHT(tmp, rb);
94  } else {
95  return tmp;
96  }
97  }
98  return res;
99 }
100 
101 
102 static inline int InitBuffer(StreamingBuffer *sb)
103 {
104  sb->buf = CALLOC(sb->cfg, 1, sb->cfg->buf_size);
105  if (sb->buf == NULL) {
106  return -1;
107  }
108  sb->buf_size = sb->cfg->buf_size;
109  return 0;
110 }
111 
113 {
114  StreamingBuffer *sb = CALLOC(cfg, 1, sizeof(StreamingBuffer));
115  if (sb != NULL) {
116  sb->buf_size = cfg->buf_size;
117  sb->cfg = cfg;
118 
119  if (cfg->buf_size > 0) {
120  if (InitBuffer(sb) == 0) {
121  return sb;
122  }
123  FREE(cfg, sb, sizeof(StreamingBuffer));
124  /* implied buf_size == 0 */
125  } else {
126  return sb;
127  }
128  }
129  return NULL;
130 }
131 
133 {
134  if (sb != NULL) {
135  SCLogDebug("sb->buf_size %u max %u", sb->buf_size, sb->buf_size_max);
136 
137  SBBFree(sb);
138  if (sb->buf != NULL) {
139  FREE(sb->cfg, sb->buf, sb->buf_size);
140  sb->buf = NULL;
141  }
142  }
143 }
144 
146 {
147  if (sb != NULL) {
149  FREE(sb->cfg, sb, sizeof(StreamingBuffer));
150  }
151 }
152 
153 #ifdef DEBUG
154 static void SBBPrintList(StreamingBuffer *sb)
155 {
156  StreamingBufferBlock *sbb = NULL;
157  RB_FOREACH(sbb, SBB, &sb->sbb_tree) {
158  SCLogDebug("sbb: offset %"PRIu64", len %u", sbb->offset, sbb->len);
159  StreamingBufferBlock *next = SBB_RB_NEXT(sbb);
160  if (next) {
161  if ((sbb->offset + sbb->len) != next->offset) {
162  SCLogDebug("gap: offset %"PRIu64", len %"PRIu64, (sbb->offset + sbb->len),
163  next->offset - (sbb->offset + sbb->len));
164  }
165  }
166  }
167 }
168 #endif
169 
170 /* setup with gap between 2 blocks
171  *
172  * [block][gap][block]
173  **/
174 static void SBBInit(StreamingBuffer *sb,
175  uint32_t rel_offset, uint32_t data_len)
176 {
178  DEBUG_VALIDATE_BUG_ON(sb->buf_offset > sb->stream_offset + rel_offset);
179 
180  /* need to set up 2: existing data block and new data block */
181  StreamingBufferBlock *sbb = CALLOC(sb->cfg, 1, sizeof(*sbb));
182  if (sbb == NULL) {
183  return;
184  }
185  sbb->offset = sb->stream_offset;
186  sbb->len = sb->buf_offset;
187 
188  StreamingBufferBlock *sbb2 = CALLOC(sb->cfg, 1, sizeof(*sbb2));
189  if (sbb2 == NULL) {
190  FREE(sb->cfg, sbb, sizeof(*sbb));
191  return;
192  }
193  sbb2->offset = sb->stream_offset + rel_offset;
194  sbb2->len = data_len;
195 
196  sb->head = sbb;
197  sb->sbb_size = sbb->len + sbb2->len;
198  SBB_RB_INSERT(&sb->sbb_tree, sbb);
199  SBB_RB_INSERT(&sb->sbb_tree, sbb2);
200 
201  SCLogDebug("sbb1 %"PRIu64", len %u, sbb2 %"PRIu64", len %u",
202  sbb->offset, sbb->len, sbb2->offset, sbb2->len);
203 #ifdef DEBUG
204  SBBPrintList(sb);
205 #endif
206  BUG_ON(sbb2->offset < sbb->len);
207 }
208 
209 /* setup with leading gap
210  *
211  * [gap][block]
212  **/
213 static void SBBInitLeadingGap(StreamingBuffer *sb,
214  uint64_t offset, uint32_t data_len)
215 {
217 
218  StreamingBufferBlock *sbb = CALLOC(sb->cfg, 1, sizeof(*sbb));
219  if (sbb == NULL)
220  return;
221  sbb->offset = offset;
222  sbb->len = data_len;
223 
224  sb->head = sbb;
225  sb->sbb_size = sbb->len;
226  SBB_RB_INSERT(&sb->sbb_tree, sbb);
227 
228  SCLogDebug("sbb %"PRIu64", len %u",
229  sbb->offset, sbb->len);
230 #ifdef DEBUG
231  SBBPrintList(sb);
232 #endif
233 }
234 
235 static inline void ConsolidateFwd(StreamingBuffer *sb,
236  struct SBB *tree, StreamingBufferBlock *sa)
237 {
238  uint64_t sa_re = sa->offset + sa->len;
239  StreamingBufferBlock *tr, *s = sa;
240  RB_FOREACH_FROM(tr, SBB, s) {
241  if (sa == tr)
242  continue;
243 
244  const uint64_t tr_re = tr->offset + tr->len;
245  SCLogDebug("-> (fwd) tr %p %"PRIu64"/%u re %"PRIu64,
246  tr, tr->offset, tr->len, tr_re);
247 
248  if (sa_re < tr->offset)
249  break; // entirely before
250 
251  /*
252  sa: [ ]
253  tr: [ ]
254  sa: [ ]
255  tr: [ ]
256  sa: [ ]
257  tr: [ ]
258  */
259  if (sa->offset >= tr->offset && sa_re <= tr_re) {
260  sb->sbb_size -= sa->len;
261  sa->len = tr->len;
262  sa->offset = tr->offset;
263  sa_re = sa->offset + sa->len;
264  SCLogDebug("-> (fwd) tr %p %"PRIu64"/%u REMOVED ECLIPSED2", tr, tr->offset, tr->len);
265  SBB_RB_REMOVE(tree, tr);
266  FREE(sb->cfg, tr, sizeof(StreamingBufferBlock));
267  /*
268  sa: [ ]
269  tr: [ ]
270  sa: [ ]
271  tr: [ ]
272  sa: [ ]
273  tr: [ ]
274  */
275  } else if (sa->offset <= tr->offset && sa_re >= tr_re) {
276  SCLogDebug("-> (fwd) tr %p %"PRIu64"/%u REMOVED ECLIPSED", tr, tr->offset, tr->len);
277  SBB_RB_REMOVE(tree, tr);
278  sb->sbb_size -= tr->len;
279  FREE(sb->cfg, tr, sizeof(StreamingBufferBlock));
280  /*
281  sa: [ ]
282  tr: [ ]
283  sa: [ ]
284  tr: [ ]
285  */
286  } else if (sa->offset < tr->offset && // starts before
287  sa_re >= tr->offset && sa_re < tr_re) // ends inside
288  {
289  // merge. sb->sbb_size includes both so we need to adjust that too.
290  uint32_t combined_len = sa->len + tr->len;
291  sa->len = tr_re - sa->offset;
292  sa_re = sa->offset + sa->len;
293  SCLogDebug("-> (fwd) tr %p %"PRIu64"/%u REMOVED MERGED", tr, tr->offset, tr->len);
294  SBB_RB_REMOVE(tree, tr);
295  sb->sbb_size -= (combined_len - sa->len); // remove what we added twice
296  FREE(sb->cfg, tr, sizeof(StreamingBufferBlock));
297  }
298  }
299 }
300 
301 static inline void ConsolidateBackward(StreamingBuffer *sb,
302  struct SBB *tree, StreamingBufferBlock *sa)
303 {
304  uint64_t sa_re = sa->offset + sa->len;
305  StreamingBufferBlock *tr, *s = sa;
306  RB_FOREACH_REVERSE_FROM(tr, SBB, s) {
307  if (sa == tr)
308  continue;
309  const uint64_t tr_re = tr->offset + tr->len;
310  SCLogDebug("-> (bwd) tr %p %"PRIu64"/%u", tr, tr->offset, tr->len);
311 
312  if (sa->offset > tr_re)
313  break; // entirely after
314 
315  if (sa->offset >= tr->offset && sa_re <= tr_re) {
316  sb->sbb_size -= sa->len; // sa entirely eclipsed so remove double accounting
317  sa->len = tr->len;
318  sa->offset = tr->offset;
319  sa_re = sa->offset + sa->len;
320  SCLogDebug("-> (bwd) tr %p %"PRIu64"/%u REMOVED ECLIPSED2", tr, tr->offset, tr->len);
321  if (sb->head == tr)
322  sb->head = sa;
323  SBB_RB_REMOVE(tree, tr);
324  FREE(sb->cfg, tr, sizeof(StreamingBufferBlock));
325  /*
326  sa: [ ]
327  tr: [ ]
328  sa: [ ]
329  tr: [ ]
330  sa: [ ]
331  tr: [ ]
332  */
333  } else if (sa->offset <= tr->offset && sa_re >= tr_re) {
334  SCLogDebug("-> (bwd) tr %p %"PRIu64"/%u REMOVED ECLIPSED", tr, tr->offset, tr->len);
335  if (sb->head == tr)
336  sb->head = sa;
337  SBB_RB_REMOVE(tree, tr);
338  sb->sbb_size -= tr->len; // tr entirely eclipsed so remove double accounting
339  FREE(sb->cfg, tr, sizeof(StreamingBufferBlock));
340  /*
341  sa: [ ]
342  tr: [ ]
343  sa: [ ]
344  tr: [ ]
345  */
346  } else if (sa->offset > tr->offset && sa_re > tr_re && sa->offset <= tr_re) {
347  // merge. sb->sbb_size includes both so we need to adjust that too.
348  uint32_t combined_len = sa->len + tr->len;
349  sa->len = sa_re - tr->offset;
350  sa->offset = tr->offset;
351  sa_re = sa->offset + sa->len;
352  SCLogDebug("-> (bwd) tr %p %"PRIu64"/%u REMOVED MERGED", tr, tr->offset, tr->len);
353  if (sb->head == tr)
354  sb->head = sa;
355  SBB_RB_REMOVE(tree, tr);
356  sb->sbb_size -= (combined_len - sa->len); // remove what we added twice
357  FREE(sb->cfg, tr, sizeof(StreamingBufferBlock));
358  }
359  }
360 }
361 
362 static int Insert(StreamingBuffer *sb, struct SBB *tree,
363  uint32_t rel_offset, uint32_t len)
364 {
365  SCLogDebug("* inserting: %u/%u\n", rel_offset, len);
366 
367  StreamingBufferBlock *sbb = CALLOC(sb->cfg, 1, sizeof(*sbb));
368  if (sbb == NULL)
369  return -1;
370  sbb->offset = sb->stream_offset + rel_offset;
371  sbb->len = len;
372  StreamingBufferBlock *res = SBB_RB_INSERT(tree, sbb);
373  if (res) {
374  // exact overlap
375  SCLogDebug("* insert failed: exact match in tree with %p %"PRIu64"/%u", res, res->offset, res->len);
376  FREE(sb->cfg, sbb, sizeof(StreamingBufferBlock));
377  return 0;
378  }
379  sb->sbb_size += len; // may adjust based on consolidation below
380  if (SBB_RB_PREV(sbb) == NULL) {
381  sb->head = sbb;
382  } else {
383  ConsolidateBackward(sb, tree, sbb);
384  }
385  ConsolidateFwd(sb, tree, sbb);
386 #ifdef DEBUG
387  SBBPrintList(sb);
388 #endif
389  return 0;
390 }
391 
392 static void SBBUpdate(StreamingBuffer *sb,
393  uint32_t rel_offset, uint32_t data_len)
394 {
395  Insert(sb, &sb->sbb_tree, rel_offset, data_len);
396 }
397 
398 static void SBBFree(StreamingBuffer *sb)
399 {
400  StreamingBufferBlock *sbb = NULL, *safe = NULL;
401  RB_FOREACH_SAFE(sbb, SBB, &sb->sbb_tree, safe) {
402  SBB_RB_REMOVE(&sb->sbb_tree, sbb);
403  sb->sbb_size -= sbb->len;
404  FREE(sb->cfg, sbb, sizeof(StreamingBufferBlock));
405  }
406  sb->head = NULL;
407 }
408 
409 static void SBBPrune(StreamingBuffer *sb)
410 {
411  SCLogDebug("pruning %p to %"PRIu64, sb, sb->stream_offset);
412  StreamingBufferBlock *sbb = NULL, *safe = NULL;
413  RB_FOREACH_SAFE(sbb, SBB, &sb->sbb_tree, safe) {
414  /* completely beyond window, we're done */
415  if (sbb->offset > sb->stream_offset) {
416  sb->head = sbb;
417  break;
418  }
419 
420  /* partly before, partly beyond. Adjust */
421  if (sbb->offset < sb->stream_offset &&
422  sbb->offset + sbb->len > sb->stream_offset) {
423  uint32_t shrink_by = sb->stream_offset - sbb->offset;
424  DEBUG_VALIDATE_BUG_ON(shrink_by > sbb->len);
425  if (sbb->len >= shrink_by) {
426  sbb->len -= shrink_by;
427  sbb->offset += shrink_by;
428  sb->sbb_size -= shrink_by;
430  }
431  sb->head = sbb;
432  break;
433  }
434 
435  SBB_RB_REMOVE(&sb->sbb_tree, sbb);
436  /* either we set it again for the next sbb, or there isn't any */
437  sb->head = NULL;
438  sb->sbb_size -= sbb->len;
439  SCLogDebug("sb %p removed %p %"PRIu64", %u", sb, sbb, sbb->offset, sbb->len);
440  FREE(sb->cfg, sbb, sizeof(StreamingBufferBlock));
441  }
442 }
443 
444 /**
445  * \internal
446  * \brief move buffer forward by 'slide'
447  */
448 static void AutoSlide(StreamingBuffer *sb)
449 {
450  uint32_t size = sb->cfg->buf_slide;
451  uint32_t slide = sb->buf_offset - size;
452  SCLogDebug("sliding %u forward, size of original buffer left after slide %u", slide, size);
453  memmove(sb->buf, sb->buf+slide, size);
454  sb->stream_offset += slide;
455  sb->buf_offset = size;
456  SBBPrune(sb);
457 }
458 
459 static int WARN_UNUSED
460 GrowToSize(StreamingBuffer *sb, uint32_t size)
461 {
462  /* try to grow in multiples of sb->cfg->buf_size */
463  uint32_t x = sb->cfg->buf_size ? size % sb->cfg->buf_size : 0;
464  uint32_t base = size - x;
465  uint32_t grow = base + sb->cfg->buf_size;
466 
467  void *ptr = REALLOC(sb->cfg, sb->buf, sb->buf_size, grow);
468  if (ptr == NULL)
469  return -1;
470 
471  /* for safe printing and general caution, lets memset the
472  * new data to 0 */
473  size_t diff = grow - sb->buf_size;
474  void *new_mem = ((char *)ptr) + sb->buf_size;
475  memset(new_mem, 0, diff);
476 
477  sb->buf = ptr;
478  sb->buf_size = grow;
479  SCLogDebug("grown buffer to %u", grow);
480 #ifdef DEBUG
481  if (sb->buf_size > sb->buf_size_max) {
482  sb->buf_size_max = sb->buf_size;
483  }
484 #endif
485  return 0;
486 }
487 
488 /** \internal
489  * \brief try to double the buffer size
490  * \retval 0 ok
491  * \retval -1 failed, buffer unchanged
492  */
493 static int WARN_UNUSED Grow(StreamingBuffer *sb)
494 {
495  uint32_t grow = sb->buf_size * 2;
496  void *ptr = REALLOC(sb->cfg, sb->buf, sb->buf_size, grow);
497  if (ptr == NULL)
498  return -1;
499 
500  /* for safe printing and general caution, lets memset the
501  * new data to 0 */
502  size_t diff = grow - sb->buf_size;
503  void *new_mem = ((char *)ptr) + sb->buf_size;
504  memset(new_mem, 0, diff);
505 
506  sb->buf = ptr;
507  sb->buf_size = grow;
508  SCLogDebug("grown buffer to %u", grow);
509 #ifdef DEBUG
510  if (sb->buf_size > sb->buf_size_max) {
511  sb->buf_size_max = sb->buf_size;
512  }
513 #endif
514  return 0;
515 }
516 
517 /**
518  * \brief slide to absolute offset
519  * \todo if sliding beyond window, we could perhaps reset?
520  */
522 {
523  if (offset > sb->stream_offset &&
524  offset <= sb->stream_offset + sb->buf_offset)
525  {
526  uint32_t slide = offset - sb->stream_offset;
527  uint32_t size = sb->buf_offset - slide;
528  SCLogDebug("sliding %u forward, size of original buffer left after slide %u", slide, size);
529  memmove(sb->buf, sb->buf+slide, size);
530  sb->stream_offset += slide;
531  sb->buf_offset = size;
532  SBBPrune(sb);
533  }
534 }
535 
536 void StreamingBufferSlide(StreamingBuffer *sb, uint32_t slide)
537 {
538  uint32_t size = sb->buf_offset - slide;
539  SCLogDebug("sliding %u forward, size of original buffer left after slide %u", slide, size);
540  memmove(sb->buf, sb->buf+slide, size);
541  sb->stream_offset += slide;
542  sb->buf_offset = size;
543  SBBPrune(sb);
544 }
545 
546 #define DATA_FITS(sb, len) \
547  ((sb)->buf_offset + (len) <= (sb)->buf_size)
548 
549 StreamingBufferSegment *StreamingBufferAppendRaw(StreamingBuffer *sb, const uint8_t *data, uint32_t data_len)
550 {
551  if (sb->buf == NULL) {
552  if (InitBuffer(sb) == -1)
553  return NULL;
554  }
555 
556  if (!DATA_FITS(sb, data_len)) {
558  AutoSlide(sb);
559  if (sb->buf_size == 0) {
560  if (GrowToSize(sb, data_len) != 0)
561  return NULL;
562  } else {
563  while (!DATA_FITS(sb, data_len)) {
564  if (Grow(sb) != 0) {
565  return NULL;
566  }
567  }
568  }
569  }
570  if (!DATA_FITS(sb, data_len)) {
571  return NULL;
572  }
573 
574  StreamingBufferSegment *seg = CALLOC(sb->cfg, 1, sizeof(StreamingBufferSegment));
575  if (seg != NULL) {
576  memcpy(sb->buf + sb->buf_offset, data, data_len);
577  seg->stream_offset = sb->stream_offset + sb->buf_offset;
578  seg->segment_len = data_len;
579  uint32_t rel_offset = sb->buf_offset;
580  sb->buf_offset += data_len;
581 
582  if (!RB_EMPTY(&sb->sbb_tree)) {
583  SBBUpdate(sb, rel_offset, data_len);
584  }
585  return seg;
586  }
587  return NULL;
588 }
589 
590 int StreamingBufferAppend(StreamingBuffer *sb, StreamingBufferSegment *seg,
591  const uint8_t *data, uint32_t data_len)
592 {
593  BUG_ON(seg == NULL);
594 
595  if (sb->buf == NULL) {
596  if (InitBuffer(sb) == -1)
597  return -1;
598  }
599 
600  if (!DATA_FITS(sb, data_len)) {
602  AutoSlide(sb);
603  if (sb->buf_size == 0) {
604  if (GrowToSize(sb, data_len) != 0)
605  return -1;
606  } else {
607  while (!DATA_FITS(sb, data_len)) {
608  if (Grow(sb) != 0) {
609  return -1;
610  }
611  }
612  }
613  }
614  if (!DATA_FITS(sb, data_len)) {
615  return -1;
616  }
617 
618  memcpy(sb->buf + sb->buf_offset, data, data_len);
619  seg->stream_offset = sb->stream_offset + sb->buf_offset;
620  seg->segment_len = data_len;
621  uint32_t rel_offset = sb->buf_offset;
622  sb->buf_offset += data_len;
623 
624  if (!RB_EMPTY(&sb->sbb_tree)) {
625  SBBUpdate(sb, rel_offset, data_len);
626  }
627  return 0;
628 }
629 
630 /**
631  * \brief add data w/o tracking a segment
632  */
634  const uint8_t *data, uint32_t data_len)
635 {
636  if (sb->buf == NULL) {
637  if (InitBuffer(sb) == -1)
638  return -1;
639  }
640 
641  if (!DATA_FITS(sb, data_len)) {
643  AutoSlide(sb);
644  if (sb->buf_size == 0) {
645  if (GrowToSize(sb, data_len) != 0)
646  return -1;
647  } else {
648  while (!DATA_FITS(sb, data_len)) {
649  if (Grow(sb) != 0) {
650  return -1;
651  }
652  }
653  }
654  }
655  if (!DATA_FITS(sb, data_len)) {
656  return -1;
657  }
658 
659  memcpy(sb->buf + sb->buf_offset, data, data_len);
660  uint32_t rel_offset = sb->buf_offset;
661  sb->buf_offset += data_len;
662 
663  if (!RB_EMPTY(&sb->sbb_tree)) {
664  SBBUpdate(sb, rel_offset, data_len);
665  }
666  return 0;
667 }
668 
669 #define DATA_FITS_AT_OFFSET(sb, len, offset) \
670  ((offset) + (len) <= (sb)->buf_size)
671 
672 /**
673  * \param offset offset relative to StreamingBuffer::stream_offset
674  */
675 int StreamingBufferInsertAt(StreamingBuffer *sb, StreamingBufferSegment *seg,
676  const uint8_t *data, uint32_t data_len,
677  uint64_t offset)
678 {
679  BUG_ON(seg == NULL);
680 
681  if (offset < sb->stream_offset)
682  return -1;
683 
684  if (sb->buf == NULL) {
685  if (InitBuffer(sb) == -1)
686  return -1;
687  }
688 
689  uint32_t rel_offset = offset - sb->stream_offset;
690  if (!DATA_FITS_AT_OFFSET(sb, data_len, rel_offset)) {
691  if (sb->cfg->flags & STREAMING_BUFFER_AUTOSLIDE) {
692  AutoSlide(sb);
693  rel_offset = offset - sb->stream_offset;
694  }
695  if (!DATA_FITS_AT_OFFSET(sb, data_len, rel_offset)) {
696  if (GrowToSize(sb, (rel_offset + data_len)) != 0)
697  return -1;
698  }
699  }
700  if (!DATA_FITS_AT_OFFSET(sb, data_len, rel_offset)) {
701  return -1;
702  }
703 
704  memcpy(sb->buf + rel_offset, data, data_len);
705  seg->stream_offset = offset;
706  seg->segment_len = data_len;
707 
708  SCLogDebug("rel_offset %u sb->stream_offset %"PRIu64", buf_offset %u",
709  rel_offset, sb->stream_offset, sb->buf_offset);
710 
711  if (RB_EMPTY(&sb->sbb_tree)) {
712  SCLogDebug("empty sbb list");
713 
714  if (sb->stream_offset == offset) {
715  SCLogDebug("empty sbb list: block exactly what was expected, fall through");
716  /* empty list, data is exactly what is expected (append),
717  * so do nothing */
718  } else if ((rel_offset + data_len) <= sb->buf_offset) {
719  SCLogDebug("empty sbb list: block is within existing region");
720  } else {
721  if (sb->buf_offset && rel_offset == sb->buf_offset) {
722  // nothing to do
723  } else if (rel_offset < sb->buf_offset) {
724  // nothing to do
725  } else if (sb->buf_offset) {
726  /* existing data, but there is a gap between us */
727  SBBInit(sb, rel_offset, data_len);
728  } else {
729  /* gap before data in empty list */
730  SCLogDebug("empty sbb list: invoking SBBInitLeadingGap");
731  SBBInitLeadingGap(sb, offset, data_len);
732  }
733  }
734  } else {
735  /* already have blocks, so append new block based on new data */
736  SBBUpdate(sb, rel_offset, data_len);
737  }
738 
739  if (rel_offset + data_len > sb->buf_offset)
740  sb->buf_offset = rel_offset + data_len;
741 
742  return 0;
743 }
744 
746  const StreamingBufferSegment *seg)
747 {
748  if (seg->stream_offset < sb->stream_offset) {
749  if (seg->stream_offset + seg->segment_len <= sb->stream_offset) {
750  return 1;
751  }
752  }
753  return 0;
754 }
755 
756 /** \brief get the data for one SBB */
758  const StreamingBufferBlock *sbb,
759  const uint8_t **data, uint32_t *data_len)
760 {
761  if (sbb->offset >= sb->stream_offset) {
762  uint64_t offset = sbb->offset - sb->stream_offset;
763  *data = sb->buf + offset;
764  if (offset + sbb->len > sb->buf_offset)
765  *data_len = sb->buf_offset - offset;
766  else
767  *data_len = sbb->len;
768  return;
769  } else {
770  uint64_t offset = sb->stream_offset - sbb->offset;
771  if (offset < sbb->len) {
772  *data = sb->buf;
773  *data_len = sbb->len - offset;
774  return;
775  }
776  }
777  *data = NULL;
778  *data_len = 0;
779  return;
780 }
781 
782 /** \brief get the data for one SBB */
784  const StreamingBufferBlock *sbb,
785  const uint8_t **data, uint32_t *data_len,
786  uint64_t offset)
787 {
788  if (offset >= sbb->offset && offset < (sbb->offset + sbb->len)) {
789  uint32_t sbblen = sbb->len - (offset - sbb->offset);
790 
791  if (offset >= sb->stream_offset) {
792  uint64_t data_offset = offset - sb->stream_offset;
793  *data = sb->buf + data_offset;
794  if (data_offset + sbblen > sb->buf_size)
795  *data_len = sb->buf_size - data_offset;
796  else
797  *data_len = sbblen;
798  BUG_ON(*data_len > sbblen);
799  return;
800  } else {
801  uint64_t data_offset = sb->stream_offset - sbb->offset;
802  if (data_offset < sbblen) {
803  *data = sb->buf;
804  *data_len = sbblen - data_offset;
805  BUG_ON(*data_len > sbblen);
806  return;
807  }
808  }
809  }
810 
811  *data = NULL;
812  *data_len = 0;
813  return;
814 }
815 
817  const StreamingBufferSegment *seg,
818  const uint8_t **data, uint32_t *data_len)
819 {
820  if (likely(sb->buf)) {
821  if (seg->stream_offset >= sb->stream_offset) {
822  uint64_t offset = seg->stream_offset - sb->stream_offset;
823  *data = sb->buf + offset;
824  if (offset + seg->segment_len > sb->buf_size)
825  *data_len = sb->buf_size - offset;
826  else
827  *data_len = seg->segment_len;
828  return;
829  } else {
830  uint64_t offset = sb->stream_offset - seg->stream_offset;
831  if (offset < seg->segment_len) {
832  *data = sb->buf;
833  *data_len = seg->segment_len - offset;
834  return;
835  }
836  }
837  }
838  *data = NULL;
839  *data_len = 0;
840  return;
841 }
842 
843 /**
844  * \retval 1 data is the same
845  * \retval 0 data is different
846  */
848  const StreamingBufferSegment *seg,
849  const uint8_t *rawdata, uint32_t rawdata_len)
850 {
851  const uint8_t *segdata = NULL;
852  uint32_t segdata_len = 0;
853  StreamingBufferSegmentGetData(sb, seg, &segdata, &segdata_len);
854  if (segdata && segdata_len &&
855  segdata_len == rawdata_len &&
856  memcmp(segdata, rawdata, segdata_len) == 0)
857  {
858  return 1;
859  }
860  return 0;
861 }
862 
864  const uint8_t **data, uint32_t *data_len,
865  uint64_t *stream_offset)
866 {
867  if (sb != NULL && sb->buf != NULL) {
868  *data = sb->buf;
869  *data_len = sb->buf_offset;
871  return 1;
872  } else {
873  *data = NULL;
874  *data_len = 0;
875  *stream_offset = 0;
876  return 0;
877  }
878 }
879 
881  const uint8_t **data, uint32_t *data_len,
882  uint64_t offset)
883 {
884  if (sb != NULL && sb->buf != NULL &&
885  offset >= sb->stream_offset &&
886  offset < (sb->stream_offset + sb->buf_offset))
887  {
888  uint32_t skip = offset - sb->stream_offset;
889  *data = sb->buf + skip;
890  *data_len = sb->buf_offset - skip;
891  return 1;
892  } else {
893  *data = NULL;
894  *data_len = 0;
895  return 0;
896  }
897 }
898 
899 /**
900  * \retval 1 data is the same
901  * \retval 0 data is different
902  */
904  const uint8_t *rawdata, uint32_t rawdata_len)
905 {
906  const uint8_t *sbdata = NULL;
907  uint32_t sbdata_len = 0;
908  uint64_t offset = 0;
909  StreamingBufferGetData(sb, &sbdata, &sbdata_len, &offset);
910  if (offset == 0 &&
911  sbdata && sbdata_len &&
912  sbdata_len == rawdata_len &&
913  memcmp(sbdata, rawdata, sbdata_len) == 0)
914  {
915  return 1;
916  }
917  SCLogDebug("sbdata_len %u, offset %"PRIu64, sbdata_len, offset);
918  printf("got:\n");
919  PrintRawDataFp(stdout, sbdata,sbdata_len);
920  printf("wanted:\n");
921  PrintRawDataFp(stdout, rawdata,rawdata_len);
922  return 0;
923 }
924 
925 #ifdef UNITTESTS
926 static void Dump(StreamingBuffer *sb)
927 {
928  PrintRawDataFp(stdout, sb->buf, sb->buf_offset);
929 }
930 
931 static void DumpSegment(StreamingBuffer *sb, StreamingBufferSegment *seg)
932 {
933  const uint8_t *data = NULL;
934  uint32_t data_len = 0;
935  StreamingBufferSegmentGetData(sb, seg, &data, &data_len);
936  if (data && data_len) {
937  PrintRawDataFp(stdout, data, data_len);
938  }
939 }
940 
941 static int StreamingBufferTest01(void)
942 {
943  StreamingBufferConfig cfg = { STREAMING_BUFFER_AUTOSLIDE, 8, 16, NULL, NULL, NULL, NULL };
945  FAIL_IF(sb == NULL);
946 
947  StreamingBufferSegment *seg1 = StreamingBufferAppendRaw(sb, (const uint8_t *)"ABCDEFGH", 8);
948  StreamingBufferSegment *seg2 = StreamingBufferAppendRaw(sb, (const uint8_t *)"01234567", 8);
949  FAIL_IF(sb->stream_offset != 0);
950  FAIL_IF(sb->buf_offset != 16);
951  FAIL_IF(seg1->stream_offset != 0);
952  FAIL_IF(seg2->stream_offset != 8);
955  FAIL_IF(!StreamingBufferSegmentCompareRawData(sb,seg1,(const uint8_t *)"ABCDEFGH", 8));
956  FAIL_IF(!StreamingBufferSegmentCompareRawData(sb,seg2,(const uint8_t *)"01234567", 8));
957  Dump(sb);
958  FAIL_IF_NOT_NULL(sb->head);
959  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
960 
961  StreamingBufferSegment *seg3 = StreamingBufferAppendRaw(sb, (const uint8_t *)"QWERTY", 6);
962  FAIL_IF(sb->stream_offset != 8);
963  FAIL_IF(sb->buf_offset != 14);
964  FAIL_IF(seg3->stream_offset != 16);
968  FAIL_IF(!StreamingBufferSegmentCompareRawData(sb,seg3,(const uint8_t *)"QWERTY", 6));
969  Dump(sb);
970  FAIL_IF_NOT_NULL(sb->head);
971  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
972 
973  StreamingBufferSegment *seg4 = StreamingBufferAppendRaw(sb, (const uint8_t *)"KLM", 3);
974  FAIL_IF(sb->stream_offset != 14);
975  FAIL_IF(sb->buf_offset != 11);
976  FAIL_IF(seg4->stream_offset != 22);
981  FAIL_IF(!StreamingBufferSegmentCompareRawData(sb,seg4,(const uint8_t *)"KLM", 3));
982  Dump(sb);
983  FAIL_IF_NOT_NULL(sb->head);
984  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
985 
986  StreamingBufferSegment *seg5 = StreamingBufferAppendRaw(sb, (const uint8_t *)"!@#$%^&*()_+<>?/,.;:'[]{}-=", 27);
987  FAIL_IF(sb->stream_offset != 17);
988  FAIL_IF(sb->buf_offset != 35);
989  FAIL_IF(seg5->stream_offset != 25);
995  FAIL_IF(!StreamingBufferSegmentCompareRawData(sb,seg5,(const uint8_t *)"!@#$%^&*()_+<>?/,.;:'[]{}-=", 27));
996  Dump(sb);
997  FAIL_IF_NOT_NULL(sb->head);
998  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
999 
1000  StreamingBufferSegment *seg6 = StreamingBufferAppendRaw(sb, (const uint8_t *)"UVWXYZ", 6);
1001  FAIL_IF(sb->stream_offset != 17);
1002  FAIL_IF(sb->buf_offset != 41);
1003  FAIL_IF(seg6->stream_offset != 52);
1010  FAIL_IF(!StreamingBufferSegmentCompareRawData(sb,seg6,(const uint8_t *)"UVWXYZ", 6));
1011  Dump(sb);
1012  FAIL_IF_NOT_NULL(sb->head);
1013  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1014 
1015  SCFree(seg1);
1016  SCFree(seg2);
1017  SCFree(seg3);
1018  SCFree(seg4);
1019  SCFree(seg5);
1020  SCFree(seg6);
1021  StreamingBufferFree(sb);
1022  PASS;
1023 }
1024 
1025 static int StreamingBufferTest02(void)
1026 {
1027  StreamingBufferConfig cfg = { 0, 8, 24, NULL, NULL, NULL, NULL };
1029  FAIL_IF(sb == NULL);
1030 
1031  StreamingBufferSegment seg1;
1032  FAIL_IF(StreamingBufferAppend(sb, &seg1, (const uint8_t *)"ABCDEFGH", 8) != 0);
1033  StreamingBufferSegment seg2;
1034  FAIL_IF(StreamingBufferAppend(sb, &seg2, (const uint8_t *)"01234567", 8) != 0);
1035  FAIL_IF(sb->stream_offset != 0);
1036  FAIL_IF(sb->buf_offset != 16);
1037  FAIL_IF(seg1.stream_offset != 0);
1038  FAIL_IF(seg2.stream_offset != 8);
1041  Dump(sb);
1042  DumpSegment(sb, &seg1);
1043  DumpSegment(sb, &seg2);
1044  FAIL_IF_NOT_NULL(sb->head);
1045  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1046 
1047  StreamingBufferSlide(sb, 6);
1048  FAIL_IF_NOT_NULL(sb->head);
1049  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1050 
1051  StreamingBufferSegment seg3;
1052  FAIL_IF(StreamingBufferAppend(sb, &seg3, (const uint8_t *)"QWERTY", 6) != 0);
1053  FAIL_IF(sb->stream_offset != 6);
1054  FAIL_IF(sb->buf_offset != 16);
1055  FAIL_IF(seg3.stream_offset != 16);
1059  Dump(sb);
1060  DumpSegment(sb, &seg1);
1061  DumpSegment(sb, &seg2);
1062  DumpSegment(sb, &seg3);
1063  FAIL_IF_NOT_NULL(sb->head);
1064  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1065 
1066  StreamingBufferSlide(sb, 6);
1070  Dump(sb);
1071  DumpSegment(sb, &seg1);
1072  DumpSegment(sb, &seg2);
1073  DumpSegment(sb, &seg3);
1074  FAIL_IF_NOT_NULL(sb->head);
1075  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1076 
1077  StreamingBufferFree(sb);
1078  PASS;
1079 }
1080 
1081 static int StreamingBufferTest03(void)
1082 {
1083  StreamingBufferConfig cfg = { 0, 8, 24, NULL, NULL, NULL, NULL };
1085  FAIL_IF(sb == NULL);
1086 
1087  StreamingBufferSegment seg1;
1088  FAIL_IF(StreamingBufferAppend(sb, &seg1, (const uint8_t *)"ABCDEFGH", 8) != 0);
1089  StreamingBufferSegment seg2;
1090  FAIL_IF(StreamingBufferInsertAt(sb, &seg2, (const uint8_t *)"01234567", 8, 14) != 0);
1091  FAIL_IF(sb->stream_offset != 0);
1092  FAIL_IF(sb->buf_offset != 22);
1093  FAIL_IF(seg1.stream_offset != 0);
1094  FAIL_IF(seg2.stream_offset != 14);
1097  Dump(sb);
1098  DumpSegment(sb, &seg1);
1099  DumpSegment(sb, &seg2);
1100  FAIL_IF_NULL(sb->head);
1101  FAIL_IF_NOT(sb->sbb_size == 16);
1102  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1103 
1104  StreamingBufferSegment seg3;
1105  FAIL_IF(StreamingBufferInsertAt(sb, &seg3, (const uint8_t *)"QWERTY", 6, 8) != 0);
1106  FAIL_IF(sb->stream_offset != 0);
1107  FAIL_IF(sb->buf_offset != 22);
1108  FAIL_IF(seg3.stream_offset != 8);
1112  Dump(sb);
1113  DumpSegment(sb, &seg1);
1114  DumpSegment(sb, &seg2);
1115  DumpSegment(sb, &seg3);
1116  FAIL_IF_NULL(sb->head);
1117  FAIL_IF_NOT(sb->sbb_size == 22);
1118  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1119 
1120  StreamingBufferSlide(sb, 10);
1124  Dump(sb);
1125  DumpSegment(sb, &seg1);
1126  DumpSegment(sb, &seg2);
1127  DumpSegment(sb, &seg3);
1128  FAIL_IF_NULL(sb->head);
1129  FAIL_IF_NOT(sb->sbb_size == 12);
1130  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1131 
1132  StreamingBufferFree(sb);
1133  PASS;
1134 }
1135 
1136 static int StreamingBufferTest04(void)
1137 {
1138  StreamingBufferConfig cfg = { 0, 8, 16, NULL, NULL, NULL, NULL };
1140  FAIL_IF(sb == NULL);
1141 
1142  StreamingBufferSegment seg1;
1143  FAIL_IF(StreamingBufferAppend(sb, &seg1, (const uint8_t *)"ABCDEFGH", 8) != 0);
1144  FAIL_IF(!RB_EMPTY(&sb->sbb_tree));
1145  StreamingBufferSegment seg2;
1146  FAIL_IF(StreamingBufferInsertAt(sb, &seg2, (const uint8_t *)"01234567", 8, 14) != 0);
1147  FAIL_IF(sb->stream_offset != 0);
1148  FAIL_IF(sb->buf_offset != 22);
1149  FAIL_IF(seg1.stream_offset != 0);
1150  FAIL_IF(seg2.stream_offset != 14);
1153  FAIL_IF(RB_EMPTY(&sb->sbb_tree));
1154  StreamingBufferBlock *sbb1 = RB_MIN(SBB, &sb->sbb_tree);
1155  FAIL_IF(sbb1 != sb->head);
1156  FAIL_IF_NULL(sbb1);
1157  FAIL_IF(sbb1->offset != 0);
1158  FAIL_IF(sbb1->len != 8);
1159  StreamingBufferBlock *sbb2 = SBB_RB_NEXT(sbb1);
1160  FAIL_IF_NULL(sbb2);
1161  FAIL_IF(sbb2 == sb->head);
1162  FAIL_IF(sbb2->offset != 14);
1163  FAIL_IF(sbb2->len != 8);
1164  Dump(sb);
1165  DumpSegment(sb, &seg1);
1166  DumpSegment(sb, &seg2);
1167  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1168 
1169  StreamingBufferSegment seg3;
1170  FAIL_IF(StreamingBufferInsertAt(sb, &seg3, (const uint8_t *)"QWERTY", 6, 8) != 0);
1171  FAIL_IF(sb->stream_offset != 0);
1172  FAIL_IF(sb->buf_offset != 22);
1173  FAIL_IF(seg3.stream_offset != 8);
1177  sbb1 = RB_MIN(SBB, &sb->sbb_tree);
1178  FAIL_IF_NULL(sbb1);
1179  FAIL_IF(sbb1 != sb->head);
1180  FAIL_IF(sbb1->offset != 0);
1181  FAIL_IF(sbb1->len != 22);
1182  FAIL_IF(SBB_RB_NEXT(sbb1));
1183  Dump(sb);
1184  DumpSegment(sb, &seg1);
1185  DumpSegment(sb, &seg2);
1186  DumpSegment(sb, &seg3);
1187  FAIL_IF_NULL(sb->head);
1188  FAIL_IF_NOT(sb->sbb_size == 22);
1189  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1190 
1191  /* far ahead of curve: */
1192  StreamingBufferSegment seg4;
1193  FAIL_IF(StreamingBufferInsertAt(sb, &seg4, (const uint8_t *)"XYZ", 3, 124) != 0);
1194  FAIL_IF(sb->stream_offset != 0);
1195  FAIL_IF(sb->buf_offset != 127);
1196  FAIL_IF(sb->buf_size != 128);
1197  FAIL_IF(seg4.stream_offset != 124);
1202  sbb1 = RB_MIN(SBB, &sb->sbb_tree);
1203  FAIL_IF_NULL(sbb1);
1204  FAIL_IF(sbb1 != sb->head);
1205  FAIL_IF(sbb1->offset != 0);
1206  FAIL_IF(sbb1->len != 22);
1207  FAIL_IF(!SBB_RB_NEXT(sbb1));
1208  Dump(sb);
1209  DumpSegment(sb, &seg1);
1210  DumpSegment(sb, &seg2);
1211  DumpSegment(sb, &seg3);
1212  DumpSegment(sb, &seg4);
1213  FAIL_IF_NULL(sb->head);
1214  FAIL_IF_NOT(sb->sbb_size == 25);
1215  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1216 
1217  FAIL_IF(!StreamingBufferSegmentCompareRawData(sb,&seg1,(const uint8_t *)"ABCDEFGH", 8));
1218  FAIL_IF(!StreamingBufferSegmentCompareRawData(sb,&seg2,(const uint8_t *)"01234567", 8));
1219  FAIL_IF(!StreamingBufferSegmentCompareRawData(sb,&seg3,(const uint8_t *)"QWERTY", 6));
1220  FAIL_IF(!StreamingBufferSegmentCompareRawData(sb,&seg4,(const uint8_t *)"XYZ", 3));
1221 
1222  StreamingBufferFree(sb);
1223  PASS;
1224 }
1225 
1226 static int StreamingBufferTest05(void)
1227 {
1228  StreamingBufferConfig cfg = { STREAMING_BUFFER_AUTOSLIDE, 8, 32, NULL, NULL, NULL, NULL };
1230 
1231  StreamingBufferSegment *seg1 = StreamingBufferAppendRaw(&sb, (const uint8_t *)"AAAAAAAA", 8);
1232  StreamingBufferSegment *seg2 = StreamingBufferAppendRaw(&sb, (const uint8_t *)"BBBBBBBB", 8);
1233  StreamingBufferSegment *seg3 = StreamingBufferAppendRaw(&sb, (const uint8_t *)"CCCCCCCC", 8);
1234  StreamingBufferSegment *seg4 = StreamingBufferAppendRaw(&sb, (const uint8_t *)"DDDDDDDD", 8);
1235  FAIL_IF(sb.stream_offset != 0);
1236  FAIL_IF(sb.buf_offset != 32);
1237  FAIL_IF(seg1->stream_offset != 0);
1238  FAIL_IF(seg2->stream_offset != 8);
1239  FAIL_IF(seg3->stream_offset != 16);
1240  FAIL_IF(seg4->stream_offset != 24);
1245  FAIL_IF(!StreamingBufferSegmentCompareRawData(&sb,seg1,(const uint8_t *)"AAAAAAAA", 8));
1246  FAIL_IF(!StreamingBufferSegmentCompareRawData(&sb,seg2,(const uint8_t *)"BBBBBBBB", 8));
1247  FAIL_IF(!StreamingBufferSegmentCompareRawData(&sb,seg3,(const uint8_t *)"CCCCCCCC", 8));
1248  FAIL_IF(!StreamingBufferSegmentCompareRawData(&sb,seg4,(const uint8_t *)"DDDDDDDD", 8));
1249  Dump(&sb);
1250  FAIL_IF_NOT(sb.head == RB_MIN(SBB, &sb.sbb_tree));
1251  StreamingBufferSegment *seg5 = StreamingBufferAppendRaw(&sb, (const uint8_t *)"EEEEEEEE", 8);
1252  FAIL_IF(!StreamingBufferSegmentCompareRawData(&sb,seg5,(const uint8_t *)"EEEEEEEE", 8));
1253  Dump(&sb);
1254  FAIL_IF_NOT(sb.head == RB_MIN(SBB, &sb.sbb_tree));
1255 
1256  SCFree(seg1);
1257  SCFree(seg2);
1258  SCFree(seg3);
1259  SCFree(seg4);
1260  SCFree(seg5);
1261  StreamingBufferClear(&sb);
1262  PASS;
1263 }
1264 
1265 /** \test lots of gaps in block list */
1266 static int StreamingBufferTest06(void)
1267 {
1268  StreamingBufferConfig cfg = { 0, 8, 16, NULL, NULL, NULL, NULL };
1270  FAIL_IF(sb == NULL);
1271 
1272  StreamingBufferSegment seg1;
1273  FAIL_IF(StreamingBufferAppend(sb, &seg1, (const uint8_t *)"A", 1) != 0);
1274  StreamingBufferSegment seg2;
1275  FAIL_IF(StreamingBufferInsertAt(sb, &seg2, (const uint8_t *)"C", 1, 2) != 0);
1276  Dump(sb);
1277  FAIL_IF_NULL(sb->head);
1278  FAIL_IF_NOT(sb->sbb_size == 2);
1279  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1280 
1281  StreamingBufferSegment seg3;
1282  FAIL_IF(StreamingBufferInsertAt(sb, &seg3, (const uint8_t *)"F", 1, 5) != 0);
1283  Dump(sb);
1284  FAIL_IF_NULL(sb->head);
1285  FAIL_IF_NOT(sb->sbb_size == 3);
1286  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1287 
1288  StreamingBufferSegment seg4;
1289  FAIL_IF(StreamingBufferInsertAt(sb, &seg4, (const uint8_t *)"H", 1, 7) != 0);
1290  Dump(sb);
1291  FAIL_IF_NULL(sb->head);
1292  FAIL_IF_NOT(sb->sbb_size == 4);
1293  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1294 
1295  StreamingBufferSegment seg5;
1296  FAIL_IF(StreamingBufferInsertAt(sb, &seg5, (const uint8_t *)"ABCDEFGHIJ", 10, 0) != 0);
1297  Dump(sb);
1298  StreamingBufferBlock *sbb1 = RB_MIN(SBB, &sb->sbb_tree);
1299  FAIL_IF_NULL(sbb1);
1300  FAIL_IF(sbb1->offset != 0);
1301  FAIL_IF(sbb1->len != 10);
1302  FAIL_IF(SBB_RB_NEXT(sbb1));
1303  FAIL_IF_NULL(sb->head);
1304  FAIL_IF_NOT(sb->sbb_size == 10);
1305  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1306 
1307  StreamingBufferSegment seg6;
1308  FAIL_IF(StreamingBufferInsertAt(sb, &seg6, (const uint8_t *)"abcdefghij", 10, 0) != 0);
1309  Dump(sb);
1310  sbb1 = RB_MIN(SBB, &sb->sbb_tree);
1311  FAIL_IF_NULL(sbb1);
1312  FAIL_IF(sbb1->offset != 0);
1313  FAIL_IF(sbb1->len != 10);
1314  FAIL_IF(SBB_RB_NEXT(sbb1));
1315  FAIL_IF_NULL(sb->head);
1316  FAIL_IF_NOT(sb->sbb_size == 10);
1317  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1318 
1319  StreamingBufferFree(sb);
1320  PASS;
1321 }
1322 
1323 /** \test lots of gaps in block list */
1324 static int StreamingBufferTest07(void)
1325 {
1326  StreamingBufferConfig cfg = { 0, 8, 16, NULL, NULL, NULL, NULL };
1328  FAIL_IF(sb == NULL);
1329 
1330  StreamingBufferSegment seg1;
1331  FAIL_IF(StreamingBufferInsertAt(sb, &seg1, (const uint8_t *)"B", 1, 1) != 0);
1332  StreamingBufferSegment seg2;
1333  FAIL_IF(StreamingBufferInsertAt(sb, &seg2, (const uint8_t *)"D", 1, 3) != 0);
1334  Dump(sb);
1335  FAIL_IF_NULL(sb->head);
1336  FAIL_IF_NOT(sb->sbb_size == 2);
1337  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1338 
1339  StreamingBufferSegment seg3;
1340  FAIL_IF(StreamingBufferInsertAt(sb, &seg3, (const uint8_t *)"F", 1, 5) != 0);
1341  Dump(sb);
1342  FAIL_IF_NULL(sb->head);
1343  FAIL_IF_NOT(sb->sbb_size == 3);
1344  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1345 
1346  StreamingBufferSegment seg4;
1347  FAIL_IF(StreamingBufferInsertAt(sb, &seg4, (const uint8_t *)"H", 1, 7) != 0);
1348  Dump(sb);
1349  FAIL_IF_NULL(sb->head);
1350  FAIL_IF_NOT(sb->sbb_size == 4);
1351  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1352 
1353  StreamingBufferSegment seg5;
1354  FAIL_IF(StreamingBufferInsertAt(sb, &seg5, (const uint8_t *)"ABCDEFGHIJ", 10, 0) != 0);
1355  Dump(sb);
1356  StreamingBufferBlock *sbb1 = RB_MIN(SBB, &sb->sbb_tree);
1357  FAIL_IF_NULL(sbb1);
1358  FAIL_IF(sbb1->offset != 0);
1359  FAIL_IF(sbb1->len != 10);
1360  FAIL_IF(SBB_RB_NEXT(sbb1));
1361  FAIL_IF_NULL(sb->head);
1362  FAIL_IF_NOT(sb->sbb_size == 10);
1363  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1364 
1365  StreamingBufferSegment seg6;
1366  FAIL_IF(StreamingBufferInsertAt(sb, &seg6, (const uint8_t *)"abcdefghij", 10, 0) != 0);
1367  Dump(sb);
1368  sbb1 = RB_MIN(SBB, &sb->sbb_tree);
1369  FAIL_IF_NULL(sbb1);
1370  FAIL_IF(sbb1->offset != 0);
1371  FAIL_IF(sbb1->len != 10);
1372  FAIL_IF(SBB_RB_NEXT(sbb1));
1373  FAIL_IF_NULL(sb->head);
1374  FAIL_IF_NOT(sb->sbb_size == 10);
1375  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1376 
1377  StreamingBufferFree(sb);
1378  PASS;
1379 }
1380 
1381 /** \test lots of gaps in block list */
1382 static int StreamingBufferTest08(void)
1383 {
1384  StreamingBufferConfig cfg = { 0, 8, 16, NULL, NULL, NULL, NULL };
1386  FAIL_IF(sb == NULL);
1387 
1388  StreamingBufferSegment seg1;
1389  FAIL_IF(StreamingBufferInsertAt(sb, &seg1, (const uint8_t *)"B", 1, 1) != 0);
1390  StreamingBufferSegment seg2;
1391  FAIL_IF(StreamingBufferInsertAt(sb, &seg2, (const uint8_t *)"D", 1, 3) != 0);
1392  Dump(sb);
1393  FAIL_IF_NULL(sb->head);
1394  FAIL_IF_NOT(sb->sbb_size == 2);
1395  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1396 
1397  StreamingBufferSegment seg3;
1398  FAIL_IF(StreamingBufferInsertAt(sb, &seg3, (const uint8_t *)"F", 1, 5) != 0);
1399  Dump(sb);
1400  FAIL_IF_NULL(sb->head);
1401  FAIL_IF_NOT(sb->sbb_size == 3);
1402  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1403 
1404  StreamingBufferSegment seg4;
1405  FAIL_IF(StreamingBufferInsertAt(sb, &seg4, (const uint8_t *)"H", 1, 7) != 0);
1406  Dump(sb);
1407  FAIL_IF_NULL(sb->head);
1408  FAIL_IF_NOT(sb->sbb_size == 4);
1409  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1410 
1411  StreamingBufferSegment seg5;
1412  FAIL_IF(StreamingBufferInsertAt(sb, &seg5, (const uint8_t *)"ABCDEFGHIJ", 10, 0) != 0);
1413  Dump(sb);
1414  StreamingBufferBlock *sbb1 = RB_MIN(SBB, &sb->sbb_tree);
1415  FAIL_IF_NULL(sbb1);
1416  FAIL_IF(sbb1->offset != 0);
1417  FAIL_IF(sbb1->len != 10);
1418  FAIL_IF(SBB_RB_NEXT(sbb1));
1419  FAIL_IF_NULL(sb->head);
1420  FAIL_IF_NOT(sb->sbb_size == 10);
1421  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1422 
1423  StreamingBufferSegment seg6;
1424  FAIL_IF(StreamingBufferAppend(sb, &seg6, (const uint8_t *)"abcdefghij", 10) != 0);
1425  Dump(sb);
1426  sbb1 = RB_MIN(SBB, &sb->sbb_tree);
1427  FAIL_IF_NULL(sbb1);
1428  FAIL_IF(sbb1->offset != 0);
1429  FAIL_IF(sbb1->len != 20);
1430  FAIL_IF(SBB_RB_NEXT(sbb1));
1431  FAIL_IF_NULL(sb->head);
1432  FAIL_IF_NOT(sb->sbb_size == 20);
1433  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1434 
1435  StreamingBufferFree(sb);
1436  PASS;
1437 }
1438 
1439 /** \test lots of gaps in block list */
1440 static int StreamingBufferTest09(void)
1441 {
1442  StreamingBufferConfig cfg = { 0, 8, 16, NULL, NULL, NULL, NULL };
1444  FAIL_IF(sb == NULL);
1445 
1446  StreamingBufferSegment seg1;
1447  FAIL_IF(StreamingBufferInsertAt(sb, &seg1, (const uint8_t *)"B", 1, 1) != 0);
1448  StreamingBufferSegment seg2;
1449  FAIL_IF(StreamingBufferInsertAt(sb, &seg2, (const uint8_t *)"D", 1, 3) != 0);
1450  Dump(sb);
1451  FAIL_IF_NULL(sb->head);
1452  FAIL_IF_NOT(sb->sbb_size == 2);
1453  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1454 
1455  StreamingBufferSegment seg3;
1456  FAIL_IF(StreamingBufferInsertAt(sb, &seg3, (const uint8_t *)"H", 1, 7) != 0);
1457  Dump(sb);
1458  FAIL_IF_NULL(sb->head);
1459  FAIL_IF_NOT(sb->sbb_size == 3);
1460  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1461 
1462  StreamingBufferSegment seg4;
1463  FAIL_IF(StreamingBufferInsertAt(sb, &seg4, (const uint8_t *)"F", 1, 5) != 0);
1464  Dump(sb);
1465  FAIL_IF_NULL(sb->head);
1466  FAIL_IF_NOT(sb->sbb_size == 4);
1467  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1468 
1469  StreamingBufferSegment seg5;
1470  FAIL_IF(StreamingBufferInsertAt(sb, &seg5, (const uint8_t *)"ABCDEFGHIJ", 10, 0) != 0);
1471  Dump(sb);
1472  StreamingBufferBlock *sbb1 = RB_MIN(SBB, &sb->sbb_tree);
1473  FAIL_IF_NULL(sbb1);
1474  FAIL_IF(sbb1->offset != 0);
1475  FAIL_IF(sbb1->len != 10);
1476  FAIL_IF(SBB_RB_NEXT(sbb1));
1477  FAIL_IF_NULL(sb->head);
1478  FAIL_IF_NOT(sb->sbb_size == 10);
1479  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1480 
1481  StreamingBufferSegment seg6;
1482  FAIL_IF(StreamingBufferInsertAt(sb, &seg6, (const uint8_t *)"abcdefghij", 10, 0) != 0);
1483  Dump(sb);
1484  sbb1 = RB_MIN(SBB, &sb->sbb_tree);
1485  FAIL_IF_NULL(sbb1);
1486  FAIL_IF(sbb1->offset != 0);
1487  FAIL_IF(sbb1->len != 10);
1488  FAIL_IF(SBB_RB_NEXT(sbb1));
1489  FAIL_IF_NULL(sb->head);
1490  FAIL_IF_NOT(sb->sbb_size == 10);
1491  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1492 
1493  StreamingBufferFree(sb);
1494  PASS;
1495 }
1496 
1497 /** \test lots of gaps in block list */
1498 static int StreamingBufferTest10(void)
1499 {
1500  StreamingBufferConfig cfg = { 0, 8, 16, NULL, NULL, NULL, NULL };
1502  FAIL_IF(sb == NULL);
1503 
1504  StreamingBufferSegment seg1;
1505  FAIL_IF(StreamingBufferInsertAt(sb, &seg1, (const uint8_t *)"A", 1, 0) != 0);
1506  Dump(sb);
1507  StreamingBufferSegment seg2;
1508  FAIL_IF(StreamingBufferInsertAt(sb, &seg2, (const uint8_t *)"D", 1, 3) != 0);
1509  Dump(sb);
1510  StreamingBufferSegment seg3;
1511  FAIL_IF(StreamingBufferInsertAt(sb, &seg3, (const uint8_t *)"H", 1, 7) != 0);
1512  Dump(sb);
1513  FAIL_IF_NULL(sb->head);
1514  FAIL_IF_NOT(sb->sbb_size == 3);
1515 
1516  StreamingBufferSegment seg4;
1517  FAIL_IF(StreamingBufferInsertAt(sb, &seg4, (const uint8_t *)"B", 1, 1) != 0);
1518  Dump(sb);
1519  StreamingBufferSegment seg5;
1520  FAIL_IF(StreamingBufferInsertAt(sb, &seg5, (const uint8_t *)"C", 1, 2) != 0);
1521  Dump(sb);
1522  StreamingBufferSegment seg6;
1523  FAIL_IF(StreamingBufferInsertAt(sb, &seg6, (const uint8_t *)"G", 1, 6) != 0);
1524  Dump(sb);
1525  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1526  FAIL_IF_NULL(sb->head);
1527  FAIL_IF_NOT(sb->sbb_size == 6);
1528 
1529  StreamingBufferSegment seg7;
1530  FAIL_IF(StreamingBufferInsertAt(sb, &seg7, (const uint8_t *)"ABCDEFGHIJ", 10, 0) != 0);
1531  Dump(sb);
1532  StreamingBufferBlock *sbb1 = RB_MIN(SBB, &sb->sbb_tree);
1533  FAIL_IF_NULL(sbb1);
1534  FAIL_IF(sbb1->offset != 0);
1535  FAIL_IF(sbb1->len != 10);
1536  FAIL_IF(SBB_RB_NEXT(sbb1));
1537  FAIL_IF_NULL(sb->head);
1538  FAIL_IF_NOT(sb->sbb_size == 10);
1539 
1540  StreamingBufferSegment seg8;
1541  FAIL_IF(StreamingBufferInsertAt(sb, &seg8, (const uint8_t *)"abcdefghij", 10, 0) != 0);
1542  Dump(sb);
1543  sbb1 = RB_MIN(SBB, &sb->sbb_tree);
1544  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1545  FAIL_IF_NULL(sbb1);
1546  FAIL_IF(sbb1->offset != 0);
1547  FAIL_IF(sbb1->len != 10);
1548  FAIL_IF(SBB_RB_NEXT(sbb1));
1549  FAIL_IF_NULL(sb->head);
1550  FAIL_IF_NOT(sb->sbb_size == 10);
1551 
1552  StreamingBufferFree(sb);
1553  PASS;
1554 }
1555 
1556 #endif
1557 
1559 {
1560 #ifdef UNITTESTS
1561  UtRegisterTest("StreamingBufferTest01", StreamingBufferTest01);
1562  UtRegisterTest("StreamingBufferTest02", StreamingBufferTest02);
1563  UtRegisterTest("StreamingBufferTest03", StreamingBufferTest03);
1564  UtRegisterTest("StreamingBufferTest04", StreamingBufferTest04);
1565  UtRegisterTest("StreamingBufferTest05", StreamingBufferTest05);
1566  UtRegisterTest("StreamingBufferTest06", StreamingBufferTest06);
1567  UtRegisterTest("StreamingBufferTest07", StreamingBufferTest07);
1568  UtRegisterTest("StreamingBufferTest08", StreamingBufferTest08);
1569  UtRegisterTest("StreamingBufferTest09", StreamingBufferTest09);
1570  UtRegisterTest("StreamingBufferTest10", StreamingBufferTest10);
1571 #endif
1572 }
FREE
#define FREE(cfg, ptr, s)
Definition: util-streaming-buffer.c:40
StreamingBuffer_::stream_offset
uint64_t stream_offset
Definition: util-streaming-buffer.h:97
len
uint8_t len
Definition: app-layer-dnp3.h:2
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
StreamingBuffer_::buf_offset
uint32_t buf_offset
Definition: util-streaming-buffer.h:101
StreamingBufferFree
void StreamingBufferFree(StreamingBuffer *sb)
Definition: util-streaming-buffer.c:145
StreamingBufferConfig_::buf_size
uint32_t buf_size
Definition: util-streaming-buffer.h:70
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
StreamingBuffer_::head
StreamingBufferBlock * head
Definition: util-streaming-buffer.h:104
StreamingBufferAppendNoTrack
int StreamingBufferAppendNoTrack(StreamingBuffer *sb, const uint8_t *data, uint32_t data_len)
add data w/o tracking a segment
Definition: util-streaming-buffer.c:633
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:298
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
StreamingBuffer_::buf
uint8_t * buf
Definition: util-streaming-buffer.h:99
RB_LEFT
#define RB_LEFT(elm, field)
Definition: tree.h:322
StreamingBuffer_::buf_size
uint32_t buf_size
Definition: util-streaming-buffer.h:100
StreamingBufferGetData
int StreamingBufferGetData(const StreamingBuffer *sb, const uint8_t **data, uint32_t *data_len, uint64_t *stream_offset)
Definition: util-streaming-buffer.c:863
RB_MIN
#define RB_MIN(name, x)
Definition: tree.h:778
StreamingBufferConfig_::flags
uint32_t flags
Definition: util-streaming-buffer.h:68
segment_len
uint32_t segment_len
Definition: util-streaming-buffer.h:0
StreamingBufferGetDataAtOffset
int StreamingBufferGetDataAtOffset(const StreamingBuffer *sb, const uint8_t **data, uint32_t *data_len, uint64_t offset)
Definition: util-streaming-buffer.c:880
StreamingBufferSegmentCompareRawData
int StreamingBufferSegmentCompareRawData(const StreamingBuffer *sb, const StreamingBufferSegment *seg, const uint8_t *rawdata, uint32_t rawdata_len)
Definition: util-streaming-buffer.c:847
stream_offset
uint64_t stream_offset
Definition: util-streaming-buffer.h:1
util-unittest.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression to true.
Definition: util-unittest.h:82
StreamingBufferClear
void StreamingBufferClear(StreamingBuffer *sb)
Definition: util-streaming-buffer.c:132
RB_EMPTY
#define RB_EMPTY(head)
Definition: tree.h:327
FAIL_IF_NOT_NULL
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
Definition: util-unittest.h:96
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
RB_ROOT
#define RB_ROOT(head)
Definition: tree.h:326
StreamingBufferInit
StreamingBuffer * StreamingBufferInit(const StreamingBufferConfig *cfg)
Definition: util-streaming-buffer.c:112
StreamingBufferSegmentIsBeforeWindow
int StreamingBufferSegmentIsBeforeWindow(const StreamingBuffer *sb, const StreamingBufferSegment *seg)
Definition: util-streaming-buffer.c:745
REALLOC
#define REALLOC(cfg, ptr, orig_s, s)
Definition: util-streaming-buffer.c:38
res
PoolThreadReserved res
Definition: stream-tcp-private.h:0
CALLOC
#define CALLOC(cfg, n, s)
Definition: util-streaming-buffer.c:36
util-print.h
RB_FOREACH_SAFE
#define RB_FOREACH_SAFE(x, name, head, y)
Definition: tree.h:791
PrintRawDataFp
void PrintRawDataFp(FILE *fp, const uint8_t *buf, uint32_t buflen)
Definition: util-print.c:141
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:277
RB_FOREACH
#define RB_FOREACH(x, name, head)
Definition: tree.h:781
StreamingBuffer_::sbb_size
uint32_t sbb_size
Definition: util-streaming-buffer.h:105
StreamingBufferCompareRawData
int StreamingBufferCompareRawData(const StreamingBuffer *sb, const uint8_t *rawdata, uint32_t rawdata_len)
Definition: util-streaming-buffer.c:903
RB_GENERATE
RB_GENERATE(SBB, StreamingBufferBlock, rb, SBBCompare)
SBB_RB_FIND_INCLUSIVE
StreamingBufferBlock * SBB_RB_FIND_INCLUSIVE(struct SBB *head, StreamingBufferBlock *elm)
Definition: util-streaming-buffer.c:79
StreamingBuffer_::sbb_tree
struct SBB sbb_tree
Definition: util-streaming-buffer.h:103
StreamingBuffer_
Definition: util-streaming-buffer.h:95
StreamingBufferSBBGetDataAtOffset
void StreamingBufferSBBGetDataAtOffset(const StreamingBuffer *sb, const StreamingBufferBlock *sbb, const uint8_t **data, uint32_t *data_len, uint64_t offset)
get the data for one SBB
Definition: util-streaming-buffer.c:783
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:71
suricata-common.h
util-streaming-buffer.h
StreamingBuffer_::cfg
const StreamingBufferConfig * cfg
Definition: util-streaming-buffer.h:96
util-validate.h
StreamingBufferConfig_
Definition: util-streaming-buffer.h:67
StreamingBufferSlideToOffset
void StreamingBufferSlideToOffset(StreamingBuffer *sb, uint64_t offset)
slide to absolute offset
Definition: util-streaming-buffer.c:521
RB_RIGHT
#define RB_RIGHT(elm, field)
Definition: tree.h:323
head
Flow * head
Definition: flow-hash.h:1
SCFree
#define SCFree(p)
Definition: util-mem.h:61
STREAMING_BUFFER_INITIALIZER
#define STREAMING_BUFFER_INITIALIZER(cfg)
Definition: util-streaming-buffer.h:112
StreamingBufferAppendRaw
StreamingBufferSegment * StreamingBufferAppendRaw(StreamingBuffer *sb, const uint8_t *data, uint32_t data_len)
Definition: util-streaming-buffer.c:549
StreamingBufferSlide
void StreamingBufferSlide(StreamingBuffer *sb, uint32_t slide)
Definition: util-streaming-buffer.c:536
DATA_FITS_AT_OFFSET
#define DATA_FITS_AT_OFFSET(sb, len, offset)
Definition: util-streaming-buffer.c:669
StreamingBufferInsertAt
int StreamingBufferInsertAt(StreamingBuffer *sb, StreamingBufferSegment *seg, const uint8_t *data, uint32_t data_len, uint64_t offset)
Definition: util-streaming-buffer.c:675
RB_FOREACH_REVERSE_FROM
#define RB_FOREACH_REVERSE_FROM(x, name, y)
Definition: tree.h:801
SBBCompare
int SBBCompare(struct StreamingBufferBlock *a, struct StreamingBufferBlock *b)
Definition: util-streaming-buffer.c:47
likely
#define likely(expr)
Definition: util-optimize.h:32
StreamingBufferAppend
int StreamingBufferAppend(StreamingBuffer *sb, StreamingBufferSegment *seg, const uint8_t *data, uint32_t data_len)
Definition: util-streaming-buffer.c:590
RB_FOREACH_FROM
#define RB_FOREACH_FROM(x, name, y)
Definition: tree.h:786
StreamingBufferSegmentGetData
void StreamingBufferSegmentGetData(const StreamingBuffer *sb, const StreamingBufferSegment *seg, const uint8_t **data, uint32_t *data_len)
Definition: util-streaming-buffer.c:816
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:304
StreamingBufferBlock::len
uint32_t len
Definition: util-streaming-buffer.h:85
StreamingBufferBlock::offset
uint64_t offset
Definition: util-streaming-buffer.h:83
StreamingBufferSBBGetData
void StreamingBufferSBBGetData(const StreamingBuffer *sb, const StreamingBufferBlock *sbb, const uint8_t **data, uint32_t *data_len)
get the data for one SBB
Definition: util-streaming-buffer.c:757
DATA_FITS
#define DATA_FITS(sb, len)
Definition: util-streaming-buffer.c:546
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:111
StreamingBufferBlock
block of continues data
Definition: util-streaming-buffer.h:82
STREAMING_BUFFER_AUTOSLIDE
#define STREAMING_BUFFER_AUTOSLIDE
Definition: util-streaming-buffer.h:65
StreamingBufferConfig_::buf_slide
uint32_t buf_slide
Definition: util-streaming-buffer.h:69
WARN_UNUSED
#define WARN_UNUSED
Definition: suricata-common.h:384
StreamingBufferRegisterTests
void StreamingBufferRegisterTests(void)
Definition: util-streaming-buffer.c:1558