📄 chatsession.cpp
字号:
{
if ( ! OnText( strLine ) )
{
Close();
return FALSE;
}
}
return TRUE;
}
BOOL CChatSession::OnText(const CString& str)
{
if ( m_pWndPrivate == NULL ) return TRUE;
if ( m_bOld )
{
if ( StartsWith( str, _T("\001ACTION ") ) )
{
m_pWndPrivate->OnRemoteMessage( TRUE, str.Mid( 8 ) );
}
else
{
m_pWndPrivate->OnRemoteMessage( FALSE, str );
}
}
else if ( StartsWith( str, _T("MESSAGE ") ) )
{
if ( StartsWith( str, _T("MESSAGE \001ACTION ") ) )
{
m_pWndPrivate->OnRemoteMessage( TRUE, str.Mid( 16 ) );
}
else
{
m_pWndPrivate->OnRemoteMessage( FALSE, str.Mid( 8 ) );
}
}
else if ( StartsWith( str, _T("NICK ") ) )
{
// New nick is : str.Mid( 5 )
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CChatSession Gnutella2 packet interface
void CChatSession::Send(CG2Packet* pPacket, BOOL bRelease)
{
ASSERT( m_bG2 );
ASSERT( pPacket != NULL );
ASSERT( m_nState >= cssHandshake );
pPacket->ToBuffer( m_pOutput );
if ( bRelease ) pPacket->Release();
OnWrite();
}
BOOL CChatSession::ReadPackets()
{
for ( BOOL bSuccess = TRUE ; bSuccess && m_pInput->m_nLength ; )
{
BYTE nInput = *( m_pInput->m_pBuffer );
if ( nInput == 0 )
{
m_pInput->Remove( 1 );
continue;
}
BYTE nLenLen = ( nInput & 0xC0 ) >> 6;
BYTE nTypeLen = ( nInput & 0x38 ) >> 3;
BYTE nFlags = ( nInput & 0x07 );
if ( nLenLen == 0 )
{
Close();
return FALSE;
}
if ( (DWORD)m_pInput->m_nLength < (DWORD)nLenLen + nTypeLen + 2 ) break;
DWORD nLength = 0;
if ( nFlags & G2_FLAG_BIG_ENDIAN )
{
BYTE* pLenIn = m_pInput->m_pBuffer + 1;
for ( BYTE nIt = nLenLen ; nIt ; nIt-- )
{
nLength <<= 8;
nLength |= *pLenIn++;
}
}
else
{
BYTE* pLenIn = m_pInput->m_pBuffer + 1;
BYTE* pLenOut = (BYTE*)&nLength;
for ( BYTE nLenCnt = nLenLen ; nLenCnt-- ; ) *pLenOut++ = *pLenIn++;
}
if ( nLength >= Settings.Gnutella1.MaximumPacket )
{
Close();
return FALSE;
}
if ( (DWORD)m_pInput->m_nLength < (DWORD)nLength + nLenLen + nTypeLen + 2 ) break;
CG2Packet* pPacket = CG2Packet::New( m_pInput->m_pBuffer );
m_pInput->Remove( nLength + nLenLen + nTypeLen + 2 );
try
{
bSuccess = OnPacket( pPacket );
}
catch ( CException* pException )
{
pException->Delete();
bSuccess = TRUE;
}
pPacket->Release();
}
if ( ! bSuccess ) Close();
return bSuccess;
}
//////////////////////////////////////////////////////////////////////
// CChatSession Gnutella2 packet handlers
BOOL CChatSession::OnPacket(CG2Packet* pPacket)
{
if ( pPacket->IsType( "CMSG" ) )
{
return OnChatMessage( pPacket );
}
else if ( pPacket->IsType( G2_PACKET_PROFILE_CHALLENGE ) )
{
return OnProfileChallenge( pPacket );
}
else if ( pPacket->IsType( G2_PACKET_PROFILE_DELIVERY ) )
{
return OnProfileDelivery( pPacket );
}
else if ( pPacket->IsType( "CHATREQ" ) )
{
return OnChatRequest( pPacket );
}
else if ( pPacket->IsType( "CHATANS" ) )
{
return OnChatAnswer( pPacket );
}
return TRUE;
}
BOOL CChatSession::OnProfileChallenge(CG2Packet* pPacket)
{
if ( ! MyProfile.IsValid() ) return TRUE;
CG2Packet* pProfile = CG2Packet::New( G2_PACKET_PROFILE_DELIVERY, TRUE );
CString strXML = MyProfile.GetXML( NULL, TRUE )->ToString( TRUE );
pProfile->WritePacket( "XML", pProfile->GetStringLen( strXML ) );
pProfile->WriteString( strXML, FALSE );
Send( pProfile, TRUE );
return TRUE;
}
BOOL CChatSession::OnProfileDelivery(CG2Packet* pPacket)
{
if ( ! pPacket->m_bCompound ) return TRUE;
if ( m_pProfile != NULL ) delete m_pProfile;
m_pProfile = NULL;
CHAR szType[9];
DWORD nLength;
while ( pPacket->ReadPacket( szType, nLength ) )
{
DWORD nOffset = pPacket->m_nPosition + nLength;
if ( strcmp( szType, "XML" ) == 0 )
{
CXMLElement* pXML = CXMLElement::FromString( pPacket->ReadString( nLength ), TRUE );
if ( pXML != NULL )
{
m_pProfile = new CGProfile();
if ( ! m_pProfile->FromXML( pXML ) || ! m_pProfile->IsValid() )
{
delete pXML;
delete m_pProfile;
m_pProfile = NULL;
}
}
}
pPacket->m_nPosition = nOffset;
}
if ( m_pProfile == NULL ) return TRUE;
m_sUserNick = m_pProfile->GetNick();
if ( m_bGUID )
{
if ( m_pGUID != m_pProfile->GUID )
{
// ERROR: Its someone else !!
m_pGUID = m_pProfile->GUID;
}
}
else
{
m_bGUID = TRUE;
m_pGUID = m_pProfile->GUID;
}
if ( m_pWndPrivate != NULL )
{
m_pWndPrivate->OnProfileReceived();
CG2Packet* pPacket = CG2Packet::New( "CHATREQ", TRUE );
pPacket->WritePacket( "USERGUID", 16 );
pPacket->Write( &m_pGUID, 16 );
Send( pPacket, TRUE );
}
return TRUE;
}
BOOL CChatSession::OnChatRequest(CG2Packet* pPacket)
{
if ( ! pPacket->m_bCompound ) return TRUE;
BOOL bGUID = FALSE;
GGUID pGUID;
CHAR szType[9];
DWORD nLength;
while ( pPacket->ReadPacket( szType, nLength ) )
{
DWORD nOffset = pPacket->m_nPosition + nLength;
if ( strcmp( szType, "USERGUID" ) == 0 && nLength >= 16 )
{
pPacket->Read( &pGUID, 16 );
bGUID = TRUE;
}
pPacket->m_nPosition = nOffset;
}
pPacket = CG2Packet::New( "CHATANS", TRUE );
pPacket->WritePacket( "USERGUID", 16 );
pPacket->Write( &MyProfile.GUID, 16 );
if ( bGUID && pGUID == MyProfile.GUID )
{
pPacket->WritePacket( "ACCEPT", 0 );
PostOpenWindow();
}
else
{
pPacket->WritePacket( "DENY", 0 );
}
Send( pPacket, TRUE );
return TRUE;
}
BOOL CChatSession::OnChatAnswer(CG2Packet* pPacket)
{
if ( ! pPacket->m_bCompound ) return TRUE;
CHAR szType[9];
DWORD nLength;
while ( pPacket->ReadPacket( szType, nLength ) )
{
DWORD nOffset = pPacket->m_nPosition + nLength;
if ( strcmp( szType, "ACCEPT" ) == 0 )
{
m_nState = cssActive;
StatusMessage( 2, IDS_CHAT_PRIVATE_ONLINE, (LPCTSTR)m_sUserNick );
StatusMessage( 0, 0 );
return TRUE;
}
else if ( strcmp( szType, "DENY" ) == 0 )
{
StatusMessage( 1, IDS_CHAT_PRIVATE_REFUSED, (LPCTSTR)m_sUserNick );
}
else if ( strcmp( szType, "AWAY" ) == 0 )
{
CString strAway = pPacket->ReadString( nLength );
StatusMessage( 1, IDS_CHAT_PRIVATE_AWAY, (LPCTSTR)m_sUserNick,
(LPCTSTR)strAway );
}
pPacket->m_nPosition = nOffset;
}
Close();
return FALSE;
}
BOOL CChatSession::OnChatMessage(CG2Packet* pPacket)
{
if ( ! pPacket->m_bCompound ) return TRUE;
BOOL bAction = FALSE;
CString strBody;
CHAR szType[9];
DWORD nLength;
while ( pPacket->ReadPacket( szType, nLength ) )
{
DWORD nOffset = pPacket->m_nPosition + nLength;
if ( strcmp( szType, "BODY" ) == 0 )
{
strBody = pPacket->ReadString( nLength );
}
else if ( strcmp( szType, "ACT" ) == 0 )
{
bAction = TRUE;
}
pPacket->m_nPosition = nOffset;
}
if ( strBody.IsEmpty() ) return TRUE;
if ( m_pWndPrivate != NULL ) m_pWndPrivate->OnRemoteMessage( bAction, strBody );
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CChatSession message interface
BOOL CChatSession::SendPrivateMessage(BOOL bAction, LPCTSTR pszText)
{
CSingleLock pLock( &ChatCore.m_pSection, TRUE );
if ( m_nState != cssActive ) return FALSE;
if ( m_bG2 )
{
CG2Packet* pPacket = CG2Packet::New( "CMSG", TRUE );
if ( bAction ) pPacket->WritePacket( "ACT", 0 );
pPacket->WritePacket( "BODY", pPacket->GetStringLen( pszText ) );
pPacket->WriteString( pszText, FALSE );
Send( pPacket, TRUE );
}
else
{
CString str;
if ( ! m_bOld ) str += _T("MESSAGE ");
if ( bAction ) str += _T("\001ACTION ");
str += pszText;
str += _T("\r\n");
Print( str );
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CChatSession status message
void CChatSession::StatusMessage(int nFlags, UINT nID, ...)
{
CString strFormat;
va_list pArgs;
if ( nID )
LoadString( strFormat, nID );
else
strFormat = _T("-");
va_start( pArgs, nID );
if ( strFormat.Find( _T("%1") ) >= 0 )
{
LPTSTR lpszTemp;
if ( ::FormatMessage( FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER,
strFormat, 0, 0, (LPTSTR)&lpszTemp, 0, &pArgs ) != 0 && lpszTemp != NULL )
{
if ( m_pWndPrivate != NULL ) m_pWndPrivate->OnStatusMessage( nFlags, lpszTemp );
LocalFree( lpszTemp );
}
}
else
{
TCHAR szMessageBuffer[1024];
_vstprintf( szMessageBuffer, strFormat, pArgs );
if ( m_pWndPrivate != NULL ) m_pWndPrivate->OnStatusMessage( nFlags, szMessageBuffer );
}
va_end( pArgs );
}
//////////////////////////////////////////////////////////////////////
// CChatSession chat window interface
void CChatSession::PostOpenWindow()
{
if ( m_pWndPrivate != NULL || m_pWndPublic != NULL ) return;
if ( CWnd* pWnd = (CWnd*)theApp.SafeMainWnd() )
{
pWnd->PostMessage( WM_OPENCHAT, (WPARAM)this );
}
}
void CChatSession::OnOpenWindow()
{
ASSERT( m_pWndPrivate == NULL && m_pWndPublic == NULL );
if ( m_bGUID )
{
m_pWndPrivate = ChatWindows.FindPrivate( &m_pGUID );
}
else
{
m_pWndPrivate = ChatWindows.FindPrivate( &m_pHost.sin_addr );
}
if ( m_pWndPrivate == NULL )
{
m_pWndPrivate = new CPrivateChatFrame();
}
if ( ! m_pWndPrivate->Accept( this ) )
{
m_pWndPrivate = new CPrivateChatFrame();
m_pWndPrivate->Accept( this );
}
m_pWndPrivate->OnProfileReceived();
StatusMessage( 2, IDS_CHAT_PRIVATE_ONLINE, (LPCTSTR)m_sUserNick );
StatusMessage( 0, 0 );
PlaySound( _T("RAZA_IncomingChat"), NULL, SND_APPLICATION|SND_ALIAS|SND_ASYNC );
m_nState = cssActive;
// Hack to open it
CWnd* pParent = m_pWndPrivate->GetParent();
if ( pParent->IsIconic() ) pParent->ShowWindow( SW_SHOWNORMAL );
pParent->BringWindowToTop();
pParent->SetForegroundWindow();
}
void CChatSession::OnCloseWindow()
{
m_pWndPrivate = NULL;
m_pWndPublic = NULL;
Close();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -