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

G2Neighbour.cpp

Go to the documentation of this file.
00001 //
00002 // G2Neighbour.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 "Statistics.h"
00028 #include "Neighbours.h"
00029 #include "G2Neighbour.h"
00030 #include "G2Packet.h"
00031 #include "G1Packet.h"
00032 #include "Buffer.h"
00033 #include "Handshakes.h"
00034 #include "Datagrams.h"
00035 #include "HostCache.h"
00036 #include "RouteCache.h"
00037 #include "VendorCache.h"
00038 #include "QuerySearch.h"
00039 #include "QueryHit.h"
00040 #include "Library.h"
00041 #include "LocalSearch.h"
00042 #include "SearchManager.h"
00043 #include "QueryHashTable.h"
00044 #include "HubHorizon.h"
00045 #include "GProfile.h"
00046 #include "Uploads.h"
00047 #include "XML.h"
00048 
00049 #ifdef _DEBUG
00050 #undef THIS_FILE
00051 static char THIS_FILE[]=__FILE__;
00052 #define new DEBUG_NEW
00053 #endif
00054 
00055 
00057 // CG2Neighbour construction
00058 
00059 CG2Neighbour::CG2Neighbour(CNeighbour* pBase) : CNeighbour( PROTOCOL_G2, pBase )
00060 {
00061         theApp.Message( MSG_DEFAULT, IDS_HANDSHAKE_ONLINE_G2, (LPCTSTR)m_sAddress,
00062                 m_sUserAgent.IsEmpty() ? _T("Unknown") : (LPCTSTR)m_sUserAgent );
00063 
00064         m_nLeafCount    = 0;
00065         m_nLeafLimit    = 0;
00066         m_bCachedKeys   = FALSE;
00067 
00068         m_pGUIDCache    = new CRouteCache();
00069         m_pHubGroup             = new CHubHorizonGroup();
00070 
00071         m_tAdjust               = 0;
00072         m_tLastPingIn   = 0;
00073         m_tLastPingOut  = 0;
00074         m_tLastPacket   = GetTickCount();
00075         m_tWaitLNI              = m_tLastPacket;
00076         m_tLastKHL              = m_tLastPacket - Settings.Gnutella2.KHLPeriod + 1000;
00077         m_tLastHAW              = m_tLastPacket;
00078 
00079         m_nQueryLimiter = 40;
00080         m_tQueryTimer   = 0;
00081         m_bBlacklisted  = FALSE;
00082 
00083         SendStartups();
00084 }
00085 
00086 CG2Neighbour::~CG2Neighbour()
00087 {
00088         delete m_pHubGroup;
00089         delete m_pGUIDCache;
00090 
00091         for ( POSITION pos = m_pOutbound.GetHeadPosition() ; pos ; )
00092         {
00093                 CG2Packet* pOutbound = (CG2Packet*)m_pOutbound.GetNext( pos );
00094                 pOutbound->Release();
00095         }
00096 }
00097 
00099 // CG2Neighbour read and write events
00100 
00101 BOOL CG2Neighbour::OnRead()
00102 {
00103         CNeighbour::OnRead();
00104         return ProcessPackets();
00105 }
00106 
00107 BOOL CG2Neighbour::OnWrite()
00108 {
00109         CBuffer* pOutput = m_pZOutput ? m_pZOutput : m_pOutput;
00110 
00111         while ( pOutput->m_nLength == 0 && m_nOutbound > 0 )
00112         {
00113                 CG2Packet* pPacket = (CG2Packet*)m_pOutbound.RemoveHead();
00114                 m_nOutbound--;
00115 
00116                 pPacket->ToBuffer( pOutput );
00117                 pPacket->Release();
00118 
00119                 CNeighbour::OnWrite();
00120         }
00121 
00122         CNeighbour::OnWrite();
00123 
00124         return TRUE;
00125 }
00126 
00128 // CG2Neighbour run event
00129 
00130 BOOL CG2Neighbour::OnRun()
00131 {
00132         if ( ! CNeighbour::OnRun() ) return FALSE;
00133 
00134         DWORD tNow = GetTickCount();
00135 
00136         if ( m_tWaitLNI > 0 && tNow - m_tWaitLNI > Settings.Gnutella2.KHLPeriod * 3 )
00137         {
00138                 Close( IDS_CONNECTION_TIMEOUT_TRAFFIC );
00139                 return FALSE;
00140         }
00141         else if ( tNow - m_tLastPingOut >= Settings.Gnutella1.PingRate )
00142         {
00143                 BOOL bNeedStable = Network.IsListening() && ! Datagrams.IsStable();
00144                 CG2Packet* pPing = CG2Packet::New( G2_PACKET_PING, TRUE );
00145 
00146                 if ( bNeedStable )
00147                 {
00148                         pPing->WritePacket( "UDP", 6 );
00149                         pPing->WriteLongLE( Network.m_pHost.sin_addr.S_un.S_addr );
00150                         pPing->WriteShortBE( htons( Network.m_pHost.sin_port ) );
00151                 }
00152 
00153                 Send( pPing );
00154                 Datagrams.Send( &m_pHost, CG2Packet::New( G2_PACKET_PING ) );
00155                 m_tLastPingOut = tNow;
00156         }
00157 
00158         if ( tNow - m_tLastKHL > Settings.Gnutella2.KHLPeriod )
00159         {
00160                 SendLNI();
00161                 SendKHL();
00162         }
00163         else if ( tNow - m_tLastHAW > Settings.Gnutella2.HAWPeriod )
00164         {
00165                 SendHAW();
00166         }
00167 
00168         // Update allowed queries based on the node type
00169         if ( m_nNodeType == ntLeaf )
00170         {
00171                 if ( ( tNow - m_tQueryTimer ) > ( 5*60*1000 ) )
00172                 {
00173                         if ( m_nQueryLimiter < 60 ) m_nQueryLimiter ++;
00174                         m_tQueryTimer = tNow;
00175                 }
00176         }
00177         else
00178         {
00179                 if ( ( tNow - m_tQueryTimer ) > ( 1000 ) )
00180                 {
00181                         if ( m_nQueryLimiter < 240 ) m_nQueryLimiter += 10;
00182                         m_tQueryTimer = tNow;
00183                 }
00184         }
00185 
00186         return TRUE;
00187 }
00188 
00190 // CG2Neighbour send packet
00191 
00192 BOOL CG2Neighbour::Send(CPacket* pPacket, BOOL bRelease, BOOL bBuffered)
00193 {
00194         BOOL bSuccess = FALSE;
00195 
00196         if ( m_nState >= nrsConnected && pPacket->m_nProtocol == PROTOCOL_G2 )
00197         {
00198                 m_nOutputCount++;
00199                 Statistics.Current.Gnutella2.Outgoing++;
00200 
00201                 if ( bBuffered )
00202                 {
00203                         if ( m_nOutbound >= Settings.Gnutella1.PacketBufferSize )
00204                         {
00205                                 CG2Packet* pRemove = (CG2Packet*)m_pOutbound.RemoveTail();
00206                                 pRemove->Release();
00207                                 m_nOutbound--;
00208                                 Statistics.Current.Gnutella2.Lost++;
00209                         }
00210 
00211                         pPacket->AddRef();
00212                         m_pOutbound.AddHead( pPacket );
00213                         m_nOutbound++;
00214                 }
00215                 else
00216                 {
00217                         pPacket->ToBuffer( m_pZOutput ? m_pZOutput : m_pOutput );
00218                 }
00219 
00220                 QueueRun();
00221 
00222                 pPacket->SmartDump( this, NULL, TRUE );
00223 
00224                 bSuccess = TRUE;
00225         }
00226 
00227         if ( bRelease ) pPacket->Release();
00228 
00229         return bSuccess;
00230 }
00231 
00233 // CG2Neighbour startup events
00234 
00235 void CG2Neighbour::SendStartups()
00236 {
00237         CG2Packet* pPing = CG2Packet::New( G2_PACKET_PING, TRUE );
00238 
00239         if ( Network.IsListening() )
00240         {
00241                 pPing->WritePacket( "UDP", 6 );
00242                 pPing->WriteLongLE( Network.m_pHost.sin_addr.S_un.S_addr );
00243                 pPing->WriteShortBE( htons( Network.m_pHost.sin_port ) );
00244         }
00245 
00246         Send( pPing, TRUE, TRUE );
00247         m_tLastPingOut = GetTickCount();
00248 
00249         Datagrams.Send( &m_pHost, CG2Packet::New( G2_PACKET_PING ) );
00250 
00251         Send( CG2Packet::New( G2_PACKET_PROFILE_CHALLENGE ), TRUE, TRUE );
00252 }
00253 
00255 // CG2Neighbour packet dispatch
00256 
00257 BOOL CG2Neighbour::ProcessPackets()
00258 {
00259         CBuffer* pInput = m_pZInput ? m_pZInput : m_pInput;
00260 
00261     BOOL bSuccess = TRUE;
00262         for ( ; bSuccess && pInput->m_nLength ; )
00263         {
00264                 BYTE nInput = *(pInput->m_pBuffer);
00265 
00266                 if ( nInput == 0 )
00267                 {
00268                         pInput->Remove( 1 );
00269                         continue;
00270                 }
00271 
00272                 BYTE nLenLen    = ( nInput & 0xC0 ) >> 6;
00273                 BYTE nTypeLen   = ( nInput & 0x38 ) >> 3;
00274                 BYTE nFlags             = ( nInput & 0x07 );
00275 
00276                 if ( (DWORD)pInput->m_nLength < (DWORD)nLenLen + nTypeLen + 2 ) break;
00277 
00278                 DWORD nLength = 0;
00279 
00280                 if ( nFlags & G2_FLAG_BIG_ENDIAN )
00281                 {
00282                         BYTE* pLenIn = pInput->m_pBuffer + 1;
00283 
00284                         for ( BYTE nIt = nLenLen ; nIt ; nIt-- )
00285                         {
00286                                 nLength <<= 8;
00287                                 nLength |= *pLenIn++;
00288                         }
00289                 }
00290                 else
00291                 {
00292                         BYTE* pLenIn    = pInput->m_pBuffer + 1;
00293                         BYTE* pLenOut   = (BYTE*)&nLength;
00294                         for ( BYTE nLenCnt = nLenLen ; nLenCnt-- ; ) *pLenOut++ = *pLenIn++;
00295                 }
00296 
00297                 if ( nLength >= Settings.Gnutella1.MaximumPacket )
00298                 {
00299                         Close( IDS_PROTOCOL_TOO_LARGE );
00300                         return FALSE;
00301                 }
00302 
00303                 if ( (DWORD)pInput->m_nLength < (DWORD)nLength + nLenLen + nTypeLen + 2 ) break;
00304 
00305                 CG2Packet* pPacket = CG2Packet::New( pInput->m_pBuffer );
00306 
00307                 try
00308                 {
00309                         bSuccess = OnPacket( pPacket );
00310                 }
00311                 catch ( CException* pException )
00312                 {
00313                         pException->Delete();
00314                         // bSuccess = FALSE;            // SHOULD THIS BE LIKE THIS?
00315                         bSuccess = TRUE;
00316                 }
00317 
00318                 pPacket->Release();
00319 
00320                 pInput->Remove( nLength + nLenLen + nTypeLen + 2 );
00321         }
00322 
00323         if ( bSuccess ) return TRUE;
00324 
00325         Close( 0 );
00326         return FALSE;
00327 }
00328 
00330 // CG2Neighbour packet handler
00331 
00332 BOOL CG2Neighbour::OnPacket(CG2Packet* pPacket)
00333 {
00334         m_nInputCount++;
00335         m_tLastPacket = GetTickCount();
00336         Statistics.Current.Gnutella2.Incoming++;
00337 
00338         pPacket->SmartDump( this, NULL, FALSE );
00339 
00340         if ( Network.RoutePacket( pPacket ) ) return TRUE;
00341 
00342         if ( pPacket->IsType( G2_PACKET_PING ) )
00343         {
00344                 return OnPing( pPacket );
00345         }
00346         else if ( pPacket->IsType( G2_PACKET_LNI ) )
00347         {
00348                 return OnLNI( pPacket );
00349         }
00350         else if ( pPacket->IsType( G2_PACKET_KHL ) )
00351         {
00352                 return OnKHL( pPacket );
00353         }
00354         else if ( pPacket->IsType( G2_PACKET_HAW ) )
00355         {
00356                 return OnHAW( pPacket );
00357         }
00358         else if ( pPacket->IsType( G2_PACKET_QUERY ) )
00359         {
00360                 return OnQuery( pPacket );
00361         }
00362         else if ( pPacket->IsType( G2_PACKET_QUERY_WRAP ) )
00363         {
00364                 //return OnQuery( pPacket );
00365                 theApp.Message( MSG_DEBUG, _T("CG2Neighbour::OnPacket Ignoring wrapped query packet") );
00366         }
00367         else if ( pPacket->IsType( G2_PACKET_HIT_WRAP ) )
00368         {
00369                 return OnCommonHit( pPacket );
00370         }
00371         else if ( pPacket->IsType( G2_PACKET_HIT ) )
00372         {
00373                 return OnCommonHit( pPacket );
00374         }
00375         else if ( pPacket->IsType( G2_PACKET_QUERY_ACK ) )
00376         {
00377                 return OnQueryAck( pPacket );
00378         }
00379         else if ( pPacket->IsType( G2_PACKET_QUERY_KEY_REQ ) )
00380         {
00381                 return OnQueryKeyReq( pPacket );
00382         }
00383         else if ( pPacket->IsType( G2_PACKET_QUERY_KEY_ANS ) )
00384         {
00385                 return OnQueryKeyAns( pPacket );
00386         }
00387         else if ( pPacket->IsType( G2_PACKET_QHT ) )
00388         {
00389                 return OnCommonQueryHash( pPacket );
00390         }
00391         else if ( pPacket->IsType( G2_PACKET_PUSH ) )
00392         {
00393                 return OnPush( pPacket );
00394         }
00395         else if ( pPacket->IsType( G2_PACKET_PROFILE_CHALLENGE ) )
00396         {
00397                 return OnProfileChallenge( pPacket );
00398         }
00399         else if ( pPacket->IsType( G2_PACKET_PROFILE_DELIVERY ) )
00400         {
00401                 return OnProfileDelivery( pPacket );
00402         }
00403 
00404         return TRUE;
00405 }
00406 
00408 // CG2Neighbour PING packet handler
00409 
00410 BOOL CG2Neighbour::OnPing(CG2Packet* pPacket)
00411 {
00412         Send( CG2Packet::New( G2_PACKET_PONG ) );
00413 
00414         if ( ! pPacket->m_bCompound ) return TRUE;
00415 
00416         BOOL bRelay = FALSE;
00417         DWORD nAddress = 0;
00418         WORD nPort = 0;
00419         CHAR szType[9];
00420         DWORD nLength;
00421 
00422         while ( pPacket->ReadPacket( szType, nLength ) )
00423         {
00424                 DWORD nNext = pPacket->m_nPosition + nLength;
00425 
00426                 if ( strcmp( szType, "UDP" ) == 0 && nLength >= 6 )
00427                 {
00428                         nAddress        = pPacket->ReadLongLE();
00429                         nPort           = pPacket->ReadShortBE();
00430                 }
00431                 else if ( strcmp( szType, "RELAY" ) == 0 )
00432                 {
00433                         bRelay = TRUE;
00434                 }
00435 
00436                 pPacket->m_nPosition = nNext;
00437         }
00438 
00439         if ( ! nPort || Network.IsFirewalledAddress( &nAddress ) ) return TRUE;
00440 
00441         if ( bRelay )
00442         {
00443                 CG2Packet* pPong = CG2Packet::New( G2_PACKET_PONG, TRUE );
00444                 pPong->WritePacket( "RELAY", 0 );
00445                 Datagrams.Send( (IN_ADDR*)&nAddress, nPort, pPong );
00446         }
00447         else
00448         {
00449                 DWORD tNow = GetTickCount();
00450                 if ( tNow - m_tLastPingIn < Settings.Gnutella1.PingFlood ) return TRUE;
00451                 m_tLastPingIn = tNow;
00452 
00453                 BYTE* pRelay = pPacket->WriteGetPointer( 7, 0 );
00454                 *pRelay++ = 0x60;
00455                 *pRelay++ = 0;
00456                 *pRelay++ = 'R'; *pRelay++ = 'E'; *pRelay++ = 'L';
00457                 *pRelay++ = 'A'; *pRelay++ = 'Y';
00458 
00459                 CPtrArray pG2Nodes;
00460 
00461                 for ( POSITION pos = Neighbours.GetIterator() ; pos ; )
00462                 {
00463                         CG2Neighbour* pNeighbour = (CG2Neighbour*)Neighbours.GetNext( pos );
00464 
00465                         if (    pNeighbour->m_nState == nrsConnected &&
00466                                         pNeighbour->m_nProtocol == PROTOCOL_G2 &&
00467                                         pNeighbour != this)
00468                         {
00469                                 pG2Nodes.Add( pNeighbour );
00470                         }
00471                 }
00472 
00473                 int nRelayTo = Settings.Gnutella2.PingRelayLimit;
00474 
00475                 int nCount = pG2Nodes.GetCount();
00476 
00477                 for ( int nCur = 0; (nCur < nCount && nCur < nRelayTo); nCur++ )
00478                 {
00479                         int nRand = rand() % pG2Nodes.GetCount();
00480 
00481                         CG2Neighbour* pNeighbour = (CG2Neighbour*)pG2Nodes.GetAt( nRand );
00482                         // Remove this debug message later
00483                         theApp.Message( MSG_DEBUG, _T("Ping Relay iteration %i picked random index %i as %s"),
00484                         nCur, nRand, (LPCTSTR)pNeighbour->m_sAddress  );
00485 
00486                         pNeighbour->Send( pPacket, FALSE );
00487                         pG2Nodes.RemoveAt( nRand );
00488                 }
00489         }
00490 
00491         return TRUE;
00492 }
00493 
00495 // CG2Neighbour LOCAL NODE INFO : send
00496 
00497 void CG2Neighbour::SendLNI()
00498 {
00499         CG2Packet* pPacket = CG2Packet::New( G2_PACKET_LNI, TRUE );
00500 
00501         QWORD nMyVolume = 0;
00502         DWORD nMyFiles = 0;
00503         LibraryMaps.GetStatistics( &nMyFiles, &nMyVolume );
00504 
00505         WORD nLeafs = 0;
00506 
00507         for ( POSITION pos = Neighbours.GetIterator() ; pos ; )
00508         {
00509                 CNeighbour* pNeighbour = Neighbours.GetNext( pos );
00510 
00511                 if (    pNeighbour != this &&
00512                                 pNeighbour->m_nState == nrsConnected &&
00513                                 pNeighbour->m_nNodeType == ntLeaf )
00514                 {
00515                         nMyFiles += pNeighbour->m_nFileCount;
00516                         nMyVolume += pNeighbour->m_nFileVolume;
00517                         nLeafs++;
00518                 }
00519         }
00520 
00521         pPacket->WritePacket( "NA", 6 );
00522         pPacket->WriteLongLE( Network.m_pHost.sin_addr.S_un.S_addr );
00523         pPacket->WriteShortBE( htons( Network.m_pHost.sin_port ) );
00524 
00525         pPacket->WritePacket( "GU", 16 );
00526         GGUID tmp( MyProfile.GUID );
00527         pPacket->Write( &tmp, 16 );
00528 
00529         pPacket->WritePacket( "V", 4 );
00530         pPacket->WriteString( SHAREAZA_VENDOR_A, FALSE );
00531 
00532         pPacket->WritePacket( "LS", 8 );
00533         pPacket->WriteLongBE( (DWORD)nMyFiles );
00534         pPacket->WriteLongBE( (DWORD)nMyVolume );
00535 
00536         if ( ! Neighbours.IsG2Leaf() )
00537         {
00538                 pPacket->WritePacket( "HS", 4 );
00539                 pPacket->WriteShortBE( nLeafs );
00540                 pPacket->WriteShortBE( Settings.Gnutella2.NumLeafs );
00541 
00542                 pPacket->WritePacket( "QK", 0 );
00543         }
00544 
00545         Send( pPacket, TRUE, FALSE );
00546 }
00547 
00549 // CG2Neighbour LOCAL NODE INFO : receive
00550 
00551 BOOL CG2Neighbour::OnLNI(CG2Packet* pPacket)
00552 {
00553         if ( ! pPacket->m_bCompound ) return TRUE;
00554 
00555         DWORD tNow = time( NULL );
00556         CHAR szType[9];
00557         DWORD nLength;
00558 
00559         m_nLeafCount = 0;
00560 
00561         while ( pPacket->ReadPacket( szType, nLength ) )
00562         {
00563                 DWORD nNext = pPacket->m_nPosition + nLength;
00564 
00565                 if ( strcmp( szType, "NA" ) == 0 && nLength >= 6 )
00566                 {
00567                         m_pHost.sin_addr.S_un.S_addr = pPacket->ReadLongLE();
00568                         m_pHost.sin_port = htons( pPacket->ReadShortBE() );
00569                 }
00570                 else if ( strcmp( szType, "GU" ) == 0 && nLength >= 16 )
00571                 {
00572                         pPacket->Read( &m_pGUID, sizeof(GGUID) );
00573                         m_bGUID = TRUE;
00574                 }
00575                 else if ( strcmp( szType, "V" ) == 0 && nLength >= 4 )
00576                 {
00577                         CHAR szVendor[5] = { 0, 0, 0, 0, 0 };
00578                         pPacket->Read( szVendor, 4 );
00579                         m_pVendor = VendorCache.Lookup( szVendor );
00580                 }
00581                 else if ( strcmp( szType, "LS" ) == 0 && nLength >= 8 )
00582                 {
00583                         m_nFileCount    = pPacket->ReadLongBE();
00584                         m_nFileVolume   = pPacket->ReadLongBE();
00585                 }
00586                 else if ( strcmp( szType, "HS" ) == 0 && nLength >= 2 )
00587                 {
00588                         m_nLeafCount = pPacket->ReadShortBE();
00589                         m_nLeafLimit = pPacket->ReadShortBE();
00590                 }
00591                 else if ( strcmp( szType, "QK" ) == 0 )
00592                 {
00593                         m_bCachedKeys = TRUE;
00594                 }
00595 
00596                 pPacket->m_nPosition = nNext;
00597         }
00598 
00599         if ( ! Network.IsFirewalledAddress( &m_pHost.sin_addr, TRUE ) &&
00600                    m_pVendor != NULL && m_nNodeType != ntLeaf )
00601         {
00602                 HostCache.Gnutella2.Add( &m_pHost.sin_addr, htons( m_pHost.sin_port ),
00603                         0, m_pVendor->m_sCode );
00604         }
00605 
00606         m_tWaitLNI = 0;
00607 
00608         return TRUE;
00609 }
00610 
00612 // CG2Neighbour KNOWN HUB LIST : send
00613 
00614 void CG2Neighbour::SendKHL()
00615 {
00616         CG2Packet* pPacket = CG2Packet::New( G2_PACKET_KHL, TRUE );
00617 
00618         DWORD nBase = pPacket->m_nPosition;
00619 
00620         for ( POSITION pos = Neighbours.GetIterator() ; pos ; )
00621         {
00622                 CG2Neighbour* pNeighbour = (CG2Neighbour*)Neighbours.GetNext( pos );
00623 
00624                 if (    pNeighbour != this &&
00625                                 pNeighbour->m_nProtocol == PROTOCOL_G2 &&
00626                                 pNeighbour->m_nState == nrsConnected &&
00627                                 pNeighbour->m_nNodeType != ntLeaf &&
00628                                 pNeighbour->m_pHost.sin_addr.S_un.S_addr != Network.m_pHost.sin_addr.S_un.S_addr )
00629                 {
00630                         if ( pNeighbour->m_pVendor && pNeighbour->m_pVendor->m_sCode.GetLength() == 4 )
00631                         {
00632                                 pPacket->WritePacket( "NH", 14 + 6, TRUE );                                     // 4
00633                                 pPacket->WritePacket( "HS", 2 );                                                        // 4
00634                                 pPacket->WriteShortBE( (WORD)pNeighbour->m_nLeafCount );        // 2
00635                                 pPacket->WritePacket( "V", 4 );                                                         // 3
00636                                 pPacket->WriteString( pNeighbour->m_pVendor->m_sCode );         // 5
00637                         }
00638                         else
00639                         {
00640                                 pPacket->WritePacket( "NH", 7 + 6, TRUE );                                      // 4
00641                                 pPacket->WritePacket( "HS", 2 );                                                        // 4
00642                                 pPacket->WriteShortBE( (WORD)pNeighbour->m_nLeafCount );        // 2
00643                                 pPacket->WriteByte( 0 );                                                                        // 1
00644                         }
00645 
00646                         pPacket->WriteLongLE( pNeighbour->m_pHost.sin_addr.S_un.S_addr );       // 4
00647                         pPacket->WriteShortBE( htons( pNeighbour->m_pHost.sin_port ) );         // 2
00648                 }
00649         }
00650 
00651         int nCount = Settings.Gnutella2.KHLHubCount;
00652         DWORD tNow = time( NULL );
00653 
00654         pPacket->WritePacket( "TS", 4 );
00655         pPacket->WriteLongBE( time( NULL ) );
00656 
00657         for ( CHostCacheHost* pHost = HostCache.Gnutella2.GetNewest() ; pHost && nCount > 0 ; pHost = pHost->m_pPrevTime )
00658         {
00659                 if (    pHost->CanQuote( tNow ) &&
00660                                 Neighbours.Get( &pHost->m_pAddress ) == NULL &&
00661                                 pHost->m_pAddress.S_un.S_addr != Network.m_pHost.sin_addr.S_un.S_addr )
00662                 {
00663                         int nLength = 10;
00664 
00665                         if ( pHost->m_pVendor && pHost->m_pVendor->m_sCode.GetLength() == 4 )
00666                                 nLength += 7;
00667                         if ( m_nNodeType == ntLeaf && pHost->m_nKeyValue != 0 && pHost->m_nKeyHost == Network.m_pHost.sin_addr.S_un.S_addr )
00668                                 nLength += 8;
00669                         if ( nLength > 10 )
00670                                 nLength ++;
00671 
00672                         pPacket->WritePacket( "CH", nLength, nLength > 10 );
00673 
00674                         if ( pHost->m_pVendor && pHost->m_pVendor->m_sCode.GetLength() == 4 )
00675                         {
00676                                 pPacket->WritePacket( "V", 4 );                                                         // 3
00677                                 pPacket->WriteString( pHost->m_pVendor->m_sCode, FALSE );       // 4
00678                         }
00679 
00680                         if ( m_nNodeType == ntLeaf && pHost->m_nKeyValue != 0 && pHost->m_nKeyHost == Network.m_pHost.sin_addr.S_un.S_addr )
00681                         {
00682                                 pPacket->WritePacket( "QK", 4 );                                                        // 4
00683                                 pPacket->WriteLongBE( pHost->m_nKeyValue );                                     // 4
00684                         }
00685 
00686                         if ( nLength > 10 ) pPacket->WriteByte( 0 );                                    // 1
00687 
00688                         pPacket->WriteLongLE( pHost->m_pAddress.S_un.S_addr );                  // 4
00689                         pPacket->WriteShortBE( pHost->m_nPort );                                                // 2
00690                         pPacket->WriteLongBE( pHost->m_tSeen );                                                 // 4
00691 
00692                         nCount--;
00693                 }
00694         }
00695 
00696         Send( pPacket, TRUE, TRUE );
00697 
00698         m_tLastKHL = GetTickCount();
00699 }
00700 
00702 // CG2Neighbour KNOWN HUB LIST : receive
00703 
00704 BOOL CG2Neighbour::OnKHL(CG2Packet* pPacket)
00705 {
00706         if ( ! pPacket->m_bCompound ) return TRUE;
00707 
00708         CHAR szType[9], szInner[9];
00709         DWORD nLength, nInner;
00710         BOOL bCompound;
00711 
00712         DWORD tNow = time( NULL );
00713 
00714         m_pHubGroup->Clear();
00715 
00716         while ( pPacket->ReadPacket( szType, nLength, &bCompound ) )
00717         {
00718                 DWORD nNext = pPacket->m_nPosition + nLength;
00719 
00720                 if (    strcmp( szType, "NH" ) == 0 ||
00721                                 strcmp( szType, "CH" ) == 0 )
00722                 {
00723                         DWORD nAddress = 0, nKey = 0, tSeen = tNow;
00724                         WORD nPort = 0, nLeafs = 0;
00725                         CString strVendor;
00726 
00727                         if ( bCompound || 0 == strcmp( szType, "NH" ) )
00728                         {
00729                                 while ( pPacket->m_nPosition < nNext && pPacket->ReadPacket( szInner, nInner ) )
00730                                 {
00731                                         DWORD nNextX = pPacket->m_nPosition + nInner;
00732 
00733                                         if ( strcmp( szInner, "NA" ) == 0 && nInner >= 6 )
00734                                         {
00735                                                 nAddress = pPacket->ReadLongLE();
00736                                                 nPort = pPacket->ReadShortBE();
00737                                         }
00738                                         else if ( strcmp( szInner, "V" ) == 0 && nInner >= 4 )
00739                                         {
00740                                                 strVendor = pPacket->ReadString( 4 );
00741                                         }
00742                                         else if ( strcmp( szInner, "QK" ) == 0 && nInner >= 4 )
00743                                         {
00744                                                 nKey = pPacket->ReadLongBE();
00745                                                 m_bCachedKeys = TRUE;
00746                                         }
00747                                         else if ( strcmp( szInner, "TS" ) == 0 && nInner >= 4 )
00748                                         {
00749                                                 tSeen = pPacket->ReadLongBE() + m_tAdjust;
00750                                         }
00751 
00752                                         pPacket->m_nPosition = nNextX;
00753                                 }
00754 
00755                                 nLength = nNext - pPacket->m_nPosition;
00756                         }
00757 
00758                         if ( nLength >= 6 )
00759                         {
00760                                 nAddress = pPacket->ReadLongLE();
00761                                 nPort = pPacket->ReadShortBE();
00762                                 if ( nLength >= 10 ) tSeen = pPacket->ReadLongBE() + m_tAdjust;
00763                         }
00764 
00765                         if ( FALSE == Network.IsFirewalledAddress( &nAddress, TRUE ) )
00766                         {
00767                                 CHostCacheHost* pCached = HostCache.Gnutella2.Add(
00768                                         (IN_ADDR*)&nAddress, nPort, tSeen, strVendor );
00769 
00770                                 if ( pCached != NULL && m_nNodeType == ntHub )
00771                                 {
00772                                         if ( pCached->m_nKeyValue == 0 ||
00773                                                  pCached->m_nKeyHost != Network.m_pHost.sin_addr.S_un.S_addr )
00774                                         {
00775                                                 pCached->SetKey( nKey, &m_pHost.sin_addr );
00776                                         }
00777                                 }
00778 
00779                                 if ( strcmp( szType, "NH" ) == 0 )
00780                                 {
00781                                         m_pHubGroup->Add( (IN_ADDR*)&nAddress, nPort );
00782                                 }
00783                         }
00784                 }
00785                 else if ( strcmp( szType, "TS" ) == 0 && nLength >= 4 )
00786                 {
00787                         m_tAdjust = (LONG)tNow - (LONG)pPacket->ReadLongBE();
00788                 }
00789 
00790                 pPacket->m_nPosition = nNext;
00791         }
00792 
00793         return TRUE;
00794 }
00795 
00797 // CG2Neighbour HUB ADVERTISEMENT WALKER : send
00798 
00799 void CG2Neighbour::SendHAW()
00800 {
00801         m_tLastHAW = GetTickCount();
00802 
00803         if ( m_nNodeType == ntLeaf || Neighbours.IsG2Leaf() ) return;
00804 
00805         CG2Packet* pPacket = CG2Packet::New( G2_PACKET_HAW, TRUE );
00806 
00807         WORD nLeafs = 0;
00808         GGUID pGUID;
00809 
00810         Network.CreateID( pGUID );
00811 
00812         for ( POSITION pos = Neighbours.GetIterator() ; pos ; )
00813         {
00814                 CNeighbour* pNeighbour = Neighbours.GetNext( pos );
00815 
00816                 if (    pNeighbour != this &&
00817                                 pNeighbour->m_nState == nrsConnected &&
00818                                 pNeighbour->m_nNodeType == ntLeaf )
00819                 {
00820                         nLeafs++;
00821                 }
00822         }
00823 
00824         pPacket->WritePacket( "NA", 6 );
00825         pPacket->WriteLongLE( Network.m_pHost.sin_addr.S_un.S_addr );
00826         pPacket->WriteShortBE( htons( Network.m_pHost.sin_port ) );
00827 
00828         pPacket->WritePacket( "HS", 2 );
00829         pPacket->WriteShortBE( nLeafs );
00830 
00831         pPacket->WritePacket( "V", 4 );
00832         pPacket->WriteString( SHAREAZA_VENDOR_A );      // 5 bytes
00833 
00834         pPacket->WriteByte( 100 );
00835         pPacket->WriteByte( 0 );
00836         pPacket->Write( &pGUID, sizeof(GGUID) );
00837 
00838         Send( pPacket, TRUE, TRUE );
00839 
00840         m_pGUIDCache->Add( &pGUID, this );
00841 }
00842 
00844 // CG2Neighbour HUB ADVERTISEMENT WALKER : receive
00845 
00846 BOOL CG2Neighbour::OnHAW(CG2Packet* pPacket)
00847 {
00848         if ( ! pPacket->m_bCompound ) return TRUE;
00849 
00850         CString strVendor;
00851         CHAR szType[9];
00852         DWORD nLength;
00853 
00854         DWORD nAddress  = 0;
00855         WORD nPort              = 0;
00856 
00857         while ( pPacket->ReadPacket( szType, nLength ) )
00858         {
00859                 DWORD nNext = pPacket->m_nPosition + nLength;
00860 
00861                 if ( strcmp( szType, "V" ) == 0 && nLength >= 4 )
00862                 {
00863                         strVendor = pPacket->ReadString( 4 );
00864                 }
00865                 else if ( strcmp( szType, "NA" ) == 0 && nLength >= 6 )
00866                 {
00867                         nAddress        = pPacket->ReadLongLE();
00868                         nPort           = pPacket->ReadShortBE();
00869                 }
00870 
00871                 pPacket->m_nPosition = nNext;
00872         }
00873 
00874         if ( pPacket->GetRemaining() < 2 + 16 ) return TRUE;
00875         if ( nAddress == 0 || nPort == 0 ) return TRUE;
00876         if ( Network.IsFirewalledAddress( &nAddress, TRUE ) ) return TRUE;
00877 
00878         BYTE* pPtr      = pPacket->m_pBuffer + pPacket->m_nPosition;
00879         BYTE nTTL       = pPacket->ReadByte();
00880         BYTE nHops      = pPacket->ReadByte();
00881 
00882         GGUID pGUID;
00883         pPacket->Read( &pGUID, sizeof(GGUID) );
00884 
00885         HostCache.Gnutella2.Add( (IN_ADDR*)&nAddress, nPort, 0, strVendor );
00886 
00887         if ( nTTL > 0 && nHops < 255 )
00888         {
00889                 m_pGUIDCache->Add( &pGUID, this );
00890 
00891                 pPtr[0] = nTTL  - 1;
00892                 pPtr[1] = nHops + 1;
00893 
00894                 if ( CG2Neighbour* pNeighbour = Neighbours.GetRandomHub( this, &pGUID ) )
00895                 {
00896                         pNeighbour->Send( pPacket, FALSE, TRUE );
00897                 }
00898         }
00899 
00900         return TRUE;
00901 }
00902 
00904 // CG2Neighbour QUERY packet handler
00905 
00906 BOOL CG2Neighbour::SendQuery(CQuerySearch* pSearch, CPacket* pPacket, BOOL bLocal)
00907 {
00908         if ( m_nState != nrsConnected )
00909         {
00910                 return FALSE;
00911         }
00912         else if ( pPacket == NULL || pPacket->m_nProtocol != PROTOCOL_G2 )
00913         {
00914                 return FALSE;
00915         }
00916         else if ( m_nNodeType == ntHub && ! bLocal )
00917         {
00918                 return FALSE;
00919         }
00920         else if ( m_pQueryTableRemote != NULL && m_pQueryTableRemote->m_bLive && ( m_nNodeType == ntLeaf || pSearch->m_bUDP ) )
00921         {
00922                 if ( ! m_pQueryTableRemote->Check( pSearch ) ) return FALSE;
00923         }
00924         else if ( m_nNodeType == ntLeaf && ! bLocal )
00925         {
00926                 return FALSE;
00927         }
00928 
00929         Send( pPacket, FALSE, ! bLocal );
00930 
00931         return TRUE;
00932 }
00933 
00934 BOOL CG2Neighbour::OnQuery(CG2Packet* pPacket)
00935 {
00936         CQuerySearch* pSearch = CQuerySearch::FromPacket( pPacket );
00937 
00938         // Check for invalid / blocked searches
00939         if ( pSearch == NULL )
00940         {
00941                 theApp.Message( MSG_DEFAULT, IDS_PROTOCOL_BAD_QUERY, (LPCTSTR)m_sAddress );
00942                 Statistics.Current.Gnutella2.Dropped++;
00943                 m_nDropCount++;
00944                 return TRUE;
00945         }
00946 
00947         // Check for excessive source searching
00948         if ( ( pSearch->m_bSHA1 ) || ( pSearch->m_bBTH ) || ( pSearch->m_bED2K ) )
00949         {
00950 
00951                 // Update allowed query operations, check for bad client
00952                 if ( m_nQueryLimiter > -60 ) 
00953                 {
00954                         m_nQueryLimiter--;
00955                 }
00956                 else if ( ! m_bBlacklisted && ( m_nNodeType == ntLeaf ) )
00957                 {
00958                         // Abusive client
00959                         m_bBlacklisted = TRUE;
00960                         theApp.Message( MSG_SYSTEM, _T("Blacklisting %s due to excess traffic"), (LPCTSTR)m_sAddress );
00961                         //Security.Ban( &m_pHost.sin_addr, ban30Mins, FALSE );
00962 
00963                 }
00964 
00965                 if ( ( m_bBlacklisted ) || ( m_nQueryLimiter < 0 ) )
00966                 {
00967                         // Too many FMS operations
00968                         if ( ! m_bBlacklisted )
00969                                 theApp.Message( MSG_DEBUG, _T("Dropping excess query traffic from %s"), (LPCTSTR)m_sAddress );
00970 
00971                         delete pSearch;
00972                         Statistics.Current.Gnutella2.Dropped++;
00973                         m_nDropCount++;
00974                         return TRUE;
00975                 }
00976         }
00977 
00978         // Check for old wrapped queries
00979         if ( pPacket->IsType( G2_PACKET_QUERY_WRAP ) )
00980         {
00981                 theApp.Message( MSG_DEBUG, _T("CG2Neighbour::OnQuery Ignoring wrapped query packet") );
00982                 delete pSearch;
00983                 Statistics.Current.Gnutella2.Dropped++;
00984                 m_nDropCount++;
00985                 return TRUE;
00986         }
00987 
00988         if ( m_nNodeType == ntLeaf && pSearch->m_bUDP &&
00989                  pSearch->m_pEndpoint.sin_addr.S_un.S_addr != m_pHost.sin_addr.S_un.S_addr )
00990         {
00991                 delete pSearch;
00992                 Statistics.Current.Gnutella2.Dropped++;
00993                 m_nDropCount++;
00994                 return TRUE;
00995         }
00996 
00997         if ( ! Network.QueryRoute->Add( &pSearch->m_pGUID, this ) )
00998         {
00999                 delete pSearch;
01000                 Statistics.Current.Gnutella2.Dropped++;
01001                 m_nDropCount++;
01002                 return TRUE;
01003         }
01004 
01005         if ( m_nNodeType != ntHub )
01006         {
01007                 /*
01008                 if ( pPacket->IsType( G2_PACKET_QUERY_WRAP ) )
01009                 {
01010                         if ( ! pPacket->SeekToWrapped() ) return TRUE;
01011                         GNUTELLAPACKET* pG1 = (GNUTELLAPACKET*)( pPacket->m_pBuffer + pPacket->m_nPosition );
01012 
01013                         if ( pG1->m_nTTL > 1 )
01014                         {
01015                                 pG1->m_nTTL--;
01016                                 pG1->m_nHops++;
01017                                 Neighbours.RouteQuery( pSearch, pPacket, this, TRUE );
01018                         }
01019                 }
01020                 else
01021                 {
01022                         Neighbours.RouteQuery( pSearch, pPacket, this, m_nNodeType == ntLeaf );
01023                 }*/
01024 
01025                 Neighbours.RouteQuery( pSearch, pPacket, this, m_nNodeType == ntLeaf );
01026         }
01027 
01028         Network.OnQuerySearch( pSearch );
01029 
01030         if ( pSearch->m_bUDP && /* Network.IsStable() && Datagrams.IsStable() && */
01031                  pSearch->m_pEndpoint.sin_addr.S_un.S_addr != m_pHost.sin_addr.S_un.S_addr )
01032         {
01033                 CLocalSearch pLocal( pSearch, &pSearch->m_pEndpoint );
01034                 pLocal.Execute();
01035         }
01036         else
01037         {
01038                 /*
01039                 BOOL bIsG1 = pPacket->IsType( G2_PACKET_QUERY_WRAP );
01040 
01041                 if ( ! bIsG1 || Settings.Gnutella1.EnableToday )
01042                 {
01043                         CLocalSearch pLocal( pSearch, this, bIsG1 );
01044                         pLocal.Execute();
01045                 }
01046                 */
01047                 CLocalSearch pLocal( pSearch, this, FALSE );
01048                 pLocal.Execute();
01049         }
01050 
01051         if ( m_nNodeType == ntLeaf ) Send( Neighbours.CreateQueryWeb( &pSearch->m_pGUID, this ), TRUE, FALSE );
01052 
01053         delete pSearch;
01054         Statistics.Current.Gnutella2.Queries++;
01055 
01056         return TRUE;
01057 }
01058 
01059 BOOL CG2Neighbour::OnQueryAck(CG2Packet* pPacket)
01060 {
01061         HostCache.Gnutella2.Add( &m_pHost.sin_addr, htons( m_pHost.sin_port ) );
01062         SearchManager.OnQueryAck( pPacket, &m_pHost, NULL );
01063         return TRUE;
01064 }
01065 
01067 // CG2Neighbour QUERY KEY REQUEST packet handler
01068 
01069 BOOL CG2Neighbour::OnQueryKeyReq(CG2Packet* pPacket)
01070 {
01071         if ( ! pPacket->m_bCompound ) return TRUE;
01072         if ( m_nNodeType != ntLeaf ) return TRUE;
01073 
01074         DWORD nLength, nAddress = 0;
01075         BOOL bCacheOkay = TRUE;
01076         CHAR szType[9];
01077         WORD nPort = 0;
01078 
01079         while ( pPacket->ReadPacket( szType, nLength ) )
01080         {
01081                 DWORD nOffset = pPacket->m_nPosition + nLength;
01082 
01083                 if ( strcmp( szType, "QNA" ) == 0 && nLength >= 6 )
01084                 {
01085                         nAddress        = pPacket->ReadLongLE();
01086                         nPort           = pPacket->ReadShortBE();
01087                 }
01088                 else if ( strcmp( szType, "REF" ) == 0 )
01089                 {
01090                         bCacheOkay = FALSE;
01091                 }
01092 
01093                 pPacket->m_nPosition = nOffset;
01094         }
01095 
01096         if ( Network.IsFirewalledAddress( &nAddress, TRUE ) || 0 == nPort ) return TRUE;
01097 
01098         CHostCacheHost* pCached = bCacheOkay ? HostCache.Gnutella2.Find( (IN_ADDR*)&nAddress ) : NULL;
01099 
01100         if ( pCached != NULL && pCached->m_nKeyValue != 0 &&
01101                  pCached->m_nKeyHost == Network.m_pHost.sin_addr.S_un.S_addr )
01102         {
01103                 CG2Packet* pAnswer = CG2Packet::New( G2_PACKET_QUERY_KEY_ANS, TRUE );
01104                 pAnswer->WritePacket( "QNA", 6 );
01105                 pAnswer->WriteLongLE( nAddress );
01106                 pAnswer->WriteShortBE( nPort );
01107                 pAnswer->WritePacket( "QK", 4 );
01108                 pAnswer->WriteLongBE( pCached->m_nKeyValue );
01109                 pAnswer->WritePacket( "CACHED", 0 );
01110                 Send( pAnswer );
01111         }
01112         else
01113         {
01114                 CG2Packet* pRequest = CG2Packet::New( G2_PACKET_QUERY_KEY_REQ, TRUE );
01115                 pRequest->WritePacket( "SNA", 4 );
01116                 pRequest->WriteLongLE( m_pHost.sin_addr.S_un.S_addr );
01117                 Datagrams.Send( (IN_ADDR*)&nAddress, nPort, pRequest, TRUE, NULL, FALSE );
01118         }
01119 
01120         return TRUE;
01121 }
01122 
01124 // CG2Neighbour QUERY KEY ANSWER packet handler
01125 
01126 BOOL CG2Neighbour::OnQueryKeyAns(CG2Packet* pPacket)
01127 {
01128         if ( ! pPacket->m_bCompound ) return TRUE;
01129         if ( m_nNodeType != ntHub ) return TRUE;
01130 
01131         DWORD nKey = 0, nAddress = 0;
01132         WORD nPort = 0;
01133 
01134         CHAR szType[9];
01135         DWORD nLength;
01136 
01137         while ( pPacket->ReadPacket( szType, nLength ) )
01138         {
01139                 DWORD nOffset = pPacket->m_nPosition + nLength;
01140 
01141                 if ( strcmp( szType, "QK" ) == 0 && nLength >= 4 )
01142                 {
01143                         nKey = pPacket->ReadLongBE();
01144                 }
01145                 else if ( strcmp( szType, "QNA" ) == 0 && nLength >= 6 )
01146                 {
01147                         nAddress        = pPacket->ReadLongLE();
01148                         nPort           = pPacket->ReadShortBE();
01149                 }
01150                 else if ( strcmp( szType, "CACHED" ) == 0 )
01151                 {
01152                         m_bCachedKeys = TRUE;
01153                 }
01154 
01155                 pPacket->m_nPosition = nOffset;
01156         }
01157 
01158         theApp.Message( MSG_DEBUG, _T("Got a query key for %s:%i via neighbour %s: 0x%x"),
01159                 (LPCTSTR)CString( inet_ntoa( *(IN_ADDR*)&nAddress ) ), nPort, (LPCTSTR)m_sAddress, nKey );
01160 
01161         if ( Network.IsFirewalledAddress( &nAddress ) || 0 == nPort ) return TRUE;
01162 
01163         CHostCacheHost* pCache = HostCache.Gnutella2.Add( (IN_ADDR*)&nAddress, nPort );
01164         if ( pCache != NULL ) pCache->SetKey( nKey, &m_pHost.sin_addr );
01165 
01166         return TRUE;
01167 }
01168 
01170 // CG2Neighbour PUSH packet handler
01171 
01172 BOOL CG2Neighbour::OnPush(CG2Packet* pPacket)
01173 {
01174         if ( ! pPacket->m_bCompound ) return TRUE;
01175 
01176         DWORD nLength = pPacket->GetRemaining();
01177 
01178         if ( ! pPacket->SkipCompound( nLength, 6 ) )
01179         {
01180                 pPacket->Debug( _T("BadPush") );
01181                 Statistics.Current.Gnutella2.Dropped++;
01182                 return TRUE;
01183         }
01184 
01185         DWORD nAddress  = pPacket->ReadLongLE();
01186         WORD nPort              = pPacket->ReadShortBE();
01187 
01188         if ( Security.IsDenied( (IN_ADDR*)&nAddress ) )
01189         {
01190                 Statistics.Current.Gnutella2.Dropped++;
01191                 m_nDropCount++;
01192                 return TRUE;
01193         }
01194         else if ( ! nPort || Network.IsFirewalledAddress( &nAddress ) )
01195         {
01196                 theApp.Message( MSG_ERROR, IDS_PROTOCOL_ZERO_PUSH, (LPCTSTR)m_sAddress );
01197                 Statistics.Current.Gnutella2.Dropped++;
01198                 m_nDropCount++;
01199                 return TRUE;
01200         }
01201 
01202         Handshakes.PushTo( (IN_ADDR*)&nAddress, nPort );
01203 
01204         return TRUE;
01205 }
01206 
01208 // CG2Neighbour USER PROFILE CHALLENGE packet handler
01209 
01210 BOOL CG2Neighbour::OnProfileChallenge(CG2Packet* pPacket)
01211 {
01212         if ( ! MyProfile.IsValid() ) return TRUE;
01213 
01214         CG2Packet* pProfile = CG2Packet::New( G2_PACKET_PROFILE_DELIVERY, TRUE );
01215 
01216         CString strXML = MyProfile.GetXML( NULL, TRUE )->ToString( TRUE );
01217 
01218         pProfile->WritePacket( "XML", pProfile->GetStringLen( strXML ) );
01219         pProfile->WriteString( strXML, FALSE );
01220 
01221         Send( pProfile, TRUE, TRUE );
01222 
01223         return TRUE;
01224 }
01225 
01227 // CG2Neighbour USER PROFILE DELIVERY packet handler
01228 
01229 BOOL CG2Neighbour::OnProfileDelivery(CG2Packet* pPacket)
01230 {
01231         if ( ! pPacket->m_bCompound ) return TRUE;
01232 
01233         CHAR szType[9];
01234         DWORD nLength;
01235 
01236         while ( pPacket->ReadPacket( szType, nLength ) )
01237         {
01238                 DWORD nOffset = pPacket->m_nPosition + nLength;
01239 
01240                 if ( strcmp( szType, "XML" ) == 0 )
01241                 {
01242                         CXMLElement* pXML = CXMLElement::FromString( pPacket->ReadString( nLength ), TRUE );
01243 
01244                         if ( pXML )
01245                         {
01246                                 if ( m_pProfile == NULL ) m_pProfile = new CGProfile();
01247                                 if ( ! m_pProfile->FromXML( pXML ) ) delete pXML;
01248                         }
01249                 }
01250 
01251                 pPacket->m_nPosition = nOffset;
01252         }
01253 
01254         return TRUE;
01255 }

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