📄 webftp.c
字号:
/***********************************************************
Copyright (c) 2005 Lenovo Corporate Research & Development
Module Name:
WebFTP.c
Abstract:
Author: WangZhe
Revision History
Create Date:2005-12-05
************************************************************/
#include "efi.h"
#include "efilib.h"
//#include "shell.h"
#include "FTPsocket.h"
#include "kwTools.h"
#include "FileSystem.h"
#include "DiskTool.h"
EFI_HANDLE g_ImageHandle;
extern INT32 nWaitSecond;
//事件列表数组
extern EFI_EVENT KW_EventList[];
extern KWEvent KW_EventIDList[];
extern INTN KW_EventCount;//当前事件个数
#define EVENT_FTPCHECKSOCKET 2
void PrintWebFTPUsage()
{
Print(L"%E Running the operation of WebFTP. :%N \n\r");
Print(L"Usages: WebFTP: \n\r");
Print(L" [-R][blocktime]:block time(seconds) for wait a message.\n\r");
Print(L"Examples:\n\r");
Print(L" WebFTP -R\n\r");
Print(L" WebFTP -R20\n\r");
}
//FTP服务器主程序
//使用了Select 模型
INT32 WebFTPServer(INTN IdleTime)//空闲时间,超过此次数,强行客户中止连接
{
SOCKADDR_IN stServerAddress;
const CHAR8 *szClientAddress;
SOCKADDR_IN stClientAddress;
SOCKET_ID ListenerSocketId;//socket监听连接句柄
SOCKET_ID ClinetSocketId;//客户端连接socket 句柄
INT32 nAddressLen;
INT32 NonBlock;
CHAR16 MessageStr[256];
CHAR16 ClientIPStr[256];
INT32 CmdCode,SubCmdCode;
EFI_STATUS Status;
INTN WaitIndex;
EFI_INPUT_KEY Key;
INTN nidle=0;//呆板记数,当为IdleTime时中止客户端连接
BOOLEAN bPrintChange=TRUE;
DiskPartitionTable m_DPT;
FileMgrControl FTP_FileMgr;//文件管理器
CreateFileMgr(&FTP_FileMgr);//创建文件管理器
FTP_FileMgr.ReMap(&FTP_FileMgr);
//获取分区列表,存放每个分区的偏移量(扇区)
GetDiskPartitionTable(&m_DPT);
//打印分区列表
PrintDiskPartitionTable(&m_DPT);
//建立socket
ListenerSocketId=socket (AF_INET, SOCK_STREAM, 0);
if( ListenerSocketId == INVALID_SOCKET )
{
Print(L"Error: fail to create a socket %d!\n",ListenerSocketId);
return -1;
}
Print(L"Success to create a socket %d\n",ListenerSocketId);
ZeroMem (&stServerAddress, sizeof(stServerAddress));
stServerAddress.sin_family = AF_INET;
stServerAddress.sin_addr.s_addr = INADDR_ANY;
stServerAddress.sin_port = htons (FTP_PORTNUM); // Server Port number
if (bind(ListenerSocketId,
(struct sockaddr*) &stServerAddress,
sizeof (stServerAddress)
) == SOCKET_ERROR)
{
Print(L"bind() failed \n");
return -1;
}
if (listen(ListenerSocketId, 5))
{
Print(L"listen() failed\n");
return -1;
}
//改为非阻断socket
NonBlock = 1;
if (ioctl(ListenerSocketId, FIONBIO, &NonBlock) == SOCKET_ERROR)
{
Print(L"ioctl() failed with error\n");
return -1;
}
//绑定
//bind(ListenerSocketId, (struct sockaddr*) &stServerAddress, sizeof (stServerAddress));
//listen (ListenerSocketId, 5);//开始监听
nAddressLen=sizeof(stClientAddress);
while(1)
{
Print(L"The server is listening on port %d now...\n", FTP_PORTNUM);
///FtpSocketTest();/////////////////////////////
WAITEVENT: nWaitSecond = 0;
Status = BS->WaitForEvent(KW_EventCount, KW_EventList, &WaitIndex);
if (EFI_ERROR(Status))
{
Print(L"Wait for Event fail with error:%r\n\r",Status);
}
switch(KW_EventIDList[WaitIndex].EventID)
{
case EVENT_KEYPRESSED:
Status = ST->ConIn->ReadKeyStroke(ST->ConIn,&Key);
Print(L"\n%d:%c\n",Key.ScanCode,Key.UnicodeChar);
if(Key.ScanCode==23)//ESC
goto Exit;
break;
case EVENT_TEST:
if(bPrintChange)Print(L"\r -");
else Print(L"\r |");
bPrintChange = !bPrintChange;
break;
case EVENT_FTPCHECKSOCKET:
ClinetSocketId = AcceptConnect (ListenerSocketId,
(struct sockaddr*)&stClientAddress, &nAddressLen);
//Print(L"=");
//Print(L"accept finish\n");
if( ClinetSocketId != INVALID_SOCKET )
{
//Print(L"Error: fail to accept an incoming connection!\n" );
goto ACCEPT_SUCCESS;
}
break;
default:break;
}
goto WAITEVENT;
//将这个scoket也设为非阻断
ACCEPT_SUCCESS:
nWaitSecond = -1;//阻断接收
NonBlock = 1;
if (ioctl(ClinetSocketId, FIONBIO, &NonBlock) == SOCKET_ERROR)
{
Print(L"ioctl() failed with error\n");
return -1;
}
szClientAddress = inet_ntoa( stClientAddress.sin_addr );
String8To16(szClientAddress,ClientIPStr);
//StringWide8To16()
Print(L"\nConnection from %s on port %d is established.\n",
ClientIPStr, FTP_PORTNUM );
GoComputerRoot(&FTP_FileMgr);//路径恢复
//首先进行密码验证
Status = RecvMessage(ClinetSocketId,MessageStr,&CmdCode,&SubCmdCode);
if(Status ==1)
{
Print(L"AC=%s,%d\n",MessageStr,CmdCode);
if((CmdCode==CHECK_PASSWORD)
&&(IsPassWordRight(MessageStr)))
{
Print(L"Allow...\n");
SendMessage(ClinetSocketId,MessageStr,ACCESS_ALLOW,0);
}
else
{
Print(L"Deny...\n");
SendMessage(ClinetSocketId,MessageStr,ACCESS_DENY,0);
Status = RecvMessage(ClinetSocketId,MessageStr,&CmdCode,&SubCmdCode);
if(Status!=1)
goto CloseClinet;//关闭这个客户端
}
}
else goto CloseClinet;//关闭这个客户端
nidle=0;
while(1)
{
//使用OnTimer等待,接收命令
WAITCMD: nWaitSecond = 0;
Status = BS->WaitForEvent(KW_EventCount, KW_EventList, &WaitIndex);
if (EFI_ERROR(Status))
{
Print(L"Wait for Event fail with error:%r\n\r",Status);
}
switch(KW_EventIDList[WaitIndex].EventID)
{
case EVENT_KEYPRESSED:
Status = ST->ConIn->ReadKeyStroke(ST->ConIn,&Key);
Print(L"\n%d:%c\n",Key.ScanCode,Key.UnicodeChar);
if(Key.ScanCode==23)//ESC
goto Exit;
break;
/*
case EVENT_TEST:
if(bPrintChange)Print(L"\r -");
else Print(L"\r |");
bPrintChange = !bPrintChange;
break;*/
case EVENT_FTPCHECKSOCKET:
Status = RecvMessage(ClinetSocketId,
MessageStr,&CmdCode,&SubCmdCode);
Print(L"\r Idletime=%d,[%d]",nidle,IdleTime);
nidle++;
if(nidle>=IdleTime)
{
goto CloseClinet;
}
if( Status == 1 )
{
goto DEALWITHCMD;
}
else if(Status == SOCKET_ERROR)
{
goto CloseClinet;
}
break;
default:break;
}
}
DEALWITHCMD:
nidle = 0;
nWaitSecond = -1;//阻断接收
switch (CmdCode)
{
case DOWNLOAD_FILE://客户端请求下载文件
Print(L"DOWNLOAD_FILE.\n");//(全名,含路径)
SendFile(ClinetSocketId, MessageStr);//发送一个文件
break;
case UPLOAD_FILE://客户端请求上载文件
Print(L"UPLOAD_FILE.\n");//(全名,含路径)
RecvFile(ClinetSocketId, MessageStr);//接收一个文件
break;
case LIST_CURDIR://请求浏览当前文件夹
Print(L"LIST_CURDIR.\n");
ListCurrentDirectory(ClinetSocketId,&FTP_FileMgr);
break;
case GOIN_DIR://进入一个指定文件夹
Print(L"GOIN_DIR.\n");
OpenSubDirectory(&FTP_FileMgr,MessageStr);
break;
case GET_DPT://发送磁盘分区表
Print(L"GET_DPT.\n");
SendDiskPartitionTable(ClinetSocketId,&m_DPT);
break;
case CLOSE_SERVER://关闭服务器
Print(L"CLOSE_SERVER.\n");
goto Exit;
break;
case CLOSE_CLIENT://关闭客户端
Print(L"CLOSE_CLIENT.\n");
goto CloseClinet;
break;
default:
Print(L"client command error!\n");
break;
}
goto WAITCMD;
//关闭这次连接
CloseClinet:
Socket_close(ClinetSocketId);
Print(L"Connection from %s on port %d is closed.\n",
ClientIPStr, FTP_PORTNUM );
}
Exit:
Socket_close(ListenerSocketId);
KillAllUserEvent();
return 0;
}
EFI_STATUS
InitializeWebFTPApplication (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
CHAR16 **Argv;
UINTN Argc;
UINTN Index;
BOOLEAN ParamRight=FALSE;
DiskPartitionTable m_DPT;
g_ImageHandle = ImageHandle;
//初始化网络执行环境
InitializeLib (g_ImageHandle,SystemTable);
InitializeLibC(g_ImageHandle,SystemTable);
InitializeShellApplication(g_ImageHandle,SystemTable);
Argv = SI->Argv;
Argc = SI->Argc;
nWaitSecond = -1;
if(Argc==1)
{
PrintWebFTPUsage();
return EFI_SUCCESS;
}
for (Index=1; Index<Argc; Index++)
{
if (Argv[Index][0] == '-')
{
if (Argv[Index][1] == 'H'||Argv[Index][1] == 'h')
{
PrintWebFTPUsage();
return EFI_SUCCESS;
}
if (Argv[Index][1] == 'R'||Argv[Index][1] == 'r')
{
if(Argv[Index][2]!='\0')
{
nWaitSecond = Atoi(&Argv[Index][2]);
if(nWaitSecond<0)nWaitSecond=-1;
}
ParamRight = TRUE;
if(nWaitSecond<0)
Print(L"nWaitSecond = -%d\n",(-1)*nWaitSecond);
else Print(L"nWaitSecond = %d\n",nWaitSecond);
}
}
}
CreateEvent(NULL,//事件句柄,为空(NULL)代表创建一个时间触发事件
EVENT_TEST, //事件ID
500,EVENTTYPE_USER);//时间事件间隔,单位是微秒,只有在EventHandle==NULL时才有效
CreateEvent(NULL,//事件句柄,为空(NULL)代表创建一个时间触发事件
EVENT_FTPCHECKSOCKET, //事件ID
1000,EVENTTYPE_USER);//时间事件间隔,单位是微秒,只有在EventHandle==NULL时才有效
CreateEvent(ST->ConIn->WaitForKey,//事件句柄,为空(NULL)代表创建一个时间触发事件
EVENT_KEYPRESSED, //事件ID
0,EVENTTYPE_SYSTEM);//时间事件间隔,单位是微秒,只有在EventHandle==NULL时才有效
nWaitSecond = 0;
if(ParamRight){WebFTPServer(30);
}
else PrintWebFTPUsage();
//获取分区列表,存放每个分区的偏移量(扇区)
// GetDiskPartitionTable(&m_DPT);
//打印分区列表
// PrintDiskPartitionTable(&m_DPT);
return EFI_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -