FileZilla Server源码分析

2024-04-28 00:32
文章标签 分析 源码 server filezilla

本文主要是介绍FileZilla Server源码分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

FileZilla Server源码分析(1)


之所以有本系列的分析,是因为两点:
  1. FileZilla 是目前非常火爆的开源ftp项目,整个项目采用C++代码编写,代码紧凑可读性高,值得学习(缺陷是注释太少)。
  2. 网络上已有的对该源码的分析基于的版本是0.9.18,分析比较粗略,无论是框架还是细节。
这里仅仅是我个人对FileZilla Server源码 0.9.34 版本的分析,能力有限,不足和错误之处还希望大家不吝斧正。
本片作为开篇,略过如何编译(该源码源码用VS2010编译),如何配置,如何使用。 FileZilla官网提供了程序和源码下载(源码包含在程序中,安装时默认为不安装),以及编译步骤和注意事项,感兴趣的朋友可以自行去官网寻找或google。

感谢:分析时参考了网友的系列文章《 FileZilla FTP服务器源代码分析》,大家可以参照比对。

首先预览一下源码目录source文件夹下的大致文件布局。



6个子目录,核心的代码(线程、socket、命令等)都放在当前目录下。6个子目录及对应代码功能:

子目录功能
includes当前版本下只有一个子目录openssl,看名识意,不多解释
install安装脚本和资源
interface界面UI实现类
misc混杂类,比较重要的如md5,StdString等
res程序编译资源,目前只有一个icon
tinyxml著名的一款基于DOM模型小巧开源的xml解析器

当前source目录下源码按实现功能大致又分为以下几种类型:

功能分类包括的文件
网络全体文件名含socket的,Server.*,
线程文件名包含Thread的文件
辅助version.*,MFC64bitFix.*,conversion.*,config.h,service.cpp等除去网络和线程的文件

文件目录结构分析完了,面对众多.h.cpp文件,需要做一些去繁取精的操作。从无关紧要的地方开始,例如version.*。

version.*中声明定义了一个函数 CStdString GetVersionString(),需要注意的就是CStdString这个类,它的实现在misc/stdString.h文件中,这个类文件较大,功能稍后部分再分析。说句实话,这个函数是很值得收藏的。

Thread.*定义了线程类CThread,只需要注意那个Run函数中对线程消息做了处理,有用的消息交由虚函数 OnThreadMessage处理。

作为Visual Studio生成的C++代码中最常出现的两个文件stdafx.h和stdafx.cpp,我们势必需要首先弄清楚它们到底包含了哪些头文件,定义了哪些宏,什么了哪些函数以及结构体。

stdafx.h中包含了自己的config.h这个文件,顺便看一下这个文件的作用,代码很少目的有两个,强制使用unicode编译和检测是否安装了最新SDK。还包含了MFC64bitFix.h这个文件,也跟进去看看。定义了一个存储文件属性的结构体 CFileStatus64,以及操作它的若干全局函数,这个文件名有点怪,和包含的功能不匹配。
第55行遇到了条件宏 #ifdef MMGR,编译条件中有定义,包含misc/mmgr.h文件。mmgr是用于管理和跟踪内存的代码,之后会重点详细分析。
conversion.h中声明的函数用于ANSI和UTF8字符的互相转换,不多解释。
AsyncSocketEx.h中实现了异步socket,之后的ControlSocket,AdminListenSocket等文件中什么的socket都是由CAsyncSocketEx类派生来的,之后分析。
至此,stdafx.h中头文件包含全部结束,下面就是宏定义了。

先补充一个知识点,各消息的值范围和作用见下图:


注册了 WM_FILEZILLA_THREADMSG消息用来线程之 间通信,定义了 WM_FILEZILLA_SERVERMSG用于进 程间通信,即FileZilla server.exe和FileZilla Server Interface.exe。
这里仅贴出两处源码中调用这两个消息的例子,便可得知后面定义的几个常数宏的用处。
// ControlSocket.cpp第400行
SendStatus(_T( " could not send reply, disconnected. " ),  0 );
m_pOwner
-> PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_DELSOCKET, m_userid);

