Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/io/net_socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ class NetSocket : public RefCounted {
virtual void set_ipv6_only_enabled(bool p_enabled) = 0;
virtual void set_tcp_no_delay_enabled(bool p_enabled) = 0;
virtual void set_reuse_address_enabled(bool p_enabled) = 0;
virtual void set_reuse_port_enabled(bool p_enabled) = 0;
virtual Error join_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) = 0;
virtual Error leave_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) = 0;

Expand Down
15 changes: 15 additions & 0 deletions core/io/packet_peer_udp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@ void PacketPeerUDP::set_broadcast_enabled(bool p_enabled) {
}
}

void PacketPeerUDP::set_reuse_address_enabled(bool p_reuse_addr) {
ERR_FAIL_COND(udp_server);
reuse_addr = p_reuse_addr;
}

void PacketPeerUDP::set_reuse_port_enabled(bool p_reuse_port) {
ERR_FAIL_COND(udp_server);
reuse_port = p_reuse_port;
}

Error PacketPeerUDP::join_multicast_group(IPAddress p_multi_address, const String &p_if_name) {
ERR_FAIL_COND_V(udp_server, ERR_LOCKED);
ERR_FAIL_COND_V(_sock.is_null(), ERR_UNAVAILABLE);
Expand Down Expand Up @@ -194,6 +204,9 @@ Error PacketPeerUDP::bind(int p_port, const IPAddress &p_bind_address, int p_rec

_sock->set_blocking_enabled(false);
_sock->set_broadcasting_enabled(broadcast);
_sock->set_reuse_address_enabled(reuse_addr);
_sock->set_reuse_port_enabled(reuse_port);

NetSocket::Address addr(p_bind_address, p_port);
err = _sock->bind(addr);

Expand Down Expand Up @@ -370,6 +383,8 @@ void PacketPeerUDP::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_local_port"), &PacketPeerUDP::get_local_port);
ClassDB::bind_method(D_METHOD("set_dest_address", "host", "port"), &PacketPeerUDP::_set_dest_address);
ClassDB::bind_method(D_METHOD("set_broadcast_enabled", "enabled"), &PacketPeerUDP::set_broadcast_enabled);
ClassDB::bind_method(D_METHOD("set_reuse_address_enabled", "reuse_address"), &PacketPeerUDP::set_reuse_address_enabled);
ClassDB::bind_method(D_METHOD("set_reuse_port_enabled", "reuse_port"), &PacketPeerUDP::set_reuse_port_enabled);
ClassDB::bind_method(D_METHOD("join_multicast_group", "multicast_address", "interface_name"), &PacketPeerUDP::join_multicast_group);
ClassDB::bind_method(D_METHOD("leave_multicast_group", "multicast_address", "interface_name"), &PacketPeerUDP::leave_multicast_group);
}
Expand Down
4 changes: 4 additions & 0 deletions core/io/packet_peer_udp.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ class PacketPeerUDP : public PacketPeer {
bool connected = false;
bool blocking = true;
bool broadcast = false;
bool reuse_addr = false;
bool reuse_port = false;
UDPServer *udp_server = nullptr;
Ref<NetSocket> _sock;

Expand Down Expand Up @@ -90,6 +92,8 @@ class PacketPeerUDP : public PacketPeer {
int get_available_packet_count() const override;
int get_max_packet_size() const override;
void set_broadcast_enabled(bool p_enabled);
void set_reuse_address_enabled(bool p_reuse_addr);
void set_reuse_port_enabled(bool p_reuse_port);
Error join_multicast_group(IPAddress p_multi_address, const String &p_if_name);
Error leave_multicast_group(IPAddress p_multi_address, const String &p_if_name);

Expand Down
15 changes: 15 additions & 0 deletions doc/classes/PacketPeerUDP.xml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,21 @@
[b]Note:[/b] [method set_broadcast_enabled] must be enabled before sending packets to a broadcast address (e.g. [code]255.255.255.255[/code]).
</description>
</method>
<method name="set_reuse_address_enabled">
<return type="void" />
<param index="0" name="reuse_address" type="bool" />
<description>
Enable or disable [code]SO_REUSEADDR[/code] on the underlying socket. This option is disabled by default.
</description>
</method>
<method name="set_reuse_port_enabled">
<return type="void" />
<param index="0" name="reuse_port" type="bool" />
<description>
Enable or disable [code]SO_REUSEPORT[/code] on the underlying socket. This option is disabled by default.
[b]Note:[/b] Not supported on Windows, use [method set_reuse_address_enabled] instead.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it supported on every other platform?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested on MacOS and Linux. In theory IOS and Android should work, however they may need some permission set. Then again due to the nature of mobile oprating system, it would be unlikely you would be able / need to run 2 instances of the same godot project at the same time

</description>
</method>
<method name="wait">
<return type="int" enum="Error" />
<description>
Expand Down
13 changes: 11 additions & 2 deletions drivers/unix/net_socket_unix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -720,11 +720,20 @@ void NetSocketUnix::set_tcp_no_delay_enabled(bool p_enabled) {
}

void NetSocketUnix::set_reuse_address_enabled(bool p_enabled) {
ERR_FAIL_COND(!is_open());
ERR_FAIL_COND(_sock < 0);

int par = p_enabled ? 1 : 0;
if (setsockopt(_sock, SOL_SOCKET, SO_REUSEADDR, &par, sizeof(int)) < 0) {
WARN_PRINT("Unable to set socket REUSEADDR option.");
WARN_PRINT("Unable to set socket SO_REUSEADDR option.");
}
}

void NetSocketUnix::set_reuse_port_enabled(bool p_enabled) {
ERR_FAIL_COND(_sock < 0);

int par = p_enabled ? 1 : 0;
if (setsockopt(_sock, SOL_SOCKET, SO_REUSEPORT, &par, sizeof(int)) < 0) {
WARN_PRINT("Unable to set socket SO_REUSEPORT option.");
}
}

Expand Down
2 changes: 2 additions & 0 deletions drivers/unix/net_socket_unix.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ class NetSocketUnix : public NetSocket {
virtual void set_ipv6_only_enabled(bool p_enabled) override;
virtual void set_tcp_no_delay_enabled(bool p_enabled) override;
virtual void set_reuse_address_enabled(bool p_enabled) override;
virtual void set_reuse_port_enabled(bool p_enabled) override;

virtual Error join_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) override;
virtual Error leave_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) override;

Expand Down
14 changes: 11 additions & 3 deletions drivers/windows/net_socket_winsock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -547,10 +547,18 @@ void NetSocketWinSock::set_tcp_no_delay_enabled(bool p_enabled) {
}

void NetSocketWinSock::set_reuse_address_enabled(bool p_enabled) {
ERR_FAIL_COND(!is_open());
ERR_FAIL_COND(_sock == INVALID_SOCKET);

int par = p_enabled ? 1 : 0;
if (setsockopt(_sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&par, sizeof(int)) < 0) {
WARN_PRINT("Unable to set socket REUSEADDR option.");
}
}
Comment on lines +552 to +556
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Windows, enabling SO_REUSEADDR actually would also enable reuse port, very bad on TCP. Denying...
Windows does not have this option, SO_REUSEADDR in this magical world means SO_REUSEPORT

Since it was deliberately disabled and SO_REUSEADDR act like SO_REUSEPORT on Windows, it might be better to keep set_reuse_address_enabled as NOP and move this to set_reuse_port_enabled. To keep existing behavior intact.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. From doing a global search in the code base. The only times NetSocketWinSock::set_reuse_address_enabled is called is in /core/io/udp_server.cpp and /core/io/tcp_server.cpp on lines 109 and 56 respectively.

From my research I don't believe it would cause any issues with existing behavior. Then again i try to stay away from Windows as a whole, so im no expert.

Ill push a new commit that moves the logic into set_reuse_port_enabled and keep set_reuse_address_enabled as a NOP like it originally was


void NetSocketWinSock::set_reuse_port_enabled(bool p_enabled) {
ERR_FAIL_COND(_sock == INVALID_SOCKET);

// On Windows, enabling SO_REUSEADDR actually would also enable reuse port, very bad on TCP. Denying...
// Windows does not have this option, SO_REUSEADDR in this magical world means SO_REUSEPORT
// SO_REUSEPORT is not supported on windows, as its features are implemented as part of SO_REUSEADDR
}

bool NetSocketWinSock::is_open() const {
Expand Down
1 change: 1 addition & 0 deletions drivers/windows/net_socket_winsock.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ class NetSocketWinSock : public NetSocket {
virtual void set_ipv6_only_enabled(bool p_enabled) override;
virtual void set_tcp_no_delay_enabled(bool p_enabled) override;
virtual void set_reuse_address_enabled(bool p_enabled) override;
virtual void set_reuse_port_enabled(bool p_enabled) override;
virtual Error join_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) override;
virtual Error leave_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) override;

Expand Down
1 change: 1 addition & 0 deletions platform/web/net_socket_web.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class NetSocketWeb : public NetSocket {
virtual void set_ipv6_only_enabled(bool p_enabled) override {}
virtual void set_tcp_no_delay_enabled(bool p_enabled) override {}
virtual void set_reuse_address_enabled(bool p_enabled) override {}
virtual void set_reuse_port_enabled(bool p_enabled) override {}
virtual Error join_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) override { return ERR_UNAVAILABLE; }
virtual Error leave_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) override { return ERR_UNAVAILABLE; }

Expand Down
3 changes: 3 additions & 0 deletions tests/core/io/test_stream_peer_tcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class MockNetSocket : public NetSocket {
virtual void set_ipv6_only_enabled(bool p_enabled) override;
virtual void set_tcp_no_delay_enabled(bool p_enabled) override;
virtual void set_reuse_address_enabled(bool p_enabled) override;
virtual void set_reuse_port_enabled(bool p_enabled) override;
virtual Error join_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) override;
virtual Error leave_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) override;

Expand Down Expand Up @@ -198,6 +199,8 @@ void MockNetSocket::set_tcp_no_delay_enabled(bool p_enabled) {}

void MockNetSocket::set_reuse_address_enabled(bool p_enabled) {}

void MockNetSocket::set_reuse_port_enabled(bool p_enabled) {}

Error MockNetSocket::join_multicast_group(const IPAddress &p_multi_address, const String &p_if_name) {
return OK;
}
Expand Down