Files
CCU621M/app/tcp_ser/debug_link.c
T

622 lines
14 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @file debug_link.c
* @brief 调试链路层实现(comm_link_ctx + TCP Socket + comm_link 分发)
*/
#include "debug_link.h"
#include "tcp_protocol.h"
#include "publicdata/public_define.h"
#include "lwip/sockets.h"
#include "lwip/netdb.h"
#include <string.h>
#include <stdio.h>
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "app_fatfs/fatfs_init.h"
#if BLE_DEBUG_EN
#include "ble_link/fc41d_ble.h"
#endif
#if TCP_DEBUG_EN
/* =============================================================================
* 会话上下文(原 comm_link_ctx.c
* ============================================================================= */
static comm_link_ctx_t s_comm_link_ctx;
comm_link_ctx_t *comm_link_ctx_get(void)
{
return &s_comm_link_ctx;
}
comm_link_session_t *comm_link_session(void)
{
return &s_comm_link_ctx.session;
}
void comm_link_ctx_reset_session(void)
{
comm_link_type_t saved_type = s_comm_link_ctx.session.type;
memset(&s_comm_link_ctx.session, 0, sizeof(s_comm_link_ctx.session));
s_comm_link_ctx.session.type = saved_type;
}
void comm_link_ctx_reset_all(void)
{
memset(&s_comm_link_ctx, 0, sizeof(s_comm_link_ctx));
}
/* =============================================================================
* TCP Socket 后端(原 tcp_server_socket.c,本文件内 static
* ============================================================================= */
#ifndef AF_INET
#define AF_INET 2
#endif
#ifndef SOCK_STREAM
#define SOCK_STREAM 1
#endif
#ifndef SOL_SOCKET
#define SOL_SOCKET 0xFFF
#endif
#ifndef SO_REUSEADDR
#define SO_REUSEADDR 0x0004
#endif
#ifndef INADDR_ANY
#define INADDR_ANY 0x00000000
#endif
#ifndef F_GETFL
#define F_GETFL 3
#endif
#ifndef F_SETFL
#define F_SETFL 4
#endif
#ifndef O_NONBLOCK
#define O_NONBLOCK 0x0004
#endif
#ifndef EWOULDBLOCK
#define EWOULDBLOCK 11
#endif
#ifndef EAGAIN
#define EAGAIN 11
#endif
#ifndef ECONNRESET
#define ECONNRESET 104
#endif
#ifndef EPIPE
#define EPIPE 32
#endif
#ifndef ECONNABORTED
#define ECONNABORTED 103
#endif
#ifndef ETIMEDOUT
#define ETIMEDOUT 110
#endif
#ifndef ENETDOWN
#define ENETDOWN 100
#endif
#ifndef ENETUNREACH
#define ENETUNREACH 101
#endif
#ifndef EHOSTUNREACH
#define EHOSTUNREACH 113
#endif
#ifndef errno
extern int errno;
#endif
#define TCP_LOCAL_PORT TCP_DEBUG_PORT
#define MAX_CLIENTS TCP_DEBUG_MAX_CLIENTS
typedef struct {
int server_socket;
int client_socket;
uint8_t is_client_connected;
struct sockaddr_in client_addr;
} tcp_socket_server_t;
static tcp_socket_server_t socket_server = {
.server_socket = -1,
.client_socket = -1,
.is_client_connected = 0,
};
static SemaphoreHandle_t socket_mutex = NULL;
static int tcp_socket_create_server(void)
{
int sock;
struct sockaddr_in server_addr;
int opt = 1;
sock = lwip_socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
TCP_PRINT("Failed to create socket: %d\r\n", sock);
return -1;
}
lwip_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(TCP_LOCAL_PORT);
if (lwip_bind(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
TCP_PRINT("Failed to bind socket to port %d\r\n", TCP_LOCAL_PORT);
lwip_close(sock);
return -1;
}
if (lwip_listen(sock, MAX_CLIENTS) < 0) {
TCP_PRINT("Failed to listen on socket\r\n");
lwip_close(sock);
return -1;
}
{
int flags = lwip_fcntl(sock, F_GETFL, 0);
lwip_fcntl(sock, F_SETFL, flags | O_NONBLOCK);
}
TCP_PRINT("TCP server socket created on port %d\r\n", TCP_LOCAL_PORT);
return sock;
}
static int tcp_socket_init(void)
{
socket_mutex = xSemaphoreCreateMutex();
if (socket_mutex == NULL) {
TCP_PRINT("Failed to create socket mutex\r\n");
return -1;
}
socket_server.server_socket = tcp_socket_create_server();
if (socket_server.server_socket < 0) {
vSemaphoreDelete(socket_mutex);
socket_mutex = NULL;
return -1;
}
socket_server.client_socket = -1;
socket_server.is_client_connected = 0;
TCP_PRINT("Socket server initialized successfully\r\n");
return 0;
}
static int tcp_socket_accept_client(void)
{
struct sockaddr_in client_addr;
socklen_t addr_len = sizeof(client_addr);
int new_sock;
if (socket_server.server_socket < 0) {
return -1;
}
if (socket_mutex != NULL) {
xSemaphoreTake(socket_mutex, portMAX_DELAY);
}
new_sock = lwip_accept(socket_server.server_socket,
(struct sockaddr *)&client_addr, &addr_len);
if (new_sock >= 0) {
if (socket_server.is_client_connected) {
TCP_PRINT("Rejecting new connection - already have a client\r\n");
lwip_close(new_sock);
if (socket_mutex != NULL) {
xSemaphoreGive(socket_mutex);
}
return 0;
}
{
int flags = lwip_fcntl(new_sock, F_GETFL, 0);
lwip_fcntl(new_sock, F_SETFL, flags | O_NONBLOCK);
}
socket_server.client_socket = new_sock;
socket_server.is_client_connected = 1;
memcpy(&socket_server.client_addr, &client_addr, sizeof(client_addr));
TCP_PRINT("Client connected from %s:%d\r\n",
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
}
if (socket_mutex != NULL) {
xSemaphoreGive(socket_mutex);
}
return (new_sock >= 0) ? 1 : 0;
}
static int tcp_socket_receive_data(uint8_t *buffer, uint32_t buffer_size)
{
int received;
if (buffer == NULL || buffer_size == 0U) {
return -1;
}
if (socket_mutex != NULL) {
xSemaphoreTake(socket_mutex, portMAX_DELAY);
}
if (!socket_server.is_client_connected || socket_server.client_socket < 0) {
if (socket_mutex != NULL) {
xSemaphoreGive(socket_mutex);
}
return -1;
}
received = lwip_recv(socket_server.client_socket, buffer, buffer_size, 0);
if (received > 0) {
TCP_PRINT("Received %d bytes from client\r\n", received);
} else if (received == 0) {
TCP_PRINT("Client disconnected\r\n");
lwip_close(socket_server.client_socket);
socket_server.client_socket = -1;
socket_server.is_client_connected = 0;
received = -1;
#if FATFS_EN
fatfs_set_write_disable_flag(FATFS_WRITE_DISABLE_TCP_DEBUG, 0);
#endif
} else {
int err = errno;
if (err != EWOULDBLOCK && err != EAGAIN) {
TCP_PRINT("Socket receive error: %d\r\n", err);
if (err == ECONNRESET || err == EPIPE || err == ECONNABORTED ||
err == ETIMEDOUT || err == ENETDOWN || err == ENETUNREACH ||
err == EHOSTUNREACH) {
TCP_PRINT("Connection error detected, closing socket\r\n");
lwip_close(socket_server.client_socket);
socket_server.client_socket = -1;
socket_server.is_client_connected = 0;
#if FATFS_EN
fatfs_set_write_disable_flag(FATFS_WRITE_DISABLE_TCP_DEBUG, 0);
#endif
}
received = -1;
} else {
received = 0;
}
}
if (socket_mutex != NULL) {
xSemaphoreGive(socket_mutex);
}
return received;
}
static int tcp_socket_send_data(const uint8_t *data, uint32_t len)
{
int sent;
if (data == NULL || len == 0U) {
return -1;
}
if (socket_mutex != NULL) {
xSemaphoreTake(socket_mutex, portMAX_DELAY);
}
if (!socket_server.is_client_connected || socket_server.client_socket < 0) {
if (socket_mutex != NULL) {
xSemaphoreGive(socket_mutex);
}
return -1;
}
sent = lwip_send(socket_server.client_socket, data, len, 0);
if (sent > 0) {
TCP_PRINT("Sent %d bytes to client\r\n", sent);
} else {
TCP_PRINT("Failed to send data: %d\r\n", sent);
if (sent < 0) {
int err = errno;
if (err == ECONNRESET || err == EPIPE) {
TCP_PRINT("Connection broken, closing socket\r\n");
lwip_close(socket_server.client_socket);
socket_server.client_socket = -1;
socket_server.is_client_connected = 0;
}
}
}
if (socket_mutex != NULL) {
xSemaphoreGive(socket_mutex);
}
return sent;
}
static int tcp_socket_is_client_connected(void)
{
int connected;
if (socket_mutex != NULL) {
xSemaphoreTake(socket_mutex, portMAX_DELAY);
}
connected = socket_server.is_client_connected;
if (socket_mutex != NULL) {
xSemaphoreGive(socket_mutex);
}
return connected;
}
static void tcp_socket_close_client(void)
{
if (socket_mutex != NULL) {
xSemaphoreTake(socket_mutex, portMAX_DELAY);
}
if (socket_server.client_socket >= 0) {
lwip_close(socket_server.client_socket);
socket_server.client_socket = -1;
}
socket_server.is_client_connected = 0;
#if FATFS_EN
fatfs_set_write_disable_flag(FATFS_WRITE_DISABLE_TCP_DEBUG, 0);
#endif
TCP_PRINT("Client connection closed\r\n");
if (socket_mutex != NULL) {
xSemaphoreGive(socket_mutex);
}
}
static void tcp_socket_close_server(void)
{
if (socket_mutex != NULL) {
xSemaphoreTake(socket_mutex, portMAX_DELAY);
}
if (socket_server.client_socket >= 0) {
lwip_close(socket_server.client_socket);
socket_server.client_socket = -1;
}
if (socket_server.server_socket >= 0) {
lwip_close(socket_server.server_socket);
socket_server.server_socket = -1;
}
socket_server.is_client_connected = 0;
#if FATFS_EN
fatfs_set_write_disable_flag(FATFS_WRITE_DISABLE_TCP_DEBUG, 0);
#endif
if (socket_mutex != NULL) {
xSemaphoreGive(socket_mutex);
vSemaphoreDelete(socket_mutex);
socket_mutex = NULL;
}
TCP_PRINT("Socket server closed\r\n");
}
static int tcp_socket_get_client_ip(char *ip_buffer, uint32_t buffer_size)
{
const char *ip_str;
if (ip_buffer == NULL || buffer_size == 0U) {
return -1;
}
if (socket_mutex != NULL) {
xSemaphoreTake(socket_mutex, portMAX_DELAY);
}
if (!socket_server.is_client_connected) {
if (socket_mutex != NULL) {
xSemaphoreGive(socket_mutex);
}
return -1;
}
ip_str = inet_ntoa(socket_server.client_addr.sin_addr);
if (ip_str != NULL) {
strncpy(ip_buffer, ip_str, buffer_size - 1U);
ip_buffer[buffer_size - 1U] = '\0';
} else {
if (socket_mutex != NULL) {
xSemaphoreGive(socket_mutex);
}
return -1;
}
if (socket_mutex != NULL) {
xSemaphoreGive(socket_mutex);
}
return 0;
}
/* =============================================================================
* comm_link 分发(原 comm_link.c
* ============================================================================= */
#define SESS (comm_link_session())
static uint8_t comm_link_using_ble(void)
{
#if BLE_DEBUG_EN
return (SESS->type == COMM_LINK_BLE) ? 1U : 0U;
#else
return 0U;
#endif
}
void comm_link_set_type(comm_link_type_t type)
{
SESS->type = type;
}
comm_link_type_t comm_link_get_type(void)
{
return SESS->type;
}
comm_link_type_t comm_link_type_from_dip(void)
{
#if BLE_DEBUG_EN
return ble_link_is_bt_mode() ? COMM_LINK_BLE : COMM_LINK_TCP;
#else
return COMM_LINK_TCP;
#endif
}
int comm_link_start(void)
{
if (comm_link_using_ble() != 0U) {
#if BLE_DEBUG_EN
return comm_link_ble_start();
#endif
}
return tcp_socket_init();
}
void comm_link_stop(void)
{
if (comm_link_using_ble() != 0U) {
#if BLE_DEBUG_EN
comm_link_ble_stop();
#endif
return;
}
tcp_socket_close_server();
}
void comm_link_process(void)
{
#if BLE_DEBUG_EN
if (comm_link_using_ble() != 0U) {
comm_link_ble_process();
}
#endif
}
int comm_link_accept_client(void)
{
if (comm_link_using_ble() != 0U) {
return 0;
}
return tcp_socket_accept_client();
}
int comm_link_is_client_connected(void)
{
if (comm_link_using_ble() != 0U) {
#if BLE_DEBUG_EN
return comm_link_ble_is_client_connected();
#endif
return 0;
}
return tcp_socket_is_client_connected();
}
void comm_link_close_client(void)
{
if (comm_link_using_ble() != 0U) {
#if BLE_DEBUG_EN
comm_link_ble_close_client();
#endif
return;
}
tcp_socket_close_client();
}
int comm_link_receive_data(uint8_t *buffer, uint32_t buffer_size)
{
if (comm_link_using_ble() != 0U) {
#if BLE_DEBUG_EN
return comm_link_ble_receive_data(buffer, buffer_size);
#endif
return 0;
}
return tcp_socket_receive_data(buffer, buffer_size);
}
int comm_link_send_data(const uint8_t *data, uint32_t len)
{
if (comm_link_using_ble() != 0U) {
#if BLE_DEBUG_EN
return comm_link_ble_send_data(data, len);
#endif
return -1;
}
return tcp_socket_send_data(data, len);
}
int comm_link_get_peer_info(char *buf, uint32_t buf_size)
{
if ((buf == NULL) || (buf_size == 0U)) {
return -1;
}
if (SESS->peer_info[0] != '\0') {
(void)snprintf(buf, buf_size, "%s", SESS->peer_info);
return 0;
}
if (comm_link_using_ble() != 0U) {
#if BLE_DEBUG_EN
return comm_link_ble_get_peer_info(buf, buf_size);
#endif
}
return tcp_socket_get_client_ip(buf, buf_size);
}
#else /* TCP_DEBUG_EN */
comm_link_ctx_t *comm_link_ctx_get(void) { return NULL; }
comm_link_session_t *comm_link_session(void) { return NULL; }
void comm_link_ctx_reset_session(void) { }
void comm_link_ctx_reset_all(void) { }
void comm_link_set_type(comm_link_type_t type) { (void)type; }
comm_link_type_t comm_link_get_type(void) { return COMM_LINK_TCP; }
comm_link_type_t comm_link_type_from_dip(void) { return COMM_LINK_TCP; }
int comm_link_start(void) { return -1; }
void comm_link_stop(void) { }
void comm_link_process(void) { }
int comm_link_accept_client(void) { return -1; }
int comm_link_is_client_connected(void) { return 0; }
void comm_link_close_client(void) { }
int comm_link_receive_data(uint8_t *buffer, uint32_t buffer_size)
{
(void)buffer;
(void)buffer_size;
return -1;
}
int comm_link_send_data(const uint8_t *data, uint32_t len)
{
(void)data;
(void)len;
return -1;
}
int comm_link_get_peer_info(char *buf, uint32_t buf_size)
{
(void)buf;
(void)buf_size;
return -1;
}
#endif /* TCP_DEBUG_EN */