Merge branch 'main' into TIF/Runtime
@@ -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 @@
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
)
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
)
|
||||
)
|
||||
|
||||
@@ -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(<ime);
|
||||
tm today;
|
||||
#if defined(AZ_PLATFORM_WINDOWS)
|
||||
localtime_s(&today, <ime);
|
||||
#else
|
||||
localtime_r(<ime, &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> </TH><TH align=center>%</TH></TR>\n"
|
||||
#define TABLE_INFO "<TR><TD>%s</TD><TD> </TD><TD align=left>%s</TD><TD align=center></TD><TD> </TD><TD valign=middle>\n\
|
||||
</TD></TR>\n\
|
||||
</TD></TR>\n"
|
||||
#define TABLE_BAR "<TR><TD>%s</TD><TD> </TD><TD align=center>%d</TD><TD align=center>%d</TD><TD> </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;
|
||||
}
|
||||