Test invitation bootstrap without IP and independent INVITE frame limits

This commit is contained in:
evgeny committed 2026-10-30 23:40:56 +01:00
1 parent e88de767ac
commit a5d7833e16
2 files changed
+73

No files matched your search

+7
View File
@@ -226,6 +226,13 @@ static void exercise(unsigned int test_mtu) {
for (int i = 0; i < e->len; i++) CHECK(e->dgram[i] == 0x31);
release(e);
e = ble_rx_get(t[0], a); CHECK(e && e->len == 1499 && e->dgram[1498] == 0x71); release(e);
e = frame(BLE_FRAME_MAX + 1, 0x81); CHECK(ble_tx_put(t[0], a, e) == BLE_ERROR); release(e);
e = frame(BLE_INVITE_FRAME_MAX + 1, 0x82);
CHECK(ble_channel_tx_put(t[0], a, BLE_CHANNEL_INVITE, e) == BLE_ERROR); release(e);
CHECK(!ble_channel_tx_put(t[0], a, BLE_CHANNEL_INVITE, frame(BLE_INVITE_FRAME_MAX, 0x83))); drain(ua);
e = ble_channel_rx_get(t[1], b, BLE_CHANNEL_INVITE); CHECK(e && e->len == BLE_INVITE_FRAME_MAX);
for (int i = 0; i < e->len; i++) CHECK(e->dgram[i] == 0x83);
release(e);
/* Два независимых канала одновременно, включая отказ TX и потерю фрагмента только INVITE. */
CHECK(ble_channel_tx_ready(t[0], a, BLE_CHANNEL_INVITE));
CHECK(!ble_tx_put(t[0], a, frame(1500, 0x61)));
@@ -13,6 +13,9 @@
#include "../../../src/chat/chat_local.h"
#include "../../../src/chat/chat_event.h"
#include "../../../src/chat/chat_setting.h"
#include "../../../src/chat/chat_core.h"
#include "../../../src/chat/chat_join.h"
#include "../../../src/chat/chat_sync.h"
#include "../../../src/chat/invite_link.h"
#include "../../../src/local_transport/protocol.h"
#include <assert.h>
@@ -337,6 +340,67 @@ static void invitation_without_etcp(void) {
uasync_destroy(ua, 0);
puts("PASS BLE invitations: connect on demand, empty name, invitation delivery without ETCP/UTUN link");
}
static int bootstrap_result;
static void bootstrap_event(struct UTUN_INSTANCE* inst, int type, const uint8_t* data, int len) {
(void)inst;
if (type == CHAT_EVT_CONNECT_RESULT) { assert(len == 28); memcpy(&bootstrap_result, data + 8, 4); }
}
/* JOIN проходит без IP и без ETCP до подписанного членства, затем тот же GATT становится групповым транспортом. */
static void bootstrap_join(unsigned att_mtu, int reverse) {
struct UTUN_INSTANCE* inst[2]; struct ble_etcp* driver[2];
ua = uasync_create(); assert(ua); created = hold = drop = 0; mtu = att_mtu;
for (int i = 0; i < 2; i++) {
inst[i] = utun_instance_create_from_str(ua, "[global]\nauto_sockets=no\n[ntp]\nenabled=no\n"
"[chatserver]\ngroup_autoconnect=0\nstorage_autoload=0\n");
assert(inst[i] && !utun_core_start(inst[i]) && !chat_service_start(inst[i]));
struct ble_config c = {.node_id = inst[i]->node_id, .company_id = 0xffff};
driver[i] = ble_etcp_create(ua, inst[i], &c, 1); assert(driver[i]); assert(!ble_start(ble_etcp_radio(driver[i])));
}
uint64_t group = chat_core_create_channel_auto(inst[0], "BLE bootstrap"); assert(group);
assert(!chat_join_store_local_key(inst[0], group, 123));
chat_event_set_handler(inst[1], bootstrap_event); drain();
for (int i = 0; i < 2; i++) {
uint8_t bytes[24]; int len = ble_identity_encode(bytes, inst[1-i]->node_id, "bootstrap");
struct ble_endpoint ep = {0}; snprintf(ep.id, sizeof(ep.id), "%d", 1-i);
ble_backend_broadcast(backends[i]->owner, &ep, bytes, len, -30);
}
drain();
if (reverse) { assert(!ble_etcp_connect(driver[0], inst[1]->node_id)); drain(); }
struct InviteData invite = {.channelId = group, .join_key = 124, .addrCount = 1};
memcpy(invite.pubkey, inst[0]->my_keys.public_key, 32);
invite.addrs[0] = (struct InviteAddr){.family = 4, .address = {127,0,0,1}, .proto = INVITE_PROTO_UDP, .port = 9};
for (int attempt = 0; attempt < 2; attempt++) {
char link[2048]; assert(invite_link_encode(&invite, NULL, link, sizeof(link)) > 0);
bootstrap_result = -999; assert(!chat_sync_join_link(inst[1], attempt + 1, link, strlen(link)));
uint64_t end = get_time_us() + 10000000;
while (bootstrap_result == -999 && get_time_us() < end) {
if (!topo_groups_peer_key_known(inst[0], inst[1]->my_keys.public_key)) {
assert(!instance_find_conn(inst[0], inst[1]->node_id));
assert(!instance_find_conn(inst[1], inst[0]->node_id));
}
uasync_poll(ua, 10);
}
assert(bootstrap_result != -999);
if (!attempt) {
assert(bootstrap_result != 0 && !topo_groups_peer_key_known(inst[0], inst[1]->my_keys.public_key));
end = get_time_us() + 100000; while (get_time_us() < end) uasync_poll(ua, 10);
invite.join_key = 123;
} else assert(bootstrap_result == 0);
}
assert(topo_groups_peer_key_known(inst[0], inst[1]->my_keys.public_key));
assert(topo_groups_peer_key_known(inst[1], inst[0]->my_keys.public_key));
struct TOPO_GROUP* g[2] = {topo_groups_find(inst[0]->topo_groups, group), topo_groups_find(inst[1]->topo_groups, group)};
assert(g[0] && g[1]);
uint64_t end = get_time_us() + 10000000;
while (get_time_us() < end && (!topo_group_peer_ready(g[0], inst[1]->node_id) ||
!topo_group_peer_ready(g[1], inst[0]->node_id))) uasync_poll(ua, 10);
assert(topo_group_peer_ready(g[0], inst[1]->node_id) && topo_group_peer_ready(g[1], inst[0]->node_id));
for (int i = 0; i < 2; i++) ble_etcp_destroy(driver[i]);
drain(); for (int i = 0; i < 2; i++) utun_instance_destroy(inst[i]); uasync_destroy(ua, 0);
printf("PASS BLE bootstrap JOIN: MTU=%u reverse=%d invalid key, retry, signed membership, ETCP and group READY\n", att_mtu, reverse);
}
int main(void) {
debug_config_init(); debug_set_level(getenv("UTUN_TEST_DEBUG") ? DEBUG_LEVEL_DEBUG : DEBUG_LEVEL_WARN);
debug_set_category_level(DEBUG_CATEGORY_DEBUG, DEBUG_LEVEL_INFO);
@@ -417,6 +481,8 @@ int main(void) {
reject_key(); assert(u_get_allocated_count() == baseline);
invitation_without_etcp(); assert(u_get_allocated_count() == baseline);
group_fallback();
bootstrap_join(23, 0);
bootstrap_join(517, 1);
puts("PASS BLE ETCP: discovery, encrypted handshake, MTU23 fragmentation, 1500-byte messages, backpressure, teardown");
return 0;
}