ServU是一款被广泛应用的FTP服务程序。它的主要特色在于简单易用、性能优越、稳定并扩展性强,能比较好的支持大并发流高带宽的FTP应用。
ServU支持以插件形式(C++DLL)扩展其功能。
I、ServU工作流程
a) ServU默认处理流程
1、客户端发出下载请求
2、ServU内核处理该请求
3、返回处理结果(如权限判断)
4、返回FTP消息到客户端
b) 插件和ServU结合时的操作流程
1、客户端发出下载请求
2、ServU将请求以事件的形式通知DLL插件去进行处理
3a、DLL插件捕捉并处理了该事件,直接返回到ServU服务
3b、DLL插件忽略该事件,转交ServU内核进行处理
4、ServU内核处理该请求
5、返回FTP消息到客户端
II、插件的配置
在ServUDaemon.ini配置文件中增加以下内容
[EXTERNAL] '插件配置段
ClientCheckDLL1=CuteSuHook.DLL 'Client事件的处理插件 EventHookDLL1=CuteSuHook.DLL 'Event事件的处理插件 |
III、插件的公共接口
插件的事件分为两类:Client事件和FtpEvent事件
两类事件由ServU触发,并传递到插件DLL。
插件需要捕捉Client事件和FtpEvent事件。其捕捉函数的C++原型为:
[EXPORT WORD CALLBACK HandleEventHook(RFTPEventStr* pEventStruc);
EXPORT int __cdecl HandleClientEvent(RClientEventStr* pEventStruc); #define EXPORT extern "C" __declspec (dllexport) |
注意:需要将这些函数导出(EXPORT)
相关代码:CuteSuHook.def
[LIBRARY CuteSuHook
EXPORTS HandleEventHook @1 HandleClientEvent @2 |
IV、事件描述结构体原型(C#描述)
客户事件结构
[internal sealed class ClientEvent { // 等同C++的RClientEventStr结构
public int Event; //事件代码(4) public int Flag; //标志,具体意义视事件而定(4) public string User; //用户名(40) public string Aux; //辅助信息(512) public string HostIP; //服务器IP地址(16) public uint SessionID; //唯一会话ID(4) public int DomainID; //唯一域ID(4) public int DomainPort; //域端口号(4) }; |
FTP事件结构
[internal sealed class FtpEvent { //等同C++的RFTPEventStr结构
public uint Event; //事件代码(4) public uint SubEvent; //子事件代码(4) public uint SessionID; //唯一会话ID(4) public string User; //用户名(40) public string ClientIP; //客户端IP(16) public string DomainIP; //域IP(16) public uint Duration; //事件周期,运行时间(4) public uint Size; //对象大小(例如文件)(4) public uint hWindow; //发送到窗口句柄(4) public uint Message; //要发送的消息(4) public IntPtr pReplyText; //回复消息地址(4) public string ReplyText; //回复消息(C++结构体中无此项) public string AuxOne; //备注1(512) public string AuxTwo; //备注2(512) public int DomainPort; //域端口号 public uint DomainID; //域ID public uint HiSize; //大小信息 }; |
V、事件代码
客户事件编码表
internal enum ClientEventCode : int {
Connect = 31, // 连接事件 Close = 32, // 关闭事件 SecureOnly = 40 // 用户是否必须通过安全连接登录 LoginMesFile = 1, // 请求登录信息文件 SignOnMes = 36, // 用户登录的消息文件 SignOffMes = 37, // 用户退出前的消息文件 Password = 3, // 验证用户密码 IPAccess = 4, // 验证IP地址 WriteFile = 5, // 验证写权限(注:只是创建新文件时) ReadFile = 6, // 验证读权限 ModifyFile = 7, // 验证修改权限 ListDir = 9, // 验证运行文件的权限 ChangeDir = 10, // 验证跳转到指定目录的权限 DeleteDir = 11, // 验证删除目录的权限 CreateDir = 12, // 验证创建目录的权限 AppendFile = 35, // 验证续传权限) ExecProg = 8, // 验证运行文件的权限 HomeDir = 2, // 返回用户的HOME路径 RelPaths = 14, // 是否显示相对于主目录的相对路径 HideHidden = 13, // 验证查看隐含文件的权限 AlwaysLogin = 23, // 总是允许登录 OneLoginPerIP = 24, // 每个IP是否只允许一个用户登录 LogClientIP = 25, // 是否记录指定IP的日志 SpeedLimit = 26, // 速度限制(限制带宽) MaxUsers = 29, // 最大用户数(某个帐号) MaxLoginPerIP = 33, // 每个IP最大登录用户数量 TimeOut = 28, // 空闲时间超时(单位:分) SessionTimeOut = 39 // 设置用户的超时时间(单位:分) } |
注1:常用事件
Connect、IPAccess、Password、LoginMsgFile、HomeDir
注2:事件发生顺序
Connect -> IPAccess(X) -> Password -> Password -> IPAccess -> Event.Login -> Event.Close
注1:常用事件
Login、Close、HookCommand、HookReply、AbortDown、ProgDown、EndDown、HookDown
注2:事件发生顺序
Login -> HookCommand / HookReply / HookDown -> ProgDown -> AbortDown / EndDown
Ftp事件编码表
internal enum FtpEventCode : int {
Connect = 2, // 发生在客户端连接服务器的时候 Close = 3, // 客户端断开连接前发生 Login = 8, // 发生在客户成功登录的情况 StartUp = 9, // 发生在上传开始的时候 AbortUp = 13, // 发生在上传终止的时候 ProgUp = 20, // 上传过程中将不断发生此事件 EndUp = 10, // 发生在上传成功结束的时候 StartDown = 11, // 发生在开始下载的时候 AbortDown = 14, // 发生在下载终止的时候 ProgDown = 21, // 下载过程中将不断发生此事件 EndDown = 12, // 发生在下载成功结束的时候 ChgDir = 18, // 当用户改变目录的时候发生 HookDown = 100, // 当客户端需要下载的时候触发 HookUp = 101, // 当客户端需要上传的时候触发 HookSite = 108, // 当执行SITE XXX命令时触发 HookChgDir = 109, // 当客户端改变当前目录时发生 HookCommand = 110, // 当客户端发出一条命令时触发 HookReply = 111 // FTP回复信息将触发此事件 } |