#include "StdAfx.h" #include "../Protocol/DNPacket.h" #include "SocketContext.h" #include "SpinBuffer.h" #include "DnServerDef.h" #include "DnServerPacketCash.h" #include "Log.h" #if defined(_SERVER) //==================================================================================================================================================// // Class ScopeSpinBufferSwitch //==================================================================================================================================================// ScopeSpinBufferSwitch::ScopeSpinBufferSwitch( CSpinBuffer* pSpinBuffer ) : m_pSpinBuffer( pSpinBuffer ), m_pBuffer( NULL ), m_uiSize( 0 ), m_uiBufferIndex( 0 ) { m_uiBufferIndex = m_pSpinBuffer->Switch( m_pBuffer, m_uiSize ); } ScopeSpinBufferSwitch::~ScopeSpinBufferSwitch() { if( m_uiBufferIndex != UINT_MAX ) m_pSpinBuffer->SwitchClear( m_uiBufferIndex ); } //==================================================================================================================================================// // Class CSpinBuffer //==================================================================================================================================================// CSpinBuffer::CSpinBuffer( const UINT uiAccessThreadCount, const UINT uiSize ) : m_uiActiveBufferIndex(0), m_uiMaxBufferCount(0) { _ASSERT( uiAccessThreadCount ); m_uiMaxBufferCount = uiAccessThreadCount+1; m_vBufferSize.reserve( m_uiMaxBufferCount ); m_vBufferOffset.reserve( m_uiMaxBufferCount ); m_vBuffer.reserve( m_uiMaxBufferCount ); for( UINT i=0 ; i Lock( m_Lock ); for( UINT i=0 ; i Lock( m_Lock ); _ASSERT( !m_qBuffer.empty() ); UINT uiReturnBufferIndex = m_uiActiveBufferIndex; pReturnBuffer = m_vBuffer[m_uiActiveBufferIndex]; uiReturnSize = m_vBufferOffset[m_uiActiveBufferIndex]; if( uiReturnSize == 0 ) return UINT_MAX; m_uiActiveBufferIndex = m_qBuffer.front(); m_qBuffer.pop(); m_vBufferOffset[m_uiActiveBufferIndex] = 0; return uiReturnBufferIndex; } void CSpinBuffer::SwitchClear( const UINT uiBufferIndex ) { ScopeLock Lock( m_Lock ); m_qBuffer.push( uiBufferIndex ); } int CSpinBuffer::Resize( const UINT32 uiSize ) { // »óÀ§¿¡¼­ µ¿±âÈ­ µÇ´Â ÇÔ¼ö _ASSERT( m_vBufferSize[m_uiActiveBufferIndex] < uiSize ); char* pResizeBuffer = new (std::nothrow) char[uiSize]; if( pResizeBuffer == NULL ) return -1; if( m_vBufferOffset[m_uiActiveBufferIndex] ) memcpy( pResizeBuffer, m_vBuffer[m_uiActiveBufferIndex], m_vBufferOffset[m_uiActiveBufferIndex] ); delete[] m_vBuffer[m_uiActiveBufferIndex]; m_vBuffer[m_uiActiveBufferIndex] = pResizeBuffer; m_vBufferSize[m_uiActiveBufferIndex] = uiSize; return 0; } int CSpinBuffer::RawPush( const void* pSrc, const UINT uiLen ) { // »óÀ§¿¡¼­ µ¿±âÈ­ µÇ´Â ÇÔ¼ö if( m_vBufferOffset[m_uiActiveBufferIndex] + uiLen > m_vBufferSize[m_uiActiveBufferIndex] ) { if( Resize( m_vBufferSize[m_uiActiveBufferIndex]*2 ) < 0 ) return -1; // Buffer Resize ÇØµµ ¸ðÀÚ¶õ´Ù¸é ¿¡·¯Ã³¸®ÇÑ´Ù. // Buffer ¸¦ ´Ù½Ã Resize ÇØµµ µÇÁö¸¸ Á¤»óÀûÀÎ °æ¿ì ¹ß»ýÇÒ ¼ö ¾ø´Â °æ¿ìÀ̱⠶§¹®¿¡ µû·Î ¿¹¿Üó¸® ÇÏÁö ¾Ê´Â´Ù. if( m_vBufferOffset[m_uiActiveBufferIndex] + uiLen > m_vBufferSize[m_uiActiveBufferIndex] ) { g_Log.Log(LogType::_ERROR, L"[RawPush] Offset:%u, uiLen:%u, Max:%u\r\n", m_vBufferOffset[m_uiActiveBufferIndex], uiLen, m_vBufferSize[m_uiActiveBufferIndex]); return -1; } } char* pBuffer = m_vBuffer[m_uiActiveBufferIndex] + m_vBufferOffset[m_uiActiveBufferIndex]; memcpy( pBuffer, pSrc, uiLen ); m_vBufferOffset[m_uiActiveBufferIndex] += uiLen; return 0; } //==================================================================================================================================================// // Class CTcpRecvSpinBuffer //==================================================================================================================================================// CTcpRecvSpinBuffer::CTcpRecvSpinBuffer( const UINT uiAccessThreadCount, const UINT uiSize ) : CSpinBuffer( uiAccessThreadCount, uiSize ) { } CTcpRecvSpinBuffer::~CTcpRecvSpinBuffer() { } int CTcpRecvSpinBuffer::Push( CSocketContext *pSocketContext ) { ScopeLock Lock( m_Lock ); int iPushCount = 0; const char* pRecvBuffer = pSocketContext->m_RecvIO.buffer; UINT uiRecvBufferLen = pSocketContext->m_RecvIO.Len; while( uiRecvBufferLen ) { UINT uiPacketLen = 0; if (pSocketContext->m_dwKeyParam == CONNECTIONKEY_AUTH) uiPacketLen = GetCompleteAuthPacketLength( pRecvBuffer, uiRecvBufferLen ); else if (pSocketContext->m_dwKeyParam == CONNECTIONKEY_BILLING) uiPacketLen = GetCompleteBillingPacketLength( pRecvBuffer, uiRecvBufferLen ); #if defined(_TW) else if (pSocketContext->m_dwKeyParam == CONNECTIONKEY_TW_AUTHLOGIN || pSocketContext->m_dwKeyParam == CONNECTIONKEY_TW_AUTHLOGOUT || pSocketContext->m_dwKeyParam == CONNECTIONKEY_TW_QUERY || pSocketContext->m_dwKeyParam == CONNECTIONKEY_TW_SHOPITEM || pSocketContext->m_dwKeyParam == CONNECTIONKEY_TW_COUPON || pSocketContext->m_dwKeyParam == CONNECTIONKEY_TW_COUPON_ROLLBACK) uiPacketLen = GetCompleteAuthPacketLength_TW( pRecvBuffer, uiRecvBufferLen ); #elif defined(_TH) else if (pSocketContext->m_dwKeyParam == CONNECTIONKEY_TH_AUTH || pSocketContext->m_dwKeyParam == CONNECTIONKEY_TH_QUERY || pSocketContext->m_dwKeyParam == CONNECTIONKEY_TH_SHOPITEM) uiPacketLen = GetCompleteAuthPacketLength_TH_Auth(pRecvBuffer, uiRecvBufferLen); else if (pSocketContext->m_dwKeyParam == CONNECTIONKEY_TH_OTP) uiPacketLen = GetCompleteAuthPacketLength_TH_OTP(pRecvBuffer, uiRecvBufferLen); #endif // #if defined(_TW) else uiPacketLen = GetCompletePacketLength( pRecvBuffer, uiRecvBufferLen ); if( uiPacketLen <= 0 ) break; if( RawPush( pRecvBuffer, uiPacketLen ) < 0 ) return -1; pRecvBuffer += uiPacketLen; uiRecvBufferLen -= uiPacketLen; ++iPushCount; } if( iPushCount > 0 ) { pSocketContext->m_RecvIO.Len = uiRecvBufferLen; if( uiRecvBufferLen ) memmove( &pSocketContext->m_RecvIO.buffer, pRecvBuffer, uiRecvBufferLen ); } return iPushCount; } int CTcpRecvSpinBuffer::Push( const DNTPacket& Packet ) { ScopeLock Lock( m_Lock ); return RawPush( &Packet, Packet.iLen ); } int CTcpRecvSpinBuffer::Push( const DNEncryptPacketSeq& Packet ) { ScopeLock Lock( m_Lock ); return RawPush( &Packet, Packet.nLen ); } UINT CTcpRecvSpinBuffer::GetCompletePacketLength( const void* pBuffer, const UINT uiLen ) const { // »óÀ§¿¡¼­ µ¿±âÈ­ µÇ´Â ÇÔ¼ö // iLen + cMainCmd + cSubCmd static const UINT uiTcpPacketHeaderSize = sizeof(USHORT)+sizeof(UCHAR)+sizeof(UCHAR); if( uiLen < uiTcpPacketHeaderSize ) return 0; const DNTPacket* pPacket = static_cast(pBuffer); return (pPacket->iLen <= uiLen) ? pPacket->iLen : 0; } UINT CTcpRecvSpinBuffer::GetCompleteAuthPacketLength( const void* pBuffer, const UINT uiLen ) const { // »óÀ§¿¡¼­ µ¿±âÈ­ µÇ´Â ÇÔ¼ö // Header + Length static const UINT uiTcpPacketHeaderSize = sizeof(BYTE) + sizeof(USHORT); if( uiLen < uiTcpPacketHeaderSize ) return 0; const TAuthHeader* pPacket = static_cast(pBuffer); USHORT wLength = SWAP16(pPacket->wLength) + uiTcpPacketHeaderSize; return (wLength <= uiLen) ? wLength : 0; } UINT CTcpRecvSpinBuffer::GetCompleteBillingPacketLength( const void* pBuffer, const UINT uiLen ) const { // »óÀ§¿¡¼­ µ¿±âÈ­ µÇ´Â ÇÔ¼ö // Header + Length static const UINT uiTcpPacketHeaderSize = sizeof(BYTE) + sizeof(UINT); if( uiLen < uiTcpPacketHeaderSize ) return 0; const TBillingHeader* pPacket = static_cast(pBuffer); UINT nLength = SWAP32(pPacket->nLength) + uiTcpPacketHeaderSize; return (nLength <= uiLen) ? nLength : 0; } #if defined(_TW) UINT CTcpRecvSpinBuffer::GetCompleteAuthPacketLength_TW( const void* pBuffer, const UINT uiLen ) const { // GASH ÀÎÁõÀº '\r\n' À» ÆÐŶÀÇ ³¡À¸·Î üũ UINT nLength = 0; for (INT iIndex = 0 ; (static_cast(uiLen) - 1) > iIndex ; ++iIndex) { if ('\r' == static_cast(pBuffer)[iIndex] && '\n' == static_cast(pBuffer)[iIndex + 1]) { nLength = iIndex + 2; break; } } return (nLength <= uiLen) ? nLength : 0; } #elif defined(_TH) UINT CTcpRecvSpinBuffer::GetCompleteAuthPacketLength_TH_Auth( const char* pBuffer, const UINT uiLen ) const { UINT nLength = 0; for (INT iIndex = 0 ; (static_cast(uiLen)) > iIndex ; ++iIndex) { if (';' == pBuffer[iIndex]) { nLength = iIndex + 1; break; } } return (nLength <= uiLen) ? nLength : 0; } UINT CTcpRecvSpinBuffer::GetCompleteAuthPacketLength_TH_OTP( const void* pBuffer, const UINT uiLen ) const { return uiLen; } #endif // #if defined(_TH) //==================================================================================================================================================// // Class CCompPacketBuffer //==================================================================================================================================================// CCompPacketBuffer::CCompPacketBuffer( const UINT uiAccessThreadCount, const UINT uiSize ) : CSpinBuffer( uiAccessThreadCount, uiSize ) { } CCompPacketBuffer::~CCompPacketBuffer() { } int CCompPacketBuffer::Push( const DNTCompPacket& Packet ) { ScopeLock Lock(m_Lock); return RawPush(&Packet, Packet.header.nLen); } UINT CCompPacketBuffer::GetLeftBufferSize() { ScopeLock Lock(m_Lock); return m_vBufferSize[m_uiActiveBufferIndex] - m_vBufferOffset[m_uiActiveBufferIndex]; } //==================================================================================================================================================// // Class CRawSpinBuffer //==================================================================================================================================================// CRawSpinBuffer::CRawSpinBuffer( const UINT uiAccessThreadCount, const UINT uiSize ) : CSpinBuffer( uiAccessThreadCount, uiSize ), m_bIsLock( false ) { } CRawSpinBuffer::~CRawSpinBuffer() { } int CRawSpinBuffer::Push( const void* pSrc, const UINT uiLen ) { _ASSERT( m_bIsLock == true ); // »óÀ§¿¡¼­ LOCK °É¾îÁà¾ß ÇÔ if( RawPush( pSrc, uiLen ) < 0 ) return -1; return uiLen; } void CRawSpinBuffer::Lock() { m_Lock.Lock(); m_bIsLock = true; } void CRawSpinBuffer::UnLock() { m_Lock.UnLock(); m_bIsLock = false; } UINT CRawSpinBuffer::GetCompletePacketLength( const void* pBuffer, const UINT uiLen ) const { return uiLen; } #endif // #if defined(_SERVER)