mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-01-08 05:47:07 +00:00
feat: Replace calls to system function in server startups (#1691)
* replace linux calls * windows api * log child PIDs in parent process * fix typo for windows * functions now return the process ID * use wchar_t for windows APIs * Update Start.cpp Try to fix MacOS issues * Conditionally include unistd.h * remove sudo config option and add error message for linux * fix windows .exe extension * REALLY fix windows * try replacing c_str() with data() * really REALLY fix Windows * Update dNet/dServer.cpp Co-authored-by: David Markowitz <39972741+EmosewaMC@users.noreply.github.com> * Update dServer.cpp
This commit is contained in:
parent
5ccd15a7d8
commit
71baa5ce90
@ -246,12 +246,10 @@ Your build directory should now look like this:
|
||||
* ...
|
||||
|
||||
## Running the server
|
||||
If everything has been configured correctly you should now be able to run the `MasterServer` binary which is located in the `build` directory. Darkflame Universe utilizes port numbers under 1024, so under Linux you either have to give the `AuthServer` binary network permissions or run it under sudo.
|
||||
To give `AuthServer` network permissions and not require sudo, run the following command
|
||||
If everything has been configured correctly you should now be able to run the `MasterServer` binary which is located in the `build` directory. Darkflame Universe utilizes port numbers under 1024, so under Linux you have to give the `AuthServer` binary network permissions by running the following command:
|
||||
```bash
|
||||
sudo setcap 'cap_net_bind_service=+ep' AuthServer
|
||||
```
|
||||
and then go to `build/masterconfig.ini` and change `use_sudo_auth` to 0.
|
||||
|
||||
### Linux Service
|
||||
If you are running this on a linux based system, it will use your terminal to run the program interactively, preventing you using it for other tasks and requiring it to be open to run the server.
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include "Game.h"
|
||||
#include "Server.h"
|
||||
|
||||
|
||||
namespace Game {
|
||||
Logger* logger = nullptr;
|
||||
dServer* server = nullptr;
|
||||
|
@ -1,7 +1,4 @@
|
||||
add_executable(AuthServer "AuthServer.cpp")
|
||||
|
||||
target_link_libraries(AuthServer ${COMMON_LIBRARIES} dServer)
|
||||
|
||||
target_include_directories(AuthServer PRIVATE ${PROJECT_SOURCE_DIR}/dServer)
|
||||
|
||||
add_compile_definitions(AuthServer PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}\"")
|
||||
|
@ -4,68 +4,146 @@
|
||||
#include "Game.h"
|
||||
#include "BinaryPathFinder.h"
|
||||
|
||||
void StartChatServer() {
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <handleapi.h>
|
||||
#include <processthreadsapi.h>
|
||||
|
||||
namespace {
|
||||
const auto startup = STARTUPINFOW{
|
||||
.cb = sizeof(STARTUPINFOW),
|
||||
.lpReserved = nullptr,
|
||||
.lpDesktop = nullptr,
|
||||
.lpTitle = nullptr,
|
||||
.dwX = 0,
|
||||
.dwY = 0,
|
||||
.dwXSize = 0,
|
||||
.dwYSize = 0,
|
||||
.dwXCountChars = 0,
|
||||
.dwYCountChars = 0,
|
||||
.dwFillAttribute = 0,
|
||||
.dwFlags = 0,
|
||||
.wShowWindow = 0,
|
||||
.cbReserved2 = 0,
|
||||
.lpReserved2 = nullptr,
|
||||
.hStdInput = INVALID_HANDLE_VALUE,
|
||||
.hStdOutput = INVALID_HANDLE_VALUE,
|
||||
.hStdError = INVALID_HANDLE_VALUE,
|
||||
};
|
||||
}
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
uint32_t StartChatServer() {
|
||||
if (Game::ShouldShutdown()) {
|
||||
LOG("Currently shutting down. Chat will not be restarted.");
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
auto chat_path = BinaryPathFinder::GetBinaryDir() / "ChatServer";
|
||||
#ifdef _WIN32
|
||||
chat_path.replace_extension(".exe");
|
||||
auto chat_startup = startup;
|
||||
auto chat_info = PROCESS_INFORMATION{};
|
||||
if (!CreateProcessW(chat_path.wstring().data(), chat_path.wstring().data(),
|
||||
nullptr, nullptr, false, 0, nullptr, nullptr,
|
||||
&chat_startup, &chat_info))
|
||||
{
|
||||
LOG("Failed to launch ChatServer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get pid and close unused handles
|
||||
auto chat_pid = chat_info.dwProcessId;
|
||||
CloseHandle(chat_info.hProcess);
|
||||
CloseHandle(chat_info.hThread);
|
||||
#else // *nix systems
|
||||
const auto chat_pid = fork();
|
||||
if (chat_pid < 0) {
|
||||
LOG("Failed to launch ChatServer");
|
||||
return 0;
|
||||
} else if (chat_pid == 0) {
|
||||
// We are the child process
|
||||
execl(chat_path.string().c_str(), chat_path.string().c_str(), nullptr);
|
||||
}
|
||||
#ifdef __APPLE__
|
||||
//macOS doesn't need sudo to run on ports < 1024
|
||||
auto result = system(((BinaryPathFinder::GetBinaryDir() / "ChatServer").string() + "&").c_str());
|
||||
#elif _WIN32
|
||||
auto result = system(("start /B " + (BinaryPathFinder::GetBinaryDir() / "ChatServer.exe").string()).c_str());
|
||||
#else
|
||||
if (std::atoi(Game::config->GetValue("use_sudo_chat").c_str())) {
|
||||
auto result = system(("sudo " + (BinaryPathFinder::GetBinaryDir() / "ChatServer").string() + "&").c_str());
|
||||
} else {
|
||||
auto result = system(((BinaryPathFinder::GetBinaryDir() / "ChatServer").string() + "&").c_str());
|
||||
}
|
||||
#endif
|
||||
LOG("ChatServer PID is %d", chat_pid);
|
||||
return chat_pid;
|
||||
}
|
||||
|
||||
void StartAuthServer() {
|
||||
uint32_t StartAuthServer() {
|
||||
if (Game::ShouldShutdown()) {
|
||||
LOG("Currently shutting down. Auth will not be restarted.");
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
#ifdef __APPLE__
|
||||
auto result = system(((BinaryPathFinder::GetBinaryDir() / "AuthServer").string() + "&").c_str());
|
||||
#elif _WIN32
|
||||
auto result = system(("start /B " + (BinaryPathFinder::GetBinaryDir() / "AuthServer.exe").string()).c_str());
|
||||
#else
|
||||
if (std::atoi(Game::config->GetValue("use_sudo_auth").c_str())) {
|
||||
auto result = system(("sudo " + (BinaryPathFinder::GetBinaryDir() / "AuthServer").string() + "&").c_str());
|
||||
} else {
|
||||
auto result = system(((BinaryPathFinder::GetBinaryDir() / "AuthServer").string() + "&").c_str());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void StartWorldServer(LWOMAPID mapID, uint16_t port, LWOINSTANCEID lastInstanceID, int maxPlayers, LWOCLONEID cloneID) {
|
||||
auto auth_path = BinaryPathFinder::GetBinaryDir() / "AuthServer";
|
||||
#ifdef _WIN32
|
||||
std::string cmd = "start /B " + (BinaryPathFinder::GetBinaryDir() / "WorldServer.exe").string() + " -zone ";
|
||||
#else
|
||||
std::string cmd;
|
||||
if (std::atoi(Game::config->GetValue("use_sudo_world").c_str())) {
|
||||
cmd = "sudo " + (BinaryPathFinder::GetBinaryDir() / "WorldServer").string() + " -zone ";
|
||||
} else {
|
||||
cmd = (BinaryPathFinder::GetBinaryDir() / "WorldServer").string() + " -zone ";
|
||||
auth_path.replace_extension(".exe");
|
||||
auto auth_startup = startup;
|
||||
auto auth_info = PROCESS_INFORMATION{};
|
||||
if (!CreateProcessW(auth_path.wstring().data(), auth_path.wstring().data(),
|
||||
nullptr, nullptr, false, 0, nullptr, nullptr,
|
||||
&auth_startup, &auth_info))
|
||||
{
|
||||
LOG("Failed to launch AuthServer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get pid and close unused handles
|
||||
auto auth_pid = auth_info.dwProcessId;
|
||||
CloseHandle(auth_info.hProcess);
|
||||
CloseHandle(auth_info.hThread);
|
||||
#else // *nix systems
|
||||
const auto auth_pid = fork();
|
||||
if (auth_pid < 0) {
|
||||
LOG("Failed to launch AuthServer");
|
||||
return 0;
|
||||
} else if (auth_pid == 0) {
|
||||
// We are the child process
|
||||
execl(auth_path.string().c_str(), auth_path.string().c_str(), nullptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
cmd.append(std::to_string(mapID));
|
||||
cmd.append(" -port ");
|
||||
cmd.append(std::to_string(port));
|
||||
cmd.append(" -instance ");
|
||||
cmd.append(std::to_string(lastInstanceID));
|
||||
cmd.append(" -maxclients ");
|
||||
cmd.append(std::to_string(maxPlayers));
|
||||
cmd.append(" -clone ");
|
||||
cmd.append(std::to_string(cloneID));
|
||||
|
||||
#ifndef _WIN32
|
||||
cmd.append("&"); //Sends our next process to the background on Linux
|
||||
#endif
|
||||
|
||||
auto ret = system(cmd.c_str());
|
||||
LOG("AuthServer PID is %d", auth_pid);
|
||||
return auth_pid;
|
||||
}
|
||||
|
||||
uint32_t StartWorldServer(LWOMAPID mapID, uint16_t port, LWOINSTANCEID lastInstanceID, int maxPlayers, LWOCLONEID cloneID) {
|
||||
auto world_path = BinaryPathFinder::GetBinaryDir() / "WorldServer";
|
||||
#ifdef _WIN32
|
||||
world_path.replace_extension(".exe");
|
||||
auto cmd = world_path.wstring() + L" -zone " + std::to_wstring(mapID) + L" -port " + std::to_wstring(port) +
|
||||
L" -instance " + std::to_wstring(lastInstanceID) + L" -maxclients " + std::to_wstring(maxPlayers) +
|
||||
L" -clone " + std::to_wstring(cloneID);
|
||||
|
||||
auto world_startup = startup;
|
||||
auto world_info = PROCESS_INFORMATION{};
|
||||
if (!CreateProcessW(world_path.wstring().data(), cmd.data(),
|
||||
nullptr, nullptr, false, 0, nullptr, nullptr,
|
||||
&world_startup, &world_info))
|
||||
{
|
||||
LOG("Failed to launch WorldServer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get pid and close unused handles
|
||||
auto world_pid = world_info.dwProcessId;
|
||||
CloseHandle(world_info.hProcess);
|
||||
CloseHandle(world_info.hThread);
|
||||
#else
|
||||
const auto world_pid = fork();
|
||||
if (world_pid < 0) {
|
||||
LOG("Failed to launch WorldServer");
|
||||
return 0;
|
||||
} else if (world_pid == 0) {
|
||||
// We are the child process
|
||||
execl(world_path.string().c_str(), world_path.string().c_str(),
|
||||
"-zone", std::to_string(mapID).c_str(),
|
||||
"-port", std::to_string(port).c_str(),
|
||||
"-instance", std::to_string(lastInstanceID).c_str(),
|
||||
"-maxclients", std::to_string(maxPlayers).c_str(),
|
||||
"-clone", std::to_string(cloneID).c_str(), nullptr);
|
||||
}
|
||||
#endif
|
||||
LOG("WorldServer PID is %d", world_pid);
|
||||
return world_pid;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include "dCommonVars.h"
|
||||
|
||||
void StartAuthServer();
|
||||
void StartChatServer();
|
||||
void StartWorldServer(LWOMAPID mapID, uint16_t port, LWOINSTANCEID lastInstanceID, int maxPlayers, LWOCLONEID cloneID);
|
||||
uint32_t StartAuthServer();
|
||||
uint32_t StartChatServer();
|
||||
uint32_t StartWorldServer(LWOMAPID mapID, uint16_t port, LWOINSTANCEID lastInstanceID, int maxPlayers, LWOCLONEID cloneID);
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "MessageType/Server.h"
|
||||
#include "MessageType/Master.h"
|
||||
|
||||
#include "BinaryPathFinder.h"
|
||||
#include "BitStreamUtils.h"
|
||||
#include "MasterPackets.h"
|
||||
#include "ZoneInstanceManager.h"
|
||||
@ -68,7 +69,16 @@ dServer::dServer(const std::string& ip, int port, int instanceID, int maxConnect
|
||||
LOG("%s Server is listening on %s:%i with encryption: %i", StringifiedEnum::ToString(serverType).data(), ip.c_str(), port, int(useEncryption));
|
||||
else
|
||||
LOG("%s Server is listening on %s:%i with encryption: %i, running zone %i / %i", StringifiedEnum::ToString(serverType).data(), ip.c_str(), port, int(useEncryption), zoneID, instanceID);
|
||||
} else { LOG("FAILED TO START SERVER ON IP/PORT: %s:%i", ip.c_str(), port); return; }
|
||||
} else {
|
||||
LOG("FAILED TO START SERVER ON IP/PORT: %s:%i", ip.c_str(), port);
|
||||
#ifdef DARKFLAME_PLATFORM_LINUX
|
||||
if (mServerType == ServerType::Auth) {
|
||||
const auto cwd = BinaryPathFinder::GetBinaryDir();
|
||||
LOG("Try running the following command before launching again:\n sudo setcap 'cap_net_bind_service=+ep' \"%s/AuthServer\"", cwd.string().c_str());
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
mLogger->SetLogToConsole(prevLogSetting);
|
||||
|
||||
@ -109,20 +119,23 @@ Packet* dServer::ReceiveFromMaster() {
|
||||
if (packet) {
|
||||
if (packet->length < 1) { mMasterPeer->DeallocatePacket(packet); return nullptr; }
|
||||
|
||||
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) {
|
||||
switch (packet->data[0]) {
|
||||
case ID_DISCONNECTION_NOTIFICATION:
|
||||
[[fallthrough]];
|
||||
case ID_CONNECTION_LOST: {
|
||||
LOG("Lost our connection to master, shutting DOWN!");
|
||||
mMasterConnectionActive = false;
|
||||
//ConnectToMaster(); //We'll just shut down now
|
||||
// ConnectToMaster(); // We'll just shut down now
|
||||
break;
|
||||
}
|
||||
|
||||
if (packet->data[0] == ID_CONNECTION_REQUEST_ACCEPTED) {
|
||||
case ID_CONNECTION_REQUEST_ACCEPTED: {
|
||||
LOG("Established connection to master, zone (%i), instance (%i)", this->GetZoneID(), this->GetInstanceID());
|
||||
mMasterConnectionActive = true;
|
||||
mMasterSystemAddress = packet->systemAddress;
|
||||
MasterPackets::SendServerInfo(this, packet);
|
||||
break;
|
||||
}
|
||||
|
||||
if (packet->data[0] == ID_USER_PACKET_ENUM) {
|
||||
case ID_USER_PACKET_ENUM: {
|
||||
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::MASTER) {
|
||||
switch (static_cast<MessageType::Master>(packet->data[3])) {
|
||||
case MessageType::Master::REQUEST_ZONE_TRANSFER_RESPONSE: {
|
||||
@ -133,12 +146,13 @@ Packet* dServer::ReceiveFromMaster() {
|
||||
*mShouldShutdown = -2;
|
||||
break;
|
||||
|
||||
//When we handle these packets in World instead dServer, we just return the packet's pointer.
|
||||
// When we handle these packets in World instead dServer, we just return the packet's pointer.
|
||||
default:
|
||||
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mMasterPeer->DeallocatePacket(packet);
|
||||
|
@ -7,15 +7,5 @@ master_server_port=2000
|
||||
# The port number to start world servers on. Will be incremented for each world
|
||||
world_port_start=3000
|
||||
|
||||
# Use sudo when launching the auth server.
|
||||
# Required by default if on Linux as auth runs on port 1001
|
||||
use_sudo_auth=1
|
||||
|
||||
# Use sudo when launching the chat server
|
||||
use_sudo_chat=0
|
||||
|
||||
# Use sudo when launching world servers
|
||||
use_sudo_world=0
|
||||
|
||||
# 0 or 1, should autostart auth, chat, and char servers
|
||||
prestart_servers=1
|
||||
|
Loading…
Reference in New Issue
Block a user