Add ENet option to disable server relaying.

It's useless when building fully authoritative servers, and prevents
various kinds of abuse.
This commit is contained in:
Fabio Alessandrelli 2019-11-26 17:21:19 +01:00
parent ef1008e53a
commit 7e592f9641
3 changed files with 57 additions and 27 deletions

View file

@ -116,6 +116,9 @@
The compression method used for network packets. These have different tradeoffs of compression speed versus bandwidth, you may need to test which one works best for your use case if you use compression at all.
</member>
<member name="refuse_new_connections" type="bool" setter="set_refuse_new_connections" getter="is_refusing_new_connections" override="true" default="false" />
<member name="server_relay" type="bool" setter="set_server_relay_enabled" getter="is_server_relay_enabled" default="true">
Enable or disable the server feature that notifies clients of other peers' connection/disconnection, and relays messages between them. When this option is [code]false[/code], clients won't be automatically notified of other peers and won't be able to send them packets through the server.
</member>
<member name="transfer_channel" type="int" setter="set_transfer_channel" getter="get_transfer_channel" default="-1">
Set the default channel to be used to transfer data. By default, this value is [code]-1[/code] which means that ENet will only use 2 channels, one for reliable and one for unreliable packets. Channel [code]0[/code] is reserved, and cannot be used. Setting this member to any value between [code]0[/code] and [member channel_count] (excluded) will force ENet to use that channel for sending data.
</member>

View file

@ -255,6 +255,10 @@ void NetworkedMultiplayerENet::poll() {
emit_signal("peer_connected", *new_id);
if (server) {
// Do not notify other peers when server_relay is disabled.
if (!server_relay)
break;
// Someone connected, notify all the peers available
for (Map<int, ENetPeer *>::Element *E = peer_map.front(); E; E = E->next()) {
@ -287,31 +291,34 @@ void NetworkedMultiplayerENet::poll() {
if (!server) {
emit_signal("connection_failed");
}
} else {
if (server) {
// Someone disconnected, notify everyone else
for (Map<int, ENetPeer *>::Element *E = peer_map.front(); E; E = E->next()) {
if (E->key() == *id)
continue;
ENetPacket *packet = enet_packet_create(NULL, 8, ENET_PACKET_FLAG_RELIABLE);
encode_uint32(SYSMSG_REMOVE_PEER, &packet->data[0]);
encode_uint32(*id, &packet->data[4]);
enet_peer_send(E->get(), SYSCH_CONFIG, packet);
}
} else {
emit_signal("server_disconnected");
close_connection();
return;
}
emit_signal("peer_disconnected", *id);
peer_map.erase(*id);
memdelete(id);
// Never fully connected.
break;
}
if (!server) {
// Client just disconnected from server.
emit_signal("server_disconnected");
close_connection();
return;
} else if (server_relay) {
// Server just received a client disconnect and is in relay mode, notify everyone else.
for (Map<int, ENetPeer *>::Element *E = peer_map.front(); E; E = E->next()) {
if (E->key() == *id)
continue;
ENetPacket *packet = enet_packet_create(NULL, 8, ENET_PACKET_FLAG_RELIABLE);
encode_uint32(SYSMSG_REMOVE_PEER, &packet->data[0]);
encode_uint32(*id, &packet->data[4]);
enet_peer_send(E->get(), SYSCH_CONFIG, packet);
}
}
emit_signal("peer_disconnected", *id);
peer_map.erase(*id);
memdelete(id);
} break;
case ENET_EVENT_TYPE_RECEIVE: {
@ -361,7 +368,13 @@ void NetworkedMultiplayerENet::poll() {
packet.from = *id;
if (target == 0) {
if (target == 1) {
// To myself and only myself
incoming_packets.push_back(packet);
} else if (!server_relay) {
// No other destination is allowed when server is not relaying
continue;
} else if (target == 0) {
// Re-send to everyone but sender :|
incoming_packets.push_back(packet);
@ -398,9 +411,6 @@ void NetworkedMultiplayerENet::poll() {
enet_packet_destroy(packet.packet);
}
} else if (target == 1) {
// To myself and only myself
incoming_packets.push_back(packet);
} else {
// To someone else, specifically
ERR_CONTINUE(!peer_map.has(target));
@ -827,6 +837,16 @@ bool NetworkedMultiplayerENet::is_always_ordered() const {
return always_ordered;
}
void NetworkedMultiplayerENet::set_server_relay_enabled(bool p_enabled) {
ERR_FAIL_COND(active);
server_relay = p_enabled;
}
bool NetworkedMultiplayerENet::is_server_relay_enabled() const {
return server_relay;
}
void NetworkedMultiplayerENet::_bind_methods() {
ClassDB::bind_method(D_METHOD("create_server", "port", "max_clients", "in_bandwidth", "out_bandwidth"), &NetworkedMultiplayerENet::create_server, DEFVAL(32), DEFVAL(0), DEFVAL(0));
@ -847,11 +867,14 @@ void NetworkedMultiplayerENet::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_channel_count"), &NetworkedMultiplayerENet::get_channel_count);
ClassDB::bind_method(D_METHOD("set_always_ordered", "ordered"), &NetworkedMultiplayerENet::set_always_ordered);
ClassDB::bind_method(D_METHOD("is_always_ordered"), &NetworkedMultiplayerENet::is_always_ordered);
ClassDB::bind_method(D_METHOD("set_server_relay_enabled", "enabled"), &NetworkedMultiplayerENet::set_server_relay_enabled);
ClassDB::bind_method(D_METHOD("is_server_relay_enabled"), &NetworkedMultiplayerENet::is_server_relay_enabled);
ADD_PROPERTY(PropertyInfo(Variant::INT, "compression_mode", PROPERTY_HINT_ENUM, "None,Range Coder,FastLZ,ZLib,ZStd"), "set_compression_mode", "get_compression_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "transfer_channel"), "set_transfer_channel", "get_transfer_channel");
ADD_PROPERTY(PropertyInfo(Variant::INT, "channel_count"), "set_channel_count", "get_channel_count");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "always_ordered"), "set_always_ordered", "is_always_ordered");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "server_relay"), "set_server_relay_enabled", "is_server_relay_enabled");
BIND_ENUM_CONSTANT(COMPRESS_NONE);
BIND_ENUM_CONSTANT(COMPRESS_RANGE_CODER);
@ -865,6 +888,7 @@ NetworkedMultiplayerENet::NetworkedMultiplayerENet() {
active = false;
server = false;
refuse_connections = false;
server_relay = true;
unique_id = 0;
target_peer = 0;
current_packet.packet = NULL;

View file

@ -78,6 +78,7 @@ private:
ENetHost *host;
bool refuse_connections;
bool server_relay;
ConnectionStatus connection_status;
@ -158,6 +159,8 @@ public:
int get_channel_count() const;
void set_always_ordered(bool p_ordered);
bool is_always_ordered() const;
void set_server_relay_enabled(bool p_enabled);
bool is_server_relay_enabled() const;
NetworkedMultiplayerENet();
~NetworkedMultiplayerENet();