00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "StdAfx.h"
00023 #include "Shareaza.h"
00024 #include "Settings.h"
00025 #include "RouteCache.h"
00026 #include "Packet.h"
00027
00028 #ifdef _DEBUG
00029 #undef THIS_FILE
00030 static char THIS_FILE[]=__FILE__;
00031 #define new DEBUG_NEW
00032 #endif
00033
00034 #define HASH_SIZE 1024
00035 #define HASH_MASK 0x3FF
00036
00037 #define MIN_BUFFER_SIZE 1024
00038 #define MAX_BUFFER_SIZE 40960
00039 #define BUFFER_BLOCK_SIZE 1024
00040
00041
00043
00044
00045 CRouteCache::CRouteCache()
00046 {
00047 m_nSeconds = 60 * 20;
00048 m_pRecent = &m_pTable[0];
00049 m_pHistory = &m_pTable[1];
00050 }
00051
00052 CRouteCache::~CRouteCache()
00053 {
00054 }
00055
00057
00058
00059 void CRouteCache::SetDuration(DWORD nSeconds)
00060 {
00061 m_nSeconds = nSeconds;
00062 Clear();
00063 }
00064
00065 BOOL CRouteCache::Add(const GGUID* pGUID, const CNeighbour* pNeighbour)
00066 {
00067 if ( CRouteCacheItem* pItem = Lookup( pGUID ) )
00068 {
00069 pItem->m_pNeighbour = pNeighbour;
00070 return FALSE;
00071 }
00072
00073 if ( m_pRecent->IsFull() )
00074 {
00075 CRouteCacheTable* pTemp = m_pRecent;
00076 m_pRecent = m_pHistory;
00077 m_pHistory = pTemp;
00078
00079 m_pRecent->Resize( m_pHistory->GetNextSize( m_nSeconds ) );
00080 }
00081
00082 m_pRecent->Add( pGUID, pNeighbour, NULL );
00083
00084 return TRUE;
00085 }
00086
00087 BOOL CRouteCache::Add(const GGUID* pGUID, const SOCKADDR_IN* pEndpoint)
00088 {
00089 if ( CRouteCacheItem* pItem = Lookup( pGUID ) )
00090 {
00091 pItem->m_pNeighbour = NULL;
00092 pItem->m_pEndpoint = *pEndpoint;
00093 return FALSE;
00094 }
00095
00096 if ( m_pRecent->IsFull() )
00097 {
00098 CRouteCacheTable* pTemp = m_pRecent;
00099 m_pRecent = m_pHistory;
00100 m_pHistory = pTemp;
00101
00102 m_pRecent->Resize( m_pHistory->GetNextSize( m_nSeconds ) );
00103 }
00104
00105 m_pRecent->Add( pGUID, NULL, pEndpoint );
00106
00107 return TRUE;
00108 }
00109
00110 CRouteCacheItem* CRouteCache::Add(const GGUID* pGUID, const CNeighbour* pNeighbour, const SOCKADDR_IN* pEndpoint, DWORD tAdded)
00111 {
00112 GGUID cGUID = *pGUID;
00113 SOCKADDR_IN cEndpoint;
00114 if ( pEndpoint != NULL ) cEndpoint = *pEndpoint;
00115
00116 if ( m_pRecent->IsFull() )
00117 {
00118 CRouteCacheTable* pTemp = m_pRecent;
00119 m_pRecent = m_pHistory;
00120 m_pHistory = pTemp;
00121
00122 m_pRecent->Resize( m_pHistory->GetNextSize( m_nSeconds ) );
00123 }
00124
00125 return m_pRecent->Add( &cGUID, pNeighbour, pEndpoint != NULL ? &cEndpoint : NULL, tAdded );
00126 }
00127
00128 CRouteCacheItem* CRouteCache::Lookup(const GGUID* pGUID, CNeighbour** ppNeighbour, SOCKADDR_IN* pEndpoint)
00129 {
00130 CRouteCacheItem* pItem = m_pRecent->Find( pGUID );
00131
00132 if ( pItem == NULL )
00133 {
00134 pItem = m_pHistory->Find( pGUID );
00135
00136 if ( pItem == NULL )
00137 {
00138 if ( ppNeighbour ) *ppNeighbour = NULL;
00139 if ( pEndpoint ) ZeroMemory( pEndpoint, sizeof(*pEndpoint) );
00140
00141 return NULL;
00142 }
00143
00144 pItem = Add( &pItem->m_pGUID, pItem->m_pNeighbour,
00145 pItem->m_pNeighbour ? NULL : &pItem->m_pEndpoint, pItem->m_tAdded );
00146 }
00147
00148 if ( ppNeighbour ) *ppNeighbour = (CNeighbour*)pItem->m_pNeighbour;
00149 if ( pEndpoint ) *pEndpoint = pItem->m_pEndpoint;
00150
00151 return pItem;
00152 }
00153
00154 void CRouteCache::Remove(CNeighbour* pNeighbour)
00155 {
00156 m_pTable[0].Remove( pNeighbour );
00157 m_pTable[1].Remove( pNeighbour );
00158 }
00159
00160 void CRouteCache::Clear()
00161 {
00162 m_pTable[0].Clear();
00163 m_pTable[1].Clear();
00164 }
00165
00166
00168
00169
00170 CRouteCacheTable::CRouteCacheTable()
00171 {
00172 m_pBuffer = NULL;
00173 m_nBuffer = 0;
00174 m_nUsed = 0;
00175 Clear();
00176 }
00177
00178 CRouteCacheTable::~CRouteCacheTable()
00179 {
00180 if ( m_pBuffer && m_nBuffer ) delete [] m_pBuffer;
00181 }
00182
00184
00185
00186 CRouteCacheItem* CRouteCacheTable::Find(const GGUID* pGUID)
00187 {
00188 WORD nGUID = 0, *ppGUID = (WORD*)pGUID;
00189 for ( int nIt = 8 ; nIt ; nIt-- ) nGUID += *ppGUID++;
00190
00191 CRouteCacheItem* pItem = *( m_pHash + ( nGUID & HASH_MASK ) );
00192
00193 for ( ; pItem ; pItem = pItem->m_pNext )
00194 {
00195 if ( *pGUID == pItem->m_pGUID ) return pItem;
00196 }
00197
00198 return NULL;
00199 }
00200
00201 CRouteCacheItem* CRouteCacheTable::Add(const GGUID* pGUID, const CNeighbour* pNeighbour, const SOCKADDR_IN* pEndpoint, DWORD nTime)
00202 {
00203 if ( m_nUsed == m_nBuffer || ! m_pFree ) return NULL;
00204
00205 WORD nGUID = 0, *ppGUID = (WORD*)pGUID;
00206 for ( int nIt = 8 ; nIt ; nIt-- ) nGUID += *ppGUID++;
00207
00208 CRouteCacheItem** pHash = m_pHash + ( nGUID & HASH_MASK );
00209
00210 CRouteCacheItem* pItem = m_pFree;
00211 m_pFree = m_pFree->m_pNext;
00212
00213 pItem->m_pNext = *pHash;
00214 *pHash = pItem;
00215
00216 pItem->m_pGUID = *pGUID;
00217 pItem->m_tAdded = nTime ? nTime : GetTickCount();
00218 pItem->m_pNeighbour = pNeighbour;
00219 if ( pEndpoint ) pItem->m_pEndpoint = *pEndpoint;
00220
00221 if ( ! m_nUsed++ )
00222 {
00223 m_tFirst = GetTickCount();
00224 }
00225 else if ( m_nUsed == m_nBuffer )
00226 {
00227 m_tLast = GetTickCount();
00228 }
00229
00230 return pItem;
00231 }
00232
00233 void CRouteCacheTable::Remove(CNeighbour* pNeighbour)
00234 {
00235 CRouteCacheItem** pHash = m_pHash;
00236
00237 for ( int nHash = 0 ; nHash < HASH_SIZE ; nHash++, pHash++ )
00238 {
00239 CRouteCacheItem** pLast = pHash;
00240
00241 for ( CRouteCacheItem* pItem = *pLast ; pItem ; )
00242 {
00243 CRouteCacheItem* pNext = pItem->m_pNext;
00244
00245 if ( pItem->m_pNeighbour == pNeighbour )
00246 {
00247 *pLast = pNext;
00248 pItem->m_pNext = m_pFree;
00249 m_pFree = pItem;
00250 m_nUsed--;
00251 }
00252 else
00253 {
00254 pLast = &pItem->m_pNext;
00255 }
00256
00257 pItem = pNext;
00258 }
00259 }
00260 }
00261
00262 void CRouteCacheTable::Resize(DWORD nSize)
00263 {
00264 nSize = min( max( nSize, DWORD(MIN_BUFFER_SIZE) ), DWORD(MAX_BUFFER_SIZE) );
00265 nSize = ( ( nSize + BUFFER_BLOCK_SIZE - 1 ) / BUFFER_BLOCK_SIZE * BUFFER_BLOCK_SIZE );
00266
00267 if ( nSize != m_nBuffer )
00268 {
00269 if ( m_pBuffer && m_nBuffer ) delete [] m_pBuffer;
00270
00271 m_nBuffer = nSize;
00272 m_pBuffer = nSize ? ( new CRouteCacheItem[ m_nBuffer ] ) : NULL;
00273 }
00274
00275 ZeroMemory( m_pHash, sizeof(CRouteCacheItem*) * HASH_SIZE );
00276
00277 m_pFree = m_pBuffer;
00278 m_nUsed = 0;
00279 m_tFirst = 0;
00280 m_tLast = 0;
00281
00282 CRouteCacheItem* pItem = m_pBuffer;
00283
00284 for ( DWORD nPos = m_nBuffer ; nPos ; nPos--, pItem++ )
00285 {
00286 if ( nPos == 1 )
00287 {
00288 pItem->m_pNext = NULL;
00289 }
00290 else
00291 {
00292 pItem->m_pNext = pItem + 1;
00293 }
00294 }
00295 }
00296
00297 DWORD CRouteCacheTable::GetNextSize(DWORD nDesired)
00298 {
00299 DWORD nSeconds = ( m_tLast - m_tFirst ) / 1000;
00300 if ( ! nSeconds ) nSeconds = 1;
00301
00302 return m_nBuffer * nDesired / nSeconds;
00303 }
00304
00305 void CRouteCacheTable::Clear()
00306 {
00307 Resize( 0 );
00308 }