mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-10-15 06:19:55 +00:00
command reply buffer and tcp oversize fix
This commit is contained in:
@@ -358,11 +358,15 @@ static void listen_thread_fn(void *a, void *b, void *c)
|
||||
}
|
||||
|
||||
uint16_t flen = (uint16_t)hdr[1] | ((uint16_t)hdr[2] << 8);
|
||||
if (flen > MAX_FRAME_SIZE) {
|
||||
LOG_WRN("Oversized frame: len=%u, closing client", flen);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Skip frames not from app ('<'), or bad length. */
|
||||
if (hdr[0] != '<' || flen == 0 || flen > MAX_FRAME_SIZE) {
|
||||
if (hdr[0] != '<' || flen == 0) {
|
||||
/* Drain and discard the payload. */
|
||||
for (uint16_t i = 0; i < flen && flen <= MAX_FRAME_SIZE; i++) {
|
||||
for (uint16_t i = 0; i < flen; i++) {
|
||||
uint8_t discard;
|
||||
if (sock_recv_all(fd, &discard, 1) != 0) {
|
||||
goto client_done;
|
||||
|
||||
@@ -250,8 +250,17 @@ static void ble_on_connected(void)
|
||||
* sync state machine), resets message sync (un-ACKed peeked message stays in
|
||||
* the queue and is re-sent on the next CMD_SYNC_NEXT_MESSAGE), and frees the
|
||||
* Ed25519 sign buffer if a sign op was interrupted (else an 8KB leak). */
|
||||
/* One deferred reply is enough: RX pauses until it has been accepted by the
|
||||
* transport. A msgq also lets the transport's disconnect callback purge it. */
|
||||
struct pending_reply_frame {
|
||||
uint16_t len;
|
||||
uint8_t buf[MAX_FRAME_SIZE];
|
||||
};
|
||||
K_MSGQ_DEFINE(pending_reply, sizeof(struct pending_reply_frame), 1, 4);
|
||||
|
||||
static void companion_session_cleanup(void)
|
||||
{
|
||||
k_msgq_purge(&pending_reply);
|
||||
#ifdef ZEPHCORE_LORA
|
||||
companion_mesh_ptr->cancelContactIterator();
|
||||
companion_mesh_ptr->cancelSyncPending();
|
||||
@@ -306,7 +315,7 @@ static const struct ble_callbacks ble_cbs = {
|
||||
|
||||
/* ========== Frame send/receive (mesh ↔ BLE/USB) ========== */
|
||||
|
||||
static size_t write_frame(const uint8_t *src, size_t len)
|
||||
static size_t transport_write_frame(const uint8_t *src, size_t len)
|
||||
{
|
||||
#if ZEPHCORE_USB_STACK
|
||||
/* When USB owns the interface, replies must go out the CDC port — the BLE
|
||||
@@ -325,6 +334,38 @@ static size_t write_frame(const uint8_t *src, size_t len)
|
||||
return zephcore_ble_send(src, (uint16_t)len);
|
||||
}
|
||||
|
||||
static size_t write_frame(const uint8_t *src, size_t len)
|
||||
{
|
||||
if (len == 0 || len > MAX_FRAME_SIZE ||
|
||||
k_msgq_num_used_get(&pending_reply) != 0) {
|
||||
return 0;
|
||||
}
|
||||
if (transport_write_frame(src, len) == len) {
|
||||
return len;
|
||||
}
|
||||
/* Only protocol replies need retention; pushes retain their existing
|
||||
* lossy semantics. Report success once we own a copy, so callers that
|
||||
* already retry (contact/message sync) don't send it twice. */
|
||||
if (src[0] < 0x80) {
|
||||
struct pending_reply_frame f;
|
||||
f.len = len;
|
||||
memcpy(f.buf, src, len);
|
||||
if (k_msgq_put(&pending_reply, &f, K_NO_WAIT) == 0) {
|
||||
return len;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void retry_pending_reply(void)
|
||||
{
|
||||
struct pending_reply_frame f;
|
||||
if (k_msgq_peek(&pending_reply, &f) == 0 &&
|
||||
transport_write_frame(f.buf, f.len) == f.len) {
|
||||
(void)k_msgq_get(&pending_reply, &f, K_NO_WAIT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Push notification callback - sends push frames to BLE.
|
||||
* Push frames have format: [push_code] [data...]
|
||||
@@ -376,7 +417,8 @@ static void process_companion_rx(void)
|
||||
} f;
|
||||
|
||||
/* Process all queued frames */
|
||||
while (k_msgq_get(zephcore_ble_get_recv_queue(), &f, K_NO_WAIT) == 0) {
|
||||
while (k_msgq_num_used_get(&pending_reply) == 0 &&
|
||||
k_msgq_get(zephcore_ble_get_recv_queue(), &f, K_NO_WAIT) == 0) {
|
||||
#ifdef ZEPHCORE_LORA
|
||||
/* An in-flight contact dump deliberately survives commands parsed
|
||||
* here — it is only cancelled by CMD_APP_START (new session) or by
|
||||
@@ -470,6 +512,10 @@ static void mesh_event_loop(void)
|
||||
/* Clear the events we're handling */
|
||||
k_event_clear(&mesh_events, events);
|
||||
|
||||
/* TX-idle resumes both the retained reply and commands left in RX.
|
||||
* Housekeeping is a fallback if a transport loses its drain kick. */
|
||||
retry_pending_reply();
|
||||
|
||||
#ifdef ZEPHCORE_LORA
|
||||
/* Handle deferred UI button actions (flood advert, pref saves).
|
||||
* Must run in this thread — LoRa TX and flash writes block. */
|
||||
@@ -489,7 +535,8 @@ static void mesh_event_loop(void)
|
||||
/* Parse inbound BLE/USB frames + USB text-CLI lines HERE (main
|
||||
* thread) before loop() drains any outbound they enqueued — keeps
|
||||
* all mesh-state mutation on one thread (see ble_on_rx_frame). */
|
||||
if (events & MESH_EVENT_BLE_RX) {
|
||||
if (events & (MESH_EVENT_BLE_RX | MESH_EVENT_CONTACT_ITER |
|
||||
MESH_EVENT_HOUSEKEEPING)) {
|
||||
process_companion_rx();
|
||||
#if ZEPHCORE_USB_STACK
|
||||
struct companion_cli_line c;
|
||||
@@ -731,7 +778,8 @@ public:
|
||||
* has not reached the TX queue yet, so a `reboot` typed into the v-contact
|
||||
* waits for its own ack before resetting. */
|
||||
bool transportTxIdle() override {
|
||||
if (companion_mesh.vcontactConfirmPending()) {
|
||||
if (companion_mesh.vcontactConfirmPending() ||
|
||||
k_msgq_num_used_get(&pending_reply) != 0) {
|
||||
return false;
|
||||
}
|
||||
#if ZEPHCORE_USB_STACK
|
||||
|
||||
Reference in New Issue
Block a user