FileZilla 源代码分析7
创始人
2024-07-21 11:40:58
0

FileZilla是一种快速、可信赖的FTP客户端以及服务器端开放源代码程式,具有多种特色、直觉的接口。本文就给大家分析下FileZilla的源代码。

  服务线程苏醒后,调用OnThreadMessage来处理这个WM_FILEZILLA_THREADMSG消息,参数是FTM_NEWSOCKET, sockethandle,接着进入AddNewSocket方法,表示有一个新的客户端需要连接上来。

  void CServerThread::AddNewSocket(SOCKET sockethandle, bool ssl)

  {

  // 首先创建了新的CControlSocket类,这也是继承于CAsyncSocketEx类的,从下面起经过一些初始化之后,就由这个CControlSocket类来接管这个客户连接了。

  CControlSocket *socket = new CControlSocket(this);

  socket->Attach(sockethandle); // 加入到FileZilla消息机制中, 建立与分发线程等之间的关系

  CStdString ip;

  unsigned int port;

  SOCKADDR_IN sockAddr;

  memset(&sockAddr, 0, sizeof(sockAddr));

  int nSockAddrLen = sizeof(sockAddr);

  BOOL bResult = socket->GetPeerName((SOCKADDR*)&sockAddr, &nSockAddrLen); // 获取socket客户端的信息

  if (bResult)

  {

  port = ntohs(sockAddr.sin_port); // 端口

  ip = inet_ntoa(sockAddr.sin_addr); // IP地址

  }

  else

  {

  socket->m_RemoteIP = _T("ip unknown");

  socket->m_userid = 0;

  socket->SendStatus(_T("Can't get remote IP, disconnected"), 1);

  socket->Close();

  delete socket;

  return;

  }

  socket->m_RemoteIP= ip;

  EnterCritSection(m_GlobalThreadsync);

  int userid = CalcUserID(); // 自动为当前socket连接生成一个客户号:userID

  if (userid == -1)

  {

  LeaveCritSection(m_GlobalThreadsync);

  socket->m_userid = 0;

  socket->SendStatus(_T("Refusing connection, server too busy!"), 1);

  socket->Send(_T("421 Server too busy, closing connection. Please retry later!"));

  socket->Close();

  delete socket;

  return;

  }

  socket->m_userid = userid;

  t_socketdata data;

  data.pSocket = socket;

  data.pThread = this;

  m_userids[userid] = data; // m_userids是static的,定义为static std::map m_userids;

  // hammering这块可以先不管

  // Check if remote IP is blocked due to hammering

  std::map::iterator iter = m_antiHammerInfo.find(sockAddr.sin_addr.s_addr);

  if (iter != m_antiHammerInfo.end())

  {

  if (iter->second > 10)

  socket->AntiHammerIncrease(25); // ~6 secs delay

  }

  LeaveCritSection(m_GlobalThreadsync);

  EnterCritSection(m_threadsync);

  // 下面记录这个服务线程所处理的CControlSocket

  m_LocalUserIDs[userid] = socket;

  LeaveCritSection(m_threadsync);

  t_connectiondata_add *conndata = new t_connectiondata_add;

  t_connop *op = new t_connop;

  op->data = conndata;

  op->op = USERCONTROL_CONNOP_ADD; // 新用户连接即将连接,在CServer的OnServerMessage中要用过

  op->userid = userid;

  conndata->pThread = this;

  memset(&sockAddr, 0, sizeof(sockAddr));

  nSockAddrLen = sizeof(sockAddr);

  bResult = socket->GetPeerName((SOCKADDR*)&sockAddr, &nSockAddrLen);

  if (bResult)

  {

  conndata->port = ntohs(sockAddr.sin_port);

  #ifdef _UNICODE

  _tcscpy(conndata->ip, ConvFromLocal(inet_ntoa(sockAddr.sin_addr))); // 拷贝字符串

  #else

  _tcscpy(conndata->ip, inet_ntoa(sockAddr.sin_addr));

  #endif

  }

  // 这里往全局的hMainWnd发送消息,

  // 消息的wParam类型为FSM_CONNECTIONDATA, 指示消息是跟connection相关的消息,参数是t_connop

  // 这些在CServer的WindowProc中处理这个消息时用到,这个消息处理结束后,会在admin窗口的下边显示

  // 类似000001 (not logged in) 127.0.0.1 的信息

  SendNotification(FSM_CONNECTIONDATA, (LPARAM)op);

  if (ssl) // SSL相关, 可以先跳过

  if (!socket->InitImplicitSsl())

  return;

  socket->AsyncSelect(FD_READ|FD_WRITE|FD_CLOSE); // 对socket上这些event建立侦听关系

  // SendStatus最终还是调用SendNotification方法,不过发送的参数是FSM_STATUSMESSAGE,

  // 因此在CServer中的处理并不一样

  socket->SendStatus(_T("Connected, sending welcome message..."), 0);

  // 这时,admin窗口的下半部分会显示类似(000003) 2006-8-24 3:26:47 - (not logged in) (127.0.0.1)> Connected, sending welcome message...

  // 下面格式化欢迎信息

  CStdString msg = m_pOptions->GetOption(OPTION_WELCOMEMESSAGE);

  if (m_RawWelcomeMessage != msg)

  {

  m_RawWelcomeMessage = msg;

  m_ParsedWelcomeMessage.clear();

  msg.Replace(_T("%%"), _T("\001"));

  msg.Replace(_T("%v"), GetVersionString());

  msg.Replace(_T("\001"), _T("%"));

  ASSERT(msg != _T(""));

  int oldpos = 0;

  msg.Replace(_T("\r\n"), _T("\n"));

  int pos=msg.Find(_T("\n"));

  CStdString line;

  while (pos!=-1)

  {

  ASSERT(pos);

  m_ParsedWelcomeMessage.push_back(_T("220-") + msg.Mid(oldpos, pos-oldpos) );

  oldpos=pos + 1;

  pos=msg.Find(_T("\n"), oldpos);

  }

  line = msg.Mid(oldpos);

  if (line != _T(""))

  m_ParsedWelcomeMessage.push_back(_T("220 ") + line);

  else

  {

  m_ParsedWelcomeMessage.back()[3] = 0;

  }

  }

  // hideStatus指示这个欢迎消息要不要发给admin port

  bool hideStatus = m_pOptions->GetOptionVal(OPTION_WELCOMEMESSAGE_HIDE) != 0;

  ASSERT(!m_ParsedWelcomeMessage.empty());

  for (std::list::iterator iter = m_ParsedWelcomeMessage.begin(); iter != m_ParsedWelcomeMessage.end(); iter++)

  // 发送给socket客户, 并且发送消息到admin port上,发送的参数是FSM_STATUSMESSAGE

  if (!socket->Send(*iter, !hideStatus))

  break;

  // 运行到这里,客户的登录界面上、admin窗口上半部已经出现了welcome信息,类似:

  // (000003) 2006-8-24 3:27:19 - (not logged in) (127.0.0.1)> 220-FileZilla Server version 0.9.18 beta

  // ((000003) 2006-8-24 3:27:22 - (not logged in) (127.0.0.1)> 220-written by Tim Kosse (Tim.Kosse@gmx.de)

  // ((000003) 2006-8-24 3:27:29 - (not logged in) (127.0.0.1)> 220 Please visit http://sourceforge.net/projects/filezilla/

通过文章完整的描述,大家应该知道了FileZilla 源代码,希望对大家有帮助!

【编辑推荐】

  1. FileZilla 源代码分析1
  2. FileZilla 源代码分析2
  3. FileZilla 源代码分析3
  4. FileZilla 源代码分析4
  5. FileZilla 源代码分析5
  6. FileZilla 源代码分析6
  7. FileZilla简单介绍

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...
《非诚勿扰》红人闫凤娇被曝厕所... 【51CTO.com 综合消息360安全专家提醒说,“闫凤娇”、“非诚勿扰”已经被黑客盯上成为了“木...
2012年第四季度互联网状况报... [[71653]]  北京时间4月25日消息,据国外媒体报道,全球知名的云平台公司Akamai Te...