Merge branch 'boost' into 'develop'
Boost
This commit is contained in:
commit
b2a84b2caf
92
.gitmodules
vendored
92
.gitmodules
vendored
@ -35,3 +35,95 @@
|
||||
path = deps/protobuf
|
||||
url = https://github.com/google/protobuf.git
|
||||
branch = 3.2.x
|
||||
[submodule "deps/boost/interprocess"]
|
||||
path = deps/boost/interprocess
|
||||
url = https://github.com/boostorg/interprocess.git
|
||||
branch = develop
|
||||
[submodule "deps/boost/config"]
|
||||
path = deps/boost/config
|
||||
url = https://github.com/boostorg/config.git
|
||||
branch = develop
|
||||
[submodule "deps/boost/date_time"]
|
||||
path = deps/boost/date_time
|
||||
url = https://github.com/boostorg/date_time.git
|
||||
branch = develop
|
||||
[submodule "deps/boost/assert"]
|
||||
path = deps/boost/assert
|
||||
url = https://github.com/boostorg/assert.git
|
||||
branch = develop
|
||||
[submodule "deps/boost/utility"]
|
||||
path = deps/boost/utility
|
||||
url = https://github.com/boostorg/utility.git
|
||||
branch = develop
|
||||
[submodule "deps/boost/detail"]
|
||||
path = deps/boost/detail
|
||||
url = https://github.com/boostorg/detail.git
|
||||
branch = develop
|
||||
[submodule "deps/boost/winapi"]
|
||||
path = deps/boost/winapi
|
||||
url = https://github.com/boostorg/winapi.git
|
||||
branch = develop
|
||||
[submodule "deps/boost/integer"]
|
||||
path = deps/boost/integer
|
||||
url = https://github.com/boostorg/integer.git
|
||||
branch = develop
|
||||
[submodule "deps/boost/move"]
|
||||
path = deps/boost/move
|
||||
url = https://github.com/boostorg/move.git
|
||||
branch = develop
|
||||
[submodule "deps/boost/static_assert"]
|
||||
path = deps/boost/static_assert
|
||||
url = https://github.com/boostorg/static_assert.git
|
||||
branch = develop
|
||||
[submodule "deps/boost/container"]
|
||||
path = deps/boost/container
|
||||
url = https://github.com/boostorg/container.git
|
||||
branch = develop
|
||||
[submodule "deps/boost/intrusive"]
|
||||
path = deps/boost/intrusive
|
||||
url = https://github.com/boostorg/intrusive.git
|
||||
branch = develop
|
||||
[submodule "deps/boost/core"]
|
||||
path = deps/boost/core
|
||||
url = https://github.com/boostorg/core.git
|
||||
branch = develop
|
||||
[submodule "deps/boost/functional"]
|
||||
path = deps/boost/functional
|
||||
url = https://github.com/boostorg/functional.git
|
||||
branch = develop
|
||||
[submodule "deps/boost/type_traits"]
|
||||
path = deps/boost/type_traits
|
||||
url = https://github.com/boostorg/type_traits.git
|
||||
branch = develop
|
||||
[submodule "deps/boost/preprocessor"]
|
||||
path = deps/boost/preprocessor
|
||||
url = https://github.com/boostorg/preprocessor.git
|
||||
branch = develop
|
||||
[submodule "deps/boost/smart_ptr"]
|
||||
path = deps/boost/smart_ptr
|
||||
url = https://github.com/boostorg/smart_ptr.git
|
||||
branch = develop
|
||||
[submodule "deps/boost/throw_exception"]
|
||||
path = deps/boost/throw_exception
|
||||
url = https://github.com/boostorg/throw_exception.git
|
||||
branch = develop
|
||||
[submodule "deps/boost/predef"]
|
||||
path = deps/boost/predef
|
||||
url = https://github.com/boostorg/predef.git
|
||||
branch = develop
|
||||
[submodule "deps/boost/mpl"]
|
||||
path = deps/boost/mpl
|
||||
url = https://github.com/boostorg/mpl.git
|
||||
branch = develop
|
||||
[submodule "deps/boost/unordered"]
|
||||
path = deps/boost/unordered
|
||||
url = https://github.com/boostorg/unordered.git
|
||||
branch = develop
|
||||
[submodule "deps/boost/iterator"]
|
||||
path = deps/boost/iterator
|
||||
url = https://github.com/boostorg/iterator.git
|
||||
branch = develop
|
||||
[submodule "deps/boost/tuple"]
|
||||
path = deps/boost/tuple
|
||||
url = https://github.com/boostorg/tuple.git
|
||||
branch = develop
|
||||
|
@ -33,6 +33,5 @@
|
||||
| `--disable-bitmessage` | Disable use of BitMessage completely. |
|
||||
| `--disable-node-log` | Disable debugging messages for Nodes in Debug builds. |
|
||||
| `--disable-base128` | Disable base128 encoding for minidumps. |
|
||||
| `--disable-steam-game` | Disable Steam's in-game setting. |
|
||||
| `--no-new-structure` | Do not use new virtual path structure (separating headers and source files). |
|
||||
| `--enable-dxsdk` | Enable DirectX SDK (required for GfxMap exporting). |
|
||||
|
1
deps/boost/assert
vendored
Submodule
1
deps/boost/assert
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 89e5b86c469c993ea4c53ebc7ed4a9b133f785a6
|
1
deps/boost/config
vendored
Submodule
1
deps/boost/config
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit b4628d91eb8b2cbf96e3dadee3d6bff97b50ae46
|
1
deps/boost/container
vendored
Submodule
1
deps/boost/container
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 23e9e8b4946f8b026ced6b048d7a62b4ca81b722
|
1
deps/boost/core
vendored
Submodule
1
deps/boost/core
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 1abd68102d26d87109b5eda8d80f8bb0382ce4df
|
1
deps/boost/date_time
vendored
Submodule
1
deps/boost/date_time
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 47cf10d5fd7cee50d4e53a6132c69a7e1cbb2d0b
|
1
deps/boost/detail
vendored
Submodule
1
deps/boost/detail
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 6c111975865d112c11101ef8221695cc4cd57562
|
1
deps/boost/functional
vendored
Submodule
1
deps/boost/functional
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit c592e854919730597b1793f85667e7d88f000d29
|
1
deps/boost/integer
vendored
Submodule
1
deps/boost/integer
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 13b153c657697129cabe7ac8b3e62ef844a62945
|
1
deps/boost/interprocess
vendored
Submodule
1
deps/boost/interprocess
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 0cd4548b45a9b9fdac2c58f2acb793095754f821
|
1
deps/boost/intrusive
vendored
Submodule
1
deps/boost/intrusive
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 286f597606de0d139e256af8c2695d90535be905
|
1
deps/boost/iterator
vendored
Submodule
1
deps/boost/iterator
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 760da84f9cbbe87afb7ef845ef5fa6be158637b7
|
1
deps/boost/move
vendored
Submodule
1
deps/boost/move
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 135e598bc4ffc63001d84f93764fddee234f1da2
|
1
deps/boost/mpl
vendored
Submodule
1
deps/boost/mpl
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 3b126bdf8c7abbfef27101232a379c8e0c3db1ac
|
1
deps/boost/predef
vendored
Submodule
1
deps/boost/predef
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 822d09f19bc2f4ea6f42da8e0be83d10ce912ce1
|
1
deps/boost/preprocessor
vendored
Submodule
1
deps/boost/preprocessor
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit d8389ffda600ce73d62b077616987744f5f83453
|
1
deps/boost/smart_ptr
vendored
Submodule
1
deps/boost/smart_ptr
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 19147212a9edd1facdc9a17cf586b79c92f4116a
|
1
deps/boost/static_assert
vendored
Submodule
1
deps/boost/static_assert
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit c2f58a187a67502a20aaa14c88625f12e400c5c1
|
1
deps/boost/throw_exception
vendored
Submodule
1
deps/boost/throw_exception
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit f94638e5225afff877347576ff7b4170971e7a2a
|
1
deps/boost/tuple
vendored
Submodule
1
deps/boost/tuple
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 895af7c97a2f74980eb459badf67787c2a3ecadf
|
1
deps/boost/type_traits
vendored
Submodule
1
deps/boost/type_traits
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 4fffc7637da8479e3f94674ef1dd0fc996a7d027
|
1
deps/boost/unordered
vendored
Submodule
1
deps/boost/unordered
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 57cc6d4bac1cc93fb8fb05696116b184f3d1fecc
|
1
deps/boost/utility
vendored
Submodule
1
deps/boost/utility
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit ccfd741c0a423e6c8dc4493e3a4e042b5a34a329
|
1
deps/boost/winapi
vendored
Submodule
1
deps/boost/winapi
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit b017fd886612a9001dfdffeb1aa4663b6e2acda8
|
2
deps/protobuf
vendored
2
deps/protobuf
vendored
@ -1 +1 @@
|
||||
Subproject commit d1f0939a42ae8a6b6bca95a4b9048d7416e72865
|
||||
Subproject commit 2c8346a259791ccb176da80e31e59f1df479bd6d
|
83
premake/boost.lua
Normal file
83
premake/boost.lua
Normal file
@ -0,0 +1,83 @@
|
||||
boost = {
|
||||
settings = nil,
|
||||
}
|
||||
|
||||
function boost.setup(settings)
|
||||
if not settings.source then error("Missing source.") end
|
||||
|
||||
boost.settings = settings
|
||||
end
|
||||
|
||||
function boost.import()
|
||||
if not boost.settings then error("Run boost.setup first") end
|
||||
|
||||
--links { "boost" }
|
||||
boost.includes()
|
||||
end
|
||||
|
||||
function boost.includes()
|
||||
if not boost.settings then error("Run boost.setup first") end
|
||||
|
||||
submodules = {
|
||||
"mpl",
|
||||
"core",
|
||||
"move",
|
||||
"tuple",
|
||||
"assert",
|
||||
"predef",
|
||||
"config",
|
||||
"detail",
|
||||
"winapi",
|
||||
"integer",
|
||||
"utility",
|
||||
"iterator",
|
||||
"container",
|
||||
"unordered",
|
||||
"date_time",
|
||||
"smart_ptr",
|
||||
"intrusive",
|
||||
"functional",
|
||||
"type_traits",
|
||||
"interprocess",
|
||||
"preprocessor",
|
||||
"static_assert",
|
||||
"throw_exception",
|
||||
}
|
||||
|
||||
for i, submodule in ipairs(submodules) do
|
||||
includedirs { path.join(boost.settings.source, string.format("%s/include", submodule)) }
|
||||
end
|
||||
|
||||
includedirs { boost.settings.source }
|
||||
end
|
||||
|
||||
function boost.project()
|
||||
if not boost.settings then error("Run boost.setup first") end
|
||||
|
||||
--[[
|
||||
project "boost"
|
||||
language "C++"
|
||||
|
||||
includedirs
|
||||
{
|
||||
boost.settings.source,
|
||||
}
|
||||
|
||||
files
|
||||
{
|
||||
path.join(boost.settings.source, "*.cpp"),
|
||||
path.join(boost.settings.source, "*.hpp"),
|
||||
}
|
||||
removefiles
|
||||
{
|
||||
path.join(boost.settings.source, "test*"),
|
||||
}
|
||||
|
||||
-- not our code, ignore POSIX usage warnings for now
|
||||
warnings "Off"
|
||||
|
||||
defines { "_LIB" }
|
||||
removedefines { "_USRDLL", "_DLL" }
|
||||
kind "StaticLib"
|
||||
]]
|
||||
end
|
20
premake5.lua
20
premake5.lua
@ -88,11 +88,6 @@ newoption {
|
||||
description = "Disable base128 encoding for minidumps."
|
||||
}
|
||||
|
||||
newoption {
|
||||
trigger = "disable-steam-game",
|
||||
description = "Disable Steam's in-game setting."
|
||||
}
|
||||
|
||||
newoption {
|
||||
trigger = "enable-dxsdk",
|
||||
description = "Enable DirectX SDK (required for GfxMap exporting)."
|
||||
@ -204,6 +199,7 @@ require "premake/pdcurses"
|
||||
require "premake/protobuf"
|
||||
require "premake/sqlite3"
|
||||
require "premake/zlib"
|
||||
require "premake/boost"
|
||||
|
||||
base128.setup
|
||||
{
|
||||
@ -260,6 +256,10 @@ zlib.setup
|
||||
},
|
||||
source = path.join(depsBasePath, "zlib"),
|
||||
}
|
||||
boost.setup
|
||||
{
|
||||
source = path.join(depsBasePath, "boost"),
|
||||
}
|
||||
|
||||
workspace "iw4x"
|
||||
location "./build"
|
||||
@ -304,7 +304,7 @@ workspace "iw4x"
|
||||
}
|
||||
includedirs {
|
||||
"%{prj.location}/src",
|
||||
"./src"
|
||||
"./src",
|
||||
}
|
||||
resincludedirs {
|
||||
"$(ProjectDir)src" -- fix for VS IDE
|
||||
@ -341,9 +341,6 @@ workspace "iw4x"
|
||||
if _OPTIONS["disable-base128"] then
|
||||
defines { "DISABLE_BASE128" }
|
||||
end
|
||||
if _OPTIONS["disable-steam-game"] then
|
||||
defines { "DISABLE_STEAM_GAME" }
|
||||
end
|
||||
if _OPTIONS["enable-dxsdk"] then
|
||||
defines { "ENABLE_DXSDK" }
|
||||
includedirs { "%DXSDK_DIR%Include" }
|
||||
@ -369,6 +366,7 @@ workspace "iw4x"
|
||||
pdcurses.import()
|
||||
protobuf.import()
|
||||
zlib.import()
|
||||
boost.import()
|
||||
|
||||
-- fix vpaths for protobuf sources
|
||||
vpaths
|
||||
@ -397,8 +395,9 @@ workspace "iw4x"
|
||||
-- Pre-build
|
||||
prebuildcommands
|
||||
{
|
||||
"cd %{_MAIN_SCRIPT_DIR}",
|
||||
"pushd %{_MAIN_SCRIPT_DIR}",
|
||||
"tools\\premake5 generate-buildinfo",
|
||||
"popd",
|
||||
}
|
||||
|
||||
-- Post-build
|
||||
@ -486,6 +485,7 @@ workspace "iw4x"
|
||||
pdcurses.project()
|
||||
protobuf.project()
|
||||
zlib.project()
|
||||
boost.project()
|
||||
|
||||
rule "ProtobufCompiler"
|
||||
display "Protobuf compiler"
|
||||
|
@ -43,7 +43,6 @@ namespace Components
|
||||
Loader::Register(new Command());
|
||||
Loader::Register(new Console());
|
||||
Loader::Register(new Friends());
|
||||
Loader::Register(new IPCPipe());
|
||||
Loader::Register(new ModList());
|
||||
Loader::Register(new Network());
|
||||
Loader::Register(new Theatre());
|
||||
@ -68,6 +67,7 @@ namespace Components
|
||||
Loader::Register(new BitMessage());
|
||||
#endif
|
||||
Loader::Register(new FileSystem());
|
||||
Loader::Register(new IPCHandler());
|
||||
Loader::Register(new ModelSurfs());
|
||||
Loader::Register(new PlayerName());
|
||||
Loader::Register(new QuickPatch());
|
||||
|
@ -59,7 +59,6 @@ namespace Components
|
||||
#include "Modules/Window.hpp"
|
||||
#include "Modules/Command.hpp"
|
||||
#include "Modules/Console.hpp"
|
||||
#include "Modules/IPCPipe.hpp"
|
||||
#include "Modules/UIScript.hpp"
|
||||
#include "Modules/ModList.hpp"
|
||||
#include "Modules/Network.hpp"
|
||||
@ -86,6 +85,7 @@ namespace Components
|
||||
#include "Modules/Threading.hpp"
|
||||
#include "Modules/BitMessage.hpp"
|
||||
#include "Modules/FileSystem.hpp"
|
||||
#include "Modules/IPCHandler.hpp"
|
||||
#include "Modules/ModelSurfs.hpp"
|
||||
#include "Modules/PlayerName.hpp"
|
||||
#include "Modules/QuickPatch.hpp"
|
||||
|
@ -6,7 +6,7 @@
|
||||
#endif
|
||||
|
||||
// Uncomment to enable process protection (conflicts with steam!)
|
||||
//#define PROCTECT_PROCESS
|
||||
#define PROCTECT_PROCESS
|
||||
|
||||
namespace Components
|
||||
{
|
||||
|
@ -212,7 +212,7 @@ namespace Components
|
||||
ConnectProtocol::ConnectProtocol()
|
||||
{
|
||||
// IPC handler
|
||||
IPCPipe::On("connect", [] (std::string data)
|
||||
IPCHandler::OnClient("connect", [] (std::string data)
|
||||
{
|
||||
Command::Execute(Utils::String::VA("connect %s", data.data()), false);
|
||||
});
|
||||
@ -229,7 +229,7 @@ namespace Components
|
||||
{
|
||||
if (!Singleton::IsFirstInstance())
|
||||
{
|
||||
IPCPipe::Write("connect", ConnectProtocol::ConnectString);
|
||||
IPCHandler::SendClient("connect", ConnectProtocol::ConnectString);
|
||||
ExitProcess(0);
|
||||
}
|
||||
else
|
||||
|
@ -507,7 +507,7 @@ namespace Components
|
||||
{ "con_outputWindowColor", { 0.25f, 0.25f, 0.25f, 0.85f } },
|
||||
};
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(patchedColors); ++i)
|
||||
for (int i = 0; i < ARRAYSIZE(patchedColors); ++i)
|
||||
{
|
||||
if (std::string(name) == patchedColors[i].name)
|
||||
{
|
||||
|
128
src/Components/Modules/IPCHandler.cpp
Normal file
128
src/Components/Modules/IPCHandler.cpp
Normal file
@ -0,0 +1,128 @@
|
||||
#include "STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
std::unordered_map<std::string, IPCHandler::Callback> IPCHandler::WorkerCallbacks;
|
||||
std::unordered_map<std::string, IPCHandler::Callback> IPCHandler::ClientCallbacks;
|
||||
|
||||
std::unique_ptr<Utils::IPC::BidirectionalChannel> IPCHandler::WorkerChannel;
|
||||
std::unique_ptr<Utils::IPC::BidirectionalChannel> IPCHandler::ClientChannel;
|
||||
|
||||
void IPCHandler::SendWorker(std::string message, std::string data)
|
||||
{
|
||||
IPCHandler::InitChannels();
|
||||
|
||||
Proto::IPC::Command command;
|
||||
command.set_command(message);
|
||||
command.set_data(data);
|
||||
|
||||
IPCHandler::WorkerChannel->send(command.SerializeAsString());
|
||||
}
|
||||
|
||||
void IPCHandler::SendClient(std::string message, std::string data)
|
||||
{
|
||||
IPCHandler::InitChannels();
|
||||
|
||||
Proto::IPC::Command command;
|
||||
command.set_command(message);
|
||||
command.set_data(data);
|
||||
|
||||
IPCHandler::ClientChannel->send(command.SerializeAsString());
|
||||
}
|
||||
|
||||
void IPCHandler::OnWorker(std::string message, IPCHandler::Callback callback)
|
||||
{
|
||||
IPCHandler::WorkerCallbacks[message] = callback;
|
||||
}
|
||||
|
||||
void IPCHandler::OnClient(std::string message, IPCHandler::Callback callback)
|
||||
{
|
||||
IPCHandler::ClientCallbacks[message] = callback;
|
||||
}
|
||||
|
||||
void IPCHandler::InitChannels()
|
||||
{
|
||||
if (!IPCHandler::WorkerChannel)
|
||||
{
|
||||
IPCHandler::WorkerChannel.reset(new Utils::IPC::BidirectionalChannel("IW4x-Worker-Channel", !Worker::IsWorker()));
|
||||
}
|
||||
|
||||
if (!IPCHandler::ClientChannel)
|
||||
{
|
||||
IPCHandler::ClientChannel.reset(new Utils::IPC::BidirectionalChannel("IW4x-Client-Channel", Singleton::IsFirstInstance()));
|
||||
}
|
||||
}
|
||||
|
||||
void IPCHandler::StartWorker()
|
||||
{
|
||||
STARTUPINFOA sInfo;
|
||||
PROCESS_INFORMATION pInfo;
|
||||
|
||||
ZeroMemory(&sInfo, sizeof(sInfo));
|
||||
ZeroMemory(&pInfo, sizeof(pInfo));
|
||||
sInfo.cb = sizeof(sInfo);
|
||||
|
||||
CreateProcessA("iw4x.exe", const_cast<char*>(Utils::String::VA("-parent %d", GetCurrentProcessId())), nullptr, nullptr, false, NULL, nullptr, nullptr, &sInfo, &pInfo);
|
||||
|
||||
if (pInfo.hThread && pInfo.hThread != INVALID_HANDLE_VALUE) CloseHandle(pInfo.hThread);
|
||||
if (pInfo.hProcess && pInfo.hProcess != INVALID_HANDLE_VALUE) CloseHandle(pInfo.hProcess);
|
||||
}
|
||||
|
||||
void IPCHandler::HandleClient()
|
||||
{
|
||||
IPCHandler::InitChannels();
|
||||
|
||||
std::string packet;
|
||||
if(IPCHandler::ClientChannel->receive(&packet))
|
||||
{
|
||||
Proto::IPC::Command command;
|
||||
if(command.ParseFromString(packet))
|
||||
{
|
||||
auto callback = IPCHandler::ClientCallbacks.find(command.command());
|
||||
if (callback != IPCHandler::ClientCallbacks.end())
|
||||
{
|
||||
callback->second(command.data());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IPCHandler::HandleWorker()
|
||||
{
|
||||
IPCHandler::InitChannels();
|
||||
|
||||
std::string packet;
|
||||
if (IPCHandler::WorkerChannel->receive(&packet))
|
||||
{
|
||||
Proto::IPC::Command command;
|
||||
if (command.ParseFromString(packet))
|
||||
{
|
||||
auto callback = IPCHandler::WorkerCallbacks.find(command.command());
|
||||
if (callback != IPCHandler::WorkerCallbacks.end())
|
||||
{
|
||||
callback->second(command.data());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IPCHandler::IPCHandler()
|
||||
{
|
||||
if (Dedicated::IsEnabled()) return;
|
||||
|
||||
IPCHandler::InitChannels();
|
||||
IPCHandler::StartWorker();
|
||||
|
||||
QuickPatch::OnFrame([]()
|
||||
{
|
||||
IPCHandler::HandleWorker();
|
||||
IPCHandler::HandleClient();
|
||||
});
|
||||
}
|
||||
|
||||
IPCHandler::~IPCHandler()
|
||||
{
|
||||
IPCHandler::WorkerCallbacks.clear();
|
||||
IPCHandler::ClientCallbacks.clear();
|
||||
}
|
||||
}
|
36
src/Components/Modules/IPCHandler.hpp
Normal file
36
src/Components/Modules/IPCHandler.hpp
Normal file
@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
namespace Components
|
||||
{
|
||||
class IPCHandler : public Component
|
||||
{
|
||||
public:
|
||||
typedef Utils::Slot<void(std::string)> Callback;
|
||||
|
||||
IPCHandler();
|
||||
~IPCHandler();
|
||||
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* getName() override { return "IPCHandler"; };
|
||||
#endif
|
||||
|
||||
static void SendWorker(std::string message, std::string data);
|
||||
static void SendClient(std::string message, std::string data);
|
||||
|
||||
static void OnWorker(std::string message, Callback callback);
|
||||
static void OnClient(std::string message, Callback callback);
|
||||
|
||||
private:
|
||||
static std::unique_ptr<Utils::IPC::BidirectionalChannel> WorkerChannel;
|
||||
static std::unique_ptr<Utils::IPC::BidirectionalChannel> ClientChannel;
|
||||
|
||||
static std::unordered_map<std::string, Callback> WorkerCallbacks;
|
||||
static std::unordered_map<std::string, Callback> ClientCallbacks;
|
||||
|
||||
static void InitChannels();
|
||||
static void StartWorker();
|
||||
|
||||
static void HandleClient();
|
||||
static void HandleWorker();
|
||||
};
|
||||
}
|
@ -1,245 +0,0 @@
|
||||
#include "STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
Pipe IPCPipe::ServerPipe;
|
||||
Pipe IPCPipe::ClientPipe;
|
||||
|
||||
#pragma region Pipe
|
||||
|
||||
Pipe::Pipe() : connectCallback(0), pipe(INVALID_HANDLE_VALUE), threadAttached(false), type(IPCTYPE_NONE), reconnectAttempt(0)
|
||||
{
|
||||
this->destroy();
|
||||
}
|
||||
|
||||
Pipe::~Pipe()
|
||||
{
|
||||
this->destroy();
|
||||
}
|
||||
|
||||
bool Pipe::connect(std::string name)
|
||||
{
|
||||
this->destroy();
|
||||
|
||||
this->type = IPCTYPE_CLIENT;
|
||||
this->setName(name);
|
||||
|
||||
this->pipe = CreateFileA(this->pipeFile, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
|
||||
if (INVALID_HANDLE_VALUE == this->pipe)
|
||||
{
|
||||
Logger::Print("Failed to connect to the pipe\n");
|
||||
|
||||
if (this->reconnectAttempt < IPC_MAX_RECONNECTS)
|
||||
{
|
||||
Logger::Print("Attempting to reconnect to the pipe.\n");
|
||||
++this->reconnectAttempt;
|
||||
std::this_thread::sleep_for(500ms);
|
||||
|
||||
return this->connect(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->destroy();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
this->reconnectAttempt = 0;
|
||||
Logger::Print("Successfully connected to the pipe\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Pipe::create(std::string name)
|
||||
{
|
||||
this->destroy();
|
||||
|
||||
this->type = IPCTYPE_SERVER;
|
||||
this->setName(name);
|
||||
|
||||
this->pipe = CreateNamedPipeA(this->pipeFile, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, sizeof(this->packet), sizeof(this->packet), NMPWAIT_USE_DEFAULT_WAIT, nullptr);
|
||||
|
||||
if (INVALID_HANDLE_VALUE != this->pipe && this->pipe)
|
||||
{
|
||||
// Only create the thread, when not performing unit tests!
|
||||
if (!Loader::PerformingUnitTests())
|
||||
{
|
||||
this->threadAttached = true;
|
||||
this->thread = std::thread(Pipe::ReceiveThread, this);
|
||||
}
|
||||
|
||||
Logger::Print("Pipe successfully created\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
Logger::Print("Failed to create the pipe\n");
|
||||
this->destroy();
|
||||
return false;
|
||||
}
|
||||
|
||||
void Pipe::onConnect(Pipe::Callback callback)
|
||||
{
|
||||
this->connectCallback = callback;
|
||||
}
|
||||
|
||||
void Pipe::setCallback(std::string command, Utils::Slot<Pipe::PacketCallback> callback)
|
||||
{
|
||||
this->packetCallbacks[command] = callback;
|
||||
}
|
||||
|
||||
bool Pipe::write(std::string command, std::string data)
|
||||
{
|
||||
if (this->type != IPCTYPE_CLIENT || this->pipe == INVALID_HANDLE_VALUE) return false;
|
||||
|
||||
Pipe::Packet _packet;
|
||||
strcpy_s(_packet.command, command.data());
|
||||
strcpy_s(_packet.buffer, data.data());
|
||||
|
||||
DWORD cbBytes;
|
||||
return (WriteFile(this->pipe, &_packet, sizeof(_packet), &cbBytes, nullptr) || GetLastError() == ERROR_IO_PENDING);
|
||||
}
|
||||
|
||||
void Pipe::destroy()
|
||||
{
|
||||
//this->Type = IPCTYPE_NONE;
|
||||
|
||||
//*this->PipeFile = 0;
|
||||
//*this->PipeName = 0;
|
||||
|
||||
if (this->pipe && INVALID_HANDLE_VALUE != this->pipe)
|
||||
{
|
||||
CancelIoEx(this->pipe, nullptr);
|
||||
//DeleteFileA(this->pipeFile);
|
||||
|
||||
if (this->type == IPCTYPE_SERVER) DisconnectNamedPipe(this->pipe);
|
||||
|
||||
CloseHandle(this->pipe);
|
||||
Logger::Print("Disconnected from the pipe.\n");
|
||||
}
|
||||
|
||||
this->pipe = nullptr;
|
||||
this->threadAttached = false;
|
||||
|
||||
if (this->thread.joinable())
|
||||
{
|
||||
Logger::Print("Terminating pipe thread...\n");
|
||||
|
||||
this->thread.join();
|
||||
|
||||
Logger::Print("Pipe thread terminated.\n");
|
||||
}
|
||||
|
||||
this->thread = std::thread();
|
||||
}
|
||||
|
||||
void Pipe::setName(std::string name)
|
||||
{
|
||||
memset(this->pipeName, 0, sizeof(this->pipeName));
|
||||
memset(this->pipeFile, 0, sizeof(this->pipeFile));
|
||||
|
||||
strncpy_s(this->pipeName, name.data(), sizeof(this->pipeName));
|
||||
sprintf_s(this->pipeFile, sizeof(this->pipeFile), "\\\\.\\Pipe\\%s", this->pipeName);
|
||||
}
|
||||
|
||||
void Pipe::ReceiveThread(Pipe* pipe)
|
||||
{
|
||||
if (!pipe || pipe->type != IPCTYPE_SERVER || pipe->pipe == INVALID_HANDLE_VALUE || !pipe->pipe) return;
|
||||
|
||||
if (ConnectNamedPipe(pipe->pipe, nullptr) == FALSE)
|
||||
{
|
||||
Logger::Print("Failed to initialize pipe reading.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
Logger::Print("Client connected to the pipe\n");
|
||||
pipe->connectCallback();
|
||||
|
||||
DWORD cbBytes;
|
||||
|
||||
while (pipe->threadAttached && pipe->pipe && pipe->pipe != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
BOOL bResult = ReadFile(pipe->pipe, &pipe->packet, sizeof(pipe->packet), &cbBytes, nullptr);
|
||||
|
||||
if (bResult && cbBytes)
|
||||
{
|
||||
if (pipe->packetCallbacks.find(pipe->packet.command) != pipe->packetCallbacks.end())
|
||||
{
|
||||
pipe->packetCallbacks[pipe->packet.command](pipe->packet.buffer);
|
||||
}
|
||||
}
|
||||
else if (pipe->threadAttached && pipe->pipe != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
Logger::Print("Failed to read from client through pipe\n");
|
||||
|
||||
DisconnectNamedPipe(pipe->pipe);
|
||||
ConnectNamedPipe(pipe->pipe, nullptr);
|
||||
pipe->connectCallback();
|
||||
}
|
||||
|
||||
ZeroMemory(&pipe->packet, sizeof(pipe->packet));
|
||||
}
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
// Callback to connect first instance's client pipe to the second instance's server pipe
|
||||
void IPCPipe::ConnectClient()
|
||||
{
|
||||
if (Singleton::IsFirstInstance())
|
||||
{
|
||||
IPCPipe::ClientPipe.connect(IPC_PIPE_NAME_CLIENT);
|
||||
}
|
||||
}
|
||||
|
||||
// Writes to the process on the other end of the pipe
|
||||
bool IPCPipe::Write(std::string command, std::string data)
|
||||
{
|
||||
return IPCPipe::ClientPipe.write(command, data);
|
||||
}
|
||||
|
||||
// Installs a callback for receiving commands from the process on the other end of the pipe
|
||||
void IPCPipe::On(std::string command, Utils::Slot<Pipe::PacketCallback> callback)
|
||||
{
|
||||
IPCPipe::ServerPipe.setCallback(command, callback);
|
||||
}
|
||||
|
||||
IPCPipe::IPCPipe()
|
||||
{
|
||||
if (Dedicated::IsEnabled()) return;
|
||||
|
||||
// Server pipe
|
||||
IPCPipe::ServerPipe.onConnect(IPCPipe::ConnectClient);
|
||||
IPCPipe::ServerPipe.create((Singleton::IsFirstInstance() ? IPC_PIPE_NAME_SERVER : IPC_PIPE_NAME_CLIENT));
|
||||
|
||||
// Connect second instance's client pipe to first instance's server pipe
|
||||
if (!Singleton::IsFirstInstance())
|
||||
{
|
||||
IPCPipe::ClientPipe.connect(IPC_PIPE_NAME_SERVER);
|
||||
}
|
||||
|
||||
IPCPipe::On("ping", [] (std::string data)
|
||||
{
|
||||
Logger::Print("Received ping form pipe, sending pong!\n");
|
||||
IPCPipe::Write("pong", data);
|
||||
});
|
||||
|
||||
IPCPipe::On("pong", [] (std::string data)
|
||||
{
|
||||
Logger::Print("Received pong form pipe!\n");
|
||||
});
|
||||
|
||||
// Test pipe functionality by sending pings
|
||||
Command::Add("ipcping", [] (Command::Params*)
|
||||
{
|
||||
Logger::Print("Sending ping to pipe!\n");
|
||||
IPCPipe::Write("ping", "");
|
||||
});
|
||||
}
|
||||
|
||||
void IPCPipe::preDestroy()
|
||||
{
|
||||
IPCPipe::ServerPipe.destroy();
|
||||
IPCPipe::ClientPipe.destroy();
|
||||
}
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#define IPC_MAX_RECONNECTS 3
|
||||
#define IPC_COMMAND_SIZE 100
|
||||
#define IPC_BUFFER_SIZE 0x2000
|
||||
|
||||
#define IPC_PIPE_NAME_SERVER "IW4x-Server"
|
||||
#define IPC_PIPE_NAME_CLIENT "IW4x-Client"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
class Pipe
|
||||
{
|
||||
public:
|
||||
struct Packet
|
||||
{
|
||||
char command[IPC_COMMAND_SIZE];
|
||||
char buffer[IPC_BUFFER_SIZE];
|
||||
};
|
||||
|
||||
enum Type
|
||||
{
|
||||
IPCTYPE_NONE,
|
||||
IPCTYPE_SERVER,
|
||||
IPCTYPE_CLIENT
|
||||
};
|
||||
|
||||
typedef void(__cdecl PacketCallback)(std::string data);
|
||||
typedef void(__cdecl Callback)();
|
||||
|
||||
Pipe();
|
||||
~Pipe();
|
||||
|
||||
bool connect(std::string name);
|
||||
bool create(std::string name);
|
||||
|
||||
bool write(std::string command, std::string data);
|
||||
void setCallback(std::string command, Utils::Slot<PacketCallback> callback);
|
||||
void onConnect(Callback callback);
|
||||
|
||||
void destroy();
|
||||
|
||||
private:
|
||||
Utils::Slot<void()> connectCallback;
|
||||
std::map<std::string, Utils::Slot<PacketCallback>> packetCallbacks;
|
||||
|
||||
HANDLE pipe;
|
||||
std::thread thread;
|
||||
bool threadAttached;
|
||||
|
||||
Type type;
|
||||
Packet packet;
|
||||
|
||||
char pipeName[MAX_PATH];
|
||||
char pipeFile[MAX_PATH];
|
||||
unsigned int reconnectAttempt;
|
||||
|
||||
void setName(std::string name);
|
||||
|
||||
static void ReceiveThread(Pipe* pipe);
|
||||
};
|
||||
|
||||
class IPCPipe : public Component
|
||||
{
|
||||
public:
|
||||
IPCPipe();
|
||||
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
const char* getName() override { return "IPCPipe"; };
|
||||
#endif
|
||||
|
||||
void preDestroy() override;
|
||||
|
||||
static bool Write(std::string command, std::string data);
|
||||
static void On(std::string command, Utils::Slot<Pipe::PacketCallback> callback);
|
||||
|
||||
private:
|
||||
static Pipe ServerPipe;
|
||||
static Pipe ClientPipe;
|
||||
|
||||
static void ConnectClient();
|
||||
};
|
||||
}
|
@ -244,7 +244,7 @@ namespace Components
|
||||
Game::newMapArena_t* arena = &ArenaLength::NewArenas[i];
|
||||
if (arena->mapName == map)
|
||||
{
|
||||
for (int j = 0; j < ARRAY_SIZE(arena->keys); ++j)
|
||||
for (int j = 0; j < ARRAYSIZE(arena->keys); ++j)
|
||||
{
|
||||
if (arena->keys[j] == "dependency"s)
|
||||
{
|
||||
@ -267,7 +267,7 @@ namespace Components
|
||||
Game::newMapArena_t* arena = &ArenaLength::NewArenas[i];
|
||||
if (arena->mapName == map)
|
||||
{
|
||||
for (int j = 0; j < ARRAY_SIZE(arena->keys); ++j)
|
||||
for (int j = 0; j < ARRAYSIZE(arena->keys); ++j)
|
||||
{
|
||||
if (arena->keys[j] == "allieschar"s)
|
||||
{
|
||||
|
@ -77,7 +77,7 @@ namespace Components
|
||||
header.sectionHeader[Game::SECTION_FIXUP].buffer = allocator.allocateArray<char>(header.sectionHeader[Game::SECTION_FIXUP].size);
|
||||
|
||||
// Load section data
|
||||
for (int i = 0; i < ARRAY_SIZE(header.sectionHeader); ++i)
|
||||
for (int i = 0; i < ARRAYSIZE(header.sectionHeader); ++i)
|
||||
{
|
||||
model.seek(header.sectionHeader[i].offset, FS_SEEK_SET);
|
||||
if (!model.read(header.sectionHeader[i].buffer, header.sectionHeader[i].size))
|
||||
|
@ -53,15 +53,8 @@ namespace Components
|
||||
|
||||
CreateProcessA("updater.exe", nullptr, nullptr, nullptr, false, NULL, nullptr, nullptr, &sInfo, &pInfo);
|
||||
|
||||
if (pInfo.hThread && pInfo.hThread != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CloseHandle(pInfo.hThread);
|
||||
}
|
||||
|
||||
if (pInfo.hProcess && pInfo.hProcess != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CloseHandle(pInfo.hProcess);
|
||||
}
|
||||
if (pInfo.hThread && pInfo.hThread != INVALID_HANDLE_VALUE) CloseHandle(pInfo.hThread);
|
||||
if (pInfo.hProcess && pInfo.hProcess != INVALID_HANDLE_VALUE) CloseHandle(pInfo.hProcess);
|
||||
|
||||
TerminateProcess(GetCurrentProcess(), exitCode);
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ namespace Components
|
||||
{
|
||||
#if(0) // Disabled for now
|
||||
{
|
||||
for (int i = 0; i < ARRAY_SIZE(PlayerName::PlayerNames); ++i)
|
||||
for (int i = 0; i < ARRAYSIZE(PlayerName::PlayerNames); ++i)
|
||||
{
|
||||
PlayerName::PlayerNames[i] = "mumu";
|
||||
}
|
||||
@ -26,7 +26,7 @@ namespace Components
|
||||
|
||||
PlayerName::~PlayerName()
|
||||
{
|
||||
for (int i = 0; i < ARRAY_SIZE(PlayerName::PlayerNames); ++i)
|
||||
for (int i = 0; i < ARRAYSIZE(PlayerName::PlayerNames); ++i)
|
||||
{
|
||||
PlayerName::PlayerNames[i].clear();
|
||||
}
|
||||
|
43
src/Main.cpp
43
src/Main.cpp
@ -20,28 +20,43 @@ namespace Main
|
||||
Main::EntryPointHook.uninstall();
|
||||
|
||||
Main::SetEnvironment();
|
||||
|
||||
Utils::Cryptography::Initialize();
|
||||
Components::Loader::Initialize();
|
||||
|
||||
if(Worker::IsWorker())
|
||||
{
|
||||
Worker::Initialize();
|
||||
}
|
||||
else
|
||||
{
|
||||
Components::Loader::Initialize();
|
||||
|
||||
#if defined(DEBUG) || defined(FORCE_UNIT_TESTS)
|
||||
if (Components::Loader::PerformingUnitTests())
|
||||
{
|
||||
DWORD result = (Components::Loader::PerformUnitTests() ? 0 : -1);
|
||||
Components::Loader::Uninitialize();
|
||||
ExitProcess(result);
|
||||
}
|
||||
if (Components::Loader::PerformingUnitTests())
|
||||
{
|
||||
DWORD result = (Components::Loader::PerformUnitTests() ? 0 : -1);
|
||||
Components::Loader::Uninitialize();
|
||||
ExitProcess(result);
|
||||
}
|
||||
#else
|
||||
if (Components::Flags::HasFlag("tests"))
|
||||
{
|
||||
Components::Logger::Print("Unit tests are disabled outside the debug environment!\n");
|
||||
}
|
||||
if (Components::Flags::HasFlag("tests"))
|
||||
{
|
||||
Components::Logger::Print("Unit tests are disabled outside the debug environment!\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void Uninitialize()
|
||||
{
|
||||
Components::Loader::Uninitialize();
|
||||
if(Worker::IsWorker())
|
||||
{
|
||||
Worker::Uninitialize();
|
||||
}
|
||||
else
|
||||
{
|
||||
Components::Loader::Uninitialize();
|
||||
}
|
||||
|
||||
Utils::Cache::Uninitialize();
|
||||
google::protobuf::ShutdownProtobufLibrary();
|
||||
}
|
||||
@ -51,8 +66,6 @@ BOOL APIENTRY DllMain(HMODULE /*hModule*/, DWORD ul_reason_for_call, LPVOID /*l
|
||||
{
|
||||
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
|
||||
{
|
||||
Steam::Proxy::RunMod();
|
||||
|
||||
// Ensure we're working with our desired binary
|
||||
if (Utils::Hook::Get<DWORD>(0x4C0FFF) != 0x6824748B)
|
||||
{
|
||||
|
9
src/Proto/ipc.proto
Normal file
9
src/Proto/ipc.proto
Normal file
@ -0,0 +1,9 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package Proto.IPC;
|
||||
|
||||
message Command
|
||||
{
|
||||
bytes command = 1;
|
||||
bytes data = 2;
|
||||
}
|
@ -18,6 +18,11 @@
|
||||
#include <d3d9.h>
|
||||
#include <Aclapi.h>
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4996)
|
||||
#include <xutility>
|
||||
#pragma warning(pop)
|
||||
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <cctype>
|
||||
@ -80,10 +85,17 @@ template <size_t S> class Sizer { };
|
||||
#include "proto/auth.pb.h"
|
||||
#include "proto/node.pb.h"
|
||||
#include "proto/rcon.pb.h"
|
||||
#include "proto/ipc.pb.h"
|
||||
|
||||
#pragma warning(pop)
|
||||
|
||||
#define ENABLE_BASE64
|
||||
#ifndef DISABLE_BASE128
|
||||
#define ENABLE_BASE128
|
||||
#endif
|
||||
|
||||
#include "Utils/IO.hpp"
|
||||
#include "Utils/IPC.hpp"
|
||||
#include "Utils/CSV.hpp"
|
||||
#include "Utils/Time.hpp"
|
||||
#include "Utils/Cache.hpp"
|
||||
@ -106,6 +118,7 @@ template <size_t S> class Sizer { };
|
||||
#include "Utils/Stream.hpp"
|
||||
|
||||
#include "Components/Loader.hpp"
|
||||
#include "Worker/Worker.hpp"
|
||||
|
||||
// Libraries
|
||||
#pragma comment(lib, "Winmm.lib")
|
||||
|
@ -5,17 +5,17 @@ namespace Steam
|
||||
::Utils::Library Proxy::Client;
|
||||
::Utils::Library Proxy::Overlay;
|
||||
|
||||
ISteamClient008* Proxy::SteamClient;
|
||||
IClientEngine* Proxy::ClientEngine;
|
||||
IClientUser* Proxy::ClientUser;
|
||||
ISteamClient008* Proxy::SteamClient = nullptr;
|
||||
IClientEngine* Proxy::ClientEngine = nullptr;
|
||||
IClientUser* Proxy::ClientUser = nullptr;
|
||||
|
||||
void* Proxy::SteamPipe;
|
||||
void* Proxy::SteamUser;
|
||||
void* Proxy::SteamPipe = nullptr;
|
||||
void* Proxy::SteamUser = nullptr;
|
||||
|
||||
Friends15* Proxy::SteamFriends;
|
||||
Utils* Proxy::SteamUtils;
|
||||
Friends15* Proxy::SteamFriends = nullptr;
|
||||
Utils* Proxy::SteamUtils = nullptr;
|
||||
|
||||
uint32_t Proxy::AppId;
|
||||
uint32_t Proxy::AppId = 0;
|
||||
|
||||
std::recursive_mutex Proxy::CallMutex;
|
||||
std::vector<Proxy::CallContainer> Proxy::Calls;
|
||||
@ -29,54 +29,15 @@ namespace Steam
|
||||
{
|
||||
Proxy::AppId = appId;
|
||||
|
||||
SetEnvironmentVariableA("SteamAppId", ::Utils::String::VA("%lu", appId));
|
||||
SetEnvironmentVariableA("SteamGameId", ::Utils::String::VA("%llu", appId & 0xFFFFFF));
|
||||
// if (!Components::Flags::HasFlag("nosteam"))
|
||||
// {
|
||||
// SetEnvironmentVariableA("SteamAppId", ::Utils::String::VA("%lu", appId));
|
||||
// SetEnvironmentVariableA("SteamGameId", ::Utils::String::VA("%llu", appId & 0xFFFFFF));
|
||||
//
|
||||
// ::Utils::IO::WriteFile("steam_appid.txt", ::Utils::String::VA("%lu", appId), false);
|
||||
// }
|
||||
|
||||
::Utils::IO::WriteFile("steam_appid.txt", ::Utils::String::VA("%lu", appId), false);
|
||||
}
|
||||
|
||||
void Proxy::SetMod(std::string mod)
|
||||
{
|
||||
#if 0
|
||||
if (!Proxy::ClientUser) return;
|
||||
|
||||
GameID_t gameID;
|
||||
gameID.m_nType = 1; // k_EGameIDTypeGameMod
|
||||
gameID.m_nAppID = Proxy::AppId & 0xFFFFFF;
|
||||
gameID.m_nModID = 0x01010101;
|
||||
|
||||
char ourPath[MAX_PATH] = { 0 };
|
||||
GetModuleFileNameA(GetModuleHandle(nullptr), ourPath, sizeof(ourPath));
|
||||
|
||||
char ourDirectory[MAX_PATH] = { 0 };
|
||||
GetCurrentDirectoryA(sizeof(ourDirectory), ourDirectory);
|
||||
|
||||
char blob[1] = { 0 };
|
||||
std::string cmdline = ::Utils::String::VA("\"%s\" -parentProc %d", ourPath, GetCurrentProcessId());
|
||||
Proxy::ClientUser->SpawnProcess(blob, 0, ourPath, cmdline.data(), 0, ourDirectory, gameID, Proxy::AppId, mod.data(), 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Proxy::RunMod()
|
||||
{
|
||||
char* command = "-parentProc ";
|
||||
char* parentProc = strstr(GetCommandLineA(), command);
|
||||
|
||||
if (parentProc)
|
||||
{
|
||||
parentProc += strlen(command);
|
||||
int pid = atoi(parentProc);
|
||||
|
||||
HANDLE processHandle = OpenProcess(SYNCHRONIZE, FALSE, pid);
|
||||
|
||||
if (processHandle && processHandle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
WaitForSingleObject(processHandle, INFINITE);
|
||||
CloseHandle(processHandle);
|
||||
}
|
||||
|
||||
TerminateProcess(GetCurrentProcess(), 0);
|
||||
}
|
||||
remove("steam_appid.txt");
|
||||
}
|
||||
|
||||
void Proxy::RegisterCall(int32_t callId, uint32_t size, uint64_t call)
|
||||
@ -142,13 +103,13 @@ namespace Steam
|
||||
}
|
||||
|
||||
Proxy::CallbackMsg message;
|
||||
while (Proxy::SteamBGetCallback(Proxy::SteamPipe, &message))
|
||||
while (Proxy::SteamBGetCallback && Proxy::SteamFreeLastCallback && Proxy::SteamBGetCallback(Proxy::SteamPipe, &message))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
Components::Logger::Print("Steam::Proxy: Callback dispatched: %d\n", message.m_iCallback);
|
||||
printf("Callback dispatched: %d\n", message.m_iCallback);
|
||||
#endif
|
||||
|
||||
Steam::Callbacks::RunCallback(message.m_iCallback, message.m_pubParam);
|
||||
//Steam::Callbacks::RunCallback(message.m_iCallback, message.m_pubParam);
|
||||
Proxy::RunCallback(message.m_iCallback, message.m_pubParam);
|
||||
Proxy::SteamFreeLastCallback(Proxy::SteamPipe);
|
||||
}
|
||||
@ -163,7 +124,7 @@ namespace Steam
|
||||
::Utils::Memory::Allocator allocator;
|
||||
|
||||
#ifdef DEBUG
|
||||
Components::Logger::Print("Steam::Proxy: Handling call: %d\n", call.callId);
|
||||
printf("Handling call: %d\n", call.callId);
|
||||
#endif
|
||||
|
||||
call.handled = true;
|
||||
@ -172,7 +133,7 @@ namespace Steam
|
||||
{
|
||||
#ifdef DEBUG
|
||||
auto error = Proxy::SteamUtils->GetAPICallFailureReason(call.call);
|
||||
Components::Logger::Print("Steam::Proxy: API call failed: %X Handle: %llX\n", error, call.call);
|
||||
printf("API call failed: %X Handle: %llX\n", error, call.call);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
@ -185,7 +146,7 @@ namespace Steam
|
||||
{
|
||||
#ifdef DEBUG
|
||||
auto error = Proxy::SteamUtils->GetAPICallFailureReason(call.call);
|
||||
Components::Logger::Print("Steam::Proxy: GetAPICallResult failed: %X Handle: %llX\n", error, call.call);
|
||||
printf("GetAPICallResult failed: %X Handle: %llX\n", error, call.call);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
@ -198,16 +159,19 @@ namespace Steam
|
||||
Proxy::UnregisterCalls();
|
||||
}
|
||||
|
||||
bool Proxy::Inititalize()
|
||||
bool Proxy::Inititalize(bool overlayOnly)
|
||||
{
|
||||
std::string directoy = Proxy::GetSteamDirectory();
|
||||
if (directoy.empty()) return false;
|
||||
|
||||
SetDllDirectoryA(Proxy::GetSteamDirectory().data());
|
||||
|
||||
Proxy::Client = ::Utils::Library(STEAMCLIENT_LIB, false);
|
||||
Proxy::Overlay = ::Utils::Library(GAMEOVERLAY_LIB, false);
|
||||
if (!Proxy::Client.valid() || !Proxy::Overlay.valid()) return false;
|
||||
if (!Proxy::Overlay.valid()) return false;
|
||||
if (overlayOnly) return true;
|
||||
|
||||
Proxy::Client = ::Utils::Library(STEAMCLIENT_LIB, false);
|
||||
if (!Proxy::Client.valid()) return false;
|
||||
|
||||
Proxy::SteamClient = Proxy::Client.get<ISteamClient008*(const char*, int*)>("CreateInterface")("SteamClient008", nullptr);
|
||||
if(!Proxy::SteamClient) return false;
|
||||
|
@ -334,12 +334,10 @@ namespace Steam
|
||||
class Proxy
|
||||
{
|
||||
public:
|
||||
static bool Inititalize();
|
||||
static bool Inititalize(bool overlayOnly = false);
|
||||
static void Uninititalize();
|
||||
|
||||
static void SetGame(uint32_t appId);
|
||||
static void SetMod(std::string mod);
|
||||
static void RunMod();
|
||||
|
||||
//Overlay related proxies
|
||||
static void SetOverlayNotificationPosition(uint32_t eNotificationPosition);
|
||||
|
@ -106,26 +106,12 @@ namespace Steam
|
||||
{
|
||||
bool SteamAPI_Init()
|
||||
{
|
||||
#ifndef DISABLE_STEAM_GAME
|
||||
if (!Components::Flags::HasFlag("nosteam"))
|
||||
{
|
||||
//Proxy::SetGame(10190);
|
||||
}
|
||||
#endif
|
||||
Proxy::SetGame(10190);
|
||||
|
||||
if (!Proxy::Inititalize())
|
||||
if (!Proxy::Inititalize(true))
|
||||
{
|
||||
OutputDebugStringA("Steamproxy not initialized properly");
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef DISABLE_STEAM_GAME
|
||||
if (!Components::Flags::HasFlag("nosteam"))
|
||||
{
|
||||
//Proxy::SetMod("IW4x - Modern Warfare 2");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -143,7 +129,7 @@ namespace Steam
|
||||
void SteamAPI_RunCallbacks()
|
||||
{
|
||||
Callbacks::RunCallbacks();
|
||||
Proxy::RunFrame();
|
||||
//Proxy::RunFrame();
|
||||
}
|
||||
|
||||
void SteamAPI_Shutdown()
|
||||
|
@ -29,7 +29,7 @@ namespace Utils
|
||||
|
||||
if (Cache::ValidUrl.empty())
|
||||
{
|
||||
for (int i = 0; i < ARRAY_SIZE(Cache::Urls); i++)
|
||||
for (int i = 0; i < ARRAYSIZE(Cache::Urls); i++)
|
||||
{
|
||||
std::string result = Utils::WebIO(useragent, Cache::GetUrl(Cache::Urls[i], path)).setTimeout(timeout)->get();
|
||||
|
||||
|
104
src/Utils/IPC.cpp
Normal file
104
src/Utils/IPC.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
#include "STDInclude.hpp"
|
||||
|
||||
namespace Utils
|
||||
{
|
||||
namespace IPC
|
||||
{
|
||||
Channel::Channel(std::string _name, int _queueSize, int _bufferSize, bool _remove) : name(_name), remove(_remove)
|
||||
{
|
||||
if(this->remove) boost::interprocess::message_queue::remove(this->name.data());
|
||||
queue.reset(new boost::interprocess::message_queue(boost::interprocess::open_or_create, this->name.data(), _queueSize, _bufferSize + sizeof(Channel::Header)));
|
||||
}
|
||||
|
||||
Channel::~Channel()
|
||||
{
|
||||
if (this->remove) boost::interprocess::message_queue::remove(this->name.data());
|
||||
}
|
||||
|
||||
bool Channel::receive(std::string* data)
|
||||
{
|
||||
if (!data) return false;
|
||||
data->clear();
|
||||
|
||||
if(this->packet.size() < this->queue->get_max_msg_size())
|
||||
{
|
||||
packet.resize(this->queue->get_max_msg_size());
|
||||
}
|
||||
|
||||
const Channel::Header* header = reinterpret_cast<const Channel::Header*>(packet.data());
|
||||
const char* buffer = reinterpret_cast<const char*>(header + 1);
|
||||
|
||||
unsigned int priority;
|
||||
boost::interprocess::message_queue::size_type recvd_size;
|
||||
|
||||
if (this->queue->try_receive(const_cast<char*>(packet.data()), packet.size(), recvd_size, priority))
|
||||
{
|
||||
if ((recvd_size - sizeof(Channel::Header)) != header->fragmentSize || header->fragmentPart) return false;
|
||||
data->append(buffer, header->fragmentSize);
|
||||
|
||||
if(header->fragmented)
|
||||
{
|
||||
Channel::Header mainHeader = *header;
|
||||
unsigned int part = mainHeader.fragmentPart;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (!this->queue->try_receive(const_cast<char*>(packet.data()), packet.size(), recvd_size, priority)) return false;
|
||||
|
||||
if (header->packetId != mainHeader.packetId || header->totalSize != mainHeader.totalSize || header->fragmentPart != (++part))
|
||||
{
|
||||
data->clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
data->append(buffer, header->fragmentSize);
|
||||
|
||||
if(header->totalSize <= data->size())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Channel::send(std::string data)
|
||||
{
|
||||
const size_t fragmentSize = (this->queue->get_max_msg_size() - sizeof(Channel::Header)) - 1;
|
||||
|
||||
Channel::Header header;
|
||||
header.fragmented = (data.size() + sizeof(Channel::Header)) > this->queue->get_max_msg_size();
|
||||
header.packetId = static_cast<short>(timeGetTime() + rand());;
|
||||
header.totalSize = data.size();
|
||||
|
||||
size_t sentSize = 0;
|
||||
for (unsigned short i = 0; sentSize < data.size(); ++i)
|
||||
{
|
||||
header.fragmentPart = i;
|
||||
header.fragmentSize = std::min(fragmentSize, data.size() - (fragmentSize * i));
|
||||
|
||||
std::string buffer;
|
||||
buffer.append(reinterpret_cast<char*>(&header), sizeof(Channel::Header));
|
||||
buffer.append(data.data() + sentSize, header.fragmentSize);
|
||||
Channel::sendMessage(buffer);
|
||||
|
||||
sentSize += header.fragmentSize;
|
||||
}
|
||||
}
|
||||
|
||||
void Channel::sendMessage(std::string data)
|
||||
{
|
||||
if (data.size() <= this->queue->get_max_msg_size())
|
||||
{
|
||||
while (!this->queue->try_send(data.data(), data.size(), 0))
|
||||
{
|
||||
std::this_thread::sleep_for(100us);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
94
src/Utils/IPC.hpp
Normal file
94
src/Utils/IPC.hpp
Normal file
@ -0,0 +1,94 @@
|
||||
#pragma once
|
||||
|
||||
namespace boost
|
||||
{
|
||||
typedef unsigned long long ulong_long_type;
|
||||
}
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4091)
|
||||
#pragma warning(disable: 4996)
|
||||
#define _SCL_SECURE_NO_WARNINGS
|
||||
|
||||
#ifdef sleep
|
||||
#undef sleep
|
||||
#endif
|
||||
|
||||
//#define BOOST_DISABLE_WIN32
|
||||
#define BOOST_USE_WINDOWS_H
|
||||
#define BOOST_DATE_TIME_NO_LIB
|
||||
#include <boost/interprocess/ipc/message_queue.hpp>
|
||||
|
||||
#undef _SCL_SECURE_NO_WARNINGS
|
||||
#pragma warning(pop)
|
||||
|
||||
namespace Utils
|
||||
{
|
||||
namespace IPC
|
||||
{
|
||||
class Channel
|
||||
{
|
||||
public:
|
||||
Channel(std::string _name, int _queueSize = 100, int _bufferSize = 1024, bool _remove = false);
|
||||
~Channel();
|
||||
|
||||
bool receive(std::string* data);
|
||||
void send(std::string data);
|
||||
|
||||
private:
|
||||
struct Header
|
||||
{
|
||||
bool fragmented;
|
||||
unsigned short packetId;
|
||||
size_t fragmentSize;
|
||||
size_t totalSize;
|
||||
unsigned int fragmentPart;
|
||||
};
|
||||
|
||||
void sendMessage(std::string data);
|
||||
|
||||
bool remove;
|
||||
std::unique_ptr<boost::interprocess::message_queue> queue;
|
||||
std::string packet;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
class BidirectionalChannel
|
||||
{
|
||||
public:
|
||||
BidirectionalChannel(std::string name, bool server, int queueSize = 100, int bufferSize = 1024) : isServer(server),
|
||||
channel1(name, queueSize, bufferSize, server),
|
||||
channel2(name + "2", queueSize, bufferSize, server)
|
||||
{}
|
||||
|
||||
bool receive(std::string* data)
|
||||
{
|
||||
if(this->isServer)
|
||||
{
|
||||
return channel1.receive(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
return channel2.receive(data);
|
||||
}
|
||||
}
|
||||
|
||||
void send(std::string data)
|
||||
{
|
||||
if (this->isServer)
|
||||
{
|
||||
return channel2.send(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
return channel1.send(data);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const bool isServer;
|
||||
Channel channel1;
|
||||
Channel channel2;
|
||||
};
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
#include "STDInclude.hpp"
|
||||
#ifndef DISABLE_BASE128
|
||||
#ifdef ENABLE_BASE128
|
||||
#include "base128.h"
|
||||
#endif
|
||||
|
||||
@ -158,7 +158,7 @@ namespace Utils
|
||||
double bytesPerSecond = (1000.0 / milliseconds) * bytes;
|
||||
|
||||
int i;
|
||||
for (i = 0; bytesPerSecond > 1000 && i < ARRAY_SIZE(sizes); ++i) // 1024 or 1000?
|
||||
for (i = 0; bytesPerSecond > 1000 && i < ARRAYSIZE(sizes); ++i) // 1024 or 1000?
|
||||
{
|
||||
bytesPerSecond /= 1000;
|
||||
}
|
||||
@ -166,6 +166,7 @@ namespace Utils
|
||||
return Utils::String::VA("%.2f %s/s", static_cast<float>(bytesPerSecond), sizes[i]);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_BASE64
|
||||
// Encodes a given string in Base64
|
||||
std::string EncodeBase64(const char* input, const unsigned long inputSize)
|
||||
{
|
||||
@ -182,8 +183,9 @@ namespace Utils
|
||||
{
|
||||
return EncodeBase64(input.data(), input.size());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_BASE128
|
||||
#ifdef ENABLE_BASE128
|
||||
// Encodes a given string in Base128
|
||||
std::string EncodeBase128(const std::string& input)
|
||||
{
|
||||
|
60
src/Worker/Runner.cpp
Normal file
60
src/Worker/Runner.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
#include "STDInclude.hpp"
|
||||
|
||||
namespace Worker
|
||||
{
|
||||
Runner::Runner(int pid) : processId(pid), terminate(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Runner::~Runner()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Runner::run()
|
||||
{
|
||||
HANDLE processHandle = OpenProcess(SYNCHRONIZE, FALSE, this->processId);
|
||||
if (!processHandle || processHandle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
printf("Unable to attach to parent process\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Successfully attached to parent process\n");
|
||||
printf("Starting worker...\n");
|
||||
|
||||
std::thread workerThread(&Runner::worker, this);
|
||||
|
||||
WaitForSingleObject(processHandle, INFINITE);
|
||||
CloseHandle(processHandle);
|
||||
|
||||
printf("Awaiting worker termination...\n");
|
||||
this->terminate = true;
|
||||
if (workerThread.joinable()) workerThread.join();
|
||||
printf("Worker terminated\n");
|
||||
}
|
||||
}
|
||||
|
||||
void Runner::worker()
|
||||
{
|
||||
printf("Worker started\n");
|
||||
Utils::IPC::BidirectionalChannel channel("IW4x-Worker-Channel", !Worker::IsWorker());
|
||||
|
||||
while (!this->terminate)
|
||||
{
|
||||
Steam::Proxy::RunFrame();
|
||||
|
||||
std::string buffer;
|
||||
if (channel.receive(&buffer))
|
||||
{
|
||||
printf("Data received: %s\n", buffer.data());
|
||||
channel.send("OK " + buffer);
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(1ms);
|
||||
}
|
||||
|
||||
printf("Terminating worker\n");
|
||||
}
|
||||
}
|
19
src/Worker/Runner.hpp
Normal file
19
src/Worker/Runner.hpp
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
namespace Worker
|
||||
{
|
||||
class Runner
|
||||
{
|
||||
public:
|
||||
Runner(int pid);
|
||||
~Runner();
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
void worker();
|
||||
|
||||
int processId;
|
||||
bool terminate;
|
||||
};
|
||||
}
|
65
src/Worker/Worker.cpp
Normal file
65
src/Worker/Worker.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
#include "STDInclude.hpp"
|
||||
|
||||
namespace Worker
|
||||
{
|
||||
int ProcessId;
|
||||
|
||||
int __stdcall EntryPoint(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, char* /*lpCmdLine*/, int /*nCmdShow*/)
|
||||
{
|
||||
Runner runner(Worker::ProcessId);
|
||||
runner.run();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
if(!Steam::Proxy::Inititalize())
|
||||
{
|
||||
printf("Failed to initialize worker!\n");
|
||||
ExitProcess(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
SetConsoleTitleA("IW4x Worker");
|
||||
#else
|
||||
FreeConsole();
|
||||
#endif
|
||||
|
||||
Utils::Hook(0x6BABA1, Worker::EntryPoint, HOOK_CALL).install()->quick();
|
||||
}
|
||||
}
|
||||
|
||||
void Uninitialize()
|
||||
{
|
||||
Steam::Proxy::Uninititalize();
|
||||
}
|
||||
|
||||
bool ParseWorkerFlag()
|
||||
{
|
||||
char* command = "-parent ";
|
||||
char* parentProc = strstr(GetCommandLineA(), command);
|
||||
|
||||
if (parentProc)
|
||||
{
|
||||
parentProc += strlen(command);
|
||||
Worker::ProcessId = atoi(parentProc);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsWorker()
|
||||
{
|
||||
static Utils::Value<bool> flag;
|
||||
|
||||
if (!flag.isValid())
|
||||
{
|
||||
flag.set(Worker::ParseWorkerFlag());
|
||||
}
|
||||
|
||||
return flag.get();
|
||||
}
|
||||
}
|
11
src/Worker/Worker.hpp
Normal file
11
src/Worker/Worker.hpp
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
namespace Worker
|
||||
{
|
||||
void Initialize();
|
||||
void Uninitialize();
|
||||
|
||||
bool IsWorker();
|
||||
}
|
||||
|
||||
#include "Runner.hpp"
|
Loading…
Reference in New Issue
Block a user