Merge pull request #1812 from alliedmodders/revert-pbproxy

Revert "Introduce a pbproxy library to solve macOS linker issues."
This commit is contained in:
David Anderson 2022-07-31 11:50:56 -07:00 committed by GitHub
commit da3e868df5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 100 additions and 581 deletions

View File

@ -627,7 +627,25 @@ class SMConfig(object):
if compiler.target.platform == 'linux':
if sdk.name in ['csgo', 'blade']:
compiler.linkflags.remove('-static-libstdc++')
compiler.linkflags += ['-lstdc++']
compiler.defines += ['_GLIBCXX_USE_CXX11_ABI=0']
elif compiler.target.platform == 'mac':
if sdk.name in ['csgo']:
# Switch libc++ to libstdc++ for protobuf linkage.
compiler.cxxflags.remove('-stdlib=libc++')
compiler.linkflags.remove('-stdlib=libc++')
compiler.linkflags.remove('-lc++')
compiler.cxxflags += ['-stdlib=libstdc++']
compiler.linkflags += ['-stdlib=libstdc++']
compiler.linkflags += ['-lstdc++']
if 'c++1y' in compiler.cxxflags:
compiler.cxxflags.remove('-std=c++1y')
compiler.cxxflags += ['-std=c++11']
elif 'c++14' in compiler.cxxflags:
compiler.cxxflags.remove('-std=c++14')
compiler.cxxflags += ['-std=c++11']
for path in paths:
compiler.cxxincludes += [os.path.join(sdk.path, *path)]

View File

