Fix steam proxy
This commit is contained in:
parent
c399eed444
commit
25a9919498
@ -1,426 +1,426 @@
|
||||
#include <std_include.hpp>
|
||||
#include "dw.hpp"
|
||||
#include "utils/hook.hpp"
|
||||
#include "game/game.hpp"
|
||||
#include "utils/nt.hpp"
|
||||
#include "utils/cryptography.hpp"
|
||||
|
||||
#include "game/demonware/services/bdLSGHello.hpp" // 7
|
||||
#include "game/demonware/services/bdStorage.hpp" // 10
|
||||
#include "game/demonware/services/bdDediAuth.hpp" // 12
|
||||
#include "game/demonware/services/bdTitleUtilities.hpp" // 12
|
||||
#include "game/demonware/services/bdDML.hpp" // 27
|
||||
#include "game/demonware/services/bdDediRSAAuth.hpp" // 26
|
||||
#include "game/demonware/services/bdSteamAuth.hpp" // 28
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
int __stdcall send_to(const SOCKET s, const char* buf, const int len, const int flags, const sockaddr* to,
|
||||
const int tolen)
|
||||
{
|
||||
if (tolen == sizeof(sockaddr_in))
|
||||
{
|
||||
const auto in_addr = reinterpret_cast<const sockaddr_in*>(to);
|
||||
const auto server = dw::find_stun_server_by_address(in_addr->sin_addr.s_addr);
|
||||
if (server) return server->send(s, buf, len, to, tolen);
|
||||
}
|
||||
|
||||
return sendto(s, buf, len, flags, to, tolen);
|
||||
}
|
||||
|
||||
int __stdcall recv_from(const SOCKET s, char* buf, const int len, const int flags, sockaddr* from, int* fromlen)
|
||||
{
|
||||
auto res = dw::recv_datagam_packet(s, buf, len, from, fromlen);
|
||||
if (res != 0) return res;
|
||||
|
||||
res = recvfrom(s, buf, len, flags, from, fromlen);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int __stdcall send(const SOCKET s, const char* buf, const int len, const int flags)
|
||||
{
|
||||
auto server = dw::find_server_by_socket(s);
|
||||
if (server) return server->send(buf, len);
|
||||
|
||||
return ::send(s, buf, len, flags);
|
||||
}
|
||||
|
||||
int __stdcall recv(const SOCKET s, char* buf, const int len, const int flags)
|
||||
{
|
||||
auto server = dw::find_server_by_socket(s);
|
||||
if (server)
|
||||
{
|
||||
const auto blocking = dw::is_blocking_socket(s, TCP_BLOCKING);
|
||||
|
||||
int result;
|
||||
do
|
||||
{
|
||||
result = server->recv(buf, len);
|
||||
if (blocking && result < 0) std::this_thread::sleep_for(1ms);
|
||||
}
|
||||
while (blocking && result < 0);
|
||||
|
||||
if (!blocking && result < 0)
|
||||
{
|
||||
WSASetLastError(WSAEWOULDBLOCK);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return ::recv(s, buf, len, flags);
|
||||
}
|
||||
|
||||
int __stdcall connect(const SOCKET s, const sockaddr* addr, const int len)
|
||||
{
|
||||
if (len == sizeof(sockaddr_in))
|
||||
{
|
||||
const auto* in_addr = reinterpret_cast<const sockaddr_in*>(addr);
|
||||
if (dw::link_socket(s, in_addr->sin_addr.s_addr)) return 0;
|
||||
}
|
||||
|
||||
return ::connect(s, addr, len);
|
||||
}
|
||||
|
||||
int __stdcall close_socket(const SOCKET s)
|
||||
{
|
||||
dw::remove_blocking_socket(s);
|
||||
dw::unlink_socket(s);
|
||||
return closesocket(s);
|
||||
}
|
||||
|
||||
int __stdcall ioctl_socket(const SOCKET s, const long cmd, u_long* argp)
|
||||
{
|
||||
if (static_cast<unsigned long>(cmd) == (FIONBIO))
|
||||
{
|
||||
dw::set_blocking_socket(s, *argp == 0);
|
||||
}
|
||||
|
||||
return ioctlsocket(s, cmd, argp);
|
||||
}
|
||||
|
||||
hostent* __stdcall get_host_by_name(char* name)
|
||||
{
|
||||
static std::mutex mutex;
|
||||
std::lock_guard<std::mutex> _(mutex);
|
||||
|
||||
unsigned long addr = 0;
|
||||
const auto server = dw::find_server_by_name(name);
|
||||
if (server) addr = server->get_address();
|
||||
|
||||
const auto stun_server = dw::find_stun_server_by_name(name);
|
||||
if (stun_server) addr = stun_server->get_address();
|
||||
|
||||
if (server || stun_server)
|
||||
{
|
||||
static in_addr address;
|
||||
address.s_addr = addr;
|
||||
|
||||
static in_addr* addr_list[2];
|
||||
addr_list[0] = &address;
|
||||
addr_list[1] = nullptr;
|
||||
|
||||
static hostent host;
|
||||
host.h_name = 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;
|
||||
}
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4996)
|
||||
|
||||
// ReSharper disable once CppDeprecatedEntity
|
||||
return gethostbyname(name);
|
||||
|
||||
#pragma warning(pop)
|
||||
}
|
||||
|
||||
bool register_hook(const std::string& process, void* stub)
|
||||
{
|
||||
const utils::nt::module main;
|
||||
|
||||
auto result = false;
|
||||
result = result || utils::hook::iat(main, "wsock32.dll", process, stub);
|
||||
result = result || utils::hook::iat(main, "WS2_32.dll", process, stub);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
bool dw::terminate_;
|
||||
std::thread dw::message_thread_;
|
||||
std::recursive_mutex dw::server_mutex_;
|
||||
std::map<SOCKET, bool> dw::blocking_sockets_;
|
||||
std::map<SOCKET, std::shared_ptr<service_server>> dw::socket_links_;
|
||||
std::map<unsigned long, std::shared_ptr<service_server>> dw::servers_;
|
||||
std::map<unsigned long, std::shared_ptr<stun_server>> dw::stun_servers_;
|
||||
std::map<SOCKET, std::queue<std::pair<std::string, std::string>>> dw::datagram_packets_;
|
||||
|
||||
uint8_t dw::encryption_key_[24];
|
||||
uint8_t dw::decryption_key_[24];
|
||||
|
||||
std::shared_ptr<service_server> dw::find_server_by_name(const std::string& name)
|
||||
{
|
||||
std::lock_guard _(server_mutex_);
|
||||
return find_server_by_address(utils::cryptography::jenkins_one_at_a_time::compute(name));
|
||||
}
|
||||
|
||||
std::shared_ptr<service_server> dw::find_server_by_address(const unsigned long address)
|
||||
{
|
||||
std::lock_guard _(server_mutex_);
|
||||
|
||||
const auto server = servers_.find(address);
|
||||
if (server != servers_.end())
|
||||
{
|
||||
return server->second;
|
||||
}
|
||||
|
||||
return std::shared_ptr<service_server>();
|
||||
}
|
||||
|
||||
std::shared_ptr<stun_server> dw::find_stun_server_by_name(const std::string& name)
|
||||
{
|
||||
std::lock_guard _(server_mutex_);
|
||||
return find_stun_server_by_address(utils::cryptography::jenkins_one_at_a_time::compute(name));
|
||||
}
|
||||
|
||||
std::shared_ptr<stun_server> dw::find_stun_server_by_address(const unsigned long address)
|
||||
{
|
||||
std::lock_guard _(server_mutex_);
|
||||
|
||||
const auto server = stun_servers_.find(address);
|
||||
if (server != stun_servers_.end())
|
||||
{
|
||||
return server->second;
|
||||
}
|
||||
|
||||
return std::shared_ptr<stun_server>();
|
||||
}
|
||||
|
||||
std::shared_ptr<service_server> dw::find_server_by_socket(const SOCKET s)
|
||||
{
|
||||
std::lock_guard _(server_mutex_);
|
||||
|
||||
const auto server = socket_links_.find(s);
|
||||
if (server != socket_links_.end())
|
||||
{
|
||||
return server->second;
|
||||
}
|
||||
|
||||
return std::shared_ptr<service_server>();
|
||||
}
|
||||
|
||||
bool dw::link_socket(const SOCKET s, const unsigned long address)
|
||||
{
|
||||
std::lock_guard _(server_mutex_);
|
||||
|
||||
const auto server = find_server_by_address(address);
|
||||
if (!server) return false;
|
||||
|
||||
socket_links_[s] = server;
|
||||
return true;
|
||||
}
|
||||
|
||||
void dw::unlink_socket(const SOCKET sock)
|
||||
{
|
||||
std::lock_guard _(server_mutex_);
|
||||
|
||||
const auto server = socket_links_.find(sock);
|
||||
if (server != socket_links_.end())
|
||||
{
|
||||
socket_links_.erase(server);
|
||||
}
|
||||
|
||||
const auto dgram_packets = datagram_packets_.find(sock);
|
||||
if (dgram_packets != datagram_packets_.end())
|
||||
{
|
||||
datagram_packets_.erase(dgram_packets);
|
||||
}
|
||||
}
|
||||
|
||||
int dw::recv_datagam_packet(const SOCKET s, char* buf, const int len, sockaddr* from, int* fromlen)
|
||||
{
|
||||
std::unique_lock lock(server_mutex_);
|
||||
|
||||
auto queue = datagram_packets_.find(s);
|
||||
if (queue != datagram_packets_.end())
|
||||
{
|
||||
const bool blocking = is_blocking_socket(s, UDP_BLOCKING);
|
||||
|
||||
lock.unlock();
|
||||
while (blocking && queue->second.empty())
|
||||
{
|
||||
std::this_thread::sleep_for(1ms);
|
||||
}
|
||||
lock.lock();
|
||||
|
||||
if (!queue->second.empty())
|
||||
{
|
||||
auto packet = queue->second.front();
|
||||
queue->second.pop();
|
||||
|
||||
*fromlen = INT(packet.first.size());
|
||||
std::memcpy(from, packet.first.data(), *fromlen);
|
||||
|
||||
const int size = std::min(len, INT(packet.second.size()));
|
||||
std::memcpy(buf, packet.second.data(), size);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
WSASetLastError(WSAEWOULDBLOCK);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dw::send_datagram_packet(const SOCKET s, const std::string& data, const sockaddr* to, const int tolen)
|
||||
{
|
||||
std::lock_guard _(server_mutex_);
|
||||
datagram_packets_[s].push({std::string(LPSTR(to), tolen), data});
|
||||
}
|
||||
|
||||
bool dw::is_blocking_socket(const SOCKET s, const bool def)
|
||||
{
|
||||
std::lock_guard _(server_mutex_);
|
||||
|
||||
if (blocking_sockets_.find(s) != blocking_sockets_.end())
|
||||
{
|
||||
return blocking_sockets_[s];
|
||||
}
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
void dw::remove_blocking_socket(const SOCKET s)
|
||||
{
|
||||
std::lock_guard _(server_mutex_);
|
||||
|
||||
const auto entry = blocking_sockets_.find(s);
|
||||
if (entry != blocking_sockets_.end())
|
||||
{
|
||||
blocking_sockets_.erase(entry);
|
||||
}
|
||||
}
|
||||
|
||||
void dw::set_blocking_socket(const SOCKET s, const bool blocking)
|
||||
{
|
||||
std::lock_guard _(server_mutex_);
|
||||
blocking_sockets_[s] = blocking;
|
||||
}
|
||||
|
||||
uint8_t* dw::get_key(const bool encrypt)
|
||||
{
|
||||
return encrypt ? encryption_key_ : decryption_key_;
|
||||
}
|
||||
|
||||
void dw::set_key(const bool encrypt, uint8_t* key)
|
||||
{
|
||||
static_assert(sizeof encryption_key_ == sizeof decryption_key_);
|
||||
std::memcpy(encrypt ? encryption_key_ : decryption_key_, key, sizeof encryption_key_);
|
||||
}
|
||||
|
||||
void dw::server_thread()
|
||||
{
|
||||
terminate_ = false;
|
||||
while (!terminate_)
|
||||
{
|
||||
std::unique_lock lock(server_mutex_);
|
||||
|
||||
for (auto& server : servers_)
|
||||
{
|
||||
server.second->run_frame();
|
||||
}
|
||||
|
||||
lock.unlock();
|
||||
|
||||
std::this_thread::sleep_for(50ms);
|
||||
}
|
||||
}
|
||||
|
||||
void dw::pre_destroy()
|
||||
{
|
||||
std::lock_guard _(server_mutex_);
|
||||
|
||||
terminate_ = true;
|
||||
if (message_thread_.joinable())
|
||||
{
|
||||
message_thread_.join();
|
||||
}
|
||||
|
||||
servers_.clear();
|
||||
stun_servers_.clear();
|
||||
socket_links_.clear();
|
||||
blocking_sockets_.clear();
|
||||
datagram_packets_.clear();
|
||||
}
|
||||
|
||||
dw::dw()
|
||||
{
|
||||
register_stun_server("mw3-stun.us.demonware.net");
|
||||
register_stun_server("mw3-stun.eu.demonware.net");
|
||||
register_stun_server("stun.jp.demonware.net");
|
||||
register_stun_server("stun.au.demonware.net");
|
||||
register_stun_server("stun.eu.demonware.net");
|
||||
register_stun_server("stun.us.demonware.net");
|
||||
|
||||
auto lsg_server = register_server("mw3-pc-lobby.prod.demonware.net");
|
||||
auto auth_server = register_server("mw3-pc-auth.prod.demonware.net");
|
||||
|
||||
auth_server->register_service<bdDediAuth>();
|
||||
auth_server->register_service<bdSteamAuth>();
|
||||
auth_server->register_service<bdDediRSAAuth>();
|
||||
|
||||
lsg_server->register_service<bdLSGHello>();
|
||||
lsg_server->register_service<bdStorage>();
|
||||
lsg_server->register_service<bdTitleUtilities>();
|
||||
lsg_server->register_service<bdDML>();
|
||||
/*lsg_server->register_service<bdMatchMaking>();
|
||||
lsg_server->register_service<bdBandwidthTest>();
|
||||
lsg_server->register_service<bdGroup>();
|
||||
lsg_server->register_service<bdAnticheat>();
|
||||
lsg_server->register_service<bdRelayService>();*/
|
||||
}
|
||||
|
||||
void dw::post_load()
|
||||
{
|
||||
message_thread_ = std::thread(server_thread);
|
||||
|
||||
io::register_hook("send", io::send);
|
||||
io::register_hook("recv", io::recv);
|
||||
io::register_hook("sendto", io::send_to);
|
||||
io::register_hook("recvfrom", io::recv_from);
|
||||
io::register_hook("connect", io::connect);
|
||||
io::register_hook("closesocket", io::close_socket);
|
||||
io::register_hook("ioctlsocket", io::ioctl_socket);
|
||||
io::register_hook("gethostbyname", io::get_host_by_name);
|
||||
|
||||
utils::hook(SELECT_VALUE(0x6F40A0, 0x6EE1C0, 0x611310), bd_logger_stub, HOOK_JUMP).install()->quick();
|
||||
}
|
||||
|
||||
void dw::bd_logger_stub(int /*type*/, const char* const /*channelName*/, const char*, const char* const /*file*/,
|
||||
const char* const function, const unsigned int /*line*/, const char* const msg, ...)
|
||||
{
|
||||
char buffer[2048];
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
|
||||
vsnprintf_s(buffer, sizeof(buffer), _TRUNCATE, msg, ap);
|
||||
printf("%s: %s\n", function, buffer);
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
REGISTER_MODULE(dw)
|
||||
}
|
||||
#include <std_include.hpp>
|
||||
#include "dw.hpp"
|
||||
#include "utils/hook.hpp"
|
||||
#include "game/game.hpp"
|
||||
#include "utils/nt.hpp"
|
||||
#include "utils/cryptography.hpp"
|
||||
|
||||
#include "game/demonware/services/bdLSGHello.hpp" // 7
|
||||
#include "game/demonware/services/bdStorage.hpp" // 10
|
||||
#include "game/demonware/services/bdDediAuth.hpp" // 12
|
||||
#include "game/demonware/services/bdTitleUtilities.hpp" // 12
|
||||
#include "game/demonware/services/bdDML.hpp" // 27
|
||||
#include "game/demonware/services/bdDediRSAAuth.hpp" // 26
|
||||
#include "game/demonware/services/bdSteamAuth.hpp" // 28
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
int __stdcall send_to(const SOCKET s, const char* buf, const int len, const int flags, const sockaddr* to,
|
||||
const int tolen)
|
||||
{
|
||||
if (tolen == sizeof(sockaddr_in))
|
||||
{
|
||||
const auto in_addr = reinterpret_cast<const sockaddr_in*>(to);
|
||||
const auto server = dw::find_stun_server_by_address(in_addr->sin_addr.s_addr);
|
||||
if (server) return server->send(s, buf, len, to, tolen);
|
||||
}
|
||||
|
||||
return sendto(s, buf, len, flags, to, tolen);
|
||||
}
|
||||
|
||||
int __stdcall recv_from(const SOCKET s, char* buf, const int len, const int flags, sockaddr* from, int* fromlen)
|
||||
{
|
||||
auto res = dw::recv_datagam_packet(s, buf, len, from, fromlen);
|
||||
if (res != 0) return res;
|
||||
|
||||
res = recvfrom(s, buf, len, flags, from, fromlen);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int __stdcall send(const SOCKET s, const char* buf, const int len, const int flags)
|
||||
{
|
||||
auto server = dw::find_server_by_socket(s);
|
||||
if (server) return server->send(buf, len);
|
||||
|
||||
return ::send(s, buf, len, flags);
|
||||
}
|
||||
|
||||
int __stdcall recv(const SOCKET s, char* buf, const int len, const int flags)
|
||||
{
|
||||
auto server = dw::find_server_by_socket(s);
|
||||
if (server)
|
||||
{
|
||||
const auto blocking = dw::is_blocking_socket(s, TCP_BLOCKING);
|
||||
|
||||
int result;
|
||||
do
|
||||
{
|
||||
result = server->recv(buf, len);
|
||||
if (blocking && result < 0) std::this_thread::sleep_for(1ms);
|
||||
}
|
||||
while (blocking && result < 0);
|
||||
|
||||
if (!blocking && result < 0)
|
||||
{
|
||||
WSASetLastError(WSAEWOULDBLOCK);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return ::recv(s, buf, len, flags);
|
||||
}
|
||||
|
||||
int __stdcall connect(const SOCKET s, const sockaddr* addr, const int len)
|
||||
{
|
||||
if (len == sizeof(sockaddr_in))
|
||||
{
|
||||
const auto* in_addr = reinterpret_cast<const sockaddr_in*>(addr);
|
||||
if (dw::link_socket(s, in_addr->sin_addr.s_addr)) return 0;
|
||||
}
|
||||
|
||||
return ::connect(s, addr, len);
|
||||
}
|
||||
|
||||
int __stdcall close_socket(const SOCKET s)
|
||||
{
|
||||
dw::remove_blocking_socket(s);
|
||||
dw::unlink_socket(s);
|
||||
return closesocket(s);
|
||||
}
|
||||
|
||||
int __stdcall ioctl_socket(const SOCKET s, const long cmd, u_long* argp)
|
||||
{
|
||||
if (static_cast<unsigned long>(cmd) == (FIONBIO))
|
||||
{
|
||||
dw::set_blocking_socket(s, *argp == 0);
|
||||
}
|
||||
|
||||
return ioctlsocket(s, cmd, argp);
|
||||
}
|
||||
|
||||
hostent* __stdcall get_host_by_name(char* name)
|
||||
{
|
||||
static std::mutex mutex;
|
||||
std::lock_guard<std::mutex> _(mutex);
|
||||
|
||||
unsigned long addr = 0;
|
||||
const auto server = dw::find_server_by_name(name);
|
||||
if (server) addr = server->get_address();
|
||||
|
||||
const auto stun_server = dw::find_stun_server_by_name(name);
|
||||
if (stun_server) addr = stun_server->get_address();
|
||||
|
||||
if (server || stun_server)
|
||||
{
|
||||
static in_addr address;
|
||||
address.s_addr = addr;
|
||||
|
||||
static in_addr* addr_list[2];
|
||||
addr_list[0] = &address;
|
||||
addr_list[1] = nullptr;
|
||||
|
||||
static hostent host;
|
||||
host.h_name = 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;
|
||||
}
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4996)
|
||||
|
||||
// ReSharper disable once CppDeprecatedEntity
|
||||
return gethostbyname(name);
|
||||
|
||||
#pragma warning(pop)
|
||||
}
|
||||
|
||||
bool register_hook(const std::string& process, void* stub)
|
||||
{
|
||||
const utils::nt::module main;
|
||||
|
||||
auto result = false;
|
||||
result = result || utils::hook::iat(main, "wsock32.dll", process, stub);
|
||||
result = result || utils::hook::iat(main, "WS2_32.dll", process, stub);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
bool dw::terminate_;
|
||||
std::thread dw::message_thread_;
|
||||
std::recursive_mutex dw::server_mutex_;
|
||||
std::map<SOCKET, bool> dw::blocking_sockets_;
|
||||
std::map<SOCKET, std::shared_ptr<service_server>> dw::socket_links_;
|
||||
std::map<unsigned long, std::shared_ptr<service_server>> dw::servers_;
|
||||
std::map<unsigned long, std::shared_ptr<stun_server>> dw::stun_servers_;
|
||||
std::map<SOCKET, std::queue<std::pair<std::string, std::string>>> dw::datagram_packets_;
|
||||
|
||||
uint8_t dw::encryption_key_[24];
|
||||
uint8_t dw::decryption_key_[24];
|
||||
|
||||
std::shared_ptr<service_server> dw::find_server_by_name(const std::string& name)
|
||||
{
|
||||
std::lock_guard _(server_mutex_);
|
||||
return find_server_by_address(utils::cryptography::jenkins_one_at_a_time::compute(name));
|
||||
}
|
||||
|
||||
std::shared_ptr<service_server> dw::find_server_by_address(const unsigned long address)
|
||||
{
|
||||
std::lock_guard _(server_mutex_);
|
||||
|
||||
const auto server = servers_.find(address);
|
||||
if (server != servers_.end())
|
||||
{
|
||||
return server->second;
|
||||
}
|
||||
|
||||
return std::shared_ptr<service_server>();
|
||||
}
|
||||
|
||||
std::shared_ptr<stun_server> dw::find_stun_server_by_name(const std::string& name)
|
||||
{
|
||||
std::lock_guard _(server_mutex_);
|
||||
return find_stun_server_by_address(utils::cryptography::jenkins_one_at_a_time::compute(name));
|
||||
}
|
||||
|
||||
std::shared_ptr<stun_server> dw::find_stun_server_by_address(const unsigned long address)
|
||||
{
|
||||
std::lock_guard _(server_mutex_);
|
||||
|
||||
const auto server = stun_servers_.find(address);
|
||||
if (server != stun_servers_.end())
|
||||
{
|
||||
return server->second;
|
||||
}
|
||||
|
||||
return std::shared_ptr<stun_server>();
|
||||
}
|
||||
|
||||
std::shared_ptr<service_server> dw::find_server_by_socket(const SOCKET s)
|
||||
{
|
||||
std::lock_guard _(server_mutex_);
|
||||
|
||||
const auto server = socket_links_.find(s);
|
||||
if (server != socket_links_.end())
|
||||
{
|
||||
return server->second;
|
||||
}
|
||||
|
||||
return std::shared_ptr<service_server>();
|
||||
}
|
||||
|
||||
bool dw::link_socket(const SOCKET s, const unsigned long address)
|
||||
{
|
||||
std::lock_guard _(server_mutex_);
|
||||
|
||||
const auto server = find_server_by_address(address);
|
||||
if (!server) return false;
|
||||
|
||||
socket_links_[s] = server;
|
||||
return true;
|
||||
}
|
||||
|
||||
void dw::unlink_socket(const SOCKET sock)
|
||||
{
|
||||
std::lock_guard _(server_mutex_);
|
||||
|
||||
const auto server = socket_links_.find(sock);
|
||||
if (server != socket_links_.end())
|
||||
{
|
||||
socket_links_.erase(server);
|
||||
}
|
||||
|
||||
const auto dgram_packets = datagram_packets_.find(sock);
|
||||
if (dgram_packets != datagram_packets_.end())
|
||||
{
|
||||
datagram_packets_.erase(dgram_packets);
|
||||
}
|
||||
}
|
||||
|
||||
int dw::recv_datagam_packet(const SOCKET s, char* buf, const int len, sockaddr* from, int* fromlen)
|
||||
{
|
||||
std::unique_lock lock(server_mutex_);
|
||||
|
||||
auto queue = datagram_packets_.find(s);
|
||||
if (queue != datagram_packets_.end())
|
||||
{
|
||||
const bool blocking = is_blocking_socket(s, UDP_BLOCKING);
|
||||
|
||||
lock.unlock();
|
||||
while (blocking && queue->second.empty())
|
||||
{
|
||||
std::this_thread::sleep_for(1ms);
|
||||
}
|
||||
lock.lock();
|
||||
|
||||
if (!queue->second.empty())
|
||||
{
|
||||
auto packet = queue->second.front();
|
||||
queue->second.pop();
|
||||
|
||||
*fromlen = INT(packet.first.size());
|
||||
std::memcpy(from, packet.first.data(), *fromlen);
|
||||
|
||||
const int size = std::min(len, INT(packet.second.size()));
|
||||
std::memcpy(buf, packet.second.data(), size);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
WSASetLastError(WSAEWOULDBLOCK);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dw::send_datagram_packet(const SOCKET s, const std::string& data, const sockaddr* to, const int tolen)
|
||||
{
|
||||
std::lock_guard _(server_mutex_);
|
||||
datagram_packets_[s].push({std::string(LPSTR(to), tolen), data});
|
||||
}
|
||||
|
||||
bool dw::is_blocking_socket(const SOCKET s, const bool def)
|
||||
{
|
||||
std::lock_guard _(server_mutex_);
|
||||
|
||||
if (blocking_sockets_.find(s) != blocking_sockets_.end())
|
||||
{
|
||||
return blocking_sockets_[s];
|
||||
}
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
void dw::remove_blocking_socket(const SOCKET s)
|
||||
{
|
||||
std::lock_guard _(server_mutex_);
|
||||
|
||||
const auto entry = blocking_sockets_.find(s);
|
||||
if (entry != blocking_sockets_.end())
|
||||
{
|
||||
blocking_sockets_.erase(entry);
|
||||
}
|
||||
}
|
||||
|
||||
void dw::set_blocking_socket(const SOCKET s, const bool blocking)
|
||||
{
|
||||
std::lock_guard _(server_mutex_);
|
||||
blocking_sockets_[s] = blocking;
|
||||
}
|
||||
|
||||
uint8_t* dw::get_key(const bool encrypt)
|
||||
{
|
||||
return encrypt ? encryption_key_ : decryption_key_;
|
||||
}
|
||||
|
||||
void dw::set_key(const bool encrypt, uint8_t* key)
|
||||
{
|
||||
static_assert(sizeof encryption_key_ == sizeof decryption_key_);
|
||||
std::memcpy(encrypt ? encryption_key_ : decryption_key_, key, sizeof encryption_key_);
|
||||
}
|
||||
|
||||
void dw::server_thread()
|
||||
{
|
||||
terminate_ = false;
|
||||
while (!terminate_)
|
||||
{
|
||||
std::unique_lock lock(server_mutex_);
|
||||
|
||||
for (auto& server : servers_)
|
||||
{
|
||||
server.second->run_frame();
|
||||
}
|
||||
|
||||
lock.unlock();
|
||||
|
||||
std::this_thread::sleep_for(50ms);
|
||||
}
|
||||
}
|
||||
|
||||
void dw::pre_destroy()
|
||||
{
|
||||
std::lock_guard _(server_mutex_);
|
||||
|
||||
terminate_ = true;
|
||||
if (message_thread_.joinable())
|
||||
{
|
||||
message_thread_.join();
|
||||
}
|
||||
|
||||
servers_.clear();
|
||||
stun_servers_.clear();
|
||||
socket_links_.clear();
|
||||
blocking_sockets_.clear();
|
||||
datagram_packets_.clear();
|
||||
}
|
||||
|
||||
dw::dw()
|
||||
{
|
||||
register_stun_server("mw3-stun.us.demonware.net");
|
||||
register_stun_server("mw3-stun.eu.demonware.net");
|
||||
register_stun_server("stun.jp.demonware.net");
|
||||
register_stun_server("stun.au.demonware.net");
|
||||
register_stun_server("stun.eu.demonware.net");
|
||||
register_stun_server("stun.us.demonware.net");
|
||||
|
||||
auto lsg_server = register_server("mw3-pc-lobby.prod.demonware.net");
|
||||
auto auth_server = register_server("mw3-pc-auth.prod.demonware.net");
|
||||
|
||||
auth_server->register_service<bdDediAuth>();
|
||||
auth_server->register_service<bdSteamAuth>();
|
||||
auth_server->register_service<bdDediRSAAuth>();
|
||||
|
||||
lsg_server->register_service<bdLSGHello>();
|
||||
lsg_server->register_service<bdStorage>();
|
||||
lsg_server->register_service<bdTitleUtilities>();
|
||||
lsg_server->register_service<bdDML>();
|
||||
/*lsg_server->register_service<bdMatchMaking>();
|
||||
lsg_server->register_service<bdBandwidthTest>();
|
||||
lsg_server->register_service<bdGroup>();
|
||||
lsg_server->register_service<bdAnticheat>();
|
||||
lsg_server->register_service<bdRelayService>();*/
|
||||
}
|
||||
|
||||
void dw::post_load()
|
||||
{
|
||||
message_thread_ = std::thread(server_thread);
|
||||
|
||||
io::register_hook("send", io::send);
|
||||
io::register_hook("recv", io::recv);
|
||||
io::register_hook("sendto", io::send_to);
|
||||
io::register_hook("recvfrom", io::recv_from);
|
||||
io::register_hook("connect", io::connect);
|
||||
io::register_hook("closesocket", io::close_socket);
|
||||
io::register_hook("ioctlsocket", io::ioctl_socket);
|
||||
io::register_hook("gethostbyname", io::get_host_by_name);
|
||||
|
||||
//utils::hook(SELECT_VALUE(0x6F40A0, 0x6EE1C0, 0x611310), bd_logger_stub, HOOK_JUMP).install()->quick();
|
||||
}
|
||||
|
||||
void dw::bd_logger_stub(int /*type*/, const char* const /*channelName*/, const char*, const char* const /*file*/,
|
||||
const char* const function, const unsigned int /*line*/, const char* const msg, ...)
|
||||
{
|
||||
char buffer[2048];
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, msg);
|
||||
|
||||
vsnprintf_s(buffer, sizeof(buffer), _TRUNCATE, msg, ap);
|
||||
printf("%s: %s\n", function, buffer);
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
REGISTER_MODULE(dw)
|
||||
}
|
||||
|
@ -12,18 +12,17 @@ class steam_proxy final : public module
|
||||
public:
|
||||
void post_start() override
|
||||
{
|
||||
if (game::is_dedi()) return;
|
||||
|
||||
this->run_mod();
|
||||
this->load_client();
|
||||
|
||||
this->clean_up_on_error();
|
||||
}
|
||||
|
||||
void post_load() override
|
||||
{
|
||||
if (game::is_dedi()) return;
|
||||
|
||||
this->load_client();
|
||||
|
||||
this->clean_up_on_error();
|
||||
|
||||
try
|
||||
{
|
||||
if (game::is_sp())
|
||||
@ -116,10 +115,8 @@ private:
|
||||
|
||||
this->steam_pipe_ = this->steam_client_module_.invoke<void*>("Steam_CreateSteamPipe");
|
||||
this->global_user_ = this->steam_client_module_.invoke<void*>("Steam_ConnectToGlobalUser", this->steam_pipe_);
|
||||
this->client_user_ = this->client_engine_.invoke<void*>(8, this->steam_pipe_, this->global_user_,
|
||||
"CLIENTUSER_INTERFACE_VERSION001"); // GetIClientUser
|
||||
this->client_utils_ = this->client_engine_.invoke<void*>(13, this->steam_pipe_,
|
||||
"CLIENTUTILS_INTERFACE_VERSION001"); // GetIClientUtils
|
||||
this->client_user_ = this->client_engine_.invoke<void*>(8, this->steam_pipe_, this->global_user_); // GetIClientUser
|
||||
this->client_utils_ = this->client_engine_.invoke<void*>(13, this->steam_pipe_); // GetIClientUtils
|
||||
}
|
||||
|
||||
void start_mod(const std::string& title, size_t app_id)
|
||||
@ -175,4 +172,4 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
//REGISTER_MODULE(steam_proxy)
|
||||
REGISTER_MODULE(steam_proxy)
|
||||
|
Loading…
Reference in New Issue
Block a user