├── .gitignore ├── Cocos2dxGameClient ├── Classes │ ├── AppDelegate.cpp │ ├── AppDelegate.h │ ├── CircularBuffer.cpp │ ├── CircularBuffer.h │ ├── GameLiftManager.cpp │ ├── GameLiftManager.h │ ├── HelloWorldScene.cpp │ ├── HelloWorldScene.h │ ├── TcpClient.cpp │ └── TcpClient.h ├── README.md ├── Resources │ ├── CloseNormal.png │ ├── CloseSelected.png │ ├── HelloWorld.png │ ├── Player.png │ ├── Projectile.png │ ├── Target.png │ └── fonts │ │ └── Marker Felt.ttf ├── cclient.png ├── cocos2d │ └── Readme.txt └── proj.win32 │ ├── CocosGameClient.sln │ ├── CocosGameClient.vcxproj │ ├── CocosGameClient.vcxproj.filters │ ├── CocosGameClient.vcxproj.user │ ├── UserDefault.xml │ ├── build-cfg.json │ ├── game.rc │ ├── main.cpp │ ├── main.h │ ├── packages.config │ ├── res │ └── game.ico │ └── resource.h ├── DummyClients ├── DummyClients.sln └── DummyClients │ ├── CircularBuffer.cpp │ ├── CircularBuffer.h │ ├── DummyClients.cpp │ ├── DummyClients.h │ ├── DummyClients.vcxproj │ ├── DummyClients.vcxproj.filters │ ├── DummyClientsLog.txt │ ├── Exception.cpp │ ├── Exception.h │ ├── FastSpinlock.cpp │ ├── FastSpinlock.h │ ├── GameLiftManager.cpp │ ├── GameLiftManager.h │ ├── GameSession.cpp │ ├── GameSession.h │ ├── INIReader.cpp │ ├── INIReader.h │ ├── IocpManager.cpp │ ├── IocpManager.h │ ├── Job.h │ ├── JobDispatcher.h │ ├── Log.cpp │ ├── Log.h │ ├── ObjectPool.h │ ├── OverlappedIOContext.cpp │ ├── OverlappedIOContext.h │ ├── PacketHandler.cpp │ ├── PlayerSession.cpp │ ├── PlayerSession.h │ ├── ReadMe.txt │ ├── Session.cpp │ ├── Session.h │ ├── ThreadLocal.cpp │ ├── ThreadLocal.h │ ├── Timer.cpp │ ├── Timer.h │ ├── WorkerThread.cpp │ ├── WorkerThread.h │ ├── config.ini │ ├── ini.c │ ├── ini.h │ ├── packages.config │ ├── stdafx.cpp │ ├── stdafx.h │ └── targetver.h ├── GameLiftGameServer ├── GameLiftGameServer.sln ├── GameLiftGameServer │ ├── CircularBuffer.cpp │ ├── CircularBuffer.h │ ├── Exception.cpp │ ├── Exception.h │ ├── FastSpinlock.cpp │ ├── FastSpinlock.h │ ├── GameLiftGameServer.cpp │ ├── GameLiftGameServer.vcxproj │ ├── GameLiftGameServer.vcxproj.filters │ ├── GameLiftManager.cpp │ ├── GameLiftManager.h │ ├── GameSession.cpp │ ├── GameSession.h │ ├── IOThread.cpp │ ├── IOThread.h │ ├── IocpManager.cpp │ ├── IocpManager.h │ ├── Log.cpp │ ├── Log.h │ ├── ObjectPool.h │ ├── OverlappedIOContext.cpp │ ├── OverlappedIOContext.h │ ├── PacketHandler.cpp │ ├── PlayerSession.cpp │ ├── PlayerSession.h │ ├── Session.cpp │ ├── Session.h │ ├── ThreadLocal.cpp │ ├── ThreadLocal.h │ ├── Timer.cpp │ ├── Timer.h │ ├── include │ │ └── aws │ │ │ └── gamelift │ │ │ ├── common │ │ │ ├── GameLiftErrors.h │ │ │ ├── GameLift_EXPORTS.h │ │ │ └── Outcome.h │ │ │ ├── internal │ │ │ ├── GameLiftCommonState.h │ │ │ ├── GameLiftServerState.h │ │ │ ├── modelmapper │ │ │ │ ├── AttributeValueMapper.h │ │ │ │ ├── BackfillMatchmakingRequestMapper.h │ │ │ │ ├── DescribePlayerSessionsMapper.h │ │ │ │ └── PlayerMapper.h │ │ │ └── network │ │ │ │ ├── AuxProxyMessageHandler.h │ │ │ │ ├── AuxProxyMessageSender.h │ │ │ │ └── Network.h │ │ │ └── server │ │ │ ├── GameLiftServerAPI.h │ │ │ ├── LogParameters.h │ │ │ ├── ProcessParameters.h │ │ │ ├── model │ │ │ ├── AttributeValue.h │ │ │ ├── DescribePlayerSessionsRequest.h │ │ │ ├── DescribePlayerSessionsResult.h │ │ │ ├── GameProperty.h │ │ │ ├── GameSession.h │ │ │ ├── GameSessionStatus.h │ │ │ ├── Player.h │ │ │ ├── PlayerSession.h │ │ │ ├── PlayerSessionCreationPolicy.h │ │ │ ├── PlayerSessionStatus.h │ │ │ ├── StartMatchBackfillRequest.h │ │ │ ├── StartMatchBackfillResult.h │ │ │ ├── StopMatchBackfillRequest.h │ │ │ ├── UpdateGameSession.h │ │ │ └── UpdateReason.h │ │ │ └── protocols │ │ │ └── sdk.pb.h │ ├── stdafx.cpp │ ├── stdafx.h │ └── targetver.h ├── upload │ ├── aws-cpp-sdk-gamelift-server.dll │ ├── install.bat │ └── logs │ │ ├── serverErr.log │ │ ├── serverLog.txt │ │ └── serverOut.log └── x64 │ └── Release │ ├── aws-cpp-sdk-gamelift-server.dll │ └── aws-cpp-sdk-gamelift-server.lib ├── GameLiftLinuxServer ├── CMakeLists.txt ├── CircularBuffer.cpp ├── CircularBuffer.h ├── ClientManager.cpp ├── ClientManager.h ├── ClientSession.cpp ├── ClientSession.h ├── Config.h ├── GameLiftManager.cpp ├── GameLiftManager.h ├── Log.cpp ├── Log.h ├── PacketHandler.cpp ├── Scheduler.cpp ├── Scheduler.h ├── Utils.h ├── build │ └── upload │ │ └── logs │ │ ├── serverErr.out │ │ ├── serverLog.out │ │ └── serverLog.txt ├── include │ └── aws │ │ └── gamelift │ │ ├── common │ │ ├── GameLiftErrors.h │ │ ├── GameLift_EXPORTS.h │ │ └── Outcome.h │ │ ├── internal │ │ ├── GameLiftCommonState.h │ │ ├── GameLiftServerState.h │ │ ├── modelmapper │ │ │ └── DescribePlayerSessionsMapper.h │ │ └── network │ │ │ ├── AuxProxyMessageHandler.h │ │ │ ├── AuxProxyMessageSender.h │ │ │ └── Network.h │ │ └── server │ │ ├── GameLiftServerAPI.h │ │ ├── LogParameters.h │ │ ├── ProcessParameters.h │ │ ├── model │ │ ├── DescribePlayerSessionsRequest.h │ │ ├── DescribePlayerSessionsResult.h │ │ ├── GameProperty.h │ │ ├── GameSession.h │ │ ├── GameSessionStatus.h │ │ ├── PlayerSession.h │ │ ├── PlayerSessionCreationPolicy.h │ │ └── PlayerSessionStatus.h │ │ └── protocols │ │ └── sdk.pb.h ├── lib │ └── sdk_lib315_unzip_here.zip └── main.cpp ├── GameLift_dist.pdf ├── LICENSE ├── PacketShare └── PacketType.h ├── README.md ├── gamelift_interaction.png └── overview.png /Cocos2dxGameClient/Classes/AppDelegate.cpp: -------------------------------------------------------------------------------- 1 | #include "AppDelegate.h" 2 | #include "HelloWorldScene.h" 3 | 4 | USING_NS_CC; 5 | 6 | AppDelegate::AppDelegate() { 7 | 8 | } 9 | 10 | AppDelegate::~AppDelegate() 11 | { 12 | } 13 | 14 | bool AppDelegate::applicationDidFinishLaunching() { 15 | // initialize director 16 | auto director = Director::getInstance(); 17 | auto glview = director->getOpenGLView(); 18 | if(!glview) { 19 | glview = GLView::create("My Game"); 20 | director->setOpenGLView(glview); 21 | } 22 | 23 | // turn on display FPS 24 | director->setDisplayStats(true); 25 | 26 | // set FPS. the default value is 1.0/60 if you don't call this 27 | director->setAnimationInterval(1.0 / 60); 28 | 29 | // create a scene. it's an autorelease object 30 | auto scene = HelloWorld::createScene(); 31 | 32 | // run 33 | director->runWithScene(scene); 34 | 35 | return true; 36 | } 37 | 38 | // This function will be called when the app is inactive. When comes a phone call,it's be invoked too 39 | void AppDelegate::applicationDidEnterBackground() { 40 | Director::getInstance()->stopAnimation(); 41 | 42 | // if you use SimpleAudioEngine, it must be pause 43 | // SimpleAudioEngine::getInstance()->pauseBackgroundMusic(); 44 | } 45 | 46 | // this function will be called when the app is active again 47 | void AppDelegate::applicationWillEnterForeground() { 48 | Director::getInstance()->startAnimation(); 49 | 50 | // if you use SimpleAudioEngine, it must resume here 51 | // SimpleAudioEngine::getInstance()->resumeBackgroundMusic(); 52 | } 53 | -------------------------------------------------------------------------------- /Cocos2dxGameClient/Classes/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #ifndef _APP_DELEGATE_H_ 2 | #define _APP_DELEGATE_H_ 3 | 4 | #include "cocos2d.h" 5 | 6 | /** 7 | @brief The cocos2d Application. 8 | 9 | The reason for implement as private inheritance is to hide some interface call by Director. 10 | */ 11 | class AppDelegate : private cocos2d::Application 12 | { 13 | public: 14 | AppDelegate(); 15 | virtual ~AppDelegate(); 16 | 17 | /** 18 | @brief Implement Director and Scene init code here. 19 | @return true Initialize success, app continue. 20 | @return false Initialize failed, app terminate. 21 | */ 22 | virtual bool applicationDidFinishLaunching(); 23 | 24 | /** 25 | @brief The function be called when the application enter background 26 | @param the pointer of the application 27 | */ 28 | virtual void applicationDidEnterBackground(); 29 | 30 | /** 31 | @brief The function be called when the application enter foreground 32 | @param the pointer of the application 33 | */ 34 | virtual void applicationWillEnterForeground(); 35 | }; 36 | 37 | #endif // _APP_DELEGATE_H_ 38 | 39 | -------------------------------------------------------------------------------- /Cocos2dxGameClient/Classes/CircularBuffer.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeliard/GameLift/4bdb482097cac9e362701732bff74e4398a1c174/Cocos2dxGameClient/Classes/CircularBuffer.cpp -------------------------------------------------------------------------------- /Cocos2dxGameClient/Classes/CircularBuffer.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeliard/GameLift/4bdb482097cac9e362701732bff74e4398a1c174/Cocos2dxGameClient/Classes/CircularBuffer.h -------------------------------------------------------------------------------- /Cocos2dxGameClient/Classes/GameLiftManager.cpp: -------------------------------------------------------------------------------- 1 | #include "GameLiftManager.h" 2 | #include "GameLiftManager.h" 3 | #include "TcpClient.h" 4 | #include "platform/CCFileUtils.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | 14 | GameLiftManager* GGameLiftManager = nullptr; 15 | 16 | GameLiftManager::GameLiftManager(const std::string& alias) : mAliasId(alias) 17 | { 18 | } 19 | 20 | void GameLiftManager::SetUpAwsClient(const std::string& region) 21 | { 22 | 23 | Aws::Client::ClientConfiguration config; 24 | config.scheme = Aws::Http::Scheme::HTTPS; 25 | config.connectTimeoutMs = 30000; 26 | config.requestTimeoutMs = 30000; 27 | 28 | config.region = region; 29 | 30 | mGLClient = Aws::MakeShared("GameLiftTest", config); 31 | 32 | } 33 | 34 | bool GameLiftManager::SearchGameSessions() 35 | { 36 | Aws::GameLift::Model::SearchGameSessionsRequest req; 37 | req.SetAliasId(mAliasId); 38 | req.SetFilterExpression("hasAvailablePlayerSessions=true"); 39 | 40 | auto outcome = mGLClient->SearchGameSessions(req); 41 | if (outcome.IsSuccess()) 42 | { 43 | auto& games = outcome.GetResult().GetGameSessions(); 44 | auto& gs = games[0]; 45 | 46 | mPort = gs.GetPort(); 47 | mServerIpAddress = gs.GetIpAddress(); 48 | mGameSessionId = gs.GetGameSessionId(); 49 | return true; 50 | } 51 | 52 | //CCLOG("%s\n", outcome.GetError().GetMessage().c_str()); 53 | 54 | return false; 55 | 56 | } 57 | 58 | bool GameLiftManager::CreatePlayerSession() 59 | { 60 | Aws::GameLift::Model::CreatePlayerSessionRequest req; 61 | req.SetGameSessionId(mGameSessionId); 62 | req.SetPlayerId("PlayerCoCos"); 63 | 64 | auto outcome = mGLClient->CreatePlayerSession(req); 65 | if (outcome.IsSuccess()) 66 | { 67 | auto& psess = outcome.GetResult().GetPlayerSession(); 68 | mPlayerSessionId = psess.GetPlayerSessionId(); 69 | 70 | return true; 71 | } 72 | 73 | //printf_s("%s\n", outcome.GetError().GetMessage().c_str()); 74 | return false; 75 | 76 | } 77 | 78 | bool GameLiftManager::ConnectPlayerSession() 79 | { 80 | if (TcpClient::getInstance()->connect(mServerIpAddress.c_str(), mPort)) 81 | { 82 | TcpClient::getInstance()->loginRequest(mPlayerSessionId); 83 | return true; 84 | } 85 | 86 | /// conn error 87 | return false; 88 | } 89 | 90 | void GameLiftManager::DoTestNow() 91 | { 92 | if (SearchGameSessions()) 93 | { 94 | if (CreatePlayerSession()) 95 | { 96 | if (ConnectPlayerSession()) 97 | { 98 | /// ok gogo 99 | } 100 | } 101 | } 102 | } 103 | 104 | -------------------------------------------------------------------------------- /Cocos2dxGameClient/Classes/GameLiftManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class GameLiftManager 5 | { 6 | public: 7 | GameLiftManager(const std::string& alias); 8 | 9 | void SetUpAwsClient(const std::string& region); 10 | 11 | bool SearchGameSessions(); 12 | bool CreatePlayerSession(); 13 | bool ConnectPlayerSession(); 14 | 15 | std::shared_ptr GetAwsClient() 16 | { 17 | return mGLClient; 18 | } 19 | 20 | const std::string& GetAliasId() const 21 | { 22 | return mAliasId; 23 | } 24 | 25 | void DoTestNow(); 26 | 27 | private: 28 | std::shared_ptr mGLClient; 29 | 30 | std::string mAliasId; 31 | 32 | // retrieved info 33 | int mPort = 0 ; 34 | std::string mServerIpAddress; 35 | std::string mGameSessionId; 36 | std::string mPlayerSessionId; 37 | 38 | 39 | 40 | }; 41 | 42 | extern GameLiftManager* GGameLiftManager; -------------------------------------------------------------------------------- /Cocos2dxGameClient/Classes/HelloWorldScene.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeliard/GameLift/4bdb482097cac9e362701732bff74e4398a1c174/Cocos2dxGameClient/Classes/HelloWorldScene.cpp -------------------------------------------------------------------------------- /Cocos2dxGameClient/Classes/HelloWorldScene.h: -------------------------------------------------------------------------------- 1 | #ifndef __HELLOWORLD_SCENE_H__ 2 | #define __HELLOWORLD_SCENE_H__ 3 | 4 | #include "cocos2d.h" 5 | 6 | class HelloWorld : public cocos2d::LayerColor 7 | { 8 | public: 9 | // there's no 'id' in cpp, so we recommend returning the class instance pointer 10 | static cocos2d::Scene* createScene(); 11 | 12 | // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone 13 | virtual bool init(); 14 | 15 | // a selector callback 16 | void menuCloseCallback(cocos2d::Ref* pSender); 17 | 18 | // implement the "static create()" method manually 19 | CREATE_FUNC(HelloWorld); 20 | 21 | 22 | void spriteMoveFinished(cocos2d::CCNode * sender); 23 | void gameLogic(float dt); 24 | 25 | void onKeyPressed(cocos2d::EventKeyboard::KeyCode keyCode, cocos2d::Event* event) {} 26 | void onKeyReleased(cocos2d::EventKeyboard::KeyCode keyCode, cocos2d::Event* event); 27 | 28 | void helloWorld() { CCLOG("HELLO~~~"); } 29 | void updatePeer(int id, float x, float y); 30 | void updateMe(float x, float y); 31 | void chatDraw(const std::string& from, const std::string& chat); 32 | 33 | 34 | private: 35 | cocos2d::CCSprite* mPlayerSprite = nullptr; 36 | std::map mPeerMap; 37 | }; 38 | 39 | #endif // __HELLOWORLD_SCENE_H__ 40 | -------------------------------------------------------------------------------- /Cocos2dxGameClient/Classes/TcpClient.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeliard/GameLift/4bdb482097cac9e362701732bff74e4398a1c174/Cocos2dxGameClient/Classes/TcpClient.cpp -------------------------------------------------------------------------------- /Cocos2dxGameClient/Classes/TcpClient.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "CircularBuffer.h" 4 | 5 | #ifndef _WIN32 6 | #include 7 | #include 8 | #else 9 | #include 10 | #endif 11 | 12 | #define BUF_SIZE 32768 13 | 14 | class TcpClient 15 | { 16 | public: 17 | static TcpClient* getInstance(); 18 | static void destroyInstance(); 19 | 20 | bool connect(const char* serverAddr, int port); 21 | 22 | 23 | /// request test 24 | void loginRequest(const std::string& playerSessionId); 25 | void chatRequest(const char* chat); 26 | void moveRequest(float x, float y); 27 | 28 | 29 | private: 30 | TcpClient(); 31 | virtual ~TcpClient(); 32 | 33 | bool initialize(); 34 | bool send(const char* data, int length); 35 | 36 | void networkThread(); 37 | void processPacket(); 38 | 39 | private: 40 | 41 | SOCKET m_sock; 42 | CircularBuffer m_recvBuffer; 43 | 44 | int m_loginId; 45 | 46 | }; 47 | 48 | -------------------------------------------------------------------------------- /Cocos2dxGameClient/README.md: -------------------------------------------------------------------------------- 1 | ## Cocos2dxGameClient 2 | 3 | A game client integrating with Cocos2D-x game engine and AWS C++ SDK. 4 | This makes GameLift Client API calls to GameLift services and makes a TCP connection to GameLiftGameServer. 5 | 6 | ## How-to 7 | 8 | - Edit main.cpp file and then set your GameLift ALIAS_ID, GAMELIFT_REGION. 9 | - Build and Run. 10 | - Press 'L' to login to the GameLiftGameServer. 11 | 12 | ## ScreenShot 13 | ![Screenshot](cclient.png) -------------------------------------------------------------------------------- /Cocos2dxGameClient/Resources/CloseNormal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeliard/GameLift/4bdb482097cac9e362701732bff74e4398a1c174/Cocos2dxGameClient/Resources/CloseNormal.png -------------------------------------------------------------------------------- /Cocos2dxGameClient/Resources/CloseSelected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeliard/GameLift/4bdb482097cac9e362701732bff74e4398a1c174/Cocos2dxGameClient/Resources/CloseSelected.png -------------------------------------------------------------------------------- /Cocos2dxGameClient/Resources/HelloWorld.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeliard/GameLift/4bdb482097cac9e362701732bff74e4398a1c174/Cocos2dxGameClient/Resources/HelloWorld.png -------------------------------------------------------------------------------- /Cocos2dxGameClient/Resources/Player.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeliard/GameLift/4bdb482097cac9e362701732bff74e4398a1c174/Cocos2dxGameClient/Resources/Player.png -------------------------------------------------------------------------------- /Cocos2dxGameClient/Resources/Projectile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeliard/GameLift/4bdb482097cac9e362701732bff74e4398a1c174/Cocos2dxGameClient/Resources/Projectile.png -------------------------------------------------------------------------------- /Cocos2dxGameClient/Resources/Target.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeliard/GameLift/4bdb482097cac9e362701732bff74e4398a1c174/Cocos2dxGameClient/Resources/Target.png -------------------------------------------------------------------------------- /Cocos2dxGameClient/Resources/fonts/Marker Felt.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeliard/GameLift/4bdb482097cac9e362701732bff74e4398a1c174/Cocos2dxGameClient/Resources/fonts/Marker Felt.ttf -------------------------------------------------------------------------------- /Cocos2dxGameClient/cclient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeliard/GameLift/4bdb482097cac9e362701732bff74e4398a1c174/Cocos2dxGameClient/cclient.png -------------------------------------------------------------------------------- /Cocos2dxGameClient/cocos2d/Readme.txt: -------------------------------------------------------------------------------- 1 | CoCos2d-x library is needed! 2 | 3 | Unzip a below file here 4 | 5 | https://github.com/zeliard/EasyGameServer/blob/master/Cocos2dxGameClient/cocos2d/unzip_this_here.zip 6 | -------------------------------------------------------------------------------- /Cocos2dxGameClient/proj.win32/CocosGameClient.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CocosGameClient", "CocosGameClient.vcxproj", "{76A39BB2-9B84-4C65-98A5-654D86B86F2A}" 5 | ProjectSection(ProjectDependencies) = postProject 6 | {98A51BA8-FC3A-415B-AC8F-8C7BD464E93E} = {98A51BA8-FC3A-415B-AC8F-8C7BD464E93E} 7 | {207BC7A9-CCF1-4F2F-A04D-45F72242AE25} = {207BC7A9-CCF1-4F2F-A04D-45F72242AE25} 8 | {F8EDD7FA-9A51-4E80-BAEB-860825D2EAC6} = {F8EDD7FA-9A51-4E80-BAEB-860825D2EAC6} 9 | EndProjectSection 10 | EndProject 11 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcocos2d", "..\cocos2d\cocos\2d\cocos2d.vcxproj", "{98A51BA8-FC3A-415B-AC8F-8C7BD464E93E}" 12 | EndProject 13 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libchipmunk", "..\cocos2d\external\chipmunk\proj.win32\chipmunk.vcxproj", "{207BC7A9-CCF1-4F2F-A04D-45F72242AE25}" 14 | EndProject 15 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libAudio", "..\cocos2d\cocos\audio\proj.win32\CocosDenshion.vcxproj", "{F8EDD7FA-9A51-4E80-BAEB-860825D2EAC6}" 16 | EndProject 17 | Global 18 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 19 | Debug|Win32 = Debug|Win32 20 | Release|Win32 = Release|Win32 21 | EndGlobalSection 22 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 23 | {76A39BB2-9B84-4C65-98A5-654D86B86F2A}.Debug|Win32.ActiveCfg = Debug|Win32 24 | {76A39BB2-9B84-4C65-98A5-654D86B86F2A}.Debug|Win32.Build.0 = Debug|Win32 25 | {76A39BB2-9B84-4C65-98A5-654D86B86F2A}.Release|Win32.ActiveCfg = Release|Win32 26 | {76A39BB2-9B84-4C65-98A5-654D86B86F2A}.Release|Win32.Build.0 = Release|Win32 27 | {98A51BA8-FC3A-415B-AC8F-8C7BD464E93E}.Debug|Win32.ActiveCfg = Debug|Win32 28 | {98A51BA8-FC3A-415B-AC8F-8C7BD464E93E}.Debug|Win32.Build.0 = Debug|Win32 29 | {98A51BA8-FC3A-415B-AC8F-8C7BD464E93E}.Release|Win32.ActiveCfg = Release|Win32 30 | {98A51BA8-FC3A-415B-AC8F-8C7BD464E93E}.Release|Win32.Build.0 = Release|Win32 31 | {207BC7A9-CCF1-4F2F-A04D-45F72242AE25}.Debug|Win32.ActiveCfg = Debug|Win32 32 | {207BC7A9-CCF1-4F2F-A04D-45F72242AE25}.Debug|Win32.Build.0 = Debug|Win32 33 | {207BC7A9-CCF1-4F2F-A04D-45F72242AE25}.Release|Win32.ActiveCfg = Release|Win32 34 | {207BC7A9-CCF1-4F2F-A04D-45F72242AE25}.Release|Win32.Build.0 = Release|Win32 35 | {F8EDD7FA-9A51-4E80-BAEB-860825D2EAC6}.Debug|Win32.ActiveCfg = Debug|Win32 36 | {F8EDD7FA-9A51-4E80-BAEB-860825D2EAC6}.Debug|Win32.Build.0 = Debug|Win32 37 | {F8EDD7FA-9A51-4E80-BAEB-860825D2EAC6}.Release|Win32.ActiveCfg = Release|Win32 38 | {F8EDD7FA-9A51-4E80-BAEB-860825D2EAC6}.Release|Win32.Build.0 = Release|Win32 39 | EndGlobalSection 40 | GlobalSection(SolutionProperties) = preSolution 41 | HideSolutionNode = FALSE 42 | EndGlobalSection 43 | EndGlobal 44 | -------------------------------------------------------------------------------- /Cocos2dxGameClient/proj.win32/CocosGameClient.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {84a8ebd7-7cf0-47f6-b75e-d441df67da40} 6 | 7 | 8 | {bb6c862e-70e9-49d9-81b7-3829a6f50471} 9 | 10 | 11 | {715254bc-d70b-4ec5-bf29-467dd3ace079} 12 | 13 | 14 | {a51839c6-905c-4295-8f40-5d0e1d05974e} 15 | 16 | 17 | 18 | 19 | win32 20 | 21 | 22 | Classes 23 | 24 | 25 | Classes 26 | 27 | 28 | Networking 29 | 30 | 31 | Networking 32 | 33 | 34 | Networking 35 | 36 | 37 | 38 | 39 | win32 40 | 41 | 42 | Classes 43 | 44 | 45 | Classes 46 | 47 | 48 | Networking 49 | 50 | 51 | Networking 52 | 53 | 54 | Networking 55 | 56 | 57 | 58 | 59 | resource 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /Cocos2dxGameClient/proj.win32/CocosGameClient.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(ProjectDir)..\Resources 5 | WindowsLocalDebugger 6 | NativeOnly 7 | 8 | 9 | $(ProjectDir)..\Resources 10 | WindowsLocalDebugger 11 | 12 | -------------------------------------------------------------------------------- /Cocos2dxGameClient/proj.win32/UserDefault.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 127.0.0.1 4 | 9001 5 | 6 | -------------------------------------------------------------------------------- /Cocos2dxGameClient/proj.win32/build-cfg.json: -------------------------------------------------------------------------------- 1 | { 2 | "copy_resources": [ 3 | { 4 | "from": "../Resources", 5 | "to": "" 6 | } 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /Cocos2dxGameClient/proj.win32/game.rc: -------------------------------------------------------------------------------- 1 | // Microsoft Visual C++ generated resource script. 2 | // 3 | #include "resource.h" 4 | 5 | #define APSTUDIO_READONLY_SYMBOLS 6 | ///////////////////////////////////////////////////////////////////////////// 7 | // 8 | // Generated from the TEXTINCLUDE 2 resource. 9 | // 10 | #define APSTUDIO_HIDDEN_SYMBOLS 11 | #include "windows.h" 12 | #undef APSTUDIO_HIDDEN_SYMBOLS 13 | ///////////////////////////////////////////////////////////////////////////// 14 | #undef APSTUDIO_READONLY_SYMBOLS 15 | 16 | ///////////////////////////////////////////////////////////////////////////// 17 | // English (U.S.) resources 18 | 19 | #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 20 | #ifdef _WIN32 21 | LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 22 | #pragma code_page(1252) 23 | #endif //_WIN32 24 | 25 | #ifdef APSTUDIO_INVOKED 26 | ///////////////////////////////////////////////////////////////////////////// 27 | // 28 | // TEXTINCLUDE 29 | // 30 | 31 | 1 TEXTINCLUDE 32 | BEGIN 33 | "resource.h\0" 34 | END 35 | 36 | #endif // APSTUDIO_INVOKED 37 | 38 | ///////////////////////////////////////////////////////////////////////////// 39 | // 40 | // Icon 41 | // 42 | 43 | // Icon with lowest ID value placed first to ensure application icon 44 | // remains consistent on all systems. 45 | GLFW_ICON ICON "res\\game.ico" 46 | 47 | ///////////////////////////////////////////////////////////////////////////// 48 | // 49 | // Version 50 | // 51 | 52 | VS_VERSION_INFO VERSIONINFO 53 | FILEVERSION 1,0,0,1 54 | PRODUCTVERSION 1,0,0,1 55 | FILEFLAGSMASK 0x3fL 56 | #ifdef _DEBUG 57 | FILEFLAGS 0x1L 58 | #else 59 | FILEFLAGS 0x0L 60 | #endif 61 | FILEOS 0x4L 62 | FILETYPE 0x2L 63 | FILESUBTYPE 0x0L 64 | BEGIN 65 | BLOCK "StringFileInfo" 66 | BEGIN 67 | BLOCK "040904B0" 68 | BEGIN 69 | VALUE "CompanyName", "\0" 70 | VALUE "FileDescription", "game Module\0" 71 | VALUE "FileVersion", "1, 0, 0, 1\0" 72 | VALUE "InternalName", "game\0" 73 | VALUE "LegalCopyright", "Copyright \0" 74 | VALUE "OriginalFilename", "game.exe\0" 75 | VALUE "ProductName", "game Module\0" 76 | VALUE "ProductVersion", "1, 0, 0, 1\0" 77 | END 78 | END 79 | BLOCK "VarFileInfo" 80 | BEGIN 81 | VALUE "Translation", 0x0409, 0x04B0 82 | END 83 | END 84 | 85 | ///////////////////////////////////////////////////////////////////////////// 86 | #endif // !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) 87 | -------------------------------------------------------------------------------- /Cocos2dxGameClient/proj.win32/main.cpp: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | #include "AppDelegate.h" 3 | #include "cocos2d.h" 4 | 5 | #include 6 | #include "GameLiftManager.h" 7 | 8 | #define ALIAS_ID "alias-xxxx-xxxx-input-yours" 9 | #define AWS_REGION "ap-northeast-1" 10 | 11 | USING_NS_CC; 12 | 13 | int APIENTRY _tWinMain(HINSTANCE hInstance, 14 | HINSTANCE hPrevInstance, 15 | LPTSTR lpCmdLine, 16 | int nCmdShow) 17 | { 18 | UNREFERENCED_PARAMETER(hPrevInstance); 19 | UNREFERENCED_PARAMETER(lpCmdLine); 20 | 21 | Aws::SDKOptions options; 22 | Aws::InitAPI(options); 23 | 24 | GGameLiftManager = new GameLiftManager(ALIAS_ID); 25 | 26 | GGameLiftManager->SetUpAwsClient(AWS_REGION); 27 | 28 | // create the application instance 29 | AppDelegate app; 30 | 31 | int end = Application::getInstance()->run(); 32 | 33 | Aws::ShutdownAPI(options); 34 | 35 | return end; 36 | } 37 | -------------------------------------------------------------------------------- /Cocos2dxGameClient/proj.win32/main.h: -------------------------------------------------------------------------------- 1 | #ifndef __MAIN_H__ 2 | #define __MAIN_H__ 3 | 4 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 5 | 6 | // Windows Header Files: 7 | #include 8 | #include 9 | 10 | // C RunTime Header Files 11 | #include "CCStdC.h" 12 | 13 | #endif // __MAIN_H__ 14 | -------------------------------------------------------------------------------- /Cocos2dxGameClient/proj.win32/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Cocos2dxGameClient/proj.win32/res/game.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeliard/GameLift/4bdb482097cac9e362701732bff74e4398a1c174/Cocos2dxGameClient/proj.win32/res/game.ico -------------------------------------------------------------------------------- /Cocos2dxGameClient/proj.win32/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by game.RC 4 | // 5 | 6 | #define IDS_PROJNAME 100 7 | #define IDR_TESTJS 100 8 | 9 | #define ID_FILE_NEW_WINDOW 32771 10 | 11 | // Next default values for new objects 12 | // 13 | #ifdef APSTUDIO_INVOKED 14 | #ifndef APSTUDIO_READONLY_SYMBOLS 15 | #define _APS_NEXT_RESOURCE_VALUE 201 16 | #define _APS_NEXT_CONTROL_VALUE 1000 17 | #define _APS_NEXT_SYMED_VALUE 101 18 | #define _APS_NEXT_COMMAND_VALUE 32775 19 | #endif 20 | #endif 21 | -------------------------------------------------------------------------------- /DummyClients/DummyClients.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DummyClients", "DummyClients\DummyClients.vcxproj", "{EC4C7B39-96D7-4D18-8034-9B6AA52BCA58}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {EC4C7B39-96D7-4D18-8034-9B6AA52BCA58}.Debug|x64.ActiveCfg = Debug|x64 15 | {EC4C7B39-96D7-4D18-8034-9B6AA52BCA58}.Debug|x64.Build.0 = Debug|x64 16 | {EC4C7B39-96D7-4D18-8034-9B6AA52BCA58}.Release|x64.ActiveCfg = Release|x64 17 | {EC4C7B39-96D7-4D18-8034-9B6AA52BCA58}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /DummyClients/DummyClients/CircularBuffer.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeliard/GameLift/4bdb482097cac9e362701732bff74e4398a1c174/DummyClients/DummyClients/CircularBuffer.cpp -------------------------------------------------------------------------------- /DummyClients/DummyClients/CircularBuffer.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeliard/GameLift/4bdb482097cac9e362701732bff74e4398a1c174/DummyClients/DummyClients/CircularBuffer.h -------------------------------------------------------------------------------- /DummyClients/DummyClients/DummyClients.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | 3 | #include 4 | 5 | #include "PacketType.h" 6 | #include "DummyClients.h" 7 | #include "Exception.h" 8 | #include "PlayerSession.h" 9 | #include "GameSession.h" 10 | #include "IocpManager.h" 11 | #include "GameLiftManager.h" 12 | #include "Log.h" 13 | #include "INIReader.h" 14 | 15 | 16 | int PLAYER_ACTION_REQUEST = 0; 17 | int TEST_PLAYER_SESSION_EXCEPT = 0; 18 | int PLAYER_ACTION_INTERVAL = 1000; 19 | 20 | int _tmain(int argc, _TCHAR* argv[]) 21 | { 22 | INIReader iniReader("config.ini"); 23 | if (iniReader.ParseError() < 0) 24 | { 25 | printf_s("config.ini not found\n"); 26 | return 0; 27 | } 28 | 29 | const std::string& aliasId = iniReader.Get("config", "ALIAS_ID", "TEST_LOCAL"); 30 | const std::string& region = iniReader.Get("config", "GAMELIFT_REGION", "127.0.0.1:9080"); 31 | const std::string& matchQueue = iniReader.Get("config", "MATCH_QUEUE_NAME", "NotUse"); 32 | 33 | int maxGameSessionCount = iniReader.GetInteger("config", "MAX_GAME_SESSIONS", 1); 34 | 35 | PLAYER_ACTION_REQUEST = iniReader.GetInteger("config", "PLAYER_ACTION_REQUEST", 60); 36 | PLAYER_ACTION_INTERVAL = iniReader.GetInteger("config", "PLAYER_ACTION_INTERVAL", 1000); 37 | 38 | int dummySessionCountPerGameSession = iniReader.GetInteger("config", "DUMMY_PLAYER_SESSION_PER_GAME_SESSION", 8); 39 | TEST_PLAYER_SESSION_EXCEPT = MAX_PLAYER_PER_GAME - dummySessionCountPerGameSession; 40 | 41 | Aws::SDKOptions options; 42 | Aws::InitAPI(options); 43 | 44 | LThreadType = THREAD_MAIN; 45 | 46 | /// for dump on crash 47 | SetUnhandledExceptionFilter(ExceptionFilter); 48 | 49 | /// Global Managers 50 | GConsoleLog = new ConsoleLog(".\\DummyClientsLog.txt"); 51 | GIocpManager = new IocpManager; 52 | GGameLiftManager = new GameLiftManager(aliasId, region, matchQueue); 53 | 54 | GGameLiftManager->SetUpAwsClient(region); 55 | 56 | if (false == GIocpManager->Initialize()) 57 | return -1; 58 | 59 | GGameLiftManager->PrepareGameSessions(maxGameSessionCount); 60 | 61 | if (false == GIocpManager->StartIoThreads()) 62 | return -1; 63 | 64 | printf_s("Start Game Sessions...\n"); 65 | 66 | 67 | if (matchQueue == "NotUse") 68 | GGameLiftManager->LaunchGameSessions(); 69 | else 70 | GGameLiftManager->LaunchGameSessionPlacement(); 71 | 72 | 73 | /// block here... 74 | getchar(); 75 | 76 | printf_s("Terminating Game Sessions...\n"); 77 | 78 | /// Disconnect request here 79 | GGameLiftManager->TerminateGameSessions(); 80 | 81 | GIocpManager->StopIoThreads(); 82 | 83 | GIocpManager->Finalize(); 84 | 85 | Aws::ShutdownAPI(options); 86 | 87 | delete GConsoleLog; 88 | return 0; 89 | } 90 | 91 | -------------------------------------------------------------------------------- /DummyClients/DummyClients/DummyClients.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | /// request sending interval (ms) 5 | extern int PLAYER_ACTION_INTERVAL; 6 | 7 | /// How many times to send a request 8 | extern int PLAYER_ACTION_REQUEST; 9 | 10 | /// Test Player Session Count == mMaxPlayerCount - TEST_PLAYER_SESSION_EXCEPT 11 | extern int TEST_PLAYER_SESSION_EXCEPT; 12 | 13 | -------------------------------------------------------------------------------- /DummyClients/DummyClients/DummyClientsLog.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeliard/GameLift/4bdb482097cac9e362701732bff74e4398a1c174/DummyClients/DummyClients/DummyClientsLog.txt -------------------------------------------------------------------------------- /DummyClients/DummyClients/Exception.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "ThreadLocal.h" 3 | #include "Exception.h" 4 | #include "Log.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define MAX_BUFF_SIZE 1024 11 | 12 | void MakeDump(EXCEPTION_POINTERS* e) 13 | { 14 | TCHAR tszFileName[MAX_BUFF_SIZE] = { 0 }; 15 | SYSTEMTIME stTime = { 0 }; 16 | GetSystemTime(&stTime); 17 | StringCbPrintf(tszFileName, 18 | _countof(tszFileName), 19 | _T("%s_%4d%02d%02d_%02d%02d%02d.dmp"), 20 | _T("EduServerDump"), 21 | stTime.wYear, 22 | stTime.wMonth, 23 | stTime.wDay, 24 | stTime.wHour, 25 | stTime.wMinute, 26 | stTime.wSecond); 27 | 28 | HANDLE hFile = CreateFile(tszFileName, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); 29 | if (hFile == INVALID_HANDLE_VALUE) 30 | return; 31 | 32 | MINIDUMP_EXCEPTION_INFORMATION exceptionInfo; 33 | exceptionInfo.ThreadId = GetCurrentThreadId(); 34 | exceptionInfo.ExceptionPointers = e; 35 | exceptionInfo.ClientPointers = FALSE; 36 | 37 | MiniDumpWriteDump( 38 | GetCurrentProcess(), 39 | GetCurrentProcessId(), 40 | hFile, 41 | MINIDUMP_TYPE(MiniDumpWithIndirectlyReferencedMemory | MiniDumpScanMemory | MiniDumpWithFullMemory), 42 | e ? &exceptionInfo : NULL, 43 | NULL, 44 | NULL); 45 | 46 | if (hFile) 47 | { 48 | CloseHandle(hFile); 49 | hFile = NULL; 50 | } 51 | 52 | } 53 | 54 | 55 | LONG WINAPI ExceptionFilter(EXCEPTION_POINTERS* exceptionInfo) 56 | { 57 | if ( IsDebuggerPresent() ) 58 | return EXCEPTION_CONTINUE_SEARCH ; 59 | 60 | 61 | THREADENTRY32 te32; 62 | DWORD myThreadId = GetCurrentThreadId(); 63 | DWORD myProcessId = GetCurrentProcessId(); 64 | 65 | HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); 66 | if (hThreadSnap != INVALID_HANDLE_VALUE) 67 | { 68 | te32.dwSize = sizeof(THREADENTRY32); 69 | 70 | if (Thread32First(hThreadSnap, &te32)) 71 | { 72 | do 73 | { 74 | /// 내 프로세스 내의 스레드중 나 자신 스레드만 빼고 멈추게.. 75 | if (te32.th32OwnerProcessID == myProcessId && te32.th32ThreadID != myThreadId) 76 | { 77 | HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, te32.th32ThreadID); 78 | if (hThread) 79 | { 80 | SuspendThread(hThread); 81 | } 82 | } 83 | 84 | } while (Thread32Next(hThreadSnap, &te32)); 85 | 86 | } 87 | 88 | CloseHandle(hThreadSnap); 89 | } 90 | 91 | 92 | std::ofstream historyOut("EduServer_exception.txt", std::ofstream::out); 93 | 94 | /// 콜히스토리 남기고 95 | historyOut << "========== WorkerThread Call History ==========" << std::endl << std::endl; 96 | for (int i = 0; i < MAX_IOTHREAD; ++i) 97 | { 98 | if (GThreadCallHistory[i]) 99 | { 100 | GThreadCallHistory[i]->DumpOut(historyOut); 101 | } 102 | } 103 | 104 | historyOut.flush(); 105 | historyOut.close(); 106 | 107 | /// 마지막으로 dump file 남기자. 108 | MakeDump(exceptionInfo); 109 | 110 | 111 | ExitProcess(1); 112 | /// 여기서 쫑 113 | 114 | return EXCEPTION_EXECUTE_HANDLER; 115 | 116 | } -------------------------------------------------------------------------------- /DummyClients/DummyClients/Exception.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | LONG WINAPI ExceptionFilter(EXCEPTION_POINTERS* exceptionInfo) ; 4 | 5 | inline void CRASH_ASSERT(bool isOk) 6 | { 7 | if ( isOk ) 8 | return ; 9 | 10 | int* crashVal = 0 ; 11 | *crashVal = 0xDEADBEEF ; 12 | } 13 | -------------------------------------------------------------------------------- /DummyClients/DummyClients/FastSpinlock.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "FastSpinlock.h" 3 | 4 | 5 | FastSpinlock::FastSpinlock() : mLockFlag(0) 6 | { 7 | } 8 | 9 | 10 | FastSpinlock::~FastSpinlock() 11 | { 12 | } 13 | 14 | 15 | void FastSpinlock::EnterLock() 16 | { 17 | for (int nloops = 0; ; nloops++) 18 | { 19 | if ( InterlockedExchange(&mLockFlag, 1) == 0 ) 20 | return; 21 | 22 | UINT uTimerRes = 1; 23 | timeBeginPeriod(uTimerRes); 24 | Sleep((DWORD)std::min(10, nloops)); 25 | timeEndPeriod(uTimerRes); 26 | } 27 | 28 | } 29 | 30 | void FastSpinlock::LeaveLock() 31 | { 32 | InterlockedExchange(&mLockFlag, 0); 33 | } -------------------------------------------------------------------------------- /DummyClients/DummyClients/FastSpinlock.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class FastSpinlock 4 | { 5 | public: 6 | FastSpinlock(); 7 | ~FastSpinlock(); 8 | 9 | void EnterLock(); 10 | void LeaveLock(); 11 | 12 | private: 13 | FastSpinlock(const FastSpinlock& rhs); 14 | FastSpinlock& operator=(const FastSpinlock& rhs); 15 | 16 | volatile long mLockFlag; 17 | }; 18 | 19 | class FastSpinlockGuard 20 | { 21 | public: 22 | FastSpinlockGuard(FastSpinlock& lock) : mLock(lock) 23 | { 24 | mLock.EnterLock(); 25 | } 26 | 27 | ~FastSpinlockGuard() 28 | { 29 | mLock.LeaveLock(); 30 | } 31 | 32 | private: 33 | FastSpinlock& mLock; 34 | }; 35 | 36 | template 37 | class ClassTypeLock 38 | { 39 | public: 40 | struct LockGuard 41 | { 42 | LockGuard() 43 | { 44 | TargetClass::mLock.EnterLock(); 45 | } 46 | 47 | ~LockGuard() 48 | { 49 | TargetClass::mLock.LeaveLock(); 50 | } 51 | 52 | }; 53 | 54 | private: 55 | static FastSpinlock mLock; 56 | 57 | //friend struct LockGuard; 58 | }; 59 | 60 | template 61 | FastSpinlock ClassTypeLock::mLock; -------------------------------------------------------------------------------- /DummyClients/DummyClients/GameLiftManager.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "GameLiftManager.h" 3 | #include "GameSession.h" 4 | #include "PacketType.h" 5 | #include 6 | #include 7 | 8 | 9 | 10 | GameLiftManager* GGameLiftManager = nullptr; 11 | 12 | 13 | 14 | GameLiftManager::GameLiftManager(const std::string& alias, const std::string& region, const std::string& matchQueue) 15 | : mAliasId(alias), mRegion(region), mMatchQueueName(matchQueue) 16 | { 17 | } 18 | 19 | void GameLiftManager::SetUpAwsClient(const std::string& region) 20 | { 21 | Aws::Client::ClientConfiguration config; 22 | config.scheme = Aws::Http::Scheme::HTTPS; 23 | config.connectTimeoutMs = 10000; 24 | config.requestTimeoutMs = 10000; 25 | 26 | config.region = region; 27 | 28 | /// In case of GameLift Local 29 | if (mAliasId == "TEST_LOCAL") 30 | { 31 | config.scheme = Aws::Http::Scheme::HTTP; 32 | config.endpointOverride = region; 33 | } 34 | 35 | mGLClient = Aws::MakeShared("GameLiftTest", config); 36 | } 37 | 38 | void GameLiftManager::PrepareGameSessions(int gsCount) 39 | { 40 | for (int i = 0; i < gsCount; ++i) 41 | { 42 | std::string gsName = "MyTestGameSession" + std::to_string(i+1); 43 | 44 | auto newGs = std::make_shared(i*MAX_PLAYER_PER_GAME, MAX_PLAYER_PER_GAME, gsName); 45 | 46 | newGs->PreparePlayerSessions(); 47 | 48 | mGameSessions.push_back(newGs); 49 | } 50 | 51 | } 52 | 53 | void GameLiftManager::LaunchGameSessions() 54 | { 55 | for (auto& gs : mGameSessions) 56 | { 57 | if (gs->CreateGameSession()) 58 | { 59 | if (gs->CreatePlayerSessions()) 60 | { 61 | gs->ConnectPlayerSessions(); 62 | } 63 | } 64 | Sleep(1000); 65 | } 66 | } 67 | 68 | void GameLiftManager::TerminateGameSessions() 69 | { 70 | for (auto& gs : mGameSessions) 71 | { 72 | gs->DisconnectPlayerSessions(); 73 | } 74 | } 75 | 76 | void GameLiftManager::LaunchGameSessionPlacement() 77 | { 78 | for (auto& gs : mGameSessions) 79 | { 80 | if (gs->StartGameSessionPlacement()) 81 | { 82 | if (gs->CreatePlayerSessions()) 83 | { 84 | gs->ConnectPlayerSessions(); 85 | } 86 | } 87 | Sleep(1000); 88 | } 89 | } 90 | 91 | -------------------------------------------------------------------------------- /DummyClients/DummyClients/GameLiftManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class GameSession; 6 | class GameLiftManager 7 | { 8 | public: 9 | GameLiftManager(const std::string& alias, const std::string& region, const std::string& matchQueue); 10 | 11 | void SetUpAwsClient(const std::string& region); 12 | void PrepareGameSessions(int gsCount); 13 | void LaunchGameSessions(); 14 | void TerminateGameSessions(); 15 | 16 | /// New API Test: StartGameSessionPlacement 17 | void LaunchGameSessionPlacement(); 18 | 19 | std::shared_ptr GetAwsClient() 20 | { 21 | return mGLClient; 22 | } 23 | 24 | const std::string& GetAliasId() const 25 | { 26 | return mAliasId; 27 | } 28 | 29 | const std::string& GetRegion() const 30 | { 31 | return mRegion; 32 | } 33 | 34 | const std::string& GetMatchQueue() const 35 | { 36 | return mMatchQueueName; 37 | } 38 | 39 | 40 | private: 41 | std::shared_ptr mGLClient; 42 | 43 | std::string mRegion; 44 | 45 | std::string mAliasId; ///< only used if MatchQueue mode is not enabled. 46 | std::string mMatchQueueName; ///< only used when MatchQueue enabled 47 | 48 | std::vector> mGameSessions; 49 | }; 50 | 51 | extern GameLiftManager* GGameLiftManager; -------------------------------------------------------------------------------- /DummyClients/DummyClients/GameSession.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "FastSpinlock.h" 5 | #include "DummyClients.h" 6 | #include 7 | 8 | class PlayerSession; 9 | 10 | class GameSession 11 | { 12 | public: 13 | GameSession(int startPlayerId, int maxPlayerCount, const std::string& name) 14 | : mStartPlayerId(startPlayerId), mMaxPlayerCount(maxPlayerCount), mGameSessionName(name) 15 | , mPort(-1) 16 | {} 17 | 18 | ~GameSession(); 19 | 20 | bool PreparePlayerSessions(); 21 | 22 | bool CreateGameSession(); 23 | bool FindAvailableGameSession(); 24 | 25 | bool CreatePlayerSessions(); 26 | bool ConnectPlayerSessions(); 27 | void DisconnectPlayerSessions(); 28 | 29 | bool StartGameSessionPlacement(); 30 | bool CheckGameSessionPlacement(); 31 | 32 | void GeneratePlacementId(); 33 | 34 | private: 35 | typedef std::list ClientList; 36 | ClientList mReadySessionList; 37 | 38 | FastSpinlock mLock; 39 | 40 | int mStartPlayerId; 41 | int mMaxPlayerCount; 42 | std::string mGameSessionName; 43 | 44 | /// retrieved info 45 | int mPort; 46 | std::string mIpAddress; 47 | std::string mGameSessionId; 48 | 49 | std::vector mPlayerSessionList; 50 | 51 | std::string mPlacementId; 52 | 53 | friend class PlayerSession; 54 | }; 55 | 56 | 57 | -------------------------------------------------------------------------------- /DummyClients/DummyClients/INIReader.cpp: -------------------------------------------------------------------------------- 1 | // Read an INI file into easy-to-access name/value pairs. 2 | 3 | // inih and INIReader are released under the New BSD license (see LICENSE.txt). 4 | // Go to the project home page for more info: 5 | // 6 | // https://github.com/benhoyt/inih 7 | 8 | #include 9 | #include 10 | #include 11 | #include "ini.h" 12 | #include "INIReader.h" 13 | 14 | using std::string; 15 | 16 | INIReader::INIReader(const string& filename) 17 | { 18 | _error = ini_parse(filename.c_str(), ValueHandler, this); 19 | } 20 | 21 | int INIReader::ParseError() const 22 | { 23 | return _error; 24 | } 25 | 26 | string INIReader::Get(const string& section, const string& name, const string& default_value) const 27 | { 28 | string key = MakeKey(section, name); 29 | // Use _values.find() here instead of _values.at() to support pre C++11 compilers 30 | return _values.count(key) ? _values.find(key)->second : default_value; 31 | } 32 | 33 | long INIReader::GetInteger(const string& section, const string& name, long default_value) const 34 | { 35 | string valstr = Get(section, name, ""); 36 | const char* value = valstr.c_str(); 37 | char* end; 38 | // This parses "1234" (decimal) and also "0x4D2" (hex) 39 | long n = strtol(value, &end, 0); 40 | return end > value ? n : default_value; 41 | } 42 | 43 | double INIReader::GetReal(const string& section, const string& name, double default_value) const 44 | { 45 | string valstr = Get(section, name, ""); 46 | const char* value = valstr.c_str(); 47 | char* end; 48 | double n = strtod(value, &end); 49 | return end > value ? n : default_value; 50 | } 51 | 52 | bool INIReader::GetBoolean(const string& section, const string& name, bool default_value) const 53 | { 54 | string valstr = Get(section, name, ""); 55 | // Convert to lower case to make string comparisons case-insensitive 56 | std::transform(valstr.begin(), valstr.end(), valstr.begin(), ::tolower); 57 | if (valstr == "true" || valstr == "yes" || valstr == "on" || valstr == "1") 58 | return true; 59 | else if (valstr == "false" || valstr == "no" || valstr == "off" || valstr == "0") 60 | return false; 61 | else 62 | return default_value; 63 | } 64 | 65 | string INIReader::MakeKey(const string& section, const string& name) 66 | { 67 | string key = section + "=" + name; 68 | // Convert to lower case to make section/name lookups case-insensitive 69 | std::transform(key.begin(), key.end(), key.begin(), ::tolower); 70 | return key; 71 | } 72 | 73 | int INIReader::ValueHandler(void* user, const char* section, const char* name, 74 | const char* value) 75 | { 76 | INIReader* reader = (INIReader*)user; 77 | string key = MakeKey(section, name); 78 | if (reader->_values[key].size() > 0) 79 | reader->_values[key] += "\n"; 80 | reader->_values[key] += value; 81 | return 1; 82 | } 83 | -------------------------------------------------------------------------------- /DummyClients/DummyClients/INIReader.h: -------------------------------------------------------------------------------- 1 | // Read an INI file into easy-to-access name/value pairs. 2 | 3 | // inih and INIReader are released under the New BSD license (see LICENSE.txt). 4 | // Go to the project home page for more info: 5 | // 6 | // https://github.com/benhoyt/inih 7 | 8 | #ifndef __INIREADER_H__ 9 | #define __INIREADER_H__ 10 | 11 | #include 12 | #include 13 | 14 | // Read an INI file into easy-to-access name/value pairs. (Note that I've gone 15 | // for simplicity here rather than speed, but it should be pretty decent.) 16 | class INIReader 17 | { 18 | public: 19 | // Construct INIReader and parse given filename. See ini.h for more info 20 | // about the parsing. 21 | INIReader(const std::string& filename); 22 | 23 | // Return the result of ini_parse(), i.e., 0 on success, line number of 24 | // first error on parse error, or -1 on file open error. 25 | int ParseError() const; 26 | 27 | // Get a string value from INI file, returning default_value if not found. 28 | std::string Get(const std::string& section, const std::string& name, 29 | const std::string& default_value) const; 30 | 31 | // Get an integer (long) value from INI file, returning default_value if 32 | // not found or not a valid integer (decimal "1234", "-1234", or hex "0x4d2"). 33 | long GetInteger(const std::string& section, const std::string& name, long default_value) const; 34 | 35 | // Get a real (floating point double) value from INI file, returning 36 | // default_value if not found or not a valid floating point value 37 | // according to strtod(). 38 | double GetReal(const std::string& section, const std::string& name, double default_value) const; 39 | 40 | // Get a boolean value from INI file, returning default_value if not found or if 41 | // not a valid true/false value. Valid true values are "true", "yes", "on", "1", 42 | // and valid false values are "false", "no", "off", "0" (not case sensitive). 43 | bool GetBoolean(const std::string& section, const std::string& name, bool default_value) const; 44 | 45 | private: 46 | int _error; 47 | std::map _values; 48 | static std::string MakeKey(const std::string& section, const std::string& name); 49 | static int ValueHandler(void* user, const char* section, const char* name, 50 | const char* value); 51 | }; 52 | 53 | #endif // __INIREADER_H__ 54 | -------------------------------------------------------------------------------- /DummyClients/DummyClients/IocpManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "ThreadLocal.h" 3 | #include "DummyClients.h" 4 | 5 | class Session; 6 | class WorkerThread; 7 | 8 | struct OverlappedSendContext; 9 | struct OverlappedPreRecvContext; 10 | struct OverlappedRecvContext; 11 | struct OverlappedDisconnectContext; 12 | 13 | #define GQCS_TIMEOUT 10 14 | 15 | enum COMPLETION_KEY 16 | { 17 | CK_NONE, 18 | CK_STOP_NOW = 0xDEAD 19 | }; 20 | 21 | 22 | class IocpManager 23 | { 24 | public: 25 | IocpManager(); 26 | ~IocpManager(); 27 | 28 | bool Initialize(); 29 | void Finalize(); 30 | 31 | bool StartIoThreads(); 32 | void StopIoThreads(); 33 | 34 | HANDLE GetComletionPort() { return mCompletionPort; } 35 | int GetIoThreadCount() { return mIoThreadCount; } 36 | 37 | static LPFN_DISCONNECTEX mFnDisconnectEx; 38 | static LPFN_CONNECTEX mFnConnectEx; 39 | 40 | private: 41 | 42 | static unsigned int WINAPI IoWorkerThread(LPVOID lpParam); 43 | 44 | private: 45 | 46 | HANDLE mCompletionPort; 47 | int mIoThreadCount; 48 | 49 | 50 | WorkerThread* mWorkerThread[MAX_IOTHREAD]; 51 | }; 52 | 53 | 54 | extern IocpManager* GIocpManager; 55 | 56 | BOOL DisconnectEx(SOCKET hSocket, LPOVERLAPPED lpOverlapped, DWORD dwFlags, DWORD reserved); 57 | 58 | BOOL ConnectEx(SOCKET hSocket, const struct sockaddr* name, int namelen, PVOID lpSendBuffer, DWORD dwSendDataLength, 59 | LPDWORD lpdwBytesSent, LPOVERLAPPED lpOverlapped); -------------------------------------------------------------------------------- /DummyClients/DummyClients/Job.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "ObjectPool.h" 5 | 6 | template 7 | struct TupleUnpacker 8 | { 9 | template 10 | static void DoExecute(ObjType* obj, void (ObjType::*memfunc)(FuncArgs...), const std::tuple& targ, Args&&... args) 11 | { 12 | TupleUnpacker::DoExecute(obj, memfunc, targ, std::get(targ), std::forward(args)...); 13 | } 14 | }; 15 | 16 | template <> 17 | struct TupleUnpacker<0> 18 | { 19 | template 20 | static void DoExecute(ObjType* obj, void (ObjType::*memfunc)(FuncArgs...), const std::tuple& targ, Args&&... args) 21 | { 22 | (obj->*memfunc)(std::forward(args)...); 23 | } 24 | }; 25 | 26 | 27 | template 28 | void DoExecuteTuple(ObjType* obj, void (ObjType::*memfunc)(FuncArgs...), std::tuple const& targ) 29 | { 30 | TupleUnpacker::DoExecute(obj, memfunc, targ); 31 | } 32 | 33 | 34 | struct NodeEntry 35 | { 36 | NodeEntry() : mNext(nullptr) {} 37 | NodeEntry* volatile mNext; 38 | }; 39 | 40 | struct JobEntry 41 | { 42 | JobEntry() {} 43 | virtual ~JobEntry() {} 44 | 45 | virtual void OnExecute() 46 | {} 47 | 48 | NodeEntry mNodeEntry; 49 | } ; 50 | 51 | 52 | template 53 | struct Job : public JobEntry, ObjectPool> 54 | { 55 | typedef void (ObjType::*MemFunc_)(ArgTypes... args); 56 | typedef std::tuple Args_; 57 | 58 | 59 | Job(ObjType* obj, MemFunc_ memfunc, ArgTypes&&... args) 60 | : mObject(obj), mMemFunc(memfunc), mArgs(std::forward(args)...) 61 | {} 62 | 63 | virtual ~Job() {} 64 | 65 | virtual void OnExecute() 66 | { 67 | DoExecuteTuple(mObject, mMemFunc, mArgs); 68 | } 69 | 70 | ObjType* mObject; 71 | MemFunc_ mMemFunc; 72 | Args_ mArgs; 73 | }; 74 | 75 | 76 | -------------------------------------------------------------------------------- /DummyClients/DummyClients/Log.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Log.h" 3 | 4 | #include 5 | 6 | void ThreadCallHistory::DumpOut(std::ostream& ost) 7 | { 8 | uint64_t count = mCounter < MAX_HISTORY ? mCounter : MAX_HISTORY; 9 | 10 | ost << "===== Recent Call History [Thread:" << mThreadId << "]" << std::endl ; 11 | 12 | for (int i = 1; i <= count; ++i) 13 | { 14 | ost << " " << mHistory[(mCounter-i) % MAX_HISTORY] << std::endl; 15 | } 16 | ost << "===== End of Recent Call History" << std::endl << std::endl; 17 | } 18 | 19 | 20 | namespace LoggerUtil 21 | { 22 | LogEvent gLogEvents[MAX_LOG_SIZE]; 23 | __int64 gCurrentLogIndex = 0; 24 | } 25 | 26 | ConsoleLog::ConsoleLog(const char* filename) 27 | { 28 | mLogFileStream.open(filename, std::ofstream::out); 29 | } 30 | 31 | ConsoleLog::~ConsoleLog() 32 | { 33 | mLogFileStream.close(); 34 | } 35 | 36 | void ConsoleLog::PrintOut(bool fileOut, const char* fmt, ...) 37 | { 38 | FastSpinlockGuard lock(mLock); 39 | 40 | char buf[512] = {}; 41 | 42 | va_list args; 43 | va_start(args, fmt); 44 | vsprintf_s(buf, fmt, args); 45 | va_end(args); 46 | 47 | printf_s("%s", buf); 48 | 49 | if (fileOut) 50 | { 51 | mLogFileStream << buf; 52 | mLogFileStream.flush(); 53 | } 54 | } 55 | 56 | ConsoleLog* GConsoleLog = nullptr; 57 | 58 | -------------------------------------------------------------------------------- /DummyClients/DummyClients/Log.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "Exception.h" 5 | #include "ThreadLocal.h" 6 | #include "FastSpinlock.h" 7 | 8 | class ThreadCallHistory 9 | { 10 | public: 11 | ThreadCallHistory(int tid) : mThreadId(tid) 12 | { 13 | memset(mHistory, 0, sizeof(mHistory)); 14 | } 15 | 16 | inline void Append(const char* funsig) 17 | { 18 | mHistory[mCounter++ % MAX_HISTORY] = funsig; 19 | } 20 | 21 | void DumpOut(std::ostream& ost = std::cout); 22 | 23 | private: 24 | enum 25 | { 26 | MAX_HISTORY = 1024 27 | }; 28 | 29 | uint64_t mCounter = 0; 30 | int mThreadId = -1; 31 | const char* mHistory[MAX_HISTORY]; 32 | }; 33 | 34 | 35 | #define TRACE_THIS \ 36 | __if_exists (this) \ 37 | { \ 38 | LRecentThisPointer = (void*)this; \ 39 | } \ 40 | if (LThreadType == THREAD_IO_WORKER) \ 41 | { \ 42 | LThreadCallHistory->Append(__FUNCSIG__); \ 43 | } 44 | 45 | 46 | 47 | 48 | 49 | namespace LoggerUtil 50 | { 51 | 52 | struct LogEvent 53 | { 54 | int mThreadId = -1; 55 | int mAdditionalInfo = 0; 56 | const char* mMessage = nullptr; 57 | }; 58 | 59 | #define MAX_LOG_SIZE 65536 ///< Must be a power of 2 60 | 61 | extern LogEvent gLogEvents[MAX_LOG_SIZE]; 62 | extern __int64 gCurrentLogIndex; 63 | 64 | inline void EventLog(const char* msg, int info) 65 | { 66 | __int64 index = _InterlockedIncrement64(&gCurrentLogIndex) - 1; 67 | LogEvent& event = gLogEvents[index & (MAX_LOG_SIZE - 1)]; 68 | event.mThreadId = LWorkerThreadId; 69 | event.mMessage = msg; 70 | event.mAdditionalInfo = info; 71 | } 72 | } 73 | 74 | #define EVENT_LOG(x, info) LoggerUtil::EventLog(x, info) 75 | 76 | 77 | class ConsoleLog 78 | { 79 | public: 80 | ConsoleLog(const char* filename); 81 | ~ConsoleLog(); 82 | 83 | void PrintOut(bool fileOut, const char* fmt, ...); 84 | 85 | private: 86 | FastSpinlock mLock; 87 | std::ofstream mLogFileStream; 88 | }; 89 | 90 | extern ConsoleLog* GConsoleLog; 91 | -------------------------------------------------------------------------------- /DummyClients/DummyClients/ObjectPool.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | /// 64bit only 7 | #define ALIGNMENT 8 8 | 9 | template 10 | class ObjectPool 11 | { 12 | public: 13 | 14 | enum 15 | { 16 | POOL_MAX_SIZE = 4096, ///< must be power of 2 17 | POOL_SIZE_MASK = POOL_MAX_SIZE - 1 18 | }; 19 | 20 | /// memory pre- allocation is just optional :) 21 | static void PrepareAllocation() 22 | { 23 | for (int i = 0; i < POOL_MAX_SIZE; ++i) 24 | mPool[i] = _aligned_malloc(sizeof(T), ALIGNMENT); 25 | 26 | mTailPos.fetch_add(POOL_MAX_SIZE); 27 | } 28 | 29 | static void* operator new(size_t objSize) 30 | { 31 | uint64_t popPos = mHeadPos.fetch_add(1); 32 | 33 | void* popVal = std::atomic_exchange(&mPool[popPos & POOL_SIZE_MASK], (void*)nullptr); 34 | if (popVal != nullptr) 35 | return popVal; 36 | 37 | return _aligned_malloc(objSize, ALIGNMENT); 38 | } 39 | 40 | static void operator delete(void* obj) 41 | { 42 | uint64_t insPos = mTailPos.fetch_add(1); 43 | 44 | void* prevVal = std::atomic_exchange(&mPool[insPos & POOL_SIZE_MASK], obj); 45 | 46 | if (prevVal != nullptr) 47 | _aligned_free(prevVal); 48 | } 49 | 50 | 51 | private: 52 | 53 | static std::atomic mPool[POOL_MAX_SIZE]; 54 | static std::atomic mHeadPos; 55 | static std::atomic mTailPos; 56 | 57 | static_assert((POOL_MAX_SIZE & POOL_SIZE_MASK) == 0x0, "pool's size must be power of 2"); 58 | }; 59 | 60 | template 61 | std::atomic ObjectPool::mPool[POOL_MAX_SIZE] = {}; 62 | 63 | template 64 | std::atomic ObjectPool::mHeadPos(0); 65 | 66 | template 67 | std::atomic ObjectPool::mTailPos(0); 68 | -------------------------------------------------------------------------------- /DummyClients/DummyClients/OverlappedIOContext.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Exception.h" 3 | #include "OverlappedIOContext.h" 4 | #include "PlayerSession.h" 5 | 6 | OverlappedIOContext::OverlappedIOContext(Session* owner, IOType ioType) 7 | : mSessionObject(owner), mIoType(ioType) 8 | { 9 | memset(&mOverlapped, 0, sizeof(OVERLAPPED)); 10 | memset(&mWsaBuf, 0, sizeof(WSABUF)); 11 | mSessionObject->AddRef(); 12 | } 13 | 14 | 15 | 16 | void DeleteIoContext(OverlappedIOContext* context) 17 | { 18 | if (nullptr == context) 19 | return; 20 | 21 | context->mSessionObject->ReleaseRef(); 22 | 23 | /// ObjectPool's operate delete dispatch 24 | switch (context->mIoType) 25 | { 26 | case IO_SEND: 27 | delete static_cast(context); 28 | break; 29 | 30 | case IO_RECV_ZERO: 31 | delete static_cast(context); 32 | break; 33 | 34 | case IO_RECV: 35 | delete static_cast(context); 36 | break; 37 | 38 | case IO_DISCONNECT: 39 | delete static_cast(context); 40 | break; 41 | 42 | case IO_CONNECT: 43 | delete static_cast(context); 44 | break; 45 | 46 | default: 47 | CRASH_ASSERT(false); 48 | } 49 | 50 | 51 | } 52 | 53 | -------------------------------------------------------------------------------- /DummyClients/DummyClients/OverlappedIOContext.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ObjectPool.h" 4 | 5 | enum IOType 6 | { 7 | IO_NONE, 8 | IO_SEND, 9 | IO_RECV, 10 | IO_RECV_ZERO, 11 | 12 | IO_DISCONNECT, 13 | IO_CONNECT 14 | }; 15 | 16 | enum DisconnectReason 17 | { 18 | DR_NONE, 19 | DR_ACTIVE, 20 | DR_ONCONNECT_ERROR, 21 | DR_IO_REQUEST_ERROR, 22 | DR_COMPLETION_ERROR, 23 | }; 24 | 25 | 26 | 27 | class Session; 28 | 29 | struct OverlappedIOContext 30 | { 31 | OverlappedIOContext(Session* owner, IOType ioType); 32 | 33 | OVERLAPPED mOverlapped; 34 | Session* mSessionObject; 35 | IOType mIoType; 36 | WSABUF mWsaBuf; 37 | 38 | }; 39 | 40 | 41 | struct OverlappedSendContext : public OverlappedIOContext, public ObjectPool 42 | { 43 | OverlappedSendContext(Session* owner) : OverlappedIOContext(owner, IO_SEND) 44 | { 45 | } 46 | }; 47 | 48 | struct OverlappedRecvContext : public OverlappedIOContext, public ObjectPool 49 | { 50 | OverlappedRecvContext(Session* owner) : OverlappedIOContext(owner, IO_RECV) 51 | { 52 | } 53 | }; 54 | 55 | struct OverlappedPreRecvContext : public OverlappedIOContext, public ObjectPool 56 | { 57 | OverlappedPreRecvContext(Session* owner) : OverlappedIOContext(owner, IO_RECV_ZERO) 58 | { 59 | } 60 | }; 61 | 62 | struct OverlappedDisconnectContext : public OverlappedIOContext, public ObjectPool 63 | { 64 | OverlappedDisconnectContext(Session* owner, DisconnectReason dr) 65 | : OverlappedIOContext(owner, IO_DISCONNECT), mDisconnectReason(dr) 66 | { 67 | } 68 | 69 | DisconnectReason mDisconnectReason; 70 | }; 71 | 72 | 73 | struct OverlappedConnectContext : public OverlappedIOContext, public ObjectPool 74 | { 75 | OverlappedConnectContext(Session* owner) : OverlappedIOContext(owner, IO_CONNECT) 76 | { 77 | } 78 | }; 79 | 80 | 81 | void DeleteIoContext(OverlappedIOContext* context); 82 | 83 | -------------------------------------------------------------------------------- /DummyClients/DummyClients/PacketHandler.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Log.h" 3 | #include "PacketType.h" 4 | #include "PlayerSession.h" 5 | #include "DummyClients.h" 6 | 7 | //@{ Handler Helper 8 | 9 | typedef void(*HandlerFunc)(PlayerSession* session); 10 | 11 | static HandlerFunc HandlerTable[PKT_MAX]; 12 | 13 | static void DefaultHandler(PlayerSession* session) 14 | { 15 | session->DisconnectRequest(DR_ACTIVE); 16 | } 17 | 18 | struct InitializeHandlers 19 | { 20 | InitializeHandlers() 21 | { 22 | for (int i = 0; i < PKT_MAX; ++i) 23 | HandlerTable[i] = DefaultHandler; 24 | } 25 | } _init_handlers_; 26 | 27 | struct RegisterHandler 28 | { 29 | RegisterHandler(int pktType, HandlerFunc handler) 30 | { 31 | HandlerTable[pktType] = handler; 32 | } 33 | }; 34 | 35 | #define REGISTER_HANDLER(PKT_TYPE) \ 36 | static void Handler_##PKT_TYPE(PlayerSession* session); \ 37 | static RegisterHandler _register_##PKT_TYPE(PKT_TYPE, Handler_##PKT_TYPE); \ 38 | static void Handler_##PKT_TYPE(PlayerSession* session) 39 | 40 | //@} 41 | 42 | void PlayerSession::OnRead(size_t len) 43 | { 44 | /// packet parsing 45 | while (true) 46 | { 47 | /// read a packet header 48 | PacketHeader header; 49 | if (false == mRecvBuffer.Peek((char*)&header, sizeof(PacketHeader))) 50 | return; 51 | 52 | /// packet completed? 53 | if (mRecvBuffer.GetStoredSize() < header.mSize) 54 | return; 55 | 56 | 57 | if (header.mType >= PKT_MAX || header.mType <= PKT_NONE) 58 | { 59 | DisconnectRequest(DR_ACTIVE); 60 | return; 61 | } 62 | 63 | /// packet dispatch... 64 | HandlerTable[header.mType](this); 65 | } 66 | } 67 | 68 | REGISTER_HANDLER(PKT_SC_LOGIN) 69 | { 70 | LoginResult inPacket; 71 | if (false == session->ParsePacket(inPacket)) 72 | { 73 | LoggerUtil::EventLog("packet parsing error: %d\n", inPacket.mType); 74 | return; 75 | } 76 | 77 | GConsoleLog->PrintOut(true, "Login OK: PlayerSessionId - %s\n", inPacket.mPlayerId); 78 | 79 | /// after 100ms, send a request 80 | session->DoAsyncAfter(PLAYER_ACTION_INTERVAL, &PlayerSession::PlayTest); 81 | } 82 | 83 | 84 | 85 | REGISTER_HANDLER(PKT_SC_CHAT) 86 | { 87 | ChatBroadcastResult inPacket; 88 | if (false == session->ParsePacket(inPacket)) 89 | { 90 | LoggerUtil::EventLog("packet parsing error: %d\n", inPacket.mType); 91 | return; 92 | } 93 | 94 | /// just for visualizing :( 95 | //printf_s("."); 96 | } 97 | 98 | 99 | REGISTER_HANDLER(PKT_SC_MOVE) 100 | { 101 | MoveBroadcastResult inPacket; 102 | if (false == session->ParsePacket(inPacket)) 103 | { 104 | LoggerUtil::EventLog("packet parsing error: %d\n", inPacket.mType); 105 | return; 106 | } 107 | 108 | /// just for visualizing :( 109 | //printf_s("M"); 110 | } -------------------------------------------------------------------------------- /DummyClients/DummyClients/PlayerSession.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Session.h" 4 | 5 | class GameSession; 6 | 7 | class PlayerSession : public Session, public ObjectPool 8 | { 9 | public: 10 | PlayerSession(GameSession* owner); 11 | virtual ~PlayerSession(); 12 | 13 | bool PrepareSession(); 14 | 15 | bool ConnectRequest(const std::string& playerSessionId, int idx); 16 | void ConnectCompletion(); 17 | 18 | virtual void OnRead(size_t len); 19 | 20 | virtual void OnDisconnect(DisconnectReason dr); 21 | 22 | template 23 | bool ParsePacket(PKT_TYPE& pkt) 24 | { 25 | return mRecvBuffer.Read((char*)&pkt, pkt.mSize); 26 | } 27 | 28 | 29 | void StartTest(); 30 | void EndTest(); 31 | 32 | void PlayTest(); 33 | 34 | 35 | private: 36 | void SetNextPos(); 37 | 38 | 39 | SOCKADDR_IN mConnectAddr; 40 | 41 | std::string mPlayerSessionId; 42 | GameSession* mOwnerGameSession; 43 | 44 | int mPlayerIdx; 45 | float mPosX; 46 | float mPosY; 47 | 48 | int mCurrDir; ///< 0~7 49 | int mMoveStep; 50 | 51 | int mPlayTestCount; 52 | } ; 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /DummyClients/DummyClients/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ### LICENSE 2 | 3 | The MIT License (MIT) 4 | 5 | Copyright (c) 2016-2017 Seungmo Koo (@teralode) 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy of 8 | this software and associated documentation files (the "Software"), to deal in 9 | the Software without restriction, including without limitation the rights to 10 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 11 | the Software, and to permit persons to whom the Software is furnished to do so, 12 | subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 19 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 20 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | 25 | ### 3rd Party Code License 26 | https://github.com/benhoyt/inih 27 | 28 | The "inih" library is distributed under the New BSD license: 29 | 30 | Copyright (c) 2009, Ben Hoyt 31 | All rights reserved. 32 | 33 | Redistribution and use in source and binary forms, with or without 34 | modification, are permitted provided that the following conditions are met: 35 | * Redistributions of source code must retain the above copyright 36 | notice, this list of conditions and the following disclaimer. 37 | * Redistributions in binary form must reproduce the above copyright 38 | notice, this list of conditions and the following disclaimer in the 39 | documentation and/or other materials provided with the distribution. 40 | * Neither the name of Ben Hoyt nor the names of its contributors 41 | may be used to endorse or promote products derived from this software 42 | without specific prior written permission. 43 | 44 | THIS SOFTWARE IS PROVIDED BY BEN HOYT ''AS IS'' AND ANY 45 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 46 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 47 | DISCLAIMED. IN NO EVENT SHALL BEN HOYT BE LIABLE FOR ANY 48 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 49 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 50 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 51 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 52 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 53 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 54 | 55 | 56 | ### HOW-TO 57 | 58 | 1. open config.ini 59 | 2. edit ALIAS_ID, GAMELIFT_REGION, and MAX_GAME_SESSIONS 60 | 3. run (AWS credential required on your PC: Environment variables or $HOME/.aws folder) 61 | 62 | -------------------------------------------------------------------------------- /DummyClients/DummyClients/Session.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "CircularBuffer.h" 3 | #include "OverlappedIOContext.h" 4 | #include "FastSpinlock.h" 5 | #include "JobDispatcher.h" 6 | 7 | class Session : public AsyncExecutable 8 | { 9 | public: 10 | Session(size_t sendBufSize, size_t recvBufSize); 11 | virtual ~Session() {} 12 | 13 | bool IsConnected() const { return !!mConnected; } 14 | 15 | void DisconnectRequest(DisconnectReason dr) ; 16 | 17 | bool PreRecv(); ///< zero byte recv 18 | bool PostRecv() ; 19 | 20 | bool PostSend(const char* data, size_t len); 21 | bool FlushSend() ; 22 | 23 | void DisconnectCompletion(DisconnectReason dr) ; 24 | void SendCompletion(DWORD transferred) ; 25 | void RecvCompletion(DWORD transferred) ; 26 | 27 | void AddRef(); 28 | void ReleaseRef(); 29 | 30 | virtual void OnRead(size_t len) {} 31 | virtual void OnDisconnect(DisconnectReason dr) {} 32 | virtual void OnRelease() {} 33 | 34 | void SetSocket(SOCKET sock) { mSocket = sock; } 35 | SOCKET GetSocket() const { return mSocket; } 36 | 37 | void EchoBack(); 38 | 39 | protected: 40 | 41 | SOCKET mSocket; 42 | 43 | CircularBuffer mRecvBuffer; 44 | CircularBuffer mSendBuffer; 45 | FastSpinlock mSendBufferLock; 46 | int mSendRequestedCount; 47 | 48 | volatile long mConnected; 49 | 50 | }; 51 | 52 | 53 | -------------------------------------------------------------------------------- /DummyClients/DummyClients/ThreadLocal.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "ThreadLocal.h" 3 | #include "Log.h" 4 | #include "Timer.h" 5 | 6 | __declspec(thread) int LThreadType = -1; 7 | __declspec(thread) int LWorkerThreadId = -1; 8 | __declspec(thread) ThreadCallHistory* LThreadCallHistory = nullptr; 9 | __declspec(thread) void* LRecentThisPointer = nullptr; 10 | 11 | __declspec(thread) Timer* LTimer = nullptr; 12 | __declspec(thread) int64_t LTickCount = 0; 13 | 14 | __declspec(thread) ExecuterListType* LExecuterList = nullptr; 15 | __declspec(thread) AsyncExecutable* LCurrentExecuterOccupyingThisThread = nullptr; 16 | 17 | ThreadCallHistory* GThreadCallHistory[MAX_IOTHREAD] = {0, }; 18 | 19 | -------------------------------------------------------------------------------- /DummyClients/DummyClients/ThreadLocal.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define MAX_IOTHREAD 8 4 | 5 | enum THREAD_TYPE 6 | { 7 | THREAD_MAIN, 8 | THREAD_IO_WORKER 9 | }; 10 | 11 | class Timer; 12 | class AsyncExecutable; 13 | class ThreadCallHistory; 14 | 15 | extern __declspec(thread) int LThreadType; 16 | extern __declspec(thread) int LWorkerThreadId; 17 | extern __declspec(thread) ThreadCallHistory* LThreadCallHistory; 18 | extern __declspec(thread) void* LRecentThisPointer; 19 | extern __declspec(thread) Timer* LTimer; 20 | extern __declspec(thread) int64_t LTickCount; 21 | 22 | typedef std::deque ExecuterListType; 23 | 24 | extern __declspec(thread) ExecuterListType* LExecuterList; 25 | extern __declspec(thread) AsyncExecutable* LCurrentExecuterOccupyingThisThread; 26 | 27 | extern ThreadCallHistory* GThreadCallHistory[MAX_IOTHREAD]; -------------------------------------------------------------------------------- /DummyClients/DummyClients/Timer.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Timer.h" 3 | #include "ThreadLocal.h" 4 | #include "JobDispatcher.h" 5 | 6 | 7 | Timer::Timer() 8 | { 9 | LTickCount = GetTickCount64(); 10 | } 11 | 12 | 13 | void Timer::PushTimerJob(AsyncExecutable* obj, uint32_t after, JobEntry* task) 14 | { 15 | obj->AddRefForThis(); ///< for timer 16 | 17 | int64_t dueTimeTick = after + LTickCount; 18 | 19 | mTimerJobQueue.push(TimerJobElement(obj, task, dueTimeTick)); 20 | } 21 | 22 | 23 | void Timer::DoTimerJob() 24 | { 25 | /// thread tick update 26 | LTickCount = GetTickCount64(); 27 | 28 | while (!mTimerJobQueue.empty()) 29 | { 30 | const TimerJobElement& timerJobElem = mTimerJobQueue.top(); 31 | 32 | if (LTickCount < timerJobElem.mExecutionTick) 33 | break; 34 | 35 | AsyncExecutable* owner = timerJobElem.mOwner; ///< 'cause mOwner can be changed in DoTask.. 36 | owner->DoTask(timerJobElem.mTask); ///< pass to the dispatcher 37 | owner->ReleaseRefForThis(); ///< for timer 38 | 39 | mTimerJobQueue.pop(); 40 | } 41 | } 42 | 43 | -------------------------------------------------------------------------------- /DummyClients/DummyClients/Timer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "Job.h" 5 | 6 | 7 | class AsyncExecutable; 8 | 9 | struct TimerJobElement 10 | { 11 | TimerJobElement(AsyncExecutable* owner, JobEntry* task, int64_t execTick) 12 | : mOwner(owner), mTask(task), mExecutionTick(execTick) 13 | {} 14 | 15 | AsyncExecutable* mOwner; 16 | JobEntry* mTask; 17 | int64_t mExecutionTick; 18 | }; 19 | 20 | struct TimerJobComparator 21 | { 22 | bool operator()(const TimerJobElement& lhs, const TimerJobElement& rhs) 23 | { 24 | return lhs.mExecutionTick > rhs.mExecutionTick; 25 | } 26 | }; 27 | 28 | 29 | typedef std::priority_queue, TimerJobComparator> TimerJobPriorityQueue; 30 | 31 | class Timer 32 | { 33 | public: 34 | 35 | Timer(); 36 | 37 | void PushTimerJob(AsyncExecutable* obj, uint32_t after, JobEntry* task); 38 | 39 | void DoTimerJob(); 40 | 41 | private: 42 | 43 | TimerJobPriorityQueue mTimerJobQueue; 44 | 45 | }; 46 | 47 | 48 | -------------------------------------------------------------------------------- /DummyClients/DummyClients/WorkerThread.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Exception.h" 3 | #include "ThreadLocal.h" 4 | #include "Timer.h" 5 | #include "DummyClients.h" 6 | #include "WorkerThread.h" 7 | #include "PlayerSession.h" 8 | #include "IocpManager.h" 9 | #include "Log.h" 10 | 11 | WorkerThread::WorkerThread(int workerThreadId, HANDLE hThread, HANDLE hCompletionPort) 12 | : mWorkerThreadId(workerThreadId), mThreadHandle(hThread), mCompletionPort(hCompletionPort) 13 | { 14 | } 15 | 16 | 17 | WorkerThread::~WorkerThread() 18 | { 19 | CloseHandle(mThreadHandle); 20 | } 21 | 22 | DWORD WorkerThread::Run() 23 | { 24 | 25 | while (true) 26 | { 27 | if ( false == DoIocpJob() ) 28 | break; 29 | 30 | /// Do Dimer Tasks 31 | LTimer->DoTimerJob(); 32 | 33 | } 34 | 35 | return 1; 36 | } 37 | 38 | bool WorkerThread::DoIocpJob() 39 | { 40 | DWORD dwTransferred = 0; 41 | OverlappedIOContext* context = nullptr; 42 | ULONG_PTR completionKey = 0; 43 | 44 | int ret = GetQueuedCompletionStatus(mCompletionPort, &dwTransferred, (PULONG_PTR)&completionKey, (LPOVERLAPPED*)&context, GQCS_TIMEOUT); 45 | 46 | Session* remote = context ? context->mSessionObject : nullptr; 47 | 48 | if (ret == 0 || dwTransferred == 0) 49 | { 50 | /// stop requested 51 | if (completionKey == CK_STOP_NOW) 52 | return false; 53 | 54 | /// check time out first 55 | if ( context == nullptr && GetLastError() == WAIT_TIMEOUT) 56 | return true; 57 | 58 | if (context->mIoType == IO_RECV || context->mIoType == IO_SEND) 59 | { 60 | CRASH_ASSERT(nullptr != remote); 61 | 62 | /// In most cases in here: ERROR_NETNAME_DELETED(64) 63 | 64 | remote->DisconnectRequest(DR_COMPLETION_ERROR); 65 | 66 | DeleteIoContext(context); 67 | 68 | return true; 69 | } 70 | } 71 | 72 | CRASH_ASSERT(nullptr != remote); 73 | 74 | bool completionOk = false; 75 | switch (context->mIoType) 76 | { 77 | case IO_CONNECT: 78 | dynamic_cast(remote)->ConnectCompletion(); 79 | completionOk = true; 80 | break; 81 | 82 | case IO_DISCONNECT: 83 | remote->DisconnectCompletion(static_cast(context)->mDisconnectReason); 84 | completionOk = true; 85 | break; 86 | 87 | case IO_RECV_ZERO: 88 | completionOk = remote->PostRecv(); 89 | break; 90 | 91 | case IO_SEND: 92 | remote->SendCompletion(dwTransferred); 93 | 94 | if (context->mWsaBuf.len != dwTransferred) 95 | GConsoleLog->PrintOut(true, "Partial SendCompletion requested [%d], sent [%d]\n", context->mWsaBuf.len, dwTransferred); 96 | else 97 | completionOk = true; 98 | 99 | break; 100 | 101 | case IO_RECV: 102 | remote->RecvCompletion(dwTransferred); 103 | 104 | 105 | completionOk = remote->PreRecv(); 106 | 107 | break; 108 | 109 | default: 110 | GConsoleLog->PrintOut(true, "Unknown I/O Type: %d\n", context->mIoType); 111 | CRASH_ASSERT(false); 112 | break; 113 | } 114 | 115 | if (!completionOk) 116 | { 117 | /// connection closing 118 | remote->DisconnectRequest(DR_IO_REQUEST_ERROR); 119 | } 120 | 121 | DeleteIoContext(context); 122 | 123 | return true; 124 | } 125 | 126 | 127 | -------------------------------------------------------------------------------- /DummyClients/DummyClients/WorkerThread.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | class WorkerThread 5 | { 6 | public: 7 | WorkerThread(int workerThreadId, HANDLE hThread, HANDLE hCompletionPort); 8 | ~WorkerThread(); 9 | 10 | DWORD Run(); 11 | 12 | bool DoIocpJob(); ///< false means End 13 | 14 | HANDLE GetHandle() { return mThreadHandle; } 15 | 16 | private: 17 | 18 | HANDLE mThreadHandle; 19 | HANDLE mCompletionPort; 20 | int mWorkerThreadId; 21 | }; 22 | 23 | -------------------------------------------------------------------------------- /DummyClients/DummyClients/config.ini: -------------------------------------------------------------------------------- 1 | [config] 2 | 3 | # Alias ID (when you test with GameLift Local, Set this TEST_LOCAL, and then set a gamelift endpoint at GAMELIFT_REGION) 4 | ALIAS_ID = alias-6e4bfc55-f83c-4373-be59-63d432ff96c 5 | 6 | # GameLift Region (when TEST_LOCAL, for example, 127.0.0.1:9080) 7 | GAMELIFT_REGION = ap-northeast-1 8 | 9 | # how many game sessions(rooms)? 10 | MAX_GAME_SESSIONS = 10 11 | 12 | # each player's request sending interval (ms) 13 | PLAYER_ACTION_INTERVAL = 1000 14 | 15 | # How many times to send a request per PLAYER_ACTION_INTERVAL 16 | PLAYER_ACTION_REQUEST = 300 17 | 18 | # Dummy Player Session Count per a game session (1~8) 19 | DUMMY_PLAYER_SESSION_PER_GAME_SESSION = 8 20 | 21 | 22 | # If you want test GameLift Match Queue Functionality, set MATCH_QUEUE_NAME. (If you specify "NotUse", this feature is disabled.) 23 | MATCH_QUEUE_NAME = GameLiftTestMatchQueue 24 | 25 | # FYI: GameLift Local Mode does not support Match Queue -------------------------------------------------------------------------------- /DummyClients/DummyClients/ini.h: -------------------------------------------------------------------------------- 1 | /* inih -- simple .INI file parser 2 | 3 | inih is released under the New BSD license (see LICENSE.txt). Go to the project 4 | home page for more info: 5 | 6 | https://github.com/benhoyt/inih 7 | 8 | */ 9 | 10 | #ifndef __INI_H__ 11 | #define __INI_H__ 12 | 13 | /* Make this header file easier to include in C++ code */ 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #include 19 | 20 | /* Typedef for prototype of handler function. */ 21 | typedef int (*ini_handler)(void* user, const char* section, 22 | const char* name, const char* value); 23 | 24 | /* Typedef for prototype of fgets-style reader function. */ 25 | typedef char* (*ini_reader)(char* str, int num, void* stream); 26 | 27 | /* Parse given INI-style file. May have [section]s, name=value pairs 28 | (whitespace stripped), and comments starting with ';' (semicolon). Section 29 | is "" if name=value pair parsed before any section heading. name:value 30 | pairs are also supported as a concession to Python's configparser. 31 | 32 | For each name=value pair parsed, call handler function with given user 33 | pointer as well as section, name, and value (data only valid for duration 34 | of handler call). Handler should return nonzero on success, zero on error. 35 | 36 | Returns 0 on success, line number of first error on parse error (doesn't 37 | stop on first error), -1 on file open error, or -2 on memory allocation 38 | error (only when INI_USE_STACK is zero). 39 | */ 40 | int ini_parse(const char* filename, ini_handler handler, void* user); 41 | 42 | /* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't 43 | close the file when it's finished -- the caller must do that. */ 44 | int ini_parse_file(FILE* file, ini_handler handler, void* user); 45 | 46 | /* Same as ini_parse(), but takes an ini_reader function pointer instead of 47 | filename. Used for implementing custom or string-based I/O. */ 48 | int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, 49 | void* user); 50 | 51 | /* Nonzero to allow multi-line value parsing, in the style of Python's 52 | configparser. If allowed, ini_parse() will call the handler with the same 53 | name for each subsequent line parsed. */ 54 | #ifndef INI_ALLOW_MULTILINE 55 | #define INI_ALLOW_MULTILINE 1 56 | #endif 57 | 58 | /* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of 59 | the file. See http://code.google.com/p/inih/issues/detail?id=21 */ 60 | #ifndef INI_ALLOW_BOM 61 | #define INI_ALLOW_BOM 1 62 | #endif 63 | 64 | /* Nonzero to allow inline comments (with valid inline comment characters 65 | specified by INI_INLINE_COMMENT_PREFIXES). Set to 0 to turn off and match 66 | Python 3.2+ configparser behaviour. */ 67 | #ifndef INI_ALLOW_INLINE_COMMENTS 68 | #define INI_ALLOW_INLINE_COMMENTS 1 69 | #endif 70 | #ifndef INI_INLINE_COMMENT_PREFIXES 71 | #define INI_INLINE_COMMENT_PREFIXES ";" 72 | #endif 73 | 74 | /* Nonzero to use stack, zero to use heap (malloc/free). */ 75 | #ifndef INI_USE_STACK 76 | #define INI_USE_STACK 1 77 | #endif 78 | 79 | /* Stop parsing on first error (default is to keep parsing). */ 80 | #ifndef INI_STOP_ON_FIRST_ERROR 81 | #define INI_STOP_ON_FIRST_ERROR 0 82 | #endif 83 | 84 | /* Maximum line length for any line in INI file. */ 85 | #ifndef INI_MAX_LINE 86 | #define INI_MAX_LINE 200 87 | #endif 88 | 89 | #ifdef __cplusplus 90 | } 91 | #endif 92 | 93 | #endif /* __INI_H__ */ 94 | -------------------------------------------------------------------------------- /DummyClients/DummyClients/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /DummyClients/DummyClients/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // DummyClients.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /DummyClients/DummyClients/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #define NOMINMAX 9 | 10 | #include "targetver.h" 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | 33 | // TODO: reference additional headers your program requires here 34 | -------------------------------------------------------------------------------- /DummyClients/DummyClients/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.40629.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GameLiftGameServer", "GameLiftGameServer\GameLiftGameServer.vcxproj", "{56131AE4-9210-499E-A61C-D832AE59004F}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Debug|x64 = Debug|x64 12 | Release|Win32 = Release|Win32 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {56131AE4-9210-499E-A61C-D832AE59004F}.Debug|Win32.ActiveCfg = Debug|Win32 17 | {56131AE4-9210-499E-A61C-D832AE59004F}.Debug|Win32.Build.0 = Debug|Win32 18 | {56131AE4-9210-499E-A61C-D832AE59004F}.Debug|x64.ActiveCfg = Debug|x64 19 | {56131AE4-9210-499E-A61C-D832AE59004F}.Debug|x64.Build.0 = Debug|x64 20 | {56131AE4-9210-499E-A61C-D832AE59004F}.Release|Win32.ActiveCfg = Release|Win32 21 | {56131AE4-9210-499E-A61C-D832AE59004F}.Release|Win32.Build.0 = Release|Win32 22 | {56131AE4-9210-499E-A61C-D832AE59004F}.Release|x64.ActiveCfg = Release|x64 23 | {56131AE4-9210-499E-A61C-D832AE59004F}.Release|x64.Build.0 = Release|x64 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/CircularBuffer.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeliard/GameLift/4bdb482097cac9e362701732bff74e4398a1c174/GameLiftGameServer/GameLiftGameServer/CircularBuffer.cpp -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/CircularBuffer.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeliard/GameLift/4bdb482097cac9e362701732bff74e4398a1c174/GameLiftGameServer/GameLiftGameServer/CircularBuffer.h -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/Exception.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "ThreadLocal.h" 3 | #include "Exception.h" 4 | #include "Log.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define MAX_BUFF_SIZE 1024 11 | 12 | void MakeDump(EXCEPTION_POINTERS* e) 13 | { 14 | TCHAR tszFileName[MAX_BUFF_SIZE] = { 0 }; 15 | SYSTEMTIME stTime = { 0 }; 16 | GetSystemTime(&stTime); 17 | StringCbPrintf(tszFileName, 18 | _countof(tszFileName), 19 | _T("logs\\%s_%4d%02d%02d_%02d%02d%02d.dmp"), 20 | _T("GameLiftGameServer"), 21 | stTime.wYear, 22 | stTime.wMonth, 23 | stTime.wDay, 24 | stTime.wHour, 25 | stTime.wMinute, 26 | stTime.wSecond); 27 | 28 | HANDLE hFile = CreateFile(tszFileName, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); 29 | if (hFile == INVALID_HANDLE_VALUE) 30 | return; 31 | 32 | MINIDUMP_EXCEPTION_INFORMATION exceptionInfo; 33 | exceptionInfo.ThreadId = GetCurrentThreadId(); 34 | exceptionInfo.ExceptionPointers = e; 35 | exceptionInfo.ClientPointers = FALSE; 36 | 37 | MiniDumpWriteDump( 38 | GetCurrentProcess(), 39 | GetCurrentProcessId(), 40 | hFile, 41 | MINIDUMP_TYPE(MiniDumpWithIndirectlyReferencedMemory | MiniDumpScanMemory | MiniDumpWithFullMemory), 42 | e ? &exceptionInfo : NULL, 43 | NULL, 44 | NULL); 45 | 46 | if (hFile) 47 | { 48 | CloseHandle(hFile); 49 | hFile = NULL; 50 | } 51 | 52 | } 53 | 54 | 55 | LONG WINAPI ExceptionFilter(EXCEPTION_POINTERS* exceptionInfo) 56 | { 57 | if ( IsDebuggerPresent() ) 58 | return EXCEPTION_CONTINUE_SEARCH ; 59 | 60 | 61 | THREADENTRY32 te32; 62 | DWORD myThreadId = GetCurrentThreadId(); 63 | DWORD myProcessId = GetCurrentProcessId(); 64 | 65 | HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); 66 | if (hThreadSnap != INVALID_HANDLE_VALUE) 67 | { 68 | te32.dwSize = sizeof(THREADENTRY32); 69 | 70 | if (Thread32First(hThreadSnap, &te32)) 71 | { 72 | do 73 | { 74 | /// except myself 75 | if (te32.th32OwnerProcessID == myProcessId && te32.th32ThreadID != myThreadId) 76 | { 77 | HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, te32.th32ThreadID); 78 | if (hThread) 79 | { 80 | SuspendThread(hThread); 81 | } 82 | } 83 | 84 | } while (Thread32Next(hThreadSnap, &te32)); 85 | 86 | } 87 | 88 | CloseHandle(hThreadSnap); 89 | } 90 | 91 | 92 | std::ofstream historyOut("logs\\exception_eventlog.txt", std::ofstream::out); 93 | 94 | LoggerUtil::EventLogDumpOut(historyOut); 95 | 96 | historyOut.flush(); 97 | historyOut.close(); 98 | 99 | /// dump file 100 | MakeDump(exceptionInfo); 101 | 102 | ExitProcess(1); 103 | 104 | /// the end here 105 | 106 | return EXCEPTION_EXECUTE_HANDLER; 107 | 108 | } -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/Exception.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | LONG WINAPI ExceptionFilter(EXCEPTION_POINTERS* exceptionInfo) ; 4 | 5 | inline void CRASH_ASSERT(bool isOk) 6 | { 7 | if ( isOk ) 8 | return ; 9 | 10 | int* crashVal = 0 ; 11 | *crashVal = 0xDEADBEEF ; 12 | } 13 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/FastSpinlock.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "FastSpinlock.h" 3 | #include "ThreadLocal.h" 4 | 5 | FastSpinlock::FastSpinlock() : mLockFlag(0) 6 | { 7 | } 8 | 9 | 10 | FastSpinlock::~FastSpinlock() 11 | { 12 | } 13 | 14 | 15 | void FastSpinlock::EnterWriteLock() 16 | { 17 | while (true) 18 | { 19 | /// wait a writelock 20 | while (mLockFlag & LF_WRITE_MASK) 21 | YieldProcessor(); 22 | 23 | if ((InterlockedAdd(&mLockFlag, LF_WRITE_FLAG) & LF_WRITE_MASK) == LF_WRITE_FLAG) 24 | { 25 | /// wait a readlock 26 | while (mLockFlag & LF_READ_MASK) 27 | YieldProcessor(); 28 | 29 | return; 30 | } 31 | 32 | InterlockedAdd(&mLockFlag, -LF_WRITE_FLAG); 33 | } 34 | 35 | } 36 | 37 | void FastSpinlock::LeaveWriteLock() 38 | { 39 | InterlockedAdd(&mLockFlag, -LF_WRITE_FLAG); 40 | } 41 | 42 | void FastSpinlock::EnterReadLock() 43 | { 44 | while (true) 45 | { 46 | /// wait a writelock 47 | while (mLockFlag & LF_WRITE_MASK) 48 | YieldProcessor(); 49 | 50 | if ((InterlockedIncrement(&mLockFlag) & LF_WRITE_MASK) == 0) 51 | return; 52 | 53 | InterlockedDecrement(&mLockFlag); 54 | } 55 | } 56 | 57 | void FastSpinlock::LeaveReadLock() 58 | { 59 | InterlockedDecrement(&mLockFlag); 60 | } -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/FastSpinlock.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | class FastSpinlock 5 | { 6 | public: 7 | FastSpinlock(); 8 | ~FastSpinlock(); 9 | 10 | /// exclusive mode 11 | void EnterWriteLock(); 12 | void LeaveWriteLock(); 13 | 14 | /// shared mode 15 | void EnterReadLock(); 16 | void LeaveReadLock(); 17 | 18 | long GetLockFlag() const { return mLockFlag; } 19 | 20 | private: 21 | 22 | enum LockFlag 23 | { 24 | LF_WRITE_MASK = 0x7FF00000, 25 | LF_WRITE_FLAG = 0x00100000, 26 | LF_READ_MASK = 0x000FFFFF 27 | }; 28 | 29 | FastSpinlock(const FastSpinlock& rhs); 30 | FastSpinlock& operator=(const FastSpinlock& rhs); 31 | 32 | volatile long mLockFlag; 33 | 34 | }; 35 | 36 | class FastSpinlockGuard 37 | { 38 | public: 39 | FastSpinlockGuard(FastSpinlock& lock, bool exclusive = true) : mLock(lock), mExclusiveMode(exclusive) 40 | { 41 | if (mExclusiveMode) 42 | mLock.EnterWriteLock(); 43 | else 44 | mLock.EnterReadLock(); 45 | } 46 | 47 | ~FastSpinlockGuard() 48 | { 49 | if (mExclusiveMode) 50 | mLock.LeaveWriteLock(); 51 | else 52 | mLock.LeaveReadLock(); 53 | } 54 | 55 | private: 56 | FastSpinlock& mLock; 57 | bool mExclusiveMode; 58 | }; 59 | 60 | template 61 | class ClassTypeLock 62 | { 63 | public: 64 | struct LockGuard 65 | { 66 | LockGuard() 67 | { 68 | TargetClass::mLock.EnterWriteLock(); 69 | } 70 | 71 | ~LockGuard() 72 | { 73 | TargetClass::mLock.LeaveWriteLock(); 74 | } 75 | 76 | }; 77 | 78 | private: 79 | static FastSpinlock mLock; 80 | 81 | //friend struct LockGuard; 82 | }; 83 | 84 | template 85 | FastSpinlock ClassTypeLock::mLock; -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/GameLiftGameServer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2016 Seungmo Koo (@teralode) 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of 7 | this software and associated documentation files (the "Software"), to deal in 8 | the Software without restriction, including without limitation the rights to 9 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 10 | the Software, and to permit persons to whom the Software is furnished to do so, 11 | subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | */ 24 | 25 | 26 | #include "stdafx.h" 27 | #include "Exception.h" 28 | #include "Log.h" 29 | #include "Session.h" 30 | #include "IocpManager.h" 31 | #include "GameLiftManager.h" 32 | 33 | 34 | int main(int argc, char* argv[]) 35 | { 36 | int portNum = 0; 37 | /// listen port override rather than dynamic port by OS 38 | if (argc < 2) 39 | printf_s("Specify Listen Port Number. Or, it will be used dynamic port by OS\n"); 40 | else 41 | portNum = atoi(argv[1]); 42 | 43 | 44 | LThreadType = THREAD_MAIN; 45 | 46 | /// for dump on crash 47 | SetUnhandledExceptionFilter(ExceptionFilter); 48 | 49 | GConsoleLog.reset(new ConsoleLog(".\\logs\\serverLog.txt")); 50 | 51 | /// GameLift 52 | GGameLiftManager.reset(new GameLiftManager); 53 | 54 | /// Global Managers 55 | GIocpManager.reset(new IocpManager); 56 | 57 | if (false == GIocpManager->Initialize(portNum)) 58 | return -1; 59 | 60 | /// Gamelift init/start! 61 | if (false == GGameLiftManager->InitializeGameLift(portNum)) 62 | return -1; 63 | 64 | if (false == GIocpManager->StartIoThreads()) 65 | return -1; 66 | 67 | GConsoleLog->PrintOut(true, "Start Server\n"); 68 | 69 | GIocpManager->StartAccept(); ///< block here... 70 | 71 | GIocpManager->Finalize(); 72 | 73 | /// Gamelift end! 74 | GGameLiftManager->FinalizeGameLift(); 75 | 76 | GConsoleLog->PrintOut(true, "End Server\n"); 77 | 78 | return 0; 79 | } 80 | 81 | 82 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/GameLiftGameServer.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {34196119-8128-4384-b286-01942e1c13f8} 14 | 15 | 16 | {ec034f17-2a39-45d2-8cc2-041dc54fea05} 17 | 18 | 19 | 20 | 21 | Main 22 | 23 | 24 | Main 25 | 26 | 27 | Utils 28 | 29 | 30 | Utils 31 | 32 | 33 | Utils 34 | 35 | 36 | Utils 37 | 38 | 39 | Utils 40 | 41 | 42 | Utils 43 | 44 | 45 | Utils 46 | 47 | 48 | Utils 49 | 50 | 51 | PacketHandling 52 | 53 | 54 | Main 55 | 56 | 57 | Main 58 | 59 | 60 | Utils 61 | 62 | 63 | GameLift 64 | 65 | 66 | GameLift 67 | 68 | 69 | GameLift 70 | 71 | 72 | 73 | 74 | Main 75 | 76 | 77 | Main 78 | 79 | 80 | Utils 81 | 82 | 83 | Utils 84 | 85 | 86 | Utils 87 | 88 | 89 | Utils 90 | 91 | 92 | Utils 93 | 94 | 95 | Utils 96 | 97 | 98 | Utils 99 | 100 | 101 | Main 102 | 103 | 104 | Main 105 | 106 | 107 | Utils 108 | 109 | 110 | PacketHandling 111 | 112 | 113 | GameLift 114 | 115 | 116 | GameLift 117 | 118 | 119 | GameLift 120 | 121 | 122 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/GameLiftManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "FastSpinLock.h" 5 | 6 | struct PacketHeader; 7 | class GameSession; 8 | class PlayerSession; 9 | 10 | class GameLiftManager 11 | { 12 | public: 13 | GameLiftManager(); 14 | 15 | bool InitializeGameLift(int listenPort); 16 | void FinalizeGameLift(); 17 | 18 | bool AcceptPlayerSession(std::shared_ptr psess, const std::string& playerSessionId); 19 | void RemovePlayerSession(std::shared_ptr psess, const std::string& playerSessionId); 20 | 21 | void OnStartGameSession(Aws::GameLift::Server::Model::GameSession myGameSession); 22 | 23 | void OnProcessTerminate(); 24 | 25 | bool OnHealthCheck() { return mActivated; } 26 | 27 | void BroadcastMessage(PacketHeader* pkt); ///< proxy for a game session 28 | 29 | private: 30 | void CheckTerminateGameSession(); 31 | void TerminateGameSession(int exitCode); 32 | 33 | private: 34 | FastSpinlock mLock; 35 | 36 | bool mActivated; 37 | int mAcceptedCount; ///< player accepted count after game-session started 38 | int mRemovedCount; ///< player removed count 39 | 40 | std::shared_ptr mGameSession; ///< 1:1 relationship, currently 41 | }; 42 | 43 | extern std::unique_ptr GGameLiftManager; -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/GameSession.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "PacketType.h" 3 | #include "PlayerSession.h" 4 | #include "GameSession.h" 5 | 6 | void GameSession::PlayerEnter(std::shared_ptr psess) 7 | { 8 | mPlayerSessions.insert(psess); 9 | } 10 | 11 | void GameSession::PlayerLeave(std::shared_ptr psess) 12 | { 13 | mPlayerSessions.erase(psess); 14 | } 15 | 16 | void GameSession::BroadcastMessage(PacketHeader* pkt) 17 | { 18 | for (auto& it : mPlayerSessions) 19 | { 20 | if (false == it->PostSend((const char*)pkt, pkt->mSize)) 21 | { 22 | it->Disconnect(DR_SENDBUFFER_ERROR); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/GameSession.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "FastSpinlock.h" 3 | 4 | class PlayerSession; 5 | struct PacketHeader; 6 | class GameLiftManager; 7 | 8 | class GameSession 9 | { 10 | private: 11 | void PlayerEnter(std::shared_ptr psess); 12 | void PlayerLeave(std::shared_ptr psess); 13 | 14 | void BroadcastMessage(PacketHeader* pkt); 15 | 16 | std::set> mPlayerSessions; 17 | 18 | friend class GameLiftManager; 19 | }; -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/IOThread.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Exception.h" 3 | #include "Log.h" 4 | #include "ThreadLocal.h" 5 | #include "Timer.h" 6 | 7 | #include "IOThread.h" 8 | #include "Session.h" 9 | 10 | #include "IocpManager.h" 11 | 12 | #define GQCS_TIMEOUT 20 13 | 14 | IOThread::IOThread(HANDLE hThread, HANDLE hCompletionPort) : mThreadHandle(hThread), mCompletionPort(hCompletionPort) 15 | { 16 | } 17 | 18 | 19 | IOThread::~IOThread() 20 | { 21 | CloseHandle(mThreadHandle); 22 | } 23 | 24 | DWORD IOThread::Run() 25 | { 26 | 27 | while (true) 28 | { 29 | DoIocpJob(); 30 | 31 | DoTimerJob(); 32 | 33 | //... ... 34 | } 35 | 36 | return 1; 37 | } 38 | 39 | void IOThread::DoIocpJob() 40 | { 41 | DWORD dwTransferred = 0; 42 | LPOVERLAPPED overlapped = nullptr; 43 | 44 | ULONG_PTR completionKey = 0; 45 | 46 | int ret = GetQueuedCompletionStatus(mCompletionPort, &dwTransferred, (PULONG_PTR)&completionKey, &overlapped, GQCS_TIMEOUT); 47 | 48 | /// general I/O processing 49 | 50 | OverlappedIOContext* context = reinterpret_cast(overlapped); 51 | 52 | SessionPtr remote = context ? context->mSessionObject : nullptr; 53 | 54 | if (ret == 0 || dwTransferred == 0) 55 | { 56 | /// check time out first 57 | if ( context == nullptr && GetLastError() == WAIT_TIMEOUT) 58 | return; 59 | 60 | 61 | if (context->mIoType == IO_RECV || context->mIoType == IO_SEND) 62 | { 63 | CRASH_ASSERT(nullptr != remote); 64 | 65 | /// In most cases in here: ERROR_NETNAME_DELETED(64) 66 | 67 | remote->Disconnect(DR_COMPLETION_ERROR); 68 | 69 | DeleteIoContext(context); 70 | 71 | return; 72 | } 73 | } 74 | 75 | CRASH_ASSERT(nullptr != remote); 76 | 77 | bool completionOk = false; 78 | switch (context->mIoType) 79 | { 80 | case IO_RECV_ZERO: 81 | completionOk = remote->PostRecv(); 82 | break; 83 | 84 | case IO_SEND: 85 | remote->SendCompletion(dwTransferred); 86 | 87 | if (context->mWsaBuf.len != dwTransferred) 88 | GConsoleLog->PrintOut(true, "Partial SendCompletion requested [%d], sent [%d]\n", context->mWsaBuf.len, dwTransferred); 89 | else 90 | completionOk = true; 91 | 92 | break; 93 | 94 | case IO_RECV: 95 | remote->RecvCompletion(dwTransferred); 96 | 97 | completionOk = remote->PreRecv(); 98 | 99 | break; 100 | 101 | default: 102 | GConsoleLog->PrintOut(true, "Unknown I/O Type: %d\n", context->mIoType); 103 | CRASH_ASSERT(false); 104 | break; 105 | } 106 | 107 | if (!completionOk) 108 | { 109 | /// connection closing 110 | remote->Disconnect(DR_IO_REQUEST_ERROR); 111 | } 112 | 113 | DeleteIoContext(context); 114 | 115 | } 116 | 117 | 118 | void IOThread::DoTimerJob() 119 | { 120 | LTimer->DoTimerJob(); 121 | } -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/IOThread.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | class IOThread 5 | { 6 | public: 7 | IOThread(HANDLE hThread, HANDLE hCompletionPort); 8 | ~IOThread(); 9 | 10 | DWORD Run(); 11 | 12 | void DoIocpJob(); 13 | void DoTimerJob(); 14 | 15 | HANDLE GetHandle() { return mThreadHandle; } 16 | 17 | private: 18 | 19 | HANDLE mThreadHandle; 20 | HANDLE mCompletionPort; 21 | }; 22 | 23 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/IocpManager.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Exception.h" 3 | #include "ThreadLocal.h" 4 | #include "Timer.h" 5 | #include "Log.h" 6 | #include "IocpManager.h" 7 | #include "IOThread.h" 8 | #include "PlayerSession.h" 9 | 10 | 11 | std::unique_ptr GIocpManager(nullptr); 12 | 13 | 14 | IocpManager::IocpManager() : mCompletionPort(NULL), mListenSocket(NULL) 15 | { 16 | memset(mIoWorkerThread, 0, sizeof(mIoWorkerThread)); 17 | } 18 | 19 | 20 | IocpManager::~IocpManager() 21 | { 22 | } 23 | 24 | bool IocpManager::Initialize(int& listenPort) 25 | { 26 | /// winsock initializing 27 | WSADATA wsa; 28 | if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) 29 | return false; 30 | 31 | /// Create I/O Completion Port 32 | mCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); 33 | if (mCompletionPort == NULL) 34 | return false; 35 | 36 | /// create TCP socket 37 | mListenSocket = socket(AF_INET, SOCK_STREAM, 0); 38 | if (mListenSocket == INVALID_SOCKET) 39 | return false; 40 | 41 | int opt = 1; 42 | setsockopt(mListenSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt, sizeof(int)); 43 | 44 | /// bind 45 | SOCKADDR_IN serveraddr; 46 | ZeroMemory(&serveraddr, sizeof(serveraddr)); 47 | serveraddr.sin_family = AF_INET; 48 | serveraddr.sin_port = htons(listenPort); 49 | serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); 50 | 51 | if (SOCKET_ERROR == bind(mListenSocket, (SOCKADDR*)&serveraddr, sizeof(serveraddr))) 52 | return false; 53 | 54 | ZeroMemory(&serveraddr, sizeof(serveraddr)); 55 | int len = sizeof(serveraddr); 56 | if (SOCKET_ERROR == getsockname(mListenSocket, (SOCKADDR*)&serveraddr, &len)) 57 | return false; 58 | 59 | listenPort = ntohs(serveraddr.sin_port); 60 | return true; 61 | } 62 | 63 | 64 | bool IocpManager::StartIoThreads() 65 | { 66 | /// create I/O Thread 67 | for (int i = 0; i < MAX_WORKER_THREAD; ++i) 68 | { 69 | DWORD dwThreadId; 70 | HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, IoWorkerThread, reinterpret_cast(i), CREATE_SUSPENDED, (unsigned int*)&dwThreadId); 71 | if (hThread == NULL) 72 | return false; 73 | 74 | mIoWorkerThread[i] = new IOThread(hThread, mCompletionPort); 75 | } 76 | 77 | /// start! 78 | for (int i = 0; i < MAX_WORKER_THREAD; ++i) 79 | { 80 | ResumeThread(mIoWorkerThread[i]->GetHandle()); 81 | } 82 | 83 | return true; 84 | } 85 | 86 | 87 | void IocpManager::StartAccept() 88 | { 89 | CRASH_ASSERT(LThreadType == THREAD_MAIN); 90 | 91 | /// listen 92 | if (SOCKET_ERROR == listen(mListenSocket, SOMAXCONN)) 93 | { 94 | GConsoleLog->PrintOut(true, "[DEBUG] listen error\n"); 95 | return; 96 | } 97 | 98 | /// accept loop 99 | while (true) 100 | { 101 | SOCKET acceptedSock = accept(mListenSocket, NULL, NULL); 102 | if (acceptedSock == INVALID_SOCKET) 103 | { 104 | GConsoleLog->PrintOut(true, "accept: invalid socket\n"); 105 | continue; 106 | } 107 | 108 | /// accepting a new player session 109 | auto newSession = std::make_shared(acceptedSock); 110 | 111 | /// connection establishing and then issuing recv 112 | if (false == newSession->OnConnect()) 113 | { 114 | newSession->Disconnect(DR_ONCONNECT_ERROR); 115 | } 116 | } 117 | 118 | 119 | } 120 | 121 | 122 | void IocpManager::Finalize() 123 | { 124 | for (int i = 0; i < MAX_WORKER_THREAD; ++i) 125 | { 126 | CloseHandle(mIoWorkerThread[i]->GetHandle()); 127 | } 128 | 129 | CloseHandle(mCompletionPort); 130 | 131 | /// winsock finalizing 132 | WSACleanup(); 133 | 134 | } 135 | 136 | unsigned int WINAPI IocpManager::IoWorkerThread(LPVOID lpParam) 137 | { 138 | LThreadType = THREAD_IO_WORKER; 139 | LWorkerThreadId = reinterpret_cast(lpParam); 140 | LTimer = new Timer; 141 | 142 | return GIocpManager->mIoWorkerThread[LWorkerThreadId]->Run(); 143 | } 144 | 145 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/IocpManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "ThreadLocal.h" 3 | 4 | 5 | class Session; 6 | class IOThread; 7 | 8 | struct OverlappedSendContext; 9 | struct OverlappedPreRecvContext; 10 | struct OverlappedRecvContext; 11 | 12 | 13 | class IocpManager 14 | { 15 | public: 16 | IocpManager(); 17 | ~IocpManager(); 18 | 19 | bool Initialize(int& listenPort); 20 | void Finalize(); 21 | 22 | bool StartIoThreads(); 23 | void StartAccept(); 24 | 25 | 26 | HANDLE GetComletionPort() { return mCompletionPort; } 27 | 28 | SOCKET* GetListenSocket() { return &mListenSocket; } 29 | 30 | private: 31 | 32 | static unsigned int WINAPI IoWorkerThread(LPVOID lpParam); 33 | 34 | private: 35 | 36 | HANDLE mCompletionPort; 37 | SOCKET mListenSocket; 38 | 39 | IOThread* mIoWorkerThread[MAX_WORKER_THREAD]; 40 | 41 | }; 42 | 43 | extern std::unique_ptr GIocpManager; 44 | 45 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/Log.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Log.h" 3 | 4 | #include 5 | 6 | 7 | ConsoleLog::ConsoleLog(const char* filename) 8 | { 9 | mLogFileStream.open(filename, std::ofstream::out); 10 | } 11 | 12 | ConsoleLog::~ConsoleLog() 13 | { 14 | mLogFileStream.close(); 15 | } 16 | 17 | void ConsoleLog::PrintOut(bool fileOut, const char* fmt, ...) 18 | { 19 | FastSpinlockGuard lock(mLock); 20 | 21 | char buf[128] = {}; 22 | 23 | va_list args; 24 | va_start(args, fmt); 25 | vsprintf_s(buf, fmt, args); 26 | va_end(args); 27 | 28 | printf_s("%s", buf); 29 | 30 | if (fileOut) 31 | { 32 | mLogFileStream << buf; 33 | mLogFileStream.flush(); 34 | } 35 | } 36 | 37 | std::unique_ptr GConsoleLog(nullptr); 38 | 39 | 40 | 41 | namespace LoggerUtil 42 | { 43 | LogEvent gLogEvents[MAX_LOG_SIZE]; 44 | __int64 gCurrentLogIndex = 0; 45 | 46 | void EventLogDumpOut(std::ostream& ost) 47 | { 48 | __int64 count = gCurrentLogIndex < MAX_LOG_SIZE ? gCurrentLogIndex : MAX_LOG_SIZE; 49 | 50 | ost << "===== Recent Sequential Event Log =====" << std::endl; 51 | 52 | for (int i = 1; i <= count ; ++i) 53 | { 54 | const LogEvent& log = gLogEvents[(gCurrentLogIndex - i) % MAX_LOG_SIZE]; 55 | ost << "TID[" << log.mThreadId << "] MSG[ " << log.mMessage << " ] INFO [" << log.mAdditionalInfo << "]" << std::endl; 56 | } 57 | 58 | ost << "===== End of Event Log =====" << std::endl; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/Log.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "Exception.h" 5 | #include "ThreadLocal.h" 6 | #include "FastSpinlock.h" 7 | 8 | class ConsoleLog 9 | { 10 | public: 11 | ConsoleLog(const char* filename); 12 | ~ConsoleLog(); 13 | 14 | void PrintOut(bool fileOut, const char* fmt, ...); 15 | 16 | private: 17 | FastSpinlock mLock; 18 | std::ofstream mLogFileStream; 19 | }; 20 | 21 | extern std::unique_ptr GConsoleLog; 22 | 23 | namespace LoggerUtil 24 | { 25 | 26 | struct LogEvent 27 | { 28 | int mThreadId = -1; 29 | int mAdditionalInfo = 0; 30 | const char* mMessage = nullptr; 31 | }; 32 | 33 | #define MAX_LOG_SIZE 65536 ///< Must be a power of 2 34 | 35 | extern LogEvent gLogEvents[MAX_LOG_SIZE]; 36 | extern __int64 gCurrentLogIndex; 37 | 38 | inline void EventLog(const char* msg, int info) 39 | { 40 | __int64 index = _InterlockedIncrement64(&gCurrentLogIndex) - 1; 41 | LogEvent& event = gLogEvents[index & (MAX_LOG_SIZE - 1)]; 42 | event.mThreadId = LWorkerThreadId; 43 | event.mMessage = msg; 44 | event.mAdditionalInfo = info; 45 | } 46 | 47 | void EventLogDumpOut(std::ostream& ost = std::cout); 48 | 49 | } 50 | 51 | #define EVENT_LOG(x, info) LoggerUtil::EventLog(x, info) 52 | 53 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/ObjectPool.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | template 4 | class ObjectPool 5 | { 6 | public: 7 | 8 | enum 9 | { 10 | POOL_MAX_SIZE = 1024, ///< must be power of 2 11 | POOL_SIZE_MASK = POOL_MAX_SIZE - 1 12 | }; 13 | 14 | /// memory pre- allocation is just optional :) 15 | static void PrepareAllocation() 16 | { 17 | for (int i = 0; i < POOL_MAX_SIZE; ++i) 18 | mPool[i] = _aligned_malloc(sizeof(T), MEMORY_ALLOCATION_ALIGNMENT); 19 | 20 | InterlockedAdd64(&mTailPos, POOL_MAX_SIZE); 21 | } 22 | 23 | static void* operator new(size_t objSize) 24 | { 25 | LONGLONG popPos = InterlockedIncrement64(&mHeadPos) - 1; 26 | 27 | void* popVal = InterlockedExchangePointer(&mPool[popPos & POOL_SIZE_MASK], nullptr); 28 | if (popVal != nullptr) 29 | return popVal; 30 | 31 | return _aligned_malloc(objSize, MEMORY_ALLOCATION_ALIGNMENT);; 32 | } 33 | 34 | static void operator delete(void* obj) 35 | { 36 | LONGLONG insPos = InterlockedIncrement64(&mTailPos) - 1; 37 | 38 | void* prevVal = InterlockedExchangePointer(&mPool[insPos & POOL_SIZE_MASK], obj); 39 | if (prevVal != nullptr) 40 | _aligned_free(prevVal); 41 | } 42 | 43 | 44 | private: 45 | 46 | static PVOID volatile mPool[POOL_MAX_SIZE]; 47 | static LONGLONG volatile mHeadPos; 48 | static LONGLONG volatile mTailPos; 49 | 50 | void* __powerof2check__[((POOL_MAX_SIZE & POOL_SIZE_MASK) == 0x0) & 0x1]; 51 | }; 52 | 53 | template 54 | PVOID volatile ObjectPool::mPool[POOL_MAX_SIZE] = {}; 55 | 56 | template 57 | LONGLONG volatile ObjectPool::mHeadPos(0); 58 | 59 | template 60 | LONGLONG volatile ObjectPool::mTailPos(0); 61 | 62 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/OverlappedIOContext.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Exception.h" 3 | #include "OverlappedIOContext.h" 4 | #include "Session.h" 5 | 6 | OverlappedIOContext::OverlappedIOContext(SessionPtr owner, IOType ioType) 7 | : mSessionObject(owner), mIoType(ioType) 8 | { 9 | memset(&mOverlapped, 0, sizeof(OVERLAPPED)); 10 | memset(&mWsaBuf, 0, sizeof(WSABUF)); 11 | } 12 | 13 | 14 | 15 | void DeleteIoContext(OverlappedIOContext* context) 16 | { 17 | if (nullptr == context) 18 | return; 19 | 20 | /// ObjectPool's operate delete dispatch 21 | switch (context->mIoType) 22 | { 23 | case IO_SEND: 24 | delete static_cast(context); 25 | break; 26 | 27 | case IO_RECV_ZERO: 28 | delete static_cast(context); 29 | break; 30 | 31 | case IO_RECV: 32 | delete static_cast(context); 33 | break; 34 | 35 | default: 36 | CRASH_ASSERT(false); 37 | } 38 | 39 | 40 | } 41 | 42 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/OverlappedIOContext.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ObjectPool.h" 4 | 5 | enum IOType 6 | { 7 | IO_NONE, 8 | IO_SEND, 9 | IO_RECV, 10 | IO_RECV_ZERO 11 | }; 12 | 13 | enum DisconnectReason 14 | { 15 | DR_NONE, 16 | DR_ACTIVE, 17 | DR_ONCONNECT_ERROR, 18 | DR_IO_REQUEST_ERROR, 19 | DR_COMPLETION_ERROR, 20 | DR_SENDFLUSH_ERROR, 21 | DR_SENDBUFFER_ERROR, 22 | DR_UNAUTH, 23 | DR_LOGOUT 24 | }; 25 | 26 | 27 | 28 | class Session; 29 | typedef std::shared_ptr SessionPtr; 30 | 31 | struct OverlappedIOContext 32 | { 33 | OverlappedIOContext(SessionPtr owner, IOType ioType); 34 | 35 | OVERLAPPED mOverlapped; 36 | SessionPtr mSessionObject; 37 | IOType mIoType; 38 | WSABUF mWsaBuf; 39 | 40 | }; 41 | 42 | 43 | struct OverlappedSendContext : public OverlappedIOContext, public ObjectPool 44 | { 45 | OverlappedSendContext(SessionPtr owner) : OverlappedIOContext(owner, IO_SEND) 46 | { 47 | } 48 | }; 49 | 50 | struct OverlappedRecvContext : public OverlappedIOContext, public ObjectPool 51 | { 52 | OverlappedRecvContext(SessionPtr owner) : OverlappedIOContext(owner, IO_RECV) 53 | { 54 | } 55 | }; 56 | 57 | struct OverlappedPreRecvContext : public OverlappedIOContext, public ObjectPool 58 | { 59 | OverlappedPreRecvContext(SessionPtr owner) : OverlappedIOContext(owner, IO_RECV_ZERO) 60 | { 61 | } 62 | }; 63 | 64 | 65 | void DeleteIoContext(OverlappedIOContext* context); 66 | 67 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/PacketHandler.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "Log.h" 3 | #include "PacketType.h" 4 | #include "PlayerSession.h" 5 | #include "GameLiftManager.h" 6 | 7 | //@{ Handler Helper 8 | 9 | typedef std::shared_ptr PlayerSessionPtr; 10 | 11 | typedef void(*HandlerFunc)(PlayerSessionPtr session); 12 | 13 | static HandlerFunc HandlerTable[PKT_MAX]; 14 | 15 | static void DefaultHandler(PlayerSessionPtr session) 16 | { 17 | session->Disconnect(DR_ACTIVE); 18 | } 19 | 20 | struct InitializeHandlers 21 | { 22 | InitializeHandlers() 23 | { 24 | for (int i = 0; i < PKT_MAX; ++i) 25 | HandlerTable[i] = DefaultHandler; 26 | } 27 | } _init_handlers_; 28 | 29 | struct RegisterHandler 30 | { 31 | RegisterHandler(int pktType, HandlerFunc handler) 32 | { 33 | HandlerTable[pktType] = handler; 34 | } 35 | }; 36 | 37 | #define REGISTER_HANDLER(PKT_TYPE) \ 38 | static void Handler_##PKT_TYPE(PlayerSessionPtr session); \ 39 | static RegisterHandler _register_##PKT_TYPE(PKT_TYPE, Handler_##PKT_TYPE); \ 40 | static void Handler_##PKT_TYPE(PlayerSessionPtr session) 41 | 42 | //@} 43 | 44 | 45 | void PlayerSession::OnRead(size_t len) 46 | { 47 | /// packet parsing 48 | while (true) 49 | { 50 | /// read a packet header 51 | PacketHeader header; 52 | if (false == mRecvBuffer.Peek((char*)&header, sizeof(PacketHeader))) 53 | return; 54 | 55 | /// check a packet completed on not 56 | if (mRecvBuffer.GetStoredSize() < header.mSize) 57 | return; 58 | 59 | 60 | if (header.mType >= PKT_MAX || header.mType <= PKT_NONE) 61 | { 62 | Disconnect(DR_ACTIVE); 63 | return; 64 | } 65 | 66 | /// packet dispatch... 67 | HandlerTable[header.mType](std::static_pointer_cast(shared_from_this())); 68 | } 69 | } 70 | 71 | ///////////////////////////////////////////////////////// 72 | REGISTER_HANDLER(PKT_CS_LOGIN) 73 | { 74 | LoginRequest inPacket; 75 | if (false == session->ParsePacket(inPacket)) 76 | { 77 | GConsoleLog->PrintOut(true, "packet parsing error: %d\n", inPacket.mType); 78 | return; 79 | } 80 | 81 | session->PlayerLogin(std::string(inPacket.mPlayerId)); 82 | 83 | } 84 | 85 | REGISTER_HANDLER(PKT_CS_EXIT) 86 | { 87 | ExitRequest inPacket; 88 | if (false == session->ParsePacket(inPacket)) 89 | { 90 | GConsoleLog->PrintOut(true, "packet parsing error: %d\n", inPacket.mType); 91 | return; 92 | } 93 | 94 | session->PlayerLogout(std::string(inPacket.mPlayerId)); 95 | 96 | } 97 | 98 | REGISTER_HANDLER(PKT_CS_CHAT) 99 | { 100 | ChatBroadcastRequest inPacket; 101 | if (false == session->ParsePacket(inPacket)) 102 | { 103 | GConsoleLog->PrintOut(true, "packet parsing error: %d\n", inPacket.mType); 104 | return; 105 | } 106 | 107 | /// direct response in case of chatting 108 | ChatBroadcastResult outPacket; 109 | 110 | strcpy_s(outPacket.mPlayerId, inPacket.mPlayerId); 111 | strcpy_s(outPacket.mChat, inPacket.mChat); 112 | 113 | //session->PostSend((const char*)&outPacket, outPacket.mSize); 114 | 115 | GGameLiftManager->BroadcastMessage(&outPacket); 116 | 117 | } 118 | 119 | 120 | REGISTER_HANDLER(PKT_CS_MOVE) 121 | { 122 | MoveRequest inPacket; 123 | if (false == session->ParsePacket(inPacket)) 124 | { 125 | GConsoleLog->PrintOut(true, "packet parsing error: %d\n", inPacket.mType); 126 | return; 127 | } 128 | 129 | /// just broadcast for now 130 | MoveBroadcastResult outPacket; 131 | outPacket.mPlayerIdx = inPacket.mPlayerIdx; 132 | outPacket.mPosX = inPacket.mPosX; 133 | outPacket.mPosY = inPacket.mPosY; 134 | 135 | GGameLiftManager->BroadcastMessage(&outPacket); 136 | } 137 | 138 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/PlayerSession.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "PlayerSession.h" 3 | #include "Log.h" 4 | 5 | #include "PacketType.h" 6 | 7 | #include "GameLiftManager.h" 8 | 9 | #define CLIENT_BUFSIZE 65536 10 | 11 | PlayerSession::PlayerSession(SOCKET sock) : Session(sock, CLIENT_BUFSIZE, CLIENT_BUFSIZE) 12 | { 13 | } 14 | 15 | PlayerSession::~PlayerSession() 16 | { 17 | } 18 | 19 | void PlayerSession::PlayerLogin(const std::string& playerId) 20 | { 21 | if (GGameLiftManager->AcceptPlayerSession(std::static_pointer_cast(shared_from_this()), playerId)) 22 | { 23 | mPlayerSessionId = playerId; 24 | 25 | LoginResult outPacket; 26 | strcpy_s(outPacket.mPlayerId, playerId.c_str()); 27 | 28 | PostSend((const char*)&outPacket, outPacket.mSize); 29 | return; 30 | } 31 | 32 | /// disconnect unauthed player 33 | Disconnect(DR_UNAUTH); 34 | } 35 | 36 | void PlayerSession::PlayerLogout(const std::string& playerId) 37 | { 38 | GGameLiftManager->RemovePlayerSession(std::static_pointer_cast(shared_from_this()), playerId); 39 | mPlayerSessionId.clear(); 40 | 41 | GConsoleLog->PrintOut(true, "[PLAYER] PlayerLogout: %s \n", playerId.c_str()); 42 | Disconnect(DR_LOGOUT); 43 | 44 | } 45 | 46 | void PlayerSession::OnDisconnect(DisconnectReason dr) 47 | { 48 | if (IsValid()) 49 | { 50 | GGameLiftManager->RemovePlayerSession(std::static_pointer_cast(shared_from_this()), mPlayerSessionId); 51 | mPlayerSessionId.clear(); 52 | } 53 | 54 | } -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/PlayerSession.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Session.h" 3 | 4 | class PlayerSession : public Session 5 | { 6 | public: 7 | PlayerSession(SOCKET sock); 8 | virtual ~PlayerSession(); 9 | 10 | bool IsValid() { return mPlayerSessionId.length() > 0; } 11 | 12 | void PlayerLogin(const std::string& playerId); 13 | void PlayerLogout(const std::string& playerId); 14 | 15 | virtual void OnRead(size_t len); 16 | virtual void OnDisconnect(DisconnectReason dr); 17 | 18 | private: 19 | 20 | std::string mPlayerSessionId; 21 | 22 | }; 23 | 24 | 25 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/Session.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "CircularBuffer.h" 3 | #include "FastSpinlock.h" 4 | #include "OverlappedIOContext.h" 5 | 6 | 7 | class Session : public std::enable_shared_from_this 8 | { 9 | public: 10 | Session(SOCKET sock, size_t sendBufSize, size_t recvBufSize); 11 | virtual ~Session() {} 12 | 13 | bool IsConnected() const { return !!mConnected; } 14 | 15 | void Disconnect(DisconnectReason dr); 16 | 17 | bool PreRecv(); ///< zero byte recv for less page-locking 18 | bool PostRecv() ; 19 | 20 | bool PostSend(const char* data, size_t len); 21 | bool FlushSend() ; 22 | 23 | void SendCompletion(DWORD transferred) ; 24 | void RecvCompletion(DWORD transferred) ; 25 | 26 | bool OnConnect(); 27 | virtual void OnRead(size_t len) {} 28 | virtual void OnDisconnect(DisconnectReason dr) {} 29 | 30 | template 31 | bool ParsePacket(PKT_TYPE& pkt) 32 | { 33 | return mRecvBuffer.Read((char*)&pkt, pkt.mSize); 34 | } 35 | 36 | void SetSocket(SOCKET sock) { mSocket = sock; } 37 | SOCKET GetSocket() const { return mSocket; } 38 | 39 | void EchoBack(); 40 | 41 | protected: 42 | 43 | SOCKET mSocket; 44 | 45 | CircularBuffer mRecvBuffer; 46 | CircularBuffer mSendBuffer; 47 | FastSpinlock mSendBufferLock; 48 | int mSendPendingCount; 49 | 50 | volatile long mConnected; 51 | 52 | SOCKADDR_IN mClientAddr; 53 | 54 | }; 55 | 56 | 57 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/ThreadLocal.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "ThreadLocal.h" 3 | #include "Timer.h" 4 | 5 | __declspec(thread) int LThreadType = -1; 6 | __declspec(thread) int LWorkerThreadId = -1; 7 | 8 | __declspec(thread) int64_t LTickCount = 0; 9 | __declspec(thread) Timer* LTimer = nullptr; 10 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/ThreadLocal.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define MAX_WORKER_THREAD 8 4 | 5 | enum THREAD_TYPE 6 | { 7 | THREAD_MAIN, 8 | THREAD_IO_WORKER 9 | }; 10 | 11 | class Timer; 12 | 13 | extern __declspec(thread) int LThreadType; 14 | extern __declspec(thread) int LWorkerThreadId; 15 | 16 | extern __declspec(thread) int64_t LTickCount; 17 | extern __declspec(thread) Timer* LTimer; 18 | 19 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/Timer.cpp: -------------------------------------------------------------------------------- 1 | #include "stdafx.h" 2 | #include "ThreadLocal.h" 3 | #include "Exception.h" 4 | #include "Session.h" 5 | #include "Timer.h" 6 | 7 | 8 | 9 | Timer::Timer() 10 | { 11 | LTickCount = GetTickCount64(); 12 | } 13 | 14 | 15 | void Timer::PushTimerJob(SessionPtr owner, const TimerTask& task, uint32_t after) 16 | { 17 | CRASH_ASSERT(LThreadType == THREAD_IO_WORKER); 18 | 19 | int64_t dueTimeTick = after + LTickCount; 20 | 21 | mTimerJobQueue.push(TimerJobElement(owner, task, dueTimeTick)); 22 | } 23 | 24 | 25 | void Timer::DoTimerJob() 26 | { 27 | /// thread tick update 28 | LTickCount = GetTickCount64(); 29 | 30 | while (!mTimerJobQueue.empty()) 31 | { 32 | TimerJobElement timerJobElem = mTimerJobQueue.top(); 33 | 34 | if (LTickCount < timerJobElem.mExecutionTick) 35 | break; 36 | 37 | timerJobElem.mTask(); 38 | 39 | mTimerJobQueue.pop(); 40 | } 41 | } 42 | 43 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/Timer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class Session; 4 | typedef std::function TimerTask; 5 | typedef std::shared_ptr SessionPtr; 6 | 7 | struct TimerJobElement 8 | { 9 | TimerJobElement(SessionPtr owner, const TimerTask& task, int64_t execTick) 10 | : mOwner(owner), mTask(task), mExecutionTick(execTick) 11 | {} 12 | 13 | SessionPtr mOwner; 14 | TimerTask mTask; 15 | int64_t mExecutionTick; 16 | }; 17 | 18 | struct TimerJobComparator 19 | { 20 | bool operator()(const TimerJobElement& lhs, const TimerJobElement& rhs) 21 | { 22 | return lhs.mExecutionTick > rhs.mExecutionTick; 23 | } 24 | }; 25 | 26 | 27 | typedef std::priority_queue, TimerJobComparator> TimerJobPriorityQueue; 28 | 29 | class Timer 30 | { 31 | public: 32 | 33 | Timer(); 34 | 35 | void PushTimerJob(SessionPtr owner, const TimerTask& task, uint32_t after); 36 | 37 | void DoTimerJob(); 38 | 39 | private: 40 | 41 | TimerJobPriorityQueue mTimerJobQueue; 42 | 43 | }; 44 | 45 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/include/aws/gamelift/common/GameLift_EXPORTS.h: -------------------------------------------------------------------------------- 1 | /* 2 | * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or 3 | * its licensors. 4 | * 5 | * For complete copyright and license terms please see the LICENSE at the root of this 6 | * distribution (the "License"). All use of this software is governed by the License, 7 | * or, if provided, by the license below or the license accompanying this file. Do not 8 | * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * 11 | */ 12 | #pragma once 13 | 14 | #include 15 | #include 16 | 17 | #ifdef _WIN32 18 | //disable windows complaining about max template size. 19 | #pragma warning (disable : 4503) 20 | #endif 21 | 22 | #if defined (_MSC_VER) 23 | #pragma warning(disable : 4251) 24 | #ifdef USE_IMPORT_EXPORT 25 | #ifdef AWS_GAMELIFT_EXPORTS 26 | #define AWS_GAMELIFT_API __declspec(dllexport) 27 | #else 28 | #define AWS_GAMELIFT_API __declspec(dllimport) 29 | #endif /* AWS_GAMELIFT_EXPORTS */ 30 | #else 31 | #define AWS_GAMELIFT_API 32 | #endif // 33 | #else /* defined (_WIN32) */ 34 | #define AWS_GAMELIFT_API 35 | #endif -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/include/aws/gamelift/internal/GameLiftCommonState.h: -------------------------------------------------------------------------------- 1 | /* 2 | * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or 3 | * its licensors. 4 | * 5 | * For complete copyright and license terms please see the LICENSE at the root of this 6 | * distribution (the "License"). All use of this software is governed by the License, 7 | * or, if provided, by the license below or the license accompanying this file. Do not 8 | * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * 11 | */ 12 | #pragma once 13 | 14 | #include 15 | #include 16 | 17 | namespace Aws 18 | { 19 | namespace GameLift 20 | { 21 | namespace Internal 22 | { 23 | enum class GAMELIFT_INTERNAL_STATE_TYPE { 24 | CLIENT, 25 | SERVER 26 | }; 27 | 28 | class GameLiftCommonState; 29 | 30 | typedef Aws::GameLift::Outcome GetInstanceOutcome; 31 | 32 | class GameLiftCommonState 33 | { 34 | public: 35 | 36 | static GetInstanceOutcome GetInstance(); 37 | 38 | static GetInstanceOutcome GetInstance(GAMELIFT_INTERNAL_STATE_TYPE stateType); 39 | 40 | static GenericOutcome SetInstance(GameLiftCommonState* instance); 41 | 42 | static GenericOutcome DestroyInstance(); 43 | 44 | virtual GAMELIFT_INTERNAL_STATE_TYPE GetStateType() = 0; 45 | 46 | //Normally this should not be public, but AwsMemory needs access to it 47 | virtual ~GameLiftCommonState(); 48 | 49 | protected: 50 | 51 | GameLiftCommonState(); 52 | 53 | private: 54 | 55 | static GameLiftCommonState* m_instance; 56 | 57 | }; 58 | 59 | } //namespace Internal 60 | } //namespace GameLift 61 | } //namespace Aws 62 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/include/aws/gamelift/internal/modelmapper/AttributeValueMapper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or 3 | * its licensors. 4 | * 5 | * For complete copyright and license terms please see the LICENSE at the root of this 6 | * distribution (the "License"). All use of this software is governed by the License, 7 | * or, if provided, by the license below or the license accompanying this file. Do not 8 | * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * 11 | */ 12 | #pragma once 13 | #include 14 | #include 15 | 16 | namespace Aws 17 | { 18 | namespace GameLift 19 | { 20 | namespace Internal 21 | { 22 | namespace ModelMapper 23 | { 24 | using namespace Aws::GameLift::Server::Model; 25 | using namespace com::amazon::whitewater::auxproxy; 26 | 27 | class AttributeValueMapper 28 | { 29 | public: 30 | #ifdef GAMELIFT_USE_STD 31 | static pbuffer::AttributeValue ParseFromAttributeValue(const AttributeValue &attrValue) 32 | { 33 | AttributeValue::AttrType type = attrValue.GetType(); 34 | pbuffer::AttributeValue event; 35 | event.set_type(static_cast(type)); 36 | 37 | switch (type) 38 | { 39 | case AttributeValue::AttrType::STRING: 40 | { 41 | event.set_s(attrValue.GetS()); 42 | break; 43 | } 44 | 45 | case AttributeValue::AttrType::STRING_LIST: 46 | { 47 | for (auto& str : attrValue.GetSL()) 48 | { 49 | event.add_sl(str); 50 | } 51 | break; 52 | } 53 | 54 | case AttributeValue::AttrType::STRING_DOUBLE_MAP: 55 | { 56 | for (const auto& iter : attrValue.GetSDM()) 57 | { 58 | (*event.mutable_sdm())[iter.first] = iter.second; 59 | } 60 | break; 61 | } 62 | 63 | default: 64 | { 65 | event.set_n(attrValue.GetN()); 66 | break; 67 | } 68 | } 69 | 70 | return event; 71 | } 72 | #else 73 | static pbuffer::AttributeValue ParseFromAttributeValue(const AttributeValue &attrValue) 74 | { 75 | AttributeValue::AttrType type = attrValue.GetType(); 76 | pbuffer::AttributeValue event; 77 | event.set_type(static_cast(type)); 78 | 79 | switch (type) 80 | { 81 | case AttributeValue::AttrType::STRING: 82 | { 83 | event.set_s(attrValue.GetS()); 84 | break; 85 | } 86 | 87 | case AttributeValue::AttrType::STRING_LIST: 88 | { 89 | int count; 90 | const AttributeValue::AttributeStringType* strs = attrValue.GetSL(count); 91 | for (int index = 0; index < count; ++index) 92 | { 93 | event.add_sl(strs[index]); 94 | } 95 | break; 96 | } 97 | 98 | case AttributeValue::AttrType::STRING_DOUBLE_MAP: 99 | { 100 | int count; 101 | const AttributeValue::KeyAndValue* entries = attrValue.GetSDM(count); 102 | for (int index = 0; index < count; ++index) 103 | { 104 | (*event.mutable_sdm())[entries[index].GetKey()] = entries[index].GetValue(); 105 | } 106 | break; 107 | } 108 | 109 | default: 110 | { 111 | event.set_n(attrValue.GetN()); 112 | break; 113 | } 114 | } 115 | 116 | return event; 117 | } 118 | #endif 119 | }; 120 | } //namespace ModelMapper 121 | } //namespace Internal 122 | } //namespace GameLift 123 | } //namespace Aws 124 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/include/aws/gamelift/internal/modelmapper/PlayerMapper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or 3 | * its licensors. 4 | * 5 | * For complete copyright and license terms please see the LICENSE at the root of this 6 | * distribution (the "License"). All use of this software is governed by the License, 7 | * or, if provided, by the license below or the license accompanying this file. Do not 8 | * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * 11 | */ 12 | #pragma once 13 | #include 14 | #include 15 | #include 16 | 17 | namespace Aws 18 | { 19 | namespace GameLift 20 | { 21 | namespace Internal 22 | { 23 | namespace ModelMapper 24 | { 25 | using namespace Aws::GameLift::Server::Model; 26 | using namespace com::amazon::whitewater::auxproxy; 27 | 28 | class PlayerMapper 29 | { 30 | public: 31 | #ifdef GAMELIFT_USE_STD 32 | static void PopulateFromPlayer(pbuffer::Player& event, const Player &player) 33 | { 34 | event.set_playerid(player.GetPlayerId()); 35 | event.set_team(player.GetTeam()); 36 | 37 | for (const auto& iter : player.GetLatencyInMs()) 38 | { 39 | (*event.mutable_latencyinms())[iter.first] = iter.second; 40 | } 41 | 42 | for (const auto& iter : player.GetPlayerAttributes()) 43 | { 44 | (*event.mutable_playerattributes())[iter.first] = 45 | AttributeValueMapper::ParseFromAttributeValue(iter.second); 46 | } 47 | } 48 | #else 49 | static void PopulateFromPlayer(pbuffer::Player& event, const Player &player) 50 | { 51 | event.set_playerid(player.GetPlayerId()); 52 | event.set_team(player.GetTeam()); 53 | 54 | int count; 55 | const Player::RegionAndLatency* entries = player.GetLatencyMs(count); 56 | for (int index = 0; index < count; ++index) 57 | { 58 | (*event.mutable_latencyinms())[entries[index].GetRegion()] = entries[index].GetLatencyMs(); 59 | } 60 | 61 | const Player::NamedAttribute* attrs = player.GetPlayerAttributes(count); 62 | for (int index = 0; index < count; ++index) 63 | { 64 | (*event.mutable_playerattributes())[attrs[index].GetName()] = 65 | AttributeValueMapper::ParseFromAttributeValue(attrs[index].GetValue()); 66 | } 67 | } 68 | #endif 69 | }; 70 | } //namespace ModelMapper 71 | } //namespace Internal 72 | } //namespace GameLift 73 | } //namespace Aws 74 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/include/aws/gamelift/internal/network/AuxProxyMessageHandler.h: -------------------------------------------------------------------------------- 1 | /* 2 | * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or 3 | * its licensors. 4 | * 5 | * For complete copyright and license terms please see the LICENSE at the root of this 6 | * distribution (the "License"). All use of this software is governed by the License, 7 | * or, if provided, by the license below or the license accompanying this file. Do not 8 | * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * 11 | */ 12 | #pragma once 13 | #include 14 | #include 15 | #include 16 | 17 | namespace Aws 18 | { 19 | namespace GameLift 20 | { 21 | namespace Internal 22 | { 23 | namespace Network 24 | { 25 | using namespace Aws::GameLift::Server::Model; 26 | 27 | class AuxProxyMessageHandler 28 | { 29 | public: 30 | virtual void OnStartGameSession(GameSession& gameSession, sio::message::list& ack_resp) = 0; 31 | virtual void OnUpdateGameSession(UpdateGameSession& gameSession, sio::message::list& ack_resp) = 0; 32 | virtual void OnTerminateProcess(long terminationTime) = 0; 33 | }; 34 | } //namespace Network 35 | } //namespace Internal 36 | } //namespace GameLift 37 | } //namespace Aws 38 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/include/aws/gamelift/internal/network/AuxProxyMessageSender.h: -------------------------------------------------------------------------------- 1 | /* 2 | * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or 3 | * its licensors. 4 | * 5 | * For complete copyright and license terms please see the LICENSE at the root of this 6 | * distribution (the "License"). All use of this software is governed by the License, 7 | * or, if provided, by the license below or the license accompanying this file. Do not 8 | * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * 11 | */ 12 | #pragma once 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #ifdef _WIN32 23 | #include 24 | #undef ERROR 25 | #undef SetPort // See http://answers.perforce.com/articles/KB/2638 26 | #endif 27 | 28 | namespace Aws 29 | { 30 | namespace GameLift 31 | { 32 | namespace Internal 33 | { 34 | namespace Network 35 | { 36 | using namespace Aws::GameLift::Server::Model; 37 | using namespace com::amazon::whitewater::auxproxy; 38 | 39 | class AuxProxyMessageSender 40 | { 41 | public: 42 | AuxProxyMessageSender(sio::client* sioClient); 43 | ~AuxProxyMessageSender(); 44 | GenericOutcome ProcessReady(int port, const Aws::GameLift::Server::LogParameters &logParameters); 45 | GenericOutcome ProcessEnding(); 46 | GenericOutcome ActivateGameSession(std::string gameSessionId); 47 | GenericOutcome TerminateGameSession(std::string gameSessionId); 48 | GenericOutcome UpdatePlayerSessionCreationPolicy(std::string gameSessionId, std::string newPlayerSessionPolicy); 49 | GenericOutcome AcceptPlayerSession(std::string playerSessionId, std::string gameSessionId); 50 | GenericOutcome RemovePlayerSession(std::string playerSessionId, std::string gameSessionId); 51 | DescribePlayerSessionsOutcome DescribePlayerSessions(const DescribePlayerSessionsRequest &describePlayerSessionsRequest); 52 | GenericOutcome ReportHealth(bool healthStatus); 53 | StartMatchBackfillOutcome BackfillMatchmaking(const StartMatchBackfillRequest &request); 54 | GenericOutcome StopMatchmaking(const StopMatchBackfillRequest &request); 55 | private: 56 | std::shared_ptr ParseMessage(google::protobuf::MessageLite* message); 57 | GenericOutcome EmitEvent(google::protobuf::MessageLite* message); 58 | DescribePlayerSessionsOutcome Call(pbuffer::DescribePlayerSessionsRequest* message); 59 | StartMatchBackfillOutcome Call(pbuffer::BackfillMatchmakingRequest* message); 60 | void Send(google::protobuf::MessageLite* message, std::function ackFunction); 61 | 62 | sio::client* m_sio_client; 63 | std::mutex m_lock; 64 | }; 65 | } //namespace Network 66 | } //namespace Internal 67 | } //namespace GameLift 68 | } //namespace Aws 69 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/include/aws/gamelift/internal/network/Network.h: -------------------------------------------------------------------------------- 1 | /* 2 | * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or 3 | * its licensors. 4 | * 5 | * For complete copyright and license terms please see the LICENSE at the root of this 6 | * distribution (the "License"). All use of this software is governed by the License, 7 | * or, if provided, by the license below or the license accompanying this file. Do not 8 | * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * 11 | */ 12 | #pragma once 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | namespace Aws 21 | { 22 | namespace GameLift 23 | { 24 | namespace Internal 25 | { 26 | namespace Network 27 | { 28 | class Network 29 | { 30 | public: 31 | Network(sio::client* sioClientToAuxProxy, sio::client* sioClientFromAuxProxy, 32 | AuxProxyMessageHandler* handler, AuxProxyMessageSender* sender); 33 | 34 | ~Network(); 35 | 36 | void OnConnected(); 37 | void OnFail(); 38 | void OnClose(sio::client::close_reason const& reason); 39 | 40 | void OnStartGameSession(std::string const& name, sio::message::ptr const& data, bool hasAck, sio::message::list &ack_resp); 41 | void OnUpdateGameSession(std::string const& name, sio::message::ptr const& data, bool hasAck, sio::message::list &ack_resp); 42 | void OnTerminateProcess(std::string const& name, sio::message::ptr const& data, bool hasAck, sio::message::list &ack_resp); 43 | 44 | AuxProxyMessageSender* getAuxProxySender() { return m_sender; }; 45 | 46 | private: 47 | FRIEND_TEST(WhenParseFromBufferedGameSessionTest, GameSessionValuesMatchbGameSessionValues); 48 | FRIEND_TEST(WhenParseFromBufferedUpdateGameSessionTest, UpdateGameSessionValuesMatchbUpdateGameSessionValues); 49 | 50 | static Aws::GameLift::Server::Model::GameSession ParseFromBufferedGameSession( 51 | const com::amazon::whitewater::auxproxy::pbuffer::GameSession& bGameSession); 52 | static Aws::GameLift::Server::Model::UpdateGameSession ParseFromBufferedUpdateGameSession( 53 | const com::amazon::whitewater::auxproxy::pbuffer::UpdateGameSession& bUpdateGameSession); 54 | void ConfigureClient(sio::client* sioClient); 55 | void PerformConnect(sio::client* sioClient, std::map query); 56 | void SetupClientHandlers(sio::client* sioClient); 57 | 58 | sio::client* m_sio_client_to_aux_proxy; 59 | sio::client* m_sio_client_from_aux_proxy; 60 | AuxProxyMessageHandler* m_handler; 61 | AuxProxyMessageSender* m_sender; 62 | 63 | bool m_connect_finish; 64 | std::mutex m_lock; 65 | std::condition_variable_any m_cond; 66 | }; 67 | } //namespace Network 68 | } //namespace Internal 69 | } //namespace GameLift 70 | } //namespace Aws 71 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/include/aws/gamelift/server/LogParameters.h: -------------------------------------------------------------------------------- 1 | /* 2 | * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or 3 | * its licensors. 4 | * 5 | * For complete copyright and license terms please see the LICENSE at the root of this 6 | * distribution (the "License"). All use of this software is governed by the License, 7 | * or, if provided, by the license below or the license accompanying this file. Do not 8 | * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * 11 | */ 12 | #pragma once 13 | #pragma warning(disable:4996) 14 | #include 15 | #include 16 | 17 | #ifndef GAMELIFT_USE_STD 18 | #ifndef MAX_LOG_PATHS 19 | #define MAX_LOG_PATHS 10 20 | #endif 21 | #ifndef MAX_PATH_LENGTH 22 | #define MAX_PATH_LENGTH 1024 23 | #endif 24 | #endif 25 | 26 | namespace Aws 27 | { 28 | namespace GameLift 29 | { 30 | namespace Server 31 | { 32 | class LogParameters 33 | { 34 | #ifdef GAMELIFT_USE_STD 35 | public: 36 | AWS_GAMELIFT_API LogParameters() { 37 | } 38 | AWS_GAMELIFT_API LogParameters(const std::vector &logPaths) : m_logPaths(logPaths){} 39 | 40 | AWS_GAMELIFT_API std::vector getLogPaths() const { return m_logPaths; } 41 | 42 | private: 43 | std::vector m_logPaths; 44 | }; 45 | #else 46 | public: 47 | AWS_GAMELIFT_API LogParameters() : m_count(0) { 48 | memset(m_logPaths, 0, sizeof(m_logPaths)); 49 | } 50 | AWS_GAMELIFT_API LogParameters(const char** logPaths, int count); 51 | 52 | AWS_GAMELIFT_API int getLogPathCount() const { return m_count; } 53 | AWS_GAMELIFT_API const char* getLogPath(int index) const { return index < m_count ? m_logPaths[index] : nullptr; } 54 | 55 | private: 56 | char m_logPaths[MAX_LOG_PATHS][MAX_PATH_LENGTH]; 57 | int m_count; 58 | }; 59 | #endif 60 | } // namespace Server 61 | } // namespace GameLift 62 | } // namespace Aws 63 | 64 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/include/aws/gamelift/server/model/GameSessionStatus.h: -------------------------------------------------------------------------------- 1 | /* 2 | * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or 3 | * its licensors. 4 | * 5 | * For complete copyright and license terms please see the LICENSE at the root of this 6 | * distribution (the "License"). All use of this software is governed by the License, 7 | * or, if provided, by the license below or the license accompanying this file. Do not 8 | * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * 11 | */ 12 | #pragma once 13 | #include 14 | #include 15 | 16 | namespace Aws 17 | { 18 | namespace GameLift 19 | { 20 | namespace Server 21 | { 22 | namespace Model 23 | { 24 | enum class GameSessionStatus 25 | { 26 | NOT_SET, 27 | ACTIVE, 28 | ACTIVATING, 29 | TERMINATED, 30 | TERMINATING 31 | }; 32 | 33 | namespace GameSessionStatusMapper 34 | { 35 | #ifdef GAMELIFT_USE_STD 36 | inline AWS_GAMELIFT_API GameSessionStatus GetGameSessionStatusForName(const std::string& s_name) { 37 | const char* name = s_name.c_str(); 38 | #else 39 | inline AWS_GAMELIFT_API GameSessionStatus GetGameSessionStatusForName(const char* name) { 40 | #endif 41 | if (strcmp(name, "ACTIVE") == 0) { 42 | return GameSessionStatus::ACTIVE; 43 | } 44 | if (strcmp(name, "ACTIVATING") == 0) { 45 | return GameSessionStatus::ACTIVATING; 46 | } 47 | if (strcmp(name, "TERMINATING") == 0) { 48 | return GameSessionStatus::TERMINATING; 49 | } 50 | if (strcmp(name, "TERMINATED") == 0) { 51 | return GameSessionStatus::TERMINATED; 52 | } 53 | return GameSessionStatus::NOT_SET; 54 | } 55 | 56 | #ifdef GAMELIFT_USE_STD 57 | inline AWS_GAMELIFT_API std::string GetNameForGameSessionStatus(GameSessionStatus value) 58 | #else 59 | inline AWS_GAMELIFT_API const char* GetNameForGameSessionStatus(GameSessionStatus value) 60 | #endif 61 | { 62 | switch (value) { 63 | case GameSessionStatus::ACTIVE: 64 | return "ACTIVE"; 65 | case GameSessionStatus::ACTIVATING: 66 | return "ACTIVATING"; 67 | case GameSessionStatus::TERMINATING: 68 | return "TERMINATING"; 69 | case GameSessionStatus::TERMINATED: 70 | return "TERMINATED"; 71 | default: 72 | return "NOT_SET"; 73 | } 74 | } 75 | } // namespace GameSessionStatusMapper 76 | } // namespace Model 77 | } // namespace Server 78 | } // namespace GameLift 79 | } // namespace Aws 80 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/include/aws/gamelift/server/model/PlayerSessionCreationPolicy.h: -------------------------------------------------------------------------------- 1 | /* 2 | * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or 3 | * its licensors. 4 | * 5 | * For complete copyright and license terms please see the LICENSE at the root of this 6 | * distribution (the "License"). All use of this software is governed by the License, 7 | * or, if provided, by the license below or the license accompanying this file. Do not 8 | * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * 11 | */ 12 | #pragma once 13 | #include 14 | 15 | namespace Aws 16 | { 17 | namespace GameLift 18 | { 19 | namespace Server 20 | { 21 | namespace Model 22 | { 23 | enum class PlayerSessionCreationPolicy 24 | { 25 | NOT_SET, 26 | ACCEPT_ALL, 27 | DENY_ALL 28 | }; 29 | 30 | namespace PlayerSessionCreationPolicyMapper { 31 | #ifdef GAMELIFT_USE_STD 32 | inline AWS_GAMELIFT_API PlayerSessionCreationPolicy GetPlayerSessionCreationPolicyForName(const std::string& name) 33 | { 34 | if (name == "ACCEPT_ALL") { 35 | return PlayerSessionCreationPolicy::ACCEPT_ALL; 36 | } 37 | if (name == "DENY_ALL") { 38 | return PlayerSessionCreationPolicy::DENY_ALL; 39 | } 40 | return PlayerSessionCreationPolicy::NOT_SET; 41 | } 42 | 43 | inline AWS_GAMELIFT_API std::string GetNameForPlayerSessionCreationPolicy(PlayerSessionCreationPolicy value) 44 | { 45 | switch (value) { 46 | case PlayerSessionCreationPolicy::ACCEPT_ALL: 47 | return "ACCEPT_ALL"; 48 | case PlayerSessionCreationPolicy::DENY_ALL: 49 | return "DENY_ALL"; 50 | default: 51 | return "NOT_SET"; 52 | } 53 | } 54 | #else 55 | inline AWS_GAMELIFT_API PlayerSessionCreationPolicy GetPlayerSessionCreationPolicyForName(const char* name) 56 | { 57 | if (strcmp(name, "ACCEPT_ALL") == 0) { 58 | return PlayerSessionCreationPolicy::ACCEPT_ALL; 59 | } 60 | if (strcmp(name, "DENY_ALL") == 0) { 61 | return PlayerSessionCreationPolicy::DENY_ALL; 62 | } 63 | return PlayerSessionCreationPolicy::NOT_SET; 64 | } 65 | 66 | inline AWS_GAMELIFT_API const char* GetNameForPlayerSessionCreationPolicy(PlayerSessionCreationPolicy value) 67 | { 68 | switch (value) { 69 | case PlayerSessionCreationPolicy::ACCEPT_ALL: 70 | return "ACCEPT_ALL"; 71 | case PlayerSessionCreationPolicy::DENY_ALL: 72 | return "DENY_ALL"; 73 | default: 74 | return "NOT_SET"; 75 | } 76 | } 77 | #endif 78 | } // namespace PlayerSessionCreationPolicyMapper 79 | } // namespace Model 80 | } // namespace Server 81 | } // namespace GameLift 82 | } // namespace Aws 83 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/include/aws/gamelift/server/model/PlayerSessionStatus.h: -------------------------------------------------------------------------------- 1 | /* 2 | * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or 3 | * its licensors. 4 | * 5 | * For complete copyright and license terms please see the LICENSE at the root of this 6 | * distribution (the "License"). All use of this software is governed by the License, 7 | * or, if provided, by the license below or the license accompanying this file. Do not 8 | * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * 11 | */ 12 | #pragma once 13 | #include 14 | 15 | namespace Aws 16 | { 17 | namespace GameLift 18 | { 19 | namespace Server 20 | { 21 | namespace Model 22 | { 23 | enum class PlayerSessionStatus 24 | { 25 | NOT_SET, 26 | RESERVED, 27 | ACTIVE, 28 | COMPLETED, 29 | TIMEDOUT 30 | }; 31 | 32 | namespace PlayerSessionStatusMapper 33 | { 34 | #ifdef GAMELIFT_USE_STD 35 | inline AWS_GAMELIFT_API PlayerSessionStatus GetPlayerSessionStatusForName(const std::string& name) 36 | { 37 | if (name == "RESERVED") { 38 | return PlayerSessionStatus::RESERVED; 39 | } 40 | if (name == "ACTIVE") { 41 | return PlayerSessionStatus::ACTIVE; 42 | } 43 | if (name == "COMPLETED") { 44 | return PlayerSessionStatus::COMPLETED; 45 | } 46 | if (name == "TIMEDOUT") { 47 | return PlayerSessionStatus::TIMEDOUT; 48 | } 49 | return PlayerSessionStatus::NOT_SET; 50 | } 51 | inline AWS_GAMELIFT_API std::string GetNameForPlayerSessionStatus(PlayerSessionStatus value) 52 | { 53 | switch (value) { 54 | case PlayerSessionStatus::RESERVED: 55 | return "RESERVED"; 56 | case PlayerSessionStatus::ACTIVE: 57 | return "ACTIVE"; 58 | case PlayerSessionStatus::COMPLETED: 59 | return "COMPLETED"; 60 | case PlayerSessionStatus::TIMEDOUT: 61 | return "TIMEDOUT"; 62 | default: 63 | return "NOT_SET"; 64 | } 65 | } 66 | #else 67 | inline AWS_GAMELIFT_API PlayerSessionStatus GetPlayerSessionStatusForName(const char* name) 68 | { 69 | if (strcmp(name, "RESERVED") == 0) { 70 | return PlayerSessionStatus::RESERVED; 71 | } 72 | if (strcmp(name, "ACTIVE") == 0) { 73 | return PlayerSessionStatus::ACTIVE; 74 | } 75 | if (strcmp(name, "COMPLETED") == 0) { 76 | return PlayerSessionStatus::COMPLETED; 77 | } 78 | if (strcmp(name, "TIMEDOUT") == 0) { 79 | return PlayerSessionStatus::TIMEDOUT; 80 | } 81 | return PlayerSessionStatus::NOT_SET; 82 | } 83 | inline AWS_GAMELIFT_API const char* GetNameForPlayerSessionStatus(PlayerSessionStatus value) 84 | { 85 | switch (value) { 86 | case PlayerSessionStatus::RESERVED: 87 | return "RESERVED"; 88 | case PlayerSessionStatus::ACTIVE: 89 | return "ACTIVE"; 90 | case PlayerSessionStatus::COMPLETED: 91 | return "COMPLETED"; 92 | case PlayerSessionStatus::TIMEDOUT: 93 | return "TIMEDOUT"; 94 | default: 95 | return "NOT_SET"; 96 | } 97 | } 98 | #endif 99 | } // namespace GameSessionStatusMapper 100 | } // namespace Model 101 | } // namespace Server 102 | } // namespace GameLift 103 | } // namespace Aws 104 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/include/aws/gamelift/server/model/UpdateReason.h: -------------------------------------------------------------------------------- 1 | /* 2 | * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or 3 | * its licensors. 4 | * 5 | * For complete copyright and license terms please see the LICENSE at the root of this 6 | * distribution (the "License"). All use of this software is governed by the License, 7 | * or, if provided, by the license below or the license accompanying this file. Do not 8 | * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * 11 | */ 12 | #pragma once 13 | #include 14 | 15 | namespace Aws 16 | { 17 | namespace GameLift 18 | { 19 | namespace Server 20 | { 21 | namespace Model 22 | { 23 | enum class UpdateReason 24 | { 25 | MATCHMAKING_DATA_UPDATED, 26 | BACKFILL_FAILED, 27 | BACKFILL_TIMED_OUT, 28 | BACKFILL_CANCELLED, 29 | UNKNOWN 30 | }; 31 | 32 | namespace UpdateReasonMapper 33 | { 34 | #ifdef GAMELIFT_USE_STD 35 | inline AWS_GAMELIFT_API UpdateReason GetUpdateReasonForName(std::string& s_name) { 36 | const char* name = s_name.c_str(); 37 | #else 38 | inline AWS_GAMELIFT_API UpdateReason GetUpdateReasonForName(const char* name) { 39 | #endif 40 | if (strcmp(name, "MATCHMAKING_DATA_UPDATED") == 0) 41 | { 42 | return UpdateReason::MATCHMAKING_DATA_UPDATED; 43 | } 44 | if (strcmp(name, "BACKFILL_FAILED") == 0) 45 | { 46 | return UpdateReason::BACKFILL_FAILED; 47 | } 48 | if (strcmp(name, "BACKFILL_TIMED_OUT") == 0) 49 | { 50 | return UpdateReason::BACKFILL_TIMED_OUT; 51 | } 52 | if (strcmp(name, "BACKFILL_CANCELLED") == 0) 53 | { 54 | return UpdateReason::BACKFILL_CANCELLED; 55 | } 56 | 57 | return UpdateReason::UNKNOWN; 58 | } 59 | #ifdef GAMELIFT_USE_STD 60 | inline AWS_GAMELIFT_API std::string GetNameForUpdateReason(UpdateReason value) 61 | #else 62 | inline AWS_GAMELIFT_API const char* GetNameForUpdateReason(UpdateReason value) 63 | #endif 64 | { 65 | switch (value) 66 | { 67 | case UpdateReason::MATCHMAKING_DATA_UPDATED: 68 | return "MATCHMAKING_DATA_UPDATED"; 69 | case UpdateReason::BACKFILL_FAILED: 70 | return "BACKFILL_FAILED"; 71 | case UpdateReason::BACKFILL_TIMED_OUT: 72 | return "BACKFILL_TIMED_OUT"; 73 | case UpdateReason::BACKFILL_CANCELLED: 74 | return "BACKFILL_CANCELLED"; 75 | default: 76 | return "UNKNOWN"; 77 | } 78 | } 79 | } // namespace GameSessionStatusMapper 80 | } // namespace Model 81 | } // namespace Server 82 | } // namespace GameLift 83 | } // namespace Aws 84 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // GameLiftGameServer.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | 34 | // TODO: reference additional headers your program requires here 35 | -------------------------------------------------------------------------------- /GameLiftGameServer/GameLiftGameServer/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /GameLiftGameServer/upload/aws-cpp-sdk-gamelift-server.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeliard/GameLift/4bdb482097cac9e362701732bff74e4398a1c174/GameLiftGameServer/upload/aws-cpp-sdk-gamelift-server.dll -------------------------------------------------------------------------------- /GameLiftGameServer/upload/install.bat: -------------------------------------------------------------------------------- 1 | vc_redist.x64.exe /q -------------------------------------------------------------------------------- /GameLiftGameServer/upload/logs/serverErr.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeliard/GameLift/4bdb482097cac9e362701732bff74e4398a1c174/GameLiftGameServer/upload/logs/serverErr.log -------------------------------------------------------------------------------- /GameLiftGameServer/upload/logs/serverLog.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeliard/GameLift/4bdb482097cac9e362701732bff74e4398a1c174/GameLiftGameServer/upload/logs/serverLog.txt -------------------------------------------------------------------------------- /GameLiftGameServer/upload/logs/serverOut.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeliard/GameLift/4bdb482097cac9e362701732bff74e4398a1c174/GameLiftGameServer/upload/logs/serverOut.log -------------------------------------------------------------------------------- /GameLiftGameServer/x64/Release/aws-cpp-sdk-gamelift-server.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeliard/GameLift/4bdb482097cac9e362701732bff74e4398a1c174/GameLiftGameServer/x64/Release/aws-cpp-sdk-gamelift-server.dll -------------------------------------------------------------------------------- /GameLiftGameServer/x64/Release/aws-cpp-sdk-gamelift-server.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeliard/GameLift/4bdb482097cac9e362701732bff74e4398a1c174/GameLiftGameServer/x64/Release/aws-cpp-sdk-gamelift-server.lib -------------------------------------------------------------------------------- /GameLiftLinuxServer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | project(GameLiftLinuxServer) 4 | 5 | add_definitions(-std=c++11) 6 | add_definitions(-DGAMELIFT_USE_STD) 7 | include_directories(include) 8 | link_directories(${CMAKE_SOURCE_DIR}/lib) 9 | 10 | file(GLOB GLServerSRC 11 | "*.h" 12 | "*.cpp" 13 | "../PacketShare/PacketType.h" 14 | ) 15 | 16 | add_executable(GameLiftLinuxServer ${GLServerSRC}) 17 | 18 | target_link_libraries(GameLiftLinuxServer aws-cpp-sdk-gamelift-server sioclient boost_date_time boost_random boost_system protobuf pthread) 19 | 20 | 21 | -------------------------------------------------------------------------------- /GameLiftLinuxServer/CircularBuffer.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeliard/GameLift/4bdb482097cac9e362701732bff74e4398a1c174/GameLiftLinuxServer/CircularBuffer.cpp -------------------------------------------------------------------------------- /GameLiftLinuxServer/CircularBuffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #define OUT 4 | 5 | class CircularBuffer 6 | { 7 | public: 8 | 9 | CircularBuffer(size_t capacity) : mBRegionPointer(nullptr), mARegionSize(0), mBRegionSize(0) 10 | { 11 | mBuffer = new char[capacity]; 12 | mBufferEnd = mBuffer + capacity; 13 | mARegionPointer = mBuffer; 14 | } 15 | 16 | ~CircularBuffer() 17 | { 18 | delete [] mBuffer; 19 | } 20 | 21 | bool Peek(OUT char* destbuf, size_t bytes) const; 22 | bool Read(OUT char* destbuf, size_t bytes); 23 | bool Write(const char* data, size_t bytes); 24 | 25 | 26 | void Remove(size_t len); 27 | 28 | size_t GetFreeSpaceSize() 29 | { 30 | if ( mBRegionPointer != nullptr ) 31 | return GetBFreeSpace(); 32 | else 33 | { 34 | if ( GetAFreeSpace() < GetSpaceBeforeA() ) 35 | { 36 | AllocateB(); 37 | return GetBFreeSpace(); 38 | } 39 | else 40 | return GetAFreeSpace(); 41 | } 42 | } 43 | 44 | size_t GetStoredSize() const 45 | { 46 | return mARegionSize + mBRegionSize; 47 | } 48 | 49 | size_t GetContiguiousBytes() const 50 | { 51 | if ( mARegionSize > 0 ) 52 | return mARegionSize; 53 | else 54 | return mBRegionSize; 55 | } 56 | 57 | void* GetBuffer() const 58 | { 59 | if( mBRegionPointer != nullptr ) 60 | return mBRegionPointer + mBRegionSize; 61 | else 62 | return mARegionPointer + mARegionSize; 63 | } 64 | 65 | 66 | void Commit(size_t len) 67 | { 68 | if ( mBRegionPointer != nullptr ) 69 | mBRegionSize += len; 70 | else 71 | mARegionSize += len; 72 | } 73 | 74 | void* GetBufferStart() const 75 | { 76 | if ( mARegionSize > 0 ) 77 | return mARegionPointer; 78 | else 79 | return mBRegionPointer; 80 | } 81 | 82 | 83 | private: 84 | 85 | void AllocateB() 86 | { 87 | mBRegionPointer = mBuffer; 88 | } 89 | 90 | size_t GetAFreeSpace() const 91 | { 92 | return (mBufferEnd - mARegionPointer - mARegionSize); 93 | } 94 | 95 | size_t GetSpaceBeforeA() const 96 | { 97 | return (mARegionPointer - mBuffer); 98 | } 99 | 100 | 101 | size_t GetBFreeSpace() const 102 | { 103 | if (mBRegionPointer == nullptr) 104 | return 0; 105 | 106 | return (mARegionPointer - mBRegionPointer - mBRegionSize); 107 | } 108 | 109 | private: 110 | 111 | char* mBuffer; 112 | char* mBufferEnd; 113 | 114 | char* mARegionPointer; 115 | size_t mARegionSize; 116 | 117 | char* mBRegionPointer; 118 | size_t mBRegionSize; 119 | 120 | }; 121 | -------------------------------------------------------------------------------- /GameLiftLinuxServer/ClientManager.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "Log.h" 13 | #include "../PacketShare/PacketType.h" 14 | #include "Utils.h" 15 | #include "ClientSession.h" 16 | #include "ClientManager.h" 17 | 18 | #include "Scheduler.h" 19 | 20 | std::unique_ptr GClientManager(nullptr); 21 | 22 | 23 | bool ClientManager::Initialize(int& listenPort) 24 | { 25 | mListenSocket = socket(AF_INET, SOCK_STREAM, 0); 26 | if (mListenSocket < 0) 27 | return false; 28 | 29 | int opt = 1; 30 | setsockopt(mListenSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt, sizeof(int)); 31 | 32 | /// bind 33 | sockaddr_in serveraddr; 34 | memset(&serveraddr, 0, sizeof(sockaddr_in)); 35 | 36 | serveraddr.sin_family = AF_INET; 37 | serveraddr.sin_port = htons(listenPort); 38 | serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); 39 | 40 | int ret = bind(mListenSocket, (sockaddr*)&serveraddr, sizeof(serveraddr)); 41 | if (ret < 0) 42 | return false; 43 | 44 | /// listen 45 | ret = listen(mListenSocket, SOMAXCONN); 46 | if (ret < 0) 47 | return false; 48 | 49 | mEpollFd = epoll_create(MAX_CONNECTION); 50 | if (mEpollFd < 0) 51 | return false; 52 | 53 | epoll_event ev; 54 | memset(&ev, 0, sizeof(ev)); 55 | ev.events = EPOLLIN; 56 | ev.data.fd = mListenSocket; 57 | ret = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mListenSocket, &ev); 58 | if (ret < 0) 59 | return false; 60 | 61 | memset(&serveraddr, 0, sizeof(sockaddr_in)); 62 | socklen_t len = sizeof(serveraddr); 63 | ret = getsockname(mListenSocket, (sockaddr*)&serveraddr, &len); 64 | if (ret < 0) 65 | return false; 66 | 67 | listenPort = ntohs(serveraddr.sin_port); 68 | 69 | return true; 70 | 71 | } 72 | 73 | void ClientManager::EventLoop() 74 | { 75 | epoll_event events[MAX_CONNECTION]; 76 | 77 | while (true) 78 | { 79 | int nfd = epoll_wait(mEpollFd, events, MAX_CONNECTION, POLL_INTERVAL); 80 | 81 | for (int i = 0; i < nfd; ++i) 82 | { 83 | if (events[i].data.fd == mListenSocket) 84 | { 85 | sockaddr_in clientAddr; 86 | socklen_t clientAddrLen = sizeof(sockaddr_in); 87 | 88 | SOCKET client = accept(mListenSocket, (sockaddr *)&clientAddr, &clientAddrLen); 89 | if (client < 0) 90 | { 91 | GConsoleLog->PrintOut(true, "accept error: IP=%s, PORT=%d\n", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port)); 92 | continue; 93 | } 94 | 95 | auto newClient = CreateClient(client); 96 | newClient->OnConnect(&clientAddr); 97 | 98 | epoll_event ev; 99 | memset(&ev, 0, sizeof(ev)); 100 | ev.events = EPOLLIN | EPOLLET; 101 | ev.data.fd = client; 102 | epoll_ctl(mEpollFd, EPOLL_CTL_ADD, client, &ev); 103 | } 104 | else 105 | { 106 | SOCKET client = events[i].data.fd; 107 | auto session = mClientList[client]; 108 | session->OnReceive(); 109 | } 110 | } 111 | 112 | FlushClientSend(); 113 | 114 | /// scheduled jobs 115 | GScheduler->DoTasks(); 116 | 117 | } 118 | 119 | } 120 | 121 | std::shared_ptr ClientManager::CreateClient(SOCKET sock) 122 | { 123 | auto client = std::make_shared(sock); 124 | mClientList.insert(ClientList::value_type(sock, client)) ; 125 | 126 | return client ; 127 | } 128 | 129 | void ClientManager::DeleteClient(std::shared_ptr client) 130 | { 131 | epoll_event ev; 132 | memset(&ev, 0, sizeof(ev)); 133 | epoll_ctl(mEpollFd, EPOLL_CTL_DEL, client->mSocket, &ev); 134 | 135 | mClientList.erase(client->mSocket); 136 | } 137 | 138 | 139 | void ClientManager::FlushClientSend() 140 | { 141 | for (auto& it : mClientList) 142 | { 143 | auto client = it.second; 144 | if (false == client->SendFlush()) 145 | { 146 | client->Disconnect(); 147 | } 148 | } 149 | } 150 | 151 | -------------------------------------------------------------------------------- /GameLiftLinuxServer/ClientManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ClientSession.h" 4 | 5 | class ClientManager 6 | { 7 | public: 8 | ClientManager() : mEpollFd(-1), mListenSocket(-1) 9 | {} 10 | 11 | bool Initialize(int& listenPort); 12 | 13 | std::shared_ptr CreateClient(SOCKET sock); 14 | void DeleteClient(std::shared_ptr client); 15 | 16 | void EventLoop(); 17 | 18 | void FlushClientSend(); 19 | 20 | 21 | private: 22 | typedef std::map> ClientList; 23 | ClientList mClientList; 24 | 25 | SOCKET mEpollFd; 26 | SOCKET mListenSocket; 27 | } ; 28 | 29 | extern std::unique_ptr GClientManager; 30 | -------------------------------------------------------------------------------- /GameLiftLinuxServer/ClientSession.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "Config.h" 9 | #include "../PacketShare/PacketType.h" 10 | #include "CircularBuffer.h" 11 | 12 | 13 | typedef int SOCKET; 14 | 15 | class ClientSession; 16 | class ClientManager; 17 | 18 | 19 | class ClientSession : public std::enable_shared_from_this 20 | { 21 | public: 22 | ClientSession(SOCKET sock) 23 | : mConnected(false), mLogon(false), mSocket(sock), mSendBuffer(BUFSIZE), mRecvBuffer(BUFSIZE) 24 | { 25 | memset(&mClientAddr, 0, sizeof(sockaddr_in)); 26 | } 27 | 28 | virtual ~ClientSession(); 29 | 30 | void OnConnect(sockaddr_in* addr); 31 | void OnDisconnect(); 32 | void Disconnect(); 33 | 34 | void OnReceive(); 35 | 36 | bool SendRequest(PacketHeader* pkt); 37 | bool SendFlush(); 38 | 39 | public: 40 | 41 | bool IsValid() { return mPlayerSessionId.length() > 0; } 42 | 43 | void PlayerLogin(const std::string& playerId); 44 | void PlayerLogout(const std::string& playerId); 45 | 46 | 47 | public: 48 | bool IsConnected() const { return mConnected; } 49 | void OnTick(); 50 | 51 | 52 | template 53 | bool ParsePacket(PKT_TYPE& pkt) 54 | { 55 | return mRecvBuffer.Read((char*)&pkt, pkt.mSize); 56 | } 57 | 58 | void DispatchPacket(); 59 | void EchoBack(); 60 | 61 | private: 62 | 63 | std::string mPlayerSessionId; 64 | 65 | bool mConnected; 66 | bool mLogon; 67 | SOCKET mSocket; 68 | 69 | sockaddr_in mClientAddr; 70 | 71 | CircularBuffer mSendBuffer; 72 | CircularBuffer mRecvBuffer; 73 | 74 | friend class ClientManager; 75 | }; 76 | 77 | 78 | -------------------------------------------------------------------------------- /GameLiftLinuxServer/Config.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeliard/GameLift/4bdb482097cac9e362701732bff74e4398a1c174/GameLiftLinuxServer/Config.h -------------------------------------------------------------------------------- /GameLiftLinuxServer/GameLiftManager.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Log.h" 3 | #include "../PacketShare/PacketType.h" 4 | #include "GameLiftManager.h" 5 | #include "ClientSession.h" 6 | 7 | 8 | std::unique_ptr GGameLiftManager(nullptr); 9 | 10 | GameLiftManager::GameLiftManager() : mActivated(false), mAcceptedCount(0), mRemovedCount(0) 11 | { 12 | } 13 | 14 | bool GameLiftManager::InitializeGameLift(int listenPort) 15 | { 16 | auto initOutcome = Aws::GameLift::Server::InitSDK(); 17 | 18 | if (!initOutcome.IsSuccess()) 19 | return false; 20 | 21 | std::string serverOut("./logs/serverOut.log"); 22 | std::string serverErr("./logs/serverErr.log"); 23 | std::vector logPaths; 24 | logPaths.push_back(serverOut); 25 | logPaths.push_back(serverErr); 26 | 27 | auto processReadyParameter = Aws::GameLift::Server::ProcessParameters( 28 | std::bind(&GameLiftManager::OnStartGameSession, this, std::placeholders::_1), 29 | std::bind(&GameLiftManager::OnProcessTerminate, this), 30 | std::bind(&GameLiftManager::OnHealthCheck, this), 31 | listenPort, Aws::GameLift::Server::LogParameters(logPaths) 32 | ); 33 | 34 | auto readyOutcome = Aws::GameLift::Server::ProcessReady(processReadyParameter); 35 | 36 | if (!readyOutcome.IsSuccess()) 37 | return false; 38 | 39 | mActivated = true; 40 | 41 | mAcceptedCount = 0; 42 | mRemovedCount = 0; 43 | 44 | GConsoleLog->PrintOut(true, "[GAMELIFT] ProcessReady Success\n"); 45 | return true; 46 | } 47 | 48 | 49 | void GameLiftManager::FinalizeGameLift() 50 | { 51 | Aws::GameLift::Server::Destroy(); 52 | } 53 | 54 | bool GameLiftManager::AcceptPlayerSession(std::shared_ptr psess, const std::string& playerSessionId) 55 | { 56 | 57 | auto outcome = Aws::GameLift::Server::AcceptPlayerSession(playerSessionId); 58 | 59 | if (outcome.IsSuccess()) 60 | { 61 | ++mAcceptedCount; 62 | mPlayerSessions.insert(psess); 63 | return true; 64 | } 65 | 66 | GConsoleLog->PrintOut(true, "[GAMELIFT] AcceptPlayerSession Fail: %s\n", outcome.GetError().GetErrorMessage().c_str()); 67 | 68 | return false; 69 | } 70 | 71 | void GameLiftManager::RemovePlayerSession(std::shared_ptr psess, const std::string& playerSessionId) 72 | { 73 | 74 | auto outcome = Aws::GameLift::Server::RemovePlayerSession(playerSessionId); 75 | if (outcome.IsSuccess()) 76 | { 77 | mPlayerSessions.erase(psess); 78 | ++mRemovedCount; 79 | } 80 | else 81 | { 82 | GConsoleLog->PrintOut(true, "[GAMELIFT] RemovePlayerSession Fail: %d %s\n", 83 | outcome.GetError().GetErrorType(), 84 | outcome.GetError().GetErrorName().c_str()); 85 | } 86 | 87 | CheckTerminateGameSession(); 88 | } 89 | 90 | void GameLiftManager::OnStartGameSession(Aws::GameLift::Server::Model::GameSession myGameSession) 91 | { 92 | Aws::GameLift::Server::ActivateGameSession(); 93 | 94 | GConsoleLog->PrintOut(true, "[GAMELIFT] OnStartGameSession Success\n"); 95 | } 96 | 97 | void GameLiftManager::OnProcessTerminate() 98 | { 99 | 100 | // game-specific tasks required to gracefully shut down a game session, 101 | // such as notifying players, preserving game state data, and other cleanup 102 | 103 | Aws::GameLift::Server::TerminateGameSession(); 104 | 105 | Aws::GameLift::Server::ProcessEnding(); 106 | 107 | mActivated = false; 108 | 109 | GConsoleLog->PrintOut(true, "[GAMELIFT] OnProcessTerminate Success\n"); 110 | } 111 | 112 | void GameLiftManager::CheckTerminateGameSession() 113 | { 114 | // accepted full, but no ones here 115 | if (mAcceptedCount >= MAX_PLAYER_PER_GAME && mRemovedCount >= MAX_PLAYER_PER_GAME) 116 | { 117 | GConsoleLog->PrintOut(true, "[GAMELIFT] Terminate GameSession\n"); 118 | 119 | Aws::GameLift::Server::TerminateGameSession(); 120 | 121 | Aws::GameLift::Server::ProcessEnding(); 122 | mActivated = false; 123 | 124 | } 125 | } 126 | 127 | void GameLiftManager::BroadcastMessage(PacketHeader* pkt) 128 | { 129 | for (auto& it : mPlayerSessions) 130 | { 131 | if (false == it->SendRequest(pkt)) 132 | { 133 | it->Disconnect(); 134 | } 135 | } 136 | 137 | } -------------------------------------------------------------------------------- /GameLiftLinuxServer/GameLiftManager.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | 7 | struct PacketHeader; 8 | class GameSession; 9 | class ClientSession; 10 | 11 | class GameLiftManager 12 | { 13 | public: 14 | GameLiftManager(); 15 | 16 | bool InitializeGameLift(int listenPort); 17 | void FinalizeGameLift(); 18 | 19 | bool AcceptPlayerSession(std::shared_ptr psess, const std::string& playerSessionId); 20 | void RemovePlayerSession(std::shared_ptr psess, const std::string& playerSessionId); 21 | 22 | void OnStartGameSession(Aws::GameLift::Server::Model::GameSession myGameSession); 23 | 24 | void OnProcessTerminate(); 25 | 26 | bool OnHealthCheck() { return mActivated; } 27 | 28 | void BroadcastMessage(PacketHeader* pkt); ///< proxy for a game session 29 | 30 | private: 31 | void CheckTerminateGameSession(); 32 | 33 | private: 34 | 35 | bool mActivated; 36 | int mAcceptedCount; ///< player accepted count after game-session started 37 | int mRemovedCount; ///< player removed count 38 | 39 | std::set> mPlayerSessions; 40 | }; 41 | 42 | extern std::unique_ptr GGameLiftManager; -------------------------------------------------------------------------------- /GameLiftLinuxServer/Log.cpp: -------------------------------------------------------------------------------- 1 | #include "Log.h" 2 | 3 | #include 4 | #include 5 | 6 | ConsoleLog::ConsoleLog(const char* filename) 7 | { 8 | mLogFileStream.open(filename, std::ofstream::out); 9 | } 10 | 11 | ConsoleLog::~ConsoleLog() 12 | { 13 | mLogFileStream.close(); 14 | } 15 | 16 | void ConsoleLog::PrintOut(bool fileOut, const char* fmt, ...) 17 | { 18 | 19 | char buf[128] = {}; 20 | 21 | va_list args; 22 | va_start(args, fmt); 23 | vsprintf(buf, fmt, args); 24 | va_end(args); 25 | 26 | printf("%s", buf); 27 | 28 | if (fileOut) 29 | { 30 | mLogFileStream << buf; 31 | mLogFileStream.flush(); 32 | } 33 | } 34 | 35 | std::unique_ptr GConsoleLog(nullptr); 36 | 37 | -------------------------------------------------------------------------------- /GameLiftLinuxServer/Log.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "Utils.h" 6 | 7 | class ConsoleLog 8 | { 9 | public: 10 | ConsoleLog(const char* filename); 11 | ~ConsoleLog(); 12 | 13 | void PrintOut(bool fileOut, const char* fmt, ...); 14 | 15 | private: 16 | 17 | std::ofstream mLogFileStream; 18 | }; 19 | 20 | extern std::unique_ptr GConsoleLog; 21 | -------------------------------------------------------------------------------- /GameLiftLinuxServer/PacketHandler.cpp: -------------------------------------------------------------------------------- 1 | #include "Log.h" 2 | #include "../PacketShare/PacketType.h" 3 | #include "ClientSession.h" 4 | #include "GameLiftManager.h" 5 | 6 | 7 | //@{ Handler Helper 8 | 9 | typedef std::shared_ptr ClientSessionPtr; 10 | 11 | typedef void(*HandlerFunc)(ClientSessionPtr session); 12 | 13 | static HandlerFunc HandlerTable[PKT_MAX]; 14 | 15 | static void DefaultHandler(ClientSessionPtr session) 16 | { 17 | GConsoleLog->PrintOut(true, "Invalid packet handler"); 18 | session->Disconnect(); 19 | } 20 | 21 | struct InitializeHandlers 22 | { 23 | InitializeHandlers() 24 | { 25 | for (int i = 0; i < PKT_MAX; ++i) 26 | HandlerTable[i] = DefaultHandler; 27 | } 28 | } _init_handlers_; 29 | 30 | struct RegisterHandler 31 | { 32 | RegisterHandler(int pktType, HandlerFunc handler) 33 | { 34 | HandlerTable[pktType] = handler; 35 | } 36 | }; 37 | 38 | #define REGISTER_HANDLER(PKT_TYPE) \ 39 | static void Handler_##PKT_TYPE(ClientSessionPtr session); \ 40 | static RegisterHandler _register_##PKT_TYPE(PKT_TYPE, Handler_##PKT_TYPE); \ 41 | static void Handler_##PKT_TYPE(ClientSessionPtr session) 42 | 43 | //@} 44 | 45 | /////////////////////////////////////////////////////////// 46 | 47 | void ClientSession::DispatchPacket() 48 | { 49 | /// packet parsing 50 | while (true) 51 | { 52 | /// read packet header 53 | PacketHeader header; 54 | if (false == mRecvBuffer.Peek((char*)&header, sizeof(PacketHeader))) 55 | return; 56 | 57 | /// packet completed? 58 | if (mRecvBuffer.GetStoredSize() < (size_t)header.mSize) 59 | return; 60 | 61 | if (header.mType >= PKT_MAX || header.mType <= PKT_NONE) 62 | { 63 | GConsoleLog->PrintOut(true, "Invalid packet type\n"); 64 | Disconnect(); 65 | return; 66 | } 67 | 68 | /// packet dispatch... 69 | HandlerTable[header.mType](shared_from_this()); 70 | } 71 | } 72 | 73 | ///////////////////////////////////////////////////////// 74 | REGISTER_HANDLER(PKT_CS_LOGIN) 75 | { 76 | LoginRequest inPacket; 77 | if (false == session->ParsePacket(inPacket)) 78 | { 79 | GConsoleLog->PrintOut(true, "packet parsing error, Type: %d\n", inPacket.mType); 80 | return; 81 | } 82 | 83 | session->PlayerLogin(std::string(inPacket.mPlayerId)); 84 | } 85 | 86 | 87 | REGISTER_HANDLER(PKT_CS_EXIT) 88 | { 89 | ExitRequest inPacket; 90 | if (false == session->ParsePacket(inPacket)) 91 | { 92 | GConsoleLog->PrintOut(true, "packet parsing error: %d\n", inPacket.mType); 93 | return; 94 | } 95 | 96 | session->PlayerLogout(std::string(inPacket.mPlayerId)); 97 | 98 | } 99 | 100 | REGISTER_HANDLER(PKT_CS_CHAT) 101 | { 102 | ChatBroadcastRequest inPacket; 103 | if (false == session->ParsePacket(inPacket)) 104 | { 105 | GConsoleLog->PrintOut(true, "[DEBUG] packet parsing error, Type: %d\n", inPacket.mType); 106 | return; 107 | } 108 | 109 | /// direct response in case of chatting 110 | ChatBroadcastResult outPacket; 111 | 112 | strcpy(outPacket.mPlayerId, inPacket.mPlayerId); 113 | strcpy(outPacket.mChat, inPacket.mChat); 114 | 115 | GGameLiftManager->BroadcastMessage(&outPacket); 116 | } 117 | 118 | 119 | REGISTER_HANDLER(PKT_CS_MOVE) 120 | { 121 | MoveRequest inPacket; 122 | if (false == session->ParsePacket(inPacket)) 123 | { 124 | GConsoleLog->PrintOut(true, "[DEBUG] packet parsing error, Type: %d\n", inPacket.mType); 125 | return; 126 | } 127 | 128 | /// just broadcast for now 129 | MoveBroadcastResult outPacket; 130 | outPacket.mPlayerIdx = inPacket.mPlayerIdx; 131 | outPacket.mPosX = inPacket.mPosX; 132 | outPacket.mPosY = inPacket.mPosY; 133 | 134 | GGameLiftManager->BroadcastMessage(&outPacket); 135 | } 136 | 137 | 138 | 139 | 140 | 141 | 142 | -------------------------------------------------------------------------------- /GameLiftLinuxServer/Scheduler.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "Scheduler.h" 3 | #include "ClientSession.h" 4 | 5 | std::unique_ptr GScheduler(nullptr); 6 | 7 | Scheduler::Scheduler() 8 | { 9 | mBeginTickPoint = Clock::now(); 10 | mCurrentTick = GetCurrentTick(); 11 | } 12 | 13 | void Scheduler::PushTask(SessionPtr owner, Task&& task, uint32_t after) 14 | { 15 | int64_t dueTimeTick = after + mCurrentTick; 16 | 17 | mTaskQueue.push(JobElement(owner, std::move(task), dueTimeTick)); 18 | } 19 | 20 | 21 | void Scheduler::DoTasks() 22 | { 23 | /// tick update 24 | mCurrentTick = GetCurrentTick(); 25 | 26 | while (!mTaskQueue.empty()) 27 | { 28 | JobElement timerJobElem = mTaskQueue.top(); 29 | 30 | if (mCurrentTick < timerJobElem.mExecutionTick) 31 | break; 32 | 33 | /// do task! 34 | timerJobElem.mTask(); 35 | 36 | mTaskQueue.pop(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /GameLiftLinuxServer/Scheduler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "Utils.h" 9 | 10 | class ClientSession; 11 | typedef std::function Task; 12 | typedef std::shared_ptr SessionPtr; 13 | 14 | struct JobElement 15 | { 16 | JobElement(SessionPtr owner, Task&& task, int64_t execTick) 17 | : mOwner(owner), mTask(std::move(task)), mExecutionTick(execTick) 18 | {} 19 | 20 | SessionPtr mOwner; 21 | Task mTask; 22 | int64_t mExecutionTick; 23 | }; 24 | 25 | struct JobComparator 26 | { 27 | bool operator()(const JobElement& lhs, const JobElement& rhs) 28 | { 29 | return lhs.mExecutionTick > rhs.mExecutionTick; 30 | } 31 | }; 32 | 33 | 34 | typedef std::priority_queue, JobComparator> TaskPriorityQueue; 35 | 36 | class Scheduler 37 | { 38 | public: 39 | using Clock = std::chrono::high_resolution_clock; 40 | Scheduler(); 41 | 42 | void PushTask(SessionPtr owner, Task&& task, uint32_t after); 43 | 44 | void DoTasks(); 45 | 46 | private: 47 | int64_t GetCurrentTick() 48 | { 49 | return std::chrono::duration_cast(Clock::now() - mBeginTickPoint).count(); 50 | } 51 | 52 | TaskPriorityQueue mTaskQueue; 53 | Clock::time_point mBeginTickPoint; 54 | int64_t mCurrentTick; 55 | }; 56 | 57 | extern std::unique_ptr GScheduler; 58 | 59 | template 60 | void CallFuncAfter(uint32_t after, T instance, F memfunc, Args&&... args) 61 | { 62 | static_assert(true == is_shared_ptr::value, "T should be shared_ptr"); 63 | 64 | GScheduler->PushTask(instance, std::bind(memfunc, instance, std::forward(args)...), after); 65 | } 66 | -------------------------------------------------------------------------------- /GameLiftLinuxServer/Utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | inline void CRASH_ASSERT(bool isOk) 4 | { 5 | if ( isOk ) 6 | return; 7 | 8 | int* crashVal = 0; 9 | *crashVal = 0xDEADBEEF; 10 | } 11 | 12 | template 13 | struct is_shared_ptr 14 | { 15 | const static bool value = false; 16 | }; 17 | 18 | template 19 | struct is_shared_ptr > 20 | { 21 | const static bool value = true; 22 | }; 23 | 24 | template 25 | struct is_shared_ptr > 26 | { 27 | const static bool value = true; 28 | }; 29 | 30 | template 31 | struct is_shared_ptr > 32 | { 33 | const static bool value = true; 34 | }; 35 | 36 | template 37 | struct is_shared_ptr > 38 | { 39 | const static bool value = true; 40 | }; 41 | 42 | -------------------------------------------------------------------------------- /GameLiftLinuxServer/build/upload/logs/serverErr.out: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /GameLiftLinuxServer/build/upload/logs/serverLog.out: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /GameLiftLinuxServer/build/upload/logs/serverLog.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /GameLiftLinuxServer/include/aws/gamelift/common/GameLift_EXPORTS.h: -------------------------------------------------------------------------------- 1 | /* 2 | * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or 3 | * its licensors. 4 | * 5 | * For complete copyright and license terms please see the LICENSE at the root of this 6 | * distribution (the "License"). All use of this software is governed by the License, 7 | * or, if provided, by the license below or the license accompanying this file. Do not 8 | * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * 11 | */ 12 | #pragma once 13 | 14 | #include 15 | #include 16 | 17 | #ifdef _WIN32 18 | //disable windows complaining about max template size. 19 | #pragma warning (disable : 4503) 20 | #endif 21 | 22 | #if defined (_MSC_VER) 23 | #pragma warning(disable : 4251) 24 | #ifdef USE_IMPORT_EXPORT 25 | #ifdef AWS_GAMELIFT_EXPORTS 26 | #define AWS_GAMELIFT_API __declspec(dllexport) 27 | #else 28 | #define AWS_GAMELIFT_API __declspec(dllimport) 29 | #endif /* AWS_GAMELIFT_EXPORTS */ 30 | #else 31 | #define AWS_GAMELIFT_API 32 | #endif // 33 | #else /* defined (_WIN32) */ 34 | #define AWS_GAMELIFT_API 35 | #endif -------------------------------------------------------------------------------- /GameLiftLinuxServer/include/aws/gamelift/internal/GameLiftCommonState.h: -------------------------------------------------------------------------------- 1 | /* 2 | * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or 3 | * its licensors. 4 | * 5 | * For complete copyright and license terms please see the LICENSE at the root of this 6 | * distribution (the "License"). All use of this software is governed by the License, 7 | * or, if provided, by the license below or the license accompanying this file. Do not 8 | * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * 11 | */ 12 | #pragma once 13 | 14 | #include 15 | #include 16 | 17 | namespace Aws 18 | { 19 | namespace GameLift 20 | { 21 | namespace Internal 22 | { 23 | enum class GAMELIFT_INTERNAL_STATE_TYPE { 24 | CLIENT, 25 | SERVER 26 | }; 27 | 28 | class GameLiftCommonState; 29 | 30 | typedef Aws::GameLift::Outcome GetInstanceOutcome; 31 | 32 | class GameLiftCommonState 33 | { 34 | public: 35 | 36 | static GetInstanceOutcome GetInstance(); 37 | 38 | static GetInstanceOutcome GetInstance(GAMELIFT_INTERNAL_STATE_TYPE stateType); 39 | 40 | static GenericOutcome SetInstance(GameLiftCommonState* instance); 41 | 42 | static GenericOutcome DestroyInstance(); 43 | 44 | virtual GAMELIFT_INTERNAL_STATE_TYPE GetStateType() = 0; 45 | 46 | //Normally this should not be public, but AwsMemory needs access to it 47 | virtual ~GameLiftCommonState(); 48 | 49 | protected: 50 | 51 | GameLiftCommonState(); 52 | 53 | private: 54 | 55 | static GameLiftCommonState* m_instance; 56 | 57 | }; 58 | 59 | } //namespace Internal 60 | } //namespace GameLift 61 | } //namespace Aws 62 | -------------------------------------------------------------------------------- /GameLiftLinuxServer/include/aws/gamelift/internal/network/AuxProxyMessageHandler.h: -------------------------------------------------------------------------------- 1 | /* 2 | * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or 3 | * its licensors. 4 | * 5 | * For complete copyright and license terms please see the LICENSE at the root of this 6 | * distribution (the "License"). All use of this software is governed by the License, 7 | * or, if provided, by the license below or the license accompanying this file. Do not 8 | * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * 11 | */ 12 | #pragma once 13 | #include 14 | #include 15 | 16 | namespace Aws 17 | { 18 | namespace GameLift 19 | { 20 | namespace Internal 21 | { 22 | namespace Network 23 | { 24 | using namespace Aws::GameLift::Server::Model; 25 | 26 | class AuxProxyMessageHandler 27 | { 28 | public: 29 | virtual void OnStartGameSession(GameSession& gameSession, sio::message::list& ack_resp) = 0; 30 | virtual void OnTerminateProcess() = 0; 31 | }; 32 | } //namespace Network 33 | } //namespace Internal 34 | } //namespace GameLift 35 | } //namespace Aws 36 | -------------------------------------------------------------------------------- /GameLiftLinuxServer/include/aws/gamelift/internal/network/AuxProxyMessageSender.h: -------------------------------------------------------------------------------- 1 | /* 2 | * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or 3 | * its licensors. 4 | * 5 | * For complete copyright and license terms please see the LICENSE at the root of this 6 | * distribution (the "License"). All use of this software is governed by the License, 7 | * or, if provided, by the license below or the license accompanying this file. Do not 8 | * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * 11 | */ 12 | #pragma once 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #ifdef _WIN32 21 | #include 22 | #undef ERROR 23 | #undef SetPort // See http://answers.perforce.com/articles/KB/2638 24 | #endif 25 | 26 | namespace Aws 27 | { 28 | namespace GameLift 29 | { 30 | namespace Internal 31 | { 32 | namespace Network 33 | { 34 | using namespace Aws::GameLift::Server::Model; 35 | using namespace com::amazon::whitewater::auxproxy; 36 | 37 | class AuxProxyMessageSender 38 | { 39 | public: 40 | AuxProxyMessageSender(sio::client* sioClient); 41 | ~AuxProxyMessageSender(); 42 | GenericOutcome ProcessReady(int port, const Aws::GameLift::Server::LogParameters &logParameters); 43 | GenericOutcome ProcessEnding(); 44 | GenericOutcome ActivateGameSession(std::string gameSessionId); 45 | GenericOutcome TerminateGameSession(std::string gameSessionId); 46 | GenericOutcome UpdatePlayerSessionCreationPolicy(std::string gameSessionId, std::string newPlayerSessionPolicy); 47 | GenericOutcome AcceptPlayerSession(std::string playerSessionId, std::string gameSessionId); 48 | GenericOutcome RemovePlayerSession(std::string playerSessionId, std::string gameSessionId); 49 | DescribePlayerSessionsOutcome DescribePlayerSessions(const DescribePlayerSessionsRequest &describePlayerSessionsRequest); 50 | GenericOutcome ReportHealth(bool healthStatus); 51 | private: 52 | std::shared_ptr ParseMessage(google::protobuf::MessageLite* message); 53 | GenericOutcome EmitEvent(google::protobuf::MessageLite* message); 54 | DescribePlayerSessionsOutcome Call(pbuffer::DescribePlayerSessionsRequest* message); 55 | void Send(google::protobuf::MessageLite* message, std::function ackFunction); 56 | 57 | sio::client* m_sio_client; 58 | std::mutex m_lock; 59 | }; 60 | } //namespace Network 61 | } //namespace Internal 62 | } //namespace GameLift 63 | } //namespace Aws 64 | -------------------------------------------------------------------------------- /GameLiftLinuxServer/include/aws/gamelift/internal/network/Network.h: -------------------------------------------------------------------------------- 1 | /* 2 | * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or 3 | * its licensors. 4 | * 5 | * For complete copyright and license terms please see the LICENSE at the root of this 6 | * distribution (the "License"). All use of this software is governed by the License, 7 | * or, if provided, by the license below or the license accompanying this file. Do not 8 | * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * 11 | */ 12 | #pragma once 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define MAIN_PID "MAIN_PID" 20 | 21 | namespace Aws 22 | { 23 | namespace GameLift 24 | { 25 | namespace Internal 26 | { 27 | namespace Network 28 | { 29 | class Network 30 | { 31 | public: 32 | Network(sio::client* sioClient, AuxProxyMessageHandler* handler, AuxProxyMessageSender* sender); 33 | 34 | ~Network(); 35 | 36 | void OnConnected(); 37 | void OnFail(); 38 | void OnClose(sio::client::close_reason const& reason); 39 | 40 | void OnStartGameSession(std::string const& name, sio::message::ptr const& data, bool hasAck, sio::message::list &ack_resp); 41 | void OnTerminateProcess(std::string const& name, sio::message::ptr const& data, bool hasAck, sio::message::list &ack_resp); 42 | 43 | AuxProxyMessageSender* getAuxProxySender() { return m_sender; }; 44 | 45 | private: 46 | Aws::GameLift::Server::Model::GameSession ParseFromBufferedGameSession(com::amazon::whitewater::auxproxy::pbuffer::GameSession bGameSession); 47 | sio::client* m_sio_client; 48 | AuxProxyMessageHandler* m_handler; 49 | AuxProxyMessageSender* m_sender; 50 | 51 | bool m_connect_finish; 52 | std::mutex m_lock; 53 | std::condition_variable_any m_cond; 54 | }; 55 | } //namespace Network 56 | } //namespace Internal 57 | } //namespace GameLift 58 | } //namespace Aws 59 | -------------------------------------------------------------------------------- /GameLiftLinuxServer/include/aws/gamelift/server/LogParameters.h: -------------------------------------------------------------------------------- 1 | /* 2 | * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or 3 | * its licensors. 4 | * 5 | * For complete copyright and license terms please see the LICENSE at the root of this 6 | * distribution (the "License"). All use of this software is governed by the License, 7 | * or, if provided, by the license below or the license accompanying this file. Do not 8 | * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * 11 | */ 12 | #pragma once 13 | 14 | #include 15 | 16 | #ifndef GAMELIFT_USE_STD 17 | #ifndef MAX_LOG_PATHS 18 | #define MAX_LOG_PATHS 10 19 | #endif 20 | #ifndef MAX_PATH_LENGTH 21 | #define MAX_PATH_LENGTH 1024 22 | #endif 23 | #endif 24 | 25 | namespace Aws 26 | { 27 | namespace GameLift 28 | { 29 | namespace Server 30 | { 31 | class LogParameters 32 | { 33 | #ifdef GAMELIFT_USE_STD 34 | public: 35 | AWS_GAMELIFT_API LogParameters() {} 36 | AWS_GAMELIFT_API LogParameters(const std::vector &logPaths) : m_logPaths(logPaths){} 37 | 38 | AWS_GAMELIFT_API std::vector getLogPaths() const { return m_logPaths; } 39 | 40 | private: 41 | std::vector m_logPaths; 42 | }; 43 | #else 44 | public: 45 | AWS_GAMELIFT_API LogParameters() : m_count(0) {} 46 | AWS_GAMELIFT_API LogParameters(const char** logPaths, int count); 47 | 48 | AWS_GAMELIFT_API int getLogPathCount() const { return m_count; } 49 | AWS_GAMELIFT_API const char* getLogPath(int index) const { return index < m_count ? m_logPaths[index] : nullptr; } 50 | 51 | private: 52 | char m_logPaths[MAX_LOG_PATHS][MAX_PATH_LENGTH]; 53 | int m_count; 54 | }; 55 | #endif 56 | } // namespace Server 57 | } // namespace GameLift 58 | } // namespace Aws 59 | 60 | -------------------------------------------------------------------------------- /GameLiftLinuxServer/include/aws/gamelift/server/model/GameProperty.h: -------------------------------------------------------------------------------- 1 | /* 2 | * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or 3 | * its licensors. 4 | * 5 | * For complete copyright and license terms please see the LICENSE at the root of this 6 | * distribution (the "License"). All use of this software is governed by the License, 7 | * or, if provided, by the license below or the license accompanying this file. Do not 8 | * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * 11 | */ 12 | #pragma once 13 | #include 14 | 15 | #ifndef GAMELIFT_USE_STD 16 | #ifndef MAX_KEY_LENGTH 17 | #define MAX_KEY_LENGTH 256 18 | #endif 19 | #ifndef MAX_VALUE_LENGTH 20 | #define MAX_VALUE_LENGTH 256 21 | #endif 22 | #endif 23 | 24 | namespace Aws 25 | { 26 | namespace GameLift 27 | { 28 | namespace Server 29 | { 30 | namespace Model 31 | { 32 | 33 | /** 34 | *

Set of key-value pairs containing information your game server requires to 35 | * set up sessions. This object allows you to pass in any set of data needed for 36 | * your game. For more information, see the Amazon 38 | * GameLift Developer Guide.

39 | */ 40 | class AWS_GAMELIFT_API GameProperty 41 | { 42 | #ifdef GAMELIFT_USE_STD 43 | public: 44 | GameProperty(){} 45 | 46 | 47 | inline const std::string& GetKey() const{ return m_key; } 48 | 49 | 50 | inline void SetKey(const std::string& value) { m_key = value; } 51 | 52 | 53 | inline void SetKey(std::string&& value) { m_key = value; } 54 | 55 | 56 | inline void SetKey(const char* value) { m_key.assign(value); } 57 | 58 | 59 | inline GameProperty& WithKey(const std::string& value) { SetKey(value); return *this; } 60 | 61 | 62 | inline GameProperty& WithKey(std::string&& value) { SetKey(value); return *this; } 63 | 64 | 65 | inline GameProperty& WithKey(const char* value) { SetKey(value); return *this; } 66 | 67 | 68 | inline const std::string& GetValue() const{ return m_value; } 69 | 70 | 71 | inline void SetValue(const std::string& value) { m_value = value; } 72 | 73 | 74 | inline void SetValue(std::string&& value) { m_value = value; } 75 | 76 | 77 | inline void SetValue(const char* value) { m_value.assign(value); } 78 | 79 | 80 | inline GameProperty& WithValue(const std::string& value) { SetValue(value); return *this; } 81 | 82 | 83 | inline GameProperty& WithValue(std::string&& value) { SetValue(value); return *this; } 84 | 85 | 86 | inline GameProperty& WithValue(const char* value) { SetValue(value); return *this; } 87 | 88 | private: 89 | std::string m_key; 90 | std::string m_value; 91 | #else 92 | public: 93 | GameProperty() 94 | { 95 | memset(m_key, 0, MAX_KEY_LENGTH); 96 | memset(m_value, 0, MAX_VALUE_LENGTH); 97 | } 98 | 99 | 100 | inline const char* GetKey() const{ return m_key; } 101 | 102 | 103 | inline void SetKey(const char* value) { strcpy(m_key, value); } 104 | 105 | 106 | inline GameProperty& WithKey(const char* value) { SetKey(value); return *this; } 107 | 108 | 109 | inline const char* GetValue() const{ return m_value; } 110 | 111 | 112 | inline void SetValue(const char* value) { strcpy(m_value, value); } 113 | 114 | 115 | inline GameProperty& WithValue(const char* value) { SetValue(value); return *this; } 116 | 117 | private: 118 | char m_key[MAX_KEY_LENGTH]; 119 | char m_value[MAX_VALUE_LENGTH]; 120 | #endif 121 | }; 122 | 123 | } // namespace Model 124 | } // namespace Server 125 | } // namespace GameLift 126 | } // namespace Aws 127 | -------------------------------------------------------------------------------- /GameLiftLinuxServer/include/aws/gamelift/server/model/GameSessionStatus.h: -------------------------------------------------------------------------------- 1 | /* 2 | * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or 3 | * its licensors. 4 | * 5 | * For complete copyright and license terms please see the LICENSE at the root of this 6 | * distribution (the "License"). All use of this software is governed by the License, 7 | * or, if provided, by the license below or the license accompanying this file. Do not 8 | * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * 11 | */ 12 | #pragma once 13 | #include 14 | 15 | namespace Aws 16 | { 17 | namespace GameLift 18 | { 19 | namespace Server 20 | { 21 | namespace Model 22 | { 23 | enum class GameSessionStatus 24 | { 25 | NOT_SET, 26 | ACTIVE, 27 | ACTIVATING, 28 | TERMINATED, 29 | TERMINATING 30 | }; 31 | 32 | namespace GameSessionStatusMapper 33 | { 34 | #ifdef GAMELIFT_USE_STD 35 | AWS_GAMELIFT_API GameSessionStatus GetGameSessionStatusForName(const std::string& name); 36 | AWS_GAMELIFT_API std::string GetNameForGameSessionStatus(GameSessionStatus value); 37 | #else 38 | AWS_GAMELIFT_API GameSessionStatus GetGameSessionStatusForName(const char* name); 39 | AWS_GAMELIFT_API const char* GetNameForGameSessionStatus(GameSessionStatus value); 40 | #endif 41 | } // namespace GameSessionStatusMapper 42 | } // namespace Model 43 | } // namespace Server 44 | } // namespace GameLift 45 | } // namespace Aws 46 | -------------------------------------------------------------------------------- /GameLiftLinuxServer/include/aws/gamelift/server/model/PlayerSessionCreationPolicy.h: -------------------------------------------------------------------------------- 1 | /* 2 | * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or 3 | * its licensors. 4 | * 5 | * For complete copyright and license terms please see the LICENSE at the root of this 6 | * distribution (the "License"). All use of this software is governed by the License, 7 | * or, if provided, by the license below or the license accompanying this file. Do not 8 | * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * 11 | */ 12 | #pragma once 13 | #include 14 | 15 | namespace Aws 16 | { 17 | namespace GameLift 18 | { 19 | namespace Server 20 | { 21 | namespace Model 22 | { 23 | enum class PlayerSessionCreationPolicy 24 | { 25 | NOT_SET, 26 | ACCEPT_ALL, 27 | DENY_ALL 28 | }; 29 | 30 | namespace PlayerSessionCreationPolicyMapper { 31 | #ifdef GAMELIFT_USE_STD 32 | inline AWS_GAMELIFT_API PlayerSessionCreationPolicy GetPlayerSessionCreationPolicyForName(const std::string& name) 33 | { 34 | if (name == "ACCEPT_ALL") { 35 | return PlayerSessionCreationPolicy::ACCEPT_ALL; 36 | } 37 | if (name == "DENY_ALL") { 38 | return PlayerSessionCreationPolicy::DENY_ALL; 39 | } 40 | return PlayerSessionCreationPolicy::NOT_SET; 41 | } 42 | 43 | inline AWS_GAMELIFT_API std::string GetNameForPlayerSessionCreationPolicy(PlayerSessionCreationPolicy value) 44 | { 45 | switch (value) { 46 | case PlayerSessionCreationPolicy::ACCEPT_ALL: 47 | return "ACCEPT_ALL"; 48 | case PlayerSessionCreationPolicy::DENY_ALL: 49 | return "DENY_ALL"; 50 | default: 51 | return "NOT_SET"; 52 | } 53 | } 54 | #else 55 | inline AWS_GAMELIFT_API PlayerSessionCreationPolicy GetPlayerSessionCreationPolicyForName(const char* name) 56 | { 57 | if (strcmp(name, "ACCEPT_ALL") == 0) { 58 | return PlayerSessionCreationPolicy::ACCEPT_ALL; 59 | } 60 | if (strcmp(name, "DENY_ALL") == 0) { 61 | return PlayerSessionCreationPolicy::DENY_ALL; 62 | } 63 | return PlayerSessionCreationPolicy::NOT_SET; 64 | } 65 | 66 | inline AWS_GAMELIFT_API const char* GetNameForPlayerSessionCreationPolicy(PlayerSessionCreationPolicy value) 67 | { 68 | switch (value) { 69 | case PlayerSessionCreationPolicy::ACCEPT_ALL: 70 | return "ACCEPT_ALL"; 71 | case PlayerSessionCreationPolicy::DENY_ALL: 72 | return "DENY_ALL"; 73 | default: 74 | return "NOT_SET"; 75 | } 76 | } 77 | #endif 78 | } // namespace PlayerSessionCreationPolicyMapper 79 | } // namespace Model 80 | } // namespace Server 81 | } // namespace GameLift 82 | } // namespace Aws 83 | -------------------------------------------------------------------------------- /GameLiftLinuxServer/include/aws/gamelift/server/model/PlayerSessionStatus.h: -------------------------------------------------------------------------------- 1 | /* 2 | * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or 3 | * its licensors. 4 | * 5 | * For complete copyright and license terms please see the LICENSE at the root of this 6 | * distribution (the "License"). All use of this software is governed by the License, 7 | * or, if provided, by the license below or the license accompanying this file. Do not 8 | * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * 11 | */ 12 | #pragma once 13 | #include 14 | 15 | namespace Aws 16 | { 17 | namespace GameLift 18 | { 19 | namespace Server 20 | { 21 | namespace Model 22 | { 23 | enum class PlayerSessionStatus 24 | { 25 | NOT_SET, 26 | RESERVED, 27 | ACTIVE, 28 | COMPLETED, 29 | TIMEDOUT 30 | }; 31 | 32 | namespace PlayerSessionStatusMapper 33 | { 34 | #ifdef GAMELIFT_USE_STD 35 | inline AWS_GAMELIFT_API PlayerSessionStatus GetPlayerSessionStatusForName(const std::string& name) 36 | { 37 | if (name == "RESERVED") { 38 | return PlayerSessionStatus::RESERVED; 39 | } 40 | if (name == "ACTIVE") { 41 | return PlayerSessionStatus::ACTIVE; 42 | } 43 | if (name == "COMPLETED") { 44 | return PlayerSessionStatus::COMPLETED; 45 | } 46 | if (name == "TIMEDOUT") { 47 | return PlayerSessionStatus::TIMEDOUT; 48 | } 49 | return PlayerSessionStatus::NOT_SET; 50 | } 51 | inline AWS_GAMELIFT_API std::string GetNameForPlayerSessionStatus(PlayerSessionStatus value) 52 | { 53 | switch (value) { 54 | case PlayerSessionStatus::RESERVED: 55 | return "RESERVED"; 56 | case PlayerSessionStatus::ACTIVE: 57 | return "ACTIVE"; 58 | case PlayerSessionStatus::COMPLETED: 59 | return "COMPLETED"; 60 | case PlayerSessionStatus::TIMEDOUT: 61 | return "TIMEDOUT"; 62 | default: 63 | return "NOT_SET"; 64 | } 65 | } 66 | #else 67 | inline AWS_GAMELIFT_API PlayerSessionStatus GetPlayerSessionStatusForName(const char* name) 68 | { 69 | if (strcmp(name, "RESERVED") == 0) { 70 | return PlayerSessionStatus::RESERVED; 71 | } 72 | if (strcmp(name, "ACTIVE") == 0) { 73 | return PlayerSessionStatus::ACTIVE; 74 | } 75 | if (strcmp(name, "COMPLETED") == 0) { 76 | return PlayerSessionStatus::COMPLETED; 77 | } 78 | if (strcmp(name, "TIMEDOUT") == 0) { 79 | return PlayerSessionStatus::TIMEDOUT; 80 | } 81 | return PlayerSessionStatus::NOT_SET; 82 | } 83 | inline AWS_GAMELIFT_API const char* GetNameForPlayerSessionStatus(PlayerSessionStatus value) 84 | { 85 | switch (value) { 86 | case PlayerSessionStatus::RESERVED: 87 | return "RESERVED"; 88 | case PlayerSessionStatus::ACTIVE: 89 | return "ACTIVE"; 90 | case PlayerSessionStatus::COMPLETED: 91 | return "COMPLETED"; 92 | case PlayerSessionStatus::TIMEDOUT: 93 | return "TIMEDOUT"; 94 | default: 95 | return "NOT_SET"; 96 | } 97 | } 98 | #endif 99 | } // namespace GameSessionStatusMapper 100 | } // namespace Model 101 | } // namespace Server 102 | } // namespace GameLift 103 | } // namespace Aws 104 | -------------------------------------------------------------------------------- /GameLiftLinuxServer/lib/sdk_lib315_unzip_here.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeliard/GameLift/4bdb482097cac9e362701732bff74e4398a1c174/GameLiftLinuxServer/lib/sdk_lib315_unzip_here.zip -------------------------------------------------------------------------------- /GameLiftLinuxServer/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Config.h" 5 | #include "Log.h" 6 | #include "Scheduler.h" 7 | #include "ClientManager.h" 8 | #include "GameLiftManager.h" 9 | 10 | int main(int argc, char* argv[]) 11 | { 12 | int portNum = 0; 13 | /// listen port override rather than dynamic port by OS 14 | if (argc < 2) 15 | printf("Specify Listen Port Number. Or, it will be used dynamic port by OS\n"); 16 | else 17 | portNum = atoi(argv[1]); 18 | 19 | 20 | 21 | GConsoleLog.reset(new ConsoleLog("./logs/serverLog.txt")); 22 | 23 | /// GameLift 24 | GGameLiftManager.reset(new GameLiftManager); 25 | 26 | /// Managers 27 | GScheduler.reset(new Scheduler); 28 | GClientManager.reset(new ClientManager); 29 | 30 | /// bind and listen 31 | if (false == GClientManager->Initialize(portNum)) 32 | return -1; 33 | 34 | /// Gamelift init/start! 35 | #ifndef ECHO_MODE 36 | if (false == GGameLiftManager->InitializeGameLift(portNum)) 37 | return -1; 38 | #endif // !ECHO_MODE 39 | 40 | printf("Server Started...\n"); 41 | 42 | GClientManager->EventLoop(); ///< block here 43 | 44 | GGameLiftManager->FinalizeGameLift(); 45 | 46 | return 0; 47 | } -------------------------------------------------------------------------------- /GameLift_dist.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeliard/GameLift/4bdb482097cac9e362701732bff74e4398a1c174/GameLift_dist.pdf -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Seungmo Koo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PacketShare/PacketType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef WIN32 4 | #include 5 | #endif // !WIN32 6 | 7 | #define MAX_CHAT_LEN 128 8 | 9 | #define MAX_SESSION_LEN 128 10 | 11 | #define MAX_PLAYER_PER_GAME 8 12 | 13 | enum PacketTypes 14 | { 15 | PKT_NONE = 0, 16 | 17 | PKT_CS_LOGIN = 1, 18 | PKT_SC_LOGIN = 2, 19 | 20 | PKT_CS_CHAT = 11, 21 | PKT_SC_CHAT = 12, 22 | 23 | PKT_CS_MOVE = 21, 24 | PKT_SC_MOVE = 22, 25 | 26 | PKT_CS_EXIT = 31, 27 | 28 | PKT_MAX = 1024 29 | } ; 30 | 31 | #pragma pack(push, 1) 32 | 33 | struct PacketHeader 34 | { 35 | PacketHeader() : mSize(0), mType(PKT_NONE) {} 36 | short mSize ; 37 | short mType ; 38 | } ; 39 | 40 | 41 | 42 | struct LoginRequest : public PacketHeader 43 | { 44 | LoginRequest() 45 | { 46 | mSize = sizeof(LoginRequest) ; 47 | mType = PKT_CS_LOGIN ; 48 | memset(mPlayerId, 0, sizeof(mPlayerId)); 49 | } 50 | 51 | char mPlayerId[MAX_SESSION_LEN]; 52 | } ; 53 | 54 | struct LoginResult : public PacketHeader 55 | { 56 | LoginResult() 57 | { 58 | mSize = sizeof(LoginResult) ; 59 | mType = PKT_SC_LOGIN ; 60 | memset(mPlayerId, 0, sizeof(mPlayerId)); 61 | } 62 | 63 | char mPlayerId[MAX_SESSION_LEN]; 64 | 65 | } ; 66 | 67 | struct ChatBroadcastRequest : public PacketHeader 68 | { 69 | ChatBroadcastRequest() 70 | { 71 | mSize = sizeof(ChatBroadcastRequest) ; 72 | mType = PKT_CS_CHAT ; 73 | 74 | memset(mPlayerId, 0, sizeof(mPlayerId)); 75 | memset(mChat, 0, sizeof(mChat)); 76 | } 77 | 78 | char mPlayerId[MAX_SESSION_LEN]; 79 | char mChat[MAX_CHAT_LEN]; 80 | } ; 81 | 82 | struct ChatBroadcastResult : public PacketHeader 83 | { 84 | ChatBroadcastResult() 85 | { 86 | mSize = sizeof(ChatBroadcastResult) ; 87 | mType = PKT_SC_CHAT ; 88 | 89 | memset(mPlayerId, 0, sizeof(mPlayerId)); 90 | memset(mChat, 0, sizeof(mChat)); 91 | } 92 | 93 | char mPlayerId[MAX_SESSION_LEN]; 94 | char mChat[MAX_CHAT_LEN]; 95 | } ; 96 | 97 | struct MoveRequest : public PacketHeader 98 | { 99 | MoveRequest() 100 | { 101 | mSize = sizeof(MoveRequest); 102 | mType = PKT_CS_MOVE; 103 | mPlayerIdx = -1; 104 | mPosX = 0; 105 | mPosY = 0; 106 | } 107 | 108 | int mPlayerIdx; 109 | float mPosX; 110 | float mPosY; 111 | }; 112 | 113 | struct MoveBroadcastResult : public PacketHeader 114 | { 115 | MoveBroadcastResult() 116 | { 117 | mSize = sizeof(MoveBroadcastResult); 118 | mType = PKT_SC_MOVE; 119 | mPlayerIdx = -1; 120 | mPosX = 0; 121 | mPosY = 0; 122 | } 123 | 124 | int mPlayerIdx; 125 | float mPosX; 126 | float mPosY; 127 | }; 128 | 129 | 130 | 131 | 132 | struct ExitRequest : public PacketHeader 133 | { 134 | ExitRequest() 135 | { 136 | mSize = sizeof(ExitRequest); 137 | mType = PKT_CS_EXIT; 138 | 139 | memset(mPlayerId, 0, sizeof(mPlayerId)); 140 | } 141 | 142 | char mPlayerId[MAX_SESSION_LEN]; 143 | 144 | }; 145 | 146 | 147 | 148 | 149 | #pragma pack(pop) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Amazon GameLift? 2 | [Amazon GameLift](https://aws.amazon.com/gamelift/) is a managed service for deploying, operating, and scaling session-based multiplayer games, reduces the time required to build a multiplayer backend from thousands of hours to just minutes. Available for developers using Amazon Lumberyard, Amazon GameLift is built on AWS’s highly available cloud infrastructure and allows you to quickly scale high-performance game servers up and down to meet player demand – without any additional engineering effort or upfront costs. 3 | 4 | ### Amazon GameLift Deep Dive from Gaming on AWS 2016 5 | The following presentation explains GameLift features and fundamentals: [Amazon GameLift Deep Dive](GameLift_dist.pdf) 6 | 7 | ## This repository? 8 | This repository consists of four projects: 9 | - GameLiftGameServer 10 | - A stand-alone game server example utilizing GameLift. But, it has no dependency with Lumberyard as well as GridMate. 11 | - WIN64-based game server which listens a TCP port for clients and handles those requests 12 | - DummyClients 13 | - WIN64-based client application for testing GameLift and GameLiftGameServer 14 | - Creating multiple clients which make TCP session to GameLiftGameServer and communicate GameLift service in order to establish game sessions and player sessions by using AWS C++ SDK 15 | - Game client workload generator: this can be extended for a GameLift scaling/stress test or scenario-based client bot test 16 | - Cocos2dxGameClient 17 | - A game client which integrates with Cocos2D-x game engine and AWS C++ SDK 18 | - GameLift Client API calls to GameLift services and a TCP connection to GameLiftGameServer 19 | - GameLiftLinuxServer 20 | - GameLiftGameServer Linux version 21 | 22 | Overview: 23 | ![Screenshot](overview.png) 24 | 25 | ## But, why? 26 | I received many questions from game developers about GameLift. Major questions were like that: 27 | - Can we use other game engines such as Unreal3D and Unity3D with GameLift? 28 | - Can we leverage GameLift-alone with no dependency with Lumberyard? 29 | - How can we integrate our own game server to GameLift without GridMate? 30 | - Is there any other GameLift sample code using TCP protocol? 31 | 32 | As you can see, the facts of the matter are to study GameLift-alone features for their game and they want to know how to use GameLift SDK. So, I have started to make a sample program for better communication with game developers. The goal of this project is to show interactions among a game server, game clients and Gamelift. 33 | 34 | ## How? 35 | It is easy to build and run GameLiftGameServer and DummyClients. The only prerequisite is Visual Studio 2013 or 2015. 36 | 1. Open GameLiftGameServer solution file and then build it. 37 | 2. Upload a GameLiftGameServer binary with affiliated files (dlls, logs in upload folder) by AWS CLI 38 | 3. Create a GameLift Fleet by AWS Console 39 | 4. Open DummyClients solution file and edit config.ini file. set ALIAS_ID, GAMELIFT_REGION and MAX_GAME_SESSIONS 40 | - Note: when you want to use [GameSessionPlacement Functionality](http://docs.aws.amazon.com/gamelift/latest/developerguide/gamelift-sdk-client-queues.html): set MATCH_QUEUE_NAME in config.ini 41 | 5. Build DummyClients and run. (AWS credential is required on your PC: environment variables or $HOME/.aws folder) 42 | 6. For Cocos2dxGameClient, edit main.cpp file, set your ALIAS_ID, AWS_REGION, and then RUN! (you can login by pressing 'L' key.) 43 | 44 | ## A Full-Stack Game Sample using GameLift 45 | The sample code provided in this repository is focused on how to use GameLift features. See [awslabs](https://github.com/awslabs/aws-gamelift-sample) for an example of a real session-based multiplayer game. 46 | 47 | ## And... 48 | Some codes are written in a quick-and-dirty manner. But I plan to continuously improve these (if someone needs :) 49 | Please pull-requests! 50 | -------------------------------------------------------------------------------- /gamelift_interaction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeliard/GameLift/4bdb482097cac9e362701732bff74e4398a1c174/gamelift_interaction.png -------------------------------------------------------------------------------- /overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zeliard/GameLift/4bdb482097cac9e362701732bff74e4398a1c174/overview.png --------------------------------------------------------------------------------