aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMosder <xmosder12@gmail.com>2026-07-23 17:35:04 +0200
committerMosder <xmosder12@gmail.com>2026-07-23 17:35:04 +0200
commit8317c3b33b9b1c70e5ae4c87c7efe33d9b9ce09a (patch)
tree8a6b5e20196a253c75b44762de223f1ea2b4a067
parent33fcaa8140784ab32cfc8c14a6fc7fdb71435265 (diff)
feat: added helper functions for dealing with memory management and refactored the codebase to use them
-rw-r--r--Makefile1
-rw-r--r--analyzer/parser/fight_results/fight_results.c109
-rw-r--r--analyzer/parser/fight_results/fight_results.h6
-rw-r--r--analyzer/parser/parser.c16
-rw-r--r--analyzer/parser/structs.c4
-rw-r--r--analyzer/structures/hashmap.c12
-rw-r--r--analyzer/structures/heap.c10
-rw-r--r--analyzer/utils/memory.c62
-rw-r--r--analyzer/utils/memory.h42
-rw-r--r--analyzer/utils/tcp.c46
10 files changed, 195 insertions, 113 deletions
diff --git a/Makefile b/Makefile
index fa3a294..cc5cb87 100644
--- a/Makefile
+++ b/Makefile
@@ -36,6 +36,7 @@ utils:
$(CC) $(CFLAGS) -c analyzer/utils/tcp.c
$(CC) $(CFLAGS) -c analyzer/utils/tcp_seq_math.c
$(CC) $(CFLAGS) -c analyzer/utils/roman.c
+ $(CC) $(CFLAGS) -c analyzer/utils/memory.c
parser:
$(CC) $(CFLAGS) -c analyzer/parser/parser.c
diff --git a/analyzer/parser/fight_results/fight_results.c b/analyzer/parser/fight_results/fight_results.c
index e7c7123..efc4b36 100644
--- a/analyzer/parser/fight_results/fight_results.c
+++ b/analyzer/parser/fight_results/fight_results.c
@@ -30,6 +30,8 @@ void cleanup_fight_results(void *data) {
for (size_t i = 0; i < fight_results->num_enemy; i++) {
free(fight_results->enemy_results[i].name);
}
+ free(fight_results->friendly_results);
+ free(fight_results->enemy_results);
}
byte_t *find_fight_results(TCPStream *stream, int offset, int *length) {
@@ -41,12 +43,6 @@ byte_t *find_fight_results(TCPStream *stream, int offset, int *length) {
return start;
}
-Item *expand_items(Item *items, size_t *items_capacity, size_t to_fit) {
- while (*items_capacity < to_fit)
- *items_capacity <<= 1;
- return realloc(items, *items_capacity * sizeof(Item));
-}
-
void get_stars(char *buffer, int incr_above_b1) {
char star_types[] = {'B', 'S', 'G'};
sprintf(buffer, " (%c%d)", star_types[incr_above_b1 / 3], incr_above_b1 % 3 + 1);
@@ -67,10 +63,11 @@ void add_gear(FriendlyResults *results, size_t *items_capacity, char *gears_str)
if (gears_separator)
gears_str = gears_separator + strlen(SEPARATOR_GEAR);
- Item item;
-
+ // get gear info for rank, name and stars / syng level
GearInfo gear_info = {0};
fill_struct(&gear_info, gear_info_fields, ARR_LEN(gear_info_fields), gear.info, strlen(gear.info), SEPARATOR_GEAR_INFO_FIELD);
+
+ // create the buffer of information about gear
char buffer[SINGLE_ITEM_BUFFER_LEN];
char roman[5];
to_roman(roman, gear_info.rank);
@@ -91,9 +88,9 @@ void add_gear(FriendlyResults *results, size_t *items_capacity, char *gears_str)
break;
}
}
- item.data = strdup(buffer);
- cleanup_struct(&gear_info, gear_info_fields, ARR_LEN(gear_info_fields));
+ // add gear with specific type
+ Item item = {.data = strdup(buffer)};
switch (gear.type) {
case TYPE_SYNG_NORMAL:
// atoi should be fine, since syng_tier starts from 1 for syngs
@@ -109,26 +106,22 @@ void add_gear(FriendlyResults *results, size_t *items_capacity, char *gears_str)
item.type = EPIC;
break;
}
+ results->items = array_append(results->items, sizeof(Item), &results->num_items, items_capacity, &item);
- // expand if needed
- if (results->num_items >= *items_capacity)
- results->items = expand_items(results->items, items_capacity, results->num_items + 1);
- results->items[results->num_items++] = item;
+ cleanup_struct(&gear_info, gear_info_fields, ARR_LEN(gear_info_fields));
// add orb to items if it exists
if (strlen(gear.orb)) {
- Item item;
- char buffer[SINGLE_ITEM_BUFFER_LEN];
Orb orb = {0};
fill_struct(&orb, orb_fields, ARR_LEN(orb_fields), gear.orb, strlen(gear.orb), SEPARATOR_ORB_FIELD);
+
+ char buffer[SINGLE_ITEM_BUFFER_LEN];
sprintf(buffer, "%sorb %s", get_artifact_size_from_id(orb.size), get_orb_name_from_id(orb.id));
- item.data = strdup(buffer);
+
+ Item item = {.data = strdup(buffer), .type = ORB};
+ results->items = array_append(results->items, sizeof(Item), &results->num_items, items_capacity, &item);
+
cleanup_struct(&orb, orb_fields, ARR_LEN(orb_fields));
- item.type = ORB;
- // expand if needed
- if (results->num_items >= *items_capacity)
- results->items = expand_items(results->items, items_capacity, results->num_items + 1);
- results->items[results->num_items++] = item;
}
cleanup_struct(&gear, gear_fields, ARR_LEN(gear_fields));
@@ -150,16 +143,10 @@ void add_drifs(FriendlyResults *results, size_t *items_capacity, char *drifs_str
if (drifs_separator)
drifs_str = drifs_separator + strlen(SEPARATOR_DRIF);
- Item item;
- item.data = strdup(drif.name);
- item.type = DRIF;
+ Item item = {.data = strdup(drif.name), .type = DRIF};
+ results->items = array_append(results->items, sizeof(Item), &results->num_items, items_capacity, &item);
cleanup_struct(&drif, drif_fields, ARR_LEN(drif_fields));
-
- // expand if needed
- if (results->num_items >= *items_capacity)
- results->items = expand_items(results->items, items_capacity, results->num_items + 1);
- results->items[results->num_items++] = item;
} while (drifs_separator);
}
@@ -180,37 +167,31 @@ void add_items(FriendlyResults *results, size_t *items_capacity, char *items_str
if (items_separator)
items_str = items_separator + strlen(SEPARATOR_ITEMS);
- Item item;
- item.data = strdup(buffer);
- item.type = NORMAL;
-
- // expand if needed
- if (results->num_items >= *items_capacity)
- results->items = expand_items(results->items, items_capacity, results->num_items + 1);
- results->items[results->num_items++] = item;
+ Item item = {.data = strdup(buffer), .type = NORMAL};
+ results->items = array_append(results->items, sizeof(Item), &results->num_items, items_capacity, &item);
} while (items_separator);
}
// parse EntityResults to FriendlyResults
FriendlyResults parse_to_friendly(EntityResults entity_results) {
- FriendlyResults results;
-
- results.name = strdup(entity_results.name);
- results.exp = entity_results.exp;
- results.gold = entity_results.gold;
- results.level = entity_results.level;
- results.psycho = entity_results.psycho;
- results.splinters = entity_results.splinters;
+ FriendlyResults results = {
+ .name = strdup(entity_results.name),
+ .exp = entity_results.exp,
+ .gold = entity_results.gold,
+ .level = entity_results.level,
+ .psycho = entity_results.psycho,
+ .splinters = entity_results.splinters,
+ .num_items = 0,
+ .saturation = 0
+ };
// create items array and add to it gear, drifs and items
- results.num_items = 0;
- results.items = malloc(INIT_ITEMS_CAPACITY * sizeof(Item));
+ results.items = safe_malloc(INIT_ITEMS_CAPACITY * sizeof(Item));
size_t items_cap = INIT_ITEMS_CAPACITY;
add_gear(&results, &items_cap, entity_results.gear);
add_drifs(&results, &items_cap, entity_results.drifs);
add_items(&results, &items_cap, entity_results.items);
- results.saturation = 0;
if (strlen(entity_results.saturation) > 0) {
int saturation_id;
sscanf(entity_results.saturation, "%d,%d", &saturation_id, &results.saturation);
@@ -222,25 +203,26 @@ FriendlyResults parse_to_friendly(EntityResults entity_results) {
// parse EntityResults to EnemyResults
EnemyResults parse_to_enemy(EntityResults entity_results) {
- EnemyResults results;
-
- results.name = strdup(entity_results.name);
- results.level = entity_results.level;
-
+ EnemyResults results = {.name = strdup(entity_results.name), .level = entity_results.level};
return results;
}
ParsedData parse_fight_results(byte_t *data, size_t length) {
- ParsedData parsed_data;
- parsed_data.data_type = TYPE_FIGHT_RESULTS;
+ ParsedData parsed_data = {.data_type = TYPE_FIGHT_RESULTS, .data_cleanup = cleanup_fight_results};
// ignore start and end indicators
data += strlen(FIGHT_RESULTS_START);
length -= strlen(FIGHT_RESULTS_START) + strlen(FIGHT_RESULTS_END);
- FightResults *results = malloc(sizeof(FightResults));
+ FightResults *results = safe_malloc(sizeof(FightResults));
+
+ results->friendly_results = safe_malloc(INIT_ENTITIES_PER_SIDE * sizeof(FriendlyResults));
results->num_friendly = 0;
+ size_t friendly_cap = INIT_ENTITIES_PER_SIDE;
+
+ results->enemy_results = safe_malloc(INIT_ENTITIES_PER_SIDE * sizeof(EnemyResults));
results->num_enemy = 0;
+ size_t enemy_cap = INIT_ENTITIES_PER_SIDE;
byte_t *entity_separator;
do {
@@ -252,12 +234,16 @@ ParsedData parse_fight_results(byte_t *data, size_t length) {
// depending on team - parse it into friendly or enemy results
switch (entity_results.team) {
- case TEAM_FRIEND:
- results->friendly_results[results->num_friendly++] = parse_to_friendly(entity_results);
+ case TEAM_FRIEND: {
+ FriendlyResults res = parse_to_friendly(entity_results);
+ results->friendly_results = array_append(results->friendly_results, sizeof(FriendlyResults), &results->num_friendly, &friendly_cap, &res);
break;
- case TEAM_ENEMY:
- results->enemy_results[results->num_enemy++] = parse_to_enemy(entity_results);
+ }
+ case TEAM_ENEMY: {
+ EnemyResults res = parse_to_enemy(entity_results);
+ results->enemy_results = array_append(results->enemy_results, sizeof(EnemyResults), &results->num_enemy, &enemy_cap, &res);
break;
+ }
}
cleanup_struct(&entity_results, entity_fields, ARR_LEN(entity_fields));
@@ -270,6 +256,5 @@ ParsedData parse_fight_results(byte_t *data, size_t length) {
} while (entity_separator);
parsed_data.data = results;
- parsed_data.data_cleanup = cleanup_fight_results;
return parsed_data;
}
diff --git a/analyzer/parser/fight_results/fight_results.h b/analyzer/parser/fight_results/fight_results.h
index 04add96..ec90394 100644
--- a/analyzer/parser/fight_results/fight_results.h
+++ b/analyzer/parser/fight_results/fight_results.h
@@ -44,14 +44,14 @@ typedef struct {
int level;
} EnemyResults;
-#define MAX_ENTITIES_PER_SIDE 8
+#define INIT_ENTITIES_PER_SIDE 6
// entire fight resutls
typedef struct {
size_t num_friendly;
- FriendlyResults friendly_results[MAX_ENTITIES_PER_SIDE];
+ FriendlyResults *friendly_results;
size_t num_enemy;
- EnemyResults enemy_results[MAX_ENTITIES_PER_SIDE];
+ EnemyResults *enemy_results;
} FightResults;
extern find_function_t find_fight_results;
diff --git a/analyzer/parser/parser.c b/analyzer/parser/parser.c
index 87ab4c0..d00cd97 100644
--- a/analyzer/parser/parser.c
+++ b/analyzer/parser/parser.c
@@ -5,13 +5,6 @@
#include "parser/find_parse_functions.h"
#include "utils/memory.h"
-// expand parsed data exponentially to fit el_count elements
-ParsedData *expand_parsed_data(ParsedData *parsed_data, size_t *capacity, size_t el_count) {
- while (*capacity < el_count)
- *capacity <<= 1;
- return realloc(parsed_data, *capacity * sizeof(ParsedData));
-}
-
// find earliest data to parse in stream
byte_t *find_earliest_data(TCPStream *stream, int stream_offset, int *earliest_length, parse_function_t **earliest_parse_fun) {
byte_t *earliest_data = NULL;
@@ -30,7 +23,7 @@ byte_t *find_earliest_data(TCPStream *stream, int stream_offset, int *earliest_l
ParsedData *parse_stream(TCPStream *stream, size_t *parsed_len, size_t *n_parsed_data) {
size_t parsed_data_capacity = INIT_PARSED_DATA_CAPACITY;
- ParsedData *parsed_data = malloc(parsed_data_capacity * sizeof(ParsedData));
+ ParsedData *parsed_data = safe_malloc(parsed_data_capacity * sizeof(ParsedData));
*n_parsed_data = 0;
int stream_offset = 0;
@@ -50,11 +43,8 @@ ParsedData *parse_stream(TCPStream *stream, size_t *parsed_len, size_t *n_parsed
// if data to parse was found, parse it and update the offset
if (earliest_data) {
- // if no capacity in parsed data array - expand it
- if (*n_parsed_data >= parsed_data_capacity)
- parsed_data = expand_parsed_data(parsed_data, &parsed_data_capacity, *n_parsed_data + 1);
-
- parsed_data[(*n_parsed_data)++] = earliest_parse_fun(earliest_data, earliest_length);
+ ParsedData new_parsed = earliest_parse_fun(earliest_data, earliest_length);
+ parsed_data = array_append(parsed_data, sizeof(ParsedData), n_parsed_data, &parsed_data_capacity, &new_parsed);
stream_offset = earliest_data - stream->data + earliest_length;
}
} while (earliest_data);
diff --git a/analyzer/parser/structs.c b/analyzer/parser/structs.c
index c59fa82..dedf0d1 100644
--- a/analyzer/parser/structs.c
+++ b/analyzer/parser/structs.c
@@ -4,12 +4,14 @@
#include <stdlib.h>
#include <string.h>
+#include "utils/memory.h"
+
void fill_struct(void *obj, const StructField *fields, size_t n_fields, const char *data, size_t data_len, const char *sep) {
for (size_t i = 0; i < n_fields; i++) {
char *next_sep = memmem(data, data_len, sep, strlen(sep));
size_t len = next_sep ? next_sep - data : data_len;
- char *str = malloc(len + 1);
+ char *str = safe_malloc(len + 1);
memcpy(str, data, len);
str[len] = '\0';
diff --git a/analyzer/structures/hashmap.c b/analyzer/structures/hashmap.c
index 84cc289..5eb27ae 100644
--- a/analyzer/structures/hashmap.c
+++ b/analyzer/structures/hashmap.c
@@ -3,6 +3,8 @@
#include <stdlib.h>
#include <string.h>
+#include "utils/memory.h"
+
HashMap *hashmap_new(
size_t key_size,
size_t value_size,
@@ -11,9 +13,9 @@ HashMap *hashmap_new(
void (*key_cleanup)(void *key),
void (*value_cleanup)(void *key)
) {
- HashMap *map = malloc(sizeof(HashMap));
+ HashMap *map = safe_malloc(sizeof(HashMap));
// initialize NULLs
- memset(map->table, 0, sizeof(HashMapNode *) * HASHMAP_TABLE_SIZE);
+ memset(map->table, 0, HASHMAP_TABLE_SIZE * sizeof(HashMapNode *));
map->key_size = key_size;
map->value_size = value_size;
map->hash = hash;
@@ -42,9 +44,9 @@ void hashmap_put(HashMap *map, void *key, void *value) {
}
// if it doesn't exist - create new node
- HashMapNode *new_node = malloc(sizeof(HashMapNode));
- new_node->key = malloc(map->key_size);
- new_node->value = malloc(map->value_size);
+ HashMapNode *new_node = safe_malloc(sizeof(HashMapNode));
+ new_node->key = safe_malloc(map->key_size);
+ new_node->value = safe_malloc(map->value_size);
memcpy(new_node->key, key, map->key_size);
memcpy(new_node->value, value, map->value_size);
diff --git a/analyzer/structures/heap.c b/analyzer/structures/heap.c
index 6102940..1267668 100644
--- a/analyzer/structures/heap.c
+++ b/analyzer/structures/heap.c
@@ -3,9 +3,11 @@
#include <stdlib.h>
#include <string.h>
+#include "utils/memory.h"
+
Heap *heap_new(size_t element_size, int (*compare)(void *element1, void *element2), void (*element_cleanup)(void *element)) {
- Heap *heap = malloc(sizeof(Heap));
- heap->data = malloc(INIT_HEAP_CAPACITY * sizeof(void *));
+ Heap *heap = safe_malloc(sizeof(Heap));
+ heap->data = safe_malloc(INIT_HEAP_CAPACITY * sizeof(void *));
heap->n_elements = 0;
heap->element_size = element_size;
heap->capacity = INIT_HEAP_CAPACITY;
@@ -40,7 +42,7 @@ void swap(void **p_el1, void **p_el2) {
void expand_heap(Heap *heap, size_t el_count) {
while (heap->capacity < el_count)
heap->capacity = (heap->capacity << 1) | 1;
- heap->data = realloc(heap->data, heap->capacity * sizeof(void *));
+ heap->data = safe_realloc(heap->data, heap->capacity * sizeof(void *));
}
void heap_insert(Heap *heap, void *element) {
@@ -50,7 +52,7 @@ void heap_insert(Heap *heap, void *element) {
// insert into the last position
size_t i = heap->n_elements;
- heap->data[i] = malloc(heap->element_size);
+ heap->data[i] = safe_malloc(heap->element_size);
memcpy(heap->data[i], element, heap->element_size);
heap->n_elements++;
diff --git a/analyzer/utils/memory.c b/analyzer/utils/memory.c
new file mode 100644
index 0000000..0a43bd3
--- /dev/null
+++ b/analyzer/utils/memory.c
@@ -0,0 +1,62 @@
+#include "memory.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+void *safe_malloc(size_t size) {
+ for (size_t i = 0; i < MAX_ALLOC_ATTEMPTS; i++) {
+ void *p = malloc(size);
+ if (p)
+ return p;
+ if (i < MAX_ALLOC_ATTEMPTS - 1) {
+ printf("Failed malloc. Retrying in 1s...\n");
+ sleep(1);
+ }
+ }
+
+ printf("ERROR: Failed malloc %d times. Exiting...", MAX_ALLOC_ATTEMPTS);
+ exit(EXIT_FAILURE);
+}
+
+void *safe_realloc(void *ptr, size_t size) {
+ if (!ptr)
+ return safe_malloc(size);
+
+ for (size_t i = 0; i < MAX_ALLOC_ATTEMPTS; i++) {
+ void *p = realloc(ptr, size);
+ if (p)
+ return p;
+ if (i < MAX_ALLOC_ATTEMPTS - 1) {
+ printf("Failed realloc. Retrying in 1s...\n");
+ sleep(1);
+ }
+ }
+
+ printf("ERROR: Failed realloc %d times. Exiting...", MAX_ALLOC_ATTEMPTS);
+ exit(EXIT_FAILURE);
+}
+
+// expand an array
+// returns pointer to the expanded array
+void *array_expand(void *arr, size_t el_size, size_t *cap, size_t to_fit) {
+ while (*cap < to_fit)
+ *cap *= 2;
+ return safe_realloc(arr, *cap * el_size);
+}
+
+void *array_append(void *arr, size_t el_size, size_t *len, size_t *cap, void *val) {
+ if (*len >= *cap)
+ arr = array_expand(arr, el_size, cap, *len + 1);
+ memcpy((char *)arr + (*len)++ * el_size, val, el_size);
+ return arr;
+}
+
+void *array_concat(void *arr1, size_t el_size, size_t *len1, size_t *cap, void *arr2, size_t len2) {
+ if (*len1 + len2 > *cap)
+ arr1 = array_expand(arr1, el_size, cap, *len1 + len2);
+ memcpy((char *)arr1 + *len1 * el_size, arr2, len2 * el_size);
+ *len1 += len2;
+ return arr1;
+}
diff --git a/analyzer/utils/memory.h b/analyzer/utils/memory.h
index 1de58b9..0973623 100644
--- a/analyzer/utils/memory.h
+++ b/analyzer/utils/memory.h
@@ -1,4 +1,46 @@
// utils/memory.h
// helper functions for dealing with memory management
+#include <stddef.h>
+
#define ARR_LEN(arr) (sizeof(arr) / sizeof(arr[0]))
+
+#define MAX_ALLOC_ATTEMPTS 3
+
+// tries malloc MAX_ALLOC_ATTEMPTS times, if all fail - exits the program
+// params:
+// - size - count of bytes to allocate
+// returns:
+// pointer to the allocated memory
+extern void *safe_malloc(size_t size);
+
+// tries realloc MAX_ALLOC_ATTEMPTS times, if all fail - exits the program
+// params:
+// - ptr - pointer to the memory to reallocate
+// - size - new size of the memory
+// returns:
+// pointer to the reallocated memory
+extern void *safe_realloc(void *ptr, size_t size);
+
+// append to array, expand if necessary
+// params:
+// - arr - array to append to
+// - el_size - size of an array element
+// - len - pointer to the length of the array
+// - cap - pointer to the capacity of the array
+// - val - pointer to the value to append to the array
+// returns:
+// new pointer to the array (different if it was realloced)
+extern void *array_append(void *arr, size_t el_size, size_t *len, size_t *cap, void *val);
+
+// concatenate 2 arrays, expand if necessary
+// params:
+// - arr1 - first array (destination)
+// - el_size - size of an array element
+// - len1 - pointer to the length of arr1
+// - cap - pointer to the capacity of arr1
+// - arr2 - second array
+// - len2 - length of arr2
+// returns:
+// new pointer to the array (different if it was realloced)
+extern void *array_concat(void *arr1, size_t el_size, size_t *len1, size_t *cap, void *arr2, size_t len2);
diff --git a/analyzer/utils/tcp.c b/analyzer/utils/tcp.c
index b925ecf..6309e64 100644
--- a/analyzer/utils/tcp.c
+++ b/analyzer/utils/tcp.c
@@ -6,15 +6,19 @@
#include <stdlib.h>
#include <string.h>
+#include "utils/memory.h"
#include "utils/tcp_seq_math.h"
// initalize default TCP segment
TCPSegment new_segment() {
- TCPSegment segment;
- segment.payload = NULL;
- segment.len = 0;
- segment.seq = 0;
- segment.port = 0;
+ // clang-format off
+ TCPSegment segment = {
+ .payload = NULL,
+ .len = 0,
+ .seq = 0,
+ .port = 0
+ };
+ // clang-format on
return segment;
}
@@ -61,19 +65,22 @@ TCPSegment get_segment_from_packet(const byte_t *packet, const struct pcap_pkthd
// get payload
int total_header_len = eth_header_len + ip_header_len + tcp_header_len;
segment.len = packet_data->caplen - total_header_len;
- segment.payload = malloc(segment.len);
+ segment.payload = safe_malloc(segment.len);
memcpy(segment.payload, packet + total_header_len, segment.len);
return segment;
}
TCPStream new_stream() {
- TCPStream stream;
- stream.data = malloc(INIT_STREAM_CAPACITY);
- stream.len = 0;
- stream.capacity = INIT_STREAM_CAPACITY;
- stream.seq = 0;
- stream.port = 0;
- stream.pending = NULL;
+ // clang-format off
+ TCPStream stream = {
+ .data = safe_malloc(INIT_STREAM_CAPACITY),
+ .len = 0,
+ .capacity = INIT_STREAM_CAPACITY,
+ .seq = 0,
+ .port = 0,
+ .pending = NULL
+ };
+ // clang-format on
return stream;
}
@@ -107,20 +114,9 @@ int in_acceptable_range(TCPStream stream, TCPSegment segment) {
return seq_in_range_ei(segment.seq, stream_expected, max_acceptable_seq);
}
-// expand stream capacity exponentially to fit new_len
-void expand_stream_capacity(TCPStream *stream, size_t new_len) {
- while (stream->capacity < new_len)
- stream->capacity <<= 1;
- stream->data = realloc(stream->data, stream->capacity);
-}
-
// add segment directly to stream
void add_segment(TCPStream *stream, TCPSegment segment, size_t data_start) {
- size_t new_stream_len = stream->len + segment.len - data_start;
- if (new_stream_len > stream->capacity)
- expand_stream_capacity(stream, new_stream_len);
- memcpy(stream->data + stream->len, segment.payload + data_start, segment.len - data_start);
- stream->len = new_stream_len;
+ stream->data = array_concat(stream->data, 1, &stream->len, &stream->capacity, segment.payload + data_start, segment.len - data_start);
}
// add pending segments to the stream