Prepare demonware emulator
This commit is contained in:
parent
dd45c6a0a5
commit
b2a7cf0dd6
11
.gitmodules
vendored
11
.gitmodules
vendored
@ -11,3 +11,14 @@
|
|||||||
path = deps/zlib
|
path = deps/zlib
|
||||||
url = https://github.com/madler/zlib.git
|
url = https://github.com/madler/zlib.git
|
||||||
branch = develop
|
branch = develop
|
||||||
|
[submodule "deps/libtomcrypt"]
|
||||||
|
path = deps/libtomcrypt
|
||||||
|
url = https://github.com/libtom/libtomcrypt.git
|
||||||
|
branch = develop
|
||||||
|
[submodule "deps/libtommath"]
|
||||||
|
path = deps/libtommath
|
||||||
|
url = https://github.com/libtom/libtommath.git
|
||||||
|
branch = develop
|
||||||
|
[submodule "deps/rapidjson"]
|
||||||
|
path = deps/rapidjson
|
||||||
|
url = https://github.com/Tencent/rapidjson.git
|
||||||
|
1
deps/libtomcrypt
vendored
Submodule
1
deps/libtomcrypt
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit e6be20bfc7e92c91dc1ef9cb5cc11a326e41f706
|
1
deps/libtommath
vendored
Submodule
1
deps/libtommath
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 4b47368501321c795d5b54d87a5bab35a21a7940
|
61
deps/premake/libtomcrypt.lua
vendored
Normal file
61
deps/premake/libtomcrypt.lua
vendored
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
libtomcrypt = {
|
||||||
|
source = path.join(dependencies.basePath, "libtomcrypt"),
|
||||||
|
}
|
||||||
|
|
||||||
|
function libtomcrypt.import()
|
||||||
|
links {
|
||||||
|
"libtomcrypt"
|
||||||
|
}
|
||||||
|
|
||||||
|
libtomcrypt.includes()
|
||||||
|
end
|
||||||
|
|
||||||
|
function libtomcrypt.includes()
|
||||||
|
includedirs {
|
||||||
|
path.join(libtomcrypt.source, "src/headers")
|
||||||
|
}
|
||||||
|
|
||||||
|
defines {
|
||||||
|
"LTC_NO_FAST",
|
||||||
|
"LTC_NO_PROTOTYPES",
|
||||||
|
"LTC_NO_RSA_BLINDING",
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
function libtomcrypt.project()
|
||||||
|
project "libtomcrypt"
|
||||||
|
language "C"
|
||||||
|
|
||||||
|
libtomcrypt.includes()
|
||||||
|
libtommath.import()
|
||||||
|
|
||||||
|
files {
|
||||||
|
path.join(libtomcrypt.source, "src/**.c"),
|
||||||
|
}
|
||||||
|
|
||||||
|
removefiles {
|
||||||
|
path.join(libtomcrypt.source, "src/**/*tab.c"),
|
||||||
|
path.join(libtomcrypt.source, "src/encauth/ocb3/**.c"),
|
||||||
|
}
|
||||||
|
|
||||||
|
defines {
|
||||||
|
"_CRT_SECURE_NO_WARNINGS",
|
||||||
|
"LTC_SOURCE",
|
||||||
|
"_LIB",
|
||||||
|
"USE_LTM"
|
||||||
|
}
|
||||||
|
|
||||||
|
removedefines {
|
||||||
|
"_DLL",
|
||||||
|
"_USRDLL"
|
||||||
|
}
|
||||||
|
|
||||||
|
linkoptions {
|
||||||
|
"-IGNORE:4221"
|
||||||
|
}
|
||||||
|
|
||||||
|
warnings "Off"
|
||||||
|
kind "StaticLib"
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(dependencies, libtomcrypt)
|
52
deps/premake/libtommath.lua
vendored
Normal file
52
deps/premake/libtommath.lua
vendored
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
libtommath = {
|
||||||
|
source = path.join(dependencies.basePath, "libtommath"),
|
||||||
|
}
|
||||||
|
|
||||||
|
function libtommath.import()
|
||||||
|
links {
|
||||||
|
"libtommath"
|
||||||
|
}
|
||||||
|
|
||||||
|
libtommath.includes()
|
||||||
|
end
|
||||||
|
|
||||||
|
function libtommath.includes()
|
||||||
|
includedirs {
|
||||||
|
libtommath.source
|
||||||
|
}
|
||||||
|
|
||||||
|
defines {
|
||||||
|
"LTM_DESC",
|
||||||
|
"__STDC_IEC_559__",
|
||||||
|
"MP_NO_DEV_URANDOM",
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
function libtommath.project()
|
||||||
|
project "libtommath"
|
||||||
|
language "C"
|
||||||
|
|
||||||
|
libtommath.includes()
|
||||||
|
|
||||||
|
files {
|
||||||
|
path.join(libtommath.source, "*.c"),
|
||||||
|
}
|
||||||
|
|
||||||
|
defines {
|
||||||
|
"_LIB"
|
||||||
|
}
|
||||||
|
|
||||||
|
removedefines {
|
||||||
|
"_DLL",
|
||||||
|
"_USRDLL"
|
||||||
|
}
|
||||||
|
|
||||||
|
linkoptions {
|
||||||
|
"-IGNORE:4221"
|
||||||
|
}
|
||||||
|
|
||||||
|
warnings "Off"
|
||||||
|
kind "StaticLib"
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(dependencies, libtommath)
|
19
deps/premake/rapidjson.lua
vendored
Normal file
19
deps/premake/rapidjson.lua
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
rapidjson = {
|
||||||
|
source = path.join(dependencies.basePath, "rapidjson"),
|
||||||
|
}
|
||||||
|
|
||||||
|
function rapidjson.import()
|
||||||
|
rapidjson.includes()
|
||||||
|
end
|
||||||
|
|
||||||
|
function rapidjson.includes()
|
||||||
|
includedirs {
|
||||||
|
path.join(rapidjson.source, "include"),
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
function rapidjson.project()
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(dependencies, rapidjson)
|
1
deps/rapidjson
vendored
Submodule
1
deps/rapidjson
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 06d58b9e848c650114556a23294d0b6440078c61
|
599
src/client/component/demonware.cpp
Normal file
599
src/client/component/demonware.cpp
Normal file
@ -0,0 +1,599 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "loader/component_loader.hpp"
|
||||||
|
|
||||||
|
#include <utils/hook.hpp>
|
||||||
|
#include <utils/thread.hpp>
|
||||||
|
|
||||||
|
#include "game/game.hpp"
|
||||||
|
#include "game/demonware/servers/lobby_server.hpp"
|
||||||
|
#include "game/demonware/servers/auth3_server.hpp"
|
||||||
|
#include "game/demonware/servers/stun_server.hpp"
|
||||||
|
#include "game/demonware/servers/umbrella_server.hpp"
|
||||||
|
#include "game/demonware/server_registry.hpp"
|
||||||
|
|
||||||
|
#define TCP_BLOCKING true
|
||||||
|
#define UDP_BLOCKING false
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
volatile bool exit_server;
|
||||||
|
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;
|
||||||
|
|
||||||
|
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 DW_DEBUG
|
||||||
|
printf("[ network ]: [getaddrinfo]: \"%s\" \"%s\"\n", name, service);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
base_server* server = tcp_servers.find(name);
|
||||||
|
if (!server)
|
||||||
|
{
|
||||||
|
server = udp_servers.find(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 DW_DEBUG
|
||||||
|
printf("[ network ]: [gethostbyname]: \"%s\"\n", 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);
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL internet_get_connected_state_stub(LPDWORD, DWORD)
|
||||||
|
{
|
||||||
|
// Allow offline play
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bd_logger_stub()
|
||||||
|
{
|
||||||
|
//printf("logged\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DW_DEBUG
|
||||||
|
void a(unsigned int n)
|
||||||
|
{
|
||||||
|
printf("bdAuth: Auth task failed with HTTP code [%u]\n", n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void b(unsigned int n)
|
||||||
|
{
|
||||||
|
printf("bdAuth: Decoded client ticket of unexpected size [%u]\n", n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void c(unsigned int n)
|
||||||
|
{
|
||||||
|
printf("bdAuth: Decoded server ticket of unexpected size [%u]\n", n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void d()
|
||||||
|
{
|
||||||
|
printf("bdAuth: Auth ticket magic number mismatch\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void e()
|
||||||
|
{
|
||||||
|
printf("bdAuth: Cross Authentication completed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void f()
|
||||||
|
{
|
||||||
|
printf("bdAuth: Auth task reply contains invalid data / format\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void g(unsigned int n)
|
||||||
|
{
|
||||||
|
printf("bdAuth: Auth task returned with error code [%u]\n", n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void h(unsigned int n)
|
||||||
|
{
|
||||||
|
printf("bdAuth: Invalid or No Task ID [%u] in Auth reply\n", n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void i()
|
||||||
|
{
|
||||||
|
printf("bdAuth: Received reply from DemonWare Auth server\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void l()
|
||||||
|
{
|
||||||
|
printf("bdAuth: Unknown error\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
utils::hook::detour handle_auth_reply_hook;
|
||||||
|
bool handle_auth_reply_stub(void* a1, void* a2, void* a3)
|
||||||
|
{
|
||||||
|
// Skip bdAuth::validateResponseSignature
|
||||||
|
//utils::hook::set(0x7D4AB0_b, 0xC301B0);
|
||||||
|
// Skip bdAuth::processPlatformData
|
||||||
|
//utils::hook::set(0x7D55C0_b, 0xC301B0);
|
||||||
|
|
||||||
|
return handle_auth_reply_hook.invoke<bool>(a1, a2, a3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void request_start_match_stub()
|
||||||
|
{
|
||||||
|
//const auto* args = "StartServer";
|
||||||
|
//game::UI_RunMenuScript(0, &args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class component final : public component_interface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
component()
|
||||||
|
{
|
||||||
|
udp_servers.create<stun_server>("phoenix.stun.us.demonware.net");
|
||||||
|
udp_servers.create<stun_server>("phoenix.stun.eu.demonware.net");
|
||||||
|
udp_servers.create<stun_server>("phoenix.stun.jp.demonware.net");
|
||||||
|
udp_servers.create<stun_server>("phoenix.stun.au.demonware.net");
|
||||||
|
|
||||||
|
udp_servers.create<stun_server>("stun.us.demonware.net");
|
||||||
|
udp_servers.create<stun_server>("stun.eu.demonware.net");
|
||||||
|
udp_servers.create<stun_server>("stun.jp.demonware.net");
|
||||||
|
udp_servers.create<stun_server>("stun.au.demonware.net");
|
||||||
|
|
||||||
|
tcp_servers.create<auth3_server>("mwr-pc-steam-auth3.prod.demonware.net");
|
||||||
|
tcp_servers.create<lobby_server>("mwr-pc-steam-lobby.prod.demonware.net");
|
||||||
|
tcp_servers.create<umbrella_server>("prod.umbrella.demonware.net");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*void* load_import(const std::string& library, const std::string& function) override
|
||||||
|
{
|
||||||
|
if (library == "WS2_32.dll")
|
||||||
|
{
|
||||||
|
if (function == "#3") return io::closesocket_stub;
|
||||||
|
if (function == "#4") return io::connect_stub;
|
||||||
|
if (function == "#5") return io::getpeername_stub;
|
||||||
|
if (function == "#6") return io::getsockname_stub;
|
||||||
|
if (function == "#10") return io::ioctlsocket_stub;
|
||||||
|
if (function == "#16") return io::recv_stub;
|
||||||
|
if (function == "#17") return io::recvfrom_stub;
|
||||||
|
if (function == "#18") return io::select_stub;
|
||||||
|
if (function == "#19") return io::send_stub;
|
||||||
|
if (function == "#20") return io::sendto_stub;
|
||||||
|
if (function == "#52") return io::gethostbyname_stub;
|
||||||
|
if (function == "getaddrinfo") return io::getaddrinfo_stub;
|
||||||
|
if (function == "freeaddrinfo") return io::freeaddrinfo_stub;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (function == "InternetGetConnectedState")
|
||||||
|
{
|
||||||
|
return io::internet_get_connected_state_stub;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
void post_unpack() override
|
||||||
|
{
|
||||||
|
server_thread = utils::thread::create_named_thread("Demonware", server_main);
|
||||||
|
|
||||||
|
/*utils::hook::set<uint8_t>(0x7C0AD9_b, 0x0); // CURLOPT_SSL_VERIFYPEER
|
||||||
|
utils::hook::set<uint8_t>(0x7C0AC5_b, 0xAF); // CURLOPT_SSL_VERIFYHOST
|
||||||
|
utils::hook::set<uint8_t>(0xA1327C_b, 0x0); // HTTPS -> HTTP
|
||||||
|
|
||||||
|
std::memcpy(reinterpret_cast<void*>(0x8D0298_b),
|
||||||
|
"http://prod.umbrella.demonware.net/v1.0/", sizeof("http://prod.umbrella.demonware.net/v1.0/"));
|
||||||
|
std::memcpy(reinterpret_cast<void*>(0x8D05A8_b),
|
||||||
|
"http://prod.uno.demonware.net/v1.0/", sizeof("http://prod.uno.demonware.net/v1.0/"));
|
||||||
|
std::memcpy(reinterpret_cast<void*>(0x9EDB08_b), "http://%s:%d/auth/", sizeof("http://%s:%d/auth/"));
|
||||||
|
|
||||||
|
// utils::hook::set<uint8_t>(0x19F8C0_b, 0xC3); // SV_SendMatchData, not sure
|
||||||
|
utils::hook::nop(0x19BB67_b, 5); // LiveStorage_SendMatchDataComplete (crashes at the end of match)
|
||||||
|
utils::hook::nop(0x19BC3F_b, 5); // LiveStorage_GettingStoreConfigComplete probably (crashes randomly)
|
||||||
|
utils::hook::nop(0x19BC48_b, 5); // similar to above (crashes in killcam)
|
||||||
|
utils::hook::set<uint8_t>(0x1A3340_b, 0xC3); // Live_CheckForFullDisconnect
|
||||||
|
|
||||||
|
// Remove some while loop that freezes the rendering for a few secs while connecting
|
||||||
|
utils::hook::nop(0x625555_b, 5);
|
||||||
|
|
||||||
|
handle_auth_reply_hook.create(0x7AC600_b, handle_auth_reply_stub);
|
||||||
|
|
||||||
|
// Skip update check in Live_SyncOnlineDataFlags
|
||||||
|
utils::hook::set(0x47A6D0_b, 0xC301B0);
|
||||||
|
// Remove update failed popup
|
||||||
|
utils::hook::set(0x47B2B0_b, 0xC301B0);
|
||||||
|
|
||||||
|
// xpartygo -> just start the match
|
||||||
|
utils::hook::jump(0x355B80_b, request_start_match_stub);
|
||||||
|
|
||||||
|
utils::hook::set(0x396AD0_b, 0xC301B0); // DB_IsZoneLoaded("ffotd")
|
||||||
|
utils::hook::set(0x4DD600_b, 0xC300B0); // dont use ffotd
|
||||||
|
utils::hook::set(0x4DD5B0_b, 0xC300B0); // dont dl ffotd
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void pre_destroy() override
|
||||||
|
{
|
||||||
|
exit_server = true;
|
||||||
|
if (server_thread.joinable())
|
||||||
|
{
|
||||||
|
server_thread.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
REGISTER_COMPONENT(demonware::component)
|
182
src/client/game/demonware/bit_buffer.cpp
Normal file
182
src/client/game/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
src/client/game/demonware/bit_buffer.hpp
Normal file
40
src/client/game/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;
|
||||||
|
};
|
||||||
|
}
|
320
src/client/game/demonware/byte_buffer.cpp
Normal file
320
src/client/game/demonware/byte_buffer.cpp
Normal file
@ -0,0 +1,320 @@
|
|||||||
|
#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_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_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_;
|
||||||
|
}
|
||||||
|
}
|
71
src/client/game/demonware/byte_buffer.hpp
Normal file
71
src/client/game/demonware/byte_buffer.hpp
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#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_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_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;
|
||||||
|
};
|
||||||
|
}
|
210
src/client/game/demonware/data_types.hpp
Normal file
210
src/client/game/demonware/data_types.hpp
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
#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 bdFileData final : public bdTaskResult
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::string file_data;
|
||||||
|
|
||||||
|
explicit bdFileData(std::string buffer) : file_data(std::move(buffer))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void serialize(byte_buffer* buffer) override
|
||||||
|
{
|
||||||
|
buffer->write_blob(this->file_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deserialize(byte_buffer* buffer) override
|
||||||
|
{
|
||||||
|
buffer->read_blob(&this->file_data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class bdFileInfo final : public bdTaskResult
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
uint64_t file_id;
|
||||||
|
uint32_t create_time;
|
||||||
|
uint32_t modified_time;
|
||||||
|
bool priv;
|
||||||
|
uint64_t owner_id;
|
||||||
|
std::string filename;
|
||||||
|
uint32_t file_size;
|
||||||
|
|
||||||
|
void serialize(byte_buffer* buffer) override
|
||||||
|
{
|
||||||
|
buffer->write_uint32(this->file_size);
|
||||||
|
buffer->write_uint64(this->file_id);
|
||||||
|
buffer->write_uint32(this->create_time);
|
||||||
|
buffer->write_uint32(this->modified_time);
|
||||||
|
buffer->write_bool(this->priv);
|
||||||
|
buffer->write_uint64(this->owner_id);
|
||||||
|
buffer->write_string(this->filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deserialize(byte_buffer* buffer) override
|
||||||
|
{
|
||||||
|
buffer->read_uint32(&this->file_size);
|
||||||
|
buffer->read_uint64(&this->file_id);
|
||||||
|
buffer->read_uint32(&this->create_time);
|
||||||
|
buffer->read_uint32(&this->modified_time);
|
||||||
|
buffer->read_bool(&this->priv);
|
||||||
|
buffer->read_uint64(&this->owner_id);
|
||||||
|
buffer->read_string(&this->filename);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class bdDMLRawData final : public bdDMLInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
uint32_t asn; // Autonomous System Number.
|
||||||
|
std::string timezone;
|
||||||
|
|
||||||
|
void serialize(byte_buffer* buffer) override
|
||||||
|
{
|
||||||
|
bdDMLInfo::serialize(buffer);
|
||||||
|
|
||||||
|
buffer->write_uint32(this->asn);
|
||||||
|
buffer->write_string(this->timezone);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deserialize(byte_buffer* buffer) override
|
||||||
|
{
|
||||||
|
bdDMLInfo::deserialize(buffer);
|
||||||
|
|
||||||
|
buffer->read_uint32(&this->asn);
|
||||||
|
buffer->read_string(&this->timezone);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// made up name
|
||||||
|
class bdFile final : public bdTaskResult
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
uint64_t owner_id;
|
||||||
|
std::string platform;
|
||||||
|
std::string filename;
|
||||||
|
uint32_t unk;
|
||||||
|
std::string data;
|
||||||
|
|
||||||
|
void serialize(byte_buffer* buffer) override
|
||||||
|
{
|
||||||
|
buffer->write_uint64(this->owner_id);
|
||||||
|
buffer->write_string(this->platform);
|
||||||
|
buffer->write_string(this->filename);
|
||||||
|
buffer->write_uint32(this->unk);
|
||||||
|
buffer->write_blob(this->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deserialize(byte_buffer* buffer) override
|
||||||
|
{
|
||||||
|
buffer->read_uint64(&this->owner_id);
|
||||||
|
buffer->read_string(&this->platform);
|
||||||
|
buffer->read_string(&this->filename);
|
||||||
|
buffer->read_uint32(&this->unk);
|
||||||
|
buffer->read_blob(&this->data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class bdFile2 final : public bdTaskResult
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
uint32_t unk1;
|
||||||
|
uint32_t unk2;
|
||||||
|
uint32_t unk3;
|
||||||
|
bool priv;
|
||||||
|
uint64_t owner_id;
|
||||||
|
std::string platform;
|
||||||
|
std::string filename;
|
||||||
|
std::string data;
|
||||||
|
|
||||||
|
void serialize(byte_buffer* buffer) override
|
||||||
|
{
|
||||||
|
buffer->write_uint32(this->unk1);
|
||||||
|
buffer->write_uint32(this->unk2);
|
||||||
|
buffer->write_uint32(this->unk3);
|
||||||
|
buffer->write_bool(this->priv);
|
||||||
|
buffer->write_uint64(this->owner_id);
|
||||||
|
buffer->write_string(this->platform);
|
||||||
|
buffer->write_string(this->filename);
|
||||||
|
buffer->write_blob(this->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deserialize(byte_buffer* buffer) override
|
||||||
|
{
|
||||||
|
buffer->read_uint32(&this->unk1);
|
||||||
|
buffer->read_uint32(&this->unk2);
|
||||||
|
buffer->read_uint32(&this->unk3);
|
||||||
|
buffer->read_bool(&this->priv);
|
||||||
|
buffer->read_uint64(&this->owner_id);
|
||||||
|
buffer->read_string(&this->platform);
|
||||||
|
buffer->read_string(&this->filename);
|
||||||
|
buffer->read_blob(&this->data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
130
src/client/game/demonware/keys.cpp
Normal file
130
src/client/game/demonware/keys.cpp
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "keys.hpp"
|
||||||
|
|
||||||
|
#include <utils/cryptography.hpp>
|
||||||
|
#include <utils/string.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_s1(const char* data_, const unsigned int data_size, const char* key,
|
||||||
|
const unsigned int key_size,
|
||||||
|
char* dst, const unsigned int dst_size)
|
||||||
|
{
|
||||||
|
char buffer[64];
|
||||||
|
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(data_, data_size));
|
||||||
|
|
||||||
|
// save output
|
||||||
|
std::memcpy(dst, result.data(), std::min(20u, (dst_size - out_offset)));
|
||||||
|
out_offset = 20;
|
||||||
|
|
||||||
|
// second loop
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
// if we filled the output buffer, exit
|
||||||
|
if (out_offset >= dst_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(data_, data_size));
|
||||||
|
|
||||||
|
// save output
|
||||||
|
std::memcpy(dst + out_offset, result.data(), std::min(20u, (dst_size - out_offset)));
|
||||||
|
out_offset += 20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void derive_keys_s1()
|
||||||
|
{
|
||||||
|
const auto out_1 = utils::cryptography::sha1::compute(packet_buffer); // out_1 size 20
|
||||||
|
|
||||||
|
auto data_3 = utils::cryptography::hmac_sha1::compute(data.m_session_key, out_1);
|
||||||
|
|
||||||
|
char out_2[16];
|
||||||
|
calculate_hmacs_s1(data_3.data(), 20, "CLIENTCHAL", 10, out_2, 16);
|
||||||
|
|
||||||
|
char out_3[72];
|
||||||
|
calculate_hmacs_s1(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);
|
||||||
|
|
||||||
|
#ifdef DW_DEBUG
|
||||||
|
printf("[DW] Response id: %s\n", utils::string::dump_hex(std::string(&out_2[8], 8)).data());
|
||||||
|
printf("[DW] Hash verify: %s\n", utils::string::dump_hex(std::string(&out_3[20], 20)).data());
|
||||||
|
printf("[DW] AES dec key: %s\n", utils::string::dump_hex(std::string(&out_3[40], 16)).data());
|
||||||
|
printf("[DW] AES enc key: %s\n", utils::string::dump_hex(std::string(&out_3[56], 16)).data());
|
||||||
|
printf("[DW] Bravo 6, going dark.\n");
|
||||||
|
#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
src/client/game/demonware/keys.hpp
Normal file
12
src/client/game/demonware/keys.hpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
void derive_keys_s1();
|
||||||
|
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();
|
||||||
|
}
|
87
src/client/game/demonware/reply.cpp
Normal file
87
src/client/game/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());
|
||||||
|
}
|
||||||
|
}
|
164
src/client/game/demonware/reply.hpp
Normal file
164
src/client/game/demonware/reply.hpp
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
#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)
|
||||||
|
: type_(_type), error_(_error), 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_)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
{
|
||||||
|
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_;
|
||||||
|
remote_reply reply_;
|
||||||
|
std::vector<std::shared_ptr<bdTaskResult>> objects_;
|
||||||
|
};
|
||||||
|
}
|
60
src/client/game/demonware/server_registry.hpp
Normal file
60
src/client/game/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_;
|
||||||
|
};
|
||||||
|
}
|
168
src/client/game/demonware/servers/auth3_server.cpp
Normal file
168
src/client/game/demonware/servers/auth3_server.cpp
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
#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/"))
|
||||||
|
{
|
||||||
|
#ifdef DW_DEBUG
|
||||||
|
printf("[DW]: [auth]: user requested authentication.\n");
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int title_id = 0;
|
||||||
|
unsigned int iv_seed = 0;
|
||||||
|
std::string identity{};
|
||||||
|
std::string 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("token") && extra_data["token"].IsString())
|
||||||
|
{
|
||||||
|
auto& token_field = extra_data["token"];
|
||||||
|
std::string token_b64(token_field.GetString(), token_field.GetStringLength());
|
||||||
|
token = utils::cryptography::base64::decode(token_b64);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DW_DEBUG
|
||||||
|
printf("[DW]: [auth]: authenticating user %s\n", token.data() + 64);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::string auth_key(reinterpret_cast<char*>(token.data() + 32), 24);
|
||||||
|
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 = 0x0EFBDADDE;
|
||||||
|
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 = reinterpret_cast<uint64_t>(token.data() + 56);
|
||||||
|
strncpy_s(ticket.m_username, sizeof(ticket.m_username), reinterpret_cast<char*>(token.data() + 64), 64);
|
||||||
|
std::memcpy(ticket.m_sessionKey, session_key.data(), 24);
|
||||||
|
|
||||||
|
const auto iv = utils::cryptography::tiger::compute(std::string(reinterpret_cast<char*>(&iv_seed), 4));
|
||||||
|
const auto ticket_enc = utils::cryptography::des3::encrypt(
|
||||||
|
std::string(reinterpret_cast<char*>(&ticket), sizeof(ticket)), iv, auth_key);
|
||||||
|
const auto ticket_b64 = utils::cryptography::base64::encode(
|
||||||
|
reinterpret_cast<const unsigned char*>(ticket_enc.data()), 128);
|
||||||
|
|
||||||
|
// server_ticket
|
||||||
|
uint8_t auth_data[128];
|
||||||
|
std::memset(&auth_data, 0, sizeof auth_data);
|
||||||
|
std::memcpy(auth_data, session_key.data(), 24);
|
||||||
|
const auto auth_data_b64 = utils::cryptography::base64::encode(auth_data, 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);
|
||||||
|
|
||||||
|
// json content
|
||||||
|
rapidjson::Document doc;
|
||||||
|
doc.SetObject();
|
||||||
|
|
||||||
|
doc.AddMember("auth_task", "29", doc.GetAllocator());
|
||||||
|
doc.AddMember("code", "700", doc.GetAllocator());
|
||||||
|
|
||||||
|
auto seed = std::to_string(iv_seed);
|
||||||
|
doc.AddMember("iv_seed", rapidjson::StringRef(seed.data(), seed.size()), doc.GetAllocator());
|
||||||
|
doc.AddMember("client_ticket", rapidjson::StringRef(ticket_b64.data(), ticket_b64.size()), doc.GetAllocator());
|
||||||
|
doc.AddMember("server_ticket", rapidjson::StringRef(auth_data_b64.data(), auth_data_b64.size()),
|
||||||
|
doc.GetAllocator());
|
||||||
|
doc.AddMember("client_id", "", doc.GetAllocator());
|
||||||
|
doc.AddMember("account_type", "steam", doc.GetAllocator());
|
||||||
|
doc.AddMember("crossplay_enabled", false, doc.GetAllocator());
|
||||||
|
doc.AddMember("loginqueue_eanbled", false, 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);
|
||||||
|
|
||||||
|
#ifdef DW_DEBUG
|
||||||
|
printf("[DW]: [auth]: user successfully authenticated.\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
16
src/client/game/demonware/servers/auth3_server.hpp
Normal file
16
src/client/game/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
src/client/game/demonware/servers/base_server.cpp
Normal file
22
src/client/game/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
src/client/game/demonware/servers/base_server.hpp
Normal file
30
src/client/game/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;
|
||||||
|
};
|
||||||
|
}
|
185
src/client/game/demonware/servers/lobby_server.cpp
Normal file
185
src/client/game/demonware/servers/lobby_server.cpp
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
#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<bdAnticheat>();
|
||||||
|
this->register_service<bdBandwidthTest>();
|
||||||
|
this->register_service<bdContentStreaming>();
|
||||||
|
this->register_service<bdCounter>();
|
||||||
|
this->register_service<bdDML>();
|
||||||
|
this->register_service<bdEventLog>();
|
||||||
|
this->register_service<bdGroup>();
|
||||||
|
this->register_service<bdTeams>();
|
||||||
|
this->register_service<bdStats>();
|
||||||
|
this->register_service<bdStats2>();
|
||||||
|
this->register_service<bdStats3>();
|
||||||
|
this->register_service<bdStorage>();
|
||||||
|
this->register_service<bdTitleUtilities>();
|
||||||
|
this->register_service<bdProfiles>();
|
||||||
|
this->register_service<bdRichPresence>();
|
||||||
|
this->register_service<bdFacebook>();
|
||||||
|
this->register_service<bdUNK63>();
|
||||||
|
this->register_service<bdUserGroups>();
|
||||||
|
this->register_service<bdMarketplace>();
|
||||||
|
this->register_service<bdLeague>();
|
||||||
|
this->register_service<bdLeague2>();
|
||||||
|
this->register_service<bdPublisherVariables>();
|
||||||
|
this->register_service<bdPresence>();
|
||||||
|
this->register_service<bdMarketingComms>();
|
||||||
|
this->register_service<bdMatchMaking>();
|
||||||
|
this->register_service<bdReward>();
|
||||||
|
};
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
#ifdef DW_DEBUG
|
||||||
|
printf("[DW]: [lobby]: received client_header_ack.\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int c8;
|
||||||
|
buffer.read_int32(&c8);
|
||||||
|
std::string packet_1 = buffer.get_remaining();
|
||||||
|
demonware::queue_packet_to_hash(packet_1);
|
||||||
|
|
||||||
|
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);
|
||||||
|
#ifdef DW_DEBUG
|
||||||
|
printf("[DW]: [lobby]: sending server_header_ack.\n");
|
||||||
|
#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)
|
||||||
|
{
|
||||||
|
#ifdef DW_DEBUG
|
||||||
|
printf("[DW]: [lobby]: received client_auth.\n");
|
||||||
|
#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_s1();
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
#ifdef DW_DEBUG
|
||||||
|
printf("[DW]: [lobby]: sending server_auth_done.\n");
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("[DW]: [lobby]: ERROR! received unk message.\n");
|
||||||
|
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
|
||||||
|
{
|
||||||
|
printf("[DW]: [lobby]: missing service '%s'\n", 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
src/client/game/demonware/servers/lobby_server.hpp
Normal file
33
src/client/game/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);
|
||||||
|
};
|
||||||
|
}
|
27
src/client/game/demonware/servers/service_server.hpp
Normal file
27
src/client/game/demonware/servers/service_server.hpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#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);
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void send_reply(reply* data) = 0;
|
||||||
|
};
|
||||||
|
}
|
62
src/client/game/demonware/servers/stun_server.cpp
Normal file
62
src/client/game/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
src/client/game/demonware/servers/stun_server.hpp
Normal file
18
src/client/game/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
src/client/game/demonware/servers/tcp_server.cpp
Normal file
84
src/client/game/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
src/client/game/demonware/servers/tcp_server.hpp
Normal file
27
src/client/game/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
src/client/game/demonware/servers/udp_server.cpp
Normal file
103
src/client/game/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
src/client/game/demonware/servers/udp_server.hpp
Normal file
62
src/client/game/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
src/client/game/demonware/servers/umbrella_server.cpp
Normal file
11
src/client/game/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
src/client/game/demonware/servers/umbrella_server.hpp
Normal file
14
src/client/game/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
src/client/game/demonware/service.hpp
Normal file
89
src/client/game/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())
|
||||||
|
{
|
||||||
|
#ifdef DW_DEBUG
|
||||||
|
printf("[DW] %s: executing task '%d'\n", name_.data(), this->task_id_);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
it->second(server, &buffer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("[DW] %s: missing task '%d'\n", 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...);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
41
src/client/game/demonware/services.hpp
Normal file
41
src/client/game/demonware/services.hpp
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#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/bdTeams.hpp" // 3
|
||||||
|
#include "services/bdStats.hpp" // 4
|
||||||
|
//#include "services/bdMessaging.hpp" // 6
|
||||||
|
#include "services/bdProfiles.hpp" // 8
|
||||||
|
#include "services/bdStorage.hpp" // 10
|
||||||
|
#include "services/bdTitleUtilities.hpp" // 12
|
||||||
|
#include "services/bdBandwidthTest.hpp" // 18
|
||||||
|
#include "services/bdStats2.hpp" // 19
|
||||||
|
#include "services/bdCounter.hpp" // 23
|
||||||
|
#include "services/bdDML.hpp" // 27
|
||||||
|
#include "services/bdGroup.hpp" // 28
|
||||||
|
//#include "services/bdCMail.hpp" // 29
|
||||||
|
#include "services/bdFacebook.hpp" // 36
|
||||||
|
#include "services/bdAnticheat.hpp" // 38
|
||||||
|
#include "services/bdContentStreaming.hpp" // 50
|
||||||
|
//#include "services/bdTags.hpp" // 52
|
||||||
|
#include "services/bdUNK63.hpp" // 63
|
||||||
|
#include "services/bdUserGroups.hpp" // 65
|
||||||
|
#include "services/bdEventLog.hpp" // 67
|
||||||
|
#include "services/bdRichPresence.hpp" // 68
|
||||||
|
//#include "services/bdTencent.hpp" // 71
|
||||||
|
//#include "services/bdCodOnlineTeams.hpp" // 72
|
||||||
|
#include "services/bdMarketplace.hpp" // 80
|
||||||
|
#include "services/bdLeague.hpp" // 81
|
||||||
|
#include "services/bdLeague2.hpp" // 82
|
||||||
|
#include "services/bdStats3.hpp" // 91
|
||||||
|
#include "services/bdPublisherVariables.hpp"// 95
|
||||||
|
// AccountLinking // 86
|
||||||
|
#include "services/bdPresence.hpp" //103
|
||||||
|
#include "services/bdMarketingComms.hpp" //104
|
||||||
|
#include "services/bdMatchMaking.hpp" //138
|
||||||
|
#include "services/bdReward.hpp" //139
|
41
src/client/game/demonware/services/bdAnticheat.cpp
Normal file
41
src/client/game/demonware/services/bdAnticheat.cpp
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
16
src/client/game/demonware/services/bdAnticheat.hpp
Normal file
16
src/client/game/demonware/services/bdAnticheat.hpp
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#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;
|
||||||
|
};
|
||||||
|
}
|
27
src/client/game/demonware/services/bdBandwidthTest.cpp
Normal file
27
src/client/game/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
src/client/game/demonware/services/bdBandwidthTest.hpp
Normal file
13
src/client/game/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
src/client/game/demonware/services/bdContentStreaming.cpp
Normal file
25
src/client/game/demonware/services/bdContentStreaming.cpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "../services.hpp"
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
bdContentStreaming::bdContentStreaming() : service(50, "bdContentStreaming")
|
||||||
|
{
|
||||||
|
this->register_task(2, &bdContentStreaming::unk2);
|
||||||
|
this->register_task(3, &bdContentStreaming::unk3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdContentStreaming::unk2(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdContentStreaming::unk3(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
}
|
14
src/client/game/demonware/services/bdContentStreaming.hpp
Normal file
14
src/client/game/demonware/services/bdContentStreaming.hpp
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
class bdContentStreaming final : public service
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bdContentStreaming();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void unk2(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void unk3(service_server* server, byte_buffer* buffer) const;
|
||||||
|
};
|
||||||
|
}
|
25
src/client/game/demonware/services/bdCounter.cpp
Normal file
25
src/client/game/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
src/client/game/demonware/services/bdCounter.hpp
Normal file
14
src/client/game/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;
|
||||||
|
};
|
||||||
|
}
|
52
src/client/game/demonware/services/bdDML.cpp
Normal file
52
src/client/game/demonware/services/bdDML.cpp
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "../services.hpp"
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
bdDML::bdDML() : service(27, "bdDML")
|
||||||
|
{
|
||||||
|
this->register_task(1, &bdDML::recordIP);
|
||||||
|
this->register_task(2, &bdDML::getUserData);
|
||||||
|
this->register_task(3, &bdDML::getUserHierarchicalData);
|
||||||
|
this->register_task(4, &bdDML::getUsersLastLogonData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdDML::recordIP(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdDML::getUserData(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
auto result = new bdDMLRawData;
|
||||||
|
result->country_code = "US";
|
||||||
|
result->country_code = "'Murica";
|
||||||
|
result->region = "New York";
|
||||||
|
result->city = "New York";
|
||||||
|
result->latitude = 0;
|
||||||
|
result->longitude = 0;
|
||||||
|
|
||||||
|
result->asn = 0x2119;
|
||||||
|
result->timezone = "+01:00";
|
||||||
|
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->add(result);
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdDML::getUserHierarchicalData(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdDML::getUsersLastLogonData(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
}
|
16
src/client/game/demonware/services/bdDML.hpp
Normal file
16
src/client/game/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;
|
||||||
|
};
|
||||||
|
}
|
49
src/client/game/demonware/services/bdEventLog.cpp
Normal file
49
src/client/game/demonware/services/bdEventLog.cpp
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#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(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::initializeFiltering(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
}
|
17
src/client/game/demonware/services/bdEventLog.hpp
Normal file
17
src/client/game/demonware/services/bdEventLog.hpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#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 initializeFiltering(service_server* server, byte_buffer* buffer) const;
|
||||||
|
};
|
||||||
|
}
|
113
src/client/game/demonware/services/bdFacebook.cpp
Normal file
113
src/client/game/demonware/services/bdFacebook.cpp
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "../services.hpp"
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
bdFacebook::bdFacebook() : service(36, "bdFacebook")
|
||||||
|
{
|
||||||
|
this->register_task(1, &bdFacebook::registerAccount);
|
||||||
|
this->register_task(2, &bdFacebook::post);
|
||||||
|
this->register_task(3, &bdFacebook::unregisterAccount);
|
||||||
|
this->register_task(5, &bdFacebook::isRegistered);
|
||||||
|
this->register_task(6, &bdFacebook::getInfo);
|
||||||
|
this->register_task(7, &bdFacebook::getRegisteredAccounts);
|
||||||
|
this->register_task(8, &bdFacebook::getFriends);
|
||||||
|
this->register_task(9, &bdFacebook::getProfilePictures);
|
||||||
|
this->register_task(10, &bdFacebook::uploadPhoto);
|
||||||
|
this->register_task(11, &bdFacebook::registerToken);
|
||||||
|
this->register_task(12, &bdFacebook::uploadVideo);
|
||||||
|
this->register_task(13, &bdFacebook::getFriendsByID);
|
||||||
|
this->register_task(14, &bdFacebook::setLikeStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdFacebook::registerAccount(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdFacebook::post(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdFacebook::unregisterAccount(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdFacebook::isRegistered(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdFacebook::getInfo(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdFacebook::getRegisteredAccounts(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdFacebook::getFriends(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdFacebook::getProfilePictures(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdFacebook::uploadPhoto(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdFacebook::registerToken(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdFacebook::uploadVideo(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdFacebook::getFriendsByID(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdFacebook::setLikeStatus(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
}
|
25
src/client/game/demonware/services/bdFacebook.hpp
Normal file
25
src/client/game/demonware/services/bdFacebook.hpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
class bdFacebook final : public service
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bdFacebook();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void registerAccount(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void post(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void unregisterAccount(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void isRegistered(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getInfo(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getRegisteredAccounts(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getFriends(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getProfilePictures(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void uploadPhoto(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void registerToken(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void uploadVideo(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getFriendsByID(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void setLikeStatus(service_server* server, byte_buffer* buffer) const;
|
||||||
|
};
|
||||||
|
}
|
41
src/client/game/demonware/services/bdGroup.cpp
Normal file
41
src/client/game/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
src/client/game/demonware/services/bdGroup.hpp
Normal file
16
src/client/game/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;
|
||||||
|
};
|
||||||
|
}
|
97
src/client/game/demonware/services/bdLeague.cpp
Normal file
97
src/client/game/demonware/services/bdLeague.cpp
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "../services.hpp"
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
bdLeague::bdLeague() : service(81, "bdLeague")
|
||||||
|
{
|
||||||
|
this->register_task(1, &bdLeague::getTeamID);
|
||||||
|
this->register_task(2, &bdLeague::getTeamIDsForUser);
|
||||||
|
this->register_task(3, &bdLeague::getTeamSubdivisions);
|
||||||
|
this->register_task(4, &bdLeague::setTeamName);
|
||||||
|
this->register_task(5, &bdLeague::setTeamIcon);
|
||||||
|
this->register_task(6, &bdLeague::getTeamInfos);
|
||||||
|
this->register_task(7, &bdLeague::getTeamLeaguesAndSubdivisions);
|
||||||
|
this->register_task(8, &bdLeague::getTeamMemberInfos);
|
||||||
|
this->register_task(10, &bdLeague::incrementGamesPlayedCount);
|
||||||
|
this->register_task(20, &bdLeague::getSubdivisionInfos);
|
||||||
|
this->register_task(21, &bdLeague::getTeamSubdivisionHistory);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdLeague::getTeamID(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdLeague::getTeamIDsForUser(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdLeague::getTeamSubdivisions(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdLeague::setTeamName(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdLeague::setTeamIcon(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdLeague::getTeamInfos(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdLeague::getTeamLeaguesAndSubdivisions(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdLeague::getTeamMemberInfos(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdLeague::incrementGamesPlayedCount(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdLeague::getSubdivisionInfos(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdLeague::getTeamSubdivisionHistory(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
}
|
23
src/client/game/demonware/services/bdLeague.hpp
Normal file
23
src/client/game/demonware/services/bdLeague.hpp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
class bdLeague final : public service
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bdLeague();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void getTeamID(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getTeamIDsForUser(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getTeamSubdivisions(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void setTeamName(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void setTeamIcon(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getTeamInfos(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getTeamLeaguesAndSubdivisions(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getTeamMemberInfos(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void incrementGamesPlayedCount(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getSubdivisionInfos(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getTeamSubdivisionHistory(service_server* server, byte_buffer* buffer) const;
|
||||||
|
};
|
||||||
|
}
|
41
src/client/game/demonware/services/bdLeague2.cpp
Normal file
41
src/client/game/demonware/services/bdLeague2.cpp
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "../services.hpp"
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
bdLeague2::bdLeague2() : service(82, "bdLeague")
|
||||||
|
{
|
||||||
|
this->register_task(1, &bdLeague2::writeStats);
|
||||||
|
this->register_task(2, &bdLeague2::readStatsByTeamID);
|
||||||
|
this->register_task(3, &bdLeague2::readStatsByRank);
|
||||||
|
this->register_task(4, &bdLeague2::readStatsByPivot);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdLeague2::writeStats(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdLeague2::readStatsByTeamID(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdLeague2::readStatsByRank(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdLeague2::readStatsByPivot(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
}
|
16
src/client/game/demonware/services/bdLeague2.hpp
Normal file
16
src/client/game/demonware/services/bdLeague2.hpp
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
class bdLeague2 final : public service
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bdLeague2();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void writeStats(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void readStatsByTeamID(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;
|
||||||
|
};
|
||||||
|
}
|
25
src/client/game/demonware/services/bdMarketingComms.cpp
Normal file
25
src/client/game/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(1, &bdMarketingComms::getMessages);
|
||||||
|
this->register_task(4, &bdMarketingComms::reportFullMessagesViewed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdMarketingComms::getMessages(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdMarketingComms::reportFullMessagesViewed(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
}
|
14
src/client/game/demonware/services/bdMarketingComms.hpp
Normal file
14
src/client/game/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 reportFullMessagesViewed(service_server* server, byte_buffer* buffer) const;
|
||||||
|
};
|
||||||
|
}
|
84
src/client/game/demonware/services/bdMarketplace.cpp
Normal file
84
src/client/game/demonware/services/bdMarketplace.cpp
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "../services.hpp"
|
||||||
|
|
||||||
|
#include <utils/io.hpp>
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
bdMarketplace::bdMarketplace() : service(80, "bdMarketplace")
|
||||||
|
{
|
||||||
|
this->register_task(42, &bdMarketplace::startExchangeTransaction); // COD POINTS purchase ?
|
||||||
|
//this->register_task(43, &bdMarketplace::purchaseOnSteamInitialize); // COD POINTS purchase ?
|
||||||
|
this->register_task(49, &bdMarketplace::getExpiredInventoryItems);
|
||||||
|
this->register_task(60, &bdMarketplace::steamProcessDurable);
|
||||||
|
this->register_task(122, &bdMarketplace::purchaseSkus);
|
||||||
|
this->register_task(130, &bdMarketplace::getBalance);
|
||||||
|
this->register_task(165, &bdMarketplace::getInventoryPaginated);
|
||||||
|
this->register_task(193, &bdMarketplace::putPlayersInventoryItems);
|
||||||
|
this->register_task(232, &bdMarketplace::getEntitlements);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdMarketplace::startExchangeTransaction(service_server* server, byte_buffer* buffer) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdMarketplace::purchaseOnSteamInitialize(service_server* server, byte_buffer* buffer) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdMarketplace::getExpiredInventoryItems(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdMarketplace::steamProcessDurable(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdMarketplace::purchaseSkus(service_server* server, byte_buffer* buffer) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdMarketplace::getBalance(service_server* server, byte_buffer* buffer) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdMarketplace::getInventoryPaginated(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdMarketplace::putPlayersInventoryItems(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdMarketplace::getEntitlements(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
}
|
21
src/client/game/demonware/services/bdMarketplace.hpp
Normal file
21
src/client/game/demonware/services/bdMarketplace.hpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
class bdMarketplace final : public service
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bdMarketplace();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void startExchangeTransaction(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void purchaseOnSteamInitialize(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getExpiredInventoryItems(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void steamProcessDurable(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void purchaseSkus(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getBalance(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getInventoryPaginated(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void putPlayersInventoryItems(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getEntitlements(service_server* server, byte_buffer* buffer) const;
|
||||||
|
};
|
||||||
|
}
|
129
src/client/game/demonware/services/bdMatchMaking.cpp
Normal file
129
src/client/game/demonware/services/bdMatchMaking.cpp
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "../services.hpp"
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
bdMatchMaking::bdMatchMaking() : service(138, "bdMatchMaking")
|
||||||
|
{
|
||||||
|
this->register_task(1, &bdMatchMaking::createSession);
|
||||||
|
this->register_task(2, &bdMatchMaking::updateSession);
|
||||||
|
this->register_task(3, &bdMatchMaking::deleteSession);
|
||||||
|
this->register_task(4, &bdMatchMaking::findSessionFromID);
|
||||||
|
this->register_task(5, &bdMatchMaking::findSessions);
|
||||||
|
this->register_task(6, &bdMatchMaking::notifyJoin);
|
||||||
|
this->register_task(8, &bdMatchMaking::inviteToSession);
|
||||||
|
this->register_task(9, &bdMatchMaking::submitPerformance);
|
||||||
|
this->register_task(10, &bdMatchMaking::getPerformanceValues);
|
||||||
|
this->register_task(11, &bdMatchMaking::getSessionInvites);
|
||||||
|
this->register_task(12, &bdMatchMaking::updateSessionPlayers);
|
||||||
|
this->register_task(13, &bdMatchMaking::findSessionsPaged);
|
||||||
|
this->register_task(14, &bdMatchMaking::findSessionsByEntityIDs);
|
||||||
|
this->register_task(15, &bdMatchMaking::findSessionsFromIDs);
|
||||||
|
this->register_task(16, &bdMatchMaking::findSessionsTwoPass);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdMatchMaking::createSession(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdMatchMaking::updateSession(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdMatchMaking::deleteSession(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdMatchMaking::findSessionFromID(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdMatchMaking::findSessions(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdMatchMaking::getPerformanceValues(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdMatchMaking::getSessionInvites(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdMatchMaking::updateSessionPlayers(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdMatchMaking::submitPerformance(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdMatchMaking::notifyJoin(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdMatchMaking::inviteToSession(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdMatchMaking::findSessionsPaged(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdMatchMaking::findSessionsByEntityIDs(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdMatchMaking::findSessionsFromIDs(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdMatchMaking::findSessionsTwoPass(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
}
|
27
src/client/game/demonware/services/bdMatchMaking.hpp
Normal file
27
src/client/game/demonware/services/bdMatchMaking.hpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
class bdMatchMaking final : public service
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bdMatchMaking();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void createSession(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void updateSession(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void deleteSession(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void findSessionFromID(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void findSessions(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void inviteToSession(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void submitPerformance(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void notifyJoin(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getPerformanceValues(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getSessionInvites(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void updateSessionPlayers(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void findSessionsPaged(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void findSessionsByEntityIDs(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void findSessionsFromIDs(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void findSessionsTwoPass(service_server* server, byte_buffer* buffer) const;
|
||||||
|
};
|
||||||
|
}
|
25
src/client/game/demonware/services/bdPresence.cpp
Normal file
25
src/client/game/demonware/services/bdPresence.cpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "../services.hpp"
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
bdPresence::bdPresence() : service(103, "bdPresence")
|
||||||
|
{
|
||||||
|
this->register_task(1, &bdPresence::unk1);
|
||||||
|
this->register_task(3, &bdPresence::unk3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdPresence::unk1(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdPresence::unk3(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
}
|
14
src/client/game/demonware/services/bdPresence.hpp
Normal file
14
src/client/game/demonware/services/bdPresence.hpp
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
class bdPresence final : public service
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bdPresence();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void unk1(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void unk3(service_server* server, byte_buffer* buffer) const;
|
||||||
|
};
|
||||||
|
}
|
73
src/client/game/demonware/services/bdProfiles.cpp
Normal file
73
src/client/game/demonware/services/bdProfiles.cpp
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "../services.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
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdProfiles::setPublicInfo(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
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
src/client/game/demonware/services/bdProfiles.hpp
Normal file
20
src/client/game/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
src/client/game/demonware/services/bdPublisherVariables.cpp
Normal file
17
src/client/game/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
src/client/game/demonware/services/bdPublisherVariables.hpp
Normal file
13
src/client/game/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;
|
||||||
|
};
|
||||||
|
}
|
41
src/client/game/demonware/services/bdReward.cpp
Normal file
41
src/client/game/demonware/services/bdReward.cpp
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "../services.hpp"
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
bdReward::bdReward() : service(139, "bdReward")
|
||||||
|
{
|
||||||
|
this->register_task(1, &bdReward::incrementTime);
|
||||||
|
this->register_task(2, &bdReward::claimRewardRoll);
|
||||||
|
this->register_task(3, &bdReward::claimClientAchievements);
|
||||||
|
this->register_task(4, &bdReward::reportRewardEvents);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdReward::incrementTime(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdReward::claimRewardRoll(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdReward::claimClientAchievements(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdReward::reportRewardEvents(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
}
|
16
src/client/game/demonware/services/bdReward.hpp
Normal file
16
src/client/game/demonware/services/bdReward.hpp
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
class bdReward final : public service
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bdReward();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void incrementTime(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void claimRewardRoll(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void claimClientAchievements(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void reportRewardEvents(service_server* server, byte_buffer* buffer) const;
|
||||||
|
};
|
||||||
|
}
|
25
src/client/game/demonware/services/bdRichPresence.cpp
Normal file
25
src/client/game/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
src/client/game/demonware/services/bdRichPresence.hpp
Normal file
14
src/client/game/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
src/client/game/demonware/services/bdStats.cpp
Normal file
113
src/client/game/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::unk3); // leaderboards
|
||||||
|
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::readStatsByEntityID);
|
||||||
|
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::unk3(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::readStatsByEntityID(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
src/client/game/demonware/services/bdStats.hpp
Normal file
25
src/client/game/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 unk3(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 readStatsByEntityID(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void writeServerValidatedStats(service_server* server, byte_buffer* buffer) const;
|
||||||
|
};
|
||||||
|
}
|
25
src/client/game/demonware/services/bdStats2.cpp
Normal file
25
src/client/game/demonware/services/bdStats2.cpp
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "../services.hpp"
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
bdStats2::bdStats2() : service(19, "bdStats")
|
||||||
|
{
|
||||||
|
this->register_task(1, &bdStats2::startArbitratedSession);
|
||||||
|
this->register_task(2, &bdStats2::writeArbitratedStats);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdStats2::startArbitratedSession(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdStats2::writeArbitratedStats(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
}
|
14
src/client/game/demonware/services/bdStats2.hpp
Normal file
14
src/client/game/demonware/services/bdStats2.hpp
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
class bdStats2 final : public service
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bdStats2();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void startArbitratedSession(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void writeArbitratedStats(service_server* server, byte_buffer* buffer) const;
|
||||||
|
};
|
||||||
|
}
|
65
src/client/game/demonware/services/bdStats3.cpp
Normal file
65
src/client/game/demonware/services/bdStats3.cpp
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "../services.hpp"
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
bdStats3::bdStats3() : service(91, "bdStats")
|
||||||
|
{
|
||||||
|
this->register_task(1, &bdStats3::deleteCSFileStats);
|
||||||
|
this->register_task(3, &bdStats3::readStatsByEntityID);
|
||||||
|
this->register_task(4, &bdStats3::readStatsByRank);
|
||||||
|
this->register_task(5, &bdStats3::readStatsByPivot);
|
||||||
|
this->register_task(6, &bdStats3::readStatsByRating);
|
||||||
|
this->register_task(7, &bdStats3::readStatsByMultipleRanks);
|
||||||
|
this->register_task(11, &bdStats3::readStatsByLeaderboardIDsAndEntityIDs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdStats3::deleteCSFileStats(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdStats3::readStatsByEntityID(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdStats3::readStatsByRank(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdStats3::readStatsByPivot(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdStats3::readStatsByRating(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdStats3::readStatsByMultipleRanks(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdStats3::readStatsByLeaderboardIDsAndEntityIDs(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
}
|
19
src/client/game/demonware/services/bdStats3.hpp
Normal file
19
src/client/game/demonware/services/bdStats3.hpp
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
class bdStats3 final : public service
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bdStats3();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void deleteCSFileStats(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 readStatsByLeaderboardIDsAndEntityIDs(service_server* server, byte_buffer* buffer) const;
|
||||||
|
};
|
||||||
|
}
|
246
src/client/game/demonware/services/bdStorage.cpp
Normal file
246
src/client/game/demonware/services/bdStorage.cpp
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "../services.hpp"
|
||||||
|
|
||||||
|
#include <utils/nt.hpp>
|
||||||
|
#include <utils/io.hpp>
|
||||||
|
#include <utils/cryptography.hpp>
|
||||||
|
|
||||||
|
#include "game/game.hpp"
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
bdStorage::bdStorage() : service(10, "bdStorage")
|
||||||
|
{
|
||||||
|
this->register_task(20, &bdStorage::list_publisher_files);
|
||||||
|
this->register_task(21, &bdStorage::get_publisher_file);
|
||||||
|
this->register_task(24, &bdStorage::set_user_file);
|
||||||
|
this->register_task(16, &bdStorage::get_user_file);
|
||||||
|
this->register_task(12, &bdStorage::unk12);
|
||||||
|
|
||||||
|
//this->map_publisher_resource("motd-.*\\.txt", DW_MOTD);
|
||||||
|
// this->map_publisher_resource("ffotd-.*\\.ff", DW_FASTFILE);
|
||||||
|
//this->map_publisher_resource("playlists(_.+)?\\.aggr", DW_PLAYLISTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdStorage::map_publisher_resource(const std::string& expression, const INT id)
|
||||||
|
{
|
||||||
|
auto data = utils::nt::load_resource(id);
|
||||||
|
this->map_publisher_resource_variant(expression, std::move(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdStorage::map_publisher_resource_variant(const std::string& expression, resource_variant resource)
|
||||||
|
{
|
||||||
|
if (resource.valueless_by_exception())
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Publisher resource variant is empty!");
|
||||||
|
}
|
||||||
|
|
||||||
|
this->publisher_resources_.emplace_back(std::regex{expression}, std::move(resource));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bdStorage::load_publisher_resource(const std::string& name, std::string& buffer)
|
||||||
|
{
|
||||||
|
for (const auto& resource : this->publisher_resources_)
|
||||||
|
{
|
||||||
|
if (std::regex_match(name, resource.first))
|
||||||
|
{
|
||||||
|
if (std::holds_alternative<std::string>(resource.second))
|
||||||
|
{
|
||||||
|
buffer = std::get<std::string>(resource.second);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buffer = std::get<callback>(resource.second)();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DW_DEBUG
|
||||||
|
printf("[DW]: [bdStorage]: missing publisher file: %s\n", name.data());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdStorage::list_publisher_files(service_server* server, byte_buffer* buffer)
|
||||||
|
{
|
||||||
|
uint32_t date;
|
||||||
|
uint16_t num_results, offset;
|
||||||
|
std::string unk, filename, data;
|
||||||
|
|
||||||
|
buffer->read_string(&unk);
|
||||||
|
buffer->read_uint32(&date);
|
||||||
|
buffer->read_uint16(&num_results);
|
||||||
|
buffer->read_uint16(&offset);
|
||||||
|
buffer->read_string(&filename);
|
||||||
|
|
||||||
|
#ifdef DW_DEBUG
|
||||||
|
printf("[DW]: [bdStorage]: list publisher files: %s\n", filename.data());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
|
||||||
|
if (this->load_publisher_resource(filename, data))
|
||||||
|
{
|
||||||
|
auto* info = new bdFileInfo;
|
||||||
|
|
||||||
|
info->file_id = *reinterpret_cast<const uint64_t*>(utils::cryptography::sha1::compute(filename).data());
|
||||||
|
info->filename = filename;
|
||||||
|
info->create_time = 0;
|
||||||
|
info->modified_time = info->create_time;
|
||||||
|
info->file_size = uint32_t(data.size());
|
||||||
|
info->owner_id = 0;
|
||||||
|
info->priv = false;
|
||||||
|
|
||||||
|
reply->add(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdStorage::get_publisher_file(service_server* server, byte_buffer* buffer)
|
||||||
|
{
|
||||||
|
std::string unk, filename;
|
||||||
|
buffer->read_string(&unk);
|
||||||
|
buffer->read_string(&filename);
|
||||||
|
|
||||||
|
#ifdef DW_DEBUG
|
||||||
|
printf("[DW]: [bdStorage]: loading publisher file: %s\n", filename.data());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::string data;
|
||||||
|
|
||||||
|
if (this->load_publisher_resource(filename, data))
|
||||||
|
{
|
||||||
|
#ifdef DW_DEBUG
|
||||||
|
printf("[DW]: [bdStorage]: sending publisher file: %s, size: %lld\n", filename.data(), data.size());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->add(new bdFileData(data));
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
server->create_reply(this->task_id(), game::BD_NO_FILE)->send();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string bdStorage::get_user_file_path(const std::string& name)
|
||||||
|
{
|
||||||
|
return "players2/user/" + name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdStorage::set_user_file(service_server* server, byte_buffer* buffer) const
|
||||||
|
{
|
||||||
|
uint64_t owner;
|
||||||
|
uint32_t numfiles;
|
||||||
|
std::string game, platform;
|
||||||
|
|
||||||
|
buffer->read_string(&game);
|
||||||
|
buffer->read_uint64(&owner);
|
||||||
|
buffer->read_string(&platform);
|
||||||
|
buffer->read_uint32(&numfiles);
|
||||||
|
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < numfiles; i++)
|
||||||
|
{
|
||||||
|
std::string filename, data;
|
||||||
|
uint32_t unk;
|
||||||
|
bool priv;
|
||||||
|
|
||||||
|
buffer->read_string(&filename);
|
||||||
|
buffer->read_blob(&data);
|
||||||
|
buffer->read_uint32(&unk);
|
||||||
|
buffer->read_bool(&priv);
|
||||||
|
|
||||||
|
const auto path = get_user_file_path(filename);
|
||||||
|
utils::io::write_file(path, data);
|
||||||
|
|
||||||
|
auto* info = new bdFile2;
|
||||||
|
|
||||||
|
info->unk1 = 0;
|
||||||
|
info->unk2 = 0;
|
||||||
|
info->unk3 = 0;
|
||||||
|
info->priv = false;
|
||||||
|
info->owner_id = owner;
|
||||||
|
info->platform = platform;
|
||||||
|
info->filename = filename;
|
||||||
|
info->data = data;
|
||||||
|
|
||||||
|
#ifdef DW_DEBUG
|
||||||
|
printf("[DW]: [bdStorage]: set user file: %s\n", filename.data());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
reply->add(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdStorage::get_user_file(service_server* server, byte_buffer* buffer) const
|
||||||
|
{
|
||||||
|
uint32_t unk32_0;
|
||||||
|
uint32_t numfiles, count = 0;
|
||||||
|
uint64_t owner;
|
||||||
|
std::string game, platform;
|
||||||
|
|
||||||
|
buffer->read_string(&game);
|
||||||
|
buffer->read_uint32(&unk32_0);
|
||||||
|
buffer->read_uint64(&owner);
|
||||||
|
buffer->read_string(&platform);
|
||||||
|
buffer->read_uint64(&owner);
|
||||||
|
buffer->read_string(&platform);
|
||||||
|
buffer->read_uint32(&numfiles);
|
||||||
|
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < numfiles; i++)
|
||||||
|
{
|
||||||
|
std::string filename, data;
|
||||||
|
buffer->read_string(&filename);
|
||||||
|
|
||||||
|
const auto path = get_user_file_path(filename);
|
||||||
|
if (!utils::io::read_file(path, &data))
|
||||||
|
{
|
||||||
|
#ifdef DW_DEBUG
|
||||||
|
printf("[DW]: [bdStorage]: get user file: missing file: %s, %s, %s\n", game.data(), filename.data(), platform.data());
|
||||||
|
#endif
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto response = new bdFile;
|
||||||
|
response->owner_id = owner;
|
||||||
|
response->unk = 0;
|
||||||
|
response->platform = platform;
|
||||||
|
response->filename = filename;
|
||||||
|
response->data = data;
|
||||||
|
|
||||||
|
reply->add(response);
|
||||||
|
++count;
|
||||||
|
|
||||||
|
#ifdef DW_DEBUG
|
||||||
|
printf("[DW]: [bdStorage]: get user file: %s, %s, %s\n", game.data(), filename.data(), platform.data());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count == numfiles)
|
||||||
|
{
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
server->create_reply(this->task_id(), game::BD_NO_FILE)->send();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdStorage::unk12(service_server* server, byte_buffer* buffer) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
}
|
27
src/client/game/demonware/services/bdStorage.hpp
Normal file
27
src/client/game/demonware/services/bdStorage.hpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
class bdStorage final : public service
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bdStorage();
|
||||||
|
|
||||||
|
private:
|
||||||
|
using callback = std::function<std::string()>;
|
||||||
|
using resource_variant = std::variant<std::string, callback>;
|
||||||
|
std::vector<std::pair<std::regex, resource_variant>> publisher_resources_;
|
||||||
|
|
||||||
|
void map_publisher_resource(const std::string& expression, INT id);
|
||||||
|
void map_publisher_resource_variant(const std::string& expression, resource_variant resource);
|
||||||
|
bool load_publisher_resource(const std::string& name, std::string& buffer);
|
||||||
|
|
||||||
|
void list_publisher_files(service_server* server, byte_buffer* buffer);
|
||||||
|
void get_publisher_file(service_server* server, byte_buffer* buffer);
|
||||||
|
void set_user_file(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void get_user_file(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void unk12(service_server* server, byte_buffer* buffer) const;
|
||||||
|
|
||||||
|
static std::string get_user_file_path(const std::string& name);
|
||||||
|
};
|
||||||
|
}
|
409
src/client/game/demonware/services/bdTeams.cpp
Normal file
409
src/client/game/demonware/services/bdTeams.cpp
Normal file
@ -0,0 +1,409 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "../services.hpp"
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
bdTeams::bdTeams() : service(3, "bdTeams")
|
||||||
|
{
|
||||||
|
this->register_task(30, &bdTeams::createTeam);
|
||||||
|
this->register_task(31, &bdTeams::updateTeamName);
|
||||||
|
this->register_task(32, &bdTeams::promoteMember);
|
||||||
|
this->register_task(33, &bdTeams::kickMember);
|
||||||
|
this->register_task(34, &bdTeams::leaveTeam);
|
||||||
|
this->register_task(35, &bdTeams::proposeMembership);
|
||||||
|
this->register_task(36, &bdTeams::rejectMembership);
|
||||||
|
this->register_task(37, &bdTeams::acceptMembership);
|
||||||
|
this->register_task(38, &bdTeams::getPublicProfiles);
|
||||||
|
this->register_task(39, &bdTeams::getPrivateProfile);
|
||||||
|
this->register_task(40, &bdTeams::getPublicMemberProfiles);
|
||||||
|
this->register_task(41, &bdTeams::getPrivateMemberProfiles);
|
||||||
|
this->register_task(42, &bdTeams::setPublicProfile);
|
||||||
|
this->register_task(43, &bdTeams::setPrivateProfile);
|
||||||
|
this->register_task(44, &bdTeams::setPublicMemberProfile);
|
||||||
|
this->register_task(45, &bdTeams::setPrivateMemberProfile);
|
||||||
|
this->register_task(46, &bdTeams::getMemberships);
|
||||||
|
this->register_task(47, &bdTeams::getMembers);
|
||||||
|
this->register_task(48, &bdTeams::getOutgoingProposals);
|
||||||
|
this->register_task(49, &bdTeams::withdrawProposal);
|
||||||
|
this->register_task(50, &bdTeams::demoteMember);
|
||||||
|
this->register_task(51, &bdTeams::promoteMemberToOwner);
|
||||||
|
this->register_task(52, &bdTeams::getTeamInfo);
|
||||||
|
this->register_task(53, &bdTeams::getIncomingProposals);
|
||||||
|
this->register_task(54, &bdTeams::sendInstantMessage);
|
||||||
|
this->register_task(56, &bdTeams::getMembershipsUser);
|
||||||
|
this->register_task(57, &bdTeams::sendInstantMessageToTeam);
|
||||||
|
this->register_task(58, &bdTeams::searchPublicTeamProfiles);
|
||||||
|
this->register_task(63, &bdTeams::addApplication);
|
||||||
|
this->register_task(64, &bdTeams::getApplicationsByTeam);
|
||||||
|
this->register_task(65, &bdTeams::acceptApplication);
|
||||||
|
this->register_task(66, &bdTeams::rejectApplication);
|
||||||
|
this->register_task(68, &bdTeams::autoJoinTeam);
|
||||||
|
this->register_task(70, &bdTeams::createTeamWithProfiles);
|
||||||
|
this->register_task(73, &bdTeams::banMember);
|
||||||
|
this->register_task(74, &bdTeams::unbanMember);
|
||||||
|
this->register_task(76, &bdTeams::blockApplication);
|
||||||
|
this->register_task(78, &bdTeams::unblockApplication);
|
||||||
|
this->register_task(80, &bdTeams::updateTeamType);
|
||||||
|
this->register_task(82, &bdTeams::setOnline);
|
||||||
|
this->register_task(83, &bdTeams::getMembershipsWithCounts);
|
||||||
|
this->register_task(84, &bdTeams::getMembershipsWithCountsUser);
|
||||||
|
this->register_task(85, &bdTeams::searchTeams);
|
||||||
|
this->register_task(86, &bdTeams::createTeamWithProfilesAndTeamType);
|
||||||
|
this->register_task(87, &bdTeams::getMembershipsWithCountsAndTeamTypeUser);
|
||||||
|
this->register_task(88, &bdTeams::getMembershipsWithCountsAndTeamType);
|
||||||
|
this->register_task(89, &bdTeams::getTeamInfoWithTeamType);
|
||||||
|
this->register_task(91, &bdTeams::setTeamAutoJoin);
|
||||||
|
this->register_task(92, &bdTeams::getTeamAutoJoin);
|
||||||
|
this->register_task(94, &bdTeams::getMembersAndPrivileges);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::createTeam(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::updateTeamName(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::promoteMember(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::kickMember(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::leaveTeam(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::proposeMembership(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::rejectMembership(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::acceptMembership(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::getPublicProfiles(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::getPrivateProfile(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::getPublicMemberProfiles(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::getPrivateMemberProfiles(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::setPublicProfile(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::setPrivateProfile(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::setPublicMemberProfile(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::setPrivateMemberProfile(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::getMemberships(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::getMembers(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::getOutgoingProposals(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::withdrawProposal(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::demoteMember(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::promoteMemberToOwner(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::getTeamInfo(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::getIncomingProposals(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::sendInstantMessage(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::getMembershipsUser(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::sendInstantMessageToTeam(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::searchPublicTeamProfiles(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::addApplication(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::getApplicationsByTeam(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::acceptApplication(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::rejectApplication(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::autoJoinTeam(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::createTeamWithProfiles(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::banMember(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::unbanMember(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::blockApplication(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::unblockApplication(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::updateTeamType(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::setOnline(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::getMembershipsWithCounts(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::getMembershipsWithCountsUser(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::searchTeams(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::createTeamWithProfilesAndTeamType(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::getMembershipsWithCountsAndTeamTypeUser(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::getMembershipsWithCountsAndTeamType(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::getTeamInfoWithTeamType(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::setTeamAutoJoin(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::getTeamAutoJoin(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTeams::getMembersAndPrivileges(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
}
|
62
src/client/game/demonware/services/bdTeams.hpp
Normal file
62
src/client/game/demonware/services/bdTeams.hpp
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
class bdTeams final : public service
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bdTeams();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void createTeam(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void updateTeamName(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void promoteMember(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void kickMember(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void leaveTeam(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void proposeMembership(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void rejectMembership(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void acceptMembership(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getPublicProfiles(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getPrivateProfile(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getPublicMemberProfiles(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getPrivateMemberProfiles(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void setPublicProfile(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void setPrivateProfile(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void setPublicMemberProfile(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void setPrivateMemberProfile(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getMemberships(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getMembers(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getOutgoingProposals(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void withdrawProposal(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void demoteMember(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void promoteMemberToOwner(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getTeamInfo(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getIncomingProposals(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void sendInstantMessage(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getMembershipsUser(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void sendInstantMessageToTeam(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void searchPublicTeamProfiles(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void addApplication(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getApplicationsByTeam(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void acceptApplication(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void rejectApplication(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void autoJoinTeam(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void createTeamWithProfiles(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void banMember(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void unbanMember(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void blockApplication(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void unblockApplication(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void updateTeamType(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void setOnline(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getMembershipsWithCounts(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getMembershipsWithCountsUser(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void searchTeams(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void createTeamWithProfilesAndTeamType(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getMembershipsWithCountsAndTeamTypeUser(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getMembershipsWithCountsAndTeamType(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getTeamInfoWithTeamType(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void setTeamAutoJoin(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getTeamAutoJoin(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getMembersAndPrivileges(service_server* server, byte_buffer* buffer) const;
|
||||||
|
};
|
||||||
|
}
|
20
src/client/game/demonware/services/bdTitleUtilities.cpp
Normal file
20
src/client/game/demonware/services/bdTitleUtilities.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "../services.hpp"
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
bdTitleUtilities::bdTitleUtilities() : service(12, "bdTitleUtilities")
|
||||||
|
{
|
||||||
|
this->register_task(6, &bdTitleUtilities::get_server_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdTitleUtilities::get_server_time(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();
|
||||||
|
}
|
||||||
|
}
|
13
src/client/game/demonware/services/bdTitleUtilities.hpp
Normal file
13
src/client/game/demonware/services/bdTitleUtilities.hpp
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
class bdTitleUtilities final : public service
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bdTitleUtilities();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void get_server_time(service_server* server, byte_buffer* buffer) const;
|
||||||
|
};
|
||||||
|
}
|
17
src/client/game/demonware/services/bdUNK63.cpp
Normal file
17
src/client/game/demonware/services/bdUNK63.cpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "../services.hpp"
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
bdUNK63::bdUNK63() : service(63, "bdUNK63")
|
||||||
|
{
|
||||||
|
//this->register_task(6, "unk6", &bdUNK63::unk6);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdUNK63::unk(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
}
|
13
src/client/game/demonware/services/bdUNK63.hpp
Normal file
13
src/client/game/demonware/services/bdUNK63.hpp
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
class bdUNK63 final : public service
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bdUNK63();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void unk(service_server* server, byte_buffer* buffer) const;
|
||||||
|
};
|
||||||
|
}
|
97
src/client/game/demonware/services/bdUserGroups.cpp
Normal file
97
src/client/game/demonware/services/bdUserGroups.cpp
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
#include <std_include.hpp>
|
||||||
|
#include "../services.hpp"
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
bdUserGroups::bdUserGroups() : service(65, "bdUserGroups")
|
||||||
|
{
|
||||||
|
this->register_task(1, &bdUserGroups::createGroup);
|
||||||
|
this->register_task(2, &bdUserGroups::deleteGroup);
|
||||||
|
this->register_task(3, &bdUserGroups::joinGroup);
|
||||||
|
this->register_task(4, &bdUserGroups::leaveGroup);
|
||||||
|
this->register_task(5, &bdUserGroups::getMembershipInfo);
|
||||||
|
this->register_task(6, &bdUserGroups::changeMemberType);
|
||||||
|
this->register_task(7, &bdUserGroups::getNumMembers);
|
||||||
|
this->register_task(8, &bdUserGroups::getMembers);
|
||||||
|
this->register_task(9, &bdUserGroups::getMemberships);
|
||||||
|
this->register_task(10, &bdUserGroups::readStatsByRank);
|
||||||
|
this->register_task(11, &bdUserGroups::getGroupLists);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdUserGroups::createGroup(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdUserGroups::deleteGroup(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdUserGroups::joinGroup(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdUserGroups::leaveGroup(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdUserGroups::getMembershipInfo(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdUserGroups::changeMemberType(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdUserGroups::getNumMembers(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdUserGroups::getMembers(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdUserGroups::getMemberships(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdUserGroups::readStatsByRank(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void bdUserGroups::getGroupLists(service_server* server, byte_buffer* /*buffer*/) const
|
||||||
|
{
|
||||||
|
// TODO:
|
||||||
|
auto reply = server->create_reply(this->task_id());
|
||||||
|
reply->send();
|
||||||
|
}
|
||||||
|
}
|
23
src/client/game/demonware/services/bdUserGroups.hpp
Normal file
23
src/client/game/demonware/services/bdUserGroups.hpp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace demonware
|
||||||
|
{
|
||||||
|
class bdUserGroups final : public service
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bdUserGroups();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void createGroup(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void deleteGroup(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void joinGroup(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void leaveGroup(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getMembershipInfo(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void changeMemberType(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getNumMembers(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getMembers(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getMemberships(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void readStatsByRank(service_server* server, byte_buffer* buffer) const;
|
||||||
|
void getGroupLists(service_server* server, byte_buffer* buffer) const;
|
||||||
|
};
|
||||||
|
}
|
@ -64,4 +64,345 @@ namespace game
|
|||||||
{
|
{
|
||||||
unsigned int name;
|
unsigned int name;
|
||||||
}; // Incomplete
|
}; // Incomplete
|
||||||
|
|
||||||
|
|
||||||
|
enum bdLobbyErrorCode : uint32_t
|
||||||
|
{
|
||||||
|
BD_NO_ERROR = 0x0,
|
||||||
|
BD_TOO_MANY_TASKS = 0x1,
|
||||||
|
BD_NOT_CONNECTED = 0x2,
|
||||||
|
BD_SEND_FAILED = 0x3,
|
||||||
|
BD_HANDLE_TASK_FAILED = 0x4,
|
||||||
|
BD_START_TASK_FAILED = 0x5,
|
||||||
|
BD_RESULT_EXCEEDS_BUFFER_SIZE = 0x64,
|
||||||
|
BD_ACCESS_DENIED = 0x65,
|
||||||
|
BD_EXCEPTION_IN_DB = 0x66,
|
||||||
|
BD_MALFORMED_TASK_HEADER = 0x67,
|
||||||
|
BD_INVALID_ROW = 0x68,
|
||||||
|
BD_EMPTY_ARG_LIST = 0x69,
|
||||||
|
BD_PARAM_PARSE_ERROR = 0x6A,
|
||||||
|
BD_PARAM_MISMATCHED_TYPE = 0x6B,
|
||||||
|
BD_SERVICE_NOT_AVAILABLE = 0x6C,
|
||||||
|
BD_CONNECTION_RESET = 0x6D,
|
||||||
|
BD_INVALID_USER_ID = 0x6E,
|
||||||
|
BD_LOBBY_PROTOCOL_VERSION_FAILURE = 0x6F,
|
||||||
|
BD_LOBBY_INTERNAL_FAILURE = 0x70,
|
||||||
|
BD_LOBBY_PROTOCOL_ERROR = 0x71,
|
||||||
|
BD_LOBBY_FAILED_TO_DECODE_UTF8 = 0x72,
|
||||||
|
BD_LOBBY_ASCII_EXPECTED = 0x73,
|
||||||
|
BD_ASYNCHRONOUS_ERROR = 0xC8,
|
||||||
|
BD_STREAMING_COMPLETE = 0xC9,
|
||||||
|
BD_MEMBER_NO_PROPOSAL = 0x12C,
|
||||||
|
BD_TEAMNAME_ALREADY_EXISTS = 0x12D,
|
||||||
|
BD_MAX_TEAM_MEMBERSHIPS_LIMITED = 0x12E,
|
||||||
|
BD_MAX_TEAM_OWNERSHIPS_LIMITED = 0x12F,
|
||||||
|
BD_NOT_A_TEAM_MEMBER = 0x130,
|
||||||
|
BD_INVALID_TEAM_ID = 0x131,
|
||||||
|
BD_INVALID_TEAM_NAME = 0x132,
|
||||||
|
BD_NOT_A_TEAM_OWNER = 0x133,
|
||||||
|
BD_NOT_AN_ADMIN_OR_OWNER = 0x134,
|
||||||
|
BD_MEMBER_PROPOSAL_EXISTS = 0x135,
|
||||||
|
BD_MEMBER_EXISTS = 0x136,
|
||||||
|
BD_TEAM_FULL = 0x137,
|
||||||
|
BD_VULGAR_TEAM_NAME = 0x138,
|
||||||
|
BD_TEAM_USERID_BANNED = 0x139,
|
||||||
|
BD_TEAM_EMPTY = 0x13A,
|
||||||
|
BD_INVALID_TEAM_PROFILE_QUERY_ID = 0x13B,
|
||||||
|
BD_TEAMNAME_TOO_SHORT = 0x13C,
|
||||||
|
BD_UNIQUE_PROFILE_DATA_EXISTS_ALREADY = 0x13D,
|
||||||
|
BD_INVALID_LEADERBOARD_ID = 0x190,
|
||||||
|
BD_INVALID_STATS_SET = 0x191,
|
||||||
|
BD_EMPTY_STATS_SET_IGNORED = 0x193,
|
||||||
|
BD_NO_DIRECT_ACCESS_TO_ARBITRATED_LBS = 0x194,
|
||||||
|
BD_STATS_WRITE_PERMISSION_DENIED = 0x195,
|
||||||
|
BD_STATS_WRITE_TYPE_DATA_TYPE_MISMATCH = 0x196,
|
||||||
|
BD_NO_STATS_FOR_USER = 0x197,
|
||||||
|
BD_INVALID_ACCESS_TO_UNRANKED_LB = 0x198,
|
||||||
|
BD_INVALID_EXTERNAL_TITLE_ID = 0x199,
|
||||||
|
BD_DIFFERENT_LEADERBOARD_SCHEMAS = 0x19A,
|
||||||
|
BD_TOO_MANY_LEADERBOARDS_REQUESTED = 0x19B,
|
||||||
|
BD_ENTITLEMENTS_ERROR = 0x19C,
|
||||||
|
BD_ENTITLEMENTS_INVALID_TITLEID = 0x19D,
|
||||||
|
BD_ENTITLEMENTS_INVALID_LEADERBOARDID = 0x19E,
|
||||||
|
BD_ENTITLEMENTS_INVALID_GET_MODE_FOR_TITLE = 0x19F,
|
||||||
|
BD_ENTITLEMENTS_URL_CONNECTION_ERROR = 0x1A0,
|
||||||
|
BD_ENTITLEMENTS_CONFIG_ERROR = 0x1A1,
|
||||||
|
BD_ENTITLEMENTS_NAMED_PARENT_ERROR = 0x1A2,
|
||||||
|
BD_ENTITLEMENTS_NAMED_KEY_ERROR = 0x1A3,
|
||||||
|
BD_TOO_MANY_ENTITY_IDS_REQUESTED = 0x1A4,
|
||||||
|
BD_STATS_READ_FAILED = 0x1A5,
|
||||||
|
BD_INVALID_TITLE_ID = 0x1F4,
|
||||||
|
BD_MESSAGING_INVALID_MAIL_ID = 0x258,
|
||||||
|
BD_SELF_BLOCK_NOT_ALLOWED = 0x259,
|
||||||
|
BD_GLOBAL_MESSAGE_ACCESS_DENIED = 0x25A,
|
||||||
|
BD_GLOBAL_MESSAGES_USER_LIMIT_EXCEEDED = 0x25B,
|
||||||
|
BD_MESSAGING_SENDER_DOES_NOT_EXIST = 0x25C,
|
||||||
|
BD_AUTH_NO_ERROR = 0x2BC,
|
||||||
|
BD_AUTH_BAD_REQUEST = 0x2BD,
|
||||||
|
BD_AUTH_SERVER_CONFIG_ERROR = 0x2BE,
|
||||||
|
BD_AUTH_BAD_TITLE_ID = 0x2BF,
|
||||||
|
BD_AUTH_BAD_ACCOUNT = 0x2C0,
|
||||||
|
BD_AUTH_ILLEGAL_OPERATION = 0x2C1,
|
||||||
|
BD_AUTH_INCORRECT_LICENSE_CODE = 0x2C2,
|
||||||
|
BD_AUTH_CREATE_USERNAME_EXISTS = 0x2C3,
|
||||||
|
BD_AUTH_CREATE_USERNAME_ILLEGAL = 0x2C4,
|
||||||
|
BD_AUTH_CREATE_USERNAME_VULGAR = 0x2C5,
|
||||||
|
BD_AUTH_CREATE_MAX_ACC_EXCEEDED = 0x2C6,
|
||||||
|
BD_AUTH_MIGRATE_NOT_SUPPORTED = 0x2C7,
|
||||||
|
BD_AUTH_TITLE_DISABLED = 0x2C8,
|
||||||
|
BD_AUTH_ACCOUNT_EXPIRED = 0x2C9,
|
||||||
|
BD_AUTH_ACCOUNT_LOCKED = 0x2CA,
|
||||||
|
BD_AUTH_UNKNOWN_ERROR = 0x2CB,
|
||||||
|
BD_AUTH_INCORRECT_PASSWORD = 0x2CC,
|
||||||
|
BD_AUTH_IP_NOT_IN_ALLOWED_RANGE = 0x2CD,
|
||||||
|
BD_AUTH_WII_TOKEN_VERIFICATION_FAILED = 0x2CE,
|
||||||
|
BD_AUTH_WII_AUTHENTICATION_FAILED = 0x2CF,
|
||||||
|
BD_AUTH_IP_KEY_LIMIT_REACHED = 0x2D0,
|
||||||
|
BD_AUTH_INVALID_GSPID = 0x2D1,
|
||||||
|
BD_AUTH_INVALID_IP_RANGE_ID = 0x2D2,
|
||||||
|
BD_AUTH_3DS_TOKEN_VERIFICATION_FAILED = 0x2D1,
|
||||||
|
BD_AUTH_3DS_AUTHENTICATION_FAILED = 0x2D2,
|
||||||
|
BD_AUTH_STEAM_APP_ID_MISMATCH = 0x2D3,
|
||||||
|
BD_AUTH_ABACCOUNTS_APP_ID_MISMATCH = 0x2D4,
|
||||||
|
BD_AUTH_CODO_USERNAME_NOT_SET = 0x2D5,
|
||||||
|
BD_AUTH_WIIU_TOKEN_VERIFICATION_FAILED = 0x2D6,
|
||||||
|
BD_AUTH_WIIU_AUTHENTICATION_FAILED = 0x2D7,
|
||||||
|
BD_AUTH_CODO_USERNAME_NOT_BASE64 = 0x2D8,
|
||||||
|
BD_AUTH_CODO_USERNAME_NOT_UTF8 = 0x2D9,
|
||||||
|
BD_AUTH_TENCENT_TICKET_EXPIRED = 0x2DA,
|
||||||
|
BD_AUTH_PS3_SERVICE_ID_MISMATCH = 0x2DB,
|
||||||
|
BD_AUTH_CODOID_NOT_WHITELISTED = 0x2DC,
|
||||||
|
BD_AUTH_PLATFORM_TOKEN_ERROR = 0x2DD,
|
||||||
|
BD_AUTH_JSON_FORMAT_ERROR = 0x2DE,
|
||||||
|
BD_AUTH_REPLY_CONTENT_ERROR = 0x2DF,
|
||||||
|
BD_AUTH_THIRD_PARTY_TOKEN_EXPIRED = 0x2E0,
|
||||||
|
BD_AUTH_CONTINUING = 0x2E1,
|
||||||
|
BD_AUTH_PLATFORM_DEVICE_ID_ERROR = 0x2E4,
|
||||||
|
BD_NO_PROFILE_INFO_EXISTS = 0x320,
|
||||||
|
BD_FRIENDSHIP_NOT_REQUSTED = 0x384,
|
||||||
|
BD_NOT_A_FRIEND = 0x385,
|
||||||
|
BD_SELF_FRIENDSHIP_NOT_ALLOWED = 0x387,
|
||||||
|
BD_FRIENDSHIP_EXISTS = 0x388,
|
||||||
|
BD_PENDING_FRIENDSHIP_EXISTS = 0x389,
|
||||||
|
BD_USERID_BANNED = 0x38A,
|
||||||
|
BD_FRIENDS_FULL = 0x38C,
|
||||||
|
BD_FRIENDS_NO_RICH_PRESENCE = 0x38D,
|
||||||
|
BD_RICH_PRESENCE_TOO_LARGE = 0x38E,
|
||||||
|
BD_NO_FILE = 0x3E8,
|
||||||
|
BD_PERMISSION_DENIED = 0x3E9,
|
||||||
|
BD_FILESIZE_LIMIT_EXCEEDED = 0x3EA,
|
||||||
|
BD_FILENAME_MAX_LENGTH_EXCEEDED = 0x3EB,
|
||||||
|
BD_EXTERNAL_STORAGE_SERVICE_ERROR = 0x3EC,
|
||||||
|
BD_CHANNEL_DOES_NOT_EXIST = 0x44D,
|
||||||
|
BD_CHANNEL_ALREADY_SUBSCRIBED = 0x44E,
|
||||||
|
BD_CHANNEL_NOT_SUBSCRIBED = 0x44F,
|
||||||
|
BD_CHANNEL_FULL = 0x450,
|
||||||
|
BD_CHANNEL_SUBSCRIPTIONS_FULL = 0x451,
|
||||||
|
BD_CHANNEL_NO_SELF_WHISPERING = 0x452,
|
||||||
|
BD_CHANNEL_ADMIN_REQUIRED = 0x453,
|
||||||
|
BD_CHANNEL_TARGET_NOT_SUBSCRIBED = 0x454,
|
||||||
|
BD_CHANNEL_REQUIRES_PASSWORD = 0x455,
|
||||||
|
BD_CHANNEL_TARGET_IS_SELF = 0x456,
|
||||||
|
BD_CHANNEL_PUBLIC_BAN_NOT_ALLOWED = 0x457,
|
||||||
|
BD_CHANNEL_USER_BANNED = 0x458,
|
||||||
|
BD_CHANNEL_PUBLIC_PASSWORD_NOT_ALLOWED = 0x459,
|
||||||
|
BD_CHANNEL_PUBLIC_KICK_NOT_ALLOWED = 0x45A,
|
||||||
|
BD_CHANNEL_MUTED = 0x45B,
|
||||||
|
BD_EVENT_DESC_TRUNCATED = 0x4B0,
|
||||||
|
BD_CONTENT_UNLOCK_UNKNOWN_ERROR = 0x514,
|
||||||
|
BD_UNLOCK_KEY_INVALID = 0x515,
|
||||||
|
BD_UNLOCK_KEY_ALREADY_USED_UP = 0x516,
|
||||||
|
BD_SHARED_UNLOCK_LIMIT_REACHED = 0x517,
|
||||||
|
BD_DIFFERENT_HARDWARE_ID = 0x518,
|
||||||
|
BD_INVALID_CONTENT_OWNER = 0x519,
|
||||||
|
BD_CONTENT_UNLOCK_INVALID_USER = 0x51A,
|
||||||
|
BD_CONTENT_UNLOCK_INVALID_CATEGORY = 0x51B,
|
||||||
|
BD_KEY_ARCHIVE_INVALID_WRITE_TYPE = 0x5DC,
|
||||||
|
BD_KEY_ARCHIVE_EXCEEDED_MAX_IDS_PER_REQUEST = 0x5DD,
|
||||||
|
BD_BANDWIDTH_TEST_TRY_AGAIN = 0x712,
|
||||||
|
BD_BANDWIDTH_TEST_STILL_IN_PROGRESS = 0x713,
|
||||||
|
BD_BANDWIDTH_TEST_NOT_PROGRESS = 0x714,
|
||||||
|
BD_BANDWIDTH_TEST_SOCKET_ERROR = 0x715,
|
||||||
|
BD_INVALID_SESSION_NONCE = 0x76D,
|
||||||
|
BD_ARBITRATION_FAILURE = 0x76F,
|
||||||
|
BD_ARBITRATION_USER_NOT_REGISTERED = 0x771,
|
||||||
|
BD_ARBITRATION_NOT_CONFIGURED = 0x772,
|
||||||
|
BD_CONTENTSTREAMING_FILE_NOT_AVAILABLE = 0x7D0,
|
||||||
|
BD_CONTENTSTREAMING_STORAGE_SPACE_EXCEEDED = 0x7D1,
|
||||||
|
BD_CONTENTSTREAMING_NUM_FILES_EXCEEDED = 0x7D2,
|
||||||
|
BD_CONTENTSTREAMING_UPLOAD_BANDWIDTH_EXCEEDED = 0x7D3,
|
||||||
|
BD_CONTENTSTREAMING_FILENAME_MAX_LENGTH_EXCEEDED = 0x7D4,
|
||||||
|
BD_CONTENTSTREAMING_MAX_THUMB_DATA_SIZE_EXCEEDED = 0x7D5,
|
||||||
|
BD_CONTENTSTREAMING_DOWNLOAD_BANDWIDTH_EXCEEDED = 0x7D6,
|
||||||
|
BD_CONTENTSTREAMING_NOT_ENOUGH_DOWNLOAD_BUFFER_SPACE = 0x7D7,
|
||||||
|
BD_CONTENTSTREAMING_SERVER_NOT_CONFIGURED = 0x7D8,
|
||||||
|
BD_CONTENTSTREAMING_INVALID_APPLE_RECEIPT = 0x7DA,
|
||||||
|
BD_CONTENTSTREAMING_APPLE_STORE_NOT_AVAILABLE = 0x7DB,
|
||||||
|
BD_CONTENTSTREAMING_APPLE_RECEIPT_FILENAME_MISMATCH = 0x7DC,
|
||||||
|
BD_CONTENTSTREAMING_HTTP_ERROR = 0x7E4,
|
||||||
|
BD_CONTENTSTREAMING_FAILED_TO_START_HTTP = 0x7E5,
|
||||||
|
BD_CONTENTSTREAMING_LOCALE_INVALID = 0x7E6,
|
||||||
|
BD_CONTENTSTREAMING_LOCALE_MISSING = 0x7E7,
|
||||||
|
BD_VOTERANK_ERROR_EMPTY_RATING_SUBMISSION = 0x7EE,
|
||||||
|
BD_VOTERANK_ERROR_MAX_VOTES_EXCEEDED = 0x7EF,
|
||||||
|
BD_VOTERANK_ERROR_INVALID_RATING = 0x7F0,
|
||||||
|
BD_MAX_NUM_TAGS_EXCEEDED = 0x82A,
|
||||||
|
BD_TAGGED_COLLECTION_DOES_NOT_EXIST = 0x82B,
|
||||||
|
BD_EMPTY_TAG_ARRAY = 0x82C,
|
||||||
|
BD_INVALID_QUERY_ID = 0x834,
|
||||||
|
BD_NO_ENTRY_TO_UPDATE = 0x835,
|
||||||
|
BD_SESSION_INVITE_EXISTS = 0x836,
|
||||||
|
BD_INVALID_SESSION_ID = 0x837,
|
||||||
|
BD_ATTACHMENT_TOO_LARGE = 0x838,
|
||||||
|
BD_INVALID_GROUP_ID = 0xAF0,
|
||||||
|
BD_MAIL_INVALID_MAIL_ID_ERROR = 0xB55,
|
||||||
|
BD_UCD_SERVICE_ERROR = 0xC80,
|
||||||
|
BD_UCD_SERVICE_DISABLED = 0xC81,
|
||||||
|
BD_UCD_UNINTIALIZED_ERROR = 0xC82,
|
||||||
|
BD_UCD_ACCOUNT_ALREADY_REGISTERED = 0xC83,
|
||||||
|
BD_UCD_ACCOUNT_NOT_REGISTERED = 0xC84,
|
||||||
|
BD_UCD_AUTH_ATTEMPT_FAILED = 0xC85,
|
||||||
|
BD_UCD_ACCOUNT_LINKING_ERROR = 0xC86,
|
||||||
|
BD_UCD_ENCRYPTION_ERROR = 0xC87,
|
||||||
|
BD_UCD_ACCOUNT_DATA_INVALID = 0xC88,
|
||||||
|
BD_UCD_ACCOUNT_DATA_INVALID_FIRSTNAME = 0xC89,
|
||||||
|
BD_UCD_ACCOUNT_DATA_INVALID_LASTNAME = 0xC8A,
|
||||||
|
BD_UCD_ACCOUNT_DATA_INVALID_DOB = 0xC8B,
|
||||||
|
BD_UCD_ACCOUNT_DATA_INVALID_EMAIL = 0xC8C,
|
||||||
|
BD_UCD_ACCOUNT_DATA_INVALID_COUNTRY = 0xC8D,
|
||||||
|
BD_UCD_ACCOUNT_DATA_INVALID_POSTCODE = 0xC8E,
|
||||||
|
BD_UCD_ACCOUNT_DATA_INVALID_PASSWORD = 0xC8F,
|
||||||
|
BD_UCD_ACCOUNT_NAME_ALREADY_RESISTERED = 0xC94,
|
||||||
|
BD_UCD_ACCOUNT_EMAIL_ALREADY_RESISTERED = 0xC95,
|
||||||
|
BD_UCD_GUEST_ACCOUNT_AUTH_CONFLICT = 0xC96,
|
||||||
|
BD_TWITCH_SERVICE_ERROR = 0xC1D,
|
||||||
|
BD_TWITCH_ACCOUNT_ALREADY_LINKED = 0xC1E,
|
||||||
|
BD_TWITCH_NO_LINKED_ACCOUNT = 0xC1F,
|
||||||
|
BD_YOUTUBE_SERVICE_ERROR = 0xCE5,
|
||||||
|
BD_YOUTUBE_SERVICE_COMMUNICATION_ERROR = 0xCE6,
|
||||||
|
BD_YOUTUBE_USER_DENIED_AUTHORIZATION = 0xCE7,
|
||||||
|
BD_YOUTUBE_AUTH_MAX_TIME_EXCEEDED = 0xCE8,
|
||||||
|
BD_YOUTUBE_USER_UNAUTHORIZED = 0xCE9,
|
||||||
|
BD_YOUTUBE_UPLOAD_MAX_TIME_EXCEEDED = 0xCEA,
|
||||||
|
BD_YOUTUBE_DUPLICATE_UPLOAD = 0xCEB,
|
||||||
|
BD_YOUTUBE_FAILED_UPLOAD = 0xCEC,
|
||||||
|
BD_YOUTUBE_ACCOUNT_ALREADY_REGISTERED = 0xCED,
|
||||||
|
BD_YOUTUBE_ACCOUNT_NOT_REGISTERED = 0xCEE,
|
||||||
|
BD_YOUTUBE_CONTENT_SERVER_ERROR = 0xCEF,
|
||||||
|
BD_YOUTUBE_UPLOAD_DOES_NOT_EXIST = 0xCF0,
|
||||||
|
BD_YOUTUBE_NO_LINKED_ACCOUNT = 0xCF1,
|
||||||
|
BD_YOUTUBE_DEVELOPER_TAGS_INVALID = 0xCF2,
|
||||||
|
BD_TWITTER_AUTH_ATTEMPT_FAILED = 0xDAD,
|
||||||
|
BD_TWITTER_AUTH_TOKEN_INVALID = 0xDAE,
|
||||||
|
BD_TWITTER_UPDATE_LIMIT_REACHED = 0xDAF,
|
||||||
|
BD_TWITTER_UNAVAILABLE = 0xDB0,
|
||||||
|
BD_TWITTER_ERROR = 0xDB1,
|
||||||
|
BD_TWITTER_TIMED_OUT = 0xDB2,
|
||||||
|
BD_TWITTER_DISABLED_FOR_USER = 0xDB3,
|
||||||
|
BD_TWITTER_ACCOUNT_AMBIGUOUS = 0xDB4,
|
||||||
|
BD_TWITTER_MAXIMUM_ACCOUNTS_REACHED = 0xDB5,
|
||||||
|
BD_TWITTER_ACCOUNT_NOT_REGISTERED = 0xDB6,
|
||||||
|
BD_TWITTER_DUPLICATE_STATUS = 0xDB7,
|
||||||
|
BD_TWITTER_ACCOUNT_ALREADY_REGISTERED = 0xE1C,
|
||||||
|
BD_FACEBOOK_AUTH_ATTEMPT_FAILED = 0xE11,
|
||||||
|
BD_FACEBOOK_AUTH_TOKEN_INVALID = 0xE12,
|
||||||
|
BD_FACEBOOK_PHOTO_DOES_NOT_EXIST = 0xE13,
|
||||||
|
BD_FACEBOOK_PHOTO_INVALID = 0xE14,
|
||||||
|
BD_FACEBOOK_PHOTO_ALBUM_FULL = 0xE15,
|
||||||
|
BD_FACEBOOK_UNAVAILABLE = 0xE16,
|
||||||
|
BD_FACEBOOK_ERROR = 0xE17,
|
||||||
|
BD_FACEBOOK_TIMED_OUT = 0xE18,
|
||||||
|
BD_FACEBOOK_DISABLED_FOR_USER = 0xE19,
|
||||||
|
BD_FACEBOOK_ACCOUNT_AMBIGUOUS = 0xE1A,
|
||||||
|
BD_FACEBOOK_MAXIMUM_ACCOUNTS_REACHED = 0xE1B,
|
||||||
|
BD_FACEBOOK_INVALID_NUM_PICTURES_REQUESTED = 0xE1C,
|
||||||
|
BD_FACEBOOK_VIDEO_DOES_NOT_EXIST = 0xE1D,
|
||||||
|
BD_FACEBOOK_ACCOUNT_ALREADY_REGISTERED = 0xE1E,
|
||||||
|
BD_APNS_INVALID_PAYLOAD = 0xE74,
|
||||||
|
BD_APNS_INVALID_TOKEN_LENGTH_ERROR = 0xE76,
|
||||||
|
BD_MAX_CONSOLEID_LENGTH_EXCEEDED = 0xEE1,
|
||||||
|
BD_MAX_WHITELIST_LENGTH_EXCEEDED = 0xEE2,
|
||||||
|
BD_USERGROUP_NAME_ALREADY_EXISTS = 0x1770,
|
||||||
|
BD_INVALID_USERGROUP_ID = 0x1771,
|
||||||
|
BD_USER_ALREADY_IN_USERGROUP = 0x1772,
|
||||||
|
BD_USER_NOT_IN_USERGROUP = 0x1773,
|
||||||
|
BD_INVALID_USERGROUP_MEMBER_TYPE = 0x1774,
|
||||||
|
BD_TOO_MANY_MEMBERS_REQUESTED = 0x1775,
|
||||||
|
BD_USERGROUP_NAME_TOO_SHORT = 0x1776,
|
||||||
|
BD_RICH_PRESENCE_DATA_TOO_LARGE = 0x1A90,
|
||||||
|
BD_RICH_PRESENCE_TOO_MANY_USERS = 0x1A91,
|
||||||
|
BD_PRESENCE_DATA_TOO_LARGE = 0x283C,
|
||||||
|
BD_PRESENCE_TOO_MANY_USERS = 0x283D,
|
||||||
|
BD_USER_LOGGED_IN_OTHER_TITLE = 0x283E,
|
||||||
|
BD_USER_NOT_LOGGED_IN = 0x283F,
|
||||||
|
BD_SUBSCRIPTION_TOO_MANY_USERS = 0x1B58,
|
||||||
|
BD_SUBSCRIPTION_TICKET_PARSE_ERROR = 0x1B59,
|
||||||
|
BD_CODO_ID_INVALID_DATA = 0x1BBC,
|
||||||
|
BD_INVALID_MESSAGE_FORMAT = 0x1BBD,
|
||||||
|
BD_TLOG_TOO_MANY_MESSAGES = 0x1BBE,
|
||||||
|
BD_CODO_ID_NOT_IN_WHITELIST = 0x1BBF,
|
||||||
|
BD_TLOG_MESSAGE_TRANSFORMATION_ERROR = 0x1BC0,
|
||||||
|
BD_REWARDS_NOT_ENABLED = 0x1BC1,
|
||||||
|
BD_MARKETPLACE_ERROR = 0x1F40,
|
||||||
|
BD_MARKETPLACE_RESOURCE_NOT_FOUND = 0x1F41,
|
||||||
|
BD_MARKETPLACE_INVALID_CURRENCY = 0x1F42,
|
||||||
|
BD_MARKETPLACE_INVALID_PARAMETER = 0x1F43,
|
||||||
|
BD_MARKETPLACE_RESOURCE_CONFLICT = 0x1F44,
|
||||||
|
BD_MARKETPLACE_STORAGE_ERROR = 0x1F45,
|
||||||
|
BD_MARKETPLACE_INTEGRITY_ERROR = 0x1F46,
|
||||||
|
BD_MARKETPLACE_INSUFFICIENT_FUNDS_ERROR = 0x1F47,
|
||||||
|
BD_MARKETPLACE_MMP_SERVICE_ERROR = 0x1F48,
|
||||||
|
BD_MARKETPLACE_PRECONDITION_REQUIRED = 0x1F49,
|
||||||
|
BD_MARKETPLACE_ITEM_MULTIPLE_PURCHASE_ERROR = 0x1F4A,
|
||||||
|
BD_MARKETPLACE_MISSING_REQUIRED_ENTITLEMENT = 0x1F4B,
|
||||||
|
BD_MARKETPLACE_VALIDATION_ERROR = 0x1F4C,
|
||||||
|
BD_MARKETPLACE_TENCENT_PAYMENT_ERROR = 0x1F4D,
|
||||||
|
BD_MARKETPLACE_SKU_NOT_COUPON_ENABLED_ERROR = 0x1F4E,
|
||||||
|
BD_LEAGUE_INVALID_TEAM_SIZE = 0x1FA4,
|
||||||
|
BD_LEAGUE_INVALID_TEAM = 0x1FA5,
|
||||||
|
BD_LEAGUE_INVALID_SUBDIVISION = 0x1FA6,
|
||||||
|
BD_LEAGUE_INVALID_LEAGUE = 0x1FA7,
|
||||||
|
BD_LEAGUE_TOO_MANY_RESULTS_REQUESTED = 0x1FA8,
|
||||||
|
BD_LEAGUE_METADATA_TOO_LARGE = 0x1FA9,
|
||||||
|
BD_LEAGUE_TEAM_ICON_TOO_LARGE = 0x1FAA,
|
||||||
|
BD_LEAGUE_TEAM_NAME_TOO_LONG = 0x1FAB,
|
||||||
|
BD_LEAGUE_ARRAY_SIZE_MISMATCH = 0x1FAC,
|
||||||
|
BD_LEAGUE_SUBDIVISION_MISMATCH = 0x2008,
|
||||||
|
BD_LEAGUE_INVALID_WRITE_TYPE = 0x2009,
|
||||||
|
BD_LEAGUE_INVALID_STATS_DATA = 0x200A,
|
||||||
|
BD_LEAGUE_SUBDIVISION_UNRANKED = 0x200B,
|
||||||
|
BD_LEAGUE_CROSS_TEAM_STATS_WRITE_PREVENTED = 0x200C,
|
||||||
|
BD_LEAGUE_INVALID_STATS_SEASON = 0x200D,
|
||||||
|
BD_COMMERCE_ERROR = 0x206C,
|
||||||
|
BD_COMMERCE_RESOURCE_NOT_FOUND = 0x206D,
|
||||||
|
BD_COMMERCE_STORAGE_INVALID_PARAMETER = 0x206E,
|
||||||
|
BD_COMMERCE_APPLICATION_INVALID_PARAMETER = 0x206F,
|
||||||
|
BD_COMMERCE_RESOURCE_CONFLICT = 0x2070,
|
||||||
|
BD_COMMERCE_STORAGE_ERROR = 0x2071,
|
||||||
|
BD_COMMERCE_INTEGRITY_ERROR = 0x2072,
|
||||||
|
BD_COMMERCE_MMP_SERVICE_ERROR = 0x2073,
|
||||||
|
BD_COMMERCE_PERMISSION_DENIED = 0x2074,
|
||||||
|
BD_COMMERCE_INSUFFICIENT_FUNDS_ERROR = 0x2075,
|
||||||
|
BD_COMMERCE_UNKNOWN_CURRENCY = 0x2076,
|
||||||
|
BD_COMMERCE_INVALID_RECEIPT = 0x2077,
|
||||||
|
BD_COMMERCE_RECEIPT_USED = 0x2078,
|
||||||
|
BD_COMMERCE_TRANSACTION_ALREADY_APPLIED = 0x2079,
|
||||||
|
BD_COMMERCE_INVALID_CURRENCY_TYPE = 0x207A,
|
||||||
|
BD_CONNECTION_COUNTER_ERROR = 0x20D0,
|
||||||
|
BD_LINKED_ACCOUNTS_INVALID_CONTEXT = 0x2198,
|
||||||
|
BD_LINKED_ACCOUNTS_INVALID_PLATFORM = 0x2199,
|
||||||
|
BD_LINKED_ACCOUNTS_LINKED_ACCOUNTS_FETCH_ERROR = 0x219A,
|
||||||
|
BD_LINKED_ACCOUNTS_INVALID_ACCOUNT = 0x219B,
|
||||||
|
BD_GMSG_INVALID_CATEGORY_ID = 0x27D8,
|
||||||
|
BD_GMSG_CATEGORY_MEMBERSHIPS_LIMIT = 0x27D9,
|
||||||
|
BD_GMSG_NONMEMBER_POST_DISALLOWED = 0x27DA,
|
||||||
|
BD_GMSG_CATEGORY_DISALLOWS_CLIENT_TYPE = 0x27DB,
|
||||||
|
BD_GMSG_PAYLOAD_TOO_BIG = 0x27DC,
|
||||||
|
BD_GMSG_MEMBER_POST_DISALLOWED = 0x27DD,
|
||||||
|
BD_GMSG_OVERLOADED = 0x27DE,
|
||||||
|
BD_GMSG_USER_PERCATEGORY_POST_RATE_EXCEEDED = 0x27DF,
|
||||||
|
BD_GMSG_USER_GLOBAL_POST_RATE_EXCEEDED = 0x27E0,
|
||||||
|
BD_GMSG_GROUP_POST_RATE_EXCEEDED = 0x27E1,
|
||||||
|
BD_MAX_ERROR_CODE = 0x27E2,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "loader/component_loader.hpp"
|
||||||
|
|
||||||
#define WEAK __declspec(selectany)
|
#define WEAK __declspec(selectany)
|
||||||
|
|
||||||
namespace game
|
namespace game
|
||||||
|
@ -1,3 +1,26 @@
|
|||||||
#include <std_include.hpp>
|
#include <std_include.hpp>
|
||||||
|
|
||||||
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language=''\"")
|
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language=''\"")
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
int s_read_arc4random(void*, size_t)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int s_read_getrandom(void*, size_t)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int s_read_urandom(void*, size_t)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int s_read_ltm_rng(void*, size_t)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -82,6 +82,13 @@
|
|||||||
#include <asmjit/core/jitruntime.h>
|
#include <asmjit/core/jitruntime.h>
|
||||||
#include <asmjit/x86/x86assembler.h>
|
#include <asmjit/x86/x86assembler.h>
|
||||||
|
|
||||||
|
#define RAPIDJSON_NOEXCEPT
|
||||||
|
#define RAPIDJSON_ASSERT(cond) if(cond); else throw std::runtime_error("rapidjson assert fail");
|
||||||
|
|
||||||
|
#include <rapidjson/document.h>
|
||||||
|
#include <rapidjson/prettywriter.h>
|
||||||
|
#include <rapidjson/stringbuffer.h>
|
||||||
|
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#pragma warning(disable: 4100)
|
#pragma warning(disable: 4100)
|
||||||
|
|
||||||
|
640
src/common/utils/cryptography.cpp
Normal file
640
src/common/utils/cryptography.cpp
Normal file
@ -0,0 +1,640 @@
|
|||||||
|
#include "string.hpp"
|
||||||
|
#include "cryptography.hpp"
|
||||||
|
#include "nt.hpp"
|
||||||
|
#include "finally.hpp"
|
||||||
|
|
||||||
|
#undef max
|
||||||
|
using namespace std::string_literals;
|
||||||
|
|
||||||
|
/// http://www.opensource.apple.com/source/CommonCrypto/CommonCrypto-55010/Source/libtomcrypt/doc/libTomCryptDoc.pdf
|
||||||
|
|
||||||
|
namespace utils::cryptography
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
struct __
|
||||||
|
{
|
||||||
|
__()
|
||||||
|
{
|
||||||
|
ltc_mp = ltm_desc;
|
||||||
|
|
||||||
|
register_cipher(&aes_desc);
|
||||||
|
register_cipher(&des3_desc);
|
||||||
|
|
||||||
|
register_prng(&sprng_desc);
|
||||||
|
register_prng(&fortuna_desc);
|
||||||
|
register_prng(&yarrow_desc);
|
||||||
|
|
||||||
|
register_hash(&sha1_desc);
|
||||||
|
register_hash(&sha256_desc);
|
||||||
|
register_hash(&sha512_desc);
|
||||||
|
}
|
||||||
|
} ___;
|
||||||
|
|
||||||
|
[[maybe_unused]] const char* cs(const uint8_t* data)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<const char*>(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] char* cs(uint8_t* data)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<char*>(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] const uint8_t* cs(const char* data)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<const uint8_t*>(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] uint8_t* cs(char* data)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<uint8_t*>(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] unsigned long ul(const size_t value)
|
||||||
|
{
|
||||||
|
return static_cast<unsigned long>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
class prng
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
prng(const ltc_prng_descriptor& descriptor, const bool autoseed = true)
|
||||||
|
: state_(std::make_unique<prng_state>())
|
||||||
|
, descriptor_(descriptor)
|
||||||
|
{
|
||||||
|
this->id_ = register_prng(&descriptor);
|
||||||
|
if (this->id_ == -1)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("PRNG "s + this->descriptor_.name + " could not be registered!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (autoseed)
|
||||||
|
{
|
||||||
|
this->auto_seed();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->descriptor_.start(this->state_.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~prng()
|
||||||
|
{
|
||||||
|
this->descriptor_.done(this->state_.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
prng_state* get_state() const
|
||||||
|
{
|
||||||
|
this->descriptor_.ready(this->state_.get());
|
||||||
|
return this->state_.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_id() const
|
||||||
|
{
|
||||||
|
return this->id_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_entropy(const void* data, const size_t length) const
|
||||||
|
{
|
||||||
|
this->descriptor_.add_entropy(static_cast<const uint8_t*>(data), ul(length), this->state_.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void read(void* data, const size_t length) const
|
||||||
|
{
|
||||||
|
this->descriptor_.read(static_cast<unsigned char*>(data), ul(length), this->get_state());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int id_;
|
||||||
|
std::unique_ptr<prng_state> state_;
|
||||||
|
const ltc_prng_descriptor& descriptor_;
|
||||||
|
|
||||||
|
void auto_seed() const
|
||||||
|
{
|
||||||
|
rng_make_prng(128, this->id_, this->state_.get(), nullptr);
|
||||||
|
|
||||||
|
int i[4]; // uninitialized data
|
||||||
|
auto* i_ptr = &i;
|
||||||
|
this->add_entropy(reinterpret_cast<uint8_t*>(&i), sizeof(i));
|
||||||
|
this->add_entropy(reinterpret_cast<uint8_t*>(&i_ptr), sizeof(i_ptr));
|
||||||
|
|
||||||
|
auto t = time(nullptr);
|
||||||
|
this->add_entropy(reinterpret_cast<uint8_t*>(&t), sizeof(t));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const prng prng_(fortuna_desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
ecc::key::key()
|
||||||
|
{
|
||||||
|
ZeroMemory(&this->key_storage_, sizeof(this->key_storage_));
|
||||||
|
}
|
||||||
|
|
||||||
|
ecc::key::~key()
|
||||||
|
{
|
||||||
|
this->free();
|
||||||
|
}
|
||||||
|
|
||||||
|
ecc::key::key(key&& obj) noexcept
|
||||||
|
: key()
|
||||||
|
{
|
||||||
|
this->operator=(std::move(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
ecc::key::key(const key& obj)
|
||||||
|
: key()
|
||||||
|
{
|
||||||
|
this->operator=(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
ecc::key& ecc::key::operator=(key&& obj) noexcept
|
||||||
|
{
|
||||||
|
if (this != &obj)
|
||||||
|
{
|
||||||
|
std::memmove(&this->key_storage_, &obj.key_storage_, sizeof(this->key_storage_));
|
||||||
|
ZeroMemory(&obj.key_storage_, sizeof(obj.key_storage_));
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ecc::key& ecc::key::operator=(const key& obj)
|
||||||
|
{
|
||||||
|
if (this != &obj && obj.is_valid())
|
||||||
|
{
|
||||||
|
this->deserialize(obj.serialize(obj.key_storage_.type));
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ecc::key::is_valid() const
|
||||||
|
{
|
||||||
|
return (!memory::is_set(&this->key_storage_, 0, sizeof(this->key_storage_)));
|
||||||
|
}
|
||||||
|
|
||||||
|
ecc_key& ecc::key::get()
|
||||||
|
{
|
||||||
|
return this->key_storage_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ecc_key& ecc::key::get() const
|
||||||
|
{
|
||||||
|
return this->key_storage_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ecc::key::get_public_key() const
|
||||||
|
{
|
||||||
|
uint8_t buffer[512] = {0};
|
||||||
|
unsigned long length = sizeof(buffer);
|
||||||
|
|
||||||
|
if (ecc_ansi_x963_export(&this->key_storage_, buffer, &length) == CRYPT_OK)
|
||||||
|
{
|
||||||
|
return std::string(cs(buffer), length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void ecc::key::set(const std::string& pub_key_buffer)
|
||||||
|
{
|
||||||
|
this->free();
|
||||||
|
|
||||||
|
if (ecc_ansi_x963_import(cs(pub_key_buffer.data()),
|
||||||
|
ul(pub_key_buffer.size()),
|
||||||
|
&this->key_storage_) != CRYPT_OK)
|
||||||
|
{
|
||||||
|
ZeroMemory(&this->key_storage_, sizeof(this->key_storage_));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ecc::key::deserialize(const std::string& key)
|
||||||
|
{
|
||||||
|
this->free();
|
||||||
|
|
||||||
|
if (ecc_import(cs(key.data()), ul(key.size()),
|
||||||
|
&this->key_storage_) != CRYPT_OK
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ZeroMemory(&this->key_storage_, sizeof(this->key_storage_));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ecc::key::serialize(const int type) const
|
||||||
|
{
|
||||||
|
uint8_t buffer[4096] = {0};
|
||||||
|
unsigned long length = sizeof(buffer);
|
||||||
|
|
||||||
|
if (ecc_export(buffer, &length, type, &this->key_storage_) == CRYPT_OK)
|
||||||
|
{
|
||||||
|
return std::string(cs(buffer), length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void ecc::key::free()
|
||||||
|
{
|
||||||
|
if (this->is_valid())
|
||||||
|
{
|
||||||
|
ecc_free(&this->key_storage_);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZeroMemory(&this->key_storage_, sizeof(this->key_storage_));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ecc::key::operator==(key& key) const
|
||||||
|
{
|
||||||
|
return (this->is_valid() && key.is_valid() && this->serialize(PK_PUBLIC) == key.serialize(PK_PUBLIC));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t ecc::key::get_hash() const
|
||||||
|
{
|
||||||
|
const auto hash = sha1::compute(this->get_public_key());
|
||||||
|
if (hash.size() >= 8)
|
||||||
|
{
|
||||||
|
return *reinterpret_cast<const uint64_t*>(hash.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ecc::key ecc::generate_key(const int bits)
|
||||||
|
{
|
||||||
|
key key;
|
||||||
|
ecc_make_key(prng_.get_state(), prng_.get_id(), bits / 8, &key.get());
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
ecc::key ecc::generate_key(const int bits, const std::string& entropy)
|
||||||
|
{
|
||||||
|
key key{};
|
||||||
|
const prng yarrow(yarrow_desc, false);
|
||||||
|
yarrow.add_entropy(entropy.data(), entropy.size());
|
||||||
|
|
||||||
|
ecc_make_key(yarrow.get_state(), yarrow.get_id(), bits / 8, &key.get());
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ecc::sign_message(const key& key, const std::string& message)
|
||||||
|
{
|
||||||
|
if (!key.is_valid()) return "";
|
||||||
|
|
||||||
|
uint8_t buffer[512];
|
||||||
|
unsigned long length = sizeof(buffer);
|
||||||
|
|
||||||
|
ecc_sign_hash(cs(message.data()), ul(message.size()), buffer, &length, prng_.get_state(), prng_.get_id(),
|
||||||
|
&key.get());
|
||||||
|
|
||||||
|
return std::string(cs(buffer), length);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ecc::verify_message(const key& key, const std::string& message, const std::string& signature)
|
||||||
|
{
|
||||||
|
if (!key.is_valid()) return false;
|
||||||
|
|
||||||
|
auto result = 0;
|
||||||
|
return (ecc_verify_hash(cs(signature.data()),
|
||||||
|
ul(signature.size()),
|
||||||
|
cs(message.data()),
|
||||||
|
ul(message.size()), &result,
|
||||||
|
&key.get()) == CRYPT_OK && result != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ecc::encrypt(const key& key, std::string& data)
|
||||||
|
{
|
||||||
|
std::string out_data{};
|
||||||
|
out_data.resize(std::max(ul(data.size() * 3), ul(0x100)));
|
||||||
|
|
||||||
|
auto out_len = ul(out_data.size());
|
||||||
|
auto crypt = [&]()
|
||||||
|
{
|
||||||
|
return ecc_encrypt_key(cs(data.data()), ul(data.size()), cs(out_data.data()), &out_len,
|
||||||
|
prng_.get_state(), prng_.get_id(), find_hash("sha512"), &key.get());
|
||||||
|
};
|
||||||
|
|
||||||
|
auto res = crypt();
|
||||||
|
|
||||||
|
if (res == CRYPT_BUFFER_OVERFLOW)
|
||||||
|
{
|
||||||
|
out_data.resize(out_len);
|
||||||
|
res = crypt();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res != CRYPT_OK)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_data.resize(out_len);
|
||||||
|
data = std::move(out_data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ecc::decrypt(const key& key, std::string& data)
|
||||||
|
{
|
||||||
|
std::string out_data{};
|
||||||
|
out_data.resize(std::max(ul(data.size() * 3), ul(0x100)));
|
||||||
|
|
||||||
|
auto out_len = ul(out_data.size());
|
||||||
|
auto crypt = [&]()
|
||||||
|
{
|
||||||
|
return ecc_decrypt_key(cs(data.data()), ul(data.size()), cs(out_data.data()), &out_len, &key.get());
|
||||||
|
};
|
||||||
|
|
||||||
|
auto res = crypt();
|
||||||
|
|
||||||
|
if (res == CRYPT_BUFFER_OVERFLOW)
|
||||||
|
{
|
||||||
|
out_data.resize(out_len);
|
||||||
|
res = crypt();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res != CRYPT_OK)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_data.resize(out_len);
|
||||||
|
data = std::move(out_data);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string rsa::encrypt(const std::string& data, const std::string& hash, const std::string& key)
|
||||||
|
{
|
||||||
|
rsa_key new_key;
|
||||||
|
rsa_import(cs(key.data()), ul(key.size()), &new_key);
|
||||||
|
const auto _ = finally([&]()
|
||||||
|
{
|
||||||
|
rsa_free(&new_key);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
std::string out_data{};
|
||||||
|
out_data.resize(std::max(ul(data.size() * 3), ul(0x100)));
|
||||||
|
|
||||||
|
auto out_len = ul(out_data.size());
|
||||||
|
auto crypt = [&]()
|
||||||
|
{
|
||||||
|
return rsa_encrypt_key(cs(data.data()), ul(data.size()), cs(out_data.data()), &out_len, cs(hash.data()),
|
||||||
|
ul(hash.size()), prng_.get_state(), prng_.get_id(), find_hash("sha512"), &new_key);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto res = crypt();
|
||||||
|
|
||||||
|
if (res == CRYPT_BUFFER_OVERFLOW)
|
||||||
|
{
|
||||||
|
out_data.resize(out_len);
|
||||||
|
res = crypt();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res == CRYPT_OK)
|
||||||
|
{
|
||||||
|
out_data.resize(out_len);
|
||||||
|
return out_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string des3::encrypt(const std::string& data, const std::string& iv, const std::string& key)
|
||||||
|
{
|
||||||
|
std::string enc_data;
|
||||||
|
enc_data.resize(data.size());
|
||||||
|
|
||||||
|
symmetric_CBC cbc;
|
||||||
|
const auto des3 = find_cipher("3des");
|
||||||
|
|
||||||
|
cbc_start(des3, cs(iv.data()), cs(key.data()), static_cast<int>(key.size()), 0, &cbc);
|
||||||
|
cbc_encrypt(cs(data.data()), cs(enc_data.data()), ul(data.size()), &cbc);
|
||||||
|
cbc_done(&cbc);
|
||||||
|
|
||||||
|
return enc_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string des3::decrypt(const std::string& data, const std::string& iv, const std::string& key)
|
||||||
|
{
|
||||||
|
std::string dec_data;
|
||||||
|
dec_data.resize(data.size());
|
||||||
|
|
||||||
|
symmetric_CBC cbc;
|
||||||
|
const auto des3 = find_cipher("3des");
|
||||||
|
|
||||||
|
cbc_start(des3, cs(iv.data()), cs(key.data()), static_cast<int>(key.size()), 0, &cbc);
|
||||||
|
cbc_decrypt(cs(data.data()), cs(dec_data.data()), ul(data.size()), &cbc);
|
||||||
|
cbc_done(&cbc);
|
||||||
|
|
||||||
|
return dec_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string tiger::compute(const std::string& data, const bool hex)
|
||||||
|
{
|
||||||
|
return compute(cs(data.data()), data.size(), hex);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string tiger::compute(const uint8_t* data, const size_t length, const bool hex)
|
||||||
|
{
|
||||||
|
uint8_t buffer[24] = {0};
|
||||||
|
|
||||||
|
hash_state state;
|
||||||
|
tiger_init(&state);
|
||||||
|
tiger_process(&state, data, ul(length));
|
||||||
|
tiger_done(&state, buffer);
|
||||||
|
|
||||||
|
std::string hash(cs(buffer), sizeof(buffer));
|
||||||
|
if (!hex) return hash;
|
||||||
|
|
||||||
|
return string::dump_hex(hash, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string aes::encrypt(const std::string& data, const std::string& iv, const std::string& key)
|
||||||
|
{
|
||||||
|
std::string enc_data;
|
||||||
|
enc_data.resize(data.size());
|
||||||
|
|
||||||
|
symmetric_CBC cbc;
|
||||||
|
const auto aes = find_cipher("aes");
|
||||||
|
|
||||||
|
cbc_start(aes, cs(iv.data()), cs(key.data()),
|
||||||
|
static_cast<int>(key.size()), 0, &cbc);
|
||||||
|
cbc_encrypt(cs(data.data()),
|
||||||
|
cs(enc_data.data()),
|
||||||
|
ul(data.size()), &cbc);
|
||||||
|
cbc_done(&cbc);
|
||||||
|
|
||||||
|
return enc_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string aes::decrypt(const std::string& data, const std::string& iv, const std::string& key)
|
||||||
|
{
|
||||||
|
std::string dec_data;
|
||||||
|
dec_data.resize(data.size());
|
||||||
|
|
||||||
|
symmetric_CBC cbc;
|
||||||
|
const auto aes = find_cipher("aes");
|
||||||
|
|
||||||
|
cbc_start(aes, cs(iv.data()), cs(key.data()),
|
||||||
|
static_cast<int>(key.size()), 0, &cbc);
|
||||||
|
cbc_decrypt(cs(data.data()),
|
||||||
|
cs(dec_data.data()),
|
||||||
|
ul(data.size()), &cbc);
|
||||||
|
cbc_done(&cbc);
|
||||||
|
|
||||||
|
return dec_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string hmac_sha1::compute(const std::string& data, const std::string& key)
|
||||||
|
{
|
||||||
|
std::string buffer;
|
||||||
|
buffer.resize(20);
|
||||||
|
|
||||||
|
hmac_state state;
|
||||||
|
hmac_init(&state, find_hash("sha1"), cs(key.data()), ul(key.size()));
|
||||||
|
hmac_process(&state, cs(data.data()), static_cast<int>(data.size()));
|
||||||
|
|
||||||
|
auto out_len = ul(buffer.size());
|
||||||
|
hmac_done(&state, cs(buffer.data()), &out_len);
|
||||||
|
|
||||||
|
buffer.resize(out_len);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string sha1::compute(const std::string& data, const bool hex)
|
||||||
|
{
|
||||||
|
return compute(cs(data.data()), data.size(), hex);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string sha1::compute(const uint8_t* data, const size_t length, const bool hex)
|
||||||
|
{
|
||||||
|
uint8_t buffer[20] = {0};
|
||||||
|
|
||||||
|
hash_state state;
|
||||||
|
sha1_init(&state);
|
||||||
|
sha1_process(&state, data, ul(length));
|
||||||
|
sha1_done(&state, buffer);
|
||||||
|
|
||||||
|
std::string hash(cs(buffer), sizeof(buffer));
|
||||||
|
if (!hex) return hash;
|
||||||
|
|
||||||
|
return string::dump_hex(hash, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string sha256::compute(const std::string& data, const bool hex)
|
||||||
|
{
|
||||||
|
return compute(cs(data.data()), data.size(), hex);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string sha256::compute(const uint8_t* data, const size_t length, const bool hex)
|
||||||
|
{
|
||||||
|
uint8_t buffer[32] = {0};
|
||||||
|
|
||||||
|
hash_state state;
|
||||||
|
sha256_init(&state);
|
||||||
|
sha256_process(&state, data, ul(length));
|
||||||
|
sha256_done(&state, buffer);
|
||||||
|
|
||||||
|
std::string hash(cs(buffer), sizeof(buffer));
|
||||||
|
if (!hex) return hash;
|
||||||
|
|
||||||
|
return string::dump_hex(hash, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string sha512::compute(const std::string& data, const bool hex)
|
||||||
|
{
|
||||||
|
return compute(cs(data.data()), data.size(), hex);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string sha512::compute(const uint8_t* data, const size_t length, const bool hex)
|
||||||
|
{
|
||||||
|
uint8_t buffer[64] = {0};
|
||||||
|
|
||||||
|
hash_state state;
|
||||||
|
sha512_init(&state);
|
||||||
|
sha512_process(&state, data, ul(length));
|
||||||
|
sha512_done(&state, buffer);
|
||||||
|
|
||||||
|
std::string hash(cs(buffer), sizeof(buffer));
|
||||||
|
if (!hex) return hash;
|
||||||
|
|
||||||
|
return string::dump_hex(hash, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string base64::encode(const uint8_t* data, const size_t len)
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
result.resize((len + 2) * 2);
|
||||||
|
|
||||||
|
auto out_len = ul(result.size());
|
||||||
|
if (base64_encode(data, ul(len), result.data(), &out_len) != CRYPT_OK)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
result.resize(out_len);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string base64::encode(const std::string& data)
|
||||||
|
{
|
||||||
|
return base64::encode(cs(data.data()), static_cast<unsigned>(data.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string base64::decode(const std::string& data)
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
result.resize((data.size() + 2) * 2);
|
||||||
|
|
||||||
|
auto out_len = ul(result.size());
|
||||||
|
if (base64_decode(data.data(), ul(data.size()), cs(result.data()), &out_len) != CRYPT_OK)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
result.resize(out_len);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int jenkins_one_at_a_time::compute(const std::string& data)
|
||||||
|
{
|
||||||
|
return compute(data.data(), data.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int jenkins_one_at_a_time::compute(const char* key, const size_t len)
|
||||||
|
{
|
||||||
|
unsigned int hash, i;
|
||||||
|
for (hash = i = 0; i < len; ++i)
|
||||||
|
{
|
||||||
|
hash += key[i];
|
||||||
|
hash += (hash << 10);
|
||||||
|
hash ^= (hash >> 6);
|
||||||
|
}
|
||||||
|
hash += (hash << 3);
|
||||||
|
hash ^= (hash >> 11);
|
||||||
|
hash += (hash << 15);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t random::get_integer()
|
||||||
|
{
|
||||||
|
uint32_t result;
|
||||||
|
random::get_data(&result, sizeof(result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string random::get_challenge()
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
result.resize(sizeof(uint32_t));
|
||||||
|
random::get_data(result.data(), result.size());
|
||||||
|
return string::dump_hex(result, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
void random::get_data(void* data, const size_t size)
|
||||||
|
{
|
||||||
|
prng_.read(data, size);
|
||||||
|
}
|
||||||
|
}
|
118
src/common/utils/cryptography.hpp
Normal file
118
src/common/utils/cryptography.hpp
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <tomcrypt.h>
|
||||||
|
|
||||||
|
namespace utils::cryptography
|
||||||
|
{
|
||||||
|
namespace ecc
|
||||||
|
{
|
||||||
|
class key final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
key();
|
||||||
|
~key();
|
||||||
|
|
||||||
|
key(key&& obj) noexcept;
|
||||||
|
key(const key& obj);
|
||||||
|
key& operator=(key&& obj) noexcept;
|
||||||
|
key& operator=(const key& obj);
|
||||||
|
|
||||||
|
bool is_valid() const;
|
||||||
|
|
||||||
|
ecc_key& get();
|
||||||
|
const ecc_key& get() const;
|
||||||
|
|
||||||
|
std::string get_public_key() const;
|
||||||
|
|
||||||
|
void set(const std::string& pub_key_buffer);
|
||||||
|
|
||||||
|
void deserialize(const std::string& key);
|
||||||
|
|
||||||
|
std::string serialize(int type = PK_PRIVATE) const;
|
||||||
|
|
||||||
|
void free();
|
||||||
|
|
||||||
|
bool operator==(key& key) const;
|
||||||
|
|
||||||
|
uint64_t get_hash() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ecc_key key_storage_{};
|
||||||
|
};
|
||||||
|
|
||||||
|
key generate_key(int bits);
|
||||||
|
key generate_key(int bits, const std::string& entropy);
|
||||||
|
std::string sign_message(const key& key, const std::string& message);
|
||||||
|
bool verify_message(const key& key, const std::string& message, const std::string& signature);
|
||||||
|
|
||||||
|
bool encrypt(const key& key, std::string& data);
|
||||||
|
bool decrypt(const key& key, std::string& data);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace rsa
|
||||||
|
{
|
||||||
|
std::string encrypt(const std::string& data, const std::string& hash, const std::string& key);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace des3
|
||||||
|
{
|
||||||
|
std::string encrypt(const std::string& data, const std::string& iv, const std::string& key);
|
||||||
|
std::string decrypt(const std::string& data, const std::string& iv, const std::string& key);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace tiger
|
||||||
|
{
|
||||||
|
std::string compute(const std::string& data, bool hex = false);
|
||||||
|
std::string compute(const uint8_t* data, size_t length, bool hex = false);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace aes
|
||||||
|
{
|
||||||
|
std::string encrypt(const std::string& data, const std::string& iv, const std::string& key);
|
||||||
|
std::string decrypt(const std::string& data, const std::string& iv, const std::string& key);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace hmac_sha1
|
||||||
|
{
|
||||||
|
std::string compute(const std::string& data, const std::string& key);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace sha1
|
||||||
|
{
|
||||||
|
std::string compute(const std::string& data, bool hex = false);
|
||||||
|
std::string compute(const uint8_t* data, size_t length, bool hex = false);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace sha256
|
||||||
|
{
|
||||||
|
std::string compute(const std::string& data, bool hex = false);
|
||||||
|
std::string compute(const uint8_t* data, size_t length, bool hex = false);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace sha512
|
||||||
|
{
|
||||||
|
std::string compute(const std::string& data, bool hex = false);
|
||||||
|
std::string compute(const uint8_t* data, size_t length, bool hex = false);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace base64
|
||||||
|
{
|
||||||
|
std::string encode(const uint8_t* data, size_t len);
|
||||||
|
std::string encode(const std::string& data);
|
||||||
|
std::string decode(const std::string& data);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace jenkins_one_at_a_time
|
||||||
|
{
|
||||||
|
unsigned int compute(const std::string& data);
|
||||||
|
unsigned int compute(const char* key, size_t len);
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace random
|
||||||
|
{
|
||||||
|
uint32_t get_integer();
|
||||||
|
std::string get_challenge();
|
||||||
|
void get_data(void* data, size_t size);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user