@ -4,43 +4,42 @@ import os
project = builder.LibraryProject('sourcemod')
project.sources += [
'MenuStyle_Valve.cpp',
'logic_bridge.cpp',
'smn_entities.cpp',
'sm_stringutil.cpp',
'MenuVoting.cpp',
'smn_events.cpp',
'frame_hooks.cpp',
'smn_nextmap.cpp',
'sourcemm_api.cpp',
'ChatTriggers.cpp',
'smn_player.cpp',
'sourcemod.cpp',
'concmd_cleaner.cpp',
'HalfLife2.cpp',
'NextMap.cpp',
'ConCmdManager.cpp',
'ConVarManager.cpp',
'ConsoleDetours.cpp',
'CoreConfig.cpp',
'EventManager.cpp',
'GameHooks.cpp',
'HalfLife2.cpp',
'Logger.cpp',
'MenuManager.cpp',
'MenuStyle_Base.cpp',
'MenuStyle_Radio.cpp',
'MenuStyle_Valve.cpp',
'MenuVoting.cpp',
'NextMap.cpp',
'PlayerManager.cpp',
'TimerSys.cpp',
'UserMessages.cpp',
'concmd_cleaner.cpp',
'frame_hooks.cpp',
'logic_bridge.cpp',
'pb_handle.cpp',
'sm_autonatives.cpp',
'sm_stringutil.cpp',
'smn_commandline.cpp',
'smn_console.cpp',
'smn_entities.cpp',
'smn_events.cpp',
'CoreConfig.cpp',
'Logger.cpp',
'smn_halflife.cpp',
'smn_console.cpp',
'UserMessages.cpp',
'MenuManager.cpp',
'smn_hudtext.cpp',
'smn_keyvalues.cpp',
'smn_nextmap.cpp',
'smn_player.cpp',
'smn_usermsgs.cpp',
'MenuStyle_Base.cpp',
'smn_keyvalues.cpp',
'smn_vector.cpp',
'sourcemm_api.cpp',
'sourcemod.cpp',
'EventManager.cpp',
'MenuStyle_Radio.cpp',
'sm_autonatives.cpp',
'ConsoleDetours.cpp',
'smn_commandline.cpp',
'GameHooks.cpp',
]
for sdk_name in SM.sdks:
@ -59,20 +58,18 @@ for sdk_name in SM.sdks:
builder.sourcePath
]
pb_includes = []
if sdk.name == 'csgo':
pb_includes = [
compiler.cxxincludes += [
os.path.join(sdk.path, 'common', 'protobuf-2.5.0', 'src'),
os.path.join(sdk.path, 'public', 'engine', 'protobuf'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf')
]
elif sdk.name == 'blade':
pb_includes = [
compiler.cxxincludes += [
os.path.join(sdk.path, 'common', 'protobuf-2.5.0', 'src'),
os.path.join(sdk.path, 'public', 'engine', 'protobuf'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'berimbau', 'protobuf')
]
compiler.cxxincludes += pb_includes
if compiler.like('msvc'):
compiler.defines += ['_ALLOW_KEYWORD_MACROS']
@ -88,9 +85,9 @@ for sdk_name in SM.sdks:
compiler.linkflags += ['-Wl,--exclude-libs=libprotobuf.a']
elif compiler.target.platform == 'mac':
if compiler.target.arch == 'x86':
lib_path = os.path.join(sdk.path, 'lib', 'osx32', 'release', 'libprotobuf-libcxx.a')
lib_path = os.path.join(sdk.path, 'lib', 'osx32', 'release', 'libprotobuf.a')
elif compiler.target.arch == 'x86_64':
lib_path = os.path.join(sdk.path, 'lib', 'osx64', 'release', 'libprotobuf-libcxx.a')
lib_path = os.path.join(sdk.path, 'lib', 'osx64', 'release', 'libprotobuf.a')
elif compiler.target.platform == 'windows':
msvc_ver = compiler.version
vs_year = ''
@ -121,53 +118,18 @@ for sdk_name in SM.sdks:
'vprof_tool.cpp',
]
pb_sources = []
if sdk.name == 'csgo':
pb_sources = [
binary.sources += [
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'netmessages.pb.cc'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessages.pb.cc'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'csgo', 'protobuf', 'cstrike15_usermessage_helpers.cpp'),
]
elif sdk.name == 'blade':
pb_sources = [
binary.sources += [
os.path.join(sdk.path, 'public', 'engine', 'protobuf', 'netmessages.pb.cc'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'berimbau', 'protobuf', 'berimbau_usermessages.pb.cc'),
os.path.join(sdk.path, 'public', 'game', 'shared', 'berimbau', 'protobuf', 'berimbau_usermessage_helpers.cpp'),
]
if len(pb_sources):
binary.sources += pb_sources
binary.compiler.cxxdefines += ['PROTOBUF_ENABLE']
if cxx.target.platform == 'mac' and sdk.name in ['csgo']:
# We need a proxy library since the game uses libstdc++.
pb_binary = SM.HL2Library(builder, cxx, 'pbproxy.' + sdk.ext, sdk)
pb_binary.sources += pb_sources
pb_binary.sources += ['pb_proxy.cpp']
pb_binary.compiler.cxxincludes += pb_includes
# Switch from libc++ to libstdc++.
pb_binary.compiler.cxxflags.remove('-stdlib=libc++')
pb_binary.compiler.linkflags.remove('-lc++')
pb_binary.compiler.linkflags.remove('-stdlib=libc++')
pb_binary.compiler.cxxflags.append('-stdlib=libstdc++')
pb_binary.compiler.linkflags.append('-lstdc++')
pb_binary.compiler.linkflags.append('-stdlib=libstdc++')
if '-std=c++1y' in pb_binary.compiler.cxxflags:
pb_binary.compiler.cxxflags.remove('-std=c++1y')
elif '-std=c++14' in pb_binary.compiler.cxxflags:
pb_binary.compiler.cxxflags.remove('-std=c++14')
if cxx.target.arch == 'x86':
pb_lib_path = os.path.join(sdk.path, 'lib', 'osx32', 'release', 'libprotobuf.a')
elif cxx.target.arch == 'x86_64':
pb_lib_path = os.path.join(sdk.path, 'lib', 'osx64', 'release', 'libprotobuf.a')
pb_binary.compiler.linkflags.append(pb_lib_path)
SM.binaries += [builder.Add(pb_binary)]
binary.compiler.cxxdefines += [
'PROTOBUF_PROXY_ENABLE',
'PROTOBUF_PROXY_BINARY_NAME="pbproxy.{}"'.format(sdk.ext),
]
SM.binaries += builder.Add(project)

View File

@ -42,10 +42,6 @@
UserMessages g_UserMsgs;
#ifdef USE_PROTOBUF_USERMESSAGES
const protobuf::Message *GetMessagePrototype(int msg_type);
#endif
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
SH_DECL_HOOK3_void(IVEngineServer, SendUserMessage, SH_NOATTRIB, 0, IRecipientFilter &, int, const protobuf::Message &);
#else
@ -62,7 +58,7 @@ UserMessages::UserMessages()
: m_InterceptBuffer(m_pBase, 2500)
{
#else
: m_InterceptBuffer(nullptr)
: m_InterceptBuffer(NULL)
{
#endif
m_HookCount = 0;
@ -237,7 +233,7 @@ google::protobuf::Message *UserMessages::StartProtobufMessage(int msg_id, const
#ifndef USE_PROTOBUF_USERMESSAGES
return NULL;
#else
PbHandle buffer;
protobuf::Message *buffer;
if (m_InExec || m_InHook)
{
@ -266,9 +262,8 @@ google::protobuf::Message *UserMessages::StartProtobufMessage(int msg_id, const
if (m_CurFlags & USERMSG_BLOCKHOOKS)
{
// direct message creation, return buffer "from engine". keep track
m_FakeEngineBuffer =
PbHandle(GetMessagePrototype(msg_id)->New(), PbHandle::Owned, PbHandle::Local);
buffer = m_FakeEngineBuffer.AsUnowned();
m_FakeEngineBuffer = GetMessagePrototype(msg_id)->New();
buffer = m_FakeEngineBuffer;
} else {
char messageName[32];
if (!GetMessageName(msg_id, messageName, sizeof(messageName)))
@ -277,30 +272,27 @@ google::protobuf::Message *UserMessages::StartProtobufMessage(int msg_id, const
return NULL;
}
// The message returned here should always local.
auto msg = OnStartMessage_Pre(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, messageName);
protobuf::Message *msg = OnStartMessage_Pre(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, messageName);
switch (m_FakeMetaRes)
{
case MRES_IGNORED:
case MRES_HANDLED:
m_FakeEngineBuffer =
PbHandle(GetMessagePrototype(msg_id)->New(), PbHandle::Owned, PbHandle::Local);
buffer = m_FakeEngineBuffer.AsUnowned();
m_FakeEngineBuffer = GetMessagePrototype(msg_id)->New();
buffer = m_FakeEngineBuffer;
break;
case MRES_OVERRIDE:
m_FakeEngineBuffer =
PbHandle(GetMessagePrototype(msg_id)->New(), PbHandle::Owned, PbHandle::Local);
m_FakeEngineBuffer = GetMessagePrototype(msg_id)->New();
// fallthrough
case MRES_SUPERCEDE:
buffer = std::move(msg);
buffer = msg;
break;
}
OnStartMessage_Post(static_cast<IRecipientFilter *>(&m_CellRecFilter), msg_id, messageName);
}
assert(!buffer.is_owned());
return buffer.GetLocalMessage();
return buffer;
#endif // USE_PROTOBUF_USERMESSAGES
}
@ -312,12 +304,11 @@ bool UserMessages::EndMessage()
}
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
PbHandle localBuffer = std::move(m_FakeEngineBuffer);
if (m_CurFlags & USERMSG_BLOCKHOOKS)
{
PbHandle priv = localBuffer.ToPrivate(m_CurId);
ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(m_CellRecFilter), m_CurId,
*priv.GetPrivateMessage());
ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(m_CellRecFilter), m_CurId, *m_FakeEngineBuffer);
delete m_FakeEngineBuffer;
m_FakeEngineBuffer = NULL;
} else {
OnMessageEnd_Pre();
@ -326,12 +317,10 @@ bool UserMessages::EndMessage()
case MRES_IGNORED:
case MRES_HANDLED:
case MRES_OVERRIDE:
{
PbHandle priv = localBuffer.ToPrivate(m_CurId);
engine->SendUserMessage(static_cast<IRecipientFilter &>(m_CellRecFilter), m_CurId,
*priv.GetPrivateMessage());
engine->SendUserMessage(static_cast<IRecipientFilter &>(m_CellRecFilter), m_CurId, *m_FakeEngineBuffer);
delete m_FakeEngineBuffer;
m_FakeEngineBuffer = NULL;
break;
}
//case MRES_SUPERCEDE:
}
@ -451,7 +440,7 @@ bool UserMessages::InternalHook(int msg_id, IBitBufUserMessageListener *pListene
}
#ifdef USE_PROTOBUF_USERMESSAGES
const protobuf::Message *GetMessagePrototype(int msg_type)
const protobuf::Message *UserMessages::GetMessagePrototype(int msg_type)
{
#if SOURCE_ENGINE == SE_CSGO
return g_Cstrike15UsermessageHelpers.GetPrototype(msg_type);
@ -538,8 +527,7 @@ void UserMessages::OnSendUserMessage_Pre(IRecipientFilter &filter, int msg_type,
}
else
{
m_FakeEngineBuffer =
PbHandle(&const_cast<protobuf::Message &>(msg), PbHandle::Unowned, PbHandle::Private);
m_FakeEngineBuffer = &const_cast<protobuf::Message &>(msg);
}
OnStartMessage_Post(&filter, msg_type, pszName);
@ -575,7 +563,7 @@ void UserMessages::OnSendUserMessage_Post(IRecipientFilter &filter, int msg_type
#endif
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
PbHandle UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name)
protobuf::Message *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name)
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name)
#else
@ -589,7 +577,7 @@ bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_typ
|| (m_InExec && (m_CurFlags & USERMSG_BLOCKHOOKS)))
{
m_InHook = false;
UM_RETURN_META_VALUE(MRES_IGNORED, nullptr);
UM_RETURN_META_VALUE(MRES_IGNORED, NULL);
}
m_CurId = msg_type;
@ -600,20 +588,22 @@ bf_write *UserMessages::OnStartMessage_Pre(IRecipientFilter *filter, int msg_typ
if (!is_intercept_empty)
{
#ifdef USE_PROTOBUF_USERMESSAGES
m_InterceptBuffer =
PbHandle(GetMessagePrototype(msg_type)->New(), PbHandle::Owned, PbHandle::Local);
UM_RETURN_META_VALUE(MRES_SUPERCEDE, m_InterceptBuffer.AsUnowned());
if (m_InterceptBuffer)
delete m_InterceptBuffer;
m_InterceptBuffer = GetMessagePrototype(msg_type)->New();
UM_RETURN_META_VALUE(MRES_SUPERCEDE, m_InterceptBuffer);
#else
m_InterceptBuffer.Reset();
UM_RETURN_META_VALUE(MRES_SUPERCEDE, &m_InterceptBuffer);
#endif
}
UM_RETURN_META_VALUE(MRES_IGNORED, nullptr);
UM_RETURN_META_VALUE(MRES_IGNORED, NULL);
}
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
void* UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name)
protobuf::Message *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name)
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name)
#else
@ -627,9 +617,9 @@ bf_write *UserMessages::OnStartMessage_Post(IRecipientFilter *filter, int msg_ty
#ifdef USE_PROTOBUF_USERMESSAGES
if (m_FakeMetaRes == MRES_SUPERCEDE)
m_OrigBuffer = m_InterceptBuffer.AsUnowned();
m_OrigBuffer = m_InterceptBuffer;
else
m_OrigBuffer = m_FakeEngineBuffer.AsUnowned();
m_OrigBuffer = m_FakeEngineBuffer;
#else
m_OrigBuffer = META_RESULT_ORIG_RET(bf_write *);
#endif
@ -725,11 +715,8 @@ void UserMessages::OnMessageEnd_Pre()
{
pInfo = (*iter);
pInfo->IsHooked = true;
#ifdef USE_PROTOBUF_USERMESSAGES
PbHandle local = m_InterceptBuffer.ToLocal(m_CurId);
res = pInfo->Callback->InterceptUserMessage(m_CurId, local.GetLocalMessage(), m_CurRecFilter);
m_InterceptBuffer.CopyFrom(local);
res = pInfo->Callback->InterceptUserMessage(m_CurId, m_InterceptBuffer, m_CurRecFilter);
#else
res = pInfo->Callback->InterceptUserMessage(m_CurId, &m_InterceptBuffer, m_CurRecFilter);
#endif
@ -781,8 +768,7 @@ void UserMessages::OnMessageEnd_Pre()
if (!handled && intercepted)
{
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
PbHandle priv = m_InterceptBuffer.ToPrivate(m_CurId);
ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(*m_CurRecFilter), m_CurId, *priv.GetPrivateMessage());
ENGINE_CALL(SendUserMessage)(static_cast<IRecipientFilter &>(*m_CurRecFilter), m_CurId, *m_InterceptBuffer);
#else
bf_write *engine_bfw;
#if SOURCE_ENGINE >= SE_LEFT4DEAD
@ -798,9 +784,12 @@ void UserMessages::OnMessageEnd_Pre()
{
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
PbHandle tmp_msg(GetMessagePrototype(m_CurId)->New(), PbHandle::Owned, PbHandle::Local);
tmp_msg.CopyFrom(m_OrigBuffer);
auto pTempMsg = tmp_msg.GetLocalMessage();
int size = m_OrigBuffer->ByteSize();
uint8 *data = (uint8 *)stackalloc(size);
m_OrigBuffer->SerializePartialToArray(data, size);
protobuf::Message *pTempMsg = GetMessagePrototype(m_CurId)->New();
pTempMsg->ParsePartialFromArray(data, size);
#else
bf_write *pTempMsg = m_OrigBuffer;
#endif
@ -823,6 +812,10 @@ void UserMessages::OnMessageEnd_Pre()
pInfo->IsHooked = false;
iter++;
}
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
delete pTempMsg;
#endif
}
UM_RETURN_META((intercepted) ? MRES_SUPERCEDE : MRES_IGNORED);

View File

@ -52,7 +52,6 @@ using namespace SourceMod;
#include <google/protobuf/message.h>
#include <google/protobuf/descriptor.h>
#include <netmessages.pb.h>
#include "pb_handle.h"
using namespace google;
#else
@ -109,8 +108,8 @@ public:
#endif
#if SOURCE_ENGINE == SE_CSGO || SOURCE_ENGINE == SE_BLADE
PbHandle OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name);
void* OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name);
protobuf::Message *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name);
protobuf::Message *OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name);
#elif SOURCE_ENGINE >= SE_LEFT4DEAD
bf_write *OnStartMessage_Pre(IRecipientFilter *filter, int msg_type, const char *msg_name);
bf_write *OnStartMessage_Post(IRecipientFilter *filter, int msg_type, const char *msg_name);
@ -122,6 +121,7 @@ public:
void OnMessageEnd_Post();
private:
#ifdef USE_PROTOBUF_USERMESSAGES
const protobuf::Message *GetMessagePrototype(int msg_type);
bool InternalHook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew);
bool InternalUnhook(int msg_id, IProtobufUserMessageListener *pListener, bool intercept, bool isNew);
#else
@ -141,11 +141,11 @@ private:
bf_read m_ReadBuffer;
#else
// The engine used to provide this. Now we track it.
PbHandle m_OrigBuffer;
PbHandle m_FakeEngineBuffer;
protobuf::Message *m_OrigBuffer;
protobuf::Message *m_FakeEngineBuffer;
META_RES m_FakeMetaRes;
PbHandle m_InterceptBuffer;
protobuf::Message *m_InterceptBuffer;
#endif
size_t m_HookCount;
bool m_InHook;

