summaryrefslogtreecommitdiffstats
path: root/modules/enet/networked_multiplayer_enet.cpp
diff options
context:
space:
mode:
authorFabio Alessandrelli <fabio.alessandrelli@gmail.com>2019-11-26 17:21:19 +0100
committerFabio Alessandrelli <fabio.alessandrelli@gmail.com>2019-11-27 11:48:31 +0100
commit7e592f96417e23c48b815c09e363d973f47b6f7f (patch)
tree299e8cb8b8c64417211613f61238281b4f6cf9ee /modules/enet/networked_multiplayer_enet.cpp
parentef1008e53a1409ea34911c293c7fb8ac2b96245e (diff)
downloadredot-engine-7e592f96417e23c48b815c09e363d973f47b6f7f.tar.gz
Add ENet option to disable server relaying.
It's useless when building fully authoritative servers, and prevents various kinds of abuse.
Diffstat (limited to 'modules/enet/networked_multiplayer_enet.cpp')
-rw-r--r--modules/enet/networked_multiplayer_enet.cpp70
1 files changed, 47 insertions, 23 deletions
diff --git a/modules/enet/networked_multiplayer_enet.cpp b/modules/enet/networked_multiplayer_enet.cpp
index 2f6ed5efc0..2f5307d041 100644
--- a/modules/enet/networked_multiplayer_enet.cpp
+++ b/modules/enet/networked_multiplayer_enet.cpp
@@ -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 {
+ // Never fully connected.
+ break;
+ }
- if (server) {
- // Someone disconnected, notify everyone else
- for (Map<int, ENetPeer *>::Element *E = peer_map.front(); E; E = E->next()) {
+ if (!server) {
- if (E->key() == *id)
- continue;
+ // Client just disconnected from server.
+ emit_signal("server_disconnected");
+ close_connection();
+ return;
+ } else if (server_relay) {
- 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;
- }
+ // 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;
- emit_signal("peer_disconnected", *id);
- peer_map.erase(*id);
- memdelete(id);
+ 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;