fix: harden tcp bridge reconnect handling

This commit is contained in:
2026-04-03 05:57:52 +08:00
parent fd1fae8ad7
commit 9fd748c512
5 changed files with 247 additions and 10 deletions
+33 -2
View File
@@ -7,6 +7,8 @@
#include "main.h"
#include "SEGGER_RTT.h"
#include "lwip/ip_addr.h"
#include "lwip/pbuf.h"
#include "lwip/tcp.h"
@@ -85,11 +87,15 @@ static err_t tcp_client_on_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
static void tcp_client_on_err(void *arg, err_t err)
{
tcp_client_ctx_t *ctx = (tcp_client_ctx_t *)arg;
(void)err;
if (ctx == NULL) {
return;
}
ctx->pcb = NULL;
ctx->status.state = TCP_CLIENT_STATE_DISCONNECTED;
ctx->status.errors++;
ctx->next_retry_ms = HAL_GetTick() + ctx->config.reconnect_interval_ms;
SEGGER_RTT_printf(0, "TCP client error=%d, reconnect scheduled\r\n", (int)err);
}
static err_t tcp_client_on_connected(void *arg, struct tcp_pcb *pcb, err_t err)
@@ -101,11 +107,17 @@ static err_t tcp_client_on_connected(void *arg, struct tcp_pcb *pcb, err_t err)
ctx->status.state = TCP_CLIENT_STATE_DISCONNECTED;
ctx->status.errors++;
ctx->next_retry_ms = HAL_GetTick() + ctx->config.reconnect_interval_ms;
SEGGER_RTT_printf(0, "TCP client connect callback failed err=%d\r\n", (int)err);
return err;
}
ctx->pcb = pcb;
ctx->status.state = TCP_CLIENT_STATE_CONNECTED;
SEGGER_RTT_printf(0,
"TCP client connected to %u.%u.%u.%u:%u\r\n",
ctx->config.server_ip[0], ctx->config.server_ip[1],
ctx->config.server_ip[2], ctx->config.server_ip[3],
ctx->config.server_port);
tcp_nagle_disable(pcb);
tcp_arg(pcb, ctx);
tcp_recv(pcb, tcp_client_on_recv);
@@ -147,6 +159,8 @@ int tcp_client_connect(void)
pcb = tcp_new_ip_type(IPADDR_TYPE_V4);
if (pcb == NULL) {
g_client.status.errors++;
g_client.status.state = TCP_CLIENT_STATE_ERROR;
SEGGER_RTT_WriteString(0, "TCP client connect failed: no PCB\r\n");
return -1;
}
@@ -157,6 +171,7 @@ int tcp_client_connect(void)
g_client.status.state = TCP_CLIENT_STATE_DISCONNECTED;
g_client.status.errors++;
g_client.next_retry_ms = HAL_GetTick() + g_client.config.reconnect_interval_ms;
SEGGER_RTT_printf(0, "TCP client bind failed err=%d\r\n", (int)err);
return -1;
}
}
@@ -169,16 +184,24 @@ int tcp_client_connect(void)
g_client.status.state = TCP_CLIENT_STATE_CONNECTING;
tcp_arg(pcb, &g_client);
tcp_err(pcb, tcp_client_on_err);
err = tcp_connect(pcb, &remote_addr, g_client.config.server_port, tcp_client_on_connected);
if (err != ERR_OK) {
tcp_err(pcb, NULL);
tcp_abort(pcb);
g_client.status.state = TCP_CLIENT_STATE_DISCONNECTED;
g_client.status.errors++;
g_client.next_retry_ms = HAL_GetTick() + g_client.config.reconnect_interval_ms;
SEGGER_RTT_printf(0, "TCP client connect start failed err=%d\r\n", (int)err);
return -1;
}
g_client.pcb = pcb;
SEGGER_RTT_printf(0,
"TCP client connecting to %u.%u.%u.%u:%u\r\n",
g_client.config.server_ip[0], g_client.config.server_ip[1],
g_client.config.server_ip[2], g_client.config.server_ip[3],
g_client.config.server_port);
return 0;
}
@@ -194,6 +217,7 @@ int tcp_client_disconnect(void)
}
g_client.status.state = TCP_CLIENT_STATE_DISCONNECTED;
SEGGER_RTT_WriteString(0, "TCP client disconnected\r\n");
return 0;
}
@@ -288,7 +312,11 @@ void tcp_client_poll(void)
{
uint32_t now;
if (!g_client.config.auto_reconnect || g_client.pcb != NULL) {
if (!g_client.config.auto_reconnect || tcp_client_is_connected()) {
return;
}
if ((g_client.pcb != NULL) && (g_client.status.state == TCP_CLIENT_STATE_CONNECTING)) {
return;
}
@@ -296,6 +324,9 @@ void tcp_client_poll(void)
if (now >= g_client.next_retry_ms) {
g_client.status.reconnect_count++;
g_client.next_retry_ms = now + g_client.config.reconnect_interval_ms;
SEGGER_RTT_printf(0,
"TCP client reconnect attempt %lu\r\n",
g_client.status.reconnect_count);
(void)tcp_client_connect();
}
}
+6
View File
@@ -8,6 +8,8 @@
#include "lwip/pbuf.h"
#include "lwip/tcp.h"
#include "SEGGER_RTT.h"
#include <string.h>
typedef struct {
@@ -49,6 +51,7 @@ static err_t tcp_server_on_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p,
}
ctx->client_pcb = NULL;
ctx->status.state = TCP_SERVER_STATE_LISTENING;
SEGGER_RTT_WriteString(0, "TCP server peer disconnected\r\n");
return ERR_OK;
}
@@ -85,6 +88,7 @@ static void tcp_server_on_err(void *arg, err_t err)
ctx->client_pcb = NULL;
ctx->status.state = TCP_SERVER_STATE_LISTENING;
ctx->status.errors++;
SEGGER_RTT_printf(0, "TCP server connection error=%d\r\n", (int)err);
}
static err_t tcp_server_on_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
@@ -103,6 +107,7 @@ static err_t tcp_server_on_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
ctx->client_pcb = newpcb;
ctx->status.state = TCP_SERVER_STATE_CONNECTED;
ctx->status.connections++;
SEGGER_RTT_WriteString(0, "TCP server client connected\r\n");
tcp_nagle_disable(newpcb);
@@ -158,6 +163,7 @@ int tcp_server_start(void)
tcp_arg(g_server.listen_pcb, &g_server);
tcp_accept(g_server.listen_pcb, tcp_server_on_accept);
g_server.status.state = TCP_SERVER_STATE_LISTENING;
SEGGER_RTT_printf(0, "TCP server listening on %u\r\n", g_server.config.port);
return 0;
}