新建项目
This commit is contained in:
1 parent
5e2e890cfc
commit
633d9b872b
1351 files changed
+730564
No files matched your search
@@ -0,0 +1,85 @@
|
||||
# telnet
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
基于letter shell运行的telnet
|
||||
|
||||
- [telnet](#telnet)
|
||||
- [简介](#简介)
|
||||
- [使用](#使用)
|
||||
- [其他](#其他)
|
||||
|
||||
## 简介
|
||||
|
||||
telnet是基于letter shell运行的一个telnet服务端,可以在一些具有网络能力的嵌入式环境中使用,特别适用于现场不方便接线条件下的调试工作,telnet默认运行在23端口,可以在`telnetd.h`文件中进行配置,也可以在启动服务前,调用`telnetdSetPort`进行修改,注意23端口可能会被系统占用
|
||||
|
||||
## 使用
|
||||
|
||||
1. 修改包含的头文件
|
||||
|
||||
telnet使用标准的socket接口实现,运行此telnet实现需要你的运行环境具有socket接口,使用时,需要首先确认你的运行环境中,提供标准socket的头文件,然后替换`telnetd.c`文件中包含的头文件
|
||||
|
||||
```c
|
||||
#include "sys/socket.h"
|
||||
#include "arpa/inet.h"
|
||||
#include "netinet/in.h"
|
||||
```
|
||||
|
||||
2. 实现线程接口
|
||||
|
||||
telnet的运行需要多任务支持,你选哟提供一个用于创建新线程的接口,下面是在linux环境下的示例
|
||||
|
||||
```c
|
||||
/**
|
||||
* @brief 新线程接口
|
||||
*
|
||||
* @param handler 线程函数
|
||||
* @param param 线程参数
|
||||
*
|
||||
* @return int 0 启动成功 -1 启动失败
|
||||
*/
|
||||
int userNewThread(void *handler, void *param)
|
||||
{
|
||||
pthread_t tid;
|
||||
|
||||
return pthread_create(&tid, NULL, handler, param) == 0 ? 0 : -1;
|
||||
}
|
||||
```
|
||||
|
||||
3. 初始化
|
||||
|
||||
```c
|
||||
telnetdInit(userNewThread);
|
||||
```
|
||||
|
||||
4. 启动
|
||||
|
||||
直接调用`telnetdStart`函数,或者在shell执行`telnetd start`命令,启动telent server
|
||||
|
||||
## 其他
|
||||
|
||||
- 只支持一个客户端连接
|
||||
|
||||
做telnet这个功能的时候发现,letter shell目前提供的接口,不好在telnet上做多客户端支持,遂暂时只支持一个客户端连接
|
||||
|
||||
- 部分shell功能不可用
|
||||
|
||||
目前的telent实现没有实现letter shell的`read`接口,所以部分依赖于此接口的功能,比如说`shellScan`都是不可用的
|
||||
|
||||
- 使用telent需要开启letter shell的伴生对象功能
|
||||
|
||||
- 性能优化
|
||||
|
||||
对于资源紧张的单片机,telnet频繁的网络操作可能会对系统性能产生压力,此时建议优化`telentd.c`中的`telnetdWrite`函数,可以使用环形缓冲区,每次此接口写入的数据不直接调用`send`函数,而是写入缓冲区,然后定时(100ms左右)调用`send`函数清空缓冲区
|
||||
|
||||
- x86 demo
|
||||
|
||||
x86 demo中实现了telnet的接口,可以直接运行试用
|
||||
|
||||
```sh
|
||||
letter:/$ telnetd setPort 4545
|
||||
letter:/$ telnetd start
|
||||
```
|
||||
@@ -0,0 +1,208 @@
|
||||
/**
|
||||
* @file telnetd.c
|
||||
* @author Letter
|
||||
* @brief telnet server for letter shell
|
||||
* @version 0.1
|
||||
* @date 2021-08-07
|
||||
*
|
||||
* @copyright (c) 2021 Letter
|
||||
*
|
||||
*/
|
||||
#include "telnetd.h"
|
||||
|
||||
#include "sys/socket.h"
|
||||
#include "arpa/inet.h"
|
||||
#include "netinet/in.h"
|
||||
|
||||
#include "shell.h"
|
||||
#include "shell_cmd_group.h"
|
||||
|
||||
#if SHELL_USING_COMPANION != 1
|
||||
#error telent for letter shell can not be used while shell companion is diabled
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief 新线程接口实例
|
||||
*/
|
||||
static NewThread newThread;
|
||||
|
||||
/**
|
||||
* @brief telnet server socket
|
||||
*/
|
||||
static int telnetdSocket;
|
||||
|
||||
/**
|
||||
* @brief telent server shell
|
||||
*/
|
||||
static Shell *telnetdShell;
|
||||
|
||||
/**
|
||||
* @brief telnet server 监听端口
|
||||
*/
|
||||
static int telnetdPort = TELNETD_DEFAULT_SERVER_PORT;
|
||||
|
||||
static void telnetdServer(void);
|
||||
static void telnetdConnection(int client);
|
||||
static void telentdWrite(char *data, short len);
|
||||
|
||||
/**
|
||||
* @brief telnet 协议命令
|
||||
*/
|
||||
static char telnetCmd[] = {0xff, 0xfb, 0x01, 0xff, 0xfb, 0x03, 0xff, 0xfc, 0x1f};
|
||||
|
||||
/**
|
||||
* @brief telnet server初始化
|
||||
*
|
||||
* @param newThreadInterface 新线程接口
|
||||
*
|
||||
* @return int 0 启动telent成功 -1 启动失败
|
||||
*/
|
||||
int telentdInit(NewThread newThreadInterface)
|
||||
{
|
||||
newThread = newThreadInterface;
|
||||
return newThread ? 0 : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 启动 telnet server
|
||||
*
|
||||
* @return int 0 启动telent成功 -1 启动失败
|
||||
*/
|
||||
int telnetdStart()
|
||||
{
|
||||
return newThread ? newThread(telnetdServer, NULL) : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 停止 telnet server
|
||||
*
|
||||
*/
|
||||
void telnetdStop()
|
||||
{
|
||||
close(telnetdSocket);
|
||||
if (telnetdShell != NULL)
|
||||
{
|
||||
close((int) shellCompanionGet(telnetdShell, SHELL_COMPANION_ID_TELNETD));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 修改telnet server 监听端口
|
||||
*
|
||||
* @param port 端口
|
||||
*
|
||||
*/
|
||||
void telnetdSetPort(int port)
|
||||
{
|
||||
telnetdPort = port;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief telent 服务
|
||||
*
|
||||
*
|
||||
*/
|
||||
static void telnetdServer(void)
|
||||
{
|
||||
struct sockaddr_in telnetdAddr;
|
||||
int client;
|
||||
struct sockaddr_in clientAddr;
|
||||
int addrLen = sizeof(clientAddr);
|
||||
|
||||
telnetdSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
memset(&telnetdAddr, 0, sizeof(telnetdAddr));
|
||||
telnetdAddr.sin_family = AF_INET,
|
||||
telnetdAddr.sin_addr.s_addr = inet_addr(TELNETD_SERVER_ADDRESS);
|
||||
telnetdAddr.sin_port = htons(telnetdPort);
|
||||
if (bind(telnetdSocket, (struct sockaddr *)&telnetdAddr, sizeof(telnetdAddr)) == 0 &&
|
||||
listen(telnetdSocket, 5) == 0)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
client = accept(telnetdSocket, (struct sockaddr *) &clientAddr, (socklen_t *) &addrLen);
|
||||
if (client > 0)
|
||||
{
|
||||
newThread(telnetdConnection, (void *) client);
|
||||
}
|
||||
else if (client <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
close(telnetdSocket);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief telnet server 连接处理
|
||||
*
|
||||
* @param client 客户端连接socket
|
||||
*
|
||||
*/
|
||||
static void telnetdConnection(int client)
|
||||
{
|
||||
int len = 0;
|
||||
char *data = SHELL_MALLOC(16);
|
||||
char *shellBuffer = SHELL_MALLOC(TELNETD_SHELL_BUFFER_SIZE);
|
||||
telnetdShell = SHELL_MALLOC(sizeof(Shell));
|
||||
|
||||
/** 处理 telent 协议 */
|
||||
send(client, telnetCmd, 9, 0);
|
||||
recv(client, data, 6, 0);
|
||||
|
||||
telnetdShell->write = telentdWrite;
|
||||
shellCompanionAdd(telnetdShell, SHELL_COMPANION_ID_TELNETD, (void *)client);
|
||||
shellInit(telnetdShell, shellBuffer, TELNETD_SHELL_BUFFER_SIZE);
|
||||
|
||||
if (TELNETD_SHELL_USER)
|
||||
{
|
||||
shellRun(telnetdShell, TELNETD_SHELL_USER);
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
len = recv(client, data, 1, 0);
|
||||
if (len == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (len == 1)
|
||||
{
|
||||
shellHandler(telnetdShell, data[0]);
|
||||
}
|
||||
}
|
||||
shellDeInit(telnetdShell);
|
||||
SHELL_FREE(data);
|
||||
SHELL_FREE(shellBuffer);
|
||||
SHELL_FREE(telnetdShell);
|
||||
telnetdShell = NULL;
|
||||
close(client);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief telnet server数据写
|
||||
*
|
||||
* @param data 写入的数据
|
||||
* @param len 数据长度
|
||||
*
|
||||
*/
|
||||
static void telentdWrite(char *data, short len)
|
||||
{
|
||||
int client = (int) shellCompanionGet(telnetdShell, SHELL_COMPANION_ID_TELNETD);
|
||||
if (client != 0)
|
||||
{
|
||||
send(client, data, len, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ShellCommand telnetdGroup[] =
|
||||
{
|
||||
SHELL_CMD_GROUP_ITEM(SHELL_TYPE_CMD_FUNC, start, telnetdStart, start telnet server),
|
||||
SHELL_CMD_GROUP_ITEM(SHELL_TYPE_CMD_FUNC, stop, telnetdStop, stop telnet server),
|
||||
SHELL_CMD_GROUP_ITEM(SHELL_TYPE_CMD_FUNC, setPort, telnetdSetPort, set telnet server port),
|
||||
SHELL_CMD_GROUP_END()
|
||||
};
|
||||
SHELL_EXPORT_CMD_GROUP(
|
||||
SHELL_CMD_PERMISSION(0)|SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN)|SHELL_CMD_DISABLE_RETURN,
|
||||
telnetd, telnetdGroup, telnet server\ninput telent -h for more help);
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* @file telnetd.h
|
||||
* @author Letter
|
||||
* @brief telnet server for letter shell
|
||||
* @version 0.1
|
||||
* @date 2021-08-07
|
||||
*
|
||||
* @copyright (c) 2021 Letter
|
||||
*
|
||||
*/
|
||||
#ifndef __TELNETD_H__
|
||||
#define __TELNETD_H__
|
||||
|
||||
/**
|
||||
* @brief 版本
|
||||
*/
|
||||
#define TELNET_VERSION "1.0.0"
|
||||
|
||||
/**
|
||||
* @brief telnetd shell伴生对象ID
|
||||
*/
|
||||
#define SHELL_COMPANION_ID_TELNETD -3
|
||||
|
||||
/**
|
||||
* @brief telnet server 监听的IP
|
||||
*/
|
||||
#define TELNETD_SERVER_ADDRESS "127.0.0.1"
|
||||
|
||||
/**
|
||||
* @brief telnet 默认监听端口
|
||||
*/
|
||||
#define TELNETD_DEFAULT_SERVER_PORT 23
|
||||
|
||||
/**
|
||||
* @brief telnet shell的数据缓冲区大小
|
||||
*/
|
||||
#define TELNETD_SHELL_BUFFER_SIZE 512
|
||||
|
||||
/**
|
||||
* @brief telnet shell的用户名,使用默认shell用户设置为NULL即可
|
||||
*/
|
||||
#define TELNETD_SHELL_USER NULL
|
||||
|
||||
/**
|
||||
* @brief 新线程接口
|
||||
*
|
||||
* @param void * 线程执行函数
|
||||
* @param void * 线程参数
|
||||
*
|
||||
* @reutrn int 0 启动线程成功 -1 启动线程失败
|
||||
*/
|
||||
typedef int (*NewThread)(void *, void *);
|
||||
|
||||
/**
|
||||
* @brief telnet server初始化
|
||||
*
|
||||
* @param newThreadInterface 新线程接口
|
||||
*
|
||||
* @return int 0 启动telent server成功 -1 启动失败
|
||||
*/
|
||||
int telentdInit(NewThread newThreadInterface);
|
||||
|
||||
/**
|
||||
* @brief 启动 telnet server
|
||||
*
|
||||
* @return int 0 启动telent成功 -1 启动失败
|
||||
*/
|
||||
int telnetdStart();
|
||||
|
||||
/**
|
||||
* @brief 停止 telnet server
|
||||
*
|
||||
*/
|
||||
void telnetdStop();
|
||||
|
||||
#endif
|
||||
Reference in new issue
Block a user