diff --git a/App/tcp_client.c b/App/tcp_client.c index 4922772..58b987a 100644 --- a/App/tcp_client.c +++ b/App/tcp_client.c @@ -239,14 +239,23 @@ int tcp_client_send(uint8_t instance, const uint8_t *data, uint16_t len) return -1; } if (tcp_sndbuf(ctx->pcb) < len) { + ctx->status.errors++; return 0; } err = tcp_write(ctx->pcb, data, len, TCP_WRITE_FLAG_COPY); + if (err == ERR_MEM) { + ctx->status.errors++; + return 0; + } if (err != ERR_OK) { ctx->status.errors++; return -1; } err = tcp_output(ctx->pcb); + if (err == ERR_MEM) { + ctx->status.errors++; + return 0; + } if (err != ERR_OK) { ctx->status.errors++; return -1; diff --git a/App/tcp_server.c b/App/tcp_server.c index 38d7df3..8936e1a 100644 --- a/App/tcp_server.c +++ b/App/tcp_server.c @@ -228,15 +228,24 @@ int tcp_server_send(uint8_t instance, const uint8_t *data, uint16_t len) return -1; } if (tcp_sndbuf(ctx->client_pcb) < len) { + ctx->status.errors++; return 0; } err = tcp_write(ctx->client_pcb, data, len, TCP_WRITE_FLAG_COPY); + if (err == ERR_MEM) { + ctx->status.errors++; + return 0; + } if (err != ERR_OK) { ctx->status.errors++; return -1; } err = tcp_output(ctx->client_pcb); + if (err == ERR_MEM) { + ctx->status.errors++; + return 0; + } if (err != ERR_OK) { ctx->status.errors++; return -1; diff --git a/App/uart_trans.c b/App/uart_trans.c index 9fb4753..0230008 100644 --- a/App/uart_trans.c +++ b/App/uart_trans.c @@ -43,6 +43,52 @@ static uint16_t ring_free(uint16_t head, uint16_t tail, uint16_t size) return (uint16_t)(size - ring_used(head, tail, size) - 1u); } +static bool ring_peek_byte(const uart_channel_ctx_t *ctx, uint16_t offset, uint8_t *out) +{ + uint16_t head; + uint16_t tail; + + if (ctx == NULL || out == NULL) { + return false; + } + + head = ctx->rx_head; + tail = ctx->rx_tail; + if (offset >= ring_used(head, tail, UART_RX_RING_BUFFER_SIZE)) { + return false; + } + + *out = ctx->rx_ring[(tail + offset) % UART_RX_RING_BUFFER_SIZE]; + return true; +} + +static bool ring_peek_span(const uart_channel_ctx_t *ctx, uint16_t offset, uint8_t *data, uint16_t len) +{ + if (ctx == NULL || data == NULL) { + return false; + } + + for (uint16_t i = 0u; i < len; ++i) { + if (!ring_peek_byte(ctx, (uint16_t)(offset + i), &data[i])) { + return false; + } + } + + return true; +} + +static void ring_drop_bytes(uart_channel_ctx_t *ctx, uint16_t len) +{ + if (ctx == NULL) { + return; + } + + while (len > 0u && ctx->rx_tail != ctx->rx_head) { + ctx->rx_tail = (uint16_t)((ctx->rx_tail + 1u) % UART_RX_RING_BUFFER_SIZE); + --len; + } +} + static int apply_uart_config(uart_channel_t channel) { uart_channel_ctx_t *ctx = &g_channels[channel]; @@ -297,63 +343,87 @@ void uart_trans_tx_cplt_handler(uart_channel_t channel) bool uart_mux_try_extract_frame(uart_channel_t channel, uart_mux_frame_t *frame) { - uint8_t sync_byte; + uart_channel_ctx_t *ctx; uint8_t header[4]; + uint8_t tail_byte; uint16_t available; uint16_t payload_len; + uint16_t sync_offset; + uint16_t total_len; if (channel >= UART_CHANNEL_MAX || frame == NULL) { return false; } - available = uart_trans_rx_available(channel); - if (available < 6u) { - return false; - } + ctx = &g_channels[channel]; - /* Scan for SYNC byte (0x7E) — discard non-matching bytes one at a time */ - if (uart_trans_read(channel, &sync_byte, 1u) != 1u) { - return false; - } - if (sync_byte != UART_MUX_SYNC) { - return false; - } - - /* Need at least: 2(len) + 1(src) + 1(dst) + payload + 1(tail) = 5 + payload */ - available = uart_trans_rx_available(channel); - if (available < 4u) { - return false; - } - - if (uart_trans_read(channel, header, sizeof(header)) != sizeof(header)) { - return false; - } - - payload_len = (uint16_t)(((uint16_t)header[0] << 8) | header[1]); - if (payload_len > sizeof(frame->payload)) { - return false; - } - if (uart_trans_rx_available(channel) < (uint16_t)(payload_len + 1u)) { - return false; - } - - frame->src_id = header[2]; - frame->dst_mask = header[3]; - frame->payload_len = payload_len; - if (payload_len > 0u) { - if (uart_trans_read(channel, frame->payload, payload_len) != payload_len) { + for (;;) { + available = uart_trans_rx_available(channel); + if (available < 6u) { return false; } - } - { - uint8_t tail = 0u; - if (uart_trans_read(channel, &tail, 1u) != 1u || tail != UART_MUX_TAIL) { + sync_offset = available; + for (uint16_t i = 0u; i < available; ++i) { + uint8_t byte = 0u; + if (!ring_peek_byte(ctx, i, &byte)) { + return false; + } + if (byte == UART_MUX_SYNC) { + sync_offset = i; + break; + } + } + + if (sync_offset == available) { + ring_drop_bytes(ctx, available); return false; } - } - return true; + if (sync_offset > 0u) { + ring_drop_bytes(ctx, sync_offset); + available = (uint16_t)(available - sync_offset); + } + + if (available < 6u) { + return false; + } + + if (!ring_peek_span(ctx, 1u, header, sizeof(header))) { + return false; + } + + payload_len = (uint16_t)(((uint16_t)header[0] << 8) | header[1]); + if (payload_len > sizeof(frame->payload)) { + ring_drop_bytes(ctx, 1u); + continue; + } + + total_len = (uint16_t)(payload_len + 6u); + if (available < total_len) { + return false; + } + + if (!ring_peek_byte(ctx, (uint16_t)(total_len - 1u), &tail_byte)) { + return false; + } + if (tail_byte != UART_MUX_TAIL) { + ring_drop_bytes(ctx, 1u); + continue; + } + + frame->src_id = header[2]; + frame->dst_mask = header[3]; + frame->payload_len = payload_len; + if (payload_len > 0u) { + if (!ring_peek_span(ctx, 5u, frame->payload, payload_len)) { + return false; + } + } + + ring_drop_bytes(ctx, total_len); + return true; + } } bool uart_mux_encode_frame(uint8_t src_id, diff --git a/Core/Src/main.c b/Core/Src/main.c index 285ee89..e04a686 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -66,7 +66,9 @@ static void App_RouteMuxUartTraffic(void); static void App_RouteTcpTraffic(void); static void StackGuard_Init(void); static void StackGuard_Check(void); -static void App_SendToUart(uint8_t uart_index, uint8_t src_id, uint8_t dst_mask, const uint8_t *data, uint16_t len); +static bool App_SendToUart(uint8_t uart_index, uint8_t src_id, uint8_t dst_mask, const uint8_t *data, uint16_t len); +static bool App_SendTcpServerPayload(uint8_t instance, const uint8_t *data, uint16_t len); +static bool App_SendTcpClientPayload(uint8_t instance, const uint8_t *data, uint16_t len); /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ @@ -261,19 +263,33 @@ static void App_Init(void) } } -static void App_SendToUart(uint8_t uart_index, uint8_t src_id, uint8_t dst_mask, const uint8_t *data, uint16_t len) +static bool App_SendTcpServerPayload(uint8_t instance, const uint8_t *data, uint16_t len) +{ + return tcp_server_send(instance, data, len) == (int)len; +} + +static bool App_SendTcpClientPayload(uint8_t instance, const uint8_t *data, uint16_t len) +{ + return tcp_client_send(instance, data, len) == (int)len; +} + +static bool App_SendToUart(uint8_t uart_index, uint8_t src_id, uint8_t dst_mask, const uint8_t *data, uint16_t len) { const device_config_t *cfg = config_get(); uart_channel_t channel = (uart_index == LINK_UART_U1) ? UART_CHANNEL_U1 : UART_CHANNEL_U0; + uint16_t written; if (cfg->mux_mode == MUX_MODE_FRAME) { uint8_t frame[APP_ROUTE_BUFFER_SIZE + 6u]; uint16_t frame_len = 0u; if (uart_mux_encode_frame(src_id, dst_mask, data, len, frame, &frame_len, sizeof(frame))) { - (void)uart_trans_write(channel, frame, frame_len); + written = uart_trans_write(channel, frame, frame_len); + return written == frame_len; } + return false; } else { - (void)uart_trans_write(channel, data, len); + written = uart_trans_write(channel, data, len); + return written == len; } } @@ -286,11 +302,13 @@ static void App_RouteTcpTraffic(void) int rc = tcp_server_recv(i, buffer, sizeof(buffer)); if (rc > 0) { uint8_t link_index = (i == 0u) ? CONFIG_LINK_S1 : CONFIG_LINK_S2; - App_SendToUart(cfg->links[link_index].uart, - config_link_index_to_endpoint(link_index), - config_uart_index_to_endpoint(cfg->links[link_index].uart), - buffer, - (uint16_t)rc); + if (!App_SendToUart(cfg->links[link_index].uart, + config_link_index_to_endpoint(link_index), + config_uart_index_to_endpoint(cfg->links[link_index].uart), + buffer, + (uint16_t)rc)) { + return; + } } } @@ -298,11 +316,13 @@ static void App_RouteTcpTraffic(void) int rc = tcp_client_recv(i, buffer, sizeof(buffer)); if (rc > 0) { uint8_t link_index = (i == 0u) ? CONFIG_LINK_C1 : CONFIG_LINK_C2; - App_SendToUart(cfg->links[link_index].uart, - config_link_index_to_endpoint(link_index), - config_uart_index_to_endpoint(cfg->links[link_index].uart), - buffer, - (uint16_t)rc); + if (!App_SendToUart(cfg->links[link_index].uart, + config_link_index_to_endpoint(link_index), + config_uart_index_to_endpoint(cfg->links[link_index].uart), + buffer, + (uint16_t)rc)) { + return; + } } } } @@ -315,37 +335,57 @@ static void App_RouteRawUartTraffic(void) len = uart_trans_read(UART_CHANNEL_U0, buffer, sizeof(buffer)); if (len > 0u) { + bool routed_ok = true; for (uint8_t i = 0; i < CONFIG_LINK_COUNT; ++i) { + bool sent = true; if (cfg->links[i].enabled == 0u || cfg->links[i].uart != LINK_UART_U0) { continue; } if (i == CONFIG_LINK_S1) { - (void)tcp_server_send(0u, buffer, len); + sent = App_SendTcpServerPayload(0u, buffer, len); } else if (i == CONFIG_LINK_S2) { - (void)tcp_server_send(1u, buffer, len); + sent = App_SendTcpServerPayload(1u, buffer, len); } else if (i == CONFIG_LINK_C1) { - (void)tcp_client_send(0u, buffer, len); + sent = App_SendTcpClientPayload(0u, buffer, len); } else if (i == CONFIG_LINK_C2) { - (void)tcp_client_send(1u, buffer, len); + sent = App_SendTcpClientPayload(1u, buffer, len); } + + if (!sent) { + routed_ok = false; + } + } + + if (!routed_ok) { + return; } } len = uart_trans_read(UART_CHANNEL_U1, buffer, sizeof(buffer)); if (len > 0u) { + bool routed_ok = true; for (uint8_t i = 0; i < CONFIG_LINK_COUNT; ++i) { + bool sent = true; if (cfg->links[i].enabled == 0u || cfg->links[i].uart != LINK_UART_U1) { continue; } if (i == CONFIG_LINK_S1) { - (void)tcp_server_send(0u, buffer, len); + sent = App_SendTcpServerPayload(0u, buffer, len); } else if (i == CONFIG_LINK_S2) { - (void)tcp_server_send(1u, buffer, len); + sent = App_SendTcpServerPayload(1u, buffer, len); } else if (i == CONFIG_LINK_C1) { - (void)tcp_client_send(0u, buffer, len); + sent = App_SendTcpClientPayload(0u, buffer, len); } else if (i == CONFIG_LINK_C2) { - (void)tcp_client_send(1u, buffer, len); + sent = App_SendTcpClientPayload(1u, buffer, len); } + + if (!sent) { + routed_ok = false; + } + } + + if (!routed_ok) { + return; } } } @@ -354,6 +394,7 @@ static void App_RouteMuxUartTraffic(void) { uart_mux_frame_t frame; const device_config_t *cfg = config_get(); + bool routed_ok; while (uart_mux_try_extract_frame(UART_CHANNEL_U0, &frame)) { #if defined(DEBUG) && (DEBUG != 0) @@ -366,33 +407,42 @@ static void App_RouteMuxUartTraffic(void) uint16_t response_len = (uint16_t)strlen(response_text); uint16_t frame_len = 0u; if (uart_mux_encode_frame(config_uart_index_to_endpoint(LINK_UART_U0), 0u, (const uint8_t *)response_text, response_len, g_mux_response_frame, &frame_len, sizeof(g_mux_response_frame))) { - (void)uart_trans_write(UART_CHANNEL_U0, g_mux_response_frame, frame_len); + if (uart_trans_write(UART_CHANNEL_U0, g_mux_response_frame, frame_len) != frame_len) { + return; + } } if (result == AT_NEED_REBOOT) { static const char hint[] = "Note: Use AT+SAVE then AT+RESET to apply changes\r\n"; response_len = (uint16_t)strlen(hint); if (uart_mux_encode_frame(config_uart_index_to_endpoint(LINK_UART_U0), 0u, (const uint8_t *)hint, response_len, g_mux_response_frame, &frame_len, sizeof(g_mux_response_frame))) { - (void)uart_trans_write(UART_CHANNEL_U0, g_mux_response_frame, frame_len); + if (uart_trans_write(UART_CHANNEL_U0, g_mux_response_frame, frame_len) != frame_len) { + return; + } } } } continue; } + routed_ok = true; if ((frame.dst_mask & ENDPOINT_S1) != 0u) { - (void)tcp_server_send(0u, frame.payload, frame.payload_len); + routed_ok = App_SendTcpServerPayload(0u, frame.payload, frame.payload_len) && routed_ok; } if ((frame.dst_mask & ENDPOINT_S2) != 0u) { - (void)tcp_server_send(1u, frame.payload, frame.payload_len); + routed_ok = App_SendTcpServerPayload(1u, frame.payload, frame.payload_len) && routed_ok; } if ((frame.dst_mask & ENDPOINT_C1) != 0u) { - (void)tcp_client_send(0u, frame.payload, frame.payload_len); + routed_ok = App_SendTcpClientPayload(0u, frame.payload, frame.payload_len) && routed_ok; } if ((frame.dst_mask & ENDPOINT_C2) != 0u) { - (void)tcp_client_send(1u, frame.payload, frame.payload_len); + routed_ok = App_SendTcpClientPayload(1u, frame.payload, frame.payload_len) && routed_ok; } if ((frame.dst_mask & ENDPOINT_UART3) != 0u && cfg->links[CONFIG_LINK_S2].uart == LINK_UART_U1) { - App_SendToUart(LINK_UART_U1, frame.src_id, ENDPOINT_UART3, frame.payload, frame.payload_len); + routed_ok = App_SendToUart(LINK_UART_U1, frame.src_id, ENDPOINT_UART3, frame.payload, frame.payload_len) && routed_ok; + } + + if (!routed_ok) { + return; } } @@ -407,33 +457,42 @@ static void App_RouteMuxUartTraffic(void) uint16_t response_len = (uint16_t)strlen(response_text); uint16_t frame_len = 0u; if (uart_mux_encode_frame(config_uart_index_to_endpoint(LINK_UART_U1), 0u, (const uint8_t *)response_text, response_len, g_mux_response_frame, &frame_len, sizeof(g_mux_response_frame))) { - (void)uart_trans_write(UART_CHANNEL_U1, g_mux_response_frame, frame_len); + if (uart_trans_write(UART_CHANNEL_U1, g_mux_response_frame, frame_len) != frame_len) { + return; + } } if (result == AT_NEED_REBOOT) { static const char hint[] = "Note: Use AT+SAVE then AT+RESET to apply changes\r\n"; response_len = (uint16_t)strlen(hint); if (uart_mux_encode_frame(config_uart_index_to_endpoint(LINK_UART_U1), 0u, (const uint8_t *)hint, response_len, g_mux_response_frame, &frame_len, sizeof(g_mux_response_frame))) { - (void)uart_trans_write(UART_CHANNEL_U1, g_mux_response_frame, frame_len); + if (uart_trans_write(UART_CHANNEL_U1, g_mux_response_frame, frame_len) != frame_len) { + return; + } } } } continue; } + routed_ok = true; if ((frame.dst_mask & ENDPOINT_S1) != 0u) { - (void)tcp_server_send(0u, frame.payload, frame.payload_len); + routed_ok = App_SendTcpServerPayload(0u, frame.payload, frame.payload_len) && routed_ok; } if ((frame.dst_mask & ENDPOINT_S2) != 0u) { - (void)tcp_server_send(1u, frame.payload, frame.payload_len); + routed_ok = App_SendTcpServerPayload(1u, frame.payload, frame.payload_len) && routed_ok; } if ((frame.dst_mask & ENDPOINT_C1) != 0u) { - (void)tcp_client_send(0u, frame.payload, frame.payload_len); + routed_ok = App_SendTcpClientPayload(0u, frame.payload, frame.payload_len) && routed_ok; } if ((frame.dst_mask & ENDPOINT_C2) != 0u) { - (void)tcp_client_send(1u, frame.payload, frame.payload_len); + routed_ok = App_SendTcpClientPayload(1u, frame.payload, frame.payload_len) && routed_ok; } if ((frame.dst_mask & ENDPOINT_UART2) != 0u) { - App_SendToUart(LINK_UART_U0, frame.src_id, ENDPOINT_UART2, frame.payload, frame.payload_len); + routed_ok = App_SendToUart(LINK_UART_U0, frame.src_id, ENDPOINT_UART2, frame.payload, frame.payload_len) && routed_ok; + } + + if (!routed_ok) { + return; } } }