Networking changes (needs P2P testing, requires clients to update unfortunately)
This commit is contained in:
parent
9e7a2e9bb9
commit
951fe787c4
@ -4,6 +4,8 @@
|
|||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "StarString_windows.hpp"
|
||||||
#else
|
#else
|
||||||
#ifdef STAR_SYSTEM_FREEBSD
|
#ifdef STAR_SYSTEM_FREEBSD
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@ -42,17 +44,19 @@ static WindowsSocketInitializer g_windowsSocketInitializer;
|
|||||||
|
|
||||||
inline String netErrorString() {
|
inline String netErrorString() {
|
||||||
#ifdef STAR_SYSTEM_WINDOWS
|
#ifdef STAR_SYSTEM_WINDOWS
|
||||||
LPVOID lpMsgBuf = NULL;
|
LPWSTR lpMsgBuf = NULL;
|
||||||
|
int error = WSAGetLastError();
|
||||||
|
|
||||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
|
||||||
|
| FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK,
|
||||||
NULL,
|
NULL,
|
||||||
WSAGetLastError(),
|
error,
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
||||||
(LPTSTR)&lpMsgBuf,
|
(LPTSTR)&lpMsgBuf,
|
||||||
0,
|
0,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
String result = String((char*)lpMsgBuf);
|
String result = strf("{} - {}", error, utf16ToString(lpMsgBuf));
|
||||||
|
|
||||||
if (lpMsgBuf != NULL)
|
if (lpMsgBuf != NULL)
|
||||||
LocalFree(lpMsgBuf);
|
LocalFree(lpMsgBuf);
|
||||||
|
@ -66,6 +66,9 @@ Maybe<PacketStats> PacketSocket::outgoingStats() const {
|
|||||||
void PacketSocket::setLegacy(bool legacy) { m_legacy = legacy; }
|
void PacketSocket::setLegacy(bool legacy) { m_legacy = legacy; }
|
||||||
bool PacketSocket::legacy() const { return m_legacy; }
|
bool PacketSocket::legacy() const { return m_legacy; }
|
||||||
|
|
||||||
|
void CompressedPacketSocket::setCompressionStreamEnabled(bool enabled) { m_useCompressionStream = enabled; }
|
||||||
|
bool CompressedPacketSocket::compressionStreamEnabled() const { return m_useCompressionStream; }
|
||||||
|
|
||||||
pair<LocalPacketSocketUPtr, LocalPacketSocketUPtr> LocalPacketSocket::openPair() {
|
pair<LocalPacketSocketUPtr, LocalPacketSocketUPtr> LocalPacketSocket::openPair() {
|
||||||
auto lhsIncomingPipe = make_shared<Pipe>();
|
auto lhsIncomingPipe = make_shared<Pipe>();
|
||||||
auto rhsIncomingPipe = make_shared<Pipe>();
|
auto rhsIncomingPipe = make_shared<Pipe>();
|
||||||
@ -146,7 +149,7 @@ void TcpPacketSocket::close() {
|
|||||||
|
|
||||||
void TcpPacketSocket::sendPackets(List<PacketPtr> packets) {
|
void TcpPacketSocket::sendPackets(List<PacketPtr> packets) {
|
||||||
auto it = makeSMutableIterator(packets);
|
auto it = makeSMutableIterator(packets);
|
||||||
if (m_useCompressionStream) {
|
if (compressionStreamEnabled()) {
|
||||||
DataStreamBuffer outBuffer;
|
DataStreamBuffer outBuffer;
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
PacketPtr& packet = it.next();
|
PacketPtr& packet = it.next();
|
||||||
@ -233,7 +236,7 @@ List<PacketPtr> TcpPacketSocket::receivePackets() {
|
|||||||
if (packetSize > ds.remaining())
|
if (packetSize > ds.remaining())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
m_incomingStats.mix(packetType, packetSize, !m_useCompressionStream);
|
m_incomingStats.mix(packetType, packetSize, !compressionStreamEnabled());
|
||||||
|
|
||||||
DataStreamExternalBuffer packetStream(ds.ptr() + ds.pos(), packetSize);
|
DataStreamExternalBuffer packetStream(ds.ptr() + ds.pos(), packetSize);
|
||||||
ByteArray uncompressed;
|
ByteArray uncompressed;
|
||||||
@ -280,19 +283,17 @@ bool TcpPacketSocket::writeData() {
|
|||||||
bool dataSent = false;
|
bool dataSent = false;
|
||||||
try {
|
try {
|
||||||
if (!m_outputBuffer.empty()) {
|
if (!m_outputBuffer.empty()) {
|
||||||
if (m_useCompressionStream) {
|
if (compressionStreamEnabled()) {
|
||||||
auto compressed = m_compressionStream.compress(m_outputBuffer);
|
auto compressedBuffer = m_compressionStream.compress(m_outputBuffer);
|
||||||
m_outputBuffer.clear();
|
m_outputBuffer.clear();
|
||||||
|
|
||||||
m_compressedBuffer.append(compressed.ptr(), compressed.size());
|
|
||||||
do {
|
do {
|
||||||
size_t written = m_socket->send(m_compressedBuffer.ptr(), m_compressedBuffer.size());
|
size_t written = m_socket->send(compressedBuffer.ptr(), compressedBuffer.size());
|
||||||
if (written > 0) {
|
if (written > 0) {
|
||||||
dataSent = true;
|
dataSent = true;
|
||||||
m_compressedBuffer.trimLeft(written);
|
compressedBuffer.trimLeft(written);
|
||||||
m_outgoingStats.mix(written);
|
m_outgoingStats.mix(written);
|
||||||
}
|
}
|
||||||
} while (!m_compressedBuffer.empty());
|
} while (!compressedBuffer.empty());
|
||||||
} else {
|
} else {
|
||||||
do {
|
do {
|
||||||
size_t written = m_socket->send(m_outputBuffer.ptr(), m_outputBuffer.size());
|
size_t written = m_socket->send(m_outputBuffer.ptr(), m_outputBuffer.size());
|
||||||
@ -321,10 +322,10 @@ bool TcpPacketSocket::readData() {
|
|||||||
if (readAmount == 0)
|
if (readAmount == 0)
|
||||||
break;
|
break;
|
||||||
dataReceived = true;
|
dataReceived = true;
|
||||||
if (m_useCompressionStream) {
|
if (compressionStreamEnabled()) {
|
||||||
m_incomingStats.mix(readAmount);
|
m_incomingStats.mix(readAmount);
|
||||||
auto decompressed = m_decompressionStream.decompress(readBuffer, readAmount);
|
auto decompressed = m_decompressionStream.decompress(readBuffer, readAmount);
|
||||||
m_inputBuffer.append(decompressed.ptr(), decompressed.size());
|
m_inputBuffer.append(decompressed);
|
||||||
} else {
|
} else {
|
||||||
m_inputBuffer.append(readBuffer, readAmount);
|
m_inputBuffer.append(readBuffer, readAmount);
|
||||||
}
|
}
|
||||||
@ -347,7 +348,6 @@ Maybe<PacketStats> TcpPacketSocket::outgoingStats() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TcpPacketSocket::setLegacy(bool legacy) {
|
void TcpPacketSocket::setLegacy(bool legacy) {
|
||||||
m_useCompressionStream = !legacy;
|
|
||||||
PacketSocket::setLegacy(legacy);
|
PacketSocket::setLegacy(legacy);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,43 +368,58 @@ void P2PPacketSocket::close() {
|
|||||||
void P2PPacketSocket::sendPackets(List<PacketPtr> packets) {
|
void P2PPacketSocket::sendPackets(List<PacketPtr> packets) {
|
||||||
auto it = makeSMutableIterator(packets);
|
auto it = makeSMutableIterator(packets);
|
||||||
|
|
||||||
while (it.hasNext()) {
|
if (compressionStreamEnabled()) {
|
||||||
PacketType currentType = it.peekNext()->type();
|
|
||||||
PacketCompressionMode currentCompressionMode = it.peekNext()->compressionMode();
|
|
||||||
|
|
||||||
DataStreamBuffer packetBuffer;
|
|
||||||
while (it.hasNext()
|
|
||||||
&& it.peekNext()->type() == currentType
|
|
||||||
&& it.peekNext()->compressionMode() == currentCompressionMode) {
|
|
||||||
if (legacy())
|
|
||||||
it.next()->writeLegacy(packetBuffer);
|
|
||||||
else
|
|
||||||
it.next()->write(packetBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Packets must read and write actual data, because this is used to
|
|
||||||
// determine packet count
|
|
||||||
starAssert(!packetBuffer.empty());
|
|
||||||
|
|
||||||
ByteArray compressedPackets;
|
|
||||||
bool mustCompress = currentCompressionMode == PacketCompressionMode::Enabled;
|
|
||||||
bool perhapsCompress = currentCompressionMode == PacketCompressionMode::Automatic && packetBuffer.size() > 64;
|
|
||||||
if (mustCompress || perhapsCompress)
|
|
||||||
compressedPackets = compressData(packetBuffer.data());
|
|
||||||
|
|
||||||
DataStreamBuffer outBuffer;
|
DataStreamBuffer outBuffer;
|
||||||
outBuffer.write(currentType);
|
while (it.hasNext()) {
|
||||||
|
PacketPtr& packet = it.next();
|
||||||
if (!compressedPackets.empty() && (mustCompress || compressedPackets.size() < packetBuffer.size())) {
|
auto packetType = packet->type();
|
||||||
outBuffer.write<bool>(true);
|
DataStreamBuffer packetBuffer;
|
||||||
outBuffer.writeData(compressedPackets.ptr(), compressedPackets.size());
|
packet->write(packetBuffer);
|
||||||
m_outgoingStats.mix(currentType, compressedPackets.size());
|
outBuffer.write(packetType);
|
||||||
} else {
|
outBuffer.writeVlqI((int)packetBuffer.size());
|
||||||
outBuffer.write<bool>(false);
|
|
||||||
outBuffer.writeData(packetBuffer.ptr(), packetBuffer.size());
|
outBuffer.writeData(packetBuffer.ptr(), packetBuffer.size());
|
||||||
m_outgoingStats.mix(currentType, packetBuffer.size());
|
m_outgoingStats.mix(packetType, packetBuffer.size(), false);
|
||||||
|
}
|
||||||
|
m_outputMessages.append(m_compressionStream.compress(outBuffer.data()));
|
||||||
|
} else {
|
||||||
|
while (it.hasNext()) {
|
||||||
|
PacketType currentType = it.peekNext()->type();
|
||||||
|
PacketCompressionMode currentCompressionMode = it.peekNext()->compressionMode();
|
||||||
|
|
||||||
|
DataStreamBuffer packetBuffer;
|
||||||
|
while (it.hasNext()
|
||||||
|
&& it.peekNext()->type() == currentType
|
||||||
|
&& it.peekNext()->compressionMode() == currentCompressionMode) {
|
||||||
|
if (legacy())
|
||||||
|
it.next()->writeLegacy(packetBuffer);
|
||||||
|
else
|
||||||
|
it.next()->write(packetBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Packets must read and write actual data, because this is used to
|
||||||
|
// determine packet count
|
||||||
|
starAssert(!packetBuffer.empty());
|
||||||
|
|
||||||
|
ByteArray compressedPackets;
|
||||||
|
bool mustCompress = currentCompressionMode == PacketCompressionMode::Enabled;
|
||||||
|
bool perhapsCompress = currentCompressionMode == PacketCompressionMode::Automatic && packetBuffer.size() > 64;
|
||||||
|
if (mustCompress || perhapsCompress)
|
||||||
|
compressedPackets = compressData(packetBuffer.data());
|
||||||
|
|
||||||
|
DataStreamBuffer outBuffer;
|
||||||
|
outBuffer.write(currentType);
|
||||||
|
|
||||||
|
if (!compressedPackets.empty() && (mustCompress || compressedPackets.size() < packetBuffer.size())) {
|
||||||
|
outBuffer.write<bool>(true);
|
||||||
|
outBuffer.writeData(compressedPackets.ptr(), compressedPackets.size());
|
||||||
|
m_outgoingStats.mix(currentType, compressedPackets.size());
|
||||||
|
} else {
|
||||||
|
outBuffer.write<bool>(false);
|
||||||
|
outBuffer.writeData(packetBuffer.ptr(), packetBuffer.size());
|
||||||
|
m_outgoingStats.mix(currentType, packetBuffer.size());
|
||||||
|
}
|
||||||
|
m_outputMessages.append(outBuffer.takeData());
|
||||||
}
|
}
|
||||||
m_outputMessages.append(outBuffer.takeData());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -422,9 +437,9 @@ List<PacketPtr> P2PPacketSocket::receivePackets() {
|
|||||||
if (packetCompressed)
|
if (packetCompressed)
|
||||||
packetBytes = uncompressData(packetBytes);
|
packetBytes = uncompressData(packetBytes);
|
||||||
|
|
||||||
m_incomingStats.mix(packetType, packetSize);
|
m_incomingStats.mix(packetType, packetSize, !compressionStreamEnabled());
|
||||||
|
|
||||||
DataStreamBuffer packetStream(std::move(packetBytes));
|
DataStreamExternalBuffer packetStream(packetBytes);
|
||||||
do {
|
do {
|
||||||
PacketPtr packet = createPacket(packetType);
|
PacketPtr packet = createPacket(packetType);
|
||||||
packet->setCompressionMode(packetCompressed ? PacketCompressionMode::Enabled : PacketCompressionMode::Disabled);
|
packet->setCompressionMode(packetCompressed ? PacketCompressionMode::Enabled : PacketCompressionMode::Disabled);
|
||||||
@ -468,7 +483,10 @@ bool P2PPacketSocket::readData() {
|
|||||||
|
|
||||||
if (m_socket) {
|
if (m_socket) {
|
||||||
while (auto message = m_socket->receiveMessage()) {
|
while (auto message = m_socket->receiveMessage()) {
|
||||||
m_inputMessages.append(message.take());
|
m_incomingStats.mix(message->size());
|
||||||
|
m_inputMessages.append(compressionStreamEnabled()
|
||||||
|
? m_decompressionStream.decompress(*message)
|
||||||
|
: *message);
|
||||||
workDone = true;
|
workDone = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,20 @@ public:
|
|||||||
virtual void setLegacy(bool legacy);
|
virtual void setLegacy(bool legacy);
|
||||||
virtual bool legacy() const;
|
virtual bool legacy() const;
|
||||||
private:
|
private:
|
||||||
bool m_legacy = true;
|
bool m_legacy = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CompressedPacketSocket : public PacketSocket {
|
||||||
|
public:
|
||||||
|
virtual ~CompressedPacketSocket() = default;
|
||||||
|
|
||||||
|
virtual void setCompressionStreamEnabled(bool enabled);
|
||||||
|
virtual bool compressionStreamEnabled() const;
|
||||||
|
private:
|
||||||
|
bool m_useCompressionStream = false;
|
||||||
|
protected:
|
||||||
|
CompressionStream m_compressionStream;
|
||||||
|
DecompressionStream m_decompressionStream;
|
||||||
};
|
};
|
||||||
|
|
||||||
// PacketSocket for local communication.
|
// PacketSocket for local communication.
|
||||||
@ -112,7 +125,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Wraps a TCP socket into a PacketSocket.
|
// Wraps a TCP socket into a PacketSocket.
|
||||||
class TcpPacketSocket : public PacketSocket {
|
class TcpPacketSocket : public CompressedPacketSocket {
|
||||||
public:
|
public:
|
||||||
static TcpPacketSocketUPtr open(TcpSocketPtr socket);
|
static TcpPacketSocketUPtr open(TcpSocketPtr socket);
|
||||||
|
|
||||||
@ -140,14 +153,10 @@ private:
|
|||||||
PacketStatCollector m_outgoingStats;
|
PacketStatCollector m_outgoingStats;
|
||||||
ByteArray m_outputBuffer;
|
ByteArray m_outputBuffer;
|
||||||
ByteArray m_inputBuffer;
|
ByteArray m_inputBuffer;
|
||||||
bool m_useCompressionStream = false;
|
|
||||||
ByteArray m_compressedBuffer;
|
|
||||||
CompressionStream m_compressionStream;
|
|
||||||
DecompressionStream m_decompressionStream;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Wraps a P2PSocket into a PacketSocket
|
// Wraps a P2PSocket into a PacketSocket
|
||||||
class P2PPacketSocket : public PacketSocket {
|
class P2PPacketSocket : public CompressedPacketSocket {
|
||||||
public:
|
public:
|
||||||
static P2PPacketSocketUPtr open(P2PSocketUPtr socket);
|
static P2PPacketSocketUPtr open(P2PSocketUPtr socket);
|
||||||
|
|
||||||
|
@ -78,6 +78,11 @@ EnumMap<PacketType> const PacketTypeNames{
|
|||||||
{PacketType::SystemObjectSpawn, "SystemObjectSpawn"}
|
{PacketType::SystemObjectSpawn, "SystemObjectSpawn"}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
EnumMap<NetCompressionMode> const NetCompressionModeNames {
|
||||||
|
{NetCompressionMode::None, "None"},
|
||||||
|
{NetCompressionMode::Zstd, "Zstd"}
|
||||||
|
};
|
||||||
|
|
||||||
Packet::~Packet() {}
|
Packet::~Packet() {}
|
||||||
|
|
||||||
void Packet::readLegacy(DataStream& ds) { read(ds); }
|
void Packet::readLegacy(DataStream& ds) { read(ds); }
|
||||||
@ -187,15 +192,27 @@ void ProtocolRequestPacket::write(DataStream& ds) const {
|
|||||||
ds.write(requestProtocolVersion);
|
ds.write(requestProtocolVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
ProtocolResponsePacket::ProtocolResponsePacket(bool allowed)
|
ProtocolResponsePacket::ProtocolResponsePacket(bool allowed, Json info)
|
||||||
: allowed(allowed) {}
|
: allowed(allowed), info(info) {}
|
||||||
|
|
||||||
void ProtocolResponsePacket::read(DataStream& ds) {
|
void ProtocolResponsePacket::read(DataStream& ds) {
|
||||||
ds.read(allowed);
|
ds.read(allowed);
|
||||||
|
if (compressionMode() == PacketCompressionMode::Enabled) {
|
||||||
|
// gross hack for backwards compatibility with older OpenSB servers
|
||||||
|
// can be removed later
|
||||||
|
auto externalBuffer = as<DataStreamExternalBuffer>(&ds);
|
||||||
|
if (!externalBuffer || !externalBuffer->atEnd())
|
||||||
|
ds.read(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProtocolResponsePacket::writeLegacy(DataStream& ds) const {
|
||||||
|
ds.write(allowed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProtocolResponsePacket::write(DataStream& ds) const {
|
void ProtocolResponsePacket::write(DataStream& ds) const {
|
||||||
ds.write(allowed);
|
writeLegacy(ds);
|
||||||
|
ds.write(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnectSuccessPacket::ConnectSuccessPacket() {}
|
ConnectSuccessPacket::ConnectSuccessPacket() {}
|
||||||
|
@ -116,16 +116,23 @@ enum class PacketType : uint8_t {
|
|||||||
};
|
};
|
||||||
extern EnumMap<PacketType> const PacketTypeNames;
|
extern EnumMap<PacketType> const PacketTypeNames;
|
||||||
|
|
||||||
|
enum class NetCompressionMode : uint8_t {
|
||||||
|
None,
|
||||||
|
Zstd
|
||||||
|
};
|
||||||
|
extern EnumMap<NetCompressionMode> const NetCompressionModeNames;
|
||||||
|
|
||||||
enum class PacketCompressionMode : uint8_t {
|
enum class PacketCompressionMode : uint8_t {
|
||||||
Disabled,
|
Disabled,
|
||||||
Enabled,
|
Automatic,
|
||||||
Automatic
|
Enabled
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Packet {
|
struct Packet {
|
||||||
virtual ~Packet();
|
virtual ~Packet();
|
||||||
|
|
||||||
virtual PacketType type() const = 0;
|
virtual PacketType type() const = 0;
|
||||||
|
virtual String const& typeName() const = 0;
|
||||||
|
|
||||||
virtual void readLegacy(DataStream& ds);
|
virtual void readLegacy(DataStream& ds);
|
||||||
virtual void read(DataStream& ds) = 0;
|
virtual void read(DataStream& ds) = 0;
|
||||||
@ -149,6 +156,7 @@ struct PacketBase : public Packet {
|
|||||||
static PacketType const Type = PacketT;
|
static PacketType const Type = PacketT;
|
||||||
|
|
||||||
PacketType type() const override { return Type; }
|
PacketType type() const override { return Type; }
|
||||||
|
String const& typeName() const override { return PacketTypeNames.getRight(Type); }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ProtocolRequestPacket : PacketBase<PacketType::ProtocolRequest> {
|
struct ProtocolRequestPacket : PacketBase<PacketType::ProtocolRequest> {
|
||||||
@ -162,12 +170,14 @@ struct ProtocolRequestPacket : PacketBase<PacketType::ProtocolRequest> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct ProtocolResponsePacket : PacketBase<PacketType::ProtocolResponse> {
|
struct ProtocolResponsePacket : PacketBase<PacketType::ProtocolResponse> {
|
||||||
ProtocolResponsePacket(bool allowed = false);
|
ProtocolResponsePacket(bool allowed = false, Json info = {});
|
||||||
|
|
||||||
void read(DataStream& ds) override;
|
void read(DataStream& ds) override;
|
||||||
|
void writeLegacy(DataStream& ds) const override;
|
||||||
void write(DataStream& ds) const override;
|
void write(DataStream& ds) const override;
|
||||||
|
|
||||||
bool allowed;
|
bool allowed;
|
||||||
|
Json info;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ServerDisconnectPacket : PacketBase<PacketType::ServerDisconnect> {
|
struct ServerDisconnectPacket : PacketBase<PacketType::ServerDisconnect> {
|
||||||
|
@ -76,6 +76,9 @@ R"JSON(
|
|||||||
"allowAdminCommands" : true,
|
"allowAdminCommands" : true,
|
||||||
"allowAdminCommandsFromAnyone" : false,
|
"allowAdminCommandsFromAnyone" : false,
|
||||||
"anonymousConnectionsAreAdmin" : false,
|
"anonymousConnectionsAreAdmin" : false,
|
||||||
|
"connectionSettings" : {
|
||||||
|
"compression" : "Zstd"
|
||||||
|
},
|
||||||
|
|
||||||
"clientP2PJoinable" : true,
|
"clientP2PJoinable" : true,
|
||||||
"clientIPJoinable" : false,
|
"clientIPJoinable" : false,
|
||||||
|
@ -81,8 +81,8 @@ Maybe<String> UniverseClient::connect(UniverseConnection connection, bool allowA
|
|||||||
{
|
{
|
||||||
auto protocolRequest = make_shared<ProtocolRequestPacket>(StarProtocolVersion);
|
auto protocolRequest = make_shared<ProtocolRequestPacket>(StarProtocolVersion);
|
||||||
protocolRequest->setCompressionMode(PacketCompressionMode::Enabled);
|
protocolRequest->setCompressionMode(PacketCompressionMode::Enabled);
|
||||||
// Signal that we're OpenStarbound. Vanilla Starbound only compresses packets above 64 bytes - by forcing it we can communicate this.
|
// Signal that we're OpenStarbound. Vanilla Starbound only compresses
|
||||||
// If you know a less cursed way, please let me know.
|
// packets above 64 bytes - by forcing it, we can communicate this.
|
||||||
connection.pushSingle(protocolRequest);
|
connection.pushSingle(protocolRequest);
|
||||||
}
|
}
|
||||||
connection.sendAll(timeout);
|
connection.sendAll(timeout);
|
||||||
@ -94,8 +94,24 @@ Maybe<String> UniverseClient::connect(UniverseConnection connection, bool allowA
|
|||||||
else if (!protocolResponsePacket->allowed)
|
else if (!protocolResponsePacket->allowed)
|
||||||
return String(strf("Join failed! Server does not support connections with protocol version {}", StarProtocolVersion));
|
return String(strf("Join failed! Server does not support connections with protocol version {}", StarProtocolVersion));
|
||||||
|
|
||||||
m_legacyServer = protocolResponsePacket->compressionMode() != PacketCompressionMode::Enabled; // True if server is vanilla
|
if (!(m_legacyServer = protocolResponsePacket->compressionMode() != PacketCompressionMode::Enabled)) {
|
||||||
connection.setLegacy(m_legacyServer);
|
if (auto compressedSocket = as<CompressedPacketSocket>(&connection.packetSocket())) {
|
||||||
|
if (protocolResponsePacket->info) {
|
||||||
|
auto compressionName = protocolResponsePacket->info.getString("compression", "None");
|
||||||
|
auto compressionMode = NetCompressionModeNames.maybeLeft(compressionName);
|
||||||
|
if (!compressionMode)
|
||||||
|
return String(strf("Join failed! Unknown net stream connection type '{}'", compressionName));
|
||||||
|
|
||||||
|
Logger::info("UniverseClient: Using '{}' network stream compression", NetCompressionModeNames.getRight(*compressionMode));
|
||||||
|
compressedSocket->setCompressionStreamEnabled(compressionMode == NetCompressionMode::Zstd);
|
||||||
|
} else if (!m_legacyServer) {
|
||||||
|
Logger::info("UniverseClient: Defaulting to Zstd network stream compression (older server version)");
|
||||||
|
compressedSocket->setCompressionStreamEnabled(true);// old OpenSB server version always expects it!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
connection.packetSocket().setLegacy(m_legacyServer);
|
||||||
|
|
||||||
connection.pushSingle(make_shared<ClientConnectPacket>(Root::singleton().assets()->digest(), allowAssetsMismatch, m_mainPlayer->uuid(), m_mainPlayer->name(),
|
connection.pushSingle(make_shared<ClientConnectPacket>(Root::singleton().assets()->digest(), allowAssetsMismatch, m_mainPlayer->uuid(), m_mainPlayer->name(),
|
||||||
m_mainPlayer->species(), m_playerStorage->loadShipData(m_mainPlayer->uuid()), m_mainPlayer->shipUpgrades(),
|
m_mainPlayer->species(), m_playerStorage->loadShipData(m_mainPlayer->uuid()), m_mainPlayer->shipUpgrades(),
|
||||||
m_mainPlayer->log()->introComplete(), account));
|
m_mainPlayer->log()->introComplete(), account));
|
||||||
|
@ -107,8 +107,8 @@ bool UniverseConnection::receiveAny(unsigned timeout) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UniverseConnection::setLegacy(bool legacy) {
|
PacketSocket& UniverseConnection::packetSocket() {
|
||||||
m_packetSocket->setLegacy(legacy);
|
return *m_packetSocket;
|
||||||
}
|
}
|
||||||
|
|
||||||
Maybe<PacketStats> UniverseConnection::incomingStats() const {
|
Maybe<PacketStats> UniverseConnection::incomingStats() const {
|
||||||
|
@ -48,7 +48,8 @@ public:
|
|||||||
// false if the timeout was reached with no packets receivable.
|
// false if the timeout was reached with no packets receivable.
|
||||||
bool receiveAny(unsigned timeout);
|
bool receiveAny(unsigned timeout);
|
||||||
|
|
||||||
void setLegacy(bool legacy);
|
// Returns a reference to the packet socket.
|
||||||
|
PacketSocket& packetSocket();
|
||||||
|
|
||||||
// Packet stats for the most recent one second window of activity incoming
|
// Packet stats for the most recent one second window of activity incoming
|
||||||
// and outgoing. Will only return valid stats if the underlying PacketSocket
|
// and outgoing. Will only return valid stats if the underlying PacketSocket
|
||||||
|
@ -1540,6 +1540,7 @@ void UniverseServer::acceptConnection(UniverseConnection connection, Maybe<HostA
|
|||||||
int clientWaitLimit = assets->json("/universe_server.config:clientWaitLimit").toInt();
|
int clientWaitLimit = assets->json("/universe_server.config:clientWaitLimit").toInt();
|
||||||
String serverAssetsMismatchMessage = assets->json("/universe_server.config:serverAssetsMismatchMessage").toString();
|
String serverAssetsMismatchMessage = assets->json("/universe_server.config:serverAssetsMismatchMessage").toString();
|
||||||
String clientAssetsMismatchMessage = assets->json("/universe_server.config:clientAssetsMismatchMessage").toString();
|
String clientAssetsMismatchMessage = assets->json("/universe_server.config:clientAssetsMismatchMessage").toString();
|
||||||
|
auto connectionSettings = configuration->get("connectionSettings");
|
||||||
|
|
||||||
RecursiveMutexLocker mainLocker(m_mainLock, false);
|
RecursiveMutexLocker mainLocker(m_mainLock, false);
|
||||||
|
|
||||||
@ -1551,6 +1552,7 @@ void UniverseServer::acceptConnection(UniverseConnection connection, Maybe<HostA
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool legacyClient = protocolRequest->compressionMode() != PacketCompressionMode::Enabled;
|
bool legacyClient = protocolRequest->compressionMode() != PacketCompressionMode::Enabled;
|
||||||
|
connection.packetSocket().setLegacy(legacyClient);
|
||||||
|
|
||||||
auto protocolResponse = make_shared<ProtocolResponsePacket>();
|
auto protocolResponse = make_shared<ProtocolResponsePacket>();
|
||||||
protocolResponse->setCompressionMode(PacketCompressionMode::Enabled); // Signal that we're OpenStarbound
|
protocolResponse->setCompressionMode(PacketCompressionMode::Enabled); // Signal that we're OpenStarbound
|
||||||
@ -1565,10 +1567,21 @@ void UniverseServer::acceptConnection(UniverseConnection connection, Maybe<HostA
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool useCompressionStream = false;
|
||||||
protocolResponse->allowed = true;
|
protocolResponse->allowed = true;
|
||||||
|
if (!legacyClient) {
|
||||||
|
auto compressionName = connectionSettings.getString("compression", "None");
|
||||||
|
auto compressionMode = NetCompressionModeNames.maybeLeft(compressionName).value(NetCompressionMode::None);
|
||||||
|
useCompressionStream = compressionMode == NetCompressionMode::Zstd;
|
||||||
|
protocolResponse->info = JsonObject{
|
||||||
|
{"compression", NetCompressionModeNames.getRight(compressionMode)}
|
||||||
|
};
|
||||||
|
}
|
||||||
connection.pushSingle(protocolResponse);
|
connection.pushSingle(protocolResponse);
|
||||||
connection.sendAll(clientWaitLimit);
|
connection.sendAll(clientWaitLimit);
|
||||||
connection.setLegacy(legacyClient);
|
|
||||||
|
if (auto compressedSocket = as<CompressedPacketSocket>(&connection.packetSocket()))
|
||||||
|
compressedSocket->setCompressionStreamEnabled(useCompressionStream);
|
||||||
|
|
||||||
String remoteAddressString = remoteAddress ? toString(*remoteAddress) : "local";
|
String remoteAddressString = remoteAddress ? toString(*remoteAddress) : "local";
|
||||||
Logger::info("UniverseServer: Awaiting connection info from {}, {} client", remoteAddressString, legacyClient ? "Starbound" : "OpenStarbound");
|
Logger::info("UniverseServer: Awaiting connection info from {}, {} client", remoteAddressString, legacyClient ? "Starbound" : "OpenStarbound");
|
||||||
|
@ -751,7 +751,7 @@ void WorldClient::handleIncomingPackets(List<PacketPtr> const& packets) {
|
|||||||
|
|
||||||
for (auto const& packet : packets) {
|
for (auto const& packet : packets) {
|
||||||
if (!inWorld() && !is<WorldStartPacket>(packet))
|
if (!inWorld() && !is<WorldStartPacket>(packet))
|
||||||
Logger::error("WorldClient received packet type {} while not in world", PacketTypeNames.getRight(packet->type()));
|
Logger::error("WorldClient received packet type {} while not in world", packet->typeName());
|
||||||
|
|
||||||
if (auto worldStartPacket = as<WorldStartPacket>(packet)) {
|
if (auto worldStartPacket = as<WorldStartPacket>(packet)) {
|
||||||
initWorld(*worldStartPacket);
|
initWorld(*worldStartPacket);
|
||||||
|
Loading…
Reference in New Issue
Block a user