Merge branch 'main' into TIF/Runtime

This commit is contained in:
jonawals
2021-04-28 13:11:29 +01:00
5475 changed files with 104625 additions and 129714 deletions
-2
View File
@@ -1,2 +0,0 @@
#Ignore these directories
SDKs
@@ -26,4 +26,4 @@ public class ${ANDROID_PROJECT_ACTIVITY} extends LumberyardActivity
System.loadLibrary("c++_shared");
Log.d("LMBR", "BootStrap: Finished Library load");
}
}
}
@@ -85,4 +85,4 @@
[
"wscript"
]
}
}
@@ -78,4 +78,4 @@
}]
}]
}
}
}
+1 -1
View File
@@ -4,4 +4,4 @@
<bool name="use_patch_obb">${ANDROID_USE_PATCH_OBB}</bool>
<bool name="enable_keep_screen_on">${ANDROID_ENABLE_KEEP_SCREEN_ON}</bool>
<bool name="disable_immersive_mode">${ANDROID_DISABLE_IMMERSIVE_MODE}</bool>
</resources>
</resources>
@@ -79,4 +79,4 @@ ${CUSTOM_APPLY_ASSET_LAYOUT_RELEASE_TASK}
${CUSTOM_GRADLE_COPY_NATIVE_DEBUG_LIB_TASK}
${CUSTOM_GRADLE_COPY_NATIVE_PROFILE_LIB_TASK}
${CUSTOM_GRADLE_COPY_NATIVE_RELEASE_LIB_TASK}
}
}
@@ -164,4 +164,4 @@
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
@@ -11,4 +11,4 @@
"version_name" : "1.0.0.0",
"orientation" : "landscape"
}
}
}
@@ -8,4 +8,4 @@
"Tags": ["Foo"],
"IconPath": "preview.png",
"EditorModule": true
}
}
@@ -8,4 +8,4 @@
"Tags": ["Foo"],
"IconPath": "preview.png",
"EditorModule": true
}
}
@@ -8,4 +8,4 @@
"Tags": ["Foo"],
"IconPath": "preview.png",
"EditorModule": true
}
}
+1 -1
View File
@@ -13,4 +13,4 @@
namespace AssetBundler
{
extern const char RelativeTestFolder[];
}
}
@@ -190,4 +190,4 @@ namespace AssetBuilder
}
return functionAddr;
}
}
}
@@ -14,4 +14,4 @@
void AssetBuilderApplication::InstallCtrlHandler()
{
}
}
@@ -32,4 +32,4 @@ namespace AssetBuilderApplicationPrivate
void AssetBuilderApplication::InstallCtrlHandler()
{
::SetConsoleCtrlHandler(AssetBuilderApplicationPrivate::CtrlHandlerRoutine, TRUE);
}
}
@@ -20,4 +20,4 @@ set(FILES
TraceMessageHook.h
TraceMessageHook.cpp
AssetBuilder.rc
)
)
@@ -117,4 +117,4 @@ namespace AssetBuilderSDK
};
typedef AZ::EBus<JobCommandTraits> JobCommandBus;
}
}
@@ -68,4 +68,4 @@ namespace AssetBuilderSDK
}
#endif //ASSETBUILDERUTILEBUSHELPER_H
#endif //ASSETBUILDERUTILEBUSHELPER_H
@@ -11,4 +11,4 @@
*/
#pragma once
#include <AssetProcessor_Traits_Linux.h>
#include <AssetProcessor_Traits_Linux.h>
@@ -11,4 +11,4 @@
*/
#pragma once
#include <AssetProcessor_Traits_Mac.h>
#include <AssetProcessor_Traits_Mac.h>
@@ -56,4 +56,4 @@
"version" : 1,
"author" : "xcode"
}
}
}
@@ -56,4 +56,4 @@
"version" : 1,
"author" : "xcode"
}
}
}
@@ -3,4 +3,4 @@
"version" : 1,
"author" : "xcode"
}
}
}
@@ -22,4 +22,4 @@ set_target_properties(AssetProcessor PROPERTIES
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Platform/Mac/gui_info.plist
RESOURCE ${CMAKE_CURRENT_SOURCE_DIR}/Platform/Mac/Images.xcassets
XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME AssetProcessorAppIcon
)
)
@@ -11,4 +11,4 @@
*/
#pragma once
#include <AssetProcessor_Traits_Windows.h>
#include <AssetProcessor_Traits_Windows.h>
@@ -85,4 +85,4 @@ namespace AssetProcessor
};
} // namespace AssetProcessor
#endif //ASSETPROCESSOR_RCQUEUESORTMODEL_H
#endif //ASSETPROCESSOR_RCQUEUESORTMODEL_H
@@ -32,4 +32,4 @@ namespace AssetProcessor
AZ::AllocatorInstance<AZ::SystemAllocator>::Destroy();
}
};
}
}
@@ -42,4 +42,4 @@ private:
QLineEdit* m_id;
QLineEdit* m_ipAddress;
AzQtComponents::SpinBox* m_port;
};
};
@@ -140,4 +140,4 @@ QListWidget::item:hover {
QListWidget QHeaderView::section {
background-color: rgb(34,34,34);
}
}
@@ -5,4 +5,4 @@
<rect id="Icon-Background" x="0" y="0" width="24" height="24"></rect>
<polygon id="Combined-Shape" fill="#FFFFFF" transform="translate(12.000000, 12.000000) rotate(90.000000) translate(-12.000000, -12.000000) " points="17 11 12 6 12 3 21 12 12 21 12 18 17 13 3 13 3 11"></polygon>
</g>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 643 B

After

Width:  |  Height:  |  Size: 644 B

@@ -5,4 +5,4 @@
<rect id="Icon-Background" x="0" y="0" width="24" height="24"></rect>
<polygon id="Combined-Shape" fill="#FFFFFF" points="7.02553943 13 12 18.0361734 12 21 3 12 12 3 12 5.98884985 7 11 21 11 21 13"></polygon>
</g>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 571 B

After

Width:  |  Height:  |  Size: 572 B

@@ -5,4 +5,4 @@
<rect id="Icon-Background" x="0" y="0" width="24" height="24"></rect>
<polygon id="Combined-Shape" fill="#FFFFFF" points="17 11 12 6 12 3 21 12 12 21 12 18 17 13 3 13 3 11"></polygon>
</g>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 544 B

After

Width:  |  Height:  |  Size: 545 B

@@ -5,4 +5,4 @@
<rect id="Icon-Background" x="0" y="0" width="24" height="24"></rect>
<polygon id="Combined-Shape" fill="#FFFFFF" transform="translate(12.000000, 12.000000) rotate(90.000000) translate(-12.000000, -12.000000) " points="7.02553943 13 12 18.0361734 12 21 3 12 12 3 12 5.98884985 7 11 21 11 21 13"></polygon>
</g>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 664 B

After

Width:  |  Height:  |  Size: 665 B

@@ -8,4 +8,4 @@
<path d="M21,3 L21,19.5 L21.0070809,19.5 L21.0070809,20.9975284 L21,20.997 L21,21 L19.5,21 L19.5,20.997 L7.97261837,21 L9.45378213,19.5 L19.5,19.5 L19.5,7 L4.5,7 L4.5,14.7148938 L3,16.0495017 L3,3 L21,3 Z" id="Combined-Shape" fill="#FFFFFF"></path>
<path d="M13.5,17 L12,17 L12,13.063 L4.06066017,21.0033009 L3,19.9426407 L10.942,12 L7,12 L7,10.5 L13.5,10.5 L13.5,17 Z" id="Combined-Shape" fill="#FFFFFF"></path>
</g>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 994 B

After

Width:  |  Height:  |  Size: 995 B

@@ -8,4 +8,4 @@
<path d="M21,3 L21,19.5 L21.0070809,19.5 L21.0070809,20.9975284 L21,20.997 L21,21 L19.5,21 L19.5,20.997 L7.97261837,21 L9.45378213,19.5 L19.5,19.5 L19.5,7 L4.5,7 L4.5,14.7148938 L3,16.0495017 L3,3 L21,3 Z" id="Combined-Shape" fill="#17A3CD"></path>
<path d="M13.5,17 L12,17 L12,13.063 L4.06066017,21.0033009 L3,19.9426407 L10.942,12 L7,12 L7,10.5 L13.5,10.5 L13.5,17 Z" id="Combined-Shape" fill="#17A3CD"></path>
</g>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 1006 B

After

Width:  |  Height:  |  Size: 1007 B

@@ -5,4 +5,4 @@
<rect id="Icon-Background" x="0" y="0" width="24" height="24"></rect>
<path d="M13,3 L13,11 L21,11 L21,13 L13,13 L13,21 L11,21 L11,13 L3,13 L3,11 L11,11 L11,3 L13,3 Z" id="Combined-Shape" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 583 B

After

Width:  |  Height:  |  Size: 584 B

