Skip to content

Commit

Permalink
Allow local port control on net_socket connections
Browse files Browse the repository at this point in the history
  • Loading branch information
dam authored and Faless committed Apr 12, 2021
1 parent cee5414 commit da8c231
Show file tree
Hide file tree
Showing 15 changed files with 162 additions and 36 deletions.
1 change: 1 addition & 0 deletions core/io/net_socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class NetSocket : public Reference {

virtual bool is_open() const = 0;
virtual int get_available_bytes() const = 0;
virtual Error get_socket_address(IP_Address *r_ip, uint16_t *r_port) const = 0;

virtual Error set_broadcasting_enabled(bool p_enabled) = 0; // Returns OK if the socket option has been set successfully.
virtual void set_blocking_enabled(bool p_enabled) = 0;
Expand Down
9 changes: 9 additions & 0 deletions core/io/packet_peer_udp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ Error PacketPeerUDP::listen(int p_port, const IP_Address &p_bind_address, int p_
ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE);
ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE);
ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V_MSG(p_port < 0 || p_port > 65535, ERR_INVALID_PARAMETER, "The local port number must be between 0 and 65535 (inclusive).");

Error err;
IP::Type ip_type = IP::TYPE_ANY;
Expand Down Expand Up @@ -210,6 +211,7 @@ Error PacketPeerUDP::connect_to_host(const IP_Address &p_host, int p_port) {
ERR_FAIL_COND_V(udp_server, ERR_LOCKED);
ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE);
ERR_FAIL_COND_V(!p_host.is_valid(), ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V_MSG(p_port < 1 || p_port > 65535, ERR_INVALID_PARAMETER, "The remote port number must be between 1 and 65535 (inclusive).");

Error err;

Expand Down Expand Up @@ -328,6 +330,12 @@ int PacketPeerUDP::get_packet_port() const {
return packet_port;
}

int PacketPeerUDP::get_local_port() const {
uint16_t local_port;
_sock->get_socket_address(nullptr, &local_port);
return local_port;
}

void PacketPeerUDP::set_dest_address(const IP_Address &p_address, int p_port) {
ERR_FAIL_COND_MSG(connected, "Destination address cannot be set for connected sockets");
peer_addr = p_address;
Expand All @@ -343,6 +351,7 @@ void PacketPeerUDP::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_connected_to_host"), &PacketPeerUDP::is_connected_to_host);
ClassDB::bind_method(D_METHOD("get_packet_ip"), &PacketPeerUDP::_get_packet_ip);
ClassDB::bind_method(D_METHOD("get_packet_port"), &PacketPeerUDP::get_packet_port);
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("join_multicast_group", "multicast_address", "interface_name"), &PacketPeerUDP::join_multicast_group);
Expand Down
1 change: 1 addition & 0 deletions core/io/packet_peer_udp.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ class PacketPeerUDP : public PacketPeer {

IP_Address get_packet_address() const;
int get_packet_port() const;
int get_local_port() const;
void set_dest_address(const IP_Address &p_address, int p_port);

Error put_packet(const uint8_t *p_buffer, int p_buffer_size) override;
Expand Down
43 changes: 35 additions & 8 deletions core/io/stream_peer_tcp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,21 +67,40 @@ void StreamPeerTCP::accept_socket(Ref<NetSocket> p_sock, IP_Address p_host, uint
peer_port = p_port;
}

Error StreamPeerTCP::connect_to_host(const IP_Address &p_host, uint16_t p_port) {
Error StreamPeerTCP::bind(int p_port, const IP_Address &p_host) {
ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE);
ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE);
ERR_FAIL_COND_V(!p_host.is_valid(), ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V_MSG(p_port < 0 || p_port > 65535, ERR_INVALID_PARAMETER, "The local port number must be between 0 and 65535 (inclusive).");

Error err;
IP::Type ip_type = p_host.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
if (p_host.is_wildcard()) {
ip_type = IP::TYPE_ANY;
}
Error err = _sock->open(NetSocket::TYPE_TCP, ip_type);
if (err != OK) {
return err;
}
_sock->set_blocking_enabled(false);
return _sock->bind(p_host, p_port);
}

err = _sock->open(NetSocket::TYPE_TCP, ip_type);
ERR_FAIL_COND_V(err != OK, FAILED);
Error StreamPeerTCP::connect_to_host(const IP_Address &p_host, int p_port) {
ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE);
ERR_FAIL_COND_V(status != STATUS_NONE, ERR_ALREADY_IN_USE);
ERR_FAIL_COND_V(!p_host.is_valid(), ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V_MSG(p_port < 1 || p_port > 65535, ERR_INVALID_PARAMETER, "The remote port number must be between 1 and 65535 (inclusive).");

_sock->set_blocking_enabled(false);
if (!_sock->is_open()) {
IP::Type ip_type = p_host.is_ipv4() ? IP::TYPE_IPV4 : IP::TYPE_IPV6;
Error err = _sock->open(NetSocket::TYPE_TCP, ip_type);
if (err != OK) {
return err;
}
_sock->set_blocking_enabled(false);
}

timeout = OS::get_singleton()->get_ticks_msec() + (((uint64_t)GLOBAL_GET("network/limits/tcp/connect_timeout_seconds")) * 1000);
err = _sock->connect_to_host(p_host, p_port);
Error err = _sock->connect_to_host(p_host, p_port);

if (err == OK) {
status = STATUS_CONNECTED;
Expand Down Expand Up @@ -300,10 +319,16 @@ IP_Address StreamPeerTCP::get_connected_host() const {
return peer_host;
}

uint16_t StreamPeerTCP::get_connected_port() const {
int StreamPeerTCP::get_connected_port() const {
return peer_port;
}

int StreamPeerTCP::get_local_port() const {
uint16_t local_port;
_sock->get_socket_address(nullptr, &local_port);
return local_port;
}

Error StreamPeerTCP::_connect(const String &p_address, int p_port) {
IP_Address ip;
if (p_address.is_valid_ip_address()) {
Expand All @@ -319,11 +344,13 @@ Error StreamPeerTCP::_connect(const String &p_address, int p_port) {
}

void StreamPeerTCP::_bind_methods() {
ClassDB::bind_method(D_METHOD("bind", "port", "host"), &StreamPeerTCP::bind, DEFVAL("*"));
ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port"), &StreamPeerTCP::_connect);
ClassDB::bind_method(D_METHOD("is_connected_to_host"), &StreamPeerTCP::is_connected_to_host);
ClassDB::bind_method(D_METHOD("get_status"), &StreamPeerTCP::get_status);
ClassDB::bind_method(D_METHOD("get_connected_host"), &StreamPeerTCP::get_connected_host);
ClassDB::bind_method(D_METHOD("get_connected_port"), &StreamPeerTCP::get_connected_port);
ClassDB::bind_method(D_METHOD("get_local_port"), &StreamPeerTCP::get_local_port);
ClassDB::bind_method(D_METHOD("disconnect_from_host"), &StreamPeerTCP::disconnect_from_host);
ClassDB::bind_method(D_METHOD("set_no_delay", "enabled"), &StreamPeerTCP::set_no_delay);

Expand Down
6 changes: 4 additions & 2 deletions core/io/stream_peer_tcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,12 @@ class StreamPeerTCP : public StreamPeer {
public:
void accept_socket(Ref<NetSocket> p_sock, IP_Address p_host, uint16_t p_port);

Error connect_to_host(const IP_Address &p_host, uint16_t p_port);
Error bind(int p_port, const IP_Address &p_host);
Error connect_to_host(const IP_Address &p_host, int p_port);
bool is_connected_to_host() const;
IP_Address get_connected_host() const;
uint16_t get_connected_port() const;
int get_connected_port() const;
int get_local_port() const;
void disconnect_from_host();

int get_available_bytes() const override;
Expand Down
8 changes: 8 additions & 0 deletions core/io/tcp_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ void TCP_Server::_bind_methods() {
ClassDB::bind_method(D_METHOD("listen", "port", "bind_address"), &TCP_Server::listen, DEFVAL("*"));
ClassDB::bind_method(D_METHOD("is_connection_available"), &TCP_Server::is_connection_available);
ClassDB::bind_method(D_METHOD("is_listening"), &TCP_Server::is_listening);
ClassDB::bind_method(D_METHOD("get_local_port"), &TCP_Server::get_local_port);
ClassDB::bind_method(D_METHOD("take_connection"), &TCP_Server::take_connection);
ClassDB::bind_method(D_METHOD("stop"), &TCP_Server::stop);
}
Expand All @@ -42,6 +43,7 @@ Error TCP_Server::listen(uint16_t p_port, const IP_Address &p_bind_address) {
ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE);
ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE);
ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V_MSG(p_port < 0 || p_port > 65535, ERR_INVALID_PARAMETER, "The local port number must be between 0 and 65535 (inclusive).");

Error err;
IP::Type ip_type = IP::TYPE_ANY;
Expand Down Expand Up @@ -74,6 +76,12 @@ Error TCP_Server::listen(uint16_t p_port, const IP_Address &p_bind_address) {
return OK;
}

int TCP_Server::get_local_port() const {
uint16_t local_port;
_sock->get_socket_address(nullptr, &local_port);
return local_port;
}

bool TCP_Server::is_listening() const {
ERR_FAIL_COND_V(!_sock.is_valid(), false);

Expand Down
1 change: 1 addition & 0 deletions core/io/tcp_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class TCP_Server : public Reference {

public:
Error listen(uint16_t p_port, const IP_Address &p_bind_address = IP_Address("*"));
int get_local_port() const;
bool is_listening() const;
bool is_connection_available() const;
Ref<StreamPeerTCP> take_connection();
Expand Down
12 changes: 8 additions & 4 deletions core/io/udp_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ void UDPServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("listen", "port", "bind_address"), &UDPServer::listen, DEFVAL("*"));
ClassDB::bind_method(D_METHOD("poll"), &UDPServer::poll);
ClassDB::bind_method(D_METHOD("is_connection_available"), &UDPServer::is_connection_available);
ClassDB::bind_method(D_METHOD("get_local_port"), &UDPServer::get_local_port);
ClassDB::bind_method(D_METHOD("is_listening"), &UDPServer::is_listening);
ClassDB::bind_method(D_METHOD("take_connection"), &UDPServer::take_connection);
ClassDB::bind_method(D_METHOD("stop"), &UDPServer::stop);
Expand Down Expand Up @@ -90,6 +91,7 @@ Error UDPServer::listen(uint16_t p_port, const IP_Address &p_bind_address) {
ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE);
ERR_FAIL_COND_V(_sock->is_open(), ERR_ALREADY_IN_USE);
ERR_FAIL_COND_V(!p_bind_address.is_valid() && !p_bind_address.is_wildcard(), ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V_MSG(p_port < 0 || p_port > 65535, ERR_INVALID_PARAMETER, "The local port number must be between 0 and 65535 (inclusive).");

Error err;
IP::Type ip_type = IP::TYPE_ANY;
Expand All @@ -112,11 +114,15 @@ Error UDPServer::listen(uint16_t p_port, const IP_Address &p_bind_address) {
stop();
return err;
}
bind_address = p_bind_address;
bind_port = p_port;
return OK;
}

int UDPServer::get_local_port() const {
uint16_t local_port;
_sock->get_socket_address(nullptr, &local_port);
return local_port;
}

bool UDPServer::is_listening() const {
ERR_FAIL_COND_V(!_sock.is_valid(), false);

Expand Down Expand Up @@ -176,8 +182,6 @@ void UDPServer::stop() {
if (_sock.is_valid()) {
_sock->close();
}
bind_port = 0;
bind_address = IP_Address();
List<Peer>::Element *E = peers.front();
while (E) {
E->get().peer->disconnect_shared_socket();
Expand Down
5 changes: 1 addition & 4 deletions core/io/udp_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,18 @@ class UDPServer : public Reference {
};
uint8_t recv_buffer[PACKET_BUFFER_SIZE];

int bind_port = 0;
IP_Address bind_address;

List<Peer> peers;
List<Peer> pending;
int max_pending_connections = 16;

Ref<NetSocket> _sock;

static void _bind_methods();

public:
void remove_peer(IP_Address p_ip, int p_port);
Error listen(uint16_t p_port, const IP_Address &p_bind_address = IP_Address("*"));
Error poll();
int get_local_port() const;
bool is_listening() const;
bool is_connection_available() const;
void set_max_pending_connections(int p_max);
Expand Down
7 changes: 7 additions & 0 deletions doc/classes/PacketPeerUDP.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@
[b]Note:[/b] Connecting to the remote peer does not help to protect from malicious attacks like IP spoofing, etc. Think about using an encryption technique like SSL or DTLS if you feel like your application is transferring sensitive information.
</description>
</method>
<method name="get_local_port" qualifiers="const">
<return type="int">
</return>
<description>
Returns the local port to which this peer is bound.
</description>
</method>
<method name="get_packet_ip" qualifiers="const">
<return type="String">
</return>
Expand Down
21 changes: 20 additions & 1 deletion doc/classes/StreamPeerTCP.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@
<tutorials>
</tutorials>
<methods>
<method name="bind">
<return type="int" enum="Error">
</return>
<argument index="0" name="port" type="int">
</argument>
<argument index="1" name="host" type="String" default="&quot;*&quot;">
</argument>
<description>
Opens the TCP socket, and binds it to the specified local address.
This method is generally not needed, and only used to force the subsequent call to [method connect_to_host] to use the specified [code]host[/code] and [code]port[/code] as source address. This can be desired in some NAT punchthrough techniques, or when forcing the source network interface.
</description>
</method>
<method name="connect_to_host">
<return type="int" enum="Error">
</return>
Expand All @@ -17,7 +29,7 @@
<argument index="1" name="port" type="int">
</argument>
<description>
Connects to the specified [code]host:port[/code] pair. A hostname will be resolved if valid. Returns [constant OK] on success or [constant FAILED] on failure.
Connects to the specified [code]host:port[/code] pair. A hostname will be resolved if valid. Returns [constant OK] on success.
</description>
</method>
<method name="disconnect_from_host">
Expand All @@ -41,6 +53,13 @@
Returns the port of this peer.
</description>
</method>
<method name="get_local_port" qualifiers="const">
<return type="int">
</return>
<description>
Returns the local port to which this peer is bound.
</description>
</method>
<method name="get_status">
<return type="int" enum="StreamPeerTCP.Status">
</return>
Expand Down
7 changes: 7 additions & 0 deletions doc/classes/TCP_Server.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@
<tutorials>
</tutorials>
<methods>
<method name="get_local_port" qualifiers="const">
<return type="int">
</return>
<description>
Returns the local port this server is listening to.
</description>
</method>
<method name="is_connection_available" qualifiers="const">
<return type="bool">
</return>
Expand Down
7 changes: 7 additions & 0 deletions doc/classes/UDPServer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,13 @@
<tutorials>
</tutorials>
<methods>
<method name="get_local_port" qualifiers="const">
<return type="int">
</return>
<description>
Returns the local port this server is listening to.
</description>
</method>
<method name="is_connection_available" qualifiers="const">
<return type="bool">
</return>
Expand Down
Loading

0 comments on commit da8c231

Please sign in to comment.