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 "Transfers.h"
00026 #include "EDClient.h"
00027 #include "EDClients.h"
00028 #include "EDPacket.h"
00029
00030 #include "Network.h"
00031 #include "Security.h"
00032 #include "Datagrams.h"
00033 #include "Downloads.h"
00034 #include "QueryHit.h"
00035 #include "SearchManager.h"
00036
00037 #include "Neighbours.h"
00038 #include "HostCache.h"
00039
00040 #ifdef _DEBUG
00041 #undef THIS_FILE
00042 static char THIS_FILE[]=__FILE__;
00043 #define new DEBUG_NEW
00044 #endif
00045
00046 CEDClients EDClients;
00047
00048
00050
00051
00052 CEDClients::CEDClients()
00053 {
00054 m_pFirst = NULL;
00055 m_pLast = NULL;
00056 m_nCount = 0;
00057 m_tLastRun = 0;
00058 m_tLastMaxClients = 0;
00059 m_tLastServerStats = 0;
00060 m_nLastServerKey = 0;
00061 m_bAllServersDone = FALSE;
00062 }
00063
00064 CEDClients::~CEDClients()
00065 {
00066 Clear();
00067 }
00068
00070
00071
00072 void CEDClients::Add(CEDClient* pClient)
00073 {
00074 ASSERT( pClient->m_pEdPrev == NULL );
00075 ASSERT( pClient->m_pEdNext == NULL );
00076
00077 pClient->m_pEdPrev = m_pLast;
00078 pClient->m_pEdNext = NULL;
00079
00080 if ( m_pLast != NULL )
00081 {
00082 m_pLast->m_pEdNext = pClient;
00083 m_pLast = pClient;
00084 }
00085 else
00086 {
00087 m_pFirst = m_pLast = pClient;
00088 }
00089
00090 m_nCount++;
00091 }
00092
00093 void CEDClients::Remove(CEDClient* pClient)
00094 {
00095 ASSERT( m_nCount > 0 );
00096
00097 if ( pClient->m_pEdPrev != NULL )
00098 pClient->m_pEdPrev->m_pEdNext = pClient->m_pEdNext;
00099 else
00100 m_pFirst = pClient->m_pEdNext;
00101
00102 if ( pClient->m_pEdNext != NULL )
00103 pClient->m_pEdNext->m_pEdPrev = pClient->m_pEdPrev;
00104 else
00105 m_pLast = pClient->m_pEdPrev;
00106
00107 m_nCount --;
00108 }
00109
00111
00112
00113 void CEDClients::Clear()
00114 {
00115 for ( CEDClient* pClient = m_pFirst ; pClient ; )
00116 {
00117 CEDClient* pNext = pClient->m_pEdNext;
00118 pClient->Remove();
00119 pClient = pNext;
00120 }
00121
00122 ASSERT( m_pFirst == NULL );
00123 ASSERT( m_pLast == NULL );
00124 ASSERT( m_nCount == 0 );
00125 }
00126
00128
00129
00130 BOOL CEDClients::PushTo(DWORD nClientID, WORD nClientPort)
00131 {
00132 CEDClient* pClient = Connect( nClientID, nClientPort, NULL, 0, NULL );
00133 if ( pClient == NULL ) return FALSE;
00134 return pClient->Connect();
00135 }
00136
00138
00139
00140 CEDClient* CEDClients::Connect(DWORD nClientID, WORD nClientPort, IN_ADDR* pServerAddress, WORD nServerPort, GGUID* pGUID)
00141 {
00142 if ( pGUID != NULL )
00143 {
00144 if ( CEDClient* pClient = GetByGUID( pGUID ) ) return pClient;
00145 }
00146
00147 if ( IsFull() ) return NULL;
00148
00149 CEDClient* pClient = NULL;
00150
00151 if ( CEDPacket::IsLowID( nClientID ) )
00152 {
00153 if ( pServerAddress == NULL || nServerPort == 0 ) return NULL;
00154 pClient = GetByID( nClientID, pServerAddress, pGUID );
00155 }
00156 else
00157 {
00158 if ( Security.IsDenied( (IN_ADDR*)&nClientID ) ) return NULL;
00159 pClient = GetByID( nClientID, NULL, pGUID );
00160 }
00161
00162 if ( pClient == NULL )
00163 {
00164 pClient = new CEDClient();
00165 pClient->ConnectTo( nClientID, nClientPort, pServerAddress, nServerPort, pGUID );
00166 }
00167
00168 return pClient;
00169 }
00170
00172
00173
00174 CEDClient* CEDClients::GetByIP(IN_ADDR* pAddress)
00175 {
00176 for ( CEDClient* pClient = m_pFirst ; pClient ; pClient = pClient->m_pEdNext )
00177 {
00178 if ( pClient->m_pHost.sin_addr.S_un.S_addr == pAddress->S_un.S_addr )
00179 return pClient;
00180 }
00181
00182 return NULL;
00183 }
00184
00185 CEDClient* CEDClients::GetByID(DWORD nClientID, IN_ADDR* pServer, GGUID* pGUID)
00186 {
00187 for ( CEDClient* pClient = m_pFirst ; pClient ; pClient = pClient->m_pEdNext )
00188 {
00189 if ( pServer && pClient->m_pServer.sin_addr.S_un.S_addr != pServer->S_un.S_addr ) continue;
00190
00191 if ( pClient->m_nClientID == nClientID )
00192 {
00193 if ( pGUID == NULL || pClient->m_pGUID == *pGUID ) return pClient;
00194 }
00195 }
00196
00197 return NULL;
00198 }
00199
00200 CEDClient* CEDClients::GetByGUID(GGUID* pGUID)
00201 {
00202 for ( CEDClient* pClient = m_pFirst ; pClient ; pClient = pClient->m_pEdNext )
00203 {
00204 if ( pClient->m_bGUID && pClient->m_pGUID == *pGUID ) return pClient;
00205 }
00206
00207 return NULL;
00208 }
00209
00211
00212
00213 BOOL CEDClients::Merge(CEDClient* pClient)
00214 {
00215 ASSERT( pClient != NULL );
00216
00217 for ( CEDClient* pOther = m_pFirst ; pOther ; pOther = pOther->m_pEdNext )
00218 {
00219 if ( pOther != pClient && pOther->Equals( pClient ) )
00220 {
00221 pClient->Merge( pOther );
00222 pOther->Remove();
00223 return TRUE;
00224 }
00225 }
00226
00227 return FALSE;
00228 }
00229
00231
00232
00233 BOOL CEDClients::IsFull(CEDClient* pCheckThis)
00234 {
00235 int nCount = 0;
00236 DWORD tNow = GetTickCount();
00237
00238
00239 for ( CEDClient* pClient = m_pFirst ; pClient ; pClient = pClient->m_pEdNext )
00240 {
00241 if ( pClient->m_hSocket != INVALID_SOCKET ) nCount++;
00242 }
00243
00244
00245 if ( nCount >= Settings.eDonkey.MaxLinks ) m_tLastMaxClients = tNow;
00246
00247
00248 if ( ( tNow - m_tLastMaxClients ) > ( 2*1000 ) ) return FALSE;
00249
00250
00251 if ( ( pCheckThis != NULL ) && ( pCheckThis->m_hSocket != INVALID_SOCKET ) ) return FALSE;
00252
00253
00254
00255 return TRUE;
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277 }
00278
00279 BOOL CEDClients::IsOverloaded()
00280 {
00281 int nCount = 0;
00282
00283 for ( CEDClient* pClient = m_pFirst ; pClient ; pClient = pClient->m_pEdNext )
00284 {
00285 if ( pClient->m_hSocket != INVALID_SOCKET ) nCount++;
00286 }
00287
00288 return ( nCount >= ( Settings.eDonkey.MaxLinks + 25 ) );
00289 }
00290
00291
00293
00294
00295 void CEDClients::OnRun()
00296 {
00297
00298
00299
00300 DWORD tNow = GetTickCount();
00301 if ( tNow - m_tLastRun < Settings.eDonkey.PacketThrottle ) return;
00302 m_tLastRun = tNow;
00303
00304 if ( Settings.eDonkey.ServerWalk && Settings.eDonkey.EnableToday )
00305 {
00306 RunGlobalStatsRequests( tNow );
00307 }
00308
00309 for ( CEDClient* pClient = m_pFirst ; pClient ; )
00310 {
00311 CEDClient* pNext = pClient->m_pEdNext;
00312 pClient->OnRunEx( tNow );
00313 pClient = pNext;
00314 }
00315 }
00316
00318
00319
00320 BOOL CEDClients::OnAccept(CConnection* pConnection)
00321 {
00322 ASSERT( pConnection != NULL );
00323
00324 if ( Settings.Connection.RequireForTransfers && ! Settings.eDonkey.EnableToday )
00325 {
00326 theApp.Message( MSG_ERROR, IDS_ED2K_CLIENT_DISABLED,
00327 (LPCTSTR)pConnection->m_sAddress );
00328 return FALSE;
00329 }
00330
00331 CSingleLock pLock( &Transfers.m_pSection );
00332 if ( ! pLock.Lock( 250 ) ) return FALSE;
00333
00334 if ( IsFull() )
00335 {
00336
00337 if ( ( GetByIP( &pConnection->m_pHost.sin_addr ) == NULL ) || ( IsOverloaded() ) )
00338 {
00339 theApp.Message( MSG_DEBUG, _T("Rejecting ed2k connection from %s, max client connections reached."),
00340 (LPCTSTR)pConnection->m_sAddress );
00341 return FALSE;
00342 }
00343 else
00344 {
00345 theApp.Message( MSG_DEBUG, _T("Accepting ed2k connection from %s despite client connection limit."),
00346 (LPCTSTR)pConnection->m_sAddress );
00347
00348 }
00349 }
00350
00351 CEDClient* pClient = new CEDClient();
00352 pClient->AttachTo( pConnection );
00353
00354 return TRUE;
00355 }
00356
00358
00359
00360
00361 BOOL CEDClients::OnUDP(SOCKADDR_IN* pHost, CEDPacket* pPacket)
00362 {
00363 CSingleLock pLock( &Transfers.m_pSection );
00364
00365 switch ( pPacket->m_nType )
00366 {
00367 case ED2K_C2C_UDP_REASKFILEPING:
00368 if ( ! pLock.Lock( 100 ) ) return FALSE;
00369 if ( CEDClient* pClient = GetByIP( &pHost->sin_addr ) )
00370 {
00371 pClient->m_nUDP = ntohs( pHost->sin_port );
00372
00373 if ( ! pClient->OnUdpReask( pPacket ) )
00374 {
00375 Datagrams.Send( pHost, CEDPacket::New( ED2K_C2C_UDP_FILENOTFOUND, ED2K_PROTOCOL_EMULE ) );
00376 }
00377 }
00378 else
00379 {
00380 Datagrams.Send( pHost, CEDPacket::New( ED2K_C2C_UDP_FILENOTFOUND, ED2K_PROTOCOL_EMULE ) );
00381 }
00382 break;
00383 case ED2K_C2C_UDP_REASKACK:
00384 if ( ! pLock.Lock( 100 ) ) return FALSE;
00385 if ( CEDClient* pClient = GetByIP( &pHost->sin_addr ) )
00386 {
00387 pClient->m_nUDP = ntohs( pHost->sin_port );
00388 pClient->OnUdpReaskAck( pPacket );
00389 }
00390 break;
00391 case ED2K_C2C_UDP_QUEUEFULL:
00392 if ( ! pLock.Lock( 100 ) ) return FALSE;
00393 if ( CEDClient* pClient = GetByIP( &pHost->sin_addr ) )
00394 {
00395 pClient->m_nUDP = ntohs( pHost->sin_port );
00396 pClient->OnUdpQueueFull( pPacket );
00397 }
00398 break;
00399 case ED2K_C2C_UDP_FILENOTFOUND:
00400 if ( ! pLock.Lock( 100 ) ) return FALSE;
00401 if ( CEDClient* pClient = GetByIP( &pHost->sin_addr ) )
00402 {
00403 pClient->m_nUDP = ntohs( pHost->sin_port );
00404 pClient->OnUdpFileNotFound( pPacket );
00405 }
00406 break;
00407 case ED2K_S2CG_SERVERSTATUS:
00408 OnServerStatus( pHost, pPacket );
00409 break;
00410 case ED2K_S2CG_SEARCHRESULT:
00411 case ED2K_S2CG_FOUNDSOURCES:
00412
00413 pHost->sin_port = htons( ntohs( pHost->sin_port ) - 4 );
00414
00415
00416 CHostCacheHost *pServer;
00417 DWORD nServerFlags = Settings.eDonkey.DefaultServerFlags;
00418 pServer = HostCache.eDonkey.Find( &pHost->sin_addr );
00419 if ( pServer && pServer->m_nUDPFlags )
00420 {
00421 nServerFlags = pServer->m_nUDPFlags;
00422 }
00423
00424
00425 if ( CQueryHit* pHits = CQueryHit::FromPacket( pPacket, pHost, nServerFlags ) )
00426 {
00427 Downloads.OnQueryHits( pHits );
00428
00429 if ( pPacket->m_nType == ED2K_S2CG_SEARCHRESULT )
00430 Network.OnQueryHits( pHits );
00431 else
00432 pHits->Delete();
00433 }
00434 break;
00435 }
00436
00437 return TRUE;
00438 }
00439
00440
00441 void CEDClients::OnServerStatus(SOCKADDR_IN* pHost, CEDPacket* pPacket)
00442 {
00443 DWORD nLen, nKey;
00444 DWORD nUsers = 0, nFiles = 0, nMaxUsers = 0, nFileLimit = 1000, nUDPFlags = 0;
00445
00446
00447 nKey = pPacket->ReadLongLE();
00448 if ( nKey != m_nLastServerKey )
00449 {
00450 theApp.Message( MSG_ERROR, _T("Received unexpected server status" ) );
00451 return;
00452 }
00453
00454
00455 m_nLastServerKey = 0;
00456 CHostCacheHost *pServer = HostCache.eDonkey.Find( &m_pLastServer );
00457 if ( pServer == NULL )
00458 {
00459 theApp.Message( MSG_DEFAULT, _T("Server status received, but server not found in host cache") );
00460 return;
00461 }
00462 if ( pServer->m_sName.GetLength() )
00463 theApp.Message( MSG_DEFAULT, _T("Server status received from %s"), pServer->m_sName );
00464 else
00465 theApp.Message( MSG_DEFAULT, _T("Server status received from %s"),
00466 (LPCTSTR)CString( inet_ntoa( m_pLastServer ) ) );
00467
00468
00469 nLen = pPacket->GetRemaining();
00470
00471 if ( nLen >= 8 )
00472 {
00473
00474 nUsers = pPacket->ReadLongLE();
00475 nFiles = pPacket->ReadLongLE();
00476 }
00477 if ( nLen >= 12 )
00478 {
00479
00480 nMaxUsers = pPacket->ReadLongLE();
00481 }
00482 if ( nLen >= 20 )
00483 {
00484
00485 nFileLimit = pPacket->ReadLongLE();
00486 pPacket->ReadLongLE();
00487 }
00488 if ( nLen >= 24 )
00489 {
00490
00491 nUDPFlags = pPacket->ReadLongLE();
00492 }
00493 if ( nLen >= 28 )
00494 {
00495
00496 pPacket->ReadLongLE();
00497 }
00498
00499
00500 pServer->m_nFailures = 0;
00501 pServer->m_tFailure = 0;
00502 pServer->m_nUserCount = nUsers;
00503 pServer->m_nUserLimit = nMaxUsers;
00504 pServer->m_nFileLimit = nFileLimit;
00505 pServer->m_nUDPFlags = nUDPFlags;
00506
00507 if ( pServer->m_tSeen < pServer->m_tStats )
00508 pServer->m_tSeen = pServer->m_tStats;
00509 if ( nUDPFlags & ED2K_SERVER_UDP_UNICODE )
00510 pServer->m_nTCPFlags |= ED2K_SERVER_TCP_UNICODE;
00511 if ( nUDPFlags & ED2K_SERVER_UDP_GETSOURCES2 )
00512 pServer->m_nTCPFlags |= ED2K_SERVER_TCP_GETSOURCES2;
00513
00514
00515
00516
00517 }
00518
00519
00520 void CEDClients::RequestServerStatus(IN_ADDR* pHost, WORD nPort)
00521 {
00522 CEDPacket* pPacket = CEDPacket::New( ED2K_C2SG_SERVERSTATUSREQUEST, ED2K_PROTOCOL_EDONKEY );
00523
00524 srand( GetTickCount() );
00525 m_nLastServerKey = 0x55AA0000 + rand();
00526 pPacket->WriteLongLE( m_nLastServerKey );
00527 Datagrams.Send( pHost, nPort + 4, pPacket );
00528 }
00529
00531
00532
00533 void CEDClients::RunGlobalStatsRequests(DWORD tNow)
00534 {
00535 CHostCacheHost *pHost;
00536
00537
00538 if ( ! Datagrams.IsStable() ) return;
00539
00540 if ( m_nLastServerKey != 0 )
00541 {
00542
00543 if ( tNow > m_tLastServerStats + Settings.Connection.TimeoutHandshake )
00544 {
00545 CSingleLock pLock( &Network.m_pSection );
00546 if ( ! pLock.Lock( 250 ) ) return;
00547
00548
00549 m_nLastServerKey = 0;
00550 theApp.Message( MSG_DEBUG, _T("Time-out waiting for ed2k server status") );
00551
00552 pHost = HostCache.eDonkey.Find( &m_pLastServer );
00553 if ( pHost )
00554 {
00555 pHost->m_tFailure = pHost->m_tStats;
00556
00557 pHost->m_nFailures ++;
00558
00559 if ( pHost->m_nFailures > 3 )
00560 {
00561 theApp.Message( MSG_DEFAULT, _T("Removing ed2k server %s"), pHost->m_sName );
00562 HostCache.eDonkey.Remove( pHost );
00563 }
00564 }
00565
00566
00567 pLock.Unlock();
00568 }
00569 }
00570
00571 if ( tNow > m_tLastServerStats + Settings.eDonkey.StatsGlobalThrottle )
00572 {
00573
00574 CSingleLock pLock( &Network.m_pSection );
00575 if ( ! pLock.Lock( 250 ) ) return;
00576
00577
00578 DWORD tSecs = time( NULL );
00579
00580
00581 for ( pHost = HostCache.eDonkey.GetNewest() ; pHost ; pHost = pHost->m_pPrevTime )
00582 {
00583
00584
00585
00586
00587
00588 if ( ( pHost->CanQuery( tSecs ) ) &&
00589 ( ( tSecs > pHost->m_tStats + Settings.eDonkey.StatsServerThrottle ) ||
00590 ( ( pHost->m_nFailures > 0 ) && ( tSecs > pHost->m_tStats + 8*60*60 ) ) ) &&
00591 ( ( pHost->m_nUDPFlags == 0 ) ||
00592 ( m_bAllServersDone ) ) )
00593 {
00594
00595 if ( ! Neighbours.Get( &pHost->m_pAddress ) )
00596 {
00597
00598 if ( pHost->m_sName.GetLength() )
00599 theApp.Message( MSG_DEFAULT, _T("Sending status request to ed2k server %s"), pHost->m_sName );
00600 else
00601 theApp.Message( MSG_DEFAULT, _T("Sending status request to ed2k server %s"), (LPCTSTR)CString( inet_ntoa( pHost->m_pAddress ) ) );
00602
00603 RequestServerStatus( &pHost->m_pAddress, pHost->m_nPort );
00604 pHost->m_tStats = tSecs;
00605 m_tLastServerStats = tNow;
00606 m_pLastServer = pHost->m_pAddress;
00607 return;
00608 }
00609 }
00610 }
00611 pLock.Unlock();
00612
00613
00614 m_bAllServersDone = TRUE;
00615
00616 m_tLastServerStats = tNow;
00617 }
00618 }