Merge pull request #59582 from Faless/net/4.x_tcp_explicit_poll

This commit is contained in:
Rémi Verschelde 2022-04-27 13:56:58 +02:00 committed by GitHub
commit 6e6fe2b025
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 51 additions and 75 deletions

View File

@ -93,7 +93,7 @@ RemoteDebuggerPeerTCP::~RemoteDebuggerPeerTCP() {
} }
void RemoteDebuggerPeerTCP::_write_out() { void RemoteDebuggerPeerTCP::_write_out() {
while (tcp_client->poll(NetSocket::POLL_TYPE_OUT) == OK) { while (tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTED && tcp_client->wait(NetSocket::POLL_TYPE_OUT) == OK) {
uint8_t *buf = out_buf.ptrw(); uint8_t *buf = out_buf.ptrw();
if (out_left <= 0) { if (out_left <= 0) {
if (out_queue.size() == 0) { if (out_queue.size() == 0) {
@ -119,7 +119,7 @@ void RemoteDebuggerPeerTCP::_write_out() {
} }
void RemoteDebuggerPeerTCP::_read_in() { void RemoteDebuggerPeerTCP::_read_in() {
while (tcp_client->poll(NetSocket::POLL_TYPE_IN) == OK) { while (tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTED && tcp_client->wait(NetSocket::POLL_TYPE_IN) == OK) {
uint8_t *buf = in_buf.ptrw(); uint8_t *buf = in_buf.ptrw();
if (in_left <= 0) { if (in_left <= 0) {
if (in_queue.size() > max_queued_messages) { if (in_queue.size() > max_queued_messages) {
@ -167,6 +167,7 @@ Error RemoteDebuggerPeerTCP::connect_to_host(const String &p_host, uint16_t p_po
tcp_client->connect_to_host(ip, port); tcp_client->connect_to_host(ip, port);
for (int i = 0; i < tries; i++) { for (int i = 0; i < tries; i++) {
tcp_client->poll();
if (tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTED) { if (tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTED) {
print_verbose("Remote Debugger: Connected!"); print_verbose("Remote Debugger: Connected!");
break; break;
@ -213,6 +214,7 @@ void RemoteDebuggerPeerTCP::poll() {
} }
void RemoteDebuggerPeerTCP::_poll() { void RemoteDebuggerPeerTCP::_poll() {
tcp_client->poll();
if (connected) { if (connected) {
_write_out(); _write_out();
_read_in(); _read_in();

View File

@ -264,6 +264,9 @@ void HTTPClientTCP::close() {
} }
Error HTTPClientTCP::poll() { Error HTTPClientTCP::poll() {
if (tcp_connection.is_valid()) {
tcp_connection->poll();
}
switch (status) { switch (status) {
case STATUS_RESOLVING: { case STATUS_RESOLVING: {
ERR_FAIL_COND_V(resolving == IP::RESOLVER_INVALID_ID, ERR_BUG); ERR_FAIL_COND_V(resolving == IP::RESOLVER_INVALID_ID, ERR_BUG);

View File

@ -242,7 +242,7 @@ Error PacketPeerUDP::connect_to_host(const IPAddress &p_host, int p_port) {
return OK; return OK;
} }
bool PacketPeerUDP::is_connected_to_host() const { bool PacketPeerUDP::is_socket_connected() const {
return connected; return connected;
} }
@ -348,7 +348,7 @@ void PacketPeerUDP::_bind_methods() {
ClassDB::bind_method(D_METHOD("wait"), &PacketPeerUDP::wait); ClassDB::bind_method(D_METHOD("wait"), &PacketPeerUDP::wait);
ClassDB::bind_method(D_METHOD("is_bound"), &PacketPeerUDP::is_bound); ClassDB::bind_method(D_METHOD("is_bound"), &PacketPeerUDP::is_bound);
ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port"), &PacketPeerUDP::connect_to_host); ClassDB::bind_method(D_METHOD("connect_to_host", "host", "port"), &PacketPeerUDP::connect_to_host);
ClassDB::bind_method(D_METHOD("is_connected_to_host"), &PacketPeerUDP::is_connected_to_host); ClassDB::bind_method(D_METHOD("is_socket_connected"), &PacketPeerUDP::is_socket_connected);
ClassDB::bind_method(D_METHOD("get_packet_ip"), &PacketPeerUDP::_get_packet_ip); 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_packet_port"), &PacketPeerUDP::get_packet_port);
ClassDB::bind_method(D_METHOD("get_local_port"), &PacketPeerUDP::get_local_port); ClassDB::bind_method(D_METHOD("get_local_port"), &PacketPeerUDP::get_local_port);

View File

@ -79,7 +79,7 @@ public:
void disconnect_shared_socket(); // Used by UDPServer void disconnect_shared_socket(); // Used by UDPServer
Error store_packet(IPAddress p_ip, uint32_t p_port, uint8_t *p_buf, int p_buf_size); // Used internally and by UDPServer Error store_packet(IPAddress p_ip, uint32_t p_port, uint8_t *p_buf, int p_buf_size); // Used internally and by UDPServer
Error connect_to_host(const IPAddress &p_host, int p_port); Error connect_to_host(const IPAddress &p_host, int p_port);
bool is_connected_to_host() const; bool is_socket_connected() const;
IPAddress get_packet_address() const; IPAddress get_packet_address() const;
int get_packet_port() const; int get_packet_port() const;

View File

@ -32,8 +32,28 @@
#include "core/config/project_settings.h" #include "core/config/project_settings.h"
Error StreamPeerTCP::_poll_connection() { Error StreamPeerTCP::poll() {
ERR_FAIL_COND_V(status != STATUS_CONNECTING || !_sock.is_valid() || !_sock->is_open(), FAILED); if (status == STATUS_CONNECTED) {
Error err;
err = _sock->poll(NetSocket::POLL_TYPE_IN, 0);
if (err == OK) {
// FIN received
if (_sock->get_available_bytes() == 0) {
disconnect_from_host();
return OK;
}
}
// Also poll write
err = _sock->poll(NetSocket::POLL_TYPE_IN_OUT, 0);
if (err != OK && err != ERR_BUSY) {
// Got an error
disconnect_from_host();
status = STATUS_ERROR;
return err;
}
} else if (status != STATUS_CONNECTING) {
return OK;
}
Error err = _sock->connect_to_host(peer_host, peer_port); Error err = _sock->connect_to_host(peer_host, peer_port);
@ -121,22 +141,7 @@ Error StreamPeerTCP::connect_to_host(const IPAddress &p_host, int p_port) {
Error StreamPeerTCP::write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block) { Error StreamPeerTCP::write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block) {
ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE); ERR_FAIL_COND_V(!_sock.is_valid(), ERR_UNAVAILABLE);
if (status == STATUS_NONE || status == STATUS_ERROR) {
return FAILED;
}
if (status != STATUS_CONNECTED) { if (status != STATUS_CONNECTED) {
if (_poll_connection() != OK) {
return FAILED;
}
if (status != STATUS_CONNECTED) {
r_sent = 0;
return OK;
}
}
if (!_sock->is_open()) {
return FAILED; return FAILED;
} }
@ -179,21 +184,10 @@ Error StreamPeerTCP::write(const uint8_t *p_data, int p_bytes, int &r_sent, bool
} }
Error StreamPeerTCP::read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block) { Error StreamPeerTCP::read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block) {
if (!is_connected_to_host()) { if (status != STATUS_CONNECTED) {
return FAILED; return FAILED;
} }
if (status == STATUS_CONNECTING) {
if (_poll_connection() != OK) {
return FAILED;
}
if (status != STATUS_CONNECTED) {
r_received = 0;
return OK;
}
}
Error err; Error err;
int to_read = p_bytes; int to_read = p_bytes;
int total_read = 0; int total_read = 0;
@ -243,36 +237,11 @@ Error StreamPeerTCP::read(uint8_t *p_buffer, int p_bytes, int &r_received, bool
} }
void StreamPeerTCP::set_no_delay(bool p_enabled) { void StreamPeerTCP::set_no_delay(bool p_enabled) {
ERR_FAIL_COND(!is_connected_to_host()); ERR_FAIL_COND(!_sock.is_valid() || !_sock->is_open());
_sock->set_tcp_no_delay_enabled(p_enabled); _sock->set_tcp_no_delay_enabled(p_enabled);
} }
bool StreamPeerTCP::is_connected_to_host() const { StreamPeerTCP::Status StreamPeerTCP::get_status() const {
return _sock.is_valid() && _sock->is_open() && (status == STATUS_CONNECTED || status == STATUS_CONNECTING);
}
StreamPeerTCP::Status StreamPeerTCP::get_status() {
if (status == STATUS_CONNECTING) {
_poll_connection();
} else if (status == STATUS_CONNECTED) {
Error err;
err = _sock->poll(NetSocket::POLL_TYPE_IN, 0);
if (err == OK) {
// FIN received
if (_sock->get_available_bytes() == 0) {
disconnect_from_host();
return status;
}
}
// Also poll write
err = _sock->poll(NetSocket::POLL_TYPE_IN_OUT, 0);
if (err != OK && err != ERR_BUSY) {
// Got an error
disconnect_from_host();
status = STATUS_ERROR;
}
}
return status; return status;
} }
@ -287,7 +256,7 @@ void StreamPeerTCP::disconnect_from_host() {
peer_port = 0; peer_port = 0;
} }
Error StreamPeerTCP::poll(NetSocket::PollType p_type, int timeout) { Error StreamPeerTCP::wait(NetSocket::PollType p_type, int timeout) {
ERR_FAIL_COND_V(_sock.is_null() || !_sock->is_open(), ERR_UNAVAILABLE); ERR_FAIL_COND_V(_sock.is_null() || !_sock->is_open(), ERR_UNAVAILABLE);
return _sock->poll(p_type, timeout); return _sock->poll(p_type, timeout);
} }
@ -346,7 +315,7 @@ Error StreamPeerTCP::_connect(const String &p_address, int p_port) {
void StreamPeerTCP::_bind_methods() { void StreamPeerTCP::_bind_methods() {
ClassDB::bind_method(D_METHOD("bind", "port", "host"), &StreamPeerTCP::bind, DEFVAL("*")); 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("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("poll"), &StreamPeerTCP::poll);
ClassDB::bind_method(D_METHOD("get_status"), &StreamPeerTCP::get_status); 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_host"), &StreamPeerTCP::get_connected_host);
ClassDB::bind_method(D_METHOD("get_connected_port"), &StreamPeerTCP::get_connected_port); ClassDB::bind_method(D_METHOD("get_connected_port"), &StreamPeerTCP::get_connected_port);

View File

@ -55,7 +55,6 @@ protected:
uint16_t peer_port = 0; uint16_t peer_port = 0;
Error _connect(const String &p_address, int p_port); Error _connect(const String &p_address, int p_port);
Error _poll_connection();
Error write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block); Error write(const uint8_t *p_data, int p_bytes, int &r_sent, bool p_block);
Error read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block); Error read(uint8_t *p_buffer, int p_bytes, int &r_received, bool p_block);
@ -66,19 +65,21 @@ public:
Error bind(int p_port, const IPAddress &p_host); Error bind(int p_port, const IPAddress &p_host);
Error connect_to_host(const IPAddress &p_host, int p_port); Error connect_to_host(const IPAddress &p_host, int p_port);
bool is_connected_to_host() const;
IPAddress get_connected_host() const; IPAddress get_connected_host() const;
int get_connected_port() const; int get_connected_port() const;
int get_local_port() const; int get_local_port() const;
void disconnect_from_host(); void disconnect_from_host();
int get_available_bytes() const override; int get_available_bytes() const override;
Status get_status(); Status get_status() const;
void set_no_delay(bool p_enabled); void set_no_delay(bool p_enabled);
// Poll functions (wait or check for writable, readable) // Poll socket updating its state.
Error poll(NetSocket::PollType p_type, int timeout = 0); Error poll();
// Wait or check for writable, readable.
Error wait(NetSocket::PollType p_type, int timeout = 0);
// Read/Write from StreamPeer // Read/Write from StreamPeer
Error put_data(const uint8_t *p_data, int p_bytes) override; Error put_data(const uint8_t *p_data, int p_bytes) override;

View File

@ -61,7 +61,7 @@
Returns whether this [PacketPeerUDP] is bound to an address and can receive packets. Returns whether this [PacketPeerUDP] is bound to an address and can receive packets.
</description> </description>
</method> </method>
<method name="is_connected_to_host" qualifiers="const"> <method name="is_socket_connected" qualifiers="const">
<return type="bool" /> <return type="bool" />
<description> <description>
Returns [code]true[/code] if the UDP socket is open and has been connected to a remote address. See [method connect_to_host]. Returns [code]true[/code] if the UDP socket is open and has been connected to a remote address. See [method connect_to_host].

View File

@ -51,16 +51,16 @@
Returns the local port to which this peer is bound. Returns the local port to which this peer is bound.
</description> </description>
</method> </method>
<method name="get_status"> <method name="get_status" qualifiers="const">
<return type="int" enum="StreamPeerTCP.Status" /> <return type="int" enum="StreamPeerTCP.Status" />
<description> <description>
Returns the status of the connection, see [enum Status]. Returns the status of the connection, see [enum Status].
</description> </description>
</method> </method>
<method name="is_connected_to_host" qualifiers="const"> <method name="poll">
<return type="bool" /> <return type="int" enum="Error" />
<description> <description>
Returns [code]true[/code] if this peer is currently connected or is connecting to a host, [code]false[/code] otherwise. Poll the socket, updating its state. See [method get_status].
</description> </description>
</method> </method>
<method name="set_no_delay"> <method name="set_no_delay">

View File

@ -115,7 +115,7 @@ Error PacketPeerMbedDTLS::_do_handshake() {
} }
Error PacketPeerMbedDTLS::connect_to_peer(Ref<PacketPeerUDP> p_base, bool p_validate_certs, const String &p_for_hostname, Ref<X509Certificate> p_ca_certs) { Error PacketPeerMbedDTLS::connect_to_peer(Ref<PacketPeerUDP> p_base, bool p_validate_certs, const String &p_for_hostname, Ref<X509Certificate> p_ca_certs) {
ERR_FAIL_COND_V(!p_base.is_valid() || !p_base->is_connected_to_host(), ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(!p_base.is_valid() || !p_base->is_socket_connected(), ERR_INVALID_PARAMETER);
base = p_base; base = p_base;
int ret = 0; int ret = 0;

View File

@ -273,6 +273,7 @@ void WSLClient::poll() {
return; // Not connected. return; // Not connected.
} }
_tcp->poll();
switch (_tcp->get_status()) { switch (_tcp->get_status()) {
case StreamPeerTCP::STATUS_NONE: case StreamPeerTCP::STATUS_NONE:
// Clean close // Clean close
@ -336,7 +337,7 @@ MultiplayerPeer::ConnectionStatus WSLClient::get_connection_status() const {
return CONNECTION_CONNECTED; return CONNECTION_CONNECTED;
} }
if (_tcp->is_connected_to_host() || _resolver_id != IP::RESOLVER_INVALID_ID) { if (_tcp->get_status() == StreamPeerTCP::STATUS_CONNECTING || _resolver_id != IP::RESOLVER_INVALID_ID) {
return CONNECTION_CONNECTING; return CONNECTION_CONNECTING;
} }