1
0
mirror of https://github.com/NevermindZZT/letter-shell.git synced 2025-01-21 10:02:54 +08:00
2021-08-10 22:04:44 +08:00

209 lines
4.5 KiB
C

/**
* @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);