ServerStage.cpp
上传用户:dzyhzl
上传日期:2019-04-29
资源大小:56270k
文件大小:20k
源码类别:

模拟服务器

开发平台:

C/C++

  1. #include "ServerStage.h"
  2. #include "IOCPServerException.h"
  3. #include "IOCPServerUtils.h"
  4. #include "IOCPServerManualResetEvent.h"
  5. #include "IOCPServerWin32Exception.h"
  6. #include "IOCPServerSocket.h"
  7. #include "ProtocolProtocol.h"
  8. /*
  9.  * Using directives
  10.  */
  11. using OnlineGameLib::Win32::CWin32Exception;
  12. using OnlineGameLib::Win32::CSocket;
  13. using OnlineGameLib::Win32::_tstring;
  14. using OnlineGameLib::Win32::CException;
  15. using OnlineGameLib::Win32::Output;
  16. using OnlineGameLib::Win32::GetTimeStamp;
  17. using OnlineGameLib::Win32::OutPutInfo;
  18. using OnlineGameLib::Win32::ToString;
  19. using OnlineGameLib::Win32::CCriticalSection;
  20. using OnlineGameLib::Win32::DumpData;
  21. using OnlineGameLib::Win32::Trace2File;
  22. /*
  23.  * Global variable
  24.  */
  25. //[ for trace
  26. #ifdef  NETWORK_DEBUG
  27. //{
  28. static DWORD gsc_dwPackID = 0;
  29. //}
  30. #endif
  31. //]
  32. /*
  33.  * Get server interface
  34.  */
  35. STDAPI QueryServerInterface
  36. (
  37. REFIID riid,
  38. void **ppv
  39. )
  40. {
  41. HRESULT hr = E_NOINTERFACE;
  42. if ( IID_IIOCPServer == riid )
  43. {
  44. CClientManager *pObject = new CClientManager( MAX_BUFFER_KEEPINPOOL, EXTEND_BUFFER_SIZE );
  45. *ppv = reinterpret_cast< void * > ( dynamic_cast< IServer * >( pObject ) );
  46. if ( *ppv )
  47. {
  48. reinterpret_cast< IUnknown * >( *ppv )->AddRef();
  49. hr = S_OK;
  50. }
  51. }
  52. if ( FAILED( hr ) )
  53. {
  54. *ppv = NULL;
  55. }
  56. return ( HRESULT )( hr );
  57. }
  58. /*
  59.  * CGameServerWorkerThread implement
  60.  */
  61. CGameServerWorkerThread::CGameServerWorkerThread(
  62. OnlineGameLib::Win32::CIOCompletionPort &iocp,
  63. CClientManager &refClientManager)
  64.    : OnlineGameLib::Win32::CSocketServer::WorkerThread(iocp)
  65.    , m_refClientManager(refClientManager)
  66. {
  67. }
  68. CGameServerWorkerThread::~CGameServerWorkerThread()
  69. {
  70. }
  71. void CGameServerWorkerThread::OnBeginProcessing()
  72. {
  73. // Output( _T("OnBeginProcessing") );
  74. }
  75. void CGameServerWorkerThread::ReadCompleted(
  76. OnlineGameLib::Win32::CSocketServer::Socket *pSocket,
  77. OnlineGameLib::Win32::CIOBuffer *pBuffer)
  78. {
  79. try
  80. {
  81. unsigned long ulnID = pSocket->GetUserData();
  82. const BYTE *pPackData = pBuffer->GetBuffer();
  83. const size_t used = pBuffer->GetUsed();
  84. m_refClientManager.RecvFromClient( ulnID, reinterpret_cast<const char*>( pPackData ), used );
  85. pBuffer->Empty();
  86. pSocket->Read( pBuffer );
  87. }
  88. catch( const CException &e )
  89. {
  90. Output( _T("ReadCompleted - Exception - ") + e.GetWhere() + _T(" - ") + e.GetMessage() );
  91. pSocket->Shutdown();
  92. }
  93. catch(...)
  94. {
  95. Output( _T("ReadCompleted - Unexpected exception") );
  96. pSocket->Shutdown();
  97. }
  98. }
  99. void CGameServerWorkerThread::OnEndProcessing()
  100. {
  101. // Output( _T("OnEndProcessing") );
  102. }
  103. void CGameServerWorkerThread::OnError( const OnlineGameLib::Win32::_tstring &message )
  104. {
  105. Output( _T("OnError - ") + message );
  106. }
  107. CGameServer::CGameServer(
  108. CClientManager &refClientManager,    
  109. unsigned long addressToListenOn,
  110. unsigned short portToListenOn,
  111. size_t maxFreeSockets,
  112. size_t maxFreeBuffers,
  113. size_t bufferSize /* = 1024 */,
  114. size_t numThreads /* = 0 */)
  115.    : OnlineGameLib::Win32::CSocketServer(addressToListenOn, portToListenOn, maxFreeSockets, maxFreeBuffers, bufferSize, numThreads)
  116.    , m_refClientManager( refClientManager )
  117. {
  118. }
  119. CGameServer::CGameServer(
  120. CClientManager &refClientManager,
  121. size_t maxFreeSockets,
  122. size_t maxFreeBuffers,
  123. size_t bufferSize /* = 1024 */,
  124. size_t numThreads /* = 0 */)
  125.    : OnlineGameLib::Win32::CSocketServer(maxFreeSockets, maxFreeBuffers, bufferSize, numThreads)
  126.    , m_refClientManager( refClientManager )
  127. {
  128. }
  129. CGameServer::~CGameServer()
  130. {
  131. /*
  132.  * If we want to be informed of any buffers or sockets being destroyed at destruction 
  133.  * time then we need to release these resources now, whilst we, the derived class,
  134.  * still exists. Once our destructor exits and the base destructor takes over we wont 
  135.  * get any more notifications...
  136.  */
  137. try
  138. {
  139. ReleaseSockets();
  140. ReleaseBuffers();
  141. }
  142. catch(...)
  143. {
  144. }
  145. }
  146. SOCKET CGameServer::CreateListeningSocket( unsigned long address, unsigned short port )
  147. {
  148. SOCKET s = ::WSASocket( AF_INET, SOCK_STREAM, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED );
  149. if ( INVALID_SOCKET == s )
  150. {
  151. throw CWin32Exception( _T("CSocket::CreateListeningSocket()"), ::WSAGetLastError() );
  152. }
  153. CSocket listeningSocket( s );
  154. CSocket::InternetAddress localAddress( address, port );
  155. listeningSocket.Bind( localAddress );
  156. listeningSocket.Listen( 5 );
  157. return listeningSocket.Detatch();
  158. }
  159. OnlineGameLib::Win32::CSocketServer::WorkerThread *CGameServer::CreateWorkerThread( 
  160. OnlineGameLib::Win32::CIOCompletionPort &iocp )
  161. {
  162. Output( _T("CreateWorkerThread") );
  163. return new CGameServerWorkerThread( iocp, m_refClientManager );
  164. }
  165. void CGameServer::OnStartAcceptingConnections()
  166. {
  167. Output( _T("OnStartAcceptingConnections") );
  168. }
  169. void CGameServer::OnStopAcceptingConnections()
  170. {
  171. Output( _T("OnStopAcceptingConnections") );
  172. }
  173.       
  174. void CGameServer::OnShutdownInitiated()
  175. {
  176. Output( _T("OnShutdownInitiated") );
  177. }
  178.       
  179. void CGameServer::OnShutdownComplete()
  180. {
  181. Output( _T("OnShutdownComplete") );
  182. }
  183. void CGameServer::OnConnectionEstablished(
  184. OnlineGameLib::Win32::CSocketServer::Socket *pSocket, 
  185. OnlineGameLib::Win32::CIOBuffer * pAddress )
  186. {
  187. Output( _T("OnConnectionEstablished") );
  188. /*
  189.  * Add Client
  190.  */
  191. m_refClientManager.AddClient( pSocket );
  192. pSocket->Read();
  193. }
  194. void CGameServer::OnConnectionClosed( 
  195. OnlineGameLib::Win32::CSocketServer::Socket * pSocket )
  196. {
  197. /*
  198.  * Delete client
  199.  */
  200. m_refClientManager.DelClient( pSocket );
  201. Output( _T("OnConnectionClosed") );
  202. }
  203. void CGameServer::OnConnectionCreated()
  204. {
  205. Output( _T("OnConnectionCreated") );
  206. }
  207. void CGameServer::OnConnectionDestroyed()
  208. {
  209. Output( _T("OnConnectionDestroyed") );
  210. }
  211. void CGameServer::OnError( const OnlineGameLib::Win32::_tstring &message )
  212. {
  213. Output( _T("OnError - ") + message );
  214. }
  215. void CGameServer::PreWrite( 
  216. OnlineGameLib::Win32::CSocketServer::Socket *pSocket, 
  217. OnlineGameLib::Win32::CIOBuffer *pBuffer, 
  218. const char *pData, 
  219. size_t dataLength )
  220. {
  221. /*
  222.  * TODO : You can change protocol that it is used to split package
  223.  */
  224. if ( pBuffer && dataLength > 0 )
  225. {
  226. PACK_HEADER ph = {0};
  227. ph.cPackBeginFlag = PACK_BEGIN_FLAG;
  228. ph.cPackEndFlag = PACK_END_FLAG;
  229. ph.wDataLen = dataLength;
  230. ph.wCRCData = MAKE_CRC_DATE( PACK_BEGIN_FLAG, PACK_END_FLAG, dataLength );
  231. pBuffer->AddData( reinterpret_cast<const char *>( &ph ), PACK_HEADER_LEN );
  232. }
  233. }
  234. STDMETHODIMP CClientManager::Startup()
  235. {
  236. HRESULT hr = E_FAIL;
  237. try
  238. {
  239. m_theGameServer.Start();
  240. hr = S_OK;
  241. }
  242. catch( const CException &e )
  243. {
  244. Output( _T("CClientManager::Startup Exception: ") + e.GetWhere() + _T(" - ") + e.GetMessage() );
  245. }
  246. catch(...)
  247. {
  248. Output( _T("CClientManager::Startup - Unexpected exception") );
  249. }
  250. return hr;
  251. }
  252. STDMETHODIMP CClientManager::Cleanup()
  253. {
  254. HRESULT hr = E_FAIL;
  255. try
  256. {
  257. m_theGameServer.StopAcceptingConnections();
  258. m_theGameServer.WaitForShutdownToComplete();
  259. hr = S_OK;
  260. }
  261. catch( const CException &e )
  262. {
  263. Output( _T("CClientManager::Cleanup Exception: ") + e.GetWhere() + _T(" - ") + e.GetMessage() );
  264. }
  265. catch(...)
  266. {
  267. Output( _T("CClientManager::Cleanup - Unexpected exception") );
  268. }
  269. return hr;
  270. }
  271. STDMETHODIMP CClientManager::OpenService(
  272. const unsigned long &ulnAddressToListenOn,
  273. const unsigned short &usnPortToListenOn )
  274. {
  275. HRESULT hr = E_FAIL;
  276. try
  277. {
  278. m_theGameServer.Open( ulnAddressToListenOn, usnPortToListenOn );
  279. m_theGameServer.StartAcceptingConnections();
  280. hr = S_OK;
  281. }
  282. catch( const CException &e )
  283. {
  284. Output( _T("CClientManager::OpenService Exception: ") + e.GetWhere() + _T(" - ") + e.GetMessage() );
  285. }
  286. catch(...)
  287. {
  288. Output( _T("CClientManager::OpenService - Unexpected exception") );
  289. }
  290. return hr;
  291. }
  292. STDMETHODIMP CClientManager::CloseService()
  293. {
  294. HRESULT hr = E_FAIL;
  295. try
  296. {
  297. m_theGameServer.StopAcceptingConnections();
  298. hr = S_OK;
  299. }
  300. catch( const CException &e )
  301. {
  302. Output( _T("CClientManager::CloseService Exception: ") + e.GetWhere() + _T(" - ") + e.GetMessage() );
  303. }
  304. catch(...)
  305. {
  306. Output( _T("CClientManager::CloseService - Unexpected exception") );
  307. }
  308. return hr;
  309. }
  310. STDMETHODIMP CClientManager::RegisterMsgFilter( CALLBACK_SERVER_EVENT pfnEventNotify )
  311. {
  312. m_pfnCallBackServerEvent = pfnEventNotify;
  313. return S_OK;
  314. }
  315. STDMETHODIMP CClientManager::PreparePackSink( )
  316. {
  317. // CCriticalSection::Owner lock( m_csSystemAction );
  318. return S_OK;
  319. }
  320. STDMETHODIMP CClientManager::PackDataToClient(
  321. const unsigned long &ulnClientID,
  322. const void * const pData,
  323. const size_t &datalength )
  324. {
  325. HRESULT hr = E_FAIL;
  326. if ( ulnClientID >= 0 && ulnClientID < MAX_CLIENT_CANBELINKED )
  327. {
  328. OnlineGameLib::Win32::CSocketServer::Socket *pSocket = 
  329. m_clientContext[ulnClientID].pSocket;
  330. if ( pSocket )
  331. {
  332. CCriticalSection::Owner locker( m_clientContext[ulnClientID].csWriteAction );
  333. try
  334. {
  335. m_clientContext[ulnClientID].pWriteBuffer->AddData( static_cast<const char * const>( pData ), datalength );
  336. hr = S_OK;
  337. }
  338. catch( const CException &e )
  339. {
  340. Output( _T("CClientManager::PackDataToClient Exception: ") + e.GetWhere() + _T(" - ") + e.GetMessage() );
  341. pSocket->Shutdown();
  342. }
  343. catch(...)
  344. {
  345. Output( _T("CClientManager::PackDataToClient - Unexpected exception") );
  346. pSocket->Shutdown();
  347. }
  348. }
  349. }
  350. return hr;
  351. }
  352. STDMETHODIMP CClientManager::SendPackToClient( )
  353. {
  354. CCriticalSection::Owner lock( m_csSystemAction );
  355. HRESULT hr = E_FAIL;
  356. for ( std_LIST::iterator i = m_usedClientStack.begin(); i != m_usedClientStack.end(); i ++ )
  357. {
  358. int nID = *i;
  359. CCriticalSection::Owner locker( m_clientContext[nID].csWriteAction );
  360. const BYTE * pPackData = m_clientContext[nID].pWriteBuffer->GetBuffer();
  361. const size_t used = m_clientContext[nID].pWriteBuffer->GetUsed();
  362. if ( used > 0 )
  363. {
  364. //[
  365. #ifdef  NETWORK_DEBUG
  366. //{
  367. static const DWORD sc_dwFlag = 0xABCD0000; // End of stream
  368. static const int sc_nFlagLen = sizeof(DWORD) * 2;
  369. DWORD dwEOSFlag[2];
  370. dwEOSFlag[0] = gsc_dwPackID ++;
  371. dwEOSFlag[1] = sc_dwFlag | ( 0xFFFF & used );
  372. m_clientContext[nID].pWriteBuffer->AddData( reinterpret_cast<const char *>( &dwEOSFlag ), sc_nFlagLen );
  373. m_clientContext[nID].pSocket->Write( reinterpret_cast<const char *>( pPackData ), used + sc_nFlagLen );
  374. /* #undef NETWORK_DEBUG_TRACE2FILE
  375. #ifdef NETWORK_DEBUG_TRACE2FILE
  376. //{
  377. Trace2File( _T("Package[ID:") + ToString( gsc_dwPackID - 1 ) + _T("]n") + DumpData( pPackData, used, 50 ) );
  378. //}
  379. #else
  380. //{
  381. Output( _T("NO.[ID:") +
  382. ToString( gsc_dwPackID - 1 ) +
  383. _T("]Pack - Len:") +
  384. ToString( used )
  385. );
  386. //}
  387. #endif // NETWORK_DEBUG_TRACE_MININFO
  388. */
  389. //}
  390. #else // NETWORK_DEBUG
  391. //{
  392. m_clientContext[nID].pSocket->Write( reinterpret_cast<const char *>( pPackData ), used );
  393. //}
  394. #endif  // NETWORK_DEBUG
  395. //]
  396. /* Output(
  397. _T("ID:") + 
  398. ToString(nID) + 
  399. _T(" - Package[length:") + 
  400. ToString( used ) + 
  401. _T("]n") + 
  402. DumpData( pPackData, used, 50 ) 
  403. );
  404. */
  405. }
  406. m_clientContext[nID].pWriteBuffer->Empty();
  407. hr = S_OK;
  408. }
  409. return hr;
  410. }
  411. STDMETHODIMP_( const void * ) CClientManager::GetPackFromClient(
  412. const unsigned long &ulnClientID,
  413. size_t &datalength )
  414. {
  415. if ( ulnClientID >= 0 && ulnClientID < MAX_CLIENT_CANBELINKED )
  416. {
  417. OnlineGameLib::Win32::CSocketServer::Socket *pSocket = 
  418. m_clientContext[ulnClientID].pSocket;
  419. if ( pSocket )
  420. {
  421. CCriticalSection::Owner locker( m_clientContext[ulnClientID].csReadAction );
  422. m_clientContext[ulnClientID].pReadBuffer->Empty();
  423. m_clientContext[ulnClientID].pRecvBuffer = ProcessDataStream(
  424. ulnClientID,
  425. m_clientContext[ulnClientID].pRecvBuffer );
  426. const BYTE *pPackData = m_clientContext[ulnClientID].pReadBuffer->GetBuffer();
  427. datalength = m_clientContext[ulnClientID].pReadBuffer->GetUsed();
  428.  
  429. return reinterpret_cast<const char*>( pPackData );
  430. }
  431. }
  432. datalength = 0;
  433. return NULL;
  434. }
  435. STDMETHODIMP CClientManager::ShutdownClient( const unsigned long &ulnClientID )
  436. {
  437. CCriticalSection::Owner lock( m_csSystemAction );
  438. if ( ulnClientID >= 0 && ulnClientID < MAX_CLIENT_CANBELINKED )
  439. {
  440. OnlineGameLib::Win32::CSocketServer::Socket *pSocket = 
  441. m_clientContext[ulnClientID].pSocket;
  442. if ( pSocket )
  443. {
  444. pSocket->Close();
  445. pSocket = NULL;
  446. m_clientContext[ulnClientID].pReadBuffer->Empty();
  447. m_clientContext[ulnClientID].pRecvBuffer->Empty();
  448. m_clientContext[ulnClientID].pWriteBuffer->Empty();
  449. }
  450. }
  451. return S_OK;
  452. }
  453. STDMETHODIMP_( size_t ) CClientManager::GetClientCount( )
  454. {
  455. CCriticalSection::Owner lock( m_csSystemAction );
  456. return m_usedClientStack.size();
  457. }
  458. STDMETHODIMP CClientManager::QueryInterface( REFIID riid, void** ppv )
  459. {
  460. /*
  461.  * By definition all COM objects support the IUnknown interface
  462.  */
  463. if( riid == IID_IUnknown )
  464. {
  465. AddRef();
  466. *ppv = dynamic_cast< IUnknown * >( this );
  467. }
  468. else if ( riid == IID_IIOCPServer )
  469. {
  470. AddRef();
  471. *ppv = dynamic_cast< IServer * >( this );
  472. }
  473. else
  474. {
  475. *ppv = NULL;
  476. return E_NOINTERFACE;
  477. }
  478. return S_OK;
  479. }
  480.     
  481. STDMETHODIMP_(ULONG) CClientManager::AddRef()
  482. {
  483. return InterlockedIncrement( &m_lRefCount );
  484. }
  485. STDMETHODIMP_(ULONG) CClientManager::Release()
  486. {
  487. if ( InterlockedDecrement( &m_lRefCount ) > 0 )
  488. {
  489. return m_lRefCount;
  490. }
  491. delete this;
  492. return 0L;
  493. }
  494. CClientManager::CClientManager( size_t maxFreeBuffers, size_t bufferSize /*1024*/ )
  495. : OnlineGameLib::Win32::CIOBuffer::Allocator( bufferSize, maxFreeBuffers )
  496. , m_lRefCount( 0L )
  497. , m_theGameServer( *this, MAX_SOCKET_KEEPINPOOL, MAX_BUFFER_KEEPINPOOL, EXTEND_BUFFER_SIZE )
  498. , m_pfnCallBackServerEvent( NULL )
  499. {
  500. int i=0;
  501. for ( i=0; i<MAX_CLIENT_CANBELINKED; i++ )
  502. {
  503. m_freeClientStack.push( i );
  504. }
  505. for ( i=0; i<MAX_CLIENT_CANBELINKED; i++ )
  506. {
  507. m_clientContext[i].pSocket = NULL;
  508. m_clientContext[i].pRecvBuffer = Allocate();
  509. m_clientContext[i].pReadBuffer = Allocate();
  510. m_clientContext[i].pWriteBuffer = Allocate();
  511. }
  512. }
  513. CClientManager::~CClientManager()
  514. {
  515. CCriticalSection::Owner lock( m_csSystemAction );
  516. /*
  517.      * Repeat until stack is empty
  518.  */
  519. while ( !m_freeClientStack.empty() )
  520. {
  521. m_freeClientStack.pop();
  522. }
  523. m_usedClientStack.erase( m_usedClientStack.begin(), m_usedClientStack.end() );
  524. for ( int i=0; i<MAX_CLIENT_CANBELINKED; i++ )
  525. {
  526. m_clientContext[i].pReadBuffer->Release();
  527. m_clientContext[i].pRecvBuffer->Release();
  528. m_clientContext[i].pWriteBuffer->Release();
  529. }
  530. try
  531. {
  532. Flush();
  533. }
  534. catch(...)
  535. {
  536. /*
  537.  * Some error was found, what are you doing now?
  538.  */
  539. }
  540. }
  541. unsigned long CClientManager::AddClient( 
  542. OnlineGameLib::Win32::CSocketServer::Socket *pSocket )
  543. {
  544. CCriticalSection::Owner lock( m_csSystemAction );
  545. unsigned long index = -1;
  546. if ( !m_freeClientStack.empty() && pSocket )
  547. {
  548. /*
  549.  * Get ID from the free table
  550.  */
  551. index = m_freeClientStack.top();
  552. m_freeClientStack.pop();
  553. /*
  554.  * Set ID into the used table
  555.  */
  556. m_usedClientStack.push_back( index );
  557. /*
  558.  * Store information
  559.  */
  560. pSocket->SetUserData( index );
  561. m_clientContext[index].pSocket = pSocket;
  562. if ( m_pfnCallBackServerEvent )
  563. {
  564. m_pfnCallBackServerEvent( index, CLIENT_CONNECT_CREATE );
  565. }
  566. Output( GetTimeStamp() + _T("Add a client [ID:") + 
  567. ToString( index ) + _T( "] current total is " ) +
  568. ToString( m_usedClientStack.size() )
  569. );
  570. }
  571. return index;
  572. }
  573. unsigned long CClientManager::DelClient(
  574. OnlineGameLib::Win32::CSocketServer::Socket *pSocket )
  575. {
  576. CCriticalSection::Owner lock( m_csSystemAction );
  577. unsigned long index = -1;
  578. if ( !m_usedClientStack.empty() && pSocket )
  579. {
  580. index = pSocket->GetUserData();
  581. m_clientContext[index].pSocket = NULL;
  582. m_clientContext[index].pReadBuffer->Empty();
  583. m_clientContext[index].pRecvBuffer->Empty();
  584. m_clientContext[index].pWriteBuffer->Empty();
  585. /*
  586.  * Call back ID into the free table
  587.  */
  588. m_freeClientStack.push( index );
  589. /*
  590.  * Erase ID from the used table
  591.  */
  592. m_usedClientStack.remove( index );
  593. if ( m_pfnCallBackServerEvent )
  594. {
  595. m_pfnCallBackServerEvent( index, CLIENT_CONNECT_CLOSE );
  596. }
  597. Output( GetTimeStamp() + _T("Del a client [ID:") + 
  598. ToString( index ) + _T( "] current total is " ) + 
  599. ToString( m_usedClientStack.size() ) );
  600. }
  601. return index;
  602. }
  603. void CClientManager::RecvFromClient(
  604.    const unsigned long &ulnID,
  605.    const char *pData,
  606.    size_t dataLength )
  607. {
  608. if ( ulnID >= 0 && ulnID < MAX_CLIENT_CANBELINKED )
  609. {
  610. OnlineGameLib::Win32::CSocketServer::Socket *pSocket = 
  611. m_clientContext[ulnID].pSocket;
  612. if ( pSocket )
  613. {
  614. CCriticalSection::Owner locker( m_clientContext[ulnID].csReadAction );
  615. m_clientContext[ulnID].pRecvBuffer->AddData( pData, dataLength );
  616. }
  617. }
  618. }
  619. void CClientManager::ProcessCommand(
  620.    const unsigned long &ulnID,
  621.    const OnlineGameLib::Win32::CIOBuffer *pBuffer) const
  622. {
  623. const BYTE *pPackData = pBuffer->GetBuffer();
  624. const size_t used = pBuffer->GetUsed();
  625. bool ok = false;
  626. WORD wDataLen = 0;
  627. PACK_HEADER ph = {0};
  628. if ( used > PACK_HEADER_LEN )
  629. {
  630. memcpy( &ph, pPackData, PACK_HEADER_LEN );
  631. wDataLen = ph.wDataLen;
  632. ok = true;
  633. }
  634. if ( ok )
  635. {
  636. const BYTE *pData = pPackData + PACK_HEADER_LEN;
  637. const size_t datalength = wDataLen;
  638. /*
  639.  * TODO : Process data receive from client
  640.  */
  641. //Output( _T("Get a package[length:") + ToString( wDataLen ) + _T("]n") + DumpData( pData, datalength, 50 ) );
  642. m_clientContext[ulnID].pReadBuffer->AddData( pData, datalength );
  643. }
  644. else
  645. {
  646. Output( "found error and close this socket!" );
  647. m_clientContext[ulnID].pSocket->Close();
  648. }
  649. }
  650. size_t CClientManager::GetMinimumMessageSize() const
  651. {
  652. /*
  653.  * The smallest possible package we accept is pack-header
  654.  * once we have this many bytes we can start with try and work out
  655.  * what we have...
  656.  */
  657. return PACK_HEADER_LEN;
  658. }
  659. size_t CClientManager::GetMessageSize(
  660. const OnlineGameLib::Win32::CIOBuffer *pBuffer ) const
  661. {
  662. const BYTE *pData = pBuffer->GetBuffer();
  663. const size_t used = pBuffer->GetUsed();
  664. PACK_HEADER ph = {0};
  665. /*
  666.  * First, verify the flag of a message
  667.  */
  668. if ( used > PACK_HEADER_LEN )
  669. {
  670. memcpy( &ph, pData, PACK_HEADER_LEN );
  671. if ( PACK_BEGIN_FLAG == ph.cPackBeginFlag && 
  672.  PACK_END_FLAG == ph.cPackEndFlag )
  673. {
  674. WORD wCRC = MAKE_CRC_DATE( PACK_BEGIN_FLAG, PACK_END_FLAG, ph.wDataLen );
  675. if ( ph.wCRCData == wCRC )
  676. {
  677. return ph.wDataLen + PACK_HEADER_LEN;
  678. }
  679. }
  680. }
  681. return 0;
  682. }
  683. OnlineGameLib::Win32::CIOBuffer *CClientManager::ProcessDataStream(
  684. const unsigned long &ulnID,
  685. OnlineGameLib::Win32::CIOBuffer *pBuffer) const
  686. {
  687. const size_t used = pBuffer->GetUsed();
  688. if ( used >= GetMinimumMessageSize() )
  689. {
  690. const size_t messageSize = GetMessageSize( pBuffer );
  691. if ( messageSize == 0 )
  692. {
  693. /*
  694.  * havent got a complete message yet.
  695.  * we null terminate our messages in the buffer, so we need to reserve
  696.  * a byte of the buffer for this purpose...
  697.  */
  698. if ( used == ( pBuffer->GetSize() - 1 ) )
  699. {
  700. Output( _T("Too much data!") );
  701. /*
  702.  * Write this message and then shutdown the sending side of the socket.
  703.  */
  704. Output( "found error and close this socket!" );
  705. m_clientContext[ulnID].pSocket->Close();
  706. /*
  707.  * throw the rubbish away
  708.  */
  709. pBuffer->Empty();
  710. }
  711. }
  712. else if ( used == messageSize )
  713. {
  714. Output( _T("Got a complete message and begin to process it") );
  715. /*
  716.  * we have a whole, distinct, message
  717.  */
  718. ProcessCommand( ulnID, pBuffer );
  719. pBuffer->Empty();
  720. }
  721. else if ( used > messageSize )
  722. {
  723. Output( _T("Got message plus extra data") );
  724. /*
  725.  * we have a message, plus some more data
  726.  * 
  727.  * allocate a new buffer, copy the extra data into it and try again...
  728.  */
  729. OnlineGameLib::Win32::CIOBuffer *pMessage = 
  730. pBuffer->SplitBuffer( messageSize );
  731. ProcessCommand( ulnID, pMessage );
  732. pMessage->Release();
  733. }
  734. }
  735. /*
  736.  * Reissue a read into the same buffer to collect more data
  737.  */
  738. return pBuffer;
  739. }