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  * \return 0 in case of success
676  * \return -1 on memory allocation errors
677  * \return negative value on other errors
678  */
679 int StreamingBufferInsertAt(StreamingBuffer *sb, StreamingBufferSegment *seg,
680  const uint8_t *data, uint32_t data_len,
681  uint64_t offset)
682 {
683  BUG_ON(seg == NULL);
684 
685  if (offset < sb->stream_offset)
686  return -2;
687 
688  if (sb->buf == NULL) {
689  if (InitBuffer(sb) == -1)
690  return -1;
691  }
692 
693  uint32_t rel_offset = offset - sb->stream_offset;
694  if (!DATA_FITS_AT_OFFSET(sb, data_len, rel_offset)) {
695  if (sb->cfg->flags & STREAMING_BUFFER_AUTOSLIDE) {
696  AutoSlide(sb);
697  rel_offset = offset - sb->stream_offset;
698  }
699  if (!DATA_FITS_AT_OFFSET(sb, data_len, rel_offset)) {
700  if (GrowToSize(sb, (rel_offset + data_len)) != 0)
701  return -1;
702  }
703  }
704  if (!DATA_FITS_AT_OFFSET(sb, data_len, rel_offset)) {
705  return -2;
706  }
707 
708  memcpy(sb->buf + rel_offset, data, data_len);
709  seg->stream_offset = offset;
710  seg->segment_len = data_len;
711 
712  SCLogDebug("rel_offset %u sb->stream_offset %"PRIu64", buf_offset %u",
713  rel_offset, sb->stream_offset, sb->buf_offset);
714 
715  if (RB_EMPTY(&sb->sbb_tree)) {
716  SCLogDebug("empty sbb list");
717 
718  if (sb->stream_offset == offset) {
719  SCLogDebug("empty sbb list: block exactly what was expected, fall through");
720  /* empty list, data is exactly what is expected (append),
721  * so do nothing */
722  } else if ((rel_offset + data_len) <= sb->buf_offset) {
723  SCLogDebug("empty sbb list: block is within existing region");
724  } else {
725  if (sb->buf_offset && rel_offset == sb->buf_offset) {
726  // nothing to do
727  } else if (rel_offset < sb->buf_offset) {
728  // nothing to do
729  } else if (sb->buf_offset) {
730  /* existing data, but there is a gap between us */
731  SBBInit(sb, rel_offset, data_len);
732  } else {
733  /* gap before data in empty list */
734  SCLogDebug("empty sbb list: invoking SBBInitLeadingGap");
735  SBBInitLeadingGap(sb, offset, data_len);
736  }
737  }
738  } else {
739  /* already have blocks, so append new block based on new data */
740  SBBUpdate(sb, rel_offset, data_len);
741  }
742 
743  if (rel_offset + data_len > sb->buf_offset)
744  sb->buf_offset = rel_offset + data_len;
745 
746  return 0;
747 }
748 
750  const StreamingBufferSegment *seg)
751 {
752  if (seg->stream_offset < sb->stream_offset) {
753  if (seg->stream_offset + seg->segment_len <= sb->stream_offset) {
754  return 1;
755  }
756  }
757  return 0;
758 }
759 
760 /** \brief get the data for one SBB */
762  const StreamingBufferBlock *sbb,
763  const uint8_t **data, uint32_t *data_len)
764 {
765  if (sbb->offset >= sb->stream_offset) {
766  uint64_t offset = sbb->offset - sb->stream_offset;
767  *data = sb->buf + offset;
768  if (offset + sbb->len > sb->buf_offset)
769  *data_len = sb->buf_offset - offset;
770  else
771  *data_len = sbb->len;
772  return;
773  } else {
774  uint64_t offset = sb->stream_offset - sbb->offset;
775  if (offset < sbb->len) {
776  *data = sb->buf;
777  *data_len = sbb->len - offset;
778  return;
779  }
780  }
781  *data = NULL;
782  *data_len = 0;
783  return;
784 }
785 
786 /** \brief get the data for one SBB */
788  const StreamingBufferBlock *sbb,
789  const uint8_t **data, uint32_t *data_len,
790  uint64_t offset)
791 {
792  if (offset >= sbb->offset && offset < (sbb->offset + sbb->len)) {
793  uint32_t sbblen = sbb->len - (offset - sbb->offset);
794 
795  if (offset >= sb->stream_offset) {
796  uint64_t data_offset = offset - sb->stream_offset;
797  *data = sb->buf + data_offset;
798  if (data_offset + sbblen > sb->buf_size)
799  *data_len = sb->buf_size - data_offset;
800  else
801  *data_len = sbblen;
802  BUG_ON(*data_len > sbblen);
803  return;
804  } else {
805  uint64_t data_offset = sb->stream_offset - sbb->offset;
806  if (data_offset < sbblen) {
807  *data = sb->buf;
808  *data_len = sbblen - data_offset;
809  BUG_ON(*data_len > sbblen);
810  return;
811  }
812  }
813  }
814 
815  *data = NULL;
816  *data_len = 0;
817  return;
818 }
819 
821  const StreamingBufferSegment *seg,
822  const uint8_t **data, uint32_t *data_len)
823 {
824  if (likely(sb->buf)) {
825  if (seg->stream_offset >= sb->stream_offset) {
826  uint64_t offset = seg->stream_offset - sb->stream_offset;
827  *data = sb->buf + offset;
828  if (offset + seg->segment_len > sb->buf_size)
829  *data_len = sb->buf_size - offset;
830  else
831  *data_len = seg->segment_len;
832  return;
833  } else {
834  uint64_t offset = sb->stream_offset - seg->stream_offset;
835  if (offset < seg->segment_len) {
836  *data = sb->buf;
837  *data_len = seg->segment_len - offset;
838  return;
839  }
840  }
841  }
842  *data = NULL;
843  *data_len = 0;
844  return;
845 }
846 
847 /**
848  * \retval 1 data is the same
849  * \retval 0 data is different
850  */
852  const StreamingBufferSegment *seg,
853  const uint8_t *rawdata, uint32_t rawdata_len)
854 {
855  const uint8_t *segdata = NULL;
856  uint32_t segdata_len = 0;
857  StreamingBufferSegmentGetData(sb, seg, &segdata, &segdata_len);
858  if (segdata && segdata_len &&
859  segdata_len == rawdata_len &&
860  memcmp(segdata, rawdata, segdata_len) == 0)
861  {
862  return 1;
863  }
864  return 0;
865 }
866 
868  const uint8_t **data, uint32_t *data_len,
869  uint64_t *stream_offset)
870 {
871  if (sb != NULL && sb->buf != NULL) {
872  *data = sb->buf;
873  *data_len = sb->buf_offset;
875  return 1;
876  } else {
877  *data = NULL;
878  *data_len = 0;
879  *stream_offset = 0;
880  return 0;
881  }
882 }
883 
885  const uint8_t **data, uint32_t *data_len,
886  uint64_t offset)
887 {
888  if (sb != NULL && sb->buf != NULL &&
889  offset >= sb->stream_offset &&
890  offset < (sb->stream_offset + sb->buf_offset))
891  {
892  uint32_t skip = offset - sb->stream_offset;
893  *data = sb->buf + skip;
894  *data_len = sb->buf_offset - skip;
895  return 1;
896  } else {
897  *data = NULL;
898  *data_len = 0;
899  return 0;
900  }
901 }
902 
903 /**
904  * \retval 1 data is the same
905  * \retval 0 data is different
906  */
908  const uint8_t *rawdata, uint32_t rawdata_len)
909 {
910  const uint8_t *sbdata = NULL;
911  uint32_t sbdata_len = 0;
912  uint64_t offset = 0;
913  StreamingBufferGetData(sb, &sbdata, &sbdata_len, &offset);
914  if (offset == 0 &&
915  sbdata && sbdata_len &&
916  sbdata_len == rawdata_len &&
917  memcmp(sbdata, rawdata, sbdata_len) == 0)
918  {
919  return 1;
920  }
921  SCLogDebug("sbdata_len %u, offset %"PRIu64, sbdata_len, offset);
922  printf("got:\n");
923  PrintRawDataFp(stdout, sbdata,sbdata_len);
924  printf("wanted:\n");
925  PrintRawDataFp(stdout, rawdata,rawdata_len);
926  return 0;
927 }
928 
929 #ifdef UNITTESTS
930 static void Dump(StreamingBuffer *sb)
931 {
932  PrintRawDataFp(stdout, sb->buf, sb->buf_offset);
933 }
934 
935 static void DumpSegment(StreamingBuffer *sb, StreamingBufferSegment *seg)
936 {
937  const uint8_t *data = NULL;
938  uint32_t data_len = 0;
939  StreamingBufferSegmentGetData(sb, seg, &data, &data_len);
940  if (data && data_len) {
941  PrintRawDataFp(stdout, data, data_len);
942  }
943 }
944 
945 static int StreamingBufferTest01(void)
946 {
947  StreamingBufferConfig cfg = { STREAMING_BUFFER_AUTOSLIDE, 8, 16, NULL, NULL, NULL, NULL };
949  FAIL_IF(sb == NULL);
950 
951  StreamingBufferSegment *seg1 = StreamingBufferAppendRaw(sb, (const uint8_t *)"ABCDEFGH", 8);
952  StreamingBufferSegment *seg2 = StreamingBufferAppendRaw(sb, (const uint8_t *)"01234567", 8);
953  FAIL_IF(sb->stream_offset != 0);
954  FAIL_IF(sb->buf_offset != 16);
955  FAIL_IF(seg1->stream_offset != 0);
956  FAIL_IF(seg2->stream_offset != 8);
959  FAIL_IF(!StreamingBufferSegmentCompareRawData(sb,seg1,(const uint8_t *)"ABCDEFGH", 8));
960  FAIL_IF(!StreamingBufferSegmentCompareRawData(sb,seg2,(const uint8_t *)"01234567", 8));
961  Dump(sb);
962  FAIL_IF_NOT_NULL(sb->head);
963  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
964 
965  StreamingBufferSegment *seg3 = StreamingBufferAppendRaw(sb, (const uint8_t *)"QWERTY", 6);
966  FAIL_IF(sb->stream_offset != 8);
967  FAIL_IF(sb->buf_offset != 14);
968  FAIL_IF(seg3->stream_offset != 16);
972  FAIL_IF(!StreamingBufferSegmentCompareRawData(sb,seg3,(const uint8_t *)"QWERTY", 6));
973  Dump(sb);
974  FAIL_IF_NOT_NULL(sb->head);
975  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
976 
977  StreamingBufferSegment *seg4 = StreamingBufferAppendRaw(sb, (const uint8_t *)"KLM", 3);
978  FAIL_IF(sb->stream_offset != 14);
979  FAIL_IF(sb->buf_offset != 11);
980  FAIL_IF(seg4->stream_offset != 22);
985  FAIL_IF(!StreamingBufferSegmentCompareRawData(sb,seg4,(const uint8_t *)"KLM", 3));
986  Dump(sb);
987  FAIL_IF_NOT_NULL(sb->head);
988  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
989 
990  StreamingBufferSegment *seg5 = StreamingBufferAppendRaw(sb, (const uint8_t *)"!@#$%^&*()_+<>?/,.;:'[]{}-=", 27);
991  FAIL_IF(sb->stream_offset != 17);
992  FAIL_IF(sb->buf_offset != 35);
993  FAIL_IF(seg5->stream_offset != 25);
999  FAIL_IF(!StreamingBufferSegmentCompareRawData(sb,seg5,(const uint8_t *)"!@#$%^&*()_+<>?/,.;:'[]{}-=", 27));
1000  Dump(sb);
1001  FAIL_IF_NOT_NULL(sb->head);
1002  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1003 
1004  StreamingBufferSegment *seg6 = StreamingBufferAppendRaw(sb, (const uint8_t *)"UVWXYZ", 6);
1005  FAIL_IF(sb->stream_offset != 17);
1006  FAIL_IF(sb->buf_offset != 41);
1007  FAIL_IF(seg6->stream_offset != 52);
1014  FAIL_IF(!StreamingBufferSegmentCompareRawData(sb,seg6,(const uint8_t *)"UVWXYZ", 6));
1015  Dump(sb);
1016  FAIL_IF_NOT_NULL(sb->head);
1017  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1018 
1019  SCFree(seg1);
1020  SCFree(seg2);
1021  SCFree(seg3);
1022  SCFree(seg4);
1023  SCFree(seg5);
1024  SCFree(seg6);
1025  StreamingBufferFree(sb);
1026  PASS;
1027 }
1028 
1029 static int StreamingBufferTest02(void)
1030 {
1031  StreamingBufferConfig cfg = { 0, 8, 24, NULL, NULL, NULL, NULL };
1033  FAIL_IF(sb == NULL);
1034 
1035  StreamingBufferSegment seg1;
1036  FAIL_IF(StreamingBufferAppend(sb, &seg1, (const uint8_t *)"ABCDEFGH", 8) != 0);
1037  StreamingBufferSegment seg2;
1038  FAIL_IF(StreamingBufferAppend(sb, &seg2, (const uint8_t *)"01234567", 8) != 0);
1039  FAIL_IF(sb->stream_offset != 0);
1040  FAIL_IF(sb->buf_offset != 16);
1041  FAIL_IF(seg1.stream_offset != 0);
1042  FAIL_IF(seg2.stream_offset != 8);
1045  Dump(sb);
1046  DumpSegment(sb, &seg1);
1047  DumpSegment(sb, &seg2);
1048  FAIL_IF_NOT_NULL(sb->head);
1049  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1050 
1051  StreamingBufferSlide(sb, 6);
1052  FAIL_IF_NOT_NULL(sb->head);
1053  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1054 
1055  StreamingBufferSegment seg3;
1056  FAIL_IF(StreamingBufferAppend(sb, &seg3, (const uint8_t *)"QWERTY", 6) != 0);
1057  FAIL_IF(sb->stream_offset != 6);
1058  FAIL_IF(sb->buf_offset != 16);
1059  FAIL_IF(seg3.stream_offset != 16);
1063  Dump(sb);
1064  DumpSegment(sb, &seg1);
1065  DumpSegment(sb, &seg2);
1066  DumpSegment(sb, &seg3);
1067  FAIL_IF_NOT_NULL(sb->head);
1068  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1069 
1070  StreamingBufferSlide(sb, 6);
1074  Dump(sb);
1075  DumpSegment(sb, &seg1);
1076  DumpSegment(sb, &seg2);
1077  DumpSegment(sb, &seg3);
1078  FAIL_IF_NOT_NULL(sb->head);
1079  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1080 
1081  StreamingBufferFree(sb);
1082  PASS;
1083 }
1084 
1085 static int StreamingBufferTest03(void)
1086 {
1087  StreamingBufferConfig cfg = { 0, 8, 24, NULL, NULL, NULL, NULL };
1089  FAIL_IF(sb == NULL);
1090 
1091  StreamingBufferSegment seg1;
1092  FAIL_IF(StreamingBufferAppend(sb, &seg1, (const uint8_t *)"ABCDEFGH", 8) != 0);
1093  StreamingBufferSegment seg2;
1094  FAIL_IF(StreamingBufferInsertAt(sb, &seg2, (const uint8_t *)"01234567", 8, 14) != 0);
1095  FAIL_IF(sb->stream_offset != 0);
1096  FAIL_IF(sb->buf_offset != 22);
1097  FAIL_IF(seg1.stream_offset != 0);
1098  FAIL_IF(seg2.stream_offset != 14);
1101  Dump(sb);
1102  DumpSegment(sb, &seg1);
1103  DumpSegment(sb, &seg2);
1104  FAIL_IF_NULL(sb->head);
1105  FAIL_IF_NOT(sb->sbb_size == 16);
1106  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1107 
1108  StreamingBufferSegment seg3;
1109  FAIL_IF(StreamingBufferInsertAt(sb, &seg3, (const uint8_t *)"QWERTY", 6, 8) != 0);
1110  FAIL_IF(sb->stream_offset != 0);
1111  FAIL_IF(sb->buf_offset != 22);
1112  FAIL_IF(seg3.stream_offset != 8);
1116  Dump(sb);
1117  DumpSegment(sb, &seg1);
1118  DumpSegment(sb, &seg2);
1119  DumpSegment(sb, &seg3);
1120  FAIL_IF_NULL(sb->head);
1121  FAIL_IF_NOT(sb->sbb_size == 22);
1122  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1123 
1124  StreamingBufferSlide(sb, 10);
1128  Dump(sb);
1129  DumpSegment(sb, &seg1);
1130  DumpSegment(sb, &seg2);
1131  DumpSegment(sb, &seg3);
1132  FAIL_IF_NULL(sb->head);
1133  FAIL_IF_NOT(sb->sbb_size == 12);
1134  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1135 
1136  StreamingBufferFree(sb);
1137  PASS;
1138 }
1139 
1140 static int StreamingBufferTest04(void)
1141 {
1142  StreamingBufferConfig cfg = { 0, 8, 16, NULL, NULL, NULL, NULL };
1144  FAIL_IF(sb == NULL);
1145 
1146  StreamingBufferSegment seg1;
1147  FAIL_IF(StreamingBufferAppend(sb, &seg1, (const uint8_t *)"ABCDEFGH", 8) != 0);
1148  FAIL_IF(!RB_EMPTY(&sb->sbb_tree));
1149  StreamingBufferSegment seg2;
1150  FAIL_IF(StreamingBufferInsertAt(sb, &seg2, (const uint8_t *)"01234567", 8, 14) != 0);
1151  FAIL_IF(sb->stream_offset != 0);
1152  FAIL_IF(sb->buf_offset != 22);
1153  FAIL_IF(seg1.stream_offset != 0);
1154  FAIL_IF(seg2.stream_offset != 14);
1157  FAIL_IF(RB_EMPTY(&sb->sbb_tree));
1158  StreamingBufferBlock *sbb1 = RB_MIN(SBB, &sb->sbb_tree);
1159  FAIL_IF(sbb1 != sb->head);
1160  FAIL_IF_NULL(sbb1);
1161  FAIL_IF(sbb1->offset != 0);
1162  FAIL_IF(sbb1->len != 8);
1163  StreamingBufferBlock *sbb2 = SBB_RB_NEXT(sbb1);
1164  FAIL_IF_NULL(sbb2);
1165  FAIL_IF(sbb2 == sb->head);
1166  FAIL_IF(sbb2->offset != 14);
1167  FAIL_IF(sbb2->len != 8);
1168  Dump(sb);
1169  DumpSegment(sb, &seg1);
1170  DumpSegment(sb, &seg2);
1171  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1172 
1173  StreamingBufferSegment seg3;
1174  FAIL_IF(StreamingBufferInsertAt(sb, &seg3, (const uint8_t *)"QWERTY", 6, 8) != 0);
1175  FAIL_IF(sb->stream_offset != 0);
1176  FAIL_IF(sb->buf_offset != 22);
1177  FAIL_IF(seg3.stream_offset != 8);
1181  sbb1 = RB_MIN(SBB, &sb->sbb_tree);
1182  FAIL_IF_NULL(sbb1);
1183  FAIL_IF(sbb1 != sb->head);
1184  FAIL_IF(sbb1->offset != 0);
1185  FAIL_IF(sbb1->len != 22);
1186  FAIL_IF(SBB_RB_NEXT(sbb1));
1187  Dump(sb);
1188  DumpSegment(sb, &seg1);
1189  DumpSegment(sb, &seg2);
1190  DumpSegment(sb, &seg3);
1191  FAIL_IF_NULL(sb->head);
1192  FAIL_IF_NOT(sb->sbb_size == 22);
1193  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1194 
1195  /* far ahead of curve: */
1196  StreamingBufferSegment seg4;
1197  FAIL_IF(StreamingBufferInsertAt(sb, &seg4, (const uint8_t *)"XYZ", 3, 124) != 0);
1198  FAIL_IF(sb->stream_offset != 0);
1199  FAIL_IF(sb->buf_offset != 127);
1200  FAIL_IF(sb->buf_size != 128);
1201  FAIL_IF(seg4.stream_offset != 124);
1206  sbb1 = RB_MIN(SBB, &sb->sbb_tree);
1207  FAIL_IF_NULL(sbb1);
1208  FAIL_IF(sbb1 != sb->head);
1209  FAIL_IF(sbb1->offset != 0);
1210  FAIL_IF(sbb1->len != 22);
1211  FAIL_IF(!SBB_RB_NEXT(sbb1));
1212  Dump(sb);
1213  DumpSegment(sb, &seg1);
1214  DumpSegment(sb, &seg2);
1215  DumpSegment(sb, &seg3);
1216  DumpSegment(sb, &seg4);
1217  FAIL_IF_NULL(sb->head);
1218  FAIL_IF_NOT(sb->sbb_size == 25);
1219  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1220 
1221  FAIL_IF(!StreamingBufferSegmentCompareRawData(sb,&seg1,(const uint8_t *)"ABCDEFGH", 8));
1222  FAIL_IF(!StreamingBufferSegmentCompareRawData(sb,&seg2,(const uint8_t *)"01234567", 8));
1223  FAIL_IF(!StreamingBufferSegmentCompareRawData(sb,&seg3,(const uint8_t *)"QWERTY", 6));
1224  FAIL_IF(!StreamingBufferSegmentCompareRawData(sb,&seg4,(const uint8_t *)"XYZ", 3));
1225 
1226  StreamingBufferFree(sb);
1227  PASS;
1228 }
1229 
1230 static int StreamingBufferTest05(void)
1231 {
1232  StreamingBufferConfig cfg = { STREAMING_BUFFER_AUTOSLIDE, 8, 32, NULL, NULL, NULL, NULL };
1234 
1235  StreamingBufferSegment *seg1 = StreamingBufferAppendRaw(&sb, (const uint8_t *)"AAAAAAAA", 8);
1236  StreamingBufferSegment *seg2 = StreamingBufferAppendRaw(&sb, (const uint8_t *)"BBBBBBBB", 8);
1237  StreamingBufferSegment *seg3 = StreamingBufferAppendRaw(&sb, (const uint8_t *)"CCCCCCCC", 8);
1238  StreamingBufferSegment *seg4 = StreamingBufferAppendRaw(&sb, (const uint8_t *)"DDDDDDDD", 8);
1239  FAIL_IF(sb.stream_offset != 0);
1240  FAIL_IF(sb.buf_offset != 32);
1241  FAIL_IF(seg1->stream_offset != 0);
1242  FAIL_IF(seg2->stream_offset != 8);
1243  FAIL_IF(seg3->stream_offset != 16);
1244  FAIL_IF(seg4->stream_offset != 24);
1249  FAIL_IF(!StreamingBufferSegmentCompareRawData(&sb,seg1,(const uint8_t *)"AAAAAAAA", 8));
1250  FAIL_IF(!StreamingBufferSegmentCompareRawData(&sb,seg2,(const uint8_t *)"BBBBBBBB", 8));
1251  FAIL_IF(!StreamingBufferSegmentCompareRawData(&sb,seg3,(const uint8_t *)"CCCCCCCC", 8));
1252  FAIL_IF(!StreamingBufferSegmentCompareRawData(&sb,seg4,(const uint8_t *)"DDDDDDDD", 8));
1253  Dump(&sb);
1254  FAIL_IF_NOT(sb.head == RB_MIN(SBB, &sb.sbb_tree));
1255  StreamingBufferSegment *seg5 = StreamingBufferAppendRaw(&sb, (const uint8_t *)"EEEEEEEE", 8);
1256  FAIL_IF(!StreamingBufferSegmentCompareRawData(&sb,seg5,(const uint8_t *)"EEEEEEEE", 8));
1257  Dump(&sb);
1258  FAIL_IF_NOT(sb.head == RB_MIN(SBB, &sb.sbb_tree));
1259 
1260  SCFree(seg1);
1261  SCFree(seg2);
1262  SCFree(seg3);
1263  SCFree(seg4);
1264  SCFree(seg5);
1265  StreamingBufferClear(&sb);
1266  PASS;
1267 }
1268 
1269 /** \test lots of gaps in block list */
1270 static int StreamingBufferTest06(void)
1271 {
1272  StreamingBufferConfig cfg = { 0, 8, 16, NULL, NULL, NULL, NULL };
1274  FAIL_IF(sb == NULL);
1275 
1276  StreamingBufferSegment seg1;
1277  FAIL_IF(StreamingBufferAppend(sb, &seg1, (const uint8_t *)"A", 1) != 0);
1278  StreamingBufferSegment seg2;
1279  FAIL_IF(StreamingBufferInsertAt(sb, &seg2, (const uint8_t *)"C", 1, 2) != 0);
1280  Dump(sb);
1281  FAIL_IF_NULL(sb->head);
1282  FAIL_IF_NOT(sb->sbb_size == 2);
1283  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1284 
1285  StreamingBufferSegment seg3;
1286  FAIL_IF(StreamingBufferInsertAt(sb, &seg3, (const uint8_t *)"F", 1, 5) != 0);
1287  Dump(sb);
1288  FAIL_IF_NULL(sb->head);
1289  FAIL_IF_NOT(sb->sbb_size == 3);
1290  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1291 
1292  StreamingBufferSegment seg4;
1293  FAIL_IF(StreamingBufferInsertAt(sb, &seg4, (const uint8_t *)"H", 1, 7) != 0);
1294  Dump(sb);
1295  FAIL_IF_NULL(sb->head);
1296  FAIL_IF_NOT(sb->sbb_size == 4);
1297  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1298 
1299  StreamingBufferSegment seg5;
1300  FAIL_IF(StreamingBufferInsertAt(sb, &seg5, (const uint8_t *)"ABCDEFGHIJ", 10, 0) != 0);
1301  Dump(sb);
1302  StreamingBufferBlock *sbb1 = RB_MIN(SBB, &sb->sbb_tree);
1303  FAIL_IF_NULL(sbb1);
1304  FAIL_IF(sbb1->offset != 0);
1305  FAIL_IF(sbb1->len != 10);
1306  FAIL_IF(SBB_RB_NEXT(sbb1));
1307  FAIL_IF_NULL(sb->head);
1308  FAIL_IF_NOT(sb->sbb_size == 10);
1309  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1310 
1311  StreamingBufferSegment seg6;
1312  FAIL_IF(StreamingBufferInsertAt(sb, &seg6, (const uint8_t *)"abcdefghij", 10, 0) != 0);
1313  Dump(sb);
1314  sbb1 = RB_MIN(SBB, &sb->sbb_tree);
1315  FAIL_IF_NULL(sbb1);
1316  FAIL_IF(sbb1->offset != 0);
1317  FAIL_IF(sbb1->len != 10);
1318  FAIL_IF(SBB_RB_NEXT(sbb1));
1319  FAIL_IF_NULL(sb->head);
1320  FAIL_IF_NOT(sb->sbb_size == 10);
1321  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1322 
1323  StreamingBufferFree(sb);
1324  PASS;
1325 }
1326 
1327 /** \test lots of gaps in block list */
1328 static int StreamingBufferTest07(void)
1329 {
1330  StreamingBufferConfig cfg = { 0, 8, 16, NULL, NULL, NULL, NULL };
1332  FAIL_IF(sb == NULL);
1333 
1334  StreamingBufferSegment seg1;
1335  FAIL_IF(StreamingBufferInsertAt(sb, &seg1, (const uint8_t *)"B", 1, 1) != 0);
1336  StreamingBufferSegment seg2;
1337  FAIL_IF(StreamingBufferInsertAt(sb, &seg2, (const uint8_t *)"D", 1, 3) != 0);
1338  Dump(sb);
1339  FAIL_IF_NULL(sb->head);
1340  FAIL_IF_NOT(sb->sbb_size == 2);
1341  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1342 
1343  StreamingBufferSegment seg3;
1344  FAIL_IF(StreamingBufferInsertAt(sb, &seg3, (const uint8_t *)"F", 1, 5) != 0);
1345  Dump(sb);
1346  FAIL_IF_NULL(sb->head);
1347  FAIL_IF_NOT(sb->sbb_size == 3);
1348  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1349 
1350  StreamingBufferSegment seg4;
1351  FAIL_IF(StreamingBufferInsertAt(sb, &seg4, (const uint8_t *)"H", 1, 7) != 0);
1352  Dump(sb);
1353  FAIL_IF_NULL(sb->head);
1354  FAIL_IF_NOT(sb->sbb_size == 4);
1355  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1356 
1357  StreamingBufferSegment seg5;
1358  FAIL_IF(StreamingBufferInsertAt(sb, &seg5, (const uint8_t *)"ABCDEFGHIJ", 10, 0) != 0);
1359  Dump(sb);
1360  StreamingBufferBlock *sbb1 = RB_MIN(SBB, &sb->sbb_tree);
1361  FAIL_IF_NULL(sbb1);
1362  FAIL_IF(sbb1->offset != 0);
1363  FAIL_IF(sbb1->len != 10);
1364  FAIL_IF(SBB_RB_NEXT(sbb1));
1365  FAIL_IF_NULL(sb->head);
1366  FAIL_IF_NOT(sb->sbb_size == 10);
1367  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1368 
1369  StreamingBufferSegment seg6;
1370  FAIL_IF(StreamingBufferInsertAt(sb, &seg6, (const uint8_t *)"abcdefghij", 10, 0) != 0);
1371  Dump(sb);
1372  sbb1 = RB_MIN(SBB, &sb->sbb_tree);
1373  FAIL_IF_NULL(sbb1);
1374  FAIL_IF(sbb1->offset != 0);
1375  FAIL_IF(sbb1->len != 10);
1376  FAIL_IF(SBB_RB_NEXT(sbb1));
1377  FAIL_IF_NULL(sb->head);
1378  FAIL_IF_NOT(sb->sbb_size == 10);
1379  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1380 
1381  StreamingBufferFree(sb);
1382  PASS;
1383 }
1384 
1385 /** \test lots of gaps in block list */
1386 static int StreamingBufferTest08(void)
1387 {
1388  StreamingBufferConfig cfg = { 0, 8, 16, NULL, NULL, NULL, NULL };
1390  FAIL_IF(sb == NULL);
1391 
1392  StreamingBufferSegment seg1;
1393  FAIL_IF(StreamingBufferInsertAt(sb, &seg1, (const uint8_t *)"B", 1, 1) != 0);
1394  StreamingBufferSegment seg2;
1395  FAIL_IF(StreamingBufferInsertAt(sb, &seg2, (const uint8_t *)"D", 1, 3) != 0);
1396  Dump(sb);
1397  FAIL_IF_NULL(sb->head);
1398  FAIL_IF_NOT(sb->sbb_size == 2);
1399  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1400 
1401  StreamingBufferSegment seg3;
1402  FAIL_IF(StreamingBufferInsertAt(sb, &seg3, (const uint8_t *)"F", 1, 5) != 0);
1403  Dump(sb);
1404  FAIL_IF_NULL(sb->head);
1405  FAIL_IF_NOT(sb->sbb_size == 3);
1406  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1407 
1408  StreamingBufferSegment seg4;
1409  FAIL_IF(StreamingBufferInsertAt(sb, &seg4, (const uint8_t *)"H", 1, 7) != 0);
1410  Dump(sb);
1411  FAIL_IF_NULL(sb->head);
1412  FAIL_IF_NOT(sb->sbb_size == 4);
1413  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1414 
1415  StreamingBufferSegment seg5;
1416  FAIL_IF(StreamingBufferInsertAt(sb, &seg5, (const uint8_t *)"ABCDEFGHIJ", 10, 0) != 0);
1417  Dump(sb);
1418  StreamingBufferBlock *sbb1 = RB_MIN(SBB, &sb->sbb_tree);
1419  FAIL_IF_NULL(sbb1);
1420  FAIL_IF(sbb1->offset != 0);
1421  FAIL_IF(sbb1->len != 10);
1422  FAIL_IF(SBB_RB_NEXT(sbb1));
1423  FAIL_IF_NULL(sb->head);
1424  FAIL_IF_NOT(sb->sbb_size == 10);
1425  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1426 
1427  StreamingBufferSegment seg6;
1428  FAIL_IF(StreamingBufferAppend(sb, &seg6, (const uint8_t *)"abcdefghij", 10) != 0);
1429  Dump(sb);
1430  sbb1 = RB_MIN(SBB, &sb->sbb_tree);
1431  FAIL_IF_NULL(sbb1);
1432  FAIL_IF(sbb1->offset != 0);
1433  FAIL_IF(sbb1->len != 20);
1434  FAIL_IF(SBB_RB_NEXT(sbb1));
1435  FAIL_IF_NULL(sb->head);
1436  FAIL_IF_NOT(sb->sbb_size == 20);
1437  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1438 
1439  StreamingBufferFree(sb);
1440  PASS;
1441 }
1442 
1443 /** \test lots of gaps in block list */
1444 static int StreamingBufferTest09(void)
1445 {
1446  StreamingBufferConfig cfg = { 0, 8, 16, NULL, NULL, NULL, NULL };
1448  FAIL_IF(sb == NULL);
1449 
1450  StreamingBufferSegment seg1;
1451  FAIL_IF(StreamingBufferInsertAt(sb, &seg1, (const uint8_t *)"B", 1, 1) != 0);
1452  StreamingBufferSegment seg2;
1453  FAIL_IF(StreamingBufferInsertAt(sb, &seg2, (const uint8_t *)"D", 1, 3) != 0);
1454  Dump(sb);
1455  FAIL_IF_NULL(sb->head);
1456  FAIL_IF_NOT(sb->sbb_size == 2);
1457  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1458 
1459  StreamingBufferSegment seg3;
1460  FAIL_IF(StreamingBufferInsertAt(sb, &seg3, (const uint8_t *)"H", 1, 7) != 0);
1461  Dump(sb);
1462  FAIL_IF_NULL(sb->head);
1463  FAIL_IF_NOT(sb->sbb_size == 3);
1464  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1465 
1466  StreamingBufferSegment seg4;
1467  FAIL_IF(StreamingBufferInsertAt(sb, &seg4, (const uint8_t *)"F", 1, 5) != 0);
1468  Dump(sb);
1469  FAIL_IF_NULL(sb->head);
1470  FAIL_IF_NOT(sb->sbb_size == 4);
1471  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1472 
1473  StreamingBufferSegment seg5;
1474  FAIL_IF(StreamingBufferInsertAt(sb, &seg5, (const uint8_t *)"ABCDEFGHIJ", 10, 0) != 0);
1475  Dump(sb);
1476  StreamingBufferBlock *sbb1 = RB_MIN(SBB, &sb->sbb_tree);
1477  FAIL_IF_NULL(sbb1);
1478  FAIL_IF(sbb1->offset != 0);
1479  FAIL_IF(sbb1->len != 10);
1480  FAIL_IF(SBB_RB_NEXT(sbb1));
1481  FAIL_IF_NULL(sb->head);
1482  FAIL_IF_NOT(sb->sbb_size == 10);
1483  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1484 
1485  StreamingBufferSegment seg6;
1486  FAIL_IF(StreamingBufferInsertAt(sb, &seg6, (const uint8_t *)"abcdefghij", 10, 0) != 0);
1487  Dump(sb);
1488  sbb1 = RB_MIN(SBB, &sb->sbb_tree);
1489  FAIL_IF_NULL(sbb1);
1490  FAIL_IF(sbb1->offset != 0);
1491  FAIL_IF(sbb1->len != 10);
1492  FAIL_IF(SBB_RB_NEXT(sbb1));
1493  FAIL_IF_NULL(sb->head);
1494  FAIL_IF_NOT(sb->sbb_size == 10);
1495  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1496 
1497  StreamingBufferFree(sb);
1498  PASS;
1499 }
1500 
1501 /** \test lots of gaps in block list */
1502 static int StreamingBufferTest10(void)
1503 {
1504  StreamingBufferConfig cfg = { 0, 8, 16, NULL, NULL, NULL, NULL };
1506  FAIL_IF(sb == NULL);
1507 
1508  StreamingBufferSegment seg1;
1509  FAIL_IF(StreamingBufferInsertAt(sb, &seg1, (const uint8_t *)"A", 1, 0) != 0);
1510  Dump(sb);
1511  StreamingBufferSegment seg2;
1512  FAIL_IF(StreamingBufferInsertAt(sb, &seg2, (const uint8_t *)"D", 1, 3) != 0);
1513  Dump(sb);
1514  StreamingBufferSegment seg3;
1515  FAIL_IF(StreamingBufferInsertAt(sb, &seg3, (const uint8_t *)"H", 1, 7) != 0);
1516  Dump(sb);
1517  FAIL_IF_NULL(sb->head);
1518  FAIL_IF_NOT(sb->sbb_size == 3);
1519 
1520  StreamingBufferSegment seg4;
1521  FAIL_IF(StreamingBufferInsertAt(sb, &seg4, (const uint8_t *)"B", 1, 1) != 0);
1522  Dump(sb);
1523  StreamingBufferSegment seg5;
1524  FAIL_IF(StreamingBufferInsertAt(sb, &seg5, (const uint8_t *)"C", 1, 2) != 0);
1525  Dump(sb);
1526  StreamingBufferSegment seg6;
1527  FAIL_IF(StreamingBufferInsertAt(sb, &seg6, (const uint8_t *)"G", 1, 6) != 0);
1528  Dump(sb);
1529  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1530  FAIL_IF_NULL(sb->head);
1531  FAIL_IF_NOT(sb->sbb_size == 6);
1532 
1533  StreamingBufferSegment seg7;
1534  FAIL_IF(StreamingBufferInsertAt(sb, &seg7, (const uint8_t *)"ABCDEFGHIJ", 10, 0) != 0);
1535  Dump(sb);
1536  StreamingBufferBlock *sbb1 = RB_MIN(SBB, &sb->sbb_tree);
1537  FAIL_IF_NULL(sbb1);
1538  FAIL_IF(sbb1->offset != 0);
1539  FAIL_IF(sbb1->len != 10);
1540  FAIL_IF(SBB_RB_NEXT(sbb1));
1541  FAIL_IF_NULL(sb->head);
1542  FAIL_IF_NOT(sb->sbb_size == 10);
1543 
1544  StreamingBufferSegment seg8;
1545  FAIL_IF(StreamingBufferInsertAt(sb, &seg8, (const uint8_t *)"abcdefghij", 10, 0) != 0);
1546  Dump(sb);
1547  sbb1 = RB_MIN(SBB, &sb->sbb_tree);
1548  FAIL_IF_NOT(sb->head == RB_MIN(SBB, &sb->sbb_tree));
1549  FAIL_IF_NULL(sbb1);
1550  FAIL_IF(sbb1->offset != 0);
1551  FAIL_IF(sbb1->len != 10);
1552  FAIL_IF(SBB_RB_NEXT(sbb1));
1553  FAIL_IF_NULL(sb->head);
1554  FAIL_IF_NOT(sb->sbb_size == 10);
1555 
1556  StreamingBufferFree(sb);
1557  PASS;
1558 }
1559 
1560 #endif
1561 
1563 {
1564 #ifdef UNITTESTS
1565  UtRegisterTest("StreamingBufferTest01", StreamingBufferTest01);
1566  UtRegisterTest("StreamingBufferTest02", StreamingBufferTest02);
1567  UtRegisterTest("StreamingBufferTest03", StreamingBufferTest03);
1568  UtRegisterTest("StreamingBufferTest04", StreamingBufferTest04);
1569  UtRegisterTest("StreamingBufferTest05", StreamingBufferTest05);
1570  UtRegisterTest("StreamingBufferTest06", StreamingBufferTest06);
1571  UtRegisterTest("StreamingBufferTest07", StreamingBufferTest07);
1572  UtRegisterTest("StreamingBufferTest08", StreamingBufferTest08);
1573  UtRegisterTest("StreamingBufferTest09", StreamingBufferTest09);
1574  UtRegisterTest("StreamingBufferTest10", StreamingBufferTest10);
1575 #endif
1576 }
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:867
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:884
StreamingBufferSegmentCompareRawData
int StreamingBufferSegmentCompareRawData(const StreamingBuffer *sb, const StreamingBufferSegment *seg, const uint8_t *rawdata, uint32_t rawdata_len)
Definition: util-streaming-buffer.c:851
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:749
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:907
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:787
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:679
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:820
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:761
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:380
StreamingBufferRegisterTests
void StreamingBufferRegisterTests(void)
Definition: util-streaming-buffer.c:1562