📄 datagrams.cpp
字号:
#ifdef DEBUG_UDP
SGP_HEADER* pTemp = (SGP_HEADER*)pPacket;
theApp.Message( MSG_DEBUG, _T("UDP: Sending (#%i) %i of %i to %s:%lu"),
pDG->m_nSequence, pTemp->nPart, pTemp->nCount,
(LPCTSTR)CString( inet_ntoa( pDG->m_pHost.sin_addr ) 0,
htons( pDG->m_pHost.sin_port ) );
#endif
break;
}
}
if ( pDG == NULL ) break;
}
if ( m_mOutput.pHistory && nTotal )
{
if ( tNow - m_mOutput.tLastSlot < METER_MINIMUM )
{
m_mOutput.pHistory[ m_mOutput.nPosition ] += nTotal;
}
else
{
m_mOutput.nPosition = ( m_mOutput.nPosition + 1 ) % METER_LENGTH;
m_mOutput.pTimes[ m_mOutput.nPosition ] = tNow;
m_mOutput.pHistory[ m_mOutput.nPosition ] = nTotal;
m_mOutput.tLastSlot = tNow;
}
}
m_mOutput.nTotal += nTotal;
Statistics.Current.Bandwidth.Outgoing += nTotal;
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CDatagrams manage output queue datagrams
void CDatagrams::ManageOutput()
{
DWORD tNow = GetTickCount();
for ( CDatagramOut* pDG = m_pOutputLast ; pDG ; )
{
CDatagramOut* pNext = pDG->m_pNextTime;
if ( tNow - pDG->m_tSent > Settings.Gnutella2.UdpOutExpire )
{
Remove( pDG );
}
pDG = pNext;
}
}
//////////////////////////////////////////////////////////////////////
// CDatagrams remove output datagrams
void CDatagrams::Remove(CDatagramOut* pDG)
{
if ( pDG->m_pBuffer )
{
pDG->m_pBuffer->m_pNext = m_pBufferFree;
m_pBufferFree = pDG->m_pBuffer;
m_pBufferFree->Clear();
pDG->m_pBuffer = NULL;
m_nBufferFree++;
}
if ( pDG->m_pNextHash ) pDG->m_pNextHash->m_pPrevHash = pDG->m_pPrevHash;
*(pDG->m_pPrevHash) = pDG->m_pNextHash;
if ( pDG->m_pNextTime )
pDG->m_pNextTime->m_pPrevTime = pDG->m_pPrevTime;
else
m_pOutputFirst = pDG->m_pPrevTime;
if ( pDG->m_pPrevTime )
pDG->m_pPrevTime->m_pNextTime = pDG->m_pNextTime;
else
m_pOutputLast = pDG->m_pNextTime;
pDG->m_pNextHash = m_pOutputFree;
m_pOutputFree = pDG;
}
//////////////////////////////////////////////////////////////////////
// CDatagrams read datagram
#define TEMP_BUFFER 4096
BOOL CDatagrams::TryRead()
{
static BYTE pBuffer[ TEMP_BUFFER ];
int nLength, nFromLen;
SOCKADDR_IN pFrom;
nFromLen = sizeof(pFrom);
nLength = recvfrom( m_hSocket, (LPSTR)pBuffer, TEMP_BUFFER, 0,
(SOCKADDR*)&pFrom, &nFromLen );
if ( nLength < 1 ) return FALSE;
if ( m_mInput.pHistory && nLength > 0 )
{
DWORD tNow = GetTickCount();
if ( tNow - m_mInput.tLastSlot < METER_MINIMUM )
{
m_mInput.pHistory[ m_mInput.nPosition ] += nLength;
}
else
{
m_mInput.nPosition = ( m_mInput.nPosition + 1 ) % METER_LENGTH;
m_mInput.pTimes[ m_mInput.nPosition ] = tNow;
m_mInput.pHistory[ m_mInput.nPosition ] = nLength;
m_mInput.tLastSlot = tNow;
}
}
m_mInput.nTotal += nLength;
Statistics.Current.Bandwidth.Incoming += nLength;
if ( Security.IsAccepted( &pFrom.sin_addr ) )
{
OnDatagram( &pFrom, pBuffer, nLength );
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CDatagrams datagram handler
BOOL CDatagrams::OnDatagram(SOCKADDR_IN* pHost, BYTE* pBuffer, DWORD nLength)
{
ED2K_UDP_HEADER* pMULE = (ED2K_UDP_HEADER*)pBuffer;
if ( nLength > sizeof(*pMULE) && (
pMULE->nProtocol == ED2K_PROTOCOL_EDONKEY ||
pMULE->nProtocol == ED2K_PROTOCOL_EMULE ||
pMULE->nProtocol == ED2K_PROTOCOL_PACKED ) )
{
CEDPacket* pPacket = CEDPacket::New( pMULE, nLength );
if ( ! pPacket->InflateOrRelease( ED2K_PROTOCOL_EMULE ) )
{
pPacket->SmartDump( NULL, &pHost->sin_addr, FALSE );
EDClients.OnUDP( pHost, pPacket );
pPacket->Release();
}
return TRUE;
}
SGP_HEADER* pSGP = (SGP_HEADER*)pBuffer;
if ( nLength >= sizeof(*pSGP) && strncmp( pSGP->szTag, SGP_TAG_2, 3 ) == 0 )
{
if ( pSGP->nPart == 0 ) return FALSE;
if ( pSGP->nCount && pSGP->nPart > pSGP->nCount ) return FALSE;
nLength -= sizeof(*pSGP);
if ( pSGP->nCount )
{
OnReceiveSGP( pHost, pSGP, nLength );
}
else
{
OnAcknowledgeSGP( pHost, pSGP, nLength );
}
return TRUE;
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////
// CDatagrams SGP receive handler
BOOL CDatagrams::OnReceiveSGP(SOCKADDR_IN* pHost, SGP_HEADER* pHeader, DWORD nLength)
{
#ifdef DEBUG_UDP
theApp.Message( MSG_DEBUG, _T("UDP: Received (#%i) %i of %i from %s"),
pHeader->nSequence, pHeader->nPart, pHeader->nCount,
(LPCTSTR)CString( inet_ntoa( pHost->sin_addr ) ) );
#endif
m_nInFrags++;
if ( pHeader->nFlags & SGP_ACKNOWLEDGE )
{
SGP_HEADER pAck;
strncpy( pAck.szTag, SGP_TAG_2, 3 );
pAck.nFlags = 0;
pAck.nSequence = pHeader->nSequence;
pAck.nPart = pHeader->nPart;
pAck.nCount = 0;
sendto( m_hSocket, (LPCSTR)&pAck, sizeof(pAck), 0,
(SOCKADDR*)pHost, sizeof(SOCKADDR_IN) );
}
BYTE nHash = pHost->sin_addr.S_un.S_un_b.s_b1
+ pHost->sin_addr.S_un.S_un_b.s_b2
+ pHost->sin_addr.S_un.S_un_b.s_b3
+ pHost->sin_addr.S_un.S_un_b.s_b4
+ pHost->sin_port
+ pHeader->nSequence;
CDatagramIn** pHash = m_pInputHash + ( nHash & HASH_MASK );
for ( CDatagramIn* pDG = *pHash ; pDG ; pDG = pDG->m_pNextHash )
{
if ( pDG->m_pHost.sin_addr.S_un.S_addr == pHost->sin_addr.S_un.S_addr &&
pDG->m_pHost.sin_port == pHost->sin_port &&
pDG->m_nSequence == pHeader->nSequence &&
pDG->m_nCount == pHeader->nCount )
{
if ( pDG->Add( pHeader->nPart, &pHeader[1], nLength ) )
{
if ( CG2Packet* pPacket = pDG->ToG2Packet() )
{
try
{
OnPacket( pHost, pPacket );
}
catch ( CException* pException )
{
pException->Delete();
}
pPacket->Release();
}
// Keep it to check sequence numbers
// Remove( pDG );
}
return TRUE;
}
}
while ( m_pInputFree == NULL || m_nBufferFree < pHeader->nCount )
{
if ( m_pInputLast == NULL ) return FALSE;
Remove( m_pInputLast );
}
if ( m_nBufferFree < pHeader->nCount ) return FALSE;
pDG = m_pInputFree;
pDG->Create( pHost, pHeader->nFlags, pHeader->nSequence, pHeader->nCount );
for ( WORD nPart = 0 ; nPart < pDG->m_nCount ; nPart++ )
{
ASSERT( pDG->m_pBuffer[ nPart ] == NULL );
pDG->m_pBuffer[ nPart ] = m_pBufferFree;
m_pBufferFree = m_pBufferFree->m_pNext;
m_nBufferFree--;
}
if ( pDG->Add( pHeader->nPart, &pHeader[1], nLength ) )
{
if ( CG2Packet* pPacket = pDG->ToG2Packet() )
{
try
{
OnPacket( pHost, pPacket );
}
catch ( CException* pException )
{
pException->Delete();
}
pPacket->Release();
}
// Don't remove it, keep it to check sequence numbers
// Remove( pDG, TRUE );
}
// Always add it to the list
pDG->m_pNextTime = NULL;
pDG->m_pPrevTime = m_pInputFirst;
if ( m_pInputFirst )
m_pInputFirst->m_pNextTime = pDG;
else
m_pInputLast = pDG;
m_pInputFirst = pDG;
m_pInputFree = pDG->m_pNextHash;
if ( *pHash ) (*pHash)->m_pPrevHash = &pDG->m_pNextHash;
pDG->m_pNextHash = *pHash;
pDG->m_pPrevHash = pHash;
*pHash = pDG;
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CDatagrams SGP acknowledgement handler
BOOL CDatagrams::OnAcknowledgeSGP(SOCKADDR_IN* pHost, SGP_HEADER* pHeader, DWORD nLength)
{
#ifdef DEBUG_UDP
theApp.Message( MSG_DEBUG, _T("UDP: Received ack (#%i) %i from %s"),
pHeader->nSequence, pHeader->nPart, (LPCTSTR)CString( inet_ntoa( pHost->sin_addr ) ) );
#endif
BYTE nHash = pHost->sin_addr.S_un.S_un_b.s_b1
+ pHost->sin_addr.S_un.S_un_b.s_b2
+ pHost->sin_addr.S_un.S_un_b.s_b3
+ pHost->sin_addr.S_un.S_un_b.s_b4
+ pHost->sin_port
+ pHeader->nSequence;
CDatagramOut** pHash = m_pOutputHash + ( nHash & HASH_MASK );
for ( CDatagramOut* pDG = *pHash ; pDG ; pDG = pDG->m_pNextHash )
{
if ( pDG->m_pHost.sin_addr.S_un.S_addr == pHost->sin_addr.S_un.S_addr &&
pDG->m_pHost.sin_port == pHost->sin_port &&
pDG->m_nSequence == pHeader->nSequence )
{
if ( pDG->Acknowledge( pHeader->nPart ) ) Remove( pDG );
return TRUE;
}
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////
// CDatagrams manage partial datagrams
void CDatagrams::ManagePartials()
{
DWORD tNow = GetTickCount();
for ( CDatagramIn* pDG = m_pInputLast ; pDG ; )
{
CDatagramIn* pNext = pDG->m_pNextTime;
if ( tNow - pDG->m_tStarted > Settings.Gnutella2.UdpInExpire )
{
Remove( pDG );
}
pDG = pNext;
}
}
//////////////////////////////////////////////////////////////////////
// CDatagrams remove a partiallly received datagram
void CDatagrams::Remove(CDatagramIn* pDG, BOOL bReclaimOnly)
{
for ( int nPart = 0 ; nPart < pDG->m_nCount ; nPart++ )
{
if ( pDG->m_pBuffer[ nPart ] )
{
pDG->m_pBuffer[ nPart ]->m_pNext = m_pBufferFree;
m_pBufferFree = pDG->m_pBuffer[ nPart ];
m_pBufferFree->Clear();
pDG->m_pBuffer[ nPart ] = NULL;
m_nBufferFree++;
}
}
if ( bReclaimOnly ) return;
if ( pDG->m_pNextHash ) pDG->m_pNextHash->m_pPrevHash = pDG->m_pPrevHash;
*(pDG->m_pPrevHash) = pDG->m_pNextHash;
if ( pDG->m_pNextTime )
pDG->m_pNextTime->m_pPrevTime = pDG->m_pPrevTime;
else
m_pInputFirst = pDG->m_pPrevTime;
if ( pDG->m_pPrevTime )
pDG->m_pPrevTime->m_pNextTime = pDG->m_pNextTime;
else
m_pInputLast = pDG->m_pNextTime;
pDG->m_pNextHash = m_pInputFree;
m_pInputFree = pDG;
}
//////////////////////////////////////////////////////////////////////
// CDatagrams packet handler
BOOL CDatagrams::OnPacket(SOCKADDR_IN* pHost, CG2Packet* pPacket)
{
pPacket->SmartDump( NULL, &pHost->sin_addr, FALSE );
m_nInPackets++;
if ( Network.RoutePacket( pPacket ) ) return TRUE;
if ( pPacket->IsType( G2_PACKET_QUERY ) )
{
return OnQuery( pHost, pPacket );
}
else if ( pPacket->IsType( G2_PACKET_QUERY_KEY_REQ ) )
{
return OnQueryKeyRequest( pHost, pPacket );
}
else if ( pPacket->IsType( G2_PACKET_HIT ) || pPacket->IsType( G2_PACKET_HIT_WRAP ) )
{
return OnHit( pHost, pPacket );
}
else if ( pPacket->IsType( G2_PACKET_QUERY_ACK ) )
{
return OnQueryAck( pHost, pPacket );
}
else if ( pPacket->IsType( G2_PACKET_QUERY_KEY_ANS ) )
{
return OnQueryKeyAnswer( pHost, pPacket );
}
else if ( pPacket->IsType( G2_PACKET_PING ) )
{
return OnPing( pHost, pPacket );
}
else if ( pPacket->IsType( G2_PACKET_PONG ) )
{
return OnPong( pHost, pPacket );
}
else if ( pPacket->IsType( G2_PACKET_PUSH ) )
{
return OnPush( pHost, pPacket );
}
else if ( pPacket->IsType( G2_PACKET_CRAWL_REQ ) )
{
return OnCrawlRequest( pHost, pPacket );
}
else if ( pPacket->IsType( G2_PACKET_CRAWL_ANS ) )
{
return OnCrawlAnswer( pHost, pPacket );
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////
// CDatagrams PING packet handler
BOOL CDatagrams::OnPing(SOCKADDR_IN* pHost, CG2Packet* pPacket)
{
Send( pHost, CG2Packet::New( G2_PACKET_PONG ) );
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CDatagrams PONG packet handler
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -