aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMosder <xmosder12@gmail.com>2026-07-13 15:32:27 +0200
committerMosder <xmosder12@gmail.com>2026-07-13 15:32:27 +0200
commit32bb25cc2666809759371436a6450574b00c0e6d (patch)
tree119171e968949292509ff2e190ae72acaa5d0fc3
parent0e9be0d902b44894ed747cabb82ea2120f2e4b45 (diff)
feat: added generic functionallity for getting the parsed data from stream
-rw-r--r--analyzer/analyzer.c24
-rw-r--r--analyzer/parser/fight_results.c33
-rw-r--r--analyzer/parser/fight_results.h40
-rw-r--r--analyzer/parser/find_parse_functions.h10
-rw-r--r--analyzer/parser/parser.c79
-rw-r--r--analyzer/parser/parser.h18
-rw-r--r--analyzer/parser/parser_defs.h46
7 files changed, 200 insertions, 50 deletions
diff --git a/analyzer/analyzer.c b/analyzer/analyzer.c
index 2e5caf8..5997c6d 100644
--- a/analyzer/analyzer.c
+++ b/analyzer/analyzer.c
@@ -1,10 +1,12 @@
#include "analyzer.h"
+#include <stdlib.h>
+
#include "parser/parser.h"
#include "utils/tcp.h"
// loop through packets received from pcap_handle and analyze the TCP stream
-void analyzer_loop(TCPStream *stream, pcap_t *pcap_handle) {
+void analyzer_loop(TCPStream *stream, pcap_t *pcap_handle, void (*parsed_data_handler)(ParsedData *parsed_data, size_t n_parsed_data)) {
// read packets from handle
struct pcap_pkthdr *packet_data;
const byte_t *packet;
@@ -23,7 +25,23 @@ void analyzer_loop(TCPStream *stream, pcap_t *pcap_handle) {
if (parsed_len > 0)
remove_parsed_data(stream, parsed_len);
- // TODO: handle parsed data
+ // if there's parsed data - call the parsed data handler
+ if (n_parsed_data > 0)
+ parsed_data_handler(parsed_data, n_parsed_data);
+
+ // free the entire parsed data memory
+ free_parsed_data(parsed_data, n_parsed_data);
+ }
+ }
+}
+
+// file analyzer parsed data handler
+void file_parsed_data_handler(ParsedData *parsed_data, size_t n_parsed_data) {
+ for (size_t i = 0; i < n_parsed_data; i++) {
+ switch (parsed_data[i].data_type) {
+ case TYPE_FIGHT_RESULTS:
+ printf("Fight results\n");
+ break;
}
}
}
@@ -41,7 +59,7 @@ void analyze_file(char *path) {
// analyze the file
TCPStream stream = new_stream();
- analyzer_loop(&stream, handle);
+ analyzer_loop(&stream, handle, file_parsed_data_handler);
destroy_stream(stream);
pcap_close(handle);
}
diff --git a/analyzer/parser/fight_results.c b/analyzer/parser/fight_results.c
index 1db79ea..8275af2 100644
--- a/analyzer/parser/fight_results.c
+++ b/analyzer/parser/fight_results.c
@@ -1,18 +1,39 @@
#include "fight_results.h"
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
-byte_t *find_fight_results(TCPStream *stream, int *length) {
- byte_t *start = memmem(stream->data, stream->len, FIGHT_RESULTS_START, strlen(FIGHT_RESULTS_START));
- byte_t *end = memmem(stream->data, stream->len, FIGHT_RESULTS_END, strlen(FIGHT_RESULTS_END));
+// function to cleanup fight results to be used in ParsedData struct
+void cleanup_fight_results(void *data) {
+ FightResults *fight_results = data;
+ for (size_t i = 0; i < fight_results->num_friendly; i++) {
+ free(fight_results->friendly_results[i].name);
+ free(fight_results->friendly_results[i].gear);
+ free(fight_results->friendly_results[i].items);
+ free(fight_results->friendly_results[i].drifs);
+ }
+ for (size_t i = 0; i < fight_results->num_enemy; i++) {
+ free(fight_results->enemy_results[i].name);
+ }
+}
+
+byte_t *find_fight_results(TCPStream *stream, int offset, int *length) {
+ byte_t *start = memmem(stream->data + offset, stream->len, FIGHT_RESULTS_START, strlen(FIGHT_RESULTS_START));
+ byte_t *end = memmem(stream->data + offset, stream->len, FIGHT_RESULTS_END, strlen(FIGHT_RESULTS_END));
*length = start != NULL && end != NULL ? end - start + strlen(FIGHT_RESULTS_END) : -1;
return start;
}
-FightResults parse_fight_results(byte_t *data, size_t length) {
+ParsedData parse_fight_results(byte_t *data, size_t length) {
+ ParsedData parsed_data;
+ parsed_data.data_type = TYPE_FIGHT_RESULTS;
+
// TODO: actually parse that data
printf("len=%zu\n%.*s\n----------------\n", length, (int)length, data);
- FightResults tmp;
- return tmp;
+
+ parsed_data.data = NULL;
+ parsed_data.data_cleanup = NULL;
+ // parsed_data.data_cleanup = cleanup_fight_results;
+ return parsed_data;
}
diff --git a/analyzer/parser/fight_results.h b/analyzer/parser/fight_results.h
index b275f2b..d8064ca 100644
--- a/analyzer/parser/fight_results.h
+++ b/analyzer/parser/fight_results.h
@@ -2,6 +2,7 @@
// utilities for parsing the fight results data
#include "../utils/tcp.h"
+#include "parser_defs.h"
// Payload structure:
// FIGHT_RESULTS_START EntityResults (SEPARATOR_ENTITY EntityResults)* FIGHT_RESULTS_END
@@ -15,6 +16,8 @@
#define SEPARATOR_ENTITY "[--]"
#define SEPARATOR_RESULT "&"
+#ifndef ENTITY_RESULTS_DEFINED
+#define ENTITY_RESULTS_DEFINED
typedef struct {
int team; // friend or enemy
char *name;
@@ -52,12 +55,15 @@ typedef struct {
char *field34;
char *saturation;
} EntityResults;
+#endif
// values of field "team"
#define TEAM_FRIEND 1
#define TEAM_ENEMY 2
// fight results data for friendly
+#ifndef FRIENDLY_RESULTS_DEFINED
+#define FRIENDLY_RESULTS_DEFINED
typedef struct {
char *name;
int exp;
@@ -71,33 +77,29 @@ typedef struct {
char *saturation_type;
int saturation;
} FriendlyResults;
+#endif
// fight results data for enemy
+#ifndef ENEMY_RESULTS_DEFINED
+#define ENEMY_RESULTS_DEFINED
typedef struct {
char *name;
int level;
} EnemyResults;
+#endif
+
+#define MAX_ENTITIES_PER_SIDE 8
// entire fight resutls
+#ifndef FIGHT_RESULTS_DEFINED
+#define FIGHT_RESULTS_DEFINED
typedef struct {
- int num_friendly;
- FriendlyResults *friendly_results;
- int num_enemy;
- EnemyResults *enemy_results;
+ size_t num_friendly;
+ FriendlyResults friendly_results[MAX_ENTITIES_PER_SIDE];
+ size_t num_enemy;
+ EnemyResults enemy_results[MAX_ENTITIES_PER_SIDE];
} FightResults;
+#endif
-// find the first fight results data in stream
-// params:
-// - stream - stream to find the fight results in
-// - length - length of the fight results data or -1 if there's no end yet
-// returns:
-// pointer to the beginning of fight results data or NULL if there's none
-extern byte_t *find_fight_results(TCPStream *stream, int *length);
-
-// parse given fight results
-// params:
-// - data - fight results data to parse
-// - length - length of fight results data
-// returns:
-// FightResults struct containing parsed data
-extern FightResults parse_fight_results(byte_t *data, size_t length);
+extern find_function_t find_fight_results;
+extern parse_function_t parse_fight_results;
diff --git a/analyzer/parser/find_parse_functions.h b/analyzer/parser/find_parse_functions.h
new file mode 100644
index 0000000..4e53274
--- /dev/null
+++ b/analyzer/parser/find_parse_functions.h
@@ -0,0 +1,10 @@
+// parser/find_parse_functions.h
+// array of find and parse functions for every result type
+
+#include "fight_results.h"
+
+#define RESULT_TYPE_COUNT 1
+
+FindParseFunctions all_find_parse_functions[RESULT_TYPE_COUNT] = {
+ {.find_fn = find_fight_results, .parse_fn = parse_fight_results}
+};
diff --git a/analyzer/parser/parser.c b/analyzer/parser/parser.c
index 7fb155f..246635c 100644
--- a/analyzer/parser/parser.c
+++ b/analyzer/parser/parser.c
@@ -2,19 +2,72 @@
#include <stdlib.h>
-ParsedData *parse_stream(TCPStream *stream, size_t *parsed_len, size_t *n_parsed_data) {
- // TODO: Need to do parsing of the entire thing (loop) and return all of the parsed data
- int length;
- byte_t *start = find_fight_results(stream, &length);
- if (start == NULL) {
- *parsed_len = stream->len;
- }
- else if (length == -1) {
- *parsed_len = 0;
+#include "find_parse_functions.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;
+ for (size_t i = 0; i < RESULT_TYPE_COUNT; i++) {
+ int length;
+ byte_t *data = all_find_parse_functions[i].find_fn(stream, stream_offset, &length);
+ // if it's the first found or earlier than earliest - save it
+ if (data && (!earliest_data || data < earliest_data)) {
+ earliest_data = data;
+ *earliest_length = length;
+ *earliest_parse_fun = all_find_parse_functions[i].parse_fn;
+ }
}
- else {
- parse_fight_results(start, length);
- *parsed_len = start - stream->data + length;
+ return earliest_data;
+}
+
+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));
+ *n_parsed_data = 0;
+
+ int stream_offset = 0;
+ byte_t *earliest_data;
+ do {
+ // find earliest data to parse
+ int earliest_length;
+ parse_function_t *earliest_parse_fun;
+ earliest_data = find_earliest_data(stream, stream_offset, &earliest_length, &earliest_parse_fun);
+
+ // if start of data to parse was found, but not the end, then finish here
+ // set parsed_len, so that the beginning of that data is at the beginning of the stream
+ if (earliest_data && earliest_length == -1) {
+ *parsed_len = earliest_data - stream->data;
+ return parsed_data;
+ }
+
+ // 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);
+ stream_offset = earliest_data - stream->data + earliest_length;
+ }
+ } while (earliest_data);
+
+ // if all was parsed - set parsed_len to stream_len and return the data
+ *parsed_len = stream->len;
+ return parsed_data;
+}
+
+void free_parsed_data(ParsedData *parsed_data, size_t n_parsed_data) {
+ for (size_t i = 0; i < n_parsed_data; i++) {
+ if (parsed_data[i].data_cleanup)
+ parsed_data[i].data_cleanup(parsed_data[i].data);
+ free(parsed_data[i].data);
}
- return NULL;
+ free(parsed_data);
}
diff --git a/analyzer/parser/parser.h b/analyzer/parser/parser.h
index 088bb5d..e2d5c5d 100644
--- a/analyzer/parser/parser.h
+++ b/analyzer/parser/parser.h
@@ -1,17 +1,11 @@
// parser/parser.h
// main parser file
-#include "fight_results.h"
-
#include "../utils/tcp.h"
+#include "fight_results.h"
+#include "parser_defs.h"
-// "generic" type for parsed data
-typedef struct {
- enum { FIGHT_RESULTS } data_type;
- union {
- FightResults fight_results;
- } data;
-} ParsedData;
+#define INIT_PARSED_DATA_CAPACITY 4
// parse a stream of TCP data
// params:
@@ -21,3 +15,9 @@ typedef struct {
// returns:
// pointer to the array of parsed data
extern ParsedData *parse_stream(TCPStream *stream, size_t *parsed_len, size_t *n_parsed_data);
+
+// free the entire parsed data array from parse_stream function
+// params:
+// - parsed_data - parsed data to free
+// - n_parsed_data - count of parsed data
+extern void free_parsed_data(ParsedData *parsed_data, size_t n_parsed_data);
diff --git a/analyzer/parser/parser_defs.h b/analyzer/parser/parser_defs.h
new file mode 100644
index 0000000..f99c2f3
--- /dev/null
+++ b/analyzer/parser/parser_defs.h
@@ -0,0 +1,46 @@
+// parser/parser_defs.h
+// useful definitions for parser files
+
+#include "../utils/tcp.h"
+
+#ifndef RESULTS_ENUM_DEFINED
+#define RESULTS_ENUM_DEFINED
+typedef enum { TYPE_FIGHT_RESULTS } ResultsEnum;
+#endif
+
+#ifndef PARSED_DATA_DEFINED
+#define PARSED_DATA_DEFINED
+// "generic" type for parsed data
+typedef struct {
+ ResultsEnum data_type; // type of data represented by an enum
+ void *data; // pointer to the parsed data
+ void (*data_cleanup)(void *data); // function to cleanup internal allocations inside data
+ // if no internal allocations - this should be NULL
+} ParsedData;
+#endif
+
+// find the first results data of specific type in stream
+// params:
+// - stream - stream to find the data in
+// - offset - offset to start finding data from
+// - length - length of the data or -1 if there's no end yet
+// returns:
+// pointer to the beginning of data or NULL if there's none
+typedef byte_t *find_function_t(TCPStream *stream, int offset, int *length);
+
+// parse given data of specifc type
+// params:
+// - data - data to parse
+// - length - length of data
+// returns:
+// ParsedData struct including the parsed data
+typedef ParsedData parse_function_t(byte_t *data, size_t length);
+
+// struct for holding the find and parse function for every result type
+#ifndef FIND_PARSE_FUNCTIONS_DEFINED
+#define FIND_PARSE_FUNCTIONS_DEFINED
+typedef struct {
+ find_function_t *find_fn;
+ parse_function_t *parse_fn;
+} FindParseFunctions;
+#endif