Skip to content

Commit

Permalink
Further sharding support.
Browse files Browse the repository at this point in the history
  • Loading branch information
TLeonardUK committed Dec 23, 2023
1 parent 3dfcda7 commit 8147322
Show file tree
Hide file tree
Showing 19 changed files with 185 additions and 33 deletions.
2 changes: 2 additions & 0 deletions Source/Injector/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ SET(SOURCES
Hooks/Hook.cpp
Hooks/ReplaceServerAddressHook.h
Hooks/ReplaceServerAddressHook.cpp
Hooks/ReplaceServerPortHook.h
Hooks/ReplaceServerPortHook.cpp
Hooks/ChangeSaveGameFilenameHook.h
Hooks/ChangeSaveGameFilenameHook.cpp
)
Expand Down
1 change: 1 addition & 0 deletions Source/Injector/Config/RuntimeConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ bool RuntimeConfig::Serialize(nlohmann::json& Json, bool Loading)
SERIALIZE_VAR(ServerHostname);
SERIALIZE_VAR(ServerPublicKey);
SERIALIZE_VAR(EnableSeperateSaveFiles);
SERIALIZE_VAR(ServerPort);

return true;
}
Expand Down
3 changes: 3 additions & 0 deletions Source/Injector/Config/RuntimeConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ class RuntimeConfig
// Public key of server being joined.
std::string ServerPublicKey = "";

// Login port to connect to on server.
int ServerPort = 50050;

// If we should use seperate saves from the retail ones.
bool EnableSeperateSaveFiles = true;

Expand Down
2 changes: 1 addition & 1 deletion Source/Injector/Hooks/ReplaceServerAddressHook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ namespace
std::string str(first_c, distance);
if (str.find(k_retail_key) == 0)
{
Log("Retail server address requested, patching.");
Log("Retail server address requested, patching to custom server address.");

const RuntimeConfig& Config = Injector::Instance().GetConfig();

Expand Down
63 changes: 63 additions & 0 deletions Source/Injector/Hooks/ReplaceServerPortHook.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Dark Souls 3 - Open Server
* Copyright (C) 2021 Tim Leonard
*
* This program is free software; licensed under the MIT license.
* You should have received a copy of the license along with this program.
* If not, see <https://opensource.org/licenses/MIT>.
*/

#include "Injector/Hooks/ReplaceServerPortHook.h"
#include "Injector/Injector/Injector.h"
#include "Shared/Core/Utils/Logging.h"
#include "Shared/Core/Utils/Strings.h"
#include "ThirdParty/detours/src/detours.h"

#include <vector>
#include <iterator>
#include <WinSock2.h>

namespace
{
using connect_p = int(WSAAPI*)(SOCKET s, const sockaddr* name, int namelen);
connect_p s_original_connect;

int WSAAPI ConnectHook(SOCKET s, const sockaddr* name, int namelen)
{
sockaddr_in* addr = (sockaddr_in*)name;

if (addr->sin_port == htons(50050))
{
const RuntimeConfig& Config = Injector::Instance().GetConfig();

Log("Attempt to connect to login server, patching port to '%i'.", Config.ServerPort);
addr->sin_port = ntohs(Config.ServerPort);
}

return s_original_connect(s, name, namelen);
}
};

bool ReplaceServerPortHook::Install(Injector& injector)
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());

s_original_connect = reinterpret_cast<connect_p>(connect);
DetourAttach(&(PVOID&)s_original_connect, ConnectHook);

DetourTransactionCommit();

return true;
}

void ReplaceServerPortHook::Uninstall()
{

}

const char* ReplaceServerPortHook::GetName()
{
return "Replace Server Port";
}

22 changes: 22 additions & 0 deletions Source/Injector/Hooks/ReplaceServerPortHook.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Dark Souls 3 - Open Server
* Copyright (C) 2021 Tim Leonard
*
* This program is free software; licensed under the MIT license.
* You should have received a copy of the license along with this program.
* If not, see <https://opensource.org/licenses/MIT>.
*/

