home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 217 / DPCS0306DVD.ISO / Toolkit / Internet / FileZilla / Server / FileZilla_Server-0.9.11.exe / source / ServerThread.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2005-08-03  |  25.2 KB  |  917 lines

  1. // FileZilla Server - a Windows ftp server
  2.  
  3. // Copyright (C) 2002-2004 - Tim Kosse <tim.kosse@gmx.de>
  4.  
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9.  
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14.  
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software
  17. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. // ServerThread.cpp: Implementierungsdatei
  20. //
  21.  
  22. #include "stdafx.h"
  23. #include "ServerThread.h"
  24. #include "ControlSocket.h"
  25. #include "transfersocket.h"
  26. #include "Options.h"
  27. #include "version.h"
  28. #include "Permissions.h"
  29. #include "ExternalIpCheck.h"
  30.  
  31. #ifdef _DEBUG
  32. #undef THIS_FILE
  33. static char THIS_FILE[] = __FILE__;
  34. #endif
  35.  
  36. std::map<int, t_socketdata> CServerThread::m_userids;
  37. CCriticalSectionWrapper CServerThread::m_GlobalThreadsync;
  38. std::map<CStdString, int> CServerThread::m_userIPs;
  39. std::list<CServerThread*> CServerThread::m_sInstanceList;
  40. std::map<DWORD, int> CServerThread::m_antiHammerInfo;
  41.  
  42. /////////////////////////////////////////////////////////////////////////////
  43. // CServerThread
  44.  
  45. CServerThread::CServerThread(int nNotificationMessageId)
  46. {
  47.     m_nNotificationMessageId = nNotificationMessageId;
  48. }
  49.  
  50. CServerThread::~CServerThread()
  51. {
  52. }
  53.  
  54. BOOL CServerThread::InitInstance()
  55. {
  56.     BOOL res = TRUE;
  57.     WSADATA wsaData;
  58.     
  59.     WORD wVersionRequested = MAKEWORD(1, 1);
  60.     int nResult = WSAStartup(wVersionRequested, &wsaData);
  61.     if (nResult != 0)
  62.         res=FALSE;
  63.     else if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
  64.     {
  65.         WSACleanup();
  66.         res=FALSE;
  67.     }
  68.     
  69.     m_timerid = SetTimer(0, 0, 1000, 0);
  70.     m_nRateTimer = SetTimer(0, 0, 100, 0);
  71.  
  72.     // Reduce anti hammer value twice an hour
  73.     m_antiHammerTimer = SetTimer(0, 0, 1800 * 1000, 0);
  74.  
  75.     m_bQuit = FALSE;
  76.     m_nRecvCount = 0;
  77.     m_nSendCount = 0;
  78.     m_pOptions = new COptions;
  79.     m_pPermissions = new CPermissions;
  80.  
  81.     EnterCritSection(m_GlobalThreadsync);
  82.     if (m_sInstanceList.empty())
  83.         m_bIsMaster = TRUE;
  84.     else
  85.         m_bIsMaster = FALSE;
  86.     m_sInstanceList.push_back(this);
  87.     LeaveCritSection(m_GlobalThreadsync);
  88.  
  89.     m_nLoopCount = 0;
  90.  
  91.     EnterCritSection(m_threadsync);
  92.     if (!m_bIsMaster)
  93.         m_pExternalIpCheck = NULL;
  94.     else
  95.         m_pExternalIpCheck = new CExternalIpCheck(this);
  96.     LeaveCritSection(m_threadsync);
  97.  
  98.     m_throttled = 0;
  99.  
  100.     return TRUE;
  101. }
  102.  
  103. DWORD CServerThread::ExitInstance()
  104. {
  105.     ASSERT(m_pPermissions);
  106.     delete m_pPermissions;
  107.     m_pPermissions=0;
  108.     delete m_pOptions;
  109.     m_pOptions=0;
  110.     KillTimer(0, m_timerid);
  111.     KillTimer(0, m_nRateTimer);
  112.     WSACleanup();
  113.  
  114.     if (m_bIsMaster)
  115.     {
  116.         EnterCritSection(m_threadsync);
  117.         delete m_pExternalIpCheck;
  118.         m_pExternalIpCheck = NULL;
  119.         LeaveCritSection(m_threadsync);
  120.     }
  121.  
  122.     EnterCritSection(m_GlobalThreadsync);
  123.     m_sInstanceList.remove(this);
  124.     if (!m_sInstanceList.empty())
  125.         m_sInstanceList.front()->m_bIsMaster = TRUE;
  126.     LeaveCritSection(m_GlobalThreadsync);
  127.  
  128.     return 0;
  129. }
  130.  
  131. /////////////////////////////////////////////////////////////////////////////
  132. // Behandlungsroutinen fⁿr Nachrichten CServerThread 
  133.  
  134. const int CServerThread::GetNumConnections()
  135. {
  136.     EnterCritSection(m_threadsync);
  137.     int num = m_LocalUserIDs.size();
  138.     LeaveCritSection(m_threadsync);
  139.     return num;
  140. }
  141.  
  142. void CServerThread::AddSocket(SOCKET sockethandle, bool ssl)
  143. {
  144.     PostThreadMessage(WM_FILEZILLA_THREADMSG, ssl ? FTM_NEWSOCKET_SSL : FTM_NEWSOCKET, (LPARAM)sockethandle);
  145. }
  146.  
  147. #define IDMAX 1000000000
  148. int CServerThread::CalcUserID()
  149. {
  150.     if (m_userids.size() >= IDMAX)
  151.         return -1;
  152.     static int curid=0;
  153.     curid++;
  154.     if (curid==IDMAX)
  155.         curid=1;
  156.     while (m_userids.find(curid) != m_userids.end())
  157.     {
  158.         curid++;
  159.         if (curid == IDMAX)
  160.             curid=1;
  161.     }
  162.     return curid;
  163. }
  164.  
  165. void CServerThread::AddNewSocket(SOCKET sockethandle, bool ssl)
  166. {
  167.     CControlSocket *socket = new CControlSocket(this);
  168.     socket->Attach(sockethandle);
  169.     CStdString ip;
  170.     unsigned int port;
  171.     
  172.     SOCKADDR_IN sockAddr;
  173.     memset(&sockAddr, 0, sizeof(sockAddr));
  174.     int nSockAddrLen = sizeof(sockAddr);
  175.     BOOL bResult = socket->GetPeerName((SOCKADDR*)&sockAddr, &nSockAddrLen);
  176.     if (bResult)
  177.     {
  178.         port = ntohs(sockAddr.sin_port);
  179.         ip = inet_ntoa(sockAddr.sin_addr);
  180.     }
  181.     else
  182.     {
  183.         socket->m_RemoteIP = "ip unknown";
  184.         socket->m_userid = 0;
  185.         socket->SendStatus("Can't get remote IP, disconnected", 1);
  186.         socket->Close();
  187.         delete socket;
  188.         return;
  189.     }
  190.     socket->m_RemoteIP=  ip;
  191.     EnterCritSection(m_GlobalThreadsync);
  192.     int userid = CalcUserID();
  193.     if (userid == -1)
  194.     {
  195.         LeaveCritSection(m_GlobalThreadsync);
  196.         socket->m_userid = 0;
  197.         socket->SendStatus("Refusing connection, server too busy!", 1);
  198.         socket->Send("421 Server too busy, closing connection. Please retry later!");
  199.         socket->Close();
  200.         delete socket;
  201.         return;
  202.     }
  203.     socket->m_userid = userid;
  204.     t_socketdata data;
  205.     data.pSocket = socket;
  206.     data.pThread = this;
  207.     m_userids[userid] = data;
  208.  
  209.     // Check if remote IP is blocked due to hammering
  210.     std::map<DWORD, int>::iterator iter = m_antiHammerInfo.find(sockAddr.sin_addr.s_addr);
  211.     if (iter != m_antiHammerInfo.end())
  212.     {
  213.         if (iter->second > 10)
  214.             socket->AntiHammerIncrease(25); // ~6 secs delay
  215.     }
  216.     LeaveCritSection(m_GlobalThreadsync);
  217.     EnterCritSection(m_threadsync);
  218.     m_LocalUserIDs[userid] = socket;
  219.     LeaveCritSection(m_threadsync);
  220.  
  221.     t_connectiondata_add *conndata = new t_connectiondata_add;
  222.     t_connop *op = new t_connop;
  223.     op->data = conndata;
  224.     op->op = USERCONTROL_CONNOP_ADD;
  225.     op->userid = userid;
  226.     conndata->pThread = this;
  227.  
  228.     memset(&sockAddr, 0, sizeof(sockAddr));
  229.     nSockAddrLen = sizeof(sockAddr);
  230.     bResult = socket->GetPeerName((SOCKADDR*)&sockAddr, &nSockAddrLen);
  231.     if (bResult)
  232.     {
  233.         conndata->port = ntohs(sockAddr.sin_port);
  234.         strcpy(conndata->ip, inet_ntoa(sockAddr.sin_addr));
  235.     }
  236.  
  237.     SendNotification(FSM_CONNECTIONDATA, (LPARAM)op);
  238.  
  239.     if (ssl)
  240.         if (!socket->InitImplicitSsl())
  241.             return;
  242.     
  243.     socket->AsyncSelect(FD_READ|FD_WRITE|FD_CLOSE);
  244.     socket->SendStatus("Connected, sending welcome message...", 0);
  245.     
  246.     CStdString msg = m_pOptions->GetOption(OPTION_WELCOMEMESSAGE);
  247.     if (m_RawWelcomeMessage != msg)
  248.     {
  249.         m_RawWelcomeMessage = msg;
  250.         m_ParsedWelcomeMessage.clear();
  251.  
  252.         msg.Replace("%%", "\001");
  253.         msg.Replace("%v", GetVersionString());
  254.         msg.Replace("\001", "%");
  255.     
  256.         ASSERT(msg!="");
  257.         int oldpos=0;
  258.         msg.Replace("\r\n", "\n");
  259.         int pos=msg.Find("\n");
  260.         CStdString line;
  261.         while (pos!=-1)
  262.         {
  263.             ASSERT(pos);
  264.             m_ParsedWelcomeMessage.push_back("220-" +  msg.Mid(oldpos, pos-oldpos) );
  265.             oldpos=pos+1;
  266.             pos=msg.Find("\n", oldpos);
  267.         }
  268.     
  269.         line = msg.Mid(oldpos);
  270.         if (line != "")
  271.             m_ParsedWelcomeMessage.push_back("220 " + line);        
  272.         else
  273.         {
  274.             m_ParsedWelcomeMessage.back()[3] = 0;
  275.         }
  276.     }
  277.     
  278.     bool hideStatus = m_pOptions->GetOptionVal(OPTION_WELCOMEMESSAGE_HIDE) != 0;
  279.     ASSERT(!m_ParsedWelcomeMessage.empty());
  280.     for (std::list<CStdString>::iterator iter = m_ParsedWelcomeMessage.begin(); iter != m_ParsedWelcomeMessage.end(); iter++)
  281.         if (!socket->Send(*iter, !hideStatus))
  282.             break;
  283. }
  284.  
  285. int CServerThread::OnThreadMessage(UINT Msg, WPARAM wParam, LPARAM lParam)
  286. {
  287.     if (Msg == WM_FILEZILLA_THREADMSG)
  288.     {
  289.         if (wParam == FTM_NEWSOCKET) //Add a new socket to this thread
  290.             AddNewSocket((SOCKET)lParam, false);
  291.         else if (wParam == FTM_NEWSOCKET_SSL) //Add a new socket to this thread
  292.             AddNewSocket((SOCKET)lParam, true);
  293.         else if (wParam==FTM_DELSOCKET) //Remove a socket from this thread
  294.         {
  295.             CControlSocket *socket=GetControlSocket(lParam);
  296.             EnterCritSection(m_threadsync);
  297.             if (m_LocalUserIDs.find(lParam)!=m_LocalUserIDs.end())
  298.                 m_LocalUserIDs.erase(m_LocalUserIDs.find(lParam));
  299.             LeaveCritSection(m_threadsync);
  300.             if (socket)
  301.             {
  302.                 socket->Close();
  303.                 EnterCritSection(m_GlobalThreadsync);
  304.                 if (m_userids.find(lParam)!=m_userids.end())
  305.                     m_userids.erase(m_userids.find(lParam));
  306.                 LeaveCritSection(m_GlobalThreadsync);
  307.                 delete socket;
  308.             }
  309.             EnterCritSection(m_threadsync);
  310.             if (m_bQuit)
  311.             {
  312.                 int count=m_LocalUserIDs.size();
  313.                 LeaveCritSection(m_threadsync);
  314.                 if (!count)
  315.                     SendNotification(FSM_THREADCANQUIT, (LPARAM)this);
  316.             }
  317.             else
  318.                 LeaveCritSection(m_threadsync);
  319.         }
  320.         else if (wParam==FTM_COMMAND)
  321.         { //Process a command sent from a client
  322.             CControlSocket *socket=GetControlSocket(lParam);
  323.             if (socket)
  324.                 socket->ParseCommand();
  325.         }
  326.         else if (wParam==FTM_TRANSFERMSG)
  327.         {
  328.             CControlSocket *socket=GetControlSocket(lParam);
  329.             if (socket)
  330.                 socket->ProcessTransferMsg();
  331.         }
  332.         else if (wParam==FTM_GOOFFLINE)
  333.         {
  334.             EnterCritSection(m_threadsync);
  335.             m_bQuit = TRUE;
  336.             int count = m_LocalUserIDs.size();
  337.             if (!count)
  338.             {
  339.                 LeaveCritSection(m_threadsync);
  340.                 SendNotification(FSM_THREADCANQUIT, (LPARAM)this);
  341.                 return 0;
  342.             }
  343.             if (lParam==2)
  344.             {
  345.                 LeaveCritSection(m_threadsync);
  346.                 return 0;
  347.             }
  348.             for (std::map<int, CControlSocket *>::iterator iter=m_LocalUserIDs.begin(); iter!=m_LocalUserIDs.end(); iter++)
  349.             {
  350.                 switch (lParam)
  351.                 {
  352.                 case 2:
  353.                     iter->second->WaitGoOffline(false);
  354.                     break;
  355.                 case 0:
  356.                 default:
  357.                     iter->second->ForceClose(0);
  358.                     break;
  359.                 case 1:
  360.                     iter->second->WaitGoOffline(true);
  361.                     break;
  362.                 }
  363.             }
  364.             LeaveCritSection(m_threadsync);
  365.         }
  366.         else if (wParam == FTM_CONTROL)
  367.             ProcessControlMessage((t_controlmessage *)lParam);
  368.     }
  369.     else if (Msg == WM_TIMER)
  370.         OnTimer(wParam, lParam);
  371.     return 0;
  372. }
  373.  
  374. void CServerThread::OnTimer(WPARAM wParam,LPARAM lParam)
  375. {
  376.     if (wParam == m_timerid)
  377.     {
  378.         EnterCritSection(m_threadsync);
  379.         
  380.         /* 
  381.          * Check timeouts and collect transfer file offsets.
  382.          * Do both in the same loop to save performance.
  383.          */
  384.  
  385.         /*
  386.          * Maximum memory required for file offsets:
  387.          * 2 unused prefix bytes, will be filled by CServer,
  388.          * This avoids buffer copying.
  389.          * For each connection 4 bytes for the userid
  390.          * and 8 for the offset.
  391.          * We do not need to store the number of elements, this
  392.          * information can be calculated from the length if neccessary.
  393.          */
  394.         int bufferLen = 2 + m_LocalUserIDs.size() * 12;
  395.         unsigned char* buffer = new unsigned char[bufferLen];
  396.         unsigned char* p = buffer + 2;
  397.         for (std::map<int, CControlSocket *>::iterator iter = m_LocalUserIDs.begin(); iter != m_LocalUserIDs.end(); iter++)
  398.         {
  399.             CControlSocket* pSocket = iter->second;
  400.             CTransferSocket* pTransferSocket = pSocket->GetTransferSocket();
  401.             if (pTransferSocket && pTransferSocket->WasActiveSinceCheck())
  402.             {
  403.                 memcpy(p, &iter->first, 4);
  404.                 p += 4;
  405.                 __int64 offset = pTransferSocket->GetCurrentFileOffset();
  406.                 memcpy(p, &offset, 8);
  407.                 p += 8;
  408.             }
  409.             iter->second->CheckForTimeout();
  410.         }
  411.         
  412.         if ((p - buffer) <= 2)
  413.             delete [] buffer;
  414.         else
  415.         {
  416.             t_connectiondata_transferoffsets* conndata = new t_connectiondata_transferoffsets;
  417.             conndata->pData = buffer;
  418.             conndata->len = p - buffer;
  419.             t_connop* op = new t_connop;
  420.             op->data = conndata;
  421.             op->op = USERCONTROL_CONNOP_TRANSFEROFFSETS;
  422.             SendNotification(FSM_CONNECTIONDATA, (LPARAM)op);
  423.         }
  424.  
  425.         LeaveCritSection(m_threadsync);
  426.  
  427.         // Check if master thread has changed
  428.         if (m_bIsMaster && !m_pExternalIpCheck)
  429.         {
  430.             EnterCritSection(m_threadsync);
  431.             m_pExternalIpCheck = new CExternalIpCheck(this);
  432.             LeaveCritSection(m_threadsync);
  433.         }
  434.     }
  435.     else if (wParam==m_nRateTimer)
  436.     {
  437.         if (m_nSendCount)
  438.         {    
  439.             SendNotification(FSM_SEND, m_nSendCount);
  440.             m_nSendCount = 0;
  441.         }
  442.         if (m_nRecvCount)
  443.         {    
  444.             SendNotification(FSM_RECV, m_nRecvCount);
  445.             m_nRecvCount = 0;
  446.         }
  447.  
  448.         if (m_bIsMaster)
  449.         {
  450.             EnterCritSection(m_GlobalThreadsync);
  451.  
  452.             std::list<CServerThread *>::iterator iter;
  453.  
  454.             //Only update the speed limits from the rule set every 2 seconds to improve performance
  455.             if (!m_nLoopCount)
  456.             {
  457.                 m_lastLimits[download] = m_pOptions->GetCurrentSpeedLimit(download);
  458.                 m_lastLimits[upload] = m_pOptions->GetCurrentSpeedLimit(upload);
  459.             }
  460.             ++m_nLoopCount %= 20;
  461.  
  462.             // Gather transfer statistics if a speed limit is set
  463.             if (m_lastLimits[download] != -1 || m_lastLimits[upload] != -1)
  464.                 for (iter = m_sInstanceList.begin(); iter != m_sInstanceList.end(); iter++)
  465.                 {
  466.                     CServerThread *pThread = *iter;
  467.                     EnterCritSection(pThread->m_threadsync);
  468.                     pThread->GatherTransferedBytes();
  469.                     LeaveCritSection(pThread->m_threadsync);
  470.                 }
  471.  
  472.             for (int i = 0; i < 2; i++)
  473.             {
  474.                 int limit = m_lastLimits[i];
  475.  
  476.                 if (limit == -1)
  477.                 {
  478.                     for (iter = m_sInstanceList.begin(); iter != m_sInstanceList.end(); iter++)
  479.                     {
  480.                         CServerThread *pThread = *iter;
  481.                         EnterCritSection(pThread->m_threadsync);
  482.                         pThread->m_SlQuotas[i].nBytesAllowedToTransfer = -1;
  483.                         pThread->m_SlQuotas[i].nTransferred = 0;
  484.                         LeaveCritSection(pThread->m_threadsync);
  485.                     }
  486.                     continue;
  487.                 }
  488.  
  489.                 limit *= 100;
  490.                 
  491.                 int nRemaining = limit;
  492.                 int nThreadLimit = limit / m_sInstanceList.size();
  493.                 
  494.                 std::list<CServerThread *> fullUsageList;
  495.                 
  496.                 for (iter = m_sInstanceList.begin(); iter != m_sInstanceList.end(); iter++)
  497.                 {
  498.                     CServerThread *pThread = *iter;
  499.                     EnterCritSection(pThread->m_threadsync);
  500.                     int r = pThread->m_SlQuotas[i].nBytesAllowedToTransfer - pThread->m_SlQuotas[i].nTransferred;
  501.                     if ( r > 0 && pThread->m_SlQuotas[i].nBytesAllowedToTransfer <= nThreadLimit)
  502.                     {
  503.                         pThread->m_SlQuotas[i].nBytesAllowedToTransfer = nThreadLimit;
  504.                         nRemaining -= pThread->m_SlQuotas[i].nTransferred;
  505.                         pThread->m_SlQuotas[i].nTransferred = 0;
  506.                     }
  507.                     else if (r > 0 && pThread->m_SlQuotas[i].nTransferred < nThreadLimit)
  508.                     {
  509.                         pThread->m_SlQuotas[i].nBytesAllowedToTransfer = nThreadLimit;
  510.                         nRemaining -= pThread->m_SlQuotas[i].nTransferred;
  511.                         pThread->m_SlQuotas[i].nTransferred = 0;
  512.                     }
  513.                     else
  514.                     {
  515.                         fullUsageList.push_back(pThread);
  516.                         // Don't unlock thread here, do it later
  517.                         continue;
  518.                     }
  519.                     LeaveCritSection(pThread->m_threadsync);
  520.                 }
  521.                 
  522.                 // fullUsageList now contains all threads which did use up its assigned quota
  523.                 std::list<CServerThread *> fullUsageList2;
  524.                 if (!fullUsageList.empty())
  525.                 {
  526.                     nThreadLimit = nRemaining / fullUsageList.size();
  527.                     for (iter = fullUsageList.begin(); iter != fullUsageList.end(); iter++)
  528.                     {    
  529.                         CServerThread *pThread = *iter;
  530.  
  531.                         // Thread has already been locked
  532.                         int r = pThread->m_SlQuotas[i].nBytesAllowedToTransfer - pThread->m_SlQuotas[i].nTransferred;
  533.                         if (r > 0)
  534.                         {
  535.                             if (pThread->m_SlQuotas[i].nTransferred > nThreadLimit)
  536.                                 pThread->m_SlQuotas[i].nBytesAllowedToTransfer = nThreadLimit;
  537.                             else
  538.                                 pThread->m_SlQuotas[i].nBytesAllowedToTransfer = pThread->m_SlQuotas[i].nTransferred;
  539.                             pThread->m_SlQuotas[i].nTransferred = 0;
  540.                             nRemaining -= pThread->m_SlQuotas[i].nBytesAllowedToTransfer;
  541.                         }
  542.                         else
  543.                         {
  544.                             fullUsageList2.push_back(pThread);
  545.                             // Don't unlock thread here either, do it later
  546.                             continue;
  547.                         }
  548.                         LeaveCritSection(pThread->m_threadsync);
  549.                     }
  550.                     
  551.                     if (!fullUsageList2.empty())
  552.                     {
  553.                         nThreadLimit = nRemaining / fullUsageList2.size();
  554.                         for (iter = fullUsageList2.begin(); iter != fullUsageList2.end(); iter++)
  555.                         {    
  556.                             CServerThread *pThread = *iter;
  557.                             pThread->m_SlQuotas[i].nTransferred = 0;
  558.                             pThread->m_SlQuotas[i].nBytesAllowedToTransfer = nThreadLimit;
  559.  
  560.                             // Finally unlock threads
  561.                             LeaveCritSection(pThread->m_threadsync);
  562.                         }
  563.                     }
  564.                 }
  565.             }
  566.             
  567.             LeaveCritSection(m_GlobalThreadsync);
  568.         }
  569.         ProcessNewSlQuota();
  570.     }
  571.     else if (m_pExternalIpCheck && wParam == m_pExternalIpCheck->GetTimerID())
  572.     {
  573.         EnterCritSection(m_threadsync);
  574.         m_pExternalIpCheck->OnTimer();
  575.         LeaveCritSection(m_threadsync);
  576.     }
  577.     else if (wParam == m_antiHammerTimer && m_bIsMaster)
  578.         AntiHammerDecrease();
  579. }
  580.  
  581. const int CServerThread::GetGlobalNumConnections()
  582. {
  583.     EnterCritSection(m_GlobalThreadsync);
  584.     int num=m_userids.size();
  585.     LeaveCritSection(m_GlobalThreadsync);
  586.     return num;
  587. }
  588.  
  589. CControlSocket * CServerThread::GetControlSocket(int userid)
  590. {
  591.     CControlSocket *ret=0;
  592.     EnterCritSection(m_threadsync);
  593.     std::map<int, CControlSocket *>::iterator iter=m_LocalUserIDs.find(userid);
  594.     if (iter!=m_LocalUserIDs.end())
  595.         ret=iter->second;
  596.     LeaveCritSection(m_threadsync);
  597.     return ret;
  598. }
  599.  
  600. void CServerThread::ProcessControlMessage(t_controlmessage *msg)
  601. {
  602.     if (msg->command==USERCONTROL_KICK)
  603.     {
  604.         CControlSocket *socket=GetControlSocket(msg->socketid);
  605.         if (socket)
  606.             socket->ForceClose(4);
  607.     }
  608.     delete msg;
  609. }
  610.  
  611. BOOL CServerThread::IsReady()
  612. {
  613.     return !m_bQuit;
  614. }
  615.  
  616. int CServerThread::GetIpCount(const CStdString &ip) const
  617. {
  618.     int count=0;
  619.     EnterCritSection(m_GlobalThreadsync);
  620.     std::map<CStdString, int>::iterator iter=m_userIPs.find(ip);
  621.     if (iter!=m_userIPs.end())
  622.         count=iter->second;
  623.     LeaveCritSection(m_GlobalThreadsync);
  624.     return count;
  625. }
  626.  
  627. void CServerThread::IncIpCount(const CStdString &ip)
  628. {
  629.     int count;
  630.     EnterCritSection(m_GlobalThreadsync);
  631.     std::map<CStdString, int>::iterator iter=m_userIPs.find(ip);
  632.     if (iter!=m_userIPs.end())
  633.         count=iter->second++;
  634.     else
  635.         m_userIPs[ip]=1;
  636.     LeaveCritSection(m_GlobalThreadsync);
  637. }
  638.  
  639. void CServerThread::DecIpCount(const CStdString &ip)
  640. {
  641.     EnterCritSection(m_GlobalThreadsync);
  642.     std::map<CStdString, int>::iterator iter=m_userIPs.find(ip);
  643.     ASSERT(iter!=m_userIPs.end());
  644.     if (iter==m_userIPs.end())
  645.     {
  646.         LeaveCritSection(m_GlobalThreadsync);
  647.         return;
  648.     }
  649.     else
  650.     {
  651.         ASSERT(iter->second);
  652.         if (iter->second)
  653.             iter->second--;
  654.     }
  655.     LeaveCritSection(m_GlobalThreadsync);
  656. }
  657.  
  658. void CServerThread::IncSendCount(int count)
  659. {
  660.     m_nSendCount += count;
  661. }
  662.  
  663. void CServerThread::IncRecvCount(int count)
  664. {
  665.     m_nRecvCount += count;
  666. }
  667.  
  668. void CServerThread::ProcessNewSlQuota()
  669. {
  670.     EnterCritSection(m_threadsync);
  671.  
  672.     std::map<int, CControlSocket *>::iterator iter;
  673.  
  674.     for (int i = 0; i < 2; i++)
  675.     {
  676.         if (m_SlQuotas[i].nBytesAllowedToTransfer == -1)
  677.         {
  678.             for (iter = m_LocalUserIDs.begin(); iter != m_LocalUserIDs.end(); iter++)
  679.             {
  680.                 CControlSocket *pControlSocket = iter->second;
  681.                 pControlSocket->m_SlQuotas[i].nBytesAllowedToTransfer = -1;
  682.                 pControlSocket->m_SlQuotas[i].nTransferred = 0;
  683.             }
  684.             continue;
  685.         }
  686.     
  687.         int nRemaining = m_SlQuotas[i].nBytesAllowedToTransfer;
  688.         int nThreadLimit = nRemaining / m_sInstanceList.size();
  689.             
  690.         std::list<CControlSocket *> fullUsageList;
  691.         
  692.         for (iter = m_LocalUserIDs.begin(); iter != m_LocalUserIDs.end(); iter++)
  693.         {
  694.             CControlSocket *pControlSocket = iter->second;
  695.             int r = pControlSocket->m_SlQuotas[i].nBytesAllowedToTransfer - pControlSocket->m_SlQuotas[i].nTransferred;
  696.             if (pControlSocket->m_SlQuotas[i].nBytesAllowedToTransfer == -1)
  697.             {
  698.                 pControlSocket->m_SlQuotas[i].nBytesAllowedToTransfer = nThreadLimit;
  699.                 pControlSocket->m_SlQuotas[i].nTransferred = 0;
  700.             }
  701.             else if (r > 0 && pControlSocket->m_SlQuotas[i].nBytesAllowedToTransfer <= nThreadLimit)
  702.             {
  703.                 pControlSocket->m_SlQuotas[i].nBytesAllowedToTransfer = nThreadLimit;
  704.                 nRemaining -= pControlSocket->m_SlQuotas[i].nTransferred;
  705.                 pControlSocket->m_SlQuotas[i].nTransferred = 0;
  706.             }
  707.             else if (r > 0 && pControlSocket->m_SlQuotas[i].nTransferred < nThreadLimit)
  708.             {
  709.                 pControlSocket->m_SlQuotas[i].nBytesAllowedToTransfer = nThreadLimit;
  710.                 nRemaining -= pControlSocket->m_SlQuotas[i].nTransferred;
  711.                 pControlSocket->m_SlQuotas[i].nTransferred = 0;
  712.             }
  713.             else
  714.             {
  715.                 fullUsageList.push_back(pControlSocket);
  716.                 continue;
  717.             }
  718.         }
  719.         
  720.         std::list<CControlSocket *> fullUsageList2;
  721.         if (!fullUsageList.empty())
  722.         {
  723.             std::list<CControlSocket *>::iterator iter;
  724.             
  725.             nThreadLimit = nRemaining / fullUsageList.size();
  726.             for (iter = fullUsageList.begin(); iter != fullUsageList.end(); iter++)
  727.             {    
  728.                 CControlSocket *pControlSocket = *iter;
  729.                 int r = pControlSocket->m_SlQuotas[i].nBytesAllowedToTransfer - pControlSocket->m_SlQuotas[i].nTransferred;
  730.                 if (r)
  731.                 {
  732.                     if (pControlSocket->m_SlQuotas[i].nTransferred > nThreadLimit)
  733.                         pControlSocket->m_SlQuotas[i].nBytesAllowedToTransfer = nThreadLimit;
  734.                     else
  735.                         pControlSocket->m_SlQuotas[i].nBytesAllowedToTransfer = pControlSocket->m_SlQuotas[i].nTransferred;
  736.                     pControlSocket->m_SlQuotas[i].nTransferred = 0;
  737.                     nRemaining -= pControlSocket->m_SlQuotas[i].nBytesAllowedToTransfer;
  738.                 }
  739.                 else
  740.                 {
  741.                     fullUsageList2.push_back(pControlSocket);
  742.                     continue;
  743.                 }
  744.             }
  745.             
  746.             if (!fullUsageList2.empty())
  747.             {
  748.                 nThreadLimit = nRemaining / fullUsageList2.size();
  749.                 for (iter = fullUsageList2.begin(); iter != fullUsageList2.end(); iter++)
  750.                 {    
  751.                     CControlSocket *pControlSocket = *iter;
  752.                     pControlSocket->m_SlQuotas[i].nTransferred = 0;
  753.                     pControlSocket->m_SlQuotas[i].nBytesAllowedToTransfer = nThreadLimit;
  754.                 }
  755.             }
  756.         }
  757.     }
  758.     
  759.     for (iter = m_LocalUserIDs.begin(); iter != m_LocalUserIDs.end(); iter++)
  760.     {
  761.         CControlSocket *pControlSocket = iter->second;
  762.         pControlSocket->Continue();
  763.     }
  764.  
  765.     LeaveCritSection(m_threadsync);
  766. }
  767.  
  768. void CServerThread::GatherTransferedBytes()
  769. {
  770.     EnterCritSection(m_threadsync);
  771.     for (std::map<int, CControlSocket *>::iterator iter = m_LocalUserIDs.begin(); iter != m_LocalUserIDs.end(); iter++)
  772.     {
  773.         for (int i = 0; i < 2; i++)
  774.         {
  775.             if (iter->second->m_SlQuotas[i].nBytesAllowedToTransfer != -1)
  776.                 if (iter->second->m_SlQuotas[i].bBypassed)
  777.                     iter->second->m_SlQuotas[i].nTransferred = 0;
  778.                 else
  779.                     m_SlQuotas[i].nTransferred += iter->second->m_SlQuotas[i].nTransferred;
  780.  
  781.             iter->second->m_SlQuotas[i].bBypassed = false;
  782.         }
  783.     }
  784.     LeaveCritSection(m_threadsync);
  785. }
  786.  
  787. CStdString CServerThread::GetExternalIP()
  788. {
  789.     CStdString ip;
  790.     EnterCritSection(m_threadsync);
  791.     if (m_pExternalIpCheck)
  792.     {
  793.         ip = m_pExternalIpCheck->GetIP();
  794.         LeaveCritSection(m_threadsync);
  795.     }
  796.     else
  797.     {
  798.         LeaveCritSection(m_threadsync);
  799.         EnterCritSection(m_GlobalThreadsync);
  800.         CServerThread *pThread = m_sInstanceList.front();
  801.         EnterCritSection(pThread->m_threadsync);
  802.         if (pThread != this && pThread->m_pExternalIpCheck)
  803.             ip = pThread->m_pExternalIpCheck->GetIP();
  804.         LeaveCritSection(pThread->m_threadsync);
  805.         LeaveCritSection(m_GlobalThreadsync);
  806.     }
  807.  
  808.     return ip;
  809. }
  810.  
  811. void CServerThread::ExternalIPFailed()
  812. {
  813.     CStdString ip;
  814.     EnterCritSection(m_threadsync);
  815.     if (m_pExternalIpCheck)
  816.     {
  817.         m_pExternalIpCheck->TriggerUpdate();
  818.         LeaveCritSection(m_threadsync);
  819.     }
  820.     else
  821.     {
  822.         LeaveCritSection(m_threadsync);
  823.         EnterCritSection(m_GlobalThreadsync);
  824.         CServerThread *pThread = m_sInstanceList.front();
  825.         EnterCritSection(pThread->m_threadsync);
  826.         if (pThread != this && pThread->m_pExternalIpCheck)
  827.             pThread->m_pExternalIpCheck->TriggerUpdate();
  828.         LeaveCritSection(pThread->m_threadsync);
  829.         LeaveCritSection(m_GlobalThreadsync);
  830.     }
  831. }
  832.  
  833. void CServerThread::SendNotification(WPARAM wParam, LPARAM lParam)
  834. {
  835.     EnterCritSection(m_threadsync);
  836.     t_Notification notification;
  837.     notification.wParam = wParam;
  838.     notification.lParam = lParam;
  839.  
  840.     if (m_pendingNotifications.empty())
  841.         PostMessage(hMainWnd, m_nNotificationMessageId, 0, 0);
  842.  
  843.     m_pendingNotifications.push_back(notification);
  844.  
  845.     // Check if main thread can't handle number of notifications fast enough, throttle thread if neccessary
  846.     if (m_pendingNotifications.size() > 200 && m_throttled < 3)
  847.     {
  848.         SetPriority(THREAD_PRIORITY_IDLE);
  849.         m_throttled = 3;
  850.     }
  851.     else if (m_pendingNotifications.size() > 150 && m_throttled < 2)
  852.     {
  853.         SetPriority(THREAD_PRIORITY_LOWEST);
  854.         m_throttled = 2;
  855.     }
  856.     else if (m_pendingNotifications.size() > 100 && !m_throttled)
  857.     {
  858.         SetPriority(THREAD_PRIORITY_BELOW_NORMAL);
  859.         m_throttled = 1;
  860.     }
  861.     
  862.     LeaveCritSection(m_threadsync);
  863. }
  864.  
  865. void CServerThread::GetNotifications(std::list<CServerThread::t_Notification>& list)
  866. {
  867.     EnterCritSection(m_threadsync);
  868.  
  869.     m_pendingNotifications.swap(list);
  870.  
  871.     if (m_throttled)
  872.         SetPriority(THREAD_PRIORITY_NORMAL);
  873.  
  874.     LeaveCritSection(m_threadsync);
  875. }
  876.  
  877. void CServerThread::AntiHammerIncrease(DWORD ip)
  878. {
  879.     EnterCritSection(m_GlobalThreadsync);
  880.  
  881.     std::map<DWORD, int>::iterator iter = m_antiHammerInfo.find(ip);
  882.     if (iter != m_antiHammerInfo.end())
  883.     {
  884.         if (iter->second < 20)
  885.             iter->second++;
  886.         LeaveCritSection(m_GlobalThreadsync);
  887.         return;
  888.     }
  889.     if (m_antiHammerInfo.size() >= 1000)
  890.     {
  891.         std::map<DWORD, int>::iterator best = m_antiHammerInfo.begin();
  892.         for (iter = m_antiHammerInfo.begin(); iter != m_antiHammerInfo.end(); iter++)
  893.         {
  894.             if (iter->second < best->second)
  895.                 best = iter;
  896.         }
  897.         m_antiHammerInfo.erase(best);
  898.     }
  899.     m_antiHammerInfo.insert(std::map<DWORD, int>::value_type(ip, 1));
  900.  
  901.     LeaveCritSection(m_GlobalThreadsync);
  902. }
  903.  
  904. void CServerThread::AntiHammerDecrease()
  905. {
  906.     EnterCritSection(m_GlobalThreadsync);
  907.  
  908.     std::map<DWORD, int> newMap;
  909.     for (std::map<DWORD, int>::iterator iter = m_antiHammerInfo.begin(); iter != m_antiHammerInfo.end(); iter++)
  910.     {
  911.         if (iter->second > 1)
  912.             newMap.insert(std::map<DWORD, int>::value_type(iter->first, iter->second - 1));
  913.     }
  914.     m_antiHammerInfo = newMap;
  915.     
  916.     LeaveCritSection(m_GlobalThreadsync);
  917. }