mirror of
https://github.com/XLabsProject/s1x-client.git
synced 2023-08-02 15:02:12 +02:00
Merge pull request #22 from XLabsProject/feature/demonware
Merge current demonware refactoring progress
This commit is contained in:
commit
ac709d54af
@ -3,6 +3,7 @@
|
||||
#include "loader/component_loader.hpp"
|
||||
#include "game/game.hpp"
|
||||
#include "scheduler.hpp"
|
||||
#include "command.hpp"
|
||||
|
||||
#include <utils/thread.hpp>
|
||||
#include <utils/flags.hpp>
|
||||
@ -32,9 +33,9 @@ namespace console
|
||||
{
|
||||
hide_console();
|
||||
|
||||
_pipe(this->handles_, 1024, _O_TEXT);
|
||||
_dup2(this->handles_[1], 1);
|
||||
_dup2(this->handles_[1], 2);
|
||||
(void)_pipe(this->handles_, 1024, _O_TEXT);
|
||||
(void)_dup2(this->handles_[1], 1);
|
||||
(void)_dup2(this->handles_[1], 2);
|
||||
|
||||
//setvbuf(stdout, nullptr, _IONBF, 0);
|
||||
//setvbuf(stderr, nullptr, _IONBF, 0);
|
||||
@ -45,6 +46,7 @@ namespace console
|
||||
scheduler::loop([this]()
|
||||
{
|
||||
this->log_messages();
|
||||
this->event_frame();
|
||||
}, scheduler::pipeline::main);
|
||||
|
||||
this->console_runner_ = utils::thread::create_named_thread("Console IO", [this]
|
||||
@ -71,7 +73,19 @@ namespace console
|
||||
|
||||
void post_unpack() override
|
||||
{
|
||||
this->initialize();
|
||||
game::Sys_ShowConsole();
|
||||
|
||||
if (!game::environment::is_dedi())
|
||||
{
|
||||
// Hide that shit
|
||||
ShowWindow(console::get_window(), SW_MINIMIZE);
|
||||
}
|
||||
|
||||
// Async console is not ready yet :/
|
||||
//this->initialize();
|
||||
|
||||
std::lock_guard<std::mutex> _(this->mutex_);
|
||||
this->console_initialized_ = true;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -84,15 +98,27 @@ namespace console
|
||||
|
||||
int handles_[2]{};
|
||||
|
||||
void event_frame()
|
||||
{
|
||||
MSG msg;
|
||||
while (PeekMessageA(&msg, nullptr, NULL, NULL, PM_REMOVE))
|
||||
{
|
||||
if (msg.message == WM_QUIT)
|
||||
{
|
||||
command::execute("quit", false);
|
||||
break;
|
||||
}
|
||||
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
void initialize()
|
||||
{
|
||||
utils::thread::create_named_thread("Console", [this]()
|
||||
{
|
||||
if (game::environment::is_dedi())
|
||||
{
|
||||
game::Sys_ShowConsole();
|
||||
}
|
||||
else if (!utils::flags::has_flag("noconsole"))
|
||||
if (game::environment::is_dedi() || !utils::flags::has_flag("noconsole"))
|
||||
{
|
||||
game::Sys_ShowConsole();
|
||||
}
|
||||
@ -195,7 +221,7 @@ namespace console
|
||||
|
||||
SetWindowPos(get_window(), nullptr, rect.left, rect.top, width, height, 0);
|
||||
|
||||
const auto logo_window = *reinterpret_cast<HWND*>(SELECT_VALUE(0x14A9F6080, 0x14B5B94D0));
|
||||
auto* const logo_window = *reinterpret_cast<HWND*>(SELECT_VALUE(0x14A9F6080, 0x14B5B94D0));
|
||||
SetWindowPos(logo_window, nullptr, 5, 5, width - 25, 60, 0);
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ namespace demonware
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> $(server_mutex);
|
||||
|
||||
servers[server->address()] = server;
|
||||
servers[server->get_address()] = server;
|
||||
}
|
||||
|
||||
auto find_server_by_address(const std::uint32_t address) -> server_ptr
|
||||
@ -176,7 +176,7 @@ namespace demonware
|
||||
if (server)
|
||||
{
|
||||
static thread_local in_addr address;
|
||||
address.s_addr = server->address();
|
||||
address.s_addr = server->get_address();
|
||||
|
||||
static thread_local in_addr* addr_list[2];
|
||||
addr_list[0] = &address;
|
||||
@ -223,7 +223,8 @@ namespace demonware
|
||||
|
||||
if (server)
|
||||
{
|
||||
return server->recv(buf, len);
|
||||
server->handle_input(buf, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
return send(s, buf, len, flags);
|
||||
@ -237,7 +238,7 @@ namespace demonware
|
||||
{
|
||||
if (server->pending_data())
|
||||
{
|
||||
return server->send(buf, len);
|
||||
return static_cast<int>(server->handle_output(buf, len));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -251,21 +252,21 @@ namespace demonware
|
||||
|
||||
int sendto_stub(SOCKET s, const char* buf, int len, int flags, const struct sockaddr* to, int tolen)
|
||||
{
|
||||
const auto* in_addr = reinterpret_cast<const sockaddr_in*>(to);
|
||||
/*const auto* in_addr = reinterpret_cast<const sockaddr_in*>(to);
|
||||
auto server = find_server_by_address(in_addr->sin_addr.s_addr);
|
||||
|
||||
if (server)
|
||||
{
|
||||
socket_link(s, in_addr->sin_addr.s_addr);
|
||||
return server->recv(buf, len);
|
||||
}
|
||||
}*/
|
||||
|
||||
return sendto(s, buf, len, flags, to, tolen);
|
||||
}
|
||||
|
||||
int recvfrom_stub(SOCKET s, char* buf, int len, int flags, struct sockaddr* from, int* fromlen)
|
||||
{
|
||||
auto server = find_server_by_socket(s);
|
||||
/*auto server = find_server_by_socket(s);
|
||||
|
||||
if (server)
|
||||
{
|
||||
@ -283,7 +284,7 @@ namespace demonware
|
||||
WSASetLastError(WSAEWOULDBLOCK);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
return recvfrom(s, buf, len, flags, from, fromlen);
|
||||
}
|
||||
|
@ -2,10 +2,16 @@
|
||||
|
||||
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;
|
||||
};
|
||||
@ -22,7 +28,7 @@ namespace demonware
|
||||
{
|
||||
}
|
||||
|
||||
virtual std::string data() override
|
||||
std::string data() override
|
||||
{
|
||||
return this->buffer_;
|
||||
}
|
||||
@ -30,16 +36,16 @@ namespace demonware
|
||||
|
||||
class typed_reply : public raw_reply
|
||||
{
|
||||
private:
|
||||
uint8_t type_;
|
||||
|
||||
protected:
|
||||
uint8_t type() const { return this->type_; }
|
||||
|
||||
public:
|
||||
typed_reply(uint8_t _type) : type_(_type)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
uint8_t type() const { return this->type_; }
|
||||
|
||||
private:
|
||||
uint8_t type_;
|
||||
};
|
||||
|
||||
class encrypted_reply final : public typed_reply
|
||||
@ -55,7 +61,7 @@ namespace demonware
|
||||
this->buffer_.append(bbuffer->get_buffer());
|
||||
}
|
||||
|
||||
virtual std::string data() override;
|
||||
std::string data() override;
|
||||
};
|
||||
|
||||
class unencrypted_reply final : public typed_reply
|
||||
@ -71,17 +77,13 @@ namespace demonware
|
||||
this->buffer_.append(bbuffer->get_buffer());
|
||||
}
|
||||
|
||||
virtual std::string data() override;
|
||||
std::string data() override;
|
||||
};
|
||||
|
||||
class service_server;
|
||||
|
||||
class remote_reply final
|
||||
{
|
||||
private:
|
||||
uint8_t type_;
|
||||
service_server* server_;
|
||||
|
||||
public:
|
||||
remote_reply(service_server* server, uint8_t _type) : type_(_type), server_(server)
|
||||
{
|
||||
@ -91,16 +93,14 @@ namespace demonware
|
||||
void send(byte_buffer* buffer, const bool encrypted);
|
||||
|
||||
uint8_t type() const { return this->type_; }
|
||||
|
||||
private:
|
||||
uint8_t type_;
|
||||
service_server* server_;
|
||||
};
|
||||
|
||||
class service_reply final
|
||||
{
|
||||
private:
|
||||
uint8_t type_;
|
||||
uint32_t error_;
|
||||
remote_reply reply_;
|
||||
std::vector<std::shared_ptr<bdTaskResult>> objects_;
|
||||
|
||||
public:
|
||||
service_reply(service_server* _server, uint8_t _type, uint32_t _error)
|
||||
: type_(_type), error_(_error), reply_(_server, 1)
|
||||
@ -150,6 +150,11 @@ namespace demonware
|
||||
{
|
||||
this->add(std::shared_ptr<bdTaskResult>(object));
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
uint8_t type_;
|
||||
uint32_t error_;
|
||||
remote_reply reply_;
|
||||
std::vector<std::shared_ptr<bdTaskResult>> objects_;
|
||||
};
|
||||
}
|
||||
|
@ -4,6 +4,9 @@
|
||||
class base_server
|
||||
{
|
||||
public:
|
||||
using stream_queue = std::queue<char>;
|
||||
using data_queue = std::queue<std::string>;
|
||||
|
||||
base_server(std::string name)
|
||||
: name_(std::move(name))
|
||||
{
|
||||
@ -27,14 +30,8 @@ public:
|
||||
return this->address_;
|
||||
}
|
||||
|
||||
virtual void frame()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool pending_data()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
virtual void frame() = 0;
|
||||
virtual bool pending_data() = 0;
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
|
@ -10,32 +10,89 @@ class tcp_server : public base_server
|
||||
public:
|
||||
using base_server::base_server;
|
||||
|
||||
int handle_input(const char* buf, int size)
|
||||
void handle_input(const char* buf, size_t size)
|
||||
{
|
||||
return 0;
|
||||
in_queue_.access([&](data_queue& queue)
|
||||
{
|
||||
queue.emplace(buf, size);
|
||||
});
|
||||
}
|
||||
|
||||
int handle_output(char* buf, int size)
|
||||
size_t handle_output(char* buf, size_t size)
|
||||
{
|
||||
return 0;
|
||||
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 pending_data() override
|
||||
{
|
||||
return !this->out_queue_.get_raw().empty();
|
||||
}
|
||||
|
||||
void frame() override
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void handle(const std::string& data) = 0;
|
||||
void send(const std::string&)
|
||||
|
||||
void send(const std::string& data)
|
||||
{
|
||||
|
||||
out_queue_.access([&](stream_queue& queue)
|
||||
{
|
||||
for (const auto& val : data)
|
||||
{
|
||||
queue.push(val);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
using stream_queue = std::queue<char>;
|
||||
using data_queue = std::queue<std::string>;
|
||||
|
||||
utils::concurrency::container<data_queue> in_queue_;
|
||||
utils::concurrency::container<stream_queue> out_queue_;
|
||||
|
||||
void frame() override
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -0,0 +1,95 @@
|
||||
#pragma once
|
||||
|
||||
#include "base_server.hpp"
|
||||
|
||||
#include <queue>
|
||||
#include <utils/concurrency.hpp>
|
||||
|
||||
class udp_server : public base_server
|
||||
{
|
||||
public:
|
||||
using base_server::base_server;
|
||||
|
||||
void handle_input(const char* buf, size_t size)
|
||||
{
|
||||
in_queue_.access([&](data_queue& queue)
|
||||
{
|
||||
queue.emplace(buf, size);
|
||||
});
|
||||
}
|
||||
|
||||
size_t handle_output(char* buf, size_t size)
|
||||
{
|
||||
if (out_queue_.get_raw().empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return out_queue_.access<size_t>([&](data_queue& queue) -> size_t
|
||||
{
|
||||
if (queue.empty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto data = std::move(queue.front());
|
||||
queue.pop();
|
||||
|
||||
const auto copy_size = std::min(size, data.size());
|
||||
std::memcpy(buf, data.data(), copy_size);
|
||||
|
||||
return copy_size;
|
||||
});
|
||||
}
|
||||
|
||||
bool pending_data() override
|
||||
{
|
||||
return !this->out_queue_.get_raw().empty();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void handle(const std::string& data) = 0;
|
||||
|
||||
void send(const std::string& data)
|
||||
{
|
||||
out_queue_.access([&](data_queue& queue)
|
||||
{
|
||||
queue.push(data);
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
utils::concurrency::container<data_queue> in_queue_;
|
||||
utils::concurrency::container<data_queue> out_queue_;
|
||||
|
||||
void frame() override
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
};
|
@ -1,70 +1,15 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../demonware.hpp"
|
||||
#include <utils/json.hpp>
|
||||
using json = nlohmann::json;
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
int server_auth3::recv(const char* buf, const int len)
|
||||
{
|
||||
if (len <= 0) return -1;
|
||||
std::lock_guard<std::recursive_mutex> _(this->mutex_);
|
||||
this->incoming_queue_.push(std::string(buf, len));
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int server_auth3::send(char* buf, int len)
|
||||
{
|
||||
if (len > 0 && !this->outgoing_queue_.empty())
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> _(this->mutex_);
|
||||
|
||||
len = std::min(len, static_cast<int>(this->outgoing_queue_.size()));
|
||||
for (auto i = 0; i < len; ++i)
|
||||
{
|
||||
buf[i] = this->outgoing_queue_.front();
|
||||
this->outgoing_queue_.pop();
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
|
||||
void server_auth3::send_reply(reply* data)
|
||||
{
|
||||
if (!data) return;
|
||||
|
||||
std::lock_guard _(this->mutex_);
|
||||
|
||||
const auto buffer = data->data();
|
||||
for (auto& byte : buffer)
|
||||
{
|
||||
this->outgoing_queue_.push(byte);
|
||||
}
|
||||
this->send(data->data());
|
||||
}
|
||||
|
||||
void server_auth3::frame()
|
||||
{
|
||||
if (!this->incoming_queue_.empty())
|
||||
{
|
||||
std::lock_guard _(this->mutex_);
|
||||
const auto packet = this->incoming_queue_.front();
|
||||
this->incoming_queue_.pop();
|
||||
|
||||
this->dispatch(packet);
|
||||
}
|
||||
}
|
||||
|
||||
bool server_auth3::pending_data()
|
||||
{
|
||||
std::lock_guard _(this->mutex_);
|
||||
return !this->outgoing_queue_.empty();
|
||||
}
|
||||
|
||||
void server_auth3::dispatch(const std::string& packet)
|
||||
void server_auth3::handle(const std::string& packet)
|
||||
{
|
||||
if (packet.starts_with("POST /auth/"))
|
||||
{
|
||||
@ -73,101 +18,113 @@ namespace demonware
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
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("extra_data") && j["extra_data"].IsString())
|
||||
{
|
||||
unsigned int title_id = 0;
|
||||
unsigned int iv_seed = 0;
|
||||
std::string identity = "";
|
||||
std::string token = "";
|
||||
rapidjson::Document extra_data;
|
||||
auto& ed = j["extra_data"];
|
||||
extra_data.Parse(ed.GetString(), ed.GetStringLength());
|
||||
|
||||
json j = json::parse(packet);
|
||||
|
||||
if (j.contains("title_id") && j["title_id"].is_string())
|
||||
title_id = std::stoul(j["title_id"].get<std::string>());
|
||||
|
||||
if (j.contains("iv_seed") && j["iv_seed"].is_string())
|
||||
iv_seed = std::stoul(j["iv_seed"].get<std::string>());
|
||||
|
||||
if (j.contains("extra_data") && j["extra_data"].is_string())
|
||||
if (extra_data.HasMember("token") && extra_data["token"].IsString())
|
||||
{
|
||||
json extra_data = json::parse(j["extra_data"].get<std::string>());
|
||||
|
||||
if (extra_data.contains("token") && extra_data["token"].is_string())
|
||||
{
|
||||
std::string token_b64 = extra_data["token"].get<std::string>();
|
||||
token = utils::cryptography::base64::decode(token_b64);
|
||||
}
|
||||
auto& token_field = extra_data["token"];
|
||||
std::string token_b64(token_field.GetString(), token_field.GetStringLength());
|
||||
token = utils::cryptography::base64::decode(token_b64);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("[demonware]: [auth]: authenticating user %s\n", std::string(&token.data()[64]).data());
|
||||
#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_t 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));
|
||||
std::string ticket_enc = utils::cryptography::des3::encrypt(
|
||||
std::string(reinterpret_cast<char*>(&ticket), sizeof(ticket)), iv, auth_key);
|
||||
std::string ticket_b64 = utils::cryptography::base64::encode((const unsigned char*)ticket_enc.c_str(), 128);
|
||||
|
||||
// server_ticket
|
||||
uint8_t auth_data[128];
|
||||
std::memset(&auth_data, 0, sizeof auth_data);
|
||||
std::memcpy(auth_data, session_key.data(), 24);
|
||||
std::string auth_data_b64 = utils::cryptography::base64::encode(auth_data, 128);
|
||||
|
||||
demonware::set_session_key(session_key);
|
||||
|
||||
// header time
|
||||
char date[64];
|
||||
time_t now = time(0);
|
||||
tm gmtm;
|
||||
gmtime_s(&gmtm, &now);
|
||||
strftime(date, 64, "%a, %d %b %G %T", &gmtm);
|
||||
|
||||
// json content
|
||||
std::string content;
|
||||
content.append("{\"auth_task\": \"29\",");
|
||||
content.append("\"code\": \"700\",");
|
||||
content.append(utils::string::va("\"iv_seed\": \"%u\",", iv_seed));
|
||||
content.append(utils::string::va("\"client_ticket\": \"%s\",", ticket_b64.c_str()));
|
||||
content.append(utils::string::va("\"server_ticket\": \"%s\",", auth_data_b64.c_str()));
|
||||
content.append("\"client_id\": \"\",");
|
||||
content.append("\"account_type\": \"steam\",");
|
||||
content.append("\"crossplay_enabled\": false,");
|
||||
content.append("\"loginqueue_eanbled\": false,");
|
||||
content.append("\"lsg_endpoint\": null,");
|
||||
content.append("}");
|
||||
|
||||
// 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", content.size()));
|
||||
result.append(content);
|
||||
|
||||
raw_reply reply(result);
|
||||
this->send_reply(&reply);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("[demonware]: [auth]: user successfully authenticated.\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("[demonware]: [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_t 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));
|
||||
std::string ticket_enc = utils::cryptography::des3::encrypt(
|
||||
std::string(reinterpret_cast<char*>(&ticket), sizeof(ticket)), iv, auth_key);
|
||||
std::string 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);
|
||||
std::string auth_data_b64 = utils::cryptography::base64::encode(auth_data, 128);
|
||||
|
||||
demonware::set_session_key(session_key);
|
||||
|
||||
// header time
|
||||
char date[64];
|
||||
time_t 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 DEBUG
|
||||
printf("[demonware]: [auth]: user successfully authenticated.\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -1,47 +1,8 @@
|
||||
#pragma once
|
||||
#include <utils/cryptography.hpp>
|
||||
#include "new/tcp_server.hpp"
|
||||
|
||||
class server_base
|
||||
{
|
||||
std::string name_;
|
||||
std::uint32_t address_ = 0;
|
||||
|
||||
public:
|
||||
server_base(std::string name) : name_(std::move(name))
|
||||
{
|
||||
this->address_ = utils::cryptography::jenkins_one_at_a_time::compute(this->name_);
|
||||
}
|
||||
|
||||
virtual ~server_base() = default;
|
||||
|
||||
std::uint32_t address() const
|
||||
{
|
||||
return this->address_;
|
||||
}
|
||||
|
||||
virtual void frame()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
virtual int recv(const char* buf, int size)
|
||||
{
|
||||
printf("PACKET\n%s\n", std::string(buf, size).data());
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual int send(char* buf, int size)
|
||||
{
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
|
||||
virtual bool pending_data()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
using server_ptr = std::shared_ptr<server_base>;
|
||||
using server_ptr = std::shared_ptr<tcp_server>;
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
@ -62,24 +23,13 @@ namespace demonware
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
class server_auth3 : public server_base
|
||||
class server_auth3 : public tcp_server
|
||||
{
|
||||
public:
|
||||
explicit server_auth3(std::string name) : server_base(name)
|
||||
{
|
||||
};
|
||||
|
||||
void frame() override;
|
||||
int recv(const char* buf, int len) override;
|
||||
int send(char* buf, int len) override;
|
||||
bool pending_data() override;
|
||||
using tcp_server::tcp_server;
|
||||
|
||||
private:
|
||||
std::recursive_mutex mutex_;
|
||||
std::queue<char> outgoing_queue_;
|
||||
std::queue<std::string> incoming_queue_;
|
||||
|
||||
void send_reply(reply* data);
|
||||
void dispatch(const std::string& packet);
|
||||
void handle(const std::string& packet) override;
|
||||
};
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../demonware.hpp"
|
||||
#include "new/tcp_server.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
|
||||
server_lobby::server_lobby(std::string name) : server_base(std::move(name))
|
||||
server_lobby::server_lobby(std::string name) : tcp_server(std::move(name))
|
||||
{
|
||||
this->register_service<bdAnticheat>();
|
||||
this->register_service<bdBandwidthTest>();
|
||||
@ -26,67 +26,13 @@ namespace demonware
|
||||
this->register_service<bdMarketing>();
|
||||
};
|
||||
|
||||
void server_lobby::frame()
|
||||
{
|
||||
if (!this->incoming_queue_.empty())
|
||||
{
|
||||
std::lock_guard _(this->mutex_);
|
||||
const auto packet = this->incoming_queue_.front();
|
||||
this->incoming_queue_.pop();
|
||||
|
||||
this->dispatch(packet);
|
||||
}
|
||||
}
|
||||
|
||||
int server_lobby::recv(const char* buf, int len)
|
||||
{
|
||||
if (len <= 3) return -1;
|
||||
std::lock_guard<std::recursive_mutex> _(this->mutex_);
|
||||
|
||||
this->incoming_queue_.push(std::string(buf, len));
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int server_lobby::send(char* buf, int len)
|
||||
{
|
||||
if (len > 0 && !this->outgoing_queue_.empty())
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> _(this->mutex_);
|
||||
|
||||
len = std::min(len, static_cast<int>(this->outgoing_queue_.size()));
|
||||
for (auto i = 0; i < len; ++i)
|
||||
{
|
||||
buf[i] = this->outgoing_queue_.front();
|
||||
this->outgoing_queue_.pop();
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
|
||||
bool server_lobby::pending_data()
|
||||
{
|
||||
std::lock_guard _(this->mutex_);
|
||||
return !this->outgoing_queue_.empty();
|
||||
}
|
||||
|
||||
void server_lobby::send_reply(reply* data)
|
||||
{
|
||||
if (!data) return;
|
||||
|
||||
std::lock_guard _(this->mutex_);
|
||||
|
||||
const auto buffer = data->data();
|
||||
for (auto& byte : buffer)
|
||||
{
|
||||
this->outgoing_queue_.push(byte);
|
||||
}
|
||||
this->send(data->data());
|
||||
}
|
||||
|
||||
void server_lobby::dispatch(const std::string& packet)
|
||||
void server_lobby::handle(const std::string& packet)
|
||||
{
|
||||
byte_buffer buffer(packet);
|
||||
buffer.set_use_data_types(false);
|
||||
@ -200,7 +146,7 @@ namespace demonware
|
||||
}
|
||||
}
|
||||
|
||||
void server_lobby::call_service(std::uint8_t id, const std::string& data)
|
||||
void server_lobby::call_service(const std::uint8_t id, const std::string& data)
|
||||
{
|
||||
const auto& it = this->services_.find(id);
|
||||
|
||||
|
@ -2,15 +2,10 @@
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class server_lobby : public server_base, service_server
|
||||
class server_lobby : public tcp_server, service_server
|
||||
{
|
||||
public:
|
||||
explicit server_lobby(std::string name);
|
||||
|
||||
void frame() override;
|
||||
int recv(const char* buf, int len) override;
|
||||
int send(char* buf, int len) override;
|
||||
bool pending_data() override;
|
||||
server_lobby(std::string name);
|
||||
|
||||
template <typename T>
|
||||
void register_service()
|
||||
@ -26,12 +21,9 @@ namespace demonware
|
||||
void send_reply(reply* data) override;
|
||||
|
||||
private:
|
||||
std::recursive_mutex mutex_;
|
||||
std::queue<char> outgoing_queue_;
|
||||
std::queue<std::string> incoming_queue_;
|
||||
std::map<std::uint8_t, std::unique_ptr<service>> services_;
|
||||
std::unordered_map<std::uint8_t, std::unique_ptr<service>> services_;
|
||||
|
||||
void dispatch(const std::string& packet);
|
||||
void call_service(std::uint8_t type, const std::string& data);
|
||||
void handle(const std::string& packet) override;
|
||||
void call_service(const std::uint8_t id, const std::string& data);
|
||||
};
|
||||
}
|
||||
|
@ -1,65 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "new/udp_server.hpp"
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
class server_stun : public server_base
|
||||
class server_stun : public udp_server
|
||||
{
|
||||
public:
|
||||
using server_base::server_base;
|
||||
|
||||
int recv(const char* buf, int len) override
|
||||
{
|
||||
if (len <= 0) return -1;
|
||||
std::lock_guard<std::recursive_mutex> _(this->mutex_);
|
||||
this->incoming_queue_.push(std::string(buf, len));
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int send(char* buf, int len) override
|
||||
{
|
||||
if (len > 0 && !this->outgoing_queue_.empty())
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> _(this->mutex_);
|
||||
|
||||
auto& data = this->outgoing_queue_.front();
|
||||
len = std::min(len, static_cast<int>(data.size()));
|
||||
for (auto i = 0; i < len; ++i)
|
||||
{
|
||||
buf[i] = data[i];
|
||||
}
|
||||
|
||||
this->outgoing_queue_.pop();
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
return SOCKET_ERROR;
|
||||
}
|
||||
|
||||
bool pending_data() override
|
||||
{
|
||||
return !outgoing_queue_.empty();
|
||||
}
|
||||
|
||||
void frame() override
|
||||
{
|
||||
if (!this->incoming_queue_.empty())
|
||||
{
|
||||
std::lock_guard _(this->mutex_);
|
||||
const auto packet = this->incoming_queue_.front();
|
||||
this->incoming_queue_.pop();
|
||||
|
||||
this->dispatch(packet);
|
||||
}
|
||||
}
|
||||
using udp_server::udp_server;
|
||||
|
||||
private:
|
||||
std::recursive_mutex mutex_;
|
||||
std::queue<std::string> outgoing_queue_;
|
||||
std::queue<std::string> incoming_queue_;
|
||||
|
||||
void dispatch(const std::string& packet)
|
||||
void handle(const std::string& packet) override
|
||||
{
|
||||
uint8_t type, version, padding;
|
||||
|
||||
@ -94,7 +45,7 @@ namespace demonware
|
||||
buffer.write_uint32(ip); // external ip
|
||||
buffer.write_uint16(3074); // port
|
||||
|
||||
send(buffer.get_buffer().data(), static_cast<int>(buffer.get_buffer().size()));
|
||||
this->send(buffer.get_buffer());
|
||||
}
|
||||
|
||||
void nat_discovery()
|
||||
@ -108,10 +59,10 @@ namespace demonware
|
||||
buffer.write_byte(0); // version
|
||||
buffer.write_uint32(ip); // external ip
|
||||
buffer.write_uint16(3074); // port
|
||||
buffer.write_uint32(this->address()); // server ip
|
||||
buffer.write_uint32(this->get_address()); // server ip
|
||||
buffer.write_uint16(3074); // server port
|
||||
|
||||
send(buffer.get_buffer().data(), static_cast<int>(buffer.get_buffer().size()));
|
||||
this->send(buffer.get_buffer());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
DECLSPEC_NORETURN void WINAPI exit_hook(const int code)
|
||||
{
|
||||
component_loader::pre_destroy();
|
||||
_exit(code); // Temporarily
|
||||
exit(code);
|
||||
}
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user