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

模拟服务器

开发平台:

C/C++

  1. #include "stdafx.h"
  2. #include "Intercessor.h"
  3. #include "AccountLoginDef.h"
  4. #include "LoginDef.h"
  5. #include "KProtocolDef.h"
  6. #include "KProtocol.h"
  7. #include "Macro.h"
  8. #include "Buffer.h"
  9. #include "SmartClient.h"
  10. using OnlineGameLib::Win32::CEvent;
  11. using OnlineGameLib::Win32::CCriticalSection;
  12. using OnlineGameLib::Win32::CPackager;
  13. OnlineGameLib::Win32::CLibrary CIntercessor::m_theHeavenLib( "heaven.dll" );
  14. OnlineGameLib::Win32::CLibrary CIntercessor::m_theRainbowLib( "rainbow.dll" );
  15. CIntercessor::CIntercessor( unsigned long lnMaxPlayerCount, CNetwork &theNetworkConfig )
  16. : m_hwndViewer( NULL )
  17. // , m_pAccSvrClient( NULL )
  18. , m_pDBRoleClient( NULL )
  19. , m_pGameSvrServer( NULL )
  20. , m_pPlayerServer( NULL )
  21. , m_hWorkingThread( INVALID_HANDLE_VALUE )
  22. , m_hHelperThread( INVALID_HANDLE_VALUE )
  23. , m_hQuitEvent( NULL, true, false, NULL /*"PM_Quit_Event"*/ )
  24. , m_hStartupWoringThreadEvent( NULL, false, false, NULL /*"PM_WORKING_EVENT"*/ )
  25. , m_hStartupHelperThreadEvent( NULL, false, false, NULL /*"PM_HELPER_EVENT"*/ )
  26. , m_theNetworkConfig( theNetworkConfig )
  27. , m_lnMaxPlayerCount( lnMaxPlayerCount )
  28. {
  29. }
  30. CIntercessor::~CIntercessor()
  31. {
  32. }
  33. bool CIntercessor::Create( HWND hwndViewer /* NULL */ )
  34. {
  35. m_hwndViewer = hwndViewer;
  36. /*
  37.  * Start a working thread
  38.  */
  39. DWORD dwThreadID = 0;
  40. m_hWorkingThread = ::CreateThread( NULL, 
  41. 0, 
  42. WorkingThreadFunction, 
  43. ( void * )this, 
  44. 0, 
  45. &dwThreadID );
  46. if ( m_hWorkingThread == INVALID_HANDLE_VALUE )
  47. {
  48. return false;
  49. }
  50. /*
  51.  * Startup a helper thread
  52.  */
  53. dwThreadID = 0;
  54. m_hHelperThread = ::CreateThread( NULL, 
  55. 0, 
  56. HelperThreadFunction, 
  57. ( void * )this,
  58. 0, 
  59. &dwThreadID );
  60. if ( m_hHelperThread == INVALID_HANDLE_VALUE )
  61. {
  62. return false;
  63. }
  64. // m_pAccSvrClient = m_theNetworkConfig.CreateAccSvrClient( m_theNetworkConfig.GetAccSvrIP(), m_theNetworkConfig.GetAccSvrPort() );
  65. // ASSERT( m_pAccSvrClient );
  66. // m_pAccSvrClient->RegisterMsgFilter( ( void * )this, AccountEventNotify );
  67. return StartupNetwork();
  68. }
  69. void CIntercessor::Destroy()
  70. {
  71. m_hQuitEvent.Set();
  72. m_hStartupWoringThreadEvent.Set();
  73. m_hStartupHelperThreadEvent.Set();
  74. SAFE_CLOSEHANDLE( m_hWorkingThread );
  75. SAFE_CLOSEHANDLE( m_hHelperThread );
  76. // SAFE_RELEASE( m_pAccSvrClient );
  77. CleanNetwork();
  78. }
  79. /*
  80. void __stdcall CIntercessor::AccountEventNotify( LPVOID lpParam, 
  81. const unsigned long &ulnEventType )
  82. {
  83. CIntercessor *pPlayerManager = reinterpret_cast< CIntercessor * >( lpParam );
  84. ASSERT( pPlayerManager );
  85. try
  86. {
  87. pPlayerManager->_AccountEventNotify( ulnEventType );
  88. }
  89. catch(...)
  90. {
  91. TRACE( "CIntercessor::AccountEventNotify exception!" );
  92. }
  93. }
  94. void CIntercessor::_AccountEventNotify( const unsigned long &ulnEventType )
  95. {
  96. switch( ulnEventType )
  97. {
  98. case enumServerConnectCreate:
  99. ::PostMessage( m_hwndViewer, WM_SERVER_STATUS, ACCOUNTSERVER_NOTIFY, CONNECTED );
  100. break;
  101. case enumServerConnectClose:
  102. ::PostMessage( m_hwndViewer, WM_SERVER_STATUS, ACCOUNTSERVER_NOTIFY, DICONNECTED );
  103. break;
  104. }
  105. }
  106. */
  107. void __stdcall CIntercessor::DBRoleEventNotify( LPVOID lpParam, 
  108. const unsigned long &ulnEventType )
  109. {
  110. CIntercessor *pPlayerManager = reinterpret_cast< CIntercessor * >( lpParam );
  111. ASSERT( pPlayerManager );
  112. try
  113. {
  114. pPlayerManager->_DBRoleEventNotify( ulnEventType );
  115. }
  116. catch(...)
  117. {
  118. TRACE( "CIntercessor::DBRoleEventNotify exception!" );
  119. }
  120. }
  121. void CIntercessor::_DBRoleEventNotify( const unsigned long &ulnEventType )
  122. {
  123. switch( ulnEventType )
  124. {
  125. case enumServerConnectCreate:
  126. ::PostMessage( m_hwndViewer, WM_SERVER_STATUS, DBROLESERVER_NOTIFY, CONNECTED );
  127. break;
  128. case enumServerConnectClose:
  129. ::PostMessage( m_hwndViewer, WM_SERVER_STATUS, DBROLESERVER_NOTIFY, DICONNECTED );
  130. break;
  131. }
  132. }
  133. void __stdcall CIntercessor::PlayerEventNotify( LPVOID lpParam,
  134. const unsigned long &ulnID,
  135. const unsigned long &ulnEventType )
  136. {
  137. CIntercessor *pPlayerManager = reinterpret_cast< CIntercessor * >( lpParam );
  138. ASSERT( pPlayerManager );
  139. try
  140. {
  141. pPlayerManager->_PlayerEventNotify( ulnID, ulnEventType );
  142. }
  143. catch(...)
  144. {
  145. TRACE( "CIntercessor::PlayerEventNotify exception!" );
  146. }
  147. }
  148. void CIntercessor::_PlayerEventNotify( const unsigned long &ulnID,
  149. const unsigned long &ulnEventType )
  150. {
  151. //CCriticalSection::Owner locker( m_csPlayerAction );
  152. switch ( ulnEventType )
  153. {
  154. case enumClientConnectCreate:
  155. {
  156. IPlayer *pPlayer = m_thePlayers[ulnID];
  157. ASSERT( pPlayer );
  158. pPlayer->Active();
  159. }
  160. break;
  161. case enumClientConnectClose:
  162. {
  163. PLAYER_MAP::iterator it;
  164. if ( m_thePlayers.end() != ( it = m_thePlayers.find( ulnID ) ) )
  165. {
  166. IPlayer *pPlayer = m_thePlayers[ulnID];
  167. ASSERT( pPlayer );
  168. pPlayer->Inactive();
  169. }
  170. }
  171. break;
  172. }
  173. }
  174. bool CIntercessor::StartupNetwork()
  175. {
  176. bool bPlayerServerSucceed = false;
  177. bool bDBRoleServerSucceed = false;
  178. bool bGameSvrServerSucceed = false;
  179. /*
  180.  * There is connectted the heaven by the rainbow
  181.  */
  182. /*
  183.  * For the db-role server
  184.  */
  185. pfnCreateClientInterface pClientFactroyFun = ( pfnCreateClientInterface )( m_theRainbowLib.GetProcAddress( _T( "CreateInterface" ) ) );
  186. IClientFactory *pClientFactory = NULL;
  187. if ( pClientFactroyFun && SUCCEEDED( pClientFactroyFun( IID_IClientFactory, reinterpret_cast< void ** >( &pClientFactory ) ) ) )
  188. {
  189. pClientFactory->SetEnvironment( 1024 * 1024 );
  190. pClientFactory->CreateClientInterface( IID_IESClient, reinterpret_cast< void ** >( &m_pDBRoleClient ) );
  191. SAFE_RELEASE( pClientFactory );
  192. }
  193. if ( m_pDBRoleClient )
  194. {
  195. m_pDBRoleClient->Startup();
  196. m_pDBRoleClient->RegisterMsgFilter( reinterpret_cast< void * >( this ), DBRoleEventNotify );
  197. if ( SUCCEEDED( m_pDBRoleClient->ConnectTo( m_theNetworkConfig.GetRoleSvrIP(), m_theNetworkConfig.GetRoleSvrPort() ) ) )
  198. {
  199. bDBRoleServerSucceed = true;
  200. }
  201. }
  202. /*
  203.  * We open the heaven to wait for the rainbow
  204.  */
  205. pfnCreateServerInterface pServerFactroyFun = 
  206. ( pfnCreateServerInterface )( m_theHeavenLib.GetProcAddress( _T( "CreateInterface" ) ) );
  207. IServerFactory *pServerFactory = NULL;
  208. if ( pServerFactroyFun && 
  209. SUCCEEDED( pServerFactroyFun( IID_IServerFactory, reinterpret_cast< void ** >( &pServerFactory ) ) ) )
  210. {
  211. pServerFactory->SetEnvironment( m_lnMaxPlayerCount, 10, 1000, 1024 * 8 );
  212. /*
  213.  * For player
  214.  */
  215. pServerFactory->CreateServerInterface( IID_IIOCPServer, reinterpret_cast< void ** >( &m_pPlayerServer ) );
  216. /*
  217.  * For gameserver
  218.  */
  219. pServerFactory->CreateServerInterface( IID_IIOCPServer, reinterpret_cast< void ** >( &m_pGameSvrServer ) );
  220. pServerFactory->Release();
  221. }
  222. if ( m_pGameSvrServer )
  223. {
  224. m_pGameSvrServer->Startup();
  225. /*
  226. IServer *pCloneGameServer = NULL;
  227. m_pGameSvrServer->QueryInterface( IID_IIOCPServer, reinterpret_cast< void ** >( &pCloneGameServer ) );
  228. IClient *pCloneAcc = NULL;
  229. m_pAccSvrClient->QueryInterface( IID_IESClient, reinterpret_cast< void ** >( &pCloneAcc ) );
  230. */
  231. static CGameServer::NI ni;
  232. ni.pServer = m_pGameSvrServer;
  233. ni.pClient = NULL; //m_pAccSvrClient;
  234. ni.hwndContainer = m_hwndViewer;
  235. m_pGameSvrServer->RegisterMsgFilter( reinterpret_cast< void * >( &ni ), CGameServer::GameSvrEventNotify );
  236. if ( SUCCEEDED( m_pGameSvrServer->OpenService( INADDR_ANY, m_theNetworkConfig.GetGameSvrOpenPort() ) ) )
  237. {
  238. bGameSvrServerSucceed = true;
  239. }
  240. }
  241. if ( m_pPlayerServer )
  242. {
  243. m_pPlayerServer->Startup();
  244. m_pPlayerServer->RegisterMsgFilter( reinterpret_cast< void * >( this ), PlayerEventNotify );
  245. if ( SUCCEEDED( m_pPlayerServer->OpenService( INADDR_ANY, m_theNetworkConfig.GetClientOpenPort() ) ) )
  246. {
  247. bPlayerServerSucceed = true;
  248. }
  249. }
  250. if ( bPlayerServerSucceed && 
  251. bDBRoleServerSucceed && 
  252. bGameSvrServerSucceed )
  253. {
  254. // IClient *pCloneAcc = NULL;
  255. // m_pAccSvrClient->QueryInterface( IID_IESClient, reinterpret_cast< void ** >( &pCloneAcc ) );
  256. IServer *pClonePlayer = NULL;
  257. m_pPlayerServer->QueryInterface( IID_IIOCPServer, reinterpret_cast< void ** >( &pClonePlayer ) );
  258. IClient *pCloneDBRole = NULL;
  259. m_pDBRoleClient->QueryInterface( IID_IESClient, reinterpret_cast< void ** >( &pCloneDBRole ) );
  260. ASSERT( /* pCloneAcc && */ pClonePlayer && pCloneDBRole );
  261. CGamePlayer::ATTACH_NETWORK( NULL/* pCloneAcc */, pClonePlayer, pCloneDBRole );
  262. /*
  263.  * Create new player
  264.  */
  265. {
  266. CCriticalSection::Owner lock( m_csPlayerAction );
  267. /*
  268.  * Initialize all of player
  269.  */
  270. for ( size_t index = 0; index < m_lnMaxPlayerCount; index ++ )
  271. {
  272. /*
  273. * Create a player node and add it into list
  274. */
  275. IPlayer *pPlayer = new CGamePlayer( index );
  276. ASSERT( pPlayer );
  277. m_thePlayers[index] = pPlayer;
  278. }
  279. }
  280. IServer *pCloneGameServer = NULL;
  281. m_pGameSvrServer->QueryInterface( IID_IIOCPServer, reinterpret_cast< void ** >( &pCloneGameServer ) );
  282. CGameServer::Begin( pCloneGameServer );
  283. m_hStartupWoringThreadEvent.Set();
  284. m_hStartupHelperThreadEvent.Set();
  285. }
  286. return ( bPlayerServerSucceed && bDBRoleServerSucceed && bGameSvrServerSucceed );
  287. }
  288. void CIntercessor::CleanNetwork()
  289. {
  290. /*
  291.  * Clear player info
  292.  */
  293. {
  294. CCriticalSection::Owner locker( m_csPlayerAction );
  295. PLAYER_MAP::iterator it;
  296. for ( it = m_thePlayers.begin(); it != m_thePlayers.end(); it ++ )
  297. {
  298. IPlayer *pPlayer = ( IPlayer * )( ( *it ).second );
  299. ASSERT( pPlayer );
  300. SAFE_DELETE( pPlayer );
  301. }
  302. m_thePlayers.erase( m_thePlayers.begin(), m_thePlayers.end() );
  303. }
  304. CGameServer::End();
  305. CGamePlayer::DETACH_NETWORK();
  306. /*
  307.  * Disconnect network and relase this resource
  308.  */
  309. if ( m_pPlayerServer )
  310. {
  311. m_pPlayerServer->CloseService();
  312. m_pPlayerServer->Cleanup();
  313. SAFE_RELEASE( m_pPlayerServer );
  314. }
  315. if ( m_pDBRoleClient )
  316. {
  317. m_pDBRoleClient->Cleanup();
  318. SAFE_RELEASE( m_pDBRoleClient );
  319. }
  320. if ( m_pGameSvrServer )
  321. {
  322. m_pGameSvrServer->CloseService();
  323. m_pGameSvrServer->Cleanup();
  324. SAFE_RELEASE( m_pGameSvrServer );
  325. }
  326. }
  327. DWORD WINAPI CIntercessor::WorkingThreadFunction( void *pV )
  328. {
  329. CIntercessor *pThis = reinterpret_cast< CIntercessor * >( pV );
  330. ASSERT( pThis );
  331. try
  332. {
  333. pThis->Working();
  334. }
  335. catch(...)
  336. {
  337. ::MessageBox( NULL, "Run a working thread is failed!", "CIntercessor class", MB_OK );
  338. }
  339. return 0;
  340. }
  341. int CIntercessor::Working()
  342. {
  343. // ::CoInitialize( NULL );
  344. m_hStartupWoringThreadEvent.Wait();
  345. while ( !m_hQuitEvent.Wait( 0 ) )
  346. {
  347. /*
  348.  * For some alive player
  349.  */
  350. {
  351. CCriticalSection::Owner locker( m_csPlayerAction );
  352. for ( size_t index = 0; index < m_lnMaxPlayerCount; index ++ )
  353. {
  354. IPlayer *pPlayer = m_thePlayers[index];
  355. ASSERT( pPlayer );
  356. if ( pPlayer && pPlayer->IsActive() )
  357. {
  358. /*
  359.  * Get data from player
  360.  */
  361. size_t datalength = 0;
  362. const void *pData = m_pPlayerServer->GetPackFromClient( index, datalength );
  363. if ( pData && datalength )
  364. {
  365. AnalyzePlayerRequire( index, pData, datalength );
  366. }
  367. /*
  368. * Execute work
  369. */
  370. pPlayer->Run();
  371. }
  372. }
  373. }
  374. ::Sleep( 1 );
  375. }
  376. // ::CoUninitialize();
  377. return 0;
  378. }
  379. DWORD WINAPI CIntercessor::HelperThreadFunction( void *pV )
  380. {
  381. CIntercessor *pThis = reinterpret_cast< CIntercessor * >( pV );
  382. ASSERT( pThis );
  383. try
  384. {
  385. pThis->Helper();
  386. }
  387. catch(...)
  388. {
  389. ::MessageBox( NULL, "Startup a helper thread is failed!", "CIntercessor class", MB_OK );
  390. }
  391. return 0;
  392. }
  393. int CIntercessor::Helper()
  394. {
  395. m_hStartupHelperThreadEvent.Wait();
  396. static const DWORD dwTimeLimit = 1000 * 10;
  397. DWORD dwStart = ::GetTickCount();
  398. DWORD dwEnd = dwStart;
  399. while ( !m_hQuitEvent.Wait( 0 ) )
  400. {
  401. /*
  402.  * ping account server
  403.  */
  404. if ( ( ( ( dwEnd = ::GetTickCount() ) - dwStart ) > dwTimeLimit ) ||
  405. ( dwStart > dwEnd ) )
  406. {
  407. dwStart = dwEnd;
  408. PING_COMMAND pc;
  409. pc.ProtocolType = c2s_ping;
  410. pc.m_dwTime = dwStart;
  411. g_theSmartClient.Send( &pc, sizeof( PING_COMMAND ) );
  412. // m_pAccSvrClient->SendPackToServer( &pc, sizeof( PING_COMMAND ) );
  413. }
  414. /*
  415.  * Get data from account-server
  416.  */
  417. size_t dataLength = 0;
  418. const void *pData = g_theSmartClient.Recv( dataLength );
  419. // const void *pData = m_pAccSvrClient->GetPackFromServer( dataLength );
  420. while( pData && dataLength )
  421. {
  422. ASSERT( CPackager::Peek( pData ) > g_nGlobalProtocolType );
  423. if ( s2c_accountlogin == *( const char * )pData )
  424. {
  425. const KAccountHead *pAUR = ( KAccountHead * )( ( ( const char * )pData ) + 1 );
  426. UINT uID = pAUR->Operate;
  427. if ( uID < m_lnMaxPlayerCount )
  428. {
  429. IPlayer *pPlayer = m_thePlayers[uID];
  430. ASSERT( pPlayer );
  431. pPlayer->AppendData( CGamePlayer::enumOwnerAccSvr, pData, dataLength );
  432. }
  433. }
  434. /*
  435.  * ping account server
  436.  */
  437. if ( ( ( ( dwEnd = ::GetTickCount() ) - dwStart ) > dwTimeLimit ) ||
  438. ( dwStart > dwEnd ) )
  439. {
  440. dwStart = dwEnd;
  441. PING_COMMAND pc;
  442. pc.ProtocolType = c2s_ping;
  443. pc.m_dwTime = dwStart;
  444. g_theSmartClient.Send( &pc, sizeof( PING_COMMAND ) );
  445. // m_pAccSvrClient->SendPackToServer( &pc, sizeof( PING_COMMAND ) );
  446. }
  447. pData = g_theSmartClient.Recv( dataLength );
  448. // pData = m_pAccSvrClient->GetPackFromServer( dataLength );
  449. }
  450. /*
  451.  * Get data from role-database
  452.  */
  453. dataLength = 0;
  454. pData = m_pDBRoleClient->GetPackFromServer( dataLength );
  455. while( pData && dataLength )
  456. {
  457. BYTE cProtocol = CPackager::Peek( pData );
  458. UINT uID = ( UINT )( -1 );
  459. if ( cProtocol < g_nGlobalProtocolType )
  460. {
  461. uID = *( const unsigned long * )( ( const char * )pData + 2 );
  462. }
  463. else // cProtocol > g_nGlobalProtocolType
  464. {
  465. TProcessData *pPD = ( TProcessData * )( pData );
  466. uID = pPD->ulIdentity;
  467. }
  468. if ( uID < m_lnMaxPlayerCount )
  469. {
  470. IPlayer *pPlayer = m_thePlayers[uID];
  471. ASSERT( pPlayer );
  472. pPlayer->AppendData( CGamePlayer::enumOwnerRoleSvr, pData, dataLength );
  473. }
  474. /*
  475.  * ping account server
  476.  */
  477. if ( ( ( ( dwEnd = ::GetTickCount() ) - dwStart ) > dwTimeLimit ) ||
  478. ( dwStart > dwEnd ) )
  479. {
  480. dwStart = dwEnd;
  481. PING_COMMAND pc;
  482. pc.ProtocolType = c2s_ping;
  483. pc.m_dwTime = dwStart;
  484. g_theSmartClient.Send( &pc, sizeof( PING_COMMAND ) );
  485. // m_pAccSvrClient->SendPackToServer( &pc, sizeof( PING_COMMAND ) );
  486. }
  487. pData = m_pDBRoleClient->GetPackFromServer( dataLength );
  488. }
  489. ::Sleep( 1 );
  490. }
  491. return 0;
  492. }
  493. bool CIntercessor::AnalyzePlayerRequire( size_t index, const void *pData, size_t datalength )
  494. {
  495. ASSERT( pData && datalength );
  496. BYTE cProtocol = *( const BYTE * )pData;
  497. switch ( cProtocol )
  498. {
  499. case c2s_login:
  500. {
  501. const BYTE *pBuffer = ( const BYTE * )pData + 1;
  502. KLoginAccountInfo *pLAI = ( KLoginAccountInfo * )pBuffer;
  503. ASSERT( pLAI );
  504. IPlayer *pPlayer = m_thePlayers[index];
  505. if ( pLAI && pPlayer )
  506. {
  507. pPlayer->AppendData( CGamePlayer::enumOwnerPlayer, pData, datalength );
  508. pPlayer->DispatchTask( CGamePlayer::enumLogin );
  509. }
  510. }
  511. break;
  512. case c2s_dbplayerselect:
  513. case c2s_newplayer:
  514. case c2s_roleserver_deleteplayer:
  515. {
  516. if ( index < m_lnMaxPlayerCount )
  517. {
  518. IPlayer *pPlayer = m_thePlayers[index];
  519. ASSERT( pPlayer );
  520. pPlayer->AppendData( CGamePlayer::enumOwnerPlayer, pData, datalength );
  521. }
  522. }
  523. break;
  524. default:
  525. break;
  526. }
  527. return true;
  528. }
  529. size_t CIntercessor::GetGameServerCount()
  530. {
  531. if ( m_pGameSvrServer )
  532. {
  533. return m_pGameSvrServer->GetClientCount();
  534. }
  535. return 0;
  536. }
  537. const char *CIntercessor::GetGameServerInfo( const unsigned long &ulnID )
  538. {
  539. if ( m_pGameSvrServer )
  540. {
  541. return m_pGameSvrServer->GetClientInfo( ulnID );
  542. }
  543. return NULL;
  544. }