Verify compact address snapshots, migration and Android JSON
This commit is contained in:
1 parent
89f031f4f9
commit
6272c8a4ad
2 files changed
+103
No files matched your search
@@ -8,6 +8,8 @@
|
||||
#include "../src/utun_instance.h"
|
||||
#include "../src/chat/chat_core.h"
|
||||
#include "../src/chat/chat_event.h"
|
||||
#include "../src/routing_layer/topo_node_sqlite.h"
|
||||
#include "../src/config_parser.h"
|
||||
#include "../tools/chatgui-android/jni_bridge/android_jni_bridge.h"
|
||||
#include "test_utils.h"
|
||||
|
||||
@@ -49,6 +51,29 @@ static int check_reply(const char* channel, const char* original, const char* ty
|
||||
u_free(json); return ok;
|
||||
}
|
||||
|
||||
/* JSON адресов для Android сохраняет IPv4/IPv6, протокол, порт, socket_id и тип профиля. */
|
||||
static int check_addresses(const char *channel) {
|
||||
struct TOPO_SOCKMETA4 meta4 = {.id = 5, .config_type = CFG_SERVER_TYPE_PUBLIC};
|
||||
struct TOPO_SOCKMETA6 meta6 = {.id = 6, .config_type = CFG_SERVER_TYPE_PUBLIC,
|
||||
.address_profile = {ADDRESS_MAP_UNCHANGED, ADDRESS_IN_OPEN, ADDRESS_SOURCE_ETCP}};
|
||||
struct TOPO_ADDR4 addr4 = {.addr = {194,63,142,140}, .port = 1333, .socket_id = 5, .protocol = TOPO_PROTO_UDP};
|
||||
struct TOPO_ADDR6 addr6 = {.addr = {0x2a,0x04,0x52,0,0,0,0,0,0,0,0,0,0,0,0,0xf},
|
||||
.port = 443, .socket_id = 6, .protocol = TOPO_PROTO_TCP};
|
||||
struct TOPO_NODE node = {.node_id = instance->node_id, .v4_sock_meta = &meta4, .v4_addrs = &addr4,
|
||||
.v6_sock_meta = &meta6, .v6_addrs = &addr6};
|
||||
REQUIRE(!topo_node_sqlite_addrs_put(instance->topo_sqlite_db, instance->node_id, &node));
|
||||
char *json = utun_bridge_get_member_detail_json(channel, instance->node_id);
|
||||
char value[128];
|
||||
REQUIRE(json && !extract(json, "$.adr[0].a", value, sizeof(value)) && !strcmp(value, "194.63.142.140"));
|
||||
REQUIRE(!extract(json, "$.adr[0].p", value, sizeof(value)) && !strcmp(value, "1333"));
|
||||
REQUIRE(!extract(json, "$.adr[0].at", value, sizeof(value)) && !strcmp(value, "4"));
|
||||
REQUIRE(!extract(json, "$.adr[0].pr", value, sizeof(value)) && !strcmp(value, "UDP"));
|
||||
REQUIRE(!extract(json, "$.adr[1].at", value, sizeof(value)) && !strcmp(value, "1"));
|
||||
REQUIRE(!extract(json, "$.adr[1].pr", value, sizeof(value)) && !strcmp(value, "TCP"));
|
||||
REQUIRE(!extract(json, "$.adr[1].p", value, sizeof(value)) && !strcmp(value, "443"));
|
||||
u_free(json); return 0;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
debug_config_init(); debug_set_level(DEBUG_LEVEL_WARN);
|
||||
char directory[512] = "/tmp/utun_android_replies_XXXXXX", config[1024], channel[64], hex[65];
|
||||
@@ -62,6 +87,7 @@ int main(void) {
|
||||
chat_core_create_channel_auto(instance, "Android replies");
|
||||
char* json = utun_bridge_get_channels_json();
|
||||
REQUIRE(!extract(json, "$[0].id", channel, sizeof(channel))); u_free(json);
|
||||
REQUIRE(!check_addresses(channel));
|
||||
uint8_t empty[32] = {0}, original[32], missing[32]; memset(missing, 0xff, sizeof(missing));
|
||||
REQUIRE(!utun_bridge_send_message(channel, "Привет 😀 \"original\"\nnext line", empty, 1) && wait_result(1) == 1);
|
||||
json = utun_bridge_get_messages_json(channel, 1, NULL, 0);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "routing_layer/topo_node_sqlite.h"
|
||||
#include "transport_layer/secure_channel.h"
|
||||
#include "transport_layer/etcp.h"
|
||||
#include "config_parser.h"
|
||||
#include "../lib/mem.h"
|
||||
#include "../lib/memory_pool.h"
|
||||
#include "../lib/u_async.h"
|
||||
@@ -35,6 +36,74 @@ static struct TOPO_NODE* record(struct UTUN_INSTANCE* inst, uint64_t timestamp,
|
||||
return ni;
|
||||
}
|
||||
|
||||
/* Новый wire и SQL сохраняют адреса, протоколы, классификацию и REALITY; смена формата оставляет bootstrap. */
|
||||
static void test_compact_addresses(struct UTUN_INSTANCE *inst) {
|
||||
sqlite3 *saved_db = inst->topo_sqlite_db;
|
||||
assert(sqlite3_open(":memory:", &inst->topo_sqlite_db) == SQLITE_OK);
|
||||
sqlite3 *db = inst->topo_sqlite_db;
|
||||
assert(!topo_node_sqlite_init(db));
|
||||
assert(!topo_node_sqlite_node_update_verified(db, inst->node_id, "address fixture", inst->my_keys.public_key,
|
||||
inst->my_ed25519_pubkey, 100, 100));
|
||||
struct TOPO_NODE *node = record(inst, INT64_MAX - 100, "address fixture", 1);
|
||||
memcpy(node->v4_addrs->addr, (uint8_t[]){194,63,142,140}, 4);
|
||||
node->v4_addrs->port = 1333; node->v4_addrs->socket_id = 5;
|
||||
node->v4_sock_meta = memory_pool_alloc(inst->topo_groups->v4_sock_meta_pool);
|
||||
node->v6_sock_meta = memory_pool_alloc(inst->topo_groups->v6_sock_meta_pool);
|
||||
node->v6_addrs = memory_pool_alloc(inst->topo_groups->v6_addr_pool);
|
||||
node->reality_socks = u_calloc(1, sizeof(*node->reality_socks));
|
||||
assert(node->v4_sock_meta && node->v6_sock_meta && node->v6_addrs && node->reality_socks);
|
||||
*node->v4_sock_meta = (struct TOPO_SOCKMETA4){.id = 5, .config_type = CFG_SERVER_TYPE_PUBLIC,
|
||||
.address_profile = {ADDRESS_MAP_UNCHANGED, ADDRESS_IN_OPEN, ADDRESS_SOURCE_ETCP}};
|
||||
*node->v6_sock_meta = (struct TOPO_SOCKMETA6){.id = 6, .config_type = CFG_SERVER_TYPE_PUBLIC,
|
||||
.address_profile = {ADDRESS_MAP_UNCHANGED, ADDRESS_IN_CONTACT, ADDRESS_SOURCE_ETCP}};
|
||||
*node->v6_addrs = (struct TOPO_ADDR6){.addr = {0x2a,0x04,0x52,0,0,0,0,0,0,0,0,0,0,0,0,0xf},
|
||||
.port = 443, .socket_id = 6, .protocol = TOPO_PROTO_TCP | TOPO_PROTO_REALITY};
|
||||
node->reality_socks->socket_id = 6; strcpy(node->reality_socks->server_name, "example.org");
|
||||
sign_record(inst, node);
|
||||
assert(sizeof(struct TOPOMSG_SOCKMETA4) == 5 && sizeof(struct TOPOMSG_SOCKMETA6) == 5);
|
||||
assert(!topo_node_sqlite_snapshot_put(db, node) && !topo_node_sqlite_addrs_put(db, inst->node_id, node));
|
||||
struct TOPO_NODE *loaded = topo_node_sqlite_snapshot_load(db, inst->topo_groups, inst->node_id);
|
||||
assert(loaded && !topo_node_verify(loaded));
|
||||
assert(!memcmp(loaded->v4_addrs->addr, node->v4_addrs->addr, 4) && loaded->v4_addrs->port == 1333);
|
||||
assert(loaded->v4_sock_meta->address_profile.inbound == ADDRESS_IN_OPEN);
|
||||
assert(!memcmp(loaded->v6_addrs->addr, node->v6_addrs->addr, 16) && loaded->v6_addrs->port == 443);
|
||||
assert(loaded->v6_addrs->protocol == (TOPO_PROTO_TCP | TOPO_PROTO_REALITY));
|
||||
assert(loaded->v6_sock_meta->address_profile.inbound == ADDRESS_IN_CONTACT);
|
||||
assert(!strcmp(loaded->reality_socks->server_name, "example.org"));
|
||||
topo_node_destroy(inst->topo_groups, loaded);
|
||||
sqlite3_stmt *statement = NULL;
|
||||
assert(sqlite3_prepare_v2(db, "SELECT family,protocol,port,socket_id,addr_type,length(options)"
|
||||
" FROM node_addresses ORDER BY family", -1, &statement, NULL) == SQLITE_OK);
|
||||
assert(sqlite3_step(statement) == SQLITE_ROW && sqlite3_column_int(statement, 0) == 4);
|
||||
assert(sqlite3_column_int(statement, 1) == TOPO_PROTO_UDP && sqlite3_column_int(statement, 2) == 1333);
|
||||
assert(sqlite3_column_int(statement, 3) == 5 && sqlite3_column_int(statement, 4) == ADDR_TYPE_DIRECT);
|
||||
assert(sqlite3_step(statement) == SQLITE_ROW && sqlite3_column_int(statement, 0) == 6);
|
||||
assert(sqlite3_column_int(statement, 1) == (TOPO_PROTO_TCP | TOPO_PROTO_REALITY));
|
||||
assert(sqlite3_column_int(statement, 2) == 443 && sqlite3_column_int(statement, 3) == 6);
|
||||
assert(sqlite3_column_int(statement, 4) == ADDR_TYPE_CONTACT && sqlite3_column_int(statement, 5) == TOPO_ADDR_REALITY_OPTS_SIZE);
|
||||
assert(sqlite3_step(statement) == SQLITE_DONE); sqlite3_finalize(statement);
|
||||
|
||||
/* Две старые колонки отмечают прежний формат. Миграция не теряет IP/port, REALITY и максимум timestamp. */
|
||||
assert(sqlite3_exec(db, "ALTER TABLE node_addresses ADD COLUMN nat_evidence INTEGER DEFAULT 1;"
|
||||
"ALTER TABLE node_addresses ADD COLUMN nat_checked INTEGER DEFAULT 1", NULL, NULL, NULL) == SQLITE_OK);
|
||||
assert(!topo_node_sqlite_init(db));
|
||||
assert(topo_node_sqlite_snapshot_timestamp(db, inst->node_id) == node->timestamp);
|
||||
assert(!topo_node_sqlite_snapshot_load(db, inst->topo_groups, inst->node_id));
|
||||
loaded = topo_node_sqlite_node_load(db, inst->topo_groups, inst->node_id);
|
||||
assert(loaded && !loaded->timestamp && loaded->v4_addrs && loaded->v6_addrs && loaded->reality_socks);
|
||||
assert(!loaded->v4_sock_meta->address_profile.source && !loaded->v6_sock_meta->address_profile.source);
|
||||
assert(loaded->v4_addrs->port == 1333 && loaded->v6_addrs->port == 443);
|
||||
assert(!strcmp(loaded->reality_socks->server_name, "example.org"));
|
||||
topo_node_destroy(inst->topo_groups, loaded);
|
||||
node->timestamp = 0;
|
||||
assert(!topo_node_sign_self(inst, node) && node->timestamp == INT64_MAX - 99);
|
||||
assert(!topo_node_sqlite_init(db));
|
||||
loaded = topo_node_sqlite_snapshot_load(db, inst->topo_groups, inst->node_id);
|
||||
assert(loaded && loaded->timestamp == node->timestamp && !topo_node_verify(loaded));
|
||||
topo_node_destroy(inst->topo_groups, loaded); topo_node_destroy(inst->topo_groups, node);
|
||||
sqlite3_close(db); inst->topo_sqlite_db = saved_db;
|
||||
}
|
||||
|
||||
static void test_bgp(struct UTUN_INSTANCE* signer) {
|
||||
struct UTUN_INSTANCE receiver = { .ua = signer->ua, .topo_groups = signer->topo_groups };
|
||||
struct TOPO_GROUP group = { .instance = &receiver, .group_id = 10, .group_type = TOPO_GROUP_TYPE_CHAT };
|
||||
@@ -77,6 +146,10 @@ int main(void) {
|
||||
assert(inst.ua);
|
||||
groups.node_registry = queue_new(inst.ua, 16, 0, 8, "snapshot_test");
|
||||
groups.v4_addr_pool = memory_pool_init(sizeof(struct TOPO_ADDR4), "snapshot_v4");
|
||||
groups.v4_sock_meta_pool = memory_pool_init(sizeof(struct TOPO_SOCKMETA4), "snapshot_meta4");
|
||||
groups.v6_sock_meta_pool = memory_pool_init(sizeof(struct TOPO_SOCKMETA6), "snapshot_meta6");
|
||||
groups.v6_addr_pool = memory_pool_init(sizeof(struct TOPO_ADDR6), "snapshot_v6");
|
||||
assert(groups.v4_addr_pool && groups.v4_sock_meta_pool && groups.v6_sock_meta_pool && groups.v6_addr_pool);
|
||||
assert(sc_generate_keypair(&inst.my_keys) == SC_OK);
|
||||
memcpy(inst.my_ed25519_privkey, inst.my_keys.private_key, 32);
|
||||
EVP_PKEY* key = EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL, inst.my_ed25519_privkey, 32);
|
||||
@@ -86,6 +159,7 @@ int main(void) {
|
||||
inst.node_id = sc_derive_node_id_from_pubkey(inst.my_keys.public_key);
|
||||
assert(sqlite3_open(":memory:", &inst.topo_sqlite_db) == SQLITE_OK);
|
||||
assert(topo_node_sqlite_init(inst.topo_sqlite_db) == 0);
|
||||
test_compact_addresses(&inst);
|
||||
|
||||
struct TOPO_NODE* first = record(&inst, 100, "old", 1);
|
||||
assert(topo_node_verify(first) == 0);
|
||||
@@ -145,6 +219,9 @@ int main(void) {
|
||||
assert(!groups.node_registry->head);
|
||||
queue_free(groups.node_registry);
|
||||
memory_pool_destroy(groups.v4_addr_pool);
|
||||
memory_pool_destroy(groups.v4_sock_meta_pool);
|
||||
memory_pool_destroy(groups.v6_sock_meta_pool);
|
||||
memory_pool_destroy(groups.v6_addr_pool);
|
||||
sqlite3_close(inst.topo_sqlite_db);
|
||||
uasync_destroy(inst.ua, 0);
|
||||
return 0;
|
||||
|
||||
Reference in new issue
Block a user