Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

Network.cpp

Go to the documentation of this file.
00001 //
00002 // Network.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 "Network.h"
00026 #include "Security.h"
00027 #include "Handshakes.h"
00028 #include "Neighbours.h"
00029 #include "Neighbour.h"
00030 #include "Datagrams.h"
00031 #include "HostCache.h"
00032 #include "RouteCache.h"
00033 #include "QueryKeys.h"
00034 #include "GProfile.h"
00035 #include "Transfers.h"
00036 #include "Downloads.h"
00037 #include "Statistics.h"
00038 #include "DiscoveryServices.h"
00039 #include "HttpRequest.h"
00040 
00041 #include "CrawlSession.h"
00042 #include "SearchManager.h"
00043 #include "QueryHashMaster.h"
00044 #include "QuerySearch.h"
00045 #include "QueryHit.h"
00046 #include "Buffer.h"
00047 #include "G1Packet.h"
00048 #include "G2Packet.h"
00049 #include "G1Neighbour.h"
00050 
00051 #include "WndMain.h"
00052 #include "WndChild.h"
00053 #include "WndSearchMonitor.h"
00054 #include "WndHitMonitor.h"
00055 
00056 #ifdef _DEBUG
00057 #undef THIS_FILE
00058 static char THIS_FILE[]=__FILE__;
00059 #define new DEBUG_NEW
00060 #endif
00061 
00062 CNetwork Network;
00063 
00064 
00066 // CNetwork construction
00067 
00068 CNetwork::CNetwork()
00069 {
00070         NodeRoute                               = new CRouteCache();
00071         QueryRoute                              = new CRouteCache();
00072         QueryKeys                               = new CQueryKeys();
00073         
00074         m_bEnabled                              = FALSE;
00075         m_bAutoConnect                  = FALSE;
00076         m_nSequence                             = 0;
00077         m_hThread                               = NULL;
00078         m_tLastConnect                  = 0;
00079         m_tStartedConnecting    = 0;
00080 }
00081 
00082 CNetwork::~CNetwork()
00083 {
00084         delete QueryKeys;
00085         delete QueryRoute;
00086         delete NodeRoute;
00087 }
00088 
00090 // CNetwork attributes
00091 
00092 BOOL CNetwork::IsAvailable() const
00093 {
00094         DWORD dwState = 0;
00095         if ( InternetGetConnectedState( &dwState, 0 ) )
00096         {
00097                 if ( ! ( dwState & INTERNET_CONNECTION_OFFLINE ) ) return TRUE;
00098         }
00099 
00100         return FALSE;
00101 }
00102 
00103 BOOL CNetwork::IsConnected() const
00104 {
00105         return m_bEnabled;
00106 }
00107 
00108 BOOL CNetwork::IsListening() const
00109 {
00110         return m_bEnabled
00111                 && ( m_pHost.sin_addr.S_un.S_addr != 0 )
00112                 && ( m_pHost.sin_port != 0 )
00113                 && ( Handshakes.IsListening() );
00114 }
00115 
00116 int CNetwork::IsWellConnected() const
00117 {
00118         return Neighbours.m_nStableCount;
00119 }
00120 
00121 BOOL CNetwork::IsStable() const
00122 {
00123         return IsListening() && ( Handshakes.m_nStableCount > 0 );
00124 }
00125 
00126 DWORD CNetwork::GetStableTime() const
00127 {
00128         if ( ! IsStable() || ! Handshakes.m_tStableTime ) return 0;
00129         return (DWORD)time( NULL ) - Handshakes.m_tStableTime;
00130 }
00131 
00132 BOOL CNetwork::IsConnectedTo(IN_ADDR* pAddress)
00133 {
00134         if ( pAddress->S_un.S_addr == m_pHost.sin_addr.S_un.S_addr ) return TRUE;
00135         if ( Handshakes.IsConnectedTo( pAddress ) ) return TRUE;
00136         if ( Neighbours.Get( pAddress ) != NULL ) return TRUE;
00137         if ( Transfers.IsConnectedTo( pAddress ) ) return TRUE;
00138         
00139         return FALSE;
00140 }
00141 
00142 BOOL CNetwork::ReadyToTransfer(DWORD tNow) const
00143 {
00144         // If a connection isn't needed for transfers, we can start any time
00145         if ( ! Settings.Connection.RequireForTransfers )
00146                 return TRUE;
00147 
00148         // If we have not started connecting, we're not ready to transfer.
00149         if ( m_tStartedConnecting == 0 )
00150                 return FALSE;
00151 
00152         // We should wait a short time after starting the connection sequence before starting downloads
00153         if ( Settings.Connection.SlowConnect )
00154                 return ( ( tNow - m_tStartedConnecting ) > 8000 );              // 8 seconds for XPsp2 users
00155         else
00156                 return ( ( tNow - m_tStartedConnecting ) > 4000 );              // 4 seconds for others
00157 }
00158 
00160 // CNetwork connection
00161 
00162 BOOL CNetwork::Connect(BOOL bAutoConnect)
00163 {
00164         CSingleLock pLock( &m_pSection, TRUE );
00165         
00166         Settings.Live.AutoClose = FALSE;
00167         if ( bAutoConnect ) 
00168         {
00169                 m_bAutoConnect = TRUE;
00170                 // Remove really old G1 hosts before trying to connect to G1
00171                 if ( Settings.Gnutella1.EnableToday ) HostCache.Gnutella1.PruneOldHosts();
00172         }
00173         
00174         // If we are already connected, see if we need to query discovery services and exit.
00175         if ( m_bEnabled )
00176         {
00177                 if ( bAutoConnect ) DiscoveryServices.Execute();
00178                 return TRUE;
00179         }
00180         
00181         // Begin network startup
00182         theApp.Message( MSG_SYSTEM, IDS_NETWORK_STARTUP );
00183 
00184         // Make sure WinINet is connected (IE is not in offline mode)
00185         if ( Settings.Connection.ForceConnectedState )
00186         {
00187                 INTERNET_CONNECTED_INFO ici = { 0 };
00188                 HINTERNET hInternet = InternetOpen( Settings.SmartAgent(), INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0 );
00189 
00190                 ici.dwConnectedState = INTERNET_STATE_CONNECTED;
00191                 InternetSetOption( hInternet, INTERNET_OPTION_CONNECTED_STATE, &ici, sizeof(ici) );
00192                 InternetCloseHandle( hInternet );
00193         }
00194 
00195         Resolve( Settings.Connection.InHost, Settings.Connection.InPort, &m_pHost );
00196         
00197         if ( Settings.Connection.FirewallStatus == CONNECTION_FIREWALLED )
00198                 theApp.Message( MSG_DEFAULT, IDS_NETWORK_FIREWALLED );
00199         
00200         SOCKADDR_IN pOutgoing;
00201 
00202         if ( Resolve( Settings.Connection.OutHost, 0, &pOutgoing ) )
00203         {
00204                 theApp.Message( MSG_DEFAULT, IDS_NETWORK_OUTGOING,
00205                         (LPCTSTR)CString( inet_ntoa( pOutgoing.sin_addr ) ),
00206                         htons( pOutgoing.sin_port ) );
00207         }
00208         else if ( Settings.Connection.OutHost.GetLength() )
00209         {
00210                 theApp.Message( MSG_ERROR, IDS_NETWORK_CANT_OUTGOING,
00211                         (LPCTSTR)Settings.Connection.OutHost );
00212         }
00213         
00214         Handshakes.Listen();
00215         Datagrams.Listen();
00216         Neighbours.Connect();
00217         
00218         NodeRoute->SetDuration( Settings.Gnutella.RouteCache );
00219         QueryRoute->SetDuration( Settings.Gnutella.RouteCache );
00220         
00221         m_bEnabled                              = TRUE;
00222         m_tStartedConnecting    = GetTickCount();
00223         m_hThread                               = AfxBeginThread( ThreadStart, this, THREAD_PRIORITY_NORMAL )->m_hThread;
00224         
00225         // if ( m_bAutoConnect && bAutoConnect ) DiscoveryServices.Execute();
00226         
00227         return TRUE;
00228 }
00229 
00231 // CNetwork disconnect
00232 
00233 void CNetwork::Disconnect()
00234 {
00235         CSingleLock pLock( &m_pSection, TRUE );
00236         
00237         if ( ! m_bEnabled ) return;
00238         
00239         theApp.Message( MSG_DEFAULT, _T("") );
00240         theApp.Message( MSG_SYSTEM, IDS_NETWORK_DISCONNECTING );
00241         
00242         m_bEnabled                              = FALSE;
00243         m_bAutoConnect                  = FALSE;
00244         m_tStartedConnecting    = 0;
00245         
00246         Neighbours.Close();
00247         
00248         pLock.Unlock();
00249         
00250         if ( m_hThread != NULL )
00251         {
00252                 m_pWakeup.SetEvent();
00253                 
00254         int nAttempt = 10;
00255                 for ( ; nAttempt > 0 ; nAttempt-- )
00256                 {
00257                         DWORD nCode;
00258                         if ( ! GetExitCodeThread( m_hThread, &nCode ) ) break;
00259                         if ( nCode != STILL_ACTIVE ) break;
00260                         Sleep( 100 );
00261                 }
00262                 
00263                 if ( nAttempt == 0 )
00264                 {
00265                         TerminateThread( m_hThread, 0 );
00266                         theApp.Message( MSG_DEBUG, _T("WARNING: Terminating CNetwork thread.") );
00267                         Sleep( 100 );
00268                 }
00269                 
00270                 m_hThread = NULL;
00271         }
00272         
00273         Handshakes.Disconnect();
00274         pLock.Lock();
00275         
00276         Neighbours.Close();
00277         Datagrams.Disconnect();
00278         
00279         NodeRoute->Clear();
00280         QueryRoute->Clear();
00281         
00282         if ( TRUE )
00283         {
00284                 for ( POSITION pos = m_pLookups.GetStartPosition() ; pos ; )
00285                 {
00286                         LPBYTE pAsync, pBuffer;
00287                         m_pLookups.GetNextAssoc( pos, (VOID*&)pAsync, (VOID*&)pBuffer );
00288                         WSACancelAsyncRequest( (HANDLE)pAsync );
00289                         delete *(CString**)pBuffer;
00290                         free( pBuffer );
00291                 }
00292                 
00293                 m_pLookups.RemoveAll();
00294         }
00295         
00296         pLock.Unlock();
00297         
00298         DiscoveryServices.Stop();
00299         
00300         theApp.Message( MSG_SYSTEM, IDS_NETWORK_DISCONNECTED ); 
00301         theApp.Message( MSG_DEFAULT, _T("") );
00302 }
00303 
00305 // CNetwork host connection
00306 
00307 BOOL CNetwork::ConnectTo(LPCTSTR pszAddress, int nPort, PROTOCOLID nProtocol, BOOL bNoUltraPeer)
00308 {
00309         CSingleLock pLock( &m_pSection, TRUE );
00310         
00311         if ( ! m_bEnabled && ! Connect() ) return FALSE;
00312         
00313         if ( nPort == 0 ) nPort = GNUTELLA_DEFAULT_PORT;
00314         theApp.Message( MSG_DEFAULT, IDS_NETWORK_RESOLVING, pszAddress );
00315         
00316         if ( AsyncResolve( pszAddress, (WORD)nPort, nProtocol, bNoUltraPeer ? 2 : 1 ) ) return TRUE;
00317         
00318         theApp.Message( MSG_ERROR, IDS_NETWORK_RESOLVE_FAIL, pszAddress );
00319         
00320         return FALSE;
00321 }
00322 
00324 // CNetwork local IP aquisition and sending
00325 
00326 void CNetwork::AcquireLocalAddress(LPCTSTR pszHeader)
00327 {
00328         int nIP[4];
00329         
00330         if ( _stscanf( pszHeader, _T("%i.%i.%i.%i"), &nIP[0], &nIP[1], &nIP[2], &nIP[3] ) != 4 ) return;
00331         
00332         IN_ADDR pAddress;
00333         
00334         pAddress.S_un.S_un_b.s_b1 = (BYTE)nIP[0];
00335         pAddress.S_un.S_un_b.s_b2 = (BYTE)nIP[1];
00336         pAddress.S_un.S_un_b.s_b3 = (BYTE)nIP[2];
00337         pAddress.S_un.S_un_b.s_b4 = (BYTE)nIP[3];
00338         
00339         if ( IsFirewalledAddress( &pAddress ) ) return;
00340         
00341         m_pHost.sin_addr = pAddress;
00342 
00343         //Security.Ban( &pAddress, banSession, 0 );             // Ban self
00344 }
00345 
00347 // CNetwork GGUID generation
00348 
00349 void CNetwork::CreateID(GGUID& oID)
00350 {
00351         oID = MyProfile.GUID;
00352         oID.w[0] += GetTickCount();
00353         oID.w[1] += m_nSequence++;
00354         oID.w[2] += rand() * ( RAND_MAX + 1 ) * ( RAND_MAX + 1 ) + rand() * ( RAND_MAX + 1 ) + rand();
00355         oID.w[3] += rand() * ( RAND_MAX + 1 ) * ( RAND_MAX + 1 ) + rand() * ( RAND_MAX + 1 ) + rand();
00356 }
00357 
00359 // CNetwork firewalled address checking
00360 
00361 BOOL CNetwork::IsFirewalledAddress(LPVOID pAddress, BOOL bIncludeSelf)
00362 {
00363         if ( ! pAddress ) return TRUE;
00364         if ( ! Settings.Connection.IgnoreLocalIP ) return FALSE;
00365         
00366         DWORD nAddress = *(DWORD*)pAddress;
00367         
00368         if ( ! nAddress ) return TRUE;
00369         if ( ( nAddress & 0xFFFF ) == 0xA8C0 ) return TRUE;
00370         if ( ( nAddress & 0xF0AC ) == 0x08AC ) return TRUE;
00371         if ( ( nAddress & 0xFF ) == 0x0A ) return TRUE;
00372         if ( ( nAddress & 0xFF ) == 0x7F ) return TRUE;         // 127.*
00373         
00374         if ( bIncludeSelf && nAddress == *(DWORD*)(&m_pHost.sin_addr) ) return TRUE;
00375         
00376         return FALSE;
00377 }
00378 
00380 // CNetwork name resolution
00381 
00382 BOOL CNetwork::Resolve(LPCTSTR pszHost, int nPort, SOCKADDR_IN* pHost, BOOL bNames) const
00383 {
00384         ZeroMemory( pHost, sizeof(*pHost) );
00385         pHost->sin_family       = PF_INET;
00386         pHost->sin_port         = htons( nPort );
00387         
00388         if ( pszHost == NULL || *pszHost == 0 ) return FALSE;
00389         
00390         CString strHost( pszHost );
00391         
00392         int nColon = strHost.Find( ':' );
00393         
00394         if ( nColon >= 0 )
00395         {
00396                 if ( _stscanf( strHost.Mid( nColon + 1 ), _T("%i"), &nPort ) == 1 )
00397                 {
00398                         pHost->sin_port = htons( nPort );
00399                 }
00400                 
00401                 strHost = strHost.Left( nColon );
00402         }
00403         
00404         USES_CONVERSION;
00405         LPCSTR pszaHost = T2CA( (LPCTSTR)strHost );
00406         
00407         DWORD dwIP = inet_addr( pszaHost );
00408         
00409         if ( dwIP == INADDR_NONE )
00410         {
00411                 if ( ! bNames ) return TRUE;
00412                 
00413                 HOSTENT* pLookup = gethostbyname( pszaHost );
00414                 
00415                 if ( pLookup == NULL ) return FALSE;
00416                 
00417                 CopyMemory( &pHost->sin_addr, pLookup->h_addr, 4 );
00418         }
00419         else
00420         {
00421                 CopyMemory( &pHost->sin_addr, &dwIP, 4 );
00422         }
00423         
00424         return TRUE;
00425 }
00426 
00427 BOOL CNetwork::AsyncResolve(LPCTSTR pszAddress, WORD nPort, PROTOCOLID nProtocol, BYTE nCommand)
00428 {
00429         CSingleLock pLock( &m_pSection );
00430         if ( ! pLock.Lock( 250 ) ) return FALSE;
00431         
00432         BYTE* pResolve = (BYTE*)malloc( MAXGETHOSTSTRUCT + 8 );
00433         
00434         USES_CONVERSION;
00435         
00436         HANDLE hAsync = WSAAsyncGetHostByName( AfxGetMainWnd()->GetSafeHwnd(), WM_WINSOCK,
00437                 T2CA(pszAddress), (LPSTR)pResolve + 8, MAXGETHOSTSTRUCT );
00438         
00439         if ( hAsync != NULL )
00440         {
00441                 *((CString**)&pResolve[0])      = new CString( pszAddress );
00442                 *((WORD*)&pResolve[4])          = nPort;
00443                 *((BYTE*)&pResolve[6])          = nProtocol;
00444                 *((BYTE*)&pResolve[7])          = nCommand;
00445                 
00446                 m_pLookups.SetAt( (LPVOID)hAsync, (LPVOID)pResolve );
00447                 return TRUE;
00448         }
00449         else
00450         {
00451                 free( pResolve );
00452                 return FALSE;
00453         }
00454 }
00455 
00456 WORD CNetwork::RandomPort() const
00457 {
00458         return 10000 + ( rand() % 50000 );
00459 }
00460 
00462 // CNetwork thread run
00463 
00464 UINT CNetwork::ThreadStart(LPVOID pParam)
00465 {
00466         CNetwork* pNetwork = (CNetwork*)pParam;
00467         pNetwork->OnRun();
00468         return 0;
00469 }
00470 
00471 void CNetwork::OnRun()
00472 {
00473         while ( m_bEnabled )
00474         {
00475                 Sleep( 50 );
00476                 WaitForSingleObject( m_pWakeup, 100 );
00477                 
00478                 if ( m_bEnabled && m_pSection.Lock() )
00479                 {
00480                         Datagrams.OnRun();
00481                         SearchManager.OnRun();
00482                         QueryHashMaster.Build();
00483                         
00484                         if ( CrawlSession.m_bActive ) CrawlSession.OnRun();
00485                         
00486                         m_pSection.Unlock();
00487                 }
00488                 
00489                 Neighbours.OnRun();
00490         }
00491 }
00492 
00494 // CNetwork resolve callback
00495 
00496 void CNetwork::OnWinsock(WPARAM wParam, LPARAM lParam)
00497 {
00498         CSingleLock pLock( &m_pSection, TRUE );
00499 
00500         LPBYTE pBuffer = NULL;
00501         if ( ! m_pLookups.Lookup( (LPVOID)wParam, (LPVOID&)pBuffer ) ) return;
00502         m_pLookups.RemoveKey( (LPVOID)wParam );
00503 
00504         CString* psHost = *(CString**)pBuffer;
00505         WORD nPort              = *(WORD*)(pBuffer + 4);
00506         BYTE nProtocol  = *(BYTE*)(pBuffer + 6);
00507         BYTE nCommand   = *(BYTE*)(pBuffer + 7);
00508         HOSTENT* pHost  = (HOSTENT*)(pBuffer + 8);
00509 
00510         if ( WSAGETASYNCERROR(lParam) == 0 )
00511         {
00512                 if ( nCommand == 0 )
00513                 {
00514                         HostCache.ForProtocol( nProtocol )->Add( (IN_ADDR*)pHost->h_addr, nPort );
00515                 }
00516                 else
00517                 {
00518                         Neighbours.ConnectTo( (IN_ADDR*)pHost->h_addr, nPort, nProtocol, FALSE, nCommand == 2 );
00519                 }
00520         }
00521         else if ( nCommand > 0 )
00522         {
00523                 theApp.Message( MSG_ERROR, IDS_NETWORK_RESOLVE_FAIL, (LPCTSTR)*psHost );
00524         }
00525         
00526         delete psHost;
00527         free( pBuffer );
00528 }
00529 
00531 // CNetwork get node route
00532 
00533 BOOL CNetwork::GetNodeRoute(GGUID* pGUID, CNeighbour** ppNeighbour, SOCKADDR_IN* pEndpoint)
00534 {
00535         if ( *pGUID == MyProfile.GUID ) return FALSE;
00536         
00537         if ( Network.NodeRoute->Lookup( pGUID, ppNeighbour, pEndpoint ) ) return TRUE;
00538         if ( ppNeighbour == NULL ) return FALSE;
00539         
00540         for ( POSITION pos = Neighbours.GetIterator() ; pos ; )
00541         {
00542                 CNeighbour* pNeighbour = Neighbours.GetNext( pos );
00543                 
00544                 if ( pNeighbour->m_bGUID && pNeighbour->m_pGUID == *pGUID )
00545                 {
00546                         *ppNeighbour = pNeighbour;
00547                         return TRUE;
00548                 }
00549         }
00550         
00551         return FALSE;
00552 }
00553 
00555 // CNetwork route generic packets
00556 
00557 BOOL CNetwork::RoutePacket(CG2Packet* pPacket)
00558 {
00559         GGUID pGUID;
00560         
00561         if ( ! pPacket->GetTo( &pGUID ) || pGUID == MyProfile.GUID ) return FALSE;
00562         
00563         CNeighbour* pOrigin = NULL;
00564         SOCKADDR_IN pEndpoint;
00565         
00566         if ( GetNodeRoute( &pGUID, &pOrigin, &pEndpoint ) )
00567         {
00568                 if ( pOrigin != NULL )
00569                 {
00570                         if ( pOrigin->m_nProtocol == PROTOCOL_G1 &&
00571                                  pPacket->IsType( G2_PACKET_PUSH ) )
00572                         {
00573                                 CG1Neighbour* pG1 = (CG1Neighbour*)pOrigin;
00574                                 pPacket->SkipCompound();
00575                                 pG1->SendG2Push( &pGUID, pPacket );
00576                         }
00577                         else
00578                         {
00579                                 pOrigin->Send( pPacket, FALSE, TRUE );
00580                         }
00581                 }
00582                 else
00583                 {
00584                         Datagrams.Send( &pEndpoint, pPacket, FALSE );
00585                 }
00586                 
00587                 Statistics.Current.Gnutella2.Routed++;
00588         }
00589         
00590         return TRUE;
00591 }
00592 
00594 // CNetwork send a push request
00595 
00596 BOOL CNetwork::SendPush(GGUID* pGUID, DWORD nIndex)
00597 {
00598         CSingleLock pLock( &Network.m_pSection );
00599         if ( ! pLock.Lock( 250 ) ) return TRUE;
00600 
00601         if ( ! IsListening() ) return FALSE;
00602         
00603         GGUID pGUID2 = *pGUID;
00604         SOCKADDR_IN pEndpoint;
00605         CNeighbour* pOrigin;
00606         int nCount = 0;
00607         
00608         while ( GetNodeRoute( &pGUID2, &pOrigin, &pEndpoint ) )
00609         {
00610                 if ( pOrigin != NULL && pOrigin->m_nProtocol == PROTOCOL_G1 )
00611                 {
00612                         CG1Packet* pPacket = CG1Packet::New( G1_PACKET_PUSH,
00613                                 Settings.Gnutella1.MaximumTTL - 1 );
00614                         
00615                         pPacket->Write( pGUID, 16 );
00616                         pPacket->WriteLongLE( nIndex );
00617                         pPacket->WriteLongLE( m_pHost.sin_addr.S_un.S_addr );
00618                         pPacket->WriteShortLE( htons( m_pHost.sin_port ) );
00619                         
00620                         pOrigin->Send( pPacket );
00621                 }
00622                 else
00623                 {
00624                         CG2Packet* pPacket = CG2Packet::New( G2_PACKET_PUSH, TRUE );
00625                         
00626                         pPacket->WritePacket( G2_PACKET_TO, 16 );
00627                         pPacket->Write( pGUID, 16 );
00628                         
00629                         pPacket->WriteByte( 0 );
00630                         pPacket->WriteLongLE( m_pHost.sin_addr.S_un.S_addr );
00631                         pPacket->WriteShortBE( htons( m_pHost.sin_port ) );
00632                         
00633                         if ( pOrigin != NULL )
00634                         {
00635                                 pOrigin->Send( pPacket );
00636                         }
00637                         else
00638                         {
00639                                 Datagrams.Send( &pEndpoint, pPacket );
00640                         }
00641                 }
00642                 
00643                 pGUID2.n[15] ++;
00644                 nCount++;
00645         }
00646         
00647         return nCount > 0;
00648 }
00649 
00651 // CNetwork hit routing
00652 
00653 BOOL CNetwork::RouteHits(CQueryHit* pHits, CPacket* pPacket)
00654 {
00655         SOCKADDR_IN pEndpoint;
00656         CNeighbour* pOrigin;
00657         
00658         if ( ! QueryRoute->Lookup( &pHits->m_pSearchID, &pOrigin, &pEndpoint ) ) return FALSE;
00659         
00660         BOOL bWrapped = FALSE;
00661         
00662         if ( pPacket->m_nProtocol == PROTOCOL_G1 )
00663         {
00664                 CG1Packet* pG1 = (CG1Packet*)pPacket;
00665                 if ( ! pG1->Hop() ) return FALSE;
00666         }
00667         else if ( pPacket->m_nProtocol == PROTOCOL_G2 )
00668         {
00669                 CG2Packet* pG2 = (CG2Packet*)pPacket;
00670 
00671                 if ( pG2->IsType( G2_PACKET_HIT ) && pG2->m_nLength > 17 )
00672                 {
00673                         BYTE* pHops = pG2->m_pBuffer + pG2->m_nLength - 17;
00674                         if ( *pHops > Settings.Gnutella1.MaximumTTL ) return FALSE;
00675                         (*pHops) ++;
00676                 }
00677                 else if ( pG2->IsType( G2_PACKET_HIT_WRAP ) )
00678                 {
00679                         if ( ! pG2->SeekToWrapped() ) return FALSE;
00680                         GNUTELLAPACKET* pG1 = (GNUTELLAPACKET*)( pPacket->m_pBuffer + pPacket->m_nPosition );
00681                         if ( pG1->m_nTTL == 0 ) return FALSE;
00682                         pG1->m_nTTL --;
00683                         pG1->m_nHops ++;
00684                         bWrapped = TRUE;
00685                 }
00686         }
00687         
00688         if ( pOrigin != NULL )
00689         {
00690                 if ( pOrigin->m_nProtocol == pPacket->m_nProtocol )
00691                 {
00692                         pOrigin->Send( pPacket, FALSE, FALSE ); // Dont buffer
00693                 }
00694                 else if ( pOrigin->m_nProtocol == PROTOCOL_G1 && pPacket->m_nProtocol == PROTOCOL_G2 )
00695                 {
00696                         if ( ! bWrapped ) return FALSE;
00697                         pPacket = CG1Packet::New( (GNUTELLAPACKET*)( pPacket->m_pBuffer + pPacket->m_nPosition ) );
00698                         pOrigin->Send( pPacket, TRUE, TRUE );
00699                 }
00700                 else if ( pOrigin->m_nProtocol == PROTOCOL_G2 && pPacket->m_nProtocol == PROTOCOL_G1 )
00701                 {
00702                         pPacket = CG2Packet::New( G2_PACKET_HIT_WRAP, (CG1Packet*)pPacket );
00703                         pOrigin->Send( pPacket, TRUE, FALSE );  // Dont buffer
00704                 }
00705                 else
00706                 {
00707                         // Should not happen either (logic flaw)
00708                         return FALSE;
00709                 }
00710         }
00711         else if ( pPacket->m_nProtocol == PROTOCOL_G2 )
00712         {
00713                 if ( pEndpoint.sin_addr.S_un.S_addr == Network.m_pHost.sin_addr.S_un.S_addr ) return FALSE;
00714                 Datagrams.Send( &pEndpoint, (CG2Packet*)pPacket, FALSE );
00715         }
00716         else
00717         {
00718                 if ( pEndpoint.sin_addr.S_un.S_addr == Network.m_pHost.sin_addr.S_un.S_addr ) return FALSE;
00719                 pPacket = CG2Packet::New( G2_PACKET_HIT_WRAP, (CG1Packet*)pPacket );
00720                 Datagrams.Send( &pEndpoint, (CG2Packet*)pPacket, TRUE );
00721         }
00722         
00723         if ( pPacket->m_nProtocol == PROTOCOL_G1 )
00724                 Statistics.Current.Gnutella1.Routed++;
00725         else if ( pPacket->m_nProtocol == PROTOCOL_G2 )
00726                 Statistics.Current.Gnutella2.Routed++;
00727         
00728         return TRUE;
00729 }
00730 
00732 // CNetwork common handler functions
00733 
00734 void CNetwork::OnQuerySearch(CQuerySearch* pSearch)
00735 {
00736         CSingleLock pLock( &theApp.m_pSection );
00737         
00738         if ( pLock.Lock( 10 ) )
00739         {
00740                 if ( CMainWnd* pMainWnd = theApp.SafeMainWnd() )
00741                 {
00742                         CWindowManager* pWindows        = &pMainWnd->m_pWindows;
00743                         CChildWnd* pChildWnd            = NULL;
00744                         CRuntimeClass* pClass           = RUNTIME_CLASS(CSearchMonitorWnd);
00745 
00746                         while ( pChildWnd = pWindows->Find( pClass, pChildWnd ) )
00747                         {
00748                                 pChildWnd->OnQuerySearch( pSearch );
00749                         }
00750                 }
00751 
00752                 pLock.Unlock();
00753         }
00754 }
00755 
00756 void CNetwork::OnQueryHits(CQueryHit* pHits)
00757 {
00758         Downloads.OnQueryHits( pHits );
00759 
00760         CSingleLock pLock( &theApp.m_pSection );
00761 
00762         if ( pLock.Lock( 250 ) )
00763         {
00764                 if ( CMainWnd* pMainWnd = theApp.SafeMainWnd() )
00765                 {
00766                         CWindowManager* pWindows        = &pMainWnd->m_pWindows;
00767                         CChildWnd* pChildWnd            = NULL;
00768                         CChildWnd* pMonitorWnd          = NULL;
00769                         CRuntimeClass* pMonitorType     = RUNTIME_CLASS(CHitMonitorWnd);
00770 
00771                         while ( pChildWnd = pWindows->Find( NULL, pChildWnd ) )
00772                         {
00773                                 if ( pChildWnd->GetRuntimeClass() == pMonitorType )
00774                                 {
00775                                         pMonitorWnd = pChildWnd;
00776                                 }
00777                                 else
00778                                 {
00779                                         if ( pChildWnd->OnQueryHits( pHits ) ) return;
00780                                 }
00781                         }
00782 
00783                         if ( pMonitorWnd != NULL )
00784                         {
00785                                 if ( pMonitorWnd->OnQueryHits( pHits ) ) return;
00786                         }
00787                 }
00788 
00789                 pLock.Unlock();
00790         }
00791 
00792         pHits->Delete();
00793 }

Generated on Thu Dec 15 10:39:45 2005 for Shareaza 2.2.1.0 by  doxygen 1.4.2