mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-11-05 07:02:13 +00:00
Initial work on TCP transport layer:
* Optionally compiled additional TCP transport layer. * Config to enable it. * Tested and functional with lcdr's tcpudp dll, udp being disabled in the dll due to port issues. * Removed unused RakNet replica manager and id manager. We've got our own replica manager since pre-open-source. * Utilizes async boost behavior. Todo: * Figure out how to do ping calculations. * Fix crashes on universe shutdown. * Test TLS on a VPS. * Remove unnecessary logging. * Test with lots of clients. * Finish "master" to "manager" naming refactor.
This commit is contained in:
341
dNet/dServer.cpp
341
dNet/dServer.cpp
@@ -8,252 +8,187 @@
|
||||
#include "MessageIdentifiers.h"
|
||||
#include "eConnectionType.h"
|
||||
#include "eServerMessageType.h"
|
||||
#include "eMasterMessageType.h"
|
||||
#include "eManagerMessageType.h"
|
||||
|
||||
#include "BitStreamUtils.h"
|
||||
#include "MasterPackets.h"
|
||||
#include "ZoneInstanceManager.h"
|
||||
#include "StringifiedEnum.h"
|
||||
|
||||
//! Replica Constructor class
|
||||
class ReplicaConstructor : public ReceiveConstructionInterface {
|
||||
public:
|
||||
ReplicaReturnResult ReceiveConstruction(RakNet::BitStream* inBitStream, RakNetTime timestamp, NetworkID networkID, NetworkIDObject* existingObject, SystemAddress senderId, ReplicaManager* caller) {
|
||||
return REPLICA_PROCESSING_DONE;
|
||||
#include "RakNetTransportLayer.h"
|
||||
#ifdef NET_ENABLE_TCP_TRANSPORT
|
||||
#include "TcpTransportLayer.h"
|
||||
#endif
|
||||
|
||||
dServer::dServer(
|
||||
const std::string& ip,
|
||||
int port,
|
||||
int instanceID,
|
||||
int maxConnections,
|
||||
bool isInternal,
|
||||
bool useEncryption,
|
||||
Logger* logger,
|
||||
const std::string masterIP,
|
||||
int masterPort,
|
||||
ServerType serverType,
|
||||
dConfig* config,
|
||||
Game::signal_t* shouldShutdown,
|
||||
unsigned int zoneID
|
||||
) {
|
||||
m_TransportType = TransportType::RakNet;
|
||||
|
||||
if (config->GetValue("transport_layer") == "tcp") {
|
||||
m_TransportType = TransportType::Tcp;
|
||||
LOG("Using TCP transport layer.");
|
||||
}
|
||||
} ConstructionCB;
|
||||
|
||||
//! Replica Download Sender class
|
||||
class ReplicaSender : public SendDownloadCompleteInterface {
|
||||
public:
|
||||
ReplicaReturnResult SendDownloadComplete(RakNet::BitStream* outBitStream, RakNetTime currentTime, SystemAddress senderId, ReplicaManager* caller) {
|
||||
return REPLICA_PROCESSING_DONE;
|
||||
}
|
||||
} SendDownloadCompleteCB;
|
||||
|
||||
//! Replica Download Receiver class
|
||||
class ReplicaReceiever : public ReceiveDownloadCompleteInterface {
|
||||
public:
|
||||
ReplicaReturnResult ReceiveDownloadComplete(RakNet::BitStream* inBitStream, SystemAddress senderId, ReplicaManager* caller) {
|
||||
return REPLICA_PROCESSING_DONE;
|
||||
}
|
||||
} ReceiveDownloadCompleteCB;
|
||||
|
||||
dServer::dServer(const std::string& ip, int port, int instanceID, int maxConnections, bool isInternal, bool useEncryption, Logger* logger, const std::string masterIP, int masterPort, ServerType serverType, dConfig* config, Game::signal_t* lastSignal, unsigned int zoneID) {
|
||||
mIP = ip;
|
||||
mPort = port;
|
||||
mZoneID = zoneID;
|
||||
mInstanceID = instanceID;
|
||||
mMaxConnections = maxConnections;
|
||||
mIsInternal = isInternal;
|
||||
mUseEncryption = useEncryption;
|
||||
mLogger = logger;
|
||||
mMasterIP = masterIP;
|
||||
mMasterPort = masterPort;
|
||||
mMasterConnectionActive = false;
|
||||
mNetIDManager = nullptr;
|
||||
mReplicaManager = nullptr;
|
||||
mServerType = serverType;
|
||||
mConfig = config;
|
||||
mShouldShutdown = lastSignal;
|
||||
//Attempt to start our server here:
|
||||
mIsOkay = Startup();
|
||||
|
||||
//Forcibly log to both the console and our file what ip, port and possibly zoneID / instanceID we're running on:
|
||||
bool prevLogSetting = mLogger->GetLogToConsole();
|
||||
mLogger->SetLogToConsole(true);
|
||||
|
||||
if (mIsOkay) {
|
||||
if (zoneID == 0)
|
||||
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; }
|
||||
|
||||
mLogger->SetLogToConsole(prevLogSetting);
|
||||
|
||||
//Connect to master if we are not master:
|
||||
if (serverType != ServerType::Master) {
|
||||
SetupForMasterConnection();
|
||||
if (!ConnectToMaster()) {
|
||||
LOG("Failed ConnectToMaster!");
|
||||
}
|
||||
else {
|
||||
LOG("Using RakNet transport layer.");
|
||||
}
|
||||
|
||||
//Set up Replica if we're a world server:
|
||||
if (serverType == ServerType::World) {
|
||||
mNetIDManager = new NetworkIDManager();
|
||||
mNetIDManager->SetIsNetworkIDAuthority(true);
|
||||
switch (m_TransportType) {
|
||||
case TransportType::RakNet:
|
||||
m_TransportLayer = std::make_unique<RakNetTransportLayer>(
|
||||
ip,
|
||||
port,
|
||||
instanceID,
|
||||
maxConnections,
|
||||
isInternal,
|
||||
useEncryption,
|
||||
logger,
|
||||
masterIP,
|
||||
masterPort,
|
||||
serverType,
|
||||
config,
|
||||
shouldShutdown,
|
||||
zoneID
|
||||
);
|
||||
break;
|
||||
case TransportType::Tcp:
|
||||
#ifdef NET_ENABLE_TCP_TRANSPORT
|
||||
m_TransportLayer = std::make_unique<TcpTransportLayer>(
|
||||
ip,
|
||||
port,
|
||||
instanceID,
|
||||
maxConnections,
|
||||
isInternal,
|
||||
useEncryption,
|
||||
logger,
|
||||
masterIP,
|
||||
masterPort,
|
||||
serverType,
|
||||
config,
|
||||
shouldShutdown,
|
||||
zoneID
|
||||
);
|
||||
#else
|
||||
throw std::runtime_error("TCP transport is not enabled!");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
mReplicaManager = new ReplicaManager();
|
||||
mReplicaManager->SetAutoParticipateNewConnections(false);
|
||||
mReplicaManager->SetAutoConstructToNewParticipants(false);
|
||||
mReplicaManager->SetAutoSerializeInScope(true);
|
||||
mReplicaManager->SetReceiveConstructionCB(&ConstructionCB);
|
||||
mReplicaManager->SetDownloadCompleteCB(&SendDownloadCompleteCB, &ReceiveDownloadCompleteCB);
|
||||
bool okey = m_TransportLayer->Startup();
|
||||
|
||||
mPeer->AttachPlugin(mReplicaManager);
|
||||
mPeer->SetNetworkIDManager(mNetIDManager);
|
||||
if (!okey) {
|
||||
LOG("Failed to start the server!");
|
||||
|
||||
throw std::runtime_error("Failed to start the server!");
|
||||
}
|
||||
}
|
||||
|
||||
dServer::~dServer() {
|
||||
Shutdown();
|
||||
m_TransportLayer->Shutdown();
|
||||
|
||||
m_TransportLayer = nullptr;
|
||||
}
|
||||
|
||||
Packet* dServer::ReceiveFromMaster() {
|
||||
if (!mMasterPeer) return nullptr;
|
||||
if (!mMasterConnectionActive) ConnectToMaster();
|
||||
|
||||
Packet* packet = mMasterPeer->Receive();
|
||||
if (packet) {
|
||||
if (packet->length < 1) { mMasterPeer->DeallocatePacket(packet); return nullptr; }
|
||||
|
||||
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) {
|
||||
LOG("Lost our connection to master, shutting DOWN!");
|
||||
mMasterConnectionActive = false;
|
||||
//ConnectToMaster(); //We'll just shut down now
|
||||
}
|
||||
|
||||
if (packet->data[0] == 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);
|
||||
}
|
||||
|
||||
if (packet->data[0] == ID_USER_PACKET_ENUM) {
|
||||
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::MASTER) {
|
||||
switch (static_cast<eMasterMessageType>(packet->data[3])) {
|
||||
case eMasterMessageType::REQUEST_ZONE_TRANSFER_RESPONSE: {
|
||||
ZoneInstanceManager::Instance()->HandleRequestZoneTransferResponse(packet);
|
||||
break;
|
||||
}
|
||||
case eMasterMessageType::SHUTDOWN:
|
||||
*mShouldShutdown = -2;
|
||||
break;
|
||||
|
||||
//When we handle these packets in World instead dServer, we just return the packet's pointer.
|
||||
default:
|
||||
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mMasterPeer->DeallocatePacket(packet);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return m_TransportLayer->ReceiveFromManager();
|
||||
}
|
||||
|
||||
Packet* dServer::Receive() {
|
||||
return mPeer->Receive();
|
||||
return m_TransportLayer->Receive();
|
||||
}
|
||||
|
||||
void dServer::DeallocatePacket(Packet* packet) {
|
||||
mPeer->DeallocatePacket(packet);
|
||||
m_TransportLayer->DeallocatePacket(packet);
|
||||
}
|
||||
|
||||
void dServer::DeallocateMasterPacket(Packet* packet) {
|
||||
mMasterPeer->DeallocatePacket(packet);
|
||||
m_TransportLayer->DeallocateManagerPacket(packet);
|
||||
}
|
||||
|
||||
void dServer::Send(RakNet::BitStream& bitStream, const SystemAddress& sysAddr, bool broadcast) {
|
||||
mPeer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE_ORDERED, 0, sysAddr, broadcast);
|
||||
m_TransportLayer->Send(bitStream, sysAddr, broadcast);
|
||||
}
|
||||
|
||||
void dServer::SendToMaster(RakNet::BitStream& bitStream) {
|
||||
if (!mMasterConnectionActive) ConnectToMaster();
|
||||
mMasterPeer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE_ORDERED, 0, mMasterSystemAddress, false);
|
||||
m_TransportLayer->SendToManager(bitStream);
|
||||
}
|
||||
|
||||
void dServer::Disconnect(const SystemAddress& sysAddr, eServerDisconnectIdentifiers disconNotifyID) {
|
||||
RakNet::BitStream bitStream;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::SERVER, eServerMessageType::DISCONNECT_NOTIFY);
|
||||
bitStream.Write(disconNotifyID);
|
||||
mPeer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE_ORDERED, 0, sysAddr, false);
|
||||
|
||||
mPeer->CloseConnection(sysAddr, true);
|
||||
m_TransportLayer->Disconnect(sysAddr, disconNotifyID);
|
||||
}
|
||||
|
||||
bool dServer::IsConnected(const SystemAddress& sysAddr) {
|
||||
return mPeer->IsConnected(sysAddr);
|
||||
}
|
||||
|
||||
bool dServer::Startup() {
|
||||
mSocketDescriptor = SocketDescriptor(uint16_t(mPort), 0);
|
||||
mPeer = RakNetworkFactory::GetRakPeerInterface();
|
||||
|
||||
if (!mPeer) return false;
|
||||
if (!mPeer->Startup(mMaxConnections, 10, &mSocketDescriptor, 1)) return false;
|
||||
|
||||
if (mIsInternal) {
|
||||
mPeer->SetIncomingPassword("3.25 DARKFLAME1", 15);
|
||||
} else {
|
||||
UpdateBandwidthLimit();
|
||||
UpdateMaximumMtuSize();
|
||||
mPeer->SetIncomingPassword("3.25 ND1", 8);
|
||||
}
|
||||
|
||||
mPeer->SetMaximumIncomingConnections(mMaxConnections);
|
||||
if (mUseEncryption) mPeer->InitializeSecurity(NULL, NULL, NULL, NULL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void dServer::UpdateMaximumMtuSize() {
|
||||
auto maxMtuSize = mConfig->GetValue("maximum_mtu_size");
|
||||
mPeer->SetMTUSize(maxMtuSize.empty() ? 1228 : std::stoi(maxMtuSize));
|
||||
}
|
||||
|
||||
void dServer::UpdateBandwidthLimit() {
|
||||
auto newBandwidth = mConfig->GetValue("maximum_outgoing_bandwidth");
|
||||
mPeer->SetPerConnectionOutgoingBandwidthLimit(!newBandwidth.empty() ? std::stoi(newBandwidth) : 0);
|
||||
}
|
||||
|
||||
void dServer::Shutdown() {
|
||||
if (mPeer) {
|
||||
mPeer->Shutdown(1000);
|
||||
RakNetworkFactory::DestroyRakPeerInterface(mPeer);
|
||||
}
|
||||
|
||||
if (mNetIDManager) {
|
||||
delete mNetIDManager;
|
||||
mNetIDManager = nullptr;
|
||||
}
|
||||
|
||||
if (mReplicaManager) {
|
||||
delete mReplicaManager;
|
||||
mReplicaManager = nullptr;
|
||||
}
|
||||
|
||||
if (mServerType != ServerType::Master && mMasterPeer) {
|
||||
mMasterPeer->Shutdown(1000);
|
||||
RakNetworkFactory::DestroyRakPeerInterface(mMasterPeer);
|
||||
}
|
||||
}
|
||||
|
||||
void dServer::SetupForMasterConnection() {
|
||||
mMasterSocketDescriptor = SocketDescriptor(uint16_t(mPort + 1), 0);
|
||||
mMasterPeer = RakNetworkFactory::GetRakPeerInterface();
|
||||
bool ret = mMasterPeer->Startup(1, 30, &mMasterSocketDescriptor, 1);
|
||||
if (!ret) LOG("Failed MasterPeer Startup!");
|
||||
}
|
||||
|
||||
bool dServer::ConnectToMaster() {
|
||||
//LOG("Connection to Master %s:%d", mMasterIP.c_str(), mMasterPort);
|
||||
return mMasterPeer->Connect(mMasterIP.c_str(), mMasterPort, "3.25 DARKFLAME1", 15);
|
||||
}
|
||||
|
||||
void dServer::UpdateReplica() {
|
||||
mReplicaManager->Update(mPeer);
|
||||
return m_TransportLayer->IsConnected(sysAddr);
|
||||
}
|
||||
|
||||
int dServer::GetPing(const SystemAddress& sysAddr) const {
|
||||
return mPeer->GetAveragePing(sysAddr);
|
||||
return m_TransportLayer->GetPing(sysAddr);
|
||||
}
|
||||
|
||||
int dServer::GetLatestPing(const SystemAddress& sysAddr) const {
|
||||
return mPeer->GetLastPing(sysAddr);
|
||||
return m_TransportLayer->GetLatestPing(sysAddr);
|
||||
}
|
||||
|
||||
const std::string& dServer::GetIP() const {
|
||||
return m_TransportLayer->GetIP();
|
||||
}
|
||||
|
||||
const int dServer::GetPort() const {
|
||||
return m_TransportLayer->GetPort();
|
||||
}
|
||||
|
||||
const int dServer::GetMaxConnections() const {
|
||||
return m_TransportLayer->GetMaxConnections();
|
||||
}
|
||||
|
||||
const bool dServer::GetIsEncrypted() const {
|
||||
return m_TransportLayer->GetIsEncrypted();
|
||||
}
|
||||
|
||||
const bool dServer::GetIsInternal() const {
|
||||
return m_TransportLayer->GetIsInternal();
|
||||
}
|
||||
|
||||
const bool dServer::GetIsOkay() const {
|
||||
return m_TransportLayer->GetIsOkay();
|
||||
}
|
||||
|
||||
Logger* dServer::GetLogger() const {
|
||||
return m_TransportLayer->GetLogger();
|
||||
}
|
||||
|
||||
const bool dServer::GetIsConnectedToMaster() const {
|
||||
return m_TransportLayer->GetIsConnectedToManager();
|
||||
}
|
||||
|
||||
const unsigned int dServer::GetZoneID() const {
|
||||
return m_TransportLayer->GetZoneID();
|
||||
}
|
||||
|
||||
const int dServer::GetInstanceID() const {
|
||||
return m_TransportLayer->GetInstanceID();
|
||||
}
|
||||
|
||||
const ServerType dServer::GetServerType() const {
|
||||
return m_TransportLayer->GetServerType();
|
||||
}
|
||||
|
||||
const std::unique_ptr<TransportLayer>& dServer::GetTransportLayer() const {
|
||||
return m_TransportLayer;
|
||||
}
|
||||
|
||||
const TransportType dServer::GetTransportType() const {
|
||||
return m_TransportType;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user