#include "stdafx.h" #include #include #include #include #include #include namespace WBANetwork { ServerSession::ServerSession( int sendBufSize, int recvBufSize ) : m_pServerNetwork( NULL ), m_bReadyToSend( true ), m_dwSendBufSize( sendBufSize ), m_dwRecvBufSize( recvBufSize ), m_dwSendReqSize( 0 ), m_dwSendCompletionSize( 0 ), m_dwMaxSizePerUpdate( m_dwSendBufSize ) { m_UID = (DWORD)(u_int64)this; m_szDequeueBuffer = _new_dbg_ BYTE [m_dwRecvBufSize]; m_CQSendBuffer.Create( m_dwSendBufSize ); m_CQRecvBuffer.Create( m_dwRecvBufSize ); } ServerSession::~ServerSession() { m_CQSendBuffer.Destroy(); m_CQRecvBuffer.Destroy(); delete [] m_szDequeueBuffer; Close(); } void ServerSession::Create() { if( NULL == m_pServerNetwork || INVALID_HANDLE_VALUE != m_Socket.GetNativeHandle() ) { //_ASSERTE(!"ServerSession::Create"); } m_Socket.Create( Socket::Protocol_TCP, true ); } void ServerSession::Create( SOCKET s, Socket::SocketAddr& addr ) { if( NULL == m_pServerNetwork || INVALID_HANDLE_VALUE != m_Socket.GetNativeHandle() ) { //_ASSERTE(!"ServerSession::Create"); } m_Socket.Attach( Socket::Protocol_TCP, s, &addr ); } void ServerSession::Close() { m_Socket.Close(); } void ServerSession::Clear() { m_CQSendBuffer.Clear(); m_CQRecvBuffer.Clear(); m_dwSendCompletionSize = 0; m_dwSendReqSize = 0; m_bReadyToSend = true; } void ServerSession::SetKill( DWORD err ) { if( m_Socket.GetNativeHandle() == INVALID_HANDLE_VALUE ) { return; } m_AResultClose.eventType = Event_Close; m_AResultClose.error = err; m_AResultClose.handler = this; m_AResultClose.transBytes = 0; m_pServerNetwork->PostCompletion( this, &m_AResultClose ); } // ÀÌ ÇÔ¼ö´Â ServerSessionÀ» »ó¼Ó¹ÞÀº Ŭ·¡½ºÀÇ »ý¼ºÀÚ¿¡¼­ »ç¿ëÇÒ ¼ö ¾ø´Ù. void ServerSession::Connect( TCHAR* ipAddress, unsigned short portNo ) { USES_CONVERSION; m_pServerNetwork->ConnectSession( this, T2A(ipAddress), portNo ); } void ServerSession::WaitForRecv() { Guard < Mutex > guard( m_MutexRecv ); ::memset( &m_AResultRecv, 0, sizeof( AsyncResult ) ); m_AResultRecv.handler = this; m_AResultRecv.eventType = Event_Receive; DWORD dwRecvSize = m_CQRecvBuffer.GetRemainBufSize(); if( dwRecvSize > 10240 ) { dwRecvSize = 10240; } int nResult = m_Socket.Recv( m_AResultRecv.szData, dwRecvSize, &m_AResultRecv ); // int nResult = m_Socket.Recv( m_CQRecvBuffer.GetWritePtr(), // m_CQRecvBuffer.GetWritableSize(), // &m_AResultRecv ); if( 0 == nResult && ERROR_IO_PENDING != m_AResultRecv.error ) { CallbackErrorHandler( m_AResultRecv.error, _T("[WBANetwork::ServerSession::WaitForRecv] Failure Recv() -> SetKill()") ); SetKill( m_AResultRecv.error ); } } void ServerSession::Update() { Flush(); } void ServerSession::Flush() { Guard < Mutex > guard( m_MutexSend ); DWORD writeSize = m_CQSendBuffer.GetReadableSize(); if( writeSize > 0 && writeSize != 52 ) writeSize = m_CQSendBuffer.GetReadableSize(); if( writeSize > m_dwMaxSizePerUpdate ) writeSize = m_dwMaxSizePerUpdate; // º¸³»±â ¹öÆÛÀÇ ³»¿ëÀ» Àü¼ÛÇÑ´Ù. { if( m_bReadyToSend == false || writeSize == 0 ) { return; } m_bReadyToSend = false; ::memset( &m_AResultSend, 0, sizeof( AsyncResult ) ); m_AResultSend.handler = this; m_AResultSend.eventType = Event_Send; m_dwSendCompletionSize = 0; m_dwSendReqSize = writeSize; /* ERROR 󸮴 Send ÇÔ¼ö¿¡¼­ ÇÏ¿´À¸¹Ç·Î ¿©±â¼­´Â °á°ú °ª ¸¸À» °¡Áö°í ¿¡·¯¸¦ È®ÀÎÇÑ´Ù. */ int nResult = m_Socket.Send( m_CQSendBuffer.GetReadPtr(), writeSize, &m_AResultSend ); if( 0 == nResult && ERROR_IO_PENDING != m_AResultSend.error ) { CallbackErrorHandler( m_AResultSend.error, _T("[WBANetwork::ServerSession::Flush] Failure Send() -> SetKill()") ); SetKill( m_AResultSend.error ); } } } //////////////////////////////////////////////////////////////////////////////////////////////// // Derived virtual function void ServerSession::HandleEvent( AsyncResult* result ) { if( NULL == result ) { //_ASSERTE(!"ServerSession::HandleEvent"); return; } switch( result->eventType ) { case Event_Accept: Clear(); OnAccept(); WaitForRecv(); break; case Event_Connect: if( 1 == result->transBytes ) { Clear(); m_pServerNetwork->AddSessionEvent( this ); OnConnect( true, result->error ); WaitForRecv(); } else { Close(); OnConnect( false, result->error ); } break; case Event_Send: { Guard < Mutex > guard( m_MutexSend ); // ¸ÕÀú, ¿Ï·áµÈ Å©±â¸¸Å­ Send buffer¿¡¼­ Á¦°ÅÇÑ´Ù. // ºñµ¿±â I/O¸¦ »ç¿ëÇ߱⠶§¹®¿¡ ¿Ï·á°¡ ¹ß»ýÇÒ ¶§ ±îÁö // º¸³»±â ¹öÆÛ´Â º¸Á¸µÇ¾î¾ß ÇÑ´Ù. m_CQSendBuffer.Dequeue( 0, result->transBytes ); // ¿äûÇÑ I/O ÀÛ¾÷ÀÇ Å©±â¸¸Å­ ¿Ï·á°¡ ¹ß»ýÇØ¾ß // ´ÙÀ½ SendÀÛ¾÷À» ¼öÇàÇÒ ¼ö ÀÖ´Ù. m_dwSendCompletionSize += result->transBytes; if( m_dwSendReqSize <= m_dwSendCompletionSize ) m_bReadyToSend = true; } OnSend( result->transBytes ); break; case Event_Receive: { if( result->transBytes == 0 ) { // 0byte receive´Â WSAGetLastError¸¦ È£Ãâ ÇÏÁö ¾Ê´Â´Ù. // EXT_ERROR_ZERO_BYTE_RECEIVE Á¤ÀǸ¦ ÇÏ¿© ¿¡·¯ Äڵ带 ¸®ÅÏÇÑ´Ù. CallbackErrorHandler( 0, _T("[WBANetwork::ServerSession::HandleEvent] Event_Receive transBytes == 0 -> SetKill()") ); DWORD dwErrorCode = EXT_ERROR_ZERO_BYTE_RECEIVE; SetKill( dwErrorCode ); break; } Guard < Mutex > guard( m_MutexRecv ); DWORD offset = 0; bool requestedRecv = false; // WSARecv ¿¡¼­ ¹ÞÀº µ¥ÀÌÅ͸¸Å­ »çÀÌÁ Áõ°¡ ½ÃÄÑÁÜ if( m_CQRecvBuffer.Enqueue( result->szData, result->transBytes ) == false ) // if( m_CQRecvBuffer.Enqueue( 0, result->transBytes ) == false ) { //_ASSERTE(!"ServerSession::HandleEvent - Event_Receive"); } DWORD recvSize = m_CQRecvBuffer.GetDataSize(); if( m_CQRecvBuffer.Peek( m_szDequeueBuffer, recvSize ) == false ) { //_ASSERTE(!"ServerSession::HandleEvent - Event_Receive"); } while( recvSize > 0 ) { DWORD totalSize = 0; // Çì´õ¸¦ Æ÷ÇÔÇÑ ÆÐŶ ÇϳªÀÇ Àüü Å©±â if( IsValidPacket( &m_szDequeueBuffer[offset], recvSize, &totalSize ) == true ) { OnReceive( ( m_szDequeueBuffer + offset ), totalSize ); offset += totalSize; recvSize -= totalSize; } else break; } if( m_CQRecvBuffer.Dequeue( 0, offset ) == false ) { //_ASSERTE(!"ServerSession::HandleEvent - Event_Receive"); } // ¾Æ·¡ WaitForRecv¸¦ È£ÃâÇÏ´Â ¼ø°£ resultÀÇ ³»¿ëÀº º¯ÇÒ ¼ö ÀÖÀ¸¹Ç·Î // ÇÊ¿äÇÏ´Ù¸é ÀÌ °÷¿¡¼­ ¹é¾÷ÇØµÎ¾î¾ß ÇÑ´Ù. if( m_CQRecvBuffer.GetWritableSize() > 0 ) { WaitForRecv(); requestedRecv = true; // i think it does not necessary...:p } else { // ¼ö½Å ¹öÆÛ¿¡ ³²Àº ¿ë·®ÀÌ ¾ø´Ù¸é ¼ö½Å ¹öÆÛ¸¦ ºñ¿ö¾ßÇÑ´Ù. CallbackErrorHandler( 0, _T("[ServerSession::HandleEvent] ¼ö½Å¹öÆÛ ºÎÁ·") ); } } break; case Event_Close: { Guard < Mutex > guard( m_MutexSend ); if(!m_Socket.IsClose()) { Close(); OnClose( result->error ); } } break; default: { if( 0 == result->transBytes ) { // 0byte receive´Â WSAGetLastError¸¦ È£Ãâ ÇÏÁö ¾Ê´Â´Ù. // EXT_ERROR_ZERO_BYTE_RECEIVE Á¤ÀǸ¦ ÇÏ¿© ¿¡·¯ Äڵ带 ¸®ÅÏÇÑ´Ù. CallbackErrorHandler( 0, _T("[WBANetwork::ServerSession::HandleEvent] Not Define Event transBytes == 0 -> SetKill()") ); DWORD dwErrorCode = EXT_ERROR_ZERO_BYTE_RECEIVE; SetKill( dwErrorCode ); } else { CallbackErrorHandler( 0, _T("[WBANetwork::ServerSession::HandleEvent] Not Define Event") ); } } break; } } void ServerSession::GetSendBufferSize( DWORD* remain, DWORD* max ) { if( 0 != remain ) *remain = m_CQSendBuffer.GetRemainBufSize(); if( 0 != max ) *max = m_CQSendBuffer.GetBufferSize(); } void ServerSession::GetRecvBufferSize( DWORD* remain, DWORD* max ) { if( 0 != remain ) *remain = m_CQRecvBuffer.GetRemainBufSize(); if( 0 != max ) *max = m_CQRecvBuffer.GetBufferSize(); } void ServerSession::SendPacket( void* buffer, int size, SEND_RET& ret ) { if(m_Socket.IsClose()) { ret = FAILD_CLOSED; return; } if( NULL == buffer ) { //_ASSERTE(!"ServerSession::SendPacket"); ret = FAILD_NULL; return; } if( m_CQSendBuffer.GetRemainBufSize() < ( DWORD )size ) { TCHAR szMsg[256] = {0, }; if ( FAILED(StringCbPrintf(szMsg, sizeof(szMsg), _T("[WBANetwork::ServerSession::SendPacket::buffer] SendBufferÀÇ ¿ë·®ºÎÁ·, Remain : %d, Packet : %d"), m_CQSendBuffer.GetRemainBufSize(), size ) )) { //_ASSERTE(!"ServerSession::SendPacket StringCbPrintf"); } CallbackErrorHandler( 0, szMsg ); ret = FAILD_OVERFLOW; return ; } Guard < Mutex > guard( m_MutexSend ); if( m_CQSendBuffer.Enqueue( ( PBYTE )buffer, size ) == false ) { TCHAR szMsg[256] = {0, }; if ( FAILED(StringCbPrintf(szMsg, sizeof(szMsg), _T("[WBANetwork::ServerSession::SendPacket::buffer] SendBufferÀÇ Enqueue½ÇÆÐ, Remain : %d, Packet : %d"), m_CQSendBuffer.GetRemainBufSize(), size ) )) { //_ASSERTE(!"ServerSession::SendPacket StringCbPrintf"); } CallbackErrorHandler( 0, szMsg ); ret = FAILD_OVERFLOW; return ; } Flush(); ret = SUCESS; } bool ServerSession::SendPacket( void* buffer, int size ) { if(m_Socket.IsClose()) return false; if( NULL == buffer ) { //_ASSERTE(!"ServerSession::SendPacket"); return false; } if( m_CQSendBuffer.GetRemainBufSize() < ( DWORD )size ) { TCHAR szMsg[256] = {0, }; if ( FAILED(StringCbPrintf(szMsg, sizeof(szMsg), _T("[WBANetwork::ServerSession::SendPacket::buffer] SendBufferÀÇ ¿ë·®ºÎÁ·, Remain : %d, Packet : %d"), m_CQSendBuffer.GetRemainBufSize(), size ) )) { //_ASSERTE(!"ServerSession::SendPacket StringCbPrintf"); } CallbackErrorHandler( 0, szMsg ); return false; } Guard < Mutex > guard( m_MutexSend ); if( m_CQSendBuffer.Enqueue( ( PBYTE )buffer, size ) == false ) { TCHAR szMsg[256] = {0, }; if ( FAILED(StringCbPrintf(szMsg, sizeof(szMsg), _T("[WBANetwork::ServerSession::SendPacket::buffer] SendBufferÀÇ Enqueue½ÇÆÐ, Remain : %d, Packet : %d"), m_CQSendBuffer.GetRemainBufSize(), size ) )) { //_ASSERTE(!"ServerSession::SendPacket StringCbPrintf"); } CallbackErrorHandler( 0, szMsg ); return false; } Flush(); return true; } bool ServerSession::SendPacket( Stream& stream ) { if( m_CQSendBuffer.GetRemainBufSize() < stream.GetDataSize() ) { TCHAR szMsg[256] = {0, }; if ( FAILED(StringCbPrintf(szMsg, sizeof(szMsg), _T("[WBANetwork::ServerSession::SendPacket::Stream] SendBufferÀÇ ¿ë·®ºÎÁ·, Remain : %d, Packet : %d"), m_CQSendBuffer.GetRemainBufSize(), stream.GetDataSize() ) )) { //_ASSERTE(!"ServerSession::SendPacket StringCbPrintf"); } CallbackErrorHandler( 0, szMsg ); return false; } Guard < Mutex > guard( m_MutexSend ); if( m_CQSendBuffer.Enqueue( stream.GetBuffer(), stream.GetDataSize() ) == false ) { TCHAR szMsg[256] = {0, }; if ( FAILED(StringCbPrintf(szMsg, sizeof(szMsg), _T("[WBANetwork::ServerSession::SendPacket::Stream] SendBufferÀÇ Enqueue½ÇÆÐ, Remain : %d, Packet : %d"), m_CQSendBuffer.GetRemainBufSize(), stream.GetDataSize() ) )) { //_ASSERTE(!"ServerSession::SendPacket StringCbPrintf"); } CallbackErrorHandler( 0, szMsg ); return false; } Flush(); return true; } // ¹öÆÛ »çÀÌÁî º¸´Ù Å« ¸Þ½ÃÁö º¸³¾¶§ °­Á¦ÀûÀ¸·Î »÷µå Çϵµ·Ï... //bool ServerSession::CompulsionSendPacket( PBYTE buffer, int length, AsyncResult* result ) //{ // int nResult = m_Socket.Send(buffer, // length, // &m_AResultSend); // // return (0 != nResult); //} DWORD ServerSession::SetKeepAlive(u_long onoff, u_long KeepaliveTime, u_long Keepaliveinterval) { return m_Socket.SetKeepAlive(onoff, KeepaliveTime, Keepaliveinterval); } }