Initial Commit - Lesson 31 (Commit #1)
This commit is contained in:
35
Plugins/GameLiftServerSDK/GameLiftServerSDK.uplugin
Normal file
35
Plugins/GameLiftServerSDK/GameLiftServerSDK.uplugin
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"FileVersion": 3,
|
||||
"Version": 5,
|
||||
"VersionName": "5.4.0",
|
||||
"FriendlyName": "GameLiftServerSDK",
|
||||
"Description": "",
|
||||
"Category": "Other",
|
||||
"CreatedBy": "",
|
||||
"CreatedByURL": "",
|
||||
"DocsURL": "",
|
||||
"MarketplaceURL": "",
|
||||
"SupportURL": "",
|
||||
"EnabledByDefault": false,
|
||||
"CanContainContent": false,
|
||||
"IsBetaVersion": false,
|
||||
"Installed": false,
|
||||
"Modules": [
|
||||
{
|
||||
"Name": "GameLiftServerSDK",
|
||||
"Type": "Runtime",
|
||||
"LoadingPhase": "PreDefault",
|
||||
"TargetAllowList": [
|
||||
"Server"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "GameLiftMetrics",
|
||||
"Type": "Runtime",
|
||||
"LoadingPhase": "PreDefault",
|
||||
"TargetAllowList": [
|
||||
"Server"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
- Support for Windows and Linux operating systems.
|
||||
- Support for Unreal Engine 4.13 or later
|
||||
- Dependency on GameLift C++ Server SDK 3.1.5
|
||||
@@ -0,0 +1,3 @@
|
||||
- Updated Google Protobuf to v3.3
|
||||
- TargetInfo updated to ReadOnlyTargetRules for UE4.16-4.18
|
||||
- Dependency on GameLift C++ Server SDK 3.2.0
|
||||
@@ -0,0 +1 @@
|
||||
- New API GetTerminationTime
|
||||
@@ -0,0 +1,2 @@
|
||||
- Support for Matchmaking backfill APIs
|
||||
- Support for 4.19, 4.20 and 4.21 versions of Unreal Engine.
|
||||
@@ -0,0 +1,2 @@
|
||||
- Support for 4.22, 4.23 and 4.24 versions of Unreal Engine.
|
||||
- Bug fixes
|
||||
@@ -0,0 +1,2 @@
|
||||
- Add missing delegate for OnUpdateGameSession
|
||||
- Deprecate TerminateGameSession API
|
||||
@@ -0,0 +1 @@
|
||||
- Support for Unreal Engine 4.25 and 4.25 plus
|
||||
@@ -0,0 +1,4 @@
|
||||
- Support for Unreal Engine 4.26
|
||||
- Support for DescribePlayerSessions API
|
||||
- Support for GetInstanceCertificate API
|
||||
- Bug fixes
|
||||
@@ -0,0 +1,6 @@
|
||||
- Support for Unreal Engine 5.1.1
|
||||
- Support for Amazon GameLift SDK 5.0
|
||||
- Added support for new SDK 5.0 APIs
|
||||
- Removed APIs no longer supported in SDK 5.0
|
||||
- Changed InitSDK to reflect new FServerParameter requirement
|
||||
- Added additional GameLift ERROR types
|
||||
@@ -0,0 +1,5 @@
|
||||
- Add InitSDK() API with no parameters. This API reads server parameters from environment variables, such as fleet ID,
|
||||
compute name, WebSocket URL, process ID and auth token. This API simplifies SDK initialization in Amazon GameLift
|
||||
managed EC2 fleets. For initialization in Amazon GameLift Anywhere fleets, call InitSDK() with the ServerParameters parameter.
|
||||
- Update ProcessReady() to retain a copy of FProcessParameters. This fixes segfaults that occur when Amazon GameLift C++ SDK
|
||||
attempts to invoke user callbacks after FProcessParameters is freed in memory.
|
||||
@@ -0,0 +1,2 @@
|
||||
- Improved the reliability of the SDK by adding automatic reconnection in the event of network interruption.
|
||||
- Fixed a problem with converting the expiration time returned from GetFleetRoleCredentials.
|
||||
@@ -0,0 +1,2 @@
|
||||
- Introduced logging capabilities for the C++ Server SDK; logs are now accessible.
|
||||
- Improved the reliability of SDK message transmission by implementing more robust reconnection mechanisms in the event of network interruptions or random message drops.
|
||||
@@ -0,0 +1,2 @@
|
||||
- Added support for GameLift container fleets.
|
||||
- Added the option to initialize the SDK using AWS Region and AWS Credentials, providing an alternative to AuthToken based authentication.
|
||||
@@ -0,0 +1,15 @@
|
||||
- Removes the need to manually download and build the server SDK. The new plugin version now includes the server SDK source code, which is automatically built along with the Unreal project using the Unreal Build Tool.
|
||||
- CMake is no longer a prerequisite.
|
||||
- Removes the need to install OpenSSL. The new plugin uses OpenSSL source in the Unreal Engine with static linking.
|
||||
- When packaging a build for Amazon GameLift Servers, you no longer need to include the libcrypto and libssl files into your game server build.
|
||||
- Integrates the Unreal cross-compiling toolkit that enables cross-compiled builds on native Windows and Linux. Removes the need for special steps, including the Amazon GameLift Servers toolkit to generate Linux libraries.
|
||||
- Adds the missing Destroy() action.
|
||||
- Supports ARM game server builds for UE5.
|
||||
- Fixes MSVC 5130 Macro Warnings.
|
||||
- Merges the two Unreal plugins (lightweight and standalone) into one repository.
|
||||
- Adds or improves client-side validation in all server SDK actions.
|
||||
- Adds more specific and improved error responses to API errors.
|
||||
- Fixes an edge case in GetFleetRoleCredentials() that causes game server crash.
|
||||
- Adds default logic to the onProcessTerminate() callback that terminates the game server process when this callback is invoked.
|
||||
- Adds idempotency token support to allow InitSDK() retries to succeed.
|
||||
- Includes autoBackfillMode in the data passed in the OnUpdateGameSession() callback.
|
||||
@@ -0,0 +1,2 @@
|
||||
- Support the Unreal Plugin and Server SDK on Unreal Engine 5.6
|
||||
- Fix compilation errors when packaging Android client targets.
|
||||
@@ -0,0 +1 @@
|
||||
- Isolate the Asio namespace in the ServerSDK module to improve packaging compatibility with other modules
|
||||
@@ -0,0 +1,2 @@
|
||||
- Adds support for publishing built-in and custom telemetry metrics, with pre-built dashboards for visualizing usage data.
|
||||
- Fixes a potential null pointer exception in the client logging when attempting to re-establish the WebSocket connection.
|
||||
BIN
Plugins/GameLiftServerSDK/Resources/Icon128.png
Normal file
BIN
Plugins/GameLiftServerSDK/Resources/Icon128.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class GameLiftMetrics : ModuleRules
|
||||
{
|
||||
public GameLiftMetrics(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
bEnableExceptions = true;
|
||||
bUseRTTI = false;
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
"GameLiftServerSDK",
|
||||
}
|
||||
);
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"CoreUObject",
|
||||
"Core",
|
||||
"Engine",
|
||||
"Sockets",
|
||||
"Networking",
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,319 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GameLiftMetrics.h"
|
||||
#include "GameLiftMetricsTypes.h"
|
||||
#include "GameLiftMetricsConfig.h"
|
||||
#include "UnrealStatCollector.h"
|
||||
#include "TickableCollector.h"
|
||||
|
||||
#include "GameLiftServerSDK.h"
|
||||
#include "aws/gamelift/server/GameLiftServerAPI.h"
|
||||
|
||||
#include "Sockets.h"
|
||||
#include "SocketSubsystem.h"
|
||||
#include "IPAddress.h"
|
||||
#include "Common/UdpSocketBuilder.h"
|
||||
|
||||
#include <aws/gamelift/metrics/GlobalMetricsProcessor.h>
|
||||
|
||||
#if PLATFORM_LINUX
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
FString FGameLiftMetricsModule::CurrentGameSessionId;
|
||||
FThreadSafeCounter FGameLiftMetricsModule::CurrentPlayerCount(0);
|
||||
|
||||
FGameLiftMetricsModule& FGameLiftMetricsModule::Load()
|
||||
{
|
||||
return FModuleManager::LoadModuleChecked<FGameLiftMetricsModule>(FName("GameLiftMetrics"));
|
||||
}
|
||||
|
||||
FGameLiftMetricsModule& FGameLiftMetricsModule::Get()
|
||||
{
|
||||
return FModuleManager::GetModuleChecked<FGameLiftMetricsModule>(FName("GameLiftMetrics"));
|
||||
}
|
||||
|
||||
FGameLiftMetricsModule* FGameLiftMetricsModule::GetPtr()
|
||||
{
|
||||
return FModuleManager::GetModulePtr<FGameLiftMetricsModule>(FName("GameLiftMetrics"));
|
||||
}
|
||||
|
||||
#if WITH_GAMELIFT_METRICS
|
||||
namespace
|
||||
{
|
||||
const TCHAR* GAMELIFT_METRICS_FLEET_ID = TEXT("GAMELIFT_SDK_FLEET_ID");
|
||||
const TCHAR* GAMELIFT_METRICS_PROCESS_ID = TEXT("GAMELIFT_SDK_PROCESS_ID");
|
||||
|
||||
GAMELIFT_METRICS_DECLARE_GAUGE(MetricMaxPlayers, "server_max_players", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
GAMELIFT_METRICS_DEFINE_GAUGE(MetricMaxPlayers);
|
||||
|
||||
GAMELIFT_METRICS_DECLARE_GAUGE(MetricPlayers, "server_players", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
GAMELIFT_METRICS_DEFINE_GAUGE(MetricPlayers);
|
||||
|
||||
GAMELIFT_METRICS_DECLARE_COUNTER(MetricServerCrashes, "game_server_crashes", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
GAMELIFT_METRICS_DEFINE_COUNTER(MetricServerCrashes);
|
||||
}
|
||||
|
||||
void FGameLiftMetricsModule::StartupModule() {}
|
||||
|
||||
void FGameLiftMetricsModule::ShutdownModule()
|
||||
{
|
||||
// Terminate here just in case the user forgot.
|
||||
Terminate();
|
||||
}
|
||||
|
||||
void FGameLiftMetricsModule::StartMetricsCollector()
|
||||
{
|
||||
FPlatformMisc::SetCrashHandler(&FGameLiftMetricsModule::CrashHandler);
|
||||
|
||||
bMetricsRunning = true;
|
||||
|
||||
auto *Module = FGameLiftMetricsModule::GetPtr();
|
||||
if (!Module)
|
||||
{
|
||||
UE_LOG(LogGameLiftMetrics, Error, TEXT("GameLiftMetrics module no longer loaded."));
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Begin ticking the collector.
|
||||
*/
|
||||
const bool bComputeFallbackGameThreadTime = !STATS;
|
||||
Module->Collector.Reset(new FTickableCollector(bComputeFallbackGameThreadTime));
|
||||
|
||||
/*
|
||||
* Create stats collector.
|
||||
*/
|
||||
if (STATS)
|
||||
{
|
||||
Module->UnrealStatCollector = TSharedPtr<FUnrealStatCollector>(new FUnrealStatCollector());
|
||||
Module->UnrealStatCollector->Subscribe();
|
||||
}
|
||||
|
||||
UE_LOG(LogGameLiftMetrics, Log, TEXT("GameLift metrics initialized successfully."));
|
||||
}
|
||||
|
||||
void FGameLiftMetricsModule::Initialize()
|
||||
{
|
||||
if (GIsEditor) return;
|
||||
|
||||
// Initialize GameLift Server SDK metrics
|
||||
auto& ServerSDKModule = FModuleManager::LoadModuleChecked<FGameLiftServerSDKModule>("GameLiftServerSDK");
|
||||
auto InitResult = ServerSDKModule.InitMetrics();
|
||||
if (!InitResult.IsSuccess())
|
||||
{
|
||||
UE_LOG(LogGameLiftMetrics, Error, TEXT("Failed to initialize GameLift metrics: %s"), *InitResult.GetError().m_errorMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
StartMetricsCollector();
|
||||
}
|
||||
|
||||
void FGameLiftMetricsModule::Initialize(const FMetricsParameters& metricsParameters)
|
||||
{
|
||||
if (GIsEditor) return;
|
||||
|
||||
// Initialize GameLift Server SDK metrics with parameters
|
||||
auto& ServerSDKModule = FModuleManager::LoadModuleChecked<FGameLiftServerSDKModule>("GameLiftServerSDK");
|
||||
auto InitResult = ServerSDKModule.InitMetrics(metricsParameters);
|
||||
if (!InitResult.IsSuccess())
|
||||
{
|
||||
UE_LOG(LogGameLiftMetrics, Error, TEXT("Failed to initialize GameLift metrics with parameters: %s"), *InitResult.GetError().m_errorMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
StartMetricsCollector();
|
||||
}
|
||||
|
||||
void FGameLiftMetricsModule::Terminate()
|
||||
{
|
||||
if (GIsEditor) { return; }
|
||||
|
||||
if (UnrealStatCollector)
|
||||
{
|
||||
UnrealStatCollector->Unsubscribe();
|
||||
UnrealStatCollector.Reset();
|
||||
}
|
||||
|
||||
Collector.Reset();
|
||||
|
||||
UE_LOG(LogGameLiftMetrics, Log, TEXT("GameLift metrics terminated successfully."));
|
||||
}
|
||||
|
||||
void FGameLiftMetricsModule::OnStartGameSession(const Aws::GameLift::Server::Model::GameSession& Session)
|
||||
{
|
||||
if (GIsEditor) { return; }
|
||||
|
||||
// Store the session ID regardless of metrics being enabled
|
||||
CurrentGameSessionId = FString(Session.GetGameSessionId());
|
||||
CurrentPlayerCount.Set(0);
|
||||
|
||||
const UGameLiftMetricsConfig& Config = UGameLiftMetricsConfig::Get();
|
||||
if (!Config.bEnableMetrics)
|
||||
{
|
||||
UE_LOG(LogGameLiftMetrics, Verbose, TEXT("Metrics disabled: Skipping OnStartGameSession metrics"));
|
||||
return;
|
||||
}
|
||||
|
||||
GAMELIFT_METRICS_SET(MetricMaxPlayers, Session.GetMaximumPlayerSessionCount());
|
||||
GAMELIFT_METRICS_RESET(MetricPlayers);
|
||||
}
|
||||
|
||||
void FGameLiftMetricsModule::OnAcceptPlayerSession()
|
||||
{
|
||||
if (GIsEditor) { return; }
|
||||
|
||||
// Always track player count even if metrics are disabled
|
||||
int32 NewPlayerCount = CurrentPlayerCount.Increment();
|
||||
|
||||
const UGameLiftMetricsConfig& Config = UGameLiftMetricsConfig::Get();
|
||||
if (!Config.bEnableMetrics)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GAMELIFT_METRICS_SET(MetricPlayers, NewPlayerCount);
|
||||
}
|
||||
|
||||
void FGameLiftMetricsModule::OnRemovePlayerSession()
|
||||
{
|
||||
if (GIsEditor) { return; }
|
||||
|
||||
// Always track player count even if metrics are disabled
|
||||
int32 NewPlayerCount = CurrentPlayerCount.Decrement();
|
||||
if (NewPlayerCount < 0)
|
||||
{
|
||||
CurrentPlayerCount.Set(0);
|
||||
NewPlayerCount = 0;
|
||||
}
|
||||
|
||||
const UGameLiftMetricsConfig& Config = UGameLiftMetricsConfig::Get();
|
||||
if (!Config.bEnableMetrics)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GAMELIFT_METRICS_SET(MetricPlayers, NewPlayerCount);
|
||||
}
|
||||
|
||||
void FGameLiftMetricsModule::ReEmitMetrics()
|
||||
{
|
||||
if (GIsEditor) { return; }
|
||||
|
||||
const UGameLiftMetricsConfig& Config = UGameLiftMetricsConfig::Get();
|
||||
if (!Config.bEnableMetrics)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GAMELIFT_METRICS_SET(MetricPlayers, CurrentPlayerCount.GetValue());
|
||||
}
|
||||
|
||||
void FGameLiftMetricsModule::CrashHandler(const FGenericCrashContext& GenericContext)
|
||||
{
|
||||
UE_LOG(LogGameLiftMetrics, Log, TEXT("Server crashed, CrashHandler being called..."));
|
||||
|
||||
const UGameLiftMetricsConfig& Config = UGameLiftMetricsConfig::Get();
|
||||
if (!Config.bEnableMetrics)
|
||||
{
|
||||
UE_LOG(LogGameLiftMetrics, Log, TEXT("Metrics disabled: Skipping crash metrics"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CurrentGameSessionId.IsEmpty())
|
||||
{
|
||||
UE_LOG(LogGameLiftMetrics, Log, TEXT("Incrementing crash metrics for session: %s"), *CurrentGameSessionId);
|
||||
GAMELIFT_METRICS_INCREMENT(MetricServerCrashes);
|
||||
GAMELIFT_METRICS_TAG_SET(MetricServerCrashes, "game_session_id", TCHAR_TO_UTF8(*CurrentGameSessionId));
|
||||
UE_LOG(LogGameLiftMetrics, Log, TEXT("Crash metrics incremented"));
|
||||
|
||||
// Force process the metrics
|
||||
UE_LOG(LogGameLiftMetrics, Log, TEXT("Sending crash metrics..."));
|
||||
Aws::GameLift::Metrics::MetricsProcess();
|
||||
|
||||
// Small sleep to allow the metrics to be sent
|
||||
UE_LOG(LogGameLiftMetrics, Log, TEXT("Waiting for metrics to send..."));
|
||||
FPlatformProcess::Sleep(0.2f);
|
||||
|
||||
UE_LOG(LogGameLiftMetrics, Log, TEXT("Crash metrics incremented and processed"));
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogGameLiftMetrics, Warning, TEXT("Server crashed with no active game session"));
|
||||
}
|
||||
}
|
||||
|
||||
bool FGameLiftMetricsModule::SetMetricsEnabled(bool bEnable)
|
||||
{
|
||||
if (GIsEditor)
|
||||
{
|
||||
UE_LOG(LogGameLiftMetrics, Warning, TEXT("Cannot enable/disable metrics in editor - only applicable in game server"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the state is already what's requested, no change needed
|
||||
if (bEnable == bMetricsRunning)
|
||||
{
|
||||
UE_LOG(LogGameLiftMetrics, Log, TEXT("Metrics already %s, no change needed"),
|
||||
bEnable ? TEXT("enabled") : TEXT("disabled"));
|
||||
return true;
|
||||
}
|
||||
// Get current configuration and check current state
|
||||
UGameLiftMetricsConfig* Config = const_cast<UGameLiftMetricsConfig*>(&UGameLiftMetricsConfig::Get());
|
||||
|
||||
if (bEnable)
|
||||
{
|
||||
// Enable metrics
|
||||
UE_LOG(LogGameLiftMetrics, Log, TEXT("Enabling GameLift metrics at runtime"));
|
||||
|
||||
// Initialize with default parameters
|
||||
Initialize();
|
||||
|
||||
// Flag is set inside Initialize method based on success
|
||||
return bMetricsRunning;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Disable metrics
|
||||
UE_LOG(LogGameLiftMetrics, Log, TEXT("Disabling GameLift metrics at runtime"));
|
||||
|
||||
// Terminate metrics system
|
||||
Terminate();
|
||||
Config->bEnableMetrics = false;
|
||||
bMetricsRunning = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool FGameLiftMetricsModule::IsMetricsEnabled() const
|
||||
{
|
||||
return bMetricsRunning;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void FGameLiftMetricsModule::StartupModule() {}
|
||||
void FGameLiftMetricsModule::ShutdownModule() {}
|
||||
void FGameLiftMetricsModule::Initialize() {}
|
||||
void FGameLiftMetricsModule::Initialize(const FMetricsParameters& metricsParameters) {}
|
||||
void FGameLiftMetricsModule::Terminate() {}
|
||||
void FGameLiftMetricsModule::OnStartGameSession(const Aws::GameLift::Server::Model::GameSession& Session) {}
|
||||
void FGameLiftMetricsModule::OnAcceptPlayerSession() {}
|
||||
void FGameLiftMetricsModule::OnRemovePlayerSession() {}
|
||||
void FGameLiftMetricsModule::ReEmitMetrics() {}
|
||||
bool FGameLiftMetricsModule::SetMetricsEnabled(bool bEnable) { return false; }
|
||||
bool FGameLiftMetricsModule::IsMetricsEnabled() const { return false; }
|
||||
|
||||
#endif // WITH_GAMELIFT_METRICS
|
||||
|
||||
IMPLEMENT_MODULE(FGameLiftMetricsModule, GameLiftMetrics)
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GameLiftMetricsConfig.h"
|
||||
|
||||
|
||||
const UGameLiftMetricsConfig& UGameLiftMetricsConfig::Get()
|
||||
{
|
||||
UGameLiftMetricsConfig* CDO = Cast<UGameLiftMetricsConfig>(StaticClass()->GetDefaultObject());
|
||||
check(IsValid(CDO));
|
||||
return *CDO;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GameLiftMetricsTypes.h"
|
||||
|
||||
DEFINE_LOG_CATEGORY(LogGameLiftMetrics);
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "MemoryStats.h"
|
||||
|
||||
#include "Engine.h"
|
||||
#include "EngineStats.h"
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Metrics {
|
||||
GAMELIFT_METRICS_DEFINE_GAUGE(MetricMemoryPhysicalTotal);
|
||||
GAMELIFT_METRICS_DEFINE_GAUGE(MetricMemoryPhysicalAvailable);
|
||||
GAMELIFT_METRICS_DEFINE_GAUGE(MetricMemoryPhysicalUsed);
|
||||
|
||||
GAMELIFT_METRICS_DEFINE_GAUGE(MetricMemoryVirtualTotal);
|
||||
GAMELIFT_METRICS_DEFINE_GAUGE(MetricMemoryVirtualAvailable);
|
||||
GAMELIFT_METRICS_DEFINE_GAUGE(MetricMemoryVirtualUsed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FMemoryStats::Collect()
|
||||
{
|
||||
auto MemoryStats = FPlatformMemory::GetStats();
|
||||
|
||||
GAMELIFT_METRICS_SET(Aws::GameLift::Metrics::MetricMemoryPhysicalTotal, MemoryStats.TotalPhysical);
|
||||
GAMELIFT_METRICS_SET(Aws::GameLift::Metrics::MetricMemoryPhysicalAvailable, MemoryStats.AvailablePhysical);
|
||||
GAMELIFT_METRICS_SET(Aws::GameLift::Metrics::MetricMemoryPhysicalUsed, MemoryStats.UsedPhysical);
|
||||
GAMELIFT_METRICS_SET(Aws::GameLift::Metrics::MetricMemoryVirtualTotal, MemoryStats.TotalVirtual);
|
||||
GAMELIFT_METRICS_SET(Aws::GameLift::Metrics::MetricMemoryVirtualAvailable, MemoryStats.AvailableVirtual);
|
||||
GAMELIFT_METRICS_SET(Aws::GameLift::Metrics::MetricMemoryVirtualUsed, MemoryStats.UsedVirtual);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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 "GameLiftMetricsTypes.h"
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Metrics {
|
||||
GAMELIFT_METRICS_DECLARE_GAUGE(MetricMemoryPhysicalTotal, "server_mem_physical_total", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
GAMELIFT_METRICS_DECLARE_GAUGE(MetricMemoryPhysicalAvailable, "server_mem_physical_available", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
GAMELIFT_METRICS_DECLARE_GAUGE(MetricMemoryPhysicalUsed, "server_mem_physical_used", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
|
||||
GAMELIFT_METRICS_DECLARE_GAUGE(MetricMemoryVirtualTotal, "server_mem_virtual_total", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
GAMELIFT_METRICS_DECLARE_GAUGE(MetricMemoryVirtualAvailable, "server_mem_virtual_available", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
GAMELIFT_METRICS_DECLARE_GAUGE(MetricMemoryVirtualUsed, "server_mem_virtual_used", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FMemoryStats
|
||||
{
|
||||
public:
|
||||
void Collect();
|
||||
};
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "NetworkStats.h"
|
||||
|
||||
#include "Engine/NetDriver.h"
|
||||
#include "Engine.h"
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Metrics {
|
||||
GAMELIFT_METRICS_DEFINE_GAUGE(MetricConnectionCount);
|
||||
|
||||
GAMELIFT_METRICS_DEFINE_COUNTER(MetricBytesIn);
|
||||
GAMELIFT_METRICS_DEFINE_COUNTER(MetricBytesOut);
|
||||
GAMELIFT_METRICS_DEFINE_COUNTER(MetricPacketsIn);
|
||||
GAMELIFT_METRICS_DEFINE_COUNTER(MetricPacketsInLost);
|
||||
GAMELIFT_METRICS_DEFINE_COUNTER(MetricPacketsOut);
|
||||
GAMELIFT_METRICS_DEFINE_COUNTER(MetricPacketsOutLost);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FNetworkStats::FNetworkStats()
|
||||
{
|
||||
if (auto NetDriver = GetNetDriver())
|
||||
{
|
||||
LastInBytes = NetDriver->InTotalBytes;
|
||||
LastOutBytes = NetDriver->OutTotalBytes;
|
||||
LastInPackets = NetDriver->InTotalPackets;
|
||||
LastOutPackets = NetDriver->OutTotalPackets;
|
||||
LastInPacketsLost = NetDriver->InTotalPacketsLost;
|
||||
LastOutPacketsLost = NetDriver->OutTotalPacketsLost;
|
||||
}
|
||||
}
|
||||
|
||||
void FNetworkStats::Collect()
|
||||
{
|
||||
if (auto NetDriver = GetNetDriver())
|
||||
{
|
||||
GAMELIFT_METRICS_ADD(Aws::GameLift::Metrics::MetricBytesIn, NetDriver->InTotalBytes - LastInBytes);
|
||||
GAMELIFT_METRICS_ADD(Aws::GameLift::Metrics::MetricBytesOut, NetDriver->OutTotalBytes - LastOutBytes);
|
||||
GAMELIFT_METRICS_ADD(Aws::GameLift::Metrics::MetricPacketsIn, NetDriver->InTotalPackets - LastInPackets);
|
||||
GAMELIFT_METRICS_ADD(Aws::GameLift::Metrics::MetricPacketsOut, NetDriver->OutTotalPackets - LastOutPackets);
|
||||
GAMELIFT_METRICS_ADD(Aws::GameLift::Metrics::MetricPacketsInLost, NetDriver->InTotalPacketsLost - LastInPacketsLost);
|
||||
GAMELIFT_METRICS_ADD(Aws::GameLift::Metrics::MetricPacketsOutLost, NetDriver->OutTotalPacketsLost - LastOutPacketsLost);
|
||||
|
||||
LastInBytes = NetDriver->InTotalBytes;
|
||||
LastOutBytes = NetDriver->OutTotalBytes;
|
||||
LastInPackets = NetDriver->InTotalPackets;
|
||||
LastOutPackets = NetDriver->OutTotalPackets;
|
||||
LastInPacketsLost = NetDriver->InTotalPacketsLost;
|
||||
LastOutPacketsLost = NetDriver->OutTotalPacketsLost;
|
||||
|
||||
GAMELIFT_METRICS_SET(Aws::GameLift::Metrics::MetricConnectionCount, NetDriver->ClientConnections.Num());
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogGameLiftMetrics, Error, TEXT("Net driver is null. Cannot log network metrics."));
|
||||
}
|
||||
}
|
||||
|
||||
const UNetDriver* FNetworkStats::GetNetDriver() const
|
||||
{
|
||||
UEngine* Engine = GEngine;
|
||||
if (!IsValid(Engine))
|
||||
{
|
||||
UE_LOG(LogGameLiftMetrics, Error, TEXT("Engine pointer is not valid when retrieving net driver."));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto& WorldContexts = Engine->GetWorldContexts();
|
||||
if (WorldContexts.Num() == 0)
|
||||
{
|
||||
// no worlds are loaded
|
||||
// generally can only be true before everything is fully initialized
|
||||
UE_LOG(LogGameLiftMetrics, Error, TEXT("No world is loaded when retrieving net driver."));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Only one world context should be present outside Editor.
|
||||
// (editor has multiple)
|
||||
// Refer to FWorldContext comment in Engine.h
|
||||
const FWorldContext& WorldContext = WorldContexts[0];
|
||||
check(WorldContext.WorldType == EWorldType::Game);
|
||||
|
||||
// In theory multiple net drivers might be present.
|
||||
// One will be for gameplay but additional ones might be opened for non-gameplay traffic.
|
||||
// Might be null during initialisation.
|
||||
if (WorldContext.ActiveNetDrivers.Num() == 0)
|
||||
{
|
||||
UE_LOG(LogGameLiftMetrics, Error, TEXT("No active net drivers. Cannot acquire network metrics."));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return WorldContext.ActiveNetDrivers[0].NetDriver;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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 "GameLiftMetricsTypes.h"
|
||||
|
||||
class UNetDriver;
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Metrics {
|
||||
GAMELIFT_METRICS_DECLARE_GAUGE(MetricConnectionCount, "server_connections", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
|
||||
GAMELIFT_METRICS_DECLARE_COUNTER(MetricBytesIn, "server_bytes_in", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
GAMELIFT_METRICS_DECLARE_COUNTER(MetricBytesOut, "server_bytes_out", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
|
||||
GAMELIFT_METRICS_DECLARE_COUNTER(MetricPacketsIn, "server_packets_in", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
GAMELIFT_METRICS_DECLARE_COUNTER(MetricPacketsInLost, "server_packets_in_lost", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
|
||||
GAMELIFT_METRICS_DECLARE_COUNTER(MetricPacketsOut, "server_packets_out", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
GAMELIFT_METRICS_DECLARE_COUNTER(MetricPacketsOutLost, "server_packets_out_lost", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FNetworkStats
|
||||
{
|
||||
public:
|
||||
FNetworkStats();
|
||||
|
||||
void Collect();
|
||||
|
||||
private:
|
||||
const UNetDriver* GetNetDriver() const;
|
||||
|
||||
private:
|
||||
int32 LastInBytes = 0;
|
||||
int32 LastOutBytes = 0;
|
||||
int32 LastInPackets = 0;
|
||||
int32 LastOutPackets = 0;
|
||||
int32 LastInPacketsLost = 0;
|
||||
int32 LastOutPacketsLost = 0;
|
||||
};
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "TickableCollector.h"
|
||||
#include "TimeStats.h"
|
||||
#include "GameLiftMetrics.h"
|
||||
|
||||
#include "Misc/App.h"
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Metrics {
|
||||
GAMELIFT_METRICS_DEFINE_GAUGE(MetricServerUp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if WITH_GAMELIFT_METRICS
|
||||
void FTickableCollector::Tick(float)
|
||||
{
|
||||
GAMELIFT_METRICS_SET(Aws::GameLift::Metrics::MetricServerUp, 1);
|
||||
|
||||
NetworkStats.Collect();
|
||||
MemoryStats.Collect();
|
||||
|
||||
const double DeltaTime = FApp::GetDeltaTime();
|
||||
GAMELIFT_METRICS_SET_SEC(Aws::GameLift::Metrics::MetricGameDeltaTime, DeltaTime);
|
||||
if (bComputeFallbackGameThreadTime)
|
||||
{
|
||||
const double EstimatedGameThreadTime = DeltaTime - FApp::GetIdleTime();
|
||||
GAMELIFT_METRICS_SET_SEC(Aws::GameLift::Metrics::MetricGameTickTime, EstimatedGameThreadTime);
|
||||
}
|
||||
|
||||
// Re-emit specific metrics so that they don't go stale.
|
||||
// Grafana reports no data for the metric after 5 minutes of it being stale.
|
||||
FGameLiftMetricsModule::Get().ReEmitMetrics();
|
||||
|
||||
Aws::GameLift::Metrics::MetricsProcess();
|
||||
}
|
||||
#else
|
||||
void FTickableCollector::Tick(float) {}
|
||||
#endif // WITH_GAMELIFT_METRICS
|
||||
|
||||
|
||||
TStatId FTickableCollector::GetStatId() const
|
||||
{
|
||||
return TStatId{};
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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 "CoreMinimal.h"
|
||||
#include "Tickable.h"
|
||||
|
||||
#include "GameLiftMetricsTypes.h"
|
||||
|
||||
#include "NetworkStats.h"
|
||||
#include "MemoryStats.h"
|
||||
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Metrics {
|
||||
GAMELIFT_METRICS_DECLARE_GAUGE(MetricServerUp, "server_up", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FTickableCollector : public FTickableGameObject
|
||||
{
|
||||
public:
|
||||
FTickableCollector(bool bComputeFallbackGameThreadTime)
|
||||
: bComputeFallbackGameThreadTime(bComputeFallbackGameThreadTime) {}
|
||||
|
||||
// FTickableGameObject
|
||||
virtual void Tick(float) override;
|
||||
|
||||
virtual bool IsTickable() const override { return true; }
|
||||
|
||||
virtual bool IsTickableWhenPaused() const override { return true; }
|
||||
virtual bool IsTickableInEditor() const override { return false; }
|
||||
virtual ETickableTickType GetTickableTickType() const override { return ETickableTickType::Always; }
|
||||
virtual TStatId GetStatId() const override;
|
||||
// ~FTickableGameObject
|
||||
|
||||
private:
|
||||
bool bComputeFallbackGameThreadTime = false;
|
||||
FNetworkStats NetworkStats;
|
||||
FMemoryStats MemoryStats;
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "TimeStats.h"
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Metrics {
|
||||
GAMELIFT_METRICS_DEFINE_TIMER(MetricGameDeltaTime);
|
||||
|
||||
GAMELIFT_METRICS_DEFINE_TIMER(MetricGameTickTime);
|
||||
GAMELIFT_METRICS_DEFINE_TIMER(MetricWorldTickTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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 "GameLiftMetricsTypes.h"
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Metrics {
|
||||
/**
|
||||
* Server time-step in milliseconds.
|
||||
*
|
||||
* This is the time between consecutive ticks.
|
||||
*
|
||||
* When the server is under performing, this will exceed the target tick rate,
|
||||
* otherwise it should hover in its vicinity.
|
||||
*
|
||||
* To compute the tick rate, compute the reciprocal: (1000 / server_delta_time)
|
||||
*/
|
||||
GAMELIFT_METRICS_DECLARE_TIMER(
|
||||
MetricGameDeltaTime, "server_delta_time",
|
||||
Aws::GameLift::Metrics::Server,
|
||||
Aws::GameLift::Metrics::SampleAll(),
|
||||
Aws::GameLift::Metrics::Percentiles(0.5, 0.9, 0.95)
|
||||
);
|
||||
|
||||
/**
|
||||
* The time it takes to process a single tick.
|
||||
*
|
||||
* A subset of delta time.
|
||||
* server_tick_time <= server_delta_time at all times. Typically (much) smaller.
|
||||
*
|
||||
* This is the time it takes to actually process the tick. The remaining
|
||||
* time-step duration is spent waiting for the next tick.
|
||||
*/
|
||||
GAMELIFT_METRICS_DECLARE_TIMER(
|
||||
MetricGameTickTime, "server_tick_time",
|
||||
Aws::GameLift::Metrics::Server,
|
||||
Aws::GameLift::Metrics::SampleAll(),
|
||||
Aws::GameLift::Metrics::Percentiles(0.5, 0.9, 0.95)
|
||||
);
|
||||
|
||||
/**
|
||||
* The time it takes to process the world update.
|
||||
*
|
||||
* A subset of tick time.
|
||||
*
|
||||
* This is the time it takes to process the Actors and Blueprints in the
|
||||
* currently loaded Map. The remainder of server_tick_time is spent in
|
||||
* other engine subsystems like network replication or physics.
|
||||
*
|
||||
* Only available in Debug or Development builds, or Shipping builds with
|
||||
* USE_FORCE_STATS=1.
|
||||
*/
|
||||
GAMELIFT_METRICS_DECLARE_TIMER(
|
||||
MetricWorldTickTime,
|
||||
"server_world_tick_time",
|
||||
Aws::GameLift::Metrics::Server,
|
||||
Aws::GameLift::Metrics::SampleAll(),
|
||||
Aws::GameLift::Metrics::Percentiles(0.5, 0.9, 0.95)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "UnrealStatCollector.h"
|
||||
|
||||
#include "Runtime/Launch/Resources/Version.h"
|
||||
|
||||
#include "TimeStats.h"
|
||||
|
||||
#include "Async/TaskGraphInterfaces.h"
|
||||
#include "Stats/Stats.h"
|
||||
#include "Stats/StatsData.h"
|
||||
#include "EngineStats.h"
|
||||
|
||||
|
||||
#if STATS
|
||||
namespace
|
||||
{
|
||||
#if ENGINE_MAJOR_VERSION >= 5
|
||||
void IncrementStatsRefCount()
|
||||
{
|
||||
StatsPrimaryEnableAdd();
|
||||
}
|
||||
|
||||
void DecrementStatsRefCount()
|
||||
{
|
||||
StatsPrimaryEnableSubtract();
|
||||
}
|
||||
#else
|
||||
void IncrementStatsRefCount()
|
||||
{
|
||||
StatsMasterEnableAdd();
|
||||
}
|
||||
|
||||
void DecrementStatsRefCount()
|
||||
{
|
||||
StatsMasterEnableSubtract();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void FUnrealStatCollector::Subscribe()
|
||||
{
|
||||
IncrementStatsRefCount();
|
||||
|
||||
/*
|
||||
* From 5.2.0 onwards, UE_STATS_THREAD_AS_PIPE is undefined and the only way to
|
||||
* access the stat system is via the new API.
|
||||
*
|
||||
* Between 5.0.0 and 5.2.0, UE_STATS_THREAD_AS_PIPE enables new API. If it is 0,
|
||||
* the old API can be used.
|
||||
*
|
||||
* See UE engine source commits 10b5e05d00df4f23d3b75f6af5ec08f8ae0e8618
|
||||
* 327a94d1a4e021714f2c3ca820fe9ed5606465bf
|
||||
* d48f6660b807c7377926cffd12020645f91772f8
|
||||
*
|
||||
* All references to UE_STATS_THREAD_AS_PIPE are removed in
|
||||
* d48f6660b807c7377926cffd12020645f91772f8.
|
||||
*/
|
||||
#if ENGINE_MAJOR_VERSION >= 5 && (ENGINE_MINOR_VERSION >= 2 || UE_STATS_THREAD_AS_PIPE)
|
||||
{
|
||||
auto& StatsState = FStatsThreadState::GetLocalState();
|
||||
StatsState.NewFrameDelegate.AddSP(this, &FUnrealStatCollector::OnNewFrame);
|
||||
}
|
||||
#else
|
||||
FSimpleDelegateGraphTask::CreateAndDispatchWhenReady
|
||||
(
|
||||
FSimpleDelegateGraphTask::FDelegate::CreateLambda(
|
||||
[WeakCollector = TWeakPtr<FUnrealStatCollector>(this->AsShared())]() {
|
||||
if (!WeakCollector.IsValid()) { return; }
|
||||
|
||||
auto& StatsState = FStatsThreadState::GetLocalState();
|
||||
StatsState.NewFrameDelegate.AddSP(WeakCollector.Pin().Get(), &FUnrealStatCollector::OnNewFrame);
|
||||
}
|
||||
),
|
||||
TStatId{},
|
||||
nullptr,
|
||||
/*
|
||||
* StatsThread is deprecated since 5.0
|
||||
*
|
||||
* Need to verify post-5.0 behaviour but:
|
||||
* - 4.27 to 5.0 should use the current method to subscribe to NewFrameDelegate
|
||||
* - 5.0 on can subscribe from game thread directly. (See FThreadStats::bUseThreadAsPipe)
|
||||
*/
|
||||
ENamedThreads::StatsThread
|
||||
);
|
||||
#endif // UE_STATS_THREAD_AS_PIPE
|
||||
}
|
||||
|
||||
void FUnrealStatCollector::Unsubscribe()
|
||||
{
|
||||
DecrementStatsRefCount();
|
||||
}
|
||||
|
||||
void FUnrealStatCollector::OnNewFrame(int64 Frame)
|
||||
{
|
||||
TArray<FStatMessage> OutStats;
|
||||
|
||||
auto& Stats = FStatsThreadState::GetLocalState();
|
||||
Stats.GetInclusiveAggregateStackStats(Frame, OutStats);
|
||||
|
||||
for (auto& Message : OutStats)
|
||||
{
|
||||
// GetShortName() is expensive and we're calling it for every stat.
|
||||
// In practice: we'll stick filter by GetRawName first and stick things in a hashmap
|
||||
// might also be able to compare FName indices
|
||||
FName ShortName = Message.NameAndInfo.GetShortName();
|
||||
|
||||
// Robustness: we can check the value type from message before blindly grabbing duration (or other types)
|
||||
|
||||
// Consult EngineStats.h for stat names
|
||||
// (There's also many other stats in other subsystems.)
|
||||
if (ShortName == TEXT("STAT_GameEngineTick"))
|
||||
{
|
||||
GAMELIFT_METRICS_SET_MS(Aws::GameLift::Metrics::MetricGameTickTime, FPlatformTime::ToMilliseconds(Message.GetValue_Duration()));
|
||||
}
|
||||
else if (ShortName == TEXT("STAT_WorldTickTime"))
|
||||
{
|
||||
GAMELIFT_METRICS_SET_MS(Aws::GameLift::Metrics::MetricWorldTickTime, FPlatformTime::ToMilliseconds(Message.GetValue_Duration()));
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
void FUnrealStatCollector::Subscribe() {}
|
||||
void FUnrealStatCollector::Unsubscribe() {}
|
||||
void FUnrealStatCollector::OnNewFrame(int64 Frame) {}
|
||||
#endif // STATS
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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 "CoreMinimal.h"
|
||||
|
||||
class FUnrealStatCollector : public TSharedFromThis<FUnrealStatCollector>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Subscribes to NewFrameDelegate in Unreal stats system.
|
||||
*/
|
||||
void Subscribe();
|
||||
|
||||
/**
|
||||
* Unsubscribes from NewFrameDelegate in Unreal stats system.
|
||||
*/
|
||||
void Unsubscribe();
|
||||
|
||||
void OnNewFrame(int64 Frame);
|
||||
};
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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 "CoreMinimal.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
#include "GameLiftMetricsTypes.h"
|
||||
|
||||
#include <aws/gamelift/metrics/GameLiftMetrics.h>
|
||||
|
||||
// Forward declarations
|
||||
struct FMetricsParameters;
|
||||
|
||||
class FSocket;
|
||||
class FUnrealStatCollector;
|
||||
class FTickableCollector;
|
||||
class UGameLiftMetricsConfig;
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Server {
|
||||
namespace Model {
|
||||
class GameSession;
|
||||
} // Model
|
||||
} // Server
|
||||
} // GameLift
|
||||
} // Aws
|
||||
|
||||
class GAMELIFTMETRICS_API FGameLiftMetricsModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
// IModuleInterface
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override;
|
||||
|
||||
virtual bool SupportsDynamicReloading() override { return false; }
|
||||
virtual bool SupportsAutomaticShutdown() override { return true; }
|
||||
// ~IModuleInterface
|
||||
|
||||
static FGameLiftMetricsModule& Load();
|
||||
static FGameLiftMetricsModule& Get();
|
||||
static FGameLiftMetricsModule* GetPtr();
|
||||
|
||||
/**
|
||||
* Initialize GameLift Metrics using default configuration. These
|
||||
* may be overriden by environment variables.
|
||||
*/
|
||||
void Initialize();
|
||||
|
||||
/**
|
||||
* Initialize GameLift Metrics with metrics parameters.
|
||||
*
|
||||
* @param metricsParameters Metrics parameters to use.
|
||||
*/
|
||||
void Initialize(const FMetricsParameters& metricsParameters);
|
||||
|
||||
/**
|
||||
* Terminate the GameLift Metrics SDK.
|
||||
*/
|
||||
void Terminate();
|
||||
|
||||
/**
|
||||
* Enable or disable metrics at runtime.
|
||||
* If metrics were previously disabled, this will initialize the metrics system.
|
||||
* If metrics were previously enabled, this will terminate the metrics system.
|
||||
*
|
||||
* @param bEnable Whether to enable or disable metrics
|
||||
* @return True if the operation was successful
|
||||
*/
|
||||
bool SetMetricsEnabled(bool bEnable);
|
||||
|
||||
/**
|
||||
* Check if metrics are currently enabled and running
|
||||
*
|
||||
* @return True if metrics are currently enabled and running
|
||||
*/
|
||||
bool IsMetricsEnabled() const;
|
||||
|
||||
/**
|
||||
* Records a new game session.
|
||||
* Call when starting a new session from the FProcessSettings::OnStartGameSession callback.
|
||||
*/
|
||||
void OnStartGameSession(const Aws::GameLift::Server::Model::GameSession&);
|
||||
|
||||
/**
|
||||
* Records a new player session.
|
||||
*
|
||||
* Call when accepting a player session.
|
||||
*/
|
||||
void OnAcceptPlayerSession();
|
||||
|
||||
/**
|
||||
* Records a removed player session.
|
||||
*
|
||||
* Call when removing a player session.
|
||||
*/
|
||||
void OnRemovePlayerSession();
|
||||
|
||||
private:
|
||||
void StartMetricsCollector();
|
||||
|
||||
TSharedPtr<FSocket> Socket;
|
||||
TUniquePtr<FTickableCollector> Collector;
|
||||
TSharedPtr<FUnrealStatCollector> UnrealStatCollector;
|
||||
static FString CurrentGameSessionId;
|
||||
static FThreadSafeCounter CurrentPlayerCount;
|
||||
bool bMetricsRunning = false; // Tracks if metrics are currently running
|
||||
|
||||
static void CrashHandler(const FGenericCrashContext& Context);
|
||||
|
||||
void ReEmitMetrics();
|
||||
|
||||
friend class FTickableCollector;
|
||||
};
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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 "CoreMinimal.h"
|
||||
|
||||
#include "GameLiftMetricsConfig.generated.h"
|
||||
|
||||
/**
|
||||
* GameLift Metrics module configuration.
|
||||
*
|
||||
* Can be configured in `DefaultGame.ini`:
|
||||
* ```
|
||||
* [/Script/GameLiftMetricsUnreal.GameLiftMetricsConfig]
|
||||
* CollectorHost = "127.0.0.1"
|
||||
* CollectorPort = 8125
|
||||
* MaxPacketSize = 2048
|
||||
* CaptureIntervalSeconds = 10
|
||||
* bEnableMetrics = true
|
||||
* ```
|
||||
*/
|
||||
UCLASS(config=Game, defaultconfig)
|
||||
class GAMELIFTMETRICS_API UGameLiftMetricsConfig : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UGameLiftMetricsConfig() = default;
|
||||
|
||||
/**
|
||||
* Returns the current configuration.
|
||||
*/
|
||||
static const UGameLiftMetricsConfig& Get();
|
||||
|
||||
/**
|
||||
* Whether metrics collection is enabled.
|
||||
* When disabled, no metrics will be collected or sent.
|
||||
*/
|
||||
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category="GameLift Metrics")
|
||||
bool bEnableMetrics = true;
|
||||
|
||||
/**
|
||||
* Host to send metrics to.
|
||||
*/
|
||||
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category="GameLift Metrics")
|
||||
FString CollectorHost = TEXT("127.0.0.1");
|
||||
|
||||
/**
|
||||
* UDP port number to send metrics to.
|
||||
*/
|
||||
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category="GameLift Metrics")
|
||||
int32 CollectorPort = 8125;
|
||||
|
||||
/**
|
||||
* Metrics capture interval before sending data to the collector.
|
||||
*/
|
||||
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category="GameLift Metrics")
|
||||
float CaptureIntervalSeconds = 10.0f;
|
||||
|
||||
/**
|
||||
* Maximum UDP packet size.
|
||||
*
|
||||
* Typical MTU for Internet packets is 1500 bytes.
|
||||
* We set the default to 1472, leaving room for headers.
|
||||
*
|
||||
* For use with collector on same machine or with AWS jumbo packets this value can be bumped up past 1500 bytes.
|
||||
*/
|
||||
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category="GameLift Metrics")
|
||||
int32 MaxPacketSize = 1472;
|
||||
};
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 "CoreMinimal.h"
|
||||
|
||||
#include <aws/gamelift/metrics/GameLiftMetrics.h>
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogGameLiftMetrics, Log, All);
|
||||
|
||||
#define WITH_GAMELIFT_METRICS (WITH_GAMELIFT && UE_SERVER)
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Metrics {
|
||||
/**
|
||||
* Logs in all server builds.
|
||||
*/
|
||||
GAMELIFT_METRICS_DEFINE_PLATFORM_API(GAMELIFTMETRICS_API, Server, WITH_GAMELIFT_METRICS && UE_SERVER);
|
||||
|
||||
/**
|
||||
* Logs in all development or debug server builds.
|
||||
*/
|
||||
GAMELIFT_METRICS_DEFINE_PLATFORM_API(GAMELIFTMETRICS_API, ServerDevelopment, WITH_GAMELIFT_METRICS && UE_SERVER && (UE_BUILD_DEVELOPMENT || UE_BUILD_DEBUG));
|
||||
|
||||
/**
|
||||
* Logs only in debug builds.
|
||||
*/
|
||||
GAMELIFT_METRICS_DEFINE_PLATFORM_API(GAMELIFTMETRICS_API, ServerDebug, WITH_GAMELIFT_METRICS && UE_SERVER && UE_BUILD_DEBUG);
|
||||
} // Metrics
|
||||
} // GameLift
|
||||
} // Aws
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
using UnrealBuildTool;
|
||||
|
||||
|
||||
public class GameLiftServerSDK : ModuleRules
|
||||
{
|
||||
public GameLiftServerSDK(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PrivateDependencyModuleNames.AddRange(new string[] { "Core", "Projects", "OpenSSL" });
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
bEnableExceptions = true;
|
||||
bUseRTTI = true;
|
||||
|
||||
// Disable windows min/max macros
|
||||
PublicDefinitions.Add("NOMINMAX");
|
||||
|
||||
if (Target.Type == TargetRules.TargetType.Server)
|
||||
{
|
||||
PublicDefinitions.Add("WITH_GAMELIFT=1");
|
||||
}
|
||||
else
|
||||
{
|
||||
PublicDefinitions.Add("WITH_GAMELIFT=0");
|
||||
}
|
||||
|
||||
// Isolate asio namespace to improve packaging compatibility with other modules
|
||||
PrivateDefinitions.Add("asio=gamelift_asio");
|
||||
PrivateDefinitions.Add("asio_signal_handler=gamelift_asio_signal_handler");
|
||||
|
||||
PrivateDefinitions.Add("AWS_GAMELIFT_EXPORTS");
|
||||
PrivateDefinitions.Add("ASIO_STANDALONE=1");
|
||||
PublicDefinitions.Add("SPDLOG_NO_EXCEPTIONS");
|
||||
|
||||
// std::invoke_result replaces std::result_of for C++17 and later
|
||||
// Asio only auto-detects this for MSVC, so override for all compilers
|
||||
if (Target.CppStandard >= CppStandardVersion.Cpp17) {
|
||||
PrivateDefinitions.Add("ASIO_HAS_STD_INVOKE_RESULT");
|
||||
}
|
||||
|
||||
PrivateDefinitions.Add("USE_IMPORT_EXPORT=1");
|
||||
if (Target.Platform == UnrealTargetPlatform.Win64)
|
||||
{
|
||||
PrivateDefinitions.Add("_WEBSOCKETPP_CPP11_STRICT_=1");
|
||||
PrivateDefinitions.Add("SPDLOG_WCHAR_TO_UTF8_SUPPORT=1");
|
||||
PrivateDefinitions.AddRange(new string[] {
|
||||
"_WIN32_WINNT_WIN10_TH2=0x0A00",
|
||||
"_WIN32_WINNT_WIN10_RS1=0x0A00",
|
||||
"_WIN32_WINNT_WIN10_RS2=0x0A00",
|
||||
"_WIN32_WINNT_WIN10_RS3=0x0A00",
|
||||
"_WIN32_WINNT_WIN10_RS4=0x0A00",
|
||||
"_WIN32_WINNT_WIN10_RS5=0x0A00",
|
||||
});
|
||||
}
|
||||
else if (Target.Platform == UnrealTargetPlatform.Linux || Target.Platform == UnrealTargetPlatform.LinuxArm64)
|
||||
{
|
||||
PrivateDefinitions.Add("ASIO_DISABLE_CO_AWAIT");
|
||||
PrivateDefinitions.Add("RAPIDJSON_NOMEMBERITERATORCLASS");
|
||||
}
|
||||
|
||||
string SpdlogPath = Path.Combine(ModuleDirectory, "../../ThirdParty/spdlog/include");
|
||||
string SpdlogSrcPath = Path.Combine(ModuleDirectory, "../../ThirdParty/spdlog/src");
|
||||
string RapidJSONPath = Path.Combine(ModuleDirectory, "../../ThirdParty/rapidjson/include");
|
||||
string AsioPath = Path.Combine(ModuleDirectory, "../../ThirdParty/asio/include");
|
||||
string WebSocketPPPath = Path.Combine(ModuleDirectory, "../../ThirdParty/websocketpp");
|
||||
string ConcurrentQueuePath = Path.Combine(ModuleDirectory, "../../ThirdParty/concurrentqueue");
|
||||
|
||||
PublicIncludePaths.Add(SpdlogPath);
|
||||
PublicIncludePaths.Add(SpdlogSrcPath);
|
||||
PrivateIncludePaths.Add(RapidJSONPath);
|
||||
PrivateIncludePaths.Add(AsioPath);
|
||||
PrivateIncludePaths.Add(WebSocketPPPath);
|
||||
PrivateIncludePaths.Add(ConcurrentQueuePath);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,558 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#include "GameLiftServerSDK.h"
|
||||
#include "Core.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
#include "Interfaces/IPluginManager.h"
|
||||
#include <cstdlib>
|
||||
|
||||
#define LOCTEXT_NAMESPACE "FGameLiftServerSDKModule"
|
||||
|
||||
void* FGameLiftServerSDKModule::GameLiftServerSDKLibraryHandle = nullptr;
|
||||
|
||||
static FProcessParameters GameLiftProcessParameters;
|
||||
|
||||
void FGameLiftServerSDKModule::StartupModule()
|
||||
{
|
||||
}
|
||||
|
||||
bool FGameLiftServerSDKModule::LoadDependency(const FString& Dir, const FString& Name, void*& Handle)
|
||||
{
|
||||
FString Lib = Name + TEXT(".") + FPlatformProcess::GetModuleExtension();
|
||||
FString Path = Dir.IsEmpty() ? *Lib : FPaths::Combine(*Dir, *Lib);
|
||||
|
||||
Handle = FPlatformProcess::GetDllHandle(*Path);
|
||||
|
||||
if (Handle == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FGameLiftServerSDKModule::FreeDependency(void*& Handle)
|
||||
{
|
||||
#if !PLATFORM_LINUX
|
||||
if (Handle != nullptr)
|
||||
{
|
||||
FPlatformProcess::FreeDllHandle(Handle);
|
||||
Handle = nullptr;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void FGameLiftServerSDKModule::ShutdownModule()
|
||||
{
|
||||
FreeDependency(GameLiftServerSDKLibraryHandle);
|
||||
}
|
||||
|
||||
FGameLiftStringOutcome FGameLiftServerSDKModule::GetSdkVersion() {
|
||||
#if WITH_GAMELIFT
|
||||
auto outcome = Aws::GameLift::Server::GetSdkVersion();
|
||||
if (outcome.IsSuccess()){
|
||||
return FGameLiftStringOutcome(outcome.GetResult());
|
||||
}
|
||||
else {
|
||||
return FGameLiftStringOutcome(FGameLiftError(outcome.GetError()));
|
||||
}
|
||||
#else
|
||||
return FGameLiftStringOutcome("");
|
||||
#endif
|
||||
}
|
||||
|
||||
FGameLiftGenericOutcome FGameLiftServerSDKModule::InitSDK() {
|
||||
#if WITH_GAMELIFT
|
||||
auto initSDKOutcome = Aws::GameLift::Server::InitSDK();
|
||||
if (initSDKOutcome.IsSuccess()) {
|
||||
return FGameLiftGenericOutcome(nullptr);
|
||||
}
|
||||
else{
|
||||
return FGameLiftGenericOutcome(FGameLiftError(initSDKOutcome.GetError()));
|
||||
}
|
||||
#else
|
||||
return FGameLiftGenericOutcome(nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
FGameLiftGenericOutcome FGameLiftServerSDKModule::InitSDK(const FServerParameters &serverParameters) {
|
||||
#if WITH_GAMELIFT
|
||||
Aws::GameLift::Server::Model::ServerParameters sdkServerParameters;
|
||||
sdkServerParameters.SetWebSocketUrl(TCHAR_TO_UTF8(*serverParameters.m_webSocketUrl));
|
||||
sdkServerParameters.SetFleetId(TCHAR_TO_UTF8(*serverParameters.m_fleetId));
|
||||
sdkServerParameters.SetProcessId(TCHAR_TO_UTF8(*serverParameters.m_processId));
|
||||
sdkServerParameters.SetHostId(TCHAR_TO_UTF8(*serverParameters.m_hostId));
|
||||
sdkServerParameters.SetAuthToken(TCHAR_TO_UTF8(*serverParameters.m_authToken));
|
||||
sdkServerParameters.SetAwsRegion(TCHAR_TO_UTF8(*serverParameters.m_awsRegion));
|
||||
sdkServerParameters.SetAccessKey(TCHAR_TO_UTF8(*serverParameters.m_accessKey));
|
||||
sdkServerParameters.SetSecretKey(TCHAR_TO_UTF8(*serverParameters.m_secretKey));
|
||||
sdkServerParameters.SetSessionToken(TCHAR_TO_UTF8(*serverParameters.m_sessionToken));
|
||||
|
||||
auto initSDKOutcome = Aws::GameLift::Server::InitSDK(sdkServerParameters);
|
||||
if (initSDKOutcome.IsSuccess()) {
|
||||
return FGameLiftGenericOutcome(nullptr);
|
||||
}
|
||||
else{
|
||||
return FGameLiftGenericOutcome(FGameLiftError(initSDKOutcome.GetError()));
|
||||
}
|
||||
#else
|
||||
return FGameLiftGenericOutcome(nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
FGameLiftGenericOutcome FGameLiftServerSDKModule::InitMetrics() {
|
||||
#if WITH_GAMELIFT
|
||||
auto initMetricsOutcome = Aws::GameLift::Server::InitMetrics();
|
||||
if (initMetricsOutcome.IsSuccess()) {
|
||||
return FGameLiftGenericOutcome(nullptr);
|
||||
}
|
||||
else {
|
||||
return FGameLiftGenericOutcome(FGameLiftError(initMetricsOutcome.GetError()));
|
||||
}
|
||||
#else
|
||||
return FGameLiftGenericOutcome(nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
FGameLiftGenericOutcome FGameLiftServerSDKModule::InitMetrics(const FMetricsParameters &metricsParameters) {
|
||||
#if WITH_GAMELIFT
|
||||
Aws::GameLift::Server::MetricsParameters sdkMetricsParameters(
|
||||
TCHAR_TO_UTF8(*metricsParameters.m_statsDHost),
|
||||
metricsParameters.m_statsDPort,
|
||||
TCHAR_TO_UTF8(*metricsParameters.m_crashReporterHost),
|
||||
metricsParameters.m_crashReporterPort,
|
||||
metricsParameters.m_flushIntervalMs,
|
||||
metricsParameters.m_maxPacketSize
|
||||
);
|
||||
|
||||
auto initMetricsOutcome = Aws::GameLift::Server::InitMetrics(sdkMetricsParameters);
|
||||
if (initMetricsOutcome.IsSuccess()) {
|
||||
return FGameLiftGenericOutcome(nullptr);
|
||||
}
|
||||
else {
|
||||
return FGameLiftGenericOutcome(FGameLiftError(initMetricsOutcome.GetError()));
|
||||
}
|
||||
#else
|
||||
return FGameLiftGenericOutcome(nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
FGameLiftGenericOutcome FGameLiftServerSDKModule::ProcessEnding() {
|
||||
#if WITH_GAMELIFT
|
||||
auto outcome = Aws::GameLift::Server::ProcessEnding();
|
||||
if (outcome.IsSuccess()){
|
||||
return FGameLiftGenericOutcome(nullptr);
|
||||
}
|
||||
else {
|
||||
return FGameLiftGenericOutcome(FGameLiftError(outcome.GetError()));
|
||||
}
|
||||
#else
|
||||
return FGameLiftGenericOutcome(nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
FGameLiftGenericOutcome FGameLiftServerSDKModule::ActivateGameSession() {
|
||||
#if WITH_GAMELIFT
|
||||
auto outcome = Aws::GameLift::Server::ActivateGameSession();
|
||||
if (outcome.IsSuccess()){
|
||||
return FGameLiftGenericOutcome(nullptr);
|
||||
}
|
||||
else {
|
||||
return FGameLiftGenericOutcome(FGameLiftError(outcome.GetError()));
|
||||
}
|
||||
#else
|
||||
return FGameLiftGenericOutcome(nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
FGameLiftGenericOutcome FGameLiftServerSDKModule::AcceptPlayerSession(const FString& playerSessionId) {
|
||||
#if WITH_GAMELIFT
|
||||
auto outcome = Aws::GameLift::Server::AcceptPlayerSession(TCHAR_TO_UTF8(*playerSessionId));
|
||||
if (outcome.IsSuccess()){
|
||||
return FGameLiftGenericOutcome(nullptr);
|
||||
}
|
||||
else {
|
||||
return FGameLiftGenericOutcome(FGameLiftError(outcome.GetError()));
|
||||
}
|
||||
#else
|
||||
return FGameLiftGenericOutcome(nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
FGameLiftGenericOutcome FGameLiftServerSDKModule::RemovePlayerSession(const FString& playerSessionId) {
|
||||
#if WITH_GAMELIFT
|
||||
auto outcome = Aws::GameLift::Server::RemovePlayerSession(TCHAR_TO_UTF8(*playerSessionId));
|
||||
if (outcome.IsSuccess()){
|
||||
return FGameLiftGenericOutcome(nullptr);
|
||||
}
|
||||
else {
|
||||
return FGameLiftGenericOutcome(FGameLiftError(outcome.GetError()));
|
||||
}
|
||||
#else
|
||||
return FGameLiftGenericOutcome(nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
FGameLiftGenericOutcome FGameLiftServerSDKModule::Destroy()
|
||||
{
|
||||
#if WITH_GAMELIFT
|
||||
auto outcome = Aws::GameLift::Server::Destroy();
|
||||
if (outcome.IsSuccess()) {
|
||||
return FGameLiftGenericOutcome(nullptr);
|
||||
}
|
||||
else {
|
||||
return FGameLiftGenericOutcome(FGameLiftError(outcome.GetError()));
|
||||
}
|
||||
#else
|
||||
return FGameLiftGenericOutcome(nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
FGameLiftDescribePlayerSessionsOutcome FGameLiftServerSDKModule::DescribePlayerSessions(const FGameLiftDescribePlayerSessionsRequest &describePlayerSessionsRequest)
|
||||
{
|
||||
#if WITH_GAMELIFT
|
||||
Aws::GameLift::Server::Model::DescribePlayerSessionsRequest request;
|
||||
request.SetGameSessionId(TCHAR_TO_UTF8(*describePlayerSessionsRequest.m_gameSessionId));
|
||||
request.SetPlayerId(TCHAR_TO_UTF8(*describePlayerSessionsRequest.m_playerId));
|
||||
request.SetPlayerSessionId(TCHAR_TO_UTF8(*describePlayerSessionsRequest.m_playerSessionId));
|
||||
request.SetPlayerSessionStatusFilter(TCHAR_TO_UTF8(*describePlayerSessionsRequest.m_playerSessionStatusFilter));
|
||||
request.SetLimit(describePlayerSessionsRequest.m_limit);
|
||||
request.SetNextToken(TCHAR_TO_UTF8(*describePlayerSessionsRequest.m_nextToken));
|
||||
|
||||
auto outcome = Aws::GameLift::Server::DescribePlayerSessions(request);
|
||||
|
||||
if (outcome.IsSuccess()) {
|
||||
auto& outres = outcome.GetResult();
|
||||
FGameLiftDescribePlayerSessionsResult result;
|
||||
|
||||
int sessionCount = 0;
|
||||
auto sessions = outres.GetPlayerSessions(sessionCount);
|
||||
if (sessionCount > 0) {
|
||||
TArray<FGameLiftPlayerSession> outSessions;
|
||||
outSessions.Reserve(sessionCount);
|
||||
|
||||
for (int i = 0; i < sessionCount; ++i) {
|
||||
auto session = sessions + i;
|
||||
FGameLiftPlayerSession& outSession = outSessions.AddDefaulted_GetRef();
|
||||
|
||||
outSession.m_playerSessionId = UTF8_TO_TCHAR(session->GetPlayerSessionId());
|
||||
outSession.m_playerId = UTF8_TO_TCHAR(session->GetPlayerId());
|
||||
outSession.m_gameSessionId = UTF8_TO_TCHAR(session->GetGameSessionId());
|
||||
outSession.m_fleetId = UTF8_TO_TCHAR(session->GetFleetId());
|
||||
outSession.m_creationTime = session->GetCreationTime();
|
||||
outSession.m_terminationTime = session->GetTerminationTime();
|
||||
|
||||
switch (session->GetStatus()) {
|
||||
case Aws::GameLift::Server::Model::PlayerSessionStatus::NOT_SET: outSession.m_status = EPlayerSessionStatus::NOT_SET; break;
|
||||
case Aws::GameLift::Server::Model::PlayerSessionStatus::RESERVED: outSession.m_status = EPlayerSessionStatus::RESERVED; break;
|
||||
case Aws::GameLift::Server::Model::PlayerSessionStatus::ACTIVE: outSession.m_status = EPlayerSessionStatus::ACTIVE; break;
|
||||
case Aws::GameLift::Server::Model::PlayerSessionStatus::COMPLETED: outSession.m_status = EPlayerSessionStatus::COMPLETED; break;
|
||||
case Aws::GameLift::Server::Model::PlayerSessionStatus::TIMEDOUT: outSession.m_status = EPlayerSessionStatus::TIMEDOUT; break;
|
||||
}
|
||||
|
||||
outSession.m_ipAddress = UTF8_TO_TCHAR(session->GetIpAddress());
|
||||
outSession.m_port = session->GetPort();
|
||||
|
||||
outSession.m_playerData = UTF8_TO_TCHAR(session->GetPlayerData());
|
||||
outSession.m_dnsName = UTF8_TO_TCHAR(session->GetDnsName());
|
||||
}
|
||||
|
||||
result.m_playerSessions = outSessions;
|
||||
}
|
||||
|
||||
result.m_nextToken = (UTF8_TO_TCHAR(outres.GetNextToken()));
|
||||
|
||||
return FGameLiftDescribePlayerSessionsOutcome(result);
|
||||
}
|
||||
else {
|
||||
return FGameLiftDescribePlayerSessionsOutcome(FGameLiftError(outcome.GetError()));
|
||||
}
|
||||
#else
|
||||
return FGameLiftDescribePlayerSessionsOutcome(FGameLiftDescribePlayerSessionsResult());
|
||||
#endif
|
||||
}
|
||||
|
||||
static void OnActivateFunctionInternal(Aws::GameLift::Server::Model::GameSession gameSession, void* state) {
|
||||
GameLiftProcessParameters.OnActivateFunction(gameSession);
|
||||
}
|
||||
|
||||
static void OnUpdateFunctionInternal(Aws::GameLift::Server::Model::UpdateGameSession updateGameSession, void* state) {
|
||||
GameLiftProcessParameters.OnUpdateFunction(updateGameSession);
|
||||
}
|
||||
|
||||
static void OnTerminateFunctionInternal(void* state) {
|
||||
GameLiftProcessParameters.OnTerminateFunction();
|
||||
}
|
||||
|
||||
static bool OnHealthCheckInternal(void* state) {
|
||||
return GameLiftProcessParameters.OnHealthCheckFunction();
|
||||
}
|
||||
|
||||
FGameLiftGenericOutcome FGameLiftServerSDKModule::ProcessReady(FProcessParameters &processParameters) {
|
||||
#if WITH_GAMELIFT
|
||||
GameLiftProcessParameters = processParameters;
|
||||
|
||||
char logPathsBuffer[MAX_LOG_PATHS][MAX_PATH_LENGTH];
|
||||
const char* logPaths[MAX_LOG_PATHS];
|
||||
|
||||
memset(logPaths, 0, sizeof(logPaths));
|
||||
memset(logPathsBuffer, 0, sizeof(logPathsBuffer));
|
||||
|
||||
//only use the first MAX_LOG_PATHS values (duplicate logic in cpp SDK)
|
||||
int32 numLogs = FMath::Min(processParameters.logParameters.Num(), MAX_LOG_PATHS);
|
||||
|
||||
for (int i = 0; i < numLogs; i++)
|
||||
{
|
||||
FTCHARToUTF8 utf8text(*processParameters.logParameters[i]);
|
||||
if (utf8text.Length() < MAX_PATH_LENGTH)
|
||||
|
||||
{
|
||||
memcpy(logPathsBuffer[i], utf8text.Get(), utf8text.Length());
|
||||
}
|
||||
|
||||
logPaths[i] = logPathsBuffer[i];
|
||||
}
|
||||
|
||||
const TSharedPtr<IPlugin> StandalonePlugin = IPluginManager::Get().FindPlugin(TEXT("GameLiftPlugin"));
|
||||
const TSharedPtr<IPlugin> LightweightPlugin = IPluginManager::Get().FindPlugin(TEXT("GameLiftServerSDK"));
|
||||
|
||||
FString pluginName;
|
||||
FString pluginVersion;
|
||||
|
||||
if (LightweightPlugin.IsValid())
|
||||
{
|
||||
pluginName = LightweightPlugin->GetName();
|
||||
pluginVersion = LightweightPlugin->GetDescriptor().VersionName;
|
||||
|
||||
}
|
||||
else if (StandalonePlugin.IsValid())
|
||||
{
|
||||
pluginName = StandalonePlugin->GetName();
|
||||
pluginVersion = StandalonePlugin->GetDescriptor().VersionName;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FGameLiftGenericOutcome(FGameLiftError(Aws::GameLift::GAMELIFT_ERROR_TYPE::SDK_VERSION_DETECTION_FAILED, "Unknown SDK Tool Name", "Couldn't find the GameLift plugin name or version. "
|
||||
"Please update this code to search for a valid name defined inside GameLift's .uplugin file.")
|
||||
);
|
||||
}
|
||||
|
||||
// Don't use Unreal's FPlatformMisc::SetEnvironmentVar because it uses Windows specific SetEnvironmentVariable API
|
||||
// which doesn't mix with GameLift SDK's use of C++ std::getenv()
|
||||
FString pluginNameEnv = "GAMELIFT_SDK_TOOL_NAME=Unreal" + pluginName;
|
||||
FString pluginVersionEnv = "GAMELIFT_SDK_TOOL_VERSION=" + pluginVersion;
|
||||
|
||||
static std::string pluginNameEnvStr = TCHAR_TO_UTF8(*pluginNameEnv);
|
||||
static std::string pluginVersionEnvStr = TCHAR_TO_UTF8(*pluginVersionEnv);
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
_putenv(pluginNameEnvStr.c_str());
|
||||
_putenv(pluginVersionEnvStr.c_str());
|
||||
#else
|
||||
putenv(const_cast<char*>(pluginNameEnvStr.c_str()));
|
||||
putenv(const_cast<char*>(pluginVersionEnvStr.c_str()));
|
||||
#endif
|
||||
|
||||
Aws::GameLift::Server::ProcessParameters processParams = Aws::GameLift::Server::ProcessParameters(
|
||||
OnActivateFunctionInternal,
|
||||
nullptr,
|
||||
OnUpdateFunctionInternal,
|
||||
nullptr,
|
||||
OnTerminateFunctionInternal,
|
||||
nullptr,
|
||||
OnHealthCheckInternal,
|
||||
nullptr,
|
||||
processParameters.port,
|
||||
Aws::GameLift::Server::LogParameters(logPaths, numLogs)
|
||||
);
|
||||
|
||||
auto outcome = Aws::GameLift::Server::ProcessReady(processParams);
|
||||
if (outcome.IsSuccess()){
|
||||
return FGameLiftGenericOutcome(nullptr);
|
||||
}
|
||||
else {
|
||||
return FGameLiftGenericOutcome(FGameLiftError(outcome.GetError()));
|
||||
}
|
||||
#else
|
||||
return FGameLiftGenericOutcome(nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
FGameLiftGenericOutcome FGameLiftServerSDKModule::UpdatePlayerSessionCreationPolicy(EPlayerSessionCreationPolicy policy)
|
||||
{
|
||||
#if WITH_GAMELIFT
|
||||
Aws::GameLift::Server::Model::PlayerSessionCreationPolicy internalPolicy = Aws::GameLift::Server::Model::PlayerSessionCreationPolicyMapper::GetPlayerSessionCreationPolicyForName(TCHAR_TO_UTF8(*GetNameForPlayerSessionCreationPolicy(policy)));
|
||||
auto outcome = Aws::GameLift::Server::UpdatePlayerSessionCreationPolicy(internalPolicy);
|
||||
if (outcome.IsSuccess()){
|
||||
return FGameLiftGenericOutcome(nullptr);
|
||||
}
|
||||
else {
|
||||
return FGameLiftGenericOutcome(FGameLiftError(outcome.GetError()));
|
||||
}
|
||||
#else
|
||||
return FGameLiftGenericOutcome(nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
FGameLiftStringOutcome FGameLiftServerSDKModule::GetGameSessionId() {
|
||||
#if WITH_GAMELIFT
|
||||
auto outcome = Aws::GameLift::Server::GetGameSessionId();
|
||||
if (outcome.IsSuccess()){
|
||||
return FGameLiftStringOutcome(outcome.GetResult());
|
||||
}
|
||||
else {
|
||||
return FGameLiftStringOutcome(FGameLiftError(outcome.GetError()));
|
||||
}
|
||||
#else
|
||||
return FGameLiftStringOutcome("");
|
||||
#endif
|
||||
}
|
||||
|
||||
FGameLiftLongOutcome FGameLiftServerSDKModule::GetTerminationTime() {
|
||||
#if WITH_GAMELIFT
|
||||
auto outcome = Aws::GameLift::Server::GetTerminationTime();
|
||||
if (outcome.IsSuccess()) {
|
||||
return FGameLiftLongOutcome(outcome.GetResult());
|
||||
}
|
||||
else {
|
||||
return FGameLiftLongOutcome(FGameLiftError(outcome.GetError()));
|
||||
}
|
||||
#else
|
||||
return FGameLiftLongOutcome(-1);
|
||||
#endif
|
||||
}
|
||||
|
||||
FGameLiftStringOutcome FGameLiftServerSDKModule::StartMatchBackfill(const FStartMatchBackfillRequest& request) {
|
||||
#if WITH_GAMELIFT
|
||||
Aws::GameLift::Server::Model::StartMatchBackfillRequest sdkRequest;
|
||||
sdkRequest.SetTicketId(TCHAR_TO_UTF8(*request.m_ticketId));
|
||||
sdkRequest.SetGameSessionArn(TCHAR_TO_UTF8(*request.m_gameSessionArn));
|
||||
sdkRequest.SetMatchmakingConfigurationArn(TCHAR_TO_UTF8(*request.m_matchmakingConfigurationArn));
|
||||
for (auto player : request.m_players) {
|
||||
Aws::GameLift::Server::Model::Player sdkPlayer;
|
||||
sdkPlayer.SetPlayerId(TCHAR_TO_UTF8(*player.m_playerId));
|
||||
sdkPlayer.SetTeam(TCHAR_TO_UTF8(*player.m_team));
|
||||
for (auto entry : player.m_latencyInMs) {
|
||||
sdkPlayer.WithLatencyMs(TCHAR_TO_UTF8(*entry.Key), entry.Value);
|
||||
}
|
||||
|
||||
std::map<std::string, Aws::GameLift::Server::Model::AttributeValue> sdkAttributeMap;
|
||||
for (auto attributeEntry : player.m_playerAttributes) {
|
||||
FAttributeValue value = attributeEntry.Value;
|
||||
Aws::GameLift::Server::Model::AttributeValue attribute;
|
||||
switch (value.m_type)
|
||||
{
|
||||
case FAttributeType::STRING:
|
||||
attribute = Aws::GameLift::Server::Model::AttributeValue(TCHAR_TO_UTF8(*value.m_S));
|
||||
break;
|
||||
case FAttributeType::DOUBLE:
|
||||
attribute = Aws::GameLift::Server::Model::AttributeValue(value.m_N);
|
||||
break;
|
||||
case FAttributeType::STRING_LIST:
|
||||
attribute = Aws::GameLift::Server::Model::AttributeValue::ConstructStringList();
|
||||
for (auto sl : value.m_SL) {
|
||||
attribute.AddString(TCHAR_TO_UTF8(*sl));
|
||||
};
|
||||
break;
|
||||
case FAttributeType::STRING_DOUBLE_MAP:
|
||||
attribute = Aws::GameLift::Server::Model::AttributeValue::ConstructStringDoubleMap();
|
||||
for (auto sdm : value.m_SDM) {
|
||||
attribute.AddStringAndDouble(TCHAR_TO_UTF8(*sdm.Key), sdm.Value);
|
||||
};
|
||||
break;
|
||||
}
|
||||
sdkPlayer.WithPlayerAttribute((TCHAR_TO_UTF8(*attributeEntry.Key)), attribute);
|
||||
}
|
||||
sdkRequest.AddPlayer(sdkPlayer);
|
||||
}
|
||||
auto outcome = Aws::GameLift::Server::StartMatchBackfill(sdkRequest);
|
||||
if (outcome.IsSuccess()) {
|
||||
return FGameLiftStringOutcome(outcome.GetResult().GetTicketId());
|
||||
}
|
||||
else {
|
||||
return FGameLiftStringOutcome(FGameLiftError(outcome.GetError()));
|
||||
}
|
||||
#else
|
||||
return FGameLiftStringOutcome("");
|
||||
#endif
|
||||
}
|
||||
|
||||
FGameLiftGenericOutcome FGameLiftServerSDKModule::StopMatchBackfill(const FStopMatchBackfillRequest& request)
|
||||
{
|
||||
#if WITH_GAMELIFT
|
||||
Aws::GameLift::Server::Model::StopMatchBackfillRequest sdkRequest;
|
||||
sdkRequest.SetTicketId(TCHAR_TO_UTF8(*request.m_ticketId));
|
||||
sdkRequest.SetGameSessionArn(TCHAR_TO_UTF8(*request.m_gameSessionArn));
|
||||
sdkRequest.SetMatchmakingConfigurationArn(TCHAR_TO_UTF8(*request.m_matchmakingConfigurationArn));
|
||||
auto outcome = Aws::GameLift::Server::StopMatchBackfill(sdkRequest);
|
||||
if (outcome.IsSuccess()) {
|
||||
return FGameLiftGenericOutcome(nullptr);
|
||||
}
|
||||
else {
|
||||
return FGameLiftGenericOutcome(FGameLiftError(outcome.GetError()));
|
||||
}
|
||||
#else
|
||||
return FGameLiftGenericOutcome(nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
FGameLiftGetComputeCertificateOutcome FGameLiftServerSDKModule::GetComputeCertificate()
|
||||
{
|
||||
#if WITH_GAMELIFT
|
||||
auto outcome = Aws::GameLift::Server::GetComputeCertificate();
|
||||
if (outcome.IsSuccess()) {
|
||||
auto& outres = outcome.GetResult();
|
||||
FGameLiftGetComputeCertificateResult result;
|
||||
result.m_certificate_path = UTF8_TO_TCHAR(outres.GetCertificatePath());
|
||||
result.m_computeName = UTF8_TO_TCHAR(outres.GetComputeName());
|
||||
return FGameLiftGetComputeCertificateOutcome(result);
|
||||
}
|
||||
else {
|
||||
return FGameLiftGetComputeCertificateOutcome(FGameLiftError(outcome.GetError()));
|
||||
}
|
||||
#else
|
||||
return FGameLiftGetComputeCertificateOutcome(FGameLiftGetComputeCertificateResult());
|
||||
#endif
|
||||
}
|
||||
|
||||
FGameLiftGetFleetRoleCredentialsOutcome FGameLiftServerSDKModule::GetFleetRoleCredentials(const FGameLiftGetFleetRoleCredentialsRequest &request)
|
||||
{
|
||||
#if WITH_GAMELIFT
|
||||
Aws::GameLift::Server::Model::GetFleetRoleCredentialsRequest sdkRequest;
|
||||
sdkRequest.SetRoleArn(TCHAR_TO_UTF8(*request.m_roleArn));
|
||||
sdkRequest.SetRoleSessionName(TCHAR_TO_UTF8(*request.m_roleSessionName));
|
||||
|
||||
auto outcome = Aws::GameLift::Server::GetFleetRoleCredentials(sdkRequest);
|
||||
|
||||
if (outcome.IsSuccess()) {
|
||||
auto& outres = outcome.GetResult();
|
||||
FGameLiftGetFleetRoleCredentialsResult result;
|
||||
result.m_assumedUserRoleArn = UTF8_TO_TCHAR(outres.GetAssumedUserRoleArn());
|
||||
result.m_assumedRoleId = UTF8_TO_TCHAR(outres.GetAssumedRoleId());
|
||||
result.m_accessKeyId = UTF8_TO_TCHAR(outres.GetAccessKeyId());
|
||||
result.m_secretAccessKey = UTF8_TO_TCHAR(outres.GetSecretAccessKey());
|
||||
result.m_sessionToken = UTF8_TO_TCHAR(outres.GetSessionToken());
|
||||
result.m_expiration = FDateTime::FromUnixTimestamp(outres.GetExpiration());
|
||||
return FGameLiftGetFleetRoleCredentialsOutcome(result);
|
||||
}
|
||||
else {
|
||||
return FGameLiftGetFleetRoleCredentialsOutcome(FGameLiftError(outcome.GetError()));
|
||||
}
|
||||
#else
|
||||
return FGameLiftGetFleetRoleCredentialsOutcome(FGameLiftGetFleetRoleCredentialsResult());
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef LOCTEXT_NAMESPACE
|
||||
|
||||
IMPLEMENT_MODULE(FGameLiftServerSDKModule, GameLiftServerSDK)
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/GameLiftCommonState.h>
|
||||
|
||||
using namespace Aws::GameLift;
|
||||
|
||||
// This is a shared pointer because many contexts (DLLs) may point to the same state.
|
||||
Aws::GameLift::Internal::GameLiftCommonState * Aws::GameLift::Internal::GameLiftCommonState::m_instance;
|
||||
|
||||
Aws::GameLift::Internal::GameLiftCommonState::GameLiftCommonState() {}
|
||||
|
||||
Aws::GameLift::Internal::GameLiftCommonState::~GameLiftCommonState() {}
|
||||
|
||||
GenericOutcome Aws::GameLift::Internal::GameLiftCommonState::SetInstance(Aws::GameLift::Internal::GameLiftCommonState *instance) {
|
||||
// If there already is an instance, fail.
|
||||
if (m_instance) {
|
||||
return GenericOutcome(GameLiftError(GAMELIFT_ERROR_TYPE::ALREADY_INITIALIZED));
|
||||
}
|
||||
|
||||
// take ownership of the new instance
|
||||
m_instance = instance;
|
||||
return GenericOutcome(nullptr);
|
||||
}
|
||||
|
||||
Aws::GameLift::Internal::GetInstanceOutcome Aws::GameLift::Internal::GameLiftCommonState::GetInstance() {
|
||||
if (!m_instance) {
|
||||
return Internal::GetInstanceOutcome(GameLiftError(GAMELIFT_ERROR_TYPE::NOT_INITIALIZED));
|
||||
}
|
||||
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
Aws::GameLift::Internal::GetInstanceOutcome Aws::GameLift::Internal::GameLiftCommonState::GetInstance(Aws::GameLift::Internal::GAMELIFT_INTERNAL_STATE_TYPE stateType) {
|
||||
if (!m_instance) {
|
||||
return Internal::GetInstanceOutcome(GameLiftError(GAMELIFT_ERROR_TYPE::NOT_INITIALIZED));
|
||||
}
|
||||
|
||||
if (m_instance->GetStateType() != stateType) {
|
||||
return Internal::GetInstanceOutcome(GameLiftError(GAMELIFT_ERROR_TYPE::INITIALIZATION_MISMATCH));
|
||||
}
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
GenericOutcome Aws::GameLift::Internal::GameLiftCommonState::DestroyInstance() {
|
||||
if (m_instance) {
|
||||
delete m_instance;
|
||||
m_instance = nullptr;
|
||||
return GenericOutcome(nullptr);
|
||||
}
|
||||
return GenericOutcome(GameLiftError(GAMELIFT_ERROR_TYPE::NOT_INITIALIZED));
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/common/GameLiftToolDetector.h>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Common {
|
||||
|
||||
void GameLiftToolDetector::SetGameLiftTool() {
|
||||
static constexpr const char* ENV_VAR_SDK_TOOL_NAME = "GAMELIFT_SDK_TOOL_NAME";
|
||||
static constexpr const char* ENV_VAR_SDK_TOOL_VERSION = "GAMELIFT_SDK_TOOL_VERSION";
|
||||
|
||||
if (!IsToolRunning()) {
|
||||
return;
|
||||
}
|
||||
const char* existingToolName = std::getenv(ENV_VAR_SDK_TOOL_NAME);
|
||||
const char* existingToolVersion = std::getenv(ENV_VAR_SDK_TOOL_VERSION);
|
||||
std::string toolName = GetToolName();
|
||||
std::string toolVersion = GetToolVersion();
|
||||
|
||||
if (existingToolName != nullptr && strlen(existingToolName) > 0) {
|
||||
std::string existingToolNameStr(existingToolName);
|
||||
std::string existingToolVersionStr(existingToolVersion != nullptr ? existingToolVersion : "");
|
||||
if (existingToolNameStr.find(toolName) == std::string::npos) {
|
||||
toolName = existingToolNameStr + "," + toolName;
|
||||
toolVersion = existingToolVersionStr + "," + toolVersion;
|
||||
} else {
|
||||
toolName = existingToolNameStr;
|
||||
toolVersion = existingToolVersionStr;
|
||||
}
|
||||
}
|
||||
#ifdef _WIN32
|
||||
_putenv_s(ENV_VAR_SDK_TOOL_NAME, toolName.c_str());
|
||||
_putenv_s(ENV_VAR_SDK_TOOL_VERSION, toolVersion.c_str());
|
||||
#else
|
||||
setenv(ENV_VAR_SDK_TOOL_NAME, toolName.c_str(), 1);
|
||||
setenv(ENV_VAR_SDK_TOOL_VERSION, toolVersion.c_str(), 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace Common
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/common/MetricsDetector.h>
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Common {
|
||||
|
||||
bool MetricsDetector::IsToolRunning() {
|
||||
try {
|
||||
#ifdef _WIN32
|
||||
std::string windowsServiceArgs = std::string(WINDOWS_SERVICE_ARGS) + WINDOWS_SERVICE_NAME;
|
||||
return CheckService(WINDOWS_SERVICE_COMMAND, windowsServiceArgs, [](const std::string& output) {
|
||||
return output.find(WINDOWS_RUNNING_STATUS) != std::string::npos;
|
||||
});
|
||||
#else
|
||||
std::string linuxServiceArgs = std::string(LINUX_SERVICE_ARGS) + LINUX_SERVICE_NAME;
|
||||
return CheckService(LINUX_SERVICE_COMMAND, linuxServiceArgs, [](const std::string& output) {
|
||||
std::string trimmedOutput = output;
|
||||
// Trim whitespace
|
||||
trimmedOutput.erase(trimmedOutput.find_last_not_of(" \n\r\t") + 1);
|
||||
trimmedOutput.erase(0, trimmedOutput.find_first_not_of(" \n\r\t"));
|
||||
return trimmedOutput == LINUX_ACTIVE_STATUS;
|
||||
});
|
||||
#endif
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool MetricsDetector::CheckService(const std::string& command, const std::string& arguments, std::function<bool(const std::string&)> outputValidator) {
|
||||
std::string fullCommand = command + " " + arguments;
|
||||
|
||||
#ifdef _WIN32
|
||||
FILE* pipe = _popen(fullCommand.c_str(), "r");
|
||||
#else
|
||||
FILE* pipe = popen(fullCommand.c_str(), "r");
|
||||
#endif
|
||||
|
||||
if (!pipe) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string result;
|
||||
char buffer[128];
|
||||
while (fgets(buffer, sizeof(buffer), pipe) != nullptr) {
|
||||
result.append(buffer);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
int exitCode = _pclose(pipe);
|
||||
#else
|
||||
int exitCode = pclose(pipe);
|
||||
#endif
|
||||
|
||||
return exitCode == 0 && outputValidator(result);
|
||||
}
|
||||
|
||||
std::string MetricsDetector::GetToolName() {
|
||||
return TOOL_NAME;
|
||||
}
|
||||
|
||||
std::string MetricsDetector::GetToolVersion() {
|
||||
return TOOL_VERSION;
|
||||
}
|
||||
|
||||
} // namespace Common
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/model/Message.h>
|
||||
#include <aws/gamelift/internal/util/JsonHelper.h>
|
||||
#include <aws/gamelift/internal/util/RandomStringGenerator.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
|
||||
std::string Message::Serialize() const {
|
||||
// Create the buffer & Writer for the object
|
||||
rapidjson::StringBuffer buffer;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
|
||||
|
||||
// Start the object and call Serialize to serialize.
|
||||
writer.StartObject();
|
||||
if (Serialize(&writer)) {
|
||||
writer.EndObject();
|
||||
return buffer.GetString();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
bool Message::Deserialize(const std::string &jsonString) {
|
||||
// Parse the json into a document
|
||||
rapidjson::Document doc;
|
||||
if (doc.Parse(jsonString.c_str()).HasParseError()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Call Deserialize to populate the object's member variables
|
||||
return Deserialize(doc);
|
||||
}
|
||||
|
||||
bool Message::Serialize(rapidjson::Writer<rapidjson::StringBuffer> *writer) const {
|
||||
JsonHelper::WriteNonEmptyString(writer, ACTION, m_action);
|
||||
JsonHelper::WriteNonEmptyString(writer, REQUEST_ID, m_requestId);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Message::Deserialize(const rapidjson::Value &value) {
|
||||
m_action = JsonHelper::SafelyDeserializeString(value, ACTION);
|
||||
m_requestId = JsonHelper::SafelyDeserializeString(value, REQUEST_ID);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const Message &message) {
|
||||
os << message.Serialize();
|
||||
return os;
|
||||
}
|
||||
|
||||
std::string Message::GenerateRandomRequestId() { return RandomStringGenerator::GenerateRandomAlphaNumericString(32); }
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/model/ResponseMessage.h>
|
||||
#include <aws/gamelift/internal/util/JsonHelper.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
bool ResponseMessage::Serialize(rapidjson::Writer<rapidjson::StringBuffer> *writer) const {
|
||||
Message::Serialize(writer);
|
||||
JsonHelper::WritePositiveInt(writer, STATUS_CODE, m_statusCode);
|
||||
JsonHelper::WriteNonEmptyString(writer, ERROR_MESSAGE, m_errorMessage);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ResponseMessage::Deserialize(const rapidjson::Value &value) {
|
||||
Message::Deserialize(value);
|
||||
m_statusCode = JsonHelper::SafelyDeserializeInt(value, STATUS_CODE);
|
||||
m_errorMessage = JsonHelper::SafelyDeserializeString(value, ERROR_MESSAGE);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const ResponseMessage &responseMessage) {
|
||||
const Message *message = &responseMessage;
|
||||
os << message->Serialize();
|
||||
return os;
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/model/Uri.h>
|
||||
#include <sstream>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
|
||||
Uri::UriBuilder &Uri::UriBuilder::AddQueryParam(const std::string &key, const std::string &value) {
|
||||
m_queryParams[key] = value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Uri::UriBuilder &Uri::UriBuilder::WithBaseUri(const std::string &baseUriString) {
|
||||
m_baseUriString = baseUriString;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Uri Uri::UriBuilder::Build() const { return Uri(m_baseUriString, m_queryParams); }
|
||||
|
||||
Uri::Uri(const std::string &baseUriString, const std::map<std::string, std::string> &queryMap) : m_baseUriString(baseUriString), m_queryMap(queryMap) {
|
||||
SetQueryString(queryMap);
|
||||
m_uriString = m_baseUriString + m_queryString;
|
||||
}
|
||||
|
||||
void Uri::SetQueryString(const std::map<std::string, std::string> &queryMap) {
|
||||
std::ostringstream queryStringStream;
|
||||
queryStringStream << "?";
|
||||
for (auto const &queryPair : queryMap) {
|
||||
// All but first param requires "&" delimiter
|
||||
if (queryStringStream.str().size() != 1) {
|
||||
queryStringStream << "&";
|
||||
}
|
||||
queryStringStream << queryPair.first << "=" << queryPair.second;
|
||||
}
|
||||
m_queryString = queryStringStream.str();
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const Uri &uri) {
|
||||
os << uri.GetUriString();
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/model/WebSocketAttributeValue.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
|
||||
std::string WebSocketAttributeValue::Serialize() const {
|
||||
// Create the buffer & Writer for the object
|
||||
rapidjson::StringBuffer buffer;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
|
||||
|
||||
// Start the object and call Serialize to serialize.
|
||||
writer.StartObject();
|
||||
if (Serialize(&writer)) {
|
||||
writer.EndObject();
|
||||
return buffer.GetString();
|
||||
}
|
||||
spdlog::warn("Could not parse into WebSocketAttributeValue");
|
||||
return "";
|
||||
}
|
||||
|
||||
bool WebSocketAttributeValue::Deserialize(const std::string &jsonString) {
|
||||
// Parse the json into a document
|
||||
rapidjson::Document doc;
|
||||
if (doc.Parse(jsonString.c_str()).HasParseError()) {
|
||||
spdlog::error("WebSocketAttributeValue: Parse error found for: {}", jsonString);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Call Deserialize to populate the object's member variables
|
||||
return Deserialize(doc);
|
||||
}
|
||||
|
||||
bool WebSocketAttributeValue::Serialize(rapidjson::Writer<rapidjson::StringBuffer> *writer) const {
|
||||
|
||||
writer->String(ATTR_TYPE);
|
||||
writer->String(GetAttributeTypeAsString().c_str());
|
||||
|
||||
switch (m_attrType) {
|
||||
case WebSocketAttrType::STRING:
|
||||
writer->String(S);
|
||||
writer->String(m_S.c_str());
|
||||
break;
|
||||
case WebSocketAttrType::DOUBLE:
|
||||
writer->String(N);
|
||||
writer->Double(m_N);
|
||||
break;
|
||||
case WebSocketAttrType::STRING_LIST:
|
||||
writer->String(SL);
|
||||
writer->StartArray();
|
||||
for (auto it = m_SL.begin(); it != m_SL.end(); ++it) {
|
||||
writer->String(it->c_str());
|
||||
}
|
||||
writer->EndArray();
|
||||
break;
|
||||
case WebSocketAttrType::STRING_DOUBLE_MAP:
|
||||
writer->String(SDM);
|
||||
writer->StartObject();
|
||||
for (auto const &property : m_SDM) {
|
||||
writer->String(property.first.c_str());
|
||||
writer->Double(property.second);
|
||||
}
|
||||
writer->EndObject();
|
||||
break;
|
||||
default:
|
||||
// Do Nothing
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebSocketAttributeValue::Deserialize(const rapidjson::Value &value) {
|
||||
std::string attrString = value.HasMember(ATTR_TYPE) ? value[ATTR_TYPE].GetString() : "";
|
||||
SetAttributeType(attrString);
|
||||
|
||||
switch (m_attrType) {
|
||||
case WebSocketAttrType::STRING:
|
||||
m_S = value.HasMember(S) ? value[S].GetString() : "";
|
||||
break;
|
||||
case WebSocketAttrType::DOUBLE:
|
||||
m_N = value.HasMember(N) ? value[N].GetDouble() : 0;
|
||||
break;
|
||||
case WebSocketAttrType::STRING_LIST:
|
||||
if (value.HasMember(SL)) {
|
||||
const rapidjson::Value &slValue = value[SL];
|
||||
std::vector<std::string> sl;
|
||||
for (rapidjson::SizeType i = 0; i < slValue.GetArray().Size(); i++) {
|
||||
sl.push_back(slValue.GetArray()[i].GetString());
|
||||
}
|
||||
m_SL = sl;
|
||||
}
|
||||
break;
|
||||
case WebSocketAttrType::STRING_DOUBLE_MAP:
|
||||
if (value.HasMember(SDM)) {
|
||||
const rapidjson::Value &sdmValue = value[SDM];
|
||||
std::map<std::string, double> sdm;
|
||||
for (rapidjson::Value::ConstMemberIterator iter = sdmValue.MemberBegin(); iter != sdmValue.MemberEnd(); ++iter) {
|
||||
sdm[iter->name.GetString()] = iter->value.GetDouble();
|
||||
}
|
||||
m_SDM = sdm;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Do Nothing
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/model/WebSocketGameSession.h>
|
||||
#include <aws/gamelift/internal/util/JsonHelper.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
|
||||
std::string WebSocketGameSession::Serialize() const {
|
||||
// Create the buffer & Writer for the object
|
||||
rapidjson::StringBuffer buffer;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
|
||||
|
||||
// Start the object and call Serialize to serialize.
|
||||
writer.StartObject();
|
||||
if (Serialize(&writer)) {
|
||||
writer.EndObject();
|
||||
return buffer.GetString();
|
||||
}
|
||||
spdlog::warn("Could not parse into WebSocketGameSession");
|
||||
return "";
|
||||
}
|
||||
|
||||
bool WebSocketGameSession::Deserialize(const std::string &jsonString) {
|
||||
// Parse the json into a document
|
||||
rapidjson::Document doc;
|
||||
if (doc.Parse(jsonString.c_str()).HasParseError()) {
|
||||
spdlog::error("WebSocketGameSession: Parse error found for: {}", jsonString);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Call Deserialize to populate the object's member variables
|
||||
return Deserialize(doc);
|
||||
}
|
||||
|
||||
bool WebSocketGameSession::Serialize(rapidjson::Writer<rapidjson::StringBuffer> *writer) const {
|
||||
JsonHelper::WriteNonEmptyString(writer, GAME_SESSION_ID, m_gameSessionId);
|
||||
JsonHelper::WriteNonEmptyString(writer, NAME, m_name);
|
||||
JsonHelper::WriteNonEmptyString(writer, FLEET_ID, m_fleetId);
|
||||
JsonHelper::WriteNonEmptyString(writer, GAME_SESSION_DATA, m_gameSessionData);
|
||||
JsonHelper::WriteNonEmptyString(writer, MATCHMAKER_DATA, m_matchmakerData);
|
||||
JsonHelper::WriteNonEmptyString(writer, DNS_NAME, m_dnsName);
|
||||
JsonHelper::WriteNonEmptyString(writer, IP_ADDRESS, m_ipAddress);
|
||||
JsonHelper::WritePositiveInt(writer, MAXIMUM_PLAYER_SESSION_COUNT, m_maximumPlayerSessionCount);
|
||||
JsonHelper::WritePositiveInt(writer, PORT, m_port);
|
||||
|
||||
writer->String(GAME_PROPERTIES);
|
||||
writer->StartObject();
|
||||
for (auto const &property : m_gameProperties) {
|
||||
writer->String(property.first.c_str());
|
||||
writer->String(property.second.c_str());
|
||||
}
|
||||
writer->EndObject();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebSocketGameSession::Deserialize(const rapidjson::Value &value) {
|
||||
m_gameSessionId = JsonHelper::SafelyDeserializeString(value, GAME_SESSION_ID);
|
||||
m_name = JsonHelper::SafelyDeserializeString(value, NAME);
|
||||
m_fleetId = JsonHelper::SafelyDeserializeString(value, FLEET_ID);
|
||||
m_gameSessionData = JsonHelper::SafelyDeserializeString(value, GAME_SESSION_DATA);
|
||||
m_matchmakerData = JsonHelper::SafelyDeserializeString(value, MATCHMAKER_DATA);
|
||||
m_dnsName = JsonHelper::SafelyDeserializeString(value, DNS_NAME);
|
||||
m_ipAddress = JsonHelper::SafelyDeserializeString(value, IP_ADDRESS);
|
||||
|
||||
m_maximumPlayerSessionCount = JsonHelper::SafelyDeserializeInt(value, MAXIMUM_PLAYER_SESSION_COUNT);
|
||||
m_port = JsonHelper::SafelyDeserializeInt(value, PORT);
|
||||
|
||||
if (value.HasMember(GAME_PROPERTIES) && !value[GAME_PROPERTIES].IsNull()) {
|
||||
for (auto itr = value[GAME_PROPERTIES].MemberBegin(); itr != value[GAME_PROPERTIES].MemberEnd(); ++itr) {
|
||||
if (itr->name.IsString() && itr->value.IsString()) {
|
||||
m_gameProperties[itr->name.GetString()] = itr->value.GetString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const WebSocketGameSession &gameSession) {
|
||||
const WebSocketGameSession *message = &gameSession;
|
||||
os << message->Serialize();
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/model/WebSocketPlayer.h>
|
||||
#include <aws/gamelift/internal/util/JsonHelper.h>
|
||||
#include <iostream>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wshadow" // Ignore shadow variable warning for Linux/Mac
|
||||
#endif
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
|
||||
std::string WebSocketPlayer::Serialize() const {
|
||||
// Create the buffer & Writer for the object
|
||||
rapidjson::StringBuffer buffer;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
|
||||
|
||||
// Start the object and call Serialize to serialize.
|
||||
writer.StartObject();
|
||||
if (Serialize(&writer)) {
|
||||
writer.EndObject();
|
||||
return buffer.GetString();
|
||||
}
|
||||
spdlog::warn("Could not parse into WebSocketPlayer");
|
||||
return "";
|
||||
}
|
||||
|
||||
bool WebSocketPlayer::Deserialize(const std::string &jsonString) {
|
||||
// Parse the json into a document
|
||||
rapidjson::Document doc;
|
||||
if (doc.Parse(jsonString.c_str()).HasParseError()) {
|
||||
spdlog::error("WebSocketPlayer: Parse error found for: {}", jsonString);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Call Deserialize to populate the object's member variables
|
||||
return Deserialize(doc);
|
||||
}
|
||||
|
||||
bool WebSocketPlayer::Serialize(rapidjson::Writer<rapidjson::StringBuffer> *writer) const {
|
||||
|
||||
JsonHelper::WriteNonEmptyString(writer, PLAYER_ID, m_playerId);
|
||||
|
||||
writer->String(PLAYER_ATTRIBUTES);
|
||||
writer->StartObject();
|
||||
for (auto const &playerAttributesIter : m_playerAttributes) {
|
||||
writer->String(playerAttributesIter.first.c_str());
|
||||
writer->StartObject();
|
||||
playerAttributesIter.second.Serialize(writer);
|
||||
writer->EndObject();
|
||||
}
|
||||
writer->EndObject();
|
||||
|
||||
writer->String(LATENCY_IN_MS);
|
||||
writer->StartObject();
|
||||
for (auto const &latencyMsIter : m_latencyInMs) {
|
||||
writer->String(latencyMsIter.first.c_str());
|
||||
writer->Int(latencyMsIter.second);
|
||||
}
|
||||
writer->EndObject();
|
||||
|
||||
JsonHelper::WriteNonEmptyString(writer, TEAM, m_team);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebSocketPlayer::Deserialize(const rapidjson::Value &value) {
|
||||
|
||||
m_playerId = JsonHelper::SafelyDeserializeString(value, PLAYER_ID);
|
||||
m_team = JsonHelper::SafelyDeserializeString(value, TEAM);
|
||||
|
||||
if (value.HasMember(PLAYER_ATTRIBUTES) && !value[PLAYER_ATTRIBUTES].IsNull()) {
|
||||
for (auto itr = value[PLAYER_ATTRIBUTES].MemberBegin(); itr != value[PLAYER_ATTRIBUTES].MemberEnd(); ++itr) {
|
||||
if (itr->name.IsString() && !itr->value.IsNull()) {
|
||||
WebSocketAttributeValue value;
|
||||
value.Deserialize(itr->value);
|
||||
m_playerAttributes[itr->name.GetString()] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (value.HasMember(LATENCY_IN_MS) && !value[LATENCY_IN_MS].IsNull()) {
|
||||
for (auto itr = value[LATENCY_IN_MS].MemberBegin(); itr != value[LATENCY_IN_MS].MemberEnd(); ++itr) {
|
||||
if (itr->name.IsString() && itr->value.IsInt()) {
|
||||
m_latencyInMs[itr->name.GetString()] = itr->value.GetInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/model/WebSocketPlayerSession.h>
|
||||
#include <aws/gamelift/internal/util/JsonHelper.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
bool WebSocketPlayerSession::Serialize(rapidjson::Writer<rapidjson::StringBuffer> *writer) const {
|
||||
JsonHelper::WriteNonEmptyString(writer, PLAYER_SESSION_ID, m_playerSessionId);
|
||||
JsonHelper::WriteNonEmptyString(writer, PLAYER_ID, m_playerId);
|
||||
JsonHelper::WriteNonEmptyString(writer, GAME_SESSION_ID, m_gameSessionId);
|
||||
JsonHelper::WriteNonEmptyString(writer, FLEET_ID, m_fleetId);
|
||||
JsonHelper::WritePositiveInt64(writer, CREATION_TIME, m_creationTime);
|
||||
JsonHelper::WritePositiveInt64(writer, TERMINATION_TIME, m_terminationTime);
|
||||
JsonHelper::WriteNonEmptyString(writer, STATUS, WebSocketPlayerSessionStatusMapper::GetNameForStatus(m_status));
|
||||
JsonHelper::WriteNonEmptyString(writer, IP_ADDRESS, m_ipAddress);
|
||||
JsonHelper::WritePositiveInt(writer, PORT, m_port);
|
||||
JsonHelper::WriteNonEmptyString(writer, PLAYER_DATA, m_playerData);
|
||||
JsonHelper::WriteNonEmptyString(writer, DNS_NAME, m_dnsName);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebSocketPlayerSession::Deserialize(const rapidjson::Value &value) {
|
||||
m_playerSessionId = JsonHelper::SafelyDeserializeString(value, PLAYER_SESSION_ID);
|
||||
m_playerId = JsonHelper::SafelyDeserializeString(value, PLAYER_ID);
|
||||
m_gameSessionId = JsonHelper::SafelyDeserializeString(value, GAME_SESSION_ID);
|
||||
m_fleetId = JsonHelper::SafelyDeserializeString(value, FLEET_ID);
|
||||
m_creationTime = JsonHelper::SafelyDeserializeInt64(value, CREATION_TIME);
|
||||
m_terminationTime = JsonHelper::SafelyDeserializeInt64(value, TERMINATION_TIME);
|
||||
m_status = WebSocketPlayerSessionStatusMapper::GetStatusForName(JsonHelper::SafelyDeserializeString(value, STATUS));
|
||||
m_ipAddress = JsonHelper::SafelyDeserializeString(value, IP_ADDRESS);
|
||||
m_port = JsonHelper::SafelyDeserializeInt(value, PORT);
|
||||
m_playerData = JsonHelper::SafelyDeserializeString(value, PLAYER_DATA);
|
||||
m_dnsName = JsonHelper::SafelyDeserializeString(value, DNS_NAME);
|
||||
return true;
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/model/adapter/DescribePlayerSessionsAdapter.h>
|
||||
#include <aws/gamelift/common/GameLift_EXPORTS.h>
|
||||
#include <aws/gamelift/server/model/PlayerSession.h>
|
||||
#include <aws/gamelift/server/model/PlayerSessionStatus.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
Server::Model::DescribePlayerSessionsResult DescribePlayerSessionsAdapter::convert(const WebSocketDescribePlayerSessionsResponse *webSocketResponse) {
|
||||
Server::Model::DescribePlayerSessionsResult result;
|
||||
#ifdef GAMELIFT_USE_STD
|
||||
result.SetNextToken(webSocketResponse->GetNextToken());
|
||||
for (auto &webSocketPlayerSession : webSocketResponse->GetPlayerSessions()) {
|
||||
Server::Model::PlayerSession playerSession =
|
||||
Server::Model::PlayerSession()
|
||||
.WithPlayerSessionId(webSocketPlayerSession.GetPlayerSessionId())
|
||||
.WithPlayerId(webSocketPlayerSession.GetPlayerId())
|
||||
.WithGameSessionId(webSocketPlayerSession.GetGameSessionId())
|
||||
.WithFleetId(webSocketPlayerSession.GetFleetId())
|
||||
.WithCreationTime(webSocketPlayerSession.GetCreationTime())
|
||||
.WithTerminationTime(webSocketPlayerSession.GetTerminationTime())
|
||||
.WithStatus(static_cast<Server::Model::PlayerSessionStatus>(static_cast<int>(webSocketPlayerSession.GetStatus())))
|
||||
.WithIpAddress(webSocketPlayerSession.GetIpAddress())
|
||||
.WithPort(webSocketPlayerSession.GetPort())
|
||||
.WithPlayerData(webSocketPlayerSession.GetPlayerData())
|
||||
.WithDnsName(webSocketPlayerSession.GetDnsName());
|
||||
result.AddPlayerSession(playerSession);
|
||||
}
|
||||
#else
|
||||
result.SetNextToken(webSocketResponse->GetNextToken().c_str());
|
||||
for (auto &webSocketPlayerSession : webSocketResponse->GetPlayerSessions()) {
|
||||
Server::Model::PlayerSession playerSession =
|
||||
Server::Model::PlayerSession()
|
||||
.WithPlayerSessionId(webSocketPlayerSession.GetPlayerSessionId().c_str())
|
||||
.WithPlayerId(webSocketPlayerSession.GetPlayerId().c_str())
|
||||
.WithGameSessionId(webSocketPlayerSession.GetGameSessionId().c_str())
|
||||
.WithFleetId(webSocketPlayerSession.GetFleetId().c_str())
|
||||
.WithCreationTime(webSocketPlayerSession.GetCreationTime())
|
||||
.WithTerminationTime(webSocketPlayerSession.GetTerminationTime())
|
||||
.WithStatus(static_cast<Server::Model::PlayerSessionStatus>(static_cast<int>(webSocketPlayerSession.GetStatus())))
|
||||
.WithIpAddress(webSocketPlayerSession.GetIpAddress().c_str())
|
||||
.WithPort(webSocketPlayerSession.GetPort())
|
||||
.WithPlayerData(webSocketPlayerSession.GetPlayerData().c_str())
|
||||
.WithDnsName(webSocketPlayerSession.GetDnsName().c_str());
|
||||
result.AddPlayerSession(playerSession);
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
WebSocketDescribePlayerSessionsRequest DescribePlayerSessionsAdapter::convert(const Server::Model::DescribePlayerSessionsRequest &request) {
|
||||
return WebSocketDescribePlayerSessionsRequest()
|
||||
.WithGameSessionId(request.GetGameSessionId())
|
||||
.WithPlayerId(request.GetPlayerId())
|
||||
.WithPlayerSessionId(request.GetPlayerSessionId())
|
||||
.WithPlayerSessionStatusFilter(request.GetPlayerSessionStatusFilter())
|
||||
.WithNextToken(request.GetNextToken())
|
||||
.WithLimit(request.GetLimit());
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/model/adapter/GetFleetRoleCredentialsAdapter.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
Server::Model::GetFleetRoleCredentialsResult GetFleetRoleCredentialsAdapter::convert(const WebSocketGetFleetRoleCredentialsResponse *webSocketResponse) {
|
||||
Server::Model::GetFleetRoleCredentialsResult result;
|
||||
|
||||
result.SetAssumedUserRoleArn(webSocketResponse->GetAssumedRoleUserArn().c_str());
|
||||
result.SetAssumedRoleId(webSocketResponse->GetAssumedRoleId().c_str());
|
||||
result.SetAccessKeyId(webSocketResponse->GetAccessKeyId().c_str());
|
||||
result.SetSecretAccessKey(webSocketResponse->GetSecretAccessKey().c_str());
|
||||
result.SetSessionToken(webSocketResponse->GetSessionToken().c_str());
|
||||
// time_t is Unix epoch in seconds, and webSocketResponse->GetExpiration() returns time in milliseconds
|
||||
// This is why we are dividing webSocketResponse->GetExpiration() by 1000
|
||||
int64_t expirationTimeInMilliSeconds = webSocketResponse->GetExpiration();
|
||||
int64_t expirationTimeInSeconds = expirationTimeInMilliSeconds / 1000;
|
||||
result.SetExpiration(static_cast<time_t>(expirationTimeInSeconds));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
WebSocketGetFleetRoleCredentialsRequest GetFleetRoleCredentialsAdapter::convert(const Server::Model::GetFleetRoleCredentialsRequest &request) {
|
||||
return WebSocketGetFleetRoleCredentialsRequest().WithRoleArn(request.GetRoleArn()).WithRoleSessionName(request.GetRoleSessionName());
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/model/adapter/StartMatchBackfillAdapter.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
|
||||
Server::Model::StartMatchBackfillResult StartMatchBackfillAdapter::convert(const WebSocketStartMatchBackfillResponse *webSocketResponse) {
|
||||
Server::Model::StartMatchBackfillResult result;
|
||||
if (webSocketResponse) {
|
||||
result.SetTicketId(webSocketResponse->GetTicketId().c_str());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
WebSocketStartMatchBackfillRequest StartMatchBackfillAdapter::convert(const Server::Model::StartMatchBackfillRequest &request) {
|
||||
std::vector<Server::Model::Player> requestPlayersAsVector;
|
||||
#ifdef GAMELIFT_USE_STD
|
||||
requestPlayersAsVector = request.GetPlayers();
|
||||
#else
|
||||
int countOfPlayers;
|
||||
const Server::Model::Player *requestPlayers = request.GetPlayers(countOfPlayers);
|
||||
for (int i = 0; i < countOfPlayers; i++) {
|
||||
Server::Model::Player playerToStore = *(requestPlayers + i);
|
||||
requestPlayersAsVector.push_back(playerToStore);
|
||||
}
|
||||
#endif
|
||||
std::vector<WebSocketPlayer> players;
|
||||
|
||||
for (auto it = requestPlayersAsVector.begin(); it != requestPlayersAsVector.end(); ++it) {
|
||||
Server::Model::Player playerToConvert = *it;
|
||||
WebSocketPlayer player = WebSocketPlayer()
|
||||
.WithPlayerId(playerToConvert.GetPlayerId())
|
||||
.WithTeam(playerToConvert.GetTeam())
|
||||
.WithPlayerAttributes(fetchAndConvertAttributes(playerToConvert))
|
||||
.WithLatencyInMs(fetchAndConvertLatency(playerToConvert));
|
||||
players.push_back(player);
|
||||
}
|
||||
|
||||
return WebSocketStartMatchBackfillRequest()
|
||||
.WithTicketId(request.GetTicketId())
|
||||
.WithGameSessionArn(request.GetGameSessionArn())
|
||||
.WithMatchmakingConfigurationArn(request.GetMatchmakingConfigurationArn())
|
||||
.WithPlayers(players);
|
||||
}
|
||||
|
||||
std::map<std::string, int> StartMatchBackfillAdapter::fetchAndConvertLatency(const Server::Model::Player &player) {
|
||||
std::map<std::string, int> result;
|
||||
#ifdef GAMELIFT_USE_STD
|
||||
result = player.GetLatencyInMs();
|
||||
#else
|
||||
int countOfLatencies;
|
||||
const Server::Model::Player::RegionAndLatency *regionAndLatency = player.GetLatencyMs(countOfLatencies);
|
||||
for (int i = 0; i < countOfLatencies; i++) {
|
||||
Server::Model::Player::RegionAndLatency latencyToConvert = *(regionAndLatency + i);
|
||||
result[latencyToConvert.GetRegion()] = latencyToConvert.GetLatencyMs();
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::map<std::string, WebSocketAttributeValue> StartMatchBackfillAdapter::fetchAndConvertAttributes(const Server::Model::Player &player) {
|
||||
std::map<std::string, Server::Model::AttributeValue> attrs;
|
||||
#ifdef GAMELIFT_USE_STD
|
||||
attrs = player.GetPlayerAttributes();
|
||||
#else
|
||||
int countOfAttributes;
|
||||
const Server::Model::Player::NamedAttribute *attributes = player.GetPlayerAttributes(countOfAttributes);
|
||||
for (int i = 0; i < countOfAttributes; i++) {
|
||||
Server::Model::Player::NamedAttribute attributeToConvert = *(attributes + i);
|
||||
attrs[attributeToConvert.GetName()] = attributeToConvert.GetValue();
|
||||
}
|
||||
#endif
|
||||
|
||||
std::map<std::string, WebSocketAttributeValue> result;
|
||||
for (auto const &attr : attrs) {
|
||||
Server::Model::AttributeValue attributeValue = attr.second;
|
||||
WebSocketAttributeValue value;
|
||||
switch (attributeValue.GetType()) {
|
||||
case Server::Model::AttributeValue::AttrType::NONE:
|
||||
value.SetAttributeType(WebSocketAttrType::NONE);
|
||||
break;
|
||||
case Server::Model::AttributeValue::AttrType::STRING:
|
||||
value.SetAttributeType(WebSocketAttrType::STRING);
|
||||
value.SetS(attributeValue.GetS());
|
||||
break;
|
||||
case Server::Model::AttributeValue::AttrType::DOUBLE:
|
||||
value.SetAttributeType(WebSocketAttrType::DOUBLE);
|
||||
value.SetN(attributeValue.GetN());
|
||||
break;
|
||||
case Server::Model::AttributeValue::AttrType::STRING_LIST:
|
||||
value.SetAttributeType(WebSocketAttrType::STRING_LIST);
|
||||
value.SetSL(convertStringList(attributeValue));
|
||||
break;
|
||||
case Server::Model::AttributeValue::AttrType::STRING_DOUBLE_MAP:
|
||||
value.SetAttributeType(WebSocketAttrType::STRING_DOUBLE_MAP);
|
||||
value.SetSDM(convertStringDoubleMap(attributeValue));
|
||||
break;
|
||||
default:
|
||||
value.SetAttributeType(WebSocketAttrType::NONE);
|
||||
break;
|
||||
}
|
||||
result[attr.first] = value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::string> StartMatchBackfillAdapter::convertStringList(const Server::Model::AttributeValue &attributeValue) {
|
||||
std::vector<std::string> result;
|
||||
|
||||
#ifdef GAMELIFT_USE_STD
|
||||
result = attributeValue.GetSL();
|
||||
#else
|
||||
int countOfStringList;
|
||||
const Server::Model::AttributeValue::AttributeStringType *stringList = attributeValue.GetSL(countOfStringList);
|
||||
for (int i = 0; i < countOfStringList; i++) {
|
||||
const Server::Model::AttributeValue::AttributeStringType *stringListItemPointer = stringList + i;
|
||||
std::string itemAsString = std::string(*stringListItemPointer);
|
||||
result.push_back(itemAsString);
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::map<std::string, double> StartMatchBackfillAdapter::convertStringDoubleMap(const Server::Model::AttributeValue &attributeValue) {
|
||||
std::map<std::string, double> result;
|
||||
|
||||
#ifdef GAMELIFT_USE_STD
|
||||
result = attributeValue.GetSDM();
|
||||
#else
|
||||
int countOfStringMap;
|
||||
const Server::Model::AttributeValue::KeyAndValue *stringAndDoubleMap = attributeValue.GetSDM(countOfStringMap);
|
||||
for (int i = 0; i < countOfStringMap; i++) {
|
||||
Server::Model::AttributeValue::KeyAndValue keyAndValue = *(stringAndDoubleMap + i);
|
||||
std::string key = std::string(keyAndValue.GetKey());
|
||||
result[key] = keyAndValue.GetValue();
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/model/message/CreateGameSessionMessage.h>
|
||||
#include <aws/gamelift/internal/util/JsonHelper.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
|
||||
bool CreateGameSessionMessage::Serialize(rapidjson::Writer<rapidjson::StringBuffer> *writer) const {
|
||||
Message::Serialize(writer);
|
||||
JsonHelper::WriteNonEmptyString(writer, GAME_SESSION_ID, m_gameSessionId);
|
||||
JsonHelper::WriteNonEmptyString(writer, GAME_SESSION_NAME, m_gameSessionName);
|
||||
JsonHelper::WriteNonEmptyString(writer, GAME_SESSION_DATA, m_gameSessionData);
|
||||
JsonHelper::WriteNonEmptyString(writer, MATCHMAKER_DATA, m_matchmakerData);
|
||||
JsonHelper::WriteNonEmptyString(writer, DNS_NAME, m_dnsName);
|
||||
JsonHelper::WriteNonEmptyString(writer, IP_ADDRESS, m_ipAddress);
|
||||
JsonHelper::WritePositiveInt(writer, MAXIMUM_PLAYER_SESSION_COUNT, m_maximumPlayerSessionCount);
|
||||
JsonHelper::WritePositiveInt(writer, PORT, m_port);
|
||||
|
||||
writer->String(GAME_PROPERTIES);
|
||||
writer->StartObject();
|
||||
for (auto const &property : m_gameProperties) {
|
||||
writer->String(property.first.c_str());
|
||||
writer->String(property.second.c_str());
|
||||
}
|
||||
writer->EndObject();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CreateGameSessionMessage::Deserialize(const rapidjson::Value &value) {
|
||||
Message::Deserialize(value);
|
||||
m_gameSessionId = JsonHelper::SafelyDeserializeString(value, GAME_SESSION_ID);
|
||||
m_gameSessionName = JsonHelper::SafelyDeserializeString(value, GAME_SESSION_NAME);
|
||||
m_gameSessionData = JsonHelper::SafelyDeserializeString(value, GAME_SESSION_DATA);
|
||||
m_matchmakerData = JsonHelper::SafelyDeserializeString(value, MATCHMAKER_DATA);
|
||||
m_dnsName = JsonHelper::SafelyDeserializeString(value, DNS_NAME);
|
||||
m_ipAddress = JsonHelper::SafelyDeserializeString(value, IP_ADDRESS);
|
||||
m_maximumPlayerSessionCount = JsonHelper::SafelyDeserializeInt(value, MAXIMUM_PLAYER_SESSION_COUNT);
|
||||
m_port = JsonHelper::SafelyDeserializeInt(value, PORT);
|
||||
|
||||
if (value.HasMember(GAME_PROPERTIES) && !value[GAME_PROPERTIES].IsNull()) {
|
||||
for (auto itr = value[GAME_PROPERTIES].MemberBegin(); itr != value[GAME_PROPERTIES].MemberEnd(); ++itr) {
|
||||
if (itr->name.IsString() && itr->value.IsString()) {
|
||||
m_gameProperties[itr->name.GetString()] = itr->value.GetString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const CreateGameSessionMessage &createGameSessionMessage) {
|
||||
const Message *message = &createGameSessionMessage;
|
||||
os << message->Serialize();
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/model/message/RefreshConnectionMessage.h>
|
||||
#include <aws/gamelift/internal/util/JsonHelper.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
bool RefreshConnectionMessage::Serialize(rapidjson::Writer<rapidjson::StringBuffer> *writer) const {
|
||||
Message::Serialize(writer);
|
||||
JsonHelper::WriteNonEmptyString(writer, REFRESH_CONNECTION_ENDPOINT, m_refreshConnectionEndpoint);
|
||||
JsonHelper::WriteNonEmptyString(writer, AUTH_TOKEN, m_authToken);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RefreshConnectionMessage::Deserialize(const rapidjson::Value &value) {
|
||||
Message::Deserialize(value);
|
||||
m_refreshConnectionEndpoint = JsonHelper::SafelyDeserializeString(value, REFRESH_CONNECTION_ENDPOINT);
|
||||
m_authToken = JsonHelper::SafelyDeserializeString(value, AUTH_TOKEN);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const RefreshConnectionMessage &refreshConnectionMessage) {
|
||||
const Message *message = &refreshConnectionMessage;
|
||||
os << message->Serialize();
|
||||
return os;
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/model/message/TerminateProcessMessage.h>
|
||||
#include <aws/gamelift/internal/util/JsonHelper.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
|
||||
bool TerminateProcessMessage::Serialize(rapidjson::Writer<rapidjson::StringBuffer> *writer) const {
|
||||
Message::Serialize(writer);
|
||||
JsonHelper::WritePositiveInt64(writer, TERMINATION_TIME, m_terminationTime);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TerminateProcessMessage::Deserialize(const rapidjson::Value &value) {
|
||||
Message::Deserialize(value);
|
||||
m_terminationTime = JsonHelper::SafelyDeserializeInt64(value, TERMINATION_TIME);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const TerminateProcessMessage &terminateProcessMessage) {
|
||||
const Message *message = &terminateProcessMessage;
|
||||
os << message->Serialize();
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/model/message/UpdateGameSessionMessage.h>
|
||||
#include <aws/gamelift/internal/util/JsonHelper.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
|
||||
bool UpdateGameSessionMessage::Serialize(rapidjson::Writer<rapidjson::StringBuffer> *writer) const {
|
||||
Message::Serialize(writer);
|
||||
// Serialize game session object
|
||||
writer->String(GAME_SESSION);
|
||||
writer->StartObject();
|
||||
m_gameSession.Serialize(writer);
|
||||
writer->EndObject();
|
||||
// Serialize update game session fields
|
||||
JsonHelper::WriteNonEmptyString(writer, UPDATE_REASON, m_updateReason);
|
||||
JsonHelper::WriteNonEmptyString(writer, BACKFILL_TICKET_ID, m_backfillTicketId);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UpdateGameSessionMessage::Deserialize(const rapidjson::Value &value) {
|
||||
Message::Deserialize(value);
|
||||
// Deserialize GameSession
|
||||
WebSocketGameSession gameSession;
|
||||
if (value.HasMember(GAME_SESSION) && !value[GAME_SESSION].IsNull()) {
|
||||
gameSession.Deserialize(value[GAME_SESSION]);
|
||||
}
|
||||
m_gameSession = gameSession;
|
||||
// Deserialize rest of fields
|
||||
m_updateReason = JsonHelper::SafelyDeserializeString(value, UPDATE_REASON);
|
||||
m_backfillTicketId = JsonHelper::SafelyDeserializeString(value, BACKFILL_TICKET_ID);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const UpdateGameSessionMessage &updateGameSessionMessage) {
|
||||
const Message *message = &updateGameSessionMessage;
|
||||
os << message->Serialize();
|
||||
return os;
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/model/request/AcceptPlayerSessionRequest.h>
|
||||
#include <aws/gamelift/internal/util/JsonHelper.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
bool AcceptPlayerSessionRequest::Serialize(rapidjson::Writer<rapidjson::StringBuffer> *writer) const {
|
||||
Message::Serialize(writer);
|
||||
JsonHelper::WriteNonEmptyString(writer, GAME_SESSION_ID, m_gameSessionId);
|
||||
JsonHelper::WriteNonEmptyString(writer, PLAYER_SESSION_ID, m_playerSessionId);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AcceptPlayerSessionRequest::Deserialize(const rapidjson::Value &value) {
|
||||
Message::Deserialize(value);
|
||||
m_gameSessionId = JsonHelper::SafelyDeserializeString(value, GAME_SESSION_ID);
|
||||
m_playerSessionId = JsonHelper::SafelyDeserializeString(value, PLAYER_SESSION_ID);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const AcceptPlayerSessionRequest &acceptPlayerSessionRequest) {
|
||||
const Message *message = &acceptPlayerSessionRequest;
|
||||
os << message->Serialize();
|
||||
return os;
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/model/request/ActivateGameSessionRequest.h>
|
||||
#include <aws/gamelift/internal/util/JsonHelper.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
|
||||
ActivateGameSessionRequest::ActivateGameSessionRequest() { SetAction(ACTIVATE_GAME_SESSION); }
|
||||
|
||||
ActivateGameSessionRequest::ActivateGameSessionRequest(std::string gameSessionId) : m_gameSessionId(gameSessionId) { SetAction(ACTIVATE_GAME_SESSION); }
|
||||
|
||||
bool ActivateGameSessionRequest::Serialize(rapidjson::Writer<rapidjson::StringBuffer> *writer) const {
|
||||
Message::Serialize(writer);
|
||||
JsonHelper::WriteNonEmptyString(writer, GAME_SESSION_ID, m_gameSessionId);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ActivateGameSessionRequest::Deserialize(const rapidjson::Value &value) {
|
||||
Message::Deserialize(value);
|
||||
m_gameSessionId = JsonHelper::SafelyDeserializeString(value, GAME_SESSION_ID);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const ActivateGameSessionRequest &activateGameSessionRequest) {
|
||||
const Message *message = &activateGameSessionRequest;
|
||||
os << message->Serialize();
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/model/request/ActivateServerProcessRequest.h>
|
||||
#include <aws/gamelift/internal/util/JsonHelper.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
|
||||
ActivateServerProcessRequest::ActivateServerProcessRequest() : m_port(-1) { SetAction(ACTIVATE_SERVER_PROCESS); }
|
||||
|
||||
ActivateServerProcessRequest::ActivateServerProcessRequest(std::string sdkVersion, std::string sdkLanguage,
|
||||
std::string sdkToolName, std::string sdkToolVersion, int port,
|
||||
const Aws::GameLift::Server::LogParameters &logParameters)
|
||||
: m_sdkVersion(sdkVersion), m_sdkLanguage(sdkLanguage), m_sdkToolName(sdkToolName), m_sdkToolVersion(sdkToolVersion), m_port(port), m_logParameters(logParameters) {
|
||||
SetAction(ACTIVATE_SERVER_PROCESS);
|
||||
};
|
||||
|
||||
bool ActivateServerProcessRequest::Serialize(rapidjson::Writer<rapidjson::StringBuffer> *writer) const {
|
||||
Message::Serialize(writer);
|
||||
JsonHelper::WriteNonEmptyString(writer, SDK_VERSION, m_sdkVersion);
|
||||
JsonHelper::WriteNonEmptyString(writer, SDK_LANGUAGE, m_sdkLanguage);
|
||||
JsonHelper::WriteNonEmptyString(writer, SDK_TOOL_NAME, m_sdkToolName);
|
||||
JsonHelper::WriteNonEmptyString(writer, SDK_TOOL_VERSION, m_sdkToolVersion);
|
||||
JsonHelper::WritePositiveInt(writer, PORT, m_port);
|
||||
JsonHelper::WriteLogParameters(writer, LOG_PATHS, m_logParameters);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ActivateServerProcessRequest::Deserialize(const rapidjson::Value &value) {
|
||||
Message::Deserialize(value);
|
||||
m_sdkVersion = JsonHelper::SafelyDeserializeString(value, SDK_VERSION);
|
||||
m_sdkLanguage = JsonHelper::SafelyDeserializeString(value, SDK_LANGUAGE);
|
||||
m_sdkToolName = JsonHelper::SafelyDeserializeString(value, SDK_TOOL_NAME);
|
||||
m_sdkToolVersion = JsonHelper::SafelyDeserializeString(value, SDK_TOOL_VERSION);
|
||||
m_port = JsonHelper::SafelyDeserializeInt(value, PORT);
|
||||
m_logParameters = JsonHelper::SafelyDeserializeLogParameters(value, LOG_PATHS);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const ActivateServerProcessRequest &activateServerProcessRequest) {
|
||||
const Message *message = &activateServerProcessRequest;
|
||||
os << message->Serialize();
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/model/request/HeartbeatServerProcessRequest.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
|
||||
bool HeartbeatServerProcessRequest::Serialize(rapidjson::Writer<rapidjson::StringBuffer> *writer) const {
|
||||
Message::Serialize(writer);
|
||||
writer->String(HEALTH_STATUS);
|
||||
writer->Bool(m_healthy);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HeartbeatServerProcessRequest::Deserialize(const rapidjson::Value &value) {
|
||||
Message::Deserialize(value);
|
||||
m_healthy = value.HasMember(HEALTH_STATUS) && value[HEALTH_STATUS].IsBool() ? value[HEALTH_STATUS].GetBool() : false;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const HeartbeatServerProcessRequest &heartbeatServerProcessRequest) {
|
||||
const Message *message = &heartbeatServerProcessRequest;
|
||||
os << message->Serialize();
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/model/request/RemovePlayerSessionRequest.h>
|
||||
#include <aws/gamelift/internal/util/JsonHelper.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
bool RemovePlayerSessionRequest::Serialize(rapidjson::Writer<rapidjson::StringBuffer> *writer) const {
|
||||
Message::Serialize(writer);
|
||||
JsonHelper::WriteNonEmptyString(writer, GAME_SESSION_ID, m_gameSessionId);
|
||||
JsonHelper::WriteNonEmptyString(writer, PLAYER_SESSION_ID, m_playerSessionId);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RemovePlayerSessionRequest::Deserialize(const rapidjson::Value &value) {
|
||||
Message::Deserialize(value);
|
||||
m_gameSessionId = JsonHelper::SafelyDeserializeString(value, GAME_SESSION_ID);
|
||||
m_playerSessionId = JsonHelper::SafelyDeserializeString(value, PLAYER_SESSION_ID);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const RemovePlayerSessionRequest &removePlayerSessionRequest) {
|
||||
const Message *message = &removePlayerSessionRequest;
|
||||
os << message->Serialize();
|
||||
return os;
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/model/request/TerminateServerProcessRequest.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
|
||||
TerminateServerProcessRequest::TerminateServerProcessRequest() { SetAction(TERMINATE_SERVER_PROCESS); }
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/model/request/UpdatePlayerSessionCreationPolicyRequest.h>
|
||||
#include <aws/gamelift/internal/util/JsonHelper.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
|
||||
bool UpdatePlayerSessionCreationPolicyRequest::Serialize(rapidjson::Writer<rapidjson::StringBuffer> *writer) const {
|
||||
Message::Serialize(writer);
|
||||
JsonHelper::WriteNonEmptyString(writer, GAME_SESSION_ID, m_gameSessionId);
|
||||
JsonHelper::WriteNonEmptyString(writer, PLAYER_SESSION_POLICY, GetPlayerSessionCreationPolicyAsString());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UpdatePlayerSessionCreationPolicyRequest::Deserialize(const rapidjson::Value &value) {
|
||||
Message::Deserialize(value);
|
||||
m_gameSessionId = JsonHelper::SafelyDeserializeString(value, GAME_SESSION_ID);
|
||||
std::string policyAsString = JsonHelper::SafelyDeserializeString(value, PLAYER_SESSION_POLICY);
|
||||
SetPlayerSessionCreationPolicy(policyAsString);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const UpdatePlayerSessionCreationPolicyRequest &updatePlayerSessionCreationPolicyRequest) {
|
||||
const Message *message = &updatePlayerSessionCreationPolicyRequest;
|
||||
os << message->Serialize();
|
||||
return os;
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/model/request/WebSocketDescribePlayerSessionsRequest.h>
|
||||
#include <aws/gamelift/internal/util/JsonHelper.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
bool WebSocketDescribePlayerSessionsRequest::Serialize(rapidjson::Writer<rapidjson::StringBuffer> *writer) const {
|
||||
Message::Serialize(writer);
|
||||
|
||||
JsonHelper::WriteNonEmptyString(writer, GAME_SESSION_ID, m_gameSessionId);
|
||||
JsonHelper::WriteNonEmptyString(writer, PLAYER_ID, m_playerId);
|
||||
JsonHelper::WriteNonEmptyString(writer, PLAYER_SESSION_ID, m_playerSessionId);
|
||||
JsonHelper::WriteNonEmptyString(writer, PLAYER_SESSION_STATUS_FILTER, m_playerSessionStatusFilter);
|
||||
JsonHelper::WriteNonEmptyString(writer, NEXT_TOKEN, m_nextToken);
|
||||
JsonHelper::WritePositiveInt(writer, LIMIT, m_limit);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebSocketDescribePlayerSessionsRequest::Deserialize(const rapidjson::Value &value) {
|
||||
Message::Deserialize(value);
|
||||
|
||||
m_gameSessionId = JsonHelper::SafelyDeserializeString(value, GAME_SESSION_ID);
|
||||
m_playerId = JsonHelper::SafelyDeserializeString(value, PLAYER_ID);
|
||||
m_playerSessionId = JsonHelper::SafelyDeserializeString(value, PLAYER_SESSION_ID);
|
||||
m_playerSessionStatusFilter = JsonHelper::SafelyDeserializeString(value, PLAYER_SESSION_STATUS_FILTER);
|
||||
m_nextToken = JsonHelper::SafelyDeserializeString(value, NEXT_TOKEN);
|
||||
m_limit = JsonHelper::SafelyDeserializeInt(value, LIMIT);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const WebSocketDescribePlayerSessionsRequest &describePlayerSessionsRequest) {
|
||||
const Message *message = &describePlayerSessionsRequest;
|
||||
os << message->Serialize();
|
||||
return os;
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/model/request/WebSocketGetComputeCertificateRequest.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
bool WebSocketGetComputeCertificateRequest::Serialize(rapidjson::Writer<rapidjson::StringBuffer> *writer) const {
|
||||
Message::Serialize(writer);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebSocketGetComputeCertificateRequest::Deserialize(const rapidjson::Value &value) {
|
||||
Message::Deserialize(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const WebSocketGetComputeCertificateRequest &getComputeCertificateRequest) {
|
||||
const Message *message = &getComputeCertificateRequest;
|
||||
os << message->Serialize();
|
||||
return os;
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/model/request/WebSocketGetFleetRoleCredentialsRequest.h>
|
||||
#include <aws/gamelift/internal/util/JsonHelper.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
bool WebSocketGetFleetRoleCredentialsRequest::Serialize(rapidjson::Writer<rapidjson::StringBuffer> *writer) const {
|
||||
Message::Serialize(writer);
|
||||
|
||||
JsonHelper::WriteNonEmptyString(writer, ROLE_ARN, m_roleArn);
|
||||
JsonHelper::WriteNonEmptyString(writer, ROLE_SESSION_NAME, m_roleSessionName);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebSocketGetFleetRoleCredentialsRequest::Deserialize(const rapidjson::Value &value) {
|
||||
Message::Deserialize(value);
|
||||
|
||||
m_roleArn = JsonHelper::SafelyDeserializeString(value, ROLE_ARN);
|
||||
m_roleSessionName = JsonHelper::SafelyDeserializeString(value, ROLE_SESSION_NAME);
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/model/request/WebSocketStartMatchBackfillRequest.h>
|
||||
#include <aws/gamelift/internal/util/JsonHelper.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
|
||||
WebSocketStartMatchBackfillRequest::WebSocketStartMatchBackfillRequest() { SetAction(ACTION); };
|
||||
|
||||
bool WebSocketStartMatchBackfillRequest::Serialize(rapidjson::Writer<rapidjson::StringBuffer> *writer) const {
|
||||
Message::Serialize(writer);
|
||||
|
||||
JsonHelper::WriteNonEmptyString(writer, TICKET_ID, m_ticketId);
|
||||
JsonHelper::WriteNonEmptyString(writer, GAME_SESSION_ARN, m_gameSessionArn);
|
||||
JsonHelper::WriteNonEmptyString(writer, MATCHMAKING_CONFIGURATION_ARN, m_matchmakingConfigurationArn);
|
||||
|
||||
writer->String(PLAYERS);
|
||||
writer->StartArray();
|
||||
for (const WebSocketPlayer &player : m_players) {
|
||||
writer->StartObject();
|
||||
player.Serialize(writer);
|
||||
writer->EndObject();
|
||||
}
|
||||
writer->EndArray();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebSocketStartMatchBackfillRequest::Deserialize(const rapidjson::Value &value) {
|
||||
Message::Deserialize(value);
|
||||
|
||||
m_ticketId = JsonHelper::SafelyDeserializeString(value, TICKET_ID);
|
||||
m_gameSessionArn = JsonHelper::SafelyDeserializeString(value, GAME_SESSION_ARN);
|
||||
m_matchmakingConfigurationArn = JsonHelper::SafelyDeserializeString(value, MATCHMAKING_CONFIGURATION_ARN);
|
||||
|
||||
m_players.clear();
|
||||
if (value.HasMember(PLAYERS) && !value[PLAYERS].IsNull()) {
|
||||
auto playerList = value[PLAYERS].GetArray();
|
||||
for (rapidjson::SizeType i = 0; i < playerList.Size(); i++) {
|
||||
auto &player = playerList[i];
|
||||
if (!player.IsNull()) {
|
||||
WebSocketPlayer webSocketPlayer;
|
||||
webSocketPlayer.Deserialize(player);
|
||||
m_players.push_back(webSocketPlayer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const WebSocketStartMatchBackfillRequest &startMatchBackfillRequest) {
|
||||
const Message *message = &startMatchBackfillRequest;
|
||||
os << message->Serialize();
|
||||
return os;
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/model/request/WebSocketStopMatchBackfillRequest.h>
|
||||
#include <aws/gamelift/internal/util/JsonHelper.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
|
||||
bool WebSocketStopMatchBackfillRequest::Serialize(rapidjson::Writer<rapidjson::StringBuffer> *writer) const {
|
||||
Message::Serialize(writer);
|
||||
JsonHelper::WriteNonEmptyString(writer, GAME_SESSION_ARN, m_gameSessionArn);
|
||||
JsonHelper::WriteNonEmptyString(writer, MATCHMAKING_CONFIG_ARN, m_matchmakingConfigurationArn);
|
||||
JsonHelper::WriteNonEmptyString(writer, TICKET_ID, m_ticketId);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebSocketStopMatchBackfillRequest::Deserialize(const rapidjson::Value &value) {
|
||||
Message::Deserialize(value);
|
||||
m_gameSessionArn = JsonHelper::SafelyDeserializeString(value, GAME_SESSION_ARN);
|
||||
m_matchmakingConfigurationArn = JsonHelper::SafelyDeserializeString(value, MATCHMAKING_CONFIG_ARN);
|
||||
m_ticketId = JsonHelper::SafelyDeserializeString(value, TICKET_ID);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const WebSocketStopMatchBackfillRequest &stopMatchBackfillMessage) {
|
||||
const Message *message = &stopMatchBackfillMessage;
|
||||
os << message->Serialize();
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/model/response/WebSocketDescribePlayerSessionsResponse.h>
|
||||
#include <aws/gamelift/internal/util/JsonHelper.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
bool WebSocketDescribePlayerSessionsResponse::Serialize(rapidjson::Writer<rapidjson::StringBuffer> *writer) const {
|
||||
Message::Serialize(writer);
|
||||
|
||||
JsonHelper::WriteNonEmptyString(writer, NEXT_TOKEN, m_nextToken);
|
||||
|
||||
writer->String(PLAYER_SESSIONS);
|
||||
writer->StartArray();
|
||||
for (const WebSocketPlayerSession &playerSession : m_playerSessions) {
|
||||
writer->StartObject();
|
||||
playerSession.Serialize(writer);
|
||||
writer->EndObject();
|
||||
}
|
||||
writer->EndArray();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebSocketDescribePlayerSessionsResponse::Deserialize(const rapidjson::Value &value) {
|
||||
Message::Deserialize(value);
|
||||
|
||||
m_nextToken = JsonHelper::SafelyDeserializeString(value, NEXT_TOKEN);
|
||||
m_playerSessions.clear();
|
||||
if (value.HasMember(PLAYER_SESSIONS) && !value[PLAYER_SESSIONS].IsNull()) {
|
||||
auto playerSessions = value[PLAYER_SESSIONS].GetArray();
|
||||
for (rapidjson::SizeType i = 0; i < playerSessions.Size(); i++) {
|
||||
auto &playerSession = playerSessions[i];
|
||||
if (!playerSession.IsNull()) {
|
||||
WebSocketPlayerSession webSocketPlayerSession;
|
||||
webSocketPlayerSession.Deserialize(playerSession);
|
||||
m_playerSessions.push_back(webSocketPlayerSession);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const WebSocketDescribePlayerSessionsResponse &describePlayerSessionsResponse) {
|
||||
const Message *message = &describePlayerSessionsResponse;
|
||||
os << message->Serialize();
|
||||
return os;
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/model/response/WebSocketGetComputeCertificateResponse.h>
|
||||
#include <aws/gamelift/internal/util/JsonHelper.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
bool WebSocketGetComputeCertificateResponse::Serialize(rapidjson::Writer<rapidjson::StringBuffer> *writer) const {
|
||||
Message::Serialize(writer);
|
||||
|
||||
JsonHelper::WriteNonEmptyString(writer, COMPUTE_NAME, m_computeName);
|
||||
JsonHelper::WriteNonEmptyString(writer, CERTIFICATE_PATH, m_certificatePath);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebSocketGetComputeCertificateResponse::Deserialize(const rapidjson::Value &value) {
|
||||
Message::Deserialize(value);
|
||||
|
||||
m_computeName = JsonHelper::SafelyDeserializeString(value, COMPUTE_NAME);
|
||||
m_certificatePath = JsonHelper::SafelyDeserializeString(value, CERTIFICATE_PATH);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const WebSocketGetComputeCertificateResponse &webSocketGetComputeCertificateResponse) {
|
||||
const Message *message = &webSocketGetComputeCertificateResponse;
|
||||
os << message->Serialize();
|
||||
return os;
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/model/response/WebSocketGetFleetRoleCredentialsResponse.h>
|
||||
#include <aws/gamelift/internal/util/JsonHelper.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
bool WebSocketGetFleetRoleCredentialsResponse::Serialize(rapidjson::Writer<rapidjson::StringBuffer> *writer) const {
|
||||
Message::Serialize(writer);
|
||||
|
||||
JsonHelper::WriteNonEmptyString(writer, ASSUMED_ROLE_USER_ARN, m_assumedRoleUserArn);
|
||||
JsonHelper::WriteNonEmptyString(writer, ASSUMED_ROLE_ID, m_assumedRoleId);
|
||||
JsonHelper::WriteNonEmptyString(writer, ACCESS_KEY_ID, m_accessKeyId);
|
||||
JsonHelper::WriteNonEmptyString(writer, SECRET_ACCESS_KEY, m_secretAccessKey);
|
||||
JsonHelper::WriteNonEmptyString(writer, SESSION_TOKEN, m_sessionToken);
|
||||
JsonHelper::WritePositiveInt64(writer, EXPIRATION, m_expiration);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebSocketGetFleetRoleCredentialsResponse::Deserialize(const rapidjson::Value &value) {
|
||||
Message::Deserialize(value);
|
||||
|
||||
m_assumedRoleUserArn = JsonHelper::SafelyDeserializeString(value, ASSUMED_ROLE_USER_ARN);
|
||||
m_assumedRoleId = JsonHelper::SafelyDeserializeString(value, ASSUMED_ROLE_ID);
|
||||
m_accessKeyId = JsonHelper::SafelyDeserializeString(value, ACCESS_KEY_ID);
|
||||
m_secretAccessKey = JsonHelper::SafelyDeserializeString(value, SECRET_ACCESS_KEY);
|
||||
m_sessionToken = JsonHelper::SafelyDeserializeString(value, SESSION_TOKEN);
|
||||
m_expiration = JsonHelper::SafelyDeserializeInt64(value, EXPIRATION);
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/model/response/WebSocketStartMatchBackfillResponse.h>
|
||||
#include <aws/gamelift/internal/util/JsonHelper.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
bool WebSocketStartMatchBackfillResponse::Serialize(rapidjson::Writer<rapidjson::StringBuffer> *writer) const {
|
||||
Message::Serialize(writer);
|
||||
JsonHelper::WriteNonEmptyString(writer, TICKET_ID, m_ticketId);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebSocketStartMatchBackfillResponse::Deserialize(const rapidjson::Value &value) {
|
||||
Message::Deserialize(value);
|
||||
m_ticketId = JsonHelper::SafelyDeserializeString(value, TICKET_ID);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const WebSocketStartMatchBackfillResponse &startMatchBackfillResponse) {
|
||||
const Message *message = &startMatchBackfillResponse;
|
||||
os << message->Serialize();
|
||||
return os;
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/network/GameLiftWebSocketClientManager.h>
|
||||
#include <aws/gamelift/internal/GameLiftServerState.h>
|
||||
|
||||
#include <aws/gamelift/internal/model/response/WebSocketDescribePlayerSessionsResponse.h>
|
||||
#include <aws/gamelift/internal/util/RandomStringGenerator.h>
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
using namespace Aws::GameLift;
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
|
||||
GenericOutcome GameLiftWebSocketClientManager::Connect(std::string websocketUrl, const std::string &authToken, const std::string &processId,
|
||||
const std::string &hostId, const std::string &fleetId, const std::map<std::string, std::string> &sigV4QueryParameters) {
|
||||
spdlog::info("Connecting to GameLift WebSocket server. websocketUrl: {}, processId: {}, hostId: {}, fleetId: {}",
|
||||
websocketUrl.c_str(), processId.c_str(), hostId.c_str(), fleetId.c_str());
|
||||
|
||||
// Due to the websocket library we're using, base URLs must end with a "/". Ensure that it is
|
||||
// present.
|
||||
if (!EndsWith(websocketUrl, REQUIRED_URL_ENDING)) {
|
||||
websocketUrl = websocketUrl + REQUIRED_URL_ENDING;
|
||||
}
|
||||
|
||||
// Build the WebSocket URI
|
||||
std::string sdkVersion = Server::GetSdkVersion().GetResult();
|
||||
std::string idempotencyToken = RandomStringGenerator::GenerateRandomAlphaNumericString(32);
|
||||
Uri::UriBuilder uriBuilder = Uri::UriBuilder()
|
||||
.WithBaseUri(websocketUrl)
|
||||
.AddQueryParam(PID_KEY, processId)
|
||||
.AddQueryParam(SDK_VERSION_KEY, sdkVersion)
|
||||
.AddQueryParam(FLAVOR_KEY, GameLiftServerState::LANGUAGE)
|
||||
.AddQueryParam(COMPUTE_ID_KEY, hostId)
|
||||
.AddQueryParam(FLEET_ID_KEY, fleetId)
|
||||
.AddQueryParam(IDEMPOTENCY_TOKEN_KEY, idempotencyToken);
|
||||
|
||||
if (!authToken.empty()) {
|
||||
uriBuilder.AddQueryParam(AUTH_TOKEN_KEY, authToken);
|
||||
} else if (!sigV4QueryParameters.empty()) {
|
||||
for (auto sigV4QueryParameter: sigV4QueryParameters) {
|
||||
uriBuilder.AddQueryParam(sigV4QueryParameter.first, sigV4QueryParameter.second);
|
||||
}
|
||||
}
|
||||
Uri uri = uriBuilder.Build();
|
||||
|
||||
// delegate to the websocket client wrapper to connect
|
||||
return m_webSocketClientWrapper->Connect(uri);
|
||||
}
|
||||
|
||||
GenericOutcome GameLiftWebSocketClientManager::SendSocketMessage(Message &message) {
|
||||
// Serialize the message
|
||||
std::string jsonMessage = message.Serialize();
|
||||
|
||||
GenericOutcome outcome = m_webSocketClientWrapper->SendSocketMessage(message.GetRequestId(), jsonMessage);
|
||||
return outcome;
|
||||
}
|
||||
|
||||
void GameLiftWebSocketClientManager::Disconnect() { m_webSocketClientWrapper->Disconnect(); }
|
||||
|
||||
bool GameLiftWebSocketClientManager::EndsWith(const std::string &actualString, const std::string &ending) {
|
||||
const int lengthDifference = (int)(actualString.length() - ending.length());
|
||||
if (lengthDifference >= 0) {
|
||||
return actualString.compare(lengthDifference, ending.length(), ending) == 0;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,430 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/network/WebSocketppClientWrapper.h>
|
||||
#include <aws/gamelift/internal/model/Message.h>
|
||||
#include <aws/gamelift/internal/model/ResponseMessage.h>
|
||||
#include <aws/gamelift/internal/retry/GeometricBackoffRetryStrategy.h>
|
||||
#include <aws/gamelift/internal/retry/RetryingCallable.h>
|
||||
#include <memory>
|
||||
#include <websocketpp/error.hpp>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
|
||||
WebSocketppClientWrapper::WebSocketppClientWrapper(std::shared_ptr<WebSocketppClientType> webSocketClient)
|
||||
: m_webSocketClient(webSocketClient), m_connectionStateChanged(false) {
|
||||
// configure logging. comment these out to get websocket logs on stdout for debugging
|
||||
m_webSocketClient->clear_access_channels(websocketpp::log::alevel::all);
|
||||
m_webSocketClient->clear_error_channels(websocketpp::log::elevel::all);
|
||||
|
||||
// initialize ASIO
|
||||
m_webSocketClient->init_asio();
|
||||
|
||||
// start in perpetual mode (do not exit processing loop when there are no connections)
|
||||
m_webSocketClient->start_perpetual();
|
||||
|
||||
// Kick off two threads that will own up to two parallel connections. These threads will live
|
||||
// until the SDK is shutdown and alternate handling connections. If a connection fails to open,
|
||||
// the thread will not hang. Instead, the thread will simply wait for another connection to
|
||||
// appear in queue.
|
||||
//
|
||||
// Flow of logic in the two threads:
|
||||
// --- SDK initialized ---
|
||||
// socket_thread_1: waiting for connection...
|
||||
// socket_thread_2: waiting for connection...
|
||||
// --- Initial connection happens ---
|
||||
// socket_thread_1: handling 1st connection
|
||||
// socket_thread_2: waiting for connection...
|
||||
// --- Connection refresh begins ---
|
||||
// socket_thread_1: finish handling 1st connection messages
|
||||
// socket_thread_2: handling 2nd connection
|
||||
// --- Connection 1 closes ---
|
||||
// socket_thread_1: waiting for connection...
|
||||
// socket_thread_2: handling 2nd connection
|
||||
// --- SDK shut down, and WebSocket client "->stop_perpetual()" is invoked ---
|
||||
// socket_thread_1: No longer waits for a connection, thread ends
|
||||
// socket_thread_2: Finishes handling 2nd connection, then thread ends
|
||||
m_socket_thread_1 = std::unique_ptr<std::thread>(new std::thread([this] { m_webSocketClient->run(); }));
|
||||
m_socket_thread_2 = std::unique_ptr<std::thread>(new std::thread([this] { m_webSocketClient->run(); }));
|
||||
|
||||
// Set callbacks
|
||||
using std::placeholders::_1;
|
||||
using std::placeholders::_2;
|
||||
|
||||
// Set timeout waiting for GameLift websocket server to respond on initial connection.
|
||||
// See: https://github.com/zaphoyd/websocketpp/blob/master/websocketpp/connection.hpp#L501
|
||||
m_webSocketClient->set_open_handshake_timeout(WEBSOCKET_OPEN_HANDSHAKE_TIMEOUT_MILLIS);
|
||||
|
||||
m_webSocketClient->set_tls_init_handler(std::bind(&WebSocketppClientWrapper::OnTlsInit, this, _1));
|
||||
m_webSocketClient->set_open_handler(std::bind(&WebSocketppClientWrapper::OnConnected, this, _1));
|
||||
m_webSocketClient->set_message_handler(std::bind(&WebSocketppClientWrapper::OnMessage, this, _1, _2));
|
||||
m_webSocketClient->set_fail_handler(std::bind(&WebSocketppClientWrapper::OnError, this, _1));
|
||||
m_webSocketClient->set_close_handler(std::bind(&WebSocketppClientWrapper::OnClose, this, _1));
|
||||
m_webSocketClient->set_interrupt_handler(std::bind(&WebSocketppClientWrapper::OnInterrupt, this, _1));
|
||||
}
|
||||
|
||||
WebSocketppClientWrapper::~WebSocketppClientWrapper() {
|
||||
// stop perpetual mode, allowing the websocketClient to destroy itself
|
||||
if (m_webSocketClient) {
|
||||
m_webSocketClient->stop_perpetual();
|
||||
}
|
||||
|
||||
spdlog::info("Destroying WebsocketPPClientWrapper");
|
||||
// close connections and join the thread
|
||||
if (m_connection && m_connection->get_state() == websocketpp::session::state::open) {
|
||||
Disconnect();
|
||||
}
|
||||
if (m_socket_thread_1 && m_socket_thread_1->joinable()) {
|
||||
m_socket_thread_1->join();
|
||||
}
|
||||
if (m_socket_thread_2 && m_socket_thread_2->joinable()) {
|
||||
m_socket_thread_2->join();
|
||||
}
|
||||
}
|
||||
|
||||
GenericOutcome WebSocketppClientWrapper::Connect(const Uri &uri) {
|
||||
spdlog::info("Opening Connection");
|
||||
// Perform connection with retries.
|
||||
// This attempts to start up a new websocket connection / thread
|
||||
m_uri = uri;
|
||||
websocketpp::lib::error_code errorCode;
|
||||
GeometricBackoffRetryStrategy retryStrategy;
|
||||
RetryingCallable callable = RetryingCallable::Builder()
|
||||
.WithRetryStrategy(&retryStrategy)
|
||||
.WithCallable([this, &uri, &errorCode] {
|
||||
spdlog::info("Attempting to perform connection");
|
||||
WebSocketppClientType::connection_ptr newConnection = PerformConnect(uri, errorCode);
|
||||
if (newConnection && newConnection->get_state() == websocketpp::session::state::open) {
|
||||
spdlog::info("Connection established, transitioning traffic");
|
||||
// "Flip" traffic from our old websocket to our new websocket. Close the old one
|
||||
// if necessary
|
||||
WebSocketppClientType::connection_ptr oldConnection = m_connection;
|
||||
m_connection = newConnection;
|
||||
if (oldConnection && oldConnection->get_state() == websocketpp::session::state::open) {
|
||||
spdlog::info("Closing previous connection");
|
||||
websocketpp::lib::error_code closeErrorCode;
|
||||
m_webSocketClient->close(oldConnection->get_handle(), websocketpp::close::status::going_away,
|
||||
"Websocket client reconnecting", closeErrorCode);
|
||||
if (errorCode.value()) {
|
||||
spdlog::warn("Failed to close old websocket after a connection refresh, ignoring.");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
spdlog::warn("Connection to Amazon GameLift Servers websocket server failed. Retrying connection if possible.");
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.Build();
|
||||
callable.call();
|
||||
|
||||
if (IsConnected()) {
|
||||
spdlog::info("Connected to endpoint");
|
||||
return GenericOutcome(nullptr);
|
||||
} else {
|
||||
spdlog::error("Connection to Amazon GameLift Servers websocket server failed. See error message in InitSDK() outcome for details.");
|
||||
m_connection = nullptr;
|
||||
switch (errorCode.value()) {
|
||||
case websocketpp::error::server_only:
|
||||
switch (m_fail_response_code) {
|
||||
case websocketpp::http::status_code::value::forbidden:
|
||||
return GenericOutcome(GAMELIFT_ERROR_TYPE::WEBSOCKET_CONNECT_FAILURE_FORBIDDEN);
|
||||
default:
|
||||
return GenericOutcome(GameLiftError(GAMELIFT_ERROR_TYPE::WEBSOCKET_CONNECT_FAILURE, errorCode.category().message(errorCode.value()).c_str(),
|
||||
errorCode.message().c_str()));
|
||||
}
|
||||
case 11001: // Host not found
|
||||
case websocketpp::error::invalid_uri:
|
||||
return GenericOutcome(GAMELIFT_ERROR_TYPE::WEBSOCKET_CONNECT_FAILURE_INVALID_URL);
|
||||
// case websocketpp::error::timeout:
|
||||
case 0: // No Response after multiple retries, i.e. timeout
|
||||
case websocketpp::error::open_handshake_timeout:
|
||||
case websocketpp::error::close_handshake_timeout:
|
||||
return GenericOutcome(GAMELIFT_ERROR_TYPE::WEBSOCKET_CONNECT_FAILURE_TIMEOUT);
|
||||
case websocketpp::error::endpoint_not_secure:
|
||||
case websocketpp::error::no_outgoing_buffers:
|
||||
case websocketpp::error::no_incoming_buffers:
|
||||
case websocketpp::error::invalid_state:
|
||||
case websocketpp::error::bad_close_code:
|
||||
case websocketpp::error::reserved_close_code:
|
||||
case websocketpp::error::invalid_close_code:
|
||||
case websocketpp::error::invalid_utf8:
|
||||
case websocketpp::error::invalid_subprotocol:
|
||||
case websocketpp::error::bad_connection:
|
||||
case websocketpp::error::con_creation_failed:
|
||||
case websocketpp::error::unrequested_subprotocol:
|
||||
case websocketpp::error::client_only:
|
||||
case websocketpp::error::http_connection_ended:
|
||||
case websocketpp::error::invalid_port:
|
||||
case websocketpp::error::async_accept_not_listening:
|
||||
case websocketpp::error::upgrade_required:
|
||||
case websocketpp::error::invalid_version:
|
||||
case websocketpp::error::unsupported_version:
|
||||
case websocketpp::error::http_parse_error:
|
||||
case websocketpp::error::extension_neg_failed:
|
||||
default:
|
||||
return GenericOutcome(GameLiftError(GAMELIFT_ERROR_TYPE::WEBSOCKET_CONNECT_FAILURE, errorCode.category().message(errorCode.value()).c_str(),
|
||||
errorCode.message().c_str()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WebSocketppClientType::connection_ptr WebSocketppClientWrapper::PerformConnect(const Uri &uri, websocketpp::lib::error_code &errorCode) {
|
||||
spdlog::info("Performing connection");
|
||||
errorCode.clear();
|
||||
// Create connection request
|
||||
WebSocketppClientType::connection_ptr newConnection = m_webSocketClient->get_connection(uri.GetUriString(), errorCode);
|
||||
if (errorCode.value()) {
|
||||
spdlog::error("Failed to GetConnection. ERROR: {}", errorCode.message());
|
||||
return newConnection;
|
||||
} else {
|
||||
spdlog::info("Connection request created successfully. Waiting for connection to establish...");
|
||||
}
|
||||
|
||||
// Queue a new connection request (the socket thread will act on it and attempt to connect)
|
||||
try {
|
||||
m_webSocketClient->connect(newConnection);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
spdlog::error("Exception while trying to connect with the webSocketClient: {}", e.what());
|
||||
}
|
||||
spdlog::info("Connection request queued.");
|
||||
// Wait for connection to succeed or fail (this makes connection synchronous)
|
||||
{
|
||||
std::unique_lock<std::mutex> lk(m_lock);
|
||||
m_cond.wait(lk, [this] { return m_connectionStateChanged; });
|
||||
spdlog::info("Connection state changed: {}", m_fail_error_code.message());
|
||||
errorCode = m_fail_error_code;
|
||||
// Reset
|
||||
m_connectionStateChanged = false;
|
||||
m_fail_error_code.clear();
|
||||
}
|
||||
|
||||
if (errorCode.value()) {
|
||||
spdlog::error("Connection failed with errorCode: {}", errorCode.message());
|
||||
}
|
||||
else {
|
||||
spdlog::info("Connection established successfully.");
|
||||
}
|
||||
|
||||
return newConnection;
|
||||
}
|
||||
|
||||
GenericOutcome WebSocketppClientWrapper::SendSocketMessage(const std::string &requestId, const std::string &message) {
|
||||
if (requestId.empty()) {
|
||||
spdlog::error("Request does not have request ID, cannot process");
|
||||
return GenericOutcome(GameLiftError(GAMELIFT_ERROR_TYPE::INTERNAL_SERVICE_EXCEPTION));
|
||||
}
|
||||
|
||||
auto waitForReconnectRetryCount = 0;
|
||||
while(!IsConnected()) {
|
||||
// m_connection will be null if reconnect failed after max reties
|
||||
if(m_connection == nullptr || ++waitForReconnectRetryCount >= WAIT_FOR_RECONNECT_MAX_RETRIES) {
|
||||
spdlog::warn("WebSocket is not connected... WebSocket failed to send message due to an error.");
|
||||
return GenericOutcome(GameLiftError(GAMELIFT_ERROR_TYPE::WEBSOCKET_SEND_MESSAGE_FAILURE));
|
||||
}
|
||||
spdlog::warn("WebSocket is not connected... isConnected: {}", IsConnected());
|
||||
std::this_thread::sleep_for(std::chrono::seconds(WAIT_FOR_RECONNECT_RETRY_DELAY_SECONDS));
|
||||
}
|
||||
|
||||
std::future<GenericOutcome> responseFuture;
|
||||
// Lock whenever we make use of 'm_requestIdToPromise' to avoid concurrent writes/reads
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_requestToPromiseLock);
|
||||
// This indicates we've already sent this message, and it's still in flight
|
||||
if (m_requestIdToPromise.count(requestId) > 0) {
|
||||
spdlog::error("Request {} already exists", requestId);
|
||||
return GenericOutcome(GameLiftError(GAMELIFT_ERROR_TYPE::BAD_REQUEST_EXCEPTION));
|
||||
}
|
||||
|
||||
std::promise<GenericOutcome> responsePromise;
|
||||
responseFuture = responsePromise.get_future();
|
||||
m_requestIdToPromise[requestId] = std::move(responsePromise);
|
||||
}
|
||||
|
||||
GenericOutcome immediateResponse = SendSocketMessageAsync(message);
|
||||
|
||||
if (!immediateResponse.IsSuccess()) {
|
||||
spdlog::error("Send Socket Message immediate response failed with error {}: {}",
|
||||
immediateResponse.GetError().GetErrorName(), immediateResponse.GetError().GetErrorMessage());
|
||||
std::lock_guard<std::mutex> lock(m_requestToPromiseLock);
|
||||
m_requestIdToPromise.erase(requestId);
|
||||
return immediateResponse;
|
||||
}
|
||||
|
||||
std::future_status promiseStatus = responseFuture.wait_for(std::chrono::milliseconds(SERVICE_CALL_TIMEOUT_MILLIS));
|
||||
|
||||
if (promiseStatus == std::future_status::timeout) {
|
||||
std::lock_guard<std::mutex> lock(m_requestToPromiseLock);
|
||||
spdlog::error("Response not received within the time limit of {} ms for request {}", SERVICE_CALL_TIMEOUT_MILLIS, requestId);
|
||||
spdlog::warn("isConnected: {}", IsConnected());
|
||||
m_requestIdToPromise.erase(requestId);
|
||||
// If a call times out, retry
|
||||
return GenericOutcome(GameLiftError(GAMELIFT_ERROR_TYPE::WEBSOCKET_RETRIABLE_SEND_MESSAGE_FAILURE));
|
||||
}
|
||||
|
||||
return responseFuture.get();
|
||||
}
|
||||
|
||||
GenericOutcome WebSocketppClientWrapper::SendSocketMessageAsync(const std::string &message) {
|
||||
if (!m_connection) {
|
||||
spdlog::error("Cannot send message: m_connection is null");
|
||||
return GenericOutcome(GameLiftError(GAMELIFT_ERROR_TYPE::WEBSOCKET_SEND_MESSAGE_FAILURE));
|
||||
}
|
||||
|
||||
spdlog::info("Sending Socket Message, isConnected:{}", IsConnected());
|
||||
websocketpp::lib::error_code errorCode;
|
||||
m_webSocketClient->send(m_connection->get_handle(), message.c_str(), websocketpp::frame::opcode::text, errorCode);
|
||||
if (errorCode.value()) {
|
||||
spdlog::error("Error Sending Socket Message: {}", errorCode.value());
|
||||
switch (errorCode.value()) {
|
||||
case websocketpp::error::no_outgoing_buffers:
|
||||
// If buffers are full, send will fail. Retryable since buffers can free up as messages
|
||||
// send.
|
||||
return GenericOutcome(GAMELIFT_ERROR_TYPE::WEBSOCKET_RETRIABLE_SEND_MESSAGE_FAILURE);
|
||||
default:
|
||||
return GenericOutcome(GameLiftError(GAMELIFT_ERROR_TYPE::WEBSOCKET_SEND_MESSAGE_FAILURE, errorCode.category().message(errorCode.value()).c_str(),
|
||||
errorCode.message().c_str()));
|
||||
}
|
||||
}
|
||||
return GenericOutcome(nullptr);
|
||||
}
|
||||
|
||||
void WebSocketppClientWrapper::Disconnect() {
|
||||
spdlog::info("Disconnecting WebSocket");
|
||||
if (m_connection != nullptr) {
|
||||
websocketpp::lib::error_code ec;
|
||||
m_webSocketClient->close(m_connection->get_handle(), websocketpp::close::status::going_away, "Websocket client closing", ec);
|
||||
if (ec) {
|
||||
spdlog::error("Error initiating close: {}",ec.message());
|
||||
}
|
||||
m_connection = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void WebSocketppClientWrapper::RegisterGameLiftCallback(const std::string &gameLiftEvent, const std::function<GenericOutcome(std::string)> &callback) {
|
||||
spdlog::info("Registering GameLift CallBack for: {}", gameLiftEvent);
|
||||
m_eventHandlers[gameLiftEvent] = callback;
|
||||
}
|
||||
|
||||
bool WebSocketppClientWrapper::IsConnected() {
|
||||
// m_connection is nullptr if 'm_webSocketClient->get_connection()' fails
|
||||
return m_connection != nullptr && m_connection->get_state() == websocketpp::session::state::open;
|
||||
}
|
||||
|
||||
void WebSocketppClientWrapper::OnConnected(websocketpp::connection_hdl connection) {
|
||||
spdlog::info("Connected to WebSocket");
|
||||
// aquire lock and set condition variables (let main thread know connection is successful)
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(m_lock);
|
||||
// set the state change variables and notify the thread that is connecting
|
||||
m_connectionStateChanged = true;
|
||||
}
|
||||
m_cond.notify_one();
|
||||
}
|
||||
|
||||
void WebSocketppClientWrapper::OnError(websocketpp::connection_hdl connection) {
|
||||
auto con = m_webSocketClient->get_con_from_hdl(connection);
|
||||
spdlog::error("Error Connecting to WebSocket");
|
||||
|
||||
// aquire lock and set condition variables (let main thread know an error has occurred)
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(m_lock);
|
||||
// set the state change variables and notify the thread that is connecting
|
||||
m_connectionStateChanged = true;
|
||||
m_fail_error_code = con->get_ec();
|
||||
m_fail_response_code = con->get_response_code();
|
||||
}
|
||||
m_cond.notify_one();
|
||||
}
|
||||
|
||||
void WebSocketppClientWrapper::OnMessage(websocketpp::connection_hdl connection, websocketpp::config::asio_client::message_type::ptr msg) {
|
||||
std::string message = msg->get_payload();
|
||||
spdlog::info("Received message from websocket endpoint");
|
||||
|
||||
ResponseMessage responseMessage;
|
||||
Message &gameLiftMessage = responseMessage;
|
||||
if (!gameLiftMessage.Deserialize(message)) {
|
||||
spdlog::error("Error Deserializing Message");
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string &action = responseMessage.GetAction();
|
||||
spdlog::info("Deserialized Message has Action: {}", action);
|
||||
const std::string &requestId = responseMessage.GetRequestId();
|
||||
const int statusCode = responseMessage.GetStatusCode();
|
||||
const std::string &errorMessage = responseMessage.GetErrorMessage();
|
||||
|
||||
// Default to a success response with no result pointer
|
||||
GenericOutcome response(nullptr);
|
||||
// Check if the response was an error. If so, update the response based on status code.
|
||||
// RequestId will be empty when we get a message not associated with a request, in which case we
|
||||
// don't expect a 200 status code either.
|
||||
if (statusCode != OK_STATUS_CODE && !requestId.empty()) {
|
||||
response = GenericOutcome(GameLiftError(statusCode, message.c_str()));
|
||||
} else {
|
||||
// If we got a success response, and we have a special event handler for this action, invoke
|
||||
// it to get the real parsed result
|
||||
if (m_eventHandlers.count(action)) {
|
||||
spdlog::info("Executing Amazon GameLift Servers Event Handler for {}", action);
|
||||
response = m_eventHandlers[action](message);
|
||||
}
|
||||
}
|
||||
|
||||
// Lock whenever we make use of 'm_requestIdToPromise' to avoid concurrent writes/reads
|
||||
std::lock_guard<std::mutex> lock(m_requestToPromiseLock);
|
||||
if (m_requestIdToPromise.count(requestId) > 0) {
|
||||
m_requestIdToPromise[requestId].set_value(response);
|
||||
m_requestIdToPromise.erase(requestId);
|
||||
}
|
||||
}
|
||||
|
||||
websocketpp::lib::shared_ptr<asio::ssl::context> WebSocketppClientWrapper::OnTlsInit(websocketpp::connection_hdl hdl) {
|
||||
websocketpp::lib::shared_ptr<asio::ssl::context> contextPtr(new asio::ssl::context(asio::ssl::context::tlsv12));
|
||||
return contextPtr;
|
||||
}
|
||||
|
||||
void WebSocketppClientWrapper::OnClose(websocketpp::connection_hdl connection) {
|
||||
auto connectionPointer = m_webSocketClient->get_con_from_hdl(connection);
|
||||
auto localCloseCode = connectionPointer->get_local_close_code();
|
||||
auto remoteCloseCode = connectionPointer->get_remote_close_code();
|
||||
bool isNormalClosure = localCloseCode == websocketpp::close::status::normal
|
||||
|| localCloseCode == websocketpp::close::status::going_away
|
||||
|| remoteCloseCode == websocketpp::close::status::normal
|
||||
|| remoteCloseCode == websocketpp::close::status::going_away;
|
||||
spdlog::info("Connection to Amazon GameLift Servers websocket server lost, Local Close Code = {}, Remote Close Code = {}.",
|
||||
websocketpp::close::status::get_string(localCloseCode).c_str(),
|
||||
websocketpp::close::status::get_string(remoteCloseCode).c_str());
|
||||
if(isNormalClosure) {
|
||||
spdlog::info("Normal Connection Closure, skipping reconnect.");
|
||||
return;
|
||||
} else {
|
||||
spdlog::info("Abnormal Connection Closure, reconnecting.");
|
||||
WebSocketppClientWrapper::Connect(m_uri);
|
||||
}
|
||||
}
|
||||
|
||||
void WebSocketppClientWrapper::OnInterrupt(websocketpp::connection_hdl connection) {
|
||||
auto connectionPointer = m_webSocketClient->get_con_from_hdl(connection);
|
||||
auto remoteEndpoint = connectionPointer->get_remote_endpoint();
|
||||
auto host = connectionPointer->get_host();
|
||||
auto port = connectionPointer->get_port();
|
||||
spdlog::warn("Interruption Happened");
|
||||
spdlog::info("In OnInterrupt(), isConnected:{}, endpoint: {}, host: {}, port: {}", IsConnected(), remoteEndpoint, host, port);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/network/callback/CreateGameSessionCallback.h>
|
||||
#include <aws/gamelift/internal/model/message/CreateGameSessionMessage.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
using namespace Aws::GameLift;
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
|
||||
GenericOutcome CreateGameSessionCallback::OnStartGameSession(const std::string &data) {
|
||||
spdlog::info("OnStartGameSession Received with raw data: {}", data);
|
||||
CreateGameSessionMessage createGameSessionMessage;
|
||||
Message &message = createGameSessionMessage;
|
||||
message.Deserialize(data);
|
||||
|
||||
GameSession gameSession;
|
||||
gameSession.WithGameSessionId(createGameSessionMessage.GetGameSessionId().c_str())
|
||||
.WithName(createGameSessionMessage.GetGameSessionName().c_str())
|
||||
.WithMaximumPlayerSessionCount(createGameSessionMessage.GetMaximumPlayerSessionCount())
|
||||
.WithIpAddress(createGameSessionMessage.GetIpAddress().c_str())
|
||||
.WithPort(createGameSessionMessage.GetPort())
|
||||
.WithGameSessionData(createGameSessionMessage.GetGameSessionData().c_str())
|
||||
.WithMatchmakerData(createGameSessionMessage.GetMatchmakerData().c_str())
|
||||
.WithDnsName(createGameSessionMessage.GetDnsName().c_str());
|
||||
|
||||
std::map<std::string, std::string>::const_iterator mapIterator;
|
||||
for (mapIterator = createGameSessionMessage.GetGameProperties().begin(); mapIterator != createGameSessionMessage.GetGameProperties().end(); mapIterator++) {
|
||||
GameProperty gameProperty;
|
||||
gameProperty.SetKey(mapIterator->first.c_str());
|
||||
gameProperty.SetValue(mapIterator->second.c_str());
|
||||
gameSession.AddGameProperty(gameProperty);
|
||||
}
|
||||
|
||||
m_gameLiftMessageHandler->OnStartGameSession(gameSession);
|
||||
|
||||
return GenericOutcome(nullptr);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/network/callback/DescribePlayerSessionsCallback.h>
|
||||
#include <aws/gamelift/internal/model/response/WebSocketDescribePlayerSessionsResponse.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
using namespace Aws::GameLift;
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
GenericOutcome DescribePlayerSessionsCallback::OnDescribePlayerSessions(const std::string &data) {
|
||||
spdlog::info("OnDescribePlayerSessions Received with raw data: {}", data);
|
||||
WebSocketDescribePlayerSessionsResponse *describePlayerSessionsResponse = new WebSocketDescribePlayerSessionsResponse();
|
||||
Message *message = describePlayerSessionsResponse;
|
||||
message->Deserialize(data);
|
||||
|
||||
return GenericOutcome(describePlayerSessionsResponse);
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/network/callback/GetComputeCertificateCallback.h>
|
||||
#include <aws/gamelift/internal/model/response/WebSocketGetComputeCertificateResponse.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
using namespace Aws::GameLift;
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
GenericOutcome GetComputeCertificateCallback::OnGetComputeCertificateCallback(const std::string &data) {
|
||||
spdlog::info("OnGetComputeCertificate Received");
|
||||
auto *response = new WebSocketGetComputeCertificateResponse();
|
||||
Message *message = response;
|
||||
message->Deserialize(data);
|
||||
|
||||
return GenericOutcome(response);
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/network/callback/GetFleetRoleCredentialsCallback.h>
|
||||
#include <aws/gamelift/internal/model/response/WebSocketGetFleetRoleCredentialsResponse.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
using namespace Aws::GameLift;
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
GenericOutcome GetFleetRoleCredentialsCallback::OnGetFleetRoleCredentials(const std::string &data) {
|
||||
spdlog::info("OnGetFleetRoleCredentials Received");
|
||||
auto *getFleetRoleCredentialsResponse = new WebSocketGetFleetRoleCredentialsResponse();
|
||||
Message *message = getFleetRoleCredentialsResponse;
|
||||
message->Deserialize(data);
|
||||
|
||||
return GenericOutcome(getFleetRoleCredentialsResponse);
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/network/callback/RefreshConnectionCallback.h>
|
||||
#include <aws/gamelift/internal/model/message/RefreshConnectionMessage.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
using namespace Aws::GameLift;
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
GenericOutcome RefreshConnectionCallback::OnRefreshConnection(const std::string &data) {
|
||||
spdlog::info("OnRefreshConnection Received with raw data: {}", data);
|
||||
RefreshConnectionMessage refreshConnectionMessage;
|
||||
Message &message = refreshConnectionMessage;
|
||||
message.Deserialize(data);
|
||||
|
||||
m_gameLiftMessageHandler->OnRefreshConnection(refreshConnectionMessage.GetRefreshConnectionEndpoint(), refreshConnectionMessage.GetAuthToken());
|
||||
|
||||
return GenericOutcome(nullptr);
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/network/callback/StartMatchBackfillCallback.h>
|
||||
#include <aws/gamelift/internal/model/response/WebSocketStartMatchBackfillResponse.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
using namespace Aws::GameLift;
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
GenericOutcome StartMatchBackfillCallback::OnStartMatchBackfill(const std::string &data) {
|
||||
spdlog::info("OnStartMatchBackfill Received with raw data: {}", data);
|
||||
WebSocketStartMatchBackfillResponse *startMatchBackfillResponse = new WebSocketStartMatchBackfillResponse();
|
||||
Message *message = startMatchBackfillResponse;
|
||||
message->Deserialize(data);
|
||||
|
||||
return GenericOutcome(startMatchBackfillResponse);
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/network/callback/TerminateProcessCallback.h>
|
||||
#include <aws/gamelift/internal/model/message/TerminateProcessMessage.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
using namespace Aws::GameLift;
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
|
||||
GenericOutcome TerminateProcessCallback::OnTerminateProcess(const std::string &data) {
|
||||
spdlog::info("OnTerminateProcess Received with raw data: {}", data);
|
||||
TerminateProcessMessage terminateProcessMessage;
|
||||
Message &message = terminateProcessMessage;
|
||||
message.Deserialize(data);
|
||||
|
||||
long terminationTime = terminateProcessMessage.GetTerminationTime();
|
||||
m_gameLiftMessageHandler->OnTerminateProcess(terminationTime);
|
||||
|
||||
return GenericOutcome(nullptr);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/network/callback/UpdateGameSessionCallback.h>
|
||||
#include <aws/gamelift/internal/model/message/UpdateGameSessionMessage.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
using namespace Aws::GameLift;
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
|
||||
GenericOutcome UpdateGameSessionCallback::OnUpdateGameSession(const std::string &data) {
|
||||
spdlog::info("OnUpdateGameSession Received with raw data: {}", data);
|
||||
UpdateGameSessionMessage updateGameSessionMessage;
|
||||
Message &message = updateGameSessionMessage;
|
||||
message.Deserialize(data);
|
||||
|
||||
GameSession gameSession;
|
||||
WebSocketGameSession webSocketGameSession = updateGameSessionMessage.GetGameSession();
|
||||
gameSession.WithGameSessionId(webSocketGameSession.GetGameSessionId().c_str())
|
||||
.WithName(webSocketGameSession.GetName().c_str())
|
||||
.WithFleetId(webSocketGameSession.GetFleetId().c_str())
|
||||
.WithMaximumPlayerSessionCount(webSocketGameSession.GetMaximumPlayerSessionCount())
|
||||
.WithIpAddress(webSocketGameSession.GetIpAddress().c_str())
|
||||
.WithPort(webSocketGameSession.GetPort())
|
||||
.WithGameSessionData(webSocketGameSession.GetGameSessionData().c_str())
|
||||
.WithMatchmakerData(webSocketGameSession.GetMatchmakerData().c_str())
|
||||
.WithDnsName(webSocketGameSession.GetDnsName().c_str());
|
||||
|
||||
std::map<std::string, std::string>::const_iterator mapIterator;
|
||||
for (mapIterator = webSocketGameSession.GetGameProperties().begin(); mapIterator != webSocketGameSession.GetGameProperties().end(); mapIterator++) {
|
||||
GameProperty gameProperty;
|
||||
gameProperty.SetKey(mapIterator->first.c_str());
|
||||
gameProperty.SetValue(mapIterator->second.c_str());
|
||||
gameSession.AddGameProperty(gameProperty);
|
||||
}
|
||||
|
||||
UpdateGameSession updateGameSession(gameSession, UpdateReasonMapper::GetUpdateReasonForName(updateGameSessionMessage.GetUpdateReason().c_str()),
|
||||
updateGameSessionMessage.GetBackfillTicketId().c_str());
|
||||
|
||||
m_gameLiftMessageHandler->OnUpdateGameSession(updateGameSession);
|
||||
|
||||
return GenericOutcome(nullptr);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/retry/GeometricBackoffRetryStrategy.h>
|
||||
#include <thread>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
|
||||
void GeometricBackoffRetryStrategy::apply(const std::function<bool(void)> &callable) {
|
||||
int retryIntervalSeconds = m_initialRetryIntervalSeconds;
|
||||
for (int i = 0; i < m_maxRetries; ++i) {
|
||||
bool success = callable();
|
||||
if (success) {
|
||||
break;
|
||||
} else {
|
||||
spdlog::warn("Connection Failed. Retrying in {} seconds...", retryIntervalSeconds);
|
||||
std::this_thread::sleep_for(std::chrono::seconds(retryIntervalSeconds));
|
||||
retryIntervalSeconds *= m_retryFactor;
|
||||
retryIntervalSeconds = retryIntervalSeconds > m_maxRetryIntervalSeconds ? m_maxRetryIntervalSeconds : retryIntervalSeconds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/retry/JitteredGeometricBackoffRetryStrategy.h>
|
||||
#include <random>
|
||||
#include <thread>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
|
||||
void JitteredGeometricBackoffRetryStrategy::apply(const std::function<bool(void)> &callable) {
|
||||
int retryIntervalMs = m_initialRetryIntervalMs;
|
||||
std::random_device rd;
|
||||
std::mt19937 randGenerator(rd());
|
||||
for (int i = 0; i < m_maxRetries; ++i) {
|
||||
bool success = callable();
|
||||
if (success) {
|
||||
break;
|
||||
} else {
|
||||
std::uniform_int_distribution<> intervalRange(m_minRetryDelayMs, retryIntervalMs);
|
||||
int currentInterval = intervalRange(randGenerator);
|
||||
spdlog::warn("Sending Message Failed. Retrying in {} milliseconds...", currentInterval);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(currentInterval));
|
||||
retryIntervalMs *= m_retryFactor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/retry/RetryingCallable.h>
|
||||
#include <thread>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
|
||||
RetryingCallable::Builder &RetryingCallable::Builder::WithCallable(const std::function<bool(void)> &callable) {
|
||||
m_callable = callable;
|
||||
return *this;
|
||||
}
|
||||
|
||||
RetryingCallable::Builder &RetryingCallable::Builder::WithRetryStrategy(RetryStrategy *retryStrategy) {
|
||||
m_retryStrategy = retryStrategy;
|
||||
return *this;
|
||||
}
|
||||
|
||||
RetryingCallable RetryingCallable::Builder::Build() const { return RetryingCallable(*m_retryStrategy, m_callable); }
|
||||
|
||||
RetryingCallable::RetryingCallable(RetryStrategy &retryStrategy, std::function<bool(void)> callable) : m_retryStrategy(retryStrategy), m_callable(callable) {}
|
||||
|
||||
void RetryingCallable::call() { m_retryStrategy.apply(m_callable); }
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/security/AwsSigV4Utility.h>
|
||||
#include <aws/gamelift/internal/util/UriEncoder.h>
|
||||
#include <openssl/opensslv.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
using namespace Aws::GameLift::Internal;
|
||||
|
||||
Aws::GameLift::Outcome<std::map<std::string, std::string>, std::string> AwsSigV4Utility::GenerateSigV4QueryParameters(const SigV4Parameters ¶meters) {
|
||||
|
||||
try {
|
||||
ValidateParameters(parameters);
|
||||
} catch (std::invalid_argument const &ex) {
|
||||
return std::string(ex.what());
|
||||
}
|
||||
|
||||
char dateBuffer[16];
|
||||
char dateTimeBuffer[32];
|
||||
strftime(dateBuffer, sizeof(dateBuffer), DateFormat, ¶meters.RequestTime);
|
||||
strftime(dateTimeBuffer, sizeof(dateTimeBuffer), DateTimeFormat, ¶meters.RequestTime);
|
||||
|
||||
const std::string formattedRequestDate(dateBuffer);
|
||||
const std::string formattedRequestDateTime(dateTimeBuffer);
|
||||
|
||||
const std::string canonicalRequest = ToSortedEncodedQueryString(parameters.QueryParams);
|
||||
|
||||
const std::string hashedCanonicalRequest = ComputeSha256Hash(canonicalRequest);
|
||||
|
||||
const std::string scope = formattedRequestDate + "/" + parameters.AwsRegion + "/" + ServiceName + "/" + TerminationString;
|
||||
|
||||
const std::string stringToSign = std::string(Algorithm) + "\n" + formattedRequestDateTime + "\n" + scope + "\n" + hashedCanonicalRequest;
|
||||
|
||||
const std::string credential = parameters.Credentials.AccessKey + "/" + scope;
|
||||
|
||||
const std::string signature = GenerateSignature(
|
||||
parameters.AwsRegion,
|
||||
parameters.Credentials.SecretKey,
|
||||
formattedRequestDate,
|
||||
ServiceName,
|
||||
stringToSign);
|
||||
|
||||
return GenerateSigV4QueryParameters(
|
||||
credential,
|
||||
formattedRequestDateTime,
|
||||
parameters.Credentials.SessionToken,
|
||||
signature);
|
||||
}
|
||||
|
||||
void AwsSigV4Utility::ValidateParameters(const SigV4Parameters ¶meters) {
|
||||
|
||||
if (parameters.AwsRegion.empty()) {
|
||||
throw std::invalid_argument("AwsRegion is required");
|
||||
}
|
||||
|
||||
if (parameters.Credentials.AccessKey.empty()) {
|
||||
throw std::invalid_argument("AccessKey is required");
|
||||
}
|
||||
|
||||
if (parameters.Credentials.SecretKey.empty()) {
|
||||
throw std::invalid_argument("SecretKey is required");
|
||||
}
|
||||
|
||||
if (parameters.QueryParams.empty()) {
|
||||
throw std::invalid_argument("QueryParams is required");
|
||||
}
|
||||
|
||||
if (parameters.RequestTime.tm_year == 0) {
|
||||
throw std::invalid_argument("RequestTime is required");
|
||||
}
|
||||
}
|
||||
|
||||
std::string AwsSigV4Utility::GenerateSignature(
|
||||
const std::string ®ion,
|
||||
const std::string &secretKey,
|
||||
const std::string &formattedRequestDateTime,
|
||||
const std::string &serviceName,
|
||||
const std::string &stringToSign) {
|
||||
|
||||
std::vector<uint8_t> encodedKeySecret = std::vector<uint8_t>(SignatureSecretKeyPrefix, SignatureSecretKeyPrefix +
|
||||
strlen(SignatureSecretKeyPrefix));
|
||||
encodedKeySecret.insert(encodedKeySecret.end(), secretKey.begin(), secretKey.end());
|
||||
|
||||
auto hashDate = ComputeHmacSha256(encodedKeySecret, formattedRequestDateTime);
|
||||
auto hashRegion = ComputeHmacSha256(hashDate, region);
|
||||
auto hashService = ComputeHmacSha256(hashRegion, serviceName);
|
||||
auto signingKey = ComputeHmacSha256(hashService, TerminationString);
|
||||
|
||||
return ToHex(ComputeHmacSha256(signingKey, stringToSign));
|
||||
}
|
||||
|
||||
std::map<std::string, std::string> AwsSigV4Utility::GenerateSigV4QueryParameters(
|
||||
const std::string &credential,
|
||||
const std::string &formattedRequestDateTime,
|
||||
const std::string &sessionToken,
|
||||
const std::string &signature) {
|
||||
|
||||
std::map<std::string, std::string> sigV4QueryParameters;
|
||||
sigV4QueryParameters[AuthorizationKey] = AuthorizationValue;
|
||||
sigV4QueryParameters[AmzAlgorithmKey] = Algorithm;
|
||||
sigV4QueryParameters[AmzCredentialKey] = UriEncoder::UriEncode(credential);
|
||||
sigV4QueryParameters[AmzDateKey] = formattedRequestDateTime;
|
||||
sigV4QueryParameters[AmzSignatureKey] = UriEncoder::UriEncode(signature);
|
||||
|
||||
if (!sessionToken.empty()) {
|
||||
sigV4QueryParameters[AmzSecurityTokenHeadersKey] = UriEncoder::UriEncode(sessionToken);
|
||||
}
|
||||
|
||||
return sigV4QueryParameters;
|
||||
}
|
||||
|
||||
std::string AwsSigV4Utility::ToSortedEncodedQueryString(const std::map<std::string, std::string> &queryParameters) {
|
||||
std::vector<std::pair<std::string, std::string> > sortedParams(queryParameters.begin(), queryParameters.end());
|
||||
std::sort(sortedParams.begin(), sortedParams.end());
|
||||
|
||||
std::ostringstream stringBuffer;
|
||||
for (auto sortedParam = sortedParams.begin(); sortedParam != sortedParams.end(); ++sortedParam) {
|
||||
if (sortedParam != sortedParams.begin()) {
|
||||
stringBuffer << "&";
|
||||
}
|
||||
stringBuffer << UriEncoder::UriEncode(sortedParam->first) << "=" << UriEncoder::UriEncode(sortedParam->second);
|
||||
}
|
||||
|
||||
return stringBuffer.str();
|
||||
}
|
||||
|
||||
// Refer to documentation in AwsSigV4Utility.h
|
||||
std::string AwsSigV4Utility::ComputeSha256Hash(const std::string &data) {
|
||||
// Because the following methods do not throw exceptions, they are not being surrounded by try-catch or use RAII for cleaning memory.
|
||||
unsigned char hash[SHA256_DIGEST_LENGTH];
|
||||
SHA256_CTX sha256;
|
||||
SHA256_Init(&sha256);
|
||||
SHA256_Update(&sha256, data.c_str(), data.size());
|
||||
SHA256_Final(hash, &sha256);
|
||||
|
||||
const std::vector<uint8_t> sha256Hash = std::vector<uint8_t>(hash, hash + SHA256_DIGEST_LENGTH);
|
||||
return ToHex(sha256Hash);
|
||||
}
|
||||
|
||||
// Refer to documentation in AwsSigV4Utility.h
|
||||
std::vector<uint8_t> AwsSigV4Utility::ComputeHmacSha256(const std::vector<uint8_t> &key, const std::string &data) {
|
||||
// Because the following methods do not throw exceptions, they are not being surrounded by try-catch or use RAII for cleaning memory.
|
||||
unsigned char hash[EVP_MAX_MD_SIZE];
|
||||
unsigned int len = 0;
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L // OpenSSL 1.1.0 or newer
|
||||
HMAC_CTX *ctx = HMAC_CTX_new();
|
||||
HMAC_Init_ex(ctx, key.data(), key.size(), EVP_sha256(), nullptr);
|
||||
HMAC_Update(ctx, reinterpret_cast<const unsigned char *>(data.c_str()), data.size());
|
||||
HMAC_Final(ctx, hash, &len);
|
||||
HMAC_CTX_free(ctx);
|
||||
#else // Older versions of OpenSSL
|
||||
HMAC_CTX ctx;
|
||||
HMAC_CTX_init(&ctx);
|
||||
HMAC_Init_ex(&ctx, key.data(), key.size(), EVP_sha256(), nullptr);
|
||||
HMAC_Update(&ctx, reinterpret_cast<const unsigned char *>(data.c_str()), data.size());
|
||||
HMAC_Final(&ctx, hash, &len);
|
||||
HMAC_CTX_cleanup(&ctx);
|
||||
#endif
|
||||
return std::vector<uint8_t>(hash, hash + len);
|
||||
}
|
||||
|
||||
std::string AwsSigV4Utility::ToHex(const std::vector<uint8_t> &hashBytes) {
|
||||
std::ostringstream stringBuffer;
|
||||
for (auto b: hashBytes) {
|
||||
stringBuffer << std::hex << std::setw(2) << std::setfill('0') << (int) b;
|
||||
}
|
||||
return stringBuffer.str();
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/security/ContainerCredentialsFetcher.h>
|
||||
#include <stdexcept>
|
||||
#include <cstdlib>
|
||||
#include "rapidjson/document.h"
|
||||
|
||||
using namespace Aws::GameLift::Internal;
|
||||
|
||||
ContainerCredentialsFetcher::ContainerCredentialsFetcher(HttpClient &httpClient)
|
||||
: httpClient(httpClient) {}
|
||||
|
||||
Aws::GameLift::Outcome<AwsCredentials, std::string> ContainerCredentialsFetcher::FetchContainerCredentials() {
|
||||
const char *credentialsRelativeUri = std::getenv(EnvironmentVariableContainerCredentialsRelativeUri.c_str());
|
||||
if (!credentialsRelativeUri) {
|
||||
return "The environment variable " + EnvironmentVariableContainerCredentialsRelativeUri + " is not set.";
|
||||
}
|
||||
|
||||
std::string relativeUri = credentialsRelativeUri;
|
||||
HttpResponse response = httpClient.SendGetRequest(ContainerCredentialProviderUrl + relativeUri);
|
||||
|
||||
if (!response.IsSuccessfulStatusCode()) {
|
||||
return std::string(
|
||||
"Failed to get Container Credentials from Container Credential Provider. HTTP Response Status Code is " +
|
||||
std::to_string(response.statusCode));
|
||||
}
|
||||
|
||||
rapidjson::Document document;
|
||||
if (document.Parse(response.body.c_str()).HasParseError()) {
|
||||
return std::string("Error parsing Container Credential Provider JSON response");
|
||||
}
|
||||
|
||||
if (!document.HasMember("AccessKeyId") || !document["AccessKeyId"].IsString()) {
|
||||
return std::string("AccessKeyId is not found in Container Credential Provider response");
|
||||
}
|
||||
|
||||
if (!document.HasMember("SecretAccessKey") || !document["SecretAccessKey"].IsString()) {
|
||||
return std::string("SecretAccessKey is not found in Container Credential Provider response");
|
||||
}
|
||||
|
||||
if (!document.HasMember("Token") || !document["Token"].IsString()) {
|
||||
return std::string("Token is not found in Container Credential Provider response");
|
||||
}
|
||||
|
||||
AwsCredentials awsCredentials(
|
||||
document["AccessKeyId"].GetString(),
|
||||
document["SecretAccessKey"].GetString(),
|
||||
document["Token"].GetString());
|
||||
return awsCredentials;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/security/ContainerMetadataFetcher.h>
|
||||
#include <stdexcept>
|
||||
#include <cstdlib>
|
||||
#include "rapidjson/document.h"
|
||||
|
||||
using namespace Aws::GameLift::Internal;
|
||||
|
||||
ContainerMetadataFetcher::ContainerMetadataFetcher(HttpClient &httpClient)
|
||||
: httpClient(httpClient) {}
|
||||
|
||||
Aws::GameLift::Outcome<ContainerTaskMetadata, std::string> ContainerMetadataFetcher::FetchContainerTaskMetadata() {
|
||||
const char *containerMetadataUri = std::getenv(EnvironmentVariableContainerMetadataUri.c_str());
|
||||
if (!containerMetadataUri) {
|
||||
return "The environment variable " + EnvironmentVariableContainerMetadataUri + " is not set.";
|
||||
}
|
||||
std::string baseUrl = containerMetadataUri;
|
||||
HttpResponse response = httpClient.SendGetRequest(baseUrl + "/" + TaskMetadataRelativePath);
|
||||
|
||||
if(!response.IsSuccessfulStatusCode()) {
|
||||
return std::string(
|
||||
"Failed to get Container Task Metadata from Container Metadata Service. HTTP Response Status Code is " +
|
||||
std::to_string(response.statusCode));
|
||||
}
|
||||
rapidjson::Document document;
|
||||
if (document.Parse(response.body.c_str()).HasParseError()) {
|
||||
return std::string("Error parsing Container Metadata Service JSON response");
|
||||
}
|
||||
if (!document.HasMember("TaskARN") || !document["TaskARN"].IsString()) {
|
||||
return std::string("TaskArn is not found in Container Metadata Service response");
|
||||
}
|
||||
std::string taskArn = document["TaskARN"].GetString();
|
||||
if (taskArn.empty()) {
|
||||
return std::string("Invalid TaskARN, value is empty");
|
||||
}
|
||||
if (taskArn.find('/') == std::string::npos) {
|
||||
return std::string("Failed to extract Task ID from container TaskArn with value " + taskArn);
|
||||
}
|
||||
std::string taskId = taskArn.substr(taskArn.find_last_of('/') + 1);
|
||||
return ContainerTaskMetadata(taskId);
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/util/GuidGenerator.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <random>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
using namespace Aws::GameLift::Internal;
|
||||
|
||||
std::string GuidGenerator::GenerateGuid() {
|
||||
std::random_device rd;
|
||||
std::uniform_int_distribution<int> dist(0, 15);
|
||||
std::uniform_int_distribution<int> dist2(8, 11);
|
||||
|
||||
std::stringstream ss;
|
||||
ss << std::hex << std::setfill('0');
|
||||
|
||||
for (int i = 0; i < 8; ++i) ss << dist(rd);
|
||||
ss << "-";
|
||||
|
||||
for (int i = 0; i < 4; ++i) ss << dist(rd);
|
||||
ss << "-";
|
||||
|
||||
ss << "4";
|
||||
for (int i = 0; i < 3; ++i) ss << dist(rd);
|
||||
ss << "-";
|
||||
|
||||
ss << dist2(rd);
|
||||
for (int i = 0; i < 3; ++i) ss << dist(rd);
|
||||
ss << "-";
|
||||
|
||||
for (int i = 0; i < 12; ++i) ss << dist(rd);
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#include <aws/gamelift/internal/util/HttpClient.h>
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#pragma comment(lib, "Ws2_32.lib")
|
||||
using ssize_t = SSIZE_T;
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <cstring>
|
||||
#endif
|
||||
#include <stdexcept>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
using namespace Aws::GameLift::Internal;
|
||||
|
||||
bool HttpResponse::IsSuccessfulStatusCode() {
|
||||
return statusCode >= 200 && statusCode <= 299;
|
||||
}
|
||||
|
||||
HttpResponse HttpClient::SendGetRequest(const std::string &url) {
|
||||
const std::tuple<std::string, int, std::string> hostAndPortAndPath = GetHostAndPortAndPath(url);
|
||||
const std::string host = std::get<0>(hostAndPortAndPath);
|
||||
const int port = std::get<1>(hostAndPortAndPath);
|
||||
const std::string path = std::get<2>(hostAndPortAndPath);
|
||||
const std::string request = "GET " + path + " HTTP/1.1\r\nHost: " + host + "\r\nConnection: close\r\n\r\n";
|
||||
int sock = -1;
|
||||
|
||||
#ifdef _WIN32
|
||||
WSADATA wsaData;
|
||||
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
|
||||
throw std::runtime_error("WSAStartup failed, error number: " + std::to_string(WSAGetLastError()));
|
||||
}
|
||||
#endif
|
||||
|
||||
try {
|
||||
sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sock < 0) {
|
||||
#ifdef _WIN32
|
||||
throw std::runtime_error("Socket creation failed, error number: " + std::to_string(WSAGetLastError()));
|
||||
#else
|
||||
throw std::runtime_error("Socket creation failed, error number: " + std::string(strerror(errno)));
|
||||
#endif
|
||||
}
|
||||
|
||||
struct sockaddr_in server_addr;
|
||||
server_addr.sin_family = AF_INET;
|
||||
server_addr.sin_port = htons(port);
|
||||
|
||||
#ifdef _WIN32
|
||||
std::wstring wide_host = std::wstring(host.begin(), host.end());
|
||||
if (InetPtonW(AF_INET, wide_host.c_str(), &server_addr.sin_addr) <= 0) {
|
||||
throw std::runtime_error("Invalid address or address not supported, error number: " + std::to_string(WSAGetLastError()));
|
||||
}
|
||||
#else
|
||||
if (inet_pton(AF_INET, host.c_str(), &server_addr.sin_addr) <= 0) {
|
||||
throw std::runtime_error("Invalid address or address not supported, error number: " + std::string(strerror(errno)));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (connect(sock, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) {
|
||||
#ifdef _WIN32
|
||||
throw std::runtime_error("Connection failed, error number: " + std::to_string(WSAGetLastError()));
|
||||
#else
|
||||
throw std::runtime_error("Connection failed, error number: " + std::string(strerror(errno)));
|
||||
#endif
|
||||
}
|
||||
|
||||
ssize_t sent = send(sock, request.c_str(), request.length(), 0);
|
||||
if (sent < 0) {
|
||||
#ifdef _WIN32
|
||||
throw std::runtime_error("Send failed, error number: " + std::to_string(WSAGetLastError()));
|
||||
#else
|
||||
throw std::runtime_error("Send failed, error number: " + std::string(strerror(errno)));
|
||||
#endif
|
||||
} else if (sent != (ssize_t) request.length()) {
|
||||
throw std::runtime_error("Send incomplete, only " + std::to_string(sent) + " bytes sent.");
|
||||
}
|
||||
|
||||
std::string fullResponse;
|
||||
char buffer[1024] = {0};
|
||||
ssize_t bytesReceived;
|
||||
while ((bytesReceived = recv(sock, buffer, sizeof(buffer) - 1, 0)) > 0) {
|
||||
fullResponse.append(buffer, bytesReceived);
|
||||
}
|
||||
|
||||
if (bytesReceived < 0) {
|
||||
#ifdef _WIN32
|
||||
throw std::runtime_error("Receive failed, error number: " + std::to_string(WSAGetLastError()));
|
||||
#else
|
||||
throw std::runtime_error("Receive failed, error number: " + std::string(strerror(errno)));
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
if (closesocket(sock) < 0) {
|
||||
spdlog::warn("Socket close failed, error number: {}", WSAGetLastError());
|
||||
}
|
||||
WSACleanup();
|
||||
#else
|
||||
if (close(sock) < 0) {
|
||||
spdlog::warn("Socket close failed, error number: {}", errno);
|
||||
}
|
||||
#endif
|
||||
sock = -1;
|
||||
|
||||
HttpResponse httpResponse = ParseHttpResponse(fullResponse);
|
||||
return httpResponse;
|
||||
} catch (const std::runtime_error& e) {
|
||||
if (sock >= 0) {
|
||||
#ifdef _WIN32
|
||||
closesocket(sock);
|
||||
WSACleanup();
|
||||
#else
|
||||
close(sock);
|
||||
#endif
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
std::tuple<std::string, int, std::string> HttpClient::GetHostAndPortAndPath(const std::string &url) {
|
||||
std::string host;
|
||||
std::string path;
|
||||
int port = 80;
|
||||
|
||||
std::size_t protocolPos = url.find("://");
|
||||
if (protocolPos == std::string::npos) {
|
||||
throw std::runtime_error("Invalid URL: Missing protocol");
|
||||
}
|
||||
|
||||
std::size_t hostStart = protocolPos + 3;
|
||||
|
||||
if (hostStart >= url.size()) {
|
||||
throw std::runtime_error("Invalid URL: Host is missing");
|
||||
}
|
||||
|
||||
std::size_t pathPos = url.find('/', hostStart);
|
||||
std::size_t portPos = url.find(':', hostStart);
|
||||
|
||||
if (portPos != std::string::npos && (pathPos == std::string::npos || portPos < pathPos)) {
|
||||
host = url.substr(hostStart, portPos - hostStart);
|
||||
std::size_t portEnd = (pathPos == std::string::npos) ? url.size() : pathPos;
|
||||
port = std::stoi(url.substr(portPos + 1, portEnd - portPos - 1));
|
||||
} else {
|
||||
if (pathPos == std::string::npos) {
|
||||
host = url.substr(hostStart);
|
||||
path = "/";
|
||||
} else {
|
||||
host = url.substr(hostStart, pathPos - hostStart);
|
||||
}
|
||||
}
|
||||
if (path.empty()) {
|
||||
if (pathPos != std::string::npos) {
|
||||
path = url.substr(pathPos);
|
||||
} else {
|
||||
path = "/";
|
||||
}
|
||||
}
|
||||
return std::make_tuple(host, port, path);
|
||||
}
|
||||
|
||||
HttpResponse HttpClient::ParseHttpResponse(const std::string &response) {
|
||||
HttpResponse httpResponse;
|
||||
std::size_t statusCodeStart = response.find("HTTP/1.1 ") + 9;
|
||||
std::size_t statusCodeEnd = response.find(" ", statusCodeStart);
|
||||
if (statusCodeStart != std::string::npos && statusCodeEnd != std::string::npos) {
|
||||
httpResponse.statusCode = std::stoi(response.substr(statusCodeStart, statusCodeEnd - statusCodeStart));
|
||||
}
|
||||
std::size_t bodyStart = response.find("\r\n\r\n");
|
||||
if (bodyStart != std::string::npos) {
|
||||
httpResponse.body = response.substr(bodyStart + 4);
|
||||
}
|
||||
if (response.find("Transfer-Encoding: chunked") != std::string::npos
|
||||
&& response.find("Content-Type: application/json") != std::string::npos) {
|
||||
int jsonStart = httpResponse.body.find("{");
|
||||
int jsonEnd = httpResponse.body.find_last_of("}");
|
||||
if (jsonStart != std::string::npos && jsonEnd != std::string::npos) {
|
||||
httpResponse.body = httpResponse.body.substr(jsonStart, jsonEnd - jsonStart + 2);
|
||||
}
|
||||
}
|
||||
return httpResponse;
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#include <aws/gamelift/internal/util/JsonHelper.h>
|
||||
|
||||
using namespace Aws::GameLift::Internal;
|
||||
|
||||
std::string JsonHelper::SafelyDeserializeString(const rapidjson::Value &value, const char *key) {
|
||||
return value.HasMember(key) && value[key].IsString() ? value[key].GetString() : "";
|
||||
}
|
||||
|
||||
void JsonHelper::WriteNonEmptyString(rapidjson::Writer<rapidjson::StringBuffer> *writer, const char *key, const std::string &value) {
|
||||
if (!value.empty()) {
|
||||
writer->String(key);
|
||||
writer->String(value.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
int JsonHelper::SafelyDeserializeInt(const rapidjson::Value &value, const char *key) {
|
||||
return value.HasMember(key) && value[key].IsInt() ? value[key].GetInt() : -1;
|
||||
}
|
||||
|
||||
void JsonHelper::WritePositiveInt(rapidjson::Writer<rapidjson::StringBuffer> *writer, const char *key, int value) {
|
||||
if (value > 0) {
|
||||
writer->String(key);
|
||||
writer->Int(value);
|
||||
}
|
||||
}
|
||||
|
||||
int64_t JsonHelper::SafelyDeserializeInt64(const rapidjson::Value &value, const char *key) {
|
||||
return value.HasMember(key) && value[key].IsInt64() ? value[key].GetInt64() : -1;
|
||||
}
|
||||
|
||||
void JsonHelper::WritePositiveInt64(rapidjson::Writer<rapidjson::StringBuffer> *writer, const char *key, int64_t value) {
|
||||
if (value > 0) {
|
||||
writer->String(key);
|
||||
writer->Int64(value);
|
||||
}
|
||||
}
|
||||
|
||||
Aws::GameLift::Server::LogParameters JsonHelper::SafelyDeserializeLogParameters(const rapidjson::Value &value, const char *key) {
|
||||
if (!value.HasMember(key) || !value[key].IsArray() || value[key].Size() == 0) {
|
||||
return Aws::GameLift::Server::LogParameters();
|
||||
}
|
||||
|
||||
const rapidjson::SizeType numLogPaths = value[key].Size();
|
||||
#ifdef GAMELIFT_USE_STD
|
||||
std::vector<std::string> logPaths = std::vector<std::string>();
|
||||
#else
|
||||
char **logPaths = new char *[numLogPaths];
|
||||
#endif
|
||||
|
||||
for (rapidjson::SizeType i = 0; i < numLogPaths; i++) {
|
||||
if (value[key][i].IsString()) {
|
||||
#ifdef GAMELIFT_USE_STD
|
||||
logPaths.push_back(value[key][i].GetString());
|
||||
#else
|
||||
logPaths[i] = new char[MAX_PATH_LENGTH];
|
||||
#ifdef WIN32
|
||||
strcpy_s(logPaths[i], MAX_PATH_LENGTH, value[key][i].GetString());
|
||||
#else
|
||||
strncpy(logPaths[i], value[key][i].GetString(), MAX_PATH_LENGTH);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef GAMELIFT_USE_STD
|
||||
return Aws::GameLift::Server::LogParameters(logPaths);
|
||||
#else
|
||||
Aws::GameLift::Server::LogParameters toReturn(logPaths, numLogPaths);
|
||||
|
||||
for (rapidjson::SizeType i = 0; i < numLogPaths; i++) {
|
||||
delete[] logPaths[i];
|
||||
}
|
||||
delete[] logPaths;
|
||||
|
||||
return toReturn;
|
||||
#endif
|
||||
}
|
||||
|
||||
void JsonHelper::WriteLogParameters(rapidjson::Writer<rapidjson::StringBuffer> *writer, const char *key, const Aws::GameLift::Server::LogParameters &value) {
|
||||
if (value.getLogPathCount() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
writer->String(key);
|
||||
writer->StartArray();
|
||||
|
||||
for (size_t i = 0; i < value.getLogPathCount(); i++) {
|
||||
const char *logPath = value.getLogPath(i);
|
||||
// If logPath is not empty, write it.
|
||||
if (logPath && logPath[0]) {
|
||||
writer->String(value.getLogPath(i));
|
||||
}
|
||||
}
|
||||
|
||||
writer->EndArray();
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#include <aws/gamelift/internal/util/LoggerHelper.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <spdlog/sinks/stdout_color_sinks.h>
|
||||
#include <spdlog/sinks/rotating_file_sink.h>
|
||||
|
||||
using namespace Aws::GameLift::Internal;
|
||||
|
||||
#ifdef GAMELIFT_USE_STD
|
||||
void LoggerHelper::InitializeLogger(const std::string& process_Id) {
|
||||
auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
|
||||
std::string serverSdkLog = "logs/gamelift-server-sdk-";
|
||||
serverSdkLog.append(process_Id).append(".log");
|
||||
auto file_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(serverSdkLog, 10485760, 5);
|
||||
|
||||
console_sink->set_pattern("%^[%Y-%m-%d %H:%M:%S] [%l] %v%$");
|
||||
file_sink->set_pattern("[%Y-%m-%d %H:%M:%S] [%l] %v");
|
||||
|
||||
spdlog::logger logger("multi_sink", { console_sink, file_sink });
|
||||
logger.set_level(spdlog::level::info);
|
||||
logger.flush_on(spdlog::level::info);
|
||||
|
||||
spdlog::set_default_logger(std::make_shared<spdlog::logger>(logger));
|
||||
}
|
||||
#else
|
||||
void LoggerHelper::InitializeLogger(const char* process_Id) {
|
||||
auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
|
||||
std::string serverSdkLog = "logs/gamelift-server-sdk-";
|
||||
serverSdkLog.append(process_Id).append(".log");
|
||||
auto file_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(serverSdkLog, 10485760, 5);
|
||||
|
||||
console_sink->set_pattern("%^[%Y-%m-%d %H:%M:%S] [%l] %v%$");
|
||||
file_sink->set_pattern("[%Y-%m-%d %H:%M:%S] [%l] %v");
|
||||
|
||||
spdlog::logger logger("multi_sink", { console_sink, file_sink });
|
||||
logger.set_level(spdlog::level::info);
|
||||
logger.flush_on(spdlog::level::info);
|
||||
|
||||
spdlog::set_default_logger(std::make_shared<spdlog::logger>(logger));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/util/RandomStringGenerator.h>
|
||||
#include <random>
|
||||
#include <sstream>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Internal {
|
||||
|
||||
std::string RandomStringGenerator::GenerateRandomAlphaNumericString(const int stringLength) {
|
||||
std::stringstream ss;
|
||||
static const char alphaNumChars[] = "0123456789"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz";
|
||||
static thread_local std::mt19937 randomNumberGenerator(std::random_device{}());
|
||||
// Distribution has an inclusive upper bound. "alphaNumChars" will end in a null terminator, so
|
||||
// we use "sizeof() - 2" to avoid out of bounds errors, and also to avoid including the null
|
||||
// terminator.
|
||||
std::uniform_int_distribution<int> distribution(0, sizeof(alphaNumChars) - 2);
|
||||
|
||||
for (int i = 0; i < stringLength; i++) {
|
||||
ss << alphaNumChars[distribution(randomNumberGenerator)];
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/internal/util/UriEncoder.h>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
using namespace Aws::GameLift::Internal;
|
||||
|
||||
std::string UriEncoder::UriEncode(const std::string &value) {
|
||||
std::ostringstream escaped;
|
||||
escaped.fill('0');
|
||||
escaped << std::hex << std::uppercase;
|
||||
for (char c: value) {
|
||||
if (isalnum(static_cast<unsigned char>(c)) || c == '-' || c == '_' || c == '.' || c == '~') {
|
||||
escaped << c;
|
||||
} else {
|
||||
escaped << '%' << std::setw(2) << static_cast<int>(static_cast<unsigned char>(c));
|
||||
}
|
||||
}
|
||||
return escaped.str();
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#include <aws/gamelift/metrics/Combiner.h>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
void Combiner::Add(MetricMessage message) {
|
||||
if (message.IsGauge()) {
|
||||
// We have to do a bit more work for gauges to convert GaugeAdd to GaugeSet
|
||||
UpdateGauge(message);
|
||||
} else {
|
||||
auto it = m_combinedMessages.find(message.Metric);
|
||||
if (it == std::end(m_combinedMessages)) {
|
||||
m_combinedMessages.emplace(message.Metric, message);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(message.IsCounter() || message.IsTimer());
|
||||
if (message.IsCounter()) {
|
||||
UpdateCounter(it->second, message);
|
||||
} else if (message.IsTimer()) {
|
||||
UpdateTimer(it->second, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Combiner::UpdateGauge(const MetricMessage &message) {
|
||||
assert(message.Type == MetricMessageType::GaugeSet ||
|
||||
message.Type == MetricMessageType::GaugeAdd);
|
||||
|
||||
if (message.Type == MetricMessageType::GaugeSet) {
|
||||
// If setting - we just use the new value
|
||||
m_combinedMessages[message.Metric] = message;
|
||||
m_gaugeHistory[message.Metric] = message;
|
||||
} else if (message.Type == MetricMessageType::GaugeAdd) {
|
||||
// If adding - we get historic value (if available) and add to it
|
||||
// if there's no historic value, we just add to 0
|
||||
double currentValue = 0;
|
||||
auto it = m_gaugeHistory.find(message.Metric);
|
||||
if (it != std::end(m_gaugeHistory)) {
|
||||
currentValue = it->second.SubmitDouble.Value;
|
||||
}
|
||||
currentValue += message.SubmitDouble.Value;
|
||||
|
||||
auto newMessage = MetricMessage::GaugeSet(*message.Metric, currentValue);
|
||||
m_combinedMessages[message.Metric] = newMessage;
|
||||
m_gaugeHistory[message.Metric] = newMessage;
|
||||
}
|
||||
}
|
||||
|
||||
void Combiner::UpdateCounter(MetricMessage ¤t,
|
||||
const MetricMessage &newMessage) {
|
||||
assert(newMessage.Type == MetricMessageType::CounterAdd);
|
||||
|
||||
// Just sum the values.
|
||||
current.SubmitDouble.Value += newMessage.SubmitDouble.Value;
|
||||
}
|
||||
|
||||
void Combiner::UpdateTimer(MetricMessage ¤t,
|
||||
const MetricMessage &newMessage) {
|
||||
assert(newMessage.Type == MetricMessageType::TimerSet);
|
||||
|
||||
// Grab or init sample count
|
||||
auto sampleCountIt = m_timerSampleCount.find(current.Metric);
|
||||
if (sampleCountIt != std::end(m_timerSampleCount)) {
|
||||
++(sampleCountIt->second);
|
||||
} else {
|
||||
// This is the second sample being added, hence we initialize it to 2.
|
||||
auto pair = m_timerSampleCount.emplace(current.Metric, 2);
|
||||
|
||||
const bool insertSuccess = pair.second;
|
||||
assert(insertSuccess);
|
||||
|
||||
sampleCountIt = pair.first;
|
||||
}
|
||||
|
||||
// Welford's algorithm
|
||||
// numerically stable mean
|
||||
//
|
||||
// Knuth - TACOP Vol 2 pg. 216
|
||||
//
|
||||
// https://nullbuffer.com/articles/welford_algorithm.html
|
||||
const double update =
|
||||
(newMessage.SubmitDouble.Value - current.SubmitDouble.Value) /
|
||||
sampleCountIt->second;
|
||||
current.SubmitDouble.Value += update;
|
||||
}
|
||||
|
||||
void Combiner::Clear() {
|
||||
m_combinedMessages.clear();
|
||||
m_timerSampleCount.clear();
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <aws/gamelift/metrics/CrashReporterClient.h>
|
||||
#include <aws/gamelift/internal/retry/RetryingCallable.h>
|
||||
#include <aws/gamelift/internal/retry/JitteredGeometricBackoffRetryStrategy.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <stdexcept>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Metrics {
|
||||
|
||||
CrashReporterClient::CrashReporterClient(const std::string& host, int port)
|
||||
: httpClient(std::make_shared<Aws::GameLift::Internal::HttpClient>()) {
|
||||
baseUrl = "http://" + host + ":" + std::to_string(port) + "/";
|
||||
}
|
||||
|
||||
CrashReporterClient::CrashReporterClient(std::shared_ptr<Aws::GameLift::Internal::HttpClient> httpClient, const std::string &host, int port)
|
||||
: httpClient(std::move(httpClient)) {
|
||||
baseUrl = "http://" + host + ":" + std::to_string(port) + "/";
|
||||
}
|
||||
|
||||
bool CrashReporterClient::isRetryableError(const std::string& errorMessage) const {
|
||||
return errorMessage.find("Connection refused") != std::string::npos ||
|
||||
errorMessage.find("Connection failed") != std::string::npos;
|
||||
}
|
||||
|
||||
void CrashReporterClient::RegisterProcessWithRetries() {
|
||||
#ifdef _WIN32
|
||||
int processPid = static_cast<int>(GetCurrentProcessId());
|
||||
#else
|
||||
int processPid = static_cast<int>(getpid());
|
||||
#endif
|
||||
std::string requestUri = baseUrl + RegisterProcessUrlPath + "?" +
|
||||
ProcessPidParameterName + "=" + std::to_string(processPid);
|
||||
|
||||
spdlog::info("Registering process with {} {} in OTEL Collector Crash Reporter", ProcessPidParameterName, processPid);
|
||||
|
||||
// 5 retries, 1s base delay with jitter (default)
|
||||
// Total max wait time: ~1s + 2s + 4s + 8s + 16s = ~31s
|
||||
Aws::GameLift::Internal::JitteredGeometricBackoffRetryStrategy retryStrategy;
|
||||
|
||||
auto callable = [this, &requestUri, processPid]() -> bool {
|
||||
try {
|
||||
auto response = httpClient->SendGetRequest(requestUri);
|
||||
if (response.IsSuccessfulStatusCode()) {
|
||||
spdlog::info("Successfully registered {} {} to OTEL Collector Crash Reporter", ProcessPidParameterName, processPid);
|
||||
return true;
|
||||
} else {
|
||||
spdlog::error("Failed to register {} {} to OTEL Collector Crash Reporter, Http response: {} - {}",
|
||||
ProcessPidParameterName, processPid, response.statusCode, response.body);
|
||||
return true; // Don't retry on HTTP errors (4xx, 5xx)
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
std::string errorMsg = e.what();
|
||||
if (isRetryableError(errorMsg)) {
|
||||
spdlog::warn("Failed to register {} {} to OTEL Collector Crash Reporter due to connection error: {}",
|
||||
ProcessPidParameterName, processPid, e.what());
|
||||
return false; // Retry on connection errors
|
||||
} else {
|
||||
spdlog::error("Failed to register {} {} to OTEL Collector Crash Reporter due to error: {}",
|
||||
ProcessPidParameterName, processPid, e.what());
|
||||
return true; // Don't retry on other errors
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Aws::GameLift::Internal::RetryingCallable::Builder()
|
||||
.WithRetryStrategy(&retryStrategy)
|
||||
.WithCallable(callable)
|
||||
.Build()
|
||||
.call();
|
||||
}
|
||||
|
||||
void CrashReporterClient::RegisterProcess() {
|
||||
RegisterProcessWithRetries();
|
||||
}
|
||||
|
||||
void CrashReporterClient::TagGameSession(const std::string& sessionId) {
|
||||
#ifdef _WIN32
|
||||
int processPid = static_cast<int>(GetCurrentProcessId());
|
||||
#else
|
||||
int processPid = static_cast<int>(getpid());
|
||||
#endif
|
||||
std::string requestUri = baseUrl + UpdateProcessUrlPath + "?" +
|
||||
ProcessPidParameterName + "=" + std::to_string(processPid) + "&" +
|
||||
SessionIdParameterName + "=" + sessionId;
|
||||
|
||||
try {
|
||||
spdlog::info("Adding {} tag {} to process with {} {} to the OTEL Collector Crash Reporter",
|
||||
SessionIdParameterName, sessionId, ProcessPidParameterName, processPid);
|
||||
auto response = httpClient->SendGetRequest(requestUri);
|
||||
if (!response.IsSuccessfulStatusCode()) {
|
||||
spdlog::error("Failed to add {} tag {} to process with {} {} in the OTEL Collector Crash Reporter, Http response: {} - {}",
|
||||
SessionIdParameterName, sessionId, ProcessPidParameterName, processPid,
|
||||
response.statusCode, response.body);
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
spdlog::error("Failed to add {} tag {} to process with {} {} in the OTEL Collector Crash Reporter due to error: {}",
|
||||
SessionIdParameterName, sessionId, ProcessPidParameterName, processPid, e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void CrashReporterClient::DeregisterProcess() {
|
||||
#ifdef _WIN32
|
||||
int processPid = static_cast<int>(GetCurrentProcessId());
|
||||
#else
|
||||
int processPid = static_cast<int>(getpid());
|
||||
#endif
|
||||
std::string requestUri = baseUrl + DeregisterProcessUrlPath + "?" +
|
||||
ProcessPidParameterName + "=" + std::to_string(processPid);
|
||||
|
||||
try {
|
||||
spdlog::info("Unregistering process with {} {} in OTEL Collector Crash Reporter",
|
||||
ProcessPidParameterName, processPid);
|
||||
auto response = httpClient->SendGetRequest(requestUri);
|
||||
if (!response.IsSuccessfulStatusCode()) {
|
||||
spdlog::error("Failed to deregister {} {} in the OTEL Collector Crash Reporter, Http response: {} - {}",
|
||||
ProcessPidParameterName, processPid, response.statusCode, response.body);
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
spdlog::error("Failed to deregister {} {} in the OTEL Collector Crash Reporter due to error: {}",
|
||||
ProcessPidParameterName, processPid, e.what());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Metrics
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#include <aws/gamelift/metrics/DerivedMetric.h>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Metrics {
|
||||
IDerivedMetric::~IDerivedMetric() {}
|
||||
|
||||
IDerivedMetricVisitor::~IDerivedMetricVisitor() {}
|
||||
|
||||
IDerivedMetricCollection::~IDerivedMetricCollection() {}
|
||||
} // namespace Metrics
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#include <aws/gamelift/metrics/DynamicMetric.h>
|
||||
|
||||
#ifndef GAMELIFT_USE_STD
|
||||
#include <cstring>
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Metrics {
|
||||
void DynamicMetric::SetKey(const char *newKey) {
|
||||
#ifdef _WIN32
|
||||
strncpy_s(m_key, DynamicMetric::MAXIMUM_KEY_LENGTH, newKey,
|
||||
DynamicMetric::MAXIMUM_KEY_LENGTH);
|
||||
#else
|
||||
strncpy(m_key, newKey, DynamicMetric::MAXIMUM_KEY_LENGTH);
|
||||
#endif // _WIN32
|
||||
}
|
||||
} // namespace Metrics
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
|
||||
#endif // !GAMELIFT_USE_STD
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#include <aws/gamelift/metrics/GlobalMetricsProcessor.h>
|
||||
#include <aws/gamelift/metrics/IMetricsProcessor.h>
|
||||
#include <aws/gamelift/metrics/MetricsProcessor.h>
|
||||
#include <aws/gamelift/metrics/LoggerMacros.h>
|
||||
#include <aws/gamelift/metrics/CrashReporterClient.h>
|
||||
#include <aws/gamelift/metrics/StatsDClient.h>
|
||||
#include <aws/gamelift/server/model/GameSession.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#ifdef __linux__
|
||||
#include <unistd.h>
|
||||
#elif defined(_WIN32) || defined(_WIN64)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
GAMELIFT_METRICS_DEFINE_GAUGE(ServerUpGauge);
|
||||
|
||||
namespace {
|
||||
std::unique_ptr<::Aws::GameLift::Metrics::IMetricsProcessor>
|
||||
GlobalProcessor(nullptr);
|
||||
std::shared_ptr<::Aws::GameLift::Metrics::StatsDClient>
|
||||
GlobalStatsDClient(nullptr);
|
||||
std::shared_ptr<::Aws::GameLift::Metrics::CrashReporterClient>
|
||||
GlobalCrashReporter(nullptr);
|
||||
|
||||
void InitializeCrashReporter(const MetricsSettings &settings) {
|
||||
std::string crashReporterHost;
|
||||
#ifdef GAMELIFT_USE_STD
|
||||
crashReporterHost = settings.CrashReporterHost;
|
||||
#else
|
||||
crashReporterHost = (settings.CrashReporterHost != nullptr) ? std::string(settings.CrashReporterHost) : "";
|
||||
#endif
|
||||
// Skip crash reporter initialization if host is empty
|
||||
if (crashReporterHost.empty()) {
|
||||
GAMELIFT_METRICS_LOG_INFO("Crash reporter disabled - host not set");
|
||||
return;
|
||||
}
|
||||
int crashReporterPort = settings.CrashReporterPort;
|
||||
GlobalCrashReporter = std::make_shared<CrashReporterClient>(crashReporterHost, crashReporterPort);
|
||||
GlobalCrashReporter->RegisterProcess();
|
||||
}
|
||||
|
||||
void InitializeStatsDClient(const MetricsSettings &settings) {
|
||||
std::string statsdHost;
|
||||
#ifdef GAMELIFT_USE_STD
|
||||
statsdHost = settings.StatsDClientHost;
|
||||
#else
|
||||
statsdHost = (settings.StatsDClientHost != nullptr) ? std::string(settings.StatsDClientHost) : "";
|
||||
#endif
|
||||
// Skip crash reporter initialization if host is empty
|
||||
if (statsdHost.empty()) {
|
||||
GAMELIFT_METRICS_LOG_INFO("StatsDClient disabled - host not set");
|
||||
return;
|
||||
}
|
||||
int statsdPort = settings.StatsDClientPort;
|
||||
GlobalStatsDClient = std::make_shared<StatsDClient>(statsdHost.c_str(), statsdPort);
|
||||
GAMELIFT_METRICS_LOG_INFO("Created StatsD client for {}:{}", statsdHost, statsdPort);
|
||||
}
|
||||
|
||||
void InitializeDefaultGlobalTags() {
|
||||
if (GlobalProcessor) {
|
||||
// Check if GAMELIFT_SDK_PROCESS_ID environment variable is set
|
||||
const char *processId = std::getenv(ENV_VAR_PROCESS_ID);
|
||||
if (processId != nullptr && processId[0] != '\0') {
|
||||
GlobalProcessor->SetGlobalTag("gamelift_process_id", processId);
|
||||
|
||||
GAMELIFT_METRICS_LOG_INFO("Set global tag gamelift_process_id: {}",
|
||||
processId);
|
||||
}
|
||||
|
||||
// Set the OS process ID (Linux and Windows).
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
DWORD pid = GetCurrentProcessId();
|
||||
std::string pidStr = std::to_string(pid);
|
||||
#else
|
||||
pid_t pid = getpid();
|
||||
std::string pidStr = std::to_string(pid);
|
||||
#endif
|
||||
GlobalProcessor->SetGlobalTag("process_pid", pidStr.c_str());
|
||||
GAMELIFT_METRICS_LOG_INFO("Set global tag process_pid: {}", pidStr);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Metrics {
|
||||
|
||||
void MetricsInitialize(const MetricsSettings &settings) {
|
||||
GAMELIFT_METRICS_LOG_INFO("Initializing GameLift Servers Metrics");
|
||||
|
||||
assert(!GlobalProcessor);
|
||||
InitializeCrashReporter(settings);
|
||||
InitializeStatsDClient(settings);
|
||||
|
||||
// Create settings with StatsD callback only if no callback is already set
|
||||
MetricsSettings settingsWithCallbackOverride = settings;
|
||||
if (!settings.SendPacketCallback) {
|
||||
settingsWithCallbackOverride.SendPacketCallback = [](const char* data, int size) {
|
||||
if (GlobalStatsDClient) {
|
||||
GlobalStatsDClient->Send(data, size);
|
||||
} else {
|
||||
GAMELIFT_METRICS_LOG_ERROR("StatsDClient is not initialized. Cannot send metrics data.");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
GlobalProcessor.reset(new MetricsProcessor(settingsWithCallbackOverride));
|
||||
InitializeDefaultGlobalTags();
|
||||
|
||||
GAMELIFT_METRICS_LOG_INFO(
|
||||
"GameLift Servers Metrics initialized successfully");
|
||||
}
|
||||
|
||||
void MetricsTerminate() {
|
||||
GAMELIFT_METRICS_SET(ServerUpGauge, 0);
|
||||
|
||||
// Process the final metrics before shutting down
|
||||
if (GlobalProcessor) {
|
||||
GlobalProcessor->ProcessMetricsNow();
|
||||
}
|
||||
|
||||
if (GlobalCrashReporter) {
|
||||
GlobalCrashReporter->DeregisterProcess();
|
||||
GlobalCrashReporter.reset();
|
||||
}
|
||||
|
||||
if (GlobalStatsDClient) {
|
||||
GlobalStatsDClient.reset();
|
||||
}
|
||||
|
||||
GlobalProcessor.reset();
|
||||
}
|
||||
|
||||
void MetricsProcess() {
|
||||
assert(GlobalProcessor);
|
||||
if (GlobalProcessor) {
|
||||
GlobalProcessor->ProcessMetrics();
|
||||
}
|
||||
}
|
||||
|
||||
void OnGameSessionStarted(
|
||||
const Aws::GameLift::Server::Model::GameSession &session) {
|
||||
assert(GlobalProcessor);
|
||||
if (GlobalProcessor) {
|
||||
GlobalProcessor->OnStartGameSession(session);
|
||||
}
|
||||
if (GlobalCrashReporter) {
|
||||
#ifdef GAMELIFT_USE_STD
|
||||
GlobalCrashReporter->TagGameSession(session.GetGameSessionId());
|
||||
#else
|
||||
GlobalCrashReporter->TagGameSession(std::string(session.GetGameSessionId()));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Metrics
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
|
||||
::Aws::GameLift::Metrics::IMetricsProcessor *GameLiftMetricsGlobalProcessor() {
|
||||
return GlobalProcessor.get();
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
#include <aws/gamelift/metrics/HighResolutionClock.h>
|
||||
|
||||
#ifndef GAMELIFT_USE_STD
|
||||
#include <aws/gamelift/metrics/InternalTypes.h>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
/**
|
||||
* We hide the internal chrono use and report a time as int64 nanoseconds
|
||||
* publicly.
|
||||
*
|
||||
* Then convert back to chrono internally.
|
||||
*/
|
||||
|
||||
namespace {
|
||||
using Nanoseconds =
|
||||
std::chrono::duration<Aws::GameLift::Metrics::Int64, std::nano>;
|
||||
}
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Metrics {
|
||||
namespace Internal {
|
||||
Int64 HighResolutionClock::Now() {
|
||||
const auto now = std::chrono::high_resolution_clock::now();
|
||||
return std::chrono::time_point_cast<Nanoseconds>(now)
|
||||
.time_since_epoch()
|
||||
.count();
|
||||
}
|
||||
|
||||
double HighResolutionClock::ToMilliseconds(Int64 duration) {
|
||||
using Milliseconds = std::chrono::duration<double, std::milli>;
|
||||
return std::chrono::duration_cast<Milliseconds>(Nanoseconds(duration))
|
||||
.count();
|
||||
}
|
||||
} // namespace Internal
|
||||
} // namespace Metrics
|
||||
} // namespace GameLift
|
||||
} // namespace Aws
|
||||
|
||||
#endif // !GAMELIFT_USE_STD
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user