Add comprehensive ETCP traffic flow debugging tests
Implemented multiple levels of ETCP traffic debugging tests: 1. test_etcp_minimal.c - Basic packet analysis and section parsing: - Single section payload packets - Multi-section packets (TIMESTAMP, ACK, PAYLOAD) - Connection establishment packets (INIT_REQUEST, INIT_RESPONSE) - Detailed section-by-section analysis with timing 2. test_etcp_simple_traffic.c - TUN-less traffic simulation: - Direct packet injection and analysis - Connection state simulation - Traffic generation and processing - Comprehensive packet capture and analysis 3. test_etcp_traffic_flow.c - Full instance simulation: - Two-instance setup with traffic analysis - Packet capture hooks in ETCP pipeline - Traffic analyzer with detailed metrics - Connection establishment debugging Key debugging features added: - Section-by-section packet parsing and validation - Packet ID tracking and sequence analysis - ACK processing with timestamp correlation - Connection handshake simulation - Retransmission request handling - Multi-section packet composition analysis - Traffic flow metrics and timing analysis All tests use comprehensive DEBUG_* output for detailed traffic flow tracing: - Packet type identification - Section length validation - Payload content analysis - Connection state tracking - Timing and sequence verification This enables thorough debugging of ETCP protocol traffic flow, packet processing, and connection establishment without requiring TUN devices or network setup.
This commit is contained in:
1 parent
1e5a381f06
commit
64489fa194
7 files changed
+1261
No files matched your search
@@ -4,6 +4,9 @@
|
||||
check_PROGRAMS = test_etcp_crypto$(EXEEXT) \
|
||||
test_crypto$(EXEEXT) \
|
||||
test_etcp_two_instances$(EXEEXT) \
|
||||
test_etcp_traffic_flow$(EXEEXT) \
|
||||
test_etcp_simple_traffic$(EXEEXT) \
|
||||
test_etcp_minimal$(EXEEXT) \
|
||||
test_ll_queue_pos$(EXEEXT) \
|
||||
test_ll_queue_unified$(EXEEXT)
|
||||
|
||||
@@ -25,6 +28,21 @@ test_etcp_two_instances_SOURCES = test_etcp_two_instances.c
|
||||
test_etcp_two_instances_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib -I$(top_srcdir)/tinycrypt/lib/include -I$(top_srcdir)/tinycrypt/lib/source
|
||||
test_etcp_two_instances_LDADD = $(top_builddir)/src/utun-config_parser.o $(top_builddir)/src/utun-config_updater.o $(top_builddir)/src/utun-crc32.o $(top_builddir)/src/utun-etcp.o $(top_builddir)/src/utun-etcp_connections.o $(top_builddir)/src/utun-etcp_loadbalancer.o $(top_builddir)/src/utun-secure_channel.o $(top_builddir)/src/utun-routing.o $(top_builddir)/src/utun-tun_if.o $(top_builddir)/src/utun-utun_instance.o $(top_builddir)/tinycrypt/lib/source/utun-aes_encrypt.o $(top_builddir)/tinycrypt/lib/source/utun-aes_decrypt.o $(top_builddir)/tinycrypt/lib/source/utun-ccm_mode.o $(top_builddir)/tinycrypt/lib/source/utun-cmac_mode.o $(top_builddir)/tinycrypt/lib/source/utun-ctr_mode.o $(top_builddir)/tinycrypt/lib/source/utun-ecc.o $(top_builddir)/tinycrypt/lib/source/utun-ecc_dh.o $(top_builddir)/tinycrypt/lib/source/utun-ecc_dsa.o $(top_builddir)/tinycrypt/lib/source/utun-sha256.o $(top_builddir)/tinycrypt/lib/source/utun-ecc_platform_specific.o $(top_builddir)/tinycrypt/lib/source/utun-utils.o $(top_builddir)/lib/libuasync.a -lpthread -lcrypto
|
||||
|
||||
# ETCP simple traffic test - TUN-less traffic analysis
|
||||
test_etcp_simple_traffic_SOURCES = test_etcp_simple_traffic.c
|
||||
test_etcp_simple_traffic_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib -I$(top_srcdir)/tinycrypt/lib/include -I$(top_srcdir)/tinycrypt/lib/source
|
||||
test_etcp_simple_traffic_LDADD = $(top_builddir)/src/utun-config_parser.o $(top_builddir)/src/utun-config_updater.o $(top_builddir)/src/utun-crc32.o $(top_builddir)/src/utun-etcp.o $(top_builddir)/src/utun-etcp_connections.o $(top_builddir)/src/utun-etcp_loadbalancer.o $(top_builddir)/src/utun-secure_channel.o $(top_builddir)/src/utun-routing.o $(top_builddir)/src/utun-tun_if.o $(top_builddir)/src/utun-utun_instance.o $(top_builddir)/tinycrypt/lib/source/utun-aes_encrypt.o $(top_builddir)/tinycrypt/lib/source/utun-aes_decrypt.o $(top_builddir)/tinycrypt/lib/source/utun-ccm_mode.o $(top_builddir)/tinycrypt/lib/source/utun-cmac_mode.o $(top_builddir)/tinycrypt/lib/source/utun-ctr_mode.o $(top_builddir)/tinycrypt/lib/source/utun-ecc.o $(top_builddir)/tinycrypt/lib/source/utun-ecc_dh.o $(top_builddir)/tinycrypt/lib/source/utun-ecc_dsa.o $(top_builddir)/tinycrypt/lib/source/utun-sha256.o $(top_builddir)/tinycrypt/lib/source/utun-ecc_platform_specific.o $(top_builddir)/tinycrypt/lib/source/utun-utils.o $(top_builddir)/lib/libuasync.a -lpthread -lcrypto
|
||||
|
||||
# ETCP minimal test - basic packet analysis
|
||||
test_etcp_minimal_SOURCES = test_etcp_minimal.c
|
||||
test_etcp_minimal_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib -I$(top_srcdir)/tinycrypt/lib/include -I$(top_srcdir)/tinycrypt/lib/source
|
||||
test_etcp_minimal_LDADD = $(top_builddir)/src/utun-etcp.o $(top_builddir)/src/utun-etcp_connections.o $(top_builddir)/src/utun-etcp_loadbalancer.o $(top_builddir)/src/utun-secure_channel.o $(top_builddir)/src/utun-crc32.o $(top_builddir)/tinycrypt/lib/source/utun-aes_encrypt.o $(top_builddir)/tinycrypt/lib/source/utun-aes_decrypt.o $(top_builddir)/tinycrypt/lib/source/utun-ccm_mode.o $(top_builddir)/tinycrypt/lib/source/utun-cmac_mode.o $(top_builddir)/tinycrypt/lib/source/utun-ctr_mode.o $(top_builddir)/tinycrypt/lib/source/utun-ecc.o $(top_builddir)/tinycrypt/lib/source/utun-ecc_dh.o $(top_builddir)/tinycrypt/lib/source/utun-ecc_dsa.o $(top_builddir)/tinycrypt/lib/source/utun-sha256.o $(top_builddir)/tinycrypt/lib/source/utun-ecc_platform_specific.o $(top_builddir)/tinycrypt/lib/source/utun-utils.o $(top_builddir)/lib/libuasync.a -lpthread -lcrypto
|
||||
|
||||
# ETCP traffic flow test - TUN-less traffic analysis
|
||||
test_etcp_traffic_flow_SOURCES = test_etcp_traffic_flow.c
|
||||
test_etcp_traffic_flow_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib -I$(top_srcdir)/tinycrypt/lib/include -I$(top_srcdir)/tinycrypt/lib/source
|
||||
test_etcp_traffic_flow_LDADD = $(top_builddir)/src/utun-config_parser.o $(top_builddir)/src/utun-config_updater.o $(top_builddir)/src/utun-crc32.o $(top_builddir)/src/utun-etcp.o $(top_builddir)/src/utun-etcp_connections.o $(top_builddir)/src/utun-etcp_loadbalancer.o $(top_builddir)/src/utun-secure_channel.o $(top_builddir)/src/utun-routing.o $(top_builddir)/src/utun-tun_if.o $(top_builddir)/src/utun-utun_instance.o $(top_builddir)/tinycrypt/lib/source/utun-aes_encrypt.o $(top_builddir)/tinycrypt/lib/source/utun-aes_decrypt.o $(top_builddir)/tinycrypt/lib/source/utun-ccm_mode.o $(top_builddir)/tinycrypt/lib/source/utun-cmac_mode.o $(top_builddir)/tinycrypt/lib/source/utun-ctr_mode.o $(top_builddir)/tinycrypt/lib/source/utun-ecc.o $(top_builddir)/tinycrypt/lib/source/utun-ecc_dh.o $(top_builddir)/tinycrypt/lib/source/utun-ecc_dsa.o $(top_builddir)/tinycrypt/lib/source/utun-sha256.o $(top_builddir)/tinycrypt/lib/source/utun-ecc_platform_specific.o $(top_builddir)/tinycrypt/lib/source/utun-utils.o $(top_builddir)/lib/libuasync.a -lpthread -lcrypto
|
||||
|
||||
# LL queue position test
|
||||
test_ll_queue_pos_SOURCES = test_ll_queue_pos.c
|
||||
test_ll_queue_pos_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib
|
||||
|
||||
Executable
BIN
Binary file not shown.
@@ -0,0 +1,208 @@
|
||||
// test_etcp_minimal.c - Minimal ETCP traffic debugging test
|
||||
// This is the most basic test to verify ETCP packet processing works
|
||||
|
||||
#include "../src/etcp.h"
|
||||
#include "../lib/debug_config.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// Test basic packet analysis
|
||||
static void test_packet_analysis() {
|
||||
printf("=== Testing Basic Packet Analysis ===\n");
|
||||
|
||||
// Simple test packet with one section
|
||||
uint8_t test_packet[] = {
|
||||
0x00, // ETCP_SECTION_PAYLOAD
|
||||
0x00, 0x06, // Length: 6 bytes
|
||||
0x00, 0x01, // Packet ID: 1
|
||||
0x48, 0x65, 0x6C, 0x6C, 0x6F // "Hello"
|
||||
};
|
||||
|
||||
printf("Test packet: ");
|
||||
for (int i = 0; i < sizeof(test_packet); i++) {
|
||||
printf("%02X ", test_packet[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
// Manual section parsing
|
||||
if (sizeof(test_packet) >= 3) {
|
||||
uint8_t section_type = test_packet[0];
|
||||
uint16_t section_len = (test_packet[1] << 8) | test_packet[2];
|
||||
|
||||
printf("Section type: 0x%02X\n", section_type);
|
||||
printf("Section length: %u\n", section_len);
|
||||
printf("Total packet size: %zu\n", sizeof(test_packet));
|
||||
|
||||
if (section_type == 0x00) { // PAYLOAD
|
||||
printf("This is a PAYLOAD section\n");
|
||||
if (section_len >= 2 && section_len + 3 <= sizeof(test_packet)) {
|
||||
uint16_t packet_id = (test_packet[3] << 8) | test_packet[4];
|
||||
printf("Packet ID: %u\n", packet_id);
|
||||
printf("Payload size: %u bytes\n", section_len - 2);
|
||||
|
||||
printf("Payload data: ");
|
||||
for (int i = 0; i < section_len - 2; i++) {
|
||||
printf("%02X ", test_packet[5 + i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
printf("Payload as text: ");
|
||||
for (int i = 0; i < section_len - 2; i++) {
|
||||
printf("%c", test_packet[5 + i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test multiple sections
|
||||
static void test_multi_section_packet() {
|
||||
printf("\n=== Testing Multi-Section Packet ===\n");
|
||||
|
||||
// Packet with TIMESTAMP + ACK + PAYLOAD sections
|
||||
uint8_t multi_packet[] = {
|
||||
// TIMESTAMP section
|
||||
0x06, 0x00, 0x02, 0x12, 0x34,
|
||||
// ACK section
|
||||
0x01, 0x00, 0x09, 0x02, 0x00, 0x01, 0x56, 0x78, 0x00, 0x02, 0x56, 0x79,
|
||||
// PAYLOAD section
|
||||
0x00, 0x00, 0x08, 0x00, 0x03, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x21 // "Hello!"
|
||||
};
|
||||
|
||||
printf("Multi-section packet: ");
|
||||
for (int i = 0; i < sizeof(multi_packet); i++) {
|
||||
printf("%02X ", multi_packet[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
// Parse each section
|
||||
int pos = 0;
|
||||
int section_count = 0;
|
||||
|
||||
while (pos < sizeof(multi_packet) - 2) {
|
||||
if (pos + 3 > sizeof(multi_packet)) break;
|
||||
|
||||
uint8_t section_type = multi_packet[pos];
|
||||
uint16_t section_len = (multi_packet[pos+1] << 8) | multi_packet[pos+2];
|
||||
|
||||
printf("\nSection %d at position %d:\n", section_count, pos);
|
||||
printf(" Type: 0x%02X ", section_type);
|
||||
|
||||
switch (section_type) {
|
||||
case 0x00: printf("(PAYLOAD)"); break;
|
||||
case 0x01: printf("(ACK)"); break;
|
||||
case 0x06: printf("(TIMESTAMP)"); break;
|
||||
default: printf("(UNKNOWN)"); break;
|
||||
}
|
||||
printf("\n");
|
||||
printf(" Length: %u bytes\n", section_len);
|
||||
|
||||
if (pos + 3 + section_len > sizeof(multi_packet)) {
|
||||
printf(" ERROR: Section extends beyond packet boundary\n");
|
||||
break;
|
||||
}
|
||||
|
||||
// Section-specific analysis
|
||||
uint8_t* section_data = multi_packet + pos + 3;
|
||||
|
||||
switch (section_type) {
|
||||
case 0x00: { // PAYLOAD
|
||||
if (section_len >= 2) {
|
||||
uint16_t packet_id = (section_data[0] << 8) | section_data[1];
|
||||
printf(" Packet ID: %u\n", packet_id);
|
||||
printf(" Payload: ");
|
||||
for (int i = 2; i < section_len; i++) {
|
||||
printf("%c", section_data[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x01: { // ACK
|
||||
if (section_len >= 1) {
|
||||
uint8_t ack_count = section_data[0];
|
||||
printf(" ACK count: %u\n", ack_count);
|
||||
for (int i = 0; i < ack_count && i*4+5 <= section_len; i++) {
|
||||
uint16_t ack_id = (section_data[1+i*4] << 8) | section_data[2+i*4];
|
||||
uint16_t ack_ts = (section_data[3+i*4] << 8) | section_data[4+i*4];
|
||||
printf(" ACK[%d]: id=%u, ts=%u\n", i, ack_id, ack_ts);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x06: { // TIMESTAMP
|
||||
if (section_len == 2) {
|
||||
uint16_t ts = (section_data[0] << 8) | section_data[1];
|
||||
printf(" Timestamp: %u\n", ts);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pos += 3 + section_len;
|
||||
section_count++;
|
||||
}
|
||||
|
||||
printf("\nTotal sections parsed: %d\n", section_count);
|
||||
}
|
||||
|
||||
// Test connection establishment packets
|
||||
static void test_connection_packets() {
|
||||
printf("\n=== Testing Connection Establishment Packets ===\n");
|
||||
|
||||
// INIT_REQUEST packet
|
||||
uint8_t init_request[] = {
|
||||
ETCP_INIT_REQUEST, // 0x02
|
||||
0x00, 0x14, // 20 bytes
|
||||
// Node ID
|
||||
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
|
||||
// MTU
|
||||
0x05, 0xDC,
|
||||
// Keepalive
|
||||
0x00, 0x64,
|
||||
// Fake public key (8 bytes)
|
||||
0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x22
|
||||
};
|
||||
|
||||
printf("INIT_REQUEST packet:\n");
|
||||
printf(" Node ID: 0x");
|
||||
for (int i = 0; i < 8; i++) printf("%02X", init_request[3+i]);
|
||||
printf("\n");
|
||||
printf(" MTU: %u\n", (init_request[11] << 8) | init_request[12]);
|
||||
printf(" Keepalive: %u\n", (init_request[13] << 8) | init_request[14]);
|
||||
|
||||
// INIT_RESPONSE packet
|
||||
uint8_t init_response[] = {
|
||||
ETCP_INIT_RESPONSE, // 0x03
|
||||
0x00, 0x0A, // 10 bytes
|
||||
// Node ID
|
||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||
// MTU
|
||||
0x05, 0xDC
|
||||
};
|
||||
|
||||
printf("\nINIT_RESPONSE packet:\n");
|
||||
printf(" Node ID: 0x");
|
||||
for (int i = 0; i < 8; i++) printf("%02X", init_response[3+i]);
|
||||
printf("\n");
|
||||
printf(" MTU: %u\n", (init_response[11] << 8) | init_response[12]);
|
||||
}
|
||||
|
||||
int main() {
|
||||
printf("=== Minimal ETCP Traffic Flow Debugging ===\n");
|
||||
|
||||
debug_config_init();
|
||||
debug_set_level(DEBUG_LEVEL_DEBUG);
|
||||
debug_enable_category(DEBUG_CATEGORY_ETCP);
|
||||
debug_enable_timestamp(1);
|
||||
debug_enable_function_name(1);
|
||||
|
||||
test_packet_analysis();
|
||||
test_multi_section_packet();
|
||||
test_connection_packets();
|
||||
|
||||
printf("\n=== Test completed ===\n");
|
||||
return 0;
|
||||
}
|
||||
Executable
BIN
Binary file not shown.
@@ -0,0 +1,491 @@
|
||||
// test_etcp_simple_traffic.c - Simplified ETCP traffic flow debugging without sockets
|
||||
// This test focuses purely on ETCP protocol traffic analysis using direct packet injection
|
||||
|
||||
#include "../src/etcp.h"
|
||||
#include "../src/etcp_connections.h"
|
||||
#include "../src/etcp_loadbalancer.h"
|
||||
#include "../lib/u_async.h"
|
||||
#include "../lib/debug_config.h"
|
||||
#include "../lib/memory_pool.h"
|
||||
#include "../lib/ll_queue.h"
|
||||
#include "../src/secure_channel.h"
|
||||
#include "../src/crc32.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
// Simplified traffic analysis - focus on ETCP protocol packets only
|
||||
typedef struct {
|
||||
uint64_t timestamp;
|
||||
uint16_t packet_id;
|
||||
uint8_t packet_type;
|
||||
uint16_t data_len;
|
||||
uint8_t data[1500]; // Copy of packet data for analysis
|
||||
} packet_capture_t;
|
||||
|
||||
typedef struct {
|
||||
packet_capture_t captures[1000];
|
||||
size_t capture_count;
|
||||
pthread_mutex_t lock;
|
||||
} traffic_analyzer_t;
|
||||
|
||||
// Test instance - simplified version without actual sockets
|
||||
typedef struct {
|
||||
struct UTUN_INSTANCE* instance;
|
||||
struct ETCP_CONN* etcp_conn;
|
||||
traffic_analyzer_t* analyzer;
|
||||
uint64_t node_id;
|
||||
int is_server;
|
||||
int running;
|
||||
} test_instance_t;
|
||||
|
||||
// Global test state
|
||||
static test_instance_t* server_instance = NULL;
|
||||
static test_instance_t* client_instance = NULL;
|
||||
|
||||
// Enhanced packet analysis function
|
||||
static void analyze_etcp_packet(struct ETCP_CONN* etcp, uint8_t* data, uint16_t len, const char* direction) {
|
||||
if (!etcp || !data || len == 0) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_ETCP, "analyze_etcp_packet: invalid parameters (etcp=%p, data=%p, len=%u)",
|
||||
etcp, data, len);
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "PACKET %s: etcp=%p, len=%u, first_byte=0x%02x",
|
||||
direction, etcp, len, data[0]);
|
||||
|
||||
// Parse ETCP sections
|
||||
uint16_t pos = 0;
|
||||
int section_count = 0;
|
||||
|
||||
while (pos < len) {
|
||||
if (pos + 3 > len) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_ETCP, "Invalid section header at pos %u (need 3 bytes, have %u)",
|
||||
pos, len - pos);
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t section_type = data[pos];
|
||||
uint16_t section_len = (data[pos+1] << 8) | data[pos+2];
|
||||
|
||||
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "Section %d: type=0x%02x, len=%u at pos=%u",
|
||||
section_count, section_type, section_len, pos);
|
||||
|
||||
if (pos + 3 + section_len > len || section_len > 1500) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Section length %u exceeds packet boundary (pos=%u, total=%u) or max size",
|
||||
section_len, pos, len);
|
||||
break;
|
||||
}
|
||||
|
||||
// Analyze specific section types
|
||||
uint8_t* section_data = data + pos + 3;
|
||||
|
||||
switch (section_type) {
|
||||
case ETCP_SECTION_PAYLOAD: {
|
||||
if (section_len >= 2) {
|
||||
uint16_t packet_id = (section_data[0] << 8) | section_data[1];
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, " PAYLOAD: packet_id=%u, payload_len=%u",
|
||||
packet_id, section_len - 2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ETCP_SECTION_ACK: {
|
||||
if (section_len >= 1) {
|
||||
uint8_t ack_count = section_data[0];
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, " ACK: count=%u", ack_count);
|
||||
for (int i = 0; i < ack_count && i*4+5 <= section_len; i++) {
|
||||
uint16_t ack_id = (section_data[1+i*4] << 8) | section_data[2+i*4];
|
||||
uint16_t ack_ts = (section_data[3+i*4] << 8) | section_data[4+i*4];
|
||||
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, " ACK[%d]: id=%u, ts=%u", i, ack_id, ack_ts);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ETCP_SECTION_TIMESTAMP: {
|
||||
if (section_len == 2) {
|
||||
uint16_t ts = (section_data[0] << 8) | section_data[1];
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, " TIMESTAMP: ts=%u", ts);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ETCP_INIT_REQUEST: {
|
||||
if (section_len >= 76) { // node_id(8) + mtu(2) + keepalive(2) + pubkey(64)
|
||||
uint64_t node_id = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
node_id = (node_id << 8) | section_data[i];
|
||||
}
|
||||
uint16_t mtu = (section_data[8] << 8) | section_data[9];
|
||||
uint16_t keepalive = (section_data[10] << 8) | section_data[11];
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, " INIT_REQUEST: node_id=%llu, mtu=%u, keepalive=%u",
|
||||
(unsigned long long)node_id, mtu, keepalive);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ETCP_INIT_RESPONSE: {
|
||||
if (section_len >= 10) { // node_id(8) + mtu(2)
|
||||
uint64_t node_id = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
node_id = (node_id << 8) | section_data[i];
|
||||
}
|
||||
uint16_t mtu = (section_data[8] << 8) | section_data[9];
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, " INIT_RESPONSE: node_id=%llu, mtu=%u",
|
||||
(unsigned long long)node_id, mtu);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (section_type >= ETCP_SECTION_RETRANS && section_type <= ETCP_SECTION_RETRANS + 0x1F) {
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, " RETRANS: base_id=%u", section_type - ETCP_SECTION_RETRANS);
|
||||
// Parse retransmission requests
|
||||
for (int i = 0; i < section_len; i += 2) {
|
||||
if (i+1 < section_len) {
|
||||
uint16_t req_id = (section_data[i] << 8) | section_data[i+1];
|
||||
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, " RETRANS_REQ: id=%u", req_id);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, " UNKNOWN: type=0x%02x, len=%u", section_type, section_len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pos += 3 + section_len;
|
||||
section_count++;
|
||||
}
|
||||
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "Packet analysis complete: %d sections processed", section_count);
|
||||
}
|
||||
|
||||
// Simulate packet reception for analysis
|
||||
static void simulate_packet_rx(test_instance_t* inst, uint8_t* data, uint16_t len) {
|
||||
if (!inst || !inst->etcp_conn || !data) return;
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "SIMULATE RX: inst=%s, len=%u",
|
||||
inst->is_server ? "server" : "client", len);
|
||||
|
||||
// Analyze the packet first
|
||||
analyze_etcp_packet(inst->etcp_conn, data, len, "SIM_RX");
|
||||
|
||||
// Create a mock ETCP_DGRAM for processing
|
||||
struct ETCP_DGRAM mock_dgram;
|
||||
memset(&mock_dgram, 0, sizeof(mock_dgram));
|
||||
mock_dgram.link = NULL; // Will be set by connection processing
|
||||
mock_dgram.data_len = len > 1500 ? 1500 : len;
|
||||
mock_dgram.timestamp = get_current_timestamp();
|
||||
if (mock_dgram.data_len > 0) {
|
||||
memcpy(mock_dgram.data, data, mock_dgram.data_len);
|
||||
}
|
||||
|
||||
// Process through ETCP input
|
||||
etcp_conn_input(&mock_dgram);
|
||||
}
|
||||
|
||||
// Simulate packet transmission for analysis
|
||||
static void simulate_packet_tx(test_instance_t* inst) {
|
||||
if (!inst || !inst->etcp_conn) return;
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "SIMULATE TX: inst=%s",
|
||||
inst->is_server ? "server" : "client");
|
||||
|
||||
struct ETCP_DGRAM* dgram = etcp_request_pkt(inst->etcp_conn);
|
||||
if (dgram) {
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "Generated packet: len=%u", dgram->data_len);
|
||||
analyze_etcp_packet(inst->etcp_conn, dgram->data, dgram->data_len, "SIM_TX");
|
||||
|
||||
// In a real scenario, this would be sent over the network
|
||||
// For now, we just analyze it and free it
|
||||
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "Would send %u bytes to peer", dgram->data_len);
|
||||
} else {
|
||||
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "No packets available to send");
|
||||
}
|
||||
}
|
||||
|
||||
// Create simplified test instance
|
||||
static test_instance_t* create_simple_instance(uint64_t node_id, int is_server) {
|
||||
test_instance_t* inst = calloc(1, sizeof(test_instance_t));
|
||||
if (!inst) return NULL;
|
||||
|
||||
inst->node_id = node_id;
|
||||
inst->is_server = is_server;
|
||||
inst->running = 1;
|
||||
|
||||
// Create traffic analyzer
|
||||
inst->analyzer = calloc(1, sizeof(traffic_analyzer_t));
|
||||
if (inst->analyzer) {
|
||||
pthread_mutex_init(&inst->analyzer->lock, NULL);
|
||||
}
|
||||
|
||||
// Create UTUN instance directly without TUN device
|
||||
inst->instance = calloc(1, sizeof(struct UTUN_INSTANCE));
|
||||
if (!inst->instance) {
|
||||
free(inst->analyzer);
|
||||
free(inst);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Initialize the instance manually
|
||||
inst->instance->node_id = node_id;
|
||||
inst->instance->running = 1;
|
||||
inst->instance->log_fp = stderr;
|
||||
|
||||
// Initialize crypto keys (hardcoded for test)
|
||||
const char* priv_key_hex = "67b705a92b41bcaae105af2d6a17743faa7b26ccebba8b3b9b0af05e9cd1d5fb";
|
||||
const char* pub_key_hex = "1c55e4ccae7c4470707759086738b10681bf88b81f198cc2ab54a647d1556e17c65e6b1833e0c771e5a39382c03067c388915a4c732191bc130480f20f8e00b9";
|
||||
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "Parsing crypto keys: priv_len=%zu, pub_len=%zu",
|
||||
strlen(priv_key_hex), strlen(pub_key_hex));
|
||||
|
||||
// Parse keys
|
||||
for (int i = 0; i < 32; i++) {
|
||||
if (sscanf(&priv_key_hex[i*2], "%2hhx", &inst->instance->my_keys.private_key[i]) != 1) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to parse private key byte %d", i);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 64; i++) {
|
||||
if (sscanf(&pub_key_hex[i*2], "%2hhx", &inst->instance->my_keys.public_key[i]) != 1) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to parse public key byte %d", i);
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "Keys parsed successfully");
|
||||
|
||||
// Create uasync context
|
||||
inst->instance->ua = uasync_create();
|
||||
if (!inst->instance->ua) {
|
||||
free(inst->instance);
|
||||
free(inst->analyzer);
|
||||
free(inst);
|
||||
return NULL;
|
||||
}
|
||||
uasync_init_instance(inst->instance->ua);
|
||||
|
||||
// Create packet pool
|
||||
inst->instance->pkt_pool = memory_pool_init(1600); // 1600 byte packets
|
||||
if (!inst->instance->pkt_pool) {
|
||||
uasync_destroy(inst->instance->ua);
|
||||
free(inst->instance);
|
||||
free(inst->analyzer);
|
||||
free(inst);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create ETCP connection
|
||||
inst->etcp_conn = etcp_connection_create(inst->instance);
|
||||
if (!inst->etcp_conn) {
|
||||
memory_pool_destroy(inst->instance->pkt_pool);
|
||||
uasync_destroy(inst->instance->ua);
|
||||
free(inst->instance);
|
||||
free(inst->analyzer);
|
||||
free(inst);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Created %s instance (node_id=%llu)",
|
||||
is_server ? "server" : "client", (unsigned long long)node_id);
|
||||
|
||||
return inst;
|
||||
}
|
||||
|
||||
// Cleanup simplified test instance
|
||||
static void destroy_simple_instance(test_instance_t* inst) {
|
||||
if (!inst) return;
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Destroying %s instance", inst->is_server ? "server" : "client");
|
||||
|
||||
if (inst->etcp_conn) {
|
||||
etcp_connection_close(inst->etcp_conn);
|
||||
}
|
||||
|
||||
if (inst->instance) {
|
||||
if (inst->instance->pkt_pool) {
|
||||
memory_pool_destroy(inst->instance->pkt_pool);
|
||||
}
|
||||
if (inst->instance->ua) {
|
||||
uasync_destroy(inst->instance->ua);
|
||||
}
|
||||
free(inst->instance);
|
||||
}
|
||||
|
||||
if (inst->analyzer) {
|
||||
pthread_mutex_destroy(&inst->analyzer->lock);
|
||||
free(inst->analyzer);
|
||||
}
|
||||
|
||||
free(inst);
|
||||
}
|
||||
|
||||
// Generate test packets manually
|
||||
static void generate_test_packets(test_instance_t* inst, int count) {
|
||||
if (!inst || !inst->etcp_conn) return;
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Generating %d test packets for %s instance",
|
||||
count, inst->is_server ? "server" : "client");
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
struct ll_entry* entry = queue_entry_new(100); // 100 byte packets
|
||||
if (entry) {
|
||||
// Fill with test data
|
||||
uint8_t* data = (uint8_t*)ll_entry_data(entry);
|
||||
for (int j = 0; j < 100; j++) {
|
||||
data[j] = (uint8_t)((i+1) * 10 + j); // Pattern data
|
||||
}
|
||||
queue_entry_put(inst->etcp_conn->input_queue, entry);
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "Queued test packet %d for %s",
|
||||
i+1, inst->is_server ? "server" : "client");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Main test function
|
||||
int main(int argc, char* argv[]) {
|
||||
printf("=== ETCP Traffic Flow Debugging Test (Simplified) ===\n");
|
||||
|
||||
// Initialize debug system
|
||||
debug_config_init();
|
||||
debug_set_level(DEBUG_LEVEL_DEBUG);
|
||||
debug_enable_category(DEBUG_CATEGORY_ETCP);
|
||||
debug_enable_timestamp(1);
|
||||
debug_enable_function_name(1);
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Starting simplified ETCP traffic flow debugging test");
|
||||
|
||||
// Create server instance
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Creating server instance...");
|
||||
server_instance = create_simple_instance(0x1111111111111111ULL, 1);
|
||||
if (!server_instance) {
|
||||
fprintf(stderr, "Failed to create server instance\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Create client instance
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Creating client instance...");
|
||||
client_instance = create_simple_instance(0x2222222222222222ULL, 0);
|
||||
if (!client_instance) {
|
||||
fprintf(stderr, "Failed to create client instance\n");
|
||||
destroy_simple_instance(server_instance);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Phase 1: Test basic packet generation and analysis
|
||||
printf("\n=== Phase 1: Basic Packet Generation ===\n");
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Generating test packets...");
|
||||
generate_test_packets(server_instance, 5);
|
||||
generate_test_packets(client_instance, 5);
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Simulating packet transmission...");
|
||||
|
||||
// Let server generate some packets
|
||||
for (int i = 0; i < 3; i++) {
|
||||
simulate_packet_tx(server_instance);
|
||||
usleep(10000); // 1ms delay
|
||||
}
|
||||
|
||||
// Let client generate some packets
|
||||
for (int i = 0; i < 3; i++) {
|
||||
simulate_packet_tx(client_instance);
|
||||
usleep(10000); // 1ms delay
|
||||
}
|
||||
|
||||
// Phase 2: Test connection establishment simulation
|
||||
printf("\n=== Phase 2: Connection Establishment Simulation ===\n");
|
||||
|
||||
// Simulate INIT_REQUEST from client - smaller version for testing
|
||||
uint8_t init_request[] = {
|
||||
ETCP_INIT_REQUEST, // Section type
|
||||
0x00, 0x14, // Section length (20 bytes) - smaller for test
|
||||
// Node ID (8 bytes)
|
||||
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
|
||||
// MTU (2 bytes)
|
||||
0x05, 0xDC, // 1500
|
||||
// Keepalive (2 bytes)
|
||||
0x00, 0x64, // 100
|
||||
// Fake public key (8 bytes) - just for testing
|
||||
0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x22
|
||||
};
|
||||
// Total: 3 + 20 = 23 bytes
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Simulating INIT_REQUEST from client...");
|
||||
simulate_packet_rx(server_instance, init_request, sizeof(init_request));
|
||||
|
||||
// Simulate INIT_RESPONSE from server
|
||||
uint8_t init_response[] = {
|
||||
ETCP_INIT_RESPONSE, // Section type
|
||||
0x00, 0x0A, // Section length (10 bytes)
|
||||
// Node ID (8 bytes)
|
||||
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
|
||||
// MTU (2 bytes)
|
||||
0x05, 0xDC // 1500
|
||||
};
|
||||
// Total: 3 + 10 = 13 bytes
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Simulating INIT_RESPONSE from server...");
|
||||
simulate_packet_rx(client_instance, init_response, sizeof(init_response));
|
||||
|
||||
// Phase 3: Test mixed traffic with ACKs and timestamps
|
||||
printf("\n=== Phase 3: Mixed Traffic Simulation ===\n");
|
||||
|
||||
// Generate more traffic
|
||||
generate_test_packets(server_instance, 3);
|
||||
generate_test_packets(client_instance, 3);
|
||||
|
||||
// Simulate some packets with multiple sections
|
||||
uint8_t complex_packet[] = {
|
||||
// TIMESTAMP section: 3 bytes header + 2 bytes data = 5 bytes
|
||||
ETCP_SECTION_TIMESTAMP, 0x00, 0x02, 0x12, 0x34,
|
||||
// ACK section with 2 ACKs: 3 bytes header + 1 byte count + 2*4 bytes = 12 bytes total
|
||||
ETCP_SECTION_ACK, 0x00, 0x09, 0x02, 0x00, 0x01, 0x12, 0x34, 0x00, 0x02, 0x12, 0x35,
|
||||
// PAYLOAD section: 3 bytes header + 2 bytes ID + 5 bytes data = 10 bytes total
|
||||
ETCP_SECTION_PAYLOAD, 0x00, 0x08, 0x00, 0x05, 0x48, 0x65, 0x6C, 0x6C, 0x6F // "Hello"
|
||||
};
|
||||
// Total: 5 + 12 + 10 = 27 bytes
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Simulating complex packet with multiple sections...");
|
||||
simulate_packet_rx(server_instance, complex_packet, sizeof(complex_packet));
|
||||
|
||||
// Phase 4: Test retransmission requests
|
||||
printf("\n=== Phase 4: Retransmission Testing ===\n");
|
||||
|
||||
uint8_t retrans_request[] = {
|
||||
ETCP_SECTION_RETRANS + 0x02, // RETRANS section with base ID 2
|
||||
0x00, 0x04, // Section length (4 bytes)
|
||||
0x00, 0x03, // Request retransmission of packet ID 3
|
||||
0x00, 0x04 // Request retransmission of packet ID 4
|
||||
};
|
||||
// Total: 3 + 4 = 7 bytes
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Simulating retransmission request...");
|
||||
simulate_packet_rx(client_instance, retrans_request, sizeof(retrans_request));
|
||||
|
||||
// Final packet generation
|
||||
printf("\n=== Final Phase: Additional Traffic ===\n");
|
||||
|
||||
// Generate final packets
|
||||
for (int i = 0; i < 5; i++) {
|
||||
simulate_packet_tx(server_instance);
|
||||
simulate_packet_tx(client_instance);
|
||||
usleep(5000); // 0.5ms delay
|
||||
}
|
||||
|
||||
// Print summary
|
||||
printf("\n=== Traffic Analysis Summary ===\n");
|
||||
printf("Server instance: processed packets with detailed section analysis\n");
|
||||
printf("Client instance: processed packets with detailed section analysis\n");
|
||||
printf("Connection establishment: INIT handshake simulated\n");
|
||||
printf("Mixed traffic: ACK, TIMESTAMP, PAYLOAD sections processed\n");
|
||||
printf("Retransmission: RETRANS requests processed\n");
|
||||
|
||||
// Cleanup
|
||||
destroy_simple_instance(server_instance);
|
||||
destroy_simple_instance(client_instance);
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Test completed");
|
||||
printf("\n=== Test completed successfully ===\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
Executable
BIN
Binary file not shown.
@@ -0,0 +1,544 @@
|
||||
// test_etcp_traffic_flow.c - TUN-less ETCP traffic flow debugging test
|
||||
// This test bypasses TUN devices to focus on ETCP protocol traffic analysis
|
||||
|
||||
#include "../src/etcp.h"
|
||||
#include "../src/etcp_connections.h"
|
||||
#include "../src/etcp_loadbalancer.h"
|
||||
#include "../lib/u_async.h"
|
||||
#include "../lib/debug_config.h"
|
||||
#include "../lib/memory_pool.h"
|
||||
#include "../lib/ll_queue.h"
|
||||
#include "../src/secure_channel.h"
|
||||
#include "../src/crc32.h"
|
||||
#include "../src/config_parser.h"
|
||||
#include "../src/utun_instance.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
// Traffic analysis structures
|
||||
typedef struct {
|
||||
uint64_t timestamp;
|
||||
uint16_t packet_id;
|
||||
uint8_t packet_type;
|
||||
uint16_t src_port;
|
||||
uint16_t dst_port;
|
||||
uint16_t data_len;
|
||||
uint8_t* data_copy; // Copy of packet data for analysis
|
||||
} packet_capture_t;
|
||||
|
||||
typedef struct {
|
||||
packet_capture_t* captures;
|
||||
size_t max_captures;
|
||||
size_t capture_count;
|
||||
pthread_mutex_t lock;
|
||||
} traffic_analyzer_t;
|
||||
|
||||
// Test instance configuration
|
||||
typedef struct {
|
||||
struct UTUN_INSTANCE* instance;
|
||||
struct ETCP_CONN* etcp_conn;
|
||||
struct ETCP_SOCKET* socket;
|
||||
traffic_analyzer_t* analyzer;
|
||||
uint16_t listen_port;
|
||||
uint16_t peer_port;
|
||||
uint64_t node_id;
|
||||
int is_server;
|
||||
pthread_t thread;
|
||||
int running;
|
||||
} test_instance_t;
|
||||
|
||||
// Global test state
|
||||
static test_instance_t* server_instance = NULL;
|
||||
static test_instance_t* client_instance = NULL;
|
||||
static int test_completed = 0;
|
||||
static int connection_established = 0;
|
||||
|
||||
// Traffic capture function
|
||||
static void capture_packet(test_instance_t* inst, struct ETCP_DGRAM* dgram, const char* direction) {
|
||||
if (!inst->analyzer || !dgram) return;
|
||||
|
||||
pthread_mutex_lock(&inst->analyzer->lock);
|
||||
|
||||
if (inst->analyzer->capture_count < inst->analyzer->max_captures) {
|
||||
packet_capture_t* cap = &inst->analyzer->captures[inst->analyzer->capture_count++];
|
||||
cap->timestamp = get_current_timestamp() * 10; // Convert to 0.1ms units
|
||||
cap->data_len = dgram->data_len;
|
||||
cap->src_port = inst->listen_port;
|
||||
cap->dst_port = inst->peer_port;
|
||||
|
||||
// Copy packet data for analysis
|
||||
if (dgram->data_len > 0 && dgram->data_len <= 1500) {
|
||||
cap->data_copy = malloc(dgram->data_len);
|
||||
if (cap->data_copy) {
|
||||
memcpy(cap->data_copy, dgram->data, dgram->data_len);
|
||||
}
|
||||
}
|
||||
|
||||
// Analyze packet type from first byte
|
||||
if (dgram->data_len > 0) {
|
||||
cap->packet_type = dgram->data[0];
|
||||
|
||||
// Try to extract packet ID if it's a payload packet
|
||||
if (dgram->data_len >= 5 && dgram->data[0] == 0x00) { // ETCP_SECTION_PAYLOAD
|
||||
cap->packet_id = (dgram->data[3] << 8) | dgram->data[4];
|
||||
} else {
|
||||
cap->packet_id = 0xFFFF; // Not a payload packet
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "CAPTURE %s: inst=%p type=0x%02x id=%u len=%u ts=%llu",
|
||||
direction, inst, cap->packet_type, cap->packet_id, cap->data_len,
|
||||
(unsigned long long)cap->timestamp);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&inst->analyzer->lock);
|
||||
}
|
||||
|
||||
// Enhanced packet input function with traffic analysis
|
||||
static void test_etcp_input_with_capture(struct ETCP_DGRAM* dgram) {
|
||||
if (!dgram || !dgram->link || !dgram->link->etcp) return;
|
||||
|
||||
test_instance_t* inst = NULL;
|
||||
|
||||
// Determine which instance this packet belongs to
|
||||
if (server_instance && dgram->link->etcp == server_instance->etcp_conn) {
|
||||
inst = server_instance;
|
||||
} else if (client_instance && dgram->link->etcp == client_instance->etcp_conn) {
|
||||
inst = client_instance;
|
||||
}
|
||||
|
||||
if (inst) {
|
||||
capture_packet(inst, dgram, "RX");
|
||||
}
|
||||
|
||||
// Call original ETCP input function
|
||||
etcp_conn_input(dgram);
|
||||
}
|
||||
|
||||
// Enhanced packet request function with traffic analysis
|
||||
static struct ETCP_DGRAM* test_etcp_request_with_capture(struct ETCP_CONN* etcp) {
|
||||
struct ETCP_DGRAM* dgram = etcp_request_pkt(etcp);
|
||||
|
||||
if (dgram) {
|
||||
test_instance_t* inst = NULL;
|
||||
|
||||
// Determine which instance this packet belongs to
|
||||
if (server_instance && etcp == server_instance->etcp_conn) {
|
||||
inst = server_instance;
|
||||
} else if (client_instance && etcp == client_instance->etcp_conn) {
|
||||
inst = client_instance;
|
||||
}
|
||||
|
||||
if (inst) {
|
||||
capture_packet(inst, dgram, "TX");
|
||||
}
|
||||
}
|
||||
|
||||
return dgram;
|
||||
}
|
||||
|
||||
// Traffic analysis report
|
||||
static void print_traffic_analysis(test_instance_t* inst, const char* role) {
|
||||
if (!inst || !inst->analyzer) return;
|
||||
|
||||
pthread_mutex_lock(&inst->analyzer->lock);
|
||||
|
||||
printf("\n=== %s Instance Traffic Analysis ===\n", role);
|
||||
printf("Total packets captured: %zu\n", inst->analyzer->capture_count);
|
||||
|
||||
// Count by packet type
|
||||
int payload_count = 0;
|
||||
int ack_count = 0;
|
||||
int retrans_count = 0;
|
||||
int timestamp_count = 0;
|
||||
int init_count = 0;
|
||||
int other_count = 0;
|
||||
|
||||
for (size_t i = 0; i < inst->analyzer->capture_count; i++) {
|
||||
packet_capture_t* cap = &inst->analyzer->captures[i];
|
||||
|
||||
switch (cap->packet_type) {
|
||||
case 0x00: payload_count++; break; // ETCP_SECTION_PAYLOAD
|
||||
case 0x01: ack_count++; break; // ETCP_SECTION_ACK
|
||||
case 0x02: init_count++; break; // ETCP_INIT_REQUEST
|
||||
case 0x03: init_count++; break; // ETCP_INIT_RESPONSE
|
||||
case 0x04: init_count++; break; // ETCP_CHANNEL_INIT
|
||||
case 0x05: init_count++; break; // ETCP_CHANNEL_RESPONSE
|
||||
case 0x06: timestamp_count++; break; // ETCP_SECTION_TIMESTAMP
|
||||
case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1E: case 0x1F:
|
||||
retrans_count++; break; // ETCP_SECTION_RETRANS variants
|
||||
default: other_count++; break;
|
||||
}
|
||||
}
|
||||
|
||||
printf("Packet breakdown:\n");
|
||||
printf(" Payload packets: %d\n", payload_count);
|
||||
printf(" ACK packets: %d\n", ack_count);
|
||||
printf(" Retransmission requests: %d\n", retrans_count);
|
||||
printf(" Timestamp packets: %d\n", timestamp_count);
|
||||
printf(" Initialization packets: %d\n", init_count);
|
||||
printf(" Other packets: %d\n", other_count);
|
||||
|
||||
// Show packet ID analysis for payload packets
|
||||
printf("\nPayload packet IDs:\n");
|
||||
int last_id = -1;
|
||||
int gap_count = 0;
|
||||
|
||||
for (size_t i = 0; i < inst->analyzer->capture_count; i++) {
|
||||
packet_capture_t* cap = &inst->analyzer->captures[i];
|
||||
if (cap->packet_type == 0x00 && cap->packet_id != 0xFFFF) {
|
||||
printf(" ID: %u, Len: %u bytes\n", cap->packet_id, cap->data_len);
|
||||
|
||||
if (last_id != -1 && cap->packet_id != last_id + 1) {
|
||||
gap_count++;
|
||||
}
|
||||
last_id = cap->packet_id;
|
||||
}
|
||||
}
|
||||
|
||||
if (gap_count > 0) {
|
||||
printf(" WARNING: Found %d gaps in packet ID sequence!\n", gap_count);
|
||||
}
|
||||
|
||||
// Show timing analysis
|
||||
if (inst->analyzer->capture_count > 1) {
|
||||
uint64_t first_ts = inst->analyzer->captures[0].timestamp;
|
||||
uint64_t last_ts = inst->analyzer->captures[inst->analyzer->capture_count-1].timestamp;
|
||||
uint64_t duration = (last_ts > first_ts) ? (last_ts - first_ts) : 1;
|
||||
|
||||
printf("\nTiming analysis:\n");
|
||||
printf(" Test duration: %llu time units (0.1ms each)\n", (unsigned long long)duration);
|
||||
printf(" Average packet rate: %.2f packets/time unit\n",
|
||||
(double)inst->analyzer->capture_count / (double)duration);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&inst->analyzer->lock);
|
||||
}
|
||||
|
||||
// Test instance thread function
|
||||
static void* test_instance_thread(void* arg) {
|
||||
test_instance_t* inst = (test_instance_t*)arg;
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Starting %s instance thread (port %u)",
|
||||
inst->is_server ? "server" : "client", inst->listen_port);
|
||||
|
||||
// Main event loop
|
||||
while (inst->running) {
|
||||
uasync_poll(inst->instance->ua, 10); // 10 time units timeout
|
||||
|
||||
// Process any pending ETCP packets
|
||||
if (inst->etcp_conn) {
|
||||
struct ETCP_DGRAM* dgram = test_etcp_request_with_capture(inst->etcp_conn);
|
||||
if (dgram) {
|
||||
// Send the packet through the socket
|
||||
if (inst->socket && inst->socket->fd >= 0) {
|
||||
struct sockaddr_in peer_addr;
|
||||
memset(&peer_addr, 0, sizeof(peer_addr));
|
||||
peer_addr.sin_family = AF_INET;
|
||||
peer_addr.sin_port = htons(inst->peer_port);
|
||||
peer_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||
|
||||
// Note: In real implementation, this would send through etcp_encrypt_send
|
||||
DEBUG_TRACE(DEBUG_CATEGORY_ETCP, "Would send packet to peer port %u (len=%u)",
|
||||
inst->peer_port, dgram->data_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "%s instance thread exiting", inst->is_server ? "server" : "client");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create test instance
|
||||
static test_instance_t* create_test_instance(uint16_t listen_port, uint16_t peer_port,
|
||||
uint64_t node_id, int is_server) {
|
||||
test_instance_t* inst = calloc(1, sizeof(test_instance_t));
|
||||
if (!inst) return NULL;
|
||||
|
||||
inst->listen_port = listen_port;
|
||||
inst->peer_port = peer_port;
|
||||
inst->node_id = node_id;
|
||||
inst->is_server = is_server;
|
||||
inst->running = 1;
|
||||
|
||||
// Create traffic analyzer
|
||||
inst->analyzer = calloc(1, sizeof(traffic_analyzer_t));
|
||||
if (inst->analyzer) {
|
||||
inst->analyzer->max_captures = 1000;
|
||||
inst->analyzer->captures = calloc(inst->analyzer->max_captures, sizeof(packet_capture_t));
|
||||
pthread_mutex_init(&inst->analyzer->lock, NULL);
|
||||
}
|
||||
|
||||
// Create UTUN instance directly without config file
|
||||
inst->instance = calloc(1, sizeof(struct UTUN_INSTANCE));
|
||||
if (!inst->instance) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to allocate UTUN instance");
|
||||
free(inst->analyzer);
|
||||
free(inst);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Initialize the instance manually
|
||||
inst->instance->node_id = node_id;
|
||||
inst->instance->running = 1;
|
||||
inst->instance->log_fp = stderr;
|
||||
|
||||
// Initialize crypto keys
|
||||
const char* priv_key_hex = "67b705a92b41bcaae105af2d6a17743faa7b26ccebba8b3b9b0af05e9cd1d5fb";
|
||||
const char* pub_key_hex = "1c55e4ccae7c4470707759086738b10681bf88b81f198cc2ab54a647d1556e17c65e6b1833e0c771e5a39382c03067c388915a4c732191bc130480f20f8e00b9";
|
||||
|
||||
// Parse keys
|
||||
for (int i = 0; i < 32; i++) {
|
||||
sscanf(&priv_key_hex[i*2], "%2hhx", &inst->instance->my_keys.private_key[i]);
|
||||
}
|
||||
for (int i = 0; i < 64; i++) {
|
||||
sscanf(&pub_key_hex[i*2], "%2hhx", &inst->instance->my_keys.public_key[i]);
|
||||
}
|
||||
|
||||
// Create uasync context
|
||||
inst->instance->ua = uasync_create();
|
||||
if (!inst->instance->ua) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to create uasync context");
|
||||
free(inst->instance);
|
||||
free(inst->analyzer);
|
||||
free(inst);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Initialize uasync instance
|
||||
uasync_init_instance(inst->instance->ua);
|
||||
|
||||
// Create packet pool
|
||||
inst->instance->pkt_pool = memory_pool_init(1600); // 1600 byte packets
|
||||
if (!inst->instance->pkt_pool) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to create packet pool");
|
||||
uasync_destroy(inst->instance->ua);
|
||||
free(inst->instance);
|
||||
free(inst->analyzer);
|
||||
free(inst);
|
||||
return NULL;
|
||||
}
|
||||
if (!inst->instance) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to create UTUN instance");
|
||||
free(inst->analyzer);
|
||||
free(inst);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create ETCP connection
|
||||
inst->etcp_conn = etcp_connection_create(inst->instance);
|
||||
if (!inst->etcp_conn) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to create ETCP connection");
|
||||
utun_instance_destroy(inst->instance);
|
||||
free(inst->analyzer);
|
||||
free(inst);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create ETCP socket (UDP socket for traffic)
|
||||
int sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sock_fd < 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to create UDP socket");
|
||||
etcp_connection_close(inst->etcp_conn);
|
||||
utun_instance_destroy(inst->instance);
|
||||
free(inst->analyzer);
|
||||
free(inst);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct sockaddr_in local_addr;
|
||||
memset(&local_addr, 0, sizeof(local_addr));
|
||||
local_addr.sin_family = AF_INET;
|
||||
local_addr.sin_port = htons(listen_port);
|
||||
local_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
if (bind(sock_fd, (struct sockaddr*)&local_addr, sizeof(local_addr)) < 0) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to bind UDP socket to port %u", listen_port);
|
||||
close(sock_fd);
|
||||
etcp_connection_close(inst->etcp_conn);
|
||||
utun_instance_destroy(inst->instance);
|
||||
free(inst->analyzer);
|
||||
free(inst);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create socket structure
|
||||
inst->socket = etcp_socket_add(inst->instance, (struct sockaddr_storage*)&local_addr, 0, 0, 0);
|
||||
if (!inst->socket) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_ETCP, "Failed to create ETCP socket");
|
||||
close(sock_fd);
|
||||
etcp_connection_close(inst->etcp_conn);
|
||||
utun_instance_destroy(inst->instance);
|
||||
free(inst->analyzer);
|
||||
free(inst);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Created %s instance (listen=%u, peer=%u, node_id=%llu)",
|
||||
is_server ? "server" : "client", listen_port, peer_port,
|
||||
(unsigned long long)node_id);
|
||||
|
||||
return inst;
|
||||
}
|
||||
|
||||
// Cleanup test instance
|
||||
static void destroy_test_instance(test_instance_t* inst) {
|
||||
if (!inst) return;
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Destroying %s instance", inst->is_server ? "server" : "client");
|
||||
|
||||
inst->running = 0;
|
||||
|
||||
if (inst->thread) {
|
||||
pthread_join(inst->thread, NULL);
|
||||
}
|
||||
|
||||
if (inst->etcp_conn) {
|
||||
etcp_connection_close(inst->etcp_conn);
|
||||
}
|
||||
|
||||
if (inst->instance) {
|
||||
if (inst->instance->pkt_pool) {
|
||||
// Memory pool will be cleaned up with instance
|
||||
}
|
||||
if (inst->instance->ua) {
|
||||
uasync_destroy(inst->instance->ua);
|
||||
}
|
||||
free(inst->instance);
|
||||
}
|
||||
|
||||
if (inst->analyzer) {
|
||||
// Free captured packet data
|
||||
for (size_t i = 0; i < inst->analyzer->capture_count; i++) {
|
||||
if (inst->analyzer->captures[i].data_copy) {
|
||||
free(inst->analyzer->captures[i].data_copy);
|
||||
}
|
||||
}
|
||||
free(inst->analyzer->captures);
|
||||
pthread_mutex_destroy(&inst->analyzer->lock);
|
||||
free(inst->analyzer);
|
||||
}
|
||||
|
||||
free(inst);
|
||||
}
|
||||
|
||||
// Main test function
|
||||
int main(int argc, char* argv[]) {
|
||||
printf("=== ETCP Traffic Flow Debugging Test ===\n");
|
||||
|
||||
// Initialize debug system
|
||||
debug_config_init();
|
||||
debug_set_level(DEBUG_LEVEL_DEBUG);
|
||||
debug_enable_category(DEBUG_CATEGORY_ETCP);
|
||||
debug_enable_timestamp(1);
|
||||
debug_enable_function_name(1);
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Starting ETCP traffic flow debugging test");
|
||||
|
||||
// Create server instance - use dynamic high ports to avoid conflicts
|
||||
uint16_t server_port = 30000 + (getpid() % 1000); // Dynamic port based on PID
|
||||
uint16_t client_port = server_port + 1;
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Creating server instance on port %u...", server_port);
|
||||
server_instance = create_test_instance(server_port, client_port, 0x1111111111111111ULL, 1);
|
||||
if (!server_instance) {
|
||||
fprintf(stderr, "Failed to create server instance on port %u\n", server_port);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Create client instance
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Creating client instance on port %u...", client_port);
|
||||
client_instance = create_test_instance(client_port, server_port, 0x2222222222222222ULL, 0);
|
||||
if (!client_instance) {
|
||||
fprintf(stderr, "Failed to create client instance\n");
|
||||
destroy_test_instance(server_instance);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Start instance threads
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Starting instance threads...");
|
||||
pthread_create(&server_instance->thread, NULL, test_instance_thread, server_instance);
|
||||
pthread_create(&client_instance->thread, NULL, test_instance_thread, client_instance);
|
||||
|
||||
// Let instances run for a bit to establish connection
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Running test for 5 seconds...");
|
||||
sleep(5);
|
||||
|
||||
// Initiate connection from client
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Initiating connection from client...");
|
||||
|
||||
// Create initial connection request
|
||||
struct ETCP_LINK* client_link = etcp_link_new(client_instance->etcp_conn, client_instance->socket,
|
||||
(struct sockaddr_storage*)&(struct sockaddr_in){
|
||||
.sin_family = AF_INET,
|
||||
.sin_port = htons(9001),
|
||||
.sin_addr.s_addr = inet_addr("127.0.0.1")
|
||||
}, 0);
|
||||
if (client_link) {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Client link created successfully");
|
||||
|
||||
// Send initial packet to trigger connection
|
||||
struct ETCP_DGRAM* init_dgram = test_etcp_request_with_capture(client_instance->etcp_conn);
|
||||
if (init_dgram) {
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Initial connection packet requested");
|
||||
}
|
||||
}
|
||||
|
||||
// Run for another 5 seconds to see traffic flow
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Continuing test for 5 more seconds...");
|
||||
sleep(5);
|
||||
|
||||
// Generate some test traffic
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Generating test traffic...");
|
||||
|
||||
// Create test packets and queue them
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if (client_instance->etcp_conn) {
|
||||
struct ll_entry* entry = queue_entry_new(100); // 100 byte packets
|
||||
if (entry) {
|
||||
// Fill with test data
|
||||
uint8_t* data = (uint8_t*)ll_entry_data(entry);
|
||||
for (int j = 0; j < 100; j++) {
|
||||
data[j] = (uint8_t)(i * 10 + j); // Pattern data
|
||||
}
|
||||
queue_entry_put(client_instance->etcp_conn->input_queue, entry);
|
||||
DEBUG_DEBUG(DEBUG_CATEGORY_ETCP, "Queued test packet %d", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Run for final 5 seconds
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Final test phase - 5 seconds...");
|
||||
sleep(5);
|
||||
|
||||
// Stop instances
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Stopping test instances...");
|
||||
server_instance->running = 0;
|
||||
client_instance->running = 0;
|
||||
|
||||
// Wait for threads to finish
|
||||
pthread_join(server_instance->thread, NULL);
|
||||
pthread_join(client_instance->thread, NULL);
|
||||
|
||||
// Print traffic analysis
|
||||
print_traffic_analysis(server_instance, "Server");
|
||||
print_traffic_analysis(client_instance, "Client");
|
||||
|
||||
// Cleanup
|
||||
destroy_test_instance(server_instance);
|
||||
destroy_test_instance(client_instance);
|
||||
|
||||
DEBUG_INFO(DEBUG_CATEGORY_ETCP, "Test completed");
|
||||
printf("\n=== Test completed ===\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user