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

模拟服务器

开发平台:

C/C++

  1. #include "ServerStage.h" 
  2. #include <time.h>
  3. #include <process.h> //Thread define
  4. #include "KSG_EncodeDecode.h"
  5. #include "Cipher.h"
  6. #include "Macro.h"
  7. #include "Exception.h"
  8. #include "SocketAddress.h"
  9. #include "Utils.h"
  10. #include "Win32Exception.h"
  11. using OnlineGameLib::Win32::CIOBuffer;
  12. using OnlineGameLib::Win32::CWin32Exception;
  13. using OnlineGameLib::Win32::_tstring;
  14. using OnlineGameLib::Win32::CCriticalSection;
  15. using OnlineGameLib::Win32::CException;
  16. using OnlineGameLib::Win32::Output;
  17. using OnlineGameLib::Win32::DumpData;
  18. using OnlineGameLib::Win32::GetTimeStamp;
  19. using OnlineGameLib::Win32::ToString;
  20. using OnlineGameLib::Win32::Trace;
  21. using OnlineGameLib::Win32::CSocketAddress;
  22. /*
  23.  * Get server factory interface
  24.  */
  25. STDAPI CreateInterface( REFIID riid, void **ppv )
  26. {
  27. HRESULT hr = E_NOINTERFACE;
  28. if ( IID_IServerFactory == riid )
  29. {
  30. CServerFactory *pObject = new CServerFactory;
  31. *ppv = reinterpret_cast< void * > ( dynamic_cast< IServerFactory * >( pObject ) );
  32. if ( *ppv )
  33. {
  34. reinterpret_cast< IUnknown * >( *ppv )->AddRef();
  35. hr = S_OK;
  36. }
  37. }
  38. if ( FAILED( hr ) )
  39. {
  40. *ppv = NULL;
  41. }
  42. return ( HRESULT )( hr );
  43. }
  44. /*
  45.  * Local per connection data
  46.  */
  47. class CPerConnectionData
  48. {
  49. public:
  50.       
  51. explicit CPerConnectionData( const _tstring &address, WPARAM wParam, const LPARAM &lParam )
  52.          : m_address( address ), m_wParam( wParam ), m_lParam( lParam )
  53. {
  54. }
  55. void SetConnectionFirstParam( WPARAM wParam )
  56. {
  57. m_wParam = wParam;
  58. }
  59. WPARAM GetConnectionFirstParam() const
  60. {
  61. return m_wParam;
  62. }
  63. LPARAM GetConnectionSecondParam() const
  64. {
  65. return m_lParam;
  66. }
  67. _tstring GetConnectionDetails() const
  68. {
  69.          return m_address;
  70. }
  71. private:
  72. const _tstring m_address;
  73. const LPARAM m_lParam;
  74. WPARAM m_wParam;
  75. /*
  76.  * No copies, do not implement
  77.  */
  78. CPerConnectionData( const CPerConnectionData &rhs );
  79. CPerConnectionData &operator=( const CPerConnectionData &rhs );
  80. };
  81. CIOCPServer::CTaskQueue::~CTaskQueue()
  82. {
  83. CCriticalSection::Owner locker( m_cs );
  84. while ( !m_theTaskStack.empty() )
  85. {
  86. m_theTaskStack.pop();
  87. }
  88. }
  89. void CIOCPServer::CTaskQueue::Push( void *pItem )
  90. {
  91. CCriticalSection::Owner locker( m_cs );
  92. m_theTaskStack.push( pItem );
  93. }
  94. void *CIOCPServer::CTaskQueue::Pop()
  95. {
  96. CCriticalSection::Owner locker( m_cs );
  97. void *pItem = NULL;
  98. if ( !m_theTaskStack.empty() )
  99. {
  100. pItem = m_theTaskStack.top();
  101. m_theTaskStack.pop();
  102. }
  103. return pItem;
  104. }
  105. static unsigned gs_holdrand = time(NULL);
  106. static inline unsigned _Rand()
  107. {
  108.     gs_holdrand = gs_holdrand * 214013L + 2531011L;
  109.      
  110.     return gs_holdrand;
  111. }
  112. static inline void RandMemSet(int nSize, unsigned char *pbyBuffer)
  113. {
  114.     _ASSERT(nSize);
  115.     _ASSERT(pbyBuffer);
  116.     while (nSize--)
  117.     {
  118.         *pbyBuffer++ = (unsigned char)_Rand();
  119.     }
  120. }
  121. CIOCPServer::CIOCPServer( size_t nPlayerMaxCount,
  122. size_t nPrecision,
  123. size_t maxFreeSockets,
  124. size_t maxFreeBuffers,
  125. size_t maxFreeBuffers_Cache,
  126. size_t bufferSize_Cache /*= 8192*/,
  127. size_t bufferSize /*= 1024*/,
  128. size_t numThreads /*= 0*/ )
  129. : OnlineGameLib::Win32::CSocketServer( maxFreeSockets, maxFreeBuffers, bufferSize, numThreads )
  130. , m_theCacheAllocator( bufferSize_Cache, maxFreeBuffers_Cache )
  131. , m_lRefCount( 0 )
  132. , m_nPlayerMaxCount( nPlayerMaxCount )
  133. , m_nPrecision( nPrecision )
  134. , m_nNetworkBufferMaxLen( bufferSize - 32 /* sizeof( protocol of network ) */ )
  135. , m_pfnCallBackServerEvent( NULL )
  136. , m_hQuitHelper( NULL, true, false, NULL /*"EVENT_IOCPSVR_QUIT"*/ )
  137. , m_hHelperThread( NULL )
  138. {
  139. /*
  140.  * m_nNetworkBufferMaxLen > 0
  141.  */
  142. ASSERT( !( m_nNetworkBufferMaxLen & 0x80000000 ) );
  143. size_t index = 0;
  144. for ( index = 0; index < nPlayerMaxCount; index ++ )
  145. {
  146. {
  147. CCriticalSection::Owner locker( m_csFCN );
  148. //m_freeClientNode.push( index );
  149. m_freeClientNode.push( index );
  150. }
  151. /*
  152.  * Create a client node and add it into list
  153.  */
  154. LPCLIENT_NODE pCN = new CLIENT_NODE;
  155. pCN->pSocket = NULL;
  156. pCN->pRecvBuffer = m_theCacheAllocator.Allocate();
  157. pCN->pReadBuffer = m_theCacheAllocator.Allocate();
  158. pCN->pWriteBuffer = m_theCacheAllocator.Allocate();
  159. {
  160. CCriticalSection::Owner locker( m_csCM );
  161. m_theClientManager[index] = pCN;
  162. }
  163. }
  164. unsigned int threadID = 0;
  165. m_hHelperThread = (HANDLE)::_beginthreadex( 0, 
  166. 0, 
  167. HelperThreadFunction,
  168. ( void * )this, 
  169. 0, 
  170. &threadID );
  171. if ( m_hHelperThread == INVALID_HANDLE_VALUE )
  172. {
  173. throw CWin32Exception( _T("CIOCPServer::CIOCPServer() - _beginthreadex"), GetLastError() );
  174. }
  175. }
  176. CIOCPServer::~CIOCPServer()
  177. {
  178. /*
  179.      * Repeat until stack is empty
  180.  */
  181. {
  182. CCriticalSection::Owner locker( m_csFCN );
  183. while ( !m_freeClientNode.empty() )
  184. {
  185. m_freeClientNode.pop();
  186. }
  187. /* while ( !m_freeClientNode.empty() )
  188. {
  189. m_freeClientNode.pop();
  190. }
  191. */
  192. }
  193. {
  194. CCriticalSection::Owner locker( m_csCM );
  195. m_usedClientNode.erase( m_usedClientNode.begin(), m_usedClientNode.end() );
  196. CLIENT_MANAGER::iterator it;
  197. for ( it = m_theClientManager.begin(); it != m_theClientManager.end(); it ++ )
  198. {
  199. LPCLIENT_NODE pCN = ( LPCLIENT_NODE )( ( *it ).second );
  200. if ( pCN )
  201. {
  202. pCN->pRecvBuffer->Release();
  203. pCN->pReadBuffer->Release();
  204. pCN->pWriteBuffer->Release();
  205. }
  206. SAFE_DELETE( pCN );
  207. }
  208. m_theClientManager.erase( m_theClientManager.begin(), m_theClientManager.end() );
  209. }
  210. m_hQuitHelper.Set();
  211. if ( WAIT_TIMEOUT == ::WaitForSingleObject( m_hHelperThread, 5000 ) )
  212. {
  213. ::TerminateThread( m_hHelperThread, 0L );
  214. }
  215. }
  216. STDMETHODIMP CIOCPServer::Startup( )
  217. {
  218. HRESULT hr = E_FAIL;
  219. try
  220. {
  221. Start();
  222. hr = S_OK;
  223. }
  224. catch( const CException &e )
  225. {
  226. Output( _T("CIOCPServer::Startup Exception: ") + e.GetWhere() + _T(" - ") + e.GetMessage() );
  227. }
  228. catch(...)
  229. {
  230. Output( _T("CIOCPServer::Startup - Unexpected exception") );
  231. }
  232. return hr;
  233. }
  234. STDMETHODIMP CIOCPServer::Cleanup( )
  235. {
  236. HRESULT hr = E_FAIL;
  237. try
  238. {
  239. StopAcceptingConnections();
  240. WaitForShutdownToComplete();
  241. hr = S_OK;
  242. }
  243. catch( const CException &e )
  244. {
  245. Output( _T("CIOCPServer::Cleanup Exception: ") + e.GetWhere() + _T(" - ") + e.GetMessage() );
  246. }
  247. catch(...)
  248. {
  249. Output( _T("CIOCPServer::Cleanup - Unexpected exception") );
  250. }
  251. return hr;
  252. }
  253. STDMETHODIMP CIOCPServer::OpenService( const unsigned long &ulnAddressToListenOn,
  254. const unsigned short &usnPortToListenOn )
  255. {
  256. HRESULT hr = E_FAIL;
  257. try
  258. {
  259. Open( ulnAddressToListenOn, usnPortToListenOn );
  260. StartAcceptingConnections();
  261. hr = S_OK;
  262. }
  263. catch( const CException &e )
  264. {
  265. Output( _T("CIOCPServer::OpenService Exception: ") + e.GetWhere() + _T(" - ") + e.GetMessage() );
  266. }
  267. catch(...)
  268. {
  269. Output( _T("CIOCPServer::OpenService - Unexpected exception") );
  270. }
  271. return hr;
  272. }
  273. STDMETHODIMP CIOCPServer::CloseService()
  274. {
  275. HRESULT hr = E_FAIL;
  276. try
  277. {
  278. StopAcceptingConnections();
  279. hr = S_OK;
  280. }
  281. catch( const CException &e )
  282. {
  283. Output( _T("CIOCPServer::CloseService Exception: ") + e.GetWhere() + _T(" - ") + e.GetMessage() );
  284. }
  285. catch(...)
  286. {
  287. Output( _T("CIOCPServer::CloseService - Unexpected exception") );
  288. }
  289. return hr;
  290. }
  291. STDMETHODIMP CIOCPServer::RegisterMsgFilter( LPVOID lpParam, 
  292. CALLBACK_SERVER_EVENT pfnEventNotify )
  293. {
  294. m_lpCallBackParam = lpParam;
  295. m_pfnCallBackServerEvent = pfnEventNotify;
  296. return S_OK;
  297. }
  298. STDMETHODIMP CIOCPServer::PreparePackSink( )
  299. {
  300. return S_OK;
  301. }
  302. STDMETHODIMP CIOCPServer::PackDataToClient( const unsigned long &ulnClientID,
  303. const void * const pData,
  304. const size_t &datalength )
  305. {
  306. HRESULT hr = E_FAIL;
  307. if ( ulnClientID < m_nPlayerMaxCount && datalength > 0 )
  308. {
  309. LPCLIENT_NODE pCN = NULL;
  310. CCriticalSection::Owner locker( m_csCM );
  311. pCN = ( LPCLIENT_NODE )( m_theClientManager[ulnClientID] );
  312. if ( pCN && pCN->pSocket )
  313. {
  314. try
  315. {
  316. CCriticalSection::Owner lock( pCN->csWriteAction );
  317. CIOBuffer *pWriteBuffer = pCN->pWriteBuffer;
  318. const size_t nNetworkBufferLen = pWriteBuffer->GetUsed();
  319. if ( ( nNetworkBufferLen >= m_nNetworkBufferMaxLen ) || 
  320. ( nNetworkBufferLen + datalength >= m_nNetworkBufferMaxLen ) )
  321. {
  322. /*
  323.  * It need send to client at once, because of buffer is full
  324.  */
  325. const BYTE *pPackData = pWriteBuffer->GetBuffer();
  326. const size_t used = pWriteBuffer->GetUsed();
  327. _SendDataEx( pCN, pPackData, used );
  328. pWriteBuffer->Empty();
  329. }
  330. pWriteBuffer->AddData( static_cast< const char * const >( pData ), datalength );
  331. hr = S_OK;
  332. }
  333. catch( const CException &e )
  334. {
  335. Output( _T("CIOCPServer::PackDataToClient Exception: ") + e.GetWhere() + _T(" - ") + e.GetMessage() );
  336. pCN->pSocket->Shutdown();
  337. }
  338. catch(...)
  339. {
  340. Output( _T("CIOCPServer::PackDataToClient - Unexpected exception") );
  341. pCN->pSocket->Shutdown();
  342. }
  343. }
  344. }
  345. return hr;
  346. }
  347. STDMETHODIMP CIOCPServer::SendPackToClient( const unsigned long &ulnClientID /* -1 */ )
  348. {
  349. HRESULT hr = E_FAIL;
  350. static const size_t s_len_protocol = sizeof( WORD );
  351. CCriticalSection::Owner locker( m_csCM );
  352. LIST::iterator it;
  353. for ( it = m_usedClientNode.begin(); it != m_usedClientNode.end(); it ++ )
  354. {
  355. size_t index = ( size_t )( *it );
  356. LPCLIENT_NODE pCN = NULL;
  357. pCN = ( LPCLIENT_NODE )( m_theClientManager[index] );
  358. if ( pCN && pCN->pSocket )
  359. {
  360. CIOBuffer *pBuffer = NULL;
  361. try
  362. {
  363. pBuffer = Allocate();
  364. /*
  365. * Add data into buffer that it is will be send
  366. */
  367. bool ok = false;
  368. {
  369. CCriticalSection::Owner lock( pCN->csWriteAction );
  370. const BYTE * pPackData = pCN->pWriteBuffer->GetBuffer();
  371. const size_t used = pCN->pWriteBuffer->GetUsed();
  372. if ( used > 0 )
  373. {
  374. /*
  375.  * Add package header
  376.  */
  377. const size_t headlength = s_len_protocol + used;
  378. pBuffer->AddData( reinterpret_cast< const char * >( &headlength ), s_len_protocol );
  379. pBuffer->AddData( reinterpret_cast< const char * >( pPackData ), used );
  380.                 _ASSERT(pCN->uKeyMode == 0);
  381. KSG_EncodeBuf(
  382. used,
  383. (unsigned char *)(pBuffer->GetBuffer() + s_len_protocol),
  384.                             &pCN->uServerKey
  385. );
  386. ok = true;
  387. }
  388. pCN->pWriteBuffer->Empty();
  389. }
  390. if ( ok )
  391. {
  392. pCN->pSocket->Write( pBuffer, true );
  393. }
  394. pBuffer->Release();
  395. hr = S_OK;
  396. }
  397. catch( const CException &e )
  398. {
  399. // add by spe 2003/07/06
  400. if (pBuffer)
  401. {
  402. pBuffer->Release();
  403. pBuffer = NULL;
  404. }
  405. Output( _T("CIOCPServer::SendPackToClient Exception: ") + e.GetWhere() + _T(" - ") + e.GetMessage() );
  406. pCN->pSocket->Shutdown();
  407. }
  408. catch(...)
  409. {
  410. // add by spe 2003/07/06
  411. if (pBuffer)
  412. {
  413. pBuffer->Release();
  414. pBuffer = NULL;
  415. }
  416. Output( _T("CIOCPServer::SendPackToClient - Unexpected exception") );
  417. pCN->pSocket->Shutdown();
  418. }
  419. }
  420. }
  421. return hr;
  422. }
  423. STDMETHODIMP CIOCPServer::SendData( const unsigned long &ulnClientID,
  424.  const void * const pData,
  425.  const size_t &datalength )
  426. {
  427. HRESULT hr = E_FAIL;
  428. static const size_t s_len_protocol = sizeof( WORD );
  429. if ( NULL == pData || 0 == datalength )
  430. {
  431. return hr;
  432. }
  433. if ( ulnClientID < m_nPlayerMaxCount )
  434. {
  435. LPCLIENT_NODE pCN = NULL;
  436. CCriticalSection::Owner locker( m_csCM );
  437. pCN = ( LPCLIENT_NODE )( m_theClientManager[ulnClientID] );
  438. if ( pCN && pCN->pSocket )
  439. {
  440. CIOBuffer *pBuffer = NULL;
  441. try
  442. {
  443. pBuffer = Allocate();
  444. /*
  445.  * Add package header
  446.  */
  447. const size_t headlength = s_len_protocol + datalength;
  448. pBuffer->AddData( reinterpret_cast< const char * >( &headlength ), s_len_protocol );
  449. /*
  450.  * Add data into buffer that it is will be send
  451.  */
  452. pBuffer->AddData( reinterpret_cast< const char * >( pData ), datalength );
  453.                 _ASSERT(pCN->uKeyMode == 0);
  454. KSG_EncodeBuf(
  455. datalength,
  456. (unsigned char *)(pBuffer->GetBuffer() + s_len_protocol),
  457.                     &pCN->uServerKey
  458. );
  459. pCN->pSocket->Write( pBuffer, true );
  460. pBuffer->Release();
  461. hr = S_OK;
  462. }
  463. catch( const CException &e )
  464. {
  465. // add by spe 2003/07/06
  466. if (pBuffer)
  467. {
  468. pBuffer->Release();
  469. pBuffer = NULL;
  470. }
  471. Output( _T("CIOCPServer::SendPackToClient Exception: ") + e.GetWhere() + _T(" - ") + e.GetMessage() );
  472. pCN->pSocket->Shutdown();
  473. }
  474. catch(...)
  475. {
  476. // add by spe 2003/07/06
  477. if (pBuffer)
  478. {
  479. pBuffer->Release();
  480. pBuffer = NULL;
  481. }
  482. Output( _T("CIOCPServer::SendPackToClient - Unexpected exception") );
  483. pCN->pSocket->Shutdown();
  484. }
  485. }
  486. }
  487. return hr;
  488. }
  489. bool CIOCPServer::_SendDataEx( LPCLIENT_NODE pNode,
  490.  const void * const pData,
  491.  const size_t &datalength )
  492. {
  493. static const size_t s_len_protocol = sizeof( WORD );
  494. bool ok = false;
  495. if ( !pNode || !pData || !datalength )
  496. {
  497. return false;
  498. }
  499. if ( pNode->pSocket )
  500. {
  501. CIOBuffer *pBuffer = NULL;
  502. try
  503. {
  504. pBuffer = Allocate();
  505. /*
  506. * Add package header
  507. */
  508. const size_t headlength = s_len_protocol + datalength;
  509. pBuffer->AddData( reinterpret_cast< const char * >( &headlength ), s_len_protocol );
  510. /*
  511. * Add data into buffer that it is will be send
  512. */
  513. pBuffer->AddData( reinterpret_cast< const char * >( pData ), datalength );
  514. _ASSERT(pNode->uKeyMode == 0);
  515. KSG_EncodeBuf(
  516. datalength,
  517. (unsigned char *)(pBuffer->GetBuffer() + s_len_protocol),
  518. &pNode->uServerKey
  519. );
  520. pNode->pSocket->Write( pBuffer, true );
  521. pBuffer->Release();
  522. ok = true;
  523. }
  524. catch( const CException &e )
  525. {
  526. // add by spe 2003/07/06
  527. if (pBuffer)
  528. {
  529. pBuffer->Release();
  530. pBuffer = NULL;
  531. }
  532. Output( _T("CIOCPServer::_SendDataEx Exception: ") + e.GetWhere() + _T(" - ") + e.GetMessage() );
  533. pNode->pSocket->Shutdown();
  534. }
  535. catch(...)
  536. {
  537. // add by spe 2003/07/06
  538. if (pBuffer)
  539. {
  540. pBuffer->Release();
  541. pBuffer = NULL;
  542. }
  543. Output( _T("CIOCPServer::_SendDataEx - Unexpected exception") );
  544. pNode->pSocket->Shutdown();
  545. }
  546. }
  547. return ok;
  548. }
  549. STDMETHODIMP_( const void * ) CIOCPServer::GetPackFromClient( const unsigned long &ulnClientID,
  550. size_t &datalength )
  551. {
  552. if ( ulnClientID < m_nPlayerMaxCount )
  553. {
  554. LPCLIENT_NODE pCN = NULL;
  555. CCriticalSection::Owner locker( m_csCM );
  556. pCN = ( LPCLIENT_NODE )( m_theClientManager[ulnClientID] );
  557. if ( pCN && pCN->pSocket )
  558. {
  559. CCriticalSection::Owner lock( pCN->csReadAction );
  560. pCN->pReadBuffer->Empty();
  561. pCN->pRecvBuffer = ProcessDataStream( pCN->pSocket, pCN->pRecvBuffer );
  562. const char *pData = reinterpret_cast< const char * >( pCN->pReadBuffer->GetBuffer() );
  563. datalength = pCN->pReadBuffer->GetUsed();
  564. return pData;
  565. }
  566. }
  567. datalength = 0;
  568. return NULL;
  569. }
  570. STDMETHODIMP CIOCPServer::ShutdownClient( const unsigned long &ulnClientID )
  571. {
  572. if ( ulnClientID < m_nPlayerMaxCount )
  573. {
  574. LPCLIENT_NODE pCN = NULL;
  575. CCriticalSection::Owner locker( m_csCM );
  576. pCN = ( LPCLIENT_NODE )( m_theClientManager[ulnClientID] );
  577. if ( pCN )
  578. {
  579. if ( pCN->pSocket )
  580. {
  581. pCN->pSocket->AbortiveClose();
  582. pCN->pSocket = NULL;
  583. }
  584. pCN->pReadBuffer->Empty();
  585. pCN->pRecvBuffer->Empty();
  586. pCN->pWriteBuffer->Empty();
  587. }
  588. }
  589. return S_OK;
  590. }
  591. STDMETHODIMP_( size_t ) CIOCPServer::GetClientCount( )
  592. {
  593. // CCriticalSection::Owner locker( m_csCM );
  594. return m_usedClientNode.size();
  595. }
  596. STDMETHODIMP_( const char * ) CIOCPServer::GetClientInfo(
  597. const unsigned long &ulnClientID )
  598. {
  599. if ( ulnClientID < m_nPlayerMaxCount )
  600. {
  601. LPCLIENT_NODE pCN = NULL;
  602. CCriticalSection::Owner locker( m_csCM );
  603. pCN = ( LPCLIENT_NODE )( m_theClientManager[ulnClientID] );
  604. if ( pCN && pCN->pSocket )
  605. {
  606. const CPerConnectionData *pData = reinterpret_cast< const CPerConnectionData * >( pCN->pSocket->GetUserPtr() );
  607. if ( pData )
  608. {
  609. return pData->GetConnectionDetails().c_str();
  610. }
  611. }
  612. }
  613. return NULL;
  614. }
  615. STDMETHODIMP CIOCPServer::QueryInterface( REFIID riid, void** ppv )
  616. {
  617. /*
  618.  * By definition all COM objects support the IUnknown interface
  619.  */
  620. if( riid == IID_IUnknown )
  621. {
  622. AddRef();
  623. *ppv = dynamic_cast< IUnknown * >( this );
  624. }
  625. else if ( riid == IID_IIOCPServer )
  626. {
  627. AddRef();
  628. *ppv = dynamic_cast< IServer * >( this );
  629. }
  630. else
  631. {
  632. *ppv = NULL;
  633. return E_NOINTERFACE;
  634. }
  635. return S_OK;
  636. }
  637.     
  638. STDMETHODIMP_(ULONG) CIOCPServer::AddRef()
  639. {
  640. return ::InterlockedIncrement( &m_lRefCount );
  641. }
  642. STDMETHODIMP_(ULONG) CIOCPServer::Release()
  643. {
  644. if ( ::InterlockedDecrement( &m_lRefCount ) > 0 )
  645. {
  646. return m_lRefCount;
  647. }
  648. delete this;
  649. return 0L;
  650. }
  651. void CIOCPServer::OnConnectionEstablished( Socket *pSocket,
  652.  OnlineGameLib::Win32::CIOBuffer *pAddress )
  653. {
  654. if ( pSocket )
  655. {
  656. pSocket->AddRef();
  657. /*
  658.  * Allocate per connection data
  659.  */
  660. CSocketAddress address( reinterpret_cast< const sockaddr * >( pAddress->GetBuffer() ) );
  661. CPerConnectionData *pData = new CPerConnectionData( address.GetAsString(), ( WPARAM )( -1 ), ( LPARAM )( pSocket ) );
  662. ASSERT( pData );
  663. m_theAddClientQueue.Push( ( void * )pData );
  664. }
  665. }
  666. bool CIOCPServer::OnConnectionClosing( Socket *pSocket )
  667. {
  668. if ( pSocket )
  669. {
  670. pSocket->Close();
  671. }
  672. return true;
  673. }
  674. void CIOCPServer::OnConnectionClosed( Socket *pSocket )
  675. {
  676. if ( pSocket )
  677. {
  678. pSocket->AddRef();
  679. /*
  680.  * Release per connection data
  681.  */
  682. CPerConnectionData *pData = reinterpret_cast< CPerConnectionData * >( pSocket->GetUserPtr() );
  683. m_theDelClientQueue.Push( pData );
  684. }
  685. }
  686. void CIOCPServer::ReadCompleted( Socket *pSocket, OnlineGameLib::Win32::CIOBuffer *pBuffer )
  687. {
  688. if (pSocket->GetMessageCallback())
  689. {
  690. ProcessMessage(pSocket, pBuffer);
  691. return;
  692. }
  693. try
  694. {
  695. const CPerConnectionData *pData = reinterpret_cast< const CPerConnectionData * >( pSocket->GetUserPtr() );
  696. if ( pData )
  697. {
  698. DWORD dwIndex = pData->GetConnectionFirstParam();
  699. const BYTE *pPackData = pBuffer->GetBuffer();
  700. const size_t used = pBuffer->GetUsed();
  701. LPCLIENT_NODE pCN = NULL;
  702. {
  703. CCriticalSection::Owner locker( m_csCM );
  704. pCN = ( LPCLIENT_NODE )( m_theClientManager[dwIndex] );
  705. if ( pCN )
  706. {
  707. CCriticalSection::Owner lock( pCN->csReadAction );
  708. pCN->pRecvBuffer->AddData( pPackData, used );
  709. }
  710. }
  711. }
  712. pBuffer->Empty();
  713. pSocket->Read( pBuffer );
  714. }
  715. catch( const CException &e )
  716. {
  717. Output( _T("ReadCompleted - Exception - ") + e.GetWhere() + _T(" - ") + e.GetMessage() );
  718. pSocket->Shutdown();
  719. }
  720. catch(...)
  721. {
  722. Output( _T("ReadCompleted - Unexpected exception") );
  723. pSocket->Shutdown();
  724. }
  725. }
  726. CIOBuffer *CIOCPServer::ProcessDataStream( Socket *pSocket, CIOBuffer *pBuffer)
  727. {
  728. const size_t used = pBuffer->GetUsed();
  729. if ( used >= GetMinimumMessageSize() )
  730. {
  731. const size_t messageSize = GetMessageSize( pBuffer );
  732. if ( messageSize == 0 )
  733. {
  734. /*
  735.  * havent got a complete message yet.
  736.  * we null terminate our messages in the buffer, so we need to reserve
  737.  * a byte of the buffer for this purpose...
  738.  */
  739. if ( used == ( pBuffer->GetSize() - 1 ) )
  740. {
  741. Output( _T("Too much data! found error and close this socket!") );
  742. /*
  743.  * Shutdown the sending side of the socket.
  744.  */
  745. pSocket->Shutdown();
  746. /*
  747.  * throw the rubbish away
  748.  */
  749. pBuffer->Empty();
  750. }
  751. }
  752. else if ( used == messageSize )
  753. {
  754. Output( _T("Got a complete message and begin to process it") );
  755. /*
  756. * we have a whole, distinct, message
  757. */
  758. ProcessCommand( pSocket, pBuffer );
  759. pBuffer->Empty();
  760. }
  761. else if ( used > messageSize )
  762. {
  763. Output( _T("Got message plus extra data") );
  764. /*
  765. * we have a message, plus some more data
  766. * allocate a new buffer, copy the extra data into it and try again
  767. */
  768. CIOBuffer *pMessage = pBuffer->SplitBuffer( messageSize );
  769. ProcessCommand( pSocket, pMessage );
  770. pMessage->Release();
  771. }
  772. }
  773. /*
  774.  * not enough data in the buffer, reissue a read into the same buffer to collect more data
  775.  */
  776. return pBuffer;
  777. }
  778. size_t CIOCPServer::GetMinimumMessageSize()
  779. {
  780. static size_t length = sizeof( WORD ) + sizeof( BYTE );
  781. /*
  782.      * The smallest possible command we accept is a byte onlye package
  783.  */
  784. return length;
  785. }
  786. size_t CIOCPServer::GetMessageSize( const CIOBuffer *pBuffer )
  787. {
  788. const BYTE *pData = pBuffer->GetBuffer();   
  789. const size_t used = pBuffer->GetUsed();
  790. WORD wHeadLen = ( WORD )( *( WORD * )( pData ) );
  791. return ( size_t )( wHeadLen );
  792. }
  793. void CIOCPServer::ProcessCommand( Socket *pSocket, const CIOBuffer *pBuffer )
  794. {
  795. static const size_t s_len_protocol = sizeof( WORD );
  796. const BYTE *pData = pBuffer->GetBuffer();   
  797. const size_t used = pBuffer->GetUsed();
  798. ASSERT( used > s_len_protocol );
  799. if ( used <= s_len_protocol )
  800. {
  801.         return;
  802. }
  803. const CPerConnectionData *pPCD = reinterpret_cast< const CPerConnectionData * >( pSocket->GetUserPtr() );
  804. if ( !pPCD )
  805. {
  806. return;
  807. }
  808. DWORD dwIndex = pPCD->GetConnectionFirstParam();
  809. LPCLIENT_NODE pCN = NULL;
  810. {
  811. CCriticalSection::Owner locker( m_csCM );
  812. if ( NULL == ( pCN = ( LPCLIENT_NODE )( m_theClientManager[dwIndex] ) ) )
  813. {
  814.             return;
  815. }
  816.         // Add by Freeway Chen
  817.         _ASSERT(pCN->uKeyMode == 0);
  818.         KSG_DecodeBuf(
  819.             used - s_len_protocol,
  820.             const_cast<unsigned char *>(pData + s_len_protocol),
  821.             &(pCN->uClientKey)
  822.         );
  823. pCN->pReadBuffer->AddData( ( const BYTE * )( pData + s_len_protocol ), used - s_len_protocol );
  824. }
  825. }
  826. CServerFactory::CServerFactory()
  827. : m_lRefCount( 0 ),
  828. m_nPlayerMaxCount( 0 ),
  829. m_nPrecision( 0 ),
  830. m_maxFreeBuffers_Cache( 0 ),
  831. m_bufferSize_Cache( 0 )
  832. {
  833. }
  834. CServerFactory::~CServerFactory()
  835. {
  836. }
  837. STDMETHODIMP CServerFactory::SetEnvironment( const size_t &nPlayerMaxCount,
  838. const size_t &nPrecision,
  839. const size_t &maxFreeBuffers_Cache,
  840. const size_t &bufferSize_Cache )
  841. {
  842. m_nPlayerMaxCount = nPlayerMaxCount;
  843. m_nPrecision = nPrecision;
  844. m_maxFreeBuffers_Cache = maxFreeBuffers_Cache;
  845. m_bufferSize_Cache = bufferSize_Cache;
  846. return S_OK;
  847. }
  848. STDMETHODIMP CServerFactory::CreateServerInterface( REFIID riid, void** ppv )
  849. {
  850. HRESULT hr = E_NOINTERFACE;
  851. if ( IID_IIOCPServer == riid )
  852. {
  853. const size_t maxPlayerCount = ( m_nPlayerMaxCount > 0 ) ? m_nPlayerMaxCount : 100;
  854. const size_t precision = ( m_nPrecision > 0 ) ? m_nPrecision : 10;
  855. const size_t maxFreeBuffers_Cache = ( m_maxFreeBuffers_Cache > 0 ) ? m_maxFreeBuffers_Cache : 10;
  856. const size_t bufferSize_Cache = ( m_bufferSize_Cache > 0 ) ? m_bufferSize_Cache : 8192;
  857. const size_t maxFreeBuffers = 10240;
  858. try
  859. {
  860. CIOCPServer *pObject = new CIOCPServer( maxPlayerCount, 
  861. precision, 
  862. maxPlayerCount,
  863. maxFreeBuffers,
  864. maxFreeBuffers_Cache,
  865. bufferSize_Cache );
  866. *ppv = reinterpret_cast< void * > ( dynamic_cast< IServer * >( pObject ) );
  867. if ( *ppv )
  868. {
  869. reinterpret_cast< IUnknown * >( *ppv )->AddRef();
  870. hr = S_OK;
  871. }
  872. }
  873. catch( ... )
  874. {
  875. TRACE( "CServerFactory::CreateServerInterface exception!" );
  876. }
  877. }
  878. if ( FAILED( hr ) )
  879. {
  880. *ppv = NULL;
  881. }
  882. return ( HRESULT )( hr );
  883. }
  884. STDMETHODIMP CServerFactory::QueryInterface( REFIID riid, void** ppv )
  885. {
  886. /*
  887.  * By definition all COM objects support the IUnknown interface
  888.  */
  889. if( riid == IID_IUnknown )
  890. {
  891. AddRef();
  892. *ppv = dynamic_cast< IUnknown * >( this );
  893. }
  894. else if ( riid == IID_IServerFactory )
  895. {
  896. AddRef();
  897. *ppv = dynamic_cast< IServerFactory * >( this );
  898. }
  899. else
  900. {
  901. *ppv = NULL;
  902. return E_NOINTERFACE;
  903. }
  904. return S_OK;
  905. }
  906.     
  907. STDMETHODIMP_(ULONG) CServerFactory::AddRef()
  908. {
  909. return ::InterlockedIncrement( &m_lRefCount );
  910. }
  911. STDMETHODIMP_(ULONG) CServerFactory::Release()
  912. {
  913. if ( ::InterlockedDecrement( &m_lRefCount ) > 0 )
  914. {
  915. return m_lRefCount;
  916. }
  917. delete this;
  918. return 0L;
  919. }
  920. unsigned int __stdcall CIOCPServer::HelperThreadFunction( void *pParam )
  921. {
  922. CIOCPServer *pThis = ( CIOCPServer * )( pParam );
  923. ASSERT( pThis );
  924. try
  925. {
  926. pThis->_HelperThreadFunction();
  927. }
  928. catch( ... )
  929. {
  930. TRACE( "CIOCPServer::HelperThreadFunction exception!" );
  931. }
  932. return 0L;
  933. }
  934. unsigned int CIOCPServer::_HelperThreadFunction()
  935. {
  936. bool bAdd, bDel;
  937. while ( !m_hQuitHelper.Wait( 0 ) )
  938. {
  939. bAdd = _HelperAddClient();
  940. bDel = _HelperDelClient();
  941. if ( !bAdd && !bDel )
  942. {
  943. ::Sleep( 1 );
  944. }
  945. }
  946. return 0L;
  947. }
  948. bool CIOCPServer::_HelperAddClient()
  949. {
  950.     static const size_t s_len_protocol = sizeof( WORD );
  951. CPerConnectionData *pData = ( CPerConnectionData * )( m_theAddClientQueue.Pop() );
  952. if ( NULL == pData )
  953. {
  954. return false;
  955. }
  956. Socket *pSocket = ( Socket * )( pData->GetConnectionSecondParam() );
  957. ASSERT( pSocket );
  958. USES_CONVERSION;
  959. DWORD dwIndex = (DWORD)( -1 );
  960. if ( pSocket )
  961. {
  962. /*
  963.  * Get ID from the free table
  964.  */
  965. {
  966. CCriticalSection::Owner locker( m_csFCN );
  967. if ( !m_freeClientNode.empty() )
  968. {
  969. dwIndex = m_freeClientNode.front();
  970. m_freeClientNode.pop();
  971. //dwIndex = m_freeClientNode.top();
  972. //m_freeClientNode.pop();
  973. }
  974. }
  975. pData->SetConnectionFirstParam( dwIndex );
  976. pSocket->SetUserPtr( pData );
  977. /*
  978.  * Store this socket if we can use it
  979.  */
  980. if ( dwIndex != (DWORD)( -1 ) )
  981. {
  982. /*
  983.  * Store socket into array
  984.  */
  985. {
  986. CCriticalSection::Owner locker( m_csCM );
  987. m_theClientManager[dwIndex]->pSocket    = pSocket;
  988.                 m_theClientManager[dwIndex]->uServerKey = _Rand();
  989.                 m_theClientManager[dwIndex]->uClientKey = _Rand();
  990.                 m_theClientManager[dwIndex]->uKeyMode   = 0;
  991. /*
  992.  * Set ID into the used table
  993.  */
  994. m_usedClientNode.push_back( dwIndex );
  995. }
  996.             #pragma pack(1)
  997.             struct  {
  998.                 WORD wLen;
  999.                 ACCOUNT_BEGIN AccountBegin;
  1000.             } SendAccountBegin;
  1001.             #pragma pack()
  1002.             RandMemSet(sizeof(SendAccountBegin), (unsigned char *)&SendAccountBegin);
  1003. {
  1004. CCriticalSection::Owner locker( m_csCM );
  1005.                 SendAccountBegin.wLen = s_len_protocol + sizeof(SendAccountBegin.AccountBegin);
  1006.                 SendAccountBegin.AccountBegin.ProtocolType = CIPHER_PROTOCOL_TYPE;
  1007.                 SendAccountBegin.AccountBegin.Mode         = m_theClientManager[dwIndex]->uKeyMode;
  1008.                 SendAccountBegin.AccountBegin.ServerKey    = ~m_theClientManager[dwIndex]->uServerKey;
  1009.                 SendAccountBegin.AccountBegin.ClientKey    = ~m_theClientManager[dwIndex]->uClientKey;
  1010. }
  1011.             pSocket->Write((BYTE *)&SendAccountBegin, sizeof(SendAccountBegin));
  1012. /*
  1013.  Output( GetTimeStamp() + _T("Add a client [ID:") + 
  1014.  ToString( dwIndex ) + _T( "] - Current total is " ) +
  1015.  ToString( m_usedClientNode.size() ) );
  1016.  */
  1017. /*
  1018.  * Post a read command to IOCP
  1019.  * Enter into a process that it can get data from network
  1020.  */
  1021. if ( m_pfnCallBackServerEvent )
  1022. {
  1023. m_pfnCallBackServerEvent( m_lpCallBackParam, dwIndex, enumClientConnectCreate );
  1024. }
  1025. Trace( pData->GetConnectionDetails().c_str(), GetTimeStamp() + _T(" Add a client [ID:") + 
  1026. ToString( dwIndex ) + _T( "] - Current total is " ) +
  1027. ToString( m_usedClientNode.size() ) );
  1028. pSocket->Read();
  1029. }
  1030. else
  1031. {
  1032. pSocket->AbortiveClose();
  1033. }
  1034. SAFE_RELEASE( pSocket );
  1035. return true;
  1036. }
  1037. else
  1038. {
  1039. SAFE_DELETE( pData );
  1040. }
  1041. return false;
  1042. }
  1043. bool CIOCPServer::_HelperDelClient()
  1044. {
  1045. CPerConnectionData *pData = ( CPerConnectionData * )( m_theDelClientQueue.Pop() );
  1046. if ( NULL == pData )
  1047. {
  1048. return false;
  1049. }
  1050. Socket *pSocket = ( Socket * )( pData->GetConnectionSecondParam() );
  1051. if ( pSocket )
  1052. {
  1053. pSocket->SetUserData( NULL );
  1054. }
  1055. DWORD dwIndex = pData->GetConnectionFirstParam();
  1056. if ( ( DWORD )( -1 ) != dwIndex )
  1057. {
  1058. if ( m_pfnCallBackServerEvent )
  1059. {
  1060. m_pfnCallBackServerEvent( m_lpCallBackParam, dwIndex, enumClientConnectClose );
  1061. }
  1062. LPCLIENT_NODE pCN = NULL;
  1063. {
  1064. CCriticalSection::Owner locker( m_csCM );
  1065. pCN = ( LPCLIENT_NODE )( m_theClientManager[dwIndex] );
  1066. if ( pCN )
  1067. {
  1068. pCN->pSocket = NULL;
  1069. pCN->pReadBuffer->Empty();
  1070. pCN->pRecvBuffer->Empty();
  1071. pCN->pWriteBuffer->Empty();
  1072. }
  1073. /*
  1074. * Erase ID from the used table
  1075. */
  1076. m_usedClientNode.remove( dwIndex );
  1077. }
  1078. /*
  1079. * A ID of call back is entered into the free table
  1080. */
  1081. {
  1082. CCriticalSection::Owner locker( m_csFCN );
  1083. //m_freeClientNode.push( dwIndex );
  1084. m_freeClientNode.push( dwIndex );
  1085. }
  1086. Trace( pData->GetConnectionDetails().c_str(), GetTimeStamp() + _T(" Del a client [ID:") + 
  1087. ToString( dwIndex ) + _T( "] - Current total is " ) +
  1088. ToString( m_usedClientNode.size() ) );
  1089. /*
  1090. Output( GetTimeStamp() + _T("Del a client [ID:") + 
  1091. ToString( dwIndex ) + _T( "] - Current total is " ) + 
  1092. ToString( m_usedClientNode.size() ) );
  1093. */
  1094. }
  1095. SAFE_RELEASE( pSocket );
  1096. SAFE_DELETE( pData );
  1097. return true;
  1098. }
  1099. STDMETHODIMP CIOCPServer::RegisterMsgFilter( const unsigned long ulnClientID, 
  1100. IMessageProcess* pfnMsgNotify )
  1101. {
  1102. HRESULT hr = E_FAIL;
  1103. if ( ulnClientID < m_nPlayerMaxCount )
  1104. {
  1105. LPCLIENT_NODE pCN = NULL;
  1106. CCriticalSection::Owner locker( m_csCM );
  1107. pCN = ( LPCLIENT_NODE )( m_theClientManager[ulnClientID] );
  1108. if ( pCN && pCN->pSocket )
  1109. {
  1110. pCN->pSocket->SetMessageCallback(pfnMsgNotify);
  1111. hr = S_OK;
  1112. }
  1113. }
  1114. return hr;
  1115. }
  1116. void CIOCPServer::ProcessMessage( Socket *pSocket, CIOBuffer *pBuffer )
  1117. {
  1118. const size_t used = pBuffer->GetUsed();
  1119. static size_t minMessageSize = sizeof( WORD ) + sizeof( BYTE );
  1120. if ( used >= minMessageSize )
  1121. {
  1122. const CPerConnectionData *pPCD = reinterpret_cast< const CPerConnectionData * >( pSocket->GetUserPtr() );
  1123. if ( !pPCD )
  1124. {
  1125. return;
  1126. }
  1127. DWORD dwIndex = pPCD->GetConnectionFirstParam();
  1128. LPCLIENT_NODE pCN;
  1129. {
  1130. CCriticalSection::Owner locker( m_csCM );
  1131. if ( NULL == ( pCN = ( LPCLIENT_NODE )( m_theClientManager[dwIndex] ) ) )
  1132. {
  1133. return;
  1134. }
  1135. // Add by Freeway Chen
  1136. _ASSERT(pCN->uKeyMode == 0);
  1137. const BYTE* pData = pBuffer->GetBuffer();
  1138. WORD processedSize = 0;
  1139. WORD messageSize = ( WORD )( *( WORD * )( pData ) );
  1140. while ( used >= processedSize + messageSize )
  1141. {
  1142. KSG_DecodeBuf(
  1143. messageSize - sizeof(WORD),
  1144. const_cast<unsigned char *>(pData + sizeof( WORD )),
  1145. &(pCN->uClientKey)
  1146. );
  1147. pSocket->GetMessageCallback()->OnMessage((VOID*)(pData+sizeof( WORD )), 
  1148. messageSize - sizeof(WORD));
  1149. pData += messageSize;
  1150. processedSize += messageSize;
  1151. if ( used < processedSize + sizeof(WORD))
  1152. {
  1153. // no more complete message
  1154. break;
  1155. }
  1156. messageSize = ( WORD )( *( WORD * )( pData ) );
  1157. }
  1158. if ( used > processedSize )
  1159. {
  1160. pBuffer->RemoveBuffer( processedSize );
  1161. }
  1162. else
  1163. {
  1164. pBuffer->Empty();
  1165. }
  1166. }
  1167. }
  1168. pSocket->Read( pBuffer );
  1169. }