View File

@ -51,9 +51,6 @@
#include <bridge/include/IVEngineServerBridge.h>
#include <bridge/include/IPlayerInfoBridge.h>
#include <bridge/include/IFileSystemBridge.h>
#if PROTOBUF_PROXY_ENABLE
# include "pb_handle.h"
#endif
sm_logic_t logicore;
@ -657,41 +654,6 @@ void CoreProviderImpl::InitializeBridge()
rootmenu = logicore.rootmenu;
}
bool CoreProviderImpl::LoadProtobufProxy(char *error, size_t maxlength)
{
#if !defined(PROTOBUF_PROXY_ENABLE)
return false;
#else
char file[PLATFORM_MAX_PATH];
#if !defined(PROTOBUF_PROXY_BINARY_NAME)
# error "No engine suffix defined"
#endif
/* Now it's time to load the logic binary */
g_SMAPI->PathFormat(file,
sizeof(file),
"%s/bin/" PLATFORM_ARCH_FOLDER PROTOBUF_PROXY_BINARY_NAME PLATFORM_LIB_EXT,
g_SourceMod.GetSourceModPath());
char myerror[255];
pbproxy_ = ke::SharedLib::Open(file, myerror, sizeof(myerror));
if (!pbproxy_) {
ke::SafeSprintf(error, maxlength, "failed to load %s: %s", file, myerror);
return false;
}
auto fn = pbproxy_->get<GetProtobufProxyFn>("GetProtobufProxy");
if (!fn) {
ke::SafeStrcpy(error, maxlength, "could not find GetProtobufProxy function");
return false;
}
gProtobufProxy = fn();
return true;
#endif
}
bool CoreProviderImpl::LoadBridge(char *error, size_t maxlength)
{
char file[PLATFORM_MAX_PATH];

View File

@ -1,35 +0,0 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod
* Copyright (C) 2020 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#include "pb_handle.h"
#if defined PROTOBUF_PROXY_ENABLE
IProtobufProxy* gProtobufProxy = nullptr;
#endif

View File

@ -1,217 +0,0 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod
* Copyright (C) 2020 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#pragma once
#if defined(PROTOBUF_ENABLE)
#include <google/protobuf/message.h>
#if defined(PROTOBUF_PROXY_ENABLE)
# include "pb_proxy.h"
extern IProtobufProxy* gProtobufProxy;
#endif
const google::protobuf::Message *GetMessagePrototype(int msg_type);
// On SDKs which use protobufs, the engine has objects compiled against a specific
// version of protobuf. Normally this is fine, we take care on Linux to use the
// same C++ ABI. On macOS however, we use libc++ to enable C++11 functionality,
// whereas the protobuf library has been compiled with libstc++. These ABIs are
// not compatible.
//
// To address the problem, we introduce PbHandle. PbHandle is a wrapper around
// protobuf::Message with two added pieces of state: whether or not the handle
// "owns" the message (and can free it in its destructor), and whether or not
// the handle was created by the engine (private) or created by SourceMod
// (local).
//
// Whenever we transfer a protobuf::Message pointer to SourceMod, we must take
// care to convert it to a Local version first. Whenever we transfer a protobuf
// pointer to the engine, we must convert it to a Private handle.
//
// For platforms with no ABI differences (almost all of them), the handle is a
// no-op. The private and local localities are compatible and no translation
// takes place.
//
// On macOS, CS:GO does require translation. SourceMod loads a tiny shim
// library that contains a copy of the protobuf sources compiled against the
// game's ABI. It then provides serialization and deserialization methods.
// SourceMod must not interact with the game's protobuf objects without first
// going through this proxy library.
//
// Note that PbHandle is not quite like unique_ptr_. It can be converted into a
// PbHandle that does not destroy the underlying object. This is mainly because
// UserMessages.cpp has rather complex state, so it is useful to track locality
// without destroying an object. An unowned PbHandle must not outlive the
// owning PbHandle.
class PbHandle
{
public:
enum Ownership {
Owned,
Unowned,
};
enum Locality {
Local,
Private,
};
PbHandle() : msg_(nullptr) {}
PbHandle(decltype(nullptr)) : msg_(nullptr) {}
PbHandle(google::protobuf::Message* msg, Ownership ownership, Locality locality)
: msg_(msg),
ownership_(ownership),
locality_(locality)
{}
PbHandle(PbHandle&& other)
: msg_(other.msg_),
ownership_(other.ownership_),
locality_(other.locality_)
{
other.msg_ = nullptr;
}
PbHandle(const PbHandle&) = delete;
~PbHandle() {
maybe_free();
}
PbHandle& operator =(PbHandle&& other) {
if (other.msg_ != msg_)
maybe_free();
msg_ = other.msg_;
ownership_ = other.ownership_;
locality_ = other.locality_;
other.msg_ = nullptr;
return *this;
}
PbHandle& operator =(const PbHandle&) = delete;
google::protobuf::Message* operator ->() const { return msg_; }
google::protobuf::Message* GetLocalMessage() {
assert(locality_ == Local);
return msg_;
}
google::protobuf::Message* GetPrivateMessage() {
assert(locality_ == Private);
return msg_;
}
PbHandle ToLocal(int msg_type) {
if (locality_ == Local)
return AsUnowned();
#if defined(PROTOBUF_PROXY_ENABLE)
PbHandle local(GetMessagePrototype(msg_type)->New(), Owned, Local);
local.CopyFromPrivate(msg_);
return local;
#else
return PbHandle(msg_, Unowned, Local);
#endif
}
PbHandle ToPrivate(int msg_type) {
if (locality_ == Private)
return AsUnowned();
#if defined(PROTOBUF_PROXY_ENABLE)
PbHandle priv(gProtobufProxy->NewPrototype(msg_type), Owned, Private);
priv.CopyFromLocal(msg_);
return priv;
#else
return PbHandle(msg_, Unowned, Private);
#endif
}
void CopyFrom(const PbHandle& other) {
if (other.msg_ == msg_) {
assert(other.locality_ == locality_);
return;
}
#if defined(PROTOBUF_PROXY_ENABLE)
if (other.locality_ == Local)
CopyFromLocal(other.msg_);
else if (other.locality_ == Private)
CopyFromPrivate(other.msg_);
#else
msg_->CopyFrom(*other.msg_);
#endif
}
PbHandle AsUnowned() {
return PbHandle(msg_, Unowned, locality_);
}
bool is_owned() const { return ownership_ == Owned; }
bool is_local() const { return locality_ == Local; }
private:
#if defined(PROTOBUF_PROXY_ENABLE)
void CopyFromPrivate(google::protobuf::Message* message) {
void* out;
size_t len;
if (!gProtobufProxy->Serialize(message, &out, &len))
return;
if (locality_ == Local)
msg_->ParsePartialFromArray(out, len);
else
gProtobufProxy->Deserialize(out, len, msg_);
gProtobufProxy->FreeBuffer(out);
}
void CopyFromLocal(google::protobuf::Message* message) {
if (locality_ == Local) {
msg_->CopyFrom(*message);
} else {
auto data = message->SerializePartialAsString();
gProtobufProxy->Deserialize(data.data(), data.size(), msg_);
}
}
#endif
void maybe_free() {
if (ownership_ != Owned)
return;
#if defined(PROTOBUF_PROXY_ENABLE)
if (locality_ == Private) {
gProtobufProxy->FreeMessage(msg_);
return;
}
#endif
delete msg_;
}
private:
google::protobuf::Message* msg_ = nullptr;
Ownership ownership_ = Unowned;
Locality locality_ = Local;
};
#endif // PROTOBUF_ENABLE

View File

@ -1,104 +0,0 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod
* Copyright (C) 2020 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#include "pb_proxy.h"
#include <stdlib.h>
#include <sm_platform.h>
#if SOURCE_ENGINE == SE_CSGO
# include <cstrike15_usermessage_helpers.h>
#elif SOURCE_ENGINE == SE_BLADE
# include <berimbau_usermessages.pb.h>
#else
# error "No source engine compatibility"
#endif
class ProtobufProxy : public IProtobufProxy
{
public:
bool Serialize(const google::protobuf::Message* message, void** out, size_t* len);
void FreeBuffer(void* data);
bool Deserialize(const void* buffer, size_t len, google::protobuf::Message* message);
google::protobuf::Message* NewPrototype(int msg_type);
void FreeMessage(google::protobuf::Message* message);
};
static ProtobufProxy sProtobufProxy;
PLATFORM_EXTERN_C IProtobufProxy*
GetProtobufProxy()
{
return &sProtobufProxy;
}
bool
ProtobufProxy::Serialize(const google::protobuf::Message* message, void** out, size_t* len)
{
*len = message->ByteSize();
*out = malloc(*len);
if (!*out)
return false;
if (!message->SerializePartialToArray(*out, *len)) {
free(*out);
return false;
}
return true;
}
void
ProtobufProxy::FreeBuffer(void* data)
{
free(data);
}
bool
ProtobufProxy::Deserialize(const void* buffer, size_t len, google::protobuf::Message* message)
{
return message->ParsePartialFromArray(buffer, len);
}
google::protobuf::Message*
ProtobufProxy::NewPrototype(int msg_type)
{
#if SOURCE_ENGINE == SE_CSGO
return g_Cstrike15UsermessageHelpers.GetPrototype(msg_type)->New();
#elif SOURCE_ENGINE == SE_BLADE
return g_BerimbauUsermessageHelpers.GetPrototype(msg_type)->New();
#else
# error "No source engine compatibility."
#endif
}
void
ProtobufProxy::FreeMessage(google::protobuf::Message* message)
{
delete message;
}

View File

@ -1,58 +0,0 @@
/**
* vim: set ts=4 sw=4 tw=99 noet :
* =============================================================================
* SourceMod
* Copyright (C) 2020 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#pragma once
#include <google/protobuf/message.h>
class IProtobufProxy
{
public:
// Serialize the given message into a buffer. The buffer and its length are placed in |out|.
// The buffer must be freed with FreeBuffer.
virtual bool Serialize(const google::protobuf::Message* message, void** out, size_t* len) = 0;
virtual void FreeBuffer(void* data) = 0;
// Deserialize the given buffer into a message.
virtual bool Deserialize(const void* buffer, size_t len, google::protobuf::Message* message) = 0;
// Allocate/free a prototype.
virtual google::protobuf::Message* NewPrototype(int msg_type) = 0;
virtual void FreeMessage(google::protobuf::Message* message) = 0;
bool Serialize(const google::protobuf::Message& message, void** out, size_t* len) {
return Serialize(&message, out, len);
}
bool Deserialize(const void* buffer, size_t len, google::protobuf::Message& message) {
return Deserialize(buffer, len, &message);
}
};
typedef IProtobufProxy*(*GetProtobufProxyFn)();

View File

@ -38,7 +38,6 @@ public:
// Local functions.
void InitializeBridge();
bool LoadProtobufProxy(char *error, size_t maxlength);
bool LoadBridge(char *error, size_t maxlength);
void ShutdownBridge();
@ -77,7 +76,6 @@ public:
}
private:
ke::RefPtr<ke::SharedLib> pbproxy_;
ke::RefPtr<ke::SharedLib> logic_;
LogicInitFunction logic_init_;
GameHooks hooks_;