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

大漠落日

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>
            欧美久久九九| 欧美精品一级| 国产欧美一区二区精品婷婷| 亚洲小说欧美另类婷婷| 亚洲视频axxx| 国内自拍视频一区二区三区| 麻豆精品一区二区av白丝在线| 久久这里只有| 亚洲精品资源美女情侣酒店| 日韩网站在线观看| 国产色综合网| 欧美二区在线播放| 欧美日韩国产精品| 久久激情视频免费观看| 欧美www视频在线观看| 在线亚洲精品| 久久精品人人做人人爽| 亚洲精品专区| 欧美一区二区三区四区在线观看地址| 亚洲国产成人av| 亚洲视频一区在线| 亚洲电影观看| 亚洲一二三四久久| 亚洲激情综合| 午夜久久tv| 亚洲色图制服丝袜| 久久久免费精品视频| 亚洲免费在线视频一区 二区| 性色av一区二区怡红| 日韩一区二区电影网| 欧美在线观看一区| 久久激情一区| 亚洲欧美bt| 洋洋av久久久久久久一区| 欧美中文在线观看国产| 夜夜嗨av一区二区三区| 久久不射中文字幕| 亚洲专区国产精品| 欧美精品99| 美女主播视频一区| 国产美女一区二区| 一本久久a久久免费精品不卡| 黄色成人在线网址| 亚洲欧美美女| 亚洲欧美日韩成人高清在线一区| 欧美黄色网络| 免费欧美在线视频| 国产综合色产| 性色av香蕉一区二区| 午夜精品久久久久99热蜜桃导演| 欧美日韩精品欧美日韩精品一| 欧美 日韩 国产在线| 韩日成人在线| 久久久精品tv| 乱人伦精品视频在线观看| 国产农村妇女毛片精品久久莱园子| 亚洲精品国产精品乱码不99| 一区二区三区亚洲| 欧美中文字幕在线观看| 久久精品国产v日韩v亚洲 | 久久久综合视频| 国产欧美精品一区二区色综合 | 久久精品人人做人人综合| 国产精品国产亚洲精品看不卡15| 99精品免费网| 亚洲午夜久久久久久久久电影网| 欧美日韩高清免费| 亚洲美女在线国产| 亚洲在线一区| 国产精品三上| 久久精品99国产精品日本| 久久久久国内| 亚洲国产精品一区二区三区| 麻豆久久婷婷| 亚洲精品中文字幕有码专区| 亚洲伊人观看| 国产麻豆综合| 久久综合九色欧美综合狠狠| 亚洲国产精品一区二区久| 亚洲视频大全| 国产一本一道久久香蕉| 久久亚洲图片| 亚洲人妖在线| 午夜在线精品偷拍| 国外成人在线视频| 欧美国产在线电影| 亚洲特色特黄| 欧美成人免费大片| 亚洲与欧洲av电影| 一区二区在线观看av| 欧美精品一线| 久久精品一区二区国产| 亚洲精品美女在线观看| 欧美一区二区在线| 亚洲精品乱码久久久久久蜜桃麻豆 | 激情综合五月天| 99国产精品久久| 久久麻豆一区二区| 夜色激情一区二区| 一区二区亚洲精品国产| 国产精品国产一区二区| 久热精品视频在线观看一区| 一区二区三区精密机械公司| 六月婷婷久久| 欧美在线一区二区| 日韩视频在线播放| 国模精品一区二区三区| 欧美色图天堂网| 久热综合在线亚洲精品| 亚洲影院在线| 日韩一级黄色大片| 欧美国产欧美综合| 久久成人18免费观看| 一区二区黄色| 亚洲免费播放| 亚洲国产精品一区二区第一页| 国产欧美日韩另类视频免费观看| 欧美精品三级日韩久久| 米奇777超碰欧美日韩亚洲| 香港久久久电影| 亚洲图片自拍偷拍| 日韩视频国产视频| 欧美激情小视频| 暖暖成人免费视频| 久久伊人亚洲| 久久在线视频在线| 久久久www成人免费无遮挡大片 | 亚洲资源在线观看| 99xxxx成人网| 99精品欧美一区二区三区| 亚洲国产日韩欧美一区二区三区| 国产一区999| 国产喷白浆一区二区三区| 国产精品日韩欧美一区| 欧美色精品在线视频| 欧美日韩一区成人| 欧美视频网址| 国产精品日韩高清| 国产色产综合产在线视频| 国产毛片精品国产一区二区三区| 国产精品日韩在线播放| 国产精品日日摸夜夜添夜夜av| 欧美性片在线观看| 国产精品色网| 国产主播一区二区三区| 激情久久久久久久久久久久久久久久| 国产欧美日韩一区二区三区在线观看 | 亚洲精品影视在线观看| 日韩亚洲精品视频| 亚洲私人黄色宅男| 午夜日韩电影| 久久黄色网页| 久久综合伊人77777尤物| 久久久亚洲成人| 嫩草国产精品入口| 欧美啪啪成人vr| 国产精品青草综合久久久久99| 国产欧美亚洲一区| 亚洲第一久久影院| 亚洲女同在线| 久久久999成人| 欧美日韩hd| 国产精品影视天天线| 在线精品国产欧美| 麻豆久久精品| 黄色日韩网站| 国产一区二区成人| 亚洲日本va在线观看| 亚洲视频中文| 蜜桃久久精品乱码一区二区| 亚洲九九九在线观看| 午夜精品短视频| 欧美电影在线观看完整版| 欧美婷婷在线| 在线亚洲精品| 久久久久九九视频| 欧美三级午夜理伦三级中视频| 狠狠狠色丁香婷婷综合久久五月 | 精品盗摄一区二区三区| 亚洲最黄网站| 毛片基地黄久久久久久天堂| 亚洲美女在线一区| 久久久一本精品99久久精品66| 欧美日本精品| 一区在线电影| 欧美一区二区高清| 亚洲国产精品电影在线观看| 性一交一乱一区二区洋洋av| 欧美国产精品久久| 国产三级精品三级| 亚洲天堂网站在线观看视频| 蜜桃av一区二区三区| 亚洲男人av电影| 欧美日韩精品一本二本三本| 亚洲高清久久| 美女视频黄 久久| 翔田千里一区二区| 国产精品久久久久天堂| 一本色道久久88综合亚洲精品ⅰ| 卡一卡二国产精品|