00001 // 00002 // BTClients.cpp 00003 // 00004 // Copyright (c) Shareaza Development Team, 2002-2005. 00005 // This file is part of SHAREAZA (www.shareaza.com) 00006 // 00007 // Shareaza is free software; you can redistribute it 00008 // and/or modify it under the terms of the GNU General Public License 00009 // as published by the Free Software Foundation; either version 2 of 00010 // the License, or (at your option) any later version. 00011 // 00012 // Shareaza is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 // GNU General Public License for more details. 00016 // 00017 // You should have received a copy of the GNU General Public License 00018 // along with Shareaza; if not, write to the Free Software 00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00020 // 00021 00022 #include "StdAfx.h" 00023 #include "Shareaza.h" 00024 #include "Settings.h" 00025 #include "Transfers.h" 00026 #include "BTClients.h" 00027 #include "BTClient.h" 00028 #include "BTTrackerRequest.h" 00029 #include "GProfile.h" 00030 00031 #ifdef _DEBUG 00032 #undef THIS_FILE 00033 static char THIS_FILE[]=__FILE__; 00034 #define new DEBUG_NEW 00035 #endif 00036 00037 CBTClients BTClients; 00038 00039 00041 // CBTClients construction 00042 00043 CBTClients::CBTClients() 00044 { 00045 m_bShutdown = FALSE; 00046 } 00047 00048 CBTClients::~CBTClients() 00049 { 00050 Clear(); 00051 } 00052 00054 // CBTClients clear 00055 00056 void CBTClients::Clear() 00057 { 00058 for ( POSITION pos = GetIterator() ; pos ; ) 00059 { 00060 GetNext( pos )->Close(); 00061 } 00062 00063 ShutdownRequests(); 00064 } 00065 00066 00068 // CBTClients GUID->SHA1 filter 00069 00070 //Note: This was removed and placed in the transfer, after a request from people running trackers. 00071 // They wanted a per-download generated ID, not static. (Do not retain between sessions.) 00072 00073 //Note 2: Official spec says "Generate per download", which is as per above. 00074 // Unofficial spec says "Generate at startup", which is how it used to be. Which is correct? 00075 00076 /* 00077 SHA1* CBTClients::GetGUID() 00078 { 00079 (GGUID&)m_pGUID = MyProfile.GUID; 00080 00081 for ( int nByte = 16 ; nByte < 20 ; nByte++ ) 00082 { 00083 m_pGUID.n[ nByte ] = MyProfile.GUID.n[ nByte % 16 ] 00084 ^ MyProfile.GUID.n[ 15 - ( nByte % 16 ) ]; 00085 } 00086 00087 return &m_pGUID; 00088 } 00089 */ 00090 00092 // CBTClients accept new connections 00093 00094 BOOL CBTClients::OnAccept(CConnection* pConnection) 00095 { 00096 ASSERT( pConnection != NULL ); 00097 00098 CSingleLock pLock( &Transfers.m_pSection ); 00099 if ( ! pLock.Lock( 250 ) ) return FALSE; 00100 00101 CBTClient* pClient = new CBTClient(); 00102 pClient->AttachTo( pConnection ); 00103 00104 return TRUE; 00105 } 00106 00108 // CBTClients add and remove 00109 00110 void CBTClients::Add(CBTClient* pClient) 00111 { 00112 ASSERT( m_pList.Find( pClient ) == NULL ); 00113 m_pList.AddHead( pClient ); 00114 } 00115 00116 void CBTClients::Remove(CBTClient* pClient) 00117 { 00118 POSITION pos = m_pList.Find( pClient ); 00119 ASSERT( pos != NULL ); 00120 m_pList.RemoveAt( pos ); 00121 } 00122 00124 // CBTClients request thread management 00125 00126 void CBTClients::Add(CBTTrackerRequest* pRequest) 00127 { 00128 CSingleLock pLock( &m_pSection, TRUE ); 00129 ASSERT( ! m_bShutdown ); 00130 m_pRequests.AddTail( pRequest ); 00131 } 00132 00133 void CBTClients::Remove(CBTTrackerRequest* pRequest) 00134 { 00135 CSingleLock pLock( &m_pSection, TRUE ); 00136 if ( POSITION pos = m_pRequests.Find( pRequest ) ) m_pRequests.RemoveAt( pos ); 00137 if ( ! m_bShutdown || m_pRequests.GetCount() > 0 ) return; 00138 pLock.Unlock(); 00139 m_pShutdown.SetEvent(); 00140 } 00141 00142 void CBTClients::ShutdownRequests() 00143 { 00144 CSingleLock pLock( &m_pSection, TRUE ); 00145 00146 if ( m_pRequests.GetCount() == 0 ) return; 00147 m_bShutdown = TRUE; 00148 pLock.Unlock(); 00149 00150 if ( WaitForSingleObject( m_pShutdown, 5000 ) == WAIT_OBJECT_0 ) return; 00151 00152 while ( TRUE ) 00153 { 00154 pLock.Lock(); 00155 if ( m_pRequests.GetCount() == 0 ) break; 00156 CBTTrackerRequest* pRequest = (CBTTrackerRequest*)m_pRequests.RemoveHead(); 00157 HANDLE hThread = pRequest->m_hThread; 00158 pLock.Unlock(); 00159 CHttpRequest::CloseThread( &hThread, _T("CBTTrackerRequest") ); 00160 } 00161 }