青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

大漠落日

while(!dead) study++;
posts - 46, comments - 126, trackbacks - 0, articles - 0
  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

FileZilla Server源碼分析(3)

Posted on 2010-06-10 13:38 亂78糟 閱讀(2357) 評論(1)  編輯 收藏 引用 所屬分類: 開源
這是分析的第三節,上一節主要講了一些和socket基礎操作相關的代碼,本節將分析核心代碼。

Service.cpp   系統服務程序

FileZillaServer可以選擇是否注冊成windows的服務程序,而這個服務程序的代碼就是由service.cpp文件實現的。
WinMain是它的入口函數,在WinMain里依次完成了下面幾項任務:
  1. 參數解析
  2. 初始化某些數據比如端口
  3. 由SCM(服務控制管理器)啟動服務,入口為ServiceMain函數;如果服務不存在,進入步驟4
  4. 根據參數設置服務,例如安裝、啟動、卸載等。
ServiceMain注冊ServiceCtrlHandler來處理服務的控制代碼,在回調函數ServiceCtrlHandler中自定義了128號控制碼,用于向窗口"FileZilla Server Helper Window"發送重新讀取配置的自定義消息WM_FILEZILLA_RELOADCONFIG
serviceMain注冊Handler成功之后,就啟動自己的工作線程ServiceExecutionThread,線程里創建了CServer對象,然后實際流程交由CServer。之后進入線程的消息循環并等待killServiceEvent信號以退出線程終止服務。
Service.cpp中KillService函數中有一個變量hMainWnd,它是在stdafx.h中聲明的,它具體是哪個窗口的句柄,干什么用,現在還是一無所知。


Server.*  真正的帶頭大哥

打開Server.h文件,開頭就可以看到許多類的前置聲明,類中聲明了眾多上一節提到的相關類對象(或集合如list),CServer類把所有核心類(線程和socket)集中起來使用。
上面已經提到Service的工作線程中調用了CServer的Create函數,我們就先從這里入手吧。
Create一開始就創建了一個窗口,標題為"FileZilla Server Helper Window",呵呵,是不是很熟悉?然后將這個窗口的句柄賦給全局變量hMainWnd,至此,終于大致了解了服務的框架骨骼。
之后又是一大堆初始化操作,包括兩個定時器,需要特別注意的是創建服務線程CServerThread時候的提供的參數WM_FILEZILLA_SERVERMSG + index,這個參數用以線程間通信,再上一節已經有過描述,稍后再具體分析。
在往下調用了CreateListenSocket函數,這個函數根據Options類中獲取的port、bindip、enablessl等參數創建監聽ftp客戶端連接的CListenSocket對象指針,并保存到m_ListenSocketList中。這里有一個很重要的函數ShowStatus,它的任務是將信息發送給admin窗口和記錄到log中。
最后調用CreateAdminListenSocket函數創建監聽admin客戶端的socket,并存入m_AdminListenSocketList中。

CServer類的分析暫時中斷一下,我們來分析上面涉及到的幾個相關類:CServerThread,CListenSocket,CControlSocket,CTransferSocket。

CServerThread繼承自CThread,構造函數有個int型參數,用來標識具體哪個線程的消息。注意,CThread本身并不是一個直接繼承于任何線程類的類,它只是負責創建并管理線程的類。m_sInstanceList是static的成員變量,被所有的CServerThread對象共享,而且這個list存儲的第一個值用于管理SL,為了標識它,作者又添加了一個BOOL成員變量m_bIsMaster,同樣還有一個static臨界區變量m_GlobalThreadsync用來同步它。如果當前對象是master,那么它還擁有一個用于實現PASV模式的CExternalIpCheck的類對象m_pExternalIpCheck,缺省值是不采用PASV的。

對CServerThread的重要的幾個Public成員函數分析一下功能:
  • GetExternalIP : 調用m_pExternalIpCheck獲取PASV的ip
  • AddSocket:給自己發送一個線程消息,該消息在OnThreadMessage函數中被處理,用來添加(SSL)socket連接

對CServerThread重要的幾個非public成員函數分析一下功能:
  • AddNewSocket:將sokcet handle綁定到新new的CControlSocket對象socket上,并為當前socket分配一個唯一的用戶ID。分配函數CalcUserID不算高效,尤其是連接用戶數量比較大的時候再分配尤其明顯。之后調用SendNotification準備發送包含連接用戶的信息的消息給CServer,最后向連接的用戶發送歡迎信息。
  • SendNotification:這個函數將需要發送的數據加入待發送list中,最牛的是它可以自動調節發送的效率。不過我發現一處小BUG,可能作者自己也沒有注意到,這兩處設置線程優先級貌似反了:
else if (m_pendingNotifications.size() > 150 && m_throttled < 2)
{
    SetPriority(THREAD_PRIORITY_LOWEST);
    m_throttled 
= 2;
}
else if (m_pendingNotifications.size() > 100 && !m_throttled)
{
    SetPriority(THREAD_PRIORITY_BELOW_NORMAL);
    m_throttled 
= 1;
}

  • OnThreadMessage:線程消息處理函數,如添加刪除用戶,解析命令,傳輸,控制,計時器等。

CListenSocket類功能很簡單,如果一個連接被accept,那么從服務線程CServerThread列表中找到負載最小的線程,然后調用的AddSocket函數,將這個連接交給這個CServerTread管理。

CControlSocket類負責與客戶端交互。
它有一個int型成員變量m_antiHammeringWaitTime,用來防止用戶攻擊(即無限次嘗試登錄),例如某用戶在60秒內連續嘗試登錄10次失敗,那么就把這個用戶加入ban列表中,比如3000秒內拒絕再次登錄等。AntiHammerIncrease 函數中對這個變量的算法沒看明白
if (m_status.hammerValue > 2000)
    m_antiHammeringWaitTime 
+= 1000 * (int)pow(1.3, (m_status.hammerValue / 400- 5);
在用戶登錄的時候就去檢測是否是“攻擊”,代碼如下:
    BOOL bResult = GetPeerName((SOCKADDR*)&sockAddr, &nSockAddrLen);
        
if (bResult)
            m_pOwner
->AntiHammerIncrease(sockAddr.sin_addr.s_addr);

        
if (m_pOwner->m_pAutoBanManager->RegisterAttempt(htonl(sockAddr.sin_addr.s_addr)))
        {
            Send(_T(
"421 Temporarily banned for too many failed login attempts"));
            ForceClose(
-1);
            
return FALSE;
        }

PassCommand函數處理所有的命令,如USER、LIST、PASV、STOR等。當收到STOR命令時,如果是PASV模式,那么調用m_transferstatus.socket->PasvTransfer(),否則新建一個CTransferSocket套接字賦給m_transferstatus.socket,然后調用SendTransferinfoNotification發送TRANSFERMODE_RECEIVE消息。不管哪種方式,最后還是通過調用CTransferSocket的InitTransfer函數實現文件傳輸。


好了,現在讓我們恢復現場。
CServer類的消息處理函數WindowProc,處理了各種消息,其中重要的是WM_DESTROYWM_FILEZILLA_SERVERMSG。前者通知并等待所有線程退出,關閉socket,銷毀資源,殺死定時器,做的都是清理工作。后者根據服務線程發送來的消息進入函數OnServerMessage中,這個函數處理了所有服務管理的消息。可以看到,很多消息最后都是通過m_pAdminInterface->SendCommand(2, 3, buffer, len)這句發送出去。CAdminInterface類管理CAdminSocket類的指針列表,SendCommand其實是調用CAdminSocket的SendCommand將消息發送出去。函數中對admin socket做了自動管理,如果操作失敗,就自動移除該socket。
CheckForTimeout每10秒由CServer的定時器調用一次,檢測admin socket是否超時,如果超時,自動移除。CAdminSocket收到數據并解析成功之后,最終交由CServer的ProcessCommand處理,該函數再一次根據Options里的設置對線程、socket進行一次校驗和調整。

我個人對ProcessCommand和SendCommand函數參數中的type或nID為int型有微議,因為這兩個參數實際只占用了不到8個字節,寫為int不利于理解,如果改成int8一眼就能看出來這個參數具體占用幾個字節。
BOOL CAdminSocket::SendCommand(int nType, int nID, const void *pData, int nDataLength)
{
    
/**/
    t_data data;
    data.pData 
= new unsigned char[nDataLength + 5];
    
*data.pData = nType;     //nType目前版本只要不為0就是合法的協議類型,代碼中用到了1和2
    
*data.pData |= nID << 2//nType和nID合用一個8字節
    data.dwOffset = 0;
    memcpy(data.pData 
+ 1&nDataLength, 4);
    
/**/
}

下面重點分析一下ProcessCommand這個函數,用偽代碼比較直觀。
BOOL CServer::ProcessCommand(CAdminSocket *pAdminSocket, int nID, unsigned char *pData, int nDataLength)
{
    
switch(nID)
    { 
    
case 2:
       
if (!nDataLength)
           
//獲取服務器狀態
       else
           
//設置服務器狀態并獲取
       else
           
//send error:wrong protocol type
       break;
     
case 3:
        
if (!nDataLength)
           
//send error
        else if (*pData == USERCONTROL_GETLIST)
           
//計算并格式化所有已連接用戶的信息到unsigned char *buffer中并發送給admin
           
//這些數據顯示在admin UI下方的user list中
        else if (*pData == USERCONTROL_KICK || *pData == USERCONTROL_BAN)
            
//*pData共5個字節,第一個為具體協議類型,后四個為userID。
            
//根據協議對userID進行操作,kick或者Ban掉。
        else
             
//send error: wrong protocol type
         break;
    
case 5:
         
if (!nDataLength)
            
//讀取基本配置然后發送給admin
         else if (*m_pOptions)
            
//解析配置字符串,創建初始化或調整CServerThread
            
//CreateListenSocket
            
//創建admin監聽sockets
          break;
     
case 6:
          
if (!nDataLength)
              
//讀取user和group的權限配置
          else
              
//解析權限配置發送給admin
          break;
     
case 8:
          pAdminSocket
->SendCommand(18, NULL, 0);
          
break;
      
default:
          
//send error: unknow command
    }
    
return true;
}

這一節涵蓋了眾多核心代碼,上面的分析相對來說還是比較粗略,所以,后面幾節在對這些粗略和遺漏部分在做更為詳細深入的挖掘,本節到這里就結束了。
因為都是看代碼時臨時寫入筆記的,所有的分析都很雜亂,希望以后我有時間可以畫一些圖,重新做一次整理。
2010-7-22補充
圖隨便畫了幾張,鏈接在此

PS: 本來上周就可以貼出來了,可是因為安裝MAC系統造成C盤WINDOWS系統數據破壞無法啟動,重裝系統導致筆記丟失,這里只能補上,拖后了一周左右。

Feedback

# re: FileZilla Server源碼分析(3) [未登錄]  回復  更多評論   

2012-03-19 16:34 by ww
SendNotification:這個函數將需要發送的數據加入待發送list中,最牛的是它可以自動調節發送的效率。不過我發現一處小BUG,可能作者自己也沒有注意到,這兩處設置線程優先級貌似反了

這個他在注釋中已經寫了
// Check if main thread can't handle number of notifications fast enough, throttle thread if neccessary


是要讓主系程 降低優先級的 并沒有作者所說的反了
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲尤物视频网| 欧美日韩人人澡狠狠躁视频| 国产精品视频免费一区| 亚洲一级黄色av| 在线一区二区三区四区| 国产精品美女久久久| 欧美日韩精品| 亚洲欧美一区二区原创| 午夜在线成人av| 在线精品福利| 亚洲国产一区二区三区在线播 | 亚洲九九精品| 国产精品视频网址| 久久久亚洲精品一区二区三区| 久久青草欧美一区二区三区| 亚洲精品自在在线观看| 亚洲视频在线视频| 一色屋精品视频在线看 | 亚洲在线播放| 久久久久久久久综合| 亚洲最新色图| 久久九九国产| 亚洲一区三区视频在线观看| 久久国产精品99国产精| 99在线|亚洲一区二区| 亚洲欧美一区二区精品久久久| 亚洲国产导航| 亚洲欧美一区二区三区极速播放| 91久久精品国产91性色| 亚洲欧美日韩综合| 日韩午夜精品| 久久九九免费视频| 亚洲综合色视频| 欧美不卡高清| 久久视频免费观看| 欧美视频中文一区二区三区在线观看 | 欧美 日韩 国产精品免费观看| 亚洲欧美国产日韩天堂区| 免费欧美日韩| 麻豆国产精品777777在线| 国产精品久久久久9999吃药| 亚洲福利在线观看| 狠狠色狠色综合曰曰| 中文精品视频| 亚洲视频在线一区观看| 免费视频一区| 欧美成人一区二区三区在线观看| 国产美女扒开尿口久久久| 99这里只有久久精品视频| 亚洲国产乱码最新视频| 久久精品在这里| 久久gogo国模裸体人体| 国产精品免费一区豆花| 99re8这里有精品热视频免费 | 国内精品伊人久久久久av一坑| 99伊人成综合| 亚洲系列中文字幕| 欧美啪啪成人vr| 亚洲国产一区二区三区高清| 亚洲精品久久视频| 欧美成人高清| 亚洲黄色在线| 一区二区三区日韩精品视频| 欧美国产精品久久| 亚洲黄色影院| 亚洲在线电影| 日韩视频不卡| 欧美日韩国产免费| 午夜精品久久久久久99热| 欧美人与禽猛交乱配| 亚洲人午夜精品| 在线亚洲观看| 国产精品三级视频| 亚洲欧美成人网| 久久久久综合| 亚洲精品国精品久久99热一| 欧美国产日韩一区二区| 亚洲免费激情| 久久久噜噜噜久久人人看| 在线成人中文字幕| 欧美黑人国产人伦爽爽爽| 99视频精品全国免费| 午夜宅男久久久| 激情五月婷婷综合| 欧美18av| 亚洲欧美日本精品| 免费久久99精品国产自| 亚洲日本欧美在线| 国产精品久久久99| 久久夜色精品国产欧美乱极品| 亚洲高清久久网| 午夜日韩电影| 亚洲福利精品| 国产精品jizz在线观看美国| 久久av二区| 亚洲精品日韩精品| 久久久久久网站| 一本色道久久综合精品竹菊| 国产乱肥老妇国产一区二| 欧美在线精品一区| 亚洲精品你懂的| 久久久午夜精品| 一区二区日韩| 伊伊综合在线| 国产精品乱码一区二区三区| 久久中文欧美| 亚洲女女做受ⅹxx高潮| 亚洲电影第1页| 久久久精品国产一区二区三区 | 一区二区高清在线观看| 国产日韩欧美二区| 欧美日韩国产美女| 久热精品在线| 亚洲欧美一区二区激情| 日韩视频免费观看高清完整版| 久久精品国产在热久久| 亚洲视频免费看| 91久久精品一区| 国产一区二区三区久久| 欧美视频一区二区三区四区| 欧美顶级少妇做爰| 久久久一区二区三区| 午夜精品国产| 亚洲视频免费在线观看| 亚洲国产精品一区制服丝袜| 久久亚洲精品伦理| 久久9热精品视频| 亚洲欧美国产精品va在线观看| 亚洲精品视频二区| 亚洲高清视频一区| 黑丝一区二区| 国产又爽又黄的激情精品视频| 国产精品久久久久久久久久三级| 欧美国产日韩一区二区在线观看| 久久乐国产精品| 欧美在线免费观看亚洲| 香蕉国产精品偷在线观看不卡| 亚洲精品午夜精品| 国产午夜久久久久| 国产精品久久久久av免费| 欧美色综合天天久久综合精品| 欧美成人精品一区二区三区| 久久久99久久精品女同性| 欧美在线日韩| 久久久亚洲国产美女国产盗摄| 性欧美8khd高清极品| 午夜电影亚洲| 久久精品2019中文字幕| 久久国产精品免费一区| 久久久久综合一区二区三区| 久久精品人人| 巨胸喷奶水www久久久免费动漫| 久久青青草原一区二区| 奶水喷射视频一区| 欧美日韩精品在线| 国产精品高清免费在线观看| 国产精品伦子伦免费视频| 国产麻豆日韩| 亚洲第一区在线观看| 亚洲国产精品高清久久久| 99精品视频免费全部在线| 亚洲一区在线免费观看| 欧美在线地址| 美女国内精品自产拍在线播放| 欧美成人dvd在线视频| 亚洲精品小视频在线观看| 99re这里只有精品6| 亚洲一区日韩| 久久久7777| 欧美精品九九| 国产日韩欧美黄色| 亚洲国产日韩美| 亚洲欧美网站| 亚洲第一中文字幕| 亚洲欧美日韩精品久久奇米色影视 | 亚洲激情欧美激情| 亚洲性视频网站| 久久青青草综合| 亚洲精品色图| 久久国产精品黑丝| 欧美日韩精品| 在线日韩视频| 午夜视频在线观看一区二区三区| 免费欧美视频| 亚洲永久在线观看| 欧美国产视频在线观看| 激情欧美亚洲| 悠悠资源网久久精品| 亚洲男同1069视频| 欧美福利电影在线观看| 亚洲欧美网站| 欧美午夜不卡视频| 日韩亚洲欧美中文三级| 久久米奇亚洲| 亚洲一区二区在线看| 欧美精品啪啪| 91久久精品国产91性色tv| 亚洲专区免费| 亚洲免费观看高清在线观看| 欧美大片免费久久精品三p|