Reject old encrypted ACKs when compact attempt pairs restart in a new epoch
This commit is contained in:
1 parent
7c09bfca7f
commit
be95e93a36
1 file changed
+44
@@ -447,6 +447,49 @@ static void oom_session_recovery(void) {
|
||||
puts("PASS encrypted OOM recovery: REINIT both owners, preserved links, stale DATA rejected, fresh delivery both ways");
|
||||
}
|
||||
|
||||
/* Настоящий AES/ingress: одинаковая пара seq=1/no=1 в новой эпохе не принимает прежний ACK. */
|
||||
static struct frame encrypted_attempt_ack(void) {
|
||||
struct ETCP_DGRAM* pkt = memory_pool_alloc(ep[1].inst.pkt_pool); CHECK(pkt);
|
||||
pkt->link = &ep[1].links[0]; pkt->data_len = etcp_ack_section_size(1); pkt->noencrypt_len = 0;
|
||||
memset(pkt->data,0,pkt->data_len); pkt->data[0] = ETCP_SECTION_ACK; pkt->data[1] = 1;
|
||||
pkt->data[ETCP_ACK_BASE_SIZE] = 1; pkt->data[ETCP_ACK_BASE_SIZE+4] = 1;
|
||||
unsigned before = tail;
|
||||
CHECK(etcp_encrypt_send(pkt) > 0 && tail == before+1 && head == before);
|
||||
memory_pool_free(ep[1].inst.pkt_pool,pkt);
|
||||
return frames[head++ % 4096];
|
||||
}
|
||||
|
||||
static void compact_attempt_epoch_reuse(void) {
|
||||
setup(0);
|
||||
ep[0].inst.data_pool = memory_pool_init(PACKET_DATA_SIZE,"attempt epoch payload"); CHECK(ep[0].inst.data_pool);
|
||||
struct frame old_ack = {0};
|
||||
uint64_t first_epoch = ep[0].c->reset_id;
|
||||
for (unsigned round = 0; round < 2; round++) {
|
||||
struct ETCP_CONN* c = ep[0].c; struct ETCP_LINK* link = &ep[0].links[0];
|
||||
link->inflight_lim_bytes = 65536;
|
||||
const uint8_t data[] = {1,0,253};
|
||||
CHECK(etcp_int_send(c,data,sizeof(data)) == 0);
|
||||
struct ETCP_DGRAM* pkt = etcp_request_pkt(c); CHECK(pkt && pkt->attempt);
|
||||
CHECK(pkt->attempt->seq == 1 && pkt->attempt->attempt_id == etcp_tx_attempt_id(1,1));
|
||||
etcp_tx_complete(pkt,1); memory_pool_free(ep[0].inst.pkt_pool,pkt);
|
||||
if (!round) {
|
||||
old_ack = encrypted_attempt_ack();
|
||||
etcp_conn_fatal_reinit(c,"attempt epoch reuse test"); converge();
|
||||
CHECK(c->reset_id != first_epoch);
|
||||
} else {
|
||||
CHECK(c->unacked_bytes == sizeof(data) && link->inflight_bytes == sizeof(data));
|
||||
uint64_t last_rx = link->last_recv_local_time;
|
||||
deliver(&old_ack,0);
|
||||
CHECK(c->unacked_bytes == sizeof(data) && link->inflight_bytes == sizeof(data));
|
||||
CHECK(!c->ack_packets_count && !link->peer_rx_data_time_us && link->last_recv_local_time == last_rx);
|
||||
struct frame fresh_ack = encrypted_attempt_ack(); deliver(&fresh_ack,0);
|
||||
CHECK(!c->unacked_bytes && !link->inflight_bytes && c->ack_packets_count == 1);
|
||||
}
|
||||
}
|
||||
teardown(); memory_pool_destroy(ep[0].inst.data_pool); ep[0].inst.data_pool = NULL;
|
||||
puts("PASS encrypted ACK isolation when compact attempt pair is reused in a new epoch");
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
debug_config_init(); debug_set_level(DEBUG_LEVEL_WARN);
|
||||
test_clock_init(10);
|
||||
@@ -463,6 +506,7 @@ int main(void) {
|
||||
}
|
||||
restart_during_confirmation(); CHECK(u_get_allocated_count() == baseline);
|
||||
oom_session_recovery(); CHECK(u_get_allocated_count() == baseline);
|
||||
compact_attempt_epoch_reuse(); CHECK(u_get_allocated_count() == baseline);
|
||||
for (int scenario=0;scenario<9;scenario++) {
|
||||
setup(scenario == 5);
|
||||
saved[2]=stream_packet(0); saved[3]=stream_packet(1);
|
||||
|
||||
Reference in new issue
Block a user