#pragma once

#include "Injector/Hooks/Hook.h"

// Hooks the connection call and swaps out the port number for the one we care about.
class ReplaceServerPortHook : public Hook
{
public:
virtual bool Install(Injector& injector) override;
virtual void Uninstall() override;
virtual const char* GetName() override;

};
3 changes: 3 additions & 0 deletions Source/Injector/Injector/Injector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "Shared/Core/Utils/Strings.h"

#include "Injector/Hooks/ReplaceServerAddressHook.h"
#include "Injector/Hooks/ReplaceServerPortHook.h"
#include "Injector/Hooks/ChangeSaveGameFilenameHook.h"

#include <thread>
Expand Down Expand Up @@ -91,6 +92,7 @@ bool Injector::Init()

Log("Server Name: %s", Config.ServerName.c_str());
Log("Server Hostname: %s", Config.ServerHostname.c_str());
Log("Server Port: %i", Config.ServerPort);
Log("");

ModuleRegion = GetModuleBaseRegion("DarkSoulsIII.exe");
Expand All @@ -106,6 +108,7 @@ bool Injector::Init()

// Add hooks we need to use based on configuration.
Hooks.push_back(std::make_unique<ReplaceServerAddressHook>());
Hooks.push_back(std::make_unique<ReplaceServerPortHook>());
if (Config.EnableSeperateSaveFiles)
{
Hooks.push_back(std::make_unique<ChangeSaveGameFilenameHook>());
Expand Down
1 change: 1 addition & 0 deletions Source/Loader/Config/InjectionConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public class InjectionConfig
public string ServerName { get; set; }
public string ServerHostname { get; set; }
public string ServerPublicKey { get; set; }
public int ServerPort { get; set; }
public bool EnableSeperateSaveFiles { get; set; }

public string ToJson()
Expand Down
1 change: 1 addition & 0 deletions Source/Loader/Config/ServerConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public class ServerConfig
public string Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public int Port { get; set; }
public string Hostname { get; set; }
public string PrivateHostname { get; set; }
public string PublicKey { get; set; }
Expand Down
1 change: 1 addition & 0 deletions Source/Loader/Forms/CreateServerDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ private void ProcessResult(WebUiApi.CreateServerResponse Result)
{
CreateServerTask = null;
DialogResult = DialogResult.OK;
Visible = false;
Close();

if (string.IsNullOrEmpty(Result.webUsername) ||
Expand Down
13 changes: 7 additions & 6 deletions Source/Loader/Forms/MainForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ private void ValidateUI()
bool HasSelectedManualServer = false;
if (ImportedServerListView.SelectedIndices.Count > 0)
{
HasSelectedManualServer = GetConfigFromHostname((ImportedServerListView.SelectedItems[0].Tag as ServerConfig).Hostname).ManualImport;
HasSelectedManualServer = GetConfigFromId((ImportedServerListView.SelectedItems[0].Tag as ServerConfig).Id).ManualImport;
}
//RemoveButton.Enabled = HasSelectedManualServer;

Expand Down Expand Up @@ -306,7 +306,7 @@ private void OnSelectedServerChanged(object sender, EventArgs e)
{
if (ImportedServerListView.SelectedItems.Count > 0)
{
CurrentServerConfig = GetConfigFromHostname((ImportedServerListView.SelectedItems[0].Tag as ServerConfig).Hostname);
CurrentServerConfig = GetConfigFromId((ImportedServerListView.SelectedItems[0].Tag as ServerConfig).Id);
}

ValidateUI();
Expand All @@ -317,7 +317,7 @@ private void OnRemoveClicked(object sender, EventArgs e)
{
if (ImportedServerListView.SelectedItems.Count > 0)
{
ServerConfig Config = GetConfigFromHostname((ImportedServerListView.SelectedItems[0].Tag as ServerConfig).Hostname);
ServerConfig Config = GetConfigFromId((ImportedServerListView.SelectedItems[0].Tag as ServerConfig).Id);

for (int i = 0; i < ServerList.Servers.Count; i++)
{
Expand Down Expand Up @@ -467,11 +467,11 @@ private void ProcessServerQueryResponse(List<ServerConfig> Servers)
BuildServerList();
}

private ServerConfig GetConfigFromHostname(string Hostname)
private ServerConfig GetConfigFromId(string Id)
{
for (int i = 0; i < ServerList.Servers.Count; i++)
{
if (ServerList.Servers[i].Hostname == Hostname)
if (ServerList.Servers[i].Id == Id)
{
return ServerList.Servers[i];
}
Expand All @@ -482,7 +482,7 @@ private ServerConfig GetConfigFromHostname(string Hostname)

private void OnLaunch(object sender, EventArgs e)
{
ServerConfig Config = GetConfigFromHostname((ImportedServerListView.SelectedItems[0].Tag as ServerConfig).Hostname);
ServerConfig Config = GetConfigFromId((ImportedServerListView.SelectedItems[0].Tag as ServerConfig).Id);

if (string.IsNullOrEmpty(Config.PublicKey))
{
Expand Down Expand Up @@ -630,6 +630,7 @@ out ProcessInfo
injectConfig.ServerName = Config.Name;
injectConfig.ServerPublicKey = Config.PublicKey;
injectConfig.ServerHostname = ConnectionHostname;
injectConfig.ServerPort = Config.Port;
injectConfig.EnableSeperateSaveFiles = ProgramSettings.Default.use_seperate_saves;

string json = injectConfig.ToJson();
Expand Down
21 changes: 13 additions & 8 deletions Source/MasterServer/src/routes/api/v1/servers.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,12 @@ function RemoveServer(Id)
}
}

function AddServer(Id, IpAddress, hostname, private_hostname, description, name, public_key, player_count, password, mods_white_list, mods_black_list, mods_required_list, version, allow_sharding, web_address)
function AddServer(Id, IpAddress, hostname, private_hostname, description, name, public_key, player_count, password, mods_white_list, mods_black_list, mods_required_list, version, allow_sharding, web_address, port)
{
var ServerObj = {
"Id": Id,
"IpAddress": IpAddress,
"Port": port,
"Hostname": hostname,
"PrivateHostname": private_hostname,
"Description": description,
Expand Down Expand Up @@ -130,7 +131,7 @@ function AddServer(Id, IpAddress, hostname, private_hostname, description, name,

GActiveServers.push(ServerObj);

console.log(`Adding server: id=${Id} ip=${IpAddress} name=${name}`);
console.log(`Adding server: id=${Id} ip=${IpAddress} port=${port} name=${name}`);
console.log(`Total servers is now ${GActiveServers.length}`);
}

Expand Down Expand Up @@ -182,6 +183,7 @@ router.get('/', async (req, res) => {
ServerInfo.push({
"Id": Server["Id"],
"IpAddress": Server["IpAddress"],
"Port": Server["Port"],
"Hostname": Server["Hostname"],
"PrivateHostname": Server["PrivateHostname"],
"Description": DisplayDescription,
Expand All @@ -199,18 +201,18 @@ router.get('/', async (req, res) => {
res.json({ "status":"success", "servers": ServerInfo });
});

// @route POST api/v1/servers/:ip_address/public_key
// @route POST api/v1/servers/:id/public_key
// @description Get the public kley of a given server.
// @access Public
router.post('/:ip_address/public_key', async (req, res) => {
router.post('/:id/public_key', async (req, res) => {
if (!('password' in req.body))
{
res.json({ "status":"error", "message":"Expected password in body." });
return;
}

var password = req.body["password"];

for (var i = 0; i < GActiveServers.length; i++)
{
if (GActiveServers[i].Id == req.params.id)
Expand Down Expand Up @@ -298,6 +300,7 @@ router.post('/', async (req, res) => {
var allow_sharding = false;
var web_address = "";
var server_id = req.connection.remoteAddress;
var port = 50050;

if ('AllowSharding' in req.body)
{
Expand All @@ -311,12 +314,14 @@ router.post('/', async (req, res) => {
{
server_id = req.body["ServerId"];
}

console.log(`serverId=${server_id}`);
if ('Port' in req.body)
{
port = req.body["Port"];
}

var version = ('ServerVersion' in req.body) ? parseInt(req.body['ServerVersion']) : 1;

AddServer(server_id, req.connection.remoteAddress, hostname, private_hostname, description, name, public_key, player_count, password, mods_white_list, mods_black_list, mods_required_list, version, allow_sharding, web_address);
AddServer(server_id, req.connection.remoteAddress, hostname, private_hostname, description, name, public_key, player_count, password, mods_white_list, mods_black_list, mods_required_list, version, allow_sharding, web_address, port);

res.json({ "status":"success" });
});
Expand Down
6 changes: 2 additions & 4 deletions Source/Server/Server/Server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,7 @@ Server::Server(const std::string& InServerId, const std::string& InServerName, c
Services.push_back(std::make_shared<LoginService>(this, &PrimaryKeyPair));
Services.push_back(std::make_shared<AuthService>(this, &PrimaryKeyPair));
Services.push_back(std::make_shared<GameService>(this, &PrimaryKeyPair));
//if (IsDefaultServer())
{
Services.push_back(std::make_shared<WebUIService>(this));
}
Services.push_back(std::make_shared<WebUIService>(this));
}

Server::~Server()
Expand Down Expand Up @@ -394,6 +391,7 @@ void Server::PollServerAdvertisement()
Body["ServerVersion"] = BuildConfig::MASTER_SERVER_CLIENT_VERSION;
Body["AllowSharding"] = Config.SupportSharding;
Body["WebAddress"] = Config.SupportSharding ? StringFormat("http://%s:%i", ((std::string)Body["Hostname"]).c_str(), Config.WebUIServerPort) : "";
Body["Port"] = Config.LoginServerPort;

MasterServerUpdateRequest = std::make_shared<NetHttpRequest>();
MasterServerUpdateRequest->SetMethod(NetHttpMethod::POST);
Expand Down
20 changes: 19 additions & 1 deletion Source/Server/Server/ServerManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,18 +104,36 @@ void ServerManager::RunUntilQuit()
NextServerPruneTime = GetSeconds() + 60.0f;
}

// Execute all callbacks.
{
std::scoped_lock lock(CallbackMutex);
for (auto& callback : Callbacks)
{
callback();
}

Callbacks.clear();
}

std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}

bool ServerManager::NewServer(const std::string& Name, const std::string& Password, std::string& OutServerId)
{
std::scoped_lock lock(m_mutex);

OutServerId = MakeGUID();
return StartServer(OutServerId, Name, Password);
}


void ServerManager::QueueCallback(std::function<void()> callback)
{
std::scoped_lock lock(CallbackMutex);

Callbacks.push_back(callback);
}

bool ServerManager::StartServer(const std::string& ServerId, const std::string& Name, const std::string& Password)
{
std::scoped_lock lock(m_mutex);
Expand Down
6 changes: 6 additions & 0 deletions Source/Server/Server/ServerManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <filesystem>
#include <queue>
#include <unordered_map>
#include <functional>

// The server manager essentially manages multiple server shards running on the same machine.

Expand All @@ -38,6 +39,8 @@ class ServerManager

bool NewServer(const std::string& Name, const std::string& Password, std::string& OutServerId);

void QueueCallback(std::function<void()> callback);

private:
bool StartServer(const std::string& ServerId, const std::string& Name = "", const std::string& Password = "");
bool StopServer(const std::string& ServerId, bool Permanent = false);
Expand All @@ -58,4 +61,7 @@ class ServerManager

std::vector<std::unique_ptr<Server>> ServerInstances;

std::mutex CallbackMutex;
std::vector<std::function<void()>> Callbacks;

};
Loading

0 comments on commit 8147322

Please sign in to comment.