From e5d1a8bda7e2f0c6ea40f56469b3f71056b1294f Mon Sep 17 00:00:00 2001
From: otavepto <153766569+otavepto@users.noreply.github.com>
Date: Fri, 3 May 2024 01:29:57 +0300
Subject: [PATCH] separate .h/.cpp files
---
dll/appticket.cpp | 266 ++
dll/auth.cpp | 600 ++-
dll/base.cpp | 15 +-
dll/callsystem.cpp | 406 ++
dll/dll/appticket.h | 290 +-
dll/dll/auth.h | 648 +--
dll/dll/base.h | 402 +-
dll/dll/callsystem.h | 132 +
dll/dll/common_includes.h | 2 +-
dll/dll/dll.h | 5 +
dll/dll/local_storage.h | 22 +-
dll/dll/network.h | 86 +-
dll/dll/settings.h | 123 +-
dll/dll/settings_parser.h | 8 +-
dll/dll/source_query.h | 6 +-
dll/dll/steam_HTMLsurface.h | 395 +-
dll/dll/steam_applist.h | 8 +-
dll/dll/steam_apps.h | 24 +-
dll/dll/steam_client.h | 120 +-
dll/dll/steam_controller.h | 1417 ++----
dll/dll/steam_friends.h | 1640 ++-----
dll/dll/steam_game_coordinator.h | 155 +-
dll/dll/steam_gamesearch.h | 237 +-
dll/dll/steam_gameserver.h | 46 +-
dll/dll/steam_gameserverstats.h | 18 +-
dll/dll/steam_http.h | 23 +-
dll/dll/steam_inventory.h | 1306 ++----
dll/dll/steam_masterserver_updater.h | 248 +-
dll/dll/steam_matchmaking.h | 1831 ++------
dll/dll/steam_matchmaking_servers.h | 91 +-
dll/dll/steam_music.h | 15 +-
dll/dll/steam_musicremote.h | 8 +-
dll/dll/steam_networking.h | 1188 +----
dll/dll/steam_networking_messages.h | 512 +--
dll/dll/steam_networking_sockets.h | 3241 +++++--------
dll/dll/steam_networking_socketsserialized.h | 153 +-
dll/dll/steam_networking_utils.h | 955 +---
dll/dll/steam_parental.h | 8 +-
dll/dll/steam_parties.h | 209 +-
dll/dll/steam_remote_storage.h | 1408 ++----
dll/dll/steam_remoteplay.h | 152 +-
dll/dll/steam_screenshots.h | 23 +-
dll/dll/steam_tv.h | 120 +-
dll/dll/steam_ugc.h | 1737 ++-----
dll/dll/steam_unified_messages.h | 121 +-
dll/dll/steam_user.h | 733 +--
dll/dll/steam_user_stats.h | 24 +-
dll/dll/steam_utils.h | 11 +-
dll/dll/steam_video.h | 8 +-
dll/dll/ugc_remote_storage_bridge.h | 26 +-
dll/settings_parser.cpp | 13 +
dll/source_query.cpp | 124 +-
dll/steam_HTMLsurface.cpp | 363 ++
dll/steam_client.cpp | 23 +-
dll/steam_controller.cpp | 1167 +++++
dll/steam_friends.cpp | 1291 ++++++
dll/steam_game_coordinator.cpp | 146 +
dll/steam_gamesearch.cpp | 215 +
dll/steam_gameserver.cpp | 8 +-
dll/steam_inventory.cpp | 963 ++++
dll/steam_masterserver_updater.cpp | 224 +
dll/steam_matchmaking.cpp | 1624 +++++++
dll/steam_matchmaking_servers.cpp | 414 +-
dll/steam_networking.cpp | 972 ++++
dll/steam_networking_messages.cpp | 419 ++
dll/steam_networking_sockets.cpp | 2098 +++++++++
dll/steam_networking_socketsserialized.cpp | 155 +
dll/steam_networking_utils.cpp | 730 +++
dll/steam_parties.cpp | 195 +
dll/steam_remote_storage.cpp | 1187 +++++
dll/steam_remoteplay.cpp | 142 +
dll/steam_screenshots.cpp | 1 +
dll/steam_tv.cpp | 119 +
dll/steam_ugc.cpp | 1429 ++++++
dll/steam_unified_messages.cpp | 119 +
dll/steam_user.cpp | 528 +++
dll/steam_user_stats.cpp | 4308 +++++++++---------
dll/steam_utils.cpp | 8 +-
dll/ugc_remote_storage_bridge.cpp | 142 +-
overlay_experimental/overlay/steam_overlay.h | 6 +-
overlay_experimental/steam_overlay.cpp | 15 +-
81 files changed, 22736 insertions(+), 17634 deletions(-)
create mode 100644 dll/appticket.cpp
create mode 100644 dll/callsystem.cpp
create mode 100644 dll/dll/callsystem.h
create mode 100644 dll/steam_HTMLsurface.cpp
create mode 100644 dll/steam_controller.cpp
create mode 100644 dll/steam_friends.cpp
create mode 100644 dll/steam_game_coordinator.cpp
create mode 100644 dll/steam_gamesearch.cpp
create mode 100644 dll/steam_inventory.cpp
create mode 100644 dll/steam_masterserver_updater.cpp
create mode 100644 dll/steam_matchmaking.cpp
create mode 100644 dll/steam_networking.cpp
create mode 100644 dll/steam_networking_messages.cpp
create mode 100644 dll/steam_networking_sockets.cpp
create mode 100644 dll/steam_networking_socketsserialized.cpp
create mode 100644 dll/steam_networking_utils.cpp
create mode 100644 dll/steam_parties.cpp
create mode 100644 dll/steam_remote_storage.cpp
create mode 100644 dll/steam_remoteplay.cpp
create mode 100644 dll/steam_tv.cpp
create mode 100644 dll/steam_ugc.cpp
create mode 100644 dll/steam_unified_messages.cpp
create mode 100644 dll/steam_user.cpp
diff --git a/dll/appticket.cpp b/dll/appticket.cpp
new file mode 100644
index 00000000..7f0a45af
--- /dev/null
+++ b/dll/appticket.cpp
@@ -0,0 +1,266 @@
+/* Copyright (C) 2019 Mr Goldberg
+ This file is part of the Goldberg Emulator
+
+ The Goldberg Emulator is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ The Goldberg Emulator is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the Goldberg Emulator; if not, see
+ . */
+
+#include "dll/appticket.h"
+
+
+void AppTicketV1::Reset()
+{
+ TicketSize = 0;
+ TicketVersion = 0;
+ Unk2 = 0;
+ UserData.clear();
+}
+
+std::vector AppTicketV1::Serialize() const
+{
+ std::vector buffer{};
+ uint8_t* pBuffer{};
+
+ buffer.resize(16 + UserData.size());
+ pBuffer = buffer.data();
+ *reinterpret_cast(pBuffer) = TicketSize; pBuffer += 4;
+ *reinterpret_cast(pBuffer) = TicketVersion; pBuffer += 4;
+ *reinterpret_cast(pBuffer) = UserData.size(); pBuffer += 4;
+ *reinterpret_cast(pBuffer) = Unk2; pBuffer += 4;
+ memcpy(pBuffer, UserData.data(), UserData.size());
+
+ return buffer;
+}
+
+bool AppTicketV1::Deserialize(const uint8_t* pBuffer, size_t size)
+{
+ if (size < 16)
+ return false;
+
+ uint32_t user_data_size;
+
+ TicketSize = *reinterpret_cast(pBuffer); pBuffer += 4;
+ TicketVersion = *reinterpret_cast(pBuffer); pBuffer += 4;
+ user_data_size = *reinterpret_cast(pBuffer); pBuffer += 4;
+
+ if (size < (user_data_size + 16))
+ return false;
+
+ Unk2 = *reinterpret_cast(pBuffer); pBuffer += 4;
+ UserData.resize(user_data_size);
+ memcpy(UserData.data(), pBuffer, user_data_size);
+
+ return true;
+}
+
+
+
+void AppTicketV2::Reset()
+{
+ TicketSize = 0;
+ TicketVersion = 0;
+ SteamID = 0;
+ AppID = 0;
+ Unk1 = 0;
+ Unk2 = 0;
+ TicketFlags = 0;
+ TicketIssueTime = 0;
+ TicketValidityEnd = 0;
+}
+
+std::vector AppTicketV2::Serialize() const
+{
+ std::vector buffer{};
+ uint8_t* pBuffer{};
+
+ buffer.resize(40);
+ pBuffer = buffer.data();
+ *reinterpret_cast(pBuffer) = TicketSize; pBuffer += 4;
+ *reinterpret_cast(pBuffer) = TicketVersion; pBuffer += 4;
+ *reinterpret_cast(pBuffer) = SteamID; pBuffer += 8;
+ *reinterpret_cast(pBuffer) = AppID; pBuffer += 4;
+ *reinterpret_cast(pBuffer) = Unk1; pBuffer += 4;
+ *reinterpret_cast(pBuffer) = Unk2; pBuffer += 4;
+ *reinterpret_cast(pBuffer) = TicketFlags; pBuffer += 4;
+ *reinterpret_cast(pBuffer) = TicketIssueTime; pBuffer += 4;
+ *reinterpret_cast(pBuffer) = TicketValidityEnd;
+
+ return buffer;
+}
+
+bool AppTicketV2::Deserialize(const uint8_t* pBuffer, size_t size)
+{
+ if (size < 40)
+ return false;
+
+ TicketSize = *reinterpret_cast(pBuffer); pBuffer += 4;
+ TicketVersion = *reinterpret_cast(pBuffer); pBuffer += 4;
+ SteamID = *reinterpret_cast(pBuffer); pBuffer += 8;
+ AppID = *reinterpret_cast(pBuffer); pBuffer += 4;
+ Unk1 = *reinterpret_cast(pBuffer); pBuffer += 4;
+ Unk2 = *reinterpret_cast(pBuffer); pBuffer += 4;
+ TicketFlags = *reinterpret_cast(pBuffer); pBuffer += 4;
+ TicketIssueTime = *reinterpret_cast(pBuffer); pBuffer += 4;
+ TicketValidityEnd = *reinterpret_cast(pBuffer);
+
+ return true;
+}
+
+
+
+void AppTicketV4::Reset()
+{
+ AppIDs.clear();
+ HasVACStatus = false;
+ HasAppValue = false;
+}
+
+std::vector AppTicketV4::Serialize()
+{
+ std::vector appids = AppIDs;
+ if (appids.size() == 0) {
+ appids.emplace_back(0);
+ }
+
+ uint16_t appid_count = static_cast(appids.size() > 140 ? 140 : appids.size());
+ size_t buffer_size = static_cast(appid_count) * 4ul + 2ul;
+ std::vector buffer{};
+ uint8_t* pBuffer{};
+
+ if (HasAppValue) {// VACStatus + AppValue
+ buffer_size += 4;
+ if (!HasVACStatus) {
+ HasVACStatus = true;
+ VACStatus = 0;
+ }
+ }
+
+ if (HasVACStatus) {// VACStatus only
+ buffer_size += 4;
+ }
+
+ buffer.resize(buffer_size);
+ pBuffer = buffer.data();
+ *reinterpret_cast(pBuffer) = appid_count;
+ pBuffer += 2;
+
+ for (int i = 0; i < appid_count && i < 140; ++i) {
+ *reinterpret_cast(pBuffer) = appids[i];
+ pBuffer += 4;
+ }
+
+ if (HasVACStatus) {
+ *reinterpret_cast(pBuffer) = VACStatus;
+ pBuffer += 4;
+ }
+
+ if (HasAppValue) {
+ *reinterpret_cast(pBuffer) = AppValue;
+ }
+
+ return buffer;
+}
+
+bool AppTicketV4::Deserialize(const uint8_t* pBuffer, size_t size)
+{
+ if (size < 2)
+ return false;
+
+ uint16_t appid_count = *reinterpret_cast(pBuffer);
+ if (size < (appid_count * 4 + 2) || appid_count >= 140)
+ return false;
+
+ AppIDs.resize(appid_count);
+ pBuffer += 2;
+ size -= 2;
+ for (int i = 0; i < appid_count; ++i) {
+ AppIDs[i] = *reinterpret_cast(pBuffer);
+ pBuffer += 4;
+ size -= 4;
+ }
+
+ HasVACStatus = false;
+ HasAppValue = false;
+
+ if (size < 4)
+ return true;
+
+ HasVACStatus = true;
+ VACStatus = *reinterpret_cast(pBuffer);
+ pBuffer += 4;
+ size -= 4;
+
+ if (size < 4)
+ return true;
+
+ HasAppValue = true;
+ AppValue = *reinterpret_cast(pBuffer);
+
+ return true;
+}
+
+
+
+bool DecryptedAppTicket::DeserializeTicket(const uint8_t* pBuffer, size_t buf_size)
+{
+ if (!TicketV1.Deserialize(pBuffer, buf_size))
+ return false;
+
+ pBuffer += 16 + TicketV1.UserData.size();
+ buf_size -= 16 + TicketV1.UserData.size();
+ if (!TicketV2.Deserialize(pBuffer, buf_size))
+ return false;
+
+ if (TicketV2.TicketVersion > 2) {
+ pBuffer += 40;
+ buf_size -= 40;
+ if (!TicketV4.Deserialize(pBuffer, buf_size))
+ return false;
+ }
+
+ return true;
+}
+
+std::vector DecryptedAppTicket::SerializeTicket()
+{
+ std::vector buffer{};
+
+ TicketV1.TicketSize = TicketV1.UserData.size() + 40 + 2 + ((TicketV4.AppIDs.size() == 0 ? 1 : TicketV4.AppIDs.size()) * 4) + (TicketV4.HasVACStatus ? 4 : 0) + (TicketV4.HasAppValue ? 4 : 0);
+ TicketV2.TicketSize = TicketV1.TicketSize - TicketV1.UserData.size();
+
+ buffer = TicketV1.Serialize();
+
+ auto v = TicketV2.Serialize();
+
+ buffer.insert(buffer.end(), v.begin(), v.end());
+ v = TicketV4.Serialize();
+ buffer.insert(buffer.end(), v.begin(), v.end());
+
+ return buffer;
+}
+
+
+
+Steam_AppTicket::Steam_AppTicket(class Settings *settings) :
+ settings(settings)
+{
+
+}
+
+uint32 Steam_AppTicket::GetAppOwnershipTicketData( uint32 nAppID, void *pvBuffer, uint32 cbBufferLength, uint32 *piAppId, uint32 *piSteamId, uint32 *piSignature, uint32 *pcbSignature )
+{
+ PRINT_DEBUG("TODO %u, %p, %u, %p, %p, %p, %p", nAppID, pvBuffer, cbBufferLength, piAppId, piSteamId, piSignature, pcbSignature);
+ std::lock_guard lock(global_mutex);
+
+ return 0;
+}
diff --git a/dll/auth.cpp b/dll/auth.cpp
index 9495198d..03550373 100644
--- a/dll/auth.cpp
+++ b/dll/auth.cpp
@@ -1,5 +1,17 @@
#include "dll/auth.h"
+#define STEAM_ID_OFFSET_TICKET (4 + 8)
+#define STEAM_TICKET_MIN_SIZE (4 + 8 + 8)
+#define STEAM_TICKET_MIN_SIZE_NEW 170
+
+#define STEAM_TICKET_PROCESS_TIME 0.03
+
+//Conan Exiles doesn't work with 512 or 128, 256 seems to be the good size
+// Usually steam send as 1024 (or recommend sending as that)
+//Steam returns 234
+#define STEAM_AUTH_TICKET_SIZE 256 //234
+
+
static inline int generate_random_int() {
int a;
randombytes((char *)&a, sizeof(a));
@@ -24,7 +36,568 @@ static uint32_t get_ticket_count() {
}
-static void steam_auth_manager_ticket_callback(void *object, Common_Message *msg)
+// source: https://github.com/Detanup01/stmsrv/blob/main/Cert/AppTicket.key
+// thanks Detanup01
+const static std::string app_ticket_key =
+ "-----BEGIN PRIVATE KEY-----\n"
+ "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMITHOY6pfsvaGTI\n"
+ "llmilPa1+ev4BsUV0IW3+F/3pQlZ+o57CO1HbepSh2a37cbGUSehOVQ7lREPVXP3\n"
+ "UdyF5tU5IMytJef5N7euM5z2IG9IszeOReO87h2AmtlwGqnRj7qd0MeVxSAuUq7P\n"
+ "C/Ir1VyOg58+wAKxaPL18upylnGJAgMBAAECgYEAnKQQj0KG9VYuTCoaL/6pfPcj\n"
+ "4PEvhaM1yrfSIKMg8YtOT/G+IsWkUZyK7L1HjUhD+FiIjRQKHNrjfdYAnJz20Xom\n"
+ "k6iVt7ugihIne1Q3pGYG8TY9P1DPdN7zEnAVY1Bh2PAlqJWrif3v8v1dUGE/dYr2\n"
+ "U3M0JhvzO7VL1B/chIECQQDqW9G5azGMA/cL4jOg0pbj9GfxjJZeT7M2rBoIaRWP\n"
+ "C3ROndyb+BNahlKk6tbvqillvvMQQiSFGw/PbmCwtLL3AkEA0/79W0q9d3YCXQGW\n"
+ "k3hQvR8HEbxLmRaRF2gU4MOa5C0JqwsmxzdK4mKoJCpVAiu1gmFonLjn2hm8i+vK\n"
+ "b7hffwJAEiMpCACTxRJJfFH1TOz/YIT5xmfq+0GPzRtkqGH5mSh5x9vPxwJb/RWI\n"
+ "L9s85y90JLuyc/+qc+K0Rol0Ujip4QJAGLXVJEn+8ajAt8SSn5fbmV+/fDK9gRef\n"
+ "S+Im5NgH+ubBBL3lBD2Orfqf7K8+f2VG3+6oufPXmpV7Y7fVPdZ40wJALDujJXgi\n"
+ "XiCBSht1YScYjfmJh2/xZWh8/w+vs5ZTtrnW2FQvfvVDG9c1hrChhpvmA0QxdgWB\n"
+ "zSsAno/utcuB9w==\n"
+ "-----END PRIVATE KEY-----\n";
+
+
+static std::vector sign_auth_data(const std::string &private_key_content, const std::vector &data, size_t effective_data_len)
+{
+ std::vector signature{};
+
+ // Hash the data using SHA-1
+ constexpr static int SHA1_DIGEST_LENGTH = 20;
+ uint8_t hash[SHA1_DIGEST_LENGTH]{};
+ int result = mbedtls_sha1(data.data(), effective_data_len, hash);
+ if (result != 0) {
+#ifndef EMU_RELEASE_BUILD
+ // we nedd a live object until the printf does its job, hence this special handling
+ std::string err_msg(256, 0);
+ mbedtls_strerror(result, &err_msg[0], err_msg.size());
+ PRINT_DEBUG("failed to hash the data via SHA1: %s", err_msg.c_str());
+#endif
+
+ return signature;
+ }
+
+ mbedtls_entropy_context entropy_ctx; // entropy context for random number generation
+ mbedtls_entropy_init(&entropy_ctx);
+
+ mbedtls_ctr_drbg_context ctr_drbg_ctx; // CTR-DRBG context for deterministic random number generation
+ mbedtls_ctr_drbg_init(&ctr_drbg_ctx);
+
+ // seed the CTR-DRBG context with random numbers
+ result = mbedtls_ctr_drbg_seed(&ctr_drbg_ctx, mbedtls_entropy_func, &entropy_ctx, nullptr, 0);
+ if (mbedtls_ctr_drbg_seed(&ctr_drbg_ctx, mbedtls_entropy_func, &entropy_ctx, nullptr, 0) != 0) {
+ mbedtls_ctr_drbg_free(&ctr_drbg_ctx);
+ mbedtls_entropy_free(&entropy_ctx);
+
+#ifndef EMU_RELEASE_BUILD
+ // we nedd a live object until the printf does its job, hence this special handling
+ std::string err_msg(256, 0);
+ mbedtls_strerror(result, &err_msg[0], err_msg.size());
+ PRINT_DEBUG("failed to seed the CTR-DRBG context: %s", err_msg.c_str());
+#endif
+
+ return signature;
+ }
+
+ mbedtls_pk_context private_key_ctx; // holds the parsed private key
+ mbedtls_pk_init(&private_key_ctx);
+
+ result = mbedtls_pk_parse_key(
+ &private_key_ctx, // will hold the parsed private key
+ (const unsigned char *)private_key_content.c_str(),
+ private_key_content.size() + 1, // we MUST include the null terminator, otherwise this API returns an error!
+ nullptr, 0, // no password stuff, private key isn't protected
+ mbedtls_ctr_drbg_random, &ctr_drbg_ctx // random number generation function + the CTR-DRBG context it requires as an input
+ );
+
+ if (result != 0) {
+ mbedtls_pk_free(&private_key_ctx);
+ mbedtls_ctr_drbg_free(&ctr_drbg_ctx);
+ mbedtls_entropy_free(&entropy_ctx);
+
+#ifndef EMU_RELEASE_BUILD
+ // we nedd a live object until the printf does its job, hence this special handling
+ std::string err_msg(256, 0);
+ mbedtls_strerror(result, &err_msg[0], err_msg.size());
+ PRINT_DEBUG("failed to parse private key: %s", err_msg.c_str());
+#endif
+
+ return signature;
+ }
+
+ // private key must be valid RSA key
+ if (mbedtls_pk_get_type(&private_key_ctx) != MBEDTLS_PK_RSA || // invalid type
+ mbedtls_pk_can_do(&private_key_ctx, MBEDTLS_PK_RSA) == 0) { // or initialized but not properly setup (maybe freed?)
+ mbedtls_pk_free(&private_key_ctx);
+ mbedtls_ctr_drbg_free(&ctr_drbg_ctx);
+ mbedtls_entropy_free(&entropy_ctx);
+
+ PRINT_DEBUG("parsed key is not a valid RSA private key");
+ return signature;
+ }
+
+ // get the underlying RSA context from the parsed private key
+ mbedtls_rsa_context* rsa_ctx = mbedtls_pk_rsa(private_key_ctx);
+
+ // resize the output buffer to accomodate the size of the private key
+ const size_t private_key_len = mbedtls_pk_get_len(&private_key_ctx);
+ if (private_key_len == 0) { // TODO must be 128 siglen
+ mbedtls_pk_free(&private_key_ctx);
+ mbedtls_ctr_drbg_free(&ctr_drbg_ctx);
+ mbedtls_entropy_free(&entropy_ctx);
+
+ PRINT_DEBUG("failed to get private key (final buffer) length");
+ return signature;
+ }
+
+ PRINT_DEBUG("computed private key (final buffer) length = %zu", private_key_len);
+ signature.resize(private_key_len);
+
+ // finally sign the computed hash using RSA and PKCS#1 padding
+ result = mbedtls_rsa_pkcs1_sign(
+ rsa_ctx,
+ mbedtls_ctr_drbg_random, &ctr_drbg_ctx,
+ MBEDTLS_MD_SHA1, // we used SHA1 to hash the data
+ sizeof(hash), hash,
+ signature.data() // output
+ );
+
+ mbedtls_pk_free(&private_key_ctx);
+ mbedtls_ctr_drbg_free(&ctr_drbg_ctx);
+ mbedtls_entropy_free(&entropy_ctx);
+
+ if (result != 0) {
+ signature.clear();
+
+#ifndef EMU_RELEASE_BUILD
+ // we nedd a live object until the printf does its job, hence this special handling
+ std::string err_msg(256, 0);
+ mbedtls_strerror(result, &err_msg[0], err_msg.size());
+ PRINT_DEBUG("RSA signing failed: %s", err_msg.c_str());
+#endif
+ }
+
+#ifndef EMU_RELEASE_BUILD
+ // we nedd a live object until the printf does its job, hence this special handling
+ auto str = common_helpers::uint8_vector_to_hex_string(signature);
+ PRINT_DEBUG("final signature [%zu bytes]:\n %s", signature.size(), str.c_str());
+#endif
+
+ return signature;
+}
+
+
+
+
+std::vector DLC::Serialize() const
+{
+ PRINT_DEBUG("AppId = %u, Licenses count = %zu", AppId, Licenses.size());
+
+ // we need this variable because we depend on the sizeof, must be 2 bytes
+ const uint16_t dlcs_licenses_count = (uint16_t)Licenses.size();
+ const size_t dlcs_licenses_total_size =
+ Licenses.size() * sizeof(Licenses[0]); // count * element size
+
+ const size_t total_size =
+ sizeof(AppId) +
+ sizeof(dlcs_licenses_count) +
+ dlcs_licenses_total_size;
+
+ std::vector buffer{};
+ buffer.resize(total_size);
+
+ uint8_t* pBuffer = &buffer[0];
+
+#define SER_VAR(v) \
+*reinterpret_cast::type *>(pBuffer) = v; \
+pBuffer += sizeof(v)
+
+ SER_VAR(AppId);
+ SER_VAR(dlcs_licenses_count);
+ for(uint32_t dlc_license : Licenses) {
+ SER_VAR(dlc_license);
+ }
+
+#undef SER_VAR
+
+ PRINT_DEBUG("final size = %zu", buffer.size());
+ return buffer;
+}
+
+std::vector AppTicketGC::Serialize() const
+{
+ const uint64_t steam_id = id.ConvertToUint64();
+
+ // must be 52
+ constexpr size_t total_size =
+ sizeof(STEAM_APPTICKET_GCLen) +
+ sizeof(GCToken) +
+ sizeof(steam_id) +
+ sizeof(ticketGenDate) +
+ sizeof(STEAM_APPTICKET_SESSIONLEN) +
+ sizeof(one) +
+ sizeof(two) +
+ sizeof(ExternalIP) +
+ sizeof(InternalIP) +
+ sizeof(TimeSinceStartup) +
+ sizeof(TicketGeneratedCount);
+
+ // check the size at compile time, we must ensure the correct size
+#ifndef EMU_RELEASE_BUILD
+ static_assert(
+ total_size == 52,
+ "AUTH::AppTicketGC::SER calculated size of serialized data != 52 bytes, your compiler has some incorrect sizes"
+ );
+#endif
+
+ PRINT_DEBUG(
+ "\n"
+ " GCToken: " "%" PRIu64 "\n"
+ " user steam_id: " "%" PRIu64 "\n"
+ " ticketGenDate: %u\n"
+ " ExternalIP: 0x%08X, InternalIP: 0x%08X\n"
+ " TimeSinceStartup: %u, TicketGeneratedCount: %u\n"
+ " SER size = %zu",
+
+ GCToken,
+ steam_id,
+ ticketGenDate,
+ ExternalIP, InternalIP,
+ TimeSinceStartup, TicketGeneratedCount,
+ total_size
+ );
+
+ std::vector buffer{};
+ buffer.resize(total_size);
+
+ uint8_t* pBuffer = &buffer[0];
+
+#define SER_VAR(v) \
+*reinterpret_cast::type *>(pBuffer) = v; \
+pBuffer += sizeof(v)
+
+ SER_VAR(STEAM_APPTICKET_GCLen);
+ SER_VAR(GCToken);
+ SER_VAR(steam_id);
+ SER_VAR(ticketGenDate);
+ SER_VAR(STEAM_APPTICKET_SESSIONLEN);
+ SER_VAR(one);
+ SER_VAR(two);
+ SER_VAR(ExternalIP);
+ SER_VAR(InternalIP);
+ SER_VAR(TimeSinceStartup);
+ SER_VAR(TicketGeneratedCount);
+
+#undef SER_VAR
+
+#ifndef EMU_RELEASE_BUILD
+ // we nedd a live object until the printf does its job, hence this special handling
+ auto str = common_helpers::uint8_vector_to_hex_string(buffer);
+ PRINT_DEBUG("final data [%zu bytes]:\n %s", buffer.size(), str.c_str());
+#endif
+
+ return buffer;
+}
+
+std::vector AppTicket::Serialize() const
+{
+ const uint64_t steam_id = id.ConvertToUint64();
+
+ PRINT_DEBUG(
+ "\n"
+ " Version: %u\n"
+ " user steam_id: " "%" PRIu64 "\n"
+ " AppId: %u\n"
+ " ExternalIP: 0x%08X, InternalIP: 0x%08X\n"
+ " TicketGeneratedDate: %u, TicketGeneratedExpireDate: %u\n"
+ " Licenses count: %zu, DLCs count: %zu",
+
+ Version,
+ steam_id,
+ AppId,
+ ExternalIP, InternalIP,
+ TicketGeneratedDate, TicketGeneratedExpireDate,
+ Licenses.size(), DLCs.size()
+ );
+
+ // we need this variable because we depend on the sizeof, must be 2 bytes
+ const uint16_t licenses_count = (uint16_t)Licenses.size();
+ const size_t licenses_total_size =
+ Licenses.size() * sizeof(Licenses[0]); // total count * element size
+
+ // we need this variable because we depend on the sizeof, must be 2 bytes
+ const uint16_t dlcs_count = (uint16_t)DLCs.size();
+ size_t dlcs_total_size = 0;
+ std::vector> serialized_dlcs{};
+ for (const DLC &dlc : DLCs) {
+ auto dlc_ser = dlc.Serialize();
+ dlcs_total_size += dlc_ser.size();
+ serialized_dlcs.push_back(dlc_ser);
+ }
+
+ //padding
+ constexpr uint16_t padding = (uint16_t)0;
+
+ // must be 42
+ constexpr size_t static_fields_size =
+ sizeof(Version) +
+ sizeof(steam_id) +
+ sizeof(AppId) +
+ sizeof(ExternalIP) +
+ sizeof(InternalIP) +
+ sizeof(AlwaysZero) +
+ sizeof(TicketGeneratedDate) +
+ sizeof(TicketGeneratedExpireDate) +
+
+ sizeof(licenses_count) +
+ sizeof(dlcs_count) +
+
+ sizeof(padding);
+
+ // check the size at compile time, we must ensure the correct size
+#ifndef EMU_RELEASE_BUILD
+ static_assert(
+ static_fields_size == 42,
+ "AUTH::AppTicket::SER calculated size of serialized data != 42 bytes, your compiler has some incorrect sizes"
+ );
+#endif
+
+ const size_t total_size =
+ static_fields_size +
+ licenses_total_size +
+ dlcs_total_size;
+
+ PRINT_DEBUG("final size = %zu", total_size);
+
+ std::vector buffer{};
+ buffer.resize(total_size);
+ uint8_t* pBuffer = &buffer[0];
+
+#define SER_VAR(v) \
+*reinterpret_cast::type *>(pBuffer) = v; \
+pBuffer += sizeof(v)
+
+ SER_VAR(Version);
+ SER_VAR(steam_id);
+ SER_VAR(AppId);
+ SER_VAR(ExternalIP);
+ SER_VAR(InternalIP);
+ SER_VAR(AlwaysZero);
+ SER_VAR(TicketGeneratedDate);
+ SER_VAR(TicketGeneratedExpireDate);
+
+#ifndef EMU_RELEASE_BUILD
+ {
+ // we nedd a live object until the printf does its job, hence this special handling
+ auto str = common_helpers::uint8_vector_to_hex_string(buffer);
+ PRINT_DEBUG("(before licenses + DLCs):\n %s", str.c_str());
+ }
+#endif
+
+ /*
+ * layout of licenses:
+ * ------------------------
+ * 2 bytes: count of licenses
+ * ------------------------
+ * [
+ * ------------------------
+ * | 4 bytes: license element
+ * ------------------------
+ * ]
+ */
+ SER_VAR(licenses_count);
+ for(uint32_t license : Licenses) {
+ SER_VAR(license);
+ }
+
+ /*
+ * layout of DLCs:
+ * ------------------------
+ * | 2 bytes: count of DLCs
+ * ------------------------
+ * [
+ * ------------------------
+ * | 4 bytes: app id
+ * ------------------------
+ * | 2 bytes: DLC licenses count
+ * ------------------------
+ * [
+ * 4 bytes: DLC license element
+ * ]
+ * ]
+ */
+ SER_VAR(dlcs_count);
+ for (const auto &dlc_ser : serialized_dlcs){
+ memcpy(pBuffer, dlc_ser.data(), dlc_ser.size());
+ pBuffer += dlc_ser.size();
+ }
+
+ //padding
+ SER_VAR(padding);
+
+#undef SER_VAR
+
+#ifndef EMU_RELEASE_BUILD
+ {
+ // we nedd a live object until the printf does its job, hence this special handling
+ auto str = common_helpers::uint8_vector_to_hex_string(buffer);
+ PRINT_DEBUG("final data [%zu bytes]:\n %s", buffer.size(), str.c_str());
+ }
+#endif
+
+ return buffer;
+}
+
+std::vector Auth_Data::Serialize() const
+{
+ /*
+ * layout of Auth_Data with GC:
+ * ------------------------
+ * X bytes: GC data blob (currently 52 bytes)
+ * ------------------------
+ * 4 bytes: remaining Auth_Data blob size (4 + Y + Z)
+ * ------------------------
+ * 4 bytes: size of ticket data layout (not blob!, hence blob + 4)
+ * ------------------------
+ * Y bytes: ticket data blob
+ * ------------------------
+ * Z bytes: App Ticket signature
+ * ------------------------
+ *
+ * total layout length = X + 4 + 4 + Y + Z
+ */
+
+ /*
+ * layout of Auth_Data without GC:
+ * ------------------------
+ * 4 bytes: size of ticket data layout (not blob!, hence blob + 4)
+ * ------------------------
+ * Y bytes: ticket data blob
+ * ------------------------
+ * Z bytes: App Ticket signature
+ * ------------------------
+ *
+ * total layout length = 4 + Y + Z
+ */
+ const uint64_t steam_id = id.ConvertToUint64();
+
+ PRINT_DEBUG(
+ "\n"
+ " HasGC: %u\n"
+ " user steam_id: " "%" PRIu64 "\n"
+ " number: " "%" PRIu64 ,
+
+ (int)HasGC,
+ steam_id,
+ number
+ );
+
+ /*
+ * layout of ticket data:
+ * ------------------------
+ * 4 bytes: size of ticket data layout (not blob!, hence blob + 4)
+ * ------------------------
+ * Y bytes: ticket data blob
+ * ------------------------
+ *
+ * total layout length = 4 + Y
+ */
+ std::vector tickedData = Ticket.Serialize();
+ // we need this variable because we depend on the sizeof, must be 4 bytes
+ const uint32_t ticket_data_layout_length =
+ sizeof(uint32_t) + // size of this uint32_t because it is included!
+ (uint32_t)tickedData.size();
+
+ size_t total_size_without_siglen = ticket_data_layout_length;
+
+ std::vector GCData{};
+ size_t gc_data_layout_length = 0;
+ if (HasGC) {
+ /*
+ * layout of GC data:
+ * ------------------------
+ * X bytes: GC data blob (currently 52 bytes)
+ * ------------------------
+ * 4 bytes: remaining Auth_Data blob size
+ * ------------------------
+ *
+ * total layout length = X + 4
+ */
+ GCData = GC.Serialize();
+ gc_data_layout_length +=
+ GCData.size() +
+ sizeof(uint32_t);
+
+ total_size_without_siglen += gc_data_layout_length;
+ }
+
+ const size_t final_buffer_size = total_size_without_siglen + STEAM_APPTICKET_SIGLEN;
+ PRINT_DEBUG("size without sig len = %zu, size with sig len (final size) = %zu",
+ total_size_without_siglen,
+ final_buffer_size
+ );
+
+ std::vector buffer;
+ buffer.resize(final_buffer_size);
+
+ uint8_t* pBuffer = &buffer[0];
+
+#define SER_VAR(v) \
+*reinterpret_cast::type *>(pBuffer) = v; \
+pBuffer += sizeof(v)
+
+ // serialize the GC data first
+ if (HasGC) {
+ memcpy(pBuffer, GCData.data(), GCData.size());
+ pBuffer += GCData.size();
+
+ // when GC data is written (HasGC),
+ // the next 4 bytes after the GCData will be the length of the remaining data in the final buffer
+ // i.e. final buffer size - length of GCData layout
+ // i.e. ticket data length + STEAM_APPTICKET_SIGLEN
+ //
+ // notice that we subtract the entire layout length, not just GCData.size(),
+ // otherwise these next 4 bytes will include themselves!
+ uint32_t remaining_length = (uint32_t)(final_buffer_size - gc_data_layout_length);
+ SER_VAR(remaining_length);
+ }
+
+ // serialize the ticket data
+ SER_VAR(ticket_data_layout_length);
+ memcpy(pBuffer, tickedData.data(), tickedData.size());
+
+#ifndef EMU_RELEASE_BUILD
+ {
+ // we nedd a live object until the printf does its job, hence this special handling
+ auto str = common_helpers::uint8_vector_to_hex_string(buffer);
+ PRINT_DEBUG("final data (before signature) [%zu bytes]:\n %s", buffer.size(), str.c_str());
+ }
+#endif
+
+ //Todo make a signature
+ std::vector signature = sign_auth_data(app_ticket_key, tickedData, total_size_without_siglen);
+ if (signature.size() == STEAM_APPTICKET_SIGLEN) {
+ memcpy(buffer.data() + total_size_without_siglen, signature.data(), signature.size());
+
+#ifndef EMU_RELEASE_BUILD
+ {
+ // we nedd a live object until the printf does its job, hence this special handling
+ auto str = common_helpers::uint8_vector_to_hex_string(buffer);
+ PRINT_DEBUG("final data (after signature) [%zu bytes]:\n %s", buffer.size(), str.c_str());
+ }
+#endif
+
+ } else {
+ PRINT_DEBUG("signature size [%zu] is invalid", signature.size());
+ }
+
+#undef SER_VAR
+
+ return buffer;
+}
+
+
+
+void Auth_Manager::ticket_callback(void *object, Common_Message *msg)
{
// PRINT_DEBUG_ENTRY();
@@ -32,22 +605,22 @@ static void steam_auth_manager_ticket_callback(void *object, Common_Message *msg
auth_manager->Callback(msg);
}
-Auth_Manager::Auth_Manager(class Settings *settings, class Networking *network, class SteamCallBacks *callbacks) {
+Auth_Manager::Auth_Manager(class Settings *settings, class Networking *network, class SteamCallBacks *callbacks)
+{
this->network = network;
this->settings = settings;
this->callbacks = callbacks;
- this->network->setCallback(CALLBACK_ID_AUTH_TICKET, settings->get_local_steam_id(), &steam_auth_manager_ticket_callback, this);
- this->network->setCallback(CALLBACK_ID_USER_STATUS, settings->get_local_steam_id(), &steam_auth_manager_ticket_callback, this);
+ this->network->setCallback(CALLBACK_ID_AUTH_TICKET, settings->get_local_steam_id(), &Auth_Manager::ticket_callback, this);
+ this->network->setCallback(CALLBACK_ID_USER_STATUS, settings->get_local_steam_id(), &Auth_Manager::ticket_callback, this);
}
Auth_Manager::~Auth_Manager()
{
- this->network->rmCallback(CALLBACK_ID_AUTH_TICKET, settings->get_local_steam_id(), &steam_auth_manager_ticket_callback, this);
- this->network->rmCallback(CALLBACK_ID_USER_STATUS, settings->get_local_steam_id(), &steam_auth_manager_ticket_callback, this);
+ this->network->rmCallback(CALLBACK_ID_AUTH_TICKET, settings->get_local_steam_id(), &Auth_Manager::ticket_callback, this);
+ this->network->rmCallback(CALLBACK_ID_USER_STATUS, settings->get_local_steam_id(), &Auth_Manager::ticket_callback, this);
}
-#define STEAM_TICKET_PROCESS_TIME 0.03
void Auth_Manager::launch_callback(CSteamID id, EAuthSessionResponse resp, double delay)
{
@@ -72,10 +645,6 @@ void Auth_Manager::launch_callback_gs(CSteamID id, bool approved)
}
}
-#define STEAM_ID_OFFSET_TICKET (4 + 8)
-#define STEAM_TICKET_MIN_SIZE (4 + 8 + 8)
-#define STEAM_TICKET_MIN_SIZE_NEW 170
-
Auth_Data Auth_Manager::getTicketData( void *pTicket, int cbMaxTicket, uint32 *pcbTicket )
{
@@ -153,11 +722,6 @@ Auth_Data Auth_Manager::getTicketData( void *pTicket, int cbMaxTicket, uint32 *p
return ticket_data;
}
-//Conan Exiles doesn't work with 512 or 128, 256 seems to be the good size
-// Usually steam send as 1024 (or recommend sending as that)
-//Steam returns 234
-#define STEAM_AUTH_TICKET_SIZE 256 //234
-
HAuthTicket Auth_Manager::getTicket( void *pTicket, int cbMaxTicket, uint32 *pcbTicket )
{
if (settings->enable_new_app_ticket)
@@ -301,6 +865,8 @@ bool Auth_Manager::endAuth(CSteamID id)
return erased;
}
+
+
void Auth_Manager::Callback(Common_Message *msg)
{
if (msg->has_low_level()) {
@@ -338,4 +904,4 @@ void Auth_Manager::Callback(Common_Message *msg)
}
}
}
-}
\ No newline at end of file
+}
diff --git a/dll/base.cpp b/dll/base.cpp
index 2e84c438..589842e1 100644
--- a/dll/base.cpp
+++ b/dll/base.cpp
@@ -17,6 +17,12 @@
#include "dll/base.h"
+std::recursive_mutex global_mutex{};
+// some arbitrary counter/time for reference
+const std::chrono::time_point startup_counter = std::chrono::high_resolution_clock::now();
+const std::chrono::time_point startup_time = std::chrono::system_clock::now();
+
+
#ifdef __WINDOWS__
void randombytes(char *buf, size_t size)
@@ -93,11 +99,6 @@ bool set_env_variable(const std::string &name, const std::string &value)
#endif
-std::recursive_mutex global_mutex{};
-
-// some arbitrary counter/time for reference
-const std::chrono::time_point startup_counter = std::chrono::high_resolution_clock::now();
-const std::chrono::time_point startup_time = std::chrono::system_clock::now();
#ifndef EMU_RELEASE_BUILD
const std::string dbg_log_file = get_full_program_path() + "STEAM_LOG.txt";
@@ -147,10 +148,6 @@ CSteamID generate_steam_id_lobby()
return CSteamID(generate_account_id(), k_EChatInstanceFlagLobby | k_EChatInstanceFlagMMSLobby, k_EUniversePublic, k_EAccountTypeChat);
}
-/// @brief Check for a timeout given some initial timepoint and a timeout in sec.
-/// @param old The initial timepoint which will be compared against current time
-/// @param timeout The max allowed time in seconds
-/// @return true if the timepoint has exceeded the max allowed timeout, false otherwise
bool check_timedout(std::chrono::high_resolution_clock::time_point old, double timeout)
{
if (timeout == 0.0) return true;
diff --git a/dll/callsystem.cpp b/dll/callsystem.cpp
new file mode 100644
index 00000000..c52bf560
--- /dev/null
+++ b/dll/callsystem.cpp
@@ -0,0 +1,406 @@
+/* Copyright (C) 2019 Mr Goldberg
+ This file is part of the Goldberg Emulator
+
+ The Goldberg Emulator is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ The Goldberg Emulator is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the Goldberg Emulator; if not, see
+ . */
+
+#include "dll/callsystem.h"
+
+
+void CCallbackMgr::SetRegister(class CCallbackBase *pCallback, int iCallback)
+{
+ pCallback->m_nCallbackFlags |= CCallbackBase::k_ECallbackFlagsRegistered;
+ pCallback->m_iCallback = iCallback;
+};
+
+void CCallbackMgr::SetUnregister(class CCallbackBase *pCallback)
+{
+ if (pCallback)
+ pCallback->m_nCallbackFlags &= !CCallbackBase::k_ECallbackFlagsRegistered;
+};
+
+bool CCallbackMgr::isServer(class CCallbackBase *pCallback)
+{
+ return (pCallback->m_nCallbackFlags & CCallbackBase::k_ECallbackFlagsGameServer) != 0;
+};
+
+
+
+Steam_Call_Result::Steam_Call_Result(SteamAPICall_t a, int icb, void *r, unsigned int s, double r_in, bool run_cc_cb)
+{
+ api_call = a;
+ result.resize(s);
+ if (s > 0 && r != NULL) {
+ memcpy(&(result[0]), r, s);
+ }
+ run_in = r_in;
+ run_call_completed_cb = run_cc_cb;
+ iCallback = icb;
+ created = std::chrono::high_resolution_clock::now();
+}
+
+bool Steam_Call_Result::operator==(const struct Steam_Call_Result& other) const
+{
+ return other.api_call == api_call && other.callbacks == callbacks;
+}
+
+bool Steam_Call_Result::timed_out() const
+{
+ return check_timedout(created, STEAM_CALLRESULT_TIMEOUT);
+}
+
+bool Steam_Call_Result::call_completed() const
+{
+ return (!reserved) && check_timedout(created, run_in);
+}
+
+bool Steam_Call_Result::can_execute() const
+{
+ return (!to_delete) && call_completed() && (has_cb() || check_timedout(created, STEAM_CALLRESULT_WAIT_FOR_CB));
+}
+
+bool Steam_Call_Result::has_cb() const
+{
+ return callbacks.size() > 0;
+}
+
+
+
+void SteamCallResults::addCallCompleted(class CCallbackBase *cb)
+{
+ if (std::find(completed_callbacks.begin(), completed_callbacks.end(), cb) == completed_callbacks.end()) {
+ completed_callbacks.push_back(cb);
+ }
+}
+
+void SteamCallResults::rmCallCompleted(class CCallbackBase *cb)
+{
+ auto c = std::find(completed_callbacks.begin(), completed_callbacks.end(), cb);
+ if (c != completed_callbacks.end()) {
+ completed_callbacks.erase(c);
+ }
+}
+
+void SteamCallResults::addCallBack(SteamAPICall_t api_call, class CCallbackBase *cb)
+{
+ auto cb_result = std::find_if(callresults.begin(), callresults.end(), [api_call](struct Steam_Call_Result const& item) { return item.api_call == api_call; });
+ if (cb_result != callresults.end()) {
+ cb_result->callbacks.push_back(cb);
+ CCallbackMgr::SetRegister(cb, cb->GetICallback());
+ }
+}
+
+bool SteamCallResults::exists(SteamAPICall_t api_call) const
+{
+ auto cr = std::find_if(callresults.begin(), callresults.end(), [api_call](struct Steam_Call_Result const& item) {
+ return item.api_call == api_call;
+ });
+ if (callresults.end() == cr) return false;
+ if (!cr->call_completed()) return false;
+ return true;
+}
+
+bool SteamCallResults::callback_result(SteamAPICall_t api_call, void *copy_to, unsigned int size)
+{
+ auto cb_result = std::find_if(callresults.begin(), callresults.end(), [api_call](struct Steam_Call_Result const& item) {
+ return item.api_call == api_call;
+ });
+ if (cb_result != callresults.end()) {
+ if (!cb_result->call_completed()) return false;
+ if (cb_result->result.size() > size) return false;
+
+ memcpy(copy_to, &(cb_result->result[0]), cb_result->result.size());
+ cb_result->to_delete = true;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void SteamCallResults::rmCallBack(SteamAPICall_t api_call, class CCallbackBase *cb)
+{
+ auto cb_result = std::find_if(callresults.begin(), callresults.end(), [api_call](struct Steam_Call_Result const& item) { return item.api_call == api_call; });
+ if (cb_result != callresults.end()) {
+ auto it = std::find(cb_result->callbacks.begin(), cb_result->callbacks.end(), cb);
+ if (it != cb_result->callbacks.end()) {
+ cb_result->callbacks.erase(it);
+ CCallbackMgr::SetUnregister(cb);
+ }
+ }
+}
+
+void SteamCallResults::rmCallBack(class CCallbackBase *cb)
+{
+ //TODO: check if callback is callback or call result?
+ for (auto & cr: callresults) {
+ auto it = std::find(cr.callbacks.begin(), cr.callbacks.end(), cb);
+ if (it != cr.callbacks.end()) {
+ cr.callbacks.erase(it);
+ }
+
+ if (cr.callbacks.size() == 0) {
+ cr.to_delete = true;
+ }
+ }
+}
+
+SteamAPICall_t SteamCallResults::addCallResult(SteamAPICall_t api_call, int iCallback, void *result, unsigned int size, double timeout, bool run_call_completed_cb)
+{
+ PRINT_DEBUG("%i", iCallback);
+ auto cb_result = std::find_if(callresults.begin(), callresults.end(), [api_call](struct Steam_Call_Result const& item) { return item.api_call == api_call; });
+ if (cb_result != callresults.end()) {
+ if (cb_result->reserved) {
+ std::chrono::high_resolution_clock::time_point created = cb_result->created;
+ std::vector temp_cbs = cb_result->callbacks;
+ *cb_result = Steam_Call_Result(api_call, iCallback, result, size, timeout, run_call_completed_cb);
+ cb_result->callbacks = temp_cbs;
+ cb_result->created = created;
+ return cb_result->api_call;
+ }
+ } else {
+ struct Steam_Call_Result res = Steam_Call_Result(api_call, iCallback, result, size, timeout, run_call_completed_cb);
+ callresults.push_back(res);
+ return callresults.back().api_call;
+ }
+
+ PRINT_DEBUG("ERROR");
+ return k_uAPICallInvalid;
+}
+
+SteamAPICall_t SteamCallResults::reserveCallResult()
+{
+ struct Steam_Call_Result res = Steam_Call_Result(generate_steam_api_call_id(), 0, NULL, 0, 0.0, true);
+ res.reserved = true;
+ callresults.push_back(res);
+ return callresults.back().api_call;
+}
+
+SteamAPICall_t SteamCallResults::addCallResult(int iCallback, void *result, unsigned int size, double timeout, bool run_call_completed_cb)
+{
+ return addCallResult(generate_steam_api_call_id(), iCallback, result, size, timeout, run_call_completed_cb);
+}
+
+void SteamCallResults::setCbAll(void (*cb_all)(std::vector result, int callback))
+{
+ this->cb_all = cb_all;
+}
+
+void SteamCallResults::runCallResults()
+{
+ unsigned long current_size = callresults.size();
+ for (unsigned i = 0; i < current_size; ++i) {
+ unsigned index = i;
+
+ if (!callresults[index].to_delete) {
+ if (callresults[index].can_execute()) {
+ std::vector result = callresults[index].result;
+ SteamAPICall_t api_call = callresults[index].api_call;
+ bool run_call_completed_cb = callresults[index].run_call_completed_cb;
+ int iCallback = callresults[index].iCallback;
+ if (run_call_completed_cb) {
+ callresults[index].run_call_completed_cb = false;
+ }
+
+ callresults[index].to_delete = true;
+ if (callresults[index].has_cb()) {
+ std::vector temp_cbs = callresults[index].callbacks;
+ for (auto & cb : temp_cbs) {
+ PRINT_DEBUG("Calling callresult %p %i", cb, cb->GetICallback());
+ global_mutex.unlock();
+ //TODO: unlock relock doesn't work if mutex was locked more than once.
+ if (run_call_completed_cb) { //run the right function depending on if it's a callback or a call result.
+ cb->Run(&(result[0]), false, api_call);
+ } else {
+ cb->Run(&(result[0]));
+ }
+ //COULD BE DELETED SO DON'T TOUCH CB
+ global_mutex.lock();
+ PRINT_DEBUG("callresult done");
+ }
+ }
+
+ if (run_call_completed_cb) {
+ //can it happen that one is removed during the callback?
+ std::vector callbacks = completed_callbacks;
+ SteamAPICallCompleted_t data{};
+ data.m_hAsyncCall = api_call;
+ data.m_iCallback = iCallback;
+ data.m_cubParam = result.size();
+
+ for (auto & cb: callbacks) {
+ PRINT_DEBUG("Call complete cb %i %p %llu", iCallback, cb, api_call);
+ //TODO: check if this is a problem or not.
+ SteamAPICallCompleted_t temp = data;
+ global_mutex.unlock();
+ cb->Run(&temp);
+ global_mutex.lock();
+ }
+
+ if (cb_all) {
+ std::vector res;
+ res.resize(sizeof(data));
+ memcpy(&(res[0]), &data, sizeof(data));
+ cb_all(res, data.k_iCallback);
+ }
+ } else {
+ if (cb_all) {
+ cb_all(result, iCallback);
+ }
+ }
+ } else {
+ if (callresults[index].timed_out()) {
+ callresults[index].to_delete = true;
+ }
+ }
+ }
+ }
+
+ PRINT_DEBUG("erase to_delete");
+ auto c = std::begin(callresults);
+ while (c != std::end(callresults)) {
+ if (c->to_delete) {
+ if (c->timed_out()) {
+ PRINT_DEBUG("removed callresult %i", c->iCallback);
+ c = callresults.erase(c);
+ } else {
+ ++c;
+ }
+ } else {
+ ++c;
+ }
+ }
+}
+
+
+
+SteamCallBacks::SteamCallBacks(SteamCallResults *results)
+{
+ this->results = results;
+}
+
+void SteamCallBacks::addCallBack(int iCallback, class CCallbackBase *cb)
+{
+ PRINT_DEBUG("%i", iCallback);
+ if (iCallback == SteamAPICallCompleted_t::k_iCallback) {
+ results->addCallCompleted(cb);
+ CCallbackMgr::SetRegister(cb, iCallback);
+ return;
+ }
+
+ if (std::find(callbacks[iCallback].callbacks.begin(), callbacks[iCallback].callbacks.end(), cb) == callbacks[iCallback].callbacks.end()) {
+ callbacks[iCallback].callbacks.push_back(cb);
+ CCallbackMgr::SetRegister(cb, iCallback);
+ for (auto & res: callbacks[iCallback].results) {
+ //TODO: timeout?
+ SteamAPICall_t api_id = results->addCallResult(iCallback, &(res[0]), res.size(), 0.0, false);
+ results->addCallBack(api_id, cb);
+ }
+ }
+}
+
+void SteamCallBacks::addCBResult(int iCallback, void *result, unsigned int size, double timeout, bool dont_post_if_already)
+{
+ if (dont_post_if_already) {
+ for (auto & r : callbacks[iCallback].results) {
+ if (r.size() == size) {
+ if (memcmp(&(r[0]), result, size) == 0) {
+ //cb already posted
+ return;
+ }
+ }
+ }
+ }
+
+ std::vector temp{};
+ temp.resize(size);
+ memcpy(&(temp[0]), result, size);
+ callbacks[iCallback].results.push_back(temp);
+ for (auto cb: callbacks[iCallback].callbacks) {
+ SteamAPICall_t api_id = results->addCallResult(iCallback, result, size, timeout, false);
+ results->addCallBack(api_id, cb);
+ }
+
+ if (callbacks[iCallback].callbacks.empty()) {
+ results->addCallResult(iCallback, result, size, timeout, false);
+ }
+}
+
+void SteamCallBacks::addCBResult(int iCallback, void *result, unsigned int size)
+{
+ addCBResult(iCallback, result, size, DEFAULT_CB_TIMEOUT, false);
+}
+
+void SteamCallBacks::addCBResult(int iCallback, void *result, unsigned int size, bool dont_post_if_already)
+{
+ addCBResult(iCallback, result, size, DEFAULT_CB_TIMEOUT, dont_post_if_already);
+}
+
+void SteamCallBacks::addCBResult(int iCallback, void *result, unsigned int size, double timeout)
+{
+ addCBResult(iCallback, result, size, timeout, false);
+}
+
+void SteamCallBacks::rmCallBack(int iCallback, class CCallbackBase *cb)
+{
+ if (iCallback == SteamAPICallCompleted_t::k_iCallback) {
+ results->rmCallCompleted(cb);
+ CCallbackMgr::SetUnregister(cb);
+ return;
+ }
+
+ auto c = std::find(callbacks[iCallback].callbacks.begin(), callbacks[iCallback].callbacks.end(), cb);
+ if (c != callbacks[iCallback].callbacks.end()) {
+ callbacks[iCallback].callbacks.erase(c);
+ CCallbackMgr::SetUnregister(cb);
+ results->rmCallBack(cb);
+ }
+}
+
+void SteamCallBacks::runCallBacks()
+{
+ for (auto & c : callbacks) {
+ c.second.results.clear();
+ }
+}
+
+
+
+void RunEveryRunCB::add(void (*cb)(void *object), void *object)
+{
+ remove(cb, object);
+ RunCBs rcb;
+ rcb.function = cb;
+ rcb.object = object;
+ cbs.push_back(rcb);
+}
+
+void RunEveryRunCB::remove(void (*cb)(void *object), void *object)
+{
+ auto c = std::begin(cbs);
+ while (c != std::end(cbs)) {
+ if (c->function == cb && c->object == object) {
+ c = cbs.erase(c);
+ } else {
+ ++c;
+ }
+ }
+}
+
+void RunEveryRunCB::run() const
+{
+ std::vector temp_cbs = cbs;
+ for (auto c : temp_cbs) {
+ c.function(c.object);
+ }
+}
diff --git a/dll/dll/appticket.h b/dll/dll/appticket.h
index 6694a750..479f9508 100644
--- a/dll/dll/appticket.h
+++ b/dll/dll/appticket.h
@@ -24,55 +24,16 @@
struct AppTicketV1
{
// Total ticket size - 16
- uint32_t TicketSize;
- uint32_t TicketVersion;
- uint32_t Unk2;
- std::vector UserData;
+ uint32_t TicketSize{};
+ uint32_t TicketVersion{};
+ uint32_t Unk2{};
+ std::vector UserData{};
- void Reset()
- {
- TicketSize = 0;
- TicketVersion = 0;
- Unk2 = 0;
- UserData.clear();
- }
+ void Reset();
- std::vector Serialize()
- {
- std::vector buffer;
- uint8_t* pBuffer;
+ std::vector Serialize() const;
- buffer.resize(16 + UserData.size());
- pBuffer = buffer.data();
- *reinterpret_cast(pBuffer) = TicketSize; pBuffer += 4;
- *reinterpret_cast(pBuffer) = TicketVersion; pBuffer += 4;
- *reinterpret_cast(pBuffer) = UserData.size(); pBuffer += 4;
- *reinterpret_cast(pBuffer) = Unk2; pBuffer += 4;
- memcpy(pBuffer, UserData.data(), UserData.size());
-
- return buffer;
- }
-
- bool Deserialize(const uint8_t* pBuffer, size_t size)
- {
- if (size < 16)
- return false;
-
- uint32_t user_data_size;
-
- TicketSize = *reinterpret_cast(pBuffer); pBuffer += 4;
- TicketVersion = *reinterpret_cast(pBuffer); pBuffer += 4;
- user_data_size = *reinterpret_cast(pBuffer); pBuffer += 4;
-
- if (size < (user_data_size + 16))
- return false;
-
- Unk2 = *reinterpret_cast(pBuffer); pBuffer += 4;
- UserData.resize(user_data_size);
- memcpy(UserData.data(), pBuffer, user_data_size);
-
- return true;
- }
+ bool Deserialize(const uint8_t* pBuffer, size_t size);
//inline uint32_t TicketSize() { return *reinterpret_cast(_Buffer); }
//inline uint32_t TicketVersion(){ return *reinterpret_cast(reinterpret_cast(_Buffer) + 4); }
@@ -84,69 +45,24 @@ struct AppTicketV1
struct AppTicketV2
{
// Totals ticket size - 16 - TicketV1::UserData.size()
- uint32_t TicketSize;
- uint32_t TicketVersion;
- uint64_t SteamID;
- uint32_t AppID;
- uint32_t Unk1;
- uint32_t Unk2;
- uint32_t TicketFlags;
- uint32_t TicketIssueTime;
- uint32_t TicketValidityEnd;
+ uint32_t TicketSize{};
+ uint32_t TicketVersion{};
+ uint64_t SteamID{};
+ uint32_t AppID{};
+ uint32_t Unk1{};
+ uint32_t Unk2{};
+ uint32_t TicketFlags{};
+ uint32_t TicketIssueTime{};
+ uint32_t TicketValidityEnd{};
- static constexpr uint32_t LicenseBorrowed = 0x00000002; // Bit 1: IsLicenseBorrowed
- static constexpr uint32_t LicenseTemporary = 0x00000004; // Bit 2: IsLicenseTemporary
+ static constexpr const uint32_t LicenseBorrowed = 0x00000002; // Bit 1: IsLicenseBorrowed
+ static constexpr const uint32_t LicenseTemporary = 0x00000004; // Bit 2: IsLicenseTemporary
- void Reset()
- {
- TicketSize = 0;
- TicketVersion = 0;
- SteamID = 0;
- AppID = 0;
- Unk1 = 0;
- Unk2 = 0;
- TicketFlags = 0;
- TicketIssueTime = 0;
- TicketValidityEnd = 0;
- }
+ void Reset();
- std::vector Serialize()
- {
- std::vector buffer;
- uint8_t* pBuffer;
+ std::vector Serialize() const;
- buffer.resize(40);
- pBuffer = buffer.data();
- *reinterpret_cast(pBuffer) = TicketSize; pBuffer += 4;
- *reinterpret_cast(pBuffer) = TicketVersion; pBuffer += 4;
- *reinterpret_cast(pBuffer) = SteamID; pBuffer += 8;
- *reinterpret_cast(pBuffer) = AppID; pBuffer += 4;
- *reinterpret_cast(pBuffer) = Unk1; pBuffer += 4;
- *reinterpret_cast(pBuffer) = Unk2; pBuffer += 4;
- *reinterpret_cast(pBuffer) = TicketFlags; pBuffer += 4;
- *reinterpret_cast(pBuffer) = TicketIssueTime; pBuffer += 4;
- *reinterpret_cast(pBuffer) = TicketValidityEnd;
-
- return buffer;
- }
-
- bool Deserialize(const uint8_t* pBuffer, size_t size)
- {
- if (size < 40)
- return false;
-
- TicketSize = *reinterpret_cast(pBuffer); pBuffer += 4;
- TicketVersion = *reinterpret_cast(pBuffer); pBuffer += 4;
- SteamID = *reinterpret_cast(pBuffer); pBuffer += 8;
- AppID = *reinterpret_cast(pBuffer); pBuffer += 4;
- Unk1 = *reinterpret_cast(pBuffer); pBuffer += 4;
- Unk2 = *reinterpret_cast(pBuffer); pBuffer += 4;
- TicketFlags = *reinterpret_cast(pBuffer); pBuffer += 4;
- TicketIssueTime = *reinterpret_cast(pBuffer); pBuffer += 4;
- TicketValidityEnd = *reinterpret_cast(pBuffer);
-
- return true;
- }
+ bool Deserialize(const uint8_t* pBuffer, size_t size);
//inline uint32_t TicketSize() { return *reinterpret_cast(_Buffer); }
//inline uint32_t TicketVersion() { return *reinterpret_cast(reinterpret_cast(_Buffer) + 4); }
@@ -161,109 +77,18 @@ struct AppTicketV2
struct AppTicketV4
{
- std::vector AppIDs;
+ std::vector AppIDs{};
bool HasVACStatus = false;
- uint32_t VACStatus;
+ uint32_t VACStatus{};
bool HasAppValue = false;
- uint32_t AppValue;
+ uint32_t AppValue{};
- void Reset()
- {
- AppIDs.clear();
- HasVACStatus = false;
- HasAppValue = false;
- }
+ void Reset();
- std::vector Serialize()
- {
- std::vector appids = AppIDs;
- if (appids.size() == 0)
- {
- appids.emplace_back(0);
- }
+ std::vector Serialize();
- uint16_t appid_count = static_cast(appids.size() > 140 ? 140 : appids.size());
- size_t buffer_size = static_cast(appid_count) * 4ul + 2ul;
- std::vector buffer;
- uint8_t* pBuffer;
-
- if (HasAppValue)
- {// VACStatus + AppValue
- buffer_size += 4;
- if (!HasVACStatus)
- {
- HasVACStatus = true;
- VACStatus = 0;
- }
- }
- if (HasVACStatus)
- {// VACStatus only
- buffer_size += 4;
- }
-
- buffer.resize(buffer_size);
- pBuffer = buffer.data();
- *reinterpret_cast(pBuffer) = appid_count;
- pBuffer += 2;
-
- for (int i = 0; i < appid_count && i < 140; ++i)
- {
- *reinterpret_cast(pBuffer) = appids[i];
- pBuffer += 4;
- }
-
- if (HasVACStatus)
- {
- *reinterpret_cast(pBuffer) = VACStatus;
- pBuffer += 4;
- }
- if (HasAppValue)
- {
- *reinterpret_cast(pBuffer) = AppValue;
- }
-
- return buffer;
- }
-
- bool Deserialize(const uint8_t* pBuffer, size_t size)
- {
- if (size < 2)
- return false;
-
- uint16_t appid_count = *reinterpret_cast(pBuffer);
- if (size < (appid_count * 4 + 2) || appid_count >= 140)
- return false;
-
- AppIDs.resize(appid_count);
- pBuffer += 2;
- size -= 2;
- for (int i = 0; i < appid_count; ++i)
- {
- AppIDs[i] = *reinterpret_cast(pBuffer);
- pBuffer += 4;
- size -= 4;
- }
-
- HasVACStatus = false;
- HasAppValue = false;
-
- if (size < 4)
- return true;
-
- HasVACStatus = true;
- VACStatus = *reinterpret_cast(pBuffer);
- pBuffer += 4;
- size -= 4;
-
- if (size < 4)
- return true;
-
- HasAppValue = true;
- AppValue = *reinterpret_cast(pBuffer);
-
- return true;
- }
+ bool Deserialize(const uint8_t* pBuffer, size_t size);
// Often 1 with empty appid
//inline uint16_t AppIDCount() { return *reinterpret_cast(_Buffer); }
@@ -277,48 +102,13 @@ struct AppTicketV4
class DecryptedAppTicket
{
public:
- AppTicketV1 TicketV1;
- AppTicketV2 TicketV2;
- AppTicketV4 TicketV4;
+ AppTicketV1 TicketV1{};
+ AppTicketV2 TicketV2{};
+ AppTicketV4 TicketV4{};
- bool DeserializeTicket(const uint8_t* pBuffer, size_t buf_size)
- {
- if (!TicketV1.Deserialize(pBuffer, buf_size))
- return false;
+ bool DeserializeTicket(const uint8_t* pBuffer, size_t buf_size);
- pBuffer += 16 + TicketV1.UserData.size();
- buf_size -= 16 + TicketV1.UserData.size();
- if (!TicketV2.Deserialize(pBuffer, buf_size))
- return false;
-
- if (TicketV2.TicketVersion > 2)
- {
- pBuffer += 40;
- buf_size -= 40;
- if (!TicketV4.Deserialize(pBuffer, buf_size))
- return false;
- }
-
- return true;
- }
-
- std::vector SerializeTicket()
- {
- std::vector buffer;
-
- TicketV1.TicketSize = TicketV1.UserData.size() + 40 + 2 + ((TicketV4.AppIDs.size() == 0 ? 1 : TicketV4.AppIDs.size()) * 4) + (TicketV4.HasVACStatus ? 4 : 0) + (TicketV4.HasAppValue ? 4 : 0);
- TicketV2.TicketSize = TicketV1.TicketSize - TicketV1.UserData.size();
-
- buffer = TicketV1.Serialize();
-
- auto v = TicketV2.Serialize();
-
- buffer.insert(buffer.end(), v.begin(), v.end());
- v = TicketV4.Serialize();
- buffer.insert(buffer.end(), v.begin(), v.end());
-
- return buffer;
- }
+ std::vector SerializeTicket();
};
@@ -326,23 +116,13 @@ class Steam_AppTicket :
public ISteamAppTicket
{
private:
- class Settings *settings;
+ class Settings *settings{};
public:
- Steam_AppTicket(class Settings *settings) :
- settings(settings)
- {
+ Steam_AppTicket(class Settings *settings);
- }
+ virtual uint32 GetAppOwnershipTicketData( uint32 nAppID, void *pvBuffer, uint32 cbBufferLength, uint32 *piAppId, uint32 *piSteamId, uint32 *piSignature, uint32 *pcbSignature );
- virtual uint32 GetAppOwnershipTicketData( uint32 nAppID, void *pvBuffer, uint32 cbBufferLength, uint32 *piAppId, uint32 *piSteamId, uint32 *piSignature, uint32 *pcbSignature )
- {
- PRINT_DEBUG("TODO %u, %p, %u, %p, %p, %p, %p", nAppID, pvBuffer, cbBufferLength, piAppId, piSteamId, piSignature, pcbSignature);
- std::lock_guard lock(global_mutex);
-
- return 0;
-
- }
};
#endif // __INCLUDED_STEAM_APP_TICKET_H__
diff --git a/dll/dll/auth.h b/dll/dll/auth.h
index 2c3fd036..3776b189 100644
--- a/dll/dll/auth.h
+++ b/dll/dll/auth.h
@@ -1,8 +1,8 @@
// source: https://github.com/Detanup01/stmsrv/blob/main/Steam3Server/Others/AppTickets.cs
// thanks Detanup01
-#ifndef AUTH_INCLUDE
-#define AUTH_INCLUDE
+#ifndef AUTH_INCLUDE_H
+#define AUTH_INCLUDE_H
#include "base.h"
#include "mbedtls/pk.h"
@@ -14,646 +14,96 @@
// the data type is important, we depend on sizeof() for each one of them
-constexpr uint32_t STEAM_APPTICKET_SIGLEN = 128;
-constexpr uint32_t STEAM_APPTICKET_GCLen = 20;
-constexpr uint32_t STEAM_APPTICKET_SESSIONLEN = 24;
-
-// source: https://github.com/Detanup01/stmsrv/blob/main/Cert/AppTicket.key
-// thanks Detanup01
-const static std::string app_ticket_key =
- "-----BEGIN PRIVATE KEY-----\n"
- "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMITHOY6pfsvaGTI\n"
- "llmilPa1+ev4BsUV0IW3+F/3pQlZ+o57CO1HbepSh2a37cbGUSehOVQ7lREPVXP3\n"
- "UdyF5tU5IMytJef5N7euM5z2IG9IszeOReO87h2AmtlwGqnRj7qd0MeVxSAuUq7P\n"
- "C/Ir1VyOg58+wAKxaPL18upylnGJAgMBAAECgYEAnKQQj0KG9VYuTCoaL/6pfPcj\n"
- "4PEvhaM1yrfSIKMg8YtOT/G+IsWkUZyK7L1HjUhD+FiIjRQKHNrjfdYAnJz20Xom\n"
- "k6iVt7ugihIne1Q3pGYG8TY9P1DPdN7zEnAVY1Bh2PAlqJWrif3v8v1dUGE/dYr2\n"
- "U3M0JhvzO7VL1B/chIECQQDqW9G5azGMA/cL4jOg0pbj9GfxjJZeT7M2rBoIaRWP\n"
- "C3ROndyb+BNahlKk6tbvqillvvMQQiSFGw/PbmCwtLL3AkEA0/79W0q9d3YCXQGW\n"
- "k3hQvR8HEbxLmRaRF2gU4MOa5C0JqwsmxzdK4mKoJCpVAiu1gmFonLjn2hm8i+vK\n"
- "b7hffwJAEiMpCACTxRJJfFH1TOz/YIT5xmfq+0GPzRtkqGH5mSh5x9vPxwJb/RWI\n"
- "L9s85y90JLuyc/+qc+K0Rol0Ujip4QJAGLXVJEn+8ajAt8SSn5fbmV+/fDK9gRef\n"
- "S+Im5NgH+ubBBL3lBD2Orfqf7K8+f2VG3+6oufPXmpV7Y7fVPdZ40wJALDujJXgi\n"
- "XiCBSht1YScYjfmJh2/xZWh8/w+vs5ZTtrnW2FQvfvVDG9c1hrChhpvmA0QxdgWB\n"
- "zSsAno/utcuB9w==\n"
- "-----END PRIVATE KEY-----\n";
-
-
-static std::vector sign_auth_data(const std::string &private_key_content, const std::vector &data, size_t effective_data_len) {
- std::vector signature{};
-
- // Hash the data using SHA-1
- constexpr static int SHA1_DIGEST_LENGTH = 20;
- uint8_t hash[SHA1_DIGEST_LENGTH]{};
- int result = mbedtls_sha1(data.data(), effective_data_len, hash);
- if (result != 0)
- {
-#ifndef EMU_RELEASE_BUILD
- // we nedd a live object until the printf does its job, hence this special handling
- std::string err_msg(256, 0);
- mbedtls_strerror(result, &err_msg[0], err_msg.size());
- PRINT_DEBUG("failed to hash the data via SHA1: %s", err_msg.c_str());
-#endif
-
- return signature;
- }
-
- mbedtls_entropy_context entropy_ctx; // entropy context for random number generation
- mbedtls_entropy_init(&entropy_ctx);
-
- mbedtls_ctr_drbg_context ctr_drbg_ctx; // CTR-DRBG context for deterministic random number generation
- mbedtls_ctr_drbg_init(&ctr_drbg_ctx);
-
- // seed the CTR-DRBG context with random numbers
- result = mbedtls_ctr_drbg_seed(&ctr_drbg_ctx, mbedtls_entropy_func, &entropy_ctx, nullptr, 0);
- if (mbedtls_ctr_drbg_seed(&ctr_drbg_ctx, mbedtls_entropy_func, &entropy_ctx, nullptr, 0) != 0)
- {
- mbedtls_ctr_drbg_free(&ctr_drbg_ctx);
- mbedtls_entropy_free(&entropy_ctx);
-
-#ifndef EMU_RELEASE_BUILD
- // we nedd a live object until the printf does its job, hence this special handling
- std::string err_msg(256, 0);
- mbedtls_strerror(result, &err_msg[0], err_msg.size());
- PRINT_DEBUG("failed to seed the CTR-DRBG context: %s", err_msg.c_str());
-#endif
-
- return signature;
- }
-
- mbedtls_pk_context private_key_ctx; // holds the parsed private key
- mbedtls_pk_init(&private_key_ctx);
-
- result = mbedtls_pk_parse_key(
- &private_key_ctx, // will hold the parsed private key
- (const unsigned char *)private_key_content.c_str(),
- private_key_content.size() + 1, // we MUST include the null terminator, otherwise this API returns an error!
- nullptr, 0, // no password stuff, private key isn't protected
- mbedtls_ctr_drbg_random, &ctr_drbg_ctx // random number generation function + the CTR-DRBG context it requires as an input
- );
-
- if (result != 0)
- {
- mbedtls_pk_free(&private_key_ctx);
- mbedtls_ctr_drbg_free(&ctr_drbg_ctx);
- mbedtls_entropy_free(&entropy_ctx);
-
-#ifndef EMU_RELEASE_BUILD
- // we nedd a live object until the printf does its job, hence this special handling
- std::string err_msg(256, 0);
- mbedtls_strerror(result, &err_msg[0], err_msg.size());
- PRINT_DEBUG("failed to parse private key: %s", err_msg.c_str());
-#endif
-
- return signature;
- }
-
- // private key must be valid RSA key
- if (mbedtls_pk_get_type(&private_key_ctx) != MBEDTLS_PK_RSA || // invalid type
- mbedtls_pk_can_do(&private_key_ctx, MBEDTLS_PK_RSA) == 0) // or initialized but not properly setup (maybe freed?)
- {
- mbedtls_pk_free(&private_key_ctx);
- mbedtls_ctr_drbg_free(&ctr_drbg_ctx);
- mbedtls_entropy_free(&entropy_ctx);
-
- PRINT_DEBUG("parsed key is not a valid RSA private key");
- return signature;
- }
-
- // get the underlying RSA context from the parsed private key
- mbedtls_rsa_context* rsa_ctx = mbedtls_pk_rsa(private_key_ctx);
-
- // resize the output buffer to accomodate the size of the private key
- const size_t private_key_len = mbedtls_pk_get_len(&private_key_ctx);
- if (private_key_len == 0) // TODO must be 128 siglen
- {
- mbedtls_pk_free(&private_key_ctx);
- mbedtls_ctr_drbg_free(&ctr_drbg_ctx);
- mbedtls_entropy_free(&entropy_ctx);
-
- PRINT_DEBUG("failed to get private key (final buffer) length");
- return signature;
- }
-
- PRINT_DEBUG("computed private key (final buffer) length = %zu", private_key_len);
- signature.resize(private_key_len);
-
- // finally sign the computed hash using RSA and PKCS#1 padding
- result = mbedtls_rsa_pkcs1_sign(
- rsa_ctx,
- mbedtls_ctr_drbg_random, &ctr_drbg_ctx,
- MBEDTLS_MD_SHA1, // we used SHA1 to hash the data
- sizeof(hash), hash,
- signature.data() // output
- );
-
- mbedtls_pk_free(&private_key_ctx);
- mbedtls_ctr_drbg_free(&ctr_drbg_ctx);
- mbedtls_entropy_free(&entropy_ctx);
-
- if (result != 0)
- {
- signature.clear();
-
-#ifndef EMU_RELEASE_BUILD
- // we nedd a live object until the printf does its job, hence this special handling
- std::string err_msg(256, 0);
- mbedtls_strerror(result, &err_msg[0], err_msg.size());
- PRINT_DEBUG("RSA signing failed: %s", err_msg.c_str());
-#endif
- }
-
-#ifndef EMU_RELEASE_BUILD
- // we nedd a live object until the printf does its job, hence this special handling
- auto str = common_helpers::uint8_vector_to_hex_string(signature);
- PRINT_DEBUG("final signature [%zu bytes]:\n %s", signature.size(), str.c_str());
-#endif
-
- return signature;
-}
+constexpr const static uint32_t STEAM_APPTICKET_SIGLEN = 128;
+constexpr const static uint32_t STEAM_APPTICKET_GCLen = 20;
+constexpr const static uint32_t STEAM_APPTICKET_SESSIONLEN = 24;
struct DLC {
- uint32_t AppId;
- std::vector Licenses;
+ uint32_t AppId{};
+ std::vector Licenses{};
- std::vector Serialize()
- {
- PRINT_DEBUG("AppId = %u, Licenses count = %zu", AppId, Licenses.size());
-
- // we need this variable because we depend on the sizeof, must be 2 bytes
- const uint16_t dlcs_licenses_count = (uint16_t)Licenses.size();
- const size_t dlcs_licenses_total_size =
- Licenses.size() * sizeof(Licenses[0]); // count * element size
-
- const size_t total_size =
- sizeof(AppId) +
- sizeof(dlcs_licenses_count) +
- dlcs_licenses_total_size;
-
- std::vector buffer;
- buffer.resize(total_size);
-
- uint8_t* pBuffer = buffer.data();
-
-#define SER_VAR(v) \
- *reinterpret_cast::type *>(pBuffer) = v; \
- pBuffer += sizeof(v)
-
- SER_VAR(AppId);
- SER_VAR(dlcs_licenses_count);
- for(uint32_t dlc_license : Licenses)
- {
- SER_VAR(dlc_license);
- }
-
-#undef SER_VAR
-
- PRINT_DEBUG("final size = %zu", buffer.size());
- return buffer;
- }
+ std::vector Serialize() const;
};
struct AppTicketGC {
- uint64_t GCToken;
- CSteamID id;
- uint32_t ticketGenDate; //epoch
- uint32_t ExternalIP;
- uint32_t InternalIP;
- uint32_t TimeSinceStartup;
- uint32_t TicketGeneratedCount;
+ uint64_t GCToken{};
+ CSteamID id{};
+ uint32_t ticketGenDate{}; //epoch
+ uint32_t ExternalIP{};
+ uint32_t InternalIP{};
+ uint32_t TimeSinceStartup{};
+ uint32_t TicketGeneratedCount{};
private:
uint32_t one = 1;
uint32_t two = 2;
public:
- std::vector Serialize()
- {
- const uint64_t steam_id = id.ConvertToUint64();
-
- // must be 52
- constexpr size_t total_size =
- sizeof(STEAM_APPTICKET_GCLen) +
- sizeof(GCToken) +
- sizeof(steam_id) +
- sizeof(ticketGenDate) +
- sizeof(STEAM_APPTICKET_SESSIONLEN) +
- sizeof(one) +
- sizeof(two) +
- sizeof(ExternalIP) +
- sizeof(InternalIP) +
- sizeof(TimeSinceStartup) +
- sizeof(TicketGeneratedCount);
-
- // check the size at compile time, we must ensure the correct size
-#ifndef EMU_RELEASE_BUILD
- static_assert(
- total_size == 52,
- "AUTH::AppTicketGC::SER calculated size of serialized data != 52 bytes, your compiler has some incorrect sizes"
- );
-#endif
-
- PRINT_DEBUG(
- "\n"
- " GCToken: " "%" PRIu64 "\n"
- " user steam_id: " "%" PRIu64 "\n"
- " ticketGenDate: %u\n"
- " ExternalIP: 0x%08X, InternalIP: 0x%08X\n"
- " TimeSinceStartup: %u, TicketGeneratedCount: %u\n"
- " SER size = %zu",
-
- GCToken,
- steam_id,
- ticketGenDate,
- ExternalIP, InternalIP,
- TimeSinceStartup, TicketGeneratedCount,
- total_size
- );
-
- std::vector buffer;
- buffer.resize(total_size);
-
- uint8_t* pBuffer = buffer.data();
-
-#define SER_VAR(v) \
- *reinterpret_cast::type *>(pBuffer) = v; \
- pBuffer += sizeof(v)
-
- SER_VAR(STEAM_APPTICKET_GCLen);
- SER_VAR(GCToken);
- SER_VAR(steam_id);
- SER_VAR(ticketGenDate);
- SER_VAR(STEAM_APPTICKET_SESSIONLEN);
- SER_VAR(one);
- SER_VAR(two);
- SER_VAR(ExternalIP);
- SER_VAR(InternalIP);
- SER_VAR(TimeSinceStartup);
- SER_VAR(TicketGeneratedCount);
-
-#undef SER_VAR
-
-#ifndef EMU_RELEASE_BUILD
- // we nedd a live object until the printf does its job, hence this special handling
- auto str = common_helpers::uint8_vector_to_hex_string(buffer);
- PRINT_DEBUG("final data [%zu bytes]:\n %s", buffer.size(), str.c_str());
-#endif
-
- return buffer;
- }
+ std::vector Serialize() const;
};
struct AppTicket {
- uint32_t Version;
- CSteamID id;
- uint32_t AppId;
- uint32_t ExternalIP;
- uint32_t InternalIP;
+ uint32_t Version{};
+ CSteamID id{};
+ uint32_t AppId{};
+ uint32_t ExternalIP{};
+ uint32_t InternalIP{};
uint32_t AlwaysZero = 0; //OwnershipFlags?
- uint32_t TicketGeneratedDate;
- uint32_t TicketGeneratedExpireDate;
- std::vector Licenses;
- std::vector DLCs;
+ uint32_t TicketGeneratedDate{};
+ uint32_t TicketGeneratedExpireDate{};
+ std::vector Licenses{};
+ std::vector DLCs{};
- std::vector Serialize()
- {
- const uint64_t steam_id = id.ConvertToUint64();
-
- PRINT_DEBUG(
- "\n"
- " Version: %u\n"
- " user steam_id: " "%" PRIu64 "\n"
- " AppId: %u\n"
- " ExternalIP: 0x%08X, InternalIP: 0x%08X\n"
- " TicketGeneratedDate: %u, TicketGeneratedExpireDate: %u\n"
- " Licenses count: %zu, DLCs count: %zu",
-
- Version,
- steam_id,
- AppId,
- ExternalIP, InternalIP,
- TicketGeneratedDate, TicketGeneratedExpireDate,
- Licenses.size(), DLCs.size()
- );
-
- // we need this variable because we depend on the sizeof, must be 2 bytes
- const uint16_t licenses_count = (uint16_t)Licenses.size();
- const size_t licenses_total_size =
- Licenses.size() * sizeof(Licenses[0]); // total count * element size
-
- // we need this variable because we depend on the sizeof, must be 2 bytes
- const uint16_t dlcs_count = (uint16_t)DLCs.size();
- size_t dlcs_total_size = 0;
- std::vector> serialized_dlcs;
- for (DLC &dlc : DLCs)
- {
- auto dlc_ser = dlc.Serialize();
- dlcs_total_size += dlc_ser.size();
- serialized_dlcs.push_back(dlc_ser);
- }
-
- //padding
- constexpr uint16_t padding = (uint16_t)0;
-
- // must be 42
- constexpr size_t static_fields_size =
- sizeof(Version) +
- sizeof(steam_id) +
- sizeof(AppId) +
- sizeof(ExternalIP) +
- sizeof(InternalIP) +
- sizeof(AlwaysZero) +
- sizeof(TicketGeneratedDate) +
- sizeof(TicketGeneratedExpireDate) +
-
- sizeof(licenses_count) +
- sizeof(dlcs_count) +
-
- sizeof(padding);
-
- // check the size at compile time, we must ensure the correct size
-#ifndef EMU_RELEASE_BUILD
- static_assert(
- static_fields_size == 42,
- "AUTH::AppTicket::SER calculated size of serialized data != 42 bytes, your compiler has some incorrect sizes"
- );
-#endif
-
- const size_t total_size =
- static_fields_size +
- licenses_total_size +
- dlcs_total_size;
-
- PRINT_DEBUG("final size = %zu", total_size);
-
- std::vector buffer;
- buffer.resize(total_size);
- uint8_t* pBuffer = buffer.data();
-
-#define SER_VAR(v) \
- *reinterpret_cast::type *>(pBuffer) = v; \
- pBuffer += sizeof(v)
-
- SER_VAR(Version);
- SER_VAR(steam_id);
- SER_VAR(AppId);
- SER_VAR(ExternalIP);
- SER_VAR(InternalIP);
- SER_VAR(AlwaysZero);
- SER_VAR(TicketGeneratedDate);
- SER_VAR(TicketGeneratedExpireDate);
-
-#ifndef EMU_RELEASE_BUILD
- {
- // we nedd a live object until the printf does its job, hence this special handling
- auto str = common_helpers::uint8_vector_to_hex_string(buffer);
- PRINT_DEBUG("(before licenses + DLCs):\n %s", str.c_str());
- }
-#endif
-
- /*
- * layout of licenses:
- * ------------------------
- * 2 bytes: count of licenses
- * ------------------------
- * [
- * ------------------------
- * | 4 bytes: license element
- * ------------------------
- * ]
- */
- SER_VAR(licenses_count);
- for(uint32_t license : Licenses)
- {
- SER_VAR(license);
- }
-
- /*
- * layout of DLCs:
- * ------------------------
- * | 2 bytes: count of DLCs
- * ------------------------
- * [
- * ------------------------
- * | 4 bytes: app id
- * ------------------------
- * | 2 bytes: DLC licenses count
- * ------------------------
- * [
- * 4 bytes: DLC license element
- * ]
- * ]
- */
- SER_VAR(dlcs_count);
- for (std::vector &dlc_ser : serialized_dlcs)
- {
- memcpy(pBuffer, dlc_ser.data(), dlc_ser.size());
- pBuffer += dlc_ser.size();
- }
-
- //padding
- SER_VAR(padding);
-
-#undef SER_VAR
-
-#ifndef EMU_RELEASE_BUILD
- {
- // we nedd a live object until the printf does its job, hence this special handling
- auto str = common_helpers::uint8_vector_to_hex_string(buffer);
- PRINT_DEBUG("final data [%zu bytes]:\n %s", buffer.size(), str.c_str());
- }
-#endif
-
- return buffer;
- }
+ std::vector Serialize() const;
};
struct Auth_Data {
- bool HasGC;
- AppTicketGC GC;
- AppTicket Ticket;
+ bool HasGC{};
+ AppTicketGC GC{};
+ AppTicket Ticket{};
//old data
- CSteamID id;
- uint64_t number;
- std::chrono::high_resolution_clock::time_point created;
+ CSteamID id{};
+ uint64_t number{};
+ std::chrono::high_resolution_clock::time_point created{};
- std::vector Serialize()
- {
- /*
- * layout of Auth_Data with GC:
- * ------------------------
- * X bytes: GC data blob (currently 52 bytes)
- * ------------------------
- * 4 bytes: remaining Auth_Data blob size (4 + Y + Z)
- * ------------------------
- * 4 bytes: size of ticket data layout (not blob!, hence blob + 4)
- * ------------------------
- * Y bytes: ticket data blob
- * ------------------------
- * Z bytes: App Ticket signature
- * ------------------------
- *
- * total layout length = X + 4 + 4 + Y + Z
- */
-
- /*
- * layout of Auth_Data without GC:
- * ------------------------
- * 4 bytes: size of ticket data layout (not blob!, hence blob + 4)
- * ------------------------
- * Y bytes: ticket data blob
- * ------------------------
- * Z bytes: App Ticket signature
- * ------------------------
- *
- * total layout length = 4 + Y + Z
- */
- const uint64_t steam_id = id.ConvertToUint64();
-
- PRINT_DEBUG(
- "\n"
- " HasGC: %u\n"
- " user steam_id: " "%" PRIu64 "\n"
- " number: " "%" PRIu64 ,
-
- (int)HasGC,
- steam_id,
- number
- );
-
- /*
- * layout of ticket data:
- * ------------------------
- * 4 bytes: size of ticket data layout (not blob!, hence blob + 4)
- * ------------------------
- * Y bytes: ticket data blob
- * ------------------------
- *
- * total layout length = 4 + Y
- */
- std::vector tickedData = Ticket.Serialize();
- // we need this variable because we depend on the sizeof, must be 4 bytes
- const uint32_t ticket_data_layout_length =
- sizeof(uint32_t) + // size of this uint32_t because it is included!
- (uint32_t)tickedData.size();
-
- size_t total_size_without_siglen = ticket_data_layout_length;
-
- std::vector GCData;
- size_t gc_data_layout_length = 0;
- if (HasGC)
- {
- /*
- * layout of GC data:
- * ------------------------
- * X bytes: GC data blob (currently 52 bytes)
- * ------------------------
- * 4 bytes: remaining Auth_Data blob size
- * ------------------------
- *
- * total layout length = X + 4
- */
- GCData = GC.Serialize();
- gc_data_layout_length +=
- GCData.size() +
- sizeof(uint32_t);
-
- total_size_without_siglen += gc_data_layout_length;
- }
-
- const size_t final_buffer_size = total_size_without_siglen + STEAM_APPTICKET_SIGLEN;
- PRINT_DEBUG("size without sig len = %zu, size with sig len (final size) = %zu",
- total_size_without_siglen,
- final_buffer_size
- );
-
- std::vector buffer;
- buffer.resize(final_buffer_size);
-
- uint8_t* pBuffer = buffer.data();
-
-#define SER_VAR(v) \
- *reinterpret_cast::type *>(pBuffer) = v; \
- pBuffer += sizeof(v)
-
- // serialize the GC data first
- if (HasGC)
- {
- memcpy(pBuffer, GCData.data(), GCData.size());
- pBuffer += GCData.size();
-
- // when GC data is written (HasGC),
- // the next 4 bytes after the GCData will be the length of the remaining data in the final buffer
- // i.e. final buffer size - length of GCData layout
- // i.e. ticket data length + STEAM_APPTICKET_SIGLEN
- //
- // notice that we subtract the entire layout length, not just GCData.size(),
- // otherwise these next 4 bytes will include themselves!
- uint32_t remaining_length = (uint32_t)(final_buffer_size - gc_data_layout_length);
- SER_VAR(remaining_length);
- }
-
- // serialize the ticket data
- SER_VAR(ticket_data_layout_length);
- memcpy(pBuffer, tickedData.data(), tickedData.size());
-
-#ifndef EMU_RELEASE_BUILD
- {
- // we nedd a live object until the printf does its job, hence this special handling
- auto str = common_helpers::uint8_vector_to_hex_string(buffer);
- PRINT_DEBUG("final data (before signature) [%zu bytes]:\n %s", buffer.size(), str.c_str());
- }
-#endif
-
- //Todo make a signature
- std::vector signature = sign_auth_data(app_ticket_key, tickedData, total_size_without_siglen);
- if (signature.size() == STEAM_APPTICKET_SIGLEN) {
- memcpy(buffer.data() + total_size_without_siglen, signature.data(), signature.size());
-
-#ifndef EMU_RELEASE_BUILD
- {
- // we nedd a live object until the printf does its job, hence this special handling
- auto str = common_helpers::uint8_vector_to_hex_string(buffer);
- PRINT_DEBUG("final data (after signature) [%zu bytes]:\n %s", buffer.size(), str.c_str());
- }
-#endif
-
- } else {
- PRINT_DEBUG("signature size [%zu] is invalid", signature.size());
- }
-
-#undef SER_VAR
-
- return buffer;
- }
+ std::vector Serialize() const;
};
class Auth_Manager {
- class Settings *settings;
- class Networking *network;
- class SteamCallBacks *callbacks;
+ class Settings *settings{};
+ class Networking *network{};
+ class SteamCallBacks *callbacks{};
+
+ std::vector inbound{};
+ std::vector outbound{};
void launch_callback(CSteamID id, EAuthSessionResponse resp, double delay=0);
void launch_callback_gs(CSteamID id, bool approved);
- std::vector inbound;
- std::vector outbound;
+
+ static void ticket_callback(void *object, Common_Message *msg);
+ void Callback(Common_Message *msg);
+
public:
Auth_Manager(class Settings *settings, class Networking *network, class SteamCallBacks *callbacks);
~Auth_Manager();
- void Callback(Common_Message *msg);
HAuthTicket getTicket( void *pTicket, int cbMaxTicket, uint32 *pcbTicket );
HAuthTicket getWebApiTicket( const char *pchIdentity );
void cancelTicket(uint32 number);
+
EBeginAuthSessionResult beginAuth(const void *pAuthTicket, int cbAuthTicket, CSteamID steamID);
bool endAuth(CSteamID id);
+
uint32 countInboundAuth();
+
bool SendUserConnectAndAuthenticate( uint32 unIPClient, const void *pvAuthBlob, uint32 cubAuthBlobSize, CSteamID *pSteamIDUser );
+
CSteamID fakeUser();
+
Auth_Data getTicketData( void *pTicket, int cbMaxTicket, uint32 *pcbTicket );
};
-#endif // AUTH_INCLUDE
+#endif // AUTH_INCLUDE_H
diff --git a/dll/dll/base.h b/dll/dll/base.h
index 4cff413b..1e02d699 100644
--- a/dll/dll/base.h
+++ b/dll/dll/base.h
@@ -15,17 +15,14 @@
License along with the Goldberg Emulator; if not, see
. */
-#ifndef BASE_INCLUDE
-#define BASE_INCLUDE
+#ifndef BASE_INCLUDE_H
+#define BASE_INCLUDE_H
#include "common_includes.h"
+#include "callsystem.h"
#define PUSH_BACK_IF_NOT_IN(vector, element) { if(std::find(vector.begin(), vector.end(), element) == vector.end()) vector.push_back(element); }
-#define STEAM_CALLRESULT_TIMEOUT 120.0
-#define STEAM_CALLRESULT_WAIT_FOR_CB 0.01
-#define DEFAULT_CB_TIMEOUT 0.002
-
extern std::recursive_mutex global_mutex;
extern const std::chrono::time_point startup_counter;
@@ -34,70 +31,13 @@ extern const std::chrono::time_point startup_time;
void randombytes(char *buf, size_t size);
std::string get_env_variable(const std::string &name);
bool set_env_variable(const std::string &name, const std::string &value);
+
+/// @brief Check for a timeout given some initial timepoint and a timeout in sec.
+/// @param old The initial timepoint which will be compared against current time
+/// @param timeout The max allowed time in seconds
+/// @return true if the timepoint has exceeded the max allowed timeout, false otherwise
bool check_timedout(std::chrono::high_resolution_clock::time_point old, double timeout);
-class CCallbackMgr
-{
-public:
- static void SetRegister(class CCallbackBase *pCallback, int iCallback) {
- pCallback->m_nCallbackFlags |= CCallbackBase::k_ECallbackFlagsRegistered;
- pCallback->m_iCallback = iCallback;
- };
-
- static void SetUnregister(class CCallbackBase *pCallback) {
- if (pCallback)
- pCallback->m_nCallbackFlags &= !CCallbackBase::k_ECallbackFlagsRegistered;
- };
-
- static bool isServer(class CCallbackBase *pCallback) {
- return (pCallback->m_nCallbackFlags & CCallbackBase::k_ECallbackFlagsGameServer) != 0;
- };
-};
-
-struct Steam_Call_Result {
- Steam_Call_Result(SteamAPICall_t a, int icb, void *r, unsigned int s, double r_in, bool run_cc_cb) {
- api_call = a;
- result.resize(s);
- if (s > 0 && r != NULL)
- memcpy(&(result[0]), r, s);
- created = std::chrono::high_resolution_clock::now();
- run_in = r_in;
- run_call_completed_cb = run_cc_cb;
- iCallback = icb;
- }
-
- bool operator==(const struct Steam_Call_Result& a)
- {
- return a.api_call == api_call && a.callbacks == callbacks;
- }
-
- bool timed_out() {
- return check_timedout(created, STEAM_CALLRESULT_TIMEOUT);
- }
-
- bool call_completed() {
- return (!reserved) && check_timedout(created, run_in);
- }
-
- bool can_execute() {
- return (!to_delete) && call_completed() && (has_cb() || check_timedout(created, STEAM_CALLRESULT_WAIT_FOR_CB));
- }
-
- bool has_cb() {
- return callbacks.size() > 0;
- }
-
- SteamAPICall_t api_call{};
- std::vector callbacks{};
- std::vector result{};
- bool to_delete = false;
- bool reserved = false;
- std::chrono::high_resolution_clock::time_point created{};
- double run_in{};
- bool run_call_completed_cb{};
- int iCallback{};
-};
-
unsigned generate_account_id();
CSteamID generate_steam_anon_user();
SteamAPICall_t generate_steam_api_call_id();
@@ -112,334 +52,10 @@ std::string canonical_path(const std::string &path);
bool file_exists_(const std::string &full_path);
unsigned int file_size_(const std::string &full_path);
-class SteamCallResults {
- std::vector callresults{};
- std::vector completed_callbacks{};
- void (*cb_all)(std::vector result, int callback) = nullptr;
-
-public:
- void addCallCompleted(class CCallbackBase *cb) {
- if (std::find(completed_callbacks.begin(), completed_callbacks.end(), cb) == completed_callbacks.end()) {
- completed_callbacks.push_back(cb);
- }
- }
-
- void rmCallCompleted(class CCallbackBase *cb) {
- auto c = std::find(completed_callbacks.begin(), completed_callbacks.end(), cb);
- if (c != completed_callbacks.end()) {
- completed_callbacks.erase(c);
- }
- }
-
- void addCallBack(SteamAPICall_t api_call, class CCallbackBase *cb) {
- auto cb_result = std::find_if(callresults.begin(), callresults.end(), [api_call](struct Steam_Call_Result const& item) { return item.api_call == api_call; });
- if (cb_result != callresults.end()) {
- cb_result->callbacks.push_back(cb);
- CCallbackMgr::SetRegister(cb, cb->GetICallback());
- }
- }
-
- bool exists(SteamAPICall_t api_call) {
- auto cr = std::find_if(callresults.begin(), callresults.end(), [api_call](struct Steam_Call_Result const& item) { return item.api_call == api_call; });
- if (cr == callresults.end()) return false;
- if (!cr->call_completed()) return false;
- return true;
- }
-
- bool callback_result(SteamAPICall_t api_call, void *copy_to, unsigned int size) {
- auto cb_result = std::find_if(callresults.begin(), callresults.end(), [api_call](struct Steam_Call_Result const& item) { return item.api_call == api_call; });
- if (cb_result != callresults.end()) {
- if (!cb_result->call_completed()) return false;
- if (cb_result->result.size() > size) return false;
-
- memcpy(copy_to, &(cb_result->result[0]), cb_result->result.size());
- cb_result->to_delete = true;
- return true;
- } else {
- return false;
- }
- }
-
- void rmCallBack(SteamAPICall_t api_call, class CCallbackBase *cb) {
- auto cb_result = std::find_if(callresults.begin(), callresults.end(), [api_call](struct Steam_Call_Result const& item) { return item.api_call == api_call; });
- if (cb_result != callresults.end()) {
- auto it = std::find(cb_result->callbacks.begin(), cb_result->callbacks.end(), cb);
- if (it != cb_result->callbacks.end()) {
- cb_result->callbacks.erase(it);
- CCallbackMgr::SetUnregister(cb);
- }
- }
- }
-
- void rmCallBack(class CCallbackBase *cb) {
- //TODO: check if callback is callback or call result?
- for (auto & cr: callresults) {
- auto it = std::find(cr.callbacks.begin(), cr.callbacks.end(), cb);
- if (it != cr.callbacks.end()) {
- cr.callbacks.erase(it);
- }
-
- if (cr.callbacks.size() == 0) {
- cr.to_delete = true;
- }
- }
- }
-
- SteamAPICall_t addCallResult(SteamAPICall_t api_call, int iCallback, void *result, unsigned int size, double timeout=DEFAULT_CB_TIMEOUT, bool run_call_completed_cb=true) {
- PRINT_DEBUG("%i", iCallback);
- auto cb_result = std::find_if(callresults.begin(), callresults.end(), [api_call](struct Steam_Call_Result const& item) { return item.api_call == api_call; });
- if (cb_result != callresults.end()) {
- if (cb_result->reserved) {
- std::chrono::high_resolution_clock::time_point created = cb_result->created;
- std::vector temp_cbs = cb_result->callbacks;
- *cb_result = Steam_Call_Result(api_call, iCallback, result, size, timeout, run_call_completed_cb);
- cb_result->callbacks = temp_cbs;
- cb_result->created = created;
- return cb_result->api_call;
- }
- } else {
- struct Steam_Call_Result res = Steam_Call_Result(api_call, iCallback, result, size, timeout, run_call_completed_cb);
- callresults.push_back(res);
- return callresults.back().api_call;
- }
-
- PRINT_DEBUG("ERROR");
- return k_uAPICallInvalid;
- }
-
- SteamAPICall_t reserveCallResult() {
- struct Steam_Call_Result res = Steam_Call_Result(generate_steam_api_call_id(), 0, NULL, 0, 0.0, true);
- res.reserved = true;
- callresults.push_back(res);
- return callresults.back().api_call;
- }
-
- SteamAPICall_t addCallResult(int iCallback, void *result, unsigned int size, double timeout=DEFAULT_CB_TIMEOUT, bool run_call_completed_cb=true) {
- return addCallResult(generate_steam_api_call_id(), iCallback, result, size, timeout, run_call_completed_cb);
- }
-
- void setCbAll(void (*cb_all)(std::vector result, int callback)) {
- this->cb_all = cb_all;
- }
-
- void runCallResults() {
- unsigned long current_size = callresults.size();
- for (unsigned i = 0; i < current_size; ++i) {
- unsigned index = i;
-
- if (!callresults[index].to_delete) {
- if (callresults[index].can_execute()) {
- std::vector result = callresults[index].result;
- SteamAPICall_t api_call = callresults[index].api_call;
- bool run_call_completed_cb = callresults[index].run_call_completed_cb;
- int iCallback = callresults[index].iCallback;
- if (run_call_completed_cb) {
- callresults[index].run_call_completed_cb = false;
- }
-
- callresults[index].to_delete = true;
- if (callresults[index].has_cb()) {
- std::vector temp_cbs = callresults[index].callbacks;
- for (auto & cb : temp_cbs) {
- PRINT_DEBUG("Calling callresult %p %i", cb, cb->GetICallback());
- global_mutex.unlock();
- //TODO: unlock relock doesn't work if mutex was locked more than once.
- if (run_call_completed_cb) { //run the right function depending on if it's a callback or a call result.
- cb->Run(&(result[0]), false, api_call);
- } else {
- cb->Run(&(result[0]));
- }
- //COULD BE DELETED SO DON'T TOUCH CB
- global_mutex.lock();
- PRINT_DEBUG("callresult done");
- }
- }
-
- if (run_call_completed_cb) {
- //can it happen that one is removed during the callback?
- std::vector callbacks = completed_callbacks;
- SteamAPICallCompleted_t data{};
- data.m_hAsyncCall = api_call;
- data.m_iCallback = iCallback;
- data.m_cubParam = result.size();
-
- for (auto & cb: callbacks) {
- PRINT_DEBUG("Call complete cb %i %p %llu", iCallback, cb, api_call);
- //TODO: check if this is a problem or not.
- SteamAPICallCompleted_t temp = data;
- global_mutex.unlock();
- cb->Run(&temp);
- global_mutex.lock();
- }
-
- if (cb_all) {
- std::vector res;
- res.resize(sizeof(data));
- memcpy(&(res[0]), &data, sizeof(data));
- cb_all(res, data.k_iCallback);
- }
- } else {
- if (cb_all) {
- cb_all(result, iCallback);
- }
- }
- } else {
- if (callresults[index].timed_out()) {
- callresults[index].to_delete = true;
- }
- }
- }
- }
-
- PRINT_DEBUG("erase to_delete");
- auto c = std::begin(callresults);
- while (c != std::end(callresults)) {
- if (c->to_delete) {
- if (c->timed_out()) {
- PRINT_DEBUG("removed callresult %i", c->iCallback);
- c = callresults.erase(c);
- } else {
- ++c;
- }
- } else {
- ++c;
- }
- }
- }
-};
-
-struct Steam_Call_Back {
- std::vector callbacks{};
- std::vector> results{};
-};
-
-class SteamCallBacks {
- std::map callbacks{};
- SteamCallResults *results{};
-
-public:
- SteamCallBacks(SteamCallResults *results) {
- this->results = results;
- }
-
- void addCallBack(int iCallback, class CCallbackBase *cb) {
- PRINT_DEBUG("%i", iCallback);
- if (iCallback == SteamAPICallCompleted_t::k_iCallback) {
- results->addCallCompleted(cb);
- CCallbackMgr::SetRegister(cb, iCallback);
- return;
- }
-
- if (std::find(callbacks[iCallback].callbacks.begin(), callbacks[iCallback].callbacks.end(), cb) == callbacks[iCallback].callbacks.end()) {
- callbacks[iCallback].callbacks.push_back(cb);
- CCallbackMgr::SetRegister(cb, iCallback);
- for (auto & res: callbacks[iCallback].results) {
- //TODO: timeout?
- SteamAPICall_t api_id = results->addCallResult(iCallback, &(res[0]), res.size(), 0.0, false);
- results->addCallBack(api_id, cb);
- }
- }
- }
-
- void addCBResult(int iCallback, void *result, unsigned int size, double timeout, bool dont_post_if_already) {
- if (dont_post_if_already) {
- for (auto & r : callbacks[iCallback].results) {
- if (r.size() == size) {
- if (memcmp(&(r[0]), result, size) == 0) {
- //cb already posted
- return;
- }
- }
- }
- }
-
- std::vector temp{};
- temp.resize(size);
- memcpy(&(temp[0]), result, size);
- callbacks[iCallback].results.push_back(temp);
- for (auto cb: callbacks[iCallback].callbacks) {
- SteamAPICall_t api_id = results->addCallResult(iCallback, result, size, timeout, false);
- results->addCallBack(api_id, cb);
- }
-
- if (callbacks[iCallback].callbacks.empty()) {
- results->addCallResult(iCallback, result, size, timeout, false);
- }
- }
-
- void addCBResult(int iCallback, void *result, unsigned int size) {
- addCBResult(iCallback, result, size, DEFAULT_CB_TIMEOUT, false);
- }
-
- void addCBResult(int iCallback, void *result, unsigned int size, bool dont_post_if_already) {
- addCBResult(iCallback, result, size, DEFAULT_CB_TIMEOUT, dont_post_if_already);
- }
-
- void addCBResult(int iCallback, void *result, unsigned int size, double timeout) {
- addCBResult(iCallback, result, size, timeout, false);
- }
-
- void rmCallBack(int iCallback, class CCallbackBase *cb) {
- if (iCallback == SteamAPICallCompleted_t::k_iCallback) {
- results->rmCallCompleted(cb);
- CCallbackMgr::SetUnregister(cb);
- return;
- }
-
- auto c = std::find(callbacks[iCallback].callbacks.begin(), callbacks[iCallback].callbacks.end(), cb);
- if (c != callbacks[iCallback].callbacks.end()) {
- callbacks[iCallback].callbacks.erase(c);
- CCallbackMgr::SetUnregister(cb);
- results->rmCallBack(cb);
- }
- }
-
- void runCallBacks() {
- for (auto & c : callbacks) {
- c.second.results.clear();
- }
- }
-};
-
-struct RunCBs {
- void (*function)(void *object) = nullptr;
- void *object{};
-};
-
-class RunEveryRunCB {
- std::vector cbs{};
-public:
- void add(void (*cb)(void *object), void *object) {
- remove(cb, object);
- RunCBs rcb;
- rcb.function = cb;
- rcb.object = object;
- cbs.push_back(rcb);
- }
-
- void remove(void (*cb)(void *object), void *object) {
- auto c = std::begin(cbs);
- while (c != std::end(cbs)) {
- if (c->function == cb && c->object == object) {
- c = cbs.erase(c);
- } else {
- ++c;
- }
- }
- }
-
- void run() {
- std::vector temp_cbs = cbs;
- for (auto c : temp_cbs) {
- c.function(c.object);
- }
- }
-};
-
void set_whitelist_ips(uint32_t *from, uint32_t *to, unsigned num_ips);
#ifdef EMU_EXPERIMENTAL_BUILD
bool crack_SteamAPI_RestartAppIfNecessary(uint32 unOwnAppID);
bool crack_SteamAPI_Init();
#endif
-#endif
+#endif // BASE_INCLUDE_H
diff --git a/dll/dll/callsystem.h b/dll/dll/callsystem.h
new file mode 100644
index 00000000..955867c1
--- /dev/null
+++ b/dll/dll/callsystem.h
@@ -0,0 +1,132 @@
+/* Copyright (C) 2019 Mr Goldberg
+ This file is part of the Goldberg Emulator
+
+ The Goldberg Emulator is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ The Goldberg Emulator is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the Goldberg Emulator; if not, see
+ . */
+
+#ifndef __INCLUDED_CALLSYSTEM_H__
+#define __INCLUDED_CALLSYSTEM_H__
+
+#include "common_includes.h"
+
+#define DEFAULT_CB_TIMEOUT 0.002
+#define STEAM_CALLRESULT_TIMEOUT 120.0
+#define STEAM_CALLRESULT_WAIT_FOR_CB 0.01
+
+
+class CCallbackMgr
+{
+public:
+ static void SetRegister(class CCallbackBase *pCallback, int iCallback);
+ static void SetUnregister(class CCallbackBase *pCallback);
+
+ static bool isServer(class CCallbackBase *pCallback);
+};
+
+struct Steam_Call_Result {
+ SteamAPICall_t api_call{};
+ std::vector callbacks{};
+ std::vector result{};
+ bool to_delete = false;
+ bool reserved = false;
+ std::chrono::high_resolution_clock::time_point created{};
+ double run_in{};
+ bool run_call_completed_cb{};
+ int iCallback{};
+
+ Steam_Call_Result(SteamAPICall_t a, int icb, void *r, unsigned int s, double r_in, bool run_cc_cb);
+
+ bool operator==(const struct Steam_Call_Result& other) const;
+
+ bool timed_out() const;
+
+ bool call_completed() const;
+
+ bool can_execute() const;
+
+ bool has_cb() const;
+
+};
+
+class SteamCallResults {
+ std::vector callresults{};
+ std::vector completed_callbacks{};
+ void (*cb_all)(std::vector result, int callback) = nullptr;
+
+public:
+ void addCallCompleted(class CCallbackBase *cb);
+
+ void rmCallCompleted(class CCallbackBase *cb);
+
+ void addCallBack(SteamAPICall_t api_call, class CCallbackBase *cb);
+
+ bool exists(SteamAPICall_t api_call) const;
+
+ bool callback_result(SteamAPICall_t api_call, void *copy_to, unsigned int size);
+
+ void rmCallBack(SteamAPICall_t api_call, class CCallbackBase *cb);
+
+ void rmCallBack(class CCallbackBase *cb);
+
+ SteamAPICall_t addCallResult(SteamAPICall_t api_call, int iCallback, void *result, unsigned int size, double timeout=DEFAULT_CB_TIMEOUT, bool run_call_completed_cb=true);
+
+ SteamAPICall_t reserveCallResult();
+
+ SteamAPICall_t addCallResult(int iCallback, void *result, unsigned int size, double timeout=DEFAULT_CB_TIMEOUT, bool run_call_completed_cb=true);
+
+ void setCbAll(void (*cb_all)(std::vector result, int callback));
+
+ void runCallResults();
+};
+
+struct Steam_Call_Back {
+ std::vector callbacks{};
+ std::vector> results{};
+};
+
+class SteamCallBacks {
+ std::map callbacks{};
+ SteamCallResults *results{};
+
+public:
+ SteamCallBacks(SteamCallResults *results);
+
+ void addCallBack(int iCallback, class CCallbackBase *cb);
+ void addCBResult(int iCallback, void *result, unsigned int size, double timeout, bool dont_post_if_already);
+ void addCBResult(int iCallback, void *result, unsigned int size);
+ void addCBResult(int iCallback, void *result, unsigned int size, bool dont_post_if_already);
+ void addCBResult(int iCallback, void *result, unsigned int size, double timeout);
+
+ void rmCallBack(int iCallback, class CCallbackBase *cb);
+
+ void runCallBacks();
+};
+
+struct RunCBs {
+ void (*function)(void *object) = nullptr;
+ void *object{};
+};
+
+class RunEveryRunCB {
+ std::vector cbs{};
+
+public:
+ void add(void (*cb)(void *object), void *object);
+
+ void remove(void (*cb)(void *object), void *object);
+
+ void run() const;
+};
+
+#endif // __INCLUDED_CALLSYSTEM_H__
diff --git a/dll/dll/common_includes.h b/dll/dll/common_includes.h
index 20a02964..a6b0b0c5 100644
--- a/dll/dll/common_includes.h
+++ b/dll/dll/common_includes.h
@@ -244,4 +244,4 @@ static inline void reset_LastError()
#define LOBBY_CONNECT_APPID ((uint32)-2)
-#endif//__INCLUDED_COMMON_INCLUDES__
+#endif //__INCLUDED_COMMON_INCLUDES__
diff --git a/dll/dll/dll.h b/dll/dll/dll.h
index 1b34715e..5d266046 100644
--- a/dll/dll/dll.h
+++ b/dll/dll/dll.h
@@ -15,6 +15,9 @@
License along with the Goldberg Emulator; if not, see
. */
+#ifndef __INCLUDED_DLL_H__
+#define __INCLUDED_DLL_H__
+
#include "steam_client.h"
#ifdef STEAMCLIENT_DLL
@@ -32,3 +35,5 @@ HSteamUser flat_hsteamuser();
HSteamPipe flat_hsteampipe();
HSteamUser flat_gs_hsteamuser();
HSteamPipe flat_gs_hsteampipe();
+
+#endif // __INCLUDED_DLL_H__
diff --git a/dll/dll/local_storage.h b/dll/dll/local_storage.h
index 104e0b61..0e9fd18c 100644
--- a/dll/dll/local_storage.h
+++ b/dll/dll/local_storage.h
@@ -15,18 +15,17 @@
License along with the Goldberg Emulator; if not, see
. */
-#ifndef LOCAL_STORAGE_INCLUDE
-#define LOCAL_STORAGE_INCLUDE
+#ifndef LOCAL_STORAGE_INCLUDE_H
+#define LOCAL_STORAGE_INCLUDE_H
#include "base.h"
#define MAX_FILENAME_LENGTH 300
-union image_pixel_t
-{
+union image_pixel_t {
uint32_t pixel;
- struct pixel_channels_t
- {
+
+ struct pixel_channels_t {
uint8_t r;
uint8_t g;
uint8_t b;
@@ -34,11 +33,10 @@ union image_pixel_t
} channels;
};
-struct image_t
-{
- size_t width;
- size_t height;
- std::vector pix_map;
+struct image_t {
+ size_t width{};
+ size_t height{};
+ std::vector pix_map{};
};
class Local_Storage {
@@ -105,4 +103,4 @@ public:
static std::string desanitize_string(std::string name);
};
-#endif
+#endif // LOCAL_STORAGE_INCLUDE_H
diff --git a/dll/dll/network.h b/dll/dll/network.h
index e3ab7466..9f255a23 100644
--- a/dll/dll/network.h
+++ b/dll/dll/network.h
@@ -21,13 +21,6 @@
#include "base.h"
#include
-inline bool protobuf_message_equal(const google::protobuf::MessageLite& msg_a,
- const google::protobuf::MessageLite& msg_b) {
- return (msg_a.GetTypeName() == msg_b.GetTypeName()) &&
- (msg_a.SerializeAsString() == msg_b.SerializeAsString());
-}
-
-
#define DEFAULT_PORT 47584
#if defined(STEAM_WIN32)
@@ -36,9 +29,18 @@ typedef unsigned int sock_t;
typedef int sock_t;
#endif
+static inline bool protobuf_message_equal(
+ const google::protobuf::MessageLite& msg_a,
+ const google::protobuf::MessageLite& msg_b)
+{
+ return (msg_a.GetTypeName() == msg_b.GetTypeName()) &&
+ (msg_a.SerializeAsString() == msg_b.SerializeAsString());
+}
+
+
struct IP_PORT {
- uint32 ip;
- uint16 port;
+ uint32 ip{};
+ uint16 port{};
bool operator <(const IP_PORT& other) const
{
return (ip < other.ip) || (ip == other.ip && port < other.port);
@@ -46,9 +48,9 @@ struct IP_PORT {
};
struct Network_Callback {
- void (*message_callback)(void *object, Common_Message *msg);
- void *object;
- CSteamID steam_id;
+ void (*message_callback)(void *object, Common_Message *msg) = nullptr;
+ void *object{};
+ CSteamID steam_id{};
};
enum Callback_Ids {
@@ -73,39 +75,33 @@ struct Network_Callback_Container {
};
struct TCP_Socket {
- sock_t sock = ~0;
+ sock_t sock = static_cast(~0);
bool received_data = false;
- std::vector recv_buffer;
- std::vector send_buffer;
- std::chrono::high_resolution_clock::time_point last_heartbeat_sent, last_heartbeat_received;
+ std::vector recv_buffer{};
+ std::vector send_buffer{};
+ std::chrono::high_resolution_clock::time_point last_heartbeat_sent{}, last_heartbeat_received{};
};
struct Connection {
- struct TCP_Socket tcp_socket_outgoing, tcp_socket_incoming;
+ struct TCP_Socket tcp_socket_outgoing{}, tcp_socket_incoming{};
bool connected = false;
- IP_PORT udp_ip_port;
+ IP_PORT udp_ip_port{};
bool udp_pinged = false;
- IP_PORT tcp_ip_port;
- std::vector ids;
- uint32 appid;
- std::chrono::high_resolution_clock::time_point last_received;
+ IP_PORT tcp_ip_port{};
+ std::vector ids{};
+ uint32 appid{};
+ std::chrono::high_resolution_clock::time_point last_received{};
};
-class Networking {
+class Networking
+{
bool enabled = false;
- bool query_alive;
- std::chrono::high_resolution_clock::time_point last_run;
- sock_t query_socket, udp_socket, tcp_socket;
- uint16 udp_port, tcp_port;
- uint32 own_ip;
- std::vector connections;
- struct Connection *find_connection(CSteamID id, uint32 appid = 0);
- struct Connection *new_connection(CSteamID id, uint32 appid);
-
- bool handle_announce(Common_Message *msg, IP_PORT ip_port);
- bool handle_low_level_udp(Common_Message *msg, IP_PORT ip_port);
- bool handle_tcp(Common_Message *msg, struct TCP_Socket &socket);
- void send_announce_broadcasts();
+ bool query_alive{};
+ std::chrono::high_resolution_clock::time_point last_run{};
+ sock_t query_socket, udp_socket{}, tcp_socket{};
+ uint16 udp_port{}, tcp_port{};
+ uint32 own_ip{};
+ std::vector connections{};
std::vector ids;
uint32 appid;
@@ -118,18 +114,30 @@ class Networking {
struct Network_Callback_Container callbacks[CALLBACK_IDS_MAX];
std::vector local_send;
+ struct Connection *find_connection(CSteamID id, uint32 appid = 0);
+ struct Connection *new_connection(CSteamID id, uint32 appid);
+
+ bool handle_announce(Common_Message *msg, IP_PORT ip_port);
+ bool handle_low_level_udp(Common_Message *msg, IP_PORT ip_port);
+ bool handle_tcp(Common_Message *msg, struct TCP_Socket &socket);
+ void send_announce_broadcasts();
+
bool add_id_connection(struct Connection *connection, CSteamID steam_id);
void run_callbacks(Callback_Ids id, Common_Message *msg);
void run_callback_user(CSteamID steam_id, bool online, uint32 appid);
void do_callbacks_message(Common_Message *msg);
Common_Message create_announce(bool request);
+
+
public:
+ Networking(CSteamID id, uint32 appid, uint16 port, std::set *custom_broadcasts, bool disable_sockets);
+ ~Networking();
+
//NOTE: for all functions ips/ports are passed/returned in host byte order
//ex: 127.0.0.1 should be passed as 0x7F000001
static std::set resolve_ip(std::string dns);
- Networking(CSteamID id, uint32 appid, uint16 port, std::set *custom_broadcasts, bool disable_sockets);
- ~Networking();
+
void addListenId(CSteamID id);
void setAppID(uint32 appid);
void Run();
@@ -161,4 +169,4 @@ public:
bool isQueryAlive();
};
-#endif
+#endif // NETWORK_INCLUDE_H
diff --git a/dll/dll/settings.h b/dll/dll/settings.h
index 5f810aca..445b9573 100644
--- a/dll/dll/settings.h
+++ b/dll/dll/settings.h
@@ -15,54 +15,57 @@
License along with the Goldberg Emulator; if not, see
. */
-#ifndef SETTINGS_INCLUDE
-#define SETTINGS_INCLUDE
+#ifndef SETTINGS_INCLUDE_H
+#define SETTINGS_INCLUDE_H
#include "base.h"
struct IP_PORT;
struct DLC_entry {
- AppId_t appID;
- std::string name;
- bool available;
+ AppId_t appID{};
+ std::string name{};
+ bool available{};
};
struct Mod_entry {
- PublishedFileId_t id;
- std::string title;
- std::string path;
+ PublishedFileId_t id{};
+ std::string title{};
+ std::string path{};
+
+ std::string previewURL{};
+ EWorkshopFileType fileType{};
+ std::string description{};
+ uint64 steamIDOwner{};
+ uint32 timeCreated{};
+ uint32 timeUpdated{};
+ uint32 timeAddedToUserList{};
+ ERemoteStoragePublishedFileVisibility visibility{};
+ bool banned = false;
+ bool acceptedForUse{};
+ bool tagsTruncated{};
+ std::string tags{};
- std::string previewURL;
- EWorkshopFileType fileType;
- std::string description;
- uint64 steamIDOwner;
- uint32 timeCreated;
- uint32 timeUpdated;
- uint32 timeAddedToUserList;
- ERemoteStoragePublishedFileVisibility visibility;
- bool banned;
- bool acceptedForUse;
- bool tagsTruncated;
- std::string tags;
// file/url information
UGCHandle_t handleFile = generate_file_handle();
UGCHandle_t handlePreviewFile = generate_file_handle();
- std::string primaryFileName;
- int32 primaryFileSize;
- std::string previewFileName;
- int32 previewFileSize;
- std::string workshopItemURL;
+
+ std::string primaryFileName{};
+ int32 primaryFileSize{};
+ std::string previewFileName{};
+ int32 previewFileSize{};
+ std::string workshopItemURL{};
+
// voting information
- uint32 votesUp;
- uint32 votesDown;
- float score;
+ uint32 votesUp{};
+ uint32 votesDown{};
+ float score{};
+
// collection details
- uint32 numChildren;
+ uint32 numChildren{}; // TODO
private:
- UGCHandle_t generate_file_handle()
- {
+ UGCHandle_t generate_file_handle() {
static UGCHandle_t val = 0;
++val;
@@ -74,12 +77,12 @@ private:
};
struct Leaderboard_config {
- enum ELeaderboardSortMethod sort_method;
- enum ELeaderboardDisplayType display_type;
+ enum ELeaderboardSortMethod sort_method{};
+ enum ELeaderboardDisplayType display_type{};
};
struct Stat_config {
- GameServerStats_Messages::StatInfo::Stat_Type type;
+ GameServerStats_Messages::StatInfo::Stat_Type type{};
union {
float default_value_float;
int32 default_value_int;
@@ -87,21 +90,21 @@ struct Stat_config {
};
struct Image_Data {
- uint32 width;
- uint32 height;
- std::string data;
+ uint32 width{};
+ uint32 height{};
+ std::string data{};
};
struct Controller_Settings {
- std::map, std::string>>> action_sets;
- std::map action_set_layer_parents;
- std::map, std::string>>> action_set_layers;
+ std::map, std::string>>> action_sets{};
+ std::map action_set_layer_parents{};
+ std::map, std::string>>> action_set_layers{};
};
struct Group_Clans {
- CSteamID id;
- std::string name;
- std::string tag;
+ CSteamID id{};
+ std::string name{};
+ std::string tag{};
};
struct Overlay_Appearance {
@@ -112,7 +115,7 @@ struct Overlay_Appearance {
constexpr const static NotificationPosition default_pos = NotificationPosition::top_right;
- std::string font_override{}; // path to a custom user-provided font
+ std::string font_override{}; // path to a custom user-provided TTF font
float font_size = 16.0f;
float icon_size = 64.0f;
@@ -157,23 +160,12 @@ struct Overlay_Appearance {
NotificationPosition invite_pos = default_pos; // lobby/game invitation
NotificationPosition chat_msg_pos = NotificationPosition::top_center; // chat message from a friend
- static NotificationPosition translate_notification_position(const std::string &str)
- {
- if (str == "top_left") return NotificationPosition::top_left;
- else if (str == "top_center") return NotificationPosition::top_center;
- else if (str == "top_right") return NotificationPosition::top_right;
- else if (str == "bot_left") return NotificationPosition::bot_left;
- else if (str == "bot_center") return NotificationPosition::bot_center;
- else if (str == "bot_right") return NotificationPosition::bot_right;
-
- PRINT_DEBUG("Invalid position '%s'", str.c_str());
- return default_pos;
- }
+ static NotificationPosition translate_notification_position(const std::string &str);
};
class Settings {
- CSteamID steam_id; // user id
- CGameID game_id;
+ CSteamID steam_id{}; // user id
+ CGameID game_id{};
std::string name{};
std::string language{}; // default "english"
CSteamID lobby_id = k_steamIDNil;
@@ -294,17 +286,21 @@ public:
#ifdef LOBBY_CONNECT
- static const bool is_lobby_connect = true;
+ static constexpr const bool is_lobby_connect = true;
#else
- static const bool is_lobby_connect = false;
+ static constexpr const bool is_lobby_connect = false;
#endif
- static std::string sanitize(const std::string &name);
Settings(CSteamID steam_id, CGameID game_id, const std::string &name, const std::string &language, bool offline);
+
+ static std::string sanitize(const std::string &name);
+
CSteamID get_local_steam_id();
CGameID get_local_game_id();
+
const char *get_local_name();
void set_local_name(const char *name);
+
const char *get_language();
void set_language(const char *language);
@@ -313,9 +309,12 @@ public:
const std::string& get_supported_languages() const;
void set_game_id(CGameID game_id);
+
void set_lobby(CSteamID lobby_id);
CSteamID get_lobby();
+
bool is_offline();
+
uint16 get_port();
void set_port(uint16 port);
@@ -361,4 +360,4 @@ public:
};
-#endif
+#endif // SETTINGS_INCLUDE_H
diff --git a/dll/dll/settings_parser.h b/dll/dll/settings_parser.h
index f80ba39d..bb996d6c 100644
--- a/dll/dll/settings_parser.h
+++ b/dll/dll/settings_parser.h
@@ -15,10 +15,10 @@
License along with the Goldberg Emulator; if not, see
. */
-#include "settings.h"
+#ifndef SETTINGS_PARSER_INCLUDE_H
+#define SETTINGS_PARSER_INCLUDE_H
-#ifndef SETTINGS_PARSER_INCLUDE
-#define SETTINGS_PARSER_INCLUDE
+#include "settings.h"
//returns game appid
uint32 create_localstorage_settings(Settings **settings_client_out, Settings **settings_server_out, Local_Storage **local_storage_out);
@@ -55,4 +55,4 @@ enum class SettingsItf {
const std::map& settings_old_interfaces();
-#endif
+#endif // SETTINGS_PARSER_INCLUDE_H
diff --git a/dll/dll/source_query.h b/dll/dll/source_query.h
index 5f9742a7..9da08429 100644
--- a/dll/dll/source_query.h
+++ b/dll/dll/source_query.h
@@ -15,14 +15,18 @@
License along with the Goldberg Emulator; if not, see
. */
+#ifndef __INCLUDED_SOURCE_QUERY_H__
+#define __INCLUDED_SOURCE_QUERY_H__
+
#include "base.h"
class Source_Query
{
- Source_Query () = delete;
+ Source_Query() = delete;
~Source_Query() = delete;
public:
static std::vector handle_source_query(const void* buffer, size_t len, Gameserver const& gs);
};
+#endif // __INCLUDED_SOURCE_QUERY_H__
diff --git a/dll/dll/steam_HTMLsurface.h b/dll/dll/steam_HTMLsurface.h
index 1aea6483..201a2d78 100644
--- a/dll/dll/steam_HTMLsurface.h
+++ b/dll/dll/steam_HTMLsurface.h
@@ -15,6 +15,9 @@
License along with the Goldberg Emulator; if not, see
. */
+#ifndef __INCLUDED_STEAM_HTMLSURFACE_H__
+#define __INCLUDED_STEAM_HTMLSURFACE_H__
+
#include "base.h"
class Steam_HTMLsurface :
@@ -24,354 +27,166 @@ public ISteamHTMLSurface003,
public ISteamHTMLSurface004,
public ISteamHTMLSurface
{
- class Settings *settings;
- class Networking *network;
- class SteamCallResults *callback_results;
- class SteamCallBacks *callbacks;
+ class Settings *settings{};
+ class Networking *network{};
+ class SteamCallResults *callback_results{};
+ class SteamCallBacks *callbacks{};
public:
-Steam_HTMLsurface(class Settings *settings, class Networking *network, class SteamCallResults *callback_results, class SteamCallBacks *callbacks)
-{
- this->settings = settings;
- this->network = network;
- this->callback_results = callback_results;
- this->callbacks = callbacks;
-}
+ Steam_HTMLsurface(class Settings *settings, class Networking *network, class SteamCallResults *callback_results, class SteamCallBacks *callbacks);
-// Must call init and shutdown when starting/ending use of the interface
-bool Init()
-{
- PRINT_DEBUG_TODO();
- std::lock_guard lock(global_mutex);
- return true;
-}
+ // Must call init and shutdown when starting/ending use of the interface
+ bool Init();
-bool Shutdown()
-{
- PRINT_DEBUG_TODO();
- std::lock_guard lock(global_mutex);
- return true;
-}
+ bool Shutdown();
-// Create a browser object for display of a html page, when creation is complete the call handle
-// will return a HTML_BrowserReady_t callback for the HHTMLBrowser of your new browser.
-// The user agent string is a substring to be added to the general user agent string so you can
-// identify your client on web servers.
-// The userCSS string lets you apply a CSS style sheet to every displayed page, leave null if
-// you do not require this functionality.
-//
-// YOU MUST HAVE IMPLEMENTED HANDLERS FOR HTML_BrowserReady_t, HTML_StartRequest_t,
-// HTML_JSAlert_t, HTML_JSConfirm_t, and HTML_FileOpenDialog_t! See the CALLBACKS
-// section of this interface (AllowStartRequest, etc) for more details. If you do
-// not implement these callback handlers, the browser may appear to hang instead of
-// navigating to new pages or triggering javascript popups.
-//
-STEAM_CALL_RESULT( HTML_BrowserReady_t )
-SteamAPICall_t CreateBrowser( const char *pchUserAgent, const char *pchUserCSS )
-{
- PRINT_DEBUG_TODO();
- std::lock_guard lock(global_mutex);
- HTML_BrowserReady_t data;
- data.unBrowserHandle = 1234869;
-
- auto ret = callback_results->addCallResult(data.k_iCallback, &data, sizeof(data));
- callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
- return ret;
-}
+ // Create a browser object for display of a html page, when creation is complete the call handle
+ // will return a HTML_BrowserReady_t callback for the HHTMLBrowser of your new browser.
+ // The user agent string is a substring to be added to the general user agent string so you can
+ // identify your client on web servers.
+ // The userCSS string lets you apply a CSS style sheet to every displayed page, leave null if
+ // you do not require this functionality.
+ //
+ // YOU MUST HAVE IMPLEMENTED HANDLERS FOR HTML_BrowserReady_t, HTML_StartRequest_t,
+ // HTML_JSAlert_t, HTML_JSConfirm_t, and HTML_FileOpenDialog_t! See the CALLBACKS
+ // section of this interface (AllowStartRequest, etc) for more details. If you do
+ // not implement these callback handlers, the browser may appear to hang instead of
+ // navigating to new pages or triggering javascript popups.
+ //
+ STEAM_CALL_RESULT( HTML_BrowserReady_t )
+ SteamAPICall_t CreateBrowser( const char *pchUserAgent, const char *pchUserCSS );
-// Call this when you are done with a html surface, this lets us free the resources being used by it
-void RemoveBrowser( HHTMLBrowser unBrowserHandle )
-{
- PRINT_DEBUG_TODO();
- std::lock_guard lock(global_mutex);
-}
+ // Call this when you are done with a html surface, this lets us free the resources being used by it
+ void RemoveBrowser( HHTMLBrowser unBrowserHandle );
-// Navigate to this URL, results in a HTML_StartRequest_t as the request commences
-void LoadURL( HHTMLBrowser unBrowserHandle, const char *pchURL, const char *pchPostData )
-{
- PRINT_DEBUG("TODO %s %s", pchURL, pchPostData);
- std::lock_guard lock(global_mutex);
- static char url[256];
- strncpy(url, pchURL, sizeof(url));
- static char target[] = "_self";
- static char title[] = "title";
-
- {
- HTML_StartRequest_t data;
- data.unBrowserHandle = unBrowserHandle;
- data.pchURL = url;
- data.pchTarget = target;
- data.pchPostData = "";
- data.bIsRedirect = false;
- callbacks->addCBResult(data.k_iCallback, &data, sizeof(data), 0.1);
- }
-
- {
- HTML_FinishedRequest_t data;
- data.unBrowserHandle = unBrowserHandle;
- data.pchURL = url;
- data.pchPageTitle = title;
- callbacks->addCBResult(data.k_iCallback, &data, sizeof(data), 0.8);
- }
-
-}
+ // Navigate to this URL, results in a HTML_StartRequest_t as the request commences
+ void LoadURL( HHTMLBrowser unBrowserHandle, const char *pchURL, const char *pchPostData );
-// Tells the surface the size in pixels to display the surface
-void SetSize( HHTMLBrowser unBrowserHandle, uint32 unWidth, uint32 unHeight )
-{
- PRINT_DEBUG_TODO();
- std::lock_guard lock(global_mutex);
-}
+ // Tells the surface the size in pixels to display the surface
+ void SetSize( HHTMLBrowser unBrowserHandle, uint32 unWidth, uint32 unHeight );
-// Stop the load of the current html page
-void StopLoad( HHTMLBrowser unBrowserHandle )
-{
- PRINT_DEBUG_TODO();
- std::lock_guard lock(global_mutex);
-}
+ // Stop the load of the current html page
+ void StopLoad( HHTMLBrowser unBrowserHandle );
-// Reload (most likely from local cache) the current page
-void Reload( HHTMLBrowser unBrowserHandle )
-{
- PRINT_DEBUG_TODO();
- std::lock_guard lock(global_mutex);
-}
+ // Reload (most likely from local cache) the current page
+ void Reload( HHTMLBrowser unBrowserHandle );
-// navigate back in the page history
-void GoBack( HHTMLBrowser unBrowserHandle )
-{
- PRINT_DEBUG_TODO();
- std::lock_guard lock(global_mutex);
-}
+ // navigate back in the page history
+ void GoBack( HHTMLBrowser unBrowserHandle );
-// navigate forward in the page history
-void GoForward( HHTMLBrowser unBrowserHandle )
-{
- PRINT_DEBUG_TODO();
- std::lock_guard lock(global_mutex);
-}
+ // navigate forward in the page history
+ void GoForward( HHTMLBrowser unBrowserHandle );
-// add this header to any url requests from this browser
-void AddHeader( HHTMLBrowser unBrowserHandle, const char *pchKey, const char *pchValue )
-{
- PRINT_DEBUG_TODO();
- std::lock_guard lock(global_mutex);
-}
+ // add this header to any url requests from this browser
+ void AddHeader( HHTMLBrowser unBrowserHandle, const char *pchKey, const char *pchValue );
-// run this javascript script in the currently loaded page
-void ExecuteJavascript( HHTMLBrowser unBrowserHandle, const char *pchScript )
-{
- PRINT_DEBUG_TODO();
- std::lock_guard lock(global_mutex);
-}
+ // run this javascript script in the currently loaded page
+ void ExecuteJavascript( HHTMLBrowser unBrowserHandle, const char *pchScript );
-// Mouse click and mouse movement commands
-void MouseUp( HHTMLBrowser unBrowserHandle, EHTMLMouseButton eMouseButton )
-{
- PRINT_DEBUG_TODO();
- std::lock_guard lock(global_mutex);
-}
+ // Mouse click and mouse movement commands
+ void MouseUp( HHTMLBrowser unBrowserHandle, EHTMLMouseButton eMouseButton );
-void MouseDown( HHTMLBrowser unBrowserHandle, EHTMLMouseButton eMouseButton )
-{
- PRINT_DEBUG_TODO();
- std::lock_guard lock(global_mutex);
-}
+ void MouseDown( HHTMLBrowser unBrowserHandle, EHTMLMouseButton eMouseButton );
-void MouseDoubleClick( HHTMLBrowser unBrowserHandle, EHTMLMouseButton eMouseButton )
-{
- PRINT_DEBUG_TODO();
- std::lock_guard lock(global_mutex);
-}
+ void MouseDoubleClick( HHTMLBrowser unBrowserHandle, EHTMLMouseButton eMouseButton );
-// x and y are relative to the HTML bounds
-void MouseMove( HHTMLBrowser unBrowserHandle, int x, int y )
-{
- PRINT_DEBUG_TODO();
- std::lock_guard lock(global_mutex);
-}
+ // x and y are relative to the HTML bounds
+ void MouseMove( HHTMLBrowser unBrowserHandle, int x, int y );
-// nDelta is pixels of scroll
-void MouseWheel( HHTMLBrowser unBrowserHandle, int32 nDelta )
-{
- PRINT_DEBUG_TODO();
- std::lock_guard lock(global_mutex);
-}
+ // nDelta is pixels of scroll
+ void MouseWheel( HHTMLBrowser unBrowserHandle, int32 nDelta );
-// keyboard interactions, native keycode is the key code value from your OS
-void KeyDown( HHTMLBrowser unBrowserHandle, uint32 nNativeKeyCode, EHTMLKeyModifiers eHTMLKeyModifiers, bool bIsSystemKey = false )
-{
- PRINT_DEBUG_TODO();
- std::lock_guard lock(global_mutex);
-}
+ // keyboard interactions, native keycode is the key code value from your OS
+ void KeyDown( HHTMLBrowser unBrowserHandle, uint32 nNativeKeyCode, EHTMLKeyModifiers eHTMLKeyModifiers, bool bIsSystemKey = false );
-void KeyDown( HHTMLBrowser unBrowserHandle, uint32 nNativeKeyCode, EHTMLKeyModifiers eHTMLKeyModifiers)
-{
- PRINT_DEBUG_TODO();
- std::lock_guard lock(global_mutex);
- KeyDown(unBrowserHandle, nNativeKeyCode, eHTMLKeyModifiers, false);
-}
+ void KeyDown( HHTMLBrowser unBrowserHandle, uint32 nNativeKeyCode, EHTMLKeyModifiers eHTMLKeyModifiers);
-void KeyUp( HHTMLBrowser unBrowserHandle, uint32 nNativeKeyCode, EHTMLKeyModifiers eHTMLKeyModifiers )
-{
- PRINT_DEBUG_ENTRY();
- std::lock_guard lock(global_mutex);
-}
+ void KeyUp( HHTMLBrowser unBrowserHandle, uint32 nNativeKeyCode, EHTMLKeyModifiers eHTMLKeyModifiers );
-// cUnicodeChar is the unicode character point for this keypress (and potentially multiple chars per press)
-void KeyChar( HHTMLBrowser unBrowserHandle, uint32 cUnicodeChar, EHTMLKeyModifiers eHTMLKeyModifiers )
-{
- PRINT_DEBUG_TODO();
- std::lock_guard lock(global_mutex);
-}
+ // cUnicodeChar is the unicode character point for this keypress (and potentially multiple chars per press)
+ void KeyChar( HHTMLBrowser unBrowserHandle, uint32 cUnicodeChar, EHTMLKeyModifiers eHTMLKeyModifiers );
-// programmatically scroll this many pixels on the page
-void SetHorizontalScroll( HHTMLBrowser unBrowserHandle, uint32 nAbsolutePixelScroll )
-{
- PRINT_DEBUG_TODO();
- std::lock_guard lock(global_mutex);
-}
+ // programmatically scroll this many pixels on the page
+ void SetHorizontalScroll( HHTMLBrowser unBrowserHandle, uint32 nAbsolutePixelScroll );
-void SetVerticalScroll( HHTMLBrowser unBrowserHandle, uint32 nAbsolutePixelScroll )
-{
- PRINT_DEBUG_TODO();
- std::lock_guard lock(global_mutex);
-}
+ void SetVerticalScroll( HHTMLBrowser unBrowserHandle, uint32 nAbsolutePixelScroll );
-// tell the html control if it has key focus currently, controls showing the I-beam cursor in text controls amongst other things
-void SetKeyFocus( HHTMLBrowser unBrowserHandle, bool bHasKeyFocus )
-{
- PRINT_DEBUG_TODO();
- std::lock_guard lock(global_mutex);
-}
+ // tell the html control if it has key focus currently, controls showing the I-beam cursor in text controls amongst other things
+ void SetKeyFocus( HHTMLBrowser unBrowserHandle, bool bHasKeyFocus );
-// open the current pages html code in the local editor of choice, used for debugging
-void ViewSource( HHTMLBrowser unBrowserHandle )
-{
- PRINT_DEBUG_TODO();
- std::lock_guard lock(global_mutex);
-}
+ // open the current pages html code in the local editor of choice, used for debugging
+ void ViewSource( HHTMLBrowser unBrowserHandle );
-// copy the currently selected text on the html page to the local clipboard
-void CopyToClipboard( HHTMLBrowser unBrowserHandle )
-{
- PRINT_DEBUG_TODO();
- std::lock_guard lock(global_mutex);
-}
+ // copy the currently selected text on the html page to the local clipboard
+ void CopyToClipboard( HHTMLBrowser unBrowserHandle );
-// paste from the local clipboard to the current html page
-void PasteFromClipboard( HHTMLBrowser unBrowserHandle )
-{
- PRINT_DEBUG_TODO();
- std::lock_guard lock(global_mutex);
-}
+ // paste from the local clipboard to the current html page
+ void PasteFromClipboard( HHTMLBrowser unBrowserHandle );
-// find this string in the browser, if bCurrentlyInFind is true then instead cycle to the next matching element
-void Find( HHTMLBrowser unBrowserHandle, const char *pchSearchStr, bool bCurrentlyInFind, bool bReverse )
-{
- PRINT_DEBUG_TODO();
- std::lock_guard lock(global_mutex);
-}
+ // find this string in the browser, if bCurrentlyInFind is true then instead cycle to the next matching element
+ void Find( HHTMLBrowser unBrowserHandle, const char *pchSearchStr, bool bCurrentlyInFind, bool bReverse );
-// cancel a currently running find
-void StopFind( HHTMLBrowser unBrowserHandle )
-{
- PRINT_DEBUG_TODO();
- std::lock_guard