@@ -106,4 +106,4 @@ namespace AssetProcessor
QByteArray m_payload;
SendMessageCallBack m_callback;
};
}
}
@@ -93,4 +93,4 @@ namespace AssetProcessor
return true;
}
} // namespace AssetProcessor
} // namespace AssetProcessor
@@ -36,4 +36,4 @@ private:
char m_streamBuffer[128];
AZStd::string m_stringBeingConcatenated;
AZStd::string m_errorStringBeingConcatenated;
};
};
@@ -66,4 +66,4 @@ namespace AssetProcessor
AZStd::map<AZ::Uuid, PotentialDependencyMetaData> m_uuids;
AZStd::map<AZ::Data::AssetId, PotentialDependencyMetaData> m_assetIds;
};
}
}
@@ -16,4 +16,4 @@ provo=copy
; this will remove "mov" from the default configuration
[RC mov]
ignore=true
ignore=true
@@ -10,4 +10,4 @@
"use_main_obb" : "false",
"use_patch_obb" : "false"
}
}
}
@@ -12,4 +12,4 @@
set(FILES
platform_android.cpp
native_app_glue_include.c
)
)
@@ -12,4 +12,4 @@
set(FILES
../Common/platform_host_main.cpp
../Common/platform_host_posix.cpp
)
)
@@ -12,4 +12,4 @@
set(FILES
../Common/platform_host_main.cpp
../Common/platform_host_posix.cpp
)
)
@@ -12,4 +12,4 @@
set(FILES
../Common/platform_host_main.cpp
platform_windows.cpp
)
)
@@ -12,4 +12,4 @@
set(FILES
Resources/Info.plist
Launcher_iOS.mm
)
)
+2 -3
View File
@@ -13,8 +13,8 @@ add_subdirectory(SceneAPI) # Needs to go before AssetProcessor since it provides
add_subdirectory(AssetProcessor)
add_subdirectory(AWSNativeSDKInit)
add_subdirectory(AzTestRunner)
add_subdirectory(CrashHandler)
add_subdirectory(CryCommonTools)
add_subdirectory(CrySCompileServer)
add_subdirectory(CryXML)
add_subdirectory(HLSLCrossCompiler)
add_subdirectory(HLSLCrossCompilerMETAL)
@@ -22,11 +22,10 @@ add_subdirectory(News)
add_subdirectory(PythonBindingsExample)
add_subdirectory(RC)
add_subdirectory(RemoteConsole)
add_subdirectory(CrashHandler)
add_subdirectory(ShaderCacheGen)
add_subdirectory(DeltaCataloger)
add_subdirectory(SerializeContextTools)
add_subdirectory(AssetBundler)
add_subdirectory(GridHub)
add_subdirectory(Standalone)
add_subdirectory(TestImpactFramework)
add_subdirectory(TestImpactFramework)
+3 -5
View File
@@ -32,11 +32,11 @@ ly_add_target(
PRIVATE
${pal_dir}
BUILD_DEPENDENCIES
PUBLIC
AZ::CrashSupport
PRIVATE
3rdParty::Crashpad
AZ::AzCore
AZ::AzFramework
AZ::CrashSupport
)
string(REPLACE "." ";" version_list "${LY_VERSION_STRING}")
@@ -67,11 +67,9 @@ ly_add_target(
PRIVATE
Uploader/include/Uploader
BUILD_DEPENDENCIES
PRIVATE
AZ::AzCore
AZ::CrashSupport
PUBLIC
3rdParty::Crashpad::Handler
AZ::CrashSupport
)
add_subdirectory(Tools)
@@ -12,4 +12,4 @@
#pragma once
#define AZ_TRAIT_CRASHHANDLER_CONVERT_MULTIBYTE_CHARS 0
#define AZ_TRAIT_CRASHHANDLER_WAIT_FOR_COMPLETED_HANDLER_LAUNCH 0
#define AZ_TRAIT_CRASHHANDLER_WAIT_FOR_COMPLETED_HANDLER_LAUNCH 0
@@ -11,4 +11,4 @@
*/
#pragma once
#include <CrashHandler_Traits_Android.h>
#include <CrashHandler_Traits_Android.h>
@@ -12,4 +12,4 @@
#pragma once
#define AZ_TRAIT_CRASHHANDLER_CONVERT_MULTIBYTE_CHARS 0
#define AZ_TRAIT_CRASHHANDLER_WAIT_FOR_COMPLETED_HANDLER_LAUNCH 0
#define AZ_TRAIT_CRASHHANDLER_WAIT_FOR_COMPLETED_HANDLER_LAUNCH 0
@@ -11,4 +11,4 @@
*/
#pragma once
#include <CrashHandler_Traits_Linux.h>
#include <CrashHandler_Traits_Linux.h>
@@ -12,4 +12,4 @@
#pragma once
#define AZ_TRAIT_CRASHHANDLER_CONVERT_MULTIBYTE_CHARS 0
#define AZ_TRAIT_CRASHHANDLER_WAIT_FOR_COMPLETED_HANDLER_LAUNCH 0
#define AZ_TRAIT_CRASHHANDLER_WAIT_FOR_COMPLETED_HANDLER_LAUNCH 0
@@ -11,4 +11,4 @@
*/
#pragma once
#include <CrashHandler_Traits_Mac.h>
#include <CrashHandler_Traits_Mac.h>
@@ -11,4 +11,4 @@
*/
#pragma once
#include <CrashHandler_Traits_Windows.h>
#include <CrashHandler_Traits_Windows.h>
@@ -12,4 +12,4 @@
#pragma once
#define AZ_TRAIT_CRASHHANDLER_CONVERT_MULTIBYTE_CHARS 1
#define AZ_TRAIT_CRASHHANDLER_WAIT_FOR_COMPLETED_HANDLER_LAUNCH 1
#define AZ_TRAIT_CRASHHANDLER_WAIT_FOR_COMPLETED_HANDLER_LAUNCH 1
@@ -11,4 +11,4 @@
*/
#pragma once
#include <CrashHandler_Traits_iOS.h>
#include <CrashHandler_Traits_iOS.h>
@@ -12,4 +12,4 @@
#pragma once
#define AZ_TRAIT_CRASHHANDLER_CONVERT_MULTIBYTE_CHARS 0
#define AZ_TRAIT_CRASHHANDLER_WAIT_FOR_COMPLETED_HANDLER_LAUNCH 0
#define AZ_TRAIT_CRASHHANDLER_WAIT_FOR_COMPLETED_HANDLER_LAUNCH 0
@@ -69,4 +69,4 @@ namespace CrashHandler
std::string m_submissionToken;
};
}
}
@@ -19,6 +19,6 @@ ly_add_target(
PUBLIC
include
BUILD_DEPENDENCIES
PRIVATE
PUBLIC
AZ::AzCore
)
@@ -82,4 +82,4 @@ namespace CrashHandler
returnPath = returnPath.substr(0, extPos);
}
}
}
}
@@ -35,4 +35,4 @@ namespace CrashHandler
time(&rawtime);
localtime_s(&timeInfo, &rawtime);
}
}
}
@@ -31,4 +31,4 @@ namespace CrashHandler
return buffer;
}
}
}
+3 -7
View File
@@ -21,13 +21,13 @@ ly_add_target(
tools_crash_handler_files.cmake
Platform/${PAL_PLATFORM_NAME}/tools_crash_handler_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
INCLUDE_DIRECTORIES
PRIVATE
PUBLIC
.
BUILD_DEPENDENCIES
PUBLIC
AZ::CrashHandler
PRIVATE
3rdParty::Qt::Core
AZ::CrashHandler
AZ::CrashSupport
AZ::AzToolsFramework
)
@@ -41,18 +41,14 @@ ly_add_target(
Platform/${PAL_PLATFORM_NAME}/tools_crash_uploader_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
INCLUDE_DIRECTORIES
PRIVATE
.
Uploader
BUILD_DEPENDENCIES
PRIVATE
3rdParty::Qt::Core
3rdParty::Qt::Gui
3rdParty::Qt::Widgets
3rdParty::Crashpad
3rdParty::Crashpad::Handler
AZ::CrashUploaderSupport
AZ::AzQtComponents
AZ::CrashSupport
TARGET_PROPERTIES
Qt5_NO_LINK_QTMAIN TRUE
)
@@ -37,4 +37,4 @@ namespace CrashHandler
virtual void GetOSAnnotations(CrashHandlerAnnotations& annotations) const override;
};
}
}
@@ -33,4 +33,4 @@ namespace CrashHandler
}
return returnPath;
}
}
}
@@ -26,4 +26,4 @@ namespace O3de
static std::string GetRootFolder();
};
}
}
@@ -33,4 +33,4 @@ namespace O3de
BufferedDataStream& operator=(const BufferedDataStream& rhs) = delete;
};
}
}
@@ -72,4 +72,4 @@ namespace O3de
std::string m_submissionToken;
std::string m_executableName;
};
}
}
@@ -31,4 +31,4 @@ namespace O3de
base::FilePath m_filePath;
};
}
}
@@ -138,7 +138,7 @@ namespace O3de
if (!logFileReader->Open(thisFile))
{
#if defined(AZ_PLATFORM_WINDOWS)
LOG(ERROR) << "Failed to open " << base::UTF16ToUTF8(thisFile.BaseName().value());
LOG(ERROR) << "Failed to open " << base::WideToUTF8(thisFile.BaseName().value());
#else
LOG(ERROR) << "Failed to open " << thisFile.BaseName().value();
#endif
@@ -149,7 +149,7 @@ namespace O3de
if (start_offset < 0)
{
#if defined(AZ_PLATFORM_WINDOWS)
LOG(ERROR) << "Failed to get offset for " << base::UTF16ToUTF8(thisFile.BaseName().value());
LOG(ERROR) << "Failed to get offset for " << base::WideToUTF8(thisFile.BaseName().value());
#else
LOG(ERROR) << "Failed to get offset for " << thisFile.BaseName().value();
#endif
@@ -162,7 +162,7 @@ namespace O3de
std::string fileNameKey{ "attachment_" };
#if defined(AZ_PLATFORM_WINDOWS)
fileNameKey += base::UTF16ToUTF8(thisFile.BaseName().value());
fileNameKey += base::WideToUTF8(thisFile.BaseName().value());
#else
fileNameKey += thisFile.BaseName().value();
#endif
@@ -246,4 +246,4 @@ namespace O3de
// Reset so we can loop again inside crashpad
optind = 0;
}
}
}
+1 -1
View File
@@ -27,4 +27,4 @@ void invert_affine(AffineParts *parts, AffineParts *inverse);
#endif // CRYINCLUDE_CRYCOMMONTOOLS_DECOMPOSE_H
}
}
@@ -294,4 +294,4 @@ NonSkeletalAnimationData::State::State()
NonSkeletalAnimationData::ModelEntry::ModelEntry()
: flags(0)
{
}
}
@@ -127,4 +127,4 @@ bool ExportSourceDecoratorBase::HasValidRotController(const IModelData* modelDat
bool ExportSourceDecoratorBase::HasValidSclController(const IModelData* modelData, int modelIndex) const
{
return this->source->HasValidSclController(modelData, modelIndex);
}
}
@@ -104,4 +104,4 @@ bool MaterialHelpers::WriteMaterials(const std::string& filename, const std::vec
{
return false;
}
}
}
@@ -51,4 +51,4 @@ set(FILES
ZipDir/ZipFileFormat.h
ZipDir/ZipFileFormat_info.h
SuffixUtil.h
)
)
+1 -1
View File
@@ -150,4 +150,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>
@@ -1,12 +0,0 @@
#
# 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.
#
add_subdirectory(CrySCompileServer)
@@ -1,63 +0,0 @@
#
# 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.
#
ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME})
ly_get_list_relative_pal_filename(common_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/Common)
ly_get_pal_tool_dirs(pal_tool_dirs ${CMAKE_CURRENT_LIST_DIR}/Platform)
ly_get_pal_tool_dirs(pal_tool_core_server_dirs ${CMAKE_CURRENT_LIST_DIR}/Core/Server/Platform)
include(${pal_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake)
if(NOT PAL_TRAIT_BUILD_CRYSCOMPILESERVER_SUPPORTED OR NOT PAL_TRAIT_BUILD_HOST_TOOLS)
return()
endif()
set(platform_tools_files)
foreach(enabled_platform ${LY_PAL_TOOLS_ENABLED})
string(TOLOWER ${enabled_platform} enabled_platform_lowercase)
ly_get_list_relative_pal_filename(pal_tool_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${enabled_platform})
list(APPEND platform_tools_files ${pal_tool_dir}/pal_tools_${enabled_platform_lowercase}.cmake)
endforeach()
ly_add_target(
NAME CrySCompileServer EXECUTABLE
NAMESPACE Legacy
FILES_CMAKE
cryscompileserver_files.cmake
PLATFORM_INCLUDE_FILES
Platform/${PAL_PLATFORM_NAME}/platform_${PAL_PLATFORM_NAME_LOWERCASE}.cmake
${platform_tools_files}
${common_dir}/${PAL_TRAIT_COMPILER_ID}/cryscompileserver_${PAL_TRAIT_COMPILER_ID_LOWERCASE}.cmake
INCLUDE_DIRECTORIES
PUBLIC
.
External
PRIVATE
${pal_tool_dirs}
${pal_tool_core_server_dirs}
BUILD_DEPENDENCIES
PRIVATE
3rdParty::zlib
AZ::AzCore
AZ::AzFramework
)
ly_add_source_properties(
SOURCES
Core/Server/CrySimpleJobCompile.cpp
CrySCompileServer.cpp
PROPERTY COMPILE_DEFINITIONS
VALUES ${LY_PAL_TOOLS_DEFINES}
)
ly_add_source_properties(
SOURCES Core/Server/CrySimpleServer.cpp
PROPERTY COMPILE_DEFINITIONS
VALUES ${LY_PAL_TOOLS_DEFINES}
)
@@ -1,39 +0,0 @@
/*
* 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.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef CRYINCLUDE_CRYSCOMPILESERVER_CORE_COMMON_H
#define CRYINCLUDE_CRYSCOMPILESERVER_CORE_COMMON_H
#pragma once
#include <AzCore/base.h>
#include <AzCore/PlatformDef.h>
#include <AzCore/PlatformIncl.h>
#if defined(AZ_PLATFORM_WINDOWS)
# if !defined(_WIN32_WINNT)
# define _WIN32_WINNT 0x0501
# endif
// Windows platform requires either a long or an unsigned long/uint64 for the
// Interlock instructions.
typedef long AtomicCountType;
#else
// Linux/Mac platforms don't support a long for the atomic types, only int32 or
// int64 (no unsigned support).
typedef int32_t AtomicCountType;
#endif
#endif // CRYINCLUDE_CRYSCOMPILESERVER_CORE_COMMON_H
@@ -1,73 +0,0 @@
/*
* 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.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "StdTypes.hpp"
#include "Error.hpp"
#include <tinyxml/tinyxml.h>
#include "Server/CrySimpleErrorLog.hpp"
#include "Server/CrySimpleJob.hpp"
#include <AzCore/base.h>
#include <AzCore/Debug/Trace.h>
#include <time.h>
ICryError::ICryError(EErrorType t)
: m_eType(t)
, m_numDupes(0)
{
}
void logmessage(const char* text, ...)
{
va_list arg;
va_start(arg, text);
char szBuffer[256];
char* error = szBuffer;
int bufferlen = sizeof(szBuffer) - 1;
memset(szBuffer, 0, sizeof(szBuffer));
long req = CCrySimpleJob::GlobalRequestNumber();
int ret = azsnprintf(error, bufferlen, "%8ld | ", req);
if (ret <= 0)
{
return;
}
error += ret;
bufferlen -= ret;
time_t ltime;
time(&ltime);
tm today;
#if defined(AZ_PLATFORM_WINDOWS)
localtime_s(&today, &ltime);
#else
localtime_r(&ltime, &today);
#endif
ret = (int)strftime(error, bufferlen, "%d/%m %H:%M:%S | ", &today);
if (ret <= 0)
{
return;
}
error += ret;
bufferlen -= ret;
vsnprintf(error, bufferlen, text, arg);
AZ_TracePrintf(0, szBuffer);
va_end(arg);
}
@@ -1,95 +0,0 @@
/*
* 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.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef __DXPSERROR__
#define __DXPSERROR__
#include <string>
#include <set>
#include "STLHelper.hpp"
// printf wrapper to format things nicely
void logmessage(const char* text, ...);
class ICryError
{
public:
enum EErrorType
{
SIMPLE_ERROR = 0,
COMPILE_ERROR,
};
enum EOutputFormatType
{
OUTPUT_EMAIL = 0,
OUTPUT_TTY,
OUTPUT_HASH,
};
ICryError(EErrorType t);
virtual ~ICryError() {};
EErrorType GetType() const { return m_eType; }
tdHash Hash() const { return CSTLHelper::Hash(GetErrorName() + GetErrorDetails(OUTPUT_HASH)); };
virtual bool Compare(const ICryError* err) const
{
if (GetType() != err->GetType())
{
return GetType() < err->GetType();
}
return Hash() < err->Hash();
};
virtual bool CanMerge([[maybe_unused]] const ICryError* err) const { return true; }
virtual void AddDuplicate([[maybe_unused]] ICryError* err) { m_numDupes++; }
uint32_t NumDuplicates() const { return m_numDupes; }
virtual void SetUniqueID([[maybe_unused]] int uniqueID) {}
virtual bool HasFile() const { return false; };
virtual void AddCCs([[maybe_unused]] std::set<std::string>& ccs) const {}
virtual std::string GetErrorName() const = 0;
virtual std::string GetErrorDetails(EOutputFormatType outputType) const = 0;
virtual std::string GetFilename() const { return "NoFile"; }
virtual std::string GetFileContents() const { return ""; }
private:
EErrorType m_eType;
uint32_t m_numDupes;
};
class CSimpleError
: public ICryError
{
public:
CSimpleError(const std::string& in_text)
: ICryError(SIMPLE_ERROR)
, m_text(in_text) {}
virtual ~CSimpleError() {}
virtual std::string GetErrorName() const { return m_text; };
virtual std::string GetErrorDetails([[maybe_unused]] EOutputFormatType outputType) const { return m_text; };
private:
std::string m_text;
};
#define CrySimple_ERROR(X) throw new CSimpleError(X)
#define CrySimple_SECURE_START try{
#define CrySimple_SECURE_END }catch (const ICryError* err) {printf(err->GetErrorName().c_str()); delete err; }
#endif
@@ -1,334 +0,0 @@
/*
* 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.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef __CSCMD5__
#define __CSCMD5__
/*
* This code implements the MD5 message-digest algorithm.
* The algorithm is due to Ron Rivest. This code was
* written by Colin Plumb in 1993, no copyright is claimed.
* This code is in the public domain; do with it what you wish.
*
* Equivalent code is available from RSA Data Security, Inc.
* This code has been tested against that, and is equivalent,
* except that you don't need to include two pages of legalese
* with every copy.
*
* To compute the message digest of a chunk of bytes, declare an
* MD5Context structure, pass it to MD5Init, call MD5Update as
* needed on buffers full of bytes, and then call MD5Final, which
* will fill a supplied 16-byte array with the digest.
*/
/* This code was modified in 1997 by Jim Kingdon of Cyclic Software to
not require an integer type which is exactly 32 bits. This work
draws on the changes for the same purpose by Tatu Ylonen
<ylo@cs.hut.fi> as part of SSH, but since I didn't actually use
that code, there is no copyright issue. I hereby disclaim
copyright in any changes I have made; this code remains in the
public domain. */
/* Note regarding cvs_* namespace: this avoids potential conflicts
with libraries such as some versions of Kerberos. No particular
need to worry about whether the system supplies an MD5 library, as
this file is only about 3k of object code. */
struct cvs_MD5Context
{
uint32_t buf[4];
uint32_t bits[2];
unsigned char in[64];
};
void cvs_MD5Init(struct cvs_MD5Context* context);
void cvs_MD5Update(struct cvs_MD5Context* context, unsigned char const* buf, unsigned len);
void cvs_MD5Final(unsigned char digest[16], struct cvs_MD5Context* context);
void cvs_MD5Transform(uint32_t buf[4], const unsigned char in[64]);
/* Little-endian byte-swapping routines. Note that these do not
depend on the size of datatypes such as uint32_t, nor do they require
us to detect the endianness of the machine we are running on. It
is possible they should be macros for speed, but I would be
surprised if they were a performance bottleneck for MD5. */
uint32_t getu32 (const unsigned char* addr)
{
return (((((unsigned long)addr[3] << 8) | addr[2]) << 8) | addr[1]) << 8 | addr[0];
}
void putu32(uint32_t data, unsigned char* addr)
{
addr[0] = (unsigned char)data;
addr[1] = (unsigned char)(data >> 8);
addr[2] = (unsigned char)(data >> 16);
addr[3] = (unsigned char)(data >> 24);
}
/*
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
* initialization constants.
*/
void cvs_MD5Init(cvs_MD5Context& rCtx)
{
rCtx.buf[0] = 0x67452301;
rCtx.buf[1] = 0xefcdab89;
rCtx.buf[2] = 0x98badcfe;
rCtx.buf[3] = 0x10325476;
rCtx.bits[0] = 0;
rCtx.bits[1] = 0;
}
/*
* Update context to reflect the concatenation of another buffer full
* of bytes.
*/
void cvs_MD5Update(cvs_MD5Context& rCtx, unsigned char const* buf, uint32_t len)
{
uint32_t t;
/* Update bitcount */
t = rCtx.bits[0];
if ((rCtx.bits[0] = (t + ((uint32_t)len << 3)) & 0xffffffff) < t)
{
rCtx.bits[1]++; /* Carry from low to high */
}
rCtx.bits[1] += len >> 29;
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
/* Handle any leading odd-sized chunks */
if (t)
{
unsigned char* p = rCtx.in + t;
t = 64 - t;
if (len < t)
{
memcpy(p, buf, len);
return;
}
memcpy(p, buf, t);
cvs_MD5Transform (rCtx.buf, rCtx.in);
buf += t;
len -= t;
}
/* Process data in 64-byte chunks */
while (len >= 64)
{
memcpy(rCtx.in, buf, 64);
cvs_MD5Transform (rCtx.buf, rCtx.in);
buf += 64;
len -= 64;
}
/* Handle any remaining bytes of data. */
memcpy(rCtx.in, buf, len);
}
/*
* Final wrapup - pad to 64-byte boundary with the bit pattern
* 1 0* (64-bit count of bits processed, MSB-first)
*/
void cvs_MD5Final(unsigned char digest[16], cvs_MD5Context& rCtx)
{
unsigned count;
uint8_t* p;
/* Compute number of bytes mod 64 */
count = (rCtx.bits[0] >> 3) & 0x3F;
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
p = rCtx.in + count;
*p++ = 0x80;
/* Bytes of padding needed to make 64 bytes */
count = 64 - 1 - count;
/* Pad out to 56 mod 64 */
if (count < 8)
{
/* Two lots of padding: Pad the first block to 64 bytes */
memset(p, 0, count);
cvs_MD5Transform (rCtx.buf, rCtx.in);
/* Now fill the next block with 56 bytes */
memset(rCtx.in, 0, 56);
}
else
{
/* Pad block to 56 bytes */
memset(p, 0, count - 8);
}
/* Append length in bits and transform */
putu32(rCtx.bits[0], rCtx.in + 56);
putu32(rCtx.bits[1], rCtx.in + 60);
cvs_MD5Transform (rCtx.buf, rCtx.in);
putu32(rCtx.buf[0], digest);
putu32(rCtx.buf[1], digest + 4);
putu32(rCtx.buf[2], digest + 8);
putu32(rCtx.buf[3], digest + 12);
//memset(&rCtx,0,sizeof(rCtx)); // In case it's sensitive
}
/* The four core functions - F1 is optimized somewhat */
/* #define F1(x, y, z) (x & y | ~x & z) */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f, w, x, y, z, data, s) \
(w += f(x, y, z) + data, w &= 0xffffffff, w = w << s | w >> (32 - s), w += x)
/*
* The core of the MD5 algorithm, this alters an existing MD5 hash to
* reflect the addition of 16 longwords of new data. MD5Update blocks
* the data and converts bytes into longwords for this routine.
*/
void cvs_MD5Transform(uint32_t buf[4], const unsigned char inraw[64])
{
uint32_t a, b, c, d;
uint32_t in[16];
int i;
for (i = 0; i < 16; ++i)
{
in[i] = getu32 (inraw + 4 * i);
}
a = buf[0];
b = buf[1];
c = buf[2];
d = buf[3];
MD5STEP(F1, a, b, c, d, in[ 0] + 0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12);
MD5STEP(F1, c, d, a, b, in[ 2] + 0x242070db, 17);
MD5STEP(F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22);
MD5STEP(F1, a, b, c, d, in[ 4] + 0xf57c0faf, 7);
MD5STEP(F1, d, a, b, c, in[ 5] + 0x4787c62a, 12);
MD5STEP(F1, c, d, a, b, in[ 6] + 0xa8304613, 17);
MD5STEP(F1, b, c, d, a, in[ 7] + 0xfd469501, 22);
MD5STEP(F1, a, b, c, d, in[ 8] + 0x698098d8, 7);
MD5STEP(F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12);
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
MD5STEP(F2, a, b, c, d, in[ 1] + 0xf61e2562, 5);
MD5STEP(F2, d, a, b, c, in[ 6] + 0xc040b340, 9);
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
MD5STEP(F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20);
MD5STEP(F2, a, b, c, d, in[ 5] + 0xd62f105d, 5);
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
MD5STEP(F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20);
MD5STEP(F2, a, b, c, d, in[ 9] + 0x21e1cde6, 5);
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
MD5STEP(F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14);
MD5STEP(F2, b, c, d, a, in[ 8] + 0x455a14ed, 20);
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
MD5STEP(F2, d, a, b, c, in[ 2] + 0xfcefa3f8, 9);
MD5STEP(F2, c, d, a, b, in[ 7] + 0x676f02d9, 14);
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
MD5STEP(F3, a, b, c, d, in[ 5] + 0xfffa3942, 4);
MD5STEP(F3, d, a, b, c, in[ 8] + 0x8771f681, 11);
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
MD5STEP(F3, a, b, c, d, in[ 1] + 0xa4beea44, 4);
MD5STEP(F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11);
MD5STEP(F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16);
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
MD5STEP(F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11);
MD5STEP(F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16);
MD5STEP(F3, b, c, d, a, in[ 6] + 0x04881d05, 23);
MD5STEP(F3, a, b, c, d, in[ 9] + 0xd9d4d039, 4);
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
MD5STEP(F3, b, c, d, a, in[ 2] + 0xc4ac5665, 23);
MD5STEP(F4, a, b, c, d, in[ 0] + 0xf4292244, 6);
MD5STEP(F4, d, a, b, c, in[ 7] + 0x432aff97, 10);
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
MD5STEP(F4, b, c, d, a, in[ 5] + 0xfc93a039, 21);
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
MD5STEP(F4, d, a, b, c, in[ 3] + 0x8f0ccc92, 10);
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
MD5STEP(F4, b, c, d, a, in[ 1] + 0x85845dd1, 21);
MD5STEP(F4, a, b, c, d, in[ 8] + 0x6fa87e4f, 6);
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
MD5STEP(F4, c, d, a, b, in[ 6] + 0xa3014314, 15);
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
MD5STEP(F4, a, b, c, d, in[ 4] + 0xf7537e82, 6);
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
MD5STEP(F4, c, d, a, b, in[ 2] + 0x2ad7d2bb, 15);
MD5STEP(F4, b, c, d, a, in[ 9] + 0xeb86d391, 21);
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}
/*
#include <stdio.h>
int
main (int argc, char **argv)
{
struct cvs_MD5Context context;
unsigned char checksum[16];
int i;
int j;
if (argc < 2)
{
fprintf (stderr, "usage: %s string-to-hash\n", argv[0]);
exit (1);
}
for (j = 1; j < argc; ++j)
{
printf ("MD5 (\"%s\") = ", argv[j]);
cvs_MD5Init (&context);
cvs_MD5Update (&context, argv[j], strlen (argv[j]));
cvs_MD5Final (checksum, &context);
for (i = 0; i < 16; i++)
{
printf ("%02x", (unsigned int) checksum[i]);
}
printf ("\n");
}
return 0;
}
*/
#endif
@@ -1,420 +0,0 @@
/*
* 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.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "Mailer.h"
#include "WindowsAPIImplementation.h"
#include <AzCore/PlatformDef.h>
#include <assert.h>
#if defined(AZ_PLATFORM_MAC)
#include <netdb.h>
#include <unistd.h>
#elif defined(AZ_PLATFORM_WINDOWS)
#include <ws2tcpip.h>
#endif
#include <AzCore/base.h>
#include <AzCore/IO/SystemFile.h>
#pragma comment(lib,"ws2_32.lib")
namespace // helpers
{
static const char cb64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
void Base64EncodeBlock(const unsigned char* in, unsigned char* out)
{
out[0] = cb64[in[0] >> 2];
out[1] = cb64[((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4)];
out[2] = cb64[((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6)];
out[3] = cb64[in[2] & 0x3f];
}
void Base64EncodeBlock(const unsigned char* in, unsigned char* out, int len)
{
out[0] = cb64[in[0] >> 2];
out[1] = cb64[((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4)];
out[2] = (unsigned char) (len > 1 ? cb64[((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6)] : '=');
out[3] = (unsigned char) (len > 2 ? cb64[in[2] & 0x3f] : '=');
}
void Base64Encode(const unsigned char* pSrc, const size_t srcLen, unsigned char* pDst, [[maybe_unused]] const size_t dstLen)
{
assert(dstLen >= 4 * ((srcLen + 2) / 3));
size_t len = srcLen;
for (; len > 2; len -= 3, pSrc += 3, pDst += 4)
{
Base64EncodeBlock(pSrc, pDst);
}
if (len > 0)
{
unsigned char in[3];
in[0] = pSrc[0];
in[1] = len > 1 ? pSrc[1] : 0;
in[2] = 0;
Base64EncodeBlock(in, pDst, (int) len);
}
}
std::string Base64EncodeString(const std::string& in)
{
const size_t srcLen = in.size();
const size_t dstLen = 4 * ((srcLen + 2) / 3);
std::string out(dstLen, 0);
Base64Encode((const unsigned char*) in.c_str(), srcLen, (unsigned char*) out.c_str(), dstLen);
return out;
}
const char* ExtractFileName(const char* filepath)
{
for (const char* p = filepath + strlen(filepath) - 1; p >= filepath; --p)
{
if (*p == '\\' || *p == '/')
{
return p + 1;
}
}
return filepath;
}
}
AZStd::atomic_long CSMTPMailer::ms_OpenSockets = {0};
CSMTPMailer::CSMTPMailer(const tstr& username, const tstr& password, const tstr& server, int port)
: m_server(server)
, m_username(username)
, m_password(password)
, m_port(port)
, m_winSockAvail(false)
, m_response()
{
#if defined(AZ_PLATFORM_WINDOWS)
WSADATA wd;
m_winSockAvail = WSAStartup(MAKEWORD(1, 1), &wd) == 0;
if (!m_winSockAvail)
{
m_response += "Error: Unable to initialize WinSock 1.1\n";
}
#endif
}
CSMTPMailer::~CSMTPMailer()
{
#if defined(AZ_PLATFORM_WINDOWS)
if (m_winSockAvail)
{
WSACleanup();
}
#endif
}
void CSMTPMailer::ReceiveLine(SOCKET connection)
{
char buf[1025];
int ret = recv(connection, buf, sizeof(buf) - 1, 0);
if (ret == SOCKET_ERROR)
{
ret = azsnprintf(buf, sizeof(buf), "Error: WinSock error %d during recv()\n", WSAGetLastError());
if (ret == sizeof(buf) || ret < 0)
{
buf[sizeof(buf) - 1] = '\0';
}
}
else
{
buf[ret] = 0;
}
m_response += buf;
}
void CSMTPMailer::SendLine(SOCKET connection, const char* format, ...) const
{
char buf[2049];
va_list args;
va_start(args, format);
int len = azvsnprintf(buf, sizeof(buf), format, args);
if (len == sizeof(buf) || len < 0)
{
buf[sizeof(buf) - 1] = '\0';
len = sizeof(buf) - 1;
}
va_end(args);
send(connection, buf, len, 0);
}
void CSMTPMailer::SendRaw(SOCKET connection, const char* data, size_t dataLen) const
{
send(connection, data, (int) dataLen, 0);
}
void CSMTPMailer::SendFile(SOCKET connection, const tattachment& filepath, const char* boundary) const
{
AZ::IO::SystemFile inputFile;
const bool wasSuccessful = inputFile.Open(filepath.second.c_str(), AZ::IO::SystemFile::SF_OPEN_READ_ONLY);
if (wasSuccessful)
{
SendLine(connection, "--%s\r\n", boundary);
SendLine(connection, "Content-Type: application/octet-stream\r\n");
SendLine(connection, "Content-Transfer-Encoding: base64\r\n");
SendLine(connection, "Content-Disposition: attachment; filename=\"%s\"\r\n", filepath.first.c_str());
SendLine(connection, "\r\n");
AZ::IO::SystemFile::SizeType fileSize = inputFile.Length();
while (fileSize)
{
const int DEF_BLOCK_SIZE = 128; // 72
char in[3 * DEF_BLOCK_SIZE];
size_t blockSize = fileSize > sizeof(in) ? sizeof(in) : fileSize;
inputFile.Read(blockSize, in);
char out[4 * DEF_BLOCK_SIZE];
Base64Encode((unsigned char*) in, blockSize, (unsigned char*) out, sizeof(out));
SendRaw(connection, out, 4 * ((blockSize + 2) / 3));
SendLine(connection, "\r\n"); // seems to get sent faster if you split up the data lines
fileSize -= blockSize;
}
}
}
SOCKET CSMTPMailer::Open(const char* host, unsigned short port, sockaddr_in& serverAddress)
{
SOCKET connection = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (connection == INVALID_SOCKET)
{
m_response += "Error: Failed to create socket\n";
return 0;
}
struct addrinfo* addressInfo{};
char portBuffer[16];
struct addrinfo hints{};
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
azsnprintf(portBuffer, AZStd::size(portBuffer), "%hu", port);
int addrInfoReturnCode = getaddrinfo(host, portBuffer, &hints, &addressInfo);
if(addrInfoReturnCode != 0)
{
char buf[1025];
int ret = azsnprintf(buf, sizeof(buf), "Error: Host %s not found\n", host);
if (ret == sizeof(buf) || ret < 0)
{
buf[sizeof(buf) - 1] = '\0';
}
m_response += buf;
closesocket(connection);
return 0;
}
if (addressInfo)
{
++ms_OpenSockets;
serverAddress = *reinterpret_cast<sockaddr_in*>(addressInfo->ai_addr);
}
return connection;
}
void CSMTPMailer::AddReceivers(SOCKET connection, const tstrcol& receivers)
{
for (tstrcol::const_iterator it = receivers.begin(), itEnd = receivers.end(); it != itEnd; ++it)
{
if (!(*it).empty())
{
SendLine(connection, "rcpt to: %s\r\n", (*it).c_str());
ReceiveLine(connection);
}
}
}
void CSMTPMailer::AssignReceivers(SOCKET connection, const char* receiverTag, const tstrcol& receivers)
{
tstrcol::const_iterator it = receivers.begin();
tstrcol::const_iterator itEnd = receivers.end();
while (it != itEnd && (*it).empty())
{
++it;
}
if (it != itEnd)
{
tstr out(receiverTag);
out += *it;
++it;
for (; it != itEnd; ++it)
{
if (!(*it).empty())
{
out += "; ";
out += *it;
}
}
out += "\r\n";
SendLine(connection, out.c_str());
}
}
void CSMTPMailer::SendAttachments(SOCKET connection, const tattachlist& attachments, const char* boundary)
{
for (tattachlist::const_iterator it = attachments.begin(), itEnd = attachments.end(); it != itEnd; ++it)
{
if (!(*it).first.empty() && !(*it).second.empty())
{
SendFile(connection, *it, boundary);
}
}
}
bool CSMTPMailer::IsEmpty(const tstrcol& col) const
{
if (!col.empty())
{
for (tstrcol::const_iterator it = col.begin(), itEnd = col.end(); it != itEnd; ++it)
{
if (!(*it).empty())
{
return false;
}
}
}
return true;
}
bool CSMTPMailer::Send(const tstr& from, const tstrcol& to, const tstrcol& cc, const tstrcol& bcc, const tstr& subject, const tstr& body, const tattachlist& attachments)
{
if (!m_winSockAvail)
{
return false;
}
if (from.empty() || IsEmpty(to))
{
return false;
}
sockaddr_in serverAddress;
SOCKET connection = Open(m_server.c_str(), m_port, serverAddress); // SMTP telnet (usually port 25)
if (connection == INVALID_SOCKET)
{
return false;
}
if (connect(connection, (sockaddr*) &serverAddress, sizeof(serverAddress)) != SOCKET_ERROR)
{
ReceiveLine(connection);
SendLine(connection, "helo localhost\r\n");
ReceiveLine(connection);
if (!m_username.empty() && !m_password.empty())
{
SendLine(connection, "auth login\r\n"); // most servers should implement this (todo: otherwise fall back to PLAIN or CRAM-MD5 (requiring EHLO))
ReceiveLine(connection);
SendLine(connection, "%s\r\n", Base64EncodeString(m_username).c_str());
ReceiveLine(connection);
SendLine(connection, "%s\r\n", Base64EncodeString(m_password).c_str());
ReceiveLine(connection);
}
SendLine(connection, "mail from: %s\r\n", from.c_str());
ReceiveLine(connection);
AddReceivers(connection, to);
AddReceivers(connection, cc);
AddReceivers(connection, bcc);
SendLine(connection, "data\r\n");
ReceiveLine(connection);
SendLine(connection, "From: %s\r\n", from.c_str());
AssignReceivers(connection, "To: ", to);
AssignReceivers(connection, "Cc: ", cc);
AssignReceivers(connection, "Bcc: ", bcc);
SendLine(connection, "Subject: %s\r\n", subject.c_str());
static const char boundary[] = "------a95ed0b485e4a9b0fd4ff93f50ad06ca"; // beware, boundary should not clash with text content of message body!
SendLine(connection, "MIME-Version: 1.0\r\n");
SendLine(connection, "Content-Type: multipart/mixed; boundary=\"%s\"\r\n", boundary);
SendLine(connection, "\r\n");
SendLine(connection, "This is a multi-part message in MIME format.\r\n");
SendLine(connection, "--%s\r\n", boundary);
SendLine(connection, "Content-Type: text/plain; charset=iso-8859-1; format=flowed\r\n"); // the used charset should support the commonly used special characters of western languages
SendLine(connection, "Content-Transfer-Encoding: 7bit\r\n");
SendLine(connection, "\r\n");
SendRaw(connection, body.c_str(), body.size());
SendLine(connection, "\r\n");
SendAttachments(connection, attachments, boundary);
SendLine(connection, "--%s--\r\n", boundary);
SendLine(connection, "\r\n.\r\n");
ReceiveLine(connection);
SendLine(connection, "quit\r\n");
ReceiveLine(connection);
}
else
{
char buf[1025];
int ret = azsnprintf(buf, sizeof(buf), "Error: Failed to connect to %s:%d\n", m_server.c_str(), m_port);
if (ret == sizeof(buf) || ret < 0)
{
buf[sizeof(buf) - 1] = '\0';
}
m_response += buf;
return false;
}
closesocket(connection);
--ms_OpenSockets;
return true;
}
const char* CSMTPMailer::GetResponse() const
{
return m_response.c_str();
}
@@ -1,72 +0,0 @@
/*
* 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.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef CRYINCLUDE_CRYSCOMPILESERVER_CORE_MAILER_H
#define CRYINCLUDE_CRYSCOMPILESERVER_CORE_MAILER_H
#pragma once
#include "Common.h"
#include "Server/CrySimpleSock.hpp"
#include <string>
#include <set>
#include <list>
#include <memory>
#include <AzCore/std/parallel/atomic.h>
class CSMTPMailer
{
public:
typedef std::string tstr;
typedef std::set<tstr> tstrcol;
typedef std::pair<std::string, std::string> tattachment;
typedef std::list<tattachment> tattachlist;
static const int DEFAULT_PORT = 25;
static AZStd::atomic_long ms_OpenSockets;
public:
CSMTPMailer(const tstr& username, const tstr& password, const tstr& server, int port = DEFAULT_PORT);
~CSMTPMailer();
bool Send(const tstr& from, const tstrcol& to, const tstrcol& cc, const tstrcol& bcc, const tstr& subject, const tstr& body, const tattachlist& attachments);
const char* GetResponse() const;
static long GetOpenSockets() { return ms_OpenSockets; }
private:
void ReceiveLine(SOCKET connection);
void SendLine(SOCKET connection, const char* format, ...) const;
void SendRaw(SOCKET connection, const char* data, size_t dataLen) const;
void SendFile(SOCKET connection, const tattachment& file, const char* boundary) const;
SOCKET Open(const char* host, unsigned short port, sockaddr_in& serverAddress);
void AddReceivers(SOCKET connection, const tstrcol& receivers);
void AssignReceivers(SOCKET connection, const char* receiverTag, const tstrcol& receivers);
void SendAttachments(SOCKET connection, const tattachlist& attachments, const char* boundary);
bool IsEmpty(const tstrcol& col) const;
private:
std::unique_ptr<CCrySimpleSock> m_socket;
tstr m_server;
tstr m_username;
tstr m_password;
int m_port;
bool m_winSockAvail;
tstr m_response;
};
#endif // CRYINCLUDE_CRYSCOMPILESERVER_CORE_MAILER_H
@@ -1,343 +0,0 @@
/*
* 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.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "StdTypes.hpp"
#include "Error.hpp"
#include "STLHelper.hpp"
#include <AzCore/PlatformDef.h>
#include <AzCore/PlatformIncl.h>
#include <AzCore/Debug/Trace.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/Casting/lossy_cast.h>
#if defined(AZ_PLATFORM_WINDOWS)
#include <io.h>
#endif
#include "MD5.hpp"
#include <assert.h>
#include <zlib.h>
#include <algorithm>
#include <functional>
#include <iterator>
#include <cstdio>
void CSTLHelper::Log(const std::string& rLog)
{
const std::string Output = rLog + "\n";
logmessage(Output.c_str());
}
void CSTLHelper::Tokenize(tdEntryVec& rRet, const std::string& Tokens, const std::string& Separator)
{
rRet.clear();
std::string::size_type Pt;
std::string::size_type Start = 0;
std::string::size_type SSize = Separator.size();
while ((Pt = Tokens.find(Separator, Start)) != std::string::npos)
{
std::string SubStr = Tokens.substr(Start, Pt - Start);
rRet.push_back(SubStr);
Start = Pt + SSize;
}
rRet.push_back(Tokens.substr(Start));
}
void CSTLHelper::Replace(std::string& rRet, const std::string& rSrc, const std::string& rToReplace, const std::string& rReplacement)
{
std::vector<uint8_t> Out;
std::vector<uint8_t> In(rSrc.c_str(), rSrc.c_str() + rSrc.size() + 1);
Replace(Out, In, rToReplace, rReplacement);
rRet = std::string(reinterpret_cast<char*>(&Out[0]));
}
void CSTLHelper::Replace(std::vector<uint8_t>& rRet, const std::vector<uint8_t>& rTokenSrc, const std::string& rToReplace, const std::string& rReplacement)
{
rRet.clear();
size_t SSize = rToReplace.size();
for (size_t a = 0, Size = rTokenSrc.size(); a < Size; a++)
{
if (a + SSize < Size && strncmp((const char*)&rTokenSrc[a], rToReplace.c_str(), SSize) == 0)
{
for (size_t b = 0, RSize = rReplacement.size(); b < RSize; b++)
{
rRet.push_back(rReplacement.c_str()[b]);
}
a += SSize - 1;
}
else
{
rRet.push_back(rTokenSrc[a]);
}
}
}
tdToken CSTLHelper::SplitToken(const std::string& rToken, const std::string& rSeparator)
{
#undef min
using namespace std;
string Token;
Remove(Token, rToken, ' ');
string::size_type Pt = Token.find(rSeparator);
return tdToken(Token.substr(0, Pt), Token.substr(std::min(Pt + 1, Token.size())));
}
void CSTLHelper::Splitizer(tdTokenList& rTokenList, const tdEntryVec& rFilter, const std::string& rSeparator)
{
rTokenList.clear();
for (size_t a = 0, Size = rFilter.size(); a < Size; a++)
{
rTokenList.push_back(SplitToken(rFilter[a], rSeparator));
}
}
void CSTLHelper::Trim(std::string& rStr, const std::string& charsToTrim)
{
std::string::size_type Pt1 = rStr.find_first_not_of(charsToTrim);
if (Pt1 == std::string::npos)
{
// At this point the string could be empty or it could only contain 'charsToTrim' characters.
// In case it's the later then trim should be applied by leaving the string empty.
rStr = "";
return;
}
std::string::size_type Pt2 = rStr.find_last_not_of(charsToTrim) + 1;
Pt2 = Pt2 - Pt1;
rStr = rStr.substr(Pt1, Pt2);
}
void CSTLHelper::Remove(std::string& rTokenDst, const std::string& rTokenSrc, const char C)
{
using namespace std;
AZ_PUSH_DISABLE_WARNING(4996, "-Wdeprecated-declarations")
remove_copy_if(rTokenSrc.begin(), rTokenSrc.end(), back_inserter(rTokenDst), [C](char token) { return token == C; });
AZ_POP_DISABLE_WARNING
}
bool CSTLHelper::ToFile(const std::string& rFileName, const std::vector<uint8_t>& rOut)
{
if (rOut.size() == 0)
{
return false;
}
AZ::IO::SystemFile outputFile;
const bool wasSuccessful = outputFile.Open(rFileName.c_str(), AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY | AZ::IO::SystemFile::SF_OPEN_CREATE);
if (wasSuccessful == false)
{
AZ_Error("ShaderCompiler", wasSuccessful, "CSTLHelper::ToFile Could not create file: %s", rFileName.c_str());
return false;
}
outputFile.Write(&rOut[0], rOut.size());
return true;
}
bool CSTLHelper::FromFile(const std::string& rFileName, std::vector<uint8_t>& rIn)
{
AZ::IO::SystemFile inputFile;
bool wasSuccess = inputFile.Open(rFileName.c_str(), AZ::IO::SystemFile::SF_OPEN_READ_WRITE);
if (!wasSuccess)
{
return false;
}
AZ::IO::SystemFile::SizeType fileSize = inputFile.Length();
if (fileSize <= 0)
{
return false;
}
rIn.resize(fileSize);
AZ::IO::SystemFile::SizeType actualReadAmount = inputFile.Read(fileSize, &rIn[0]);
return actualReadAmount == fileSize;
}
bool CSTLHelper::ToFileCompressed(const std::string& rFileName, const std::vector<uint8_t>& rOut)
{
std::vector<uint8_t> buf;
unsigned long sourceLen = (unsigned long)rOut.size();
unsigned long destLen = compressBound(sourceLen) + 16;
buf.resize(destLen);
compress(buf.data(), &destLen, &rOut[0], sourceLen);
if (destLen > 0)
{
AZ::IO::SystemFile outputFile;
const bool wasSuccessful = outputFile.Open(rFileName.c_str(), AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY | AZ::IO::SystemFile::SF_OPEN_CREATE);
AZ_Error("ShaderCompiler", wasSuccessful, "Could not create compressed file: %s", rFileName.c_str());
if (wasSuccessful == false)
{
return false;
}
AZ::IO::SystemFile::SizeType bytesWritten = outputFile.Write(&sourceLen, sizeof(sourceLen));
AZ_Error("ShaderCompiler", bytesWritten == sizeof(sourceLen), "Could not save out size of compressed data to %s", rFileName.c_str());
if (bytesWritten != sizeof(sourceLen))
{
return false;
}
bytesWritten = outputFile.Write(buf.data(), destLen);
AZ_Error("ShaderCompiler", bytesWritten == destLen, "Could not save out compressed data to %s", rFileName.c_str());
if (bytesWritten != destLen)
{
return false;
}
return true;
}
else
{
return false;
}
}
bool CSTLHelper::FromFileCompressed(const std::string& rFileName, std::vector<uint8_t>& rIn)
{
std::vector<uint8_t> buf;
AZ::IO::SystemFile inputFile;
const bool wasSuccessful = inputFile.Open(rFileName.c_str(), AZ::IO::SystemFile::SF_OPEN_READ_ONLY);
AZ_Error("ShaderCompiler", wasSuccessful, "Could not read: ", rFileName.c_str());
if (!wasSuccessful)
{
return false;
}
AZ::IO::SystemFile::SizeType FileLen = inputFile.Length();
AZ_Error("ShaderCompiler", FileLen > 0, "Error getting file-size of ", rFileName.c_str());
if (FileLen <= 0)
{
return false;
}
unsigned long uncompressedLen = 0;
// Possible, expected, loss of data from u64 to u32. Zlib supports only unsigned long
unsigned long sourceLen = azlossy_caster((FileLen - 4));
buf.resize(sourceLen);
AZ::IO::SystemFile::SizeType bytesReadIn = inputFile.Read(sizeof(uncompressedLen), &uncompressedLen);
AZ_Warning("ShaderCompiler", bytesReadIn == sizeof(uncompressedLen), "Expected to read in %d but read in %d from file %s", sizeof(uncompressedLen), bytesReadIn, rFileName.c_str());
bytesReadIn = inputFile.Read(buf.size(), buf.data());
AZ_Warning("ShaderCompiler", bytesReadIn == buf.size(), "Expected to read in %d but read in %d from file %s", buf.size(), bytesReadIn, rFileName.c_str());
unsigned long nUncompressedBytes = uncompressedLen;
rIn.resize(uncompressedLen);
int nRes = uncompress(rIn.data(), &nUncompressedBytes, buf.data(), sourceLen);
return nRes == Z_OK && nUncompressedBytes == uncompressedLen;
}
//////////////////////////////////////////////////////////////////////////
bool CSTLHelper::AppendToFile(const std::string& rFileName, const std::vector<uint8_t>& rOut)
{
AZ::IO::SystemFile outputFile;
int openMode = AZ::IO::SystemFile::SF_OPEN_APPEND;
if (!AZ::IO::SystemFile::Exists(rFileName.c_str()))
{
openMode = AZ::IO::SystemFile::SF_OPEN_CREATE | AZ::IO::SystemFile::SF_OPEN_CREATE_PATH | AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY;
}
const bool wasSuccessful = outputFile.Open(rFileName.c_str(), openMode);
AZ_Error("ShaderCompiler", wasSuccessful, "Could not open file for appending: %s", rFileName.c_str());
if (wasSuccessful == false)
{
return false;
}
[[maybe_unused]] AZ::IO::SystemFile::SizeType bytesWritten = outputFile.Write(rOut.data(), rOut.size());
AZ_Warning("ShaderCompiler", bytesWritten == rOut.size(), "Did not write out all the data to the file: %s", rFileName.c_str());
return true;
}
//////////////////////////////////////////////////////////////////////////
tdHash CSTLHelper::Hash(const uint8_t* pData, const size_t Size)
{
tdHash CheckSum;
cvs_MD5Context MD5Context;
cvs_MD5Init(MD5Context);
cvs_MD5Update(MD5Context, pData, static_cast<uint32_t>(Size));
cvs_MD5Final(CheckSum.hash, MD5Context);
return CheckSum;
}
static char C2A[17] = "0123456789ABCDEF";
std::string CSTLHelper::Hash2String(const tdHash& rHash)
{
std::string Ret;
for (size_t a = 0, Size = std::min<size_t>(sizeof(rHash.hash), 16u); a < Size; a++)
{
const uint8_t C1 = rHash[a] & 0xf;
const uint8_t C2 = rHash[a] >> 4;
Ret += C2A[C1];
Ret += C2A[C2];
}
return Ret;
}
tdHash CSTLHelper::String2Hash(const std::string& rStr)
{
assert(rStr.size() == 32);
tdHash Ret;
for (size_t a = 0, Size = std::min<size_t>(rStr.size(), 32u); a < Size; a += 2)
{
const uint8_t C1 = rStr.c_str()[a];
const uint8_t C2 = rStr.c_str()[a + 1];
Ret[a >> 1] = C1 - (C1 >= '0' && C1 <= '9' ? '0' : 'A' - 10);
Ret[a >> 1] |= (C2 - (C2 >= '0' && C2 <= '9' ? '0' : 'A' - 10)) << 4;
}
return Ret;
}
//////////////////////////////////////////////////////////////////////////
bool CSTLHelper::Compress(const std::vector<uint8_t>& rIn, std::vector<uint8_t>& rOut)
{
unsigned long destLen, sourceLen = (unsigned long)rIn.size();
destLen = compressBound(sourceLen) + 16;
rOut.resize(destLen + 4);
compress(&rOut[4], &destLen, &rIn[0], sourceLen);
rOut.resize(destLen + 4);
*(uint32_t*)(&rOut[0]) = sourceLen;
return true;
}
bool CSTLHelper::Uncompress(const std::vector<uint8_t>& rIn, std::vector<uint8_t>& rOut)
{
unsigned long sourceLen = (unsigned long)rIn.size() - 4;
unsigned long nUncompressed = *(uint32_t*)(&rIn[0]);
unsigned long nUncompressedBytes = nUncompressed;
rOut.resize(nUncompressed);
int nRes = uncompress(&rOut[0], &nUncompressedBytes, &rIn[4], sourceLen);
return nRes == Z_OK && nUncompressed == nUncompressedBytes;
}
@@ -1,112 +0,0 @@
/*
* 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.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef __STLHELPER__
#define __STLHELPER__
#include <vector>
#include <string>
typedef std::vector<std::string> tdEntryVec;
typedef std::pair<std::string, std::string> tdToken;
typedef std::vector<tdToken> tdTokenList;
typedef std::vector<uint8_t> tdDataVector;
//typedef std::vector<uint8_t> tdHash;
struct tdHash
{
uint8_t hash[16];
inline bool operator<(const tdHash& other) const { return memcmp(hash, other.hash, sizeof(hash)) < 0; }
inline bool operator>(const tdHash& other) const { return memcmp(hash, other.hash, sizeof(hash)) > 0; }
inline bool operator==(const tdHash& other) const { return memcmp(hash, other.hash, sizeof(hash)) == 0; }
inline uint8_t& operator[](size_t nIndex) { return hash[nIndex]; }
inline const uint8_t& operator[](size_t nIndex) const { return hash[nIndex]; }
};
class CSTLHelper
{
static tdHash Hash(const uint8_t* pData, const size_t Size);
public:
static void Tokenize(tdEntryVec& rRet, const std::string& Tokens, const std::string& Separator);
static tdToken SplitToken(const std::string& rToken, const std::string& rSeparator);
static void Splitizer(tdTokenList& rTokenList, const tdEntryVec& rFilter, const std::string& rSeparator);
static void Trim(std::string& rStr, const std::string& charsToTrim);
static void Remove(std::string& rTokenDst, const std::string& rTokenSrc, const char C);
static void Replace(std::vector<uint8_t>& rRet, const std::vector<uint8_t>& rTokenSrc, const std::string& rToReplace, const std::string& rReplacement);
static void Replace(std::string& rRet, const std::string& rSrc, const std::string& rToReplace, const std::string& rReplacement);
static bool ToFile(const std::string& rFileName, const std::vector<uint8_t>& rOut);
static bool FromFile(const std::string& rFileName, std::vector<uint8_t>& rIn);
static bool AppendToFile(const std::string& rFileName, const std::vector<uint8_t>& rOut);
static bool ToFileCompressed(const std::string& rFileName, const std::vector<uint8_t>& rOut);
static bool FromFileCompressed(const std::string& rFileName, std::vector<uint8_t>& rIn);
static bool Compress(const std::vector<uint8_t>& rIn, std::vector<uint8_t>& rOut);
static bool Uncompress(const std::vector<uint8_t>& rIn, std::vector<uint8_t>& rOut);
static void EndianSwizzleU64(uint64_t& S)
{
uint8_t* pT = reinterpret_cast<uint8_t*>(&S);
uint8_t T;
T = pT[0];
pT[0] = pT[7];
pT[7] = T;
T = pT[1];
pT[1] = pT[6];
pT[6] = T;
T = pT[2];
pT[2] = pT[5];
pT[5] = T;
T = pT[3];
pT[3] = pT[4];
pT[4] = T;
}
static void EndianSwizzleU32(uint32_t& S)
{
uint8_t* pT = reinterpret_cast<uint8_t*>(&S);
uint8_t T;
T = pT[0];
pT[0] = pT[3];
pT[3] = T;
T = pT[1];
pT[1] = pT[2];
pT[2] = T;
}
static void EndianSwizzleU16(uint16_t& S)
{
uint8_t* pT = reinterpret_cast<uint8_t*>(&S);
uint8_t T;
T = pT[0];
pT[0] = pT[1];
pT[1] = T;
}
static void Log(const std::string& rLog);
static tdHash Hash(const std::string& rStr) { return Hash(reinterpret_cast<const uint8_t*>(rStr.c_str()), rStr.size()); }
static tdHash Hash(const std::vector<uint8_t>& rData) { return Hash(&rData[0], rData.size()); }
static tdHash Hash(const std::vector<uint8_t>& rData, size_t Size) { return Hash(&rData[0], Size); }
static std::string Hash2String(const tdHash& rHash);
static tdHash String2Hash(const std::string& rStr);
};
#define CRYSIMPLE_LOG(X) CSTLHelper::Log(X)
#endif
@@ -1,311 +0,0 @@
/*
* 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.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "CrySimpleCache.hpp"
#include "CrySimpleServer.hpp"
#include <Core/StdTypes.hpp>
#include <Core/Error.hpp>
#include <Core/STLHelper.hpp>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/std/time.h>
#include <AzCore/std/algorithm.h>
enum EFileEntryHeaderFlags
{
EFEHF_NONE = (0 << 0),
EFEHF_REFERENCE = (1 << 0),
};
#pragma pack(push, 1)
struct SFileEntryHeader
{
char signature[4]; // entry signature.
uint32_t dataSize; // Size of entry data.
uint32_t flags; // Flags
uint8_t hash[16]; // Hash code for the data.
};
#pragma pack(pop)
static const int MAX_DATA_SIZE = 1024 * 1024;
CCrySimpleCache& CCrySimpleCache::Instance()
{
static CCrySimpleCache g_Cache;
return g_Cache;
}
void CCrySimpleCache::Init()
{
CCrySimpleMutexAutoLock Lock(m_Mutex);
m_CachingEnabled = false;
m_Hit = 0;
m_Miss = 0;
}
std::string CCrySimpleCache::CreateFileName(const tdHash& rHash) const
{
AZStd::string Name;
Name = CSTLHelper::Hash2String(rHash).c_str();
char Tmp[4] = "012";
Tmp[0] = Name.c_str()[0];
Tmp[1] = Name.c_str()[1];
Tmp[2] = Name.c_str()[2];
AZ::IO::Path resultFileName = SEnviropment::Instance().m_CachePath / Tmp / Name;
return std::string{ resultFileName.c_str(), resultFileName.Native().size() };
}
bool CCrySimpleCache::Find(const tdHash& rHash, tdDataVector& rData)
{
if (!m_CachingEnabled)
{
return false;
}
CCrySimpleMutexAutoLock Lock(m_Mutex);
tdEntries::iterator it = m_Entries.find(rHash);
if (it != m_Entries.end())
{
tdData::iterator dataIt = m_Data.find(it->second);
if (dataIt == m_Data.end())
{
m_Miss++;
return false;
}
m_Hit++;
rData = dataIt->second;
return true;
}
m_Miss++;
return false;
}
void CCrySimpleCache::Add(const tdHash& rHash, const tdDataVector& rData)
{
if (!m_CachingEnabled)
{
return;
}
if (rData.size() > 0)
{
SFileEntryHeader hdr;
memcpy(hdr.signature, "SHDR", 4);
hdr.dataSize = (uint32_t)rData.size();
hdr.flags = EFEHF_NONE;
memcpy(hdr.hash, &rHash, sizeof(hdr.hash));
const uint8_t* pData = &rData[0];
tdHash DataHash = CSTLHelper::Hash(rData);
{
CCrySimpleMutexAutoLock Lock(m_Mutex);
m_Entries[rHash] = DataHash;
if (m_Data.find(DataHash) == m_Data.end())
{
m_Data[DataHash] = rData;
}
else
{
hdr.flags |= EFEHF_REFERENCE;
hdr.dataSize = sizeof(tdHash);
pData = reinterpret_cast<const uint8_t*>(&DataHash);
}
}
tdDataVector buf;
buf.resize(sizeof(hdr) + hdr.dataSize);
memcpy(&buf[0], &hdr, sizeof(hdr));
memcpy(&buf[sizeof(hdr)], pData, hdr.dataSize);
tdDataVector* pPendingCacheEntry = new tdDataVector(buf);
{
CCrySimpleMutexAutoLock LockFile(m_FileMutex);
m_PendingCacheEntries.push_back(pPendingCacheEntry);
if (m_PendingCacheEntries.size() > 10000)
{
printf("Warning: Too many pending entries not saved to disk!!!");
}
}
}
}
//////////////////////////////////////////////////////////////////////////
bool CCrySimpleCache::LoadCacheFile(const std::string& filename)
{
AZ::u64 startTimeInMillis = AZStd::GetTimeUTCMilliSecond();
printf("Loading shader cache from %s\n", filename.c_str());
tdDataVector rData;
tdHash hash;
bool bLoadedOK = true;
uint32_t Loaded = 0;
uint32_t num = 0;
uint64_t nFilePos = 0;
//////////////////////////////////////////////////////////////////////////
AZ::IO::SystemFile cacheFile;
const bool wasSuccessful = cacheFile.Open(filename.c_str(), AZ::IO::SystemFile::SF_OPEN_READ_ONLY);
if (!wasSuccessful)
{
return false;
}
AZ::IO::SystemFile::SizeType fileSize = cacheFile.Length();
uint64_t SizeAdded = 0;
uint64_t SizeAddedCount = 0;
uint64_t SizeSaved = 0;
uint64_t SizeSavedCount = 0;
while (nFilePos < fileSize)
{
SFileEntryHeader hdr;
AZ::IO::SystemFile::SizeType bytesReadIn = cacheFile.Read(sizeof(hdr), &hdr);
if (bytesReadIn != sizeof(hdr))
{
break;
}
if (memcmp(hdr.signature, "SHDR", 4) != 0)
{
// Bad Entry!
bLoadedOK = false;
printf("\nSkipping Invalid cache entry %d\n at file position: %llu because signature is bad", num, nFilePos);
break;
}
if (hdr.dataSize > MAX_DATA_SIZE || hdr.dataSize == 0)
{
// Too big entry, probably invalid.
bLoadedOK = false;
printf("\nSkipping Invalid cache entry %d\n at file position: %llu because data size is too big", num, nFilePos);
break;
}
rData.resize(hdr.dataSize);
bytesReadIn = cacheFile.Read(hdr.dataSize, rData.data());
if (bytesReadIn != hdr.dataSize)
{
break;
}
memcpy(&hash, hdr.hash, sizeof(hdr.hash));
if (hdr.flags & EFEHF_REFERENCE)
{
if (hdr.dataSize != sizeof(tdHash))
{
// Too big entry, probably invalid.
bLoadedOK = false;
printf("\nSkipping Invalid cache entry %d\n at file position: %llu, was flagged as cache reference but size was %d", num, nFilePos, hdr.dataSize);
break;
}
bool bSkip = false;
tdHash DataHash = *reinterpret_cast<tdHash*>(&rData[0]);
tdData::iterator it = m_Data.find(DataHash);
if (it == m_Data.end())
{
// Too big entry, probably invalid.
bSkip = true; // don't abort reading whole file just yet - skip only this entry
printf("\nSkipping Invalid cache entry %d\n at file position: %llu, data-hash references to not existing data ", num, nFilePos);
}
if (!bSkip)
{
m_Entries[hash] = DataHash;
SizeSaved += it->second.size();
SizeSavedCount++;
}
}
else
{
tdHash DataHash = CSTLHelper::Hash(rData);
m_Entries[hash] = DataHash;
if (m_Data.find(DataHash) == m_Data.end())
{
SizeAdded += rData.size();
m_Data[DataHash] = rData;
SizeAddedCount++;
}
else
{
SizeSaved += rData.size();
SizeSavedCount++;
}
}
if (num % 1000 == 0)
{
AZ::u64 endTimeInMillis = AZStd::GetTimeUTCMilliSecond();
Loaded = static_cast<uint32_t>(nFilePos * 100 / fileSize);
printf("\rLoad:%3u%% %6uk t=%llus Compress: (Count)%llu%% %lluk:%lluk (MB)%llu%% %lluMB:%lluMB", Loaded, num / 1000u, (endTimeInMillis - startTimeInMillis),
SizeAddedCount / AZStd::GetMax((SizeAddedCount + SizeSavedCount) / 100ull, 1ull),
SizeAddedCount / 1000, SizeSavedCount / 1000,
SizeAdded / AZStd::GetMax((SizeAdded + SizeSaved) / 100ull, 1ull),
SizeAdded / (MAX_DATA_SIZE), SizeSaved / (MAX_DATA_SIZE));
}
num++;
nFilePos += hdr.dataSize + sizeof(SFileEntryHeader);
}
printf("\n%d shaders loaded from cache\n", num);
return bLoadedOK;
}
void CCrySimpleCache::Finalize()
{
m_CachingEnabled = true;
printf("\n caching enabled\n");
}
//////////////////////////////////////////////////////////////////////////
void CCrySimpleCache::ThreadFunc_SavePendingCacheEntries()
{
// Check pending entries and save them to disk.
bool bListEmpty = false;
do
{
tdDataVector* pPendingCacheEntry = 0;
{
CCrySimpleMutexAutoLock LockFile(m_FileMutex);
if (!m_PendingCacheEntries.empty())
{
pPendingCacheEntry = m_PendingCacheEntries.front();
m_PendingCacheEntries.pop_front();
}
//CSTLHelper::AppendToFile( SEnviropment::Instance().m_CachePath+"Cache.dat",buf );
bListEmpty = m_PendingCacheEntries.empty();
}
if (pPendingCacheEntry)
{
AZ::IO::Path cacheDatPath = SEnviropment::Instance().m_CachePath / "Cache.dat";
CSTLHelper::AppendToFile(std::string{ cacheDatPath.c_str(), cacheDatPath.Native().size() }, *pPendingCacheEntry);
delete pPendingCacheEntry;
}
} while (!bListEmpty);
}
@@ -1,68 +0,0 @@
/*
* 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.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef __CRYSIMPLECACHE__
#define __CRYSIMPLECACHE__
#include "CrySimpleMutex.hpp"
#include <Core/STLHelper.hpp>
#include <map>
#include <vector>
#include <list>
/*class CCrySimpleCacheEntry
{
tdCache
public:
protected:
private:
};*/
typedef std::map<tdHash, tdHash> tdEntries;
typedef std::map<tdHash, tdDataVector> tdData;
class CCrySimpleCache
{
volatile bool m_CachingEnabled;
int m_Hit;
int m_Miss;
tdEntries m_Entries;
tdData m_Data;
CCrySimpleMutex m_Mutex;
CCrySimpleMutex m_FileMutex;
std::list<tdDataVector*> m_PendingCacheEntries;
std::string CreateFileName(const tdHash& rHash) const;
public:
void Init();
bool Find(const tdHash& rHash, tdDataVector& rData);
void Add(const tdHash& rHash, const tdDataVector& rData);
bool LoadCacheFile(const std::string& filename);
void Finalize();
void ThreadFunc_SavePendingCacheEntries();
static CCrySimpleCache& Instance();
std::list<tdDataVector*>& PendingCacheEntries(){return m_PendingCacheEntries; }
int Hit() const{return m_Hit; }
int Miss() const{return m_Miss; }
int EntryCount() const{return static_cast<int>(m_Entries.size()); }
};
#endif
@@ -1,274 +0,0 @@
/*
* 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.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "CrySimpleErrorLog.hpp"
#include "CrySimpleServer.hpp"
#include "CrySimpleJob.hpp"
#include <Core/Common.h>
#include <Core/StdTypes.hpp>
#include <Core/Error.hpp>
#include <Core/STLHelper.hpp>
#include <Core/Mailer.h>
#include <tinyxml/tinyxml.h>
#include <AzCore/std/time.h>
#include <AzCore/IO/SystemFile.h>
#include <string>
#include <map>
#include <algorithm>
#ifdef _MSC_VER
#include <process.h>
#include <direct.h>
#endif
#ifdef UNIX
#include <pthread.h>
#endif
static unsigned int volatile g_bSendingMail = false;
static unsigned int volatile g_nMailNum = 0;
CCrySimpleErrorLog& CCrySimpleErrorLog::Instance()
{
static CCrySimpleErrorLog g_Cache;
return g_Cache;
}
CCrySimpleErrorLog::CCrySimpleErrorLog()
{
m_lastErrorTime = 0;
}
void CCrySimpleErrorLog::Init()
{
}
bool CCrySimpleErrorLog::Add(ICryError* err)
{
CCrySimpleMutexAutoLock Lock(m_LogMutex);
if (m_Log.size() > 150)
{
// too many, just throw this error away
return false; // no ownership of this error
}
m_Log.push_back(err);
m_lastErrorTime = AZStd::GetTimeUTCMilliSecond();
return true; // take ownership of this error
}
inline bool CmpError(ICryError* a, ICryError* b)
{
return a->Compare(b);
}
void CCrySimpleErrorLog::SendMail()
{
CSMTPMailer::tstrcol Rcpt;
std::string mailBody;
tdEntryVec RcptVec;
CSTLHelper::Tokenize(RcptVec, SEnviropment::Instance().m_FailEMail, ";");
for (size_t i = 0; i < RcptVec.size(); i++)
{
Rcpt.insert(RcptVec[i]);
}
tdErrorList tempLog;
{
CCrySimpleMutexAutoLock Lock(m_LogMutex);
m_Log.swap(tempLog);
}
#if defined(_MSC_VER)
{
char compName[256];
DWORD size = ARRAYSIZE(compName);
typedef BOOL (WINAPI * FP_GetComputerNameExA)(COMPUTER_NAME_FORMAT, LPSTR, LPDWORD);
FP_GetComputerNameExA pGetComputerNameExA = (FP_GetComputerNameExA) GetProcAddress(LoadLibrary("kernel32.dll"), "GetComputerNameExA");
if (pGetComputerNameExA)
{
pGetComputerNameExA(ComputerNamePhysicalDnsFullyQualified, compName, &size);
}
else
{
GetComputerName(compName, &size);
}
mailBody += std::string("Report sent from ") + compName + "...\n\n";
}
#endif
{
bool dedupe = SEnviropment::Instance().m_DedupeErrors;
std::vector<ICryError*> errors;
if (!dedupe)
{
for (tdErrorList::const_iterator it = tempLog.begin(); it != tempLog.end(); ++it)
{
errors.push_back(*it);
}
}
else
{
std::map<tdHash, ICryError*> uniqErrors;
for (tdErrorList::const_iterator it = tempLog.begin(); it != tempLog.end(); ++it)
{
ICryError* err = *it;
tdHash hash = err->Hash();
std::map<tdHash, ICryError*>::iterator uniq = uniqErrors.find(hash);
if (uniq != uniqErrors.end())
{
uniq->second->AddDuplicate(err);
delete err;
}
else
{
uniqErrors[hash] = err;
}
}
for (std::map<tdHash, ICryError*>::iterator it = uniqErrors.begin(); it != uniqErrors.end(); ++it)
{
errors.push_back(it->second);
}
}
std::string body = mailBody;
CSMTPMailer::tstrcol cc;
CSMTPMailer::tattachlist Attachment;
std::sort(errors.begin(), errors.end(), CmpError);
int a = 0;
for (uint32_t i = 0; i < errors.size(); i++)
{
ICryError* err = errors[i];
err->SetUniqueID(a + 1);
// doesn't have to be related to any job/error,
// we just use it to differentiate "1-IlluminationPS.txt" from "1-IlluminationPS.txt"
long req = CCrySimpleJob::GlobalRequestNumber();
if (err->HasFile())
{
char Filename[1024];
azsprintf(Filename, "%d-req%ld-%s", a + 1, req, err->GetFilename().c_str());
char DispFilename[1024];
azsprintf(DispFilename, "%d-%s", a + 1, err->GetFilename().c_str());
std::string sErrorFile = (SEnviropment::Instance().m_ErrorPath / Filename).c_str();
std::vector<uint8_t> bytes;
std::string text = err->GetFileContents();
bytes.resize(text.size() + 1);
std::copy(text.begin(), text.end(), bytes.begin());
while (bytes.size() && bytes[bytes.size() - 1] == 0)
{
bytes.pop_back();
}
CrySimple_SECURE_START
CSTLHelper::ToFile(sErrorFile, bytes);
Attachment.push_back(CSMTPMailer::tattachment(DispFilename, sErrorFile));
CrySimple_SECURE_END
}
body += std::string("=============================================================\n");
body += err->GetErrorDetails(ICryError::OUTPUT_EMAIL) + "\n";
err->AddCCs(cc);
a++;
if (i == errors.size() - 1 || !err->CanMerge(errors[i + 1]))
{
CSMTPMailer::tstrcol bcc;
CSMTPMailer mail("", "", SEnviropment::Instance().m_MailServer);
mail.Send(SEnviropment::Instance().m_FailEMail, Rcpt, cc, bcc, err->GetErrorName(), body, Attachment);
a = 0;
body = mailBody;
cc.clear();
for (CSMTPMailer::tattachlist::iterator attach = Attachment.begin(); attach != Attachment.end(); ++attach)
{
AZ::IO::SystemFile::Delete(attach->second.c_str());
}
Attachment.clear();
}
delete err;
}
}
g_bSendingMail = false;
}
//////////////////////////////////////////////////////////////////////////
void CCrySimpleErrorLog::Tick()
{
if (SEnviropment::Instance().m_MailInterval == 0)
{
return;
}
AZ::u64 lastError = 0;
bool forceFlush = false;
{
CCrySimpleMutexAutoLock Lock(m_LogMutex);
if (m_Log.size() == 0)
{
return;
}
// log has gotten pretty big, force a flush to avoid losing any errors
if (m_Log.size() > 100)
{
forceFlush = true;
}
lastError = m_lastErrorTime;
}
AZ::u64 t = AZStd::GetTimeUTCMilliSecond();
if (forceFlush || t < lastError || (t - lastError) > SEnviropment::Instance().m_MailInterval * 1000)
{
if (!g_bSendingMail)
{
g_bSendingMail = true;
g_nMailNum++;
logmessage("Sending Errors Mail %d\n", g_nMailNum);
CCrySimpleErrorLog::Instance().SendMail();
}
}
}
@@ -1,42 +0,0 @@
/*
* 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.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef __CRYSIMPLEERRORLOG__
#define __CRYSIMPLEERRORLOG__
#include "CrySimpleMutex.hpp"
#include <vector>
#include <list>
class ICryError;
typedef std::list<ICryError*> tdErrorList;
class CCrySimpleErrorLog
{
CCrySimpleMutex m_LogMutex; // protects both below variables
tdErrorList m_Log; // error log
AZ::u64 m_lastErrorTime; // last time an error came in (we mail out a little after we've stopped receiving errors)
void Init();
void SendMail();
CCrySimpleErrorLog();
public:
bool Add(ICryError* err);
void Tick();
static CCrySimpleErrorLog& Instance();
};
#endif
@@ -1,33 +0,0 @@
/*
* 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.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef __CRYSIMPLEFILEGUARD__
#define __CRYSIMPLEFILEGUARD__
#include <Core/Common.h>
#include <string>
class CCrySimpleFileGuard
{
std::string m_FileName;
public:
CCrySimpleFileGuard(const std::string& rFileName)
: m_FileName(rFileName)
{
}
~CCrySimpleFileGuard()
{
remove(m_FileName.c_str());
}
};
#endif
@@ -1,228 +0,0 @@
/*
* 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.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "CrySimpleHTTP.hpp"
#include "CrySimpleSock.hpp"
#include "CrySimpleJobCompile.hpp"
#include "CrySimpleServer.hpp"
#include "CrySimpleCache.hpp"
#include <Core/StdTypes.hpp>
#include <Core/Error.hpp>
#include <Core/STLHelper.hpp>
#include <tinyxml/tinyxml.h>
#include <AzCore/Jobs/Job.h>
#include <AzCore/std/algorithm.h>
#include <AzCore/std/string/string.h>
#include <assert.h>
#include <memory>
//////////////////////////////////////////////////////////////////////////
class CHTTPRequest
{
CCrySimpleSock* m_pSock;
public:
CHTTPRequest(CCrySimpleSock* pSock)
: m_pSock(pSock){}
~CHTTPRequest(){delete m_pSock; }
CCrySimpleSock* Socket(){return m_pSock; }
};
#define HTML_HEADER "HTTP/1.1 200 OK\n\
Server: Shader compile server %s\n\
Content-Length: %zu\n\
Content-Language: de (nach RFC 3282 sowie RFC 1766)\n\
Content-Type: text/html\n\
Connection: close\n\
\n\
<html><title>shader compile server %s</title><body>"
#define TABLE_START "<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=2 WIDTH=640>\n\
<TR bgcolor=lightgrey><TH align=left>Description</TH><TH WIDTH=5></TH><TH>Value</TH><TH>Max</TH>\n\
<TH WIDTH=10>&nbsp;</TH><TH align=center>%</TH></TR>\n"
#define TABLE_INFO "<TR><TD>%s</TD><TD>&nbsp;</TD><TD align=left>%s</TD><TD align=center></TD><TD>&nbsp;</TD><TD valign=middle>\n\
</TD></TR>\n\
</TD></TR>\n"
#define TABLE_BAR "<TR><TD>%s</TD><TD>&nbsp;</TD><TD align=center>%d</TD><TD align=center>%d</TD><TD>&nbsp;</TD><TD valign=middle>\n\
<TABLE><TR><TD bgcolor=darkred style=\"width: %d;\" ></TD>\n\
<TD><FONT SIZE=1>%d%%</FONT></TD></TR>\n\
</TABLE></TD></TR>\n\
</TD></TR>\n"
#define TABLE_END "</TABLE>"
std::string CreateBar(const std::string& rName, int Value, int Max, int Percentage)
{
AZStd::string formattedString = AZStd::string::format(TABLE_BAR, rName.c_str(), Value, Max, Percentage, Percentage);
return formattedString.c_str();
}
std::string CreateInfoText(const std::string& rName, const std::string& rValue)
{
AZStd::string formattedString = AZStd::string::format(TABLE_INFO, rName.c_str(), rValue.c_str());
return formattedString.c_str();
}
std::string CreateInfoText(const std::string& rName, int Value)
{
char Text[64];
azsprintf(Text, "%d", Value);
return CreateInfoText(rName, Text);
}
class HttpProcessRequestJob
: public AZ::Job
{
public:
HttpProcessRequestJob(CHTTPRequest* request)
: AZ::Job(true, nullptr)
, m_request(request) { }
protected:
void Process() override
{
#if defined(AZ_PLATFORM_WINDOWS)
FILETIME IdleTime0, IdleTime1;
FILETIME KernelTime0, KernelTime1;
FILETIME UserTime0, UserTime1;
int Ret0 = GetSystemTimes(&IdleTime0, &KernelTime0, &UserTime0);
Sleep(100);
int Ret1 = GetSystemTimes(&IdleTime1, &KernelTime1, &UserTime1);
const int Idle = IdleTime1.dwLowDateTime - IdleTime0.dwLowDateTime;
const int Kernel = KernelTime1.dwLowDateTime - KernelTime0.dwLowDateTime;
const int User = UserTime1.dwLowDateTime - UserTime0.dwLowDateTime;
//const int Idle = IdleTime1.dwHighDateTime-IdleTime0.dwHighDateTime;
//const int Kernel = KernelTime1.dwHighDateTime-KernelTime0.dwHighDateTime;
//const int User = UserTime1.dwHighDateTime-UserTime0.dwHighDateTime;
const int Total = Kernel + User;
#else
int Ret0 = 0;
int Ret1 = 0;
int Total = 0;
int Idle = 0;
#endif
std::string Ret = TABLE_START;
Ret += CreateInfoText("<b>Load</b>:", "");
if (Ret0 && Ret1 && Total)
{
Ret += CreateBar("CPU-Usage", Total - Idle, Total, 100 - Idle * 100 / Total);
}
Ret += CreateBar("CompileTasks", CCrySimpleJobCompile::GlobalCompileTasks(),
CCrySimpleJobCompile::GlobalCompileTasksMax(),
CCrySimpleJobCompile::GlobalCompileTasksMax() ?
CCrySimpleJobCompile::GlobalCompileTasks() * 100 /
CCrySimpleJobCompile::GlobalCompileTasksMax() : 0);
Ret += CreateInfoText("<b>Setup</b>:", "");
Ret += CreateInfoText("Root", SEnviropment::Instance().m_Root.c_str());
Ret += CreateInfoText("CompilerPath", SEnviropment::Instance().m_CompilerPath.c_str());
Ret += CreateInfoText("CachePath", SEnviropment::Instance().m_CachePath.c_str());
Ret += CreateInfoText("TempPath", SEnviropment::Instance().m_TempPath.c_str());
Ret += CreateInfoText("ErrorPath", SEnviropment::Instance().m_ErrorPath.c_str());
Ret += CreateInfoText("ShaderPath", SEnviropment::Instance().m_ShaderPath.c_str());
Ret += CreateInfoText("FailEMail", SEnviropment::Instance().m_FailEMail);
Ret += CreateInfoText("MailServer", SEnviropment::Instance().m_MailServer);
Ret += CreateInfoText("port", SEnviropment::Instance().m_port);
Ret += CreateInfoText("MailInterval", SEnviropment::Instance().m_MailInterval);
Ret += CreateInfoText("Caching", SEnviropment::Instance().m_Caching ? "Enabled" : "Disabled");
Ret += CreateInfoText("FallbackServer", SEnviropment::Instance().m_FallbackServer == "" ? "None" : SEnviropment::Instance().m_FallbackServer);
Ret += CreateInfoText("FallbackTreshold", static_cast<int>(SEnviropment::Instance().m_FallbackTreshold));
Ret += CreateInfoText("DumpShaders", static_cast<int>(SEnviropment::Instance().m_DumpShaders));
Ret += CreateInfoText("<b>Cache</b>:", "");
Ret += CreateInfoText("Entries", CCrySimpleCache::Instance().EntryCount());
Ret += CreateBar("Hits", CCrySimpleCache::Instance().Hit(),
CCrySimpleCache::Instance().Hit() + CCrySimpleCache::Instance().Miss(),
CCrySimpleCache::Instance().Hit() * 100 / AZStd::GetMax(1, (CCrySimpleCache::Instance().Hit() + CCrySimpleCache::Instance().Miss())));
Ret += CreateInfoText("Pending Entries", static_cast<int>(CCrySimpleCache::Instance().PendingCacheEntries().size()));
Ret += TABLE_END;
Ret += "</Body></hmtl>";
char Text[sizeof(HTML_HEADER) + 1024];
azsprintf(Text, HTML_HEADER, __DATE__, Ret.size(), __DATE__);
Ret = std::string(Text) + Ret;
m_request->Socket()->Send(Ret);
}
private:
std::unique_ptr<CHTTPRequest> m_request;
};
class HttpServerJob
: public AZ::Job
{
public:
HttpServerJob(CCrySimpleHTTP* simpleHttp)
: AZ::Job(true, nullptr)
, m_simpleHttp(simpleHttp) { }
protected:
void Process()
{
m_simpleHttp->Run();
}
private:
CCrySimpleHTTP* m_simpleHttp;
};
//////////////////////////////////////////////////////////////////////////
CCrySimpleHTTP::CCrySimpleHTTP()
: m_pServerSocket(0)
{
CrySimple_SECURE_START
Init();
CrySimple_SECURE_END
}
void CCrySimpleHTTP::Init()
{
m_pServerSocket = new CCrySimpleSock(61480, SEnviropment::Instance().m_WhitelistAddresses); //http
m_pServerSocket->Listen();
HttpServerJob* serverJob = new HttpServerJob(this);
serverJob->Start();
}
void CCrySimpleHTTP::Run()
{
while (1)
{
// New client message, receive new client socket connection.
CCrySimpleSock* newClientSocket = m_pServerSocket->Accept();
if(!newClientSocket)
{
continue;
}
// HTTP Request Data for new job
CHTTPRequest* pData = new CHTTPRequest(newClientSocket);
HttpProcessRequestJob* requestJob = new HttpProcessRequestJob(pData);
requestJob->Start();
}
}
@@ -1,36 +0,0 @@
/*
* 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.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef __CrySimpleHTTP__
#define __CrySimpleHTTP__
#include <AzCore/std/parallel/atomic.h>
#include <Core/Common.h>
#include <string>
extern bool g_Success;
class CCrySimpleSock;
class CCrySimpleHTTP
{
static AZStd::atomic_long ms_ExceptionCount;
CCrySimpleSock* m_pServerSocket;
void Init();
public:
CCrySimpleHTTP();
void Run();
};
#endif
@@ -1,211 +0,0 @@
/*
* 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.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "CrySimpleJob.hpp"
#include "CrySimpleFileGuard.hpp"
#include "CrySimpleServer.hpp"
#include <Core/StdTypes.hpp>
#include <Core/Error.hpp>
#include <Core/STLHelper.hpp>
#include <Core/Common.h>
#include <Core/WindowsAPIImplementation.h>
#include <tinyxml/tinyxml.h>
#include <thread>
#include <sstream>
#include <fstream>
AZStd::atomic_long CCrySimpleJob::m_GlobalRequestNumber = {0};
CCrySimpleJob::CCrySimpleJob(uint32_t requestIP)
: m_State(ECSJS_NONE)
, m_RequestIP(requestIP)
{
++m_GlobalRequestNumber;
}
CCrySimpleJob::~CCrySimpleJob()
{
}
bool CCrySimpleJob::ExecuteCommand(const std::string& rCmd, std::string& outError)
{
const bool showStdOuput = false; // For Debug: Set to true if you want the compiler's standard ouput printed out as well.
const bool showStdErrorOuput = SEnviropment::Instance().m_PrintWarnings;
#ifdef _MSC_VER
bool Ret = false;
DWORD ExitCode = 0;
STARTUPINFO StartupInfo;
PROCESS_INFORMATION ProcessInfo;
memset(&StartupInfo, 0, sizeof(StartupInfo));
memset(&ProcessInfo, 0, sizeof(ProcessInfo));
StartupInfo.cb = sizeof(StartupInfo);
std::string Path = "";
std::string::size_type Pt = rCmd.find_first_of(' ');
if (Pt != std::string::npos)
{
std::string First = std::string(rCmd.c_str(), Pt);
std::string::size_type Pt2 = First.find_last_of('/');
if (Pt2 != std::string::npos)
{
Path = std::string(First.c_str(), Pt2);
}
else
{
Pt = std::string::npos;
}
}
HANDLE hReadErr, hWriteErr;
{
CreatePipe(&hReadErr, &hWriteErr, NULL, 0);
SetHandleInformation(hWriteErr, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
StartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
StartupInfo.hStdOutput = (showStdOuput) ? GetStdHandle(STD_OUTPUT_HANDLE) : NULL;
StartupInfo.hStdError = hWriteErr;
StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
BOOL processCreated = CreateProcess(NULL, (char*)rCmd.c_str(), 0, 0, TRUE, CREATE_DEFAULT_ERROR_MODE, 0, Pt != std::string::npos ? Path.c_str() : 0, &StartupInfo, &ProcessInfo) != false;
if (!processCreated)
{
outError = "Couldn't create process - missing compiler for cmd?: '" + rCmd + "'";
}
else
{
std::string error;
DWORD waitResult = 0;
HANDLE waitHandles[] = { ProcessInfo.hProcess, hReadErr };
while (true)
{
//waitResult = WaitForMultipleObjects(sizeof(waitHandles) / sizeof(waitHandles[0]), waitHandles, FALSE, 1000 );
waitResult = WaitForSingleObject(ProcessInfo.hProcess, 1000);
if (waitResult == WAIT_FAILED)
{
break;
}
DWORD bytesRead, bytesAvailable;
while (PeekNamedPipe(hReadErr, NULL, 0, NULL, &bytesAvailable, NULL) && bytesAvailable)
{
char buff[4096];
ReadFile(hReadErr, buff, sizeof(buff) - 1, &bytesRead, 0);
buff[bytesRead] = '\0';
error += buff;
}
CSTLHelper::Trim(error," \t\r\n");
//if (waitResult == WAIT_OBJECT_0 || waitResult == WAIT_TIMEOUT)
//break;
if (waitResult == WAIT_OBJECT_0)
{
break;
}
}
//if (waitResult != WAIT_TIMEOUT)
{
GetExitCodeProcess(ProcessInfo.hProcess, &ExitCode);
if (ExitCode)
{
Ret = false;
outError = error;
}
else
{
if (showStdErrorOuput && !error.empty())
{
AZ_Printf(0, "\n%s\n", error.c_str());
}
Ret = true;
}
}
/*
else
{
Ret = false;
outError = std::string("Timed out executing compiler: ") + rCmd;
TerminateProcess(ProcessInfo.hProcess, 1);
}
*/
CloseHandle(ProcessInfo.hProcess);
CloseHandle(ProcessInfo.hThread);
}
CloseHandle(hReadErr);
if (hWriteErr)
{
CloseHandle(hWriteErr);
}
}
return Ret;
#endif
#if defined(AZ_PLATFORM_LINUX) || defined(AZ_PLATFORM_MAC)
std::thread::id threadId = std::this_thread::get_id();
std::stringstream threadIdStream;
threadIdStream << threadId;
// Multiple threads could execute a command, therefore the temporary file has to be unique per thread.
AZ::IO::Path errorTempFilePath = SEnviropment::Instance().m_TempPath / AZStd::string::format("stderr_%s.log", threadIdStream.str().c_str());
std::string stdErrorTempFilename{ errorTempFilePath.c_str(), errorTempFilePath.Native().size() };
CCrySimpleFileGuard FGTmpOutput(stdErrorTempFilename); // Delete file at the end of this function
std::string systemCmd = rCmd;
if(!showStdOuput)
{
// Standard output redirected to null to disable it
systemCmd += " > /dev/null";
}
// Standard error ouput redirected to the temporary file
systemCmd += " 2> \"" + stdErrorTempFilename + "\"";
int ret = system(systemCmd.c_str());
// Obtain standard error output
std::ifstream fileStream(stdErrorTempFilename.c_str());
std::stringstream stdErrorStream;
stdErrorStream << fileStream.rdbuf();
std::string stdErrorString = stdErrorStream.str();
CSTLHelper::Trim(stdErrorString," \t\r\n");
if (ret != 0)
{
outError = stdErrorString;
return false;
}
else
{
if (showStdErrorOuput && !stdErrorString.empty())
{
AZ_Printf(0, "\n%s\n", stdErrorString.c_str());
}
return true;
}
#endif
}
@@ -1,74 +0,0 @@
/*
* 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.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef __CRYSIMPLEJOB__
#define __CRYSIMPLEJOB__
#include <Core/Common.h>
#include <string>
#include <vector>
#include <string>
#include <AzCore/std/parallel/atomic.h>
class TiXmlElement;
enum ECrySimpleJobState
{
ECSJS_NONE,
ECSJS_DONE = 1, //this is checked on client side, don't change!
ECSJS_JOBNOTFOUND,
ECSJS_CACHEHIT,
ECSJS_ERROR,
ECSJS_ERROR_COMPILE = 5, //this is checked on client side, don't change!
ECSJS_ERROR_COMPRESS,
ECSJS_ERROR_FILEIO,
ECSJS_ERROR_INVALID_PROFILE,
ECSJS_ERROR_INVALID_PROJECT,
ECSJS_ERROR_INVALID_PLATFORM,
ECSJS_ERROR_INVALID_PROGRAM,
ECSJS_ERROR_INVALID_ENTRY,
ECSJS_ERROR_INVALID_COMPILEFLAGS,
ECSJS_ERROR_INVALID_COMPILER,
ECSJS_ERROR_INVALID_LANGUAGE,
ECSJS_ERROR_INVALID_SHADERREQUESTLINE,
ECSJS_ERROR_INVALID_SHADERLIST,
};
class CCrySimpleJob
{
ECrySimpleJobState m_State;
uint32_t m_RequestIP;
static AZStd::atomic_long m_GlobalRequestNumber;
protected:
virtual bool ExecuteCommand(const std::string& rCmd, std::string& outError);
public:
CCrySimpleJob(uint32_t requestIP);
virtual ~CCrySimpleJob();
virtual bool Execute(const TiXmlElement* pElement) = 0;
void State(ECrySimpleJobState S)
{
if (m_State < ECSJS_ERROR || S >= ECSJS_ERROR)
{
m_State = S;
}
}
ECrySimpleJobState State() const { return m_State; }
const uint32_t& RequestIP() const { return m_RequestIP; }
static long GlobalRequestNumber() { return m_GlobalRequestNumber; }
};
#endif
@@ -1,36 +0,0 @@
/*
* 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.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "CrySimpleJobCache.hpp"
#include "CrySimpleCache.hpp"
#include <Core/StdTypes.hpp>
#include <Core/Error.hpp>
#include <Core/STLHelper.hpp>
#include <Core/Common.h>
#include <tinyxml/tinyxml.h>
CCrySimpleJobCache::CCrySimpleJobCache(uint32_t requestIP)
: CCrySimpleJob(requestIP)
{
}
void CCrySimpleJobCache::CheckHashID(std::vector<uint8_t>& rVec, size_t Size)
{
m_HashID = CSTLHelper::Hash(rVec, Size);
if (CCrySimpleCache::Instance().Find(m_HashID, rVec))
{
State(ECSJS_CACHEHIT);
logmessage("\r"); // Just update cache hit number
}
}
@@ -1,35 +0,0 @@
/*
* 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.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef __CRYSIMPLEJOBCACHE__
#define __CRYSIMPLEJOBCACHE__
#include "CrySimpleJob.hpp"
#include <Core/STLHelper.hpp>
class CCrySimpleJobCache
: public CCrySimpleJob
{
tdHash m_HashID;
protected:
void CheckHashID(std::vector<uint8_t>& rVec, size_t Size);
public:
CCrySimpleJobCache(uint32_t requestIP);
tdHash HashID() const{return m_HashID; }
};
#endif
@@ -1,969 +0,0 @@
/*
* 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.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#include "CrySimpleSock.hpp"
#include "CrySimpleJobCompile.hpp"
#include "CrySimpleFileGuard.hpp"
#include "CrySimpleServer.hpp"
#include "CrySimpleCache.hpp"
#include "ShaderList.hpp"
#include <Core/Error.hpp>
#include <Core/STLHelper.hpp>
#include <tinyxml/tinyxml.h>
#include <Core/StdTypes.hpp>
#include <Core/WindowsAPIImplementation.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/std/algorithm.h>
#include <AzCore/std/sort.h>
#include <AzCore/std/string/string.h>
#include <AzCore/std/containers/unordered_map.h>
#include <zlib.h>
#include <iostream>
#include <fstream>
#include <sstream>
#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS)
#undef AZ_RESTRICTED_SECTION
#define CRYSIMPLEJOBCOMPILE_CPP_SECTION_1 1
#endif
#define MAX_COMPILER_WAIT_TIME (60 * 1000)
AZStd::atomic_long CCrySimpleJobCompile::m_GlobalCompileTasks = {0};
AZStd::atomic_long CCrySimpleJobCompile::m_GlobalCompileTasksMax = {0};
volatile int32_t CCrySimpleJobCompile::m_RemoteServerID = 0;
volatile int64_t CCrySimpleJobCompile::m_GlobalCompileTime = 0;
struct STimer
{
int64_t m_freq;
STimer()
{
QueryPerformanceFrequency((LARGE_INTEGER*)&m_freq);
}
int64_t GetTime() const
{
int64_t t;
QueryPerformanceCounter((LARGE_INTEGER*)&t);
return t;
}
double TimeToSeconds(int64_t t)
{
return ((double)t) / m_freq;
}
};
STimer g_Timer;
// This function validates executables up to version 21
// because it's received within the compilation flags.
bool ValidateExecutableStringLegacy(const AZStd::string& executableString)
{
AZStd::string::size_type endOfCommand = executableString.find(" ");
// Game always sends some type of options after the command. If we don't
// have a space then that implies that there are no options. Reject the
// command as someone being malicious
if (endOfCommand == AZStd::string::npos)
{
return false;
}
AZStd::string commandString = executableString.substr(0, endOfCommand);
// The game never sends a parent directory in the compiler flags so lets
// reject any commands that have .. in it
if (commandString.find("..") != AZStd::string::npos)
{
return false;
}
// Though the code later down would fail gracefully reject any absolute paths here
if (commandString.find("\\\\") != AZStd::string::npos ||
commandString.find(":") != AZStd::string::npos)
{
return false;
}
// Only allow a subset of executables to be accepted...
if (commandString.find("fxc.exe") == AZStd::string::npos &&
commandString.find("FXC.exe") == AZStd::string::npos &&
commandString.find("HLSLcc.exe") == AZStd::string::npos &&
commandString.find("HLSLcc_dedicated.exe") == AZStd::string::npos &&
commandString.find("DXProvoShaderCompiler.exe") == AZStd::string::npos &&
commandString.find("dxcGL") == AZStd::string::npos &&
commandString.find("dxcMetal") == AZStd::string::npos)
{
return false;
}
return true;
}
CCrySimpleJobCompile::CCrySimpleJobCompile(uint32_t requestIP, EProtocolVersion Version, std::vector<uint8_t>* pRVec)
: CCrySimpleJobCache(requestIP)
, m_Version(Version)
, m_pRVec(pRVec)
{
++m_GlobalCompileTasks;
if (m_GlobalCompileTasksMax < m_GlobalCompileTasks)
{
//Need this cast as the copy assignment operator is implicitly deleted
m_GlobalCompileTasksMax = static_cast<long>(m_GlobalCompileTasks);
}
}
CCrySimpleJobCompile::~CCrySimpleJobCompile()
{
--m_GlobalCompileTasks;
}
bool CCrySimpleJobCompile::Execute(const TiXmlElement* pElement)
{
std::vector<uint8_t>& rVec = *m_pRVec;
size_t Size = SizeOf(rVec);
CheckHashID(rVec, Size);
if (State() == ECSJS_CACHEHIT)
{
State(ECSJS_DONE);
return true;
}
if (!SEnviropment::Instance().m_FallbackServer.empty() && m_GlobalCompileTasks > SEnviropment::Instance().m_FallbackTreshold)
{
tdEntryVec ServerVec;
CSTLHelper::Tokenize(ServerVec, SEnviropment::Instance().m_FallbackServer, ";");
uint32_t Idx = m_RemoteServerID++;
uint32_t Count = (uint32_t)ServerVec.size();
std::string Server = ServerVec[Idx % Count];
printf(" Remote Compile on %s ...\n", Server.c_str());
CCrySimpleSock Sock(Server, SEnviropment::Instance().m_port);
if (Sock.Valid())
{
Sock.Forward(rVec);
std::vector<uint8_t> Tmp;
if (Sock.Backward(Tmp))
{
rVec = Tmp;
if (Tmp.size() <= 4 || (m_Version == EPV_V002 && Tmp[4] != ECSJS_DONE))
{
State(ECSJS_ERROR_COMPILE);
CrySimple_ERROR("failed to compile request");
return false;
}
State(ECSJS_DONE);
//printf("done\n");
}
else
{
printf("failed, fallback to local\n");
}
}
else
{
printf("failed, fallback to local\n");
}
}
if (State() == ECSJS_NONE)
{
if (!Compile(pElement, rVec) || rVec.size() == 0)
{
State(ECSJS_ERROR_COMPILE);
CrySimple_ERROR("failed to compile request");
return false;
}
tdDataVector rDataRaw;
rDataRaw.swap(rVec);
if (!CSTLHelper::Compress(rDataRaw, rVec))
{
State(ECSJS_ERROR_COMPRESS);
CrySimple_ERROR("failed to compress request");
return false;
}
State(ECSJS_DONE);
}
// Cache compiled data
const char* pCaching = pElement->Attribute("Caching");
if (State() != ECSJS_ERROR && (!pCaching || std::string(pCaching) == "1"))
{
CCrySimpleCache::Instance().Add(HashID(), rVec);
}
return true;
}
bool CCrySimpleJobCompile::Compile(const TiXmlElement* pElement, std::vector<uint8_t>& rVec)
{
AZStd::string platform;
AZStd::string compiler;
AZStd::string language;
AZStd::string shaderPath;
if (m_Version >= EPV_V0023)
{
// NOTE: These attributes were alredy validated.
platform = pElement->Attribute("Platform");
compiler = pElement->Attribute("Compiler");
language = pElement->Attribute("Language");
shaderPath = AZStd::string::format("%s%s-%s-%s/", SEnviropment::Instance().m_ShaderPath.c_str(), platform.c_str(), compiler.c_str(), language.c_str());
}
else
{
// In previous versions Platform attribute is the language
platform = "N/A";
language = pElement->Attribute("Platform");
// Map shader language to shader compiler key
const AZStd::unordered_map<AZStd::string, AZStd::string> languageToCompilerMap
{
{
"GL4", SEnviropment::m_GLSL_HLSLcc
},{
"GLES3_0", SEnviropment::m_GLSL_HLSLcc
},{
"GLES3_1", SEnviropment::m_GLSL_HLSLcc
},{
"DX11", SEnviropment::m_D3D11_FXC
},{
"METAL", SEnviropment::m_METAL_HLSLcc
},{
"ORBIS", SEnviropment::m_Orbis_DXC
},{
"JASPER", SEnviropment::m_Jasper_FXC
}
};
auto foundShaderLanguage = languageToCompilerMap.find(language);
if (foundShaderLanguage == languageToCompilerMap.end())
{
State(ECSJS_ERROR_INVALID_LANGUAGE);
CrySimple_ERROR("Trying to compile with invalid shader language");
return false;
}
if (m_Version < EPV_V0022)
{
compiler = "N/A"; // Compiler exe will be specified inside 'compile flags', this variable won't be used
}
else
{
compiler = foundShaderLanguage->second;
if (!SEnviropment::Instance().IsShaderCompilerValid(compiler))
{
State(ECSJS_ERROR_INVALID_COMPILER);
CrySimple_ERROR("Trying to compile with invalid shader compiler");
return false;
}
}
shaderPath = AZStd::string::format("%s%s/", SEnviropment::Instance().m_ShaderPath.c_str(), language.c_str());
}
shaderPath = AZ::IO::PathView(shaderPath).LexicallyNormal().Native();
if (!IsPathValid(shaderPath))
{
State(ECSJS_ERROR);
CrySimple_ERROR("Shaders output path is invalid");
return false;
}
// Create shaders directory
AZ::IO::SystemFile::CreateDir( shaderPath.c_str() );
const char* pProfile = pElement->Attribute("Profile");
const char* pProgram = pElement->Attribute("Program");
const char* pEntry = pElement->Attribute("Entry");
const char* pCompileFlags = pElement->Attribute("CompileFlags");
const char* pShaderRequestLine = pElement->Attribute("ShaderRequest");
if (!pProfile)
{
State(ECSJS_ERROR_INVALID_PROFILE);
CrySimple_ERROR("failed to extract Profile of the request");
return false;
}
if (!pProgram)
{
State(ECSJS_ERROR_INVALID_PROGRAM);
CrySimple_ERROR("failed to extract Program of the request");
return false;
}
if (!pEntry)
{
State(ECSJS_ERROR_INVALID_ENTRY);
CrySimple_ERROR("failed to extract Entry of the request");
return false;
}
if (!pShaderRequestLine)
{
State(ECSJS_ERROR_INVALID_SHADERREQUESTLINE);
CrySimple_ERROR("failed to extract ShaderRequest of the request");
return false;
}
if (!pCompileFlags)
{
State(ECSJS_ERROR_INVALID_COMPILEFLAGS);
CrySimple_ERROR("failed to extract CompileFlags of the request");
return false;
}
// Validate that the shader request line has a set of open/close parens as
// the code below this expects at least the open paren to be in the string.
// Without the open paren the code below will crash the compiler
std::string strippedShaderRequestLine(pShaderRequestLine);
const size_t locationOfOpenParen = strippedShaderRequestLine.find("(");
const size_t locationOfCloseParen = strippedShaderRequestLine.find(")");
if (locationOfOpenParen == std::string::npos ||
locationOfCloseParen == std::string::npos || locationOfCloseParen < locationOfOpenParen)
{
State(ECSJS_ERROR_INVALID_SHADERREQUESTLINE);
CrySimple_ERROR("invalid ShaderRequest attribute");
return false;
}
static AZStd::atomic_long nTmpCounter = { 0 };
++nTmpCounter;
const auto tmpIndex = AZStd::string::format("%ld", static_cast<long>(nTmpCounter));
const AZ::IO::Path TmpIn = SEnviropment::Instance().m_TempPath / (tmpIndex + ".In");
const AZ::IO::Path TmpOut = SEnviropment::Instance().m_TempPath / (tmpIndex + ".Out");
CCrySimpleFileGuard FGTmpIn(TmpIn.c_str());
CCrySimpleFileGuard FGTmpOut(TmpOut.c_str());
CSTLHelper::ToFile(TmpIn.c_str(), std::vector<uint8_t>(pProgram, &pProgram[strlen(pProgram)]));
AZ::IO::Path compilerPath = SEnviropment::Instance().m_CompilerPath;
AZStd::string command;
if (m_Version >= EPV_V0022)
{
AZStd::string compilerExecutable;
bool validCompiler = SEnviropment::Instance().GetShaderCompilerExecutable(compiler, compilerExecutable);
if (!validCompiler)
{
State(ECSJS_ERROR_INVALID_COMPILER);
CrySimple_ERROR("Trying to compile with unknown compiler");
return false;
}
AZStd::string commandStringToFormat = (compilerPath / compilerExecutable).Native();
#if defined(AZ_PLATFORM_LINUX) || defined(AZ_PLATFORM_MAC)
// Surrounding compiler path+executable with quotes to support spaces in the path.
// NOTE: Executable has a space at the end on purpose, inserting quote before.
commandStringToFormat.insert(0, "\"");
commandStringToFormat.insert(commandStringToFormat.length()-1, "\"");
#endif
commandStringToFormat.append(pCompileFlags);
if (strstr(pCompileFlags, "-fxc") != nullptr)
{
AZStd::string fxcCompilerExecutable;
bool validFXCCompiler = SEnviropment::Instance().GetShaderCompilerExecutable(SEnviropment::m_D3D11_FXC, fxcCompilerExecutable);
if (!validFXCCompiler)
{
State(ECSJS_ERROR_INVALID_COMPILER);
CrySimple_ERROR("FXC compiler executable cannot be found");
return false;
}
AZ::IO::Path fxcLocation = compilerPath / fxcCompilerExecutable;
// Handle an extra string parameter to specify the base directory where the fxc compiler is located
command = AZStd::move(AZStd::string::format(commandStringToFormat.c_str(), fxcLocation.c_str(), pEntry, pProfile, TmpOut.c_str(), TmpIn.c_str()));
}
else
{
command = AZStd::move(AZStd::string::format(commandStringToFormat.c_str(), pEntry, pProfile, TmpOut.c_str(), TmpIn.c_str()));
}
}
else
{
if (!ValidateExecutableStringLegacy(pCompileFlags))
{
State(ECSJS_ERROR_INVALID_COMPILEFLAGS);
CrySimple_ERROR("CompileFlags failed validation");
return false;
}
if (strstr(pCompileFlags, "-fxc=\"%s") != nullptr)
{
// Check that the string after the %s is a valid shader compiler
// executable
AZStd::string tempString(pCompileFlags);
const AZStd::string::size_type fxcOffset = tempString.find("%s") + 2;
const AZStd::string::size_type endOfFxcString = tempString.find(" ", fxcOffset);
tempString = tempString.substr(fxcOffset, endOfFxcString);
if (!ValidateExecutableStringLegacy(tempString))
{
State(ECSJS_ERROR_INVALID_COMPILEFLAGS);
CrySimple_ERROR("CompileFlags failed validation");
return false;
}
// Handle an extra string parameter to specify the base directory where the fxc compiler is located
command = AZStd::move(AZStd::string::format(pCompileFlags, compilerPath.c_str(), pEntry, pProfile, TmpOut.c_str(), TmpIn.c_str()));
// Need to add the string for escaped quotes around the path to the compiler. This is in case the path has spaces.
// Adding just quotes (escaped) doesn't work because this cmd line is used to execute another process.
AZStd::string insertPattern = "\\\"";
// Search for the next space until that path exists. Then we assume that's the path to the executable.
size_t startPos = command.find(compilerPath.Native());
for (size_t pos = command.find(" ", startPos); pos != AZStd::string::npos; pos = command.find(" ", pos + 1))
{
if (AZ::IO::SystemFile::Exists(command.substr(startPos, pos - startPos).c_str()))
{
command.insert(pos, insertPattern);
command.insert(startPos, insertPattern);
}
}
}
else
{
command = AZStd::move(AZStd::string::format(pCompileFlags, pEntry, pProfile, TmpOut.c_str(), TmpIn.c_str()));
}
command = compilerPath.Native() + command;
}
AZStd::string hardwareTarget;
#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS)
#if defined(TOOLS_SUPPORT_JASPER)
#define AZ_RESTRICTED_SECTION CRYSIMPLEJOBCOMPILE_CPP_SECTION_1
#include AZ_RESTRICTED_FILE_EXPLICIT(CrySimpleJobCompile_cpp, jasper)
#endif
#if defined(TOOLS_SUPPORT_PROVO)
#define AZ_RESTRICTED_SECTION CRYSIMPLEJOBCOMPILE_CPP_SECTION_1
#include AZ_RESTRICTED_FILE_EXPLICIT(CrySimpleJobCompile_cpp, provo)
#endif
#if defined(TOOLS_SUPPORT_SALEM)
#define AZ_RESTRICTED_SECTION CRYSIMPLEJOBCOMPILE_CPP_SECTION_1
#include AZ_RESTRICTED_FILE_EXPLICIT(CrySimpleJobCompile_cpp, salem)
#endif
#endif
int64_t t0 = g_Timer.GetTime();
std::string outError;
std::string shaderName;
std::stringstream crcStringStream;
// Dump source shader
if (SEnviropment::Instance().m_DumpShaders)
{
unsigned long crc = crc32(0l, Z_NULL, 0);
// shader permutations start with '('
size_t position = strippedShaderRequestLine.find('(');
// split the string into shader name
shaderName = strippedShaderRequestLine.substr(0, position);
// split the string into permutation
std::string permutation = strippedShaderRequestLine.substr(position, strippedShaderRequestLine.length() - position);
// replace illegal filename characters with valid ones
AZStd::replace(shaderName.begin(), shaderName.end(), '<', '(');
AZStd::replace(shaderName.begin(), shaderName.end(), '>', ')');
AZStd::replace(shaderName.begin(), shaderName.end(), '/', '_');
AZStd::replace(shaderName.begin(), shaderName.end(), '|', '+');
AZStd::replace(shaderName.begin(), shaderName.end(), '*', '^');
AZStd::replace(shaderName.begin(), shaderName.end(), ':', ';');
AZStd::replace(shaderName.begin(), shaderName.end(), '?', '!');
AZStd::replace(shaderName.begin(), shaderName.end(), '%', '$');
crc = crc32(crc, reinterpret_cast<const unsigned char*>(permutation.c_str()), static_cast<unsigned int>(permutation.length()));
crcStringStream << crc;
const std::string HlslDump = shaderPath.c_str() + shaderName + "_" + crcStringStream.str() + ".hlsl";
CSTLHelper::ToFile(HlslDump, std::vector<uint8_t>(pProgram, &pProgram[strlen(pProgram)]));
std::ofstream crcFile;
std::string crcFileName = shaderPath.c_str() + shaderName + "_" + crcStringStream.str() + ".txt";
crcFile.open(crcFileName, std::ios_base::trunc);
if (!crcFile.fail())
{
// store permutation
crcFile << permutation;
}
else
{
std::cout << "Error opening file " + crcFileName << std::endl;
}
crcFile.close();
}
if (SEnviropment::Instance().m_PrintCommands)
{
AZ_Printf(0, "Compiler Command:\n%s\n\n", command.c_str());
}
if (!ExecuteCommand(command.c_str(), outError))
{
unsigned char* nIP = (unsigned char*) &RequestIP();
char sIP[128];
azsprintf(sIP, "%d.%d.%d.%d", nIP[0], nIP[1], nIP[2], nIP[3]);
const char* pProject = pElement->Attribute("Project");
const char* pTags = pElement->Attribute("Tags");
const char* pEmailCCs = pElement->Attribute("EmailCCs");
std::string project = pProject ? pProject : "Unk/";
std::string ccs = pEmailCCs ? pEmailCCs : "";
std::string tags = pTags ? pTags : "";
std::string filteredError;
AZ::IO::Path patchFilePath = TmpIn;
patchFilePath.ReplaceFilename(AZ::IO::PathView{ AZStd::string{ TmpIn.Filename().Native() } + ".patched" });
CSTLHelper::Replace(filteredError, outError, patchFilePath.c_str(), "%filename%"); // DXPS does its own patching
CSTLHelper::Replace(filteredError, filteredError, TmpIn.c_str(), "%filename%");
// replace any that don't have the full path
CSTLHelper::Replace(filteredError, filteredError, (tmpIndex + ".In.patched").c_str(), "%filename%"); // DXPS does its own patching
CSTLHelper::Replace(filteredError, filteredError, (tmpIndex + ".In").c_str(), "%filename%");
CSTLHelper::Replace(filteredError, filteredError, "\r\n", "\n");
State(ECSJS_ERROR_COMPILE);
throw new CCompilerError(pEntry, filteredError, ccs, sIP, pShaderRequestLine, pProgram, project, platform.c_str(), compiler.c_str(), language.c_str(), tags, pProfile);
}
if (!CSTLHelper::FromFile(TmpOut.c_str(), rVec))
{
State(ECSJS_ERROR_FILEIO);
std::string errorString("Could not read: ");
errorString += std::string(TmpOut.c_str(), TmpOut.Native().size());
CrySimple_ERROR(errorString.c_str());
return false;
}
// Dump cross-compiled shader
if (SEnviropment::Instance().m_DumpShaders)
{
AZStd::string fileExtension = language;
AZStd::transform(fileExtension.begin(), fileExtension.end(), fileExtension.begin(), tolower);
std::string shaderDump = shaderPath.c_str() + shaderName + "_" + crcStringStream.str() + "." + fileExtension.c_str();
CSTLHelper::ToFile(shaderDump, rVec);
}
int64_t t1 = g_Timer.GetTime();
int64_t dt = t1 - t0;
m_GlobalCompileTime += dt;
int millis = (int)(g_Timer.TimeToSeconds(dt) * 1000.0);
int secondsTotal = (int)g_Timer.TimeToSeconds(m_GlobalCompileTime);
logmessage("Compiled [%5dms|%8ds] (%s - %s - %s - %s) %s\n", millis, secondsTotal, platform.c_str(), compiler.c_str(), language.c_str(), pProfile, pEntry);
if (hardwareTarget.empty())
{
logmessage("Compiled [%5dms|%8ds] (% 5s %s) %s\n", millis, secondsTotal, platform.c_str(), pProfile, pEntry);
}
else
{
logmessage("Compiled [%5dms|%8ds] (% 5s %s) %s %s\n", millis, secondsTotal, platform.c_str(), pProfile, pEntry, hardwareTarget.c_str());
}
return true;
}
//////////////////////////////////////////////////////////////////////////
inline bool SortByLinenum(const std::pair<int, std::string>& f1, const std::pair<int, std::string>& f2)
{
return f1.first < f2.first;
}
CCompilerError::CCompilerError(const std::string& entry, const std::string& errortext, const std::string& ccs, const std::string& IP,
const std::string& requestLine, const std::string& program, const std::string& project,
const std::string& platform, const std::string& compiler, const std::string& language, const std::string& tags, const std::string& profile)
: ICryError(COMPILE_ERROR)
, m_entry(entry)
, m_errortext(errortext)
, m_IP(IP)
, m_program(program)
, m_project(project)
, m_platform(platform)
, m_compiler(compiler)
, m_language(language)
, m_tags(tags)
, m_profile(profile)
, m_uniqueID(0)
{
m_requests.push_back(requestLine);
Init();
CSTLHelper::Tokenize(m_CCs, ccs, ";");
}
void CCompilerError::Init()
{
while (!m_errortext.empty() && (m_errortext.back() == '\r' || m_errortext.back() == '\n'))
{
m_errortext.pop_back();
}
if (m_requests[0].size())
{
m_shader = m_requests[0];
size_t offs = m_shader.find('>');
if (offs != std::string::npos)
{
m_shader.erase(0, m_shader.find('>') + 1); // remove <2> version
}
offs = m_shader.find('@');
if (offs != std::string::npos)
{
m_shader.erase(m_shader.find('@')); // remove everything after @
}
offs = m_shader.find('/');
if (offs != std::string::npos)
{
m_shader.erase(m_shader.find('/')); // remove everything after / (used on xenon)
}
}
else
{
// default to entry function
m_shader = m_entry;
size_t len = m_shader.length();
// if it ends in ?S then trim those two characters
if (m_shader[len - 1] == 'S')
{
m_shader.pop_back();
m_shader.pop_back();
}
}
std::vector<std::string> lines;
CSTLHelper::Tokenize(lines, m_errortext, "\n");
for (uint32_t i = 0; i < lines.size(); i++)
{
std::string& line = lines[i];
if (line.substr(0, 5) == "error")
{
m_errors.push_back(std::pair<int, std::string>(-1, line));
m_hasherrors += line;
continue;
}
if (line.find(": error") == std::string::npos)
{
continue;
}
if (line.substr(0, 10) != "%filename%")
{
continue;
}
if (line[10] != '(')
{
continue;
}
uint32_t c = 11;
int linenum = 0;
{
bool ln = true;
while (c < line.length() &&
((line[c] >= '0' && line[c] <= '9') || line[c] == ',' || line[c] == '-')
)
{
if (line[c] == ',')
{
ln = false; // reached column, don't save the value - just keep reading to the end
}
if (ln)
{
linenum *= 10;
linenum += line[c] - '0';
}
c++;
}
if (c >= line.length())
{
continue;
}
if (line[c] != ')')
{
continue;
}
c++;
}
while (c < line.length() && (line[c] == ' ' || line[c] == ':'))
{
c++;
}
if (line.substr(c, 5) != "error")
{
continue;
}
m_errors.push_back(std::pair<int, std::string>(linenum, line));
m_hasherrors += line.substr(c);
}
AZStd::sort(m_errors.begin(), m_errors.end(), SortByLinenum);
}
std::string CCompilerError::GetErrorLines() const
{
std::string ret = "";
for (uint32_t i = 0; i < m_errors.size(); i++)
{
if (m_errors[i].first < 0)
{
ret += m_errors[i].second + "\n";
}
else if (i > 0 && m_errors[i - 1].first < 0)
{
ret += "\n" + GetContext(m_errors[i].first) + "\n" + m_errors[i].second + "\n\n";
}
else if (i > 0 && m_errors[i - 1].first == m_errors[i].first)
{
ret.pop_back(); // pop extra newline
ret += m_errors[i].second + "\n\n";
}
else
{
ret += GetContext(m_errors[i].first) + "\n" + m_errors[i].second + "\n\n";
}
}
return ret;
}
std::string CCompilerError::GetContext(int linenum, int context, std::string prefix) const
{
std::vector<std::string> lines;
CSTLHelper::Tokenize(lines, m_program, "\n");
std::string ret = "";
linenum--; // line numbers start at one
char sLineNum[16];
for (uint32_t i = AZStd::GetMax(0U, (uint32_t)(linenum - context)); i <= AZStd::GetMin((uint32_t)lines.size() - 1U, (uint32_t)(linenum + context)); i++)
{
azsprintf(sLineNum, "% 3d", i + 1);
ret += sLineNum;
ret += " ";
if (prefix.size())
{
if (i == linenum)
{
ret += "*";
}
else
{
ret += " ";
}
ret += prefix;
ret += " ";
}
ret += lines[i] + "\n";
}
return ret;
}
void CCompilerError::AddDuplicate(ICryError* err)
{
ICryError::AddDuplicate(err);
if (err->GetType() == COMPILE_ERROR)
{
CCompilerError* comperr = (CCompilerError*)err;
m_requests.insert(m_requests.end(), comperr->m_requests.begin(), comperr->m_requests.end());
}
}
bool CCompilerError::Compare(const ICryError* err) const
{
if (GetType() != err->GetType())
{
return GetType() < err->GetType();
}
CCompilerError* e = (CCompilerError*)err;
if (m_platform != e->m_platform)
{
return m_platform < e->m_platform;
}
if (m_compiler != e->m_compiler)
{
return m_compiler < e->m_compiler;
}
if (m_language != e->m_language)
{
return m_language < e->m_language;
}
if (m_shader != e->m_shader)
{
return m_shader < e->m_shader;
}
if (m_entry != e->m_entry)
{
return m_entry < e->m_entry;
}
return Hash() < err->Hash();
}
bool CCompilerError::CanMerge(const ICryError* err) const
{
if (GetType() != err->GetType()) // don't merge with non compile errors
{
return false;
}
CCompilerError* e = (CCompilerError*)err;
if (m_platform != e->m_platform || m_compiler != e->m_compiler || m_language != e->m_language || m_shader != e->m_shader)
{
return false;
}
if (m_CCs.size() != e->m_CCs.size())
{
return false;
}
for (size_t a = 0, S = m_CCs.size(); a < S; a++)
{
if (m_CCs[a] != e->m_CCs[a])
{
return false;
}
}
return true;
}
void CCompilerError::AddCCs(std::set<std::string>& ccs) const
{
for (size_t a = 0, S = m_CCs.size(); a < S; a++)
{
ccs.insert(m_CCs[a]);
}
}
std::string CCompilerError::GetErrorName() const
{
return std::string("[") + m_tags + "] Shader Compile Errors in " + m_shader + " on " + m_language + " for " + m_platform + " " + m_compiler;
}
std::string CCompilerError::GetErrorDetails(EOutputFormatType outputType) const
{
std::string errorString("");
char sUniqueID[16], sNumDuplicates[16];
azsprintf(sUniqueID, "%d", m_uniqueID);
azsprintf(sNumDuplicates, "%d", NumDuplicates());
std::string errorOutput;
CSTLHelper::Replace(errorOutput, GetErrorLines(), "%filename%", std::string(sUniqueID) + "-" + GetFilename());
std::string fullOutput;
CSTLHelper::Replace(fullOutput, m_errortext, "%filename%", std::string(sUniqueID) + "-" + GetFilename());
if (outputType == OUTPUT_HASH)
{
errorString = GetFilename() + m_IP + m_platform + m_compiler + m_language + m_project + m_entry + m_tags + m_profile + m_hasherrors /*+ m_requestline*/;
}
else if (outputType == OUTPUT_EMAIL)
{
errorString = std::string("=== Shader compile error in ") + m_entry + " (" + sNumDuplicates + " duplicates)\n\n";
/////
errorString += std::string("* From: ") + m_IP + " on " + m_language + " for " + m_platform + " " + m_compiler + " " + m_project;
if (m_tags != "")
{
errorString += std::string(" (Tags: ") + m_tags + ")";
}
errorString += "\n";
/////
errorString += std::string("* Target profile: ") + m_profile + "\n";
/////
bool hasrequests = false;
for (uint32_t i = 0; i < m_requests.size(); i++)
{
if (m_requests[i].size())
{
errorString += std::string("* Shader request line: ") + m_requests[i] + "\n";
hasrequests = true;
}
}
errorString += "\n";
if (hasrequests)
{
errorString += "* Shader source from first listed request\n";
}
errorString += std::string("* Reported error(s) from ") + sUniqueID + "-" + GetFilename() + "\n\n";
errorString += errorOutput + "\n\n";
errorString += std::string("* Full compiler output:\n\n");
errorString += fullOutput + "\n";
}
else if (outputType == OUTPUT_TTY)
{
errorString = std::string("=== Shader compile error in ") + m_entry + " { " + m_requests[0] + " }\n";
// errors only
errorString += std::string("* Reported error(s):\n\n");
errorString += errorOutput;
errorString += m_errortext;
}
return errorString;
}

Some files were not shown because too many files have changed in this diff Show More