Accept full GATT RX when reused ACL has unknown TX MTU
This commit is contained in:
1 parent
3124c82bd4
commit
01af2df02b
3 files changed
+34
-6
No files matched your search
+11
-5
@@ -32,7 +32,8 @@ struct ble_connection {
|
||||
struct ble_stats stats;
|
||||
struct ble_endpoint endpoint;
|
||||
struct ble_channel_state channels[BLE_CHANNEL_COUNT];
|
||||
unsigned int capacity;
|
||||
unsigned int capacity; /* Безопасный TX budget; после reuse ACL backend может знать только минимум MTU23. */
|
||||
int rx_above_tx_logged;
|
||||
uint16_t pending_bytes;
|
||||
/* ID монотонен по модулю 65536; кольцо хранит размеры и границы кадров, собственных ретрансляций нет. */
|
||||
uint16_t tx_next, tx_acked, rx_last, ack_sent, flight_head, flight_count, flight_bytes;
|
||||
@@ -442,10 +443,15 @@ void ble_backend_received(struct ble_transport* t, ble_link_id id, enum ble_wire
|
||||
DEBUG_WARN(CAT, "BLE value before mandatory subscriptions link=%llu channel=%d bytes=%zu", (unsigned long long)id, wire, len);
|
||||
close_link(t, c, "value before subscriptions"); return;
|
||||
}
|
||||
if (!data || !len || len > c->capacity || (unsigned)wire >= BLE_WIRE_COUNT) {
|
||||
if (!data || !len || len > BLE_VALUE_MAX || (unsigned)wire >= BLE_WIRE_COUNT) {
|
||||
DEBUG_WARN(CAT, "BLE invalid wire value link=%llu channel=%d bytes=%zu", (unsigned long long)id, wire, len);
|
||||
close_link(t, c, "invalid wire value"); return;
|
||||
}
|
||||
if (len > c->capacity && !c->rx_above_tx_logged) {
|
||||
c->rx_above_tx_logged = 1;
|
||||
DEBUG_INFO(CAT, "BLE RX exceeds conservative TX budget link=%llu bytes=%zu TX_capacity=%u RX_limit=%u",
|
||||
(unsigned long long)id, len, c->capacity, BLE_VALUE_MAX);
|
||||
}
|
||||
if (wire == BLE_WIRE_ACK) {
|
||||
if (len != 2) {
|
||||
DEBUG_WARN(CAT, "BLE invalid ACK length link=%llu bytes=%zu", (unsigned long long)id, len);
|
||||
@@ -510,9 +516,9 @@ void ble_backend_received(struct ble_transport* t, ble_link_id id, enum ble_wire
|
||||
if (t->config.callbacks.connection) t->config.callbacks.connection(t->config.arg, id, peer, BLE_READY, "HELLO accepted");
|
||||
pump(t, c); return;
|
||||
}
|
||||
if (!c->ready || len <= HEADER || len > c->capacity || data[0] != FRAME) {
|
||||
DEBUG_WARN(CAT, "BLE invalid value link=%llu channel=%d bytes=%zu capacity=%u ready=%d type=%u",
|
||||
(unsigned long long)id, channel, len, c->capacity, c->ready, len ? data[0] : 0);
|
||||
if (!c->ready || len <= HEADER || data[0] != FRAME) {
|
||||
DEBUG_WARN(CAT, "BLE invalid value link=%llu channel=%d bytes=%zu ready=%d type=%u",
|
||||
(unsigned long long)id, channel, len, c->ready, len ? data[0] : 0);
|
||||
c->stats.dropped++;
|
||||
ch->rx_size = ch->rx_offset = 0; return;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ struct fake_link {
|
||||
struct ble_backend { struct ble_transport* owner; struct UASYNC* ua; void* task; int index, started; struct fake_link links[16]; };
|
||||
static struct ble_backend* backends[3];
|
||||
static unsigned int mtu = 23;
|
||||
static int conservative_receiver;
|
||||
static int hold, drop, reject_peer, ready_count, writable_count;
|
||||
static int hold_ack;
|
||||
static unsigned ack_delay_us;
|
||||
@@ -73,7 +74,7 @@ static void run(void* arg) {
|
||||
uint8_t ack[2] = {f->ack_id >> 8, f->ack_id}; f->ack_held = 0; f->ack_delivered = f->ack_id;
|
||||
if (f->peer && slot(f->peer, f->other)) ble_backend_received(f->peer->owner, f->other, BLE_WIRE_ACK, ack, 2);
|
||||
}
|
||||
if (!f->len) { f->len = 1; ble_backend_opened(b->owner, f->id, mtu); }
|
||||
if (!f->len) { f->len = 1; ble_backend_opened(b->owner, f->id, conservative_receiver && b->index == 1 ? 23 : mtu); }
|
||||
if (!f->pending || hold) continue;
|
||||
struct fake_link* target = f->peer ? slot(f->peer, f->other) : NULL;
|
||||
if (target && !target->len) { schedule(b); continue; } /* Удалённая подписка должна завершиться до доставки HELLO. */
|
||||
@@ -388,10 +389,30 @@ static void exercise_frame_window(unsigned test_mtu) {
|
||||
ble_destroy(a); ble_destroy(b); uasync_destroy(ua, 0);
|
||||
printf("BLE frame window PASS (MTU=%u, two frames, partial/final/duplicate ACK, writable, independent INVITE)\n", test_mtu);
|
||||
}
|
||||
/* ACL уже имеет MTU517, но новый Android GATT server ещё не получил onMtuChanged. RX не ограничивается TX fallback. */
|
||||
static void exercise_unknown_mtu(void) {
|
||||
mtu = 517; conservative_receiver = 1; hold = hold_ack = drop = reject_peer = 0;
|
||||
struct UASYNC* ua = uasync_create(); CHECK(ua);
|
||||
struct ble_config cfg = {.node_id = 1, .company_id = 0xffff};
|
||||
struct ble_transport* a = ble_create(ua, &cfg); cfg.node_id = 2;
|
||||
struct ble_transport* b = ble_create(ua, &cfg); CHECK(a && b && !ble_start(a) && !ble_start(b)); drain(ua);
|
||||
struct ble_endpoint ep = {"1"}; ble_link_id id = ble_connect(a, &ep, 2); CHECK(id); drain(ua);
|
||||
ble_link_id other = incoming_ids[1];
|
||||
CHECK(!ble_tx_put(a, id, frame(BLE_FRAME_MAX, 0x91)));
|
||||
CHECK(!ble_channel_tx_put(a, id, BLE_CHANNEL_INVITE, frame(BLE_INVITE_FRAME_MAX, 0x92)));
|
||||
CHECK(!ble_tx_put(b, other, frame(BLE_FRAME_MAX, 0x93))); drain(ua);
|
||||
struct ll_entry* e = ble_rx_get(b, other); CHECK(e && e->len == BLE_FRAME_MAX && e->dgram[1499] == 0x91); release(e);
|
||||
e = ble_channel_rx_get(b, other, BLE_CHANNEL_INVITE);
|
||||
CHECK(e && e->len == BLE_INVITE_FRAME_MAX && e->dgram[BLE_INVITE_FRAME_MAX - 1] == 0x92); release(e);
|
||||
e = ble_rx_get(a, id); CHECK(e && e->len == BLE_FRAME_MAX && e->dgram[1499] == 0x93); release(e);
|
||||
ble_destroy(a); ble_destroy(b); uasync_destroy(ua, 0); conservative_receiver = 0;
|
||||
puts("BLE unknown MTU PASS (TX minimum23, RX517, duplex DATA and full INVITE)");
|
||||
}
|
||||
int main(void) {
|
||||
debug_config_init(); debug_set_level(DEBUG_LEVEL_WARN);
|
||||
debug_set_category_level(DEBUG_CATEGORY_DEBUG, DEBUG_LEVEL_INFO);
|
||||
size_t before = u_get_allocated_count();
|
||||
exercise_unknown_mtu(); CHECK(u_get_allocated_count() == before);
|
||||
for (unsigned i = 0; i < 2; i++) {
|
||||
exercise_resume_order(i ? 517 : 23, 0); exercise_resume_order(i ? 517 : 23, 1);
|
||||
exercise_resume_stream(i ? 517 : 23); CHECK(u_get_allocated_count() == before);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* Реальная доставка INVITE без GUI: config peer_hex link_file. GUI с этой идентичностью должен быть остановлен.
|
||||
* Конфиг только читается; БД в памяти, IP-службы и CHAT не запускаются, ETCP требует известного участника. */
|
||||
#include "../ble_etcp.h"
|
||||
#include "../../../src/utun_instance.h"
|
||||
#include "../../../src/chat/chat_local.h"
|
||||
#include "../../../src/chat/chat_event.h"
|
||||
#include "../../../lib/debug_config.h"
|
||||
|
||||
Reference in new issue
Block a user