Merge pull request #119 from Mauler125/LiveAPI

LiveAPI implementation
This commit is contained in:
Kawe Mazidjatari 2024-04-05 15:24:42 +02:00 committed by GitHub
commit 49d7394f30
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
575 changed files with 284073 additions and 3055 deletions

View File

@ -580,6 +580,123 @@ Mbed TLS & l8w8jwt
// limitations under the License.
////////////////////////////////////////////////////////////////////////////
************************************************************************************
DirtySDK (EA WebKit)
************************************************************************************
// Copyright (C) 1999-2007, 2009-2010, 2012-2013 Electronic Arts Inc
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
////////////////////////////////////////////////////////////////////////////
************************************************************************************
EAThread (EA WebKit)
************************************************************************************
//--------------------------------------------------------------------------
// Copyright (C) 2017 Electronic Arts Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//--------------------------------------------------------------------------
//
// Additional licenses also apply to this software package as detailed below.
//
//--------------------------------------------------------------------------
// Copyright (c) 2015 Jeff Preshing
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgement in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
//--------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////
************************************************************************************
EABase (EA WebKit)
************************************************************************************
// Copyright (C) 2002-2013 Electronic Arts Inc
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
////////////////////////////////////////////////////////////////////////////
************************************************************************************
Zstandard
************************************************************************************

View File

@ -46,6 +46,10 @@ add_subdirectory( thirdparty/cppnet )
set( FOLDER_CONTEXT "Thirdparty/Networking" )
add_subdirectory( thirdparty/protobuf )
add_subdirectory( thirdparty/curl )
add_subdirectory( thirdparty/dirtysdk )
set( FOLDER_CONTEXT "Thirdparty/Threading" )
add_subdirectory( thirdparty/ea/EAThread )
set( FOLDER_CONTEXT "Tools" )
add_subdirectory( sdklauncher )

View File

@ -141,6 +141,7 @@ macro( thirdparty_suppress_warnings )
/wd4244 # Type conversion truncation; protobuf has many, but this appears intentional.
/wd4245 # 'return': conversion signed/unsigned mismatch
/wd4267 # Type conversion truncation; protobuf has many, but this appears intentional.
/wd4295 # Array is too small to include terminating null character.
/wd4307 # Integral constant overflow.
/wd4389 # Signed/unsigned mismatch.
/wd4456 # Declaration hides previous local declaration.

View File

@ -48,7 +48,7 @@ macro( apply_project_settings )
# https://rapidjson.org/md_doc_features.html
# https://github.com/Tencent/rapidjson/issues/1227
# https://github.com/Tencent/rapidjson/issues/2260
"RAPIDJSON_PARSE_DEFAULT_FLAGS=kParseIterativeFlag"
"RAPIDJSON_PARSE_DEFAULT_FLAGS=kParseIterativeFlag|kParseValidateEncodingFlag"
# Target is 64bits only.
"PLATFORM_64BITS"

View File

@ -40,9 +40,10 @@ bool Miles_Initialize()
// if we are loading english and the file is still not found, we can let it hit the regular engine error, since that is not recoverable
if (!FileSystem()->FileExists(baseStreamFilePath.c_str()))
{
Error(eDLL_T::AUDIO, NO_ERROR, "%s: attempted to load language '%s' but the required stream bank (%s) was not found. falling back to english...\n", pszLanguage, baseStreamFilePath.c_str());
Error(eDLL_T::AUDIO, NO_ERROR, "%s: attempted to load language '%s' but the required streaming source file (%s) was not found. falling back to english...\n", __FUNCTION__, pszLanguage, baseStreamFilePath.c_str());
pszLanguage = MILES_DEFAULT_LANGUAGE;
miles_language->SetValue(pszLanguage);
}
}
@ -67,7 +68,27 @@ void MilesQueueEventRun(Miles::Queue* queue, const char* eventName)
void MilesBankPatch(Miles::Bank* bank, char* streamPatch, char* localizedStreamPatch)
{
// TODO [REXX]: add print for patch loading when Miles::Bank struct is mapped out a bit better with file name
if (miles_debug.GetBool())
{
Msg(eDLL_T::AUDIO,
"%s: patching bank \"%s\". stream patches: \"%s\", \"%s\"\n",
__FUNCTION__,
bank->GetBankName(),
V_UnqualifiedFileName(streamPatch), V_UnqualifiedFileName(localizedStreamPatch)
);
}
const Miles::BankHeader_t* header = bank->GetHeader();
if (header->bankIndex >= header->project->bankCount)
Error(eDLL_T::AUDIO, EXIT_FAILURE,
"%s: Attempted to patch bank '%s' that identified itself as bank idx %i.\nProject expects a highest index of %i\n",
__FUNCTION__,
bank->GetBankName(),
header->bankIndex,
header->project->bankCount - 1
);
v_MilesBankPatch(bank, streamPatch, localizedStreamPatch);
}

View File

@ -4,6 +4,9 @@ constexpr char MILES_DEFAULT_LANGUAGE[] = "english";
namespace Miles
{
constexpr int TEMPLATEID_FLAG_SOURCE = 0x40000000;
struct Queue
{
char gap0[0x8];
@ -11,8 +14,107 @@ namespace Miles
char gap10[0x20];
};
struct BankHeader_t;
struct Source_t
{
BankHeader_t* bank; // reserved on disk - written at runtime
char gap8[80];
};
struct Event_t
{
int nameOffset;
int unkOffset; // offset into BankHeader_t::unk_68 data - some sort of event metadata?
};
// internal project data structure
struct IntProjectData_t
{
char gap0[0xCF0];
int bankCount;
BankHeader_t** loadedBanks;
};
struct BankHeader_t
{
int magic; // 'CBNK'
int version; // 32
uint32_t dataSize;
int bankMagic; // 'BANK'
const char* bankName;
void* unk_18;
IntProjectData_t* project;
void* unk_28;
void* unk_30;
void* unk_38;
void* unk_40; // used to index into both sources and localised sources
Source_t* sources;
Source_t* localizedSources;
void* unk_58;
Event_t* events;
void* unk_68;
const char* stringTable;
void* unk_78;
void* unk_80;
void* unk_88;
uint8_t bankIndex;
// 3 byte padding
uint32_t localizedSourceCount;
uint32_t sourceCount;
uint32_t patchCount;
uint32_t eventCount;
uint32_t count_A4;
uint32_t count_A8;
uint32_t count_AC;
uint32_t buildTag;
uint32_t unk_B4;
uint32_t someDataSize;
const char* GetBankName() const
{
return bankName;
}
};
static_assert(offsetof(BankHeader_t, project) == 0x20);
static_assert(offsetof(BankHeader_t, stringTable) == 0x70);
static_assert(offsetof(BankHeader_t, unk_B4) == 0xB4);
struct Bank
{
// TODO [REXX]: map out this struct and its internal counterpart
void* internalData;
void* unk_8;
char* fileData;
int unk_18;
char gap_1c[4];
const Miles::BankHeader_t* GetHeader() const
{
return reinterpret_cast<Miles::BankHeader_t*>(fileData);
}
const char* GetBankName() const
{
return GetHeader()->GetBankName();
}
};
static_assert(sizeof(Bank) == 0x20);
}

View File

@ -562,7 +562,7 @@ void Cmd_Exec_f(const CCommand& args)
// Prevent users from running neo strafe commands and other quick hacks.
// TODO: when reBar becomes a thing, we should verify this function and
// flag users that patch them out.
if (!ThreadInServerFrameThread() && g_pClientState->IsActive())
if (g_pClientState->IsActive() && !ThreadInServerFrameThread())
{
const int execQuota = sv_quota_scriptExecsPerSecond.GetInt();

View File

@ -111,6 +111,10 @@ ConVar* net_usesocketsforloopback;
ConVar* net_data_block_enabled = nullptr;
ConVar* net_datablock_networkLossForSlowSpeed = nullptr;
ConVar* net_compressDataBlock = nullptr;
ConVar* net_showmsg = nullptr;
ConVar* net_blockmsg = nullptr;
ConVar* net_showpeaks = nullptr;
//-----------------------------------------------------------------------------
// RUI |
#ifndef DEDICATED
@ -183,6 +187,10 @@ void ConVar_InitShipped(void)
net_datablock_networkLossForSlowSpeed = g_pCVar->FindVar("net_datablock_networkLossForSlowSpeed");
net_usesocketsforloopback = g_pCVar->FindVar("net_usesocketsforloopback");
net_showmsg = g_pCVar->FindVar("net_showmsg");
net_blockmsg = g_pCVar->FindVar("net_blockmsg");
net_showpeaks = g_pCVar->FindVar("net_showpeaks");
#ifndef CLIENT_DLL
sv_stats = g_pCVar->FindVar("sv_stats");

View File

@ -98,6 +98,10 @@ extern ConVar* net_data_block_enabled;
extern ConVar* net_datablock_networkLossForSlowSpeed;
extern ConVar* net_compressDataBlock;
extern ConVar* net_showmsg;
extern ConVar* net_blockmsg;
extern ConVar* net_showpeaks;
extern ConVar ssl_verify_peer;
extern ConVar curl_timeout;
extern ConVar curl_debug;

View File

@ -41,6 +41,8 @@ target_link_libraries( ${PROJECT_NAME} PRIVATE
"wldap32.lib"
"ws2_32.lib"
"Rpcrt4.lib"
"iphlpapi.lib"
"Winmm.lib"
"vpc"
"memoverride"
@ -56,6 +58,7 @@ target_link_libraries( ${PROJECT_NAME} PRIVATE
"vphysics"
"SigCache_Pb"
"LiveAPI_Pb"
"SV_RCon_Pb"
"CL_RCon_Pb"
@ -75,6 +78,9 @@ target_link_libraries( ${PROJECT_NAME} PRIVATE
"libdetour"
"navdebugutils"
"EAThread"
"DirtySDK"
"networksystem"
"pluginsystem"
"filesystem"
@ -156,6 +162,11 @@ target_compile_definitions( ${PROJECT_NAME} PRIVATE
endif()
target_include_directories( ${PROJECT_NAME} PRIVATE
"${THIRDPARTY_SOURCE_DIR}/dirtysdk/include/"
"${THIRDPARTY_SOURCE_DIR}/ea/"
)
target_link_options( ${PROJECT_NAME} PRIVATE
"/STACK:8000000" # Match game executable stack reserve size

View File

@ -11,7 +11,4 @@
//#else
# define Assert(condition, ...) assert(condition)
# define AssertFatalMsg Assert
// TODO: this needs to go to dbg.h
# define AssertMsg(condition, ...) assert(condition)
//#endif

View File

@ -3,6 +3,7 @@
#include "core/init.h"
#include "core/logdef.h"
#include "core/logger.h"
#include "tier0/cpu.h"
#include "tier0/basetypes.h"
#include "tier0/crashhandler.h"
#include "tier0/commandline.h"
@ -25,6 +26,12 @@
bool g_bSdkInitialized = false;
bool g_bSdkInitCallInitiated = false;
bool g_bSdkShutdownCallInitiated = false;
bool g_bSdkShutdownInitiatedFromConsoleHandler = false;
HMODULE s_hModuleHandle = NULL;
//#############################################################################
// UTILITY
//#############################################################################
@ -76,6 +83,28 @@ void Tier0_Init()
void SDK_Init()
{
assert(!g_bSdkInitialized);
CheckSystemCPU(); // Check CPU as early as possible; error out if CPU isn't supported.
if (g_bSdkInitCallInitiated)
{
spdlog::error("Recursive initialization!\n");
return;
}
// Set after checking cpu and initializing MathLib since we check CPU
// features there. Else we crash on the recursive initialization error as
// SpdLog uses SSE features.
g_bSdkInitCallInitiated = true;
MathLib_Init(); // Initialize Mathlib.
PEB64* pEnv = CModule::GetProcessEnvironmentBlock();
g_GameDll.InitFromBase(pEnv->ImageBaseAddress);
g_SDKDll.InitFromBase((QWORD)s_hModuleHandle);
Tier0_Init();
if (!CommandLine()->CheckParm("-launcher"))
@ -95,7 +124,9 @@ void SDK_Init()
SpdLog_Init(bAnsiColor);
Show_Emblem();
Winsock_Init(); // Initialize Winsock.
Winsock_Startup(); // Initialize Winsock.
DirtySDK_Startup();
Systems_Init();
WinSys_Init();
@ -118,13 +149,25 @@ void SDK_Shutdown()
{
assert(g_bSdkInitialized);
if (!g_bSdkInitialized)
// Also check CPU in shutdown, since this function is exported, if they
// call this with an unsupported CPU we should let them know rather than
// crashing the process.
CheckSystemCPU();
if (g_bSdkShutdownCallInitiated)
{
spdlog::error("Recursive shutdown!\n");
return;
}
g_bSdkInitialized = false;
g_bSdkShutdownCallInitiated = true;
if (!g_bSdkInitialized)
{
spdlog::error("Not initialized!\n");
return;
}
Msg(eDLL_T::NONE, "GameSDK shutdown initiated\n");
curl_global_cleanup();
@ -135,10 +178,18 @@ void SDK_Shutdown()
WinSys_Shutdown();
Systems_Shutdown();
DirtySDK_Shutdown();
Winsock_Shutdown();
SpdLog_Shutdown();
Console_Shutdown();
// If the shutdown was initiated from the console window itself, don't
// shutdown the console as it would otherwise deadlock in FreeConsole!
if (!g_bSdkShutdownInitiatedFromConsoleHandler)
Console_Shutdown();
g_bSdkInitialized = false;
}
//#############################################################################
@ -147,27 +198,18 @@ void SDK_Shutdown()
BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
{
CheckCPU(); // Check CPU as early as possible; error out if CPU isn't supported.
MathLib_Init(); // Initialize Mathlib.
NOTE_UNUSED(lpReserved);
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
{
PEB64* pEnv = CModule::GetProcessEnvironmentBlock();
g_GameDll.InitFromBase(pEnv->ImageBaseAddress);
g_SDKDll.InitFromBase((QWORD)hModule);
SDK_Init();
s_hModuleHandle = hModule;
break;
}
case DLL_PROCESS_DETACH:
{
SDK_Shutdown();
s_hModuleHandle = NULL;
break;
}
}

View File

@ -59,6 +59,9 @@
#include "engine/server/datablock_sender.h"
#endif // !CLIENT_DLL
#include "studiorender/studiorendercontext.h"
#ifndef CLIENT_DLL
#include "rtech/liveapi/liveapi.h"
#endif // !CLIENT_DLL
#include "rtech/rstdlib.h"
#include "rtech/rson.h"
#include "rtech/async/asyncio.h"
@ -148,6 +151,11 @@
#include "windows/id3dx.h"
#endif // !DEDICATED
#include "DirtySDK/dirtysock.h"
#include "DirtySDK/dirtysock/netconn.h"
#include "DirtySDK/proto/protossl.h"
#include "DirtySDK/proto/protowebsocket.h"
/////////////////////////////////////////////////////////////////////////////////////////////////
//
@ -242,6 +250,8 @@ void Systems_Init()
ServerScriptRegister_Callback = Script_RegisterServerFunctions;
CoreServerScriptRegister_Callback = Script_RegisterCoreServerFunctions;
AdminPanelScriptRegister_Callback = Script_RegisterAdminPanelFunctions;
ServerScriptRegisterEnum_Callback = Script_RegisterServerEnums;
#endif// !CLIENT_DLL
#ifndef SERVER_DLL
@ -275,6 +285,10 @@ void Systems_Shutdown()
RCONClient()->Shutdown();
#endif // !SERVER_DLL
#ifndef CLIENT_DLL
LiveAPISystem()->Shutdown();
#endif// !CLIENT_DLL
CFastTimer shutdownTimer;
shutdownTimer.Start();
@ -309,25 +323,51 @@ void Systems_Shutdown()
//
/////////////////////////////////////////////////////
void Winsock_Init()
void Winsock_Startup()
{
WSAData wsaData{};
int nError = ::WSAStartup(MAKEWORD(2, 2), &wsaData);
const int nError = ::WSAStartup(MAKEWORD(2, 2), &wsaData);
if (nError != 0)
{
Error(eDLL_T::COMMON, NO_ERROR, "%s: Failed to start Winsock: (%s)\n",
Error(eDLL_T::COMMON, 0, "%s: Windows Sockets API startup failure: (%s)\n",
__FUNCTION__, NET_ErrorString(WSAGetLastError()));
}
}
void Winsock_Shutdown()
{
int nError = ::WSACleanup();
const int nError = ::WSACleanup();
if (nError != 0)
{
Error(eDLL_T::COMMON, NO_ERROR, "%s: Failed to stop Winsock: (%s)\n",
Error(eDLL_T::COMMON, 0, "%s: Windows Sockets API shutdown failure: (%s)\n",
__FUNCTION__, NET_ErrorString(WSAGetLastError()));
}
}
void DirtySDK_Startup()
{
const int32_t netConStartupRet = NetConnStartup("-servicename=sourcesdk");
if (netConStartupRet < 0)
{
Error(eDLL_T::COMMON, 0, "%s: Network connection module startup failure: (%i)\n",
__FUNCTION__, netConStartupRet);
}
}
void DirtySDK_Shutdown()
{
const int32_t netConShutdownRet = NetConnShutdown(0);
if (netConShutdownRet < 0)
{
Error(eDLL_T::COMMON, 0, "%s: Network connection module shutdown failure: (%i)\n",
__FUNCTION__, netConShutdownRet);
}
}
void QuerySystemInfo()
{
#ifndef DEDICATED
@ -378,33 +418,6 @@ void QuerySystemInfo()
}
}
void CheckCPU() // Respawn's engine and our SDK utilize POPCNT, SSE3 and SSSE3 (Supplemental SSE 3 Instructions).
{
CpuIdResult_t cpuResult;
__cpuid(reinterpret_cast<int*>(&cpuResult), 1);
char szBuf[1024];
if ((cpuResult.ecx & (1 << 0)) == 0)
{
V_snprintf(szBuf, sizeof(szBuf), "CPU does not have %s!\n", "SSE 3");
MessageBoxA(NULL, szBuf, "Unsupported CPU", MB_ICONERROR | MB_OK);
ExitProcess(0xFFFFFFFF);
}
if ((cpuResult.ecx & (1 << 9)) == 0)
{
V_snprintf(szBuf, sizeof(szBuf), "CPU does not have %s!\n", "SSSE 3 (Supplemental SSE 3 Instructions)");
MessageBoxA(NULL, szBuf, "Unsupported CPU", MB_ICONERROR | MB_OK);
ExitProcess(0xFFFFFFFF);
}
if ((cpuResult.ecx & (1 << 23)) == 0)
{
V_snprintf(szBuf, sizeof(szBuf), "CPU does not have %s!\n", "POPCNT");
MessageBoxA(NULL, szBuf, "Unsupported CPU", MB_ICONERROR | MB_OK);
ExitProcess(0xFFFFFFFF);
}
}
#if defined (DEDICATED)
#define SIGDB_FILE "cfg/server/startup.bin"
#elif defined (CLIENT_DLL)

View File

@ -1,18 +1,20 @@
#pragma once
void SDK_Init();
void SDK_Shutdown();
PLATFORM_INTERFACE void SDK_Init();
PLATFORM_INTERFACE void SDK_Shutdown();
void Systems_Init();
void Systems_Shutdown();
void Winsock_Init();
void Winsock_Startup();
void Winsock_Shutdown();
void DirtySDK_Startup();
void DirtySDK_Shutdown();
void QuerySystemInfo();
void CheckCPU();
void DetourInit();
void DetourAddress();
void DetourRegister();
extern bool g_bSdkInitialized;
extern bool g_bSdkShutdownInitiatedFromConsoleHandler;

View File

@ -101,6 +101,8 @@ void SpdLog_Init(const bool bAnsiColor)
#endif // !_TOOLS
spdlog::set_level(spdlog::level::trace);
spdlog::flush_every(std::chrono::seconds(5));
bInitialized = true;
}

View File

@ -35,6 +35,7 @@
#include "engine/cmodel_bsp.h"
#ifndef CLIENT_DLL
#include "engine/server/server.h"
#include "rtech/liveapi/liveapi.h"
#endif // !CLIENT_DLL
#include "rtech/stryder/stryder.h"
#include "rtech/playlists/playlists.h"
@ -305,6 +306,10 @@ void CHostState::Setup(void)
RCONClient()->Init();
#endif // !DEDICATED
#ifndef CLIENT_DLL
LiveAPISystem()->Init();
#endif // !CLIENT_DLL
if (net_useRandomKey.GetBool())
{
NET_GenerateKey();

View File

@ -372,7 +372,7 @@ void CNetChan::_Shutdown(CNetChan* pChan, const char* szReason, uint8_t bBadRep,
bool CNetChan::_ProcessMessages(CNetChan* pChan, bf_read* pBuf)
{
#ifndef CLIENT_DLL
if (!ThreadInServerFrameThread() || !net_processTimeBudget.GetInt())
if (!net_processTimeBudget.GetInt() || !ThreadInServerFrameThread())
return pChan->ProcessMessages(pBuf);
const double flStartTime = Plat_FloatTime();
@ -417,7 +417,25 @@ bool CNetChan::_ProcessMessages(CNetChan* pChan, bf_read* pBuf)
bool CNetChan::ProcessMessages(bf_read* buf)
{
m_bStopProcessing = false;
//const double flStartTime = Plat_FloatTime();
const char* showMsgName = net_showmsg->GetString();
const char* blockMsgName = net_blockmsg->GetString();
const int netPeak = net_showpeaks->GetInt();
if (*showMsgName == '0')
{
showMsgName = NULL; // dont do strcmp all the time
}
if (*blockMsgName == '0')
{
blockMsgName = NULL; // dont do strcmp all the time
}
if (netPeak > 0 && netPeak < buf->GetNumBytesLeft())
{
showMsgName = "1"; // show messages for this packet only
}
while (true)
{
@ -457,6 +475,26 @@ bool CNetChan::ProcessMessages(bf_read* buf)
return false;
}
if (showMsgName)
{
if ((*showMsgName == '1') || !Q_stricmp(showMsgName, netMsg->GetName()))
{
Msg(eDLL_T::ENGINE, "%s(%s): Received: %s\n",
__FUNCTION__, GetAddress(), netMsg->ToString());
}
}
if (blockMsgName)
{
if ((*blockMsgName == '1') || !Q_stricmp(blockMsgName, netMsg->GetName()))
{
Msg(eDLL_T::ENGINE, "%s(%s): Blocked: %s\n",
__FUNCTION__, GetAddress(), netMsg->ToString());
continue;
}
}
// Netmessage calls the Process function that was registered by
// it's MessageHandler.
m_bProcessingMessages = true;

View File

@ -19,6 +19,7 @@
#include "ebisusdk/EbisuSDK.h"
#include "public/edict.h"
#include "pluginsystem/pluginsystem.h"
#include "rtech/liveapi/liveapi.h"
//---------------------------------------------------------------------------------
// Console variables
@ -215,6 +216,7 @@ void CServer::BroadcastMessage(CNetMessage* const msg, const bool onlyActive, co
void CServer::FrameJob(double flFrameTime, bool bRunOverlays, bool bUpdateFrame)
{
CServer__FrameJob(flFrameTime, bRunOverlays, bUpdateFrame);
LiveAPISystem()->RunFrame();
}
//---------------------------------------------------------------------------------

View File

@ -12,7 +12,6 @@
#include "networksystem/pylon.h"
#include "networksystem/bansystem.h"
#include "engine/client/client.h"
#include "tier1/cvar.h"
#include "server.h"
//-----------------------------------------------------------------------------

View File

@ -382,37 +382,36 @@ void CRConServer::Authenticate(const cl_rcon::request& request, CConnectedNetCon
{
return;
}
else // Authorize.
// Authorize.
if (Comparator(request.requestmsg()))
{
if (Comparator(request.requestmsg()))
data.m_bAuthorized = true;
if (++m_nAuthConnections >= sv_rcon_maxconnections.GetInt())
{
data.m_bAuthorized = true;
if (++m_nAuthConnections >= sv_rcon_maxconnections.GetInt())
{
m_Socket.CloseListenSocket();
CloseNonAuthConnection();
}
const char* pSendLogs = (!sv_rcon_sendlogs.GetBool() || data.m_bInputOnly) ? "0" : "1";
SendEncode(data.m_hSocket, s_AuthMessage, pSendLogs,
sv_rcon::response_t::SERVERDATA_RESPONSE_AUTH, static_cast<int>(eDLL_T::NETCON));
m_Socket.CloseListenSocket();
CloseNonAuthConnection();
}
else // Bad password.
const char* pSendLogs = (!sv_rcon_sendlogs.GetBool() || data.m_bInputOnly) ? "0" : "1";
SendEncode(data.m_hSocket, s_AuthMessage, pSendLogs,
sv_rcon::response_t::SERVERDATA_RESPONSE_AUTH, static_cast<int>(eDLL_T::NETCON));
}
else // Bad password.
{
const netadr_t& netAdr = m_Socket.GetAcceptedSocketAddress(m_nConnIndex);
if (sv_rcon_debug.GetBool())
{
const netadr_t& netAdr = m_Socket.GetAcceptedSocketAddress(m_nConnIndex);
if (sv_rcon_debug.GetBool())
{
Msg(eDLL_T::SERVER, "Bad RCON password attempt from '%s'\n", netAdr.ToString());
}
SendEncode(data.m_hSocket, s_WrongPwMessage, "",
sv_rcon::response_t::SERVERDATA_RESPONSE_AUTH, static_cast<int>(eDLL_T::NETCON));
data.m_bAuthorized = false;
data.m_bValidated = false;
data.m_nFailedAttempts++;
Msg(eDLL_T::SERVER, "Bad RCON password attempt from '%s'\n", netAdr.ToString());
}
SendEncode(data.m_hSocket, s_WrongPwMessage, "",
sv_rcon::response_t::SERVERDATA_RESPONSE_AUTH, static_cast<int>(eDLL_T::NETCON));
data.m_bAuthorized = false;
data.m_bValidated = false;
data.m_nFailedAttempts++;
}
}
@ -510,7 +509,7 @@ bool CRConServer::ProcessMessage(const char* pMsgBuf, const int nMsgLen)
//-----------------------------------------------------------------------------
void CRConServer::Execute(const cl_rcon::request& request) const
{
const string& commandString = request.requestmsg().c_str();
const string& commandString = request.requestmsg();
const char* const pCommandString = commandString.c_str();
ConCommandBase* pCommandBase = g_pCVar->FindCommandBase(pCommandString);
@ -523,6 +522,9 @@ void CRConServer::Execute(const cl_rcon::request& request) const
const char* const pValueString = request.requestval().c_str();
if (pCommandBase->IsFlagSet(FCVAR_SERVER_FRAME_THREAD))
ThreadJoinServerJob();
if (!pCommandBase->IsCommand())
{
// Here we want to skip over the command string in the value buffer.

View File

@ -114,6 +114,23 @@ int Sys_GetProcessUpTime(char* szBuffer)
return v_Sys_GetProcessUpTime(szBuffer);
}
//-----------------------------------------------------------------------------
// Purpose: Gets the build string of the game (defined in build.txt), if the file
// is absent, the changelist # will be returned instead
//-----------------------------------------------------------------------------
const char* Sys_GetBuildString(void)
{
return v_Sys_GetBuildString();
}
//-----------------------------------------------------------------------------
// Purpose: Gets the platform string
//-----------------------------------------------------------------------------
const char* Sys_GetPlatformString(void)
{
return "PC";
}
void VSys_Utils::Detour(const bool bAttach) const
{
DetourSetup(&v_Error, &_Error, bAttach);

View File

@ -4,6 +4,7 @@
inline void(*v_Error)(const char* fmt, ...);
inline void(*v_Warning)(int, const char* fmt, ...);
inline int(*v_Sys_GetProcessUpTime)(char* szBuffer);
inline const char* (*v_Sys_GetBuildString)(void);
#ifndef DEDICATED
inline void(*v_Con_NPrintf)(int pos, const char* fmt, ...);
#endif // !DEDICATED
@ -11,6 +12,8 @@ inline void(*v_Con_NPrintf)(int pos, const char* fmt, ...);
///////////////////////////////////////////////////////////////////////////////
int Sys_GetProcessUpTime(char* szBuffer);
const char* Sys_GetBuildString(void);
const char* Sys_GetPlatformString(void);
///////////////////////////////////////////////////////////////////////////////
class VSys_Utils : public IDetour
@ -20,6 +23,7 @@ class VSys_Utils : public IDetour
LogFunAdr("Error", v_Error);
LogFunAdr("Warning", v_Warning);
LogFunAdr("Sys_GetProcessUpTime", v_Sys_GetProcessUpTime);
LogFunAdr("Sys_GetProcessUpTime", v_Sys_GetBuildString);
#ifndef DEDICATED
LogFunAdr("Con_NPrintf", v_Con_NPrintf);
#endif // !DEDICATED
@ -29,6 +33,7 @@ class VSys_Utils : public IDetour
g_GameDll.FindPatternSIMD("48 89 4C 24 08 48 89 54 24 10 4C 89 44 24 18 4C 89 4C 24 20 53 55 41 54 41 56 B8 58 10 ?? ?? E8").GetPtr(v_Error);
g_GameDll.FindPatternSIMD("48 89 54 24 ?? 4C 89 44 24 ?? 4C 89 4C 24 ?? 48 83 EC 28 4C 8D 44 24 ?? E8 ?? ?? ?? ?? 48 83 C4 28 C3 CC CC CC CC CC CC CC CC CC CC CC CC CC CC 48 89 5C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 8B 05 ?? ?? ?? ??").GetPtr(v_Warning);
g_GameDll.FindPatternSIMD("40 57 48 83 EC 30 48 8B F9 8B 0D ?? ?? ?? ??").GetPtr(v_Sys_GetProcessUpTime);
g_GameDll.FindPatternSIMD("E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? 48 8B E8").FollowNearCallSelf().GetPtr(v_Sys_GetBuildString);
#ifndef DEDICATED
g_GameDll.FindPatternSIMD("48 89 4C 24 ?? 48 89 54 24 ?? 4C 89 44 24 ?? 4C 89 4C 24 ?? C3").GetPtr(v_Con_NPrintf);
#endif // !DEDICATED

View File

@ -41,7 +41,7 @@ endif()
if( ${PROJECT_NAME} STREQUAL "server_static" )
add_sources( SOURCE_GROUP "Server"
add_sources( SOURCE_GROUP "AI"
"server/ai_network.cpp"
"server/ai_network.h"
"server/ai_networkmanager.cpp"
@ -49,36 +49,59 @@ add_sources( SOURCE_GROUP "Server"
"server/ai_node.h"
"server/ai_utility.cpp"
"server/ai_utility.h"
"server/detour_impl.h"
)
add_sources( SOURCE_GROUP "Entity"
"server/baseanimating.cpp"
"server/baseanimating.h"
"server/baseanimatingoverlay.h"
"server/basecombatcharacter.h"
"server/baseentity.cpp"
"server/baseentity.h"
"server/cbase.cpp"
"server/cbase.h"
"server/detour_impl.h"
"server/entitylist.cpp"
"server/entitylist.h"
"server/entityoutput.cpp"
"server/entityoutput.h"
)
add_sources( SOURCE_GROUP "Network"
"server/networkproperty.cpp"
"server/networkproperty.h"
)
add_sources( SOURCE_GROUP "Player"
"server/player.cpp"
"server/player.h"
"server/playerlocaldata.h"
)
add_sources( SOURCE_GROUP "Script"
"server/vscript_server.cpp"
"server/vscript_server.h"
)
add_sources( SOURCE_GROUP "Physics"
"server/physics_main.cpp"
"server/physics_main.h"
)
add_sources( SOURCE_GROUP "Utility"
"server/cbase.cpp"
"server/cbase.h"
"server/gameinterface.cpp"
"server/gameinterface.h"
"server/movehelper_server.cpp"
"server/movehelper_server.h"
"server/networkproperty.cpp"
"server/networkproperty.h"
"server/physics_main.cpp"
"server/physics_main.h"
"server/player.cpp"
"server/player.h"
"server/playerlocaldata.h"
"server/util_server.cpp"
"server/util_server.h"
"server/variant_t.cpp"
"server/variant_t.h"
"server/vscript_server.cpp"
"server/vscript_server.h"
)
add_sources( SOURCE_GROUP "LiveAPI"
"server/liveapi/liveapi.cpp"
"server/liveapi/liveapi.h"
)
add_sources( SOURCE_GROUP "Public"
@ -152,6 +175,7 @@ endif()
target_include_directories( ${PROJECT_NAME} PRIVATE
"${ENGINE_SOURCE_DIR}/tier0/"
"${ENGINE_SOURCE_DIR}/tier1/"
"${THIRDPARTY_SOURCE_DIR}/mbedtls/include"
)
endmacro()

View File

@ -60,7 +60,7 @@ static ConCommand script_ui("script_ui", SQVM_UIScript_f, "Run input code as UI
//-----------------------------------------------------------------------------
// Purpose: checks if the server index is valid, raises an error if not
//-----------------------------------------------------------------------------
static SQBool Script_CheckServerIndex(HSQUIRRELVM v, SQInteger iServer)
static SQBool Script_CheckServerIndexAndFailure(HSQUIRRELVM v, SQInteger iServer)
{
SQInteger iCount = static_cast<SQInteger>(g_ServerListManager.m_vServerList.size());
@ -69,6 +69,11 @@ static SQBool Script_CheckServerIndex(HSQUIRRELVM v, SQInteger iServer)
v_SQVM_RaiseError(v, "Index must be less than %i.\n", iCount);
return false;
}
else if (iServer == -1) // If its still -1, then 'sq_getinteger' failed
{
v_SQVM_RaiseError(v, "Invalid argument type provided.\n");
return false;
}
return true;
}
@ -89,7 +94,7 @@ namespace VScriptCode
g_ServerListManager.RefreshServerList(serverMessage, iCount);
sq_pushinteger(v, static_cast<SQInteger>(iCount));
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
@ -100,7 +105,7 @@ namespace VScriptCode
size_t iCount = g_ServerListManager.m_vServerList.size();
sq_pushinteger(v, static_cast<SQInteger>(iCount));
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
@ -108,10 +113,13 @@ namespace VScriptCode
//-----------------------------------------------------------------------------
SQRESULT GetHiddenServerName(HSQUIRRELVM v)
{
SQChar* privateToken = sq_getstring(v, 1);
const SQChar* privateToken = nullptr;
if (!VALID_CHARSTAR(privateToken))
return SQ_OK;
if (SQ_FAILED(sq_getstring(v, 2, &privateToken)) || VALID_CHARSTAR(privateToken))
{
v_SQVM_ScriptError("Empty or null private token");
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
}
string hiddenServerRequestMessage;
NetGameServer_t serverListing;
@ -120,28 +128,22 @@ namespace VScriptCode
if (!result)
{
if (hiddenServerRequestMessage.empty())
{
sq_pushstring(v, "Request failed", -1);
}
else
{
hiddenServerRequestMessage = Format("Request failed: %s", hiddenServerRequestMessage.c_str());
sq_pushstring(v, hiddenServerRequestMessage.c_str(), -1);
}
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
if (serverListing.name.empty())
{
if (hiddenServerRequestMessage.empty())
{
hiddenServerRequestMessage = Format("Server listing empty");
}
else
{
hiddenServerRequestMessage = Format("Server listing empty: %s", hiddenServerRequestMessage.c_str());
}
sq_pushstring(v, hiddenServerRequestMessage.c_str(), -1);
}
@ -151,7 +153,7 @@ namespace VScriptCode
sq_pushstring(v, hiddenServerRequestMessage.c_str(), -1);
}
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
@ -160,17 +162,17 @@ namespace VScriptCode
SQRESULT GetServerName(HSQUIRRELVM v)
{
AUTO_LOCK(g_ServerListManager.m_Mutex);
SQInteger iServer = sq_getinteger(v, 1);
if (!Script_CheckServerIndex(v, iServer))
{
return SQ_ERROR;
}
SQInteger iServer = -1;
sq_getinteger(v, 2, &iServer);
if (!Script_CheckServerIndexAndFailure(v, iServer))
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
const string& serverName = g_ServerListManager.m_vServerList[iServer].name;
sq_pushstring(v, serverName.c_str(), -1);
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
@ -179,17 +181,17 @@ namespace VScriptCode
SQRESULT GetServerDescription(HSQUIRRELVM v)
{
AUTO_LOCK(g_ServerListManager.m_Mutex);
SQInteger iServer = sq_getinteger(v, 1);
if (!Script_CheckServerIndex(v, iServer))
{
return SQ_ERROR;
}
SQInteger iServer = -1;
sq_getinteger(v, 2, &iServer);
if (!Script_CheckServerIndexAndFailure(v, iServer))
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
const string& serverDescription = g_ServerListManager.m_vServerList[iServer].description;
sq_pushstring(v, serverDescription.c_str(), -1);
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
@ -198,17 +200,17 @@ namespace VScriptCode
SQRESULT GetServerMap(HSQUIRRELVM v)
{
AUTO_LOCK(g_ServerListManager.m_Mutex);
SQInteger iServer = sq_getinteger(v, 1);
if (!Script_CheckServerIndex(v, iServer))
{
return SQ_ERROR;
}
SQInteger iServer = -1;
sq_getinteger(v, 2, &iServer);
if (!Script_CheckServerIndexAndFailure(v, iServer))
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
const string& svServerMapName = g_ServerListManager.m_vServerList[iServer].map;
sq_pushstring(v, svServerMapName.c_str(), -1);
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
@ -217,17 +219,17 @@ namespace VScriptCode
SQRESULT GetServerPlaylist(HSQUIRRELVM v)
{
AUTO_LOCK(g_ServerListManager.m_Mutex);
SQInteger iServer = sq_getinteger(v, 1);
if (!Script_CheckServerIndex(v, iServer))
{
return SQ_ERROR;
}
SQInteger iServer = -1;
sq_getinteger(v, 2, &iServer);
if (!Script_CheckServerIndexAndFailure(v, iServer))
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
const string& serverPlaylist = g_ServerListManager.m_vServerList[iServer].playlist;
sq_pushstring(v, serverPlaylist.c_str(), -1);
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
@ -236,17 +238,17 @@ namespace VScriptCode
SQRESULT GetServerCurrentPlayers(HSQUIRRELVM v)
{
AUTO_LOCK(g_ServerListManager.m_Mutex);
SQInteger iServer = sq_getinteger(v, 1);
if (!Script_CheckServerIndex(v, iServer))
{
return SQ_ERROR;
}
SQInteger iServer = -1;
sq_getinteger(v, 2, &iServer);
if (!Script_CheckServerIndexAndFailure(v, iServer))
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
const SQInteger playerCount = g_ServerListManager.m_vServerList[iServer].numPlayers;
sq_pushinteger(v, playerCount);
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
@ -255,17 +257,17 @@ namespace VScriptCode
SQRESULT GetServerMaxPlayers(HSQUIRRELVM v)
{
AUTO_LOCK(g_ServerListManager.m_Mutex);
SQInteger iServer = sq_getinteger(v, 1);
if (!Script_CheckServerIndex(v, iServer))
{
return SQ_ERROR;
}
SQInteger iServer = -1;
sq_getinteger(v, 2, &iServer);
if (!Script_CheckServerIndexAndFailure(v, iServer))
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
const SQInteger maxPlayers = g_ServerListManager.m_vServerList[iServer].maxPlayers;
sq_pushinteger(v, maxPlayers);
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
@ -283,7 +285,10 @@ namespace VScriptCode
PromoRightDesc
};
R5RPromoData ePromoIndex = static_cast<R5RPromoData>(sq_getinteger(v, 1));
SQInteger idx = 0;
sq_getinteger(v, 2, &idx);
R5RPromoData ePromoIndex = static_cast<R5RPromoData>(idx);
const char* pszPromoKey;
switch (ePromoIndex)
@ -326,7 +331,7 @@ namespace VScriptCode
}
sq_pushstring(v, pszPromoKey, -1);
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
SQRESULT GetEULAContents(HSQUIRRELVM v)
@ -349,7 +354,7 @@ namespace VScriptCode
sq_pushstring(v, error.c_str(), -1);
}
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
@ -357,16 +362,24 @@ namespace VScriptCode
//-----------------------------------------------------------------------------
SQRESULT ConnectToServer(HSQUIRRELVM v)
{
SQChar* ipAddress = sq_getstring(v, 1);
SQChar* cryptoKey = sq_getstring(v, 2);
const SQChar* ipAddress = nullptr;
if (SQ_FAILED(sq_getstring(v, 2, &ipAddress)))
{
v_SQVM_ScriptError("Missing ip address");
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
}
if (!VALID_CHARSTAR(ipAddress) || VALID_CHARSTAR(cryptoKey))
return SQ_OK;
const SQChar* cryptoKey = nullptr;
if (SQ_FAILED(sq_getstring(v, 3, &cryptoKey)))
{
v_SQVM_ScriptError("Missing encryption key");
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
}
Msg(eDLL_T::UI, "Connecting to server with ip address '%s' and encryption key '%s'\n", ipAddress, cryptoKey);
g_ServerListManager.ConnectToServer(ipAddress, cryptoKey);
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
@ -375,11 +388,13 @@ namespace VScriptCode
SQRESULT ConnectToListedServer(HSQUIRRELVM v)
{
AUTO_LOCK(g_ServerListManager.m_Mutex);
SQInteger iServer = sq_getinteger(v, 1);
if (!Script_CheckServerIndex(v, iServer))
SQInteger iServer = -1;
sq_getinteger(v, 2, &iServer);
if (!Script_CheckServerIndexAndFailure(v, iServer))
{
return SQ_ERROR;
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
}
const NetGameServer_t& gameServer = g_ServerListManager.m_vServerList[iServer];
@ -387,7 +402,7 @@ namespace VScriptCode
g_ServerListManager.ConnectToServer(gameServer.address, gameServer.port,
gameServer.netKey);
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
@ -395,15 +410,19 @@ namespace VScriptCode
//-----------------------------------------------------------------------------
SQRESULT ConnectToHiddenServer(HSQUIRRELVM v)
{
SQChar* privateToken = sq_getstring(v, 1);
const SQChar* privateToken = nullptr;
const SQRESULT strRet = sq_getstring(v, 2, &privateToken);
if (!VALID_CHARSTAR(privateToken))
return SQ_OK;
if (SQ_FAILED(strRet) || VALID_CHARSTAR(privateToken))
{
v_SQVM_ScriptError("Empty or null private token");
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
}
string hiddenServerRequestMessage;
NetGameServer_t netListing;
bool result = g_MasterServer.GetServerByToken(netListing, hiddenServerRequestMessage, privateToken); // Send token connect request.
const bool result = g_MasterServer.GetServerByToken(netListing, hiddenServerRequestMessage, privateToken); // Send token connect request.
if (result)
{
g_ServerListManager.ConnectToServer(netListing.address, netListing.port, netListing.netKey);
@ -413,7 +432,7 @@ namespace VScriptCode
Warning(eDLL_T::UI, "Failed to connect to private server: %s\n", hiddenServerRequestMessage.c_str());
}
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
@ -422,7 +441,7 @@ namespace VScriptCode
SQRESULT IsClientDLL(HSQUIRRELVM v)
{
sq_pushbool(v, ::IsClientDLL());
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
}
}

View File

@ -12,6 +12,8 @@
#include "game/server/detour_impl.h"
#include "game/server/ai_networkmanager.h"
#include "vscript/languages/squirrel_re/vsquirrel.h"
static ConVar navmesh_always_reachable("navmesh_always_reachable", "0", FCVAR_DEVELOPMENTONLY, "Marks goal poly from agent poly as reachable regardless of table data ( !slower! )");
inline uint32_t g_HullMasks[10] = // Hull mask table [r5apex_ds.exe + 131a2f8].
@ -46,7 +48,7 @@ void ClearNavMeshForHull(int hullSize)
// Frees tiles, polys, tris, anything dynamically
// allocated for this navmesh, and the navmesh itself.
v_Detour_FreeNavMesh(nav);
delete nav;
free(nav);
g_pNavMesh[hullSize] = nullptr;
}
@ -128,12 +130,17 @@ bool Detour_IsLoaded()
//-----------------------------------------------------------------------------
void Detour_HotSwap()
{
Assert(ThreadInMainOrServerFrameThread());
g_pServerScript->ExecuteCodeCallback("CodeCallback_OnNavMeshHotSwapBegin");
// Free and re-init NavMesh.
Detour_LevelShutdown();
v_Detour_LevelInit();
if (!Detour_IsLoaded())
Error(eDLL_T::SERVER, NOERROR, "%s - Failed to hot swap NavMesh\n", __FUNCTION__);
g_pServerScript->ExecuteCodeCallback("CodeCallback_OnNavMeshHotSwapEnd");
}
/*
@ -161,7 +168,7 @@ static void Detour_HotSwap_f()
Msg(eDLL_T::SERVER, "Hot swap took '%lf' seconds\n", timer.GetDuration().GetSeconds());
}
static ConCommand navmesh_hotswap("navmesh_hotswap", Detour_HotSwap_f, "Hot swap the NavMesh for all hulls", FCVAR_DEVELOPMENTONLY);
static ConCommand navmesh_hotswap("navmesh_hotswap", Detour_HotSwap_f, "Hot swap the NavMesh for all hulls", FCVAR_DEVELOPMENTONLY | FCVAR_SERVER_FRAME_THREAD);
///////////////////////////////////////////////////////////////////////////////
void VRecast::Detour(const bool bAttach) const

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,11 @@
#ifndef SERVER_LIVEAPI_H
#define SERVER_LIVEAPI_H
#define LIVEAPI_MAJOR_VERSION 0
#define LIVEAPI_MINOR_VERSION 1
#define LIVEAPI_REVISION "Rev: " MKSTRING(LIVEAPI_MAJOR_VERSION) "." MKSTRING(LIVEAPI_MINOR_VERSION)
extern void Script_RegisterLiveAPIFunctions(CSquirrelVM* const s);
extern void Script_RegisterLiveAPIEnums(CSquirrelVM* const s);
#endif // SERVER_LIVEAPI_H

View File

@ -14,6 +14,7 @@
#include "vscript/vscript.h"
#include "vscript/languages/squirrel_re/include/sqvm.h"
#include "liveapi/liveapi.h"
#include "vscript_server.h"
#include <engine/host_state.h>
#include <networksystem/hostmanager.h>
@ -33,7 +34,7 @@ static void SQVM_ServerScript_f(const CCommand& args)
Script_Execute(args.ArgS(), SQCONTEXT::SERVER);
}
}
static ConCommand script("script", SQVM_ServerScript_f, "Run input code as SERVER script on the VM", FCVAR_DEVELOPMENTONLY | FCVAR_GAMEDLL | FCVAR_CHEAT);
static ConCommand script("script", SQVM_ServerScript_f, "Run input code as SERVER script on the VM", FCVAR_DEVELOPMENTONLY | FCVAR_GAMEDLL | FCVAR_CHEAT | FCVAR_SERVER_FRAME_THREAD);
namespace VScriptCode
{
@ -47,17 +48,25 @@ namespace VScriptCode
//-----------------------------------------------------------------------------
SQRESULT CreateServer(HSQUIRRELVM v)
{
SQChar* serverName = sq_getstring(v, 1);
SQChar* serverDescription = sq_getstring(v, 2);
SQChar* serverMapName = sq_getstring(v, 3);
SQChar* serverPlaylist = sq_getstring(v, 4);
ServerVisibility_e serverVisibility = static_cast<ServerVisibility_e>(sq_getinteger(v, 5));
const SQChar* serverName = nullptr;
const SQChar* serverDescription = nullptr;
const SQChar* serverMapName = nullptr;
const SQChar* serverPlaylist = nullptr;
sq_getstring(v, 2, &serverName);
sq_getstring(v, 3, &serverDescription);
sq_getstring(v, 4, &serverMapName);
sq_getstring(v, 5, &serverPlaylist);
SQInteger serverVisibility = 0;
sq_getinteger(v, 6, &serverVisibility);
if (!VALID_CHARSTAR(serverName) ||
!VALID_CHARSTAR(serverMapName) ||
!VALID_CHARSTAR(serverPlaylist))
{
return SQ_OK;
v_SQVM_ScriptError("Empty or null server criteria");
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
}
// Adjust browser settings.
@ -69,13 +78,10 @@ namespace VScriptCode
details.playlist = serverPlaylist;
// Launch server.
g_ServerHostManager.SetVisibility(serverVisibility);
g_ServerHostManager.SetVisibility(ServerVisibility_e(serverVisibility));
g_ServerHostManager.LaunchServer(g_pServer->IsActive());
return SQ_OK;
//v_SQVM_RaiseError(v, "\"%s\" is not supported on client builds.\n", "CreateServer");
//return SQ_ERROR;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
// Purpose: shuts the server down and disconnects all clients
@ -85,7 +91,7 @@ namespace VScriptCode
if (g_pHostState->m_bActiveGame)
g_pHostState->m_iNextState = HostStates_t::HS_GAME_SHUTDOWN;
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
@ -93,16 +99,24 @@ namespace VScriptCode
//-----------------------------------------------------------------------------
SQRESULT KickPlayerByName(HSQUIRRELVM v)
{
SQChar* playerName = sq_getstring(v, 1);
SQChar* reason = sq_getstring(v, 2);
const SQChar* playerName = nullptr;
const SQChar* reason = nullptr;
sq_getstring(v, 2, &playerName);
sq_getstring(v, 3, &reason);
if (!VALID_CHARSTAR(playerName))
{
v_SQVM_ScriptError("Empty or null player name");
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
}
// Discard empty strings, this will use the default message instead.
if (!VALID_CHARSTAR(reason))
reason = nullptr;
g_BanSystem.KickPlayerByName(playerName, reason);
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
@ -110,16 +124,24 @@ namespace VScriptCode
//-----------------------------------------------------------------------------
SQRESULT KickPlayerById(HSQUIRRELVM v)
{
SQChar* playerHandle = sq_getstring(v, 1);
SQChar* reason = sq_getstring(v, 2);
const SQChar* playerHandle = nullptr;
const SQChar* reason = nullptr;
sq_getstring(v, 2, &playerHandle);
sq_getstring(v, 3, &reason);
if (!VALID_CHARSTAR(playerHandle))
{
v_SQVM_ScriptError("Empty or null player handle");
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
}
// Discard empty strings, this will use the default message instead.
if (!VALID_CHARSTAR(reason))
reason = nullptr;
g_BanSystem.KickPlayerById(playerHandle, reason);
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
@ -127,16 +149,24 @@ namespace VScriptCode
//-----------------------------------------------------------------------------
SQRESULT BanPlayerByName(HSQUIRRELVM v)
{
SQChar* playerName = sq_getstring(v, 1);
SQChar* reason = sq_getstring(v, 2);
const SQChar* playerName = nullptr;
const SQChar* reason = nullptr;
sq_getstring(v, 2, &playerName);
sq_getstring(v, 3, &reason);
if (!VALID_CHARSTAR(playerName))
{
v_SQVM_ScriptError("Empty or null player name");
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
}
// Discard empty strings, this will use the default message instead.
if (!VALID_CHARSTAR(reason))
reason = nullptr;
g_BanSystem.BanPlayerByName(playerName, reason);
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
@ -144,16 +174,24 @@ namespace VScriptCode
//-----------------------------------------------------------------------------
SQRESULT BanPlayerById(HSQUIRRELVM v)
{
SQChar* playerHandle = sq_getstring(v, 1);
SQChar* reason = sq_getstring(v, 2);
const SQChar* playerHandle = nullptr;
const SQChar* reason = nullptr;
sq_getstring(v, 2, &playerHandle);
sq_getstring(v, 3, &reason);
if (!VALID_CHARSTAR(playerHandle))
{
v_SQVM_ScriptError("Empty or null player handle");
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
}
// Discard empty strings, this will use the default message instead.
if (!VALID_CHARSTAR(reason))
reason = nullptr;
g_BanSystem.BanPlayerById(playerHandle, reason);
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
@ -161,10 +199,18 @@ namespace VScriptCode
//-----------------------------------------------------------------------------
SQRESULT UnbanPlayer(HSQUIRRELVM v)
{
SQChar* szCriteria = sq_getstring(v, 1);
const SQChar* szCriteria = nullptr;
sq_getstring(v, 2, &szCriteria);
if (!VALID_CHARSTAR(szCriteria))
{
v_SQVM_ScriptError("Empty or null player criteria");
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
}
g_BanSystem.UnbanPlayer(szCriteria);
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
@ -173,7 +219,7 @@ namespace VScriptCode
SQRESULT GetNumHumanPlayers(HSQUIRRELVM v)
{
sq_pushinteger(v, g_pServer->GetNumHumanPlayers());
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
@ -182,7 +228,7 @@ namespace VScriptCode
SQRESULT GetNumFakeClients(HSQUIRRELVM v)
{
sq_pushinteger(v, g_pServer->GetNumFakeClients());
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
@ -191,9 +237,9 @@ namespace VScriptCode
SQRESULT IsServerActive(HSQUIRRELVM v)
{
bool isActive = g_pServer->IsActive();
sq_pushbool(v, isActive);
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
@ -202,7 +248,7 @@ namespace VScriptCode
SQRESULT IsDedicated(HSQUIRRELVM v)
{
sq_pushbool(v, ::IsDedicated());
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
}
}
@ -216,6 +262,13 @@ void Script_RegisterServerFunctions(CSquirrelVM* s)
Script_RegisterCommonAbstractions(s);
Script_RegisterCoreServerFunctions(s);
Script_RegisterAdminPanelFunctions(s);
Script_RegisterLiveAPIFunctions(s);
}
void Script_RegisterServerEnums(CSquirrelVM* const s)
{
Script_RegisterLiveAPIEnums(s);
}
//---------------------------------------------------------------------------------

View File

@ -1,5 +1,6 @@
#ifndef VSCRIPT_SERVER_H
#define VSCRIPT_SERVER_H
#include "vscript/languages/squirrel_re/vsquirrel.h"
namespace VScriptCode
{
@ -26,6 +27,8 @@ void Script_RegisterServerFunctions(CSquirrelVM* s);
void Script_RegisterCoreServerFunctions(CSquirrelVM* s);
void Script_RegisterAdminPanelFunctions(CSquirrelVM* s);
void Script_RegisterServerEnums(CSquirrelVM* const s);
#define DEFINE_SERVER_SCRIPTFUNC_NAMED(s, functionName, helpString, \
returnType, parameters) \
s->RegisterFunction(#functionName, MKSTRING(Script_##functionName), \

View File

@ -28,7 +28,7 @@ namespace VScriptCode
SQRESULT GetSDKVersion(HSQUIRRELVM v)
{
sq_pushstring(v, SDK_VERSION, -1);
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
@ -39,7 +39,7 @@ namespace VScriptCode
std::lock_guard<std::mutex> l(g_InstalledMapsMutex);
if (g_InstalledMaps.IsEmpty())
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
sq_newarray(v, 0);
@ -51,7 +51,7 @@ namespace VScriptCode
sq_arrayappend(v, -2);
}
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
//-----------------------------------------------------------------------------
@ -62,7 +62,7 @@ namespace VScriptCode
std::lock_guard<std::mutex> l(g_PlaylistsVecMutex);
if (g_vAllPlaylists.empty())
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
sq_newarray(v, 0);
for (const string& it : g_vAllPlaylists)
@ -71,7 +71,7 @@ namespace VScriptCode
sq_arrayappend(v, -2);
}
return SQ_OK;
SCRIPT_CHECK_AND_RETURN(v, SQ_OK);
}
SQRESULT ScriptError(HSQUIRRELVM v)
@ -80,17 +80,10 @@ namespace VScriptCode
SQInteger a4 = 0;
if (SQVM_sprintf(v, 0, 1, &a4, &pString) < 0)
return SQ_ERROR;
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
v_SQVM_ScriptError("%s", pString);
// this should be moved to a wrapper for all script funcs
if (*reinterpret_cast<DWORD*>(&v->_sharedstate->gap43b9[127]))
{
v_SQVM_ThrowError(*reinterpret_cast<QWORD*>(&v->_sharedstate->gap43b9[111]), v);
}
return SQ_ERROR;
SCRIPT_CHECK_AND_RETURN(v, SQ_ERROR);
}
}
}
@ -118,3 +111,37 @@ void Script_RegisterListenServerConstants(CSquirrelVM* s)
const SQBool hasListenServer = !IsClientDLL();
s->RegisterConstant("LISTEN_SERVER", hasListenServer);
}
//---------------------------------------------------------------------------------
// Purpose: server enums
// Input : *s -
//---------------------------------------------------------------------------------
void Script_RegisterCommonEnums_Server(CSquirrelVM* const s)
{
v_Script_RegisterCommonEnums_Server(s);
if (ServerScriptRegisterEnum_Callback)
ServerScriptRegisterEnum_Callback(s);
}
//---------------------------------------------------------------------------------
// Purpose: client/ui enums
// Input : *s -
//---------------------------------------------------------------------------------
void Script_RegisterCommonEnums_Client(CSquirrelVM* const s)
{
v_Script_RegisterCommonEnums_Client(s);
const SQCONTEXT context = s->GetContext();
if (context == SQCONTEXT::CLIENT && ClientScriptRegisterEnum_Callback)
ClientScriptRegisterEnum_Callback(s);
else if (context == SQCONTEXT::UI && UIScriptRegisterEnum_Callback)
UIScriptRegisterEnum_Callback(s);
}
void VScriptShared::Detour(const bool bAttach) const
{
DetourSetup(&v_Script_RegisterCommonEnums_Server, &Script_RegisterCommonEnums_Server, bAttach);
DetourSetup(&v_Script_RegisterCommonEnums_Client, &Script_RegisterCommonEnums_Client, bAttach);
}

View File

@ -3,6 +3,9 @@
#include "vscript/languages/squirrel_re/include/squirrel.h"
#include "vscript/languages/squirrel_re/vsquirrel.h"
inline void (*v_Script_RegisterCommonEnums_Server)(CSquirrelVM* const s);
inline void (*v_Script_RegisterCommonEnums_Client)(CSquirrelVM* const s);
inline void*(*v_Script_Remote_BeginRegisteringFunctions)(void);
inline void*(*v_RestoreRemoteChecksumsFromSaveGame)(void* a1, void* a2);
@ -32,13 +35,22 @@ class VScriptShared : public IDetour
{
virtual void GetAdr(void) const
{
LogFunAdr("Script_RegisterCommonEnums_Server", v_Script_RegisterCommonEnums_Server);
LogFunAdr("Script_RegisterCommonEnums_Client", v_Script_RegisterCommonEnums_Client);
LogFunAdr("Remote_BeginRegisteringFunctions", v_Script_Remote_BeginRegisteringFunctions);
LogFunAdr("RestoreRemoteChecksumsFromSaveGame", v_RestoreRemoteChecksumsFromSaveGame);
LogVarAdr("g_nServerRemoteChecksum", g_nServerRemoteChecksum);
LogVarAdr("g_nClientRemoteChecksum", g_nClientRemoteChecksum);
}
virtual void GetFun(void) const
{
g_GameDll.FindPatternSIMD("E8 ? ? ? ? 48 8B CB E8 ? ? ? ? 48 8B 43 08 BF ? ? ? ? 48 8B 50 60 48 8D 05 ? ? ? ? 48 89 82 ? ? ? ? 65 48 8B 04 25 ? ? ? ? 48 03 38 8B 07 39 05 ? ? ? ? 0F 8F ? ? ? ? 48 8D 05 ? ? ? ? 48 8D 0D ? ? ? ? 48 89 05 ? ? ? ? E8 ? ? ? ? 48 8D 05 ? ? ? ? 89 35 ? ? ? ? 48 89 05 ? ? ? ? 4C 8D 35 ? ? ? ?")
.FollowNearCallSelf().GetPtr(v_Script_RegisterCommonEnums_Server);
g_GameDll.FindPatternSIMD("E8 ? ? ? ? 48 8B CB E8 ? ? ? ? 48 8B 43 08 BF ? ? ? ? 48 8B 50 60 48 8D 05 ? ? ? ? 48 89 82 ? ? ? ? 65 48 8B 04 25 ? ? ? ? 48 03 38 8B 07 39 05 ? ? ? ? 0F 8F ? ? ? ? 48 8D 05 ? ? ? ? 48 8D 0D ? ? ? ? 48 89 05 ? ? ? ? E8 ? ? ? ? 48 8D 05 ? ? ? ? 89 35 ? ? ? ? 48 89 05 ? ? ? ? 4C 8D 3D ? ? ? ?")
.FollowNearCallSelf().GetPtr(v_Script_RegisterCommonEnums_Client);
g_GameDll.FindPatternSIMD("48 83 EC 28 83 3D ?? ?? ?? ?? ?? 74 10").GetPtr(v_Script_Remote_BeginRegisteringFunctions);
g_GameDll.FindPatternSIMD("48 89 4C 24 ?? 41 54 48 83 EC 40").GetPtr(v_RestoreRemoteChecksumsFromSaveGame);
}
@ -48,7 +60,7 @@ class VScriptShared : public IDetour
g_nClientRemoteChecksum = CMemory(v_Script_Remote_BeginRegisteringFunctions).Offset(0x0).FindPatternSelf("89 05", CMemory::Direction::DOWN, 150).ResolveRelativeAddressSelf(0x2, 0x6).RCast<uint32_t*>();
}
virtual void GetCon(void) const { }
virtual void Detour(const bool bAttach) const { }
virtual void Detour(const bool bAttach) const;
};
///////////////////////////////////////////////////////////////////////////////

View File

@ -252,8 +252,8 @@ bool CConsole::DrawSurface(void)
const static int colorLoggerWindowFlags =
ImGuiWindowFlags_NoMove |
ImGuiWindowFlags_HorizontalScrollbar |
ImGuiWindowFlags_AlwaysVerticalScrollbar |
ImGuiWindowFlags_NoNavInputs;
ImGuiWindowFlags_NoNavInputs |
ImGuiWindowFlags_OverlayHorizontalScrollbar;
ImGui::BeginChild(m_loggerLabel, ImVec2(0, -footerHeightReserve), loggerFlags, colorLoggerWindowFlags);

View File

@ -6,25 +6,13 @@
//===========================================================================//
#include "core/stdafx.h"
#include "core/logdef.h"
#include "core/init.h"
#include "tier0/crashhandler.h"
#include "tier0/commandline.h"
#include "tier1/strtools.h"
#include "launcher/launcher.h"
#include <eiface.h>
int LauncherMain(HINSTANCE hInstance)
{
// Flush buffers every 5 seconds for every logger.
// Has to be done here, don't move this to SpdLog
// init, as this could cause deadlocks on certain
// compilers (VS2017)!!!
spdlog::flush_every(std::chrono::seconds(5));
int results = v_LauncherMain(hInstance);
Msg(eDLL_T::NONE, "%s returned: %s\n", __FUNCTION__, ExitCodeToString(results));
return results;
}
// Remove all but the last -game parameter.
// This is for mods based off something other than Half-Life 2 (like HL2MP mods).
// The Steam UI does 'steam -applaunch 320 -game c:\steam\steamapps\sourcemods\modname', but applaunch inserts
@ -52,19 +40,6 @@ void RemoveSpuriousGameParameters()
}
}
const char* ExitCodeToString(int nCode)
{
switch (nCode)
{
case EXIT_SUCCESS:
return "EXIT_SUCCESS";
case EXIT_FAILURE:
return "EXIT_FAILURE";
default:
return "UNKNOWN_EXIT_CODE";
}
}
LONG WINAPI TopLevelExceptionFilter(EXCEPTION_POINTERS* pExceptionPointers)
{
// Don't run the unhandled exception filter from the
@ -79,7 +54,6 @@ LONG WINAPI TopLevelExceptionFilter(EXCEPTION_POINTERS* pExceptionPointers)
void VLauncher::Detour(const bool bAttach) const
{
DetourSetup(&v_LauncherMain, &LauncherMain, bAttach);
DetourSetup(&v_TopLevelExceptionFilter, &TopLevelExceptionFilter, bAttach);
DetourSetup(&v_RemoveSpuriousGameParameters, &RemoveSpuriousGameParameters, bAttach);
}

View File

@ -1,12 +1,13 @@
#ifndef LAUNCHER_H
#define LAUNCHER_H
// NOTE: cannot hook this! this function is hooked by loader.dll and is also
// used to gracefully shutdown the SDK.
inline int(*v_LauncherMain)(HINSTANCE hInstance);
inline LONG(*v_TopLevelExceptionFilter)(EXCEPTION_POINTERS* pExceptionPointer);
inline void(*v_RemoveSpuriousGameParameters)(void);
const char* ExitCodeToString(int nCode);
///////////////////////////////////////////////////////////////////////////////
class VLauncher : public IDetour
{

View File

@ -39,10 +39,14 @@ static const IMAGE_DOS_HEADER* s_DosHeader = nullptr;
static const IMAGE_NT_HEADERS64* s_NtHeaders = nullptr;
static HMODULE s_SdkModule = NULL;
typedef void (*InitFunc)(void);
static InitFunc s_SdkInitFunc = NULL;
static InitFunc s_SdkShutdownFunc = NULL;
//-----------------------------------------------------------------------------
// WinMain function pointer
// LauncherMain function pointer
//-----------------------------------------------------------------------------
static int (*v_WinMain)(HINSTANCE, HINSTANCE, LPSTR, int) = nullptr;
static int (*v_LauncherMain)(HINSTANCE, HINSTANCE, LPSTR, int) = nullptr;
//-----------------------------------------------------------------------------
// Purpose: Terminates the process with an error when called
@ -100,16 +104,49 @@ static void InitGameSDK(const LPSTR lpCmdLine)
{
Assert(0);
FatalError("Failed to load SDK: error code = %08x\n", GetLastError());
return;
}
s_SdkInitFunc = (InitFunc)GetProcAddress(s_SdkModule, "SDK_Init");
if (s_SdkInitFunc)
s_SdkShutdownFunc = (InitFunc)GetProcAddress(s_SdkModule, "SDK_Shutdown");
if (!s_SdkInitFunc || !s_SdkShutdownFunc)
{
Assert(0);
FatalError("Loaded SDK is invalid: error code = %08x\n", GetLastError());
return;
}
s_SdkInitFunc();
}
//-----------------------------------------------------------------------------
// Purpose: Unloads the SDK module
//-----------------------------------------------------------------------------
static void ShutdownGameSDK()
{
if (s_SdkModule)
{
s_SdkShutdownFunc();
FreeLibrary(s_SdkModule);
s_SdkModule = NULL;
}
}
//-----------------------------------------------------------------------------
// Purpose: WinMain hook; loads the SDK before LauncherMain
// Purpose: LauncherMain hook; loads the SDK before the game inits
//-----------------------------------------------------------------------------
int WINAPI hWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
int WINAPI hLauncherMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
InitGameSDK(lpCmdLine); // Init GameSDK, internal function calls LauncherMain.
return v_WinMain(hInstance, hPrevInstance, lpCmdLine, nShowCmd);
const int ret = v_LauncherMain(hInstance, hPrevInstance, lpCmdLine, nShowCmd);
ShutdownGameSDK();
return ret;
}
//-----------------------------------------------------------------------------
@ -120,7 +157,7 @@ static void AttachEP()
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&v_WinMain, &hWinMain);
DetourAttach(&v_LauncherMain, &hLauncherMain);
HRESULT hr = DetourTransactionCommit();
if (hr != NO_ERROR) // Failed to hook into the process, terminate...
@ -138,7 +175,7 @@ static void DetachEP()
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&v_WinMain, &hWinMain);
DetourDetach(&v_LauncherMain, &hLauncherMain);
HRESULT hr = DetourTransactionCommit();
Assert(hr != NO_ERROR);
@ -159,7 +196,7 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
s_NtHeaders = (IMAGE_NT_HEADERS64*)((uintptr_t)s_DosHeader
+ (uintptr_t)s_DosHeader->e_lfanew);
v_WinMain = CModule::GetExportedSymbol((QWORD)s_DosHeader, "WinMain")
v_LauncherMain = CModule::GetExportedSymbol((QWORD)s_DosHeader, "LauncherMain")
.RCast<int (*)(HINSTANCE, HINSTANCE, LPSTR, int)>();
AttachEP();
@ -168,9 +205,6 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
case DLL_PROCESS_DETACH:
{
if (s_SdkModule)
FreeLibrary(s_SdkModule);
DetachEP();
break;
}

View File

@ -4059,11 +4059,6 @@ void MathLib_Init(float gamma, float texGamma, float brightness, int overbright)
// FIXME: Hook SSE into VectorAligned + Vector4DAligned
#if !defined( _GAMECONSOLE )
CheckCPUforSSE2();
#endif //!360
s_bMathlibInitialized = true;
InitSinCosTable();

View File

@ -1,4 +1,16 @@
cmake_minimum_required( VERSION 3.16 )
add_module( "lib" "LiveAPI_Pb" "vpc" ${FOLDER_CONTEXT} FALSE TRUE )
start_sources()
add_sources( SOURCE_GROUP "Runtime"
"events.pb.cc"
"events.pb.h"
)
end_sources()
thirdparty_suppress_warnings()
add_module( "lib" "SigCache_Pb" "vpc" ${FOLDER_CONTEXT} FALSE TRUE )
start_sources()

22396
src/protoc/events.pb.cc Normal file

File diff suppressed because it is too large Load Diff

25973
src/protoc/events.pb.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -548,15 +548,11 @@ struct PakDecoder_t
size_t bufferSizeNeeded;
union
{
// current byte and current bit of byte
uint64_t currentByte;
};
// current byte and current bit of byte
uint64_t currentByte;
uint32_t currentBit;
uint32_t dword6C;
uint32_t dword6C;
uint64_t qword70;
union

View File

@ -161,6 +161,38 @@ template<class T> inline void AssertValidReadWritePtr(T* /*ptr*/, int count = 1)
#define AssertValidThis()
#endif
//-----------------------------------------------------------------------------
// Macro to protect functions that are not reentrant
#ifdef _DEBUG
class CReentryGuard
{
public:
CReentryGuard(int* pSemaphore)
: m_pSemaphore(pSemaphore)
{
++(*m_pSemaphore);
}
~CReentryGuard()
{
--(*m_pSemaphore);
}
private:
int* m_pSemaphore;
};
#define ASSERT_NO_REENTRY() \
static int fSemaphore##__LINE__; \
Assert( !fSemaphore##__LINE__ ); \
CReentryGuard ReentryGuard##__LINE__( &fSemaphore##__LINE__ )
#else
#define ASSERT_NO_REENTRY()
#endif
#define AssertMsg(condition, ...) assert(condition)
typedef void (*CoreMsgVCallbackSink_t)(LogType_t logType, LogLevel_t logLevel, eDLL_T context,
const char* pszLogger, const char* pszFormat, va_list args, const UINT exitCode, const char* pszUptimeOverride);

View File

@ -30,18 +30,56 @@ struct JobContext_s
__int64 unknownInt;
};
typedef struct JobUserData_s
{
JobUserData_s(int32_t si)
{
data.sint = si;
}
JobUserData_s(uint32_t ui)
{
data.uint = ui;
}
JobUserData_s(int64_t si)
{
data.sint = si;
}
JobUserData_s(uint64_t ui)
{
data.uint = ui;
}
JobUserData_s(double sa)
{
data.scal = sa;
}
JobUserData_s(void* pt)
{
data.ptr = pt;
}
union
{
int64_t sint;
uint64_t uint;
double scal;
void* ptr;
} data;
} JobUserData_t;
// Array size = 2048*sizeof(JobContext_s)
inline JobContext_s* job_JT_Context = nullptr;
extern bool JT_IsJobDone(const JobID_t jobId);
extern JobID_t JTGuts_AddJob(JobTypeID_t jobTypeId, JobID_t jobId, void* callbackFunc, void* callbackArg);
extern JobID_t JT_GetCurrentJob();
inline void(*JT_ParallelCall)(void);
inline void*(*JT_HelpWithAnything)(bool bShouldLoadPak);
inline bool(*JT_HelpWithJobTypes)(JobHelpCallback_t, JobFifoLock_s* pFifoLock, __int64 a3, __int64 a4);
inline __int64(*JT_HelpWithJobTypesOrSleep)(JobHelpCallback_t, JobFifoLock_s* pFifoLock, __int64 a3, __int64 a4, volatile signed __int64* a5, char a6);
inline bool(*JT_HelpWithJobTypes)(JobHelpCallback_t, JobUserData_t userData, __int64 a3, __int64 a4);
inline __int64(*JT_HelpWithJobTypesOrSleep)(JobHelpCallback_t, JobUserData_t userData, __int64 a3, __int64 a4, volatile signed __int64* a5, char a6);
inline __int64(*JT_WaitForJobAndOnlyHelpWithJobTypes)(JobID_t, uint64_t unkMask1, uint64_t unkMask2);
inline bool(*JT_AcquireFifoLockOrHelp)(struct JobFifoLock_s* pFifo);
inline void(*JT_ReleaseFifoLock)(struct JobFifoLock_s* pFifo);
@ -61,6 +99,7 @@ class VJobThread : public IDetour
LogFunAdr("JT_HelpWithAnything", JT_HelpWithAnything);
LogFunAdr("JT_HelpWithJobTypes", JT_HelpWithJobTypes);
LogFunAdr("JT_HelpWithJobTypesOrSleep", JT_HelpWithJobTypesOrSleep);
LogFunAdr("JT_WaitForJobAndOnlyHelpWithJobTypes", JT_WaitForJobAndOnlyHelpWithJobTypes);
LogFunAdr("JT_AcquireFifoLockOrHelp", JT_AcquireFifoLockOrHelp);
LogFunAdr("JT_ReleaseFifoLock", JT_ReleaseFifoLock);
@ -76,6 +115,7 @@ class VJobThread : public IDetour
g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 30 80 3D ?? ?? ?? ?? ??").GetPtr(JT_HelpWithAnything);
g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 4C 89 4C 24 ?? 4C 89 44 24 ?? 55 56 57 41 54 41 55 41 56 41 57 48 83 EC 60").GetPtr(JT_HelpWithJobTypes);
g_GameDll.FindPatternSIMD("4C 89 4C 24 ?? 4C 89 44 24 ?? 48 89 54 24 ?? 48 89 4C 24 ?? 55 53 56 57 41 54 41 55 41 56 41 57 48 8D 6C 24 ??").GetPtr(JT_HelpWithJobTypesOrSleep);
g_GameDll.FindPatternSIMD("48 89 6C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 41 56 48 83 EC 30 8B F9").GetPtr(JT_WaitForJobAndOnlyHelpWithJobTypes);
g_GameDll.FindPatternSIMD("48 83 EC 08 65 48 8B 04 25 ?? ?? ?? ?? 4C 8B C1").GetPtr(JT_AcquireFifoLockOrHelp);
g_GameDll.FindPatternSIMD("48 83 EC 28 44 8B 11").GetPtr(JT_ReleaseFifoLock);
g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 41 56 48 83 EC 30 65 48 8B 04 25 ?? ?? ?? ?? BA ?? ?? ?? ??").GetPtr(JT_AllocateJob);

View File

@ -1,6 +1,9 @@
#ifndef THREADTOOLS_H
#define THREADTOOLS_H
#include "dbg.h"
#ifndef BUILDING_MATHLIB
#include "jobthread.h"
#endif // BUILDING_MATHLIB
inline void ThreadSleep(unsigned nMilliseconds)
{
@ -116,16 +119,14 @@ FORCEINLINE ThreadId_t ThreadGetCurrentId()
extern ThreadId_t* g_ThreadMainThreadID;
extern ThreadId_t* g_ThreadServerFrameThreadID;
inline JobID_t* g_CurrentServerFrameJobID;
inline JobID_t* g_AllocatedServerFrameJobID;
FORCEINLINE bool ThreadInMainThread()
{
return (ThreadGetCurrentId() == (*g_ThreadMainThreadID));
}
FORCEINLINE bool ThreadInServerFrameThread()
{
return (ThreadGetCurrentId() == (*g_ThreadServerFrameThreadID));
}
PLATFORM_INTERFACE bool ThreadInMainThread();
PLATFORM_INTERFACE bool ThreadInServerFrameThread();
PLATFORM_INTERFACE bool ThreadInMainOrServerFrameThread();
PLATFORM_INTERFACE bool ThreadCouldDoServerWork();
PLATFORM_INTERFACE void ThreadJoinServerJob();
#endif // !BUILDING_MATHLIB
@ -263,7 +264,7 @@ typedef CInterlockedIntT<unsigned> CInterlockedUInt;
#ifndef BUILDING_MATHLIB
//=============================================================================
inline ThreadId_t(*v_DeclareCurrentThreadIsMainThread)(void);
#endif // !BUILDING_MATHLIB
@ -431,9 +432,10 @@ FORCEINLINE bool CThreadSpinRWLock::TryLockForWrite()
if (!(curValue.m_i32 & 0x00010000) && ThreadInterlockedAssignIf((LONG*)&curValue.m_i32, 0x00010000, 0))
{
ThreadMemoryBarrier();
Assert(m_iWriteDepth == 0 && m_writerId == 0);
Assert(m_writerId == 0);
m_writerId = ThreadGetCurrentId();
#ifdef REENTRANT_THREAD_SPIN_RW_LOCK
Assert(m_iWriteDepth == 0);
m_iWriteDepth++;
#endif
return true;
@ -561,15 +563,20 @@ class VThreadTools : public IDetour
{
virtual void GetAdr(void) const
{
LogFunAdr("DeclareCurrentThreadIsMainThread", v_DeclareCurrentThreadIsMainThread);
LogVarAdr("g_ThreadMainThreadID", g_ThreadMainThreadID);
LogVarAdr("g_ThreadServerFrameThreadID", g_ThreadServerFrameThreadID);
LogVarAdr("g_CurrentServerFrameJobID", g_CurrentServerFrameJobID);
LogVarAdr("g_AllocatedServerFrameJobID", g_AllocatedServerFrameJobID);
}
virtual void GetFun(void) const
virtual void GetFun(void) const { }
virtual void GetVar(void) const
{
g_GameDll.FindPatternSIMD("48 83 EC 28 FF 15 ?? ?? ?? ?? 89 05 ?? ?? ?? ?? 48 83 C4 28").GetPtr(v_DeclareCurrentThreadIsMainThread);
g_GameDll.FindPatternSIMD("66 89 54 24 ?? 53 55 56 57 41 54 48 81 EC ?? ?? ?? ??")
.FindPatternSelf("39 05").ResolveRelativeAddressSelf(2, 6).GetPtr(g_CurrentServerFrameJobID);
g_GameDll.FindPatternSIMD("48 83 EC 28 FF 15 ?? ?? ?? ?? 8B 0D ?? ?? ?? ??")
.FindPatternSelf("8B 0D").ResolveRelativeAddressSelf(2, 6).GetPtr(g_AllocatedServerFrameJobID);
}
virtual void GetVar(void) const { }
virtual void GetCon(void) const { }
virtual void Detour(const bool /*bAttach*/) const { }
};

View File

@ -122,6 +122,7 @@ int CompareIPv6(const IN6_ADDR& ipA, const IN6_ADDR& ipB);
/////////////////////////////////////////////////////////////////////////////
// Time
uint64_t GetUnixTimeStamp();
std::chrono::nanoseconds IntervalToDuration(const float flInterval);
/////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,31 @@
//=============================================================================//
//
// Purpose: simple class that could be used to manage depths of nested elements
//
//=============================================================================//
#ifndef TIER1_DEPTHCOUNTER_H
#define TIER1_DEPTHCOUNTER_H
template<class T>
class CDepthCounter
{
public:
CDepthCounter(T& counter) : ref(counter)
{
ref++;
}
~CDepthCounter()
{
ref--;
}
T Get()
{
return ref;
}
private:
T& ref;
};
#endif // TIER1_DEPTHCOUNTER_H

View File

@ -90,6 +90,10 @@ ssize_t V_vsnprintfRet(char* pDest, size_t maxLen, const char* pFormat, va_list
// Strip white space at the beginning and end of a string
ssize_t V_StrTrim(char* pStr);
class CUtlStringList;
void V_SplitString2(const char* pString, const char** pSeparators, ssize_t nSeparators, CUtlStringList& outStrings);
void V_SplitString(const char* pString, const char* pSeparator, CUtlStringList& outStrings);
int V_UTF8ToUnicode(const char* pUTF8, wchar_t* pwchDest, int cubDestSizeInBytes);
int V_UnicodeToUTF8(const wchar_t* pUnicode, char* pUTF8, int cubDestSizeInBytes);

1299
src/public/tier1/utlhash.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -61,14 +61,6 @@ public:
// Copy the array.
CUtlVector<T, A>& operator=(const CUtlVector<T, A>& other);
// NOTE<R5SDK>:
// Do not call after initialization or after adding elements.
// This is added so it could be constructed nicely. Since the
// game executable in monolithic, we couldn't import the malloc
// functions, and thus not construct automatically when using
// the game's memalloc singleton.
void Init();
// element access
T& operator[](int i);
const T& operator[](int i) const;
@ -664,15 +656,6 @@ inline CUtlVector<T, A>& CUtlVector<T, A>::operator=(const CUtlVector<T, A>& oth
return *this;
}
template< typename T, class A >
void CUtlVector<T, A>::Init()
{
m_Memory.m_pMemory = nullptr;
m_Memory.m_nAllocationCount = 0;
m_Memory.m_nGrowSize = 0;
m_Size = 0;
}
//-----------------------------------------------------------------------------
// element access
//-----------------------------------------------------------------------------
@ -1417,24 +1400,23 @@ void CUtlVector<T, A>::Validate(CValidator& validator, char* pchName)
// A vector class for storing pointers, so that the elements pointed to by the pointers are deleted
// on exit.
template<class T> class CUtlVectorAutoPurge : public CUtlVector< T, CUtlMemory< T, int> >
template<class T> class CUtlVectorAutoPurge : public CUtlVector< T >
{
public:
~CUtlVectorAutoPurge(void)
{
this->PurgeAndDeleteElements();
}
};
// easy string list class with dynamically allocated strings. For use with V_SplitString, etc.
// Frees the dynamic strings in destructor.
class CUtlStringList : public CUtlVectorAutoPurge< char*>
class CUtlStringList : public CUtlVectorAutoPurge<char*>
{
public:
void CopyAndAddToTail(char const* pString) // clone the string and add to the end
{
char* pNewStr = new char[1 + strlen(pString)];
char* const pNewStr = new char[strlen(pString) + 1];
strcpy(pNewStr, pString);
AddToTail(pNewStr);
}
@ -1446,27 +1428,25 @@ public:
CUtlStringList() {}
// !TODO:
CUtlStringList(char const* pString, char const* pSeparator)
{
SplitString(pString, pSeparator);
}
//CUtlStringList(char const* pString, char const* pSeparator)
//{
// SplitString(pString, pSeparator);
//}
CUtlStringList(char const* pString, const char** pSeparators, ssize_t nSeparators)
{
SplitString2(pString, pSeparators, nSeparators);
}
//CUtlStringList(char const* pString, const char** pSeparators, int nSeparators)
//{
// SplitString2(pString, pSeparators, nSeparators);
//}
void SplitString(char const* pString, char const* pSeparator)
{
V_SplitString(pString, pSeparator, *this);
}
//void SplitString(char const* pString, char const* pSeparator)
//{
// V_SplitString(pString, pSeparator, *this);
//}
//void SplitString2(char const* pString, const char** pSeparators, int nSeparators)
//{
// V_SplitString2(pString, pSeparators, nSeparators, *this);
//}
void SplitString2(char const* pString, const char** pSeparators, ssize_t nSeparators)
{
V_SplitString2(pString, pSeparators, nSeparators, *this);
}
private:
CUtlStringList(const CUtlStringList& other); // copying directly will cause double-release of the same strings; maybe we need to do a deep copy, but unless and until such need arises, this will guard against double-release
};

View File

@ -0,0 +1,144 @@
//===========================================================================//
//
// Purpose: WebSocket implementation
//
//===========================================================================//
#ifndef TIER2_WEBSOCKET_H
#define TIER2_WEBSOCKET_H
#define WEBSOCKET_DEFAULT_BUFFER_SIZE 1024
//-----------------------------------------------------------------------------
// forward declarations
//-----------------------------------------------------------------------------
struct ProtoWebSocketRefT;
class CWebSocket
{
public:
enum ConnState_e
{
// The socket has to be created and setup
CS_CREATE = 0,
// The socket connection is established
CS_CONNECTED,
// The socket is listening for data
CS_LISTENING,
// The socket is destroyed and deallocated (if retries are set, the
// code will set the state to 'CS_RETRY' and reattempt to establish
// a connection up to ConnParams_s::maxRetries times
CS_DESTROYED,
// The socket was destroyed and deallocated, and marked for a retry
// attempt
CS_RETRY,
// The socket was destroyed and deallocated, and is marked unavailable.
// the code will remove this connection from the list and no further
// attempts will be made
CS_UNAVAIL
};
//-------------------------------------------------------------------------
// Connection parameters for the system & each individual connection, if
// these are changed, call CWebSocket::UpdateParams() to apply the new
// parameters on the system and each connection
//-------------------------------------------------------------------------
struct ConnParams_s
{
ConnParams_s()
{
bufSize = WEBSOCKET_DEFAULT_BUFFER_SIZE;
retryTime = 0.0f;
maxRetries = 0;
timeOut = -1;
keepAlive = -1;
laxSSL = 0;
}
// Total amount of buffer size that could be queued up and sent
int32_t bufSize;
// Total amount of time between each connection attempt
float retryTime;
// Maximum number of retries
// NOTE: the initial attempt is not counted as a retry attempt; if this
// field is set to 5, then the code will perform 1 connection attempt +
// 5 retries before giving up and marking this connection as unavailable
int32_t maxRetries;
// Total amount of time in seconds before the connection is timing out
int32_t timeOut;
// Time interval in seconds for the periodical keepalive pong message
int32_t keepAlive;
// Whether to validate the clients certificate, if this is set, no
// validation is performed
int32_t laxSSL;
};
//-------------------------------------------------------------------------
// Represents an individual socket connection
//-------------------------------------------------------------------------
struct ConnContext_s
{
ConnContext_s(const char* const addr)
{
webSocket = nullptr;
address = addr;
state = CS_CREATE;
tryCount = 0;
lastQueryTime = 0;
}
bool Connect(const double queryTime, const ConnParams_s& params);
bool Process(const double queryTime);
void SetParams(const ConnParams_s& params);
void Disconnect();
void Reconnect();
void Destroy();
ProtoWebSocketRefT* webSocket;
ConnState_e state;
int tryCount; // Number of connection attempts
double lastQueryTime;
CUtlString address;
};
CWebSocket();
bool Init(const char* const addressList, const ConnParams_s& params, const char*& initError);
void Shutdown();
bool UpdateAddressList(const char* const addressList);
void UpdateParams(const ConnParams_s& params);
void Update();
void DeleteUnavailable();
void DisconnectAll();
void ReconnectAll();
void ClearAll();
void SendData(const char* const dataBuf, const int32_t dataSize);
bool IsInitialized() const;
private:
bool m_initialized;
ConnParams_s m_connParams;
CUtlVector<ConnContext_s> m_addressList;
};
#endif // TIER2_WEBSOCKET_H

View File

@ -15,17 +15,6 @@ DECLARE_POINTER_HANDLE(HSCRIPT);
typedef int ScriptDataType_t;
typedef void* ScriptFunctionBindingStorageType_t;
enum ScriptLanguage_t
{
SL_NONE,
SL_GAMEMONKEY,
SL_SQUIRREL,
SL_LUA,
SL_PYTHON,
SL_DEFAULT = SL_SQUIRREL
};
//---------------------------------------------------------
enum ExtendedFieldType

View File

@ -0,0 +1,781 @@
//////////////////////////////////////////////////////////////////////
// Apex Legends Live API
// Copyright 2023 Respawn Entertainment
//
// Contains all messages used by LiveAPI with annotations as comments
// See readme.txt for more information on how to consume this file
//////////////////////////////////////////////////////////////////////
syntax = "proto3";
package rtech.liveapi;
//////////////////////////////////////////////////////////////////////
// Intermediary messages:
// Not used directly, but as part of other messages
//////////////////////////////////////////////////////////////////////
message Vector3
{
float x = 1;
float y = 2;
float z = 3;
}
message Player
{
string name = 1;
uint32 teamId = 2;
Vector3 pos = 3;
Vector3 angles = 4;
uint32 currentHealth = 5;
uint32 maxHealth = 6;
uint32 shieldHealth = 7;
uint32 shieldMaxHealth = 8;
string nucleusHash = 9;
string hardwareName = 10;
string teamName = 11;
uint32 squadIndex = 12;
string character = 13;
string skin = 14;
}
message CustomMatch_LobbyPlayer
{
string name = 1;
uint32 teamId = 2;
string nucleusHash = 3;
string hardwareName = 4;
}
message Datacenter
{
uint64 timestamp = 1;
string category = 2;
string name = 3;
}
message Version
{
uint32 major_num = 1;
uint32 minor_num = 2;
uint32 build_stamp = 3;
string revision = 4;
}
message InventoryItem
{
int32 quantity = 1;
string item = 2;
// any mods or additional info on the item
string extraData = 3;
}
message LoadoutConfiguration
{
repeated InventoryItem weapons = 1;
repeated InventoryItem equipment = 2;
}
//////////////////////////////////////////////////////////////////////
// Output messages:
// Game events that describe the ongoing state of the match
// Every message will have a timestamp and category
//////////////////////////////////////////////////////////////////////
// Traffic initialization
// This message is sent upon successfully connecting over WebSockets
message Init
{
uint64 timestamp = 1;
string category = 2;
string gameVersion = 3;
Version apiVersion = 4;
string platform = 5;
// Named specified by `liveapi_session_name`
string name = 6;
}
// Response to the CustomMatch_GetLobbyPlayers
// Contains the list of all players in the lobby
message CustomMatch_LobbyPlayers
{
string playerToken = 1;
repeated CustomMatch_LobbyPlayer players = 2;
}
/////////////////////////////////////////
// Observer Events
/////////////////////////////////////////
// Event when the observer camera switches from viewing one player to another
message ObserverSwitched
{
uint64 timestamp = 1;
string category = 2;
Player observer = 3;
Player target = 4;
repeated Player targetTeam = 5;
}
// Used by observers to annotate events uniquely
message ObserverAnnotation
{
uint64 timestamp = 1;
string category = 2;
int32 annotationSerial = 3;
}
/////////////////////////////////////////
// Match Information
/////////////////////////////////////////
// Sent during the first phase of a match. This event gives a full description of what match is being played
message MatchSetup
{
uint64 timestamp = 1;
string category = 2;
string map = 3;
string playlistName = 4;
string playlistDesc = 5;
Datacenter datacenter = 6;
bool aimAssistOn = 7;
bool anonymousMode = 8;
string serverId = 9;
LoadoutConfiguration startingLoadout = 10;
}
// Sent whenever the match changes phases (e.g. prematch, playing)
message GameStateChanged
{
uint64 timestamp = 1;
string category = 2;
string state = 3;
}
// Occurs when any player has locked in a character during legend select
message CharacterSelected
{
uint64 timestamp = 1;
string category = 2;
Player player = 3;
}
// Event to summarize the match after it has ended
message MatchStateEnd
{
uint64 timestamp = 1;
string category = 2;
string state = 3;
repeated Player winners = 4;
}
// Fired whenever the ring begins moving in a match
message RingStartClosing
{
uint64 timestamp = 1;
string category = 2;
uint32 stage = 3;
Vector3 center = 4;
float currentRadius = 5;
float endRadius = 6;
float shrinkDuration= 7;
}
// Used when the ring has finished moving and prior to it moving again
message RingFinishedClosing
{
uint64 timestamp = 1;
string category = 2;
uint32 stage = 3;
Vector3 center = 4;
float currentRadius = 5;
float shrinkDuration= 7;
}
// Used when a player has connected to the match
message PlayerConnected
{
uint64 timestamp = 1;
string category = 2;
Player player = 3;
}
// Used when a player has disconnected, even temporarily
// `canReconnect` will indicate if the player is able to reconnect or has forfeited
message PlayerDisconnected
{
uint64 timestamp = 1;
string category = 2;
Player player = 3;
bool canReconnect = 4;
bool isAlive = 5;
}
// Generic event for a change in the player stats
// Common stat names that can come with this event include "knockdowns", "revivesGiven", "kills"
message PlayerStatChanged
{
uint64 timestamp = 1;
string category = 2;
Player player = 3;
string statName = 4;
oneof newValue // R5R: formerly of type `uint32`
{
uint32 intValue = 5;
float floatValue= 6;
bool boolValue = 7;
}
}
// Event used to notify when a player goes above their current tier level
// Tier levels start at 1. Following this event, players may have Upgrades to their legend
// Selection of upgrades will produce a separate `LegendUpgradeSelected` event
message PlayerUpgradeTierChanged
{
uint64 timestamp = 1;
string category = 2;
Player player = 3;
int32 level = 4;
}
/////////////////////////////////////////
// Combat events
/////////////////////////////////////////
// Event describing a player taking damage
// Details include the attacker, victim, the weapon used and the amount of damage
message PlayerDamaged
{
uint64 timestamp = 1;
string category = 2;
Player attacker = 3;
Player victim = 4;
string weapon = 5;
uint32 damageInflicted = 6;
}
// Sent when a player is killed. Details are similar to PlayerDamaged event
// The `awardedTo` field describes the player that the kill is given to
message PlayerKilled
{
uint64 timestamp = 1;
string category = 2;
Player attacker = 3;
Player victim = 4;
Player awardedTo = 5;
string weapon = 6;
}
// Event describing a player that has been downed after taking sufficient damage
// Similar to PlayerDamaged, but may not be sent in certain game modes (e.g. Control)
message PlayerDowned
{
uint64 timestamp = 1;
string category = 2;
Player attacker = 3;
Player victim = 4;
string weapon = 5;
}
// Sent when a player is killed if there is an assist awarded
// This event may come in rapid succession to the PlayerKilled event with a corresponding `victim` field
message PlayerAssist
{
uint64 timestamp = 1;
string category = 2;
Player assistant = 3;
Player victim = 4;
string weapon = 5;
}
// Occurs when the entire squad in a game has been eliminated
// The event contains all player in said squad. May not occur in certain game modes
message SquadEliminated
{
uint64 timestamp = 1;
string category = 2;
repeated Player players = 3;
}
// Occurs when Gibraltars shield has taken any enemy damage
// The field `damageInflicted` will indicate how much was absorbed by the shield
message GibraltarShieldAbsorbed
{
uint64 timestamp = 1;
string category = 2;
Player attacker = 3;
Player victim = 4;
uint32 damageInflicted = 6;
}
// Occurs when Revenant, while using his Forged Shadows ultimate, takes any enemy damage
// This event is distinct from `PlayerDamaged` since the player may receive no actual damage if the shadow is able to absorb it
// The field `damageInflicted` will indicate how much damage (in total) was dealt
// If there is any leftover damage that goes affects the player, that amount will be what is registered in a different `PlayerDamaged` event
message RevenantForgedShadowDamaged
{
uint64 timestamp = 1;
string category = 2;
Player attacker = 3;
Player victim = 4;
uint32 damageInflicted = 6;
}
/////////////////////////////////////////
// Interaction events
/////////////////////////////////////////
// Sent when a player is respawned and comes back into game
// For example, when using a respawn beacon
message PlayerRespawnTeam
{
uint64 timestamp = 1;
string category = 2;
Player player = 3;
repeated Player respawned = 4; // R5R: formerly of type `string`
}
// Occurs when a player finishes assisting a downed player
// May not be sent in certain game modes (e.g. Control)
message PlayerRevive
{
uint64 timestamp = 1;
string category = 2;
Player player = 3;
Player revived = 4;
}
// Specific Arenas-only event that occurs when players select an item
message ArenasItemSelected
{
uint64 timestamp = 1;
string category = 2;
Player player = 3;
string item = 4;
int32 quantity = 5;
}
// Specific Arenas-only event that occurs when players deselect an item
message ArenasItemDeselected
{
uint64 timestamp = 1;
string category = 2;
Player player = 3;
string item = 4;
int32 quantity = 5;
}
// Event that occurs when a player has picked up loot into their inventory
message InventoryPickUp
{
uint64 timestamp = 1;
string category = 2;
Player player = 3;
string item = 4;
int32 quantity = 5;
}
// Event that occurs when a player has dropped loot from their inventory
// The item itself may have attachments that will be described in the `extraData` field
message InventoryDrop
{
uint64 timestamp = 1;
string category = 2;
Player player = 3;
string item = 4;
int32 quantity = 5;
repeated string extraData = 6;
}
// Used to indicate the player has used a consumable item (e.g. syringe, shield cell) from their inventory
message InventoryUse
{
uint64 timestamp = 1;
string category = 2;
Player player = 3;
string item = 4;
int32 quantity = 5;
}
// Event used when a teammate banner has been picked up
message BannerCollected
{
uint64 timestamp = 1;
string category = 2;
Player player = 3;
Player collected = 4;
}
// Used to indicate that the player has activated one of their legend's abilities
// The ability can be a Tactical or an Ultimate and is decribed in the `linkedEntity` field
// For example: `linkedEntity: "Tactical (Eye of the Allfather)"` for Bloodhound's tactical
message PlayerAbilityUsed
{
uint64 timestamp = 1;
string category = 2;
Player player = 3;
string linkedEntity = 4;
}
// Signals that a player has selected an upgrade at a particular tier level
// Updates to their tier level will be sent as a PlayerUpgradeTierChanged event
message LegendUpgradeSelected
{
uint64 timestamp = 1;
string category = 2;
Player player = 3;
string upgradeName = 4;
string upgradeDesc = 5;
int32 level = 6;
}
// Indicates that a player has started using the zipline
message ZiplineUsed
{
uint64 timestamp = 1;
string category = 2;
Player player = 3;
string linkedEntity = 4;
}
// Used to indicate that a player has tossed a grenade
// The `linkedEntity` will describe the grenade in further detail and it may be a legend's Ability
// For example: `linkedEntity: "Ultimate (Rolling Thunder)"` for Bangalore's Ultimate ability
message GrenadeThrown
{
uint64 timestamp = 1;
string category = 2;
Player player = 3;
string linkedEntity = 4;
}
// Event specifying that a player has picked up loot from Loba's Black Market
// This event may fire in quick succession to the InventoryPickUp event
message BlackMarketAction
{
uint64 timestamp = 1;
string category = 2;
Player player = 3;
string item = 4;
}
// Used to indicate a player has traversed a Wraith Portal
message WraithPortal
{
uint64 timestamp = 1;
string category = 2;
Player player = 3;
}
// Used to indicate a player has traversed a Warp Gate
message WarpGateUsed
{
uint64 timestamp = 1;
string category = 2;
Player player = 3;
}
// Used to indicate that a player has used ammo
// This event may not fire immediately and updates may be batched to save bandwidth
message AmmoUsed
{
uint64 timestamp = 1;
string category = 2;
Player player = 3;
string ammoType = 4;
uint32 amountUsed = 5;
uint32 oldAmmoCount = 6;
uint32 newAmmoCount = 7;
}
// Used to indicate that a player has switched weapons, either to a weapon in their inventory or swapped with a weapon on the ground
message WeaponSwitched
{
uint64 timestamp = 1;
string category = 2;
Player player = 3;
string oldWeapon = 4;
string newWeapon = 5;
}
/////////////////////////////////////////
// Custom events
/////////////////////////////////////////
import "google/protobuf/struct.proto";
// Event defining custom user data that is otherwise too specific to create dedicated messages for
message CustomEvent
{
uint64 timestamp = 1;
string category = 2;
string name = 3;
google.protobuf.Struct data = 4;
}
//////////////////////////////////////////////////////////////////////
// Input messages:
// Used by observers to programmatically interact with the game
//////////////////////////////////////////////////////////////////////
// Enum used to quickly described the target of a ChangeCamera operation
enum PlayerOfInterest
{
UNSPECIFIED = 0;
// cycle through known Players in a team
NEXT = 1;
PREVIOUS = 2;
// Go to an interesting player
KILL_LEADER = 3;
CLOSEST_ENEMY = 4;
CLOSEST_PLAYER = 5;
LATEST_ATTACKER = 6;
}
// Request to change the observer camera
// If changing by a target's name, be aware that the
// - server may skip the request if the player is not actively in the game (i.e. waiting for reconnect, downed or killed)
// - If the string is longer than 256 characters, the request will fail
message ChangeCamera
{
oneof target
{
// Set the camera to an interesting player (e.g. the Kill Leader)
PlayerOfInterest poi = 1;
// Change camera to a player by name
string name = 2;
}
}
// Request message to toggle pause in a match type that supports it
message PauseToggle
{
float preTimer = 1;
}
// Request to create a custom match lobby
message CustomMatch_CreateLobby
{
}
// Request to join an existing custom match lobby identified by the `roleToken`
message CustomMatch_JoinLobby
{
string roleToken = 1;
}
// Request to leave a custom match lobby
message CustomMatch_LeaveLobby
{
}
// Request to programatically change your player's ready state in a custom match lobby
message CustomMatch_SetReady
{
bool isReady = 1;
}
// Request to retrieve all connected players in a custom match lobby
message CustomMatch_GetLobbyPlayers
{
}
// Request to change the state of matchmaking in a custom match lobby
// When enabled is True, the lobby will attempt to being a match
message CustomMatch_SetMatchmaking
{
bool enabled = 1;
}
// Request to assign a particular player to a specific team
// Note that the `targetHardwareName` and `targetNucleusHash` can be obtained from a prior request to CustomMatch_GetLobbyPlayers
// If the parameters do not match any lobby player, the request is ignored
// The `teamId` is across the entire lobby. Meaning, observers have a teamId of 0 and match players will be teamId of 1 and upwards
message CustomMatch_SetTeam
{
int32 teamId = 1;
string targetHardwareName = 2;
string targetNucleusHash = 3;
}
// Request to remove a player from the currently connected custom match lobby
message CustomMatch_KickPlayer
{
string targetHardwareName = 1;
string targetNucleusHash = 2;
}
// Request to alter the settings of a custom match lobby
// Your request should specify all fields being set with the new value
// For convinience, call `CustomMatch_GetSettings` to get the full state of settings
message CustomMatch_SetSettings
{
string playlistName = 1;
bool adminChat = 2;
bool teamRename = 3;
bool selfAssign = 4;
bool aimAssist = 5;
bool anonMode = 6;
}
// Review all the current settings. This request will be replied to with
// `CustomMatch_SetSettings` from which you can modify and reply with any new values for your convenience
message CustomMatch_GetSettings
{
}
// Request to set the name of a team in custom match lobby
// Requires special access and is subject to text filtering
message CustomMatch_SetTeamName
{
int32 teamId = 1;
string teamName = 2;
}
// Request to programatically send a chat message to the entire custom match lobby
message CustomMatch_SendChat
{
string text = 1;
}
// Envelope message for any Live API request
// This allows a single uniform data structure for requests to be made and for the game to receive them
// Specifically, there is only one possible action per request. You can request an acknowledgement of your request by setting `withAck` to true
// Acknowledgements will come in the form of a Response message. More information can be found with that event
//
// A single example to create a CustomMatch_JoinLobby request in python is as follows
// ```
// req = Request()
// req.customMatch_JoinLobby.roleToken = "<some token>"
// req.withAck = True
// ```
// For more information, consult the Protobuf documentation for your language of choice and look at details regarding the `oneof` field (https://protobuf.dev/programming-guides/proto3/#oneof)
message Request
{
// Receive an acknowledgement of the request having been received
bool withAck = 1;
// Preshared key to use with the request. Only necessary if the connecting game has a preshared key specified through `cl_liveapi_requests_psk`
string preSharedKey = 2;
oneof actions
{
ChangeCamera changeCam = 4;
PauseToggle pauseToggle = 5;
// Custom Match specific requests (reserved 10 -> 30)
CustomMatch_CreateLobby customMatch_CreateLobby = 10;
CustomMatch_JoinLobby customMatch_JoinLobby = 11;
CustomMatch_LeaveLobby customMatch_LeaveLobby = 12;
CustomMatch_SetReady customMatch_SetReady = 13;
CustomMatch_SetMatchmaking customMatch_SetMatchmaking = 14;
CustomMatch_SetTeam customMatch_SetTeam = 15;
CustomMatch_KickPlayer customMatch_KickPlayer = 16;
CustomMatch_SetSettings customMatch_SetSettings = 17;
CustomMatch_SendChat customMatch_SendChat = 18;
CustomMatch_GetLobbyPlayers customMatch_GetLobbyPlayers = 19;
CustomMatch_SetTeamName customMatch_SetTeamName = 20;
CustomMatch_GetSettings customMatch_GetSettings = 21;
}
}
//////////////////////////////////////////////////////////////////////
// Reply messages:
// Used by the game to send data to any connected clients
//////////////////////////////////////////////////////////////////////
import "google/protobuf/any.proto";
// Message used to indicate the status of a request
// Generally, it is used to provide a plain text, detailed response in case of failures or problems
message RequestStatus
{
string status = 1;
}
// Message used to indicate the response to a request made to the API
// Only the requesting part will receive this message and this message is only sent if the request required an acknowledgement by setting `withAck` to true in the Request object
// This message is always sent within a LiveAPIEvent and never on its own to allow any applications to have a uniform method of reading events over the wire
// If `success` is true, it does not mean that the Request has finished or that it was completed correctly. In this case, it means that it was successfully received and contains no issues (it is a well-formed request)
// The `result` field may sometimes be populated to give more context around the request, especially in the case of error
// Refer to the LiveAPIEvent message on how to the the Any field
message Response
{
bool success = 1;
google.protobuf.Any result = 2;
}
// Envelope for all LiveAPI Events
// Any game events or responses to requests will be sent using this message. The specific event or message is stored in the `gameMessage` field
// Before proceeding, familiarize yourself with the proto3 `Any` field type at: https://protobuf.dev/programming-guides/proto3/#any
// In order to read the message successfully, check the type contained in `gameMessage` and create an instance of that type where you can unpack the data to
// Protobuf has several ways of doing type to instance lookups that will allow you to do this after you've generated bindings
// For example, to read and unpack any LiveAPIEvent in Python, the following can be done (assume `pb_msg` contains the LiveAPIEvent object)
// ```
// from events_pb2 import *
// from google.protobuf import symbol_database
// [ ... ]
// result_type = pb_msg.gameMessage.TypeName()
// msg_result = symbol_database.Default().GetSymbol(result_type)()
// pb_msg.gameMessage.Unpack(msg_result) # msg_result now holds the actual event you want to read
// ```
message LiveAPIEvent
{
fixed32 event_size = 1;
google.protobuf.Any gameMessage = 3;
}

View File

@ -1,3 +1,4 @@
protoc64 --cpp_out=. sig_map.proto
protoc64 --cpp_out=. sv_rcon.proto
protoc64 --cpp_out=. cl_rcon.proto
protoc64 --cpp_out=. events.proto

View File

@ -34,6 +34,11 @@ add_sources( SOURCE_GROUP "Pak"
"pak/paktools.h"
)
add_sources( SOURCE_GROUP "LiveAPI"
"liveapi/liveapi.cpp"
"liveapi/liveapi.h"
)
add_sources( SOURCE_GROUP "Public"
"${ENGINE_SOURCE_DIR}/public/rtech/iasync.h"
"${ENGINE_SOURCE_DIR}/public/rtech/ipakfile.h"
@ -41,6 +46,11 @@ add_sources( SOURCE_GROUP "Public"
end_sources()
target_include_directories( ${PROJECT_NAME} PRIVATE
"${THIRDPARTY_SOURCE_DIR}/dirtysdk/include/"
"${THIRDPARTY_SOURCE_DIR}/ea/"
)
add_module( "lib" "rson" "vpc" ${FOLDER_CONTEXT} TRUE TRUE )
start_sources()

View File

@ -0,0 +1,299 @@
//===========================================================================//
//
// Purpose: LiveAPI WebSocket implementation
//
//===========================================================================//
#include "liveapi.h"
#include "protobuf/util/json_util.h"
#include "DirtySDK/dirtysock.h"
#include "DirtySDK/dirtysock/netconn.h"
#include "DirtySDK/proto/protossl.h"
#include "DirtySDK/proto/protowebsocket.h"
//-----------------------------------------------------------------------------
// change callbacks
//-----------------------------------------------------------------------------
static void LiveAPI_EnabledChangedCallback(IConVar* var, const char* pOldValue)
{
LiveAPISystem()->ToggleInit();
}
static void LiveAPI_WebSocketEnabledChangedCallback(IConVar* var, const char* pOldValue)
{
LiveAPISystem()->ToggleInitWebSocket();
}
static void LiveAPI_ParamsChangedCallback(IConVar* var, const char* pOldValue)
{
LiveAPISystem()->UpdateParams();
}
static void LiveAPI_AddressChangedCallback(IConVar* var, const char* pOldValue)
{
LiveAPISystem()->RebootWebSocket();
}
//-----------------------------------------------------------------------------
// console variables
//-----------------------------------------------------------------------------
ConVar liveapi_enabled("liveapi_enabled", "0", FCVAR_RELEASE | FCVAR_SERVER_FRAME_THREAD, "Enable LiveAPI functionality", &LiveAPI_EnabledChangedCallback);
ConVar liveapi_session_name("liveapi_session_name", "liveapi_session", FCVAR_RELEASE | FCVAR_SERVER_FRAME_THREAD, "LiveAPI session name to identify this connection");
ConVar liveapi_truncate_hash_fields("liveapi_truncate_hash_fields", "1", FCVAR_RELEASE | FCVAR_SERVER_FRAME_THREAD, "Whether to truncate hash fields in LiveAPI events to save on I/O");
// WebSocket core
static ConVar liveapi_websocket_enabled("liveapi_websocket_enabled", "0", FCVAR_RELEASE | FCVAR_SERVER_FRAME_THREAD, "Whether to use WebSocket to transmit LiveAPI events", &LiveAPI_WebSocketEnabledChangedCallback);
static ConVar liveapi_servers("liveapi_servers", "", FCVAR_RELEASE | FCVAR_SERVER_FRAME_THREAD, "Comma separated list of addresses to connect to", &LiveAPI_AddressChangedCallback, "ws://domain.suffix:port");
// WebSocket connection base parameters
static ConVar liveapi_retry_count("liveapi_retry_count", "5", FCVAR_RELEASE | FCVAR_SERVER_FRAME_THREAD, "Amount of times to retry connecting before marking the connection as unavailable", &LiveAPI_ParamsChangedCallback);
static ConVar liveapi_retry_time("liveapi_retry_time", "30", FCVAR_RELEASE | FCVAR_SERVER_FRAME_THREAD, "Amount of time between each retry", &LiveAPI_ParamsChangedCallback);
// WebSocket connection context parameters
static ConVar liveapi_timeout("liveapi_timeout", "300", FCVAR_RELEASE | FCVAR_SERVER_FRAME_THREAD, "WebSocket connection timeout in seconds", &LiveAPI_ParamsChangedCallback);
static ConVar liveapi_keepalive("liveapi_keepalive", "30", FCVAR_RELEASE | FCVAR_SERVER_FRAME_THREAD, "Interval of time to send Pong to any connected server", &LiveAPI_ParamsChangedCallback);
static ConVar liveapi_lax_ssl("liveapi_lax_ssl", "1", FCVAR_RELEASE | FCVAR_SERVER_FRAME_THREAD, "Skip SSL certificate validation for all WSS connections (allows the use of self-signed certificates)", &LiveAPI_ParamsChangedCallback);
// Print core
static ConVar liveapi_print_enabled("liveapi_print_enabled", "0", FCVAR_RELEASE | FCVAR_SERVER_FRAME_THREAD, "Whether to enable the printing of all events to a LiveAPI JSON file");
// Print parameters
static ConVar liveapi_print_pretty("liveapi_print_pretty", "0", FCVAR_RELEASE | FCVAR_SERVER_FRAME_THREAD, "Whether to print events in a formatted manner to the LiveAPI JSON file");
static ConVar liveapi_print_primitive("liveapi_print_primitive", "0", FCVAR_RELEASE | FCVAR_SERVER_FRAME_THREAD, "Whether to print primitive event fields to the LiveAPI JSON file");
//-----------------------------------------------------------------------------
// constructors/destructors
//-----------------------------------------------------------------------------
LiveAPI::LiveAPI()
{
matchLogCount = 0;
initialLog = false;
initialized = false;
}
LiveAPI::~LiveAPI()
{
}
//-----------------------------------------------------------------------------
// Initialization of the LiveAPI system
//-----------------------------------------------------------------------------
void LiveAPI::Init()
{
if (!liveapi_enabled.GetBool())
return;
InitWebSocket();
initialized = true;
}
//-----------------------------------------------------------------------------
// Shutdown of the LiveAPI system
//-----------------------------------------------------------------------------
void LiveAPI::Shutdown()
{
webSocketSystem.Shutdown();
DestroyLogger();
initialized = false;
}
//-----------------------------------------------------------------------------
// Toggle between init or deinit depending on current init state and the value
// of the cvar 'liveapi_enabled'
//-----------------------------------------------------------------------------
void LiveAPI::ToggleInit()
{
const bool enabled = liveapi_enabled.GetBool();
if (enabled && !initialized)
Init();
else if (!enabled && initialized)
Shutdown();
}
//-----------------------------------------------------------------------------
// Populate the connection params structure
//-----------------------------------------------------------------------------
void LiveAPI::CreateParams(CWebSocket::ConnParams_s& params)
{
params.bufSize = LIVE_API_MAX_FRAME_BUFFER_SIZE;
params.retryTime = liveapi_retry_time.GetFloat();
params.maxRetries = liveapi_retry_count.GetInt();
params.timeOut = liveapi_timeout.GetInt();
params.keepAlive = liveapi_keepalive.GetInt();
params.laxSSL = liveapi_lax_ssl.GetInt();
}
//-----------------------------------------------------------------------------
// Update the websocket parameters and apply them on all connections
//-----------------------------------------------------------------------------
void LiveAPI::UpdateParams()
{
CWebSocket::ConnParams_s connParams;
CreateParams(connParams);
webSocketSystem.UpdateParams(connParams);
}
//-----------------------------------------------------------------------------
// Initialize the websocket system
//-----------------------------------------------------------------------------
void LiveAPI::InitWebSocket()
{
if (!liveapi_websocket_enabled.GetBool())
return;
CWebSocket::ConnParams_s connParams;
CreateParams(connParams);
const char* initError = nullptr;
if (!webSocketSystem.Init(liveapi_servers.GetString(), connParams, initError))
{
Error(eDLL_T::RTECH, 0, "LiveAPI: WebSocket initialization failed! [%s]\n", initError);
return;
}
}
//-----------------------------------------------------------------------------
// Shutdown the websocket system
//-----------------------------------------------------------------------------
void LiveAPI::ShutdownWebSocket()
{
webSocketSystem.Shutdown();
}
//-----------------------------------------------------------------------------
// Toggle between init or deinit depending on current init state and the value
// of the cvar 'liveapi_websocket_enabled'
//-----------------------------------------------------------------------------
void LiveAPI::ToggleInitWebSocket()
{
const bool enabled = liveapi_websocket_enabled.GetBool();
if (enabled && !WebSocketInitialized())
InitWebSocket();
else if (!enabled && WebSocketInitialized())
ShutdownWebSocket();
}
//-----------------------------------------------------------------------------
// Reboot the websocket system and reconnect to addresses specified in cvar
// 'liveapi_servers'
//-----------------------------------------------------------------------------
void LiveAPI::RebootWebSocket()
{
ShutdownWebSocket();
InitWebSocket();
}
//-----------------------------------------------------------------------------
// Create the file logger
//-----------------------------------------------------------------------------
void LiveAPI::CreateLogger()
{
// Its possible that one was already created but never closed, this is
// possible if the game scripts crashed or something along those lines.
DestroyLogger();
if (!liveapi_print_enabled.GetBool())
return; // Logging is disabled
matchLogger = spdlog::basic_logger_mt("match_logger",
Format("platform/liveapi/logs/%s/match_%d.json", g_LogSessionUUID.c_str(), matchLogCount++));
matchLogger.get()->set_pattern("%v");
matchLogger.get()->info("[\n");
}
//-----------------------------------------------------------------------------
// Destroy the file logger
//-----------------------------------------------------------------------------
void LiveAPI::DestroyLogger()
{
if (initialLog)
initialLog = false;
if (!matchLogger)
return; // Nothing to drop
matchLogger.get()->info("\n]\n");
matchLogger.reset();
spdlog::drop("match_logger");
}
//-----------------------------------------------------------------------------
// LiveAPI state machine
//-----------------------------------------------------------------------------
void LiveAPI::RunFrame()
{
if (!IsEnabled())
return;
if (WebSocketInitialized())
webSocketSystem.Update();
}
//-----------------------------------------------------------------------------
// Send an event to all sockets
//-----------------------------------------------------------------------------
void LiveAPI::LogEvent(const google::protobuf::Message* const toTransmit, const google::protobuf::Message* toPrint)
{
if (!IsEnabled())
return;
if (WebSocketInitialized())
{
const string data = toTransmit->SerializeAsString();
webSocketSystem.SendData(data.c_str(), (int)data.size());
}
// NOTE: we don't check on the cvar 'liveapi_print_enabled' here because if
// this cvar gets disabled on the fly and we check it here, the output will
// be truncated and thus invalid! Log for as long as the SpdLog instance is
// valid.
if (matchLogger)
{
std::string jsonStr(initialLog ? ",\n" : "");
google::protobuf::util::JsonPrintOptions options;
options.add_whitespace = liveapi_print_pretty.GetBool();
options.always_print_primitive_fields = liveapi_print_primitive.GetBool();
google::protobuf::util::MessageToJsonString(*toPrint, &jsonStr, options);
// Remove the trailing newline character
if (options.add_whitespace && !jsonStr.empty())
jsonStr.pop_back();
matchLogger.get()->info(jsonStr);
if (!initialLog)
initialLog = true;
}
}
//-----------------------------------------------------------------------------
// Returns whether the system is enabled
//-----------------------------------------------------------------------------
bool LiveAPI::IsEnabled() const
{
return liveapi_enabled.GetBool();
}
//-----------------------------------------------------------------------------
// Returns whether the system is able to run
//-----------------------------------------------------------------------------
bool LiveAPI::IsValidToRun() const
{
return (IsEnabled() && (WebSocketInitialized() || FileLoggerInitialized()));
}
static LiveAPI s_liveApi;
//-----------------------------------------------------------------------------
// Singleton accessor
//-----------------------------------------------------------------------------
LiveAPI* LiveAPISystem()
{
return &s_liveApi;
}

View File

@ -0,0 +1,59 @@
#ifndef RTECH_LIVEAPI_H
#define RTECH_LIVEAPI_H
#include "tier2/websocket.h"
#include "thirdparty/protobuf/message.h"
#define LIVE_API_MAX_FRAME_BUFFER_SIZE 0x8000
extern ConVar liveapi_enabled;
extern ConVar liveapi_session_name;
extern ConVar liveapi_truncate_hash_fields;
struct ProtoWebSocketRefT;
typedef void (*LiveAPISendCallback_t)(ProtoWebSocketRefT* webSocket);
class LiveAPI
{
public:
LiveAPI();
~LiveAPI();
void Init();
void Shutdown();
void ToggleInit();
void CreateParams(CWebSocket::ConnParams_s& params);
void UpdateParams();
void InitWebSocket();
void ShutdownWebSocket();
void ToggleInitWebSocket();
void RebootWebSocket();
void CreateLogger();
void DestroyLogger();
void RunFrame();
void LogEvent(const google::protobuf::Message* const toTransmit, const google::protobuf::Message* toPrint);
bool IsEnabled() const;
bool IsValidToRun() const;
inline bool WebSocketInitialized() const { return webSocketSystem.IsInitialized(); }
inline bool FileLoggerInitialized() const { return matchLogger != nullptr; }
private:
CWebSocket webSocketSystem;
std::shared_ptr<spdlog::logger> matchLogger;
int matchLogCount;
bool initialLog;
bool initialized;
};
LiveAPI* LiveAPISystem();
#endif // RTECH_LIVEAPI_H

191
src/thirdparty/dirtysdk/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,191 @@
cmake_minimum_required( VERSION 3.16 )
add_module( "lib" "DirtySDK" "" ${FOLDER_CONTEXT} TRUE TRUE )
start_sources()
add_sources( SOURCE_GROUP "Platform"
# Core source files
"source/platform/plat-str.c"
"source/platform/plat-time.c"
)
add_sources( SOURCE_GROUP "Comm"
# Core source files
"source/comm/commsrp.c"
"source/comm/commudp.c"
"source/comm/commudputil.c"
)
add_sources( SOURCE_GROUP "Crypto"
# Core source files
"source/crypt/cryptaes.c"
"source/crypt/cryptarc4.c"
"source/crypt/cryptchacha.c"
"source/crypt/cryptcurve.c"
"source/crypt/cryptgcm.c"
"source/crypt/crypthash.c"
"source/crypt/crypthmac.c"
"source/crypt/cryptmd5.c"
"source/crypt/cryptmont.c"
"source/crypt/cryptnist.c"
"source/crypt/cryptrandcommon.c"
"source/crypt/cryptrsa.c"
"source/crypt/cryptsha1.c"
"source/crypt/cryptsha2.c"
# Optional core source files
"source/crypt/cryptbn.c"
# PC plat source files
"source/crypt/cryptrand.c"
)
add_sources( SOURCE_GROUP "Crypto/Include"
# Core include files
"source/crypt/cryptrandpriv.h"
"source/crypt/cryptrandcommon.h"
)
add_sources( SOURCE_GROUP "Socket"
# Core source files
"source/dirtysock/dirtyaddr.c"
"source/dirtysock/dirtycert.c"
"source/dirtysock/dirtyerr.c"
"source/dirtysock/dirtylib.c"
"source/dirtysock/dirtylib.cpp"
"source/dirtysock/dirtymem.c"
"source/dirtysock/dirtynames.c"
"source/dirtysock/dirtynet.c"
"source/dirtysock/dirtythread.cpp"
"source/dirtysock/dirtyuser.c"
"source/dirtysock/netconn.c"
"source/dirtysock/netconncommon.c"
#"source/dirtysock/netconnlocaluser.cpp"
# PC plat source files
"source/dirtysock/dirtyaddr.c"
"source/dirtysock/pc/dirtyerrpc.c"
"source/dirtysock/pc/dirtylibwin.c"
"source/dirtysock/pc/dirtynetwin.c"
"source/dirtysock/pc/netconnwin.c"
)
add_sources( SOURCE_GROUP "Socket/Include"
# Core include files
"source/dirtysock/dirtynetpriv.h"
"source/dirtysock/netconncommon.h"
"source/dirtysock/netconnlocaluser.h"
)
add_sources( SOURCE_GROUP "Game"
# Core source files
"source/game/connapi.c"
"source/game/netgamedist.c"
"source/game/netgamedistserv.c"
"source/game/netgamelink.c"
"source/game/netgameutil.c"
)
add_sources( SOURCE_GROUP "Codec"
# Core source files
"source/graph/dirtygif.c"
"source/graph/dirtygraph.c"
"source/graph/dirtyjpg.c"
"source/graph/dirtypng.c"
)
add_sources( SOURCE_GROUP "Misc"
# Core source files
"source/misc/qosclient.c"
"source/misc/qoscommon.c"
"source/misc/weblog.c"
)
add_sources( SOURCE_GROUP "Misc/Include"
# Core include files
"source/misc/userapipriv.h"
)
add_sources( SOURCE_GROUP "Protocol"
# Core source files
"source/proto/protoadvt.c"
"source/proto/protohttpmanager.c"
"source/proto/protohttpserv.c"
"source/proto/protohttputil.c"
"source/proto/protohttp2.c"
"source/proto/protoname.c"
"source/proto/protostream.c"
"source/proto/prototunnel.c"
"source/proto/protoupnp.c"
# PC plat source files
"source/proto/protohttp.c"
"source/proto/protomangle.c"
"source/proto/protossl.c"
"source/proto/protowebsocket.c"
)
add_sources( SOURCE_GROUP "Utility"
# Core source files
"source/util/aws.c"
"source/util/binary7.c"
"source/util/base64.c"
"source/util/hpack.c"
"source/util/jsonformat.c"
"source/util/jsonparse.c"
"source/util/murmurhash3.c"
"source/util/protobufcommon.c"
"source/util/protobufread.c"
"source/util/protobufwrite.c"
"source/util/utf8.c"
)
add_sources( SOURCE_GROUP "Voip"
# Core source files
"source/voip/voiptunnel.c"
"source/voip/voipgroup.c"
# PC plat source files
"source/voip/voip.c"
"source/voip/voipblocklist.c"
"source/voip/voipconduit.c"
"source/voip/voipcodec.c"
"source/voip/voipcommon.c"
"source/voip/voipconnection.c"
"source/voip/voipdvi.c"
"source/voip/voipmixer.c"
"source/voip/voippcm.c"
"source/voip/pc/voipheadsetpc.c"
"source/voip/pc/voippc.c"
"source/voip/voiptranscribe.c"
"source/voip/pc/voipnarratepc.cpp"
)
add_sources( SOURCE_GROUP "Voip/Include"
# Core include files
"source/voip/voipcommon.h"
"source/voip/voipconduit.h"
"source/voip/voipconnection.h"
"source/voip/voipdvi.h"
"source/voip/voipmixer.h"
"source/voip/voippacket.h"
"source/voip/voippcm.h"
"source/voip/voippriv.h"
)
add_sources( SOURCE_GROUP "XML"
# Core source files
"source/xml/xmlformat.c"
"source/xml/xmlparse.c"
)
end_sources()
thirdparty_suppress_warnings()
target_include_directories( ${PROJECT_NAME} PRIVATE
"${THIRDPARTY_SOURCE_DIR}/dirtysdk/include/"
"${THIRDPARTY_SOURCE_DIR}/ea/"
"${THIRDPARTY_SOURCE_DIR}/ea/EAThread/include/"
"${THIRDPARTY_SOURCE_DIR}/dirtysdk/source/crypt/"
"${THIRDPARTY_SOURCE_DIR}/dirtysdk/source/dirtysock/"
"${THIRDPARTY_SOURCE_DIR}/dirtysdk/source/voip/"
)
target_compile_definitions( ${PROJECT_NAME} PRIVATE DIRTYCODE_LOGGING=0 )

6769
src/thirdparty/dirtysdk/changelog.txt vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,143 @@
/*H********************************************************************************/
/*!
\File Zfile.h
\Description
Host file operations.
\Copyright
Copyright (c) 2005 Electronic Arts Inc.
\Version 02/16/2005 (jbrookes) First Version
*/
/********************************************************************************H*/
#ifndef _Zfile_h
#define _Zfile_h
/*** Include files ****************************************************************/
#if (defined(DIRTYCODE_LINUX)) || (defined(DIRTYCODE_APPLEIOS))
#include <stdio.h>
#endif
/*** Defines **********************************************************************/
#if (defined(DIRTYCODE_LINUX)) || (defined(DIRTYCODE_APPLEIOS))
#define ZFILE_INVALID (NULL)
#else
#define ZFILE_INVALID (-1) //!< an invalid ZfileT handle
#endif
#define ZFILE_OPENFLAG_RDONLY (1)
#define ZFILE_OPENFLAG_WRONLY (2)
#define ZFILE_OPENFLAG_RDWR (ZFILE_OPENFLAG_RDONLY|ZFILE_OPENFLAG_WRONLY)
#define ZFILE_OPENFLAG_CREATE (4)
#define ZFILE_OPENFLAG_BINARY (8)
#define ZFILE_OPENFLAG_APPEND (16)
#define ZFILE_SEEKFLAG_CUR (1)
#define ZFILE_SEEKFLAG_END (2)
#define ZFILE_SEEKFLAG_SET (3)
#define ZFILE_ERROR_NONE (0) //!< no error
#define ZFILE_ERROR_FILEOPEN (-1) //!< generic error opening the file (reading or writing)
#define ZFILE_ERROR_FILECLOSE (-2) //!< generic error closing the file
#define ZFILE_ERROR_FILEWRITE (-3) //!< generic error occurred writing to the file
#define ZFILE_ERROR_FILEDELETE (-4) //!< generic error deleting the file
#define ZFILE_ERROR_FILESTAT (-5) //!< generic error trying to fstat a file
#define ZFILE_ERROR_FILERENAME (-6) //!< generic error renaming a file
#define ZFILE_ERROR_FILENAME (-7) //!< bad filename
#define ZFILE_ERROR_NULLPOINTER (-8) //!< null pointer passed in where data was expected
#define ZFILE_ERROR_NOSUCHFILE (-9) //!< file does not exist
#define ZFILE_ERROR_PERMISSION (-10) //!< permission denied (on opening/writing)
#define ZFILE_PATHFILE_LENGTHMAX (512) //!< max length of a path/filename string
/*** Macros ***********************************************************************/
#define ZFILESTAT_MODE_READ (0x01) //!< file has read flag set
#define ZFILESTAT_MODE_WRITE (0x02) //!< file has write flag set
#define ZFILESTAT_MODE_EXECUTE (0x04) //!< file has execute flag set
#define ZFILESTAT_MODE_PERMISSIONMASK (0x07) //!< mask for mode flags
#define ZFILESTAT_MODE_FILE (0x10) //!< item is a file
#define ZFILESTAT_MODE_DIR (0x20) //!< item is a directory
#define ZFILESTAT_MODE_FILETYPEMASK (0x30) //!< mask for file type flags
/*** Type Definitions *************************************************************/
typedef struct ZFileStatT
{
int64_t iSize; //!< file size in bytes
uint32_t uTimeCreate; //!< file creation time, seconds since epoch
uint32_t uTimeAccess; //!< last access time, seconds since epoch
uint32_t uTimeModify; //!< last modification time, seconds since epoch
uint16_t uMode; //!< file mode (file/dir and R/W/X)
uint16_t uPad1; //!< pad out to even boundary
} ZFileStatT;
#if !defined(DIRTYCODE_LINUX) && !defined(DIRTYCODE_APPLEIOS)
typedef intptr_t ZFileT;
#else
typedef FILE * ZFileT;
#endif
/*** Variables ********************************************************************/
/*** Functions ********************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/*
Platform-specific implementations (Zfileplatform.c)
*/
// open a file
DIRTYCODE_API ZFileT ZFileOpen(const char *pFileName, uint32_t uFlags);
// close a file
DIRTYCODE_API int32_t ZFileClose(ZFileT iFileId);
// read from a file
DIRTYCODE_API int32_t ZFileRead(ZFileT iFileId, void *pData, int32_t iSize);
// write to a file
DIRTYCODE_API int32_t ZFileWrite(ZFileT iFileId, void *pData, int32_t iSize);
// seek in a file
DIRTYCODE_API int64_t ZFileSeek(ZFileT iFileId, int64_t iOffset, uint32_t uFlags);
// delete a file
DIRTYCODE_API int32_t ZFileDelete(const char *pFileName);
// get file status information
DIRTYCODE_API int32_t ZFileStat(const char *pFileName, ZFileStatT *pFileStat);
// rename a file
DIRTYCODE_API int32_t ZFileRename(const char *pOldname, const char *pNewname);
// create a directory
DIRTYCODE_API int32_t ZFileMkdir(const char *pPathName);
/*
Platform-inspecific implementations (Zfile.c)
*/
// get file size
DIRTYCODE_API int64_t ZFileSize(ZFileT iFileId);
// open a file and load it into memory and null-terminate (in case it is a text file)
DIRTYCODE_API char *ZFileLoad(const char *pFileName, int32_t *pFileSize, uint32_t bBinary);
// save (overwrite) null-terminated data to a file
DIRTYCODE_API int32_t ZFileSave(const char *pFileName, const char *pData, int32_t iSize, uint32_t uFlags);
#ifdef __cplusplus
};
#endif
#endif // _Zfile_h

View File

@ -0,0 +1,121 @@
/*H********************************************************************************/
/*!
\File zlib.h
\Description
A simple console style test library that provides a basic
notion of processes, output routines and memory allocation.
Used to implement simple test programs in a unix-style
command-line environment.
\Copyright
Copyright (c) 2005 Electronic Arts Inc.
\Version 09/15/1999 (gschaefer) Initial Design
\Version 11/08/1999 (gschaefer) Cleanup and revision
\Version 03/17/2005 (jfrank) Cleanup and revision
*/
/********************************************************************************H*/
#ifndef _zlib_h
#define _zlib_h
/*** Include files ****************************************************************/
#include "DirtySDK/dirtysock/dirtylib.h"
/*** Defines **********************************************************************/
#define ZLIB_STATUS_RUNNING ((signed)0x80000000)
#define ZLIB_STATUS_UNKNOWN ((signed)0x80000001)
/*** Macros ***********************************************************************/
/*** Type Definitions *************************************************************/
typedef struct ZEnviron ZEnviron;
typedef struct ZContext ZContext;
typedef struct ZConsole ZConsole;
typedef int32_t (ZCommand)(ZContext *pArgz, int32_t iArgc, char **pArgv);
/*** Variables ********************************************************************/
/*** Functions ********************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
// create a new process environment. Parses command line and gets process ready to run.
DIRTYCODE_API ZEnviron *ZCreate(ZConsole *pConsole, const char *pCmdline);
// destroy process environment
DIRTYCODE_API void ZDestroy(ZEnviron *pEnv);
// execute a process within an existing environment.
DIRTYCODE_API void ZInvoke(ZEnviron *pEnv, ZCommand *pCmd);
// get process id of current process
DIRTYCODE_API int32_t ZGetPid(void);
// set current environment from context
DIRTYCODE_API void ZSet(ZContext *context);
// let process signal it wants a callback (has not completed).
DIRTYCODE_API int32_t ZCallback(ZCommand *pCmd, int32_t iDelay);
// give time to any existing processes that need it.
DIRTYCODE_API int32_t ZTask(void);
// remove any environments containing complete processes.
DIRTYCODE_API void ZCleanup(void);
// kill all active processes in preparation for shutdown
DIRTYCODE_API void ZShutdown(void);
// allow a process to allocate persistant private context.
DIRTYCODE_API ZContext *ZContextCreate(int32_t iSize);
// return tick count in milliseconds.
DIRTYCODE_API uint32_t ZTick(void);
// put process to sleep for some period of time
DIRTYCODE_API void ZSleep(uint32_t uMSecs);
// display output using standard printf semantics.
DIRTYCODE_API void ZPrintf(const char *pFmt, ...);
// display output using standard printf semantics (no hook)
DIRTYCODE_API void ZPrintf2(const char *pFmt, ...);
#if DIRTYCODE_LOGGING
#define ZPrintfDbg(_x) ZPrintf _x
#else
#define ZPrintfDbg(_x) { }
#endif
// set zprint callback
DIRTYCODE_API void ZPrintfHook(int32_t (*pPrintfHook)(void *pParm, const char *pText), void *pParm);
// show list of all process environments.
DIRTYCODE_API int32_t ZCmdPS(ZContext *pArgz, int32_t iArgc, char **pArgv);
// kill an existing process.
DIRTYCODE_API int32_t ZCmdKill(ZContext *pArgz, int32_t iArgc, char **pArgv);
// return status of current env, command.
DIRTYCODE_API int32_t ZGetStatus(ZEnviron *pEnv);
// return status of process with specified pid
DIRTYCODE_API int32_t ZGetStatusPid(int32_t iPid);
// get fourcc/integer from command-line argument
DIRTYCODE_API int32_t ZGetIntArg(const char *pArg);
#ifdef __cplusplus
};
#endif
#endif // _zlib_h

View File

@ -0,0 +1,63 @@
/*H********************************************************************************/
/*!
\File zlist.h
\Description
Generic list module for samples to use.
\Copyright
Copyright (c) 2005 Electronic Arts Inc.
\Version 04/26/2005 (jfrank) First Version
*/
/********************************************************************************H*/
#ifndef _zlist_h
#define _zlist_h
/*** Include files ****************************************************************/
/*** Defines **********************************************************************/
#define ZLIST_ERROR_NONE (0) //!< no error (success)
#define ZLIST_ERROR_NULLPOINTER (-1) //!< a null pointer ref was used
#define ZLIST_ERROR_FULL (-2) //!< sending/receiving list is full (msg dropped)
/*** Macros ***********************************************************************/
/*** Type Definitions *************************************************************/
typedef struct ZListT ZListT;
/*** Variables ********************************************************************/
/*** Functions ********************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
// create a list object
DIRTYCODE_API ZListT *ZListCreate(int32_t iNumEntries, int32_t iEntrySize);
// add an entry to the back of a data list
DIRTYCODE_API int32_t ZListPushBack(ZListT *pList, void *pEntry);
// get an entry off the front of a data list
DIRTYCODE_API int32_t ZListPopFront(ZListT *pList, void *pEntry);
// examine the front entry of a data list
DIRTYCODE_API void *ZListPeekFront(ZListT *pList);
// erase and entire list
DIRTYCODE_API void ZListClear(ZListT *pList);
// destroy a list object
DIRTYCODE_API void ZListDestroy(ZListT *pList);
#ifdef __cplusplus
};
#endif
#endif // _zlist_h

View File

@ -0,0 +1,48 @@
/*H********************************************************************************/
/*!
\File zmem.h
\Description
ZAlloc (malloc) and ZFree (free) implementations for use on all platforms.
\Copyright
Copyright (c) 2005 Electronic Arts Inc.
\Version 03/16/2005 (jfrank) First Version
*/
/********************************************************************************H*/
#ifndef _zmem_h
#define _zmem_h
/*** Include files ****************************************************************/
// include this so we can use zmemtrack alongside the zmem libraries
#include "zmemtrack.h"
/*** Defines **********************************************************************/
/*** Macros ***********************************************************************/
/*** Type Definitions *************************************************************/
/*** Variables ********************************************************************/
/*** Functions ********************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
// allocate some memory, uSize bytes in length
DIRTYCODE_API void *ZMemAlloc(uint32_t uSize);
// free a previously allocated memory chunk
DIRTYCODE_API uint32_t ZMemFree(void *pMem);
#ifdef __cplusplus
};
#endif
#endif // _zmem_h

View File

@ -0,0 +1,62 @@
/*H********************************************************************************/
/*!
\File zmemtrack.h
\Description
Routines for tracking memory allocations.
\Copyright
Copyright (c) 2005 Electronic Arts Inc.
\Version 02/15/2005 (jbrookes) First Version, based on jfrank's implementation.
*/
/********************************************************************************H*/
#ifndef _zmemtrack_h
#define _zmemtrack_h
/*** Include files ****************************************************************/
/*** Defines **********************************************************************/
#define ZMEMTRACK_PRINTFLAG_TRACKING (1) //!< print more verbose output
/*** Macros ***********************************************************************/
/*** Type Definitions *************************************************************/
//! logging function
typedef void (ZMemtrackLogCbT)(const char *pText, void *pUserData);
/*** Variables ********************************************************************/
/*** Functions ********************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
// init Zmemtrack module
DIRTYCODE_API void ZMemtrackStartup(void);
// shut down Zmemtrack module
DIRTYCODE_API void ZMemtrackShutdown(void);
// set the logging callback
DIRTYCODE_API void ZMemtrackCallback(ZMemtrackLogCbT *pLoggingCb, void *pUserData);
// track an allocation
DIRTYCODE_API void ZMemtrackAlloc(void *pMem, uint32_t uSize, uint32_t uTag);
// track a free operation
DIRTYCODE_API void ZMemtrackFree(void *pMem, uint32_t *pSize);
// print current tracking info
DIRTYCODE_API void ZMemtrackPrint(uint32_t uFlags, uint32_t uTag, const char *pModuleName);
#ifdef __cplusplus
};
#endif
#endif // _zmemtrack_h

View File

@ -0,0 +1,404 @@
/*H********************************************************************************/
/*!
\File zfilepc.c
\Description
Basic file operations (open, read, write, close, size).
\Notes
None.
\Copyright
Copyright (c) Electronic Arts 2004. ALL RIGHTS RESERVED.
\Version 1.0 11/18/1004 (jbrookes) First Version
\Version 1.1 03/16/2005 (jfrank) Updates for common sample libraries
*/
/********************************************************************************H*/
/*** Include files ****************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <io.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <direct.h> // _mkdir
#include "DirtySDK/platform.h"
#include "DirtySDK/dirtysock/dirtylib.h"
#include "zfile.h"
#include "zlib.h"
#include "zmem.h"
/*** Defines **********************************************************************/
/*** Type Definitions *************************************************************/
/*** Variables ********************************************************************/
/*** Private Functions ************************************************************/
/*** Public functions *************************************************************/
/*F********************************************************************************/
/*!
\Function ZFileOpen
\Description
Open a file.
\Input *pFileName - file name to open
\Input uFlags - flags dictating how to open the file
\Output
int32_t - file descriptor, or -1 if there was an error
\Version 1.0 03/16/2005 (jfrank) First Version
*/
/********************************************************************************F*/
ZFileT ZFileOpen(const char *pFileName, uint32_t uFlags)
{
char strMode[16] = "";
FILE *pFile;
if(pFileName == NULL)
return(ZFILE_INVALID);
if(strlen(pFileName) == 0)
return(ZFILE_INVALID);
ds_memclr(strMode, sizeof(strMode));
// map zfile flags to Win32 Mode flags
if (uFlags & ZFILE_OPENFLAG_APPEND)
{
strcat(strMode, "a");
if (uFlags & ZFILE_OPENFLAG_RDONLY)
strcat(strMode, "+");
}
else if (uFlags & ZFILE_OPENFLAG_RDONLY)
{
strcat(strMode, "r");
if (uFlags & ZFILE_OPENFLAG_WRONLY)
strcat(strMode, "+");
}
else if (uFlags & ZFILE_OPENFLAG_WRONLY)
strcat(strMode, "w");
if (uFlags & ZFILE_OPENFLAG_BINARY)
strcat(strMode, "b");
if ((pFile = fopen(pFileName, strMode)) != NULL)
{
return((ZFileT)pFile);
}
else
{
ZPrintfDbg(("zfilepc: error %d opening file '%s'\n", errno, pFileName));
return(ZFILE_INVALID);
}
}
/*F********************************************************************************/
/*!
\Function ZFileClose
\Description
Close a file
\Input iFileId - file descriptor
\Output int32_t - return value from fclose()
\Version 1.0 11/18/2004 (jbrookes) First Version
*/
/********************************************************************************F*/
int32_t ZFileClose(ZFileT iFileId)
{
if (iFileId != ZFILE_INVALID)
{
return(fclose((FILE *)iFileId));
}
else
{
return(ZFILE_ERROR_FILECLOSE);
}
}
/*F********************************************************************************/
/*!
\Function ZFileRead
\Description
Read from a file.
\Input *pData - pointer to buffer to read to
\Input iSize - amount of data to read
\Input iFileId - file descriptor
\Output
Number of bytes read
\Version 1.0 11/18/2004 (jbrookes) First Version
*/
/********************************************************************************F*/
int32_t ZFileRead(ZFileT iFileId, void *pData, int32_t iSize)
{
int32_t iResult;
iResult = (int32_t)fread(pData, 1, iSize, (FILE *)iFileId);
return(ferror((FILE *)iFileId) ? 0 : iResult);
}
/*F********************************************************************************/
/*!
\Function ZFileWrite
\Description
Write to a file.
\Input *pData - pointer to buffer to write from
\Input iSize - amount of data to write
\Input iFileId - file descriptor
\Output
Number of bytes written
\Version 1.0 11/18/2004 (jbrookes) First Version
*/
/********************************************************************************F*/
int32_t ZFileWrite(ZFileT iFileId, void *pData, int32_t iSize)
{
if ((iFileId == ZFILE_INVALID) || (pData == NULL) || (iSize == 0))
{
return(ZFILE_ERROR_FILEWRITE);
}
return((int32_t)fwrite(pData, 1, iSize, (FILE *)iFileId));
}
/*F********************************************************************************/
/*!
\Function ZFileSeek
\Description
Seek to location in file.
\Input iFileId - file id to seek
\Input iOffset - offset to seek to
\Input uFlags - seek mode (ZFILE_SEEKFLAG_*)
\Output
int64_t - resultant seek location, or -1 on error
\Version 03/16/2005 (jfrank) First Version
*/
/********************************************************************************F*/
int64_t ZFileSeek(ZFileT iFileId, int64_t iOffset, uint32_t uFlags)
{
int64_t iResult;
int32_t iFlags=0;
if (uFlags == ZFILE_SEEKFLAG_CUR)
iFlags = SEEK_CUR;
else if (uFlags == ZFILE_SEEKFLAG_END)
iFlags = SEEK_END;
else if (uFlags == ZFILE_SEEKFLAG_SET)
iFlags = SEEK_SET;
iResult = _fseeki64((FILE *)iFileId, iOffset, iFlags);
iResult = _ftelli64((FILE *)iFileId);
return((iResult >= 0) ? iResult : -1);
}
/*F********************************************************************************/
/*!
\Function ZFileDelete
\Description
Delete a file.
\Input *pFileName - filename of file to delete
\Output int32_t - 0=success, error code otherwise
\Version 03/23/2005 (jfrank) First Version
*/
/********************************************************************************F*/
int32_t ZFileDelete(const char *pFileName)
{
int32_t iResult;
if(pFileName == NULL)
return(ZFILE_ERROR_FILENAME);
iResult = remove(pFileName);
if(iResult == 0)
return(ZFILE_ERROR_NONE);
else
return(ZFILE_ERROR_FILEDELETE);
}
/*F********************************************************************************/
/*!
\Function ZFileStat
\Description
Get File Stat information on a file/dir.
\Input *pFileName - filename/dir to stat
\Input *pStat
\Output int32_t - 0=success, error code otherwise
\Version 03/25/2005 (jfrank) First Version
*/
/********************************************************************************F*/
int32_t ZFileStat(const char *pFileName, ZFileStatT *pFileStat)
{
struct _stat FileStat;
int32_t iResult;
// check for error conditions
if(pFileName == NULL)
return(ZFILE_ERROR_FILENAME);
if(pFileStat == NULL)
return(ZFILE_ERROR_NULLPOINTER);
// get file status
iResult = _stat(pFileName, &FileStat);
// check for some specific errors
if((iResult == -1) && (errno == ENOENT))
return(ZFILE_ERROR_NOSUCHFILE);
else if(errno == EACCES)
return(ZFILE_ERROR_PERMISSION);
else if(iResult != 0)
return(ZFILE_ERROR_FILESTAT);
// clear the incoming buffer
ds_memclr(pFileStat, sizeof(ZFileStatT));
// copy from the PC-specific structures
pFileStat->iSize = FileStat.st_size;
pFileStat->uTimeAccess = FileStat.st_atime;
pFileStat->uTimeCreate = FileStat.st_ctime;
pFileStat->uTimeModify = FileStat.st_mtime;
// get the file modes
if(FileStat.st_mode & _S_IFDIR)
pFileStat->uMode |= ZFILESTAT_MODE_DIR;
if(FileStat.st_mode & _S_IFREG)
pFileStat->uMode |= ZFILESTAT_MODE_FILE;
if(FileStat.st_mode & _S_IREAD)
pFileStat->uMode |= ZFILESTAT_MODE_READ;
if(FileStat.st_mode & _S_IWRITE)
pFileStat->uMode |= ZFILESTAT_MODE_WRITE;
if(FileStat.st_mode & _S_IEXEC)
pFileStat->uMode |= ZFILESTAT_MODE_EXECUTE;
// done - return no error
return(ZFILE_ERROR_NONE);
}
/*F********************************************************************************/
/*!
\Function ZFileRename
\Description
Rename a file.
\Input *pOldname - old name
\Input *pNewname - new name
\Output int32_t - 0=success, error code otherwise
\Version 03/30/2005 (jfrank) First Version
*/
/********************************************************************************F*/
int32_t ZFileRename(const char *pOldname, const char *pNewname)
{
int32_t iResult;
// check for error conditions
if((pOldname == NULL) || (pNewname == NULL))
return(ZFILE_ERROR_NULLPOINTER);
// rename the file
iResult = rename(pOldname, pNewname);
if(iResult == 0)
return(ZFILE_ERROR_NONE);
else
return(ZFILE_ERROR_FILERENAME);
}
/*F********************************************************************************/
/*!
\Function ZFileMkdir
\Description
Make a directory, recursively
\Input *pPathName - directory path to create
\Output
int32_t - 0=success, error code otherwise
\Version 01/25/2012 (jbrookes)
*/
/********************************************************************************F*/
int32_t ZFileMkdir(const char *pPathName)
{
char strPath[1024], *pPath, cTerm = '\0';
// copy pathname
ds_strnzcpy(strPath, pPathName, sizeof(strPath));
// translate forward slashes to backward slashes
for (pPath = strPath; *pPath != '\0'; pPath += 1)
{
if (*pPath == '/')
{
*pPath = '\\';
}
}
// traverse pathname, making each directory component as we go
for (pPath = strPath; ; pPath += 1)
{
if (*pPath == '\\')
{
cTerm = *pPath;
*pPath = '\0';
}
if (*pPath == '\0')
{
int32_t iResult;
if ((iResult = _mkdir(strPath)) != 0)
{
if (errno == ENOENT)
{
ZPrintfDbg(("zfilepc: could not create directory '%s'\n", strPath));
return(-1);
}
if (errno == EEXIST)
{
ZPrintfDbg(("zfilepc: directory %s already exists\n", strPath));
}
}
}
if (cTerm != '\0')
{
*pPath = cTerm;
cTerm = '\0';
}
if (*pPath == '\0')
{
break;
}
}
return(0);
}

View File

@ -0,0 +1,472 @@
/*H********************************************************************************/
/*!
\File zfilepc.c
\Description
Basic file operations (open, read, write, close, size).
\Notes
None.
\Copyright
Copyright (c) Electronic Arts 2004. ALL RIGHTS RESERVED.
\Version 1.0 11/18/1004 (jbrookes) First Version
\Version 1.1 03/16/2005 (jfrank) Updates for common sample libraries
*/
/********************************************************************************H*/
/*** Include files ****************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <unistd.h>
#include "DirtySDK/platform.h"
#include "DirtySDK/dirtysock/dirtyerr.h"
#include "DirtySDK/dirtysock/dirtylib.h"
#include "zfile.h"
#include "zlib.h"
#include "zmem.h"
/*** Defines **********************************************************************/
/*** Type Definitions *************************************************************/
/*** Variables ********************************************************************/
/*** Private Functions ************************************************************/
/*F********************************************************************************/
/*!
\Function _ZFilePathTranslate
\Description
Translate a path from dos-style to unix-style
\Input *pPathName - path name to translate
\Input *pStrBuf - [out] output for translated path
\Input iBufLen - size of output buffer
\Output
char * - pointer to translated path
\Version 10/10/2013 (jbrookes)
*/
/********************************************************************************F*/
static char *_ZFilePathTranslate(const char *pPathName, char *pStrBuf, int32_t iBufLen)
{
char *pPath;
// copy pathname
ds_strnzcpy(pStrBuf, pPathName, iBufLen);
// translate any backward slashes to forward slashes
for (pPath = pStrBuf; *pPath != '\0'; pPath += 1)
{
if (*pPath == '\\')
{
*pPath = '/';
}
}
return(pStrBuf);
}
/*** Public functions *************************************************************/
/*F********************************************************************************/
/*!
\Function ZFileOpen
\Description
Open a file.
\Input *pFileName - file name to open
\Input uFlags - flags dictating how to open the file
\Output
int32_t - file descriptor, or -1 if there was an error
\Version 1.0 03/16/2005 (jfrank) First Version
*/
/********************************************************************************F*/
ZFileT ZFileOpen(const char *pFileName, uint32_t uFlags)
{
char strFileName[4096];
char strMode[16] = "";
FILE *pFile;
if ((pFileName == NULL) || (pFileName[0] == '\0'))
{
return(ZFILE_INVALID);
}
pFileName = _ZFilePathTranslate(pFileName, strFileName, sizeof(strFileName));
ds_memclr(strMode, sizeof(strMode));
// map zfile flags to Win32 Mode flags
if (uFlags & ZFILE_OPENFLAG_APPEND)
{
strcat(strMode, "a");
if (uFlags & ZFILE_OPENFLAG_RDONLY)
strcat(strMode, "+");
}
else if (uFlags & ZFILE_OPENFLAG_RDONLY)
{
strcat(strMode, "r");
if (uFlags & ZFILE_OPENFLAG_WRONLY)
strcat(strMode, "+");
}
else if (uFlags & ZFILE_OPENFLAG_WRONLY)
{
strcat(strMode, "w");
}
if (uFlags & ZFILE_OPENFLAG_BINARY)
{
strcat(strMode, "b");
}
if ((pFile = fopen(pFileName, strMode)) != NULL)
{
return((ZFileT)pFile);
}
else
{
return(ZFILE_INVALID);
}
}
/*F********************************************************************************/
/*!
\Function ZFileClose
\Description
Close a file
\Input iFileId - file descriptor
\Output int32_t - return value from fclose()
\Version 1.0 11/18/2004 (jbrookes) First Version
*/
/********************************************************************************F*/
int32_t ZFileClose(ZFileT iFileId)
{
return(fclose((FILE *)iFileId));
}
/*F********************************************************************************/
/*!
\Function ZFileRead
\Description
Read from a file.
\Input *pData - pointer to buffer to read to
\Input iSize - amount of data to read
\Input iFileId - file descriptor
\Output
Number of bytes read
\Version 1.0 11/18/2004 (jbrookes) First Version
*/
/********************************************************************************F*/
int32_t ZFileRead(ZFileT iFileId, void *pData, int32_t iSize)
{
int32_t iResult = (int32_t)fread(pData, 1, iSize, (FILE *)iFileId);
return(ferror((FILE *)iFileId) ? -1 : iResult);
}
/*F********************************************************************************/
/*!
\Function ZFileWrite
\Description
Write to a file.
\Input *pData - pointer to buffer to write from
\Input iSize - amount of data to write
\Input iFileId - file descriptor
\Output
Number of bytes written
\Version 1.0 11/18/2004 (jbrookes) First Version
*/
/********************************************************************************F*/
int32_t ZFileWrite(ZFileT iFileId, void *pData, int32_t iSize)
{
int32_t iResult;
if (iFileId == ZFILE_INVALID)
{
return(0);
}
if ((pData == NULL) || (iSize == 0))
{
return(0);
}
iResult = (int32_t)fwrite(pData, 1, iSize, (FILE *)iFileId);
return(iResult);
}
/*F********************************************************************************/
/*!
\Function ZFileSeek
\Description
Seek to location in file.
\Input iFileId - file id to seek
\Input iOffset - offset to seek to
\Input uFlags - seek mode (ZFILE_SEEKFLAG_*)
\Output
int64_t - resultant seek location, or -1 on error
\Version 03/16/2005 (jfrank) First Version
*/
/********************************************************************************F*/
int64_t ZFileSeek(ZFileT iFileId, int64_t iOffset, uint32_t uFlags)
{
int64_t iResult;
int32_t iFlags=0;
if (uFlags == ZFILE_SEEKFLAG_CUR)
{
iFlags = SEEK_CUR;
}
else if (uFlags == ZFILE_SEEKFLAG_END)
{
iFlags = SEEK_END;
}
else if (uFlags == ZFILE_SEEKFLAG_SET)
{
iFlags = SEEK_SET;
}
fseek((FILE *)iFileId, iOffset, iFlags);
iResult = ftell((FILE *)iFileId);
return((iResult >= 0) ? iResult : -1);
}
/*F********************************************************************************/
/*!
\Function ZFileDelete
\Description
Delete a file.
\Input *pFileName - filename of file to delete
\Output int32_t - 0=success, error code otherwise
\Version 03/23/2005 (jfrank) First Version
*/
/********************************************************************************F*/
int32_t ZFileDelete(const char *pFileName)
{
char strFileName[4096];
int32_t iResult;
if ((pFileName == NULL) || (pFileName[0] == '\0'))
{
return(ZFILE_ERROR_FILENAME);
}
pFileName = _ZFilePathTranslate(pFileName, strFileName, sizeof(strFileName));
iResult = remove(pFileName);
if (iResult == 0)
{
return(ZFILE_ERROR_NONE);
}
else
{
return(ZFILE_ERROR_FILEDELETE);
}
}
/*F********************************************************************************/
/*!
\Function ZFileStat
\Description
Get File Stat information on a file/dir.
\Input *pFileName - filename/dir to stat
\Input *pStat
\Output int32_t - 0=success, error code otherwise
\Version 03/25/2005 (jfrank) First Version
*/
/********************************************************************************F*/
int32_t ZFileStat(const char *pFileName, ZFileStatT *pFileStat)
{
#if !defined(DIRTYCODE_NX)
char strFileName[4096];
struct stat FileStat;
int32_t iResult;
// check for error conditions
if (pFileName == NULL)
{
return(ZFILE_ERROR_FILENAME);
}
if (pFileStat == NULL)
{
return(ZFILE_ERROR_NULLPOINTER);
}
pFileName = _ZFilePathTranslate(pFileName, strFileName, sizeof(strFileName));
// get file status
iResult = stat(pFileName, &FileStat);
// check for some specific errors
if ((iResult == -1) && (errno == ENOENT))
{
return(ZFILE_ERROR_NOSUCHFILE);
}
else if (errno == EACCES)
{
return(ZFILE_ERROR_PERMISSION);
}
else if (iResult != 0)
{
return(ZFILE_ERROR_FILESTAT);
}
// clear the incoming buffer
ds_memclr(pFileStat, sizeof(ZFileStatT));
// copy from the PC-specific structures
pFileStat->iSize = FileStat.st_size;
pFileStat->uTimeAccess = (uint32_t)FileStat.st_atime;
pFileStat->uTimeCreate = (uint32_t)FileStat.st_ctime;
pFileStat->uTimeModify = (uint32_t)FileStat.st_mtime;
// get the file modes
if (S_ISDIR(FileStat.st_mode))
{
pFileStat->uMode |= ZFILESTAT_MODE_DIR;
}
if (S_ISREG(FileStat.st_mode))
{
pFileStat->uMode |= ZFILESTAT_MODE_FILE;
}
if (FileStat.st_mode & S_IRUSR)
{
pFileStat->uMode |= ZFILESTAT_MODE_READ;
}
if (FileStat.st_mode & S_IWUSR)
{
pFileStat->uMode |= ZFILESTAT_MODE_WRITE;
}
if (FileStat.st_mode & S_IXUSR)
{
pFileStat->uMode |= ZFILESTAT_MODE_EXECUTE;
}
#endif
// done - return no error
return(ZFILE_ERROR_NONE);
}
/*F********************************************************************************/
/*!
\Function ZFileRename
\Description
Rename a file.
\Input *pOldname - old name
\Input *pNewname - new name
\Output int32_t - 0=success, error code otherwise
\Version 03/30/2005 (jfrank) First Version
*/
/********************************************************************************F*/
int32_t ZFileRename(const char *pOldname, const char *pNewname)
{
int32_t iResult;
// check for error conditions
if ((pOldname == NULL) || (pNewname == NULL))
{
return(ZFILE_ERROR_NULLPOINTER);
}
// rename the file
iResult = rename(pOldname, pNewname);
return((iResult == 0) ? ZFILE_ERROR_NONE : ZFILE_ERROR_FILERENAME);
}
/*F********************************************************************************/
/*!
\Function ZFileMkdir
\Description
Make a directory, recursively
\Input *pPathName - directory path to create
\Output
int32_t - 0=success, error code otherwise
\Version 01/25/2012 (jbrookes)
*/
/********************************************************************************F*/
int32_t ZFileMkdir(const char *pPathName)
{
char strPathName[4096], *pPath, cTerm = '\0';
pPath = _ZFilePathTranslate(pPathName, strPathName, sizeof(strPathName));
// traverse pathname, making each directory component as we go
for ( ; ; pPath += 1)
{
if (*pPath == '/')
{
cTerm = *pPath;
*pPath = '\0';
}
if (*pPath == '\0')
{
int32_t iResult;
if ((iResult = mkdir(strPathName, S_IRWXU)) != 0)
{
if (errno == EEXIST)
{
ZPrintfDbg(("zfilepc: directory %s already exists\n", strPathName));
}
else
{
ZPrintfDbg(("zfileunix: could not create directory '%s' err=%s\n", strPathName, DirtyErrGetName(errno)));
return(-1);
}
}
}
if (cTerm != '\0')
{
*pPath = cTerm;
cTerm = '\0';
}
if (*pPath == '\0')
{
break;
}
}
return(0);
}

View File

@ -0,0 +1,199 @@
/*H********************************************************************************/
/*!
\File zfile.c
\Description
Platform-inspecific host file operations.
\Copyright
Copyright (c) 2005 Electronic Arts Inc.
\Version 02/16/2005 (jbrookes) First Version
*/
/********************************************************************************H*/
/*** Include files ****************************************************************/
#include <stdio.h>
#include <string.h>
#include "DirtySDK/platform.h"
#include "zmem.h"
#include "zlib.h"
#include "zfile.h"
/*** Defines **********************************************************************/
/*** Type Definitions *************************************************************/
/*** Variables ********************************************************************/
/*** Private Functions ************************************************************/
/*** Public functions *************************************************************/
/*F********************************************************************************/
/*!
\Function ZFileSize
\Description
Get file size.
\Input iFileId - file id to get size of
\Output
int32_t - file size, or -1 on error
\Version 02/16/2005 (jbrookes)
*/
/********************************************************************************F*/
int64_t ZFileSize(ZFileT iFileId)
{
int64_t iEnd = ZFileSeek(iFileId, 0, ZFILE_SEEKFLAG_END);
ZFileSeek(iFileId, 0, ZFILE_SEEKFLAG_SET);
return(iEnd);
}
/*F********************************************************************************/
/*!
\Function ZFileLoad
\Description
Open a file and read it into memory.
\Input *pFilename - pointer to name of file to read
\Input *pFileSize - [out] storage for file size
\Input uOpenFlags - open flags, or zero for default (READONLY)
\Output
char * - pointer to file data, or NULL
\Version 02/16/2005 (jbrookes)
*/
/********************************************************************************F*/
char *ZFileLoad(const char *pFileName, int32_t *pFileSize, uint32_t uOpenFlags)
{
int64_t iFileSize64;
int32_t iFileSize, iResult;
char *pFileMem;
ZFileT iFileId;
// determine open flags
if (uOpenFlags == 0)
{
uOpenFlags = ZFILE_OPENFLAG_RDONLY;
}
// open the file
iFileId = ZFileOpen(pFileName, uOpenFlags);
if (iFileId == ZFILE_INVALID)
{
printf("zfile: unable to open file '%s'\n", pFileName);
return(NULL);
}
// get the file size
iFileSize64 = ZFileSize(iFileId);
if (iFileSize64 < 0)
{
printf("zfile: unable to get size of file '%s'\n", pFileName);
return(NULL);
}
iFileSize = (int32_t)iFileSize64; // this function does not support files >2GB
// allocate and clear memory for the file
pFileMem = (char *) ZMemAlloc(iFileSize+1);
if (pFileMem == NULL)
{
printf("zfile: unable to allocate %d bytes to load file '%s'\n", iFileSize+1, pFileName);
return(NULL);
}
ds_memclr(pFileMem, iFileSize+1);
// read file into memory
iResult = ZFileRead(iFileId, pFileMem, iFileSize);
if (iResult <= 0)
{
printf("zfile: unable to read file '%s'\n", pFileName);
return(NULL);
}
/* null-terminate; we do this in addition to the memset up above because
under windows the size of a text file on disk may be larger than the
file in memory */
pFileMem[iResult] = '\0';
// if size parameter is not null, set it
if (pFileSize != NULL)
{
*pFileSize = iResult;
}
// close the file
iResult = ZFileClose(iFileId);
if (iResult < 0)
{
printf("zfile: error closing file '%s'\n", pFileName);
}
// return pointer to memory
return(pFileMem);
}
/*F********************************************************************************/
/*!
\Function ZFileSave
\Description
Save data to a file. (OVERWRITE and CREATE by default)
\Input *pFilename - pointer to name of file to read
\Input *pData - pointer to data to save to a file
\Input iSize - amount of data to save to the file
\Input uOpenFlags - open flags, or zero for default (WRONLY|CREATE)
\Output
int32_t - 0 if success, error code otherwise
\Version 03/18/2005 (jfrank)
*/
/********************************************************************************F*/
int32_t ZFileSave(const char *pFileName, const char *pData, int32_t iSize, uint32_t uOpenFlags)
{
int32_t iResult;
ZFileT iFileId;
// determine what flags to use
if (uOpenFlags == 0)
{
uOpenFlags = ZFILE_OPENFLAG_WRONLY | ZFILE_OPENFLAG_CREATE;
}
// open the file
iFileId = ZFileOpen(pFileName, uOpenFlags);
if (iFileId == ZFILE_INVALID)
{
ZPrintf("zfile: unable to open file '%s' with flags 0x%X\n", pFileName, uOpenFlags);
return(ZFILE_ERROR_FILEOPEN);
}
// now write the data
iResult = ZFileWrite(iFileId, (char *)pData, iSize);
if(iResult != iSize)
{
ZPrintf("zfile: write error - size to write [%d] size written [%d]\n", iSize, iResult);
return(ZFILE_ERROR_FILEWRITE);
}
// and close the file
iResult = ZFileClose(iFileId);
if(iResult != 0)
{
ZPrintf("zfile: close error [%d=0x%X]\n", iResult, iResult);
return(ZFILE_ERROR_FILECLOSE);
}
// else successful save occurred
return(ZFILE_ERROR_NONE);
}

View File

@ -0,0 +1,805 @@
/*H********************************************************************************/
/*!
\File zlib.c
\Description
A simple console style test library that provides a basic
notion of processes, output routines and memory allocation.
Used to implement simple test programs in a unix-style
command-line environment.
\Copyright
Copyright (c) 2005 Electronic Arts Inc.
\Version 09/15/1999 (gschaefer) Initial Design
\Version 11/08/1999 (gschaefer) Cleanup and revision
\Version 03/17/2005 (jfrank) Cleanup and revision
*/
/********************************************************************************H*/
/*** Include files ****************************************************************/
#if defined(_WIN32) && !defined(_XBOX)
#define WIN32_LEAN_AND_MEAN 1
#pragma warning(push,0)
#include <windows.h>
#pragma warning(pop)
#endif
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "DirtySDK/platform.h"
#include "DirtySDK/dirtydefs.h"
#include "DirtySDK/dirtysock.h"
#include "DirtySDK/dirtysock/dirtylib.h"
#include "DirtySDK/dirtysock/netconn.h"
#include "zlib.h"
#include "zmem.h"
/*** Defines **********************************************************************/
#if !defined(_WIN32) || defined(DIRTYCODE_XBOXONE) || defined(DIRTYCODE_GDK)
#define wsprintf sprintf
#endif
/*** Type Definitions *************************************************************/
struct ZEnviron
{
ZEnviron *pNext; //!< list of active process contexts
ZContext *pContext; //!< process private context
ZConsole *pConsole; //!< console output pointer
ZCommand *pCommand; //!< pointer to process code
uint32_t uRuntime; //!< number of ms process has run
uint32_t uRuncount; //!< number of time slices
int32_t iPID; //!< process identifier
int32_t iStatus; //!< exit status
uint32_t uSchedule; //!< next scheduled tick to run at
int32_t iArgc; //!< arg count for program
char *pArgv[200]; //!< pointer to entry parms
char strArgb[16*1024]; //!< buffer to hold entry parms
};
/*** Variables ********************************************************************/
static ZEnviron *_pEnvCurr = NULL; //!< current process
static ZEnviron *_pEnvList = NULL; //!< list of processes
static void *_Zlib_pPrintfParm = NULL;
static int32_t (*_Zlib_pPrintfHook)(void *pParm, const char *pText) = NULL;
/*** Private Functions ************************************************************/
/*** Public functions *************************************************************/
/*F********************************************************************************/
/*!
\Function ZCreate
\Description
Create a new process environment. Parses command line
and gets process ready to run.
\Input console - default output console for process
\Input cmdline - the entry command line params
\Output ZEnviron - new process environment
\Version 09/15/1999 (gschaefer)
*/
/********************************************************************************F*/
ZEnviron *ZCreate(ZConsole *console, const char *cmdline)
{
char term;
char *s;
ZEnviron *env;
static uint32_t pid = 1;
// get new environment
env = (ZEnviron *)ZMemAlloc(sizeof(*env));
ds_memclr(env, sizeof(*env));
// assign unique pid
env->iPID = pid++;
// save console ref
env->pConsole = console;
// copy command line
ds_strnzcpy(env->strArgb, cmdline, sizeof(env->strArgb));
s = env->strArgb;
// parse command line
for (env->iArgc = 0; env->iArgc < (signed)(sizeof(env->pArgv)/sizeof(env->pArgv[0])); env->iArgc += 1)
{
// skip to next token
while ((*s != 0) && (*s <= ' '))
++s;
// see if anything to save
if (*s == 0)
break;
// see if there is a terminator
term = ((*s == '"') || (*s == '\'') ? *s++ : 0);
// record start of token
env->pArgv[env->iArgc] = s;
// find end of token
while ((*s != 0) && (((term == 0) && (*s > ' ')) || ((term != 0) && (*s != term))))
++s;
// terminate token
if (*s != 0)
*s++ = 0;
}
// set status to terminated
env->iStatus = 0;
env->uSchedule = (uint32_t)(-1);
// put into process list
env->pNext = _pEnvList;
_pEnvList = env;
// return new environment
return(env);
}
/*F********************************************************************************/
/*!
\Function ZDestroy
\Description
Destroy a process environment
\Input env - existing process environment
\Version 09/15/1999 (gschaefer)
*/
/********************************************************************************F*/
void ZDestroy(ZEnviron *env)
{
ZEnviron **scan;
// remove from environment list
for (scan = &_pEnvList; *scan != NULL; scan = &(*scan)->pNext)
{
if (*scan == env)
{
*scan = env->pNext;
break;
}
}
// remove from active
if (_pEnvCurr == env)
_pEnvCurr = NULL;
// destroy any attached context
if (env->pContext != NULL)
ZMemFree(env->pContext);
// destroy the environment
ZMemFree(env);
return;
}
/*F********************************************************************************/
/*!
\Function ZInvoke
\Description
Execute a process within an existing environment
\Input env - existing environment
\Input cmd - process code pointer
\Version 09/15/1999 (gschaefer)
*/
/********************************************************************************F*/
void ZInvoke(ZEnviron *env, ZCommand *cmd)
{
uint32_t tick1, tick2;
// make sure there is a current environment
if (env == NULL)
return;
_pEnvCurr = env;
// if this is first run
if (cmd != NULL)
{
// save the command
_pEnvCurr->pCommand = cmd;
// remove any existing context
ZContextCreate(0);
}
else if (_pEnvCurr->pCommand == NULL)
{
return;
}
// invoke the command
tick1 = ZTick();
_pEnvCurr->uSchedule = (uint32_t)(-1);
_pEnvCurr->uRuncount += 1;
_pEnvCurr->iStatus = _pEnvCurr->pCommand(_pEnvCurr->pContext, _pEnvCurr->iArgc, _pEnvCurr->pArgv);
tick2 = ZTick();
_pEnvCurr->uRuntime += tick2-tick1;
// handle callback request
if ((_pEnvCurr->uSchedule != (uint32_t)(-1)) && (_pEnvCurr->iStatus == ZLIB_STATUS_RUNNING))
_pEnvCurr->uSchedule += tick2;
}
/*F********************************************************************************/
/*!
\Function ZSet
\Description
Set current environment, based on specified context
\Input context - context; environment that owns this context will be made current
\Version 10/10/2012 (jbrookes)
*/
/********************************************************************************F*/
void ZSet(ZContext *context)
{
ZEnviron *env;
// find context
for (env = _pEnvCurr; env != NULL && env->pContext != context; env = env->pNext)
;
// found it? make it current
if (env != NULL)
{
_pEnvCurr = env;
}
}
/*F********************************************************************************/
/*!
\Function ZGetPid
\Description
Get process id of current environment
\Output
int32_t - pid, or zero if no current environment
\Version 10/10/2012 (jbrookes)
*/
/********************************************************************************F*/
int32_t ZGetPid(void)
{
int32_t iPID = 0;
if (_pEnvCurr != NULL)
{
iPID = _pEnvCurr->iPID;
}
return(iPID);
}
/*F********************************************************************************/
/*!
\Function ZCallback
\Description
Let process signal it wants a callback (has not completed)
\Input cmd - pointer to callback code
\Input delay - milliseconds until callback
\Output int32_t - special return value that process returns with
\Version 09/15/1999 (gschaefer)
*/
/********************************************************************************F*/
int32_t ZCallback(ZCommand *cmd, int32_t delay)
{
_pEnvCurr->pCommand = cmd;
_pEnvCurr->uSchedule = delay;
return(ZLIB_STATUS_RUNNING);
}
/*F********************************************************************************/
/*!
\Function ZTask
\Description
Give time to any existing processes that need it.
\Output int32_t - number of ticks until the next requested update
\Version 09/15/1999 (gschaefer)
*/
/********************************************************************************F*/
int32_t ZTask(void)
{
ZEnviron *env;
uint32_t tick = ZTick();
uint32_t next = tick+1000;
// walk environ list and execute processes which are scheduled
for (env = _pEnvList; env != NULL; env = env->pNext)
{
if (tick > env->uSchedule)
ZInvoke(env, NULL);
if (next > env->uSchedule)
next = env->uSchedule;
}
// figure time until next tick
tick = ZTick();
return((tick > next) ? 0 : next-tick);
}
/*F********************************************************************************/
/*!
\Function ZCleanup
\Description
Remove any environments containing complete processes.
\Version 09/15/1999 (gschaefer)
*/
/********************************************************************************F*/
void ZCleanup(void)
{
ZEnviron *env;
for (env = _pEnvList; env != NULL;)
{
if (env->uSchedule == (uint32_t)(-1))
{
ZEnviron *kill = env;
env = env->pNext;
ZDestroy(kill);
}
else
{
env = env->pNext;
}
}
}
/*F********************************************************************************/
/*!
\Function ZShutdown
\Description
Kill all active processes in preparation for shutdown.
\Version 02/18/03 (jbrookes)
*/
/********************************************************************************F*/
void ZShutdown(void)
{
ZEnviron *env;
for (env = _pEnvList; env != NULL; env = env->pNext)
{
// kill the process
env->uSchedule = (uint32_t)(-1);
env->iStatus = (env->pCommand)(env->pContext, 0, env->pArgv);
env->uSchedule = (uint32_t)(-1);
}
while(_pEnvList != NULL)
{
ZTask();
ZCleanup();
}
}
/*F********************************************************************************/
/*!
\Function ZCreateContext
\Description
Allow a process to allocate persistent private context.
\Input size - size of needed context
\Output ZContext * - context of requested size
\Version 09/15/1999 (gschaefer)
*/
/********************************************************************************F*/
ZContext *ZContextCreate(int32_t size)
{
if (_pEnvCurr == NULL)
return(NULL);
if (_pEnvCurr->pContext != NULL)
ZMemFree(_pEnvCurr->pContext);
_pEnvCurr->pContext = ((size > 0) ? (ZContext *)ZMemAlloc(size) : NULL);
return(_pEnvCurr->pContext);
}
/*F********************************************************************************/
/*!
\Function ZPrintf
\Description
Display output using standard printf semantics.
\Input Standard printf inputs.
\Version 09/15/1999 (gschaefer)
*/
/********************************************************************************F*/
void ZPrintf(const char *fmt, ...)
{
char text[4096];
va_list args;
int32_t iOutput=1;
// parse the data
va_start(args, fmt);
ds_vsnprintf(text, sizeof(text), fmt, args);
va_end(args);
// send to debug hook if set
if (_Zlib_pPrintfHook != NULL)
{
iOutput = _Zlib_pPrintfHook(_Zlib_pPrintfParm, text);
}
// if debug hook didn't override output, print here
if (iOutput != 0)
{
#if defined(DIRTYCODE_PC) || defined(DIRTYCODE_XBOXONE) || defined(DIRTYCODE_GDK)
OutputDebugStringA(text);
#else
printf("%s", text);
#endif
}
}
/*F********************************************************************************/
/*!
\Function ZPrintf2
\Description
Display output using standard printf semantics (no hook).
\Input Standard printf inputs.
\Version 10/18/2011 (jbrookes)
*/
/********************************************************************************F*/
void ZPrintf2(const char *fmt, ...)
{
char text[4096];
va_list args;
// parse the data
va_start(args, fmt);
ds_vsnprintf(text, sizeof(text), fmt, args);
va_end(args);
// print here
#if defined(DIRTYCODE_PC) || defined(DIRTYCODE_XBOXONE) || defined(DIRTYCODE_GDK)
OutputDebugStringA(text);
#else
printf("%s", text);
#endif
}
/*F********************************************************************************/
/*!
\Function ZPrintfHook
\Description
Hook into output.
\Input *pPrintfHook - pointer to function to call with output
\Input *pParm - user parameter
\Output
None.
\Version 03/23/2006 (jbrookes)
*/
/********************************************************************************F*/
void ZPrintfHook(int32_t (*pPrintfHook)(void *pParm, const char *pText), void *pParm)
{
_Zlib_pPrintfHook = pPrintfHook;
_Zlib_pPrintfParm = pParm;
}
/*F********************************************************************************/
/*!
\Function ZCmdPS
\Description
Show list of all process environments.
\Input *argz - context
\Input argc - arg count
\Input argz - arg strings
\Output int32_t - exit code
\Version 10/04/1999 (gschaefer)
*/
/********************************************************************************F*/
int32_t ZCmdPS(ZContext *argz, int32_t argc, char **pArgv)
{
ZEnviron *env;
uint32_t tick = ZTick();
// handle help
if (argc == 0) {
ZPrintf("%s - show process status list\r\n", pArgv[0]);
return(0);
}
// show process status list
ZPrintf(" PID STATUS ITER TIME COMMAND\r\n");
for (env = _pEnvList; env != NULL; env = env->pNext) {
int32_t i;
char text[256];
char *s = text;
// dont show ourselves
if (env == _pEnvCurr)
continue;
// put in pid
s += wsprintf(s, "%5d", env->iPID);
// add in state/time till next
if (env->uSchedule == (uint32_t)(-1))
{
s += wsprintf(s, " F %4d", env->iStatus);
}
else
{
int32_t timeout = env->uSchedule-tick;
if (timeout < 0)
timeout = 0;
if (timeout > 9999)
timeout = 9999;
s += wsprintf(s, " S %4d", timeout);
}
// show run count
s += wsprintf(s, " %4d", (env->uRuncount < 9999 ? env->uRuncount : 9999));
// show time used
s += wsprintf(s, " %2d.%03d", env->uRuntime/1000, env->uRuntime%1000);
// show command name
s += wsprintf(s, " %s", env->pArgv[0]);
// show command parms
for (i = 1; i < env->iArgc; ++i)
s += wsprintf(s, " '%s'", env->pArgv[i]);
// end of line
*s++ = '\r';
*s++ = '\n';
*s = 0;
ZPrintf("%s", text);
}
return(0);
}
/*F********************************************************************************/
/*!
\Function ZCmdKill
\Description
Kill an existing process.
\Input *argz - context
\Input argc - arg count
\Input argz - arg strings
\Output int32_t - exit code
\Version 10/04/1999 (gschaefer)
*/
/********************************************************************************F*/
int32_t ZCmdKill(ZContext *argz, int32_t argc, char **pArgv)
{
int32_t pid;
char *s, *d;
ZEnviron *env;
// handle help
if (argc == 0) {
ZPrintf("%s pid|name - kill a running command\r\n", pArgv[0]);
return(0);
}
// check usage
if (argc != 2) {
ZPrintf("usage: %s pid|name\r\n", pArgv[0]);
return(-1);
}
// get the pid
pid = 0;
for (s = pArgv[1]; (*s >= '0') && (*s <= '9'); ++s)
pid = (pid * 10) + (*s & 15);
// if its zero, see if the name matches
for (env = _pEnvList; env != NULL; env = env->pNext)
{
for (s = pArgv[1], d = env->pArgv[0]; *s != 0; ++s, ++d)
{
if (*s != *d)
break;
}
if (*s == 0)
{
pid = env->iPID;
break;
}
}
// make sure we got something
if (pid <= 0)
{
ZPrintf("%s: invalid pid: %s\r\n", pArgv[0], pArgv[1]);
return(-2);
}
// search process list for match
for (env = _pEnvList; env != NULL; env = env->pNext) {
if ((env != _pEnvCurr) && (env->iPID == pid))
break;
}
// error if no matching process
if (env == NULL)
{
ZPrintf("%s: no such process %d\r\n", pArgv[0], pid);
return(-3);
}
// if already dead
if (env->uSchedule == (uint32_t)(-1))
{
ZPrintf("%s: process %d already dead\r\n", pArgv[0], pid);
return(-4);
}
// kill the process
env->uSchedule = (uint32_t)(-1);
env->iStatus = (env->pCommand)(env->pContext, 0, env->pArgv);
env->uSchedule = (uint32_t)(-1);
return(0);
}
/*F********************************************************************************/
/*!
\Function ZGetStatus
\Description
Return status of current command. Returns -1 if pEnv is Null.
\Input pEnv -pointer to current env, command.
\Output Status of current command. Returns -1 if pEnv is Null.
\Version 29/11/2005 (TE)
*/
/********************************************************************************F*/
int32_t ZGetStatus(ZEnviron *pEnv)
{
return(pEnv ? pEnv->iStatus :-1);
}
/*F********************************************************************************/
/*!
\Function ZGetStatusPid
\Description
Get status of the process specified by pid
\Output
int32_t - status, or ZLIB_STATUS_UNKNOWN if process is not found
\Version 10/10/2012 (jbrookes)
*/
/********************************************************************************F*/
int32_t ZGetStatusPid(int32_t iPID)
{
ZEnviron *env;
// show process status list
for (env = _pEnvList; env != NULL; env = env->pNext)
{
if (env->iPID == iPID)
{
return(env->iStatus);
}
}
return(ZLIB_STATUS_UNKNOWN);
}
/*F********************************************************************************/
/*!
\Function ZGetIntArg
\Description
Get fourcc/integer from command-line argument
\Input *pArg - pointer to argument
\Version 11/26/2018 (jbrookes)
*/
/********************************************************************************F*/
int32_t ZGetIntArg(const char *pArg)
{
int32_t iValue;
// check for possible fourcc value
if ((strlen(pArg) == 4) && (isalpha(pArg[0]) || isalpha(pArg[1]) || isalpha(pArg[2]) || isalpha(pArg[3])))
{
iValue = pArg[0] << 24;
iValue |= pArg[1] << 16;
iValue |= pArg[2] << 8;
iValue |= pArg[3];
}
else
{
iValue = (signed)strtol(pArg, NULL, 10);
}
return(iValue);
}
/*F*************************************************************************************/
/*!
\Function ZTick
\Description
Return some kind of increasing tick count with millisecond scale (does
not need to have millisecond precision, but higher precision is better).
\Output
uint32_t - millisecond tick count
\Version 1.0 05/06/2005 (jfrank) First Version
*/
/*************************************************************************************F*/
uint32_t ZTick(void)
{
return(NetTick());
}
/*F********************************************************************************/
/*!
\Function ZSleep
\Description
Put process to sleep for some period of time
\Input uMSecs - Number of milliseconds to sleep for.
\Version 05/06/2005 (jfrank)
*/
/********************************************************************************F*/
void ZSleep(uint32_t uMSecs)
{
NetConnSleep(uMSecs);
}

View File

@ -0,0 +1,270 @@
/*H********************************************************************************/
/*!
\File zlist.h
\Description
Generic list module for samples to use.
\Copyright
Copyright (c) 2005 Electronic Arts Inc.
\Version 04/26/2005 (jfrank) First Version
*/
/********************************************************************************H*/
/*** Include files ****************************************************************/
#include "DirtySDK/dirtysock.h"
#include "zmem.h"
#include "zlib.h"
#include "zlist.h"
/*** Defines **********************************************************************/
/*** Type Definitions *************************************************************/
struct ZListT
{
uint32_t iNumEntries; //!< number of entries in the list
uint32_t iEntrySize; //!< size of each entry
uint32_t uHead; //!< index of input list head entry
uint32_t uTail; //!< index of input list tail entry
void *pData; //!< data
};
/*** Variables ********************************************************************/
/*** Private Functions ************************************************************/
/*** Public functions *************************************************************/
/*F********************************************************************************/
/*!
\Function ZListCreate
\Description
Create a list object
\Input iMaxEntries - maximum number of entries in the list
\Input iEntrySize - maximum size of each entry in the list
\Output ZListT * - pointer to the created list
\Version 04/26/2005 (jfrank)
*/
/********************************************************************************F*/
ZListT *ZListCreate(int32_t iNumEntries, int32_t iEntrySize)
{
ZListT *pList;
// check for errors
if((iNumEntries <= 0) || (iEntrySize <= 0))
{
ZPrintf("Could not create list with [%d] entries of size [%d] total size [%d]\n",
iNumEntries, iEntrySize, iNumEntries * iEntrySize);
return(NULL);
}
// create the list
pList = (ZListT *)ZMemAlloc(sizeof(ZListT));
ds_memclr(pList, sizeof(*pList));
pList->iEntrySize = iEntrySize;
pList->iNumEntries = iNumEntries;
pList->pData = (ZListT *)ZMemAlloc(iNumEntries * iEntrySize);
return(pList);
}
/*F********************************************************************************/
/*!
\Function ZListPushBack
\Description
Add and entry to the back of a data list
\Input pList - pointer to the list to use
\Input pEntry - entry to add (will be copied in)
\Output int32_t - 0 for success, error code otherwise
\TODO
The current implementation doesn't wrap the queue, so if the head
starts chasing the tail but doesn't catch up, a large amount of the
buffer space can end up being wasted. Either the queue needs to be
modified to wrap, or the buffer memory shifted to allow the head to
be reset to zero without catching the tail.
\Version 04/26/2005 (jfrank)
*/
/********************************************************************************F*/
int32_t ZListPushBack(ZListT *pList, void *pEntry)
{
char *pDest;
// check to make sure we got an entry
if ((pEntry == NULL) || (pList == NULL))
{
return(ZLIST_ERROR_NULLPOINTER);
}
// see if the list is full
if (pList->uTail >= pList->iNumEntries)
{
return(ZLIST_ERROR_FULL);
}
// insert into the list
pDest = (char *)pList->pData + (pList->uTail * pList->iEntrySize);
ds_memcpy(pDest, pEntry, pList->iEntrySize);
// increment the tail pointer
pList->uTail++;
// done
return(0);
}
/*F********************************************************************************/
/*!
\Function ZListPopFront
\Description
Get an entry off the front of a data list
\Input pList - pointer to the list to destroy
\Input pEntry - destination for the entry to get (will be copied in), NULL to discard data
\Output int32_t - <0 for error, 0 for no data left, >0 for amount of data left
\Version 04/26/2005 (jfrank)
*/
/********************************************************************************F*/
int32_t ZListPopFront(ZListT *pList, void *pEntry)
{
uint32_t uAmtLeft;
char *pSrc;
// check to make sure we got an entry
if (pList == NULL)
{
return(ZLIST_ERROR_NULLPOINTER);
}
// see if the list is empty
uAmtLeft = pList->uTail - pList->uHead;
if (uAmtLeft == 0)
{
// no error - list is just empty
return(0);
}
else
{
// only copy data if we have a container for it
if (pEntry)
{
// copy from the list into the new location
pSrc = (char *)pList->pData + (pList->uHead * pList->iEntrySize);
ds_memcpy(pEntry, (void *)pSrc, pList->iEntrySize);
}
pList->uHead++;
// test for empty list situation
if (pList->uHead == pList->uTail)
{
// empty list - reset
pList->uHead = 0;
pList->uTail = 0;
}
}
// done
return(uAmtLeft);
}
/*F********************************************************************************/
/*!
\Function ZListPeekFront
\Description
Examine the front entry of a data list
\Input pList - pointer to the list to destroy
\Output void * - pointer to the first entry, NULL if empty
\Version 04/26/2005 (jfrank)
*/
/********************************************************************************F*/
void *ZListPeekFront(ZListT *pList)
{
char *pSrc;
// check for errors
if(pList == NULL)
{
return(NULL);
}
// if list is empty, return NULL
if (pList->uHead == pList->uTail)
{
return(NULL);
}
// otherwise return a pointer to the data in question
pSrc = (char *)pList->pData + (pList->uHead * pList->iEntrySize);
return(pSrc);
}
/*F********************************************************************************/
/*!
\Function ZListClear
\Description
Clear the entire list
\Input pList - pointer to the list to destroy
\Output None
\Version 04/26/2005 (jfrank)
*/
/********************************************************************************F*/
void ZListClear(ZListT *pList)
{
if(pList)
{
ds_memclr(pList->pData, pList->iNumEntries * pList->iEntrySize);
pList->uHead = 0;
pList->uTail = 0;
}
}
/*F********************************************************************************/
/*!
\Function ZListDestroy
\Description
Destroy a list object and free all associated memory
\Input pList - pointer to the list to destroy
\Output None
\Version 04/26/2005 (jfrank)
*/
/********************************************************************************F*/
void ZListDestroy(ZListT *pList)
{
if (pList)
{
if (pList->pData)
{
ZMemFree(pList->pData);
}
ZMemFree(pList);
}
}

View File

@ -0,0 +1,83 @@
/*H********************************************************************************/
/*!
\File zmem.c
\Description
Memory implementations for use on all platforms.
\Copyright
Copyright (c) 2005 Electronic Arts Inc.
\Version 03/16/2005 (jfrank) First Version
*/
/********************************************************************************H*/
/*** Include files ****************************************************************/
#include <stdlib.h>
#include <string.h>
#include "DirtySDK/platform.h"
#include "DirtySDK/dirtysock.h"
#include "zmemtrack.h"
#include "zmem.h"
/*** Defines **********************************************************************/
/*** Type Definitions *************************************************************/
/*** Variables ********************************************************************/
/*** Private Functions ************************************************************/
/*** Public functions *************************************************************/
/*F********************************************************************************/
/*!
\Function ZMemAlloc
\Description
Allocate some memory
\Input uSize - amount of memory, in bytes, to allocate
\Output void * - pointer to an allocated memory chunk
\Version 03/16/2005 (jfrank)
*/
/********************************************************************************F*/
void *ZMemAlloc(uint32_t uSize)
{
void *pMem;
if ((pMem = (void *)malloc(uSize)) != NULL)
{
ds_memset(pMem, 0xCD, uSize);
ZMemtrackAlloc(pMem, uSize, 0);
}
return(pMem);
}
/*F********************************************************************************/
/*!
\Function ZMemFree
\Description
Free a previously allocated chunk of memory
\Input void *pMem - pointer to an allocated memory chunk
\Output None
\Version 03/16/2005 (jfrank)
*/
/********************************************************************************F*/
uint32_t ZMemFree(void *pMem)
{
uint32_t uSize;
ZMemtrackFree(pMem, &uSize);
ds_memset(pMem, 0xEF, uSize);
free(pMem);
return(uSize);
}

View File

@ -0,0 +1,371 @@
/*H********************************************************************************/
/*!
\File zmemtrack.c
\Description
Routines for tracking memory allocations.
\Copyright
Copyright (c) 2005-2017 Electronic Arts Inc.
\Version 02/15/2005 (jbrookes) First Version, based on jfrank's implementation.
*/
/********************************************************************************H*/
/*** Include files ****************************************************************/
#include <stdio.h>
#include <ctype.h>
#include "DirtySDK/platform.h"
#include "zlib.h"
#include "zmem.h"
#include "zmemtrack.h"
/*** Defines **********************************************************************/
#define ZMEMTRACK_MEMDUMPBYTES (64) //!< number of bytes to print around the leak
#define ZMEMTRACK_MAXALLOCATIONS (1024*8) //!< maximum list allocation size
/*** Type Definitions *************************************************************/
typedef struct ZMemtrackElemT
{
void *pMem;
uint32_t uMemSize;
uint32_t uTag;
} ZMemtrackElemT;
typedef struct ZMemtrackRefT
{
uint32_t uNumAllocations;
uint32_t uMaxAllocations;
uint32_t uTotalAllocations;
uint32_t uTotalMemory;
uint32_t uMaxMemory;
uint8_t bOverflow;
uint8_t bStarted;
uint8_t _pad[2];
ZMemtrackLogCbT *pLoggingCb;
void *pUserData;
ZMemtrackElemT MemList[ZMEMTRACK_MAXALLOCATIONS];
} ZMemtrackRefT;
/*** Variables ********************************************************************/
static ZMemtrackRefT _ZMemtrack_Ref;
/*** Private Functions ************************************************************/
/*F********************************************************************************/
/*!
\Function _ZMemtrackLogPrintf
\Description
Logs the information from the module
\Input *pFormat - information to log
\Input ... - additional parameters
\Version 09/18/2017 (eesponda)
*/
/********************************************************************************F*/
static void _ZMemtrackLogPrintf(const char *pFormat, ...)
{
char strText[2048];
int32_t iOffset = 0;
va_list Args;
ZMemtrackRefT *pRef = &_ZMemtrack_Ref;
// format output
va_start(Args, pFormat);
iOffset += ds_vsnprintf(strText+iOffset, sizeof(strText)-iOffset, pFormat, Args);
va_end(Args);
// forward to callback, or print if not callback installed
if (pRef->pLoggingCb != NULL)
{
pRef->pLoggingCb(strText, pRef->pUserData);
}
else
{
ZPrintf("zmemtrack: %s", strText);
}
}
/*F********************************************************************************/
/*!
\Function _ZMemtrackPrintLeak
\Description
Print a memory leak to debug output.
\Input *pElem - pointer to allocation that was leaked
\Version 02/15/2005 (jbrookes)
*/
/********************************************************************************F*/
static void _ZMemtrackPrintLeak(ZMemtrackElemT *pElem)
{
static const char _hex[] = "0123456789ABCDEF";
uint32_t uBytes;
char strOutput[128];
int32_t iOutput = 2;
_ZMemtrackLogPrintf("allocated: [%d] bytes at [%p] with tag '%c%c%c%c'\n", pElem->uMemSize, pElem->pMem,
(uint8_t)(pElem->uTag>>24), (uint8_t)(pElem->uTag>>16), (uint8_t)(pElem->uTag>>8), (uint8_t)(pElem->uTag));
ds_memset(strOutput, ' ', sizeof(strOutput)-1);
strOutput[sizeof(strOutput)-1] = '\0';
for (uBytes = 0; (uBytes < pElem->uMemSize) && (uBytes < ZMEMTRACK_MEMDUMPBYTES); uBytes++, iOutput += 2)
{
unsigned char cByte = ((unsigned char *)(pElem->pMem))[uBytes];
strOutput[iOutput] = _hex[cByte>>4];
strOutput[iOutput+1] = _hex[cByte&0xf];
strOutput[(iOutput/2)+40] = isprint(cByte) ? cByte : '.';
if (uBytes > 0)
{
if (((uBytes+1) % 16) == 0)
{
strOutput[(iOutput/2)+40+1] = '\0';
_ZMemtrackLogPrintf("%s\n", strOutput);
ds_memset(strOutput, ' ', sizeof(strOutput)-1);
strOutput[sizeof(strOutput)-1] = '\0';
iOutput = 0;
}
else if (((uBytes+1) % 4) == 0)
{
iOutput++;
}
}
}
if (((uBytes > ZMEMTRACK_MEMDUMPBYTES) && (uBytes % ZMEMTRACK_MEMDUMPBYTES) != 0) || (pElem->uMemSize < 16))
{
strOutput[(iOutput/2)+40+1] = '\0';
_ZMemtrackLogPrintf("%s\n", strOutput);
}
}
/*** Public functions *************************************************************/
/*F********************************************************************************/
/*!
\Function ZMemtrackStartup
\Description
Start up the ZMemtracking module.
\Version 02/15/2005 (jbrookes)
*/
/********************************************************************************F*/
void ZMemtrackStartup(void)
{
ZMemtrackRefT *pRef = &_ZMemtrack_Ref;
ds_memclr(pRef, sizeof(*pRef));
pRef->bStarted = TRUE;
}
/*F********************************************************************************/
/*!
\Function ZMemtrackShutdown
\Description
Shut down the ZMemtracking module.
\Version 02/15/2005 (jbrookes)
*/
/********************************************************************************F*/
void ZMemtrackShutdown(void)
{
// dump the current status of the entire module
ZMemtrackPrint(ZMEMTRACK_PRINTFLAG_TRACKING, 0, NULL);
_ZMemtrack_Ref.bStarted = FALSE;
}
/*F********************************************************************************/
/*!
\Function ZMemtrackCallback
\Description
Set the logging callback
\Input *pLoggingCb - logging function pointer
\Input *pUserData - additional data to pass along
\Version 09/18/2017 (eesponda)
*/
/********************************************************************************F*/
void ZMemtrackCallback(ZMemtrackLogCbT *pLoggingCb, void *pUserData)
{
ZMemtrackRefT *pRef = &_ZMemtrack_Ref;
pRef->pLoggingCb = pLoggingCb;
pRef->pUserData = pUserData;
}
/*F********************************************************************************/
/*!
\Function ZMemtrackAlloc
\Description
Track an allocation.
\Input *pMem - pointer to allocated memory block
\Input uSize - size of allocated memory block
\Input uTag - allocation tag
\Version 02/15/2005 (jbrookes)
*/
/********************************************************************************F*/
void ZMemtrackAlloc(void *pMem, uint32_t uSize, uint32_t uTag)
{
ZMemtrackRefT *pRef = &_ZMemtrack_Ref;
uint32_t uMemEntry;
// now if we got the memory, add to the list
if ((pMem == NULL) || (pRef->bStarted == FALSE))
{
return;
}
// find a clear spot
for (uMemEntry = 0; uMemEntry < ZMEMTRACK_MAXALLOCATIONS; uMemEntry++)
{
if (pRef->MemList[uMemEntry].pMem == NULL)
{
// get the memory location
pRef->uTotalMemory += uSize;
pRef->uNumAllocations += 1;
pRef->uTotalAllocations += 1;
// update high-water tracking
if (pRef->uMaxAllocations < pRef->uNumAllocations)
{
pRef->uMaxAllocations = pRef->uNumAllocations;
}
if (pRef->uMaxMemory < pRef->uTotalMemory)
{
pRef->uMaxMemory = pRef->uTotalMemory;
}
// store the info
pRef->MemList[uMemEntry].pMem = pMem;
pRef->MemList[uMemEntry].uMemSize = uSize;
pRef->MemList[uMemEntry].uTag = uTag;
break;
}
}
// check to see if we ran out of room to store this stuff
if (uMemEntry == ZMEMTRACK_MAXALLOCATIONS)
{
pRef->bOverflow = 1;
}
}
/*F********************************************************************************/
/*!
\Function ZMemtrackFree
\Description
Track a free operation.
\Input *pMem - pointer to allocated memory block
\Input *pSize - [out] storage for memory block size
\Version 02/15/2005 (jbrookes)
*/
/********************************************************************************F*/
void ZMemtrackFree(void *pMem, uint32_t *pSize)
{
ZMemtrackRefT *pRef = &_ZMemtrack_Ref;
uint32_t uMemEntry;
if ((pMem == NULL) || (pRef->bStarted == FALSE))
{
*pSize = 0;
return;
}
for (uMemEntry = 0, *pSize = 0; uMemEntry < ZMEMTRACK_MAXALLOCATIONS; uMemEntry++)
{
if (pRef->MemList[uMemEntry].pMem == pMem)
{
pRef->uTotalMemory -= pRef->MemList[uMemEntry].uMemSize;
pRef->uNumAllocations -= 1;
*pSize = pRef->MemList[uMemEntry].uMemSize;
ds_memclr(&pRef->MemList[uMemEntry], sizeof(pRef->MemList[uMemEntry]));
break;
}
}
}
/*F********************************************************************************/
/*!
\Function ZMemtrackPrint
\Description
Print overall memory info.
\Input uFlags - ZMemtrack_PRINTFLAG_*
\Input uTag - [optional] if non-zero, only display memory leaks stamped with this tag
\Input *pModuleName - [optional] pointer to module name
\Version 02/15/2005 (jbrookes)
*/
/********************************************************************************F*/
void ZMemtrackPrint(uint32_t uFlags, uint32_t uTag, const char *pModuleName)
{
ZMemtrackRefT *pRef = &_ZMemtrack_Ref;
uint32_t uMemEntry;
if (uFlags & ZMEMTRACK_PRINTFLAG_TRACKING)
{
_ZMemtrackLogPrintf("memory report\n");
_ZMemtrackLogPrintf(" maximum number of allocations at once: [%u]\n", pRef->uMaxAllocations);
_ZMemtrackLogPrintf(" current number of allocations : [%u]\n", pRef->uNumAllocations);
_ZMemtrackLogPrintf(" total number of allocations ever : [%u]\n", pRef->uTotalAllocations);
_ZMemtrackLogPrintf(" maximum memory allocated : [%u] bytes\n", pRef->uMaxMemory);
_ZMemtrackLogPrintf(" current memory allocated : [%u] bytes\n", pRef->uTotalMemory);
_ZMemtrackLogPrintf("\n");
}
if (pRef->bOverflow)
{
_ZMemtrackLogPrintf("WARNING: Allocation watcher overflowed!");
}
// see if there were any leaks
for (uMemEntry = 0; uMemEntry < ZMEMTRACK_MAXALLOCATIONS; uMemEntry++)
{
ZMemtrackElemT *pElem = &pRef->MemList[uMemEntry];
if ((pElem->pMem != NULL) && ((uTag == 0) || (pElem->uTag == uTag)))
{
break;
}
}
// if there were leaks, display them
if (uMemEntry != ZMEMTRACK_MAXALLOCATIONS)
{
_ZMemtrackLogPrintf("detected %s memory leaks!\n", pModuleName != NULL ? pModuleName : "");
for ( ; uMemEntry < ZMEMTRACK_MAXALLOCATIONS; uMemEntry++)
{
ZMemtrackElemT *pElem = &pRef->MemList[uMemEntry];
if ((pElem->pMem != NULL) && ((uTag == 0) || (pElem->uTag == uTag)))
{
_ZMemtrackPrintLeak(pElem);
}
}
}
}

View File

@ -0,0 +1,36 @@
/*H*************************************************************************************/
/*!
\File voipopus.c
\Description
PC Audio Encoder / Decoder using Opus
\Copyright
Copyright (c) Electronic Arts 2017. ALL RIGHTS RESERVED.
\Version 07/03/2017 (eesponda)
*/
/*************************************************************************************H*/
#ifndef _voipopus_h
#define _voipopus_h
/*** Includes **************************************************************************/
#include "DirtySDK/platform.h"
#include "DirtySDK/voip/voipcodec.h"
/*** Variables *************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
// opus codec definition
DIRTYCODE_API extern const VoipCodecDefT VoipOpus_CodecDef;
#if defined(__cplusplus)
}
#endif
#endif // _voipopus_h

View File

@ -0,0 +1,46 @@
/*H********************************************************************************/
/*!
\File voipspeex.h
\Description
PC Audio Encoder / Decoder using Speex
\Copyright
Copyright (c) Electronic Arts 2007. ALL RIGHTS RESERVED.
\Version 1.0 04/02/2007 (cadam) First version
*/
/********************************************************************************H*/
#ifndef _voipspeex_h
#define _voipspeex_h
/*** Include files ****************************************************************/
#include "DirtySDK/platform.h"
#include "DirtySDK/dirtysock/dirtymem.h"
#include "DirtySDK/voip/voipcodec.h"
#include "DirtySDK/voip/voip.h"
/*** Defines **********************************************************************/
/*** Macros ***********************************************************************/
/*** Type Definitions *************************************************************/
/*** Variables ********************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
// speex codec definition
DIRTYCODE_API extern const VoipCodecDefT VoipSpeex_CodecDef;
/*** Functions ********************************************************************/
#ifdef __cplusplus
}
#endif
#endif // _voipspeex_h

View File

@ -0,0 +1,582 @@
/*H*************************************************************************************/
/*!
\File voipopus.c
\Description
PC Audio Encoder / Decoder using Opus
\Copyright
Copyright (c) Electronic Arts 2017. ALL RIGHTS RESERVED.
\Notes
We depend on the Speex resampler for resampling (recommended by Opus)
\Version 07/03/2017 (eesponda)
*/
/*************************************************************************************H*/
/*** Include files *********************************************************************/
#include "DirtySDK/dirtysock.h"
#include <opus.h>
#include <speex/speex_resampler.h>
#include "DirtySDK/dirtysock/dirtyerr.h"
#include "DirtySDK/dirtysock/dirtymem.h"
#include "DirtySDK/voip/voip.h"
#include "voipopus.h"
/*** Defines ***************************************************************************/
//! maximum duration frame
#define VOIPOPUS_MAX_FRAME (5760)
//! sampling rate we support in Hz
#if !defined(VOIPOPUS_DEFAULT_SAMPLING_RATE)
#define VOIPOPUS_DEFAULT_SAMPLING_RATE (16000)
#endif
//! duration of the frame in milliseconds; 20ms
#define VOIPOPUS_FRAMEDURATION (20)
//! number of channels we support (mono or stereo)
#define VOIPOPUS_DEFAULT_CHANNELS (1)
//! hard-coded maximum output used when encoding, this is taken from value in voippacket.h (VOIP_MAXMICRPKTSIZE)
#define VOIPOPUS_MAX_OUTPUT (1238)
//! speex resampler quality value (it is a number from 1 - 10)
#define VOIPOPUS_RESAMPLER_QUALITY (3)
//! this much space will be needed to resample 20ms of audio
#define VOIPOPUS_RESAMPLE_BUFFER_SIZE ((VOIPOPUS_FRAMEDURATION * VOIPOPUS_DEFAULT_SAMPLING_RATE * sizeof(float)) / 1000)
/*** Macros ****************************************************************************/
//! calculate the sample rate based on number of samples
#define VOIPOPUS_GetSampleRate(uNumSamples) (((uNumSamples) * 1000) / VOIPOPUS_FRAMEDURATION)
/*** Type Definition *******************************************************************/
//! voipopus module state
typedef struct VoipOpusRefT
{
VoipCodecRefT CodecState;
int32_t iMemGroup; //!< memgroup id
void *pMemGroupUserData; //!< memgroup userdata
int32_t iVerbose; //!< logging verbosity level
int32_t iOutputVolume; //!< volumn configuration
uint32_t uSampleRateIn; //!< what is the sample rate of the data being passed to encode
uint32_t uResamplerRate; //!< sample rate that our resampler is configured to. this allows us to switch the resampler on and off without reallocation
uint8_t bInt32Input; //!< is the input data coming as 32 bit integers
uint8_t bFloatInput; //!< is the input data coming as 32 bit floats
uint8_t _pad[2];
SpeexResamplerState *pSpeexResampler; //!< resampler used if sample rate != VOIPOPUS_DEFAULT_SAMPLING_RATE
OpusEncoder *pEncoder; //!< opus encoder
OpusDecoder *aDecoders[1]; //!< opus variable decoders (must come last!)
} VoipOpusRefT;
/*** Function Prototypes ***************************************************************/
static VoipCodecRefT *_VoipOpusCreate(int32_t iNumDecoders);
static void _VoipOpusDestroy(VoipCodecRefT *pState);
static int32_t _VoipOpusEncodeBlock(VoipCodecRefT *pState, uint8_t *pOutput, const int16_t *pInput, int32_t iNumSamples);
static int32_t _VoipOpusDecodeBlock(VoipCodecRefT *pState, int32_t *pOutput, const uint8_t *pInput, int32_t iInputBytes, int32_t iChannel);
static void _VoipOpusReset(VoipCodecRefT *pState);
static int32_t _VoipOpusControl(VoipCodecRefT *pState, int32_t iControl, int32_t iValue, int32_t iValue2, void *pValue);
static int32_t _VoipOpusStatus(VoipCodecRefT *pState, int32_t iSelect, int32_t iValue, void *pBuffer, int32_t iBufSize);
/*** Variables *************************************************************************/
//! voipopus codec definition
const VoipCodecDefT VoipOpus_CodecDef =
{
_VoipOpusCreate,
_VoipOpusDestroy,
_VoipOpusEncodeBlock,
_VoipOpusDecodeBlock,
_VoipOpusReset,
_VoipOpusControl,
_VoipOpusStatus
};
#if DIRTYSOCK_ERRORNAMES
//! errors returned from the opus api
static const DirtyErrT _VoipOpus_aErrList[] =
{
DIRTYSOCK_ErrorName(OPUS_OK), // 0; No Error
DIRTYSOCK_ErrorName(OPUS_BAD_ARG), // -1; One of more invalid/out of range arguments
DIRTYSOCK_ErrorName(OPUS_BUFFER_TOO_SMALL), // -2; The mode struct passed is invalid
DIRTYSOCK_ErrorName(OPUS_INTERNAL_ERROR), // -3; An internal error was detected
DIRTYSOCK_ErrorName(OPUS_INVALID_PACKET), // -4; The compressed data passed is corrupted
DIRTYSOCK_ErrorName(OPUS_UNIMPLEMENTED), // -5; Invalid/unsupported request number
DIRTYSOCK_ErrorName(OPUS_INVALID_STATE), // -6; An encoder or decoder structure is invalid or already freed
DIRTYSOCK_ErrorName(OPUS_ALLOC_FAIL), // -7; Memory allocation has failed
DIRTYSOCK_ListEnd()
};
#endif
/*** Private Functions *****************************************************************/
/*F*************************************************************************************/
/*!
\Function _VoipOpusCreate
\Description
Create a Opus codec state.
\Input iNumDecoders - number of decoder channels
\Output
VoipCodecStateT * - pointer to opus codec state
\Version 07/03/2017 (eesponda)
*/
/*************************************************************************************F*/
static VoipCodecRefT *_VoipOpusCreate(int32_t iNumDecoders)
{
VoipOpusRefT *pState;
int32_t iResult, iMemGroup, iDecoder, iMemSize;
void *pMemGroupUserData;
// query memgroup information
iMemGroup = VoipStatus(NULL, 'mgrp', 0, NULL, 0);
VoipStatus(NULL, 'mgud', 0, &pMemGroupUserData, sizeof(pMemGroupUserData));
// allocate and initialize module state
iMemSize = sizeof(*pState) + (sizeof(OpusDecoder *) * (iNumDecoders - 1));
if ((pState = (VoipOpusRefT *)DirtyMemAlloc(iMemSize, VOIP_MEMID, iMemGroup, pMemGroupUserData)) == NULL)
{
NetPrintf(("voipopus: unable to allocate module state\n"));
return(NULL);
}
ds_memclr(pState, iMemSize);
pState->CodecState.pCodecDef = &VoipOpus_CodecDef;
pState->CodecState.iDecodeChannels = iNumDecoders;
pState->CodecState.bVadEnabled = TRUE;
pState->iMemGroup = iMemGroup;
pState->pMemGroupUserData = pMemGroupUserData;
pState->iVerbose = 2;
pState->iOutputVolume = 1 << VOIP_CODEC_OUTPUT_FRACTIONAL;
// allocate and initialize the encoder
if ((iMemSize = opus_encoder_get_size(VOIPOPUS_DEFAULT_CHANNELS)) <= 0)
{
NetPrintf(("voipopus: unable to get encoder size for allocation\n"));
_VoipOpusDestroy(&pState->CodecState);
return(NULL);
}
if ((pState->pEncoder = (OpusEncoder *)DirtyMemAlloc(iMemSize, VOIP_MEMID, iMemGroup, pMemGroupUserData)) == NULL)
{
NetPrintf(("voipopus: unable to allocate the encoder\n"));
_VoipOpusDestroy(&pState->CodecState);
return(NULL);
}
if ((iResult = opus_encoder_init(pState->pEncoder, VOIPOPUS_DEFAULT_SAMPLING_RATE, VOIPOPUS_DEFAULT_CHANNELS, OPUS_APPLICATION_VOIP)) != OPUS_OK)
{
NetPrintf(("voipopus: unable to initialize the encoder (err=%s)\n", DirtyErrGetNameList(iResult, _VoipOpus_aErrList)));
_VoipOpusDestroy(&pState->CodecState);
return(NULL);
}
// allocate and initialize the decoders
if ((iMemSize = opus_decoder_get_size(VOIPOPUS_DEFAULT_CHANNELS)) <= 0)
{
NetPrintf(("voipopus: unable to get decoder size for allocation\n"));
_VoipOpusDestroy(&pState->CodecState);
return(NULL);
}
for (iDecoder = 0; iDecoder < iNumDecoders; iDecoder += 1)
{
if ((pState->aDecoders[iDecoder] = (OpusDecoder *)DirtyMemAlloc(iMemSize, VOIP_MEMID, iMemGroup, pMemGroupUserData)) == NULL)
{
NetPrintf(("voipopus: unable to allocate the decoder\n"));
_VoipOpusDestroy(&pState->CodecState);
return(NULL);
}
if ((iResult = opus_decoder_init(pState->aDecoders[iDecoder], VOIPOPUS_DEFAULT_SAMPLING_RATE, VOIPOPUS_DEFAULT_CHANNELS)) != OPUS_OK)
{
NetPrintf(("voipopus: unable to initialize the decoder (err=%s)\n", DirtyErrGetNameList(iResult, _VoipOpus_aErrList)));
_VoipOpusDestroy(&pState->CodecState);
return(NULL);
}
}
return(&pState->CodecState);
}
/*F*************************************************************************************/
/*!
\Function _VoipOpusDestroy
\Description
Destroy the Opus codec state
\Input *pState - codec state
\Version 07/03/2017 (eesponda)
*/
/*************************************************************************************F*/
static void _VoipOpusDestroy(VoipCodecRefT *pState)
{
OpusDecoder **pDecoder;
int32_t iDecoder;
VoipOpusRefT *pOpus = (VoipOpusRefT *)pState;
for (iDecoder = 0; iDecoder < pOpus->CodecState.iDecodeChannels; iDecoder += 1)
{
if ((pDecoder = &pOpus->aDecoders[iDecoder]) != NULL)
{
DirtyMemFree(*pDecoder, VOIP_MEMID, pOpus->iMemGroup, pOpus->pMemGroupUserData);
*pDecoder = NULL;
}
}
if (pOpus->pEncoder != NULL)
{
DirtyMemFree(pOpus->pEncoder, VOIP_MEMID, pOpus->iMemGroup, pOpus->pMemGroupUserData);
pOpus->pEncoder = NULL;
}
if (pOpus->pSpeexResampler != NULL)
{
speex_resampler_destroy(pOpus->pSpeexResampler);
pOpus->pSpeexResampler = NULL;
}
DirtyMemFree(pOpus, VOIP_MEMID, pOpus->iMemGroup, pOpus->pMemGroupUserData);
}
/*F*************************************************************************************/
/*!
\Function _VoipOpusConvertInt32ToFloat
\Description
Convert int32_t samples into floats, within the same buffer passed in
\Input *pState - codec state
\Input *pInSamples - input int32_t samples
\Input iNumSamples - number of samples in pInSamples
\Output
int32_t - number of samples converted
\Version 04/09/2019 (cvienneau)
*/
/*************************************************************************************F*/
static int32_t _VoipOpusConvertInt32ToFloat(VoipCodecRefT *pState, uint8_t *pInBytes, int32_t iNumSamples)
{
VoipOpusRefT *pOpus = (VoipOpusRefT *)pState;
if (pOpus->bInt32Input)
{
int32_t *pInput = (int32_t*)pInBytes;
float *pOutput = (float*)pInBytes;
int32_t iBufferIndex;
for (iBufferIndex = 0; iBufferIndex < iNumSamples; ++iBufferIndex)
{
pOutput[iBufferIndex] = (float)pInput[iBufferIndex] / INT32_MAX;
}
return (iBufferIndex);
}
return(0);
}
/*F*************************************************************************************/
/*!
\Function _VoipOpusResample
\Description
Resample in coming samples to the rate of VOIPOPUS_DEFAULT_SAMPLING_RATE.
If VOIPOPUS_DEFAULT_SAMPLING_RATE equal iNumSamples no resampling is done.
\Input *pState - codec state
\Input *pInBytes - input samples in byte array
\Input iNumSamples - number of samples in pInBytes
\Input *pOutBytes - output samples written
\Input uOutBuffSize - size of pOutBytes
\Output
int32_t - number of samples written
\Version 03/26/2019 (tcho)
*/
/*************************************************************************************F*/
static int32_t _VoipOpusResample(VoipCodecRefT *pState, const uint8_t *pInBytes, int32_t iNumSamples, uint8_t *pOutBytes, uint32_t uOutBuffSize)
{
VoipOpusRefT *pOpus = (VoipOpusRefT *)pState;
int32_t iOutputSamples = iNumSamples; //default skipped resample
int32_t iError;
if (pOpus->bFloatInput)
{
iOutputSamples = uOutBuffSize / sizeof(float); //goes into speex_resampler_process_float as buffer size, comes out as samples written
if ((iError = speex_resampler_process_float(pOpus->pSpeexResampler, 0, (const float *)pInBytes, (uint32_t *)&iNumSamples, (float *)pOutBytes, (uint32_t *)&iOutputSamples)) != 0)
{
NetPrintf(("voipopus: error resampling float, %d input samples (Error = %d).\n", iNumSamples, iError));
}
}
else
{
iOutputSamples = uOutBuffSize / sizeof(int16_t); //goes into speex_resampler_process_int as buffer size, comes out as samples written
if ((iError = speex_resampler_process_int(pOpus->pSpeexResampler, 0, (const int16_t *)pInBytes, (uint32_t *)&iNumSamples, (int16_t *)pOutBytes, (uint32_t *)&iOutputSamples)) != 0)
{
NetPrintf(("voipopus: error resampling int16, %d input samples, %d (Error = %d).\n", iNumSamples, iError));
}
}
return(iOutputSamples);
}
/*F*************************************************************************************/
/*!
\Function _VoipOpusEncodeBlock
\Description
Encode a buffer 16-bit audio or float sample using the Opus encoder
\Input *pState - codec state
\Input *pOutput - [out] outbut buffer
\Input *pInput - input buffer
\Input iNumSamples - the number of samples to encode
\Output
int32_t - positive=number of encoded bytes, negative=error
\Version 07/03/2017 (eesponda)
*/
/*************************************************************************************F*/
static int32_t _VoipOpusEncodeBlock(VoipCodecRefT *pState, uint8_t *pOutput, const int16_t *pInput, int32_t iNumSamples)
{
VoipOpusRefT *pOpus = (VoipOpusRefT *)pState;
int32_t iResult = -1;
uint32_t uSampleRateIn;
uint8_t aResampledData[VOIPOPUS_RESAMPLE_BUFFER_SIZE];
/* if we haven't set a sample rate manually via the 'insr' control calculate the sample rate based on number of samples. this is with the assumption of 20ms audio
$$todo$$ investigate removing the manual calls of 'insr' on xbox if we can confirm that this calculation works */
uSampleRateIn = (pOpus->uSampleRateIn == 0) ? VOIPOPUS_GetSampleRate(iNumSamples) : pOpus->uSampleRateIn;
// convert the data to a useable format if needed
iResult = _VoipOpusConvertInt32ToFloat(pState, (uint8_t*)pInput, iNumSamples);
if (uSampleRateIn != VOIPOPUS_DEFAULT_SAMPLING_RATE)
{
// re-create the resampler if needed
if (uSampleRateIn != pOpus->uResamplerRate)
{
if (pOpus->pSpeexResampler != NULL)
{
speex_resampler_destroy(pOpus->pSpeexResampler);
}
if ((pOpus->pSpeexResampler = speex_resampler_init_frac(VOIPOPUS_DEFAULT_CHANNELS, uSampleRateIn, VOIPOPUS_DEFAULT_SAMPLING_RATE, uSampleRateIn, VOIPOPUS_DEFAULT_SAMPLING_RATE, VOIPOPUS_RESAMPLER_QUALITY, &iResult)) == NULL)
{
NetPrintf(("voipopus: unable to allocate resampler (Error = %d).\n", iResult));
return(iResult);
}
pOpus->uResamplerRate = uSampleRateIn;
}
// resample the data if needed
iResult = _VoipOpusResample(pState, (uint8_t*)pInput, iNumSamples, aResampledData, sizeof(aResampledData));
if (iResult != iNumSamples)
{
pInput = (const int16_t*)aResampledData;
iNumSamples = iResult;
}
}
// encode as float or int16
if (pOpus->bFloatInput)
{
if ((iResult = opus_encode_float(pOpus->pEncoder, (float*)pInput, iNumSamples, pOutput, VOIPOPUS_MAX_OUTPUT)) < 0)
{
NetPrintf(("voipopus: unable to encode float (err=%s)\n", DirtyErrGetNameList(iResult, _VoipOpus_aErrList)));
}
}
else
{
if ((iResult = opus_encode(pOpus->pEncoder, pInput, iNumSamples, pOutput, VOIPOPUS_MAX_OUTPUT)) < 0)
{
NetPrintf(("voipopus: unable to encode int16_t (err=%s)\n", DirtyErrGetNameList(iResult, _VoipOpus_aErrList)));
}
}
return(iResult);
}
/*F*************************************************************************************/
/*!
\Function _VoipOpusDecodeBlock
\Description
Decode a Opus encoded input to 16-bit linear PCM samples
\Input *pState - codec state
\Input *pOutput - [out] outbut buffer
\Input *pInput - input buffer
\Input iInputBytes - size of the input buffer
\Input iChannel - the decode channel for which we are decoding data
\Output
int32_t - positive=number of decoded samples, negative=error
\Version 07/03/2017 (eesponda)
*/
/*************************************************************************************F*/
static int32_t _VoipOpusDecodeBlock(VoipCodecRefT *pState, int32_t *pOutput, const uint8_t *pInput, int32_t iInputBytes, int32_t iChannel)
{
VoipOpusRefT *pOpus = (VoipOpusRefT *)pState;
int32_t iResult, iSample;
int16_t aOutput[VOIPOPUS_MAX_FRAME];
if ((iChannel < 0) || (iChannel > pOpus->CodecState.iDecodeChannels))
{
NetPrintf(("voipopus: trying to decode with invalid decoder channel\n"));
return(-1);
}
if ((iResult = opus_decode(pOpus->aDecoders[iChannel], pInput, iInputBytes, aOutput, VOIPOPUS_MAX_FRAME, 0)) < 0)
{
NetPrintf(("voipopus: unable to decode (err=%s)\n", DirtyErrGetNameList(iResult, _VoipOpus_aErrList)));
}
// accumulate output in the expected format
for (iSample = 0; iSample < iResult; iSample += 1)
{
pOutput[iSample] += (aOutput[iSample] * pOpus->iOutputVolume) >> VOIP_CODEC_OUTPUT_FRACTIONAL;
}
return(iResult);
}
/*F*************************************************************************************/
/*!
\Function _VoipOpusReset
\Description
Reset the codec state
\Input *pState - codec state
\Version 07/03/2017 (eesponda)
*/
/*************************************************************************************F*/
static void _VoipOpusReset(VoipCodecRefT *pState)
{
int32_t iChannel;
VoipOpusRefT *pOpus = (VoipOpusRefT *)pState;
opus_encoder_ctl(pOpus->pEncoder, OPUS_RESET_STATE);
for (iChannel = 0; iChannel < pOpus->CodecState.iDecodeChannels; iChannel += 1)
{
opus_decoder_ctl(pOpus->aDecoders[iChannel], OPUS_RESET_STATE);
}
}
/*F*************************************************************************************/
/*!
\Function _VoipOpusControl
\Description
Set control options
\Input *pState - codec state
\Input iControl - control selector
\Input iValue - selector specific
\Input iValue2 - selector specific
\Input *pValue - selector specific
\Output
int32_t - selector specific
\Notes
iControl can be one of the following:
\verbatim
'plvl' - Set the output volumn
'infl' - Set if the input samples are float via iValue, (default int16)
'inin' - Set if the input samples are int32_t via iValue, (default int16)
'insr' - Set the input sample rate
'spam' - Set debug output verbosity
\endverbatim
\Version 07/03/2017 (eesponda)
*/
/*************************************************************************************F*/
static int32_t _VoipOpusControl(VoipCodecRefT *pState, int32_t iControl, int32_t iValue, int32_t iValue2, void *pValue)
{
VoipOpusRefT *pOpus = (VoipOpusRefT *)pState;
if (iControl == 'plvl')
{
pOpus->iOutputVolume = iValue;
return(0);
}
if (iControl == 'infl')
{
pOpus->bInt32Input = FALSE;
pOpus->bFloatInput = iValue;
return(0);
}
if (iControl == 'inin')
{
pOpus->bInt32Input = iValue; //int32s are converted to float, so we set both
pOpus->bFloatInput = iValue;
return(0);
}
if (iControl == 'insr')
{
pOpus->uSampleRateIn = iValue;
return(0);
}
if (iControl == 'spam')
{
pOpus->iVerbose = iValue;
return(0);
}
// unhandled control
return(-1);
}
/*F*************************************************************************************/
/*!
\Function _VoipOpusStatus
\Description
Get codec status
\Input *pState - codec state
\Input iSelect - status selector
\Input iValue - selector-specific
\Input *pBuffer - [out] storage for selector output
\Input iBufSize - size of output buffer
\Output
int32_t - selector specific
\Notes
iSelect can be one of the following:
\verbatim
'vlen' - returns TRUE to indicate we are using variable length frames
\endverbatim
\Version 07/03/2017 (eesponda)
*/
/*************************************************************************************F*/
static int32_t _VoipOpusStatus(VoipCodecRefT *pState, int32_t iSelect, int32_t iValue, void *pBuffer, int32_t iBufSize)
{
if (iSelect == 'vlen')
{
*(uint8_t *)pBuffer = TRUE;
return(0);
}
// unhandle selector
return(-1);
}

View File

@ -0,0 +1,663 @@
/*H*************************************************************************************************/
/*!
\File voipspeex.c
\Description
PC Audio Encoder / Decoder using Speex
\Copyright
Copyright (c) Electronic Arts 2007. ALL RIGHTS RESERVED.
\Version 1.0 04/02/2007 (cadam) First version
*/
/*************************************************************************************************H*/
/*** Include files *********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "DirtySDK/dirtysock/dirtylib.h"
#include "DirtySDK/dirtysock/dirtymem.h"
#include "voipspeex.h"
#include <speex/speex.h>
#include <speex/speex_preprocess.h>
/*** Defines ***************************************************************************/
#define VOIPSPEEX_ENABLED (TRUE) // enable speex codec
#ifndef VOIPSPEEX_PREPROCESS
#define VOIPSPEEX_PREPROCESS (0) // Speex preprocessor
#endif
// encode/decode information
#define VOIPSPEEX_FRAME_SIZE (160)
#define VOIPSPEEX_MAX_BYTES (200)
#define VOIPSPEEX_COMP_SIZE (38)
// speex settings
#define VOIPSPEEX_COMPLEXITY (1)
#define VOIPSPEEX_QUALITY (8)
#define VOIPSPEEX_PERCEPTUAL (1)
// speex preprocessor settings
#define VOIPSPEEX_DENOISE (1)
#define VOIPSPEEX_AGC (1)
#define VOIPSPEEX_PROB_START (30)
#define VOIPSPEEX_PROB_CONTINUE (7)
/*** Macros ****************************************************************************/
/*** Type Definitions ******************************************************************/
//! voipspeex decoder ref
typedef struct VoipSpeexDecoderT
{
int32_t iChannel;
void *pDecodeState;
} VoipSpeexDecoderT;
//! voipspeex module state
typedef struct VoipSpeexStateT
{
VoipCodecRefT CodecState;
// module memory group
int32_t iMemGroup;
void *pMemGroupUserData;
int32_t iNumChannels;
int32_t iOutputVolume;
SpeexBits sEncodeBits;
SpeexBits *pDecodeBits;
void *pEncodeState;
VoipSpeexDecoderT *pDecoders;
SpeexPreprocessState *pPreprocessor;
#if DIRTYCODE_LOGGING
int32_t iDebugLevel;
#endif
} VoipSpeexStateT;
/*** Function Prototypes ***************************************************************/
#if VOIPSPEEX_ENABLED
static VoipCodecRefT *_VoipSpeexCreate(int32_t iDecodeChannels);
static void _VoipSpeexDestroy(VoipCodecRefT *pState);
static int32_t _VoipSpeexEncodeBlock(VoipCodecRefT *pState, uint8_t *pOut, const int16_t *pInp, int32_t iNumSamples);
static int32_t _VoipSpeexDecodeBlock(VoipCodecRefT *pState, int32_t *pOut, const uint8_t *pInp, int32_t iInputBytes, int32_t iChannel);
static void _VoipSpeexReset(VoipCodecRefT *pState);
static int32_t _VoipSpeexControl(VoipCodecRefT *pState, int32_t iControl, int32_t iValue, int32_t iValue2, void *pValue);
static int32_t _VoipSpeexStatus(VoipCodecRefT *pState, int32_t iSelect, int32_t iValue, void *pBuffer, int32_t iBufSize);
#else
static VoipCodecRefT *_VoipSpeexCreate(int32_t iDecodeChannels) { return NULL; }
static void _VoipSpeexDestroy(VoipCodecRefT *pState) { }
static int32_t _VoipSpeexEncodeBlock(VoipCodecRefT *pState, uint8_t *pOut, const int16_t *pInp, int32_t iNumSamples) { return -1; }
static int32_t _VoipSpeexDecodeBlock(VoipCodecRefT *pState, int32_t *pOut, const uint8_t *pInp, int32_t iInputBytes, int32_t iChannel) { return -1; }
static void _VoipSpeexReset(VoipCodecRefT *pState) { }
static int32_t _VoipSpeexControl(VoipCodecRefT *pState, int32_t iControl, int32_t iValue, int32_t iValue2, void *pValue) { return -1; }
static int32_t _VoipSpeexStatus(VoipCodecRefT *pState, int32_t iSelect, int32_t iValue, void *pBuffer, int32_t iBufSize) { return -1; }
#endif
/*** Variables *************************************************************************/
//! voipspeex codec block
const VoipCodecDefT VoipSpeex_CodecDef =
{
_VoipSpeexCreate,
_VoipSpeexDestroy,
_VoipSpeexEncodeBlock,
_VoipSpeexDecodeBlock,
_VoipSpeexReset,
_VoipSpeexControl,
_VoipSpeexStatus,
};
#if VOIPSPEEX_ENABLED
/*** Private Functions *****************************************************************/
/*F*************************************************************************************************/
/*!
\Function _VoipSpeexSetControls
\Description
Sets all the controls on the codec
\Input pCodecState - codec state
\Version 01/12/08 (grouse)
*/
/*************************************************************************************************F*/
static void _VoipSpeexSetControls( VoipCodecRefT *pCodecState )
{
VoipSpeexStateT *pState = (VoipSpeexStateT *)pCodecState;
int32_t iChannel;
int32_t iComplexity = VOIPSPEEX_COMPLEXITY;
int32_t iQuality = VOIPSPEEX_QUALITY;
int32_t iPerceptual = VOIPSPEEX_PERCEPTUAL;
#if VOIPSPEEX_PREPROCESS
int32_t iDenoise = VOIPSPEEX_DENOISE;
int32_t iAGC = VOIPSPEEX_AGC;
int32_t iProbStart = VOIPSPEEX_PROB_START;
int32_t iProbContinue = VOIPSPEEX_PROB_CONTINUE;
#endif
int32_t iReturnVal = 0;
iReturnVal = speex_encoder_ctl(pState->pEncodeState, SPEEX_SET_COMPLEXITY, &iComplexity);
if( iReturnVal != 0 )
{
NetPrintf(("voipspeex: error setting encoder control SPEEX_SET_COMPLEXITY with code %d\n", iReturnVal));
}
iReturnVal = speex_encoder_ctl(pState->pEncodeState, SPEEX_SET_QUALITY, &iQuality);
if( iReturnVal != 0 )
{
NetPrintf(("voipspeex: error setting encoder control SPEEX_SET_QUALITY with code %d\n", iReturnVal));
}
for (iChannel=0; iChannel < pState->CodecState.iDecodeChannels; iChannel++)
{
iReturnVal = speex_decoder_ctl(pState->pDecoders[iChannel].pDecodeState, SPEEX_SET_ENH, &iPerceptual);
if( iReturnVal != 0 )
{
NetPrintf(("voipspeex: error setting decoder control SPEEX_SET_ENH for decoder %d with code %d\n", iChannel, iReturnVal));
}
}
#if VOIPSPEEX_PREPROCESS
iReturnVal = speex_preprocess_ctl(pState->pPreprocessor, SPEEX_PREPROCESS_SET_DENOISE, &iDenoise);
if( iReturnVal != 0 )
{
NetPrintf(("voipspeex: error setting preprocessor control SPEEX_PREPROCESS_SET_DENOISE with code %d\n", iReturnVal));
}
iReturnVal = speex_preprocess_ctl(pState->pPreprocessor, SPEEX_PREPROCESS_SET_AGC, &iAGC);
if( iReturnVal != 0 )
{
NetPrintf(("voipspeex: error setting preprocessor control SPEEX_PREPROCESS_SET_AGC with code %d\n", iReturnVal));
}
iReturnVal = speex_preprocess_ctl(pState->pPreprocessor, SPEEX_PREPROCESS_SET_PROB_START, &iProbStart);
if( iReturnVal != 0 )
{
NetPrintf(("voipspeex: error re-setting preprocessor control SPEEX_PREPROCESS_SET_PROB_START with code %d\n", iReturnVal));
}
iReturnVal = speex_preprocess_ctl(pState->pPreprocessor, SPEEX_PREPROCESS_SET_PROB_CONTINUE, &iProbContinue);
if( iReturnVal != 0 )
{
NetPrintf(("voipspeex: error re-setting preprocessor control SPEEX_PREPROCESS_SET_PROB_CONTINUE with code %d\n", iReturnVal));
}
#endif
}
/*F*************************************************************************************************/
/*!
\Function _VoipSpeexCreate
\Description
Create a Speex codec state.
\Input iDecodeChannels - number of decoder channels
\Output
VoipCodecStateT * - pointer to speex codec state
\Version 04/02/2007 (cadam)
*/
/*************************************************************************************************F*/
static VoipCodecRefT *_VoipSpeexCreate(int32_t iDecodeChannels)
{
VoipSpeexStateT *pState;
int32_t iMemGroup;
void *pMemGroupUserData;
int32_t iChannel;
// Query mem group id
iMemGroup = VoipStatus(NULL, 'mgrp', 0, NULL, 0);
// Query mem group user data
VoipStatus(NULL, 'mgud', 0, &pMemGroupUserData, sizeof(pMemGroupUserData));
// allocate memory for the state structure and initialize the variables
pState = (VoipSpeexStateT *)DirtyMemAlloc(sizeof(VoipSpeexStateT), VOIP_MEMID, iMemGroup, pMemGroupUserData);
ds_memclr(pState, sizeof(VoipSpeexStateT));
NetPrintfVerbose((pState->iDebugLevel, 0, "voipspeex: allocated module reference at %p\n", pState));
// initialize the state variables
pState->CodecState.pCodecDef = &VoipSpeex_CodecDef;
pState->CodecState.iDecodeChannels = iDecodeChannels;
pState->CodecState.bVadEnabled = TRUE;
pState->iMemGroup = iMemGroup;
pState->pMemGroupUserData = pMemGroupUserData;
pState->iNumChannels = iDecodeChannels;
// set the power threshold and output level
pState->iOutputVolume = 1 << VOIP_CODEC_OUTPUT_FRACTIONAL;
// initialize the speex bits
speex_bits_init(&pState->sEncodeBits);
// create and initialize the encoder
pState->pEncodeState = speex_encoder_init(&speex_nb_mode);
if (pState->pEncodeState == NULL)
{
NetPrintf(("voipspeex: failed to create encoder\n"));
speex_bits_destroy(&pState->sEncodeBits);
DirtyMemFree(pState, VOIP_MEMID, pState->iMemGroup, pState->pMemGroupUserData);
return(NULL);
}
// allocate an array of pointers to hold pointers to one decoder per channel
pState->pDecoders = DirtyMemAlloc(sizeof(VoipSpeexDecoderT) * iDecodeChannels, VOIP_MEMID, pState->iMemGroup, pState->pMemGroupUserData);
NetPrintfVerbose((pState->iDebugLevel, 0, "voipspeex: decoder array allocated %d bytes at %p\n", sizeof(VoipSpeexDecoderT) * iDecodeChannels, pState->pDecoders));
pState->pDecodeBits = DirtyMemAlloc(sizeof(SpeexBits) * iDecodeChannels, VOIP_MEMID, pState->iMemGroup, pState->pMemGroupUserData);
NetPrintfVerbose((pState->iDebugLevel, 0, "voipspeex: decode bits array allocated %d bytes at %p\n", sizeof(SpeexBits) * iDecodeChannels, pState->pDecodeBits));
// initialize the decoders
for (iChannel = 0; iChannel < pState->iNumChannels; iChannel++)
{
pState->pDecoders[iChannel].iChannel = iChannel;
pState->pDecoders[iChannel].pDecodeState = speex_decoder_init(&speex_nb_mode);
if (pState->pDecoders[iChannel].pDecodeState == NULL)
{
// we only need to destroy the ones before the failure
pState->iNumChannels = iChannel;
NetPrintf(("voipspeex: failed to create decoder %d\n", iChannel));
for (iChannel = 0; iChannel < pState->iNumChannels; iChannel++)
{
speex_decoder_destroy(pState->pDecoders[iChannel].pDecodeState);
speex_bits_destroy(&pState->pDecodeBits[iChannel]);
}
DirtyMemFree(pState->pDecoders, VOIP_MEMID, pState->iMemGroup, pState->pMemGroupUserData);
DirtyMemFree(pState->pDecodeBits, VOIP_MEMID, pState->iMemGroup, pState->pMemGroupUserData);
speex_encoder_destroy(pState->pEncodeState);
DirtyMemFree(pState, VOIP_MEMID, pState->iMemGroup, pState->pMemGroupUserData);
return(NULL);
}
speex_bits_init(&pState->pDecodeBits[iChannel]);
}
#if VOIPSPEEX_PREPROCESS
pState->pPreprocessor = speex_preprocess_state_init(VOIPSPEEX_FRAME_SIZE, 8000);
if (pState->pPreprocessor == NULL)
{
NetPrintf(("voipspeex: Failed to create pre-processor\n"));
for (iChannel = 0; iChannel < pState->iNumChannels; iChannel++)
{
if (pState->pDecoders[iChannel].pDecodeState)
{
speex_decoder_destroy(pState->pDecoders[iChannel].pDecodeState);
speex_bits_destroy(&pState->pDecodeBits[iChannel]);
}
}
DirtyMemFree(pState->pDecoders, VOIP_MEMID, pState->iMemGroup, pState->pMemGroupUserData);
DirtyMemFree(pState->pDecodeBits, VOIP_MEMID, pState->iMemGroup, pState->pMemGroupUserData);
speex_encoder_destroy(pState->pEncodeState);
DirtyMemFree(pState, VOIP_MEMID, pState->iMemGroup, pState->pMemGroupUserData);
return(NULL);
}
#else
pState->pPreprocessor = NULL;
#endif
_VoipSpeexSetControls(&pState->CodecState);
NetPrintfVerbose((pState->iDebugLevel, 0, "voipspeex: returning %p\n", &pState->CodecState));
return(&pState->CodecState);
}
/*F*************************************************************************************************/
/*!
\Function _VoipSpeexDestroy
\Description
Destroy a Speex codec state.
\Input *pState - state to destroy
\Version 04/02/2007 (cadam)
*/
/*************************************************************************************************F*/
static void _VoipSpeexDestroy(VoipCodecRefT *pCodecState)
{
int32_t i;
VoipSpeexStateT *pState = (VoipSpeexStateT *)pCodecState;
#if VOIPSPEEX_PREPROCESS
speex_preprocess_state_destroy(pState->pPreprocessor);
#endif
// destroy the decoders then free the memory that was allocated for them
for (i = 0; i < pState->iNumChannels; i++)
{
speex_decoder_destroy(pState->pDecoders[i].pDecodeState);
speex_bits_destroy(&pState->pDecodeBits[i]);
}
// free the array that held the decoders
DirtyMemFree(pState->pDecoders, VOIP_MEMID, pState->iMemGroup, pState->pMemGroupUserData);
// free the array that held the decode bits
DirtyMemFree(pState->pDecodeBits, VOIP_MEMID, pState->iMemGroup, pState->pMemGroupUserData);
// destroy the encoder
speex_encoder_destroy(pState->pEncodeState);
// destroy the SpeexBits
speex_bits_destroy(&pState->sEncodeBits);
// free the state
DirtyMemFree(pState, VOIP_MEMID, pState->iMemGroup, pState->pMemGroupUserData);
}
/*F*************************************************************************************************/
/*!
\Function _VoipSpeexEncodeBlock
\Description
Encode a buffer 16-bit audio samples using the Speex encoder.
\Input *pState - pointer to encode state
\Input *pOut - pointer to output buffer
\Input *pInp - pointer to input buffer
\Input iNumSamples - number of samples to encode
\Output
int32_t - size of compressed data in bytes
\Version 04/05/2007 (cadam)
*/
/*************************************************************************************************F*/
static int32_t _VoipSpeexEncodeBlock(VoipCodecRefT *pCodecState, unsigned char *pOut, const int16_t *pInp, int32_t iNumSamples)
{
int32_t iFrame, iNumFrames, iSample;
VoipSpeexStateT *pState = (VoipSpeexStateT *)pCodecState;
unsigned char *pOutput = pOut;
const int16_t *pInput = pInp;
spx_int16_t iFrameBuffer[VOIPSPEEX_FRAME_SIZE];
int32_t iNumBytes, iNumBytesEncoded = 0;
iNumFrames = iNumSamples/VOIPSPEEX_FRAME_SIZE;
NetPrintfVerbose((pState->iDebugLevel, 2, "voipspeex: encoding %d samples (%d frames)\n", iNumSamples, iNumFrames));
if ((iNumSamples % VOIPSPEEX_FRAME_SIZE) != 0)
{
NetPrintf(("voipspeex: error - speex encoder can only encode multiples of %d samples.\n", VOIPSPEEX_FRAME_SIZE));
return(0);
}
for (iFrame = 0; iFrame < iNumFrames; iFrame++)
{
ds_memclr(iFrameBuffer, sizeof(iFrameBuffer));
// convert the 16 bit input values to a float buffer for Speex
for (iSample = 0; iSample < VOIPSPEEX_FRAME_SIZE; iSample++)
{
iFrameBuffer[iSample] = pInput[iSample];
}
// reset the SpeexBits
speex_bits_reset(&pState->sEncodeBits);
#if VOIPSPEEX_PREPROCESS
speex_preprocess(pState->pPreprocessor, iFrameBuffer, NULL);
#endif
// encode the frame
speex_encode_int(pState->pEncodeState, iFrameBuffer, &pState->sEncodeBits);
// write the result to the output and get the number of bytes written
iNumBytes = speex_bits_write(&pState->sEncodeBits, (char *)pOutput, VOIPSPEEX_MAX_BYTES);
// increment the pointers and the total number of bytes written
pInput += VOIPSPEEX_FRAME_SIZE;
pOutput += iNumBytes;
iNumBytesEncoded += iNumBytes;
}
return(iNumBytesEncoded);
}
/*F*************************************************************************************************/
/*!
\Function _VoipSpeexDecodeBlock
\Description
Decode Speex-encoded input to 16-bit linear PCM samples, and accumulate in the given output buffer.
\Input *pState - pointer to decode state
\Input *pOut - pointer to output buffer
\Input *pInp - pointer to input buffer
\Input iInputBytes - size of input data
\Input iChannel - the decode channel for which we are decoding data
\Output
int32_t - number of samples decoded
\Version 04/05/2007 (cadam)
*/
/*************************************************************************************************F*/
static int32_t _VoipSpeexDecodeBlock(VoipCodecRefT *pCodecState, int32_t *pOut, const unsigned char *pInp, int32_t iInputBytes, int32_t iChannel)
{
int32_t iFrame, iFrameSize, iNumFrames, iSample;
VoipSpeexStateT *pState = (VoipSpeexStateT *)pCodecState;
int32_t *pOutput = pOut;
unsigned char *pInput = (unsigned char *)pInp;
spx_int16_t iFrameBuffer[VOIPSPEEX_FRAME_SIZE];
iFrameSize = VOIPSPEEX_COMP_SIZE;
iNumFrames = iInputBytes/iFrameSize;
if (iInputBytes == 0)
{
NetPrintf(("voipspeex: no data to decode\n"));
return(0);
}
if ((iInputBytes % iFrameSize) != 0)
{
NetPrintf(("voipspeex: speex decoder can only decode multiples of %d bytes (%d submitted)\n", iFrameSize, iInputBytes));
return(0);
}
NetPrintfVerbose((pState->iDebugLevel, 2, "voipspeex: decoding %d bytes (%d frames)\n", iInputBytes, iNumFrames));
for (iFrame = 0; iFrame < iNumFrames; iFrame++)
{
ds_memclr(iFrameBuffer, sizeof(iFrameBuffer));
// reset the SpeexBits
speex_bits_reset(&pState->pDecodeBits[iChannel]);
// read the bits from the input
speex_bits_read_from(&pState->pDecodeBits[iChannel], (char *)pInput, iFrameSize);
// decode the bits
speex_decode_int(pState->pDecoders[iChannel].pDecodeState, &pState->pDecodeBits[iChannel], iFrameBuffer);
// convert the float buffer to an int32_t array for Speex
for (iSample = 0; iSample < VOIPSPEEX_FRAME_SIZE; iSample++)
{
pOutput[iSample] += (((int32_t)iFrameBuffer[iSample] * pState->iOutputVolume) >> VOIP_CODEC_OUTPUT_FRACTIONAL);
}
// increment the pointers and the total number of bytes written
pInput += iFrameSize;
pOutput += VOIPSPEEX_FRAME_SIZE;
}
return(iNumFrames * VOIPSPEEX_FRAME_SIZE);
}
/*F*************************************************************************************************/
/*!
\Function _VoipSpeexReset
\Description
Resets codec state.
\Input *pState - pointer to decode state
\Version 04/05/2007 (cadam)
*/
/*************************************************************************************************F*/
static void _VoipSpeexReset(VoipCodecRefT *pCodecState)
{
int32_t i;
VoipSpeexStateT *pState = (VoipSpeexStateT *)pCodecState;
// reset the SpeexBits
speex_bits_reset(&pState->sEncodeBits);
// reset the encoder
speex_encoder_ctl(pState->pEncodeState, SPEEX_RESET_STATE, NULL);
// reset the decoders
for (i = 0; i < pState->iNumChannels; i++)
{
speex_decoder_ctl(pState->pDecoders[i].pDecodeState, SPEEX_RESET_STATE, NULL);
}
_VoipSpeexSetControls(&pState->CodecState);
}
/*F*************************************************************************************************/
/*!
\Function _VoipSpeexControl
\Description
Modifies parameters of the codec
\Input *pState - pointer to decode state
\Input iControl - control selector
\Input iValue - selector specific
\Input iValue2 - selector specific
\Input *pValue - selector specific
\Output
int32_t - selector specific
\Notes
iControl can be one of the following:
\verbatim
'plvl' - Set the output power level
'spam' - Set debug output verbosity (debug only)
\endverbatim
\Version 03/12/2008 (grouse)
*/
/*************************************************************************************************F*/
static int32_t _VoipSpeexControl(VoipCodecRefT *pCodecState, int32_t iControl, int32_t iValue, int32_t iValue2, void *pValue)
{
VoipSpeexStateT *pState = (VoipSpeexStateT *)pCodecState;
if ((iControl == 'plvl') && (pState != NULL))
{
pState->iOutputVolume = iValue;
return(0);
}
#if DIRTYCODE_LOGGING
if ((iControl == 'spam') && (pState != NULL))
{
pState->iDebugLevel = iValue;
return(0);
}
#endif
NetPrintf(("voipspeex: unhandled control selector '%C'\n", iControl));
return(-1);
}
/*F*************************************************************************************************/
/*!
\Function _VoipSpeexStatus
\Description
Get codec status
\Input *pCodecState - pointer to decode state
\Input iSelect - status selector
\Input iValue - selector-specific
\Input *pBuffer - [out] storage for selector output
\Input iBufSize - size of output buffer
\Output
int32_t - selector specific
\Notes
iSelect can be one of the following:
\verbatim
'fsiz' - size of encoder output / decoder input in bytes (iValue=samples per frame)
'fsmp' - frame sample size for current codec
\endverbatim
\Version 10/11/2011 (jbrookes)
*/
/*************************************************************************************************F*/
static int32_t _VoipSpeexStatus(VoipCodecRefT *pCodecState, int32_t iSelect, int32_t iValue, void *pBuffer, int32_t iBufSize)
{
VoipSpeexStateT *pModuleState = (VoipSpeexStateT *)pCodecState;
// these options require module state
if (pModuleState != NULL)
{
if (iSelect == 'fsiz')
{
return((iValue/VOIPSPEEX_FRAME_SIZE) * VOIPSPEEX_COMP_SIZE);
}
if (iSelect == 'fsmp')
{
return(VOIPSPEEX_FRAME_SIZE);
}
}
NetPrintfVerbose((pModuleState->iDebugLevel, 1, "voipspeex: unhandled status selector '%C'\n", iSelect));
return(-1);
}
// speex function overrides
void _speex_fatal(const char *str, const char *file, int line)
{
NetPrintf(("Fatal (internal) error in %s, line %d: %s\n", file, line, str ));
}
void speex_warning(const char *str)
{
NetPrintf(("libspeex: warning: %s\n", str));
}
void speex_warning_int(const char *str, int val)
{
NetPrintf(("libspeex: warning: %s %d\n", str, val));
}
void speex_notify(const char *str)
{
NetPrintf(("libspeex: notification: %s\n", str));
}
#endif // VOIPSPEEX_ENABLED

View File

@ -0,0 +1,337 @@
/*H*************************************************************************************/
/*!
\File commall.h
\Description
This is the common communication header required for use with any
of the CommXXXX routines. It provides a unified calling structure
as well as unified status and error values.
\Copyright
Copyright (c) Electronic Arts 2002
\Version 0.5 02/23/1999 (gschaefer) First Version
\Version 1.0 02/25/1999 (gschaefer) Alpha release
\Version 1.1 11/20/2002 (jbrookes) Added Send() flags parameter, protocol definitions.
*/
/*************************************************************************************H*/
#ifndef _commall_h
#define _commall_h
/*!
\Moduledef CommAll CommAll
\Modulemember Comm
*/
//@{
/*** Include files *********************************************************************/
#include "DirtySDK/platform.h"
/*** Defines ***************************************************************************/
#define COMM_OFFLINE 1 //!< status - offline
#define COMM_CONNECTING 2 //!< status - connecting
#define COMM_ONLINE 3 //!< status - online
#define COMM_FAILURE 4 //!< status - failure
#define COMM_PENDING 1 //!< pending
#define COMM_NOERROR 0 //!< no error
#define COMM_BADPARM -1 //!< invalid parameter
#define COMM_BADSTATE -2 //!< invalid state
#define COMM_BADADDRESS -3 //!< invalid address
#define COMM_NORESOURCE -4 //!< no resources available
#define COMM_UNEXPECTED -5 //!< unexpected
#define COMM_MINBUFFER -6 //!< minbuffer
#define COMM_NODATA -7 //!< no data available
#define COMM_INPROGRESS -8 //!< operation in progress
#define COMM_PORTBOUND -9 //!< requested local port is already bound
// start of protocol numbering
#define COMM_PROTO_TCP (1) //!< TCP protocol
#define COMM_PROTO_UDP (2) //!< UDP protocol
#define COMM_PROTO_SRP (3) //!< SRP protocol
#define COMM_FLAGS_RELIABLE 0 //!< CommRef->Send() flag - use reliable transmission
#define COMM_FLAGS_UNRELIABLE 1 //!< CommRef->Send() flag - use unreliable transmission
#define COMM_FLAGS_BROADCAST 2 //!< CommRef->Send() flag - use unreliable broadcast transmission
/*** Macros ****************************************************************************/
/*** Type Definitions ******************************************************************/
typedef struct CommRef CommRef;
//! common reference type
struct CommRef
{
//! construct the class
/*!
* note: initialized winsock for first class. also creates linked
* list of all current instances of the class and worker thread
* to do most udp stuff.
*
* entry: maxwid=max record width, maxinp/maxout=input/output packet buffer size
* exit: none
*/
CommRef* (*Construct)(int32_t maxwid, int32_t maxinp, int32_t maxout);
//! destruct the class
/*!
* entry: none
* exit: none
*/
void (*Destroy)(CommRef *what);
//! resolve an address
/*!
* entry: what=endpoint ref, addr=address, buffer=target buffer, buflen=length
* exit: <0=error, 0=in progress, >0=complete
*/
int32_t (*Resolve)(struct CommRef *what, const char *addr, char *buf, int32_t len, char iDiv);
//! stop the resolver
/*!
* entry: what=endpoint ref
* exit: none
*/
void (*Unresolve)(CommRef *what);
//! listen for a connection
/*!
* entry: addr=port to listen on (only :port portion used)
* exit: negative=error, zero=ok
*/
int32_t (*Listen)(CommRef *what, const char *addr);
//! stop listening
/*!
* entry: none
* exit: negative=error, zero=ok
*/
int32_t (*Unlisten)(CommRef *what);
//! initiate a connection to a peer
/*!
* note: does not currently perform dns translation
*
* entry: addr=address in ip-address:port form
* exit: negative=error, zero=ok
*/
int32_t (*Connect)(CommRef *what, const char *addr);
//! terminate a connection
/*!
* entry: none
* exit: negative=error, zero=ok
*/
int32_t (*Unconnect)(CommRef *what);
//! set event callback hook
/*!
* Note1: this is an optional callback which is called after new data has been
* received and buffered or at other times where the protocol state has
* significantly changed. It is called by a private thread so the routines it
* uses must be thread safe. It can be used to provide "life" to servers or
* other modules which use comm services. The code must not take too long to
* execute since it will impact comm performance if it does.
*
* Note2: By disabling and enabling this callback at specific times, it is
* possible to avoid threading concerns in the upper layer (i.e., if you
* disable the callback while the callback is executing, this call will block
* until the callback completes).
*
* entry: comm reference
* exit: none
*/
void (*Callback)(CommRef *what, void (*callback)(CommRef *ref, int32_t event));
//! return current stream status
/*!
* entry: none
* exit: CONNECTING, OFFLINE, ONLINE or FAILURE
*/
int32_t (*Status)(CommRef *what);
//! control connection behavior (optional)
/*!
* see specific implementation for entry and exit parameter descriptions
*/
int32_t (*Control)(CommRef *what, int32_t iControl, int32_t iValue, void *pValue);
//! return current clock tick
/*!
* entry: none
* exit: elapsed millisecs from some epoch
*/
uint32_t (*Tick)(CommRef *what);
//! send a packet
/*!
* note: zero length packets may not be sent (they are ignored)
*
* entry: buffer=pointer to data, length=length of data, flags=COMM_FLAGS_* (see defines above)
* exit: negative=error, zero=ok
*/
int32_t (*Send)(CommRef *what, const void *buffer, int32_t length, uint32_t flags);
//! peek at waiting packet
/*!
* entry: target=target buffer, length=buffer length, when=tick received at
* exit: negative=nothing pending, else packet length
*/
int32_t (*Peek)(CommRef *what, void *target, int32_t length, uint32_t *when);
//! receive a packet from the buffer
/*!
* entry: target=target buffer, length=buffer length, what=tick received at
* exit: negative=error, else packet length
*/
int32_t (*Recv)(CommRef *what, void *target, int32_t length, uint32_t *when);
//! send data callback hook
/*!
* Note: this is an optional callback which is called immediately before
* a packet is transmitted. Due to error handling, it may get called more
* than once for the same packet if the packet is sent more than once.
*
* entry: same as Send
* exit: none
*/
void (*SendCallback)(CommRef *what, void *buffer, int32_t length, uint32_t when);
//! receive data callback hook
/*!
* Note: this is an optional callback which is called immediately after
* a packet is received. By the time this function is called, the packet
* is available for input via the Recv function.
*
* entry: same as Recv
* exit: none
*/
void (*RecvCallback)(CommRef *what, void *target, int32_t length, uint32_t when);
//! module memory group
int32_t memgroup;
void *memgrpusrdata;
//! user definable storage
int32_t refnum;
//! user definable reference
void *refptr;
//! socket ref
SocketT *sockptr;
//! maximum packet width (read only)
uint16_t maxwid;
//! maximum number of input packets buffered
uint8_t maxinp;
//! maximum number of output packets buffered
uint8_t maxout;
//! data transfer statistics (read only)
int32_t datasent;
//! data transfer statistics (read only)
int32_t datarcvd;
//! data transfer statistics (read only)
int32_t packsent;
//! data transfer statistics (read only)
int32_t packrcvd;
//! data transfer statistics (read only)
int32_t packlost;
//! data tranfer statictics (read only)
uint32_t packsaved; // tracks the number of packers recovered by commudp redundancy mechanism
//! data transfer statistics (read only)
int32_t naksent;
//! data transfer statistics (read only)
int32_t overhead; // tracks the sent overhead including IP4 and UDP header
//! data transfer statistics (read only)
int32_t rcvoverhead; // tracks the receive overhead including IP4 and UDP header
//!< host ip address (read only)
uint32_t hostip;
//!< peer ip address (read only)
uint32_t peerip;
//!< host port (read only)
uint16_t hostport;
//!< peer port (read only)
uint16_t peerport;
//!< if packet was received (read only)
uint8_t bpackrcvd;
uint8_t _pad[3];
};
// typedef versions for discrete declarations
typedef CommRef *(CommAllConstructT)(int32_t maxwid, int32_t maxinp, int32_t maxout);
typedef void (CommAllDestroyT)(CommRef *what);
typedef int32_t (CommAllResolveT)(struct CommRef *what, const char *addr, char *buf, int32_t len, char iDiv);
typedef void (CommAllUnresolveT)(CommRef *what);
typedef int32_t (CommAllListenT)(CommRef *what, const char *addr);
typedef int32_t (CommAllUnlistenT)(CommRef *what);
typedef int32_t (CommAllConnectT)(CommRef *what, const char *addr);
typedef int32_t (CommAllUnconnectT)(CommRef *what);
typedef void (CommAllCallbackT)(CommRef *what, void (*callback)(CommRef *ref, int32_t event));
typedef int32_t (CommAllStatusT)(CommRef *what);
typedef int32_t (CommAllControlT)(CommRef *what, int32_t iControl, int32_t iValue, void *pValue);
typedef uint32_t (CommAllTickT)(CommRef *what);
typedef int32_t (CommAllSendT)(CommRef *what, const void *buffer, int32_t length, uint32_t flags);
typedef int32_t (CommAllPeekT)(CommRef *what, void *target, int32_t length, uint32_t *when);
typedef int32_t (CommAllRecvT)(CommRef *what, void *target, int32_t length, uint32_t *when);
typedef void (CommAllSendCallbackT)(CommRef *what, const void *, int32_t length, uint32_t when);
typedef void (CommAllRecvCallbackT)(CommRef *what, void *target, int32_t length, uint32_t when);
typedef void (CommAllEventCallbackT)(CommRef *what, int32_t event);
/*** Variables *************************************************************************/
/*** Functions *************************************************************************/
// known protocol constructors (these also appear in the .h file for the
// protocol in question, but are included here for convenience) -- see
// protocol .h file for more details
/*
* Construct the class
*
* entry: maxwid=max record width, maxinp/maxout=input/output packet buffer size
* exit: none
*/
#if 0
//typedef struct CommUDPRef CommUDPRef;
CommRef *CommUDPConstruct(int32_t maxwid, int32_t maxinp, int32_t maxout);
//typedef struct CommSRPRef CommSRPRef;
CommRef *CommSRPConstruct(int32_t maxwid, int32_t maxinp, int32_t maxout);
#endif
//@}
#endif // _commall_h

View File

@ -0,0 +1,103 @@
/*H*************************************************************************************/
/*!
\File commsrp.h
\Description
This is CommSRP (Selectively Reliable Protocol), a datagram packet-based
transport class.
\Copyright
Copyright Electronic Arts 1999-2003
\Version 0.5 01/03/03 (jbrookes) Initial Version, based on CommTCP
\Version 0.7 01/07/03 (jbrookes) Working unreliable transport, based on CommUDP
\Version 0.8 01/08/03 (jbrookes) Working reliable transport.
\Version 0.9 02/09/03 (jbrookes) Added support for sending zero-byte packets, and fixed PS2 alignment issue.
*/
/*************************************************************************************H*/
#ifndef _commsrp_h
#define _commsrp_h
/*!
\Moduledef CommSRP CommSRP
\Modulemember Comm
*/
//@{
/*** Include files *********************************************************************/
#include "DirtySDK/platform.h"
/*** Defines ***************************************************************************/
/*** Macros ****************************************************************************/
/*** Type Definitions ******************************************************************/
// basic reference returned/used by all routines
typedef struct CommSRPRef CommSRPRef;
/*** Variables *************************************************************************/
/*** Functions *************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
// construct the class
DIRTYCODE_API CommSRPRef *CommSRPConstruct(int32_t maxwid, int32_t maxinp, int32_t maxout);
// destruct the class
DIRTYCODE_API void CommSRPDestroy(CommSRPRef *what);
// resolve an address
DIRTYCODE_API int32_t CommSRPResolve(CommSRPRef *what, const char *addr, char *buf, int32_t len, char div);
// stop the resolver
DIRTYCODE_API void CommSRPUnresolve(CommSRPRef *what);
// listen for a connection
DIRTYCODE_API int32_t CommSRPListen(CommSRPRef *what, const char *addr);
// stop listening
DIRTYCODE_API int32_t CommSRPUnlisten(CommSRPRef *what);
// initiate a connection to a peer
DIRTYCODE_API int32_t CommSRPConnect(CommSRPRef *what, const char *addr);
// terminate a connection
DIRTYCODE_API int32_t CommSRPUnconnect(CommSRPRef *what);
// set event callback hook
DIRTYCODE_API void CommSRPCallback(CommSRPRef *what, void (*callback)(CommRef *ref, int32_t event));
// return current stream status
DIRTYCODE_API int32_t CommSRPStatus(CommSRPRef *what);
// return current clock tick
DIRTYCODE_API uint32_t CommSRPTick(CommSRPRef *what);
// send a packet
DIRTYCODE_API int32_t CommSRPSend(CommSRPRef *what, const void *buffer, int32_t length, uint32_t flags);
// peek at waiting packet
DIRTYCODE_API int32_t CommSRPPeek(CommSRPRef *what, void *target, int32_t length, uint32_t *when);
// receive a packet from the buffer
DIRTYCODE_API int32_t CommSRPRecv(CommSRPRef *what, void *target, int32_t length, uint32_t *when);
#ifdef __cplusplus
}
#endif
//@}
#endif // _commsrp_h

View File

@ -0,0 +1,120 @@
/*H*************************************************************************************************/
/*!
\File commudp.h
\Description
This is a simple UDP transport class which incorporations the notions of virtual
connections and error free transfer. The protocol is optimized for use in a real-time
environment where latency is more important than bandwidth. Overhead is low with
the protocol adding only 8 bytes per packet on top of that required by UDP itself.
\Notes
None.
\Copyright
Copyright (c) Tiburon Entertainment / Electronic Arts 1999-2003. ALL RIGHTS RESERVED.
\Version 0.1 02/09/99 (GWS) First Version
\Version 0.2 02/14/99 (GWS) Revised and enhanced
\Version 0.5 02/14/99 (GWS) Alpha release
\Version 1.0 07/30/99 (GWS) Final release
\Version 2.0 10/27/99 (GWS) Revised to use winsock 1.1/2.0
\Version 2.1 12/04/99 (GWS) Removed winsock 1.1 support
\Version 2.2 01/12/00 (GWS) Fixed receive tick bug
\Version 2.3 06/12/00 (GWS) Added fastack for low-latency nets
\Version 2.4 07/07/00 (GWS) Added firewall penetrator
\Version 3.0 12/04/00 (GWS) Reported to dirtysock
\Version 3.1 11/20/02 (JLB) Added Send() flags parameter
\Version 3.2 02/18/03 (JLB) Fixes for multiple connection support
\Version 3.3 05/06/03 (GWS) Allowed poke to come from any IP
\Version 3.4 09/02/03 (JLB) Added unreliable packet type
\Version 4.0 09/12/03 (JLB) Per-send optional unreliable transport
*/
/*************************************************************************************************H*/
#ifndef _commudp_h
#define _commudp_h
/*!
\Moduledef CommUDP CommUDP
\Modulemember Comm
*/
//@{
/*** Include files *********************************************************************/
#include "DirtySDK/platform.h"
/*** Defines ***************************************************************************/
/*** Macros ****************************************************************************/
/*** Type Definitions ******************************************************************/
// basic reference returned/used by all routines
typedef struct CommUDPRef CommUDPRef;
/*** Variables *************************************************************************/
/*** Functions *************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
// construct the class
DIRTYCODE_API CommUDPRef *CommUDPConstruct(int32_t iMaxWid, int32_t iMaxInp, int32_t iMaxOut);
// destruct the class
DIRTYCODE_API void CommUDPDestroy(CommUDPRef *pRef);
// resolve an address
DIRTYCODE_API int32_t CommUDPResolve(CommUDPRef *pRef, const char *pAddr, char *pBuf, int32_t iLen, char cDiv);
// resolve an address
DIRTYCODE_API void CommUDPUnresolve(CommUDPRef *pRef);
// listen for a connection
DIRTYCODE_API int32_t CommUDPListen(CommUDPRef *pRef, const char *pAddr);
// stop listening
DIRTYCODE_API int32_t CommUDPUnlisten(CommUDPRef *pRef);
// initiate a connection to a peer
DIRTYCODE_API int32_t CommUDPConnect(CommUDPRef *pRef, const char *pAddr);
// terminate a connection
DIRTYCODE_API int32_t CommUDPUnconnect(CommUDPRef *pRef);
// set event callback hook
DIRTYCODE_API void CommUDPCallback(CommUDPRef *pRef, void (*pCallback)(void *pRef, int32_t iEvent));
// return current stream status
DIRTYCODE_API int32_t CommUDPStatus(CommUDPRef *pRef);
// control connection behavior
DIRTYCODE_API int32_t CommUDPControl(CommUDPRef *pRef, int32_t iControl, int32_t iValue, void *pValue);
// return current clock tick
DIRTYCODE_API uint32_t CommUDPTick(CommUDPRef *pRef);
// send a packet
DIRTYCODE_API int32_t CommUDPSend(CommUDPRef *pRef, const void *pBuffer, int32_t iLength, uint32_t uFlags);
// peek at waiting packet
DIRTYCODE_API int32_t CommUDPPeek(CommUDPRef *pRef, void *pTarget, int32_t iLength, uint32_t *pWhen);
// receive a packet from the buffer
DIRTYCODE_API int32_t CommUDPRecv(CommUDPRef *pRef, void *pTarget, int32_t iLength, uint32_t *pWhen);
#ifdef __cplusplus
}
#endif
//@}
#endif // _commudp_h

View File

@ -0,0 +1,92 @@
/*H*************************************************************************************************/
/*!
\File commudputil.h
\Description
CommUdp knowledge to be shared with gameserver implementation.
\Copyright
Copyright (c) 2006-2017 Electronic Arts Inc.
\Version 1.0 09/01/2017 (mclouatre) First Version
*/
/*************************************************************************************************H*/
#ifndef _commudputil_h
#define _commudputil_h
/*!
\Moduledef CommUDP CommUDP
\Modulemember Comm
*/
//@{
/*** Include files *********************************************************************/
#include "DirtySDK/platform.h"
/*** Defines ***************************************************************************/
//! define protocol packet types
enum {
COMMUDP_RAW_PACKET_INIT = 1, // initiate a connection
COMMUDP_RAW_PACKET_CONN, // confirm a connection
COMMUDP_RAW_PACKET_DISC, // terminate a connection
COMMUDP_RAW_PACKET_NAK, // force resend of lost data
COMMUDP_RAW_PACKET_POKE, // try and poke through firewall
COMMUDP_RAW_PACKET_UNREL = 128, // unreliable packet send (must be power of two)
// 128-255 reserved for unreliable packet sequence
COMMUDP_RAW_PACKET_DATA = 256, // initial data packet sequence number (must be power of two)
/* Width of the sequence window, can be anything provided
RAW_PACKET_DATA + RAW_PACKET_DATA_WINDOW
doesn't overlap the meta-data bits. */
COMMUDP_RAW_PACKET_DATA_WINDOW = (1 << 24) - 256
};
#define COMMUDP_RAW_METATYPE1_SIZE (8)
#define COMMUDP_SEQ_META_SHIFT (28 - 4)
#define COMMUDP_SEQ_MULTI_SHIFT (28)
#define COMMUDP_SEQ_MULTI_INC (1 << COMMUDP_SEQ_MULTI_SHIFT)
#define COMMUDP_SEQ_MASK (0x00ffffff)
/*** Macros ****************************************************************************/
/*** Type Definitions ******************************************************************/
/*** Variables *************************************************************************/
/*** Functions *************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
// Encodes a subpacket size field.
DIRTYCODE_API uint32_t CommUDPUtilEncodeSubpacketSize(uint8_t *pBuf, uint32_t uVal);
// Decodes a subpacket size field (see _CommUDPEncodeSubpacketSize for notes)
DIRTYCODE_API uint32_t CommUDPUtilDecodeSubpacketSize(const uint8_t *pBuf, int32_t *pVal);
// Extracts metatype from host-ordered commupd header seq field (RawUDPPacketT.body.uSeq)
DIRTYCODE_API uint32_t CommUDPUtilGetMetaTypeFromSeq(uint32_t uSeq);
// Returns the metadata size for a given metadata type.
DIRTYCODE_API uint32_t CommUDPUtilGetMetaSize(uint32_t uMetaType);
// Extracts the number of extra subpackets (excluding the main subpacket) from host - ordered commupd header seq field(RawUDPPacketT.body.uSeq)
DIRTYCODE_API uint32_t CommUDPUtilGetExtraSubPktCountFromSeq(uint32_t uSeq);
#ifdef __cplusplus
}
#endif
//@}
#endif // _commudputil_h

View File

@ -0,0 +1,97 @@
/*H********************************************************************************/
/*!
\File cryptaes.h
\Description
An implementation of the AES-128 and AES-256 cipher, based on the FIPS
standard, intended for use with the TLS AES cipher suites.
This implementation deliberately uses the naming conventions from the
standard where possible in order to aid comprehension.
\Notes
References:
FIPS197 standard: http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
\Copyright
Copyright (c) 2011 Electronic Arts
\Version 01/20/2011 (jbrookes) First Version
*/
/********************************************************************************H*/
#ifndef _cryptaes_h
#define _cryptaes_h
/*!
\Moduledef CryptAes CryptAes
\Modulemember Crypt
*/
//@{
/*** Include files ****************************************************************/
#include "DirtySDK/platform.h"
/*** Defines **********************************************************************/
#define CRYPTAES_MAXROUNDS (14)
#define CRYPTAES_KEYTYPE_ENCRYPT (0)
#define CRYPTAES_KEYTYPE_DECRYPT (1)
/*** Macros ***********************************************************************/
/*** Type Definitions *************************************************************/
typedef struct CryptAesKeyScheduleT
{
uint16_t uNumRounds;
uint16_t uKeyWords;
uint32_t aKeySchedule[(CRYPTAES_MAXROUNDS+1)*8];
} CryptAesKeyScheduleT;
// opaque module state
typedef struct CryptAesT CryptAesT;
//! all fields are PRIVATE
struct CryptAesT
{
CryptAesKeyScheduleT KeySchedule;
uint8_t aInitVec[16]; //!< initialization vector/CBC state
};
/*** Variables ********************************************************************/
/*** Functions ********************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
// initialize state for AES encryption/decryption module
DIRTYCODE_API void CryptAesInit(CryptAesT *pAes, const uint8_t *pKeyBuf, int32_t iKeyLen, uint32_t uKeyType, const uint8_t *pInitVec);
// encrypt data with the AES cipher in CBC mode
DIRTYCODE_API void CryptAesEncrypt(CryptAesT *pAes, uint8_t *pBuffer, int32_t iLength);
// decrypt data with the AES cipher in CBC mode
DIRTYCODE_API void CryptAesDecrypt(CryptAesT *pAes, uint8_t *pBuffer, int32_t iLength);
// encrypt a 16 byte data block with AES cipher
DIRTYCODE_API void CryptAesEncryptBlock(CryptAesKeyScheduleT *pKeySchedule, const uint8_t *pInput, uint8_t *pOutput);
// decrypt a 16 byte data block with AES cipher
DIRTYCODE_API void CryptAesDecryptBlock(CryptAesKeyScheduleT *pKeySchedule, const uint8_t *pInput, uint8_t *pOutput);
// initialize AES key schedule
DIRTYCODE_API void CryptAesInitKeySchedule(CryptAesKeyScheduleT *pKeySchedule, const uint8_t *pKeyBuf, int32_t iKeyLen, uint32_t uKeyType);
#ifdef __cplusplus
}
#endif
//@}
#endif // _cryptaes_h

View File

@ -0,0 +1,102 @@
/*H*************************************************************************************/
/*!
\File cryptarc4.h
\Description
This module is a from-scratch ARC4 implementation designed to avoid
any intellectual property complications. The ARC4 stream cipher is
known to produce output that is compatible with the RC4 stream cipher.
\Notes
This algorithm from this cypher was taken from the web site: ciphersaber.gurus.com
It is based on the RC4 compatible algorithm that was published in the 2nd ed of
the book Applied Cryptography by Bruce Schneier. This is a private-key stream
cipher which means that some other secure way of exchanging cipher keys prior
to algorithm use is required. Its strength is directly related to the key exchange
algorithm strengh. In operation, each individual stream message must use a unique
key. This is handled by appending on 10 byte random value onto the private key.
This 10-byte data can be sent by public means to the receptor (or included at the
start of a file or whatever). When the private key is combined with this public
key, it essentially puts the cypher into a random starting state (it is like
using a message digest routine to generate a random hash for password comparison).
The code below was written from scratch using only a textual algorithm description.
\Copyright
Copyright (c) Electronic Arts 2000-2002
\Version 1.0 02/25/2000 (gschaefer) First Version
\Version 1.1 11/06/2002 (jbrookes) Removed Create()/Destroy() to eliminate mem alloc dependencies.
*/
/*************************************************************************************H*/
#ifndef _cryptarc4_h
#define _cryptarc4_h
/*!
\Moduledef CryptArc4 CryptArc4
\Modulemember Crypt
*/
//@{
/*** Include files *********************************************************************/
#include "DirtySDK/platform.h"
/*** Defines ***************************************************************************/
/*** Macros ****************************************************************************/
/*** Type Definitions ******************************************************************/
typedef struct CryptArc4T CryptArc4T;
//! all fields are PRIVATE
struct CryptArc4T
{
uint8_t state[256];
uint8_t walk;
uint8_t swap;
};
/*** Variables *************************************************************************/
/*** Functions *************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
// create state for ARC4 encryption/decryption module.
DIRTYCODE_API void CryptArc4Init(CryptArc4T *pState, const unsigned char *pKeyBuf, int32_t iKeyLen, int32_t iIter);
// apply the cipher to the data. calling twice undoes the uncryption
DIRTYCODE_API void CryptArc4Apply(CryptArc4T *pState, unsigned char *pBuffer, int32_t iLength);
// advance the cipher state by iLength bytes
DIRTYCODE_API void CryptArc4Advance(CryptArc4T *pState, int32_t iLength);
// encrypt an asciiz string, with a 7-bit asciiz string result
DIRTYCODE_API void CryptArc4StringEncrypt(char *pDst, int32_t iLen, const char *pSrc, const uint8_t *pKey, int32_t iKey, int32_t iIter);
// decrypt an asciiz string, from a 7-bit asciiz encrypted string
DIRTYCODE_API void CryptArc4StringDecrypt(char *pDst, int32_t iLen, const char *pSrc, const uint8_t *pKey, int32_t iKey, int32_t iIter);
#if DIRTYCODE_DEBUG
// encryption/decryption helper intended for use with static strings that need to be encrypted in the binary
#define CryptArc4StringEncryptStatic(_pStr, _iStrSize, _pKey, _iKeySize, _pStrSrc) CryptArc4StringEncryptStaticCode(_pStr, _iStrSize, _pKey, _iKeySize, _pStrSrc)
#else
// release version of string encrypt; does not pass source (plaintext) string
#define CryptArc4StringEncryptStatic(_pStr, _iStrSize, _pKey, _iKeySize, _pStrSrc) CryptArc4StringEncryptStaticCode(_pStr, _iStrSize, _pKey, _iKeySize, NULL)
#endif
// encryption/decryption helper intended for use with static strings that need to be encrypted in the binary (do not call directly; use CryptArc4StringEncryptStatic() wrapper)
DIRTYCODE_API int32_t CryptArc4StringEncryptStaticCode(char *pStr, int32_t iStrSize, const uint8_t *pKey, int32_t iKeySize, const char *pStrSrc);
#ifdef __cplusplus
}
#endif
//@}
#endif // _cryptarc4_h

View File

@ -0,0 +1,156 @@
/*H*************************************************************************************/
/*!
\File cryptbn.h
\Description
This module is implements big integer math needed for our cryptography
\Copyright
Copyright (c) Electronic Arts 2017. ALL RIGHTS RESERVED.
\Version 01/18/2017 (eesponda) First version split from CryptRSA
*/
/*************************************************************************************H*/
#ifndef _cryptbn_h
#define _cryptbn_h
/*!
\Moduledef CryptBn CryptBn
\Modulemember Crypt
*/
//@{
/*** Include files ********************************************************************/
#include "DirtySDK/platform.h"
/*** Defines **************************************************************************/
// size of a each unit in the large number
#if defined(DIRTYCODE_PC) && DIRTYCODE_64BITPTR == 0
#define UCRYPT_SIZE (4)
#else
#define UCRYPT_SIZE (8)
#endif
// bits per word
#define UCRYPT_BITSIZE (UCRYPT_SIZE*8)
// maximum bits of number (add one unit of wiggle room)
#define CRYPTBN_MAX_BITS (4096+UCRYPT_BITSIZE)
// maximum width of number
#define CRYPTBN_MAX_WIDTH (CRYPTBN_MAX_BITS/UCRYPT_BITSIZE)
/*** Type Definitions *****************************************************************/
// define crypt types based on UCRYPT_SIZE
#if (UCRYPT_SIZE == 4)
typedef uint32_t ucrypt_t;
#else
typedef uint64_t ucrypt_t;
#endif
//! big number state
typedef struct CryptBnT
{
ucrypt_t aData[CRYPTBN_MAX_WIDTH];
int32_t iWidth;
uint32_t uSign;
} CryptBnT;
/*** Functions *************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
// init big number state at specific width
DIRTYCODE_API void CryptBnInit(CryptBnT *pState, int32_t iWidth);
// init big number state with an unsigned number
DIRTYCODE_API void CryptBnInitSet(CryptBnT *pState, uint32_t uValue);
// init big number state from a buffer
DIRTYCODE_API int32_t CryptBnInitFrom(CryptBnT *pState, int32_t iWidth, const uint8_t *pSource, int32_t iLength);
// init big number state from a buffer as little-endian
DIRTYCODE_API int32_t CryptBnInitLeFrom(CryptBnT *pState, const uint8_t *pSource, int32_t iLength);
// left shift the big number by a bit
DIRTYCODE_API void CryptBnLeftShift(CryptBnT *pState);
// left shift the big number by multiple bits
DIRTYCODE_API void CryptBnLeftShift2(CryptBnT *pState, int32_t iBits);
// right shift the big number by a bit
#define CryptBnRightShift(pState) CryptBnRightShift2(pState, 1)
// right shift the big number by multiple bits
DIRTYCODE_API void CryptBnRightShift2(CryptBnT *pState, int32_t iBits);
// tests a bit in the big number and returns if it is set
DIRTYCODE_API uint8_t CryptBnBitTest(const CryptBnT *pState, int32_t iBit);
// set a bit in the big number
DIRTYCODE_API void CryptBnBitSet(CryptBnT *pState, int32_t iBit);
// bitwise and two big numbers
DIRTYCODE_API void CryptBnBitAnd(CryptBnT *pState, const CryptBnT *pLhs, const CryptBnT *pRhs);
// bitwise xor two big numbers
DIRTYCODE_API void CryptBnBitXor(CryptBnT *pState, const CryptBnT *pLhs, const CryptBnT *pRhs);
// returns bit length
DIRTYCODE_API int32_t CryptBnBitLen(const CryptBnT *pState);
// returns byte length
DIRTYCODE_API int32_t CryptBnByteLen(const CryptBnT *pState);
// add two big numbers over modulus
DIRTYCODE_API void CryptBnModAdd(CryptBnT *pState, const CryptBnT *pAdd1, const CryptBnT *pAdd2, const CryptBnT *pMod);
// accumulate one big number into another
DIRTYCODE_API void CryptBnAccumulate(CryptBnT *pState, const CryptBnT *pAdd);
// increment the number by 1
DIRTYCODE_API void CryptBnIncrement(CryptBnT *pState);
// subtract two big numbers
DIRTYCODE_API void CryptBnSubtract(CryptBnT *pState, const CryptBnT *pSub1, const CryptBnT *pSub2);
// subtract the number by 1
DIRTYCODE_API void CryptBnDecrement(CryptBnT *pState);
// perform modular multiply operation
DIRTYCODE_API void CryptBnModMultiply(CryptBnT *pState, const CryptBnT *pMul1, const CryptBnT *pMul2, const CryptBnT *pMod);
// multiplication using classical algorithm
DIRTYCODE_API void CryptBnMultiply(CryptBnT *pState, const CryptBnT *pMul1, const CryptBnT *pMul2);
// does a modulus/divide operation using the classical method
DIRTYCODE_API void CryptBnMod(const CryptBnT *pDividend, const CryptBnT *pDivisor, CryptBnT *pRemainder, CryptBnT *pQuotient);
// perform inverse modulo operation
DIRTYCODE_API void CryptBnInverseMod(CryptBnT *pState, const CryptBnT *pMod);
// copy the big number data into output buffer
DIRTYCODE_API void CryptBnFinal(const CryptBnT *pState, uint8_t *pResult, int32_t iLength);
// copy the bit number data into output buffer as little endian
DIRTYCODE_API void CryptBnFinalLe(const CryptBnT *pState, uint8_t *pResult, int32_t iLength);
// copy a big number
DIRTYCODE_API void CryptBnClone(CryptBnT *pDst, const CryptBnT *pSrc);
// print the big number to the log
DIRTYCODE_API void CryptBnPrint(const CryptBnT *pState, const char *pTitle);
// compare two big numbers
DIRTYCODE_API int32_t CryptBnCompare(const CryptBnT *pLhs, const CryptBnT *pRhs);
#ifdef __cplusplus
}
#endif
//@}
#endif // _cryptbn_h

View File

@ -0,0 +1,65 @@
/*H********************************************************************************/
/*!
\File cryptchacha.h
\Description
\Copyright
Copyright (c) 2018 Electronic Arts
\Version 02/12/2018 (jbrookes) First Version
*/
/********************************************************************************H*/
#ifndef _cryptchacha_h
#define _cryptchacha_h
/*!
\Moduledef CryptChaCha CryptChaCha
\Modulemember Crypt
*/
//@{
/*** Include files ****************************************************************/
#include "DirtySDK/platform.h"
/*** Defines **********************************************************************/
/*** Macros ***********************************************************************/
/*** Type Definitions *************************************************************/
// opaque module state
typedef struct CryptChaChaT CryptChaChaT;
//! all fields are PRIVATE
struct CryptChaChaT
{
uint32_t aInput[16];
};
/*** Variables ********************************************************************/
/*** Functions ********************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
// initialize state for ChaCha encryption/decryption module
DIRTYCODE_API void CryptChaChaInit(CryptChaChaT *pChaCha, const uint8_t *pKeyBuf, int32_t iKeyLen);
// encrypt data with the ChaCha cipher
DIRTYCODE_API int32_t CryptChaChaEncrypt(CryptChaChaT *pChaCha, uint8_t *pBuffer, int32_t iLength, const uint8_t *pInitVec, int32_t iIvLen, const uint8_t *pAddData, int32_t iAddLen, uint8_t *pTag, int32_t iTagLen);
// decrypt data with the ChaCha cipher
DIRTYCODE_API int32_t CryptChaChaDecrypt(CryptChaChaT *pChaCha, uint8_t *pBuffer, int32_t iLength, const uint8_t *pInitVec, int32_t iIvLen, const uint8_t *pAddData, int32_t iAddLen, const uint8_t *pTag, int32_t iTagLen);
#ifdef __cplusplus
}
#endif
//@}
#endif // _cryptgcm_h

View File

@ -0,0 +1,98 @@
/*H********************************************************************************/
/*!
\File cryptcurve.h
\Description
This module implements an interface over our different curve crypto APIs
\Copyright
Copyright (c) Electronic Arts 2018. ALL RIGHTS RESERVED.
*/
/********************************************************************************H*/
#ifndef _cryptcurve_h
#define _cryptcurve_h
/*!
\Moduledef CryptCurve CryptCurve
\Modulemember Crypt
*/
//@{
/*** Include files ****************************************************************/
#include "DirtySDK/platform.h"
#include "DirtySDK/crypt/cryptbn.h"
#include "DirtySDK/crypt/cryptdef.h"
#include "DirtySDK/crypt/cryptnist.h"
/*** Defines **********************************************************************/
//! maximum state storage we need for diffie hellman
#define CRYPTCURVE_DH_MAXSTATE (sizeof(CryptNistDhT))
//! maximum state storage we need for digital signature algorithm
#define CRYPTCURVE_DSA_MAXSTATE (sizeof(CryptNistDsaT))
/*** Type Definitions *************************************************************/
//! curve init function
typedef int32_t (CryptCurveInitT)(void *pState, int32_t iCurveType);
//! curve generate public function
typedef int32_t (CryptCurvePublicT)(void *pState, CryptEccPointT *pResult, uint32_t *pCryptUsecs);
//! curve generate secret function
typedef int32_t (CryptCurveSecretT)(void *pState, CryptEccPointT *pPublicKey, CryptEccPointT *pResult, uint32_t *pCryptUsecs);
//! curve init point
typedef int32_t (CryptCurvePointInitT)(CryptEccPointT *pPoint, const uint8_t *pBuffer, int32_t iBufLen);
//! curve output point to buffer (for dh cases)
typedef int32_t (CryptCurvePointFinalT)(void *pState, const CryptEccPointT *pPoint, uint8_t bSecret, uint8_t *pBuffer, int32_t iBufLen);
//! curve generate dsa signature
typedef int32_t (CryptCurveSignT)(void *pState, const CryptBnT *pPrivateKey, const uint8_t *pHash, int32_t iHashSize, CryptEccPointT *pSignature, uint32_t *pCryptUsecs);
//! curve verify dsa signature
typedef int32_t (CryptCurveVerifyT)(void *pState, CryptEccPointT *pPublicKey, const uint8_t *pHash, int32_t iHashSize, CryptEccPointT *pSignature, uint32_t *pCryptUsecs);
//! interface for dh functionality
typedef struct CryptCurveDhT
{
CryptCurveInitT *Init;
CryptCurvePublicT *Public;
CryptCurveSecretT *Secret;
CryptCurvePointInitT *PointInit;
CryptCurvePointFinalT *PointFinal;
int32_t iCurveType;
} CryptCurveDhT;
//! interface for dsa functionality
typedef struct CryptCurveDsaT
{
CryptCurveInitT *Init;
CryptCurveSignT *Sign;
CryptCurveVerifyT *Verify;
CryptCurvePointInitT *PointInit;
int32_t iCurveType;
} CryptCurveDsaT;
/*** Functions ********************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
// get dh reference and initializes based on curve type
DIRTYCODE_API const CryptCurveDhT *CryptCurveGetDh(int32_t iCurveType);
// get dsa reference and initializes based on curve type
DIRTYCODE_API const CryptCurveDsaT *CryptCurveGetDsa(int32_t iCurveType);
#ifdef __cplusplus
}
#endif
//@}
#endif // _cryptcurve_h

View File

@ -0,0 +1,89 @@
/*H*******************************************************************/
/*!
\File cryptdef.h
\Description
Common definitions for Crypt modules
\Copyright
Copyright (c) Electronic Arts 2013
\Version 1.0 11/19/2013 (jbrookes) First Version
*/
/*******************************************************************H*/
#ifndef _cryptdef_h
#define _cryptdef_h
/*!
\Moduledef CryptDef CryptDef
\Modulemember Crypt
*/
//@{
/*** Include files ***************************************************/
#include "DirtySDK/platform.h"
#include "DirtySDK/crypt/cryptbn.h"
/*** Defines *********************************************************/
/*** Macros **********************************************************/
/*** Type Definitions ************************************************/
//! a binary large object, such as a modulus or exponent
typedef struct CryptBinaryObjT
{
uint8_t *pObjData;
int32_t iObjSize;
} CryptBinaryObjT;
//! used for the point calculations that are used for elliptic curve crypto
typedef struct CryptEccPointT
{
CryptBnT X;
CryptBnT Y;
} CryptEccPointT;
//! curve supported groups as per: https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
typedef enum CryptCurveE
{
CRYPTCURVE_UNASSIGNED,
CRYPTCURVE_SECT163K1,
CRYPTCURVE_SECT163R1,
CRYPTCURVE_SECT163R2,
CRYPTCURVE_SECT193R1,
CRYPTCURVE_SECT193R2,
CRYPTCURVE_SECT233K1,
CRYPTCURVE_SECT233R1,
CRYPTCURVE_SECT239K1,
CRYPTCURVE_SECT283K1,
CRYPTCURVE_SECT283R1,
CRYPTCURVE_SECT409K1,
CRYPTCURVE_SECT409R1,
CRYPTCURVE_SECT571K1,
CRYPTCURVE_SECT571R1,
CRYPTCURVE_SECP160K1,
CRYPTCURVE_SECP160R1,
CRYPTCURVE_SECP160R2,
CRYPTCURVE_SECP192K1,
CRYPTCURVE_SECP192R1,
CRYPTCURVE_SECP224K1,
CRYPTCURVE_SECP224R1,
CRYPTCURVE_SECP256K1,
CRYPTCURVE_SECP256R1,
CRYPTCURVE_SECP384R1,
CRYPTCURVE_SECP521R1,
CRYPTCURVE_BRAINPOOLP256R1,
CRYPTCURVE_BRAINPOOLP384R1,
CRYPTCURVE_BRAINPOOLP512R1,
CRYPTCURVE_X25519,
CRYPTCURVE_X448,
CRYPTCURVE_MAX = CRYPTCURVE_X448
} CryptCurveE;
//@}
#endif // _cryptdef_h

View File

@ -0,0 +1,81 @@
/*H********************************************************************************/
/*!
\File cryptgcm.h
\Description
An implementation of the GCM-128 and GCM-256 cipher, based on the NIST
standard, intended for use in implementation of TLS1.1 GCM cipher suites.
This implementation uses Shoup's method utilizing 4-bit tables as described
in the GCM specifications. While not particularly fast, table generation
is quick and memory usage required small. This implementation is restricted
to a feature set suitable for implementation of TLS1.1 GCM cipher suites.
\Copyright
Copyright (c) 2014 Electronic Arts
\Version 07/01/2014 (jbrookes) First Version
*/
/********************************************************************************H*/
#ifndef _cryptgcm_h
#define _cryptgcm_h
/*!
\Moduledef CryptGcm CryptGcm
\Modulemember Crypt
*/
//@{
/*** Include files ****************************************************************/
#include "DirtySDK/platform.h"
#include "DirtySDK/crypt/cryptaes.h"
/*** Defines **********************************************************************/
/*** Macros ***********************************************************************/
/*** Type Definitions *************************************************************/
// opaque module state
typedef struct CryptGcmT CryptGcmT;
//! all fields are PRIVATE
struct CryptGcmT
{
uint64_t HL[16]; //!< precalculated htable, low
uint64_t HH[16]; //!< precalculated htable, high
uint64_t uLen; //!< data length
uint64_t uAddLen; //!< additional data length
uint8_t aBaseEctr[16]; //!< first ECTR for tag
uint8_t aY[16]; //!< y scratch buffer
uint8_t aBuf[16]; //!< I/O scratch buffer
uint32_t uMode; //!< CRYPTAES_KETYPE_ENCRYPT or CRYPTAES_KEYTYPE_DECRYPT
CryptAesKeyScheduleT KeySchedule; //!< AES key schedule
};
/*** Variables ********************************************************************/
/*** Functions ********************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
// initialize state for GCM encryption/decryption module
DIRTYCODE_API void CryptGcmInit(CryptGcmT *pGcm, const uint8_t *pKeyBuf, int32_t iKeyLen);
// encrypt data with the GCM cipher
DIRTYCODE_API int32_t CryptGcmEncrypt(CryptGcmT *pGcm, uint8_t *pBuffer, int32_t iLength, const uint8_t *pInitVec, int32_t iIvLen, const uint8_t *pAddData, int32_t iAddLen, uint8_t *pTag, int32_t iTagLen);
// decrypt data with the GCM cipher
DIRTYCODE_API int32_t CryptGcmDecrypt(CryptGcmT *pGcm, uint8_t *pBuffer, int32_t iLength, const uint8_t *pInitVec, int32_t iIvLen, const uint8_t *pAddData, int32_t iAddLen, uint8_t *pTag, int32_t iTagLen);
#ifdef __cplusplus
}
#endif
//@}
#endif // _cryptgcm_h

View File

@ -0,0 +1,98 @@
/*H*******************************************************************/
/*!
\File crypthash.h
\Description
This module implements a generic wrapper for all cryptograph
hash modules.
\Copyright
Copyright (c) Electronic Arts 2013
\Version 1.0 11/05/2013 (jbrookes) First Version
*/
/*******************************************************************H*/
#ifndef _crypthash_h
#define _crypthash_h
/*!
\Moduledef CryptHash CryptHash
\Modulemember Crypt
*/
//@{
/*** Include files ***************************************************/
#include "DirtySDK/platform.h"
#include "DirtySDK/crypt/cryptmd5.h"
#include "DirtySDK/crypt/cryptsha1.h"
#include "DirtySDK/crypt/cryptsha2.h"
#include "DirtySDK/util/murmurhash3.h"
/*** Defines *********************************************************/
typedef enum CryptHashTypeE
{
CRYPTHASH_NULL,
CRYPTHASH_MURMUR3, //!< murmerhash3; NOT cryto grade but VERY fast, use with caution
CRYPTHASH_MD5, //!< MD5; semi-obsolete, use with caution
CRYPTHASH_SHA1, //!< SHA1
CRYPTHASH_SHA224, //!< SHA2-224
CRYPTHASH_SHA256, //!< SHA2-256
CRYPTHASH_SHA384, //!< SHA2-384
CRYPTHASH_SHA512, //!< SHA2-512
CRYPTHASH_NUMHASHES
} CryptHashTypeE;
#define CRYPTHASH_MAXDIGEST (CRYPTSHA2_HASHSIZE_MAX) //!< SHA2 has the largest digest size
#define CRYPTHASH_MAXSTATE (sizeof(CryptSha2T)) //!< SHA2 has the largest state
/*** Macros **********************************************************/
/*** Type Definitions ************************************************/
//! crypthash init func
typedef void (CryptHashInitT)(void *pState, int32_t iHashSize);
//! crypthash update func
typedef void (CryptHashUpdateT)(void *pState, const uint8_t *pInput, uint32_t uInputLength);
//! crypthash final func
typedef void (CryptHashFinalT)(void *pState, void *pBuffer, uint32_t uLength);
//! crypthash function block
typedef struct CryptHashT
{
CryptHashInitT *Init;
CryptHashUpdateT *Update;
CryptHashFinalT *Final;
CryptHashTypeE eHashType;
int32_t iHashSize;
} CryptHashT;
/*** Variables *******************************************************/
/*** Functions *******************************************************/
#ifdef __cplusplus
extern "C" {
#endif
//!< get reference to hash function
DIRTYCODE_API const CryptHashT *CryptHashGet(CryptHashTypeE eHashType);
//!< get hash size of specified hash function
DIRTYCODE_API int32_t CryptHashGetSize(CryptHashTypeE eHashType);
//!< get hash type based on size of hash (excludes murmurhash3)
DIRTYCODE_API CryptHashTypeE CryptHashGetBySize(int32_t iHashSize);
#ifdef __cplusplus
}
#endif
//@}
#endif // _crypthash_h

View File

@ -0,0 +1,62 @@
/*H********************************************************************************/
/*!
\File crypthmac.h
\Description
\Notes
References:
\Copyright
Copyright (c) 2013 Electronic Arts Inc.
\Version 01/14/2013 (jbrookes) First Version
*/
/********************************************************************************H*/
#ifndef _crypthmac_h
#define _crypthmac_h
/*!
\Moduledef CryptHmac CryptHmac
\Modulemember Crypt
*/
//@{
/*** Include files ****************************************************************/
#include "DirtySDK/platform.h"
/*** Defines **********************************************************************/
/*** Macros ***********************************************************************/
/*** Type Definitions *************************************************************/
typedef struct CryptHmacMsgT
{
const uint8_t *pMessage;
int32_t iMessageLen;
} CryptHmacMsgT;
/*** Variables ********************************************************************/
/*** Functions ********************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
// calculate HMAC message digest algorithm
DIRTYCODE_API int32_t CryptHmacCalc(uint8_t *pBuffer, int32_t iBufLen, const uint8_t *pMessage, int32_t iMessageLen, const uint8_t *pKey, int32_t iKeyLen, CryptHashTypeE eHashType);
// calculate HMAC message digest algorithm; this version allows multiple buffers to allow for easy hashing of sparse messages
DIRTYCODE_API int32_t CryptHmacCalcMulti(uint8_t *pBuffer, int32_t iBufLen, const CryptHmacMsgT *pMessageList, int32_t iNumMessages, const uint8_t *pKey, int32_t iKeyLen, CryptHashTypeE eHashType);
#ifdef __cplusplus
}
#endif
//@}
#endif

View File

@ -0,0 +1,137 @@
/*H*************************************************************************************************/
/*!
\File cryptmd5.h
\Description
The MD5 message digest algorithm developed by Ron Rivest and documented
in RFC1321. This implementation is based on the RFC but does not use the
sample code.. It should be free from intellectual property concerns and
a reference is included below which further clarifies this point.
Note that this implementation is limited to hashing no more than 2^32
bytes after which its results would be impatible with a fully compliant
implementation.
\Notes
http://www.ietf.org/ietf/IPR/RSA-MD-all
The following was recevied Fenbruary 23,2000
From: "Linn, John" <jlinn@rsasecurity.com>
February 19, 2000
The purpose of this memo is to clarify the status of intellectual
property rights asserted by RSA Security Inc. ("RSA") in the MD2, MD4 and
MD5 message-digest algorithms, which are documented in RFC-1319, RFC-1320,
and RFC-1321 respectively.
Implementations of these message-digest algorithms, including
implementations derived from the reference C code in RFC-1319, RFC-1320, and
RFC-1321, may be made, used, and sold without license from RSA for any
purpose.
No rights other than the ones explicitly set forth above are
granted. Further, although RSA grants rights to implement certain
algorithms as defined by identified RFCs, including implementations derived
from the reference C code in those RFCs, no right to use, copy, sell, or
distribute any other implementations of the MD2, MD4, or MD5 message-digest
algorithms created, implemented, or distributed by RSA is hereby granted by
implication, estoppel, or otherwise. Parties interested in licensing
security components and toolkits written by RSA should contact the company
to discuss receiving a license. All other questions should be directed to
Margaret K. Seif, General Counsel, RSA Security Inc., 36 Crosby Drive,
Bedford, Massachusetts 01730.
Implementations of the MD2, MD4, or MD5 algorithms may be subject to
United States laws and regulations controlling the export of technical data,
computer software, laboratory prototypes and other commodities (including
the Arms Export Control Act, as amended, and the Export Administration Act
of 1970). The transfer of certain technical data and commodities may
require a license from the cognizant agency of the United States Government.
RSA neither represents that a license shall not be required for a particular
implementation nor that, if required, one shall be issued.
DISCLAIMER: RSA MAKES NO REPRESENTATIONS AND EXTENDS NO WARRANTIES
OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, VALIDITY OF
INTELLECTUAL PROPERTY RIGHTS, ISSUED OR PENDING, OR THE ABSENCE OF LATENT OR
OTHER DEFECTS, WHETHER OR NOT DISCOVERABLE, IN CONNECTION WITH THE MD2, MD4,
OR MD5 ALGORITHMS. NOTHING IN THIS GRANT OF RIGHTS SHALL BE CONSTRUED AS A
REPRESENTATION OR WARRANTY GIVEN BY RSA THAT THE IMPLEMENTATION OF THE
ALGORITHM WILL NOT INFRINGE THE INTELLECTUAL PROPERTY RIGHTS OF ANY THIRD
PARTY. IN NO EVENT SHALL RSA, ITS TRUSTEES, DIRECTORS, OFFICERS, EMPLOYEES,
PARENTS AND AFFILIATES BE LIABLE FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES OF
ANY KIND RESULTING FROM IMPLEMENTATION OF THIS ALGORITHM, INCLUDING ECONOMIC
DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, REGARDLESS OF WHETHER RSA
SHALL BE ADVISED, SHALL HAVE OTHER REASON TO KNOW, OR IN FACT SHALL KNOW OF
\Copyright
Copyright (c) Tiburon Entertainment / Electronic Arts 2002. ALL RIGHTS RESERVED.
\Version 1.0 03/16/2001 (GWS) First Version
*/
/*************************************************************************************************H*/
#ifndef _cryptmd5_h
#define _cryptmd5_h
/*!
\Moduledef CryptMD5 CryptMD5
\Modulemember Crypt
*/
//@{
/*** Include files *********************************************************************/
#include "DirtySDK/platform.h"
/*** Defines ***************************************************************************/
#define MD5_BINARY_OUT 16 //!< length of binary output
#define MD5_STRING_OUT 33 //!< length of string output
/*** Macros ****************************************************************************/
/*** Type Definitions ******************************************************************/
typedef struct CryptMD5T CryptMD5T;
//! all fields are PRIVATE
struct CryptMD5T
{
unsigned char strData[64+8];//!< partial data block (8 for padding)
uint32_t uCount; //!< total byte count
uint32_t uRegs[4]; //!< the digest registers
};
/*** Variables *************************************************************************/
/*** Functions *************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
// init the MD5 context.
DIRTYCODE_API void CryptMD5Init(CryptMD5T *pContext);
// init the MD5 context (alternate form)
DIRTYCODE_API void CryptMD5Init2(CryptMD5T *pContext, int32_t iHashSize);
// add data to the MD5 context (hash the data).
DIRTYCODE_API void CryptMD5Update(CryptMD5T *pContext, const void *pBuffer, int32_t iLength);
// convert MD5 state into final output form
DIRTYCODE_API void CryptMD5Final(CryptMD5T *pContext, void *pBuffer, int32_t iLength);
#ifdef __cplusplus
}
#endif
//@}
#endif // _cryptmd5_h

View File

@ -0,0 +1,91 @@
/*H********************************************************************************/
/*!
\File cryptmont.h
\Description
This module implements the math for elliptic curve cryptography
using montgomery curves
\Copyright
Copyright (c) Electronic Arts 2018. ALL RIGHTS RESERVED.
*/
/********************************************************************************H*/
#ifndef _cryptmont_h
#define _cryptmont_h
/*!
\Moduledef CryptMont CryptMont
\Modulemember Crypt
*/
//@{
#include "DirtySDK/platform.h"
#include "DirtySDK/crypt/cryptbn.h"
#include "DirtySDK/crypt/cryptdef.h"
/*** Type Definitions **************************************************************/
typedef struct CryptMontT
{
CryptBnT Prime; //!< curve prime
CryptBnT PrimeMin2; //!< curve prime - 2 used for exponentiation
CryptBnT BasePoint; //!< curve base point (only u)
CryptBnT A24; //!< constant used for calculations
CryptBnT PrivateKey; //!< private key
//! working state
CryptBnT X_2;
CryptBnT X_3;
CryptEccPointT Result; //!< cached result and z_2/z_3 during the point state
int32_t iMemGroup; //!< memgroup id
void *pMemGroupUserdata; //!< memgroup userdata
CryptBnT *pTable; //!< table used for sliding window in exponentiation
enum
{
CRYPTMONT_COMPUTE_POINT,//!< calculate the point
CRYPTMONT_COMPUTE_EXP //!< calculate the final result
} eState; //!< current state of the calculation
int16_t iBitIndex; //!< bit index for the calculation (private key or exponent)
uint8_t bAccumulOne; //!< used to skip the first multiply
uint8_t uSwap; //!< current swap state
uint32_t uCryptUsecs; //!< total number of usecs the operation took
int32_t iCurveType; //!< what curve were we initialized with
} CryptMontT;
/*** Functions ********************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
// init the curve state
DIRTYCODE_API int32_t CryptMontInit(CryptMontT *pState, int32_t iCurveType);
// for testing-purposes; set the private key
DIRTYCODE_API void CryptMontSetPrivateKey(CryptMontT *pState, const uint8_t *pKey);
// generates a public key based on the curve parameters: BasePoint * Secret
DIRTYCODE_API int32_t CryptMontPublic(CryptMontT *pState, CryptEccPointT *pResult, uint32_t *pCryptUsecs);
// generate a shared secret based on the curve parameters and other parties public key: PublicKey * Secret
DIRTYCODE_API int32_t CryptMontSecret(CryptMontT *pState, CryptEccPointT *pPublicKey, CryptEccPointT *pResult, uint32_t *pCryptUsecs);
// initialize a point on the curve from a buffer
DIRTYCODE_API int32_t CryptMontPointInitFrom(CryptEccPointT *pPoint, const uint8_t *pBuffer, int32_t iBufSize);
// output a point to a buffer
DIRTYCODE_API int32_t CryptMontPointFinal(const CryptMontT *pState, const CryptEccPointT *pPoint, uint8_t bSecret, uint8_t *pBuffer, int32_t iBufSize);
#ifdef __cplusplus
}
#endif
//@}
#endif // _cryptmont_h

View File

@ -0,0 +1,116 @@
/*H********************************************************************************/
/*!
\File cryptnist.h
\Description
This module implements the math for elliptic curve cryptography
using curves in short Weierstrass form (NIST curves)
\Copyright
Copyright (c) Electronic Arts 2017. ALL RIGHTS RESERVED.
*/
/********************************************************************************H*/
#ifndef _cryptnist_h
#define _cryptnist_h
/*!
\Moduledef CryptNist CryptNist
\Modulemember Crypt
*/
//@{
/*** Include files ****************************************************************/
#include "DirtySDK/platform.h"
#include "DirtySDK/crypt/cryptbn.h"
#include "DirtySDK/crypt/cryptdef.h"
/*** Defines **********************************************************************/
//! window size used for sliding window
#define CRYPTNIST_WINDOW_SIZE (5)
//! precomputed table size based on the window size
#define CRYPTNIST_TABLE_SIZE (1 << (CRYPTNIST_WINDOW_SIZE - 1))
/*** Type Definitions *************************************************************/
//! private state that defines the curve
typedef struct CryptNistT
{
CryptBnT Prime; //!< the finite field that the curve is defined over
CryptBnT CoefficientA; //!< cofficient that defines the curve
CryptBnT CoefficientB; //!< cofficient that defines the curve
CryptEccPointT BasePoint; //!< generator point on the curve
CryptBnT Order; //!< the number of point operations on the curve until the resultant line is vertical
int32_t iMemGroup; //!< memgroup id
void *pMemGroupUserdata; //!< memgroup userdata
CryptEccPointT *pTable; //!< precomputed values used for for computation
int32_t iKeyIndex; //!< current bit index state when generating
int32_t iSize; //!< size of curve parameters
uint32_t uCryptUSecs; //!< number of total usecs the operation took
} CryptNistT;
//! state dealing with diffie hellmen key exchange
typedef struct CryptNistDhT
{
CryptNistT Ecc; //!< base ecc state
CryptBnT PrivateKey; //!< private key used to calculate public key and shared secret
CryptEccPointT Result; //!< working state
} CryptNistDhT;
//! state dealing with dsa sign and verify
typedef struct CryptNistDsaT
{
CryptNistT Ecc; //!< base ecc state
CryptBnT K; //!< secret used for signing operations
CryptBnT U1; //!< used for verification operations
CryptBnT U2; //!< used for verification operations
CryptEccPointT Result; //!< working state
} CryptNistDsaT;
/*** Functions ********************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
// initializes the crypt state to perform diffie hellmen key exchange
DIRTYCODE_API int32_t CryptNistInitDh(CryptNistDhT *pState, int32_t iCurveType);
// initializes the crypt state to perform dsa sign and verify
DIRTYCODE_API int32_t CryptNistInitDsa(CryptNistDsaT *pState, int32_t iCurveType);
// generates a public key based on the curve parameters: BasePoint * Secret
DIRTYCODE_API int32_t CryptNistPublic(CryptNistDhT *pState, CryptEccPointT *pResult, uint32_t *pCryptUsecs);
// generate a shared secret based on the curve parameters and other parties public key: PublicKey * Secret
DIRTYCODE_API int32_t CryptNistSecret(CryptNistDhT *pState, CryptEccPointT *pPublicKey, CryptEccPointT *pResult, uint32_t *pCryptUsecs);
// generate a ecdsa signature
DIRTYCODE_API int32_t CryptNistSign(CryptNistDsaT *pState, const CryptBnT *pPrivateKey, const uint8_t *pHash, int32_t iHashSize, CryptEccPointT *pSignature, uint32_t *pCryptUsecs);
// verify a ecdsa signature
DIRTYCODE_API int32_t CryptNistVerify(CryptNistDsaT *pState, CryptEccPointT *pPublicKey, const uint8_t *pHash, int32_t iHashSize, CryptEccPointT *pSignature, uint32_t *pCryptUsecs);
// check if the point is on the curve
DIRTYCODE_API uint8_t CryptNistPointValidate(const CryptNistDhT *pState, const CryptEccPointT *pPoint);
// initialize a point on the curve from a buffer
DIRTYCODE_API int32_t CryptNistPointInitFrom(CryptEccPointT *pPoint, const uint8_t *pBuffer, int32_t iBufLen);
// output a point to a buffer (for dh, dsa encoding looks different which we do in protossl)
DIRTYCODE_API int32_t CryptNistPointFinal(const CryptNistDhT *pState, const CryptEccPointT *pPoint, uint8_t bSecret, uint8_t *pBuffer, int32_t iBufLen);
#ifdef __cplusplus
}
#endif
//@}
#endif // _cryptnist_h

View File

@ -0,0 +1,53 @@
/*H********************************************************************************/
/*!
\File cryptrand.h
\Description
Cryptographic random number generator. Uses system-defined rng where
available.
\Copyright
Copyright (c) 2012 Electronic Arts Inc.
\Version 12/05/2012 (jbrookes) First Version
*/
/********************************************************************************H*/
#ifndef _cryptrand_h
#define _cryptrand_h
/*!
\Moduledef CryptRand CryptRand
\Modulemember Crypt
*/
//@{
/*** Include files ****************************************************************/
#include "DirtySDK/platform.h"
/*** Defines **********************************************************************/
/*** Macros ***********************************************************************/
/*** Type Definitions *************************************************************/
/*** Variables ********************************************************************/
/*** Functions ********************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
// get random data
DIRTYCODE_API void CryptRandGet(uint8_t *pBuffer, int32_t iBufSize);
#ifdef __cplusplus
}
#endif
//@}
#endif // _cryptrand_h

View File

@ -0,0 +1,138 @@
/*H*************************************************************************************/
/*!
\File cryptrsa.h
\Description
This module is a from-scratch RSA implementation in order to avoid any
intellectual property issues. The 1024 bit RSA public key encryption algorithm
was implemented from a specification provided by Netscape for SSL implementation
(see protossl.h).
\Copyright
Copyright (c) Tiburon Entertainment / Electronic Arts 2002. ALL RIGHTS RESERVED.
\Version 03/08/2002 (gschaefer) First Version (protossl)
\Version 11/18/2002 (jbrookes) Names changed to include "Proto"
\Version 03/05/2003 (jbrookes) Split RSA encryption from protossl
*/
/*************************************************************************************H*/
#ifndef _cryptrsa_h
#define _cryptrsa_h
/*!
\Moduledef CryptRSA CryptRSA
\Modulemember Crypt
*/
//@{
/*** Include files *********************************************************************/
#include "DirtySDK/platform.h"
#include "DirtySDK/crypt/cryptbn.h"
#include "DirtySDK/crypt/cryptdef.h"
/*** Defines ***************************************************************************/
/*** Macros ****************************************************************************/
/*** Type Definitions ******************************************************************/
//! union of our working state depending on the type of operations
typedef union CryptRSAWorkingT
{
struct
{
CryptBnT Modulus; //!< public key modulus
CryptBnT Exponent; //!< public key exponent
// working memory for modular exponentiation
CryptBnT Powerof;
CryptBnT Accumul;
} PublicKey;
struct
{
/* selected private key state we use for chinese remainder theorum computation
we have access to the other data (modulus, exponent) but it is not used so
not worth storing */
CryptBnT PrimeP; //!< prime factor p of modulus
CryptBnT PrimeQ; //!< prime factor q of modulus
CryptBnT ExponentP; //!< exponent dP mod p-1
CryptBnT ExponentQ; //!< exponent dQ mod q-1
CryptBnT Coeffecient; //!< inverse of q mod p
// working memory for modular exponentiation
CryptBnT PowerofP;
CryptBnT PowerofQ;
CryptBnT M1;
CryptBnT M2;
// current state of computation
enum
{
CRT_COMPUTE_M1,
CRT_COMPUTE_M2
} eState;
} PrivateKey;
} CryptRSAWorkingT;
//! cryptrsa state
typedef struct CryptRSAT
{
CryptRSAWorkingT Working; //!< working state & data for doing modular exponentiation
CryptBnT *pTable; //!< table used in sliding window for precomputed powers
CryptBnT aTable[1]; //!< fixed sized table used for public key operations which is our base case
// memory allocation data
int32_t iMemGroup;
void *pMemGroupUserData;
int32_t iKeyModSize; //!< size of public key modulus
uint8_t EncryptBlock[1024]; //!< input/output data
int16_t iExpBitIndex; //!< bit index into the current exponent we are working on
uint8_t bAccumulOne; //!< can we skip the first multiply?
uint8_t bPrivate; //!< are we public or private key operation?
// rsa profiling info
uint32_t uCryptMsecs;
uint32_t uCryptUsecs;
uint32_t uNumExpCalls;
} CryptRSAT;
/*** Variables *************************************************************************/
/*** Functions *************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
// init rsa state
DIRTYCODE_API int32_t CryptRSAInit(CryptRSAT *pState, const uint8_t *pModulus, int32_t iModSize, const uint8_t *pExponent, int32_t iExpSize);
// init rsa state for private key data
DIRTYCODE_API int32_t CryptRSAInit2(CryptRSAT *pState, int32_t iModSize, const CryptBinaryObjT *pPrimeP, const CryptBinaryObjT *pPrimeQ, const CryptBinaryObjT *pExponentP, const CryptBinaryObjT *pExponentQ, const CryptBinaryObjT *pCoeffecient);
// setup the master shared secret for encryption
DIRTYCODE_API void CryptRSAInitMaster(CryptRSAT *pState, const uint8_t *pMaster, int32_t iMasterLen);
// setup the master shared secret for encryption using PKCS1.5
DIRTYCODE_API void CryptRSAInitPrivate(CryptRSAT *pState, const uint8_t *pMaster, int32_t iMasterLen);
// setup the encrypted signature for decryption.
DIRTYCODE_API void CryptRSAInitSignature(CryptRSAT *pState, const uint8_t *pSig, int32_t iSigLen);
// do the encryption/decryption
DIRTYCODE_API int32_t CryptRSAEncrypt(CryptRSAT *pState, int32_t iIter);
#ifdef __cplusplus
}
#endif
//@}
#endif // _cryptrsa_h

View File

@ -0,0 +1,84 @@
/*H*******************************************************************/
/*!
\File cryptsha1.h
\Description
This module implements SHA1 as defined in RFC 3174.
\Copyright
Copyright (c) Electronic Arts 2004. ALL RIGHTS RESERVED.
\Notes
The implementation is based on the algorithm description in sections
3 through 6 of RFC 3174 and not on the C code in section 7.
The code deliberately uses some of the naming conventions from
the RFC to in order to aid comprehension.
This implementation is limited to hashing no more than 2^32-9 bytes.
It will silently produce the wrong result if an attempt is made to
hash more data.
\Version 1.0 06/06/2004 (sbevan) First Version
*/
/*******************************************************************H*/
#ifndef _cryptsha1_h
#define _cryptsha1_h
/*!
\Moduledef CryptSha1 CryptSha1
\Modulemember Crypt
*/
//@{
/*** Include files ***************************************************/
#include "DirtySDK/platform.h"
/*** Defines *********************************************************/
#define CRYPTSHA1_HASHSIZE (160/8) //!< length of SHA1 hash
/*** Macros **********************************************************/
/*** Type Definitions ************************************************/
typedef struct CryptSha1T CryptSha1T;
//! all fields are PRIVATE
struct CryptSha1T
{
uint32_t uCount; //!< total length of hash data in bytes
uint32_t uPartialCount; //!< # bytes in the strData
uint32_t H[5]; //!< message digest
uint8_t strData[16*4]; //!< partial data block
};
/*** Variables *******************************************************/
/*** Functions *******************************************************/
#ifdef __cplusplus
extern "C" {
#endif
// init the SHA1 context.
DIRTYCODE_API void CryptSha1Init(CryptSha1T *pSha1);
// init the SHA1 context (alternate form)
DIRTYCODE_API void CryptSha1Init2(CryptSha1T *pSha1, int32_t iHashSize);
// add data to the SHA1 context (hash the data).
DIRTYCODE_API void CryptSha1Update(CryptSha1T *pSha1, const uint8_t *pInput, uint32_t uInputLength);
// convert SHA1 state into final output form
DIRTYCODE_API void CryptSha1Final(CryptSha1T *pSha1, void *pBuffer, uint32_t uLength);
#ifdef __cplusplus
}
#endif
//@}
#endif

View File

@ -0,0 +1,87 @@
/*H*******************************************************************/
/*!
\File cryptsha2.h
\Description
This module implements SHA2 as defined in RFC 6234, which is
itself based on FIPS 180-2.
\Notes
This implementation is limited to hashing no more than 2^32-9
bytes. It will silently produce the wrong result if an attempt
is made to hash more data.
\Copyright
Copyright (c) Electronic Arts 2013
\Version 1.0 11/04/2013 (jbrookes) First Version
*/
/*******************************************************************H*/
#ifndef _cryptsha2_h
#define _cryptsha2_h
/*!
\Moduledef CryptSha2 CryptSha2
\Modulemember Crypt
*/
//@{
/*** Include files ***************************************************/
#include "DirtySDK/platform.h"
/*** Defines *********************************************************/
//! maximum hash result
#define CRYPTSHA224_HASHSIZE (28)
#define CRYPTSHA256_HASHSIZE (32)
#define CRYPTSHA384_HASHSIZE (48)
#define CRYPTSHA512_HASHSIZE (64)
#define CRYPTSHA2_HASHSIZE_MAX (CRYPTSHA512_HASHSIZE)
/*** Macros **********************************************************/
/*** Type Definitions ************************************************/
//! private SHA2 state
typedef struct CryptSha2T
{
uint32_t uCount; //!< total length of hash data in bytes
uint8_t uHashSize; //!< hash size
uint8_t uBlockSize; //!< 64/128 depending on mode
uint8_t uPartialCount; //!< # bytes in the partial data block
uint8_t _pad;
union
{
uint32_t H_32[8];
uint64_t H_64[8];
}TempHash; //!< temporary hash state
uint8_t strData[128]; //!< partial data block
} CryptSha2T;
/*** Variables *******************************************************/
/*** Functions *******************************************************/
#ifdef __cplusplus
extern "C" {
#endif
// init the SHA2 context.
DIRTYCODE_API void CryptSha2Init(CryptSha2T *pSha2, int32_t iHashSize);
// add data to the SHA2 context (hash the data).
DIRTYCODE_API void CryptSha2Update(CryptSha2T *pSha2, const uint8_t *pInput, uint32_t uInputLength);
// convert SHA2 state into final output form
DIRTYCODE_API void CryptSha2Final(CryptSha2T *pSha2, uint8_t *pBuffer, uint32_t uLength);
#ifdef __cplusplus
}
#endif
//@}
#endif // _cryptsha2_h

View File

@ -0,0 +1,49 @@
/*H********************************************************************************/
/*!
\File dirtydefs.h
\Description:
DirtySock platform independent definitions and enumerations.
[DEPRECATE]
\Copyright
Copyright (c) Electronic Arts 1999-2005
\Version 1.0 02/03/99 (JLB) First Version
\Version 1.1 04/01/99 (MDB) Added Endian types
\Version 1.2 03/27/02 (GWS) Made NULL C++ friendly, added DIRTYCODE_IOP, CODE_UNIX
\Version 1.3 02/22/05 (JEF) Moved CODE_XXX to DIRTYCODE_XXX to avoid conflicts
\Version 1.4 03/22/05 (GWS) Replaced with include of platform.h
*/
/********************************************************************************H*/
#ifndef _dirtydefs_h
#define _dirtydefs_h
/*** Include files ****************************************************************/
#include "DirtySDK/platform.h"
/*** Defines **********************************************************************/
// Microsoft Facilty codes when building a HRESTULT go up to 81, so we'll just start at 128
// we have 11 bits to work with giving us a max value of 2047
#define DIRTYAPI_SOCKET (128)
#define DIRTYAPI_PROTO_HTTP (129)
#define DIRTYAPI_PROTO_SSL (130)
#define DIRTYAPI_QOS (131)
#define DIRTYAPI_MAX (2047)
#define DIRTYAPI_SOCKET_ERR_ALREADY_ACTIVE (-1)
#define DIRTYAPI_SOCKET_ERR_NO_MEMORY (-2)
#define DIRTYAPI_SOCKET_ERR_HOST_NAME_CACHE (-3)
#define DIRTYAPI_SOCKET_ERR_PLATFORM_SPECIFIC (-4)
/*** Macros ***********************************************************************/
/*** Type Definitions *************************************************************/
#endif // _dirtydefs_h

View File

@ -0,0 +1,746 @@
/*H********************************************************************************/
/*!
\File dirtylang.h
\Description
Country and Language Code Information
\Notes
This module provides country and language codes for both client and
server code in DirtySDK.
2-letter language codes are currently available here:
http://en.wikipedia.org/wiki/ISO_639
2-letter country codes are currently available here:
http://en.wikipedia.org/wiki/ISO_3166
\Copyright
Copyright (c) Electronic Arts 2004. ALL RIGHTS RESERVED.
\Version 1.0 11/30/2004 (jfrank) First Version
*/
/********************************************************************************H*/
#ifndef _dirtylang_h
#define _dirtylang_h
/*!
\Moduledef DirtyLang DirtyLang
\Modulemember DirtySock
*/
//@{
/*** Include files ****************************************************************/
#include "DirtySDK/platform.h"
/*** Defines **********************************************************************/
//! Commonly used locality values
#define LOBBYAPI_LOCALITY_UNKNOWN ('zzZZ')
#define LOBBYAPI_LOCALITY_EN_US ('enUS')
#define LOBBYAPI_LOCALITY_BLANK ('\0\0\0\0')
#define LOBBYAPI_LOCALITY_WILDCARD ('****')
#define LOBBYAPI_LOCALITY_DEFAULT LOBBYAPI_LOCALITY_EN_US
#define LOBBYAPI_LOCALITY_DEFAULT_STR "enUS"
#define LOBBYAPI_LOCALITY_UNKNOWN_STR "zzZZ"
//! Non-specific, commonly used country and language codes
#define LOBBYAPI_LANGUAGE_UNKNOWN ('zz')
#define LOBBYAPI_COUNTRY_UNKNOWN ('ZZ')
#define LOBBYAPI_LANGUAGE_WILDCARD ('**')
#define LOBBYAPI_COUNTRY_WILDCARD ('**')
#define LOBBYAPI_LANGUAGE_UNKNOWN_STR ("zz")
#define LOBBYAPI_COUNTRY_UNKNOWN_STR ("ZZ")
//! Languages
#define LOBBYAPI_LANGUAGE_AFAN_OROMO ('om')
#define LOBBYAPI_LANGUAGE_ABKHAZIAN ('ab')
#define LOBBYAPI_LANGUAGE_AFAR ('aa')
#define LOBBYAPI_LANGUAGE_AFRIKAANS ('af')
#define LOBBYAPI_LANGUAGE_ALBANIAN ('sq')
#define LOBBYAPI_LANGUAGE_AMHARIC ('am')
#define LOBBYAPI_LANGUAGE_ARABIC ('ar')
#define LOBBYAPI_LANGUAGE_ARMENIAN ('hy')
#define LOBBYAPI_LANGUAGE_ASSAMESE ('as')
#define LOBBYAPI_LANGUAGE_AYMARA ('ay')
#define LOBBYAPI_LANGUAGE_AZERBAIJANI ('az')
#define LOBBYAPI_LANGUAGE_BASHKIR ('ba')
#define LOBBYAPI_LANGUAGE_BASQUE ('eu')
#define LOBBYAPI_LANGUAGE_BENGALI ('bn')
#define LOBBYAPI_LANGUAGE_BHUTANI ('dz')
#define LOBBYAPI_LANGUAGE_BIHARI ('bh')
#define LOBBYAPI_LANGUAGE_BISLAMA ('bi')
#define LOBBYAPI_LANGUAGE_BRETON ('br')
#define LOBBYAPI_LANGUAGE_BULGARIAN ('bg')
#define LOBBYAPI_LANGUAGE_BURMESE ('my')
#define LOBBYAPI_LANGUAGE_BYELORUSSIAN ('be')
#define LOBBYAPI_LANGUAGE_CAMBODIAN ('km')
#define LOBBYAPI_LANGUAGE_CATALAN ('ca')
#define LOBBYAPI_LANGUAGE_CHINESE ('zh')
#define LOBBYAPI_LANGUAGE_CORSICAN ('co')
#define LOBBYAPI_LANGUAGE_CROATIAN ('hr')
#define LOBBYAPI_LANGUAGE_CZECH ('cs')
#define LOBBYAPI_LANGUAGE_DANISH ('da')
#define LOBBYAPI_LANGUAGE_DUTCH ('nl')
#define LOBBYAPI_LANGUAGE_ENGLISH ('en')
#define LOBBYAPI_LANGUAGE_ESPERANTO ('eo')
#define LOBBYAPI_LANGUAGE_ESTONIAN ('et')
#define LOBBYAPI_LANGUAGE_FAEROESE ('fo')
#define LOBBYAPI_LANGUAGE_FIJI ('fj')
#define LOBBYAPI_LANGUAGE_FINNISH ('fi')
#define LOBBYAPI_LANGUAGE_FRENCH ('fr')
#define LOBBYAPI_LANGUAGE_FRISIAN ('fy')
#define LOBBYAPI_LANGUAGE_GALICIAN ('gl')
#define LOBBYAPI_LANGUAGE_GEORGIAN ('ka')
#define LOBBYAPI_LANGUAGE_GERMAN ('de')
#define LOBBYAPI_LANGUAGE_GREEK ('el')
#define LOBBYAPI_LANGUAGE_GREENLANDIC ('kl')
#define LOBBYAPI_LANGUAGE_GUARANI ('gn')
#define LOBBYAPI_LANGUAGE_GUJARATI ('gu')
#define LOBBYAPI_LANGUAGE_HAUSA ('ha')
#define LOBBYAPI_LANGUAGE_HEBREW ('he')
#define LOBBYAPI_LANGUAGE_HINDI ('hi')
#define LOBBYAPI_LANGUAGE_HUNGARIAN ('hu')
#define LOBBYAPI_LANGUAGE_ICELANDIC ('is')
#define LOBBYAPI_LANGUAGE_INDONESIAN ('id')
#define LOBBYAPI_LANGUAGE_INTERLINGUA ('ia')
#define LOBBYAPI_LANGUAGE_INTERLINGUE ('ie')
#define LOBBYAPI_LANGUAGE_INUPIAK ('ik')
#define LOBBYAPI_LANGUAGE_INUKTITUT ('iu')
#define LOBBYAPI_LANGUAGE_IRISH ('ga')
#define LOBBYAPI_LANGUAGE_ITALIAN ('it')
#define LOBBYAPI_LANGUAGE_JAPANESE ('ja')
#define LOBBYAPI_LANGUAGE_JAVANESE ('jw')
#define LOBBYAPI_LANGUAGE_KANNADA ('kn')
#define LOBBYAPI_LANGUAGE_KASHMIRI ('ks')
#define LOBBYAPI_LANGUAGE_KAZAKH ('kk')
#define LOBBYAPI_LANGUAGE_KINYARWANDA ('rw')
#define LOBBYAPI_LANGUAGE_KIRGHIZ ('ky')
#define LOBBYAPI_LANGUAGE_KIRUNDI ('rn')
#define LOBBYAPI_LANGUAGE_KOREAN ('ko')
#define LOBBYAPI_LANGUAGE_KURDISH ('ku')
#define LOBBYAPI_LANGUAGE_LAOTHIAN ('lo')
#define LOBBYAPI_LANGUAGE_LATIN ('la')
#define LOBBYAPI_LANGUAGE_LATVIAN_LETTISH ('lv')
#define LOBBYAPI_LANGUAGE_LINGALA ('ln')
#define LOBBYAPI_LANGUAGE_LITHUANIAN ('lt')
#define LOBBYAPI_LANGUAGE_MACEDONIAN ('mk')
#define LOBBYAPI_LANGUAGE_MALAGASY ('mg')
#define LOBBYAPI_LANGUAGE_MALAY ('ms')
#define LOBBYAPI_LANGUAGE_MALAYALAM ('ml')
#define LOBBYAPI_LANGUAGE_MALTESE ('mt')
#define LOBBYAPI_LANGUAGE_MAORI ('mi')
#define LOBBYAPI_LANGUAGE_MARATHI ('mr')
#define LOBBYAPI_LANGUAGE_MOLDAVIAN ('mo')
#define LOBBYAPI_LANGUAGE_MONGOLIAN ('mn')
#define LOBBYAPI_LANGUAGE_NAURU ('na')
#define LOBBYAPI_LANGUAGE_NEPALI ('ne')
#define LOBBYAPI_LANGUAGE_NORWEGIAN ('no')
#define LOBBYAPI_LANGUAGE_OCCITAN ('oc')
#define LOBBYAPI_LANGUAGE_ORIYA ('or')
#define LOBBYAPI_LANGUAGE_PASHTO_PUSHTO ('ps')
#define LOBBYAPI_LANGUAGE_PERSIAN ('fa')
#define LOBBYAPI_LANGUAGE_POLISH ('pl')
#define LOBBYAPI_LANGUAGE_PORTUGUESE ('pt')
#define LOBBYAPI_LANGUAGE_PUNJABI ('pa')
#define LOBBYAPI_LANGUAGE_QUECHUA ('qu')
#define LOBBYAPI_LANGUAGE_RHAETO_ROMANCE ('rm')
#define LOBBYAPI_LANGUAGE_ROMANIAN ('ro')
#define LOBBYAPI_LANGUAGE_RUSSIAN ('ru')
#define LOBBYAPI_LANGUAGE_SAMOAN ('sm')
#define LOBBYAPI_LANGUAGE_SANGRO ('sg')
#define LOBBYAPI_LANGUAGE_SANSKRIT ('sa')
#define LOBBYAPI_LANGUAGE_SCOTS_GAELIC ('gd')
#define LOBBYAPI_LANGUAGE_SERBIAN ('sr')
#define LOBBYAPI_LANGUAGE_SERBO_CROATIAN ('sh')
#define LOBBYAPI_LANGUAGE_SESOTHO ('st')
#define LOBBYAPI_LANGUAGE_SETSWANA ('tn')
#define LOBBYAPI_LANGUAGE_SHONA ('sn')
#define LOBBYAPI_LANGUAGE_SINDHI ('sd')
#define LOBBYAPI_LANGUAGE_SINGHALESE ('si')
#define LOBBYAPI_LANGUAGE_SISWATI ('ss')
#define LOBBYAPI_LANGUAGE_SLOVAK ('sk')
#define LOBBYAPI_LANGUAGE_SLOVENIAN ('sl')
#define LOBBYAPI_LANGUAGE_SOMALI ('so')
#define LOBBYAPI_LANGUAGE_SPANISH ('es')
#define LOBBYAPI_LANGUAGE_SUDANESE ('su')
#define LOBBYAPI_LANGUAGE_SWAHILI ('sw')
#define LOBBYAPI_LANGUAGE_SWEDISH ('sv')
#define LOBBYAPI_LANGUAGE_TAGALOG ('tl')
#define LOBBYAPI_LANGUAGE_TAJIK ('tg')
#define LOBBYAPI_LANGUAGE_TAMIL ('ta')
#define LOBBYAPI_LANGUAGE_TATAR ('tt')
#define LOBBYAPI_LANGUAGE_TELUGU ('te')
#define LOBBYAPI_LANGUAGE_THAI ('th')
#define LOBBYAPI_LANGUAGE_TIBETAN ('bo')
#define LOBBYAPI_LANGUAGE_TIGRINYA ('ti')
#define LOBBYAPI_LANGUAGE_TONGA ('to')
#define LOBBYAPI_LANGUAGE_TSONGA ('ts')
#define LOBBYAPI_LANGUAGE_TURKISH ('tr')
#define LOBBYAPI_LANGUAGE_TURKMEN ('tk')
#define LOBBYAPI_LANGUAGE_TWI ('tw')
#define LOBBYAPI_LANGUAGE_UIGHUR ('ug')
#define LOBBYAPI_LANGUAGE_UKRAINIAN ('uk')
#define LOBBYAPI_LANGUAGE_URDU ('ur')
#define LOBBYAPI_LANGUAGE_UZBEK ('uz')
#define LOBBYAPI_LANGUAGE_VIETNAMESE ('vi')
#define LOBBYAPI_LANGUAGE_VOLAPUK ('vo')
#define LOBBYAPI_LANGUAGE_WELSH ('cy')
#define LOBBYAPI_LANGUAGE_WOLOF ('wo')
#define LOBBYAPI_LANGUAGE_XHOSA ('xh')
#define LOBBYAPI_LANGUAGE_YIDDISH ('yi')
#define LOBBYAPI_LANGUAGE_YORUBA ('yo')
#define LOBBYAPI_LANGUAGE_ZHUANG ('za')
#define LOBBYAPI_LANGUAGE_ZULU ('zu')
// Languages: added on Mar-25-2011 according to ISO 639-1
#define LOBBYAPI_LANGUAGE_BOSNIAN ('bs')
#define LOBBYAPI_LANGUAGE_DIVEHI ('dv')
#define LOBBYAPI_LANGUAGE_IGBO ('ig')
#define LOBBYAPI_LANGUAGE_LUXEMBOURGISH ('lb')
#define LOBBYAPI_LANGUAGE_YI ('ii')
#define LOBBYAPI_LANGUAGE_NORWEGIAN_BOKMAL ('nb')
#define LOBBYAPI_LANGUAGE_NORWEGIAN_NYNORSK ('nn')
#define LOBBYAPI_LANGUAGE_SAMI ('se')
// Default language
#define LOBBYAPI_LANGUAGE_DEFAULT LOBBYAPI_LANGUAGE_ENGLISH
#define LOBBYAPI_LANGUAGE_DEFAULT_STR "en"
//! Countries
#define LOBBYAPI_COUNTRY_AFGHANISTAN ('AF')
#define LOBBYAPI_COUNTRY_ALBANIA ('AL')
#define LOBBYAPI_COUNTRY_ALGERIA ('DZ')
#define LOBBYAPI_COUNTRY_AMERICAN_SAMOA ('AS')
#define LOBBYAPI_COUNTRY_ANDORRA ('AD')
#define LOBBYAPI_COUNTRY_ANGOLA ('AO')
#define LOBBYAPI_COUNTRY_ANGUILLA ('AI')
#define LOBBYAPI_COUNTRY_ANTARCTICA ('AQ')
#define LOBBYAPI_COUNTRY_ANTIGUA_BARBUDA ('AG')
#define LOBBYAPI_COUNTRY_ARGENTINA ('AR')
#define LOBBYAPI_COUNTRY_ARMENIA ('AM')
#define LOBBYAPI_COUNTRY_ARUBA ('AW')
#define LOBBYAPI_COUNTRY_AUSTRALIA ('AU')
#define LOBBYAPI_COUNTRY_AUSTRIA ('AT')
#define LOBBYAPI_COUNTRY_AZERBAIJAN ('AZ')
#define LOBBYAPI_COUNTRY_BAHAMAS ('BS')
#define LOBBYAPI_COUNTRY_BAHRAIN ('BH')
#define LOBBYAPI_COUNTRY_BANGLADESH ('BD')
#define LOBBYAPI_COUNTRY_BARBADOS ('BB')
#define LOBBYAPI_COUNTRY_BELARUS ('BY')
#define LOBBYAPI_COUNTRY_BELGIUM ('BE')
#define LOBBYAPI_COUNTRY_BELIZE ('BZ')
#define LOBBYAPI_COUNTRY_BENIN ('BJ')
#define LOBBYAPI_COUNTRY_BERMUDA ('BM')
#define LOBBYAPI_COUNTRY_BHUTAN ('BT')
#define LOBBYAPI_COUNTRY_BOLIVIA ('BO')
#define LOBBYAPI_COUNTRY_BOSNIA_HERZEGOVINA ('BA')
#define LOBBYAPI_COUNTRY_BOTSWANA ('BW')
#define LOBBYAPI_COUNTRY_BOUVET_ISLAND ('BV')
#define LOBBYAPI_COUNTRY_BRAZIL ('BR')
#define LOBBYAPI_COUNTRY_BRITISH_INDIAN_OCEAN_TERRITORY ('IO')
#define LOBBYAPI_COUNTRY_BRUNEI_DARUSSALAM ('BN')
#define LOBBYAPI_COUNTRY_BULGARIA ('BG')
#define LOBBYAPI_COUNTRY_BURKINA_FASO ('BF')
#define LOBBYAPI_COUNTRY_BURUNDI ('BI')
#define LOBBYAPI_COUNTRY_CAMBODIA ('KH')
#define LOBBYAPI_COUNTRY_CAMEROON ('CM')
#define LOBBYAPI_COUNTRY_CANADA ('CA')
#define LOBBYAPI_COUNTRY_CAPE_VERDE ('CV')
#define LOBBYAPI_COUNTRY_CAYMAN_ISLANDS ('KY')
#define LOBBYAPI_COUNTRY_CENTRAL_AFRICAN_REPUBLIC ('CF')
#define LOBBYAPI_COUNTRY_CHAD ('TD')
#define LOBBYAPI_COUNTRY_CHILE ('CL')
#define LOBBYAPI_COUNTRY_CHINA ('CN')
#define LOBBYAPI_COUNTRY_CHRISTMAS_ISLAND ('CX')
#define LOBBYAPI_COUNTRY_COCOS_KEELING_ISLANDS ('CC')
#define LOBBYAPI_COUNTRY_COLOMBIA ('CO')
#define LOBBYAPI_COUNTRY_COMOROS ('KM')
#define LOBBYAPI_COUNTRY_CONGO ('CG')
#define LOBBYAPI_COUNTRY_COOK_ISLANDS ('CK')
#define LOBBYAPI_COUNTRY_COSTA_RICA ('CR')
#define LOBBYAPI_COUNTRY_COTE_DIVOIRE ('CI')
#define LOBBYAPI_COUNTRY_CROATIA ('HR')
#define LOBBYAPI_COUNTRY_CUBA ('CU')
#define LOBBYAPI_COUNTRY_CYPRUS ('CY')
#define LOBBYAPI_COUNTRY_CZECH_REPUBLIC ('CZ')
#define LOBBYAPI_COUNTRY_DENMARK ('DK')
#define LOBBYAPI_COUNTRY_DJIBOUTI ('DJ')
#define LOBBYAPI_COUNTRY_DOMINICA ('DM')
#define LOBBYAPI_COUNTRY_DOMINICAN_REPUBLIC ('DO')
#define LOBBYAPI_COUNTRY_EAST_TIMOR ('TP')
#define LOBBYAPI_COUNTRY_ECUADOR ('EC')
#define LOBBYAPI_COUNTRY_EGYPT ('EG')
#define LOBBYAPI_COUNTRY_EL_SALVADOR ('SV')
#define LOBBYAPI_COUNTRY_EQUATORIAL_GUINEA ('GQ')
#define LOBBYAPI_COUNTRY_ERITREA ('ER')
#define LOBBYAPI_COUNTRY_ESTONIA ('EE')
#define LOBBYAPI_COUNTRY_ETHIOPIA ('ET')
#define LOBBYAPI_COUNTRY_EUROPE_SSGFI_ONLY ('EU')
#define LOBBYAPI_COUNTRY_FALKLAND_ISLANDS ('FK')
#define LOBBYAPI_COUNTRY_FAEROE_ISLANDS ('FO')
#define LOBBYAPI_COUNTRY_FIJI ('FJ')
#define LOBBYAPI_COUNTRY_FINLAND ('FI')
#define LOBBYAPI_COUNTRY_FRANCE ('FR')
#define LOBBYAPI_COUNTRY_FRANCE_METROPOLITAN ('FX')
#define LOBBYAPI_COUNTRY_FRENCH_GUIANA ('GF')
#define LOBBYAPI_COUNTRY_FRENCH_POLYNESIA ('PF')
#define LOBBYAPI_COUNTRY_FRENCH_SOUTHERN_TERRITORIES ('TF')
#define LOBBYAPI_COUNTRY_GABON ('GA')
#define LOBBYAPI_COUNTRY_GAMBIA ('GM')
#define LOBBYAPI_COUNTRY_GEORGIA ('GE')
#define LOBBYAPI_COUNTRY_GERMANY ('DE')
#define LOBBYAPI_COUNTRY_GHANA ('GH')
#define LOBBYAPI_COUNTRY_GIBRALTAR ('GI')
#define LOBBYAPI_COUNTRY_GREECE ('GR')
#define LOBBYAPI_COUNTRY_GREENLAND ('GL')
#define LOBBYAPI_COUNTRY_GRENADA ('GD')
#define LOBBYAPI_COUNTRY_GUADELOUPE ('GP')
#define LOBBYAPI_COUNTRY_GUAM ('GU')
#define LOBBYAPI_COUNTRY_GUATEMALA ('GT')
#define LOBBYAPI_COUNTRY_GUINEA ('GN')
#define LOBBYAPI_COUNTRY_GUINEA_BISSAU ('GW')
#define LOBBYAPI_COUNTRY_GUYANA ('GY')
#define LOBBYAPI_COUNTRY_HAITI ('HT')
#define LOBBYAPI_COUNTRY_HEARD_AND_MC_DONALD_ISLANDS ('HM')
#define LOBBYAPI_COUNTRY_HONDURAS ('HN')
#define LOBBYAPI_COUNTRY_HONG_KONG ('HK')
#define LOBBYAPI_COUNTRY_HUNGARY ('HU')
#define LOBBYAPI_COUNTRY_ICELAND ('IS')
#define LOBBYAPI_COUNTRY_INDIA ('IN')
#define LOBBYAPI_COUNTRY_INDONESIA ('ID')
#define LOBBYAPI_COUNTRY_INTERNATIONAL_SSGFI_ONLY ('II')
#define LOBBYAPI_COUNTRY_IRAN ('IR')
#define LOBBYAPI_COUNTRY_IRAQ ('IQ')
#define LOBBYAPI_COUNTRY_IRELAND ('IE')
#define LOBBYAPI_COUNTRY_ISRAEL ('IL')
#define LOBBYAPI_COUNTRY_ITALY ('IT')
#define LOBBYAPI_COUNTRY_JAMAICA ('JM')
#define LOBBYAPI_COUNTRY_JAPAN ('JP')
#define LOBBYAPI_COUNTRY_JORDAN ('JO')
#define LOBBYAPI_COUNTRY_KAZAKHSTAN ('KZ')
#define LOBBYAPI_COUNTRY_KENYA ('KE')
#define LOBBYAPI_COUNTRY_KIRIBATI ('KI')
#define LOBBYAPI_COUNTRY_KOREA_DEMOCRATIC_PEOPLES_REPUBLIC_OF ('KP')
#define LOBBYAPI_COUNTRY_KOREA_REPUBLIC_OF ('KR')
#define LOBBYAPI_COUNTRY_KUWAIT ('KW')
#define LOBBYAPI_COUNTRY_KYRGYZSTAN ('KG')
#define LOBBYAPI_COUNTRY_LAO_PEOPLES_DEMOCRATIC_REPUBLIC ('LA')
#define LOBBYAPI_COUNTRY_LATVIA ('LV')
#define LOBBYAPI_COUNTRY_LEBANON ('LB')
#define LOBBYAPI_COUNTRY_LESOTHO ('LS')
#define LOBBYAPI_COUNTRY_LIBERIA ('LR')
#define LOBBYAPI_COUNTRY_LIBYAN_ARAB_JAMAHIRIYA ('LY')
#define LOBBYAPI_COUNTRY_LIECHTENSTEIN ('LI')
#define LOBBYAPI_COUNTRY_LITHUANIA ('LT')
#define LOBBYAPI_COUNTRY_LUXEMBOURG ('LU')
#define LOBBYAPI_COUNTRY_MACAU ('MO')
#define LOBBYAPI_COUNTRY_MACEDONIA_THE_FORMER_YUGOSLAV_REPUBLIC_OF ('MK')
#define LOBBYAPI_COUNTRY_MADAGASCAR ('MG')
#define LOBBYAPI_COUNTRY_MALAWI ('MW')
#define LOBBYAPI_COUNTRY_MALAYSIA ('MY')
#define LOBBYAPI_COUNTRY_MALDIVES ('MV')
#define LOBBYAPI_COUNTRY_MALI ('ML')
#define LOBBYAPI_COUNTRY_MALTA ('MT')
#define LOBBYAPI_COUNTRY_MARSHALL_ISLANDS ('MH')
#define LOBBYAPI_COUNTRY_MARTINIQUE ('MQ')
#define LOBBYAPI_COUNTRY_MAURITANIA ('MR')
#define LOBBYAPI_COUNTRY_MAURITIUS ('MU')
#define LOBBYAPI_COUNTRY_MAYOTTE ('YT')
#define LOBBYAPI_COUNTRY_MEXICO ('MX')
#define LOBBYAPI_COUNTRY_MICRONESIA_FEDERATED_STATES_OF ('FM')
#define LOBBYAPI_COUNTRY_MOLDOVA_REPUBLIC_OF ('MD')
#define LOBBYAPI_COUNTRY_MONACO ('MC')
#define LOBBYAPI_COUNTRY_MONGOLIA ('MN')
#define LOBBYAPI_COUNTRY_MONTSERRAT ('MS')
#define LOBBYAPI_COUNTRY_MOROCCO ('MA')
#define LOBBYAPI_COUNTRY_MOZAMBIQUE ('MZ')
#define LOBBYAPI_COUNTRY_MYANMAR ('MM')
#define LOBBYAPI_COUNTRY_NAMIBIA ('NA')
#define LOBBYAPI_COUNTRY_NAURU ('NR')
#define LOBBYAPI_COUNTRY_NEPAL ('NP')
#define LOBBYAPI_COUNTRY_NETHERLANDS ('NL')
#define LOBBYAPI_COUNTRY_NETHERLANDS_ANTILLES ('AN')
#define LOBBYAPI_COUNTRY_NEW_CALEDONIA ('NC')
#define LOBBYAPI_COUNTRY_NEW_ZEALAND ('NZ')
#define LOBBYAPI_COUNTRY_NICARAGUA ('NI')
#define LOBBYAPI_COUNTRY_NIGER ('NE')
#define LOBBYAPI_COUNTRY_NIGERIA ('NG')
#define LOBBYAPI_COUNTRY_NIUE ('NU')
#define LOBBYAPI_COUNTRY_NORFOLK_ISLAND ('NF')
#define LOBBYAPI_COUNTRY_NORTHERN_MARIANA_ISLANDS ('MP')
#define LOBBYAPI_COUNTRY_NORWAY ('NO')
#define LOBBYAPI_COUNTRY_OMAN ('OM')
#define LOBBYAPI_COUNTRY_PAKISTAN ('PK')
#define LOBBYAPI_COUNTRY_PALAU ('PW')
#define LOBBYAPI_COUNTRY_PANAMA ('PA')
#define LOBBYAPI_COUNTRY_PAPUA_NEW_GUINEA ('PG')
#define LOBBYAPI_COUNTRY_PARAGUAY ('PY')
#define LOBBYAPI_COUNTRY_PERU ('PE')
#define LOBBYAPI_COUNTRY_PHILIPPINES ('PH')
#define LOBBYAPI_COUNTRY_PITCAIRN ('PN')
#define LOBBYAPI_COUNTRY_POLAND ('PL')
#define LOBBYAPI_COUNTRY_PORTUGAL ('PT')
#define LOBBYAPI_COUNTRY_PUERTO_RICO ('PR')
#define LOBBYAPI_COUNTRY_QATAR ('QA')
#define LOBBYAPI_COUNTRY_REUNION ('RE')
#define LOBBYAPI_COUNTRY_ROMANIA ('RO')
#define LOBBYAPI_COUNTRY_RUSSIAN_FEDERATION ('RU')
#define LOBBYAPI_COUNTRY_RWANDA ('RW')
#define LOBBYAPI_COUNTRY_SAINT_KITTS_AND_NEVIS ('KN')
#define LOBBYAPI_COUNTRY_SAINT_LUCIA ('LC')
#define LOBBYAPI_COUNTRY_SAINT_VINCENT_AND_THE_GRENADINES ('VC')
#define LOBBYAPI_COUNTRY_SAMOA ('WS')
#define LOBBYAPI_COUNTRY_SAN_MARINO ('SM')
#define LOBBYAPI_COUNTRY_SAO_TOME_AND_PRINCIPE ('ST')
#define LOBBYAPI_COUNTRY_SAUDI_ARABIA ('SA')
#define LOBBYAPI_COUNTRY_SENEGAL ('SN')
#define LOBBYAPI_COUNTRY_SEYCHELLES ('SC')
#define LOBBYAPI_COUNTRY_SIERRA_LEONE ('SL')
#define LOBBYAPI_COUNTRY_SINGAPORE ('SG')
#define LOBBYAPI_COUNTRY_SLOVAKIA ('SK')
#define LOBBYAPI_COUNTRY_SLOVENIA ('SI')
#define LOBBYAPI_COUNTRY_SOLOMON_ISLANDS ('SB')
#define LOBBYAPI_COUNTRY_SOMALIA ('SO')
#define LOBBYAPI_COUNTRY_SOUTH_AFRICA ('ZA')
#define LOBBYAPI_COUNTRY_SOUTH_GEORGIA_AND_THE_SOUTH_SANDWICH_ISLANDS ('GS')
#define LOBBYAPI_COUNTRY_SPAIN ('ES')
#define LOBBYAPI_COUNTRY_SRI_LANKA ('LK')
#define LOBBYAPI_COUNTRY_ST_HELENA_ASCENSION_AND_TRISTAN_DA_CUNHA ('SH')
#define LOBBYAPI_COUNTRY_ST_PIERRE_AND_MIQUELON ('PM')
#define LOBBYAPI_COUNTRY_SUDAN ('SD')
#define LOBBYAPI_COUNTRY_SURINAME ('SR')
#define LOBBYAPI_COUNTRY_SVALBARD_AND_JAN_MAYEN_ISLANDS ('SJ')
#define LOBBYAPI_COUNTRY_SWAZILAND ('SZ')
#define LOBBYAPI_COUNTRY_SWEDEN ('SE')
#define LOBBYAPI_COUNTRY_SWITZERLAND ('CH')
#define LOBBYAPI_COUNTRY_SYRIAN_ARAB_REPUBLIC ('SY')
#define LOBBYAPI_COUNTRY_TAIWAN ('TW')
#define LOBBYAPI_COUNTRY_TAJIKISTAN ('TJ')
#define LOBBYAPI_COUNTRY_TANZANIA_UNITED_REPUBLIC_OF ('TZ')
#define LOBBYAPI_COUNTRY_THAILAND ('TH')
#define LOBBYAPI_COUNTRY_TOGO ('TG')
#define LOBBYAPI_COUNTRY_TOKELAU ('TK')
#define LOBBYAPI_COUNTRY_TONGA ('TO')
#define LOBBYAPI_COUNTRY_TRINIDAD_AND_TOBAGO ('TT')
#define LOBBYAPI_COUNTRY_TUNISIA ('TN')
#define LOBBYAPI_COUNTRY_TURKEY ('TR')
#define LOBBYAPI_COUNTRY_TURKMENISTAN ('TM')
#define LOBBYAPI_COUNTRY_TURKS_AND_CAICOS_ISLANDS ('TC')
#define LOBBYAPI_COUNTRY_TUVALU ('TV')
#define LOBBYAPI_COUNTRY_UGANDA ('UG')
#define LOBBYAPI_COUNTRY_UKRAINE ('UA')
#define LOBBYAPI_COUNTRY_UNITED_ARAB_EMIRATES ('AE')
#define LOBBYAPI_COUNTRY_UNITED_KINGDOM ('GB')
#define LOBBYAPI_COUNTRY_UNITED_STATES ('US')
#define LOBBYAPI_COUNTRY_UNITED_STATES_MINOR_OUTLYING_ISLANDS ('UM')
#define LOBBYAPI_COUNTRY_URUGUAY ('UY')
#define LOBBYAPI_COUNTRY_UZBEKISTAN ('UZ')
#define LOBBYAPI_COUNTRY_VANUATU ('VU')
#define LOBBYAPI_COUNTRY_VATICAN_CITY_STATE ('VA')
#define LOBBYAPI_COUNTRY_VENEZUELA ('VE')
#define LOBBYAPI_COUNTRY_VIETNAM ('VN')
#define LOBBYAPI_COUNTRY_VIRGIN_ISLANDS_BRITISH ('VG')
#define LOBBYAPI_COUNTRY_VIRGIN_ISLANDS_US ('VI')
#define LOBBYAPI_COUNTRY_WALLIS_AND_FUTUNA_ISLANDS ('WF')
#define LOBBYAPI_COUNTRY_WESTERN_SAHARA ('EH')
#define LOBBYAPI_COUNTRY_YEMEN ('YE')
#define LOBBYAPI_COUNTRY_YUGOSLAVIA ('YU')
#define LOBBYAPI_COUNTRY_ZAIRE ('ZR')
#define LOBBYAPI_COUNTRY_ZAMBIA ('ZM')
#define LOBBYAPI_COUNTRY_ZIMBABWE ('ZW')
// Countries: added on Mar-25-2011
#define LOBBYAPI_COUNTRY_SERBIA_AND_MONTENEGRO ('CS')
#define LOBBYAPI_COUNTRY_MONTENEGRO ('ME')
#define LOBBYAPI_COUNTRY_SERBIA ('RS')
#define LOBBYAPI_COUNTRY_CONGO_DRC ('CD')
#define LOBBYAPI_COUNTRY_PALESTINIAN_TERRITORY ('PS')
#define LOBBYAPI_COUNTRY_GUERNSEY ('GG')
#define LOBBYAPI_COUNTRY_JERSEY ('JE')
#define LOBBYAPI_COUNTRY_ISLE_OF_MAN ('IM')
#define LOBBYAPI_COUNTRY_TIMOR_LESTE ('TL')
// Default country
#define LOBBYAPI_COUNTRY_DEFAULT LOBBYAPI_COUNTRY_UNITED_STATES
#define LOBBYAPI_COUNTRY_DEFAULT_STR "US"
//! Currencies (ISO-4217)
#define LOBBYAPI_CURRENCY_UNITED_ARAB_EMIRATS_DIRHAM ('AED')
#define LOBBYAPI_CURRENCY_AFGHAN_AFGHANI ('AFN')
#define LOBBYAPI_CURRENCY_ALBANIAN_LEK ('ALL')
#define LOBBYAPI_CURRENCY_ARMENIAN_DRAM ('AMD')
#define LOBBYAPI_CURRENCY_NETHERLANDS_ANTILLEAN_GUILDER ('ANG')
#define LOBBYAPI_CURRENCY_ANGOLAN_KWANZA ('AOA')
#define LOBBYAPI_CURRENCY_ARGENTINE_PESO ('ARS')
#define LOBBYAPI_CURRENCY_AUSTRALIAN_DOLLAR ('AUD')
#define LOBBYAPI_CURRENCY_ARUBAN_FLORIN ('AWG')
#define LOBBYAPI_CURRENCY_AZERBAIJANI_PMANAT ('AZN')
#define LOBBYAPI_CURRENCY_BOSNIA_AND_HERZEGOVINA_CONVERTIBLE_MARK ('BAM')
#define LOBBYAPI_CURRENCY_BARBADOS_DOLLAR ('BBD')
#define LOBBYAPI_CURRENCY_BANGLADESHI_TAKA ('BDT')
#define LOBBYAPI_CURRENCY_BULGARIAN_LEV ('BGN')
#define LOBBYAPI_CURRENCY_BAHRAINI_DINAR ('BHD')
#define LOBBYAPI_CURRENCY_BURUNDIAN_FRANC ('BIF')
#define LOBBYAPI_CURRENCY_BERMUDIAN_DOLLAR ('BMD')
#define LOBBYAPI_CURRENCY_BRUNEI_DOLLAR ('BND')
#define LOBBYAPI_CURRENCY_BOLIVIANO ('BOB')
#define LOBBYAPI_CURRENCY_BOLIVIAN_MVDOL ('BOV')
#define LOBBYAPI_CURRENCY_BRAZILIAN_REAL ('BRL')
#define LOBBYAPI_CURRENCY_BAHAMIAN_DOLLAR ('BSD')
#define LOBBYAPI_CURRENCY_BHUTANESE_NGULTRUM ('BTN')
#define LOBBYAPI_CURRENCY_BOTSWANA_PULA ('BWP')
#define LOBBYAPI_CURRENCY_BELARUSIAN_RUBLE ('BYR')
#define LOBBYAPI_CURRENCY_BELIZE_DOLLAR ('BZD')
#define LOBBYAPI_CURRENCY_CANADIAN_DOLLAR ('CAD')
#define LOBBYAPI_CURRENCY_CONGOLESE_FRANC ('CDF')
#define LOBBYAPI_CURRENCY_WIR_EURO ('CHE')
#define LOBBYAPI_CURRENCY_SWISS_FRANC ('CHF')
#define LOBBYAPI_CURRENCY_WIR_FRANC ('CHW')
#define LOBBYAPI_CURRENCY_UNIDAD_DE_FOMENTO ('CLF')
#define LOBBYAPI_CURRENCY_CHILEAN_PESO ('CLP')
#define LOBBYAPI_CURRENCY_CHINESE_YUAN ('CNY')
#define LOBBYAPI_CURRENCY_COLOBIAN_PESO ('COP')
#define LOBBYAPI_CURRENCY_UNIDAD_DE_VALOR_REAL ('COU')
#define LOBBYAPI_CURRENCY_COSTA_RICAN_COLON ('CRC')
#define LOBBYAPI_CURRENCY_CUBAN_CONVERTIBLE_PESO ('CUC')
#define LOBBYAPI_CURRENCY_CUBAN_PESO ('CUP')
#define LOBBYAPI_CURRENCY_CAP_VERDE_ESCUDO ('CVE')
#define LOBBYAPI_CURRENCY_CZECH_KORUNA ('CZK')
#define LOBBYAPI_CURRENCY_DJIBOUTIAN_FRANC ('DJF')
#define LOBBYAPI_CURRENCY_DANISH_KRONE ('DKK')
#define LOBBYAPI_CURRENCY_DOMINICAN_PESO ('DOP')
#define LOBBYAPI_CURRENCY_ALGERIAN_DINAR ('DZD')
#define LOBBYAPI_CURRENCY_EGYPTIAN_POUND ('EGP')
#define LOBBYAPI_CURRENCY_ERITREAN_NAKFA ('ERN')
#define LOBBYAPI_CURRENCY_ETHIOPIAN_BIRR ('ETB')
#define LOBBYAPI_CURRENCY_EURO ('EUR')
#define LOBBYAPI_CURRENCY_FIJI_DOLLAR ('FJD')
#define LOBBYAPI_CURRENCY_FALKLAND_ISLANDS_POUND ('FKP')
#define LOBBYAPI_CURRENCY_POUND_STERLING ('GBP')
#define LOBBYAPI_CURRENCY_GEORGIAN_LARI ('GEL')
#define LOBBYAPI_CURRENCY_GHANAIAN_CEDI ('GHS')
#define LOBBYAPI_CURRENCY_GIBRALTAR_POUND ('GIP')
#define LOBBYAPI_CURRENCY_GAMBIAN_DALASI ('GMD')
#define LOBBYAPI_CURRENCY_GUINEAN_FRANC ('GNF')
#define LOBBYAPI_CURRENCY_GUATEMALAN_QUETZAL ('GTQ')
#define LOBBYAPI_CURRENCY_GUYANESE_DOLLAR ('GYD')
#define LOBBYAPI_CURRENCY_HONG_KONG_DOLLAR ('HKD')
#define LOBBYAPI_CURRENCY_HONDURAN_LEMPIRA ('HNL')
#define LOBBYAPI_CURRENCY_CROATIAN_KUNA ('HRK')
#define LOBBYAPI_CURRENCY_HAITIAN_GOURDE ('HTG')
#define LOBBYAPI_CURRENCY_HUNGARIAN_FORINT ('HUF')
#define LOBBYAPI_CURRENCY_INDONESIAN_RUPIAH ('IDR')
#define LOBBYAPI_CURRENCY_ISRAELI_NEW_SHEQEL ('ILS')
#define LOBBYAPI_CURRENCY_INDIAN_RUPEE ('INR')
#define LOBBYAPI_CURRENCY_IRAQI_DINAR ('IQD')
#define LOBBYAPI_CURRENCY_IRANIAN_RIAL ('IRR')
#define LOBBYAPI_CURRENCY_ICELANDIC_KRONA ('ISK')
#define LOBBYAPI_CURRENCY_JAMAICAN_DOLLAR ('JMD')
#define LOBBYAPI_CURRENCY_JORDANIAN_DINAR ('JOD')
#define LOBBYAPI_CURRENCY_JAPANESE_YEN ('JPY')
#define LOBBYAPI_CURRENCY_KENYAN_SHILLING ('KES')
#define LOBBYAPI_CURRENCY_KYRGYZSTANI_SOM ('KGS')
#define LOBBYAPI_CURRENCY_CAMBODIAN_RIEL ('KHR')
#define LOBBYAPI_CURRENCY_COMORO_FRANC ('KMF')
#define LOBBYAPI_CURRENCY_NORTH_KOREAN_WON ('KPW')
#define LOBBYAPI_CURRENCY_SOUTH_KOREAN_WON ('KRW')
#define LOBBYAPI_CURRENCY_KUWAITI_DINAR ('KWD')
#define LOBBYAPI_CURRENCY_CAYMAN_ISLANDS_DOLLAR ('KYD')
#define LOBBYAPI_CURRENCY_KAZAKHSTANI_TENGE ('KZT')
#define LOBBYAPI_CURRENCY_LAO_KIP ('LAK')
#define LOBBYAPI_CURRENCY_LEBANESE_POUND ('LBP')
#define LOBBYAPI_CURRENCY_SRI_LANKAN_RUPEE ('LKR')
#define LOBBYAPI_CURRENCY_LIBERIAN_DOLLAR ('LRD')
#define LOBBYAPI_CURRENCY_LESOTHO_LOTI ('LSL')
#define LOBBYAPI_CURRENCY_LITHUANIAN_LITAS ('LTL')
#define LOBBYAPI_CURRENCY_LATVIAN_LATS ('LVL')
#define LOBBYAPI_CURRENCY_LYBIAN_DINAR ('LYD')
#define LOBBYAPI_CURRENCY_MOROCCAN_DIRHAM ('MAD')
#define LOBBYAPI_CURRENCY_MOLDOVAN_LEU ('MDL')
#define LOBBYAPI_CURRENCY_MALAGASY_ARIARY ('MGA')
#define LOBBYAPI_CURRENCY_MACEDONIAN_DENAR ('MKD')
#define LOBBYAPI_CURRENCY_MYANMA_KYAT ('MMK')
#define LOBBYAPI_CURRENCY_MONGOLIAN_TUGRIK ('MNT')
#define LOBBYAPI_CURRENCY_MACANESE_PATACA ('MOP')
#define LOBBYAPI_CURRENCY_MAURITANIAN_OUGUIYA ('MRO')
#define LOBBYAPI_CURRENCY_MAURITIAN_RUPEE ('MUR')
#define LOBBYAPI_CURRENCY_MALDIVIAN_RUFIYAA ('MVR')
#define LOBBYAPI_CURRENCY_MALAWAIAN_KWACHA ('MWK')
#define LOBBYAPI_CURRENCY_MEXICAN_PESO ('MXN')
#define LOBBYAPI_CURRENCY_MEXICAN_UNIDAD_DE_INVERSION ('MXV')
#define LOBBYAPI_CURRENCY_MALAYSIAN_RINGGIT ('MYR')
#define LOBBYAPI_CURRENCY_MOZAMBICAN_METICAL ('MZN')
#define LOBBYAPI_CURRENCY_NAMIBIAN_DOLLAR ('NAD')
#define LOBBYAPI_CURRENCY_NIGERIAN_NAIRA ('NGN')
#define LOBBYAPI_CURRENCY_NICARAGUAN_CORDOBA ('NIO')
#define LOBBYAPI_CURRENCY_NORVEGIAN_KRONE ('NOK')
#define LOBBYAPI_CURRENCY_NEPALESE_RUPEE ('NPR')
#define LOBBYAPI_CURRENCY_NEW_ZEALAND_DOLLAR ('NZD')
#define LOBBYAPI_CURRENCY_OMANI_RIAL ('OMR')
#define LOBBYAPI_CURRENCY_PANAMANIAN_BALBOA ('PAB')
#define LOBBYAPI_CURRENCY_PERUVIAN_NUEVO_SOL ('PEN')
#define LOBBYAPI_CURRENCY_PAPUA_NEW_GUINEAN_KINA ('PGK')
#define LOBBYAPI_CURRENCY_PHILIPPINE_PESO ('PHP')
#define LOBBYAPI_CURRENCY_PAKISTANI_RUPEE ('PKR')
#define LOBBYAPI_CURRENCY_POLISH_ZLOTY ('PLN')
#define LOBBYAPI_CURRENCY_PARAGUAYAN_GUARANI ('PYG')
#define LOBBYAPI_CURRENCY_QATARI_RIAL ('QAR')
#define LOBBYAPI_CURRENCY_ROMANIAN_NEW_LEU ('RON')
#define LOBBYAPI_CURRENCY_SERBIAN_DINAR ('RSD')
#define LOBBYAPI_CURRENCY_RUSSIAN_RUBLE ('RUB')
#define LOBBYAPI_CURRENCY_RWANDAN_FRANC ('RWF')
#define LOBBYAPI_CURRENCY_SAUDI_RIYAL ('SAR')
#define LOBBYAPI_CURRENCY_SOLOMON_ISLANDS_DOLLAR ('SBD')
#define LOBBYAPI_CURRENCY_SEYCHELLES_RUPEE ('SRC')
#define LOBBYAPI_CURRENCY_SUDANESE_POUND ('SDG')
#define LOBBYAPI_CURRENCY_SWEDISH_KRONA ('SEK')
#define LOBBYAPI_CURRENCY_SINGAPORE_DOLLAR ('SGD')
#define LOBBYAPI_CURRENCY_SAINT_HELENA_POUND ('SHP')
#define LOBBYAPI_CURRENCY_SIERRA_LEONEAN_LEONE ('SLL')
#define LOBBYAPI_CURRENCY_SOMALI_SHILLING ('SOS')
#define LOBBYAPI_CURRENCY_SURINAMESE_DOLLAR ('SRD')
#define LOBBYAPI_CURRENCY_SOUTH_SUDANESE_POUND ('SSP')
#define LOBBYAPI_CURRENCY_SAO_TOME_AND_PRINCIPE_DOBRA ('STD')
#define LOBBYAPI_CURRENCY_SYRIAN_POUND ('SYP')
#define LOBBYAPI_CURRENCY_SWAZI_LILANGENI ('SZL')
#define LOBBYAPI_CURRENCY_THAI_BAHT ('THB')
#define LOBBYAPI_CURRENCY_TAJIKISTANI_SOMONI ('TJS')
#define LOBBYAPI_CURRENCY_TURKMENISTANI_MANAT ('TMT')
#define LOBBYAPI_CURRENCY_TUNISIAN_DINAR ('TND')
#define LOBBYAPI_CURRENCY_TONGAN_PAANGA ('TOP')
#define LOBBYAPI_CURRENCY_TURKISH_LIRA ('TRY')
#define LOBBYAPI_CURRENCY_TRINIDAD_AND_TOBAGO_DOLLAR ('TTD')
#define LOBBYAPI_CURRENCY_NEW_TAIWAN_DOLLAR ('TWD')
#define LOBBYAPI_CURRENCY_TANZANIAN_SHILLING ('TZS')
#define LOBBYAPI_CURRENCY_UKRAINIAN_HRYVNIA ('UAH')
#define LOBBYAPI_CURRENCY_UGANDAN_SHILLING ('UGX')
#define LOBBYAPI_CURRENCY_UNITED_STATES_DOLLAR ('USD')
#define LOBBYAPI_CURRENCY_UNITED_STATES_DOLLAR_NEXT_DAY ('USN')
#define LOBBYAPI_CURRENCY_UNITED_STATES_DOLLAR_SAME_DAY ('USS')
#define LOBBYAPI_CURRENCY_URUGUAY_PESO_EN_UNIDADES_INDEXADAS ('UYI')
#define LOBBYAPI_CURRENCY_URUGUAYAN_PESO ('UYU')
#define LOBBYAPI_CURRENCY_UZBEKISTAN_SOM ('UZS')
#define LOBBYAPI_CURRENCY_VENEZUELAN_BOLIVAR_FUERTE ('VEF')
#define LOBBYAPI_CURRENCY_VIETNAMESE_DONG ('VND')
#define LOBBYAPI_CURRENCY_VANUATU_VATU ('VUV')
#define LOBBYAPI_CURRENCY_SAMOAN_TALA ('WST')
#define LOBBYAPI_CURRENCY_CFA_FRANC_BEAC ('XAF')
#define LOBBYAPI_CURRENCY_EAST_CARABBEAN_DOLLAR ('XCD')
#define LOBBYAPI_CURRENCY_CFA_FRANC_BCEAO ('XOF')
#define LOBBYAPI_CURRENCY_CFP_FRANC ('XPF')
#define LOBBYAPI_CURRENCY_YEMENI_RIAL ('YER')
#define LOBBYAPI_CURRENCY_SOUTH_AFRICAN_RAND ('ZAR')
#define LOBBYAPI_CURRENCY_ZAMBIAN_KWACHA ('ZMK')
#define LOBBYAPI_CURRENCY_ZIMBABWE_DOLLAR ('ZWL')
// Default currency
#define LOBBYAPI_CURRENCY_DEFAULT LOBBYAPI_CURRENCY_UNITED_STATES_DOLLAR
#define LOBBYAPI_CURRENCY_DEFAULT_STR "USD"
/*** Macros ***********************************************************************/
//! Write the currency code to a character string
#define LOBBYAPI_CreateCurrencyString(strOutstring, uCurrency) \
{ \
(strOutstring)[0] = (char)(((uCurrency) >> 16 ) & 0xFF); \
(strOutstring)[1] = (char)(((uCurrency) >> 8) & 0xFF); \
(strOutstring)[2] = (char)((uCurrency) & 0xFF); \
(strOutstring)[3]='\0'; \
}
//! toupper replacement
#define LOBBYAPI_LocalizerTokenToUpper(uCharToModify) \
((((unsigned char)(uCharToModify) >= 'a') && ((unsigned char)(uCharToModify) <= 'z')) ? \
(((unsigned char)(uCharToModify)) & (~32)) : \
(uCharToModify))
//! tolower replacement
#define LOBBYAPI_LocalizerTokenToLower(uCharToModify) \
((((unsigned char)(uCharToModify) >= 'A') && ((unsigned char)(uCharToModify) <= 'Z')) ? \
(((unsigned char)(uCharToModify)) | (32)) : \
(uCharToModify))
//! Create a localizer token from shorts representing country and language
#define LOBBYAPI_LocalizerTokenCreate(uLanguage, uCountry) \
(((LOBBYAPI_LocalizerTokenShortToLower(uLanguage)) << 16) + (LOBBYAPI_LocalizerTokenShortToUpper(uCountry)))
//! Create a localizer token from strings containing country and language
#define LOBBYAPI_LocalizerTokenCreateFromStrings(strLanguage, strCountry) \
(LOBBYAPI_LocalizerTokenCreate(LOBBYAPI_LocalizerTokenGetShortFromString(strLanguage),LOBBYAPI_LocalizerTokenGetShortFromString(strCountry)))
//! Create a localizer token from a single string (language + country - ex: "enUS")
#define LOBBYAPI_LocalizerTokenCreateFromString(strLocality) \
(LOBBYAPI_LocalizerTokenCreateFromStrings(&(strLocality)[0], &(strLocality)[2]))
//! Get a int16_t integer from a string
#define LOBBYAPI_LocalizerTokenGetShortFromString(strInstring) (( (((unsigned char*)(strInstring) == NULL) || ((unsigned char*)strInstring)[0] == '\0')) ? \
((uint16_t)(0)) : \
((uint16_t)((((unsigned char*)strInstring)[0] << 8) | ((unsigned char*)strInstring)[1])))
//! Pull the country (int16_t) from a localizer token (int32_t)
#define LOBBYAPI_LocalizerTokenGetCountry(uToken) ((uint16_t)((uToken) & 0xFFFF))
//! Pull the language (int16_t) from a localizer token (int32_t)
#define LOBBYAPI_LocalizerTokenGetLanguage(uToken) ((uint16_t)(((uToken) >> 16) & 0xFFFF))
//! Replace the country in a locality value
#define LOBBYAPI_LocalizerTokenSetCountry(uToken, uCountry) (uToken) = (((uToken) & 0xFFFF0000) | (uCountry));
//! Replace the language in a locality value
#define LOBBYAPI_LocalizerTokenSetLanguage(uToken, uLanguage) (uToken) = (((uToken) & 0x0000FFFF) | ((uLanguage) << 16));
//! Write the country contained in a localizer token to a character string
#define LOBBYAPI_LocalizerTokenCreateCountryString(strOutstring, uToken) \
{ \
(strOutstring)[0] = (char)(((uToken) >> 8) & 0xFF); \
(strOutstring)[1] = (char)((uToken) & 0xFF); \
(strOutstring)[2]='\0'; \
}
//! Write the language contained in a localizer token to a character string
#define LOBBYAPI_LocalizerTokenCreateLanguageString(strOutstring, uToken) \
{ \
(strOutstring)[0]=(char)(((uToken) >> 24) & 0xFF); \
(strOutstring)[1]=(char)(((uToken) >> 16) & 0xFF); \
(strOutstring)[2]='\0'; \
}
//! Write the entire locality string to a character string
#define LOBBYAPI_LocalizerTokenCreateLocalityString(strOutstring, uToken) \
{ \
(strOutstring)[0]=(char)(((uToken) >> 24) & 0xFF); \
(strOutstring)[1]=(char)(((uToken) >> 16) & 0xFF); \
(strOutstring)[2]=(char)(((uToken) >> 8) & 0xFF); \
(strOutstring)[3]=(char)((uToken) & 0xFF); \
(strOutstring)[4]='\0'; \
}
//! Macro to provide an easy way to display the token in character format
#define LOBBYAPI_LocalizerTokenPrintCharArray(uToken) \
(char)(((uToken)>>24)&0xFF), (char)(((uToken)>>16)&0xFF), (char)(((uToken)>>8)&0xFF), (char)((uToken)&0xFF)
//! Provide a way to capitalize the elements in a int16_t
#define LOBBYAPI_LocalizerTokenShortToUpper(uShort) \
((uint16_t)(((LOBBYAPI_LocalizerTokenToUpper(((uShort) >> 8) & 0xFF)) << 8) + \
(LOBBYAPI_LocalizerTokenToUpper((uShort) & 0xFF))))
//! Provide a way to lowercase the elements in a int16_t
#define LOBBYAPI_LocalizerTokenShortToLower(uShort) \
((uint16_t)(((LOBBYAPI_LocalizerTokenToLower(((uShort) >> 8) & 0xFF)) << 8) + \
(LOBBYAPI_LocalizerTokenToLower((uShort) & 0xFF))))
/*** Type Definitions *************************************************************/
/*** Variables ********************************************************************/
/*** Functions ********************************************************************/
//@}
#endif // _dirtylang_h

View File

@ -0,0 +1,44 @@
/*H*************************************************************************************/
/*!
\File dirtysock.h
\Description
Platform independent interface to network layers. Based on
BSD sockets, but with performance modifications. Allows truly
portable modules to be written and moved to different platforms
needing only different support wrappers (no change to actual
network modes).
\Copyright
Copyright (c) Electronic Arts 2001-2014
\Version 1.0 08/01/2001 (gschaefer) First Version
*/
/*************************************************************************************H*/
#ifndef _dirtysock_h
#define _dirtysock_h
/*** Include files *********************************************************************/
#include "DirtySDK/platform.h"
#ifndef DIRTYSOCK
#define DIRTYSOCK (TRUE)
#include "DirtySDK/dirtydefs.h"
#include "DirtySDK/dirtysock/dirtynet.h"
#include "DirtySDK/dirtysock/dirtylib.h"
#endif
/*** Defines ***************************************************************************/
/*** Macros ****************************************************************************/
/*** Type Definitions ******************************************************************/
/*** Variables *************************************************************************/
/*** Functions *************************************************************************/
#endif // _dirtysock_h

View File

@ -0,0 +1,98 @@
/*H********************************************************************************/
/*!
\File dirtyaddr.h
\Description
Definition for portable address type.
\Copyright
Copyright (c) Electronic Arts 2004
\Version 1.0 04/07/2004 (jbrookes) First Version
*/
/********************************************************************************H*/
#ifndef _dirtyaddr_h
#define _dirtyaddr_h
/*!
\Moduledef DirtyAddr DirtyAddr
\Modulemember DirtySock
*/
//@{
/*** Include files ****************************************************************/
#include "DirtySDK/platform.h"
/*** Defines **********************************************************************/
#if defined(DIRTYCODE_XBOXONE) && !defined(DIRTYCODE_GDK)
/* In production, when an xboxone is located behind an OpenWRT based router that has
an IPv6 connection, the router defaults to assigning ULA prefixes via SLAAC and
DHCPv6. This results in the console having a global IPv6 address, a link local
IPv6 address, 2 ULA IPv6 addresses, and an IPv4 address. In such a scenario,
the Secure Device Address of the console is large enough that it cannot fit in a
127-byte DirtyAddrT (size used on other platforms).
After checking with MS, we got a confirmation that the size of a
SecureDevicAddress will never exceed 300 bytes. (enforced both in the
Windows::Networking::XboxLive and the Windows::Xbox::Networking namespaces).
A call to DirtyAddrSetInfoXboxOne() for a 300-byte SecureDeviceAddress blob
results in 370 bytes being written in the DirtyAddrT. Consequently, it is safe
to make the size DIRTYADDR_MACHINEADDR_MAXLEN 372 on xboxone.
*/
#define DIRTYADDR_MACHINEADDR_MAXLEN (372)
#else
#define DIRTYADDR_MACHINEADDR_MAXLEN (127)
#endif
#define DIRTYADDR_MACHINEADDR_MAXSIZE (DIRTYADDR_MACHINEADDR_MAXLEN + 1)
/*** Macros ***********************************************************************/
//! compare two opaque addresses for equality (same=TRUE, different=FALSE)
#define DirtyAddrCompare(_pAddr1, _pAddr2) (!strcmp((_pAddr1)->strMachineAddr, (_pAddr2)->strMachineAddr))
/*** Type Definitions *************************************************************/
//! opaque address type
typedef struct DirtyAddrT
{
char strMachineAddr[DIRTYADDR_MACHINEADDR_MAXSIZE];
} DirtyAddrT;
/*** Variables ********************************************************************/
/*** Functions ********************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
//! convert a DirtyAddrT to native format
DIRTYCODE_API uint32_t DirtyAddrToHostAddr(void *pOutput, int32_t iBufLen, const DirtyAddrT *pAddr);
//! convert a host-format address to native format
DIRTYCODE_API uint32_t DirtyAddrFromHostAddr(DirtyAddrT *pAddr, const void *pInput);
//! get local address in DirtyAddr form
DIRTYCODE_API uint32_t DirtyAddrGetLocalAddr(DirtyAddrT *pAddr);
#if defined(DIRTYCODE_XBOXONE) && !defined(DIRTYCODE_GDK)
//! get Xbox One extended info into dirtyaddr
DIRTYCODE_API uint8_t DirtyAddrGetInfoXboxOne(const DirtyAddrT *pDirtyAddr, void *pXuid, void *pSecureDeviceAddressBlob, int32_t *pBlobSize);
//! set Xbox One extended info into dirtyaddr
DIRTYCODE_API void DirtyAddrSetInfoXboxOne(DirtyAddrT *pDirtyAddr, const void *pXuid, const void *pSecureDeviceAddressBlob, int32_t iBlobSize);
#endif
#ifdef __cplusplus
}
#endif
//@}
#endif // _dirtyaddr_h

View File

@ -0,0 +1,77 @@
/*H********************************************************************************/
/*!
\File dirtycert.h
\Description
This module defines the CA fallback mechanism which is used by ProtoSSL.
\Copyright
Copyright (c) 2012 Electronic Arts Inc.
\Version 01/23/2012 (szhu)
*/
/********************************************************************************H*/
#ifndef _dirtycert_h
#define _dirtycert_h
/*!
\Moduledef NetConnDefs NetConnDefs
\Modulemember DirtySock
*/
//@{
/*** Include files ****************************************************************/
#include "DirtySDK/platform.h"
#include "DirtySDK/proto/protossl.h"
/*** Defines **********************************************************************/
#define DIRTYCERT_SERVICENAME_SIZE (128)
/*** Macros ***********************************************************************/
/*** Type Definitions *************************************************************/
// opaque module state ref
typedef struct DirtyCertRefT DirtyCertRefT;
/*** Variables ********************************************************************/
/*** Functions ********************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
// create dirtycert module
DIRTYCODE_API int32_t DirtyCertCreate(void);
// release resources and destroy module
DIRTYCODE_API int32_t DirtyCertDestroy(void);
// initiate a CA fetch request
DIRTYCODE_API int32_t DirtyCertCARequestCert(const ProtoSSLCertInfoT *pCertInfo, const char *pHost, int32_t iPort);
// initiate a CA prefetch request
DIRTYCODE_API void DirtyCertCAPreloadCerts(const char *pServiceName);
// if a CA fetch request is complete
DIRTYCODE_API int32_t DirtyCertCARequestDone(int32_t iRequestId);
// release resources used by a CA fetch request
DIRTYCODE_API int32_t DirtyCertCARequestFree(int32_t iRequestId);
// control module behavior
DIRTYCODE_API int32_t DirtyCertControl(int32_t iControl, int32_t iValue, int32_t iValue2, void *pValue);
// get module status
DIRTYCODE_API int32_t DirtyCertStatus(int32_t iStatus, void *pBuffer, int32_t iBufSize);
#ifdef __cplusplus
}
#endif
//@}
#endif // _dirtycert_h

View File

@ -0,0 +1,97 @@
/*H********************************************************************************/
/*!
\File dirtyerr.h
\Description
Dirtysock debug error routines.
\Copyright
Copyright (c) 2005 Electronic Arts
\Version 06/13/2005 (jbrookes) First Version
*/
/********************************************************************************H*/
#ifndef _dirtyerr_h
#define _dirtyerr_h
/*!
\Moduledef DirtyErr DirtyErr
\Modulemember DirtySock
*/
//@{
/*** Include files ****************************************************************/
#include "DirtySDK/platform.h"
/*** Defines **********************************************************************/
#define DIRTYSOCK_ERRORNAMES (DIRTYCODE_LOGGING && TRUE)
#define DIRTYSOCK_LISTTERM (0x45454545)
/*** Macros ***********************************************************************/
#if DIRTYSOCK_ERRORNAMES
#define DIRTYSOCK_ErrorName(_iError) { (uint32_t)_iError, #_iError }
#define DIRTYSOCK_ListEnd() { DIRTYSOCK_LISTTERM, "" }
#endif
/*** Type Definitions *************************************************************/
typedef struct DirtyErrT
{
uint32_t uError;
const char *pErrorName;
} DirtyErrT;
#ifdef DIRTYCODE_PS4
typedef void (*DirtySockAppErrorCallback)(int32_t errorCode);
#endif
/*** Variables ********************************************************************/
/*** Functions ********************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
#ifdef DIRTYCODE_PS4
//set Application Error Callback
void DirtyErrAppCallbackSet(DirtySockAppErrorCallback pCallback);
//Inovke App Error Callback if set to report sony error code back to application layer
void DirtyErrAppReport(int32_t iError);
#endif
// take a system-specific error code, and either resolve it to its define name or format it as a hex number
DIRTYCODE_API void DirtyErrName(char *pBuffer, int32_t iBufSize, uint32_t uError);
// same as DirtyErrName, but references the specified list
DIRTYCODE_API void DirtyErrNameList(char *pBuffer, int32_t iBufSize, uint32_t uError, const DirtyErrT *pList);
// same as DirtyErrName, except a pointer is returned
DIRTYCODE_API const char *DirtyErrGetName(uint32_t uError);
// same as DirtyErrGetName, but references the specified list
DIRTYCODE_API const char *DirtyErrGetNameList(uint32_t uError, const DirtyErrT *pList);
// create a unique error code for use accross DirtySDK
DIRTYCODE_API uint32_t DirtyErrGetHResult(uint16_t uFacility, int16_t iCode, uint8_t bFailure);
// break a hresult back into its components
DIRTYCODE_API void DirtyErrDecodeHResult(uint32_t hResult, uint16_t* uFacility, int16_t* iCode, uint8_t* bCustomer, uint8_t* bFailure);
#ifdef __cplusplus
}
#endif
//@}
#endif // _dirtyerr_h

View File

@ -0,0 +1,234 @@
/*H**************************************************************************************/
/*!
\File dirtylib.h
\Description
Provide basic library functions for use by network layer code.
This is needed because the network code is platform/project
independent and needs to rely on a certain set of basic
functions.
\Copyright
Copyright (c) Electronic Arts 2001-2018
\Version 0.5 08/01/01 (GWS) First Version
\Version 1.0 12/31/01 (GWS) Redesigned for Tiburon environment
*/
/**************************************************************************************H*/
#ifndef _dirtylib_h
#define _dirtylib_h
/*!
\Moduledef DirtyLib DirtyLib
\Modulemember DirtySock
*/
//@{
/*** Include files *********************************************************************/
#include "DirtySDK/platform.h"
/*** Defines ***************************************************************************/
// define platform-specific options
#ifndef DIRTYCODE_LOGGING
#if DIRTYCODE_DEBUG
//in debug mode logging is defaulted to on
#define DIRTYCODE_LOGGING (1)
#else
//if its not specified then turn it off
#define DIRTYCODE_LOGGING (0)
#endif
#endif
//! define NetCrit options
#define NETCRIT_OPTION_NONE (0) //!< default settings
#define NETCRIT_OPTION_SINGLETHREADENABLE (1) //!< enable the crit even when in single-threaded mode
// debug printing routines
#if DIRTYCODE_LOGGING
#define NetPrintf(_x) NetPrintfCode _x
#define NetPrintfVerbose(_x) NetPrintfVerboseCode _x
#define NetPrintArray(_pMem, _iSize, _pTitle) NetPrintArrayCode(_pMem, _iSize, _pTitle)
#define NetPrintMem(_pMem, _iSize, _pTitle) NetPrintMemCode(_pMem, _iSize, _pTitle)
#define NetPrintWrap(_pString, _iWrapCol) NetPrintWrapCode(_pString, _iWrapCol)
#define NetTimeStampEnable(_bEnableTimeStamp) NetTimeStampEnableCode(_bEnableTimeStamp)
#else
#define NetPrintf(_x) { }
#define NetPrintfVerbose(_x) { }
#define NetPrintArray(_pMem, _iSize, _pTitle) { }
#define NetPrintMem(_pMem, _iSize, _pTitle) { }
#define NetPrintWrap(_pString, _iWrapCol) { }
#define NetTimeStampEnable(_bEnableTimeStamp) { }
#endif
/*** Macros ****************************************************************************/
/*** Type Definitions ******************************************************************/
typedef struct NetCritPrivT NetCritPrivT;
//! critical section definition
typedef struct NetCritT
{
NetCritPrivT *pData;
} NetCritT;
/*** Variables *************************************************************************/
/*** Functions *************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/*
Portable routines implemented in dirtynet.c
*/
// platform-common create (called internally by NetLibCreate)
DIRTYCODE_API void NetLibCommonInit(void);
// platform-common shutdown (called internally by NetLibDestroy)
DIRTYCODE_API void NetLibCommonShutdown(void);
// reset net idle list
DIRTYCODE_API void NetIdleReset(void);
// remove a function to the idle callback list.
DIRTYCODE_API void NetIdleAdd(void (*proc)(void *ref), void *ref);
// call all the functions in the idle list.
DIRTYCODE_API void NetIdleDel(void (*proc)(void *ref), void *ref);
// make sure all idle calls have completed
DIRTYCODE_API void NetIdleDone(void);
// add a function to the idle callback list
DIRTYCODE_API void NetIdleCall(void);
// return 32-bit hash from given input string
DIRTYCODE_API int32_t NetHash(const char *pString);
// return 32-bit hash from given buffer
DIRTYCODE_API int32_t NetHashBin(const void *pBuffer, uint32_t uLength);
// return 32-bit CRC from given buffer
DIRTYCODE_API int32_t NetCrc32(const uint8_t *pBuffer, int32_t iBufLen, const uint32_t *pCrcTable);
// A simple psuedo-random sequence generator
DIRTYCODE_API uint32_t NetRand(uint32_t uLimit);
// return time
DIRTYCODE_API uint64_t NetTime(void);
// enable logging time stamp
DIRTYCODE_API void NetTimeStampEnableCode(uint8_t bEnableTimeStamp);
// hook into debug output
DIRTYCODE_API void NetPrintfHook(int32_t (*pPrintfDebugHook)(void *pParm, const char *pText), void *pParm);
// diagnostic output routine (do not call directly, use NetPrintf() wrapper
DIRTYCODE_API int32_t NetPrintfCode(const char *fmt, ...);
// diagnostic output routine (do not call directly, use NetPrintf() wrapper
DIRTYCODE_API void NetPrintfVerboseCode(int32_t iVerbosityLevel, int32_t iCheckLevel, const char *pFormat, ...);
// print input buffer with wrapping (do not call directly; use NetPrintWrap() wrapper)
DIRTYCODE_API void NetPrintWrapCode(const char *pData, int32_t iWrapCol);
// print memory as hex (do not call directly; use NetPrintMem() wrapper)
DIRTYCODE_API void NetPrintMemCode(const void *pMem, int32_t iSize, const char *pTitle);
// print memory as a c-style array (do not call directly; use NetPrintArray() wrapper)
DIRTYCODE_API void NetPrintArrayCode(const void *pMem, int32_t iSize, const char *pTitle);
/*
Platform-specific routines implemented in dirtynet<platform>.c
*/
// initialize the network library functions.
DIRTYCODE_API void NetLibCreate(int32_t iThreadPrio, int32_t iThreadStackSize, int32_t iThreadCpuAffinity);
// shutdown the network library.
DIRTYCODE_API void NetLibDestroy(uint32_t uShutdownFlags);
// return an increasing tick count with millisecond scale
DIRTYCODE_API uint32_t NetTick(void);
// return microsecond timer, intended for debug timing purposes only
DIRTYCODE_API uint64_t NetTickUsec(void);
/*
The NetTickDiff() macro implies 2 steps.
The first step consists in substracting 2 unsigned values. When working with unsigned
types, modular arithmetic (aka "wrap around" behavior) is taking place. It is similar
to reading a clock.
Adding clockwise: 9 + 4 = 1 (13 mod 12)
Substracting counterclockwise: 1 - 4 = 9 (-3 mod 12)
Obviously the value range here is [0,0xFFFFFFFF] and not [0,11].
By the virtue of modular arithmetic, the difference between _uNewTime and _uOldTime is
always valid, even in scenarios where one (or both) of the two values has just
"wrapped around".
The second step consists in casting the unsigned result of step 1 into a signed
integer. The result of that second step is the final outcome of the macro, i.e. a
value ranging between
-2147483648 (2's complement notation: 0x80000000) and
2147483647 (2's complement notation: 0x7FFFFFFF)
Consequently, the maximum time difference (positive or negative) that can be calculated
between _uNewTime and _uOldTime is 2147483647 ms, i.e. approximately 596,8 hours (24,9 days).
Any longer period of time captured with an initial call to NetTick() and a final
call to NetTick() and then calculated by feeding both values to NetTickDiff() would
incorrectly result in a time difference much shorter than reality.
If _uNewTime is more recent than _uOldTime (by not more than 596,8 hours), then
the returned time difference will be positive.
If _uOldTime is more recent than _uNewTime (by not more than 596,8 hours), then
the returned time difference will be negative.
*/
// return signed difference between new tick count and old tick count (new - old)
#define NetTickDiff(_uNewTime, _uOldTime) ((signed)((_uNewTime) - (_uOldTime)))
// return localtime
DIRTYCODE_API struct tm *NetLocalTime(struct tm *pTm, uint64_t uElap);
// convert a platform-specific time format to generic time format
DIRTYCODE_API struct tm *NetPlattimeToTime(struct tm *pTm, void *pPlatTime);
// convert a platform-specific time format to generic time format, with milliseconds
DIRTYCODE_API struct tm *NetPlattimeToTimeMs(struct tm *pTm, int32_t *pImSec);
// initialize a critical section for use -- includes name for verbose debugging on some platforms
DIRTYCODE_API int32_t NetCritInit(NetCritT *pCrit, const char *pCritName);
// initialize a critical section with the ability to set options (NETCRIT_OPTION_*)
DIRTYCODE_API int32_t NetCritInit2(NetCritT *pCrit, const char *pCritName, uint32_t uFlags);
// release resources and destroy critical section
DIRTYCODE_API void NetCritKill(NetCritT *pCrit);
// attempt to gain access to critical section
DIRTYCODE_API int32_t NetCritTry(NetCritT *pCrit);
// enter a critical section, blocking if needed
DIRTYCODE_API void NetCritEnter(NetCritT *pCrit);
// leave a critical section
DIRTYCODE_API void NetCritLeave(NetCritT *pCrit);
#ifdef __cplusplus
}
#endif
//@}
#endif // _dirtylib_h

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