Squashed commit of the following:
commit f44d146e4ac906ff898e8968c6857fd2280f6d20 Author: project-bo4 <127137346+project-bo4@users.noreply.github.com> Date: Thu May 11 13:39:29 2023 -0700 remove lpc package from repository commit 29fb0f63e50de468ab0b9db35f7e8fdadf58afc3 Author: project-bo4 <themanwithantidote@gmail.com> Date: Thu May 11 13:06:13 2023 -0700 generic improvements + added identity configuration + objectstore improvements + added battlenet 'US' servers to blocklist + some other minor improvements commit 5d5e31099ebcce5a637b9a02d4936a97fb0802a7 Author: project-bo4 <themanwithantidote@gmail.com> Date: Sat Mar 25 16:32:52 2023 -0700 lpc improvements + fix lpc issue with foreign languages(non-english) not being considered in listing + check lpc files pre-start and warn user if missing any of core items commit 2de1a54b6f4cc5c44dc906871021cfbc85057ca9 Author: project-bo4 <themanwithantidote@gmail.com> Date: Thu Mar 23 12:45:56 2023 -0700 demonware improvements + handle object store uploadUserObject + silence bdUNK125 commit 710dcc3ec6178071d67c27e5bf6705f08cabe7e2 Author: project-bo4 <themanwithantidote@gmail.com> Date: Mon Mar 20 13:43:56 2023 -0700 forgot to update names commit 217682dfb07b35f7a09399fb2698924bb7fe8b77 Author: project-bo4 <themanwithantidote@gmail.com> Date: Mon Mar 20 11:09:18 2023 -0700 upload lpc and update readme commit 83f812b33b90791a8d13b9468f27da51e0a4f2b9 Author: project-bo4 <themanwithantidote@gmail.com> Date: Mon Mar 20 10:53:43 2023 -0700 demonware emulator + demonware emulator + platform name and id + xxhash and picoproto - remove g_runframe hook -disable discovery(save time) + improvements to utils + add new resources
This commit is contained in:
@ -1,30 +1,137 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
#include <utils/hook.hpp>
|
||||
|
||||
#include <utils/io.hpp>
|
||||
#include <utils/hook.hpp>
|
||||
#include <utils/thread.hpp>
|
||||
|
||||
#include "demonware/servers/lobby_server.hpp"
|
||||
#include "demonware/servers/auth3_server.hpp"
|
||||
#include "demonware/servers/stun_server.hpp"
|
||||
#include "demonware/servers/umbrella_server.hpp"
|
||||
#include "demonware/server_registry.hpp"
|
||||
|
||||
#define TCP_BLOCKING true
|
||||
#define UDP_BLOCKING false
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
const char* blocked_hosts[] =
|
||||
const char* blocked_hosts[] =
|
||||
{
|
||||
"us.cdn.blizzard.com",
|
||||
"us.actual.battle.net",
|
||||
"eu.cdn.blizzard.com",
|
||||
"eu.actual.battle.net",
|
||||
"level3.blizzard.com",
|
||||
"blzddist1-a.akamaihd.net",
|
||||
"level3.ssl.blizzard.com",
|
||||
"eu.actual.battle.net"
|
||||
"level3.ssl.blizzard.com"
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
std::atomic_bool exit_server{ false };
|
||||
std::thread server_thread{};
|
||||
utils::concurrency::container<std::unordered_map<SOCKET, bool>> blocking_sockets{};
|
||||
utils::concurrency::container<std::unordered_map<SOCKET, tcp_server*>> socket_map{};
|
||||
server_registry<tcp_server> tcp_servers{};
|
||||
server_registry<udp_server> udp_servers{};
|
||||
std::unordered_map<void*, void*> original_imports{};
|
||||
|
||||
namespace network
|
||||
tcp_server* find_server(const SOCKET socket)
|
||||
{
|
||||
return socket_map.access<tcp_server*>([&](const std::unordered_map<SOCKET, tcp_server*>& map) -> tcp_server*
|
||||
{
|
||||
const auto entry = map.find(socket);
|
||||
if (entry == map.end())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return entry->second;
|
||||
});
|
||||
}
|
||||
|
||||
bool socket_link(const SOCKET socket, const uint32_t address)
|
||||
{
|
||||
auto* server = tcp_servers.find(address);
|
||||
if (!server)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
socket_map.access([&](std::unordered_map<SOCKET, tcp_server*>& map)
|
||||
{
|
||||
map[socket] = server;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void socket_unlink(const SOCKET socket)
|
||||
{
|
||||
socket_map.access([&](std::unordered_map<SOCKET, tcp_server*>& map)
|
||||
{
|
||||
const auto entry = map.find(socket);
|
||||
if (entry != map.end())
|
||||
{
|
||||
map.erase(entry);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool is_socket_blocking(const SOCKET socket, const bool def)
|
||||
{
|
||||
return blocking_sockets.access<bool>([&](std::unordered_map<SOCKET, bool>& map)
|
||||
{
|
||||
const auto entry = map.find(socket);
|
||||
if (entry == map.end())
|
||||
{
|
||||
return def;
|
||||
}
|
||||
|
||||
return entry->second;
|
||||
});
|
||||
}
|
||||
|
||||
void remove_blocking_socket(const SOCKET socket)
|
||||
{
|
||||
blocking_sockets.access([&](std::unordered_map<SOCKET, bool>& map)
|
||||
{
|
||||
const auto entry = map.find(socket);
|
||||
if (entry != map.end())
|
||||
{
|
||||
map.erase(entry);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void add_blocking_socket(const SOCKET socket, const bool block)
|
||||
{
|
||||
blocking_sockets.access([&](std::unordered_map<SOCKET, bool>& map)
|
||||
{
|
||||
map[socket] = block;
|
||||
});
|
||||
}
|
||||
|
||||
void server_main()
|
||||
{
|
||||
exit_server = false;
|
||||
|
||||
while (!exit_server)
|
||||
{
|
||||
tcp_servers.frame();
|
||||
udp_servers.frame();
|
||||
std::this_thread::sleep_for(50ms);
|
||||
}
|
||||
}
|
||||
|
||||
namespace io
|
||||
{
|
||||
int getaddrinfo_stub(const char* name, const char* service,
|
||||
const addrinfo* hints, addrinfo** res)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
logger::write(logger::LOG_TYPE_DEBUG, "[ NETWORK ]: [getaddrinfo]: \"%s\" \"%s\"", name, service);
|
||||
#ifndef NDEBUG
|
||||
logger::write(logger::LOG_TYPE_DEBUG, "[ network ]: [getaddrinfo]: \"%s\" \"%s\"", name, service);
|
||||
#endif
|
||||
|
||||
for (auto i = 0; i < ARRAYSIZE(blocked_hosts); ++i)
|
||||
@ -35,22 +142,299 @@ namespace demonware
|
||||
}
|
||||
}
|
||||
|
||||
return WSAHOST_NOT_FOUND;
|
||||
/* TODO: RE-ROUTE DW HOSTS TO CUSTOM DW SERVER */
|
||||
base_server* server = tcp_servers.find(name);
|
||||
if (!server)
|
||||
{
|
||||
server = udp_servers.find(name);
|
||||
}
|
||||
|
||||
return getaddrinfo(name, service, hints, res);
|
||||
if (!server)
|
||||
{
|
||||
return getaddrinfo(name, service, hints, res);
|
||||
}
|
||||
|
||||
const auto address = utils::memory::get_allocator()->allocate<sockaddr>();
|
||||
const auto ai = utils::memory::get_allocator()->allocate<addrinfo>();
|
||||
|
||||
auto in_addr = reinterpret_cast<sockaddr_in*>(address);
|
||||
in_addr->sin_addr.s_addr = server->get_address();
|
||||
in_addr->sin_family = AF_INET;
|
||||
|
||||
ai->ai_family = AF_INET;
|
||||
ai->ai_socktype = SOCK_STREAM;
|
||||
ai->ai_addr = address;
|
||||
ai->ai_addrlen = sizeof(sockaddr);
|
||||
ai->ai_next = nullptr;
|
||||
ai->ai_flags = 0;
|
||||
ai->ai_protocol = 0;
|
||||
ai->ai_canonname = const_cast<char*>(name);
|
||||
|
||||
*res = ai;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void freeaddrinfo_stub(addrinfo* ai)
|
||||
{
|
||||
if (!utils::memory::get_allocator()->find(ai))
|
||||
{
|
||||
return freeaddrinfo(ai);
|
||||
}
|
||||
|
||||
utils::memory::get_allocator()->free(ai->ai_addr);
|
||||
utils::memory::get_allocator()->free(ai);
|
||||
}
|
||||
|
||||
int getpeername_stub(const SOCKET s, sockaddr* addr, socklen_t* addrlen)
|
||||
{
|
||||
auto* server = find_server(s);
|
||||
|
||||
if (server)
|
||||
{
|
||||
auto in_addr = reinterpret_cast<sockaddr_in*>(addr);
|
||||
in_addr->sin_addr.s_addr = server->get_address();
|
||||
in_addr->sin_family = AF_INET;
|
||||
*addrlen = sizeof(sockaddr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return getpeername(s, addr, addrlen);
|
||||
}
|
||||
|
||||
int getsockname_stub(const SOCKET s, sockaddr* addr, socklen_t* addrlen)
|
||||
{
|
||||
auto* server = find_server(s);
|
||||
|
||||
if (server)
|
||||
{
|
||||
auto in_addr = reinterpret_cast<sockaddr_in*>(addr);
|
||||
in_addr->sin_addr.s_addr = server->get_address();
|
||||
in_addr->sin_family = AF_INET;
|
||||
*addrlen = sizeof(sockaddr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return getsockname(s, addr, addrlen);
|
||||
}
|
||||
|
||||
hostent* gethostbyname_stub(const char* name)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
logger::write(logger::LOG_TYPE_DEBUG, "[ NETWORK ]: [gethostbyname]: \"%s\"", name);
|
||||
#ifndef NDEBUG
|
||||
logger::write(logger::LOG_TYPE_DEBUG, "[ network ]: [gethostbyname]: \"%s\"", name);
|
||||
#endif
|
||||
|
||||
base_server* server = tcp_servers.find(name);
|
||||
if (!server)
|
||||
{
|
||||
server = udp_servers.find(name);
|
||||
}
|
||||
|
||||
if (!server)
|
||||
{
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4996)
|
||||
return gethostbyname(name);
|
||||
return gethostbyname(name);
|
||||
#pragma warning(pop)
|
||||
}
|
||||
|
||||
static thread_local in_addr address{};
|
||||
address.s_addr = server->get_address();
|
||||
|
||||
static thread_local in_addr* addr_list[2]{};
|
||||
addr_list[0] = &address;
|
||||
addr_list[1] = nullptr;
|
||||
|
||||
static thread_local hostent host{};
|
||||
host.h_name = const_cast<char*>(name);
|
||||
host.h_aliases = nullptr;
|
||||
host.h_addrtype = AF_INET;
|
||||
host.h_length = sizeof(in_addr);
|
||||
host.h_addr_list = reinterpret_cast<char**>(addr_list);
|
||||
|
||||
return &host;
|
||||
}
|
||||
|
||||
int connect_stub(const SOCKET s, const struct sockaddr* addr, const int len)
|
||||
{
|
||||
if (len == sizeof(sockaddr_in))
|
||||
{
|
||||
const auto* in_addr = reinterpret_cast<const sockaddr_in*>(addr);
|
||||
if (socket_link(s, in_addr->sin_addr.s_addr)) return 0;
|
||||
}
|
||||
|
||||
return connect(s, addr, len);
|
||||
}
|
||||
|
||||
int closesocket_stub(const SOCKET s)
|
||||
{
|
||||
remove_blocking_socket(s);
|
||||
socket_unlink(s);
|
||||
|
||||
return closesocket(s);
|
||||
}
|
||||
|
||||
int send_stub(const SOCKET s, const char* buf, const int len, const int flags)
|
||||
{
|
||||
auto* server = find_server(s);
|
||||
|
||||
if (server)
|
||||
{
|
||||
server->handle_input(buf, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
return send(s, buf, len, flags);
|
||||
}
|
||||
|
||||
int recv_stub(const SOCKET s, char* buf, const int len, const int flags)
|
||||
{
|
||||
auto* server = find_server(s);
|
||||
|
||||
if (server)
|
||||
{
|
||||
if (server->pending_data())
|
||||
{
|
||||
return static_cast<int>(server->handle_output(buf, len));
|
||||
}
|
||||
else
|
||||
{
|
||||
WSASetLastError(WSAEWOULDBLOCK);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return recv(s, buf, len, flags);
|
||||
}
|
||||
|
||||
int sendto_stub(const SOCKET s, const char* buf, const int len, const int flags, const sockaddr* to,
|
||||
const int tolen)
|
||||
{
|
||||
const auto* in_addr = reinterpret_cast<const sockaddr_in*>(to);
|
||||
auto* server = udp_servers.find(in_addr->sin_addr.s_addr);
|
||||
|
||||
if (server)
|
||||
{
|
||||
server->handle_input(buf, len, { s, to, tolen });
|
||||
return len;
|
||||
}
|
||||
|
||||
return sendto(s, buf, len, flags, to, tolen);
|
||||
}
|
||||
|
||||
int recvfrom_stub(const SOCKET s, char* buf, const int len, const int flags, struct sockaddr* from,
|
||||
int* fromlen)
|
||||
{
|
||||
// Not supported yet
|
||||
if (is_socket_blocking(s, UDP_BLOCKING))
|
||||
{
|
||||
return recvfrom(s, buf, len, flags, from, fromlen);
|
||||
}
|
||||
|
||||
size_t result = 0;
|
||||
udp_servers.for_each([&](udp_server& server)
|
||||
{
|
||||
if (server.pending_data(s))
|
||||
{
|
||||
result = server.handle_output(
|
||||
s, buf, static_cast<size_t>(len), from, fromlen);
|
||||
}
|
||||
});
|
||||
|
||||
if (result)
|
||||
{
|
||||
return static_cast<int>(result);
|
||||
}
|
||||
|
||||
return recvfrom(s, buf, len, flags, from, fromlen);
|
||||
}
|
||||
|
||||
int select_stub(const int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds,
|
||||
struct timeval* timeout)
|
||||
{
|
||||
if (exit_server)
|
||||
{
|
||||
return select(nfds, readfds, writefds, exceptfds, timeout);
|
||||
}
|
||||
|
||||
auto result = 0;
|
||||
std::vector<SOCKET> read_sockets;
|
||||
std::vector<SOCKET> write_sockets;
|
||||
|
||||
socket_map.access([&](std::unordered_map<SOCKET, tcp_server*>& sockets)
|
||||
{
|
||||
for (auto& s : sockets)
|
||||
{
|
||||
if (readfds)
|
||||
{
|
||||
if (FD_ISSET(s.first, readfds))
|
||||
{
|
||||
if (s.second->pending_data())
|
||||
{
|
||||
read_sockets.push_back(s.first);
|
||||
FD_CLR(s.first, readfds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (writefds)
|
||||
{
|
||||
if (FD_ISSET(s.first, writefds))
|
||||
{
|
||||
write_sockets.push_back(s.first);
|
||||
FD_CLR(s.first, writefds);
|
||||
}
|
||||
}
|
||||
|
||||
if (exceptfds)
|
||||
{
|
||||
if (FD_ISSET(s.first, exceptfds))
|
||||
{
|
||||
FD_CLR(s.first, exceptfds);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if ((!readfds || readfds->fd_count == 0) && (!writefds || writefds->fd_count == 0))
|
||||
{
|
||||
timeout->tv_sec = 0;
|
||||
timeout->tv_usec = 0;
|
||||
}
|
||||
|
||||
result = select(nfds, readfds, writefds, exceptfds, timeout);
|
||||
if (result < 0) result = 0;
|
||||
|
||||
for (const auto& socket : read_sockets)
|
||||
{
|
||||
if (readfds)
|
||||
{
|
||||
FD_SET(socket, readfds);
|
||||
result++;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& socket : write_sockets)
|
||||
{
|
||||
if (writefds)
|
||||
{
|
||||
FD_SET(socket, writefds);
|
||||
result++;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int ioctlsocket_stub(const SOCKET s, const long cmd, u_long* argp)
|
||||
{
|
||||
if (static_cast<unsigned long>(cmd) == (FIONBIO))
|
||||
{
|
||||
add_blocking_socket(s, *argp == 0);
|
||||
}
|
||||
|
||||
return ioctlsocket(s, cmd, argp);
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,6 +453,15 @@ namespace demonware
|
||||
|
||||
original_imports[result->first] = result->second;
|
||||
}
|
||||
|
||||
void check_lpc_files()
|
||||
{
|
||||
if (!utils::io::file_exists("LPC/.manifest") || !utils::io::file_exists("LPC/core_ffotd_tu23_639_cf92ecf4a75d3f79.ff") || !utils::io::file_exists("LPC/core_playlists_tu23_639_cf92ecf4a75d3f79.ff"))
|
||||
{
|
||||
MessageBoxA(nullptr, "some required LPC files seems to be missing. You need to get and place them manually since this emulator doesnt host and provide those files; read instructions in github documentation for more info.",
|
||||
"LPC Files Missing", MB_ICONERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
@ -76,17 +469,39 @@ namespace demonware
|
||||
public:
|
||||
component()
|
||||
{
|
||||
/* PLACE_HOLDER */
|
||||
udp_servers.create<stun_server>("ops4-stun.us.demonware.net");
|
||||
udp_servers.create<stun_server>("ops4-stun.eu.demonware.net");
|
||||
udp_servers.create<stun_server>("ops4-stun.jp.demonware.net");
|
||||
udp_servers.create<stun_server>("ops4-stun.au.demonware.net");
|
||||
|
||||
tcp_servers.create<auth3_server>("ops4-pc-auth3.prod.demonware.net");
|
||||
tcp_servers.create<lobby_server>("ops4-pc-lobby.prod.demonware.net");
|
||||
tcp_servers.create<umbrella_server>("prod.umbrella.demonware.net");
|
||||
}
|
||||
|
||||
void pre_start() override
|
||||
{
|
||||
register_hook("gethostbyname", network::gethostbyname_stub);
|
||||
register_hook("getaddrinfo", network::getaddrinfo_stub);
|
||||
register_hook("send", io::send_stub);
|
||||
register_hook("recv", io::recv_stub);
|
||||
register_hook("sendto", io::sendto_stub);
|
||||
register_hook("recvfrom", io::recvfrom_stub);
|
||||
register_hook("connect", io::connect_stub);
|
||||
register_hook("select", io::select_stub);
|
||||
register_hook("closesocket", io::closesocket_stub);
|
||||
register_hook("ioctlsocket", io::ioctlsocket_stub);
|
||||
register_hook("gethostbyname", io::gethostbyname_stub);
|
||||
register_hook("getaddrinfo", io::getaddrinfo_stub);
|
||||
register_hook("freeaddrinfo", io::freeaddrinfo_stub);
|
||||
register_hook("getpeername", io::getpeername_stub);
|
||||
register_hook("getsockname", io::getsockname_stub);
|
||||
|
||||
check_lpc_files();
|
||||
}
|
||||
|
||||
void post_unpack() override
|
||||
{
|
||||
server_thread = utils::thread::create_named_thread("Demonware", server_main);
|
||||
|
||||
utils::hook::set<uint8_t>(0x144508469_g, 0x0); // CURLOPT_SSL_VERIFYPEER
|
||||
utils::hook::set<uint8_t>(0x144508455_g, 0xAF); // CURLOPT_SSL_VERIFYHOST
|
||||
utils::hook::set<uint8_t>(0x144B28D98_g, 0x0); // HTTPS -> HTTP
|
||||
@ -94,19 +509,16 @@ namespace demonware
|
||||
utils::hook::copy_string(0x144A27C70_g, "http://prod.umbrella.demonware.net");
|
||||
utils::hook::copy_string(0x144A2BAA0_g, "http://prod.uno.demonware.net/v1.0");
|
||||
utils::hook::copy_string(0x144A29CB0_g, "http://%s:%d/auth/");
|
||||
|
||||
|
||||
/*************************************************************************************************************
|
||||
** TODO : in order to record match, while playing (as host?) game live-streams netcode to the content server
|
||||
** continuously troughout the play time. planning to patch it so it streams in memory before uploading
|
||||
** full demo at end of match to improve network performance
|
||||
**
|
||||
**
|
||||
*************************************************************************************************************/
|
||||
}
|
||||
|
||||
void pre_destroy() override
|
||||
{
|
||||
exit_server = true;
|
||||
if (server_thread.joinable())
|
||||
{
|
||||
server_thread.join();
|
||||
}
|
||||
|
||||
for (const auto& import : original_imports)
|
||||
{
|
||||
utils::hook::set(import.first, import.second);
|
||||
|
@ -72,7 +72,7 @@ namespace exception
|
||||
utils::thread::suspend_other_threads();
|
||||
show_mouse_cursor();
|
||||
|
||||
MessageBoxA(nullptr, error_str.data(), "Project-bo4 ERROR", MB_ICONERROR);
|
||||
MessageBoxA(nullptr, error_str.data(), "Project-BO4 ERROR", MB_ICONERROR);
|
||||
TerminateProcess(GetCurrentProcess(), exception_data.code);
|
||||
}
|
||||
|
||||
@ -84,7 +84,7 @@ namespace exception
|
||||
++recovery_data.recovery_counts;
|
||||
|
||||
game::Com_Error(game::ERR_DROP, "Fatal error (0x%08X) at 0x%p (0x%p).\nA minidump has been written.\n\n"
|
||||
"BOIII has tried to recover your game, but it might not run stable anymore.\n\n"
|
||||
"Project-BO4 has tried to recover your game, but it might not run stable anymore.\n\n"
|
||||
"Make sure to update your graphics card drivers and install operating system updates!\n"
|
||||
"Closing or restarting Steam might also help.",
|
||||
exception_data.code, exception_data.address,
|
||||
@ -129,7 +129,7 @@ namespace exception
|
||||
info.append("\r\n");
|
||||
};
|
||||
|
||||
line("Project-bo4 Crash Dump");
|
||||
line("Project-BO4 Crash Dump");
|
||||
line("");
|
||||
line(game::version_string);
|
||||
//line("Version: "s + VERSION);
|
||||
|
31
source/proxy-dll/component/experimental.cpp
Normal file
31
source/proxy-dll/component/experimental.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
#include <std_include.hpp>
|
||||
#include <utils/hook.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
namespace experimental
|
||||
{
|
||||
namespace
|
||||
{
|
||||
utils::hook::detour liveinventory_getitemquantity_hook;
|
||||
int liveinventory_getitemquantity_stub(int controller_index, const int item_id)
|
||||
{
|
||||
return 1; // TODO: Higher quanity for zombie consumable loot
|
||||
|
||||
return liveinventory_getitemquantity_hook.invoke<int>(controller_index, item_id);
|
||||
}
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
void post_unpack() override
|
||||
{
|
||||
liveinventory_getitemquantity_hook.create(0x1437F6ED0_g, liveinventory_getitemquantity_stub);
|
||||
|
||||
utils::hook::set(0x142DD0E10_g, 0xC301B0); // Live_Qos_Finished
|
||||
utils::hook::set(0x1438C2C70_g, 0xC301B0); // Live_Contracts? related to bdUNK125
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(experimental::component)
|
@ -8,23 +8,20 @@
|
||||
|
||||
namespace logger
|
||||
{
|
||||
std::string get_type_str(const int type)
|
||||
const char* LogTypeNames[] =
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case 1:
|
||||
return "INFO";
|
||||
case 2:
|
||||
return "WARN";
|
||||
case 3:
|
||||
return "ERROR";
|
||||
default:
|
||||
return "DEBUG";
|
||||
}
|
||||
}
|
||||
"DEBUG",
|
||||
"INFO",
|
||||
"WARN",
|
||||
"ERROR"
|
||||
};
|
||||
|
||||
void write(const int type, std::string str)
|
||||
{
|
||||
#ifndef _DEBUG
|
||||
if (type == LOG_TYPE_DEBUG) return;
|
||||
#endif // _DEBUG
|
||||
|
||||
#ifdef OUTPUT_DEBUG_API
|
||||
OutputDebugStringA(str.c_str());
|
||||
#endif // OUTPUT_DEBUG_API
|
||||
@ -38,7 +35,7 @@ namespace logger
|
||||
stream << "" << std::put_time(t, "%Y-%m-%d %H:%M:%S") << "\t";
|
||||
#endif // PREPEND_TIMESTAMP
|
||||
|
||||
stream << "[ " << get_type_str(type) << " ] " << str << std::endl;
|
||||
stream << "[ " << LogTypeNames[type] << " ] " << str << std::endl;
|
||||
}
|
||||
|
||||
void write(const int type, const char* fmt, ...)
|
||||
@ -64,6 +61,10 @@ namespace logger
|
||||
public:
|
||||
void pre_start() override
|
||||
{
|
||||
#ifdef REMOVE_PREVIOUS_LOG
|
||||
utils::io::remove_file("project-bo4.log");
|
||||
#endif // REMOVE_PREVIOUS_LOG
|
||||
|
||||
write(LOG_TYPE_INFO, "=======================================================================================================");
|
||||
write(LOG_TYPE_INFO, " Project-BO4 Initializing ... %s[0x%llX]", utils::nt::library{}.get_name().c_str(), utils::nt::library{}.get_ptr());
|
||||
write(LOG_TYPE_INFO, "=======================================================================================================");
|
||||
@ -75,4 +76,4 @@ namespace logger
|
||||
}
|
||||
};
|
||||
}
|
||||
REGISTER_COMPONENT(logger::component)
|
||||
REGISTER_COMPONENT(logger::component)
|
@ -1,22 +1,53 @@
|
||||
#include <std_include.hpp>
|
||||
#include "platform.hpp"
|
||||
#include "loader/component_loader.hpp"
|
||||
#include "utils/hook.hpp"
|
||||
#include <utils/hook.hpp>
|
||||
#include <utils/string.hpp>
|
||||
#include <utils/identity.hpp>
|
||||
#include <utils/json_config.hpp>
|
||||
#include <utils/cryptography.hpp>
|
||||
#include "WinReg.hpp"
|
||||
#include "definitions/t8_engine.hpp"
|
||||
|
||||
namespace platform
|
||||
{
|
||||
uint64_t bnet_get_userid()
|
||||
{
|
||||
static uint64_t userid = 0;
|
||||
if (!userid)
|
||||
{
|
||||
uint32_t default_xuid = utils::cryptography::xxh32::compute(utils::identity::get_sys_username());
|
||||
userid = utils::json_config::ReadUnsignedInteger("identity", "xuid", default_xuid);
|
||||
}
|
||||
|
||||
return userid;
|
||||
}
|
||||
|
||||
const char* bnet_get_username()
|
||||
{
|
||||
static std::string username{};
|
||||
if (username.empty())
|
||||
{
|
||||
std::string default_name = utils::identity::get_sys_username();
|
||||
username = utils::json_config::ReadString("identity", "name", default_name);
|
||||
}
|
||||
|
||||
return username.data();
|
||||
}
|
||||
|
||||
std::string get_userdata_directory()
|
||||
{
|
||||
return std::format("players/bnet-{}", bnet_get_userid());
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
//utils::hook::detour BattleNet_API_RequestAppTicket_Hook;
|
||||
//bool BattleNet_API_RequestAppTicket_stub(char* sessionToken, char* accountToken)
|
||||
//{
|
||||
// /* PLACE_HOLDER */
|
||||
//}
|
||||
|
||||
utils::hook::detour PC_TextChat_Print_Hook;
|
||||
void PC_TextChat_Print_Stub(const char* text)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
logger::write(logger::LOG_TYPE_DEBUG, "PC_TextChat_Print(%s)", text);
|
||||
#endif
|
||||
}
|
||||
|
||||
void check_platform_registry()
|
||||
@ -51,16 +82,19 @@ namespace platform
|
||||
utils::hook::set<uint8_t>(0x142307B40_g, 0xC3); // patch#2 Annoying function crashing game; related to BattleNet (TODO : Needs Further Investigation)
|
||||
utils::hook::set<uint32_t>(0x143D08290_g, 0x90C301B0); // patch#3 BattleNet_IsModeAvailable? (patch to mov al,1 retn)
|
||||
|
||||
utils::hook::nop(0x1437DA454_g, 13); // begin cross-auth even without platform being initialized
|
||||
utils::hook::set(0x1444E34C0_g, 0xC301B0); // Checks extended_data and extra_data in json object [bdAuthPC::processPlatformData]
|
||||
utils::hook::nop(0x1437DA454_g, 13); // begin cross-auth even without platform being initialized [LiveConnect_BeginCrossAuthPlatform]
|
||||
utils::hook::set(0x1444D2D60_g, 0xC301B0); // Auth3 Response RSA signature check [bdAuth::validateResponseSignature]
|
||||
utils::hook::set(0x1444E34C0_g, 0xC301B0); // Auth3 Response platform extended data check [bdAuthPC::processPlatformData]
|
||||
|
||||
//PC_TextChat_Print_Hook.create(0x000000000_g, PC_TextChat_Print_Stub); // Disable useless system messages passed into chat box
|
||||
//BattleNet_API_RequestAppTicket_Hook.create(0x000000000_g, BattleNet_API_RequestAppTicket_stub); // Implement custom encryption token
|
||||
}
|
||||
|
||||
int priority() override
|
||||
{
|
||||
return 9996;
|
||||
utils::hook::nop(0x1438994E9_g, 22); // get live name even without platform being initialized [Live_UserSignedIn]
|
||||
utils::hook::nop(0x1438C3476_g, 22); // get live xuid even without platform being initialized [LiveUser_UserGetXuid]
|
||||
|
||||
utils::hook::jump(0x142325C70_g, bnet_get_username); // detour battlenet username
|
||||
utils::hook::jump(0x142325CA0_g, bnet_get_userid); // detour battlenet userid
|
||||
|
||||
//PC_TextChat_Print_Hook.create(0x1422D4A20_g, PC_TextChat_Print_Stub); // Disable useless system messages passed into chat box
|
||||
|
||||
logger::write(logger::LOG_TYPE_INFO, "[ PLATFORM ]: BattleTag: '%s', BattleID: '%llu'", bnet_get_username(), bnet_get_userid());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -2,5 +2,7 @@
|
||||
|
||||
namespace platform
|
||||
{
|
||||
/* PLACE_HOLDER */
|
||||
uint64_t bnet_get_userid();
|
||||
const char* bnet_get_username();
|
||||
std::string get_userdata_directory();
|
||||
}
|
@ -166,8 +166,8 @@ namespace scheduler
|
||||
void post_unpack() override
|
||||
{
|
||||
r_end_frame_hook.create(0x14361E260_g, r_end_frame_stub); // R_EndFrame
|
||||
main_frame_hook.create(0x14288BAE0_g, main_frame_stub); // Com_Frame
|
||||
g_run_frame_hook.create(0x142D08FC0_g, server_frame_stub); // G_RunFrame
|
||||
//main_frame_hook.create(0x14288BAE0_g, main_frame_stub); // Com_Frame
|
||||
//g_run_frame_hook.create(0x142D08FC0_g, server_frame_stub); // G_RunFrame
|
||||
}
|
||||
|
||||
void pre_destroy() override
|
||||
|
@ -125,7 +125,7 @@ namespace discovery
|
||||
|
||||
if (symbols_list.find("com_get_build_version") != symbols_list.end())
|
||||
{
|
||||
const char* build_version = utils::hook::invoke<const char*>(symbols_list["com_get_build_version"]); // Com_GetBuildVersion()
|
||||
const char* build_version = utils::hook::invoke<const char*>(symbols_list["com_get_build_version"]);
|
||||
logger::write(logger::LOG_TYPE_DEBUG, "Address-List Discovery Results for BlackOps4 %s", build_version);
|
||||
}
|
||||
|
||||
@ -163,5 +163,5 @@ namespace discovery
|
||||
}
|
||||
};
|
||||
}
|
||||
REGISTER_COMPONENT(discovery::component)
|
||||
|
||||
//REGISTER_COMPONENT(discovery::component)
|
||||
|
182
source/proxy-dll/demonware/bit_buffer.cpp
Normal file
182
source/proxy-dll/demonware/bit_buffer.cpp
Normal file
@ -0,0 +1,182 @@
|
||||
#include <std_include.hpp>
|
||||
#include "bit_buffer.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
bool bit_buffer::read_bytes(const unsigned int bytes, unsigned char* output)
|
||||
{
|
||||
return this->read(bytes * 8, output);
|
||||
}
|
||||
|
||||
bool bit_buffer::read_bool(bool* output)
|
||||
{
|
||||
if (!this->read_data_type(1))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return this->read(1, output);
|
||||
}
|
||||
|
||||
bool bit_buffer::read_uint32(unsigned int* output)
|
||||
{
|
||||
if (!this->read_data_type(8))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return this->read(32, output);
|
||||
}
|
||||
|
||||
bool bit_buffer::read_data_type(const char expected)
|
||||
{
|
||||
char data_type = 0;
|
||||
|
||||
if (!this->use_data_types_) return true;
|
||||
if (this->read(5, &data_type))
|
||||
{
|
||||
return (data_type == expected);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bit_buffer::write_bytes(const unsigned int bytes, const char* data)
|
||||
{
|
||||
return this->write_bytes(bytes, reinterpret_cast<const unsigned char*>(data));
|
||||
}
|
||||
|
||||
bool bit_buffer::write_bytes(const unsigned int bytes, const unsigned char* data)
|
||||
{
|
||||
return this->write(bytes * 8, data);
|
||||
}
|
||||
|
||||
bool bit_buffer::write_bool(bool data)
|
||||
{
|
||||
if (this->write_data_type(1))
|
||||
{
|
||||
return this->write(1, &data);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bit_buffer::write_int32(int data)
|
||||
{
|
||||
if (this->write_data_type(7))
|
||||
{
|
||||
return this->write(32, &data);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bit_buffer::write_uint32(unsigned int data)
|
||||
{
|
||||
if (this->write_data_type(8))
|
||||
{
|
||||
return this->write(32, &data);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool bit_buffer::write_data_type(char data)
|
||||
{
|
||||
if (!this->use_data_types_)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return this->write(5, &data);
|
||||
}
|
||||
|
||||
bool bit_buffer::read(unsigned int bits, void* output)
|
||||
{
|
||||
if (bits == 0) return false;
|
||||
if ((this->current_bit_ + bits) > (this->buffer_.size() * 8)) return false;
|
||||
|
||||
int cur_byte = this->current_bit_ >> 3;
|
||||
auto cur_out = 0;
|
||||
|
||||
const char* bytes = this->buffer_.data();
|
||||
const auto output_bytes = static_cast<unsigned char*>(output);
|
||||
|
||||
while (bits > 0)
|
||||
{
|
||||
const int min_bit = (bits < 8) ? bits : 8;
|
||||
const auto this_byte = bytes[cur_byte++] & 0xFF;
|
||||
const int remain = this->current_bit_ & 7;
|
||||
|
||||
if ((min_bit + remain) <= 8)
|
||||
{
|
||||
output_bytes[cur_out] = BYTE((0xFF >> (8 - min_bit)) & (this_byte >> remain));
|
||||
}
|
||||
else
|
||||
{
|
||||
output_bytes[cur_out] = BYTE(
|
||||
(0xFF >> (8 - min_bit)) & (bytes[cur_byte] << (8 - remain)) | (this_byte >> remain));
|
||||
}
|
||||
|
||||
cur_out++;
|
||||
this->current_bit_ += min_bit;
|
||||
bits -= min_bit;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool bit_buffer::write(const unsigned int bits, const void* data)
|
||||
{
|
||||
if (bits == 0) return false;
|
||||
this->buffer_.resize(this->buffer_.size() + (bits >> 3) + 1);
|
||||
|
||||
int bit = bits;
|
||||
const auto bytes = const_cast<char*>(this->buffer_.data());
|
||||
const auto* input_bytes = static_cast<const unsigned char*>(data);
|
||||
|
||||
while (bit > 0)
|
||||
{
|
||||
const int bit_pos = this->current_bit_ & 7;
|
||||
auto rem_bit = 8 - bit_pos;
|
||||
const auto this_write = (bit < rem_bit) ? bit : rem_bit;
|
||||
|
||||
const BYTE mask = ((0xFF >> rem_bit) | (0xFF << (bit_pos + this_write)));
|
||||
const int byte_pos = this->current_bit_ >> 3;
|
||||
|
||||
const BYTE temp_byte = (mask & bytes[byte_pos]);
|
||||
const BYTE this_bit = ((bits - bit) & 7);
|
||||
const auto this_byte = (bits - bit) >> 3;
|
||||
|
||||
auto this_data = input_bytes[this_byte];
|
||||
|
||||
const auto next_byte = (((bits - 1) >> 3) > this_byte) ? input_bytes[this_byte + 1] : 0;
|
||||
|
||||
this_data = BYTE((next_byte << (8 - this_bit)) | (this_data >> this_bit));
|
||||
|
||||
const BYTE out_byte = (~mask & (this_data << bit_pos) | temp_byte);
|
||||
bytes[byte_pos] = out_byte;
|
||||
|
||||
this->current_bit_ += this_write;
|
||||
bit -= this_write;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void bit_buffer::set_use_data_types(const bool use_data_types)
|
||||
{
|
||||
this->use_data_types_ = use_data_types;
|
||||
}
|
||||
|
||||
unsigned int bit_buffer::size() const
|
||||
{
|
||||
return this->current_bit_ / 8 + (this->current_bit_ % 8 ? 1 : 0);
|
||||
}
|
||||
|
||||
std::string& bit_buffer::get_buffer()
|
||||
{
|
||||
this->buffer_.resize(this->size());
|
||||
return this->buffer_;
|
||||
}
|
||||
}
|
40
source/proxy-dll/demonware/bit_buffer.hpp
Normal file
40
source/proxy-dll/demonware/bit_buffer.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class bit_buffer final
|
||||
{
|
||||
public:
|
||||
bit_buffer() = default;
|
||||
|
||||
explicit bit_buffer(std::string buffer) : buffer_(std::move(buffer))
|
||||
{
|
||||
}
|
||||
|
||||
bool read_bytes(unsigned int bytes, unsigned char* output);
|
||||
bool read_bool(bool* output);
|
||||
bool read_uint32(unsigned int* output);
|
||||
bool read_data_type(char expected);
|
||||
|
||||
bool write_bytes(unsigned int bytes, const char* data);
|
||||
bool write_bytes(unsigned int bytes, const unsigned char* data);
|
||||
bool write_bool(bool data);
|
||||
bool write_int32(int data);
|
||||
bool write_uint32(unsigned int data);
|
||||
bool write_data_type(char data);
|
||||
|
||||
bool read(unsigned int bits, void* output);
|
||||
bool write(unsigned int bits, const void* data);
|
||||
|
||||
void set_use_data_types(bool use_data_types);
|
||||
|
||||
unsigned int size() const;
|
||||
|
||||
std::string& get_buffer();
|
||||
|
||||
private:
|
||||
std::string buffer_{};
|
||||
unsigned int current_bit_ = 0;
|
||||
bool use_data_types_ = true;
|
||||
};
|
||||
}
|
365
source/proxy-dll/demonware/byte_buffer.cpp
Normal file
365
source/proxy-dll/demonware/byte_buffer.cpp
Normal file
@ -0,0 +1,365 @@
|
||||
#include <std_include.hpp>
|
||||
#include "byte_buffer.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
bool byte_buffer::read_bool(bool* output)
|
||||
{
|
||||
if (!this->read_data_type(1)) return false;
|
||||
return this->read(1, output);
|
||||
}
|
||||
|
||||
bool byte_buffer::read_byte(char* output)
|
||||
{
|
||||
if (!this->read_data_type(2)) return false;
|
||||
return this->read(1, output);
|
||||
}
|
||||
|
||||
bool byte_buffer::read_ubyte(unsigned char* output)
|
||||
{
|
||||
if (!this->read_data_type(3)) return false;
|
||||
return this->read(1, output);
|
||||
}
|
||||
|
||||
bool byte_buffer::read_int16(short* output)
|
||||
{
|
||||
if (!this->read_data_type(5)) return false;
|
||||
return this->read(2, output);
|
||||
}
|
||||
|
||||
bool byte_buffer::read_uint16(unsigned short* output)
|
||||
{
|
||||
if (!this->read_data_type(6)) return false;
|
||||
return this->read(2, output);
|
||||
}
|
||||
|
||||
bool byte_buffer::read_int32(int* output)
|
||||
{
|
||||
if (!this->read_data_type(7)) return false;
|
||||
return this->read(4, output);
|
||||
}
|
||||
|
||||
bool byte_buffer::read_uint32(unsigned int* output)
|
||||
{
|
||||
if (!this->read_data_type(8)) return false;
|
||||
return this->read(4, output);
|
||||
}
|
||||
|
||||
bool byte_buffer::read_int64(__int64* output)
|
||||
{
|
||||
if (!this->read_data_type(9)) return false;
|
||||
return this->read(8, output);
|
||||
}
|
||||
|
||||
bool byte_buffer::read_uint64(unsigned __int64* output)
|
||||
{
|
||||
if (!this->read_data_type(10)) return false;
|
||||
return this->read(8, output);
|
||||
}
|
||||
|
||||
bool byte_buffer::read_float(float* output)
|
||||
{
|
||||
if (!this->read_data_type(13)) return false;
|
||||
return this->read(4, output);
|
||||
}
|
||||
|
||||
bool byte_buffer::read_string(std::string* output)
|
||||
{
|
||||
char* out_data;
|
||||
if (this->read_string(&out_data))
|
||||
{
|
||||
output->clear();
|
||||
output->append(out_data);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool byte_buffer::read_string(char** output)
|
||||
{
|
||||
if (!this->read_data_type(16)) return false;
|
||||
|
||||
*output = const_cast<char*>(this->buffer_.data()) + this->current_byte_;
|
||||
this->current_byte_ += strlen(*output) + 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool byte_buffer::read_string(char* output, const int length)
|
||||
{
|
||||
if (!this->read_data_type(16)) return false;
|
||||
|
||||
strcpy_s(output, length, const_cast<char*>(this->buffer_.data()) + this->current_byte_);
|
||||
this->current_byte_ += strlen(output) + 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool byte_buffer::read_blob(std::string* output)
|
||||
{
|
||||
char* out_data;
|
||||
int length;
|
||||
if (this->read_blob(&out_data, &length))
|
||||
{
|
||||
output->clear();
|
||||
output->append(out_data, length);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool byte_buffer::read_blob(char** output, int* length)
|
||||
{
|
||||
if (!this->read_data_type(0x13))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int size;
|
||||
this->read_uint32(&size);
|
||||
|
||||
*output = const_cast<char*>(this->buffer_.data()) + this->current_byte_;
|
||||
*length = static_cast<int>(size);
|
||||
|
||||
this->current_byte_ += size;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool byte_buffer::read_struct(std::string* output)
|
||||
{
|
||||
char* out_data;
|
||||
int length;
|
||||
if (this->read_struct(&out_data, &length))
|
||||
{
|
||||
output->clear();
|
||||
output->append(out_data, length);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool byte_buffer::read_struct(char** output, int* length)
|
||||
{
|
||||
if (!this->read_data_type(0x17))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int size;
|
||||
this->read_uint32(&size);
|
||||
|
||||
*output = const_cast<char*>(this->buffer_.data()) + this->current_byte_;
|
||||
*length = static_cast<int>(size);
|
||||
|
||||
this->current_byte_ += size;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool byte_buffer::read_data_type(const char expected)
|
||||
{
|
||||
if (!this->use_data_types_) return true;
|
||||
|
||||
char type;
|
||||
this->read(1, &type);
|
||||
return type == expected;
|
||||
}
|
||||
|
||||
bool byte_buffer::read_array_header(const unsigned char expected, unsigned int* element_count,
|
||||
unsigned int* element_size)
|
||||
{
|
||||
if (element_count) *element_count = 0;
|
||||
if (element_size) *element_size = 0;
|
||||
|
||||
if (!this->read_data_type(expected + 100)) return false;
|
||||
|
||||
uint32_t array_size, el_count;
|
||||
if (!this->read_uint32(&array_size)) return false;
|
||||
|
||||
this->set_use_data_types(false);
|
||||
this->read_uint32(&el_count);
|
||||
this->set_use_data_types(true);
|
||||
|
||||
if (element_count) *element_count = el_count;
|
||||
if (element_size) *element_size = array_size / el_count;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool byte_buffer::write_bool(bool data)
|
||||
{
|
||||
this->write_data_type(1);
|
||||
return this->write(1, &data);
|
||||
}
|
||||
|
||||
bool byte_buffer::write_byte(char data)
|
||||
{
|
||||
this->write_data_type(2);
|
||||
return this->write(1, &data);
|
||||
}
|
||||
|
||||
bool byte_buffer::write_ubyte(unsigned char data)
|
||||
{
|
||||
this->write_data_type(3);
|
||||
return this->write(1, &data);
|
||||
}
|
||||
|
||||
bool byte_buffer::write_int16(short data)
|
||||
{
|
||||
this->write_data_type(5);
|
||||
return this->write(2, &data);
|
||||
}
|
||||
|
||||
bool byte_buffer::write_uint16(unsigned short data)
|
||||
{
|
||||
this->write_data_type(6);
|
||||
return this->write(2, &data);
|
||||
}
|
||||
|
||||
bool byte_buffer::write_int32(int data)
|
||||
{
|
||||
this->write_data_type(7);
|
||||
return this->write(4, &data);
|
||||
}
|
||||
|
||||
bool byte_buffer::write_uint32(unsigned int data)
|
||||
{
|
||||
this->write_data_type(8);
|
||||
return this->write(4, &data);
|
||||
}
|
||||
|
||||
bool byte_buffer::write_int64(__int64 data)
|
||||
{
|
||||
this->write_data_type(9);
|
||||
return this->write(8, &data);
|
||||
}
|
||||
|
||||
bool byte_buffer::write_uint64(unsigned __int64 data)
|
||||
{
|
||||
this->write_data_type(10);
|
||||
return this->write(8, &data);
|
||||
}
|
||||
|
||||
bool byte_buffer::write_data_type(char data)
|
||||
{
|
||||
if (!this->use_data_types_) return true;
|
||||
return this->write(1, &data);
|
||||
}
|
||||
|
||||
bool byte_buffer::write_float(float data)
|
||||
{
|
||||
this->write_data_type(13);
|
||||
return this->write(4, &data);
|
||||
}
|
||||
|
||||
bool byte_buffer::write_string(const std::string& data)
|
||||
{
|
||||
return this->write_string(data.data());
|
||||
}
|
||||
|
||||
bool byte_buffer::write_string(const char* data)
|
||||
{
|
||||
this->write_data_type(16);
|
||||
return this->write(static_cast<int>(strlen(data)) + 1, data);
|
||||
}
|
||||
|
||||
bool byte_buffer::write_blob(const std::string& data)
|
||||
{
|
||||
return this->write_blob(data.data(), INT(data.size()));
|
||||
}
|
||||
|
||||
bool byte_buffer::write_blob(const char* data, const int length)
|
||||
{
|
||||
this->write_data_type(0x13);
|
||||
this->write_uint32(length);
|
||||
|
||||
return this->write(length, data);
|
||||
}
|
||||
|
||||
bool byte_buffer::write_struct(const std::string& data)
|
||||
{
|
||||
return this->write_struct(data.data(), INT(data.size()));
|
||||
}
|
||||
|
||||
bool byte_buffer::write_struct(const char* data, const int length)
|
||||
{
|
||||
this->write_data_type(0x17);
|
||||
this->write_uint32(length);
|
||||
|
||||
return this->write(length, data);
|
||||
}
|
||||
|
||||
bool byte_buffer::write_array_header(const unsigned char type, const unsigned int element_count,
|
||||
const unsigned int element_size)
|
||||
{
|
||||
const auto using_types = this->is_using_data_types();
|
||||
this->set_use_data_types(false);
|
||||
|
||||
auto result = this->write_ubyte(type + 100);
|
||||
|
||||
this->set_use_data_types(true);
|
||||
result &= this->write_uint32(element_count * element_size);
|
||||
this->set_use_data_types(false);
|
||||
|
||||
result &= this->write_uint32(element_count);
|
||||
|
||||
this->set_use_data_types(using_types);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool byte_buffer::read(const int bytes, void* output)
|
||||
{
|
||||
if (bytes + this->current_byte_ > this->buffer_.size()) return false;
|
||||
|
||||
std::memmove(output, this->buffer_.data() + this->current_byte_, bytes);
|
||||
this->current_byte_ += bytes;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool byte_buffer::write(const int bytes, const void* data)
|
||||
{
|
||||
this->buffer_.append(static_cast<const char*>(data), bytes);
|
||||
this->current_byte_ += bytes;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool byte_buffer::write(const std::string& data)
|
||||
{
|
||||
return this->write(static_cast<int>(data.size()), data.data());
|
||||
}
|
||||
|
||||
void byte_buffer::set_use_data_types(const bool use_data_types)
|
||||
{
|
||||
this->use_data_types_ = use_data_types;
|
||||
}
|
||||
|
||||
size_t byte_buffer::size() const
|
||||
{
|
||||
return this->buffer_.size();
|
||||
}
|
||||
|
||||
bool byte_buffer::is_using_data_types() const
|
||||
{
|
||||
return use_data_types_;
|
||||
}
|
||||
|
||||
std::string& byte_buffer::get_buffer()
|
||||
{
|
||||
return this->buffer_;
|
||||
}
|
||||
|
||||
std::string byte_buffer::get_remaining()
|
||||
{
|
||||
return std::string(this->buffer_.begin() + this->current_byte_, this->buffer_.end());
|
||||
}
|
||||
|
||||
bool byte_buffer::has_more_data() const
|
||||
{
|
||||
return this->buffer_.size() > this->current_byte_;
|
||||
}
|
||||
}
|
75
source/proxy-dll/demonware/byte_buffer.hpp
Normal file
75
source/proxy-dll/demonware/byte_buffer.hpp
Normal file
@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class byte_buffer final
|
||||
{
|
||||
public:
|
||||
byte_buffer() = default;
|
||||
|
||||
explicit byte_buffer(std::string buffer) : buffer_(std::move(buffer))
|
||||
{
|
||||
}
|
||||
|
||||
bool read_bool(bool* output);
|
||||
bool read_byte(char* output);
|
||||
bool read_ubyte(unsigned char* output);
|
||||
bool read_int16(short* output);
|
||||
bool read_uint16(unsigned short* output);
|
||||
bool read_int32(int* output);
|
||||
bool read_uint32(unsigned int* output);
|
||||
bool read_int64(__int64* output);
|
||||
bool read_uint64(unsigned __int64* output);
|
||||
bool read_float(float* output);
|
||||
bool read_string(char** output);
|
||||
bool read_string(char* output, int length);
|
||||
bool read_string(std::string* output);
|
||||
bool read_blob(char** output, int* length);
|
||||
bool read_blob(std::string* output);
|
||||
bool read_struct(char** output, int* length);
|
||||
bool read_struct(std::string* output);
|
||||
bool read_data_type(char expected);
|
||||
|
||||
bool read_array_header(unsigned char expected, unsigned int* element_count,
|
||||
unsigned int* element_size = nullptr);
|
||||
|
||||
bool write_bool(bool data);
|
||||
bool write_byte(char data);
|
||||
bool write_ubyte(unsigned char data);
|
||||
bool write_int16(short data);
|
||||
bool write_uint16(unsigned short data);
|
||||
bool write_int32(int data);
|
||||
bool write_uint32(unsigned int data);
|
||||
bool write_int64(__int64 data);
|
||||
bool write_uint64(unsigned __int64 data);
|
||||
bool write_data_type(char data);
|
||||
bool write_float(float data);
|
||||
bool write_string(const char* data);
|
||||
bool write_string(const std::string& data);
|
||||
bool write_blob(const char* data, int length);
|
||||
bool write_blob(const std::string& data);
|
||||
bool write_struct(const char* data, int length);
|
||||
bool write_struct(const std::string& data);
|
||||
|
||||
bool write_array_header(unsigned char type, unsigned int element_count, unsigned int element_size);
|
||||
|
||||
bool read(int bytes, void* output);
|
||||
bool write(int bytes, const void* data);
|
||||
bool write(const std::string& data);
|
||||
|
||||
void set_use_data_types(bool use_data_types);
|
||||
size_t size() const;
|
||||
|
||||
bool is_using_data_types() const;
|
||||
|
||||
std::string& get_buffer();
|
||||
std::string get_remaining();
|
||||
|
||||
bool has_more_data() const;
|
||||
|
||||
private:
|
||||
std::string buffer_;
|
||||
size_t current_byte_ = 0;
|
||||
bool use_data_types_ = true;
|
||||
};
|
||||
}
|
189
source/proxy-dll/demonware/data_types.hpp
Normal file
189
source/proxy-dll/demonware/data_types.hpp
Normal file
@ -0,0 +1,189 @@
|
||||
#pragma once
|
||||
|
||||
#include "byte_buffer.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class bdTaskResult
|
||||
{
|
||||
public:
|
||||
virtual ~bdTaskResult() = default;
|
||||
|
||||
virtual void serialize(byte_buffer*)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void deserialize(byte_buffer*)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class bdTimeStamp final : public bdTaskResult
|
||||
{
|
||||
public:
|
||||
uint32_t unix_time;
|
||||
|
||||
void serialize(byte_buffer* buffer) override
|
||||
{
|
||||
buffer->write_uint32(this->unix_time);
|
||||
}
|
||||
|
||||
void deserialize(byte_buffer* buffer) override
|
||||
{
|
||||
buffer->read_uint32(&this->unix_time);
|
||||
}
|
||||
};
|
||||
|
||||
class bdDMLInfo : public bdTaskResult
|
||||
{
|
||||
public:
|
||||
std::string country_code; // Char [3]
|
||||
std::string country; // Char [65]
|
||||
std::string region; // Char [65]
|
||||
std::string city; // Char [129]
|
||||
float latitude;
|
||||
float longitude;
|
||||
uint32_t asn; // Autonomous System Number.
|
||||
std::string timezone;
|
||||
|
||||
void serialize(byte_buffer* buffer) override
|
||||
{
|
||||
buffer->write_string(this->country_code);
|
||||
buffer->write_string(this->country);
|
||||
buffer->write_string(this->region);
|
||||
buffer->write_string(this->city);
|
||||
buffer->write_float(this->latitude);
|
||||
buffer->write_float(this->longitude);
|
||||
buffer->write_uint32(this->asn);
|
||||
buffer->write_string(this->timezone);
|
||||
}
|
||||
|
||||
void deserialize(byte_buffer* buffer) override
|
||||
{
|
||||
buffer->read_string(&this->country_code);
|
||||
buffer->read_string(&this->country);
|
||||
buffer->read_string(&this->region);
|
||||
buffer->read_string(&this->city);
|
||||
buffer->read_float(&this->latitude);
|
||||
buffer->read_float(&this->longitude);
|
||||
buffer->read_uint32(&this->asn);
|
||||
buffer->read_string(&this->timezone);
|
||||
}
|
||||
};
|
||||
|
||||
class bdDMLHierarchicalInfo final : public bdDMLInfo
|
||||
{
|
||||
public:
|
||||
uint32_t m_tier0;
|
||||
uint32_t m_tier1;
|
||||
uint32_t m_tier2;
|
||||
uint32_t m_tier3;
|
||||
uint32_t m_confidence;
|
||||
|
||||
void serialize(byte_buffer* buffer) override
|
||||
{
|
||||
bdDMLInfo::serialize(buffer);
|
||||
|
||||
buffer->write_uint32(this->m_tier0);
|
||||
buffer->write_uint32(this->m_tier1);
|
||||
buffer->write_uint32(this->m_tier2);
|
||||
buffer->write_uint32(this->m_tier3);
|
||||
buffer->write_uint32(this->m_confidence);
|
||||
}
|
||||
|
||||
void deserialize(byte_buffer* buffer) override
|
||||
{
|
||||
bdDMLInfo::deserialize(buffer);
|
||||
|
||||
buffer->read_uint32(&this->m_tier0);
|
||||
buffer->read_uint32(&this->m_tier1);
|
||||
buffer->read_uint32(&this->m_tier2);
|
||||
buffer->read_uint32(&this->m_tier3);
|
||||
buffer->read_uint32(&this->m_confidence);
|
||||
}
|
||||
};
|
||||
|
||||
class bdStructedDataBuffer final : public bdTaskResult
|
||||
{
|
||||
public:
|
||||
std::string structed_data_protobuffer;
|
||||
|
||||
void serialize(byte_buffer* buffer) override
|
||||
{
|
||||
buffer->write_struct(this->structed_data_protobuffer);
|
||||
}
|
||||
|
||||
void deserialize(byte_buffer* buffer) override
|
||||
{
|
||||
buffer->read_struct(&this->structed_data_protobuffer);
|
||||
}
|
||||
};
|
||||
|
||||
class bdMarketplaceInventory final : public bdTaskResult
|
||||
{
|
||||
public:
|
||||
uint64_t m_userID;
|
||||
std::string m_accountType;
|
||||
uint32_t m_itemId;
|
||||
uint32_t m_itemQuantity;
|
||||
uint32_t m_itemXp;
|
||||
std::string m_itemData;
|
||||
uint32_t m_expireDateTime;
|
||||
int64_t m_expiryDuration;
|
||||
uint16_t m_collisionField;
|
||||
uint32_t m_modDateTime;
|
||||
uint32_t m_customSourceType;
|
||||
|
||||
void serialize(byte_buffer* buffer) override
|
||||
{
|
||||
buffer->write_uint64(this->m_userID);
|
||||
buffer->write_string(this->m_accountType);
|
||||
buffer->write_uint32(this->m_itemId);
|
||||
buffer->write_uint32(this->m_itemQuantity);
|
||||
buffer->write_uint32(this->m_itemXp);
|
||||
buffer->write_blob(this->m_itemData);
|
||||
buffer->write_uint32(this->m_expireDateTime);
|
||||
buffer->write_int64(this->m_expiryDuration);
|
||||
buffer->write_uint16(this->m_collisionField);
|
||||
buffer->write_uint32(this->m_modDateTime);
|
||||
buffer->write_uint32(this->m_customSourceType);
|
||||
}
|
||||
|
||||
void deserialize(byte_buffer* buffer) override
|
||||
{
|
||||
buffer->read_uint64(&this->m_userID);
|
||||
buffer->read_string(&this->m_accountType);
|
||||
buffer->read_uint32(&this->m_itemId);
|
||||
buffer->read_uint32(&this->m_itemQuantity);
|
||||
buffer->read_uint32(&this->m_itemXp);
|
||||
buffer->read_blob(&this->m_itemData);
|
||||
buffer->read_uint32(&this->m_expireDateTime);
|
||||
buffer->read_int64(&this->m_expiryDuration);
|
||||
buffer->read_uint16(&this->m_collisionField);
|
||||
buffer->read_uint32(&this->m_modDateTime);
|
||||
buffer->read_uint32(&this->m_customSourceType);
|
||||
}
|
||||
};
|
||||
|
||||
class bdPublicProfileInfo final : public bdTaskResult
|
||||
{
|
||||
public:
|
||||
uint64_t m_entityID;
|
||||
int32_t m_VERSION;
|
||||
std::string m_ddl;
|
||||
|
||||
void serialize(byte_buffer* buffer) override
|
||||
{
|
||||
buffer->write_uint64(this->m_entityID);
|
||||
buffer->write_int32(this->m_VERSION);
|
||||
buffer->write_blob(this->m_ddl);
|
||||
}
|
||||
|
||||
void deserialize(byte_buffer* buffer) override
|
||||
{
|
||||
buffer->read_uint64(&this->m_entityID);
|
||||
buffer->read_int32(&this->m_VERSION);
|
||||
buffer->read_blob(&this->m_ddl);
|
||||
}
|
||||
};
|
||||
}
|
141
source/proxy-dll/demonware/keys.cpp
Normal file
141
source/proxy-dll/demonware/keys.cpp
Normal file
@ -0,0 +1,141 @@
|
||||
#include <std_include.hpp>
|
||||
#include "keys.hpp"
|
||||
|
||||
#include <utils/cryptography.hpp>
|
||||
#include <utils/string.hpp>
|
||||
#include <utils/io.hpp>
|
||||
|
||||
#include "resource.hpp"
|
||||
#include <utils/nt.hpp>
|
||||
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
struct data_t
|
||||
{
|
||||
char m_session_key[24];
|
||||
char m_response[8];
|
||||
char m_hmac_key[20];
|
||||
char m_enc_key[16];
|
||||
char m_dec_key[16];
|
||||
} data{};
|
||||
|
||||
std::string packet_buffer;
|
||||
|
||||
void calculate_hmacs(const char* dataxx, const unsigned int data_size,
|
||||
const char* key, const unsigned int key_size,
|
||||
char* dest, const unsigned int dest_size)
|
||||
{
|
||||
char buffer[512];
|
||||
unsigned int pos = 0;
|
||||
unsigned int out_offset = 0;
|
||||
char count = 1;
|
||||
std::string result;
|
||||
|
||||
// buffer add key
|
||||
std::memcpy(&buffer[pos], key, key_size);
|
||||
pos += key_size;
|
||||
|
||||
// buffer add count
|
||||
buffer[pos] = count;
|
||||
pos++;
|
||||
|
||||
// calculate hmac
|
||||
result = utils::cryptography::hmac_sha1::compute(std::string(buffer, pos), std::string(dataxx, data_size));
|
||||
|
||||
// save output
|
||||
std::memcpy(dest, result.data(), std::min(20u, (dest_size - out_offset)));
|
||||
out_offset = 20;
|
||||
|
||||
// second loop
|
||||
while (true)
|
||||
{
|
||||
// if we filled the output buffer, exit
|
||||
if (out_offset >= dest_size)
|
||||
break;
|
||||
|
||||
// buffer add last result
|
||||
pos = 0;
|
||||
std::memcpy(&buffer[pos], result.data(), 20);
|
||||
pos += 20;
|
||||
|
||||
// buffer add key
|
||||
std::memcpy(&buffer[pos], key, key_size);
|
||||
pos += key_size;
|
||||
|
||||
// buffer add count
|
||||
count++;
|
||||
buffer[pos] = count;
|
||||
pos++;
|
||||
|
||||
// calculate hmac
|
||||
result = utils::cryptography::hmac_sha1::compute(std::string(buffer, pos), std::string(dataxx, data_size));
|
||||
|
||||
// save output
|
||||
std::memcpy(dest + out_offset, result.data(), std::min(20u, (dest_size - out_offset)));
|
||||
out_offset += 20;
|
||||
}
|
||||
}
|
||||
|
||||
void derive_keys_iw8()
|
||||
{
|
||||
std::string BD_AUTH_TRAFFIC_SIGNING_KEY = utils::nt::load_resource(DW_AUTH_TRAFFIC_SIGNING_KEY);
|
||||
|
||||
const auto packet_hash = utils::cryptography::sha1::compute(packet_buffer);
|
||||
|
||||
char out_1[24];
|
||||
calculate_hmacs(data.m_session_key, 24, BD_AUTH_TRAFFIC_SIGNING_KEY.data(), 294, out_1, 24);
|
||||
|
||||
auto data_3 = utils::cryptography::hmac_sha1::compute(std::string(out_1, 24), packet_hash);
|
||||
|
||||
char out_2[16];
|
||||
calculate_hmacs(data_3.data(), 20, "CLIENTCHAL", 10, out_2, 16);
|
||||
|
||||
char out_3[72];
|
||||
calculate_hmacs(data_3.data(), 20, "BDDATA", 6, out_3, 72);
|
||||
|
||||
|
||||
std::memcpy(data.m_response, &out_2[8], 8);
|
||||
std::memcpy(data.m_hmac_key, &out_3[20], 20);
|
||||
std::memcpy(data.m_dec_key, &out_3[40], 16);
|
||||
std::memcpy(data.m_enc_key, &out_3[56], 16);
|
||||
|
||||
#ifndef NDEBUG
|
||||
logger::write(logger::LOG_TYPE_DEBUG, "[DW] Response id: %s", utils::string::dump_hex(std::string(&out_2[8], 8)).data());
|
||||
logger::write(logger::LOG_TYPE_DEBUG, "[DW] Hash verify: %s", utils::string::dump_hex(std::string(&out_3[20], 20)).data());
|
||||
logger::write(logger::LOG_TYPE_DEBUG, "[DW] AES dec key: %s", utils::string::dump_hex(std::string(&out_3[40], 16)).data());
|
||||
logger::write(logger::LOG_TYPE_DEBUG, "[DW] AES enc key: %s", utils::string::dump_hex(std::string(&out_3[56], 16)).data());
|
||||
logger::write(logger::LOG_TYPE_DEBUG, "[DW] Bravo 6, going dark.");
|
||||
#endif
|
||||
}
|
||||
|
||||
void queue_packet_to_hash(const std::string& packet)
|
||||
{
|
||||
packet_buffer.append(packet);
|
||||
}
|
||||
|
||||
void set_session_key(const std::string& key)
|
||||
{
|
||||
std::memcpy(data.m_session_key, key.data(), 24);
|
||||
}
|
||||
|
||||
std::string get_decrypt_key()
|
||||
{
|
||||
return std::string(data.m_dec_key, 16);
|
||||
}
|
||||
|
||||
std::string get_encrypt_key()
|
||||
{
|
||||
return std::string(data.m_enc_key, 16);
|
||||
}
|
||||
|
||||
std::string get_hmac_key()
|
||||
{
|
||||
return std::string(data.m_hmac_key, 20);
|
||||
}
|
||||
|
||||
std::string get_response_id()
|
||||
{
|
||||
return std::string(data.m_response, 8);
|
||||
}
|
||||
}
|
12
source/proxy-dll/demonware/keys.hpp
Normal file
12
source/proxy-dll/demonware/keys.hpp
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
void derive_keys_iw8();
|
||||
void queue_packet_to_hash(const std::string& packet);
|
||||
void set_session_key(const std::string& key);
|
||||
std::string get_decrypt_key();
|
||||
std::string get_encrypt_key();
|
||||
std::string get_hmac_key();
|
||||
std::string get_response_id();
|
||||
}
|
627
source/proxy-dll/demonware/objects.cpp
Normal file
627
source/proxy-dll/demonware/objects.cpp
Normal file
@ -0,0 +1,627 @@
|
||||
#include <std_include.hpp>
|
||||
#include <utils/io.hpp>
|
||||
#include <utils/string.hpp>
|
||||
#include <utils/cryptography.hpp>
|
||||
#include <component/platform.hpp>
|
||||
#include "protobuf_helper.hpp"
|
||||
|
||||
#include "objects.hpp"
|
||||
|
||||
#include "resource.hpp"
|
||||
#include <utils/nt.hpp>
|
||||
|
||||
#define PUBLISHER_OBJECTS_ENUMERATE_LPC_DIR
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
std::string HexStringToBinaryString(const std::string& hex_str)
|
||||
{
|
||||
std::string data{};
|
||||
|
||||
for (unsigned int i = 0; i < hex_str.length(); i += 2) {
|
||||
std::string byteString = hex_str.substr(i, 2);
|
||||
char byte = (char)strtol(byteString.c_str(), NULL, 16);
|
||||
data.push_back(byte);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
std::string get_publisher_file_checksum(std::string file)
|
||||
{
|
||||
std::string file_data;
|
||||
if (!utils::io::read_file(file, &file_data)) return "";
|
||||
|
||||
std::string checksum_md5 = utils::cryptography::md5::compute(file_data);
|
||||
|
||||
return utils::cryptography::base64::encode(checksum_md5);
|
||||
}
|
||||
|
||||
std::vector<objectMetadata> get_publisher_objects_list(const std::string& category)
|
||||
{
|
||||
std::vector<objectMetadata> result;
|
||||
|
||||
#ifdef PUBLISHER_OBJECTS_ENUMERATE_LPC_DIR
|
||||
std::vector<std::string> files = utils::io::list_files("LPC");
|
||||
|
||||
for (std::string file : files)
|
||||
{
|
||||
if (!utils::string::ends_with(file, ".ff")) continue;
|
||||
|
||||
int64_t timestamp = static_cast<int64_t>(time(nullptr));
|
||||
result.push_back({ "treyarch", utils::io::file_name(file), get_publisher_file_checksum(file), utils::io::file_size(file), timestamp, timestamp, "" });
|
||||
}
|
||||
#else // PUBLISHER_OBJECTS_ENUMERATE_CSV_LIST
|
||||
const auto objects_list_csv = utils::nt::load_resource(DW_PUBLISHER_OBJECTS_LIST);
|
||||
std::vector<std::string> items = utils::string::split(objects_list_csv, "\r\n"); // WTF!?
|
||||
|
||||
for (std::string item : items)
|
||||
{
|
||||
std::string checksum = utils::cryptography::base64::encode(HexStringToBinaryString(utils::string::split(item, ',')[2]));
|
||||
std::string name = utils::string::split(item, ',')[0];
|
||||
uint64_t length = std::stoull(utils::string::split(item, ',')[1]);
|
||||
|
||||
int64_t timestamp = static_cast<int64_t>(time(nullptr));
|
||||
result.push_back({ "treyarch", name, checksum, length, timestamp, timestamp, "" });
|
||||
}
|
||||
#endif // PUBLISHER_OBJECTS_ENUMERATE_LPC_DIR
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string generate_publisher_objects_list_json(const std::string& category)
|
||||
{
|
||||
rapidjson::StringBuffer json_buffer{};
|
||||
rapidjson::PrettyWriter<rapidjson::StringBuffer> json_writer(json_buffer);
|
||||
|
||||
json_writer.StartObject();
|
||||
|
||||
json_writer.Key("next");
|
||||
json_writer.String("TODO");
|
||||
|
||||
json_writer.Key("nextPageToken");
|
||||
json_writer.Null();
|
||||
|
||||
json_writer.Key("objects");
|
||||
json_writer.StartArray();
|
||||
|
||||
std::vector<objectMetadata> objects = get_publisher_objects_list(category);
|
||||
|
||||
for (objectMetadata object : objects)
|
||||
{
|
||||
json_writer.StartObject();
|
||||
|
||||
json_writer.Key("owner");
|
||||
json_writer.String(object.owner);
|
||||
|
||||
json_writer.Key("expiresOn");
|
||||
json_writer.Uint(0);
|
||||
|
||||
json_writer.Key("name");
|
||||
json_writer.String(object.name);
|
||||
|
||||
json_writer.Key("checksum");
|
||||
json_writer.String(object.checksum);
|
||||
|
||||
json_writer.Key("acl");
|
||||
json_writer.String("public");
|
||||
|
||||
json_writer.Key("objectID");
|
||||
json_writer.Uint(0);
|
||||
json_writer.Key("contentID");
|
||||
json_writer.Null();
|
||||
json_writer.Key("objectVersion");
|
||||
json_writer.String("");
|
||||
json_writer.Key("contentVersion");
|
||||
json_writer.Null();
|
||||
|
||||
json_writer.Key("contentLength");
|
||||
json_writer.Uint64(object.contentLength);
|
||||
|
||||
json_writer.Key("context");
|
||||
json_writer.String("t8-bnet");
|
||||
|
||||
json_writer.Key("category");
|
||||
json_writer.Null();
|
||||
|
||||
json_writer.Key("created");
|
||||
json_writer.Uint64(object.created);
|
||||
|
||||
json_writer.Key("modified");
|
||||
json_writer.Uint64(object.modified);
|
||||
|
||||
json_writer.Key("extraData");
|
||||
json_writer.Null();
|
||||
json_writer.Key("extraDataSize");
|
||||
json_writer.Null();
|
||||
json_writer.Key("summaryContentLength");
|
||||
json_writer.Null();
|
||||
json_writer.Key("summaryChecksum");
|
||||
json_writer.Null();
|
||||
json_writer.Key("hasSummary");
|
||||
json_writer.Bool(false);
|
||||
|
||||
json_writer.EndObject();
|
||||
}
|
||||
|
||||
json_writer.EndArray();
|
||||
|
||||
json_writer.EndObject();
|
||||
|
||||
return json_buffer.GetString();
|
||||
}
|
||||
|
||||
std::string get_user_file_path(const std::string& file)
|
||||
{
|
||||
return std::format("{}/{}", platform::get_userdata_directory(), file);
|
||||
}
|
||||
|
||||
std::string get_user_file_checksum(std::string file_path)
|
||||
{
|
||||
std::string file_data;
|
||||
if (!utils::io::read_file(file_path, &file_data)) return "";
|
||||
|
||||
return std::to_string(utils::cryptography::xxh32::compute(file_data));
|
||||
}
|
||||
|
||||
std::string get_user_file_content(std::string file_path)
|
||||
{
|
||||
std::string file_data;
|
||||
if (!utils::io::read_file(file_path, &file_data)) return "";
|
||||
|
||||
return utils::cryptography::base64::encode(file_data);
|
||||
}
|
||||
|
||||
std::string deliver_user_objects_vectorized_json(std::vector<objectMetadata> requested_items)
|
||||
{
|
||||
rapidjson::StringBuffer json_buffer{};
|
||||
rapidjson::PrettyWriter<rapidjson::StringBuffer> json_writer(json_buffer);
|
||||
|
||||
json_writer.StartObject();
|
||||
|
||||
json_writer.Key("objects");
|
||||
json_writer.StartArray();
|
||||
|
||||
for (size_t i = 0; i < requested_items.size(); i++)
|
||||
{
|
||||
if (requested_items[i].contentLength == 0 || requested_items[i].contentURL.empty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//std::string file_path = get_user_file_path(requested_items[i].owner, requested_items[i].name);
|
||||
|
||||
json_writer.StartObject();
|
||||
|
||||
json_writer.Key("metadata");
|
||||
json_writer.StartObject();
|
||||
|
||||
json_writer.Key("owner");
|
||||
json_writer.String(requested_items[i].owner.data());
|
||||
|
||||
json_writer.Key("expiresOn");
|
||||
json_writer.Uint(0);
|
||||
|
||||
json_writer.Key("name");
|
||||
json_writer.String(requested_items[i].name.data());
|
||||
|
||||
json_writer.Key("checksum");
|
||||
json_writer.String(requested_items[i].checksum.data());
|
||||
|
||||
json_writer.Key("acl");
|
||||
json_writer.String("public");
|
||||
|
||||
json_writer.Key("objectID");
|
||||
json_writer.Uint(0);
|
||||
json_writer.Key("contentID");
|
||||
json_writer.Null();
|
||||
json_writer.Key("objectVersion");
|
||||
json_writer.String("");
|
||||
json_writer.Key("contentVersion");
|
||||
json_writer.Null();
|
||||
|
||||
json_writer.Key("contentLength");
|
||||
json_writer.Uint64(requested_items[i].contentLength);
|
||||
|
||||
json_writer.Key("context");
|
||||
json_writer.String("t8-bnet");
|
||||
|
||||
json_writer.Key("category");
|
||||
json_writer.Null();
|
||||
|
||||
json_writer.Key("created");
|
||||
json_writer.Uint64(requested_items[i].created);
|
||||
|
||||
json_writer.Key("modified");
|
||||
json_writer.Uint64(requested_items[i].modified);
|
||||
|
||||
json_writer.Key("extraData");
|
||||
json_writer.Null();
|
||||
json_writer.Key("extraDataSize");
|
||||
json_writer.Null();
|
||||
json_writer.Key("summaryContentLength");
|
||||
json_writer.Null();
|
||||
json_writer.Key("summaryChecksum");
|
||||
json_writer.Null();
|
||||
json_writer.Key("hasSummary");
|
||||
json_writer.Bool(false);
|
||||
|
||||
json_writer.EndObject();
|
||||
|
||||
json_writer.Key("content");
|
||||
json_writer.String(requested_items[i].contentURL.data());
|
||||
|
||||
json_writer.Key("requestIndex");
|
||||
json_writer.Uint64(i);
|
||||
|
||||
json_writer.EndObject();
|
||||
}
|
||||
|
||||
json_writer.EndArray();
|
||||
|
||||
json_writer.Key("errors");
|
||||
json_writer.StartArray();
|
||||
for (size_t i = 0; i < requested_items.size(); i++)
|
||||
{
|
||||
if (requested_items[i].contentLength == 0 || requested_items[i].contentURL.empty())
|
||||
{
|
||||
json_writer.StartObject();
|
||||
|
||||
json_writer.Key("requestIndex");
|
||||
json_writer.Uint64(i);
|
||||
json_writer.Key("owner");
|
||||
json_writer.String(requested_items[i].owner.data());
|
||||
json_writer.Key("name");
|
||||
json_writer.String(requested_items[i].name.data());
|
||||
json_writer.Key("error");
|
||||
json_writer.String("Error:ClientError:NotFound");
|
||||
|
||||
json_writer.EndObject();
|
||||
}
|
||||
}
|
||||
json_writer.EndArray();
|
||||
|
||||
json_writer.EndObject();
|
||||
|
||||
return json_buffer.GetString();
|
||||
}
|
||||
|
||||
std::string deliver_user_objects_vectorized_json(std::vector<objectID> requested_items)
|
||||
{
|
||||
std::vector<objectMetadata> files_metadata_list;
|
||||
|
||||
for (objectID file : requested_items)
|
||||
{
|
||||
std::string file_path = get_user_file_path(file.name);
|
||||
int64_t timestamp = static_cast<int64_t>(time(nullptr));
|
||||
files_metadata_list.push_back({ file.owner, file.name, get_user_file_checksum(file_path), utils::io::file_size(file_path), timestamp, timestamp, get_user_file_content(file_path) });
|
||||
}
|
||||
|
||||
return deliver_user_objects_vectorized_json(files_metadata_list);
|
||||
}
|
||||
|
||||
std::string generate_user_objects_list_json()
|
||||
{
|
||||
rapidjson::StringBuffer json_buffer{};
|
||||
rapidjson::PrettyWriter<rapidjson::StringBuffer> json_writer(json_buffer);
|
||||
|
||||
json_writer.StartObject();
|
||||
|
||||
json_writer.Key("nextPageToken");
|
||||
json_writer.Null();
|
||||
|
||||
json_writer.Key("next");
|
||||
json_writer.String("TODO");
|
||||
|
||||
json_writer.Key("objects");
|
||||
json_writer.StartArray();
|
||||
|
||||
std::string userdata_directory = platform::get_userdata_directory();
|
||||
|
||||
if (utils::io::directory_exists(userdata_directory))
|
||||
{
|
||||
std::vector<std::string> user_objects = utils::io::list_files(userdata_directory);
|
||||
|
||||
for (std::string object : user_objects)
|
||||
{
|
||||
json_writer.StartObject();
|
||||
|
||||
json_writer.Key("metadata");
|
||||
json_writer.StartObject();
|
||||
|
||||
json_writer.Key("owner");
|
||||
json_writer.String(std::format("bnet-{}", platform::bnet_get_userid()));
|
||||
|
||||
json_writer.Key("expiresOn");
|
||||
json_writer.Uint(0);
|
||||
|
||||
json_writer.Key("name");
|
||||
json_writer.String(utils::io::file_name(object));
|
||||
|
||||
json_writer.Key("checksum");
|
||||
json_writer.String(get_user_file_checksum(object));
|
||||
|
||||
json_writer.Key("acl");
|
||||
json_writer.String("public");
|
||||
|
||||
json_writer.Key("objectID");
|
||||
json_writer.Uint(0);
|
||||
json_writer.Key("contentID");
|
||||
json_writer.Null();
|
||||
json_writer.Key("objectVersion");
|
||||
json_writer.String("");
|
||||
json_writer.Key("contentVersion");
|
||||
json_writer.Null();
|
||||
|
||||
json_writer.Key("contentLength");
|
||||
json_writer.Uint64(utils::io::file_size(object));
|
||||
|
||||
json_writer.Key("context");
|
||||
json_writer.String("t8-bnet");
|
||||
|
||||
json_writer.Key("category");
|
||||
json_writer.Null();
|
||||
|
||||
json_writer.Key("created");
|
||||
json_writer.Uint64(static_cast<int64_t>(time(nullptr)));
|
||||
|
||||
json_writer.Key("modified");
|
||||
json_writer.Uint64(static_cast<int64_t>(time(nullptr)));
|
||||
|
||||
json_writer.Key("extraData");
|
||||
json_writer.Null();
|
||||
json_writer.Key("extraDataSize");
|
||||
json_writer.Null();
|
||||
json_writer.Key("summaryContentLength");
|
||||
json_writer.Null();
|
||||
json_writer.Key("summaryChecksum");
|
||||
json_writer.Null();
|
||||
json_writer.Key("hasSummary");
|
||||
json_writer.Bool(false);
|
||||
|
||||
json_writer.EndObject();
|
||||
|
||||
json_writer.Key("tags");
|
||||
json_writer.StartArray();
|
||||
json_writer.EndArray();
|
||||
|
||||
json_writer.Key("statistics");
|
||||
json_writer.StartArray();
|
||||
json_writer.EndArray();
|
||||
|
||||
json_writer.EndObject();
|
||||
}
|
||||
}
|
||||
json_writer.EndArray();
|
||||
|
||||
json_writer.EndObject();
|
||||
|
||||
return json_buffer.GetString();
|
||||
}
|
||||
|
||||
std::string generate_user_objects_count_json()
|
||||
{
|
||||
std::string userdata_directory = platform::get_userdata_directory();
|
||||
|
||||
int files_count = 0;
|
||||
if (utils::io::directory_exists(userdata_directory))
|
||||
{
|
||||
files_count = static_cast<int32_t>(utils::io::list_files(userdata_directory).size());
|
||||
}
|
||||
|
||||
|
||||
rapidjson::StringBuffer json_buffer{};
|
||||
rapidjson::PrettyWriter<rapidjson::StringBuffer> json_writer(json_buffer);
|
||||
|
||||
json_writer.StartObject();
|
||||
|
||||
json_writer.Key("total");
|
||||
json_writer.Uint(files_count);
|
||||
|
||||
json_writer.Key("noCategory");
|
||||
json_writer.Uint(files_count);
|
||||
|
||||
json_writer.Key("categories");
|
||||
json_writer.StartObject();
|
||||
json_writer.EndObject();
|
||||
|
||||
json_writer.EndObject();
|
||||
|
||||
return json_buffer.GetString();
|
||||
}
|
||||
|
||||
std::string construct_file_upload_result_json(const std::string& uploaded_file)
|
||||
{
|
||||
std::string file_path = get_user_file_path(uploaded_file);
|
||||
|
||||
rapidjson::StringBuffer json_buffer{};
|
||||
rapidjson::PrettyWriter<rapidjson::StringBuffer> json_writer(json_buffer);
|
||||
|
||||
json_writer.StartObject();
|
||||
|
||||
json_writer.Key("metadata");
|
||||
json_writer.StartObject();
|
||||
|
||||
json_writer.Key("owner");
|
||||
json_writer.String(std::format("bnet-{}", platform::bnet_get_userid()));
|
||||
|
||||
json_writer.Key("expiresOn");
|
||||
json_writer.Uint(0);
|
||||
|
||||
json_writer.Key("name");
|
||||
json_writer.String(uploaded_file);
|
||||
|
||||
json_writer.Key("checksum");
|
||||
json_writer.String(get_user_file_checksum(file_path));
|
||||
|
||||
json_writer.Key("acl");
|
||||
json_writer.String("public");
|
||||
|
||||
json_writer.Key("objectID");
|
||||
json_writer.Uint(0);
|
||||
json_writer.Key("contentID");
|
||||
json_writer.Null();
|
||||
json_writer.Key("objectVersion");
|
||||
json_writer.String("");
|
||||
json_writer.Key("contentVersion");
|
||||
json_writer.Null();
|
||||
|
||||
json_writer.Key("contentLength");
|
||||
json_writer.Uint64(utils::io::file_size(file_path));
|
||||
|
||||
json_writer.Key("context");
|
||||
json_writer.String("t8-bnet");
|
||||
|
||||
json_writer.Key("category");
|
||||
json_writer.Null();
|
||||
|
||||
json_writer.Key("created");
|
||||
json_writer.Uint64(static_cast<uint32_t>(time(nullptr)));
|
||||
|
||||
json_writer.Key("modified");
|
||||
json_writer.Uint64(static_cast<uint32_t>(time(nullptr)));
|
||||
|
||||
json_writer.Key("extraData");
|
||||
json_writer.Null();
|
||||
json_writer.Key("extraDataSize");
|
||||
json_writer.Null();
|
||||
json_writer.Key("summaryContentLength");
|
||||
json_writer.Null();
|
||||
json_writer.Key("summaryChecksum");
|
||||
json_writer.Null();
|
||||
json_writer.Key("hasSummary");
|
||||
json_writer.Bool(false);
|
||||
|
||||
json_writer.EndObject();
|
||||
|
||||
json_writer.EndObject();
|
||||
|
||||
return json_buffer.GetString();
|
||||
}
|
||||
|
||||
std::string construct_vectorized_upload_list_json(std::vector<objectMetadata> uploaded_files)
|
||||
{
|
||||
rapidjson::StringBuffer json_buffer{};
|
||||
rapidjson::PrettyWriter<rapidjson::StringBuffer> json_writer(json_buffer);
|
||||
|
||||
json_writer.StartObject();
|
||||
|
||||
json_writer.Key("objects");
|
||||
json_writer.StartArray();
|
||||
|
||||
for (size_t i = 0; i < uploaded_files.size(); i++)
|
||||
{
|
||||
//std::string file_path = get_user_file_path(requested_items[i].owner, requested_items[i].name);
|
||||
|
||||
json_writer.StartObject();
|
||||
|
||||
json_writer.Key("metadata");
|
||||
json_writer.StartObject();
|
||||
|
||||
json_writer.Key("owner");
|
||||
json_writer.String(uploaded_files[i].owner.data());
|
||||
|
||||
json_writer.Key("expiresOn");
|
||||
json_writer.Uint(0);
|
||||
|
||||
json_writer.Key("name");
|
||||
json_writer.String(uploaded_files[i].name.data());
|
||||
|
||||
json_writer.Key("checksum");
|
||||
json_writer.String(uploaded_files[i].checksum.data());
|
||||
|
||||
json_writer.Key("acl");
|
||||
json_writer.String("public");
|
||||
|
||||
json_writer.Key("objectID");
|
||||
json_writer.Uint(0);
|
||||
json_writer.Key("contentID");
|
||||
json_writer.Null();
|
||||
json_writer.Key("objectVersion");
|
||||
json_writer.String("");
|
||||
json_writer.Key("contentVersion");
|
||||
json_writer.Null();
|
||||
|
||||
json_writer.Key("contentLength");
|
||||
json_writer.Uint64(uploaded_files[i].contentLength);
|
||||
|
||||
json_writer.Key("context");
|
||||
json_writer.String("t8-bnet");
|
||||
|
||||
json_writer.Key("category");
|
||||
json_writer.Null();
|
||||
|
||||
json_writer.Key("created");
|
||||
json_writer.Uint64(uploaded_files[i].created);
|
||||
|
||||
json_writer.Key("modified");
|
||||
json_writer.Uint64(uploaded_files[i].modified);
|
||||
|
||||
json_writer.Key("extraData");
|
||||
json_writer.Null();
|
||||
json_writer.Key("extraDataSize");
|
||||
json_writer.Null();
|
||||
json_writer.Key("summaryContentLength");
|
||||
json_writer.Null();
|
||||
json_writer.Key("summaryChecksum");
|
||||
json_writer.Null();
|
||||
json_writer.Key("hasSummary");
|
||||
json_writer.Bool(false);
|
||||
|
||||
json_writer.EndObject();
|
||||
|
||||
json_writer.Key("requestIndex");
|
||||
json_writer.Uint64(i);
|
||||
|
||||
json_writer.EndObject();
|
||||
}
|
||||
|
||||
json_writer.EndArray();
|
||||
|
||||
json_writer.Key("errors");
|
||||
json_writer.StartArray();
|
||||
json_writer.EndArray();
|
||||
|
||||
json_writer.Key("validationTokens");
|
||||
json_writer.StartArray();
|
||||
json_writer.EndArray();
|
||||
|
||||
json_writer.EndObject();
|
||||
|
||||
return json_buffer.GetString();
|
||||
}
|
||||
|
||||
std::string construct_vectorized_upload_list_json(std::vector<std::string> uploaded_files)
|
||||
{
|
||||
std::vector<objectMetadata> files_metadata_list;
|
||||
|
||||
for (std::string file : uploaded_files)
|
||||
{
|
||||
std::string file_path = get_user_file_path(file);
|
||||
int64_t timestamp = static_cast<int64_t>(time(nullptr));
|
||||
files_metadata_list.push_back({ std::format("bnet-{}", platform::bnet_get_userid()), file, get_user_file_checksum(file_path), utils::io::file_size(file_path), timestamp, timestamp, get_user_file_content(file_path) });
|
||||
}
|
||||
|
||||
return construct_vectorized_upload_list_json(files_metadata_list);
|
||||
}
|
||||
|
||||
std::string serialize_objectstore_structed_buffer(std::string payload)
|
||||
{
|
||||
bdProtobufHelper header_1st;
|
||||
header_1st.writeString(1, "Content-Length", 16);
|
||||
header_1st.writeString(2, utils::string::va("%u", payload.length()), 8);
|
||||
|
||||
bdProtobufHelper header_2nd;
|
||||
header_2nd.writeString(1, "Authorization", 16);
|
||||
header_2nd.writeString(2, "Bearer project-bo4", 2048);
|
||||
|
||||
|
||||
bdProtobufHelper buffer;
|
||||
buffer.writeString(1, header_1st.buffer.data(), static_cast<uint32_t>(header_1st.buffer.length()));
|
||||
buffer.writeString(1, header_2nd.buffer.data(), static_cast<uint32_t>(header_2nd.buffer.length()));
|
||||
buffer.writeUInt64(2, 200); // Status Code; Anything NON-2XX is Treated as Error
|
||||
buffer.writeString(3, payload.data(), static_cast<uint32_t>(payload.length()));
|
||||
|
||||
return buffer.buffer;
|
||||
}
|
||||
}
|
38
source/proxy-dll/demonware/objects.hpp
Normal file
38
source/proxy-dll/demonware/objects.hpp
Normal file
@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
struct objectID
|
||||
{
|
||||
std::string owner;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
struct objectMetadata
|
||||
{
|
||||
std::string owner;
|
||||
std::string name;
|
||||
std::string checksum;
|
||||
uint64_t contentLength;
|
||||
int64_t created;
|
||||
int64_t modified;
|
||||
std::string contentURL;
|
||||
};
|
||||
|
||||
std::string get_user_file_path(const std::string& file);
|
||||
|
||||
std::string generate_publisher_objects_list_json(const std::string& category);
|
||||
|
||||
std::string construct_file_upload_result_json(const std::string& uploaded_file);
|
||||
|
||||
std::string generate_user_objects_list_json();
|
||||
std::string generate_user_objects_count_json();
|
||||
|
||||
std::string deliver_user_objects_vectorized_json(std::vector<objectMetadata> requested_items);
|
||||
std::string deliver_user_objects_vectorized_json(std::vector<objectID> requested_items);
|
||||
|
||||
std::string construct_vectorized_upload_list_json(std::vector<objectMetadata> uploaded_files);
|
||||
std::string construct_vectorized_upload_list_json(std::vector<std::string> uploaded_files);
|
||||
|
||||
std::string serialize_objectstore_structed_buffer(std::string payload);
|
||||
}
|
110
source/proxy-dll/demonware/protobuf_helper.cpp
Normal file
110
source/proxy-dll/demonware/protobuf_helper.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
#include <std_include.hpp>
|
||||
#include "protobuf_helper.hpp"
|
||||
#include "ida_defs.h"
|
||||
|
||||
bdProtobufHelper::bdProtobufHelper() {}
|
||||
bdProtobufHelper::~bdProtobufHelper() {}
|
||||
|
||||
/* Yes we unlocked next level of copy-pasta; someone bring the trophy :) */
|
||||
|
||||
bool bdProtobufHelper::encodeVarInt(uint64_t value)
|
||||
{
|
||||
__int64 v2; // rbx
|
||||
unsigned __int64 v4; // rax
|
||||
char v5; // cl
|
||||
char valuea[16]; // [rsp+20h] [rbp-28h] BYREF
|
||||
|
||||
v2 = 0i64;
|
||||
if (value)
|
||||
{
|
||||
do
|
||||
{
|
||||
if ((unsigned int)v2 >= 0xA)
|
||||
break;
|
||||
v4 = value;
|
||||
v5 = value | 0x80;
|
||||
value >>= 7;
|
||||
valuea[v2] = v5;
|
||||
v2 = (unsigned int)(v2 + 1);
|
||||
} while (v4 >= 0x80);
|
||||
valuea[(unsigned int)(v2 - 1)] &= 0x7Fu;
|
||||
}
|
||||
else
|
||||
{
|
||||
valuea[0] = 0;
|
||||
LODWORD(v2) = 1;
|
||||
}
|
||||
//return bdStructSerializationOutputStream::write(stream, valuea, v2) == (_DWORD)v2;
|
||||
this->buffer.append(std::string(valuea, v2));
|
||||
this->length += v2;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool bdProtobufHelper::encodeVarInt(int64_t value)
|
||||
{
|
||||
unsigned __int64 v2; // rax
|
||||
|
||||
v2 = 2 * value;
|
||||
if (value < 0)
|
||||
v2 = ~v2;
|
||||
return bdProtobufHelper::encodeVarInt(v2);
|
||||
}
|
||||
|
||||
bool bdProtobufHelper::encodeString(const char* value, uint32_t len)
|
||||
{
|
||||
bool result; // al
|
||||
|
||||
result = bdProtobufHelper::encodeVarInt(static_cast<uint64_t>(len));
|
||||
if (result)
|
||||
{
|
||||
this->buffer.append(std::string(value, len));
|
||||
this->length += len;
|
||||
}
|
||||
//result = bdStructSerializationOutputStream::write(stream, value, len) == len;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool bdProtobufHelper::encodeTag(uint32_t tagId, eWireType wireType)
|
||||
{
|
||||
unsigned __int64 tag = (int)wireType | (8i64 * tagId);
|
||||
return bdProtobufHelper::encodeVarInt(tag);
|
||||
}
|
||||
|
||||
bool bdProtobufHelper::writeInt64(uint32_t tag, int64_t value)
|
||||
{
|
||||
return bdProtobufHelper::encodeTag(tag, WIRETYPE_VARINT) && bdProtobufHelper::encodeVarInt(value);
|
||||
}
|
||||
|
||||
bool bdProtobufHelper::writeUInt64(uint32_t tag, uint64_t value)
|
||||
{
|
||||
return bdProtobufHelper::encodeTag(tag, WIRETYPE_VARINT) && bdProtobufHelper::encodeVarInt(value);
|
||||
}
|
||||
|
||||
bool bdProtobufHelper::writeInt32(uint32_t tag, int32_t value)
|
||||
{
|
||||
return bdProtobufHelper::encodeTag(tag, WIRETYPE_VARINT) && bdProtobufHelper::encodeVarInt(static_cast<int64_t>(value));
|
||||
}
|
||||
|
||||
bool bdProtobufHelper::writeUInt32(uint32_t tag, uint32_t value)
|
||||
{
|
||||
return bdProtobufHelper::encodeTag(tag, WIRETYPE_VARINT) && bdProtobufHelper::encodeVarInt(static_cast<uint64_t>(value));
|
||||
}
|
||||
|
||||
bool bdProtobufHelper::writeString(uint32_t tag, const char* value, uint32_t size)
|
||||
{
|
||||
unsigned int v5; // edi
|
||||
const void* v8; // rax
|
||||
|
||||
v5 = size;
|
||||
v8 = memchr(value, 0, size);
|
||||
if (v8)
|
||||
v5 = (_DWORD)v8 - (_DWORD)value;
|
||||
return bdProtobufHelper::encodeTag(tag, WIRETYPE_STRING) && bdProtobufHelper::encodeString(value, v5);
|
||||
}
|
||||
|
||||
bool bdProtobufHelper::writeBlob(uint32_t tag, void* buffer, uint32_t size)
|
||||
{
|
||||
return bdProtobufHelper::encodeTag(tag, WIRETYPE_STRING) && bdProtobufHelper::encodeString(reinterpret_cast<const char*>(buffer), size);
|
||||
}
|
38
source/proxy-dll/demonware/protobuf_helper.hpp
Normal file
38
source/proxy-dll/demonware/protobuf_helper.hpp
Normal file
@ -0,0 +1,38 @@
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
enum eWireType
|
||||
{
|
||||
WIRETYPE_VARINT = 0,
|
||||
WIRETYPE_64BIT = 1,
|
||||
WIRETYPE_STRING = 2,
|
||||
WIRETYPE_32BIT = 5,
|
||||
WIRETYPE_INVALID = -1
|
||||
};
|
||||
|
||||
class bdProtobufHelper
|
||||
{
|
||||
public:
|
||||
std::string buffer{};
|
||||
uint32_t length{};
|
||||
|
||||
bdProtobufHelper();
|
||||
~bdProtobufHelper();
|
||||
|
||||
bool write(const void* value, uint32_t byteCount);
|
||||
bool writeString(uint32_t tag, const char* value, uint32_t size);
|
||||
bool writeBlob(uint32_t tag, void* buffer, uint32_t size);
|
||||
bool writeInt64(uint32_t tag, int64_t value);
|
||||
bool writeUInt64(uint32_t tag, uint64_t value);
|
||||
bool writeInt32(uint32_t tag, int32_t value);
|
||||
bool writeUInt32(uint32_t tag, uint32_t value);
|
||||
|
||||
|
||||
private:
|
||||
bool encodeTag(uint32_t tagId, eWireType wireType);
|
||||
bool encodeVarInt(int64_t value);
|
||||
bool encodeVarInt(uint64_t value);
|
||||
bool encodeString(const char* value, uint32_t len);
|
||||
|
||||
|
||||
};
|
87
source/proxy-dll/demonware/reply.cpp
Normal file
87
source/proxy-dll/demonware/reply.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
#include <std_include.hpp>
|
||||
#include "keys.hpp"
|
||||
#include "reply.hpp"
|
||||
#include "servers/service_server.hpp"
|
||||
|
||||
#include <utils/cryptography.hpp>
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
std::string unencrypted_reply::data()
|
||||
{
|
||||
byte_buffer result;
|
||||
result.set_use_data_types(false);
|
||||
|
||||
result.write_int32(static_cast<int>(this->buffer_.size()) + 2);
|
||||
result.write_bool(false);
|
||||
result.write_ubyte(this->type());
|
||||
result.write(this->buffer_);
|
||||
|
||||
return result.get_buffer();
|
||||
}
|
||||
|
||||
std::string encrypted_reply::data()
|
||||
{
|
||||
byte_buffer result;
|
||||
result.set_use_data_types(false);
|
||||
|
||||
byte_buffer enc_buffer;
|
||||
enc_buffer.set_use_data_types(false);
|
||||
|
||||
enc_buffer.write_uint32(static_cast<unsigned int>(this->buffer_.size())); // service data size CHECKTHIS!!
|
||||
enc_buffer.write_ubyte(this->type()); // TASK_REPLY type
|
||||
enc_buffer.write(this->buffer_); // service data
|
||||
|
||||
auto aligned_data = enc_buffer.get_buffer();
|
||||
auto size = aligned_data.size();
|
||||
size = ~15 & (size + 15); // 16 byte align
|
||||
aligned_data.resize(size);
|
||||
|
||||
// seed
|
||||
std::string seed("\x5E\xED\x5E\xED\x5E\xED\x5E\xED\x5E\xED\x5E\xED\x5E\xED\x5E\xED", 16);
|
||||
|
||||
// encrypt
|
||||
const auto enc_data = utils::cryptography::aes::encrypt(aligned_data, seed, demonware::get_encrypt_key());
|
||||
|
||||
// header : encrypted service data : hash
|
||||
static auto msg_count = 0;
|
||||
msg_count++;
|
||||
|
||||
byte_buffer response;
|
||||
response.set_use_data_types(false);
|
||||
|
||||
response.write_int32(30 + static_cast<int>(enc_data.size()));
|
||||
response.write_ubyte(static_cast<unsigned char>(0xAB));
|
||||
response.write_ubyte(static_cast<unsigned char>(0x85));
|
||||
response.write_int32(msg_count);
|
||||
response.write(16, seed.data());
|
||||
response.write(enc_data);
|
||||
|
||||
// hash entire packet and append end
|
||||
auto hash_data = utils::cryptography::hmac_sha1::compute(response.get_buffer(), demonware::get_hmac_key());
|
||||
hash_data.resize(8);
|
||||
response.write(8, hash_data.data());
|
||||
|
||||
return response.get_buffer();
|
||||
}
|
||||
|
||||
void remote_reply::send(bit_buffer* buffer, const bool encrypted)
|
||||
{
|
||||
std::unique_ptr<typed_reply> reply;
|
||||
|
||||
if (encrypted) reply = std::make_unique<encrypted_reply>(this->type_, buffer);
|
||||
else reply = std::make_unique<unencrypted_reply>(this->type_, buffer);
|
||||
|
||||
this->server_->send_reply(reply.get());
|
||||
}
|
||||
|
||||
void remote_reply::send(byte_buffer* buffer, const bool encrypted)
|
||||
{
|
||||
std::unique_ptr<typed_reply> reply;
|
||||
|
||||
if (encrypted) reply = std::make_unique<encrypted_reply>(this->type_, buffer);
|
||||
else reply = std::make_unique<unencrypted_reply>(this->type_, buffer);
|
||||
|
||||
this->server_->send_reply(reply.get());
|
||||
}
|
||||
}
|
198
source/proxy-dll/demonware/reply.hpp
Normal file
198
source/proxy-dll/demonware/reply.hpp
Normal file
@ -0,0 +1,198 @@
|
||||
#pragma once
|
||||
|
||||
#include "bit_buffer.hpp"
|
||||
#include "byte_buffer.hpp"
|
||||
#include "data_types.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class reply
|
||||
{
|
||||
public:
|
||||
reply() = default;
|
||||
|
||||
reply(reply&&) = delete;
|
||||
reply(const reply&) = delete;
|
||||
reply& operator=(reply&&) = delete;
|
||||
reply& operator=(const reply&) = delete;
|
||||
|
||||
virtual ~reply() = default;
|
||||
virtual std::string data() = 0;
|
||||
};
|
||||
|
||||
class raw_reply : public reply
|
||||
{
|
||||
protected:
|
||||
std::string buffer_;
|
||||
|
||||
public:
|
||||
raw_reply() = default;
|
||||
|
||||
explicit raw_reply(std::string data) : buffer_(std::move(data))
|
||||
{
|
||||
}
|
||||
|
||||
std::string data() override
|
||||
{
|
||||
return this->buffer_;
|
||||
}
|
||||
};
|
||||
|
||||
class typed_reply : public raw_reply
|
||||
{
|
||||
public:
|
||||
typed_reply(const uint8_t _type) : type_(_type)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
uint8_t type() const { return this->type_; }
|
||||
|
||||
private:
|
||||
uint8_t type_;
|
||||
};
|
||||
|
||||
class encrypted_reply final : public typed_reply
|
||||
{
|
||||
public:
|
||||
encrypted_reply(const uint8_t type, bit_buffer* bbuffer) : typed_reply(type)
|
||||
{
|
||||
this->buffer_.append(bbuffer->get_buffer());
|
||||
}
|
||||
|
||||
encrypted_reply(const uint8_t type, byte_buffer* bbuffer) : typed_reply(type)
|
||||
{
|
||||
this->buffer_.append(bbuffer->get_buffer());
|
||||
}
|
||||
|
||||
std::string data() override;
|
||||
};
|
||||
|
||||
class unencrypted_reply final : public typed_reply
|
||||
{
|
||||
public:
|
||||
unencrypted_reply(const uint8_t _type, bit_buffer* bbuffer) : typed_reply(_type)
|
||||
{
|
||||
this->buffer_.append(bbuffer->get_buffer());
|
||||
}
|
||||
|
||||
unencrypted_reply(const uint8_t _type, byte_buffer* bbuffer) : typed_reply(_type)
|
||||
{
|
||||
this->buffer_.append(bbuffer->get_buffer());
|
||||
}
|
||||
|
||||
std::string data() override;
|
||||
};
|
||||
|
||||
class service_server;
|
||||
|
||||
class remote_reply final
|
||||
{
|
||||
public:
|
||||
remote_reply(service_server* server, uint8_t _type) : type_(_type), server_(server)
|
||||
{
|
||||
}
|
||||
|
||||
void send(bit_buffer* buffer, bool encrypted);
|
||||
void send(byte_buffer* buffer, bool encrypted);
|
||||
|
||||
uint8_t type() const { return this->type_; }
|
||||
|
||||
private:
|
||||
uint8_t type_;
|
||||
service_server* server_;
|
||||
};
|
||||
|
||||
class service_reply final
|
||||
{
|
||||
public:
|
||||
service_reply(service_server* _server, const uint8_t _type, const uint32_t _error, const bool _structed)
|
||||
: type_(_type), error_(_error), structed_(_structed), reply_(_server, 1)
|
||||
{
|
||||
}
|
||||
|
||||
uint64_t send()
|
||||
{
|
||||
static uint64_t id = 0x0000000000000000;
|
||||
const auto transaction_id = ++id;
|
||||
|
||||
byte_buffer buffer;
|
||||
buffer.write_uint64(transaction_id);
|
||||
buffer.write_uint32(this->error_);
|
||||
buffer.write_ubyte(this->type_);
|
||||
|
||||
if (!this->error_)
|
||||
{
|
||||
if (!structed_)
|
||||
{
|
||||
buffer.write_uint32(uint32_t(this->objects_.size()));
|
||||
if (!this->objects_.empty())
|
||||
{
|
||||
buffer.write_uint32(uint32_t(this->objects_.size()));
|
||||
|
||||
for (auto& object : this->objects_)
|
||||
{
|
||||
object->serialize(&buffer);
|
||||
}
|
||||
|
||||
this->objects_.clear();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!this->objects_.empty())
|
||||
{
|
||||
this->objects_[0]->serialize(&buffer);
|
||||
this->objects_.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer.write_uint64(transaction_id);
|
||||
}
|
||||
|
||||
this->reply_.send(&buffer, true);
|
||||
return transaction_id;
|
||||
}
|
||||
|
||||
void add(const std::shared_ptr<bdTaskResult>& object)
|
||||
{
|
||||
this->objects_.push_back(object);
|
||||
}
|
||||
|
||||
void add(bdTaskResult* object)
|
||||
{
|
||||
this->add(std::shared_ptr<bdTaskResult>(object));
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t type_;
|
||||
uint32_t error_;
|
||||
bool structed_;
|
||||
remote_reply reply_;
|
||||
std::vector<std::shared_ptr<bdTaskResult>> objects_;
|
||||
};
|
||||
|
||||
class structure_reply final
|
||||
{
|
||||
public:
|
||||
structure_reply(service_server* _server, const uint8_t _type)
|
||||
: reply_(_server, _type, 0, 1)
|
||||
{
|
||||
}
|
||||
|
||||
uint64_t send(const std::string& buffer)
|
||||
{
|
||||
auto result = new bdStructedDataBuffer;
|
||||
result->structed_data_protobuffer = buffer;
|
||||
|
||||
this->reply_.add(result);
|
||||
|
||||
return this->reply_.send();
|
||||
}
|
||||
|
||||
private:
|
||||
service_reply reply_;
|
||||
};
|
||||
}
|
60
source/proxy-dll/demonware/server_registry.hpp
Normal file
60
source/proxy-dll/demonware/server_registry.hpp
Normal file
@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
|
||||
#include "servers/base_server.hpp"
|
||||
#include <utils/cryptography.hpp>
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
template <typename T>
|
||||
class server_registry
|
||||
{
|
||||
static_assert(std::is_base_of<base_server, T>::value, "Invalid server registry type");
|
||||
|
||||
public:
|
||||
template <typename S, typename ...Args>
|
||||
void create(Args&&... args)
|
||||
{
|
||||
static_assert(std::is_base_of<T, S>::value, "Invalid server type");
|
||||
|
||||
auto server = std::make_unique<S>(std::forward<Args>(args)...);
|
||||
const auto address = server->get_address();
|
||||
servers_[address] = std::move(server);
|
||||
}
|
||||
|
||||
void for_each(const std::function<void(T&)>& callback) const
|
||||
{
|
||||
for (auto& server : servers_)
|
||||
{
|
||||
callback(*server.second);
|
||||
}
|
||||
}
|
||||
|
||||
T* find(const std::string& name)
|
||||
{
|
||||
const auto address = utils::cryptography::jenkins_one_at_a_time::compute(name);
|
||||
return find(address);
|
||||
}
|
||||
|
||||
T* find(const uint32_t address)
|
||||
{
|
||||
const auto it = servers_.find(address);
|
||||
if (it == servers_.end())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return it->second.get();
|
||||
}
|
||||
|
||||
void frame()
|
||||
{
|
||||
for (auto& server : servers_)
|
||||
{
|
||||
server.second->frame();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::unordered_map<uint32_t, std::unique_ptr<T>> servers_;
|
||||
};
|
||||
}
|
185
source/proxy-dll/demonware/servers/auth3_server.cpp
Normal file
185
source/proxy-dll/demonware/servers/auth3_server.cpp
Normal file
@ -0,0 +1,185 @@
|
||||
#include <std_include.hpp>
|
||||
|
||||
#include "auth3_server.hpp"
|
||||
#include "../keys.hpp"
|
||||
|
||||
#include <utils/cryptography.hpp>
|
||||
#include <utils/string.hpp>
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
namespace
|
||||
{
|
||||
#pragma pack(push, 1)
|
||||
struct auth_ticket
|
||||
{
|
||||
unsigned int m_magicNumber;
|
||||
char m_type;
|
||||
unsigned int m_titleID;
|
||||
unsigned int m_timeIssued;
|
||||
unsigned int m_timeExpires;
|
||||
unsigned __int64 m_licenseID;
|
||||
unsigned __int64 m_userID;
|
||||
char m_username[64];
|
||||
char m_sessionKey[24];
|
||||
char m_usingHashMagicNumber[3];
|
||||
char m_hash[4];
|
||||
};
|
||||
#pragma pack(pop)
|
||||
}
|
||||
|
||||
void auth3_server::send_reply(reply* data)
|
||||
{
|
||||
if (!data) return;
|
||||
this->send(data->data());
|
||||
}
|
||||
|
||||
void auth3_server::handle(const std::string& packet)
|
||||
{
|
||||
if (packet.starts_with("POST /auth/"))
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
logger::write(logger::LOG_TYPE_DEBUG, "[DW]: [auth]: user requested authentication.");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int title_id = 0;
|
||||
unsigned int iv_seed = 0;
|
||||
std::string identity{};
|
||||
std::string session_token{};
|
||||
std::string account_token{};
|
||||
|
||||
rapidjson::Document j;
|
||||
j.Parse(packet.data(), packet.size());
|
||||
|
||||
if (j.HasMember("title_id") && j["title_id"].IsString())
|
||||
{
|
||||
title_id = std::stoul(j["title_id"].GetString());
|
||||
}
|
||||
|
||||
if (j.HasMember("iv_seed") && j["iv_seed"].IsString())
|
||||
{
|
||||
iv_seed = std::stoul(j["iv_seed"].GetString());
|
||||
}
|
||||
|
||||
if (j.HasMember("identity") && j["identity"].IsString())
|
||||
{
|
||||
identity = j["identity"].GetString();
|
||||
}
|
||||
|
||||
if (j.HasMember("extra_data") && j["extra_data"].IsString())
|
||||
{
|
||||
rapidjson::Document extra_data;
|
||||
auto& ed = j["extra_data"];
|
||||
extra_data.Parse(ed.GetString(), ed.GetStringLength());
|
||||
|
||||
if (extra_data.HasMember("session_token") && extra_data["session_token"].IsString())
|
||||
{
|
||||
auto& token_field = extra_data["session_token"];
|
||||
std::string token_b64(token_field.GetString(), token_field.GetStringLength());
|
||||
session_token = token_b64;
|
||||
}
|
||||
if (extra_data.HasMember("account_token") && extra_data["account_token"].IsString())
|
||||
{
|
||||
auto& token_field = extra_data["account_token"];
|
||||
std::string token_b64(token_field.GetString(), token_field.GetStringLength());
|
||||
account_token = utils::cryptography::base64::decode(token_b64);
|
||||
}
|
||||
}
|
||||
|
||||
std::string session_key(
|
||||
"\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37", 24);
|
||||
|
||||
// client_ticket
|
||||
auth_ticket ticket{};
|
||||
std::memset(&ticket, 0x0, sizeof ticket);
|
||||
ticket.m_magicNumber = 0xEFBDADDE;
|
||||
ticket.m_type = 0;
|
||||
ticket.m_titleID = title_id;
|
||||
ticket.m_timeIssued = static_cast<uint32_t>(time(nullptr));
|
||||
ticket.m_timeExpires = ticket.m_timeIssued + 30000;
|
||||
ticket.m_licenseID = 0;
|
||||
ticket.m_userID = 0;
|
||||
strncpy_s(ticket.m_username, sizeof(ticket.m_username), session_token.data(), session_token.length());
|
||||
std::memcpy(ticket.m_sessionKey, session_key.data(), 24);
|
||||
|
||||
const auto client_ticket_b64 = utils::cryptography::base64::encode(reinterpret_cast<const unsigned char*>(&ticket), sizeof(ticket));
|
||||
|
||||
// server_ticket
|
||||
uint8_t server_ticket[128];
|
||||
std::memset(&server_ticket, 0, sizeof server_ticket);
|
||||
std::memcpy(server_ticket, session_key.data(), 24);
|
||||
const auto server_ticket_b64 = utils::cryptography::base64::encode(server_ticket, 128);
|
||||
|
||||
demonware::set_session_key(session_key);
|
||||
|
||||
// header time
|
||||
char date[64];
|
||||
const auto now = time(nullptr);
|
||||
tm gmtm{};
|
||||
gmtime_s(&gmtm, &now);
|
||||
strftime(date, 64, "%a, %d %b %G %T", &gmtm);
|
||||
|
||||
rapidjson::Document extra;
|
||||
extra.SetObject();
|
||||
|
||||
std::string username = std::string(ticket.m_username, sizeof(ticket.m_username)).data();
|
||||
extra.AddMember("username", username, extra.GetAllocator());
|
||||
extra.AddMember("time_to_live", 9999, extra.GetAllocator());
|
||||
|
||||
const auto lul = utils::cryptography::base64::encode("lul");
|
||||
extra.AddMember("extended_data", lul, extra.GetAllocator());
|
||||
|
||||
rapidjson::StringBuffer extra_buffer{};
|
||||
rapidjson::Writer<rapidjson::StringBuffer, rapidjson::Document::EncodingType, rapidjson::ASCII<>>
|
||||
extra_writer(extra_buffer);
|
||||
extra.Accept(extra_writer);
|
||||
|
||||
std::string extra_data{};
|
||||
extra_data.append(extra_buffer.GetString(), extra_buffer.GetLength());
|
||||
// json content
|
||||
rapidjson::Document doc;
|
||||
doc.SetObject();
|
||||
|
||||
doc.AddMember("auth_task", "85", doc.GetAllocator());
|
||||
doc.AddMember("code", "700", doc.GetAllocator());
|
||||
|
||||
auto seed = std::to_string(iv_seed);
|
||||
doc.AddMember("iv_seed", seed, doc.GetAllocator());
|
||||
doc.AddMember("client_ticket", client_ticket_b64, doc.GetAllocator());
|
||||
doc.AddMember("server_ticket", server_ticket_b64, doc.GetAllocator());
|
||||
doc.AddMember("client_id", "treyarch-cod-t8-bnet", doc.GetAllocator());
|
||||
doc.AddMember("account_type", "bnet", doc.GetAllocator());
|
||||
doc.AddMember("crossplay_enabled", false, doc.GetAllocator());
|
||||
doc.AddMember("loginqueue_eanbled", false, doc.GetAllocator());
|
||||
doc.AddMember("identity", identity, doc.GetAllocator());
|
||||
doc.AddMember("extra_data", extra_data, doc.GetAllocator());
|
||||
doc.AddMember("service_level", "paid", doc.GetAllocator());
|
||||
|
||||
rapidjson::Value value{};
|
||||
doc.AddMember("lsg_endpoint", value, doc.GetAllocator());
|
||||
|
||||
rapidjson::StringBuffer buffer{};
|
||||
rapidjson::Writer<rapidjson::StringBuffer, rapidjson::Document::EncodingType, rapidjson::ASCII<>>
|
||||
writer(buffer);
|
||||
doc.Accept(writer);
|
||||
|
||||
// http stuff
|
||||
std::string result;
|
||||
result.append("HTTP/1.1 200 OK\r\n");
|
||||
result.append("Server: TornadoServer/4.5.3\r\n");
|
||||
result.append("Content-Type: application/json\r\n");
|
||||
result.append(utils::string::va("Date: %s GMT\r\n", date));
|
||||
result.append(utils::string::va("Content-Length: %d\r\n\r\n", buffer.GetLength()));
|
||||
result.append(buffer.GetString(), buffer.GetLength());
|
||||
|
||||
raw_reply reply(result);
|
||||
|
||||
this->send_reply(&reply);
|
||||
|
||||
#ifndef NDEBUG
|
||||
logger::write(logger::LOG_TYPE_DEBUG, "[DW]: [auth]: user successfully authenticated.");
|
||||
#endif
|
||||
}
|
||||
}
|
16
source/proxy-dll/demonware/servers/auth3_server.hpp
Normal file
16
source/proxy-dll/demonware/servers/auth3_server.hpp
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
#include "tcp_server.hpp"
|
||||
#include "../reply.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class auth3_server : public tcp_server
|
||||
{
|
||||
public:
|
||||
using tcp_server::tcp_server;
|
||||
|
||||
private:
|
||||
void send_reply(reply* data);
|
||||
void handle(const std::string& packet) override;
|
||||
};
|
||||
}
|
22
source/proxy-dll/demonware/servers/base_server.cpp
Normal file
22
source/proxy-dll/demonware/servers/base_server.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
#include <std_include.hpp>
|
||||
#include "base_server.hpp"
|
||||
|
||||
#include <utils/cryptography.hpp>
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
base_server::base_server(std::string name): name_(std::move(name))
|
||||
{
|
||||
this->address_ = utils::cryptography::jenkins_one_at_a_time::compute(this->name_);
|
||||
}
|
||||
|
||||
const std::string& base_server::get_name() const
|
||||
{
|
||||
return this->name_;
|
||||
}
|
||||
|
||||
uint32_t base_server::get_address() const
|
||||
{
|
||||
return this->address_;
|
||||
}
|
||||
}
|
30
source/proxy-dll/demonware/servers/base_server.hpp
Normal file
30
source/proxy-dll/demonware/servers/base_server.hpp
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class base_server
|
||||
{
|
||||
public:
|
||||
using stream_queue = std::queue<char>;
|
||||
using data_queue = std::queue<std::string>;
|
||||
|
||||
base_server(std::string name);
|
||||
|
||||
base_server(base_server&&) = delete;
|
||||
base_server(const base_server&) = delete;
|
||||
base_server& operator=(base_server&&) = delete;
|
||||
base_server& operator=(const base_server&) = delete;
|
||||
|
||||
virtual ~base_server() = default;
|
||||
|
||||
const std::string& get_name() const;
|
||||
|
||||
uint32_t get_address() const;
|
||||
|
||||
virtual void frame() = 0;
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
std::uint32_t address_ = 0;
|
||||
};
|
||||
}
|
181
source/proxy-dll/demonware/servers/lobby_server.cpp
Normal file
181
source/proxy-dll/demonware/servers/lobby_server.cpp
Normal file
@ -0,0 +1,181 @@
|
||||
#include <std_include.hpp>
|
||||
#include "lobby_server.hpp"
|
||||
|
||||
#include "../services.hpp"
|
||||
#include "../keys.hpp"
|
||||
|
||||
#include <utils/cryptography.hpp>
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
lobby_server::lobby_server(std::string name) : tcp_server(std::move(name))
|
||||
{
|
||||
this->register_service<bdStats>();
|
||||
this->register_service<bdProfiles>();
|
||||
this->register_service<bdTitleUtilities>();
|
||||
this->register_service<bdKeyArchive>();
|
||||
this->register_service<bdBandwidthTest>();
|
||||
this->register_service<bdCounter>();
|
||||
this->register_service<bdDML>();
|
||||
this->register_service<bdGroup>();
|
||||
this->register_service<bdAnticheat>();
|
||||
this->register_service<bdTags>();
|
||||
this->register_service<bdPooledStorage>();
|
||||
this->register_service<bdEventLog>();
|
||||
this->register_service<bdRichPresence>();
|
||||
this->register_service<bdMarketplace>();
|
||||
this->register_service<bdPublisherVariables>();
|
||||
this->register_service<bdMarketingComms>();
|
||||
this->register_service<bdUNK125>();
|
||||
this->register_service<bdObjectStore>();
|
||||
this->register_service<bdLootGeneration>();
|
||||
};
|
||||
|
||||
void lobby_server::send_reply(reply* data)
|
||||
{
|
||||
if (!data) return;
|
||||
this->send(data->data());
|
||||
}
|
||||
|
||||
void lobby_server::handle(const std::string& packet)
|
||||
{
|
||||
byte_buffer buffer(packet);
|
||||
buffer.set_use_data_types(false);
|
||||
|
||||
try
|
||||
{
|
||||
while (buffer.has_more_data())
|
||||
{
|
||||
int size;
|
||||
buffer.read_int32(&size);
|
||||
|
||||
if (size <= 0)
|
||||
{
|
||||
const std::string zero("\x00\x00\x00\x00", 4);
|
||||
raw_reply reply(zero);
|
||||
this->send_reply(&reply);
|
||||
return;
|
||||
}
|
||||
else if (size == 0xC8)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
logger::write(logger::LOG_TYPE_DEBUG, "[DW]: [lobby]: received client_header_ack.");
|
||||
#endif
|
||||
|
||||
int c8;
|
||||
buffer.read_int32(&c8);
|
||||
std::string packet_1 = buffer.get_remaining();
|
||||
demonware::queue_packet_to_hash(packet_1);
|
||||
|
||||
/* msgType[BYTE] serverSelectedProto[DWORD] cypher210ConnID[QWORD] serverNonce[QWORD] */
|
||||
/* 0x81(129) 0xD2(210) 0x3713371337133713 0x3713371337133713 */
|
||||
|
||||
const std::string packet_2(
|
||||
"\x16\x00\x00\x00\xab\x81\xd2\x00\x00\x00\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37\x13\x37",
|
||||
26);
|
||||
demonware::queue_packet_to_hash(packet_2);
|
||||
|
||||
raw_reply reply(packet_2);
|
||||
this->send_reply(&reply);
|
||||
#ifndef NDEBUG
|
||||
logger::write(logger::LOG_TYPE_DEBUG, "[DW]: [lobby]: sending server_header_ack.");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (buffer.size() < size_t(size)) return;
|
||||
|
||||
uint8_t check_ab;
|
||||
buffer.read_ubyte(&check_ab);
|
||||
if (check_ab == 0xAB)
|
||||
{
|
||||
uint8_t type;
|
||||
buffer.read_ubyte(&type);
|
||||
|
||||
if (type == 0x82)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
logger::write(logger::LOG_TYPE_DEBUG, "[DW]: [lobby]: received client_auth.");
|
||||
#endif
|
||||
std::string packet_3(packet.data(), packet.size() - 8); // this 8 are client hash check?
|
||||
|
||||
demonware::queue_packet_to_hash(packet_3);
|
||||
demonware::derive_keys_iw8();
|
||||
|
||||
char buff[14] = "\x0A\x00\x00\x00\xAB\x83";
|
||||
std::memcpy(&buff[6], demonware::get_response_id().data(), 8);
|
||||
std::string response(buff, 14);
|
||||
|
||||
raw_reply reply(response);
|
||||
this->send_reply(&reply);
|
||||
|
||||
#ifndef NDEBUG
|
||||
logger::write(logger::LOG_TYPE_DEBUG, "[DW]: [lobby]: sending server_auth_done.");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
else if (type == 0x85)
|
||||
{
|
||||
uint32_t msg_count;
|
||||
buffer.read_uint32(&msg_count);
|
||||
|
||||
char seed[16];
|
||||
buffer.read(16, &seed);
|
||||
|
||||
std::string enc = buffer.get_remaining();
|
||||
|
||||
char hash[8];
|
||||
std::memcpy(hash, &(enc.data()[enc.size() - 8]), 8);
|
||||
|
||||
std::string dec = utils::cryptography::aes::decrypt(
|
||||
std::string(enc.data(), enc.size() - 8), std::string(seed, 16),
|
||||
demonware::get_decrypt_key());
|
||||
|
||||
byte_buffer serv(dec);
|
||||
serv.set_use_data_types(false);
|
||||
|
||||
uint32_t serv_size;
|
||||
serv.read_uint32(&serv_size);
|
||||
|
||||
uint8_t magic; // 0x86
|
||||
serv.read_ubyte(&magic);
|
||||
|
||||
uint8_t service_id;
|
||||
serv.read_ubyte(&service_id);
|
||||
|
||||
this->call_service(service_id, serv.get_remaining());
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
logger::write(logger::LOG_TYPE_DEBUG, "[DW]: [lobby]: ERROR! received unk message.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void lobby_server::call_service(const uint8_t id, const std::string& data)
|
||||
{
|
||||
const auto& it = this->services_.find(id);
|
||||
|
||||
if (it != this->services_.end())
|
||||
{
|
||||
it->second->exec_task(this, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger::write(logger::LOG_TYPE_DEBUG, "[DW]: [lobby]: missing service '%s'", utils::string::va("%d", id));
|
||||
|
||||
// return no error
|
||||
byte_buffer buffer(data);
|
||||
uint8_t task_id;
|
||||
buffer.read_ubyte(&task_id);
|
||||
|
||||
this->create_reply(task_id)->send();
|
||||
}
|
||||
}
|
||||
}
|
33
source/proxy-dll/demonware/servers/lobby_server.hpp
Normal file
33
source/proxy-dll/demonware/servers/lobby_server.hpp
Normal file
@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include "tcp_server.hpp"
|
||||
#include "service_server.hpp"
|
||||
#include "../service.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class lobby_server : public tcp_server, service_server
|
||||
{
|
||||
public:
|
||||
lobby_server(std::string name);
|
||||
|
||||
template <typename T>
|
||||
void register_service()
|
||||
{
|
||||
static_assert(std::is_base_of<service, T>::value, "service must inherit from service");
|
||||
|
||||
auto service = std::make_unique<T>();
|
||||
const uint8_t id = service->id();
|
||||
|
||||
this->services_[id] = std::move(service);
|
||||
}
|
||||
|
||||
void send_reply(reply* data) override;
|
||||
|
||||
private:
|
||||
std::unordered_map<uint8_t, std::unique_ptr<service>> services_;
|
||||
|
||||
void handle(const std::string& packet) override;
|
||||
void call_service(uint8_t id, const std::string& data);
|
||||
};
|
||||
}
|
33
source/proxy-dll/demonware/servers/service_server.hpp
Normal file
33
source/proxy-dll/demonware/servers/service_server.hpp
Normal file
@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include "../reply.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class service_server
|
||||
{
|
||||
public:
|
||||
virtual ~service_server() = default;
|
||||
|
||||
virtual std::shared_ptr<remote_reply> create_message(uint8_t type)
|
||||
{
|
||||
auto reply = std::make_shared<remote_reply>(this, type);
|
||||
return reply;
|
||||
}
|
||||
|
||||
|
||||
virtual std::shared_ptr<service_reply> create_reply(uint8_t type, uint32_t error = 0)
|
||||
{
|
||||
auto reply = std::make_shared<service_reply>(this, type, error, false);
|
||||
return reply;
|
||||
}
|
||||
|
||||
virtual std::shared_ptr<structure_reply> create_structed_reply(uint8_t type)
|
||||
{
|
||||
auto reply = std::make_shared<structure_reply>(this, type);
|
||||
return reply;
|
||||
}
|
||||
|
||||
virtual void send_reply(reply* data) = 0;
|
||||
};
|
||||
}
|
62
source/proxy-dll/demonware/servers/stun_server.cpp
Normal file
62
source/proxy-dll/demonware/servers/stun_server.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
#include <std_include.hpp>
|
||||
#include "stun_server.hpp"
|
||||
|
||||
#include "../byte_buffer.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
void stun_server::handle(const endpoint_data& endpoint, const std::string& packet)
|
||||
{
|
||||
uint8_t type, version, padding;
|
||||
|
||||
byte_buffer buffer(packet);
|
||||
buffer.set_use_data_types(false);
|
||||
buffer.read_ubyte(&type);
|
||||
buffer.read_ubyte(&version);
|
||||
buffer.read_ubyte(&padding);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case 30:
|
||||
this->ip_discovery(endpoint);
|
||||
break;
|
||||
case 20:
|
||||
this->nat_discovery(endpoint);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void stun_server::ip_discovery(const endpoint_data& endpoint)
|
||||
{
|
||||
const uint32_t ip = 0x0100007f;
|
||||
|
||||
byte_buffer buffer;
|
||||
buffer.set_use_data_types(false);
|
||||
buffer.write_ubyte(31); // type
|
||||
buffer.write_ubyte(2); // version
|
||||
buffer.write_ubyte(0); // version
|
||||
buffer.write_uint32(ip); // external ip
|
||||
buffer.write_uint16(3074); // port
|
||||
|
||||
this->send(endpoint, buffer.get_buffer());
|
||||
}
|
||||
|
||||
void stun_server::nat_discovery(const endpoint_data& endpoint)
|
||||
{
|
||||
const uint32_t ip = 0x0100007f;
|
||||
|
||||
byte_buffer buffer;
|
||||
buffer.set_use_data_types(false);
|
||||
buffer.write_ubyte(21); // type
|
||||
buffer.write_ubyte(2); // version
|
||||
buffer.write_ubyte(0); // version
|
||||
buffer.write_uint32(ip); // external ip
|
||||
buffer.write_uint16(3074); // port
|
||||
buffer.write_uint32(this->get_address()); // server ip
|
||||
buffer.write_uint16(3074); // server port
|
||||
|
||||
this->send(endpoint, buffer.get_buffer());
|
||||
}
|
||||
}
|
18
source/proxy-dll/demonware/servers/stun_server.hpp
Normal file
18
source/proxy-dll/demonware/servers/stun_server.hpp
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "udp_server.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class stun_server : public udp_server
|
||||
{
|
||||
public:
|
||||
using udp_server::udp_server;
|
||||
|
||||
private:
|
||||
void handle(const endpoint_data& endpoint, const std::string& packet) override;
|
||||
|
||||
void ip_discovery(const endpoint_data& endpoint);
|
||||
void nat_discovery(const endpoint_data& endpoint);
|
||||
};
|
||||
}
|
84
source/proxy-dll/demonware/servers/tcp_server.cpp
Normal file
84
source/proxy-dll/demonware/servers/tcp_server.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
#include <std_include.hpp>
|
||||
#include "tcp_server.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
void tcp_server::handle_input(const char* buf, size_t size)
|
||||
{
|
||||
in_queue_.access([&](data_queue& queue)
|
||||
{
|
||||
queue.emplace(buf, size);
|
||||
});
|
||||
}
|
||||
|
||||
size_t tcp_server::handle_output(char* buf, size_t size)
|
||||
{
|
||||
if (out_queue_.get_raw().empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return out_queue_.access<size_t>([&](stream_queue& queue)
|
||||
{
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
if (queue.empty())
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
||||
buf[i] = queue.front();
|
||||
queue.pop();
|
||||
}
|
||||
|
||||
return size;
|
||||
});
|
||||
}
|
||||
|
||||
bool tcp_server::pending_data()
|
||||
{
|
||||
return !this->out_queue_.get_raw().empty();
|
||||
}
|
||||
|
||||
void tcp_server::frame()
|
||||
{
|
||||
if (this->in_queue_.get_raw().empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
std::string packet{};
|
||||
const auto result = this->in_queue_.access<bool>([&](data_queue& queue)
|
||||
{
|
||||
if (queue.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
packet = std::move(queue.front());
|
||||
queue.pop();
|
||||
return true;
|
||||
});
|
||||
|
||||
if (!result)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
this->handle(packet);
|
||||
}
|
||||
}
|
||||
|
||||
void tcp_server::send(const std::string& data)
|
||||
{
|
||||
out_queue_.access([&](stream_queue& queue)
|
||||
{
|
||||
for (const auto& val : data)
|
||||
{
|
||||
queue.push(val);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
27
source/proxy-dll/demonware/servers/tcp_server.hpp
Normal file
27
source/proxy-dll/demonware/servers/tcp_server.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "base_server.hpp"
|
||||
#include <utils/concurrency.hpp>
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class tcp_server : public base_server
|
||||
{
|
||||
public:
|
||||
using base_server::base_server;
|
||||
|
||||
void handle_input(const char* buf, size_t size);
|
||||
size_t handle_output(char* buf, size_t size);
|
||||
bool pending_data();
|
||||
void frame() override;
|
||||
|
||||
protected:
|
||||
virtual void handle(const std::string& data) = 0;
|
||||
|
||||
void send(const std::string& data);
|
||||
|
||||
private:
|
||||
utils::concurrency::container<data_queue> in_queue_;
|
||||
utils::concurrency::container<stream_queue> out_queue_;
|
||||
};
|
||||
}
|
103
source/proxy-dll/demonware/servers/udp_server.cpp
Normal file
103
source/proxy-dll/demonware/servers/udp_server.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
#include <std_include.hpp>
|
||||
#include "udp_server.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
void udp_server::handle_input(const char* buf, size_t size, endpoint_data endpoint)
|
||||
{
|
||||
in_queue_.access([&](in_queue& queue)
|
||||
{
|
||||
in_packet p;
|
||||
p.data = std::string{buf, size};
|
||||
p.endpoint = std::move(endpoint);
|
||||
|
||||
queue.emplace(std::move(p));
|
||||
});
|
||||
}
|
||||
|
||||
size_t udp_server::handle_output(SOCKET socket, char* buf, size_t size, sockaddr* address, int* addrlen)
|
||||
{
|
||||
return out_queue_.access<size_t>([&](socket_queue_map& map) -> size_t
|
||||
{
|
||||
const auto entry = map.find(socket);
|
||||
if (entry == map.end())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto& queue = entry->second;
|
||||
|
||||
if (queue.empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto data = std::move(queue.front());
|
||||
queue.pop();
|
||||
|
||||
const auto copy_size = std::min(size, data.data.size());
|
||||
std::memcpy(buf, data.data.data(), copy_size);
|
||||
std::memcpy(address, &data.address, sizeof(data.address));
|
||||
*addrlen = sizeof(data.address);
|
||||
|
||||
return copy_size;
|
||||
});
|
||||
}
|
||||
|
||||
bool udp_server::pending_data(SOCKET socket)
|
||||
{
|
||||
return this->out_queue_.access<bool>([&](const socket_queue_map& map)
|
||||
{
|
||||
const auto entry = map.find(socket);
|
||||
if (entry == map.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return !entry->second.empty();
|
||||
});
|
||||
}
|
||||
|
||||
void udp_server::send(const endpoint_data& endpoint, std::string data)
|
||||
{
|
||||
out_queue_.access([&](socket_queue_map& map)
|
||||
{
|
||||
out_packet p;
|
||||
p.data = std::move(data);
|
||||
p.address = endpoint.address;
|
||||
|
||||
map[endpoint.socket].emplace(std::move(p));
|
||||
});
|
||||
}
|
||||
|
||||
void udp_server::frame()
|
||||
{
|
||||
if (this->in_queue_.get_raw().empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
in_packet packet{};
|
||||
const auto result = this->in_queue_.access<bool>([&](in_queue& queue)
|
||||
{
|
||||
if (queue.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
packet = std::move(queue.front());
|
||||
queue.pop();
|
||||
return true;
|
||||
});
|
||||
|
||||
if (!result)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
this->handle(packet.endpoint, std::move(packet.data));
|
||||
}
|
||||
}
|
||||
}
|
62
source/proxy-dll/demonware/servers/udp_server.hpp
Normal file
62
source/proxy-dll/demonware/servers/udp_server.hpp
Normal file
@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#include "base_server.hpp"
|
||||
#include <utils/concurrency.hpp>
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class udp_server : public base_server
|
||||
{
|
||||
public:
|
||||
struct endpoint_data
|
||||
{
|
||||
SOCKET socket{};
|
||||
sockaddr_in address{};
|
||||
|
||||
endpoint_data() = default;
|
||||
|
||||
endpoint_data(const SOCKET sock, const sockaddr* addr, const int size)
|
||||
{
|
||||
if (size != sizeof(this->address))
|
||||
{
|
||||
throw std::runtime_error("Invalid size");
|
||||
}
|
||||
|
||||
this->socket = sock;
|
||||
std::memcpy(&this->address, addr, sizeof(this->address));
|
||||
}
|
||||
};
|
||||
|
||||
using base_server::base_server;
|
||||
|
||||
void handle_input(const char* buf, size_t size, endpoint_data endpoint);
|
||||
size_t handle_output(SOCKET socket, char* buf, size_t size, sockaddr* address, int* addrlen);
|
||||
bool pending_data(SOCKET socket);
|
||||
|
||||
void frame() override;
|
||||
|
||||
protected:
|
||||
virtual void handle(const endpoint_data& endpoint, const std::string& data) = 0;
|
||||
void send(const endpoint_data& endpoint, std::string data);
|
||||
|
||||
private:
|
||||
struct in_packet
|
||||
{
|
||||
std::string data;
|
||||
endpoint_data endpoint;
|
||||
};
|
||||
|
||||
struct out_packet
|
||||
{
|
||||
std::string data;
|
||||
sockaddr_in address;
|
||||
};
|
||||
|
||||
using in_queue = std::queue<in_packet>;
|
||||
using out_queue = std::queue<out_packet>;
|
||||
using socket_queue_map = std::unordered_map<SOCKET, out_queue>;
|
||||
|
||||
utils::concurrency::container<in_queue> in_queue_;
|
||||
utils::concurrency::container<socket_queue_map> out_queue_;
|
||||
};
|
||||
}
|
11
source/proxy-dll/demonware/servers/umbrella_server.cpp
Normal file
11
source/proxy-dll/demonware/servers/umbrella_server.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include <std_include.hpp>
|
||||
|
||||
#include "umbrella_server.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
void umbrella_server::handle(const std::string& packet)
|
||||
{
|
||||
// TODO:
|
||||
}
|
||||
}
|
14
source/proxy-dll/demonware/servers/umbrella_server.hpp
Normal file
14
source/proxy-dll/demonware/servers/umbrella_server.hpp
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include "tcp_server.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class umbrella_server : public tcp_server
|
||||
{
|
||||
public:
|
||||
using tcp_server::tcp_server;
|
||||
|
||||
private:
|
||||
void handle(const std::string& packet) override;
|
||||
};
|
||||
}
|
89
source/proxy-dll/demonware/service.hpp
Normal file
89
source/proxy-dll/demonware/service.hpp
Normal file
@ -0,0 +1,89 @@
|
||||
#pragma once
|
||||
#include <utils/string.hpp>
|
||||
#include "servers/service_server.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class service
|
||||
{
|
||||
using callback_t = std::function<void(service_server*, byte_buffer*)>;
|
||||
|
||||
uint8_t id_;
|
||||
std::string name_;
|
||||
std::mutex mutex_;
|
||||
uint8_t task_id_;
|
||||
std::map<uint8_t, callback_t> tasks_;
|
||||
|
||||
public:
|
||||
virtual ~service() = default;
|
||||
service(service&&) = delete;
|
||||
service(const service&) = delete;
|
||||
service& operator=(const service&) = delete;
|
||||
|
||||
service(const uint8_t id, std::string name) : id_(id), name_(std::move(name)), task_id_(0)
|
||||
{
|
||||
}
|
||||
|
||||
uint8_t id() const
|
||||
{
|
||||
return this->id_;
|
||||
}
|
||||
|
||||
const std::string& name() const
|
||||
{
|
||||
return this->name_;
|
||||
}
|
||||
|
||||
uint8_t task_id() const
|
||||
{
|
||||
return this->task_id_;
|
||||
}
|
||||
|
||||
virtual void exec_task(service_server* server, const std::string& data)
|
||||
{
|
||||
std::lock_guard<std::mutex> _(this->mutex_);
|
||||
|
||||
byte_buffer buffer(data);
|
||||
|
||||
buffer.read_ubyte(&this->task_id_);
|
||||
|
||||
const auto& it = this->tasks_.find(this->task_id_);
|
||||
|
||||
if (it != this->tasks_.end())
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
logger::write(logger::LOG_TYPE_DEBUG, "[DW] %s: executing task '%d'", name_.data(), this->task_id_);
|
||||
#endif
|
||||
|
||||
it->second(server, &buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger::write(logger::LOG_TYPE_DEBUG, "[DW] %s: missing task '%d'", name_.data(), this->task_id_);
|
||||
|
||||
// return no error
|
||||
server->create_reply(this->task_id_)->send();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
template <typename Class, typename T, typename... Args>
|
||||
void register_task(const uint8_t id, T (Class::* callback)(Args ...) const)
|
||||
{
|
||||
this->tasks_[id] = [this, callback](Args ... args) -> T
|
||||
{
|
||||
return (reinterpret_cast<Class*>(this)->*callback)(args...);
|
||||
};
|
||||
}
|
||||
|
||||
template <typename Class, typename T, typename... Args>
|
||||
void register_task(const uint8_t id, T (Class::* callback)(Args ...))
|
||||
{
|
||||
this->tasks_[id] = [this, callback](Args ... args) -> T
|
||||
{
|
||||
return (reinterpret_cast<Class*>(this)->*callback)(args...);
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
28
source/proxy-dll/demonware/services.hpp
Normal file
28
source/proxy-dll/demonware/services.hpp
Normal file
@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include "bit_buffer.hpp"
|
||||
#include "byte_buffer.hpp"
|
||||
#include "data_types.hpp"
|
||||
#include "reply.hpp"
|
||||
#include "service.hpp"
|
||||
#include "servers/service_server.hpp"
|
||||
|
||||
#include "services/bdStats.hpp" // 4 [ UNKNOWN ]
|
||||
#include "services/bdProfiles.hpp" // 8
|
||||
#include "services/bdTitleUtilities.hpp" // 12 [ ESSENTIAL ]
|
||||
#include "services/bdKeyArchive.hpp" // 15 [ USELESS ]
|
||||
#include "services/bdBandwidthTest.hpp" // 18
|
||||
#include "services/bdCounter.hpp" // 23
|
||||
#include "services/bdDML.hpp" // 27 [ ESSENTIAL ]
|
||||
#include "services/bdGroup.hpp" // 28 [ USELESS ]
|
||||
#include "services/bdAnticheat.hpp" // 38 [ UNKNOWN ]
|
||||
#include "services/bdTags.hpp" // 52
|
||||
#include "services/bdPooledStorage.hpp" // 58
|
||||
#include "services/bdEventLog.hpp" // 67
|
||||
#include "services/bdRichPresence.hpp" // 68
|
||||
#include "services/bdMarketplace.hpp" // 80
|
||||
#include "services/bdPublisherVariables.hpp"// 95
|
||||
#include "services/bdMarketingComms.hpp" // 104
|
||||
#include "services/bdUNK125.hpp" // 125 [ PATCHED OUT ]
|
||||
#include "services/bdObjectStore.hpp" // 193 [ ESSENTIAL ]
|
||||
#include "services/bdLootGeneration.hpp" // 195 [ UNKNOWN ]
|
49
source/proxy-dll/demonware/services/bdAnticheat.cpp
Normal file
49
source/proxy-dll/demonware/services/bdAnticheat.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../services.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
bdAnticheat::bdAnticheat() : service(38, "bdAnticheat")
|
||||
{
|
||||
this->register_task(2, &bdAnticheat::answerChallenges);
|
||||
this->register_task(3, &bdAnticheat::reportConsoleID);
|
||||
this->register_task(4, &bdAnticheat::reportConsoleDetails);
|
||||
this->register_task(5, &bdAnticheat::answerTOTPChallenge);
|
||||
this->register_task(6, &bdAnticheat::reportExtendedAuthInfo);
|
||||
}
|
||||
|
||||
void bdAnticheat::answerChallenges(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO: Read data as soon as needed
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdAnticheat::reportConsoleID(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO: Read data as soon as needed
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdAnticheat::reportConsoleDetails(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO: Read data as soon as needed
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdAnticheat::answerTOTPChallenge(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO: Read data as soon as needed
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdAnticheat::reportExtendedAuthInfo(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO: Read data as soon as needed
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
}
|
17
source/proxy-dll/demonware/services/bdAnticheat.hpp
Normal file
17
source/proxy-dll/demonware/services/bdAnticheat.hpp
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class bdAnticheat final : public service
|
||||
{
|
||||
public:
|
||||
bdAnticheat();
|
||||
|
||||
private:
|
||||
void answerChallenges(service_server* server, byte_buffer* buffer) const;
|
||||
void reportConsoleID(service_server* server, byte_buffer* buffer) const;
|
||||
void reportConsoleDetails(service_server* server, byte_buffer* buffer) const;
|
||||
void answerTOTPChallenge(service_server* server, byte_buffer* buffer) const;
|
||||
void reportExtendedAuthInfo(service_server* server, byte_buffer* buffer) const;
|
||||
};
|
||||
}
|
27
source/proxy-dll/demonware/services/bdBandwidthTest.cpp
Normal file
27
source/proxy-dll/demonware/services/bdBandwidthTest.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../services.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
static uint8_t bandwidth_iw6[51] =
|
||||
{
|
||||
0x0F, 0xC1, 0x1C, 0x37, 0xB8, 0xEF, 0x7C, 0xD6, 0x00, 0x00, 0x04,
|
||||
0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0xF4, 0x01, 0x00, 0x00, 0xD0, 0x07,
|
||||
0x00, 0x00, 0x10, 0x27, 0x00, 0x00, 0x88, 0x13, 0x00, 0x00, 0xF4, 0x01,
|
||||
0x00, 0x00, 0x02, 0x0C, 0x88, 0xB3, 0x04, 0x65, 0x89, 0xBF, 0xC3, 0x6A,
|
||||
0x27, 0x94, 0xD4, 0x8F
|
||||
};
|
||||
|
||||
bdBandwidthTest::bdBandwidthTest() : service(18, "bdBandwidthTest")
|
||||
{
|
||||
}
|
||||
|
||||
void bdBandwidthTest::exec_task(service_server* server, const std::string& data)
|
||||
{
|
||||
byte_buffer buffer;
|
||||
buffer.write(sizeof bandwidth_iw6, bandwidth_iw6);
|
||||
|
||||
auto reply = server->create_message(5);
|
||||
reply->send(&buffer, true);
|
||||
}
|
||||
}
|
13
source/proxy-dll/demonware/services/bdBandwidthTest.hpp
Normal file
13
source/proxy-dll/demonware/services/bdBandwidthTest.hpp
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class bdBandwidthTest final : public service
|
||||
{
|
||||
public:
|
||||
bdBandwidthTest();
|
||||
|
||||
private:
|
||||
void exec_task(service_server* server, const std::string& data) override;
|
||||
};
|
||||
}
|
25
source/proxy-dll/demonware/services/bdCounter.cpp
Normal file
25
source/proxy-dll/demonware/services/bdCounter.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../services.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
bdCounter::bdCounter() : service(23, "bdCounter")
|
||||
{
|
||||
this->register_task(1, &bdCounter::incrementCounters);
|
||||
this->register_task(2, &bdCounter::getCounterTotals);
|
||||
}
|
||||
|
||||
void bdCounter::incrementCounters(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdCounter::getCounterTotals(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
}
|
14
source/proxy-dll/demonware/services/bdCounter.hpp
Normal file
14
source/proxy-dll/demonware/services/bdCounter.hpp
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class bdCounter final : public service
|
||||
{
|
||||
public:
|
||||
bdCounter();
|
||||
|
||||
private:
|
||||
void incrementCounters(service_server* server, byte_buffer* buffer) const;
|
||||
void getCounterTotals(service_server* server, byte_buffer* buffer) const;
|
||||
};
|
||||
}
|
37
source/proxy-dll/demonware/services/bdDML.cpp
Normal file
37
source/proxy-dll/demonware/services/bdDML.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../services.hpp"
|
||||
|
||||
#include <utils/io.hpp>
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
bdDML::bdDML() : service(27, "bdDML")
|
||||
{
|
||||
this->register_task(3, &bdDML::getUserHierarchicalData);
|
||||
}
|
||||
|
||||
void bdDML::getUserHierarchicalData(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
auto result = new bdDMLHierarchicalInfo;
|
||||
result->country_code = "US";
|
||||
result->country = "United States";
|
||||
result->region = "New York";
|
||||
result->city = "New York";
|
||||
result->latitude = 0;
|
||||
result->longitude = 0;
|
||||
|
||||
result->asn = 0x2119;
|
||||
result->timezone = "+01:00";
|
||||
|
||||
result->m_tier0 = 0;
|
||||
result->m_tier1 = 0;
|
||||
result->m_tier2 = 0;
|
||||
result->m_tier3 = 0;
|
||||
result->m_confidence = 0;
|
||||
|
||||
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->add(result);
|
||||
reply->send();
|
||||
}
|
||||
}
|
16
source/proxy-dll/demonware/services/bdDML.hpp
Normal file
16
source/proxy-dll/demonware/services/bdDML.hpp
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class bdDML final : public service
|
||||
{
|
||||
public:
|
||||
bdDML();
|
||||
|
||||
private:
|
||||
void recordIP(service_server* server, byte_buffer* buffer) const;
|
||||
void getUserData(service_server* server, byte_buffer* buffer) const;
|
||||
void getUserHierarchicalData(service_server* server, byte_buffer* buffer) const;
|
||||
void getUsersLastLogonData(service_server* server, byte_buffer* buffer) const;
|
||||
};
|
||||
}
|
57
source/proxy-dll/demonware/services/bdEventLog.cpp
Normal file
57
source/proxy-dll/demonware/services/bdEventLog.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../services.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
bdEventLog::bdEventLog() : service(67, "bdEventLog")
|
||||
{
|
||||
this->register_task(1, &bdEventLog::recordEvent);
|
||||
this->register_task(2, &bdEventLog::recordEventBin);
|
||||
this->register_task(3, &bdEventLog::recordEvents);
|
||||
this->register_task(4, &bdEventLog::recordEventsBin);
|
||||
this->register_task(5, &bdEventLog::recordEventsMixed);
|
||||
this->register_task(6, &bdEventLog::initializeFiltering);
|
||||
}
|
||||
|
||||
void bdEventLog::recordEvent(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdEventLog::recordEventBin(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdEventLog::recordEvents(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdEventLog::recordEventsBin(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdEventLog::recordEventsMixed(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdEventLog::initializeFiltering(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
}
|
18
source/proxy-dll/demonware/services/bdEventLog.hpp
Normal file
18
source/proxy-dll/demonware/services/bdEventLog.hpp
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class bdEventLog final : public service
|
||||
{
|
||||
public:
|
||||
bdEventLog();
|
||||
|
||||
private:
|
||||
void recordEvent(service_server* server, byte_buffer* buffer) const;
|
||||
void recordEventBin(service_server* server, byte_buffer* buffer) const;
|
||||
void recordEvents(service_server* server, byte_buffer* buffer) const;
|
||||
void recordEventsBin(service_server* server, byte_buffer* buffer) const;
|
||||
void recordEventsMixed(service_server* server, byte_buffer* buffer) const;
|
||||
void initializeFiltering(service_server* server, byte_buffer* buffer) const;
|
||||
};
|
||||
}
|
41
source/proxy-dll/demonware/services/bdGroup.cpp
Normal file
41
source/proxy-dll/demonware/services/bdGroup.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../services.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
bdGroup::bdGroup() : service(28, "bdGroup")
|
||||
{
|
||||
this->register_task(1, &bdGroup::setGroups);
|
||||
this->register_task(2, &bdGroup::setGroupsForEntity);
|
||||
this->register_task(3, &bdGroup::getEntityGroups);
|
||||
this->register_task(4, &bdGroup::getGroupCounts);
|
||||
}
|
||||
|
||||
void bdGroup::setGroups(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdGroup::setGroupsForEntity(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdGroup::getEntityGroups(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdGroup::getGroupCounts(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
}
|
16
source/proxy-dll/demonware/services/bdGroup.hpp
Normal file
16
source/proxy-dll/demonware/services/bdGroup.hpp
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class bdGroup final : public service
|
||||
{
|
||||
public:
|
||||
bdGroup();
|
||||
|
||||
private:
|
||||
void setGroups(service_server* server, byte_buffer* buffer) const;
|
||||
void setGroupsForEntity(service_server* server, byte_buffer* buffer) const;
|
||||
void getEntityGroups(service_server* server, byte_buffer* buffer) const;
|
||||
void getGroupCounts(service_server* server, byte_buffer* buffer) const;
|
||||
};
|
||||
}
|
48
source/proxy-dll/demonware/services/bdKeyArchive.cpp
Normal file
48
source/proxy-dll/demonware/services/bdKeyArchive.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../services.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
bdKeyArchive::bdKeyArchive() : service(15, "bdKeyArchive")
|
||||
{
|
||||
this->register_task(1, &bdKeyArchive::write);
|
||||
this->register_task(2, &bdKeyArchive::read);
|
||||
this->register_task(3, &bdKeyArchive::readAll);
|
||||
this->register_task(5, &bdKeyArchive::readMultipleEntityIDs);
|
||||
this->register_task(6, &bdKeyArchive::writeMultipleEntityIDs);
|
||||
}
|
||||
|
||||
void bdKeyArchive::write(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdKeyArchive::read(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdKeyArchive::readAll(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdKeyArchive::readMultipleEntityIDs(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
void bdKeyArchive::writeMultipleEntityIDs(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
}
|
17
source/proxy-dll/demonware/services/bdKeyArchive.hpp
Normal file
17
source/proxy-dll/demonware/services/bdKeyArchive.hpp
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class bdKeyArchive final : public service
|
||||
{
|
||||
public:
|
||||
bdKeyArchive();
|
||||
|
||||
private:
|
||||
void write(service_server* server, byte_buffer* buffer) const;
|
||||
void read(service_server* server, byte_buffer* buffer) const;
|
||||
void readAll(service_server* server, byte_buffer* buffer) const;
|
||||
void readMultipleEntityIDs(service_server* server, byte_buffer* buffer) const;
|
||||
void writeMultipleEntityIDs(service_server* server, byte_buffer* buffer) const;
|
||||
};
|
||||
}
|
17
source/proxy-dll/demonware/services/bdLootGeneration.cpp
Normal file
17
source/proxy-dll/demonware/services/bdLootGeneration.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../services.hpp"
|
||||
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
bdLootGeneration::bdLootGeneration() : service(195, "bdLootGeneration")
|
||||
{
|
||||
this->register_task(2, &bdLootGeneration::getPlayerState);
|
||||
}
|
||||
|
||||
void bdLootGeneration::getPlayerState(service_server* server, byte_buffer* buffer) const
|
||||
{
|
||||
auto reply = server->create_structed_reply(this->task_id());
|
||||
reply->send(""); // Un-handled
|
||||
}
|
||||
}
|
13
source/proxy-dll/demonware/services/bdLootGeneration.hpp
Normal file
13
source/proxy-dll/demonware/services/bdLootGeneration.hpp
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class bdLootGeneration final : public service
|
||||
{
|
||||
public:
|
||||
bdLootGeneration();
|
||||
|
||||
private:
|
||||
void getPlayerState(service_server* server, byte_buffer* buffer) const;
|
||||
};
|
||||
}
|
25
source/proxy-dll/demonware/services/bdMarketingComms.cpp
Normal file
25
source/proxy-dll/demonware/services/bdMarketingComms.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../services.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
bdMarketingComms::bdMarketingComms() : service(104, "bdMarketingComms")
|
||||
{
|
||||
this->register_task(6, &bdMarketingComms::getMessages);
|
||||
this->register_task(7, &bdMarketingComms::reportMessagesViewed);
|
||||
}
|
||||
|
||||
void bdMarketingComms::getMessages(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdMarketingComms::reportMessagesViewed(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
}
|
14
source/proxy-dll/demonware/services/bdMarketingComms.hpp
Normal file
14
source/proxy-dll/demonware/services/bdMarketingComms.hpp
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class bdMarketingComms final : public service
|
||||
{
|
||||
public:
|
||||
bdMarketingComms();
|
||||
|
||||
private:
|
||||
void getMessages(service_server* server, byte_buffer* buffer) const;
|
||||
void reportMessagesViewed(service_server* server, byte_buffer* buffer) const;
|
||||
};
|
||||
}
|
26
source/proxy-dll/demonware/services/bdMarketplace.cpp
Normal file
26
source/proxy-dll/demonware/services/bdMarketplace.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../services.hpp"
|
||||
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
bdMarketplace::bdMarketplace() : service(80, "bdMarketplace")
|
||||
{
|
||||
this->register_task(204, &bdMarketplace::getInventoryPaginated);
|
||||
this->register_task(245, &bdMarketplace::getBalancesV3);
|
||||
}
|
||||
|
||||
void bdMarketplace::getInventoryPaginated(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdMarketplace::getBalancesV3(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_structed_reply(this->task_id());
|
||||
reply->send("");
|
||||
}
|
||||
}
|
14
source/proxy-dll/demonware/services/bdMarketplace.hpp
Normal file
14
source/proxy-dll/demonware/services/bdMarketplace.hpp
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class bdMarketplace final : public service
|
||||
{
|
||||
public:
|
||||
bdMarketplace();
|
||||
|
||||
private:
|
||||
void getInventoryPaginated(service_server* server, byte_buffer* buffer) const;
|
||||
void getBalancesV3(service_server* server, byte_buffer* buffer) const;
|
||||
};
|
||||
}
|
168
source/proxy-dll/demonware/services/bdObjectStore.cpp
Normal file
168
source/proxy-dll/demonware/services/bdObjectStore.cpp
Normal file
@ -0,0 +1,168 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../services.hpp"
|
||||
#include <picoproto.h>
|
||||
|
||||
#include <utils/io.hpp>
|
||||
#include "../objects.hpp"
|
||||
#include <utils/cryptography.hpp>
|
||||
#include <component/platform.hpp>
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
bdObjectStore::bdObjectStore() : service(193, "bdObjectStore")
|
||||
{
|
||||
this->register_task(3, &bdObjectStore::listUserObjects);
|
||||
this->register_task(18, &bdObjectStore::getUserObjectCounts);
|
||||
|
||||
this->register_task(8, &bdObjectStore::getPublisherObject);
|
||||
this->register_task(9, &bdObjectStore::listPublisherObjectsByCategory);
|
||||
|
||||
this->register_task(6, &bdObjectStore::getUserObjectsVectorized);
|
||||
this->register_task(2, &bdObjectStore::uploadUserObject);
|
||||
this->register_task(5, &bdObjectStore::getUserObject); // Un-handled; Not used by engine at all
|
||||
this->register_task(7, &bdObjectStore::uploadUserObjectsVectorized);
|
||||
|
||||
this->register_task(16, &bdObjectStore::getPublisherObjectMetadatas); // Un-handled; Not needed if user already has LPC
|
||||
}
|
||||
|
||||
void bdObjectStore::getUserObject(service_server* server, byte_buffer* buffer) const
|
||||
{
|
||||
auto reply = server->create_reply(this->task_id(), 20000/*BD_OBJECTSTORE_PROXY_OBJECT_NOT_FOUND*/);
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdObjectStore::getPublisherObject(service_server* server, byte_buffer* buffer) const
|
||||
{
|
||||
auto reply = server->create_reply(this->task_id(), 20000/*BD_OBJECTSTORE_PROXY_OBJECT_NOT_FOUND*/);
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdObjectStore::listUserObjects(service_server* server, byte_buffer* buffer) const
|
||||
{
|
||||
std::string response_json = generate_user_objects_list_json();
|
||||
std::string response_buff = serialize_objectstore_structed_buffer(response_json);
|
||||
|
||||
auto reply = server->create_structed_reply(this->task_id());
|
||||
reply->send(response_buff);
|
||||
}
|
||||
|
||||
void bdObjectStore::getUserObjectCounts(service_server* server, byte_buffer* buffer) const
|
||||
{
|
||||
std::string response_json = generate_user_objects_count_json();
|
||||
std::string response_buff = serialize_objectstore_structed_buffer(response_json);
|
||||
|
||||
auto reply = server->create_structed_reply(this->task_id());
|
||||
reply->send(response_buff);
|
||||
}
|
||||
|
||||
void bdObjectStore::listPublisherObjectsByCategory(service_server* server, byte_buffer* buffer) const
|
||||
{
|
||||
std::string response_json = generate_publisher_objects_list_json("");
|
||||
std::string response_buff = serialize_objectstore_structed_buffer(response_json);
|
||||
|
||||
auto reply = server->create_structed_reply(this->task_id());
|
||||
reply->send(response_buff);
|
||||
}
|
||||
|
||||
void bdObjectStore::getUserObjectsVectorized(service_server* server, byte_buffer* buffer) const
|
||||
{
|
||||
std::string structed_data;
|
||||
buffer->read_struct(&structed_data);
|
||||
|
||||
picoproto::Message request_buffer;
|
||||
request_buffer.ParseFromBytes(reinterpret_cast<uint8_t*>(structed_data.data()), structed_data.size());
|
||||
|
||||
std::string str4 = request_buffer.GetString(4);
|
||||
picoproto::Message nested_buffer;
|
||||
nested_buffer.ParseFromBytes(reinterpret_cast<uint8_t*>(str4.data()), str4.size());
|
||||
|
||||
std::vector<objectID> requested_objects_list;
|
||||
|
||||
rapidjson::Document requested_objects_list_json;
|
||||
requested_objects_list_json.Parse(nested_buffer.GetString(2));
|
||||
for (rapidjson::SizeType i = 0; i < requested_objects_list_json.Size(); i++) {
|
||||
requested_objects_list.push_back({ std::format("bnet-{}", platform::bnet_get_userid())/*requested_objects_list_json[i]["owner"].GetString()*/, requested_objects_list_json[i]["name"].GetString() });
|
||||
}
|
||||
|
||||
std::string response_json = deliver_user_objects_vectorized_json(requested_objects_list);
|
||||
std::string response_buff = serialize_objectstore_structed_buffer(response_json);
|
||||
|
||||
auto reply = server->create_structed_reply(this->task_id());
|
||||
reply->send(response_buff);
|
||||
}
|
||||
|
||||
void bdObjectStore::getPublisherObjectMetadatas(service_server* server, byte_buffer* buffer) const
|
||||
{
|
||||
auto reply = server->create_structed_reply(this->task_id());
|
||||
reply->send(""); // Un-handled
|
||||
}
|
||||
|
||||
void bdObjectStore::uploadUserObject(service_server* server, byte_buffer* buffer) const
|
||||
{
|
||||
std::string structed_data;
|
||||
buffer->read_struct(&structed_data);
|
||||
|
||||
picoproto::Message request_buffer;
|
||||
request_buffer.ParseFromBytes(reinterpret_cast<uint8_t*>(structed_data.data()), structed_data.size());
|
||||
|
||||
std::string request = request_buffer.GetString(1);
|
||||
std::string url = request_buffer.GetString(2);
|
||||
std::string data = request_buffer.GetString(3);
|
||||
|
||||
std::string file = utils::string::split(url, '/')[8];
|
||||
std::string path = get_user_file_path(file);
|
||||
|
||||
if (!utils::io::write_file(path, data))
|
||||
logger::write(logger::LOG_TYPE_DEBUG, "[bdObjectStore::uploadUserObject] error on writing '%s'", file.data());
|
||||
else
|
||||
logger::write(logger::LOG_TYPE_DEBUG, "[bdObjectStore::uploadUserObject] saved user file '%s'", file.data());
|
||||
|
||||
std::string response_json = construct_file_upload_result_json(file);
|
||||
std::string response_buff = serialize_objectstore_structed_buffer(response_json);
|
||||
|
||||
auto reply = server->create_structed_reply(this->task_id());
|
||||
reply->send(response_buff);
|
||||
}
|
||||
|
||||
void bdObjectStore::uploadUserObjectsVectorized(service_server* server, byte_buffer* buffer) const
|
||||
{
|
||||
std::string structed_data;
|
||||
buffer->read_struct(&structed_data);
|
||||
|
||||
picoproto::Message request_buffer;
|
||||
request_buffer.ParseFromBytes(reinterpret_cast<uint8_t*>(structed_data.data()), structed_data.size());
|
||||
|
||||
std::string request = request_buffer.GetString(1);
|
||||
std::string payload = request_buffer.GetString(3);
|
||||
|
||||
rapidjson::Document vectorized_upload_json;
|
||||
vectorized_upload_json.Parse(payload.data());
|
||||
|
||||
std::vector<std::string> uploaded_objects_list;
|
||||
|
||||
const rapidjson::Value& objects = vectorized_upload_json["objects"];
|
||||
for (rapidjson::SizeType i = 0; i < objects.Size(); i++) // Uses SizeType instead of size_t
|
||||
{
|
||||
const rapidjson::Value& content = objects[i]["content"];
|
||||
const rapidjson::Value& name = objects[i]["metadata"]["name"];
|
||||
const rapidjson::Value& checksum = objects[i]["metadata"]["checksum"];
|
||||
|
||||
std::string data = utils::cryptography::base64::decode(content.GetString());
|
||||
const auto path = std::format("{}/{}", platform::get_userdata_directory(), name.GetString());
|
||||
|
||||
uploaded_objects_list.push_back(name.GetString());
|
||||
|
||||
if (!utils::io::write_file(path, data))
|
||||
logger::write(logger::LOG_TYPE_DEBUG, "[bdObjectStore::uploadUserObjectsVectorized] error on writing '%s'", name.GetString());
|
||||
else
|
||||
logger::write(logger::LOG_TYPE_DEBUG, "[bdObjectStore::uploadUserObjectsVectorized] saved user file '%s'", name.GetString());
|
||||
}
|
||||
|
||||
std::string response_json = construct_vectorized_upload_list_json(uploaded_objects_list);
|
||||
std::string response_buff = serialize_objectstore_structed_buffer(response_json);
|
||||
|
||||
auto reply = server->create_structed_reply(this->task_id());
|
||||
reply->send(response_buff);
|
||||
}
|
||||
}
|
||||
|
21
source/proxy-dll/demonware/services/bdObjectStore.hpp
Normal file
21
source/proxy-dll/demonware/services/bdObjectStore.hpp
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class bdObjectStore final : public service
|
||||
{
|
||||
public:
|
||||
bdObjectStore();
|
||||
|
||||
private:
|
||||
void getUserObject(service_server* server, byte_buffer* buffer) const;
|
||||
void getPublisherObject(service_server* server, byte_buffer* buffer) const;
|
||||
void listUserObjects(service_server* server, byte_buffer* buffer) const;
|
||||
void getUserObjectCounts(service_server* server, byte_buffer* buffer) const;
|
||||
void listPublisherObjectsByCategory(service_server* server, byte_buffer* buffer) const;
|
||||
void getUserObjectsVectorized(service_server* server, byte_buffer* buffer) const;
|
||||
void getPublisherObjectMetadatas(service_server* server, byte_buffer* buffer) const;
|
||||
void uploadUserObject(service_server* server, byte_buffer* buffer) const;
|
||||
void uploadUserObjectsVectorized(service_server* server, byte_buffer* buffer) const;
|
||||
};
|
||||
}
|
97
source/proxy-dll/demonware/services/bdPooledStorage.cpp
Normal file
97
source/proxy-dll/demonware/services/bdPooledStorage.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../services.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
bdPooledStorage::bdPooledStorage() : service(58, "bdPooledStorage")
|
||||
{
|
||||
this->register_task(1, &bdPooledStorage::getPooledMetaDataByID);
|
||||
this->register_task(5, &bdPooledStorage::_preUpload);
|
||||
this->register_task(6, &bdPooledStorage::_postUploadFile);
|
||||
this->register_task(8, &bdPooledStorage::remove);
|
||||
this->register_task(9, &bdPooledStorage::_preDownload);
|
||||
this->register_task(17, &bdPooledStorage::_preUploadSummary);
|
||||
this->register_task(18, &bdPooledStorage::_postUploadSummary);
|
||||
this->register_task(19, &bdPooledStorage::_preDownloadSummary);
|
||||
this->register_task(20, &bdPooledStorage::_preUploadMultiPart);
|
||||
this->register_task(21, &bdPooledStorage::_postUploadMultiPart);
|
||||
this->register_task(22, &bdPooledStorage::_preDownloadMultiPart);
|
||||
}
|
||||
|
||||
void bdPooledStorage::getPooledMetaDataByID(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdPooledStorage::_preUpload(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdPooledStorage::_postUploadFile(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdPooledStorage::remove(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdPooledStorage::_preDownload(service_server* server, byte_buffer* buffer) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdPooledStorage::_preUploadSummary(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdPooledStorage::_postUploadSummary(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdPooledStorage::_preDownloadSummary(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdPooledStorage::_preUploadMultiPart(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdPooledStorage::_postUploadMultiPart(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdPooledStorage::_preDownloadMultiPart(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
}
|
23
source/proxy-dll/demonware/services/bdPooledStorage.hpp
Normal file
23
source/proxy-dll/demonware/services/bdPooledStorage.hpp
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class bdPooledStorage final : public service
|
||||
{
|
||||
public:
|
||||
bdPooledStorage();
|
||||
|
||||
private:
|
||||
void getPooledMetaDataByID(service_server* server, byte_buffer* buffer) const;
|
||||
void _preUpload(service_server* server, byte_buffer* buffer) const;
|
||||
void _postUploadFile(service_server* server, byte_buffer* buffer) const;
|
||||
void remove(service_server* server, byte_buffer* buffer) const;
|
||||
void _preDownload(service_server* server, byte_buffer* buffer) const;
|
||||
void _preUploadSummary(service_server* server, byte_buffer* buffer) const;
|
||||
void _postUploadSummary(service_server* server, byte_buffer* buffer) const;
|
||||
void _preDownloadSummary(service_server* server, byte_buffer* buffer) const;
|
||||
void _preUploadMultiPart(service_server* server, byte_buffer* buffer) const;
|
||||
void _postUploadMultiPart(service_server* server, byte_buffer* buffer) const;
|
||||
void _preDownloadMultiPart(service_server* server, byte_buffer* buffer) const;
|
||||
};
|
||||
}
|
95
source/proxy-dll/demonware/services/bdProfiles.cpp
Normal file
95
source/proxy-dll/demonware/services/bdProfiles.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../services.hpp"
|
||||
#include <utils/io.hpp>
|
||||
#include <component/platform.hpp>
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
bdProfiles::bdProfiles() : service(8, "bdProfiles")
|
||||
{
|
||||
this->register_task(1, &bdProfiles::getPublicInfos);
|
||||
this->register_task(2, &bdProfiles::getPrivateInfo);
|
||||
this->register_task(3, &bdProfiles::setPublicInfo);
|
||||
this->register_task(4, &bdProfiles::setPrivateInfo);
|
||||
this->register_task(5, &bdProfiles::deleteProfile);
|
||||
this->register_task(6, &bdProfiles::setPrivateInfoByUserID);
|
||||
this->register_task(7, &bdProfiles::getPrivateInfoByUserID);
|
||||
this->register_task(8, &bdProfiles::setPublicInfoByUserID);
|
||||
}
|
||||
|
||||
void bdProfiles::getPublicInfos(service_server* server, byte_buffer* buffer) const
|
||||
{
|
||||
uint64_t entity_id;
|
||||
buffer->read_uint64(&entity_id);
|
||||
|
||||
auto* result = new bdPublicProfileInfo;
|
||||
result->m_entityID = entity_id;
|
||||
result->m_VERSION = 4;
|
||||
|
||||
if (utils::io::read_file(std::format("{}/profileInfo_{}", platform::get_userdata_directory(), entity_id), &result->m_ddl))
|
||||
{
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->add(result);
|
||||
reply->send();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto reply = server->create_reply(this->task_id(), 800/*BD_NO_PROFILE_INFO_EXISTS*/);
|
||||
reply->send();
|
||||
}
|
||||
}
|
||||
|
||||
void bdProfiles::setPublicInfo(service_server* server, byte_buffer* buffer) const
|
||||
{
|
||||
int32_t version; std::string ddl;
|
||||
buffer->read_int32(&version);
|
||||
buffer->read_blob(&ddl);
|
||||
|
||||
utils::io::write_file(std::format("{}/profileInfo_{}", platform::get_userdata_directory(), platform::bnet_get_userid()), ddl);
|
||||
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdProfiles::getPrivateInfo(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdProfiles::setPrivateInfo(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdProfiles::deleteProfile(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdProfiles::setPrivateInfoByUserID(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdProfiles::getPrivateInfoByUserID(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdProfiles::setPublicInfoByUserID(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
}
|
20
source/proxy-dll/demonware/services/bdProfiles.hpp
Normal file
20
source/proxy-dll/demonware/services/bdProfiles.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class bdProfiles final : public service
|
||||
{
|
||||
public:
|
||||
bdProfiles();
|
||||
|
||||
private:
|
||||
void getPublicInfos(service_server* server, byte_buffer* buffer) const;
|
||||
void getPrivateInfo(service_server* server, byte_buffer* buffer) const;
|
||||
void setPublicInfo(service_server* server, byte_buffer* buffer) const;
|
||||
void setPrivateInfo(service_server* server, byte_buffer* buffer) const;
|
||||
void deleteProfile(service_server* server, byte_buffer* buffer) const;
|
||||
void setPrivateInfoByUserID(service_server* server, byte_buffer* buffer) const;
|
||||
void getPrivateInfoByUserID(service_server* server, byte_buffer* buffer) const;
|
||||
void setPublicInfoByUserID(service_server* server, byte_buffer* buffer) const;
|
||||
};
|
||||
}
|
17
source/proxy-dll/demonware/services/bdPublisherVariables.cpp
Normal file
17
source/proxy-dll/demonware/services/bdPublisherVariables.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../services.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
bdPublisherVariables::bdPublisherVariables() : service(95, "bdPublisherVariables")
|
||||
{
|
||||
this->register_task(1, &bdPublisherVariables::retrievePublisherVariables);
|
||||
}
|
||||
|
||||
void bdPublisherVariables::retrievePublisherVariables(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
}
|
13
source/proxy-dll/demonware/services/bdPublisherVariables.hpp
Normal file
13
source/proxy-dll/demonware/services/bdPublisherVariables.hpp
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class bdPublisherVariables final : public service
|
||||
{
|
||||
public:
|
||||
bdPublisherVariables();
|
||||
|
||||
private:
|
||||
void retrievePublisherVariables(service_server* server, byte_buffer* buffer) const;
|
||||
};
|
||||
}
|
25
source/proxy-dll/demonware/services/bdRichPresence.cpp
Normal file
25
source/proxy-dll/demonware/services/bdRichPresence.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../services.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
bdRichPresence::bdRichPresence() : service(68, "bdRichPresence")
|
||||
{
|
||||
this->register_task(1, &bdRichPresence::setInfo);
|
||||
this->register_task(2, &bdRichPresence::getInfo);
|
||||
}
|
||||
|
||||
void bdRichPresence::setInfo(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdRichPresence::getInfo(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
}
|
14
source/proxy-dll/demonware/services/bdRichPresence.hpp
Normal file
14
source/proxy-dll/demonware/services/bdRichPresence.hpp
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class bdRichPresence final : public service
|
||||
{
|
||||
public:
|
||||
bdRichPresence();
|
||||
|
||||
private:
|
||||
void setInfo(service_server* server, byte_buffer* buffer) const;
|
||||
void getInfo(service_server* server, byte_buffer* buffer) const;
|
||||
};
|
||||
}
|
113
source/proxy-dll/demonware/services/bdStats.cpp
Normal file
113
source/proxy-dll/demonware/services/bdStats.cpp
Normal file
@ -0,0 +1,113 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../services.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
bdStats::bdStats() : service(4, "bdStats")
|
||||
{
|
||||
this->register_task(1, &bdStats::writeStats);
|
||||
this->register_task(2, &bdStats::deleteStats);
|
||||
this->register_task(3, &bdStats::readStatsByEntityID);
|
||||
this->register_task(4, &bdStats::readStatsByRank);
|
||||
this->register_task(5, &bdStats::readStatsByPivot);
|
||||
this->register_task(6, &bdStats::readStatsByRating);
|
||||
this->register_task(7, &bdStats::readStatsByMultipleRanks);
|
||||
this->register_task(8, &bdStats::readExternalTitleStats);
|
||||
this->register_task(10, &bdStats::readExternalTitleNamedStats);
|
||||
this->register_task(11, &bdStats::readStatsByLeaderboardIDsAndEntityIDs);
|
||||
this->register_task(12, &bdStats::readStatsByMultipleRatings);
|
||||
this->register_task(13, &bdStats::startTaskStatReadByEntityIDV2);
|
||||
//this->register_task(14, &bdStats::writeServerValidatedStats);
|
||||
}
|
||||
|
||||
void bdStats::writeStats(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdStats::deleteStats(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdStats::readStatsByEntityID(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdStats::readStatsByRank(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdStats::readStatsByPivot(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdStats::readStatsByRating(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdStats::readStatsByMultipleRanks(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdStats::readExternalTitleStats(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdStats::readExternalTitleNamedStats(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdStats::readStatsByLeaderboardIDsAndEntityIDs(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdStats::readStatsByMultipleRatings(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdStats::startTaskStatReadByEntityIDV2(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdStats::writeServerValidatedStats(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
}
|
25
source/proxy-dll/demonware/services/bdStats.hpp
Normal file
25
source/proxy-dll/demonware/services/bdStats.hpp
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class bdStats final : public service
|
||||
{
|
||||
public:
|
||||
bdStats();
|
||||
|
||||
private:
|
||||
void writeStats(service_server* server, byte_buffer* buffer) const;
|
||||
void deleteStats(service_server* server, byte_buffer* buffer) const;
|
||||
void readStatsByEntityID(service_server* server, byte_buffer* buffer) const;
|
||||
void readStatsByRank(service_server* server, byte_buffer* buffer) const;
|
||||
void readStatsByPivot(service_server* server, byte_buffer* buffer) const;
|
||||
void readStatsByRating(service_server* server, byte_buffer* buffer) const;
|
||||
void readStatsByMultipleRanks(service_server* server, byte_buffer* buffer) const;
|
||||
void readExternalTitleStats(service_server* server, byte_buffer* buffer) const;
|
||||
void readExternalTitleNamedStats(service_server* server, byte_buffer* buffer) const;
|
||||
void readStatsByLeaderboardIDsAndEntityIDs(service_server* server, byte_buffer* buffer) const;
|
||||
void readStatsByMultipleRatings(service_server* server, byte_buffer* buffer) const;
|
||||
void startTaskStatReadByEntityIDV2(service_server* server, byte_buffer* buffer) const;
|
||||
void writeServerValidatedStats(service_server* server, byte_buffer* buffer) const;
|
||||
};
|
||||
}
|
49
source/proxy-dll/demonware/services/bdTags.cpp
Normal file
49
source/proxy-dll/demonware/services/bdTags.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../services.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
bdTags::bdTags() : service(52, "bdTags")
|
||||
{
|
||||
this->register_task(1, &bdTags::getTagsForEntityIDs);
|
||||
this->register_task(2, &bdTags::setTagsForEntityID);
|
||||
this->register_task(3, &bdTags::removeTagsForEntityID);
|
||||
this->register_task(4, &bdTags::removeAllTagsForEntityID);
|
||||
this->register_task(5, &bdTags::searchByTagsBase);
|
||||
}
|
||||
|
||||
void bdTags::getTagsForEntityIDs(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdTags::setTagsForEntityID(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdTags::removeTagsForEntityID(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdTags::removeAllTagsForEntityID(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdTags::searchByTagsBase(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
}
|
17
source/proxy-dll/demonware/services/bdTags.hpp
Normal file
17
source/proxy-dll/demonware/services/bdTags.hpp
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class bdTags final : public service
|
||||
{
|
||||
public:
|
||||
bdTags();
|
||||
|
||||
private:
|
||||
void getTagsForEntityIDs(service_server* server, byte_buffer* buffer) const;
|
||||
void setTagsForEntityID(service_server* server, byte_buffer* buffer) const;
|
||||
void removeTagsForEntityID(service_server* server, byte_buffer* buffer) const;
|
||||
void removeAllTagsForEntityID(service_server* server, byte_buffer* buffer) const;
|
||||
void searchByTagsBase(service_server* server, byte_buffer* buffer) const;
|
||||
};
|
||||
}
|
68
source/proxy-dll/demonware/services/bdTitleUtilities.cpp
Normal file
68
source/proxy-dll/demonware/services/bdTitleUtilities.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../services.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
bdTitleUtilities::bdTitleUtilities() : service(12, "bdTitleUtilities")
|
||||
{
|
||||
this->register_task(1, &bdTitleUtilities::verifyString);
|
||||
this->register_task(2, &bdTitleUtilities::getTitleStats);
|
||||
this->register_task(6, &bdTitleUtilities::getServerTime);
|
||||
this->register_task(7, &bdTitleUtilities::areUsersOnline);
|
||||
this->register_task(8, &bdTitleUtilities::getMAC);
|
||||
this->register_task(9, &bdTitleUtilities::getUserNames);
|
||||
this->register_task(10, &bdTitleUtilities::getUserIDs);
|
||||
}
|
||||
|
||||
void bdTitleUtilities::getServerTime(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
auto* const time_result = new bdTimeStamp;
|
||||
time_result->unix_time = uint32_t(time(nullptr));
|
||||
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->add(time_result);
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdTitleUtilities::verifyString(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdTitleUtilities::getTitleStats(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdTitleUtilities::areUsersOnline(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdTitleUtilities::getMAC(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdTitleUtilities::getUserNames(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
|
||||
void bdTitleUtilities::getUserIDs(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_reply(this->task_id());
|
||||
reply->send();
|
||||
}
|
||||
}
|
19
source/proxy-dll/demonware/services/bdTitleUtilities.hpp
Normal file
19
source/proxy-dll/demonware/services/bdTitleUtilities.hpp
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class bdTitleUtilities final : public service
|
||||
{
|
||||
public:
|
||||
bdTitleUtilities();
|
||||
|
||||
private:
|
||||
void verifyString(service_server* server, byte_buffer* buffer) const;
|
||||
void getTitleStats(service_server* server, byte_buffer* buffer) const;
|
||||
void getServerTime(service_server* server, byte_buffer* buffer) const;
|
||||
void areUsersOnline(service_server* server, byte_buffer* buffer) const;
|
||||
void getMAC(service_server* server, byte_buffer* buffer) const;
|
||||
void getUserNames(service_server* server, byte_buffer* buffer) const;
|
||||
void getUserIDs(service_server* server, byte_buffer* buffer) const;
|
||||
};
|
||||
}
|
41
source/proxy-dll/demonware/services/bdUNK125.cpp
Normal file
41
source/proxy-dll/demonware/services/bdUNK125.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../services.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
bdUNK125::bdUNK125() : service(125, "bdUNK125")
|
||||
{
|
||||
this->register_task(1, &bdUNK125::task_unk1);
|
||||
this->register_task(2, &bdUNK125::task_unk2);
|
||||
this->register_task(3, &bdUNK125::task_unk3);
|
||||
this->register_task(9, &bdUNK125::task_unk9);
|
||||
}
|
||||
|
||||
void bdUNK125::task_unk1(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_structed_reply(this->task_id());
|
||||
reply->send("");
|
||||
}
|
||||
|
||||
void bdUNK125::task_unk2(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_structed_reply(this->task_id());
|
||||
reply->send("");
|
||||
}
|
||||
|
||||
void bdUNK125::task_unk3(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_structed_reply(this->task_id());
|
||||
reply->send("");
|
||||
}
|
||||
|
||||
void bdUNK125::task_unk9(service_server* server, byte_buffer* /*buffer*/) const
|
||||
{
|
||||
// TODO:
|
||||
auto reply = server->create_structed_reply(this->task_id());
|
||||
reply->send("");
|
||||
}
|
||||
}
|
16
source/proxy-dll/demonware/services/bdUNK125.hpp
Normal file
16
source/proxy-dll/demonware/services/bdUNK125.hpp
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class bdUNK125 final : public service
|
||||
{
|
||||
public:
|
||||
bdUNK125();
|
||||
|
||||
private:
|
||||
void task_unk1(service_server* server, byte_buffer* buffer) const;
|
||||
void task_unk2(service_server* server, byte_buffer* buffer) const;
|
||||
void task_unk3(service_server* server, byte_buffer* buffer) const;
|
||||
void task_unk9(service_server* server, byte_buffer* buffer) const;
|
||||
};
|
||||
}
|
@ -5,6 +5,9 @@
|
||||
#define ID_ICON 102
|
||||
#define IMAGE_SPLASH 103
|
||||
|
||||
#define DW_PUBLISHER_OBJECTS_LIST 104
|
||||
#define DW_AUTH_TRAFFIC_SIGNING_KEY 105
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
|
@ -51,7 +51,7 @@ END
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
ID_ICON ICON "resources/icon.ico"
|
||||
ID_ICON ICON "resources/icon.ico"
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@ -59,7 +59,10 @@ ID_ICON ICON "resources/icon.ico"
|
||||
// RCDATA
|
||||
//
|
||||
|
||||
IMAGE_SPLASH RCDATA "resources/splash.jpg"
|
||||
IMAGE_SPLASH RCDATA "resources/splash.jpg"
|
||||
|
||||
DW_PUBLISHER_OBJECTS_LIST RCDATA "resources/dw/publisher_objects_list.csv"
|
||||
DW_AUTH_TRAFFIC_SIGNING_KEY RCDATA "resources/dw/auth_traffic_signing_key.dat"
|
||||
|
||||
|
||||
#endif // English (United States) resources
|
||||
|
BIN
source/proxy-dll/resources/dw/auth_traffic_signing_key.dat
Normal file
BIN
source/proxy-dll/resources/dw/auth_traffic_signing_key.dat
Normal file
Binary file not shown.
12
source/proxy-dll/resources/dw/publisher_objects_list.csv
Normal file
12
source/proxy-dll/resources/dw/publisher_objects_list.csv
Normal file
@ -0,0 +1,12 @@
|
||||
arasafe_core_ffotd_tu23_639_cf92ecf4a75d3f79.ff,2432,FCB3F6D4A4A21A2AE399E3D8F2430126
|
||||
arasafe_core_playlists_tu23_639_cf92ecf4a75d3f79.ff,2432,2C20B802AEA7FCDFF599BA40B554FB58
|
||||
core_ffotd_tu23_639_cf92ecf4a75d3f79.ff,10315840,002F37761AF31051C400EC8DB5095062
|
||||
core_playlists_tu23_639_cf92ecf4a75d3f79.ff,30912,99DD77754218042A01D8F2D082028C68
|
||||
en_core_ffotd_tu23_639_cf92ecf4a75d3f79.ff,38784,8C6ED0DCA0ECA3AF1B9811AC2108E5CE
|
||||
en_core_playlists_tu23_639_cf92ecf4a75d3f79.ff,25472,210E50AB866C9AFCBE7B866E5059C1DD
|
||||
gersafe_core_ffotd_tu23_639_cf92ecf4a75d3f79.ff,2432,0120914E8A43330ECB5B211208E0763E
|
||||
gersafe_core_playlists_tu23_639_cf92ecf4a75d3f79.ff,2432,814775B5E27BE462607537852C9C42F1
|
||||
jpsafe_core_ffotd_tu23_639_cf92ecf4a75d3f79.ff,2432,2D743D8D63B074A97151807CA502ABC4
|
||||
jpsafe_core_playlists_tu23_639_cf92ecf4a75d3f79.ff,2432,71BEA66B0385C06EB1F660A64F36654D
|
||||
k15safe_core_ffotd_tu23_639_cf92ecf4a75d3f79.ff,2432,8125C3EC0729F0D33C1373E60CD6D61B
|
||||
k15safe_core_playlists_tu23_639_cf92ecf4a75d3f79.ff,2432,4DB74A55B84648964E866132C66DFB3F
|
|
@ -563,6 +563,46 @@ namespace utils::cryptography
|
||||
return string::dump_hex(hash, "");
|
||||
}
|
||||
|
||||
std::string md5::compute(const std::string& data, const bool hex)
|
||||
{
|
||||
return compute(cs(data.data()), data.size(), hex);
|
||||
}
|
||||
|
||||
std::string md5::compute(const uint8_t* data, const size_t length, const bool hex)
|
||||
{
|
||||
uint8_t buffer[16] = { 0 };
|
||||
|
||||
hash_state state;
|
||||
md5_init(&state);
|
||||
md5_process(&state, data, ul(length));
|
||||
md5_done(&state, buffer);
|
||||
|
||||
std::string hash(cs(buffer), sizeof(buffer));
|
||||
if (!hex) return hash;
|
||||
|
||||
return string::dump_hex(hash, "");
|
||||
}
|
||||
|
||||
uint32_t xxh32::compute(const std::string& data)
|
||||
{
|
||||
return compute(cs(data.data()), data.size());
|
||||
}
|
||||
|
||||
uint32_t xxh32::compute(const uint8_t* data, const size_t length)
|
||||
{
|
||||
return XXHash32::hash(data, length, 0);
|
||||
}
|
||||
|
||||
uint64_t xxh64::compute(const std::string& data)
|
||||
{
|
||||
return compute(cs(data.data()), data.size());
|
||||
}
|
||||
|
||||
uint64_t xxh64::compute(const uint8_t* data, const size_t length)
|
||||
{
|
||||
return XXHash64::hash(data, length, 0);
|
||||
}
|
||||
|
||||
std::string base64::encode(const uint8_t* data, const size_t len)
|
||||
{
|
||||
std::string result;
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
#include <string>
|
||||
#include <tomcrypt.h>
|
||||
#include <xxhash32.h>
|
||||
#include <xxhash64.h>
|
||||
|
||||
namespace utils::cryptography
|
||||
{
|
||||
@ -96,6 +98,24 @@ namespace utils::cryptography
|
||||
std::string compute(const uint8_t* data, size_t length, bool hex = false);
|
||||
}
|
||||
|
||||
namespace md5
|
||||
{
|
||||
std::string compute(const std::string& data, bool hex = false);
|
||||
std::string compute(const uint8_t* data, size_t length, bool hex = false);
|
||||
}
|
||||
|
||||
namespace xxh32
|
||||
{
|
||||
uint32_t compute(const std::string& data);
|
||||
uint32_t compute(const uint8_t* data, size_t length);
|
||||
}
|
||||
|
||||
namespace xxh64
|
||||
{
|
||||
uint64_t compute(const std::string& data);
|
||||
uint64_t compute(const uint8_t* data, size_t length);
|
||||
}
|
||||
|
||||
namespace base64
|
||||
{
|
||||
std::string encode(const uint8_t* data, size_t len);
|
||||
|
@ -1,11 +1,12 @@
|
||||
#include "smbios.hpp"
|
||||
#include "identity.hpp"
|
||||
#include "memory.hpp"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <intrin.h>
|
||||
#include <lmcons.h>
|
||||
|
||||
namespace utils::smbios
|
||||
namespace utils::identity
|
||||
{
|
||||
namespace
|
||||
{
|
||||
@ -61,7 +62,19 @@ namespace utils::smbios
|
||||
}
|
||||
}
|
||||
|
||||
std::string get_uuid()
|
||||
std::string get_sys_username()
|
||||
{
|
||||
char username[UNLEN + 1];
|
||||
DWORD username_len = UNLEN + 1;
|
||||
if (!GetUserNameA(username, &username_len))
|
||||
{
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
return std::string{ username, username_len - 1 };
|
||||
}
|
||||
|
||||
std::string get_sys_uuid()
|
||||
{
|
||||
auto smbios_data = get_smbios_data();
|
||||
auto* raw_data = reinterpret_cast<RawSMBIOSData*>(smbios_data.data());
|
9
source/shared-code/utils/identity.hpp
Normal file
9
source/shared-code/utils/identity.hpp
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace utils::identity
|
||||
{
|
||||
std::string get_sys_username();
|
||||
std::string get_sys_uuid();
|
||||
}
|
@ -78,6 +78,14 @@ namespace utils::io
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string file_name(const std::string& path)
|
||||
{
|
||||
const auto pos = path.find_last_of('/');
|
||||
if (pos == std::string::npos) return path;
|
||||
|
||||
return path.substr(pos + 1);
|
||||
}
|
||||
|
||||
size_t file_size(const std::string& file)
|
||||
{
|
||||
if (file_exists(file))
|
||||
@ -94,6 +102,13 @@ namespace utils::io
|
||||
return 0;
|
||||
}
|
||||
|
||||
time_t file_timestamp(const std::string& file)
|
||||
{
|
||||
const auto time = std::chrono::clock_cast<std::chrono::system_clock>(std::filesystem::last_write_time(file));
|
||||
|
||||
return std::chrono::system_clock::to_time_t(time);
|
||||
}
|
||||
|
||||
bool create_directory(const std::string& directory)
|
||||
{
|
||||
return std::filesystem::create_directories(directory);
|
||||
@ -115,6 +130,8 @@ namespace utils::io
|
||||
|
||||
for (auto& file : std::filesystem::directory_iterator(directory))
|
||||
{
|
||||
if (std::filesystem::is_directory(file.path())) continue;
|
||||
|
||||
files.push_back(file.path().generic_string());
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,9 @@ namespace utils::io
|
||||
bool write_file(const std::string& file, const std::string& data, bool append = false);
|
||||
bool read_file(const std::string& file, std::string* data);
|
||||
std::string read_file(const std::string& file);
|
||||
std::string file_name(const std::string& path);
|
||||
size_t file_size(const std::string& file);
|
||||
time_t file_timestamp(const std::string& file);
|
||||
bool create_directory(const std::string& directory);
|
||||
bool directory_exists(const std::string& directory);
|
||||
bool directory_is_empty(const std::string& directory);
|
||||
|
184
source/shared-code/utils/json_config.cpp
Normal file
184
source/shared-code/utils/json_config.cpp
Normal file
@ -0,0 +1,184 @@
|
||||
#include "json_config.hpp"
|
||||
#include "io.hpp"
|
||||
|
||||
#include <rapidjson/document.h>
|
||||
#include <rapidjson/stringbuffer.h>
|
||||
#include <rapidjson/prettywriter.h>
|
||||
|
||||
namespace utils::json_config
|
||||
{
|
||||
rapidjson::Document json_doc{};
|
||||
std::string file_name = "project-bo4.json";
|
||||
|
||||
namespace
|
||||
{
|
||||
bool read_json_config()
|
||||
{
|
||||
std::string json_data{};
|
||||
if (!io::read_file(file_name, &json_data)) return false;
|
||||
|
||||
json_doc.Parse(json_data);
|
||||
|
||||
if (json_doc.HasParseError()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool write_json_config()
|
||||
{
|
||||
rapidjson::StringBuffer buffer;
|
||||
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer);
|
||||
json_doc.Accept(writer);
|
||||
|
||||
std::string json_data(buffer.GetString(), buffer.GetLength());
|
||||
if (!io::write_file(file_name, json_data)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
rapidjson::Document& get_json_document()
|
||||
{
|
||||
static bool json_initialized = false;
|
||||
if (!json_initialized)
|
||||
{
|
||||
if (!read_json_config()) {
|
||||
json_doc = rapidjson::Document(rapidjson::kObjectType);
|
||||
}
|
||||
|
||||
json_initialized = true;
|
||||
}
|
||||
|
||||
/*if (json_doc != NULL) */return json_doc;
|
||||
}
|
||||
|
||||
rapidjson::Value& get_json_section(const char* szSection)
|
||||
{
|
||||
rapidjson::Document& doc = get_json_document();
|
||||
|
||||
if (!doc.HasMember(szSection))
|
||||
{
|
||||
doc.AddMember(rapidjson::StringRef(szSection), rapidjson::kObjectType, doc.GetAllocator());
|
||||
}
|
||||
|
||||
rapidjson::Value& section = doc[szSection];
|
||||
|
||||
if (!section.IsObject()) section.SetObject();
|
||||
|
||||
return section;
|
||||
}
|
||||
|
||||
std::string ReadString(const char* szSection, const char* szKey, const std::string& strDefaultValue)
|
||||
{
|
||||
rapidjson::Document& doc = get_json_document();
|
||||
rapidjson::Value& section = get_json_section(szSection);
|
||||
|
||||
if (!section.HasMember(szKey)) {
|
||||
section.AddMember(rapidjson::StringRef(szKey), strDefaultValue, doc.GetAllocator());
|
||||
}
|
||||
else if (!section[szKey].IsString()) {
|
||||
section[szKey].SetString(strDefaultValue, doc.GetAllocator());
|
||||
}
|
||||
else {
|
||||
return section[szKey].GetString();
|
||||
}
|
||||
|
||||
write_json_config();
|
||||
return section[szKey].GetString();
|
||||
}
|
||||
|
||||
void WriteString(const char* szSection, const char* szKey, const std::string& strValue)
|
||||
{
|
||||
rapidjson::Document& doc = get_json_document();
|
||||
rapidjson::Value& section = get_json_section(szSection);
|
||||
|
||||
if (!section.HasMember(szKey)) {
|
||||
section.AddMember(rapidjson::StringRef(szKey), strValue, doc.GetAllocator());
|
||||
}
|
||||
else {
|
||||
section[szKey].SetString(strValue, doc.GetAllocator());
|
||||
}
|
||||
|
||||
write_json_config();
|
||||
}
|
||||
|
||||
unsigned int ReadUnsignedInteger(const char* szSection, const char* szKey, unsigned int iDefaultValue)
|
||||
{
|
||||
rapidjson::Document& doc = get_json_document();
|
||||
rapidjson::Value& section = get_json_section(szSection);
|
||||
|
||||
if (!section.HasMember(szKey)) {
|
||||
section.AddMember(rapidjson::StringRef(szKey), iDefaultValue, doc.GetAllocator());
|
||||
}
|
||||
else if (!section[szKey].IsUint()) {
|
||||
section[szKey].SetUint(iDefaultValue);
|
||||
}
|
||||
else {
|
||||
return section[szKey].GetUint();
|
||||
}
|
||||
|
||||
write_json_config();
|
||||
return section[szKey].GetUint();
|
||||
}
|
||||
|
||||
int ReadInteger(const char* szSection, const char* szKey, int iDefaultValue)
|
||||
{
|
||||
return static_cast<int>(ReadUnsignedInteger(szSection, szKey, static_cast<unsigned int>(iDefaultValue)));
|
||||
}
|
||||
|
||||
void WriteUnsignedInteger(const char* szSection, const char* szKey, unsigned int iValue)
|
||||
{
|
||||
rapidjson::Document& doc = get_json_document();
|
||||
rapidjson::Value& section = get_json_section(szSection);
|
||||
|
||||
if (!section.HasMember(szKey)) {
|
||||
section.AddMember(rapidjson::StringRef(szKey), iValue, doc.GetAllocator());
|
||||
}
|
||||
else {
|
||||
section[szKey].SetUint(iValue);
|
||||
}
|
||||
|
||||
write_json_config();
|
||||
}
|
||||
|
||||
void WriteInteger(const char* szSection, const char* szKey, int iValue)
|
||||
{
|
||||
ReadUnsignedInteger(szSection, szKey, static_cast<unsigned int>(iValue));
|
||||
}
|
||||
|
||||
bool ReadBoolean(const char* szSection, const char* szKey, bool bolDefaultValue)
|
||||
{
|
||||
rapidjson::Document& doc = get_json_document();
|
||||
rapidjson::Value& section = get_json_section(szSection);
|
||||
|
||||
if (!section.HasMember(szKey)) {
|
||||
section.AddMember(rapidjson::StringRef(szKey), bolDefaultValue, doc.GetAllocator());
|
||||
}
|
||||
else if (!section[szKey].IsBool()) {
|
||||
section[szKey].SetBool(bolDefaultValue);
|
||||
}
|
||||
else {
|
||||
return section[szKey].GetBool();
|
||||
}
|
||||
|
||||
write_json_config();
|
||||
return section[szKey].GetBool();
|
||||
}
|
||||
|
||||
void WriteBoolean(const char* szSection, const char* szKey, bool bolValue)
|
||||
{
|
||||
rapidjson::Document& doc = get_json_document();
|
||||
rapidjson::Value& section = get_json_section(szSection);
|
||||
|
||||
if (!section.HasMember(szKey)) {
|
||||
section.AddMember(rapidjson::StringRef(szKey), bolValue, doc.GetAllocator());
|
||||
}
|
||||
else {
|
||||
section[szKey].SetBool(bolValue);
|
||||
}
|
||||
|
||||
write_json_config();
|
||||
}
|
||||
}
|
17
source/shared-code/utils/json_config.hpp
Normal file
17
source/shared-code/utils/json_config.hpp
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
namespace utils::json_config
|
||||
{
|
||||
std::string ReadString(const char* szSection, const char* szKey, const std::string& strDefaultValue);
|
||||
void WriteString(const char* szSection, const char* szKey, const std::string& strValue);
|
||||
|
||||
unsigned int ReadUnsignedInteger(const char* szSection, const char* szKey, unsigned int iDefaultValue);
|
||||
void WriteUnsignedInteger(const char* szSection, const char* szKey, unsigned int iValue);
|
||||
|
||||
int ReadInteger(const char* szSection, const char* szKey, int iDefaultValue);
|
||||
void WriteInteger(const char* szSection, const char* szKey, int iValue);
|
||||
|
||||
bool ReadBoolean(const char* szSection, const char* szKey, bool bolDefaultValue);
|
||||
void WriteBoolean(const char* szSection, const char* szKey, bool bolValue);
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace utils::smbios
|
||||
{
|
||||
std::string get_uuid();
|
||||
}
|
@ -34,6 +34,23 @@ namespace utils::string
|
||||
return elems;
|
||||
}
|
||||
|
||||
std::vector<std::string> split(const std::string& s, const std::string& delim)
|
||||
{
|
||||
size_t pos_start = 0, pos_end, delim_len = delim.length();
|
||||
std::string token;
|
||||
std::vector<std::string> elems;
|
||||
|
||||
while ((pos_end = s.find(delim, pos_start)) != std::string::npos) {
|
||||
token = s.substr(pos_start, pos_end - pos_start);
|
||||
pos_start = pos_end + delim_len;
|
||||
elems.push_back(token);
|
||||
}
|
||||
|
||||
elems.push_back(s.substr(pos_start));
|
||||
|
||||
return elems;
|
||||
}
|
||||
|
||||
std::string to_lower(std::string text)
|
||||
{
|
||||
std::transform(text.begin(), text.end(), text.begin(), [](const char input)
|
||||
|
@ -81,6 +81,7 @@ namespace utils::string
|
||||
const char* va(const char* fmt, ...);
|
||||
|
||||
std::vector<std::string> split(const std::string& s, char delim);
|
||||
std::vector<std::string> split(const std::string& s, const std::string& delim);
|
||||
|
||||
std::string to_lower(std::string text);
|
||||
std::string to_upper(std::string text);
|
||||
|
Reference in New Issue
Block a user