#include "tcp_server.h" #include "FreeRTOS.h" #include "task.h" #include "queue.h" #include "lwip/api.h" #include "lwip/ip_addr.h" #include "app_runtime.h" #include "config.h" #include "debug_log.h" #include "route_msg.h" #define TCP_SERVER_ACCEPT_TIMEOUT_MS 100 #define TCP_SERVER_STOP_POLL_MS 50u static BaseType_t tcp_server_stop_requested(void) { return (app_network_task_stop_requested() != pdFALSE) ? pdTRUE : pdFALSE; } static BaseType_t tcp_server_delay_with_stop(uint32_t delay_ms) { uint32_t remaining_ms = delay_ms; while (remaining_ms > 0u) { uint32_t slice_ms = (remaining_ms > TCP_SERVER_STOP_POLL_MS) ? TCP_SERVER_STOP_POLL_MS : remaining_ms; if (tcp_server_stop_requested() != pdFALSE) { return pdFALSE; } vTaskDelay(pdMS_TO_TICKS(slice_ms)); remaining_ms -= slice_ms; } return (tcp_server_stop_requested() == pdFALSE) ? pdTRUE : pdFALSE; } static err_t tcp_server_worker(struct netconn *conn, uint8_t link_index) { struct netbuf *buf; const device_config_t *cfg = config_get(); uint8_t uart_endpoint = config_uart_index_to_endpoint(cfg->links[link_index].uart); uint8_t src_endpoint = config_link_index_to_endpoint(link_index); err_t err; route_msg_t *tx_msg; route_send_result_t route_result; netconn_set_recvtimeout(conn, 10); for (;;) { if (tcp_server_stop_requested() != pdFALSE) { return ERR_CLSD; } err = netconn_recv(conn, &buf); if (err == ERR_OK) { do { void *data; uint16_t len; netbuf_data(buf, &data, &len); route_result = route_send(xTcpRxQueue, src_endpoint, uart_endpoint, (link_index == CONFIG_LINK_S1) ? ROUTE_CONN_S1 : ROUTE_CONN_S2, (const uint8_t *)data, len, pdMS_TO_TICKS(10)); if (route_result != ROUTE_SEND_OK) { debug_log_printf("[SRV] idx=%u rx-route-fail rc=%s len=%u\r\n", (unsigned int)link_index, route_send_result_to_str(route_result), (unsigned int)len); netbuf_delete(buf); return ERR_CLSD; } } while (netbuf_next(buf) >= 0); netbuf_delete(buf); } else if (err == ERR_TIMEOUT) { if (tcp_server_stop_requested() != pdFALSE) { return ERR_CLSD; } } else { break; } while (xQueueReceive(xLinkTxQueues[link_index], &tx_msg, 0) == pdPASS) { if (tcp_server_stop_requested() != pdFALSE) { route_msg_free(tx_msg); return ERR_CLSD; } err = netconn_write(conn, tx_msg->data, tx_msg->len, NETCONN_COPY); route_msg_free(tx_msg); if (err != ERR_OK) { return err; } } } return err; } static void tcp_server_task(uint8_t link_index) { const device_config_t *cfg; struct netconn *listener; struct netconn *newconn; netconn_thread_init(); for (;;) { if (tcp_server_stop_requested() != pdFALSE) { break; } while (g_netif_ready == pdFALSE) { if (tcp_server_stop_requested() != pdFALSE) { goto exit_task; } vTaskDelay(pdMS_TO_TICKS(100)); } cfg = config_get(); if (cfg->links[link_index].enabled == 0u) { if (tcp_server_stop_requested() != pdFALSE) { break; } if (tcp_server_delay_with_stop(500u) == pdFALSE) { break; } continue; } listener = netconn_new(NETCONN_TCP); if (listener == NULL) { if (tcp_server_delay_with_stop(500u) == pdFALSE) { break; } continue; } netconn_set_recvtimeout(listener, TCP_SERVER_ACCEPT_TIMEOUT_MS); if (netconn_bind(listener, IP_ADDR_ANY, cfg->links[link_index].local_port) != ERR_OK || netconn_listen(listener) != ERR_OK) { netconn_delete(listener); if (tcp_server_delay_with_stop(500u) == pdFALSE) { break; } continue; } for (;;) { if (tcp_server_stop_requested() != pdFALSE || cfg->links[link_index].enabled == 0u) { break; } if (netconn_accept(listener, &newconn) == ERR_OK) { tcp_server_worker(newconn, link_index); netconn_close(newconn); netconn_delete(newconn); } } netconn_close(listener); netconn_delete(listener); } exit_task: netconn_thread_cleanup(); app_on_network_task_exit(xTaskGetCurrentTaskHandle()); vTaskDelete(NULL); } void TcpSrvTask_S1(void *argument) { (void)argument; tcp_server_task(CONFIG_LINK_S1); } void TcpSrvTask_S2(void *argument) { (void)argument; tcp_server_task(CONFIG_LINK_S2); }