GameLiftPlugin/Source/GameLiftServer/Source/GameLiftServerSDK/Public/aws/gamelift/internal/GameLiftServerState.h (170 lines of code) (raw):
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <aws/gamelift/internal/GameLiftCommonState.h>
#include <aws/gamelift/internal/network/GameLiftWebSocketClientManager.h>
#include <aws/gamelift/internal/network/IGameLiftMessageHandler.h>
#include <aws/gamelift/internal/network/IWebSocketClientWrapper.h>
#include <aws/gamelift/internal/network/callback/CreateGameSessionCallback.h>
#include <aws/gamelift/internal/network/callback/DescribePlayerSessionsCallback.h>
#include <aws/gamelift/internal/network/callback/GetComputeCertificateCallback.h>
#include <aws/gamelift/internal/network/callback/GetFleetRoleCredentialsCallback.h>
#include <aws/gamelift/internal/network/callback/RefreshConnectionCallback.h>
#include <aws/gamelift/internal/network/callback/StartMatchBackfillCallback.h>
#include <aws/gamelift/internal/network/callback/TerminateProcessCallback.h>
#include <aws/gamelift/internal/network/callback/UpdateGameSessionCallback.h>
#include <aws/gamelift/server/GameLiftServerAPI.h>
#include <aws/gamelift/server/model/ServerParameters.h>
#include <aws/gamelift/server/model/StartMatchBackfillRequest.h>
#include <aws/gamelift/server/model/StopMatchBackfillRequest.h>
#include <aws/gamelift/server/model/UpdateGameSession.h>
#include <condition_variable>
#include <mutex>
namespace Aws {
namespace GameLift {
namespace Internal {
using namespace Aws::GameLift::Server::Model;
#ifndef GAMELIFT_USE_STD
typedef Outcome<GameLiftServerState *, GameLiftError> InitSDKOutcome;
#endif
class GameLiftServerState : public GameLiftCommonState, public IGameLiftMessageHandler {
public:
static constexpr const char *LANGUAGE = "Cpp";
private:
static constexpr const char *ENV_VAR_WEBSOCKET_URL = "GAMELIFT_SDK_WEBSOCKET_URL";
static constexpr const char *ENV_VAR_COMPUTE_TYPE = "GAMELIFT_COMPUTE_TYPE";
static constexpr const char *ENV_VAR_AUTH_TOKEN = "GAMELIFT_SDK_AUTH_TOKEN";
static constexpr const char *ENV_VAR_PROCESS_ID = "GAMELIFT_SDK_PROCESS_ID";
static constexpr const char *ENV_VAR_HOST_ID = "GAMELIFT_SDK_HOST_ID";
static constexpr const char *ENV_VAR_FLEET_ID = "GAMELIFT_SDK_FLEET_ID";
static constexpr const char *ENV_VAR_AWS_REGION = "GAMELIFT_REGION";
static constexpr const char *ENV_VAR_ACCESS_KEY = "GAMELIFT_ACCESS_KEY";
static constexpr const char *ENV_VAR_SECRET_KEY = "GAMELIFT_SECRET_KEY";
static constexpr const char *ENV_VAR_SESSION_TOKEN = "GAMELIFT_SESSION_TOKEN";
static constexpr const char *COMPUTE_TYPE_CONTAINER = "CONTAINER";
static constexpr const char *AGENTLESS_CONTAINER_PROCESS_ID = "ManagedResource";
static constexpr const int HEALTHCHECK_INTERVAL_MILLIS = 60 * 1000;
static constexpr const int HEALTHCHECK_MAX_JITTER_MILLIS = 10 * 1000;
static constexpr const int HEALTHCHECK_TIMEOUT_MILLIS = HEALTHCHECK_INTERVAL_MILLIS - HEALTHCHECK_MAX_JITTER_MILLIS;
void GetOverrideParams(char **webSocketUrl,
char **authToken,
char **processId,
char **hostId,
char **fleetId,
char **computeType,
char **awsRegion,
char **accessKey,
char **secretKey,
char **sessionToken);
Outcome<std::map<std::string, std::string>, std::string> GetSigV4QueryParameters(char *awsRegion,
char *accessKey,
char *secretKey,
char *sessionToken);
void ReportHealth();
void HealthCheck();
int GetNextHealthCheckIntervalMillis();
#ifdef GAMELIFT_USE_STD
public:
static Server::InitSDKOutcome CreateInstance(std::shared_ptr<IWebSocketClientWrapper> webSocketClientWrapper);
virtual GAMELIFT_INTERNAL_STATE_TYPE GetStateType() override { return GAMELIFT_INTERNAL_STATE_TYPE::SERVER; };
// Singleton constructors should be private, but we are using a custom allocator that needs to
// be able to see them. Don't use these.
GameLiftServerState();
~GameLiftServerState();
GenericOutcome ProcessReady(const Aws::GameLift::Server::ProcessParameters &processParameters);
GenericOutcome ProcessEnding();
GenericOutcome InitializeNetworking(const Aws::GameLift::Server::Model::ServerParameters &serverParameters);
GenericOutcome SendSocketMessageWithRetries(Message &message);
GenericOutcome ActivateGameSession();
GenericOutcome UpdatePlayerSessionCreationPolicy(PlayerSessionCreationPolicy newPlayerSessionPolicy);
std::string GetGameSessionId() const;
long GetTerminationTime() const;
GenericOutcome AcceptPlayerSession(const std::string &playerSessionId);
GenericOutcome RemovePlayerSession(const std::string &playerSessionId);
DescribePlayerSessionsOutcome DescribePlayerSessions(const Aws::GameLift::Server::Model::DescribePlayerSessionsRequest &describePlayerSessionsRequest);
StartMatchBackfillOutcome StartMatchBackfill(const Aws::GameLift::Server::Model::StartMatchBackfillRequest &startMatchBackfillRequest);
GenericOutcome StopMatchBackfill(const Aws::GameLift::Server::Model::StopMatchBackfillRequest &stopMatchBackfillRequest);
GetComputeCertificateOutcome GetComputeCertificate();
bool IsProcessReady() const { return m_processReady; }
// From Network::AuxProxyMessageHandler
void OnStartGameSession(GameSession &gameSession) override;
void OnUpdateGameSession(UpdateGameSession &gameSession) override;
void OnTerminateProcess(long terminationTime) override;
void OnRefreshConnection(const std::string &refreshConnectionEndpoint, const std::string &authToken) override;
private:
std::function<void(Aws::GameLift::Server::Model::GameSession)> m_onStartGameSession;
std::function<void(Aws::GameLift::Server::Model::UpdateGameSession)> m_onUpdateGameSession;
std::function<void()> m_onProcessTerminate;
std::function<bool()> m_onHealthCheck;
#else
public:
template <class WrapperT> static Internal::InitSDKOutcome CreateInstance() { return ConstructInternal(std::make_shared<WrapperT>()); }
template <class WrapperT, class ClientT> static Internal::InitSDKOutcome CreateInstance() {
return ConstructInternal(std::make_shared<WrapperT>(std::make_shared<ClientT>()));
}
std::shared_ptr<IWebSocketClientWrapper> GetWebSocketClientWrapper() const;
virtual GAMELIFT_INTERNAL_STATE_TYPE GetStateType() override { return GAMELIFT_INTERNAL_STATE_TYPE::SERVER; };
// Singleton constructors should be private, but we are using a custom allocator that needs to
// be able to see them. Don't use these.
GameLiftServerState();
~GameLiftServerState();
GenericOutcome ProcessReady(const Aws::GameLift::Server::ProcessParameters &processParameters);
GenericOutcome ProcessEnding();
GenericOutcome InitializeNetworking(const Aws::GameLift::Server::Model::ServerParameters &ServerParameters);
GenericOutcome SendSocketMessageWithRetries(Message &message);
GenericOutcome ActivateGameSession();
GenericOutcome UpdatePlayerSessionCreationPolicy(PlayerSessionCreationPolicy newPlayerSessionPolicy);
const char *GetGameSessionId();
long GetTerminationTime();
GenericOutcome AcceptPlayerSession(const std::string &playerSessionId);
GenericOutcome RemovePlayerSession(const std::string &playerSessionId);
DescribePlayerSessionsOutcome DescribePlayerSessions(const Aws::GameLift::Server::Model::DescribePlayerSessionsRequest &describePlayerSessionsRequest);
StartMatchBackfillOutcome StartMatchBackfill(const Aws::GameLift::Server::Model::StartMatchBackfillRequest &request);
GenericOutcome StopMatchBackfill(const Aws::GameLift::Server::Model::StopMatchBackfillRequest &request);
GetComputeCertificateOutcome GetComputeCertificate();
bool IsProcessReady() { return m_processReady; }
// From Network::AuxProxyMessageHandler
void OnStartGameSession(GameSession &gameSession) override;
void OnUpdateGameSession(UpdateGameSession &gameSession) override;
void OnTerminateProcess(long terminationTime) override;
void OnRefreshConnection(const std::string &refreshConnectionEndpoint, const std::string &authToken) override;
private:
std::function<void(Aws::GameLift::Server::Model::GameSession, void *)> m_onStartGameSession;
std::function<void(Aws::GameLift::Server::Model::UpdateGameSession, void *)> m_onUpdateGameSession;
std::function<void(void *)> m_onProcessTerminate;
std::function<bool(void *)> m_onHealthCheck;
void *m_startGameSessionState;
void *m_updateGameSessionState;
void *m_processTerminateState;
void *m_healthCheckState;
void *startGameSessionState;
void *processTerminateState;
void *healthCheckState;
static Internal::InitSDKOutcome ConstructInternal(std::shared_ptr<IWebSocketClientWrapper> webSocketClientWrapper);
#endif
public:
GetFleetRoleCredentialsOutcome GetFleetRoleCredentials(const Aws::GameLift::Server::Model::GetFleetRoleCredentialsRequest &request);
// When within 15 minutes of expiration we retrieve new instance role credentials
static constexpr const time_t INSTANCE_ROLE_CREDENTIAL_TTL_MIN = 60 * 15;
private:
bool AssertNetworkInitialized();
void SetUpCallbacks();
bool m_processReady;
// Only one game session per process.
std::string m_gameSessionId;
long m_terminationTime;
GameLiftWebSocketClientManager *m_webSocketClientManager;
std::shared_ptr<IWebSocketClientWrapper> m_webSocketClientWrapper;
// Callbacks
std::unique_ptr<CreateGameSessionCallback> m_createGameSessionCallback;
std::unique_ptr<DescribePlayerSessionsCallback> m_describePlayerSessionsCallback;
std::unique_ptr<GetComputeCertificateCallback> m_getComputeCertificateCallback;
std::unique_ptr<GetFleetRoleCredentialsCallback> m_getFleetRoleCredentialsCallback;
std::unique_ptr<TerminateProcessCallback> m_terminateProcessCallback;
std::unique_ptr<UpdateGameSessionCallback> m_updateGameSessionCallback;
std::unique_ptr<StartMatchBackfillCallback> m_startMatchBackfillCallback;
std::unique_ptr<RefreshConnectionCallback> m_refreshConnectionCallback;
std::string m_connectionEndpoint;
std::string m_authToken;
std::string m_fleetId;
std::string m_hostId;
std::string m_processId;
// Assume we're on managed EC2, if GetFleetRoleCredentials fails we know to set this to false
bool m_onManagedEC2 = true;
std::map<std::string, GetFleetRoleCredentialsResult> m_instanceRoleResultCache;
std::unique_ptr<std::thread> m_healthCheckThread;
std::condition_variable m_healthCheckConditionVariable;
std::mutex m_healthCheckMutex;
bool m_healthCheckInterrupted;
};
} // namespace Internal
} // namespace GameLift
} // namespace Aws