mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-01-09 14:27:10 +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
|
## 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.
|
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:
|
||||||
To give `AuthServer` network permissions and not require sudo, run the following command
|
|
||||||
```bash
|
```bash
|
||||||
sudo setcap 'cap_net_bind_service=+ep' AuthServer
|
sudo setcap 'cap_net_bind_service=+ep' AuthServer
|
||||||
```
|
```
|
||||||
and then go to `build/masterconfig.ini` and change `use_sudo_auth` to 0.
|
|
||||||
|
|
||||||
### Linux Service
|
### 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.
|
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 "Game.h"
|
||||||
#include "Server.h"
|
#include "Server.h"
|
||||||
|
|
||||||
|
|
||||||
namespace Game {
|
namespace Game {
|
||||||
Logger* logger = nullptr;
|
Logger* logger = nullptr;
|
||||||
dServer* server = nullptr;
|
dServer* server = nullptr;
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
add_executable(AuthServer "AuthServer.cpp")
|
add_executable(AuthServer "AuthServer.cpp")
|
||||||
|
|
||||||
target_link_libraries(AuthServer ${COMMON_LIBRARIES} dServer)
|
target_link_libraries(AuthServer ${COMMON_LIBRARIES} dServer)
|
||||||
|
|
||||||
target_include_directories(AuthServer PRIVATE ${PROJECT_SOURCE_DIR}/dServer)
|
target_include_directories(AuthServer PRIVATE ${PROJECT_SOURCE_DIR}/dServer)
|
||||||
|
|
||||||
add_compile_definitions(AuthServer PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}\"")
|
add_compile_definitions(AuthServer PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}\"")
|
||||||
|
@ -4,68 +4,146 @@
|
|||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
#include "BinaryPathFinder.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()) {
|
if (Game::ShouldShutdown()) {
|
||||||
LOG("Currently shutting down. Chat will not be restarted.");
|
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
|
#endif
|
||||||
|
LOG("ChatServer PID is %d", chat_pid);
|
||||||
|
return chat_pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StartAuthServer() {
|
uint32_t StartAuthServer() {
|
||||||
if (Game::ShouldShutdown()) {
|
if (Game::ShouldShutdown()) {
|
||||||
LOG("Currently shutting down. Auth will not be restarted.");
|
LOG("Currently shutting down. Auth will not be restarted.");
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
#ifdef __APPLE__
|
auto auth_path = BinaryPathFinder::GetBinaryDir() / "AuthServer";
|
||||||
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) {
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
std::string cmd = "start /B " + (BinaryPathFinder::GetBinaryDir() / "WorldServer.exe").string() + " -zone ";
|
auth_path.replace_extension(".exe");
|
||||||
#else
|
auto auth_startup = startup;
|
||||||
std::string cmd;
|
auto auth_info = PROCESS_INFORMATION{};
|
||||||
if (std::atoi(Game::config->GetValue("use_sudo_world").c_str())) {
|
if (!CreateProcessW(auth_path.wstring().data(), auth_path.wstring().data(),
|
||||||
cmd = "sudo " + (BinaryPathFinder::GetBinaryDir() / "WorldServer").string() + " -zone ";
|
nullptr, nullptr, false, 0, nullptr, nullptr,
|
||||||
} else {
|
&auth_startup, &auth_info))
|
||||||
cmd = (BinaryPathFinder::GetBinaryDir() / "WorldServer").string() + " -zone ";
|
{
|
||||||
|
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
|
#endif
|
||||||
|
LOG("AuthServer PID is %d", auth_pid);
|
||||||
cmd.append(std::to_string(mapID));
|
return auth_pid;
|
||||||
cmd.append(" -port ");
|
}
|
||||||
cmd.append(std::to_string(port));
|
|
||||||
cmd.append(" -instance ");
|
uint32_t StartWorldServer(LWOMAPID mapID, uint16_t port, LWOINSTANCEID lastInstanceID, int maxPlayers, LWOCLONEID cloneID) {
|
||||||
cmd.append(std::to_string(lastInstanceID));
|
auto world_path = BinaryPathFinder::GetBinaryDir() / "WorldServer";
|
||||||
cmd.append(" -maxclients ");
|
#ifdef _WIN32
|
||||||
cmd.append(std::to_string(maxPlayers));
|
world_path.replace_extension(".exe");
|
||||||
cmd.append(" -clone ");
|
auto cmd = world_path.wstring() + L" -zone " + std::to_wstring(mapID) + L" -port " + std::to_wstring(port) +
|
||||||
cmd.append(std::to_string(cloneID));
|
L" -instance " + std::to_wstring(lastInstanceID) + L" -maxclients " + std::to_wstring(maxPlayers) +
|
||||||
|
L" -clone " + std::to_wstring(cloneID);
|
||||||
#ifndef _WIN32
|
|
||||||
cmd.append("&"); //Sends our next process to the background on Linux
|
auto world_startup = startup;
|
||||||
#endif
|
auto world_info = PROCESS_INFORMATION{};
|
||||||
|
if (!CreateProcessW(world_path.wstring().data(), cmd.data(),
|
||||||
auto ret = system(cmd.c_str());
|
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
|
#pragma once
|
||||||
#include "dCommonVars.h"
|
#include "dCommonVars.h"
|
||||||
|
|
||||||
void StartAuthServer();
|
uint32_t StartAuthServer();
|
||||||
void StartChatServer();
|
uint32_t StartChatServer();
|
||||||
void StartWorldServer(LWOMAPID mapID, uint16_t port, LWOINSTANCEID lastInstanceID, int maxPlayers, LWOCLONEID cloneID);
|
uint32_t StartWorldServer(LWOMAPID mapID, uint16_t port, LWOINSTANCEID lastInstanceID, int maxPlayers, LWOCLONEID cloneID);
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "MessageType/Server.h"
|
#include "MessageType/Server.h"
|
||||||
#include "MessageType/Master.h"
|
#include "MessageType/Master.h"
|
||||||
|
|
||||||
|
#include "BinaryPathFinder.h"
|
||||||
#include "BitStreamUtils.h"
|
#include "BitStreamUtils.h"
|
||||||
#include "MasterPackets.h"
|
#include "MasterPackets.h"
|
||||||
#include "ZoneInstanceManager.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));
|
LOG("%s Server is listening on %s:%i with encryption: %i", StringifiedEnum::ToString(serverType).data(), ip.c_str(), port, int(useEncryption));
|
||||||
else
|
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);
|
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);
|
mLogger->SetLogToConsole(prevLogSetting);
|
||||||
|
|
||||||
@ -109,20 +119,23 @@ Packet* dServer::ReceiveFromMaster() {
|
|||||||
if (packet) {
|
if (packet) {
|
||||||
if (packet->length < 1) { mMasterPeer->DeallocatePacket(packet); return nullptr; }
|
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!");
|
LOG("Lost our connection to master, shutting DOWN!");
|
||||||
mMasterConnectionActive = false;
|
mMasterConnectionActive = false;
|
||||||
//ConnectToMaster(); //We'll just shut down now
|
// ConnectToMaster(); // We'll just shut down now
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
case ID_CONNECTION_REQUEST_ACCEPTED: {
|
||||||
if (packet->data[0] == ID_CONNECTION_REQUEST_ACCEPTED) {
|
|
||||||
LOG("Established connection to master, zone (%i), instance (%i)", this->GetZoneID(), this->GetInstanceID());
|
LOG("Established connection to master, zone (%i), instance (%i)", this->GetZoneID(), this->GetInstanceID());
|
||||||
mMasterConnectionActive = true;
|
mMasterConnectionActive = true;
|
||||||
mMasterSystemAddress = packet->systemAddress;
|
mMasterSystemAddress = packet->systemAddress;
|
||||||
MasterPackets::SendServerInfo(this, packet);
|
MasterPackets::SendServerInfo(this, packet);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
case ID_USER_PACKET_ENUM: {
|
||||||
if (packet->data[0] == ID_USER_PACKET_ENUM) {
|
|
||||||
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::MASTER) {
|
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::MASTER) {
|
||||||
switch (static_cast<MessageType::Master>(packet->data[3])) {
|
switch (static_cast<MessageType::Master>(packet->data[3])) {
|
||||||
case MessageType::Master::REQUEST_ZONE_TRANSFER_RESPONSE: {
|
case MessageType::Master::REQUEST_ZONE_TRANSFER_RESPONSE: {
|
||||||
@ -133,12 +146,13 @@ Packet* dServer::ReceiveFromMaster() {
|
|||||||
*mShouldShutdown = -2;
|
*mShouldShutdown = -2;
|
||||||
break;
|
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:
|
default:
|
||||||
|
|
||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mMasterPeer->DeallocatePacket(packet);
|
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
|
# The port number to start world servers on. Will be incremented for each world
|
||||||
world_port_start=3000
|
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
|
# 0 or 1, should autostart auth, chat, and char servers
|
||||||
prestart_servers=1
|
prestart_servers=1
|
||||||
|
Loading…
Reference in New Issue
Block a user