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 "Statistics.h"
00026 #include "Network.h"
00027 #include "Datagrams.h"
00028 #include "Datagram.h"
00029 #include "DatagramPart.h"
00030 #include "Buffer.h"
00031
00032 #include "Handshakes.h"
00033 #include "Neighbours.h"
00034 #include "Neighbour.h"
00035 #include "RouteCache.h"
00036 #include "LocalSearch.h"
00037 #include "SearchManager.h"
00038 #include "QuerySearch.h"
00039 #include "QueryHit.h"
00040 #include "GProfile.h"
00041 #include "CrawlSession.h"
00042
00043 #include "G2Neighbour.h"
00044 #include "G2Packet.h"
00045 #include "EDClients.h"
00046 #include "EDPacket.h"
00047 #include "Security.h"
00048 #include "HostCache.h"
00049 #include "QueryKeys.h"
00050 #include "LibraryMaps.h"
00051
00052 #ifdef _DEBUG
00053 #undef THIS_FILE
00054 static char THIS_FILE[]=__FILE__;
00055 #define new DEBUG_NEW
00056 #endif
00057
00058 #define HASH_SIZE 32
00059 #define HASH_MASK 31
00060
00061 #define TEMP_BUFFER 4096
00062 #define METER_MINIMUM 100
00063 #define METER_LENGTH 24
00064 #define METER_PERIOD 2000
00065 #define METER_SECOND 1000
00066
00067 CDatagrams Datagrams;
00068
00069
00071
00072
00073 CDatagrams::CDatagrams()
00074 {
00075 m_hSocket = INVALID_SOCKET;
00076 m_nSequence = 0;
00077 m_bStable = FALSE;
00078
00079 ZeroMemory( &m_mInput, sizeof(m_mInput) );
00080 ZeroMemory( &m_mOutput, sizeof(m_mOutput) );
00081
00082 m_nInBandwidth = m_nInFrags = m_nInPackets = 0;
00083 m_nOutBandwidth = m_nOutFrags = m_nOutPackets = 0;
00084 }
00085
00086 CDatagrams::~CDatagrams()
00087 {
00088 Disconnect();
00089 }
00090
00092
00093
00094 BOOL CDatagrams::Listen()
00095 {
00096 if ( m_hSocket != INVALID_SOCKET ) return FALSE;
00097
00098 m_hSocket = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
00099 if ( m_hSocket == INVALID_SOCKET ) return FALSE;
00100
00101 SOCKADDR_IN saHost;
00102
00103 if ( Network.Resolve( Settings.Connection.InHost, Settings.Connection.InPort, &saHost ) )
00104 {
00105
00106 if ( ! Settings.Connection.InBind ) saHost.sin_addr.S_un.S_addr = 0;
00107 }
00108 else if ( Network.Resolve( Settings.Connection.OutHost, Settings.Connection.InPort, &saHost ) )
00109 {
00110
00111 }
00112 else
00113 {
00114 saHost = Network.m_pHost;
00115 if ( ! Settings.Connection.InBind ) saHost.sin_addr.S_un.S_addr = 0;
00116 }
00117
00118 if ( bind( m_hSocket, (SOCKADDR*)&saHost, sizeof(saHost) ) == 0 )
00119 {
00120 theApp.Message( MSG_DEFAULT, IDS_NETWORK_LISTENING_UDP,
00121 (LPCTSTR)CString( inet_ntoa( saHost.sin_addr ) ), htons( saHost.sin_port ) );
00122 }
00123
00124 WSAEventSelect( m_hSocket, Network.m_pWakeup, FD_READ );
00125
00126 m_nBufferBuffer = Settings.Gnutella2.UdpBuffers;
00127 m_pBufferBuffer = new CBuffer[ m_nBufferBuffer ];
00128 m_pBufferFree = m_pBufferBuffer;
00129 m_nBufferFree = m_nBufferBuffer;
00130
00131 CBuffer* pBuffer = m_pBufferBuffer;
00132
00133 for ( DWORD nPos = m_nBufferBuffer ; nPos ; nPos--, pBuffer++ )
00134 {
00135 pBuffer->m_pNext = ( nPos == 1 ) ? NULL : ( pBuffer + 1 );
00136 }
00137
00138 m_nInputBuffer = Settings.Gnutella2.UdpInFrames;
00139 m_pInputBuffer = new CDatagramIn[ m_nInputBuffer ];
00140 m_pInputFree = m_pInputBuffer;
00141
00142 CDatagramIn* pDGI = m_pInputBuffer;
00143
00144 for ( DWORD nPos = m_nInputBuffer ; nPos ; nPos--, pDGI++ )
00145 {
00146 pDGI->m_pNextHash = ( nPos == 1 ) ? NULL : ( pDGI + 1 );
00147 }
00148
00149 m_nOutputBuffer = Settings.Gnutella2.UdpOutFrames;
00150 m_pOutputBuffer = new CDatagramOut[ m_nOutputBuffer ];
00151 m_pOutputFree = m_pOutputBuffer;
00152
00153 CDatagramOut* pDGO = m_pOutputBuffer;
00154
00155 for ( DWORD nPos = m_nOutputBuffer ; nPos ; nPos--, pDGO++ )
00156 {
00157 pDGO->m_pNextHash = ( nPos == 1 ) ? NULL : ( pDGO + 1 );
00158 }
00159
00160 ZeroMemory( m_pInputHash, sizeof(CDatagramIn*) * HASH_SIZE );
00161 ZeroMemory( m_pOutputHash, sizeof(CDatagramIn*) * HASH_SIZE );
00162
00163 m_pInputFirst = m_pInputLast = NULL;
00164 m_pOutputFirst = m_pOutputLast = NULL;
00165
00166 m_tLastWrite = 0;
00167
00168 m_nInFrags = m_nInPackets = 0;
00169 m_nOutFrags = m_nOutPackets = 0;
00170
00171 return TRUE;
00172 }
00173
00175
00176
00177 void CDatagrams::Disconnect()
00178 {
00179 if ( m_hSocket == INVALID_SOCKET ) return;
00180
00181 closesocket( m_hSocket );
00182 m_hSocket = INVALID_SOCKET;
00183
00184 delete [] m_pOutputBuffer;
00185 m_pOutputBuffer = NULL;
00186 m_nOutputBuffer = 0;
00187 m_pOutputFirst = m_pOutputLast = m_pOutputFree = NULL;
00188
00189 delete [] m_pInputBuffer;
00190 m_pInputBuffer = NULL;
00191 m_nInputBuffer = 0;
00192 m_pInputFirst = m_pInputLast = m_pInputFree = NULL;
00193
00194 delete [] m_pBufferBuffer;
00195 m_pBufferBuffer = NULL;
00196 m_nBufferBuffer = 0;
00197
00198 m_nInBandwidth = m_nInFrags = m_nInPackets = 0;
00199 m_nOutBandwidth = m_nOutFrags = m_nOutPackets = 0;
00200 }
00201
00203
00204
00205 BOOL CDatagrams::IsStable()
00206 {
00207 if ( m_hSocket == INVALID_SOCKET ) return FALSE;
00208 if ( ! Network.IsListening() ) return FALSE;
00209
00210 if ( Settings.Connection.FirewallStatus == CONNECTION_FIREWALLED )
00211 return FALSE;
00212 else if ( Settings.Connection.FirewallStatus == CONNECTION_OPEN )
00213 return TRUE;
00214 else
00215 return m_bStable;
00216 }
00217
00219
00220
00221 BOOL CDatagrams::Send(IN_ADDR* pAddress, WORD nPort, CPacket* pPacket, BOOL bRelease, LPVOID pToken, BOOL bAck)
00222 {
00223 SOCKADDR_IN pHost;
00224
00225 pHost.sin_family = PF_INET;
00226 pHost.sin_addr = *pAddress;
00227 pHost.sin_port = htons( nPort );
00228
00229 return Send( &pHost, pPacket, bRelease, pToken, bAck );
00230 }
00231
00232 BOOL CDatagrams::Send(SOCKADDR_IN* pHost, CPacket* pPacket, BOOL bRelease, LPVOID pToken, BOOL bAck)
00233 {
00234 ASSERT( pHost != NULL && pPacket != NULL );
00235
00236 if ( m_hSocket == INVALID_SOCKET || Security.IsDenied( &pHost->sin_addr ) )
00237 {
00238 if ( bRelease ) pPacket->Release();
00239 return FALSE;
00240 }
00241
00242 if ( pPacket->m_nProtocol == PROTOCOL_ED2K )
00243 {
00244 CBuffer pBuffer;
00245
00246 ((CEDPacket*)pPacket)->ToBufferUDP( &pBuffer );
00247 pPacket->SmartDump( NULL, &pHost->sin_addr, TRUE );
00248 if ( bRelease ) pPacket->Release();
00249
00250 if ( ntohs( pHost->sin_port ) != 4669 )
00251 {
00252 sendto( m_hSocket, (LPSTR)pBuffer.m_pBuffer, pBuffer.m_nLength, 0,
00253 (SOCKADDR*)pHost, sizeof(SOCKADDR_IN) );
00254 }
00255
00256 return TRUE;
00257 }
00258 else if ( pPacket->m_nProtocol != PROTOCOL_G2 )
00259 {
00260 if ( bRelease ) pPacket->Release();
00261 return FALSE;
00262 }
00263
00264 if ( m_pOutputFree == NULL || m_pBufferFree == NULL )
00265 {
00266 if ( m_pOutputLast == NULL )
00267 {
00268 if ( bRelease ) pPacket->Release();
00269 theApp.Message( MSG_DEBUG, _T("CDatagrams output frames exhausted.") );
00270 return FALSE;
00271 }
00272 Remove( m_pOutputLast );
00273 }
00274
00275 if ( m_pBufferFree == NULL )
00276 {
00277 if ( bRelease ) pPacket->Release();
00278 theApp.Message( MSG_DEBUG, _T("CDatagrams output frames really exhausted.") );
00279 return FALSE;
00280 }
00281
00282 CDatagramOut* pDG = m_pOutputFree;
00283 m_pOutputFree = m_pOutputFree->m_pNextHash;
00284
00285 if ( m_nInFrags < 1 ) bAck = FALSE;
00286
00287 pDG->Create( pHost, (CG2Packet*)pPacket, m_nSequence++, m_pBufferFree, bAck );
00288
00289 m_pBufferFree = m_pBufferFree->m_pNext;
00290 m_nBufferFree--;
00291
00292 pDG->m_pToken = pToken;
00293 pDG->m_pNextTime = NULL;
00294 pDG->m_pPrevTime = m_pOutputFirst;
00295
00296 if ( m_pOutputFirst )
00297 m_pOutputFirst->m_pNextTime = pDG;
00298 else
00299 m_pOutputLast = pDG;
00300
00301 m_pOutputFirst = pDG;
00302
00303 BYTE nHash = pHost->sin_addr.S_un.S_un_b.s_b1
00304 + pHost->sin_addr.S_un.S_un_b.s_b2
00305 + pHost->sin_addr.S_un.S_un_b.s_b3
00306 + pHost->sin_addr.S_un.S_un_b.s_b4
00307 + pHost->sin_port
00308 + pDG->m_nSequence;
00309
00310 CDatagramOut** pHash = m_pOutputHash + ( nHash & HASH_MASK );
00311
00312 if ( *pHash ) (*pHash)->m_pPrevHash = &pDG->m_pNextHash;
00313 pDG->m_pNextHash = *pHash;
00314 pDG->m_pPrevHash = pHash;
00315 *pHash = pDG;
00316
00317 m_nOutPackets++;
00318
00319 pPacket->SmartDump( NULL, &pHost->sin_addr, TRUE );
00320
00321 #ifdef DEBUG_UDP
00322 pPacket->Debug( _T("UDP Out") );
00323 theApp.Message( MSG_DEBUG, _T("UDP: Queued (#%i) x%i for %s:%lu"),
00324 pDG->m_nSequence, pDG->m_nCount,
00325 (LPCTSTR)CString( inet_ntoa( pDG->m_pHost.sin_addr ) ),
00326 htons( pDG->m_pHost.sin_port ) );
00327 #endif
00328
00329 if ( bRelease ) pPacket->Release();
00330
00331 TryWrite();
00332
00333 return TRUE;
00334 }
00335
00337
00338
00339 void CDatagrams::PurgeToken(LPVOID pToken)
00340 {
00341 CSingleLock pLock( &Network.m_pSection );
00342 if ( ! pLock.Lock( 100 ) ) return;
00343
00344 int nCount = 0;
00345
00346 for ( CDatagramOut* pDG = m_pOutputLast ; pDG ; )
00347 {
00348 CDatagramOut* pNext = pDG->m_pNextTime;
00349
00350 if ( pDG->m_pToken == pToken )
00351 {
00352 Remove( pDG );
00353 nCount++;
00354 }
00355
00356 pDG = pNext;
00357 }
00358
00359 if ( nCount ) theApp.Message( MSG_DEBUG, _T("CDatagrams::PurgeToken() = %i"), nCount );
00360 }
00361
00363
00364
00365 void CDatagrams::OnRun()
00366 {
00367 if ( m_hSocket == INVALID_SOCKET ) return;
00368
00369 TryWrite();
00370 ManageOutput();
00371
00372 do
00373 {
00374 ManagePartials();
00375 }
00376 while ( TryRead() );
00377
00378 Measure();
00379 }
00380
00382
00383
00384 void CDatagrams::Measure()
00385 {
00386 DWORD tCutoff = GetTickCount() - METER_PERIOD;
00387 DWORD* pInHistory = m_mInput.pHistory;
00388 DWORD* pInTime = m_mInput.pTimes;
00389 DWORD* pOutHistory = m_mOutput.pHistory;
00390 DWORD* pOutTime = m_mOutput.pTimes;
00391 DWORD nInput = 0;
00392 DWORD nOutput = 0;
00393
00394 for ( int tNow = METER_LENGTH ; tNow ; tNow-- )
00395 {
00396 if ( *pInTime >= tCutoff ) nInput += *pInHistory;
00397 if ( *pOutTime >= tCutoff ) nOutput += *pOutHistory;
00398 pInHistory++, pInTime++;
00399 pOutHistory++, pOutTime++;
00400 }
00401
00402 m_nInBandwidth = m_mInput.nMeasure = nInput * 1000 / METER_PERIOD;
00403 m_nOutBandwidth = m_mOutput.nMeasure = nOutput * 1000 / METER_PERIOD;
00404 }
00405
00407
00408
00409 BOOL CDatagrams::TryWrite()
00410 {
00411 DWORD tNow = GetTickCount();
00412 DWORD nLimit = 0xFFFFFFFF;
00413 DWORD nTotal = 0;
00414
00415 if ( Settings.Live.BandwidthScale <= 100 )
00416 {
00417 DWORD tCutoff = tNow - METER_SECOND;
00418 DWORD* pHistory = m_mOutput.pHistory;
00419 DWORD* pTime = m_mOutput.pTimes;
00420 DWORD nUsed = 0;
00421
00422 for ( int nSeek = METER_LENGTH ; nSeek ; nSeek--, pHistory++, pTime++ )
00423 {
00424 if ( *pTime >= tCutoff ) nUsed += *pHistory;
00425 }
00426
00427 nLimit = Settings.Connection.OutSpeed * 128;
00428 if ( Settings.Bandwidth.UdpOut != 0 ) nLimit = Settings.Bandwidth.UdpOut;
00429
00430 if ( Settings.Live.BandwidthScale < 100 )
00431 {
00432 nLimit = nLimit * Settings.Live.BandwidthScale / 100;
00433 }
00434
00435 nLimit = ( nUsed >= nLimit ) ? 0 : ( nLimit - nUsed );
00436 }
00437
00438 DWORD nLastHost = 0;
00439
00440 while ( nLimit > 0 )
00441 {
00442 CDatagramOut* pDG = m_pOutputFirst;
00443 for ( ; pDG ; pDG = pDG->m_pPrevTime )
00444 {
00445 BYTE* pPacket;
00446 DWORD nPacket;
00447
00448 if ( nLastHost == pDG->m_pHost.sin_addr.S_un.S_addr )
00449 {
00450
00451 }
00452 else if ( pDG->GetPacket( tNow, &pPacket, &nPacket, m_nInFrags > 0 ) )
00453 {
00454 sendto( m_hSocket, (LPCSTR)pPacket, nPacket, 0,
00455 (SOCKADDR*)&pDG->m_pHost, sizeof(SOCKADDR_IN) );
00456
00457 nLastHost = pDG->m_pHost.sin_addr.S_un.S_addr;
00458
00459 if ( nLimit >= nPacket )
00460 nLimit -= nPacket;
00461 else
00462 nLimit = 0;
00463
00464 m_tLastWrite = GetTickCount();
00465 nTotal += nPacket;
00466 m_nOutFrags++;
00467
00468 #ifdef DEBUG_UDP
00469 SGP_HEADER* pTemp = (SGP_HEADER*)pPacket;
00470 theApp.Message( MSG_DEBUG, _T("UDP: Sending (#%i) %i of %i to %s:%lu"),
00471 pDG->m_nSequence, pTemp->nPart, pTemp->nCount,
00472 (LPCTSTR)CString( inet_ntoa( pDG->m_pHost.sin_addr ) 0,
00473 htons( pDG->m_pHost.sin_port ) );
00474 #endif
00475
00476 break;
00477 }
00478 }
00479
00480 if ( pDG == NULL ) break;
00481 }
00482
00483 if ( m_mOutput.pHistory && nTotal )
00484 {
00485 if ( tNow - m_mOutput.tLastSlot < METER_MINIMUM )
00486 {
00487 m_mOutput.pHistory[ m_mOutput.nPosition ] += nTotal;
00488 }
00489 else
00490 {
00491 m_mOutput.nPosition = ( m_mOutput.nPosition + 1 ) % METER_LENGTH;
00492 m_mOutput.pTimes[ m_mOutput.nPosition ] = tNow;
00493 m_mOutput.pHistory[ m_mOutput.nPosition ] = nTotal;
00494 m_mOutput.tLastSlot = tNow;
00495 }
00496 }
00497
00498 m_mOutput.nTotal += nTotal;
00499 Statistics.Current.Bandwidth.Outgoing += nTotal;
00500
00501 return TRUE;
00502 }
00503
00505
00506
00507 void CDatagrams::ManageOutput()
00508 {
00509 DWORD tNow = GetTickCount();
00510
00511 for ( CDatagramOut* pDG = m_pOutputLast ; pDG ; )
00512 {
00513 CDatagramOut* pNext = pDG->m_pNextTime;
00514
00515 if ( tNow - pDG->m_tSent > Settings.Gnutella2.UdpOutExpire )
00516 {
00517 Remove( pDG );
00518 }
00519
00520 pDG = pNext;
00521 }
00522 }
00523
00525
00526
00527 void CDatagrams::Remove(CDatagramOut* pDG)
00528 {
00529 if ( pDG->m_pBuffer )
00530 {
00531 pDG->m_pBuffer->m_pNext = m_pBufferFree;
00532 m_pBufferFree = pDG->m_pBuffer;
00533 m_pBufferFree->Clear();
00534 pDG->m_pBuffer = NULL;
00535 m_nBufferFree++;
00536 }
00537
00538 if ( pDG->m_pNextHash ) pDG->m_pNextHash->m_pPrevHash = pDG->m_pPrevHash;
00539 *(pDG->m_pPrevHash) = pDG->m_pNextHash;
00540
00541 if ( pDG->m_pNextTime )
00542 pDG->m_pNextTime->m_pPrevTime = pDG->m_pPrevTime;
00543 else
00544 m_pOutputFirst = pDG->m_pPrevTime;
00545
00546 if ( pDG->m_pPrevTime )
00547 pDG->m_pPrevTime->m_pNextTime = pDG->m_pNextTime;
00548 else
00549 m_pOutputLast = pDG->m_pNextTime;
00550
00551 pDG->m_pNextHash = m_pOutputFree;
00552 m_pOutputFree = pDG;
00553 }
00554
00556
00557
00558 #define TEMP_BUFFER 4096
00559
00560 BOOL CDatagrams::TryRead()
00561 {
00562 static BYTE pBuffer[ TEMP_BUFFER ];
00563 int nLength, nFromLen;
00564 SOCKADDR_IN pFrom;
00565
00566 nFromLen = sizeof(pFrom);
00567 nLength = recvfrom( m_hSocket, (LPSTR)pBuffer, TEMP_BUFFER, 0,
00568 (SOCKADDR*)&pFrom, &nFromLen );
00569
00570 if ( nLength < 1 ) return FALSE;
00571
00572 if ( m_mInput.pHistory && nLength > 0 )
00573 {
00574 DWORD tNow = GetTickCount();
00575
00576 if ( tNow - m_mInput.tLastSlot < METER_MINIMUM )
00577 {
00578 m_mInput.pHistory[ m_mInput.nPosition ] += nLength;
00579 }
00580 else
00581 {
00582 m_mInput.nPosition = ( m_mInput.nPosition + 1 ) % METER_LENGTH;
00583 m_mInput.pTimes[ m_mInput.nPosition ] = tNow;
00584 m_mInput.pHistory[ m_mInput.nPosition ] = nLength;
00585 m_mInput.tLastSlot = tNow;
00586 }
00587 }
00588
00589 m_mInput.nTotal += nLength;
00590 Statistics.Current.Bandwidth.Incoming += nLength;
00591
00592 if ( Security.IsAccepted( &pFrom.sin_addr ) )
00593 {
00594 OnDatagram( &pFrom, pBuffer, nLength );
00595 }
00596
00597 return TRUE;
00598 }
00599
00601
00602
00603 BOOL CDatagrams::OnDatagram(SOCKADDR_IN* pHost, BYTE* pBuffer, DWORD nLength)
00604 {
00605 ED2K_UDP_HEADER* pMULE = (ED2K_UDP_HEADER*)pBuffer;
00606
00607 if ( nLength > sizeof(*pMULE) && (
00608 pMULE->nProtocol == ED2K_PROTOCOL_EDONKEY ||
00609 pMULE->nProtocol == ED2K_PROTOCOL_EMULE ||
00610 pMULE->nProtocol == ED2K_PROTOCOL_PACKED ) )
00611 {
00612 CEDPacket* pPacket = CEDPacket::New( pMULE, nLength );
00613
00614 if ( ! pPacket->InflateOrRelease( ED2K_PROTOCOL_EMULE ) )
00615 {
00616 pPacket->SmartDump( NULL, &pHost->sin_addr, FALSE );
00617 EDClients.OnUDP( pHost, pPacket );
00618 pPacket->Release();
00619 }
00620
00621 return TRUE;
00622 }
00623
00624 SGP_HEADER* pSGP = (SGP_HEADER*)pBuffer;
00625
00626 if ( nLength >= sizeof(*pSGP) && strncmp( pSGP->szTag, SGP_TAG_2, 3 ) == 0 )
00627 {
00628 if ( pSGP->nPart == 0 ) return FALSE;
00629 if ( pSGP->nCount && pSGP->nPart > pSGP->nCount ) return FALSE;
00630
00631 nLength -= sizeof(*pSGP);
00632
00633 if ( pSGP->nCount )
00634 {
00635 OnReceiveSGP( pHost, pSGP, nLength );
00636 }
00637 else
00638 {
00639 OnAcknowledgeSGP( pHost, pSGP, nLength );
00640 }
00641
00642 return TRUE;
00643 }
00644
00645 return FALSE;
00646 }
00647
00649
00650
00651 BOOL CDatagrams::OnReceiveSGP(SOCKADDR_IN* pHost, SGP_HEADER* pHeader, DWORD nLength)
00652 {
00653 #ifdef DEBUG_UDP
00654 theApp.Message( MSG_DEBUG, _T("UDP: Received (#%i) %i of %i from %s"),
00655 pHeader->nSequence, pHeader->nPart, pHeader->nCount,
00656 (LPCTSTR)CString( inet_ntoa( pHost->sin_addr ) ) );
00657 #endif
00658
00659 m_nInFrags++;
00660
00661 if ( pHeader->nFlags & SGP_ACKNOWLEDGE )
00662 {
00663 SGP_HEADER pAck;
00664
00665 strncpy( pAck.szTag, SGP_TAG_2, 3 );
00666 pAck.nFlags = 0;
00667 pAck.nSequence = pHeader->nSequence;
00668 pAck.nPart = pHeader->nPart;
00669 pAck.nCount = 0;
00670
00671 sendto( m_hSocket, (LPCSTR)&pAck, sizeof(pAck), 0,
00672 (SOCKADDR*)pHost, sizeof(SOCKADDR_IN) );
00673 }
00674
00675 BYTE nHash = pHost->sin_addr.S_un.S_un_b.s_b1
00676 + pHost->sin_addr.S_un.S_un_b.s_b2
00677 + pHost->sin_addr.S_un.S_un_b.s_b3
00678 + pHost->sin_addr.S_un.S_un_b.s_b4
00679 + pHost->sin_port
00680 + pHeader->nSequence;
00681
00682 CDatagramIn** pHash = m_pInputHash + ( nHash & HASH_MASK );
00683
00684 CDatagramIn* pDG = *pHash;
00685 for ( ; pDG ; pDG = pDG->m_pNextHash )
00686 {
00687 if ( pDG->m_pHost.sin_addr.S_un.S_addr == pHost->sin_addr.S_un.S_addr &&
00688 pDG->m_pHost.sin_port == pHost->sin_port &&
00689 pDG->m_nSequence == pHeader->nSequence &&
00690 pDG->m_nCount == pHeader->nCount )
00691 {
00692 if ( pDG->Add( pHeader->nPart, &pHeader[1], nLength ) )
00693 {
00694 if ( CG2Packet* pPacket = pDG->ToG2Packet() )
00695 {
00696 try
00697 {
00698 OnPacket( pHost, pPacket );
00699 }
00700 catch ( CException* pException )
00701 {
00702 pException->Delete();
00703 }
00704
00705 pPacket->Release();
00706 }
00707
00708
00709
00710 }
00711
00712 return TRUE;
00713 }
00714 }
00715
00716 while ( m_pInputFree == NULL || m_nBufferFree < pHeader->nCount )
00717 {
00718 if ( m_pInputLast == NULL ) return FALSE;
00719 Remove( m_pInputLast );
00720 }
00721
00722 if ( m_nBufferFree < pHeader->nCount ) return FALSE;
00723
00724 pDG = m_pInputFree;
00725
00726 pDG->Create( pHost, pHeader->nFlags, pHeader->nSequence, pHeader->nCount );
00727
00728 for ( WORD nPart = 0 ; nPart < pDG->m_nCount ; nPart++ )
00729 {
00730 ASSERT( pDG->m_pBuffer[ nPart ] == NULL );
00731 pDG->m_pBuffer[ nPart ] = m_pBufferFree;
00732 m_pBufferFree = m_pBufferFree->m_pNext;
00733 m_nBufferFree--;
00734 }
00735
00736 if ( pDG->Add( pHeader->nPart, &pHeader[1], nLength ) )
00737 {
00738 if ( CG2Packet* pPacket = pDG->ToG2Packet() )
00739 {
00740 try
00741 {
00742 OnPacket( pHost, pPacket );
00743 }
00744 catch ( CException* pException )
00745 {
00746 pException->Delete();
00747 }
00748 pPacket->Release();
00749 }
00750
00751
00752
00753 }
00754
00755
00756
00757 pDG->m_pNextTime = NULL;
00758 pDG->m_pPrevTime = m_pInputFirst;
00759
00760 if ( m_pInputFirst )
00761 m_pInputFirst->m_pNextTime = pDG;
00762 else
00763 m_pInputLast = pDG;
00764
00765 m_pInputFirst = pDG;
00766 m_pInputFree = pDG->m_pNextHash;
00767
00768 if ( *pHash ) (*pHash)->m_pPrevHash = &pDG->m_pNextHash;
00769 pDG->m_pNextHash = *pHash;
00770 pDG->m_pPrevHash = pHash;
00771 *pHash = pDG;
00772
00773 return TRUE;
00774 }
00775
00777
00778
00779 BOOL CDatagrams::OnAcknowledgeSGP(SOCKADDR_IN* pHost, SGP_HEADER* pHeader, DWORD nLength)
00780 {
00781 #ifdef DEBUG_UDP
00782 theApp.Message( MSG_DEBUG, _T("UDP: Received ack (#%i) %i from %s"),
00783 pHeader->nSequence, pHeader->nPart, (LPCTSTR)CString( inet_ntoa( pHost->sin_addr ) ) );
00784 #endif
00785
00786 BYTE nHash = pHost->sin_addr.S_un.S_un_b.s_b1
00787 + pHost->sin_addr.S_un.S_un_b.s_b2
00788 + pHost->sin_addr.S_un.S_un_b.s_b3
00789 + pHost->sin_addr.S_un.S_un_b.s_b4
00790 + pHost->sin_port
00791 + pHeader->nSequence;
00792
00793 CDatagramOut** pHash = m_pOutputHash + ( nHash & HASH_MASK );
00794
00795 for ( CDatagramOut* pDG = *pHash ; pDG ; pDG = pDG->m_pNextHash )
00796 {
00797 if ( pDG->m_pHost.sin_addr.S_un.S_addr == pHost->sin_addr.S_un.S_addr &&
00798 pDG->m_pHost.sin_port == pHost->sin_port &&
00799 pDG->m_nSequence == pHeader->nSequence )
00800 {
00801 if ( pDG->Acknowledge( pHeader->nPart ) ) Remove( pDG );
00802 return TRUE;
00803 }
00804 }
00805
00806 return FALSE;
00807 }
00808
00810
00811
00812 void CDatagrams::ManagePartials()
00813 {
00814 DWORD tNow = GetTickCount();
00815
00816 for ( CDatagramIn* pDG = m_pInputLast ; pDG ; )
00817 {
00818 CDatagramIn* pNext = pDG->m_pNextTime;
00819
00820 if ( tNow - pDG->m_tStarted > Settings.Gnutella2.UdpInExpire )
00821 {
00822 Remove( pDG );
00823 }
00824
00825 pDG = pNext;
00826 }
00827 }
00828
00830
00831
00832 void CDatagrams::Remove(CDatagramIn* pDG, BOOL bReclaimOnly)
00833 {
00834 for ( int nPart = 0 ; nPart < pDG->m_nCount ; nPart++ )
00835 {
00836 if ( pDG->m_pBuffer[ nPart ] )
00837 {
00838 pDG->m_pBuffer[ nPart ]->m_pNext = m_pBufferFree;
00839 m_pBufferFree = pDG->m_pBuffer[ nPart ];
00840 m_pBufferFree->Clear();
00841 pDG->m_pBuffer[ nPart ] = NULL;
00842 m_nBufferFree++;
00843 }
00844 }
00845
00846 if ( bReclaimOnly ) return;
00847
00848 if ( pDG->m_pNextHash ) pDG->m_pNextHash->m_pPrevHash = pDG->m_pPrevHash;
00849 *(pDG->m_pPrevHash) = pDG->m_pNextHash;
00850
00851 if ( pDG->m_pNextTime )
00852 pDG->m_pNextTime->m_pPrevTime = pDG->m_pPrevTime;
00853 else
00854 m_pInputFirst = pDG->m_pPrevTime;
00855
00856 if ( pDG->m_pPrevTime )
00857 pDG->m_pPrevTime->m_pNextTime = pDG->m_pNextTime;
00858 else
00859 m_pInputLast = pDG->m_pNextTime;
00860
00861 pDG->m_pNextHash = m_pInputFree;
00862 m_pInputFree = pDG;
00863 }
00864
00866
00867
00868 BOOL CDatagrams::OnPacket(SOCKADDR_IN* pHost, CG2Packet* pPacket)
00869 {
00870 pPacket->SmartDump( NULL, &pHost->sin_addr, FALSE );
00871
00872 m_nInPackets++;
00873
00874 if ( Network.RoutePacket( pPacket ) ) return TRUE;
00875
00876 if ( pPacket->IsType( G2_PACKET_QUERY ) )
00877 {
00878 return OnQuery( pHost, pPacket );
00879 }
00880 else if ( pPacket->IsType( G2_PACKET_QUERY_KEY_REQ ) )
00881 {
00882 return OnQueryKeyRequest( pHost, pPacket );
00883 }
00884 else if ( pPacket->IsType( G2_PACKET_HIT ) )
00885 {
00886 return OnHit( pHost, pPacket );
00887 }
00888 else if ( pPacket->IsType( G2_PACKET_HIT_WRAP ) )
00889 {
00890 return OnHit( pHost, pPacket );
00891 }
00892 else if ( pPacket->IsType( G2_PACKET_QUERY_ACK ) )
00893 {
00894 return OnQueryAck( pHost, pPacket );
00895 }
00896 else if ( pPacket->IsType( G2_PACKET_QUERY_KEY_ANS ) )
00897 {
00898 return OnQueryKeyAnswer( pHost, pPacket );
00899 }
00900 else if ( pPacket->IsType( G2_PACKET_PING ) )
00901 {
00902 return OnPing( pHost, pPacket );
00903 }
00904 else if ( pPacket->IsType( G2_PACKET_PONG ) )
00905 {
00906 return OnPong( pHost, pPacket );
00907 }
00908 else if ( pPacket->IsType( G2_PACKET_PUSH ) )
00909 {
00910 return OnPush( pHost, pPacket );
00911 }
00912 else if ( pPacket->IsType( G2_PACKET_CRAWL_REQ ) )
00913 {
00914 return OnCrawlRequest( pHost, pPacket );
00915 }
00916 else if ( pPacket->IsType( G2_PACKET_CRAWL_ANS ) )
00917 {
00918 return OnCrawlAnswer( pHost, pPacket );
00919 }
00920
00921 return FALSE;
00922 }
00923
00925
00926
00927 BOOL CDatagrams::OnPing(SOCKADDR_IN* pHost, CG2Packet* pPacket)
00928 {
00929 Send( pHost, CG2Packet::New( G2_PACKET_PONG ) );
00930 return TRUE;
00931 }
00932
00934
00935
00936 BOOL CDatagrams::OnPong(SOCKADDR_IN* pHost, CG2Packet* pPacket)
00937 {
00938 if ( ! pPacket->m_bCompound ) return TRUE;
00939
00940 BOOL bRelayed = FALSE;
00941 CHAR szType[9];
00942 DWORD nLength;
00943
00944 while ( pPacket->ReadPacket( szType, nLength ) )
00945 {
00946 DWORD nOffset = pPacket->m_nPosition + nLength;
00947 if ( strcmp( szType, "RELAY" ) == 0 ) bRelayed = TRUE;
00948 pPacket->m_nPosition = nOffset;
00949 }
00950
00951 if ( ! bRelayed ) return TRUE;
00952
00953 if ( ! Network.IsConnectedTo( &pHost->sin_addr ) ) m_bStable = TRUE;
00954
00955
00956
00957
00958
00959
00960 return TRUE;
00961 }
00962
00964
00965
00966 BOOL CDatagrams::OnQuery(SOCKADDR_IN* pHost, CG2Packet* pPacket)
00967 {
00968 CQuerySearch* pSearch = CQuerySearch::FromPacket( pPacket, pHost );
00969
00970 if ( pSearch == NULL || ! pSearch->m_bUDP )
00971 {
00972 if ( pSearch ) delete pSearch;
00973 theApp.Message( MSG_ERROR, IDS_PROTOCOL_BAD_QUERY,
00974 (LPCTSTR)CString( inet_ntoa( pHost->sin_addr ) ) );
00975 Statistics.Current.Gnutella2.Dropped++;
00976 return FALSE;
00977 }
00978
00979 if ( Security.IsDenied( &pSearch->m_pEndpoint.sin_addr ) )
00980 {
00981 delete pSearch;
00982 Statistics.Current.Gnutella2.Dropped++;
00983 return FALSE;
00984 }
00985
00986 if ( ! Network.QueryKeys->Check( pSearch->m_pEndpoint.sin_addr.S_un.S_addr, pSearch->m_nKey ) )
00987 {
00988 DWORD nKey = Network.QueryKeys->Create( pSearch->m_pEndpoint.sin_addr.S_un.S_addr );
00989
00990 CString strNode = inet_ntoa( pSearch->m_pEndpoint.sin_addr );
00991 theApp.Message( MSG_DEBUG, _T("Issuing correction for node %s's query key for %s"),
00992 (LPCTSTR)CString( inet_ntoa( pHost->sin_addr ) ), (LPCTSTR)strNode );
00993
00994 CG2Packet* pAnswer = CG2Packet::New( G2_PACKET_QUERY_KEY_ANS, TRUE );
00995 pAnswer->WritePacket( "QK", 4 );
00996 pAnswer->WriteLongBE( nKey );
00997
00998 if ( pHost->sin_addr.S_un.S_addr != pSearch->m_pEndpoint.sin_addr.S_un.S_addr )
00999 {
01000 pAnswer->WritePacket( "SNA", 4 );
01001 pAnswer->WriteLongLE( pHost->sin_addr.S_un.S_addr );
01002 }
01003
01004 Send( &pSearch->m_pEndpoint, pAnswer, TRUE );
01005
01006 delete pSearch;
01007 return TRUE;
01008 }
01009
01010 if ( ! Network.QueryRoute->Add( &pSearch->m_pGUID, &pSearch->m_pEndpoint ) )
01011 {
01012 CG2Packet* pAnswer = CG2Packet::New( G2_PACKET_QUERY_ACK, TRUE );
01013 pAnswer->WritePacket( "D", 8 );
01014 pAnswer->WriteLongLE( Network.m_pHost.sin_addr.S_un.S_addr );
01015 pAnswer->WriteShortBE( htons( Network.m_pHost.sin_port ) );
01016 pAnswer->WriteShortBE( 0 );
01017 pAnswer->WriteByte( 0 );
01018 pAnswer->Write( &pSearch->m_pGUID, sizeof(GGUID) );
01019 Send( &pSearch->m_pEndpoint, pAnswer, TRUE );
01020
01021 delete pSearch;
01022 Statistics.Current.Gnutella2.Dropped++;
01023 return TRUE;
01024 }
01025
01026 Neighbours.RouteQuery( pSearch, pPacket, NULL, TRUE );
01027
01028 Network.OnQuerySearch( pSearch );
01029
01030 CLocalSearch pLocal( pSearch, &pSearch->m_pEndpoint );
01031 pLocal.Execute();
01032
01033 Send( &pSearch->m_pEndpoint, Neighbours.CreateQueryWeb( &pSearch->m_pGUID ), TRUE );
01034
01035 delete pSearch;
01036
01037 return TRUE;
01038 }
01039
01041
01042
01043 BOOL CDatagrams::OnQueryAck(SOCKADDR_IN* pHost, CG2Packet* pPacket)
01044 {
01045 CHostCacheHost* pCache = HostCache.Gnutella2.Add( &pHost->sin_addr, htons( pHost->sin_port ) );
01046 if ( pCache ) pCache->m_tAck = pCache->m_nFailures = 0;
01047
01048 GGUID pGUID;
01049
01050 if ( SearchManager.OnQueryAck( pPacket, pHost, &pGUID ) )
01051 {
01052 CNeighbour* pNeighbour = NULL;
01053 SOCKADDR_IN pEndpoint;
01054
01055 if ( Network.QueryRoute->Lookup( &pGUID, &pNeighbour, &pEndpoint ) )
01056 {
01057
01058
01059 if ( pNeighbour != NULL && pNeighbour->m_nNodeType == ntLeaf )
01060 {
01061 pNeighbour->Send( pPacket, FALSE, FALSE );
01062 }
01063 else
01064 {
01065
01066 }
01067 }
01068 }
01069
01070 return TRUE;
01071 }
01072
01074
01075
01076 BOOL CDatagrams::OnHit(SOCKADDR_IN* pHost, CG2Packet* pPacket)
01077 {
01078 int nHops = 0;
01079 CQueryHit* pHits = CQueryHit::FromPacket( pPacket, &nHops );
01080
01081 if ( pHits == NULL )
01082 {
01083 pPacket->Debug( _T("BadHit") );
01084 theApp.Message( MSG_ERROR, IDS_PROTOCOL_BAD_HIT,
01085 (LPCTSTR)CString( inet_ntoa( pHost->sin_addr ) ) );
01086 Statistics.Current.Gnutella2.Dropped++;
01087 return FALSE;
01088 }
01089
01090 if ( Security.IsDenied( &pHits->m_pAddress ) || nHops > (int)Settings.Gnutella1.MaximumTTL )
01091 {
01092 pHits->Delete();
01093 Statistics.Current.Gnutella2.Dropped++;
01094 return FALSE;
01095 }
01096
01097 Network.NodeRoute->Add( &pHits->m_pClientID, pHost );
01098
01099 if ( SearchManager.OnQueryHits( pHits ) )
01100 {
01101 Network.RouteHits( pHits, pPacket );
01102 }
01103
01104 Network.OnQueryHits( pHits );
01105
01106 return TRUE;
01107 }
01108
01110
01111
01112 BOOL CDatagrams::OnQueryKeyRequest(SOCKADDR_IN* pHost, CG2Packet* pPacket)
01113 {
01114 if ( ! Neighbours.IsG2Hub() ) return FALSE;
01115
01116 DWORD nRequestedAddress = pHost->sin_addr.S_un.S_addr;
01117 WORD nRequestedPort = ntohs( pHost->sin_port );
01118 DWORD nSendingAddress = pHost->sin_addr.S_un.S_addr;
01119
01120 if ( pPacket->m_bCompound )
01121 {
01122 CHAR szType[9];
01123 DWORD nLength;
01124
01125 while ( pPacket->ReadPacket( szType, nLength ) )
01126 {
01127 DWORD nOffset = pPacket->m_nPosition + nLength;
01128
01129 if ( strcmp( szType, "RNA" ) == 0 && nLength >= 6 )
01130 {
01131 nRequestedAddress = pPacket->ReadLongLE();
01132 nRequestedPort = pPacket->ReadShortBE();
01133 }
01134 else if ( strcmp( szType, "SNA" ) == 0 && nLength >= 4 )
01135 {
01136 nSendingAddress = pPacket->ReadLongLE();
01137 }
01138
01139 pPacket->m_nPosition = nOffset;
01140 }
01141 }
01142
01143 CString strNode = inet_ntoa( *(IN_ADDR*)&nRequestedAddress );
01144 theApp.Message( MSG_DEBUG, _T("Node %s asked for a query key for node %s:%i"),
01145 (LPCTSTR)CString( inet_ntoa( pHost->sin_addr ) ), (LPCTSTR)strNode, nRequestedPort );
01146
01147 if ( Network.IsFirewalledAddress( &nRequestedAddress, TRUE ) || 0 == nRequestedPort ) return TRUE;
01148
01149 DWORD nKey = Network.QueryKeys->Create( nRequestedAddress );
01150
01151 CG2Packet* pAnswer = CG2Packet::New( G2_PACKET_QUERY_KEY_ANS, TRUE );
01152
01153 pAnswer->WritePacket( "QK", 4 );
01154 pAnswer->WriteLongBE( nKey );
01155
01156 if ( nRequestedAddress != nSendingAddress )
01157 {
01158 pAnswer->WritePacket( "SNA", 4 );
01159 pAnswer->WriteLongLE( nSendingAddress );
01160 }
01161
01162 Send( (IN_ADDR*)&nRequestedAddress, nRequestedPort, pAnswer, TRUE );
01163
01164 return TRUE;
01165 }
01166
01168
01169
01170 BOOL CDatagrams::OnQueryKeyAnswer(SOCKADDR_IN* pHost, CG2Packet* pPacket)
01171 {
01172 if ( ! pPacket->m_bCompound ) return FALSE;
01173
01174 DWORD nKey = 0, nAddress = 0;
01175
01176 CHAR szType[9];
01177 DWORD nLength;
01178
01179 while ( pPacket->ReadPacket( szType, nLength ) )
01180 {
01181 DWORD nOffset = pPacket->m_nPosition + nLength;
01182
01183 if ( strcmp( szType, "QK" ) == 0 && nLength >= 4 )
01184 {
01185 nKey = pPacket->ReadLongBE();
01186 }
01187 else if ( strcmp( szType, "SNA" ) == 0 && nLength >= 4 )
01188 {
01189 nAddress = pPacket->ReadLongLE();
01190 }
01191
01192 pPacket->m_nPosition = nOffset;
01193 }
01194
01195 theApp.Message( MSG_DEBUG, _T("Got a query key for %s:%lu: 0x%x"),
01196 (LPCTSTR)CString( inet_ntoa( pHost->sin_addr ) ), htons( pHost->sin_port ), nKey );
01197
01198 CHostCacheHost* pCache = HostCache.Gnutella2.Add(
01199 &pHost->sin_addr, htons( pHost->sin_port ) );
01200
01201 if ( pCache != NULL ) pCache->SetKey( nKey );
01202
01203 if ( nAddress != 0 && nAddress != Network.m_pHost.sin_addr.S_un.S_addr )
01204 {
01205 if ( CNeighbour* pNeighbour = Neighbours.Get( (IN_ADDR*)&nAddress ) )
01206 {
01207 BYTE* pOut = pPacket->WriteGetPointer( 11, 0 );
01208
01209 *pOut++ = 0x50;
01210 *pOut++ = 6;
01211 *pOut++ = 'Q';
01212 *pOut++ = 'N';
01213 *pOut++ = 'A';
01214 *pOut++ = pHost->sin_addr.S_un.S_un_b.s_b1;
01215 *pOut++ = pHost->sin_addr.S_un.S_un_b.s_b2;
01216 *pOut++ = pHost->sin_addr.S_un.S_un_b.s_b3;
01217 *pOut++ = pHost->sin_addr.S_un.S_un_b.s_b4;
01218
01219 if ( pPacket->m_bBigEndian )
01220 {
01221 *pOut++ = (BYTE)( pHost->sin_port & 0xFF );
01222 *pOut++ = (BYTE)( pHost->sin_port >> 8 );
01223 }
01224 else
01225 {
01226 *pOut++ = (BYTE)( pHost->sin_port >> 8 );
01227 *pOut++ = (BYTE)( pHost->sin_port & 0xFF );
01228 }
01229
01230 pNeighbour->Send( pPacket, FALSE, FALSE );
01231 }
01232 }
01233
01234 return TRUE;
01235 }
01236
01238
01239
01240 BOOL CDatagrams::OnPush(SOCKADDR_IN* pHost, CG2Packet* pPacket)
01241 {
01242 DWORD nLength = pPacket->GetRemaining();
01243
01244 if ( ! pPacket->SkipCompound( nLength, 6 ) )
01245 {
01246 pPacket->Debug( _T("BadPush") );
01247 Statistics.Current.Gnutella2.Dropped++;
01248 return FALSE;
01249 }
01250
01251 DWORD nAddress = pPacket->ReadLongLE();
01252 WORD nPort = pPacket->ReadShortBE();
01253
01254 if ( Security.IsDenied( (IN_ADDR*)&nAddress ) ||
01255 Network.IsFirewalledAddress( &nAddress ) )
01256 {
01257 Statistics.Current.Gnutella2.Dropped++;
01258 return TRUE;
01259 }
01260
01261 Handshakes.PushTo( (IN_ADDR*)&nAddress, nPort );
01262
01263 return TRUE;
01264 }
01265
01267
01268
01269 BOOL CDatagrams::OnCrawlRequest(SOCKADDR_IN* pHost, CG2Packet* pPacket)
01270 {
01271 if ( ! pPacket->m_bCompound ) return FALSE;
01272
01273 BOOL bWantLeaves = FALSE;
01274 BOOL bWantNames = FALSE;
01275 BOOL bWantGPS = FALSE;
01276 BOOL bWantREXT = FALSE;
01277 BOOL bIsHub = ( ! Neighbours.IsG2Leaf() ) && ( Neighbours.IsG2Hub() || Neighbours.IsG2HubCapable() );
01278
01279 CHAR szType[9];
01280 DWORD nLength;
01281
01282 while ( pPacket->ReadPacket( szType, nLength ) )
01283 {
01284 DWORD nNext = pPacket->m_nPosition + nLength;
01285
01286 if ( strcmp( szType, "RLEAF" ) == 0 )
01287 {
01288 bWantLeaves = TRUE;
01289 }
01290 else if ( strcmp( szType, "RNAME" ) == 0 )
01291 {
01292 bWantNames = TRUE;
01293 }
01294 else if ( strcmp( szType, "RGPS" ) == 0 )
01295 {
01296 bWantGPS = TRUE;
01297 }
01298 else if ( strcmp( szType, "REXT" ) == 0 )
01299 {
01300 bWantREXT = TRUE;
01301 }
01302
01303 pPacket->m_nPosition = nNext;
01304 }
01305
01306 pPacket = CG2Packet::New( G2_PACKET_CRAWL_ANS, TRUE );
01307
01308 CString strNick;
01309 DWORD nGPS = 0;
01310 CString vendorCode;
01311 CString currentVersion;
01312
01313 if ( bWantNames ) strNick = MyProfile.GetNick().Left( 255 );
01314
01315 if ( bWantGPS ) nGPS = MyProfile.GetPackedGPS();
01316
01317 if ( bWantREXT )
01318 {
01319 vendorCode = VENDOR_CODE;
01320 currentVersion = CLIENT_NAME;
01321 currentVersion += " ";
01322 currentVersion += theApp.m_sVersion;
01323 }
01324
01325 pPacket->WritePacket(
01326 "SELF",
01327 16 + ( strNick.GetLength() ? pPacket->GetStringLen( strNick ) + 6 : 0 ) +
01328 ( nGPS ? 5 + 4 : 0 ) + (vendorCode.GetLength() ? pPacket->GetStringLen( vendorCode ) + 3 : 0 ) +
01329 (currentVersion.GetLength() ? pPacket->GetStringLen( currentVersion ) + 4 : 0 ) +
01330 (bIsHub ? 5 : 6),
01331 TRUE );
01332
01333 pPacket->WritePacket( "NA", 6 );
01334 pPacket->WriteLongLE( Network.m_pHost.sin_addr.S_un.S_addr );
01335 pPacket->WriteShortBE( htons( Network.m_pHost.sin_port ) );
01336
01337 pPacket->WritePacket( "HS", 2 );
01338 pPacket->WriteShortBE( Neighbours.GetCount( PROTOCOL_G2, -1, ntLeaf ) );
01339
01340 if ( strNick.GetLength() )
01341 {
01342 pPacket->WritePacket( "NAME", pPacket->GetStringLen( strNick) );
01343 pPacket->WriteString( strNick, FALSE );
01344 }
01345 if ( vendorCode.GetLength() )
01346 {
01347 pPacket->WritePacket( "V", pPacket->GetStringLen( vendorCode) );
01348 pPacket->WriteString( vendorCode, FALSE );
01349 }
01350 if ( currentVersion.GetLength() )
01351 {
01352 pPacket->WritePacket( "CV", pPacket->GetStringLen( currentVersion) );
01353 pPacket->WriteString( currentVersion, FALSE );
01354 }
01355
01356 if ( bIsHub )
01357 {
01358 pPacket->WritePacket( "HUB", 0 );
01359 }
01360 else
01361 {
01362 pPacket->WritePacket( "LEAF", 0 );
01363 }
01364
01365 if ( nGPS )
01366 {
01367 pPacket->WritePacket( "GPS", 4 );
01368 pPacket->WriteLongBE( nGPS );
01369 }
01370
01371 for ( POSITION pos = Neighbours.GetIterator() ; pos ; )
01372 {
01373 CNeighbour* pNeighbour = Neighbours.GetNext( pos );
01374 if ( pNeighbour->m_nState < nrsConnected ) continue;
01375
01376 int nExtraLen = 0;
01377 strNick.Empty();
01378 nGPS = 0;
01379
01380 if ( pNeighbour->m_nProtocol == PROTOCOL_G2 )
01381 {
01382 if ( CGProfile* pProfile = ((CG2Neighbour*)pNeighbour)->m_pProfile )
01383 {
01384 if ( bWantNames ) strNick = pProfile->GetNick().Left( 255 );
01385
01386 if ( bWantGPS ) nGPS = pProfile->GetPackedGPS();
01387
01388 if ( strNick.GetLength() ) nExtraLen += 6 + pPacket->GetStringLen( strNick );
01389 if ( nGPS ) nExtraLen += 9;
01390 }
01391 }
01392
01393 if ( pNeighbour->m_nProtocol == PROTOCOL_G2 &&
01394 pNeighbour->m_nNodeType != ntLeaf )
01395 {
01396 pPacket->WritePacket( "NH", 16 + nExtraLen, TRUE );
01397
01398 pPacket->WritePacket( "NA", 6 );
01399 pPacket->WriteLongLE( pNeighbour->m_pHost.sin_addr.S_un.S_addr );
01400 pPacket->WriteShortBE( htons( pNeighbour->m_pHost.sin_port ) );
01401
01402 pPacket->WritePacket( "HS", 2 );
01403 pPacket->WriteShortBE( (WORD)((CG2Neighbour*)pNeighbour)->m_nLeafCount );
01404 }
01405 else if ( pNeighbour->m_nNodeType == ntLeaf && bWantLeaves )
01406 {
01407 pPacket->WritePacket( "NL", 10 + nExtraLen, TRUE );
01408
01409 pPacket->WritePacket( "NA", 6 );
01410 pPacket->WriteLongLE( pNeighbour->m_pHost.sin_addr.S_un.S_addr );
01411 pPacket->WriteShortBE( htons( pNeighbour->m_pHost.sin_port ) );
01412 }
01413 else
01414 {
01415 nExtraLen = 0;
01416 }
01417
01418 if ( nExtraLen > 0 )
01419 {
01420 if ( strNick.GetLength() )
01421 {
01422 pPacket->WritePacket( "NAME", pPacket->GetStringLen( strNick ) );
01423 pPacket->WriteString( strNick, FALSE );
01424 }
01425
01426 if ( nGPS )
01427 {
01428 pPacket->WritePacket( "GPS", 4 );
01429 pPacket->WriteLongBE( nGPS );
01430 }
01431 }
01432 }
01433
01434 Send( pHost, pPacket );
01435
01436 return TRUE;
01437 }
01438
01439 BOOL CDatagrams::OnCrawlAnswer(SOCKADDR_IN* pHost, CG2Packet* pPacket)
01440 {
01441 CrawlSession.OnCrawl( pHost, pPacket );
01442 return TRUE;
01443 }