//Server.cpp第813行器
int index = GetNextThreadNotificationID();
CServerThread *pThread = new CServerThread(WM_FILEZILLA_SERVERMSG + index);
m_ThreadNotificationIDs[index] = pThread;

从上面代码可以看出 PostThreadMessage的第二个参数wParam就是定义的数字宏,第三个参数是结构t_statusmsg,这些宏功能分别是:

FSM_STATUSMESSAGE:在管理窗口或log中显示并记录状态信息
FSM_CONNECTIONDATA:和连接相关的信息,如新用户连接,登录,退出等
FSM_THREADCANQUIT:退出线程
FSM_SEND:发送数据时用于管理窗口统计发送字节数
FSM_RECV:接受数据时用于管理窗口统计接收字节数
其余的就不多写了,宏名比较直观的显示出意思。

在往下定义了一系列的结构如 t_statusmsg,之后用到的地方在详述,知道这些结构在哪个文件中定义的就行了。
接着就是extern HWND hMainWnd; 这个外联的句柄就是下一节将要提到的CServer的窗口类句柄。
最后定义了一个CCriticalSectionWrapper类和两个帮助检测临界区死锁的函数,尤其是前者,DEBUG版本时错误的使用将导致当前线程挂起。

SpeedLimit.*:  速度限制(包括时间段限制)

这里针对UI性比较强,FillBuffer这个函数将所有限制条件格式化成一个char字符串,ParseBuffer则是解析这个字符串,采用这个 类,可以轻松实现强大的自定义限速功能。

defs.h: 这个类定义了服务器的状态,如在线、离线、锁住 等。


Options.*,OptionTypes.h

OptionTypes.h中定义了一个结构数组 m_Optinons,保存所有配置项信息,如是否使用SSL,同时在线最大用户数量,上传下载限速等等,所有这些大部分都被使用在Option那个对话框UI上。
t_option结构中有一个BOOL bOnlyLocal成员用于标示该项是否可以仅能够被本地连接修改,数组中只有最后两项Server name 和 server display name为TRUE,Options类就是操作配置文件的实体类(注意,它使用了tinyXML),服务器的配置文件存储在exe同级目录下,叫FileZilla Srver.xml。Options的主要操作是针对内存中的配置,只有与默认值不同的项才会存入配置文件中。
Options还有一个隐藏的friend窗体类 COptionsHelperWindow,定义在cpp文件中,这个类用于通过用post WM_USER给窗体消息这种异步的方式去更新option实例,而不是options类自身。
有了Options类和OptionTypes.h中定义的配置类型,就可以通过诸如 m_pOptions->GetOptionVal(OPTION_ENABLELOGGING)这样的方法方便的获取到配置。

FileLogger.*  日志

这个类中包含Options类的一个对象指针,用来读取日志文件的相关配置。

iputils.* 判断IP合法性以及是否处于某个过滤范围

它采用了大名鼎鼎的boost库的regex来判断,这个库之后有时间一定要好好研究一下。

autobanmanager.*  阻止用户继续登录的方法类文件

AutoBan这个设置项是一个非常浪费资源的,因为它对每一个失败的ip都要记录查询内存中的两个map。

Accounts.* 账户

Accounts.h中声明了3个类,t_directory,t_group,还有继承于t_group的t_user。
t_directory仅仅含有一些权限声明,相当于一个struct,被t_group和t_user使用。
剩余两个类主要做的事是对配置的读取分析,所有的数据都是基于字符串的。

permission.* 对用户、群组访问资源进行鉴权

权限配置信息记录在FileZilla Server.xml中。
服务器对每一个group和user都有权限限制,group权限优先于user权限,在 CheckFilePermissions 函数中可以看出。

conversion.* utf8和ansi字符的相互转化


ExternalIpCheck.*  PASV模式

根据配置获取ip。

所有辅助文件已经分析完毕,下级节开始分析socket和线程类。

这篇关于FileZilla Server源码分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/941905

相关文章

Python 基于http.server模块实现简单http服务的代码举例

《Python基于http.server模块实现简单http服务的代码举例》Pythonhttp.server模块通过继承BaseHTTPRequestHandler处理HTTP请求,使用Threa... 目录测试环境代码实现相关介绍模块简介类及相关函数简介参考链接测试环境win11专业版python

SQL Server 查询数据库及数据文件大小的方法

《SQLServer查询数据库及数据文件大小的方法》文章介绍了查询数据库大小的SQL方法及存储过程实现,涵盖当前数据库、所有数据库的总大小及文件明细,本文结合实例代码给大家介绍的非常详细,感兴趣的... 目录1. 直接使用SQL1.1 查询当前数据库大小1.2 查询所有数据库的大小1.3 查询每个数据库的详

Spring Boot 整合 SSE(Server-Sent Events)实战案例(全网最全)

《SpringBoot整合SSE(Server-SentEvents)实战案例(全网最全)》本文通过实战案例讲解SpringBoot整合SSE技术,涵盖实现原理、代码配置、异常处理及前端交互,... 目录Spring Boot 整合 SSE(Server-Sent Events)1、简述SSE与其他技术的对

Android 缓存日志Logcat导出与分析最佳实践

《Android缓存日志Logcat导出与分析最佳实践》本文全面介绍AndroidLogcat缓存日志的导出与分析方法,涵盖按进程、缓冲区类型及日志级别过滤,自动化工具使用,常见问题解决方案和最佳实... 目录android 缓存日志(Logcat)导出与分析全攻略为什么要导出缓存日志?按需过滤导出1. 按

Linux中的HTTPS协议原理分析

《Linux中的HTTPS协议原理分析》文章解释了HTTPS的必要性:HTTP明文传输易被篡改和劫持,HTTPS通过非对称加密协商对称密钥、CA证书认证和混合加密机制,有效防范中间人攻击,保障通信安全... 目录一、什么是加密和解密?二、为什么需要加密?三、常见的加密方式3.1 对称加密3.2非对称加密四、

MySQL中读写分离方案对比分析与选型建议

《MySQL中读写分离方案对比分析与选型建议》MySQL读写分离是提升数据库可用性和性能的常见手段,本文将围绕现实生产环境中常见的几种读写分离模式进行系统对比,希望对大家有所帮助... 目录一、问题背景介绍二、多种解决方案对比2.1 原生mysql主从复制2.2 Proxy层中间件:ProxySQL2.3

python使用Akshare与Streamlit实现股票估值分析教程(图文代码)

《python使用Akshare与Streamlit实现股票估值分析教程(图文代码)》入职测试中的一道题,要求:从Akshare下载某一个股票近十年的财务报表包括,资产负债表,利润表,现金流量表,保存... 目录一、前言二、核心知识点梳理1、Akshare数据获取2、Pandas数据处理3、Matplotl

python panda库从基础到高级操作分析

《pythonpanda库从基础到高级操作分析》本文介绍了Pandas库的核心功能,包括处理结构化数据的Series和DataFrame数据结构,数据读取、清洗、分组聚合、合并、时间序列分析及大数据... 目录1. Pandas 概述2. 基本操作:数据读取与查看3. 索引操作:精准定位数据4. Group

MySQL中EXISTS与IN用法使用与对比分析

《MySQL中EXISTS与IN用法使用与对比分析》在MySQL中,EXISTS和IN都用于子查询中根据另一个查询的结果来过滤主查询的记录,本文将基于工作原理、效率和应用场景进行全面对比... 目录一、基本用法详解1. IN 运算符2. EXISTS 运算符二、EXISTS 与 IN 的选择策略三、性能对比

SQL Server跟踪自动统计信息更新实战指南

《SQLServer跟踪自动统计信息更新实战指南》本文详解SQLServer自动统计信息更新的跟踪方法,推荐使用扩展事件实时捕获更新操作及详细信息,同时结合系统视图快速检查统计信息状态,重点强调修... 目录SQL Server 如何跟踪自动统计信息更新:深入解析与实战指南 核心跟踪方法1️⃣ 利用系统目录