|
|
|
|
/******************************************************************************
|
|
|
|
|
|
|
|
|
|
版权所有 (C), 2018-2099, Radkil
|
|
|
|
|
|
|
|
|
|
******************************************************************************
|
|
|
|
|
文 件 名 : My_Lwip.c
|
|
|
|
|
版 本 号 : 初稿
|
|
|
|
|
作 者 : Radkil
|
|
|
|
|
生成日期 : 2026年5月21日
|
|
|
|
|
最近修改 :
|
|
|
|
|
功能描述 : LWIP中间层
|
|
|
|
|
|
|
|
|
|
修改历史 :
|
|
|
|
|
1.日 期 : 2026年5月21日
|
|
|
|
|
作 者 : Radkil
|
|
|
|
|
修改内容 : 创建文件
|
|
|
|
|
|
|
|
|
|
******************************************************************************/
|
|
|
|
|
#include "common.h"
|
|
|
|
|
#ifdef USE_LWIP
|
|
|
|
|
#include "lwip/sockets.h"
|
|
|
|
|
#include "lwip/netdb.h"
|
|
|
|
|
#include "FreeRTOS.h"
|
|
|
|
|
#include "task.h"
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include "common.h"
|
|
|
|
|
#include "ringbuffer.h"
|
|
|
|
|
#include "semphr.h"
|
|
|
|
|
#include "lua_base.h"
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
|
|
|
|
/*----------------------------------------------*
|
|
|
|
|
* 外部变量说明 *
|
|
|
|
|
*----------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
/*----------------------------------------------*
|
|
|
|
|
* 外部函数原型说明 *
|
|
|
|
|
*----------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
/*----------------------------------------------*
|
|
|
|
|
* 内部函数原型说明 *
|
|
|
|
|
*----------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
/*----------------------------------------------*
|
|
|
|
|
* 全局变量 *
|
|
|
|
|
*----------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
/*----------------------------------------------*
|
|
|
|
|
* 模块级变量 *
|
|
|
|
|
*----------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
/*----------------------------------------------*
|
|
|
|
|
* 常量定义 *
|
|
|
|
|
*----------------------------------------------*/
|
|
|
|
|
|
|
|
|
|
/*----------------------------------------------*
|
|
|
|
|
* 宏定义 *
|
|
|
|
|
*----------------------------------------------*/
|
|
|
|
|
#define PORT 23 // 监听的端口号
|
|
|
|
|
#define RECV_SIZE 1024 // 接收缓冲区大小
|
|
|
|
|
#define IAC 255
|
|
|
|
|
#define WILL 251
|
|
|
|
|
#define DO 253
|
|
|
|
|
#define ECHO 1
|
|
|
|
|
#define SGA 3
|
|
|
|
|
static int connect_fd = -1; //socket套接字
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
static rd_ringbuf_t *g_rb_handle = NULL;
|
|
|
|
|
SemaphoreHandle_t xSemaphore;
|
|
|
|
|
StaticSemaphore_t xSemaphoreBuffer;
|
|
|
|
|
SemaphoreHandle_t xMutex;
|
|
|
|
|
StaticSemaphore_t xMutexBuffer;
|
|
|
|
|
|
|
|
|
|
void Myprint_Init(void)
|
|
|
|
|
{
|
|
|
|
|
g_rb_handle = rd_RingbufferCreate(RECV_SIZE);
|
|
|
|
|
rd_RingbufferReset(g_rb_handle);
|
|
|
|
|
xSemaphore = xSemaphoreCreateCountingStatic(5, 0, &xSemaphoreBuffer);
|
|
|
|
|
xMutex = xSemaphoreCreateMutexStatic(&xMutexBuffer);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Myprint_timer(void)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Myprint_IRQHandler(void)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int Myprint_putchar(uint8_t ch)
|
|
|
|
|
{
|
|
|
|
|
if (connect_fd < 0) return 0;
|
|
|
|
|
char tx_buf[2];
|
|
|
|
|
if (ch == '\n')
|
|
|
|
|
{
|
|
|
|
|
tx_buf[0] = '\r';
|
|
|
|
|
tx_buf[1] = '\n';
|
|
|
|
|
if (write(connect_fd, tx_buf, 2) < 0) return EOF;
|
|
|
|
|
return 2;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
tx_buf[0] = ch;
|
|
|
|
|
if (write(connect_fd, tx_buf, 1) < 0) return EOF;
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Myprint_getchar(char *ch)
|
|
|
|
|
{
|
|
|
|
|
while (1)
|
|
|
|
|
{
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE)
|
|
|
|
|
{
|
|
|
|
|
if (xSemaphoreTake(xMutex, portMAX_DELAY) == pdTRUE)
|
|
|
|
|
{
|
|
|
|
|
ret = rd_RingbufferGet(g_rb_handle, ch, 1);
|
|
|
|
|
xSemaphoreGive(xMutex);
|
|
|
|
|
if (ret > 0)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
void ShowLWIPstate(void)
|
|
|
|
|
{
|
|
|
|
|
stats_display();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void luaprint_talnet(const char *fmt, ...)
|
|
|
|
|
{
|
|
|
|
|
static char temp[RECV_SIZE];
|
|
|
|
|
va_list args;
|
|
|
|
|
va_start(args, fmt);
|
|
|
|
|
int len = vsprintf(temp, fmt, args);
|
|
|
|
|
va_end(args);
|
|
|
|
|
if (len > 0 && connect_fd >= 0)
|
|
|
|
|
{
|
|
|
|
|
// 将 \n 转换为 \r\n,分段发送
|
|
|
|
|
int start = 0;
|
|
|
|
|
for (int i = 0; i < len; i++)
|
|
|
|
|
{
|
|
|
|
|
if (temp[i] == '\n')
|
|
|
|
|
{
|
|
|
|
|
if (i > start)
|
|
|
|
|
write(connect_fd, &temp[start], i - start);
|
|
|
|
|
write(connect_fd, "\r\n", 2);
|
|
|
|
|
start = i + 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (start < len)
|
|
|
|
|
write(connect_fd, &temp[start], len - start);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void vTCPServer_Task(void *pvParameters)
|
|
|
|
|
{
|
|
|
|
|
int listen_fd;
|
|
|
|
|
struct sockaddr_in server_addr, client_addr;
|
|
|
|
|
char temp[RECV_SIZE];
|
|
|
|
|
int ret;
|
|
|
|
|
socklen_t addr_len = sizeof(struct sockaddr_in);
|
|
|
|
|
|
|
|
|
|
// 1. 创建 socket (AF_INET表示IPv4, SOCK_STREAM表示TCP)
|
|
|
|
|
listen_fd = socket(AF_INET, SOCK_STREAM, 0);
|
|
|
|
|
if (listen_fd < 0)
|
|
|
|
|
{
|
|
|
|
|
log_e("Socket create failed!\r\n");
|
|
|
|
|
vTaskDelete(NULL);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2. 绑定 IP 和端口 (INADDR_ANY 表示绑定本地所有网卡IP)
|
|
|
|
|
memset(&server_addr, 0, sizeof(server_addr));
|
|
|
|
|
server_addr.sin_family = AF_INET;
|
|
|
|
|
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
|
|
|
server_addr.sin_port = htons(PORT);
|
|
|
|
|
|
|
|
|
|
if (bind(listen_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
|
|
|
|
|
{
|
|
|
|
|
log_e("Bind failed!\r\n");
|
|
|
|
|
close(listen_fd);
|
|
|
|
|
vTaskDelete(NULL);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 3. 开始监听,最大排队连接数为 5
|
|
|
|
|
if (listen(listen_fd, 5) < 0)
|
|
|
|
|
{
|
|
|
|
|
log_e("Listen failed!\r\n");
|
|
|
|
|
close(listen_fd);
|
|
|
|
|
vTaskDelete(NULL);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log_i("TCP Server is running on port %d...\r\n", PORT);
|
|
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
|
{
|
|
|
|
|
// 4. 阻塞等待客户端连接
|
|
|
|
|
connect_fd = accept(listen_fd, (struct sockaddr *)&client_addr, &addr_len);
|
|
|
|
|
if (connect_fd < 0)
|
|
|
|
|
{
|
|
|
|
|
log_w("Accept failed!\r\n");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifdef USE_TALNET
|
|
|
|
|
lua_init(luaprint_talnet);
|
|
|
|
|
// 发送telnet协商:服务端负责回显,进入字符模式
|
|
|
|
|
unsigned char telnet_neg[] = {
|
|
|
|
|
IAC, WILL, ECHO,
|
|
|
|
|
IAC, WILL, SGA
|
|
|
|
|
};
|
|
|
|
|
write(connect_fd, telnet_neg, sizeof(telnet_neg));
|
|
|
|
|
#endif
|
|
|
|
|
// 打印连接的客户端 IP 和端口
|
|
|
|
|
log_i("New client connected: %s:%d\r\n",
|
|
|
|
|
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
|
|
|
|
|
// 5. 循环接收并回显数据
|
|
|
|
|
|
|
|
|
|
// char *welcome = "\n> ";
|
|
|
|
|
// write(connect_fd, welcome, strlen(welcome));
|
|
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
|
{
|
|
|
|
|
// 阻塞接收数据
|
|
|
|
|
ret = read(connect_fd, &temp, RECV_SIZE);
|
|
|
|
|
|
|
|
|
|
if (ret > 0)
|
|
|
|
|
{
|
|
|
|
|
#ifdef USE_TALNET
|
|
|
|
|
lua_repl(temp, ret, 1);
|
|
|
|
|
#else
|
|
|
|
|
write(connect_fd, temp, ret);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
else if (ret == 0)
|
|
|
|
|
{
|
|
|
|
|
// 客户端正常断开连接
|
|
|
|
|
log_i("Client disconnected.\r\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// 接收出错
|
|
|
|
|
log_e("Read data error!\r\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 关闭与当前客户端的连接
|
|
|
|
|
close(connect_fd);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|