diff options
| author | Mosder <xmosder12@gmail.com> | 2026-07-13 15:32:27 +0200 |
|---|---|---|
| committer | Mosder <xmosder12@gmail.com> | 2026-07-13 15:32:27 +0200 |
| commit | 32bb25cc2666809759371436a6450574b00c0e6d (patch) | |
| tree | 119171e968949292509ff2e190ae72acaa5d0fc3 | |
| parent | 0e9be0d902b44894ed747cabb82ea2120f2e4b45 (diff) | |
feat: added generic functionallity for getting the parsed data from stream
| -rw-r--r-- | analyzer/analyzer.c | 24 | ||||
| -rw-r--r-- | analyzer/parser/fight_results.c | 33 | ||||
| -rw-r--r-- | analyzer/parser/fight_results.h | 40 | ||||
| -rw-r--r-- | analyzer/parser/find_parse_functions.h | 10 | ||||
| -rw-r--r-- | analyzer/parser/parser.c | 79 | ||||
| -rw-r--r-- | analyzer/parser/parser.h | 18 | ||||
| -rw-r--r-- | analyzer/parser/parser_defs.h | 46 |
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 |
