?? 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 + -