From 025cc04d9e8ec12cea749b6831fb8bc5c78894e2 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Fri, 4 Oct 2019 12:58:06 +0200 Subject: [PATCH 1/5] Re-implement WebSocket get host/port. Was lost during library switch --- modules/websocket/emws_client.cpp | 4 ++-- modules/websocket/websocket_client.cpp | 2 ++ modules/websocket/wsl_client.cpp | 7 +++++-- modules/websocket/wsl_peer.cpp | 11 ++++------- modules/websocket/wsl_peer.h | 3 ++- modules/websocket/wsl_server.cpp | 4 +++- modules/websocket/wsl_server.h | 1 + 7 files changed, 19 insertions(+), 13 deletions(-) diff --git a/modules/websocket/emws_client.cpp b/modules/websocket/emws_client.cpp index 409cc9f6994..a59dd163607 100644 --- a/modules/websocket/emws_client.cpp +++ b/modules/websocket/emws_client.cpp @@ -193,12 +193,12 @@ void EMWSClient::disconnect_from_host(int p_code, String p_reason) { IP_Address EMWSClient::get_connected_host() const { - return IP_Address(); + ERR_FAIL_V_MSG(IP_Address(), "Not supported in HTML5 export."); }; uint16_t EMWSClient::get_connected_port() const { - return 1025; + ERR_FAIL_V_MSG(0, "Not supported in HTML5 export."); }; int EMWSClient::get_max_packet_size() const { diff --git a/modules/websocket/websocket_client.cpp b/modules/websocket/websocket_client.cpp index 4ff5404c612..8f03efdd831 100644 --- a/modules/websocket/websocket_client.cpp +++ b/modules/websocket/websocket_client.cpp @@ -134,6 +134,8 @@ void WebSocketClient::_on_error() { void WebSocketClient::_bind_methods() { ClassDB::bind_method(D_METHOD("connect_to_url", "url", "protocols", "gd_mp_api"), &WebSocketClient::connect_to_url, DEFVAL(PoolVector()), DEFVAL(false)); ClassDB::bind_method(D_METHOD("disconnect_from_host", "code", "reason"), &WebSocketClient::disconnect_from_host, DEFVAL(1000), DEFVAL("")); + ClassDB::bind_method(D_METHOD("get_connected_host"), &WebSocketClient::get_connected_host); + ClassDB::bind_method(D_METHOD("get_connected_port"), &WebSocketClient::get_connected_port); ClassDB::bind_method(D_METHOD("set_verify_ssl_enabled", "enabled"), &WebSocketClient::set_verify_ssl_enabled); ClassDB::bind_method(D_METHOD("is_verify_ssl_enabled"), &WebSocketClient::is_verify_ssl_enabled); diff --git a/modules/websocket/wsl_client.cpp b/modules/websocket/wsl_client.cpp index 0006a057e06..5f254eb9e66 100644 --- a/modules/websocket/wsl_client.cpp +++ b/modules/websocket/wsl_client.cpp @@ -86,6 +86,7 @@ void WSLClient::_do_handshake() { WSLPeer::PeerData *data = memnew(struct WSLPeer::PeerData); data->obj = this; data->conn = _connection; + data->tcp = _tcp; data->is_server = false; data->id = 1; _peer->make_context(data, _in_buf_size, _in_pkt_size, _out_buf_size, _out_pkt_size); @@ -305,12 +306,14 @@ void WSLClient::disconnect_from_host(int p_code, String p_reason) { IP_Address WSLClient::get_connected_host() const { - return IP_Address(); + ERR_FAIL_COND_V(!_peer->is_connected_to_host(), IP_Address()); + return _peer->get_connected_host(); } uint16_t WSLClient::get_connected_port() const { - return 1025; + ERR_FAIL_COND_V(!_peer->is_connected_to_host(), 0); + return _peer->get_connected_port(); } Error WSLClient::set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffer, int p_out_packets) { diff --git a/modules/websocket/wsl_peer.cpp b/modules/websocket/wsl_peer.cpp index 74fb901232d..32beccde5d6 100644 --- a/modules/websocket/wsl_peer.cpp +++ b/modules/websocket/wsl_peer.cpp @@ -208,7 +208,6 @@ void WSLPeer::make_context(PeerData *p_data, unsigned int p_in_buf_size, unsigne _data = p_data; _data->peer = this; _data->valid = true; - _connection = Ref(_data->conn); if (_data->is_server) wslay_event_context_server_init(&(_data->ctx), &wsl_callbacks, _data); @@ -302,18 +301,16 @@ void WSLPeer::close(int p_code, String p_reason) { IP_Address WSLPeer::get_connected_host() const { - ERR_FAIL_COND_V(!is_connected_to_host(), IP_Address()); + ERR_FAIL_COND_V(!is_connected_to_host() || _data->tcp.is_null(), IP_Address()); - IP_Address ip; - return ip; + return _data->tcp->get_connected_host(); } uint16_t WSLPeer::get_connected_port() const { - ERR_FAIL_COND_V(!is_connected_to_host(), 0); + ERR_FAIL_COND_V(!is_connected_to_host() || _data->tcp.is_null(), 0); - uint16_t port = 0; - return port; + return _data->tcp->get_connected_port(); } void WSLPeer::invalidate() { diff --git a/modules/websocket/wsl_peer.h b/modules/websocket/wsl_peer.h index d51b304fe1c..01ad2504688 100644 --- a/modules/websocket/wsl_peer.h +++ b/modules/websocket/wsl_peer.h @@ -35,6 +35,7 @@ #include "core/error_list.h" #include "core/io/packet_peer.h" +#include "core/io/stream_peer_tcp.h" #include "core/ring_buffer.h" #include "packet_buffer.h" #include "websocket_peer.h" @@ -55,6 +56,7 @@ public: void *obj; void *peer; Ref conn; + Ref tcp; int id; wslay_event_context_ptr ctx; @@ -77,7 +79,6 @@ private: static bool _wsl_poll(struct PeerData *p_data); static void _wsl_destroy(struct PeerData **p_data); - Ref _connection; struct PeerData *_data; uint8_t _is_string; // Our packet info is just a boolean (is_string), using uint8_t for it. diff --git a/modules/websocket/wsl_server.cpp b/modules/websocket/wsl_server.cpp index efb526eed1a..dbf153bd4a6 100644 --- a/modules/websocket/wsl_server.cpp +++ b/modules/websocket/wsl_server.cpp @@ -185,6 +185,7 @@ void WSLServer::poll() { WSLPeer::PeerData *data = memnew(struct WSLPeer::PeerData); data->obj = this; data->conn = ppeer->connection; + data->tcp = ppeer->tcp; data->is_server = true; data->id = id; @@ -204,12 +205,13 @@ void WSLServer::poll() { return; while (_server->is_connection_available()) { - Ref conn = _server->take_connection(); + Ref conn = _server->take_connection(); if (is_refusing_new_connections()) continue; // Conn will go out-of-scope and be closed. Ref peer = memnew(PendingPeer); peer->connection = conn; + peer->tcp = conn; peer->time = OS::get_singleton()->get_ticks_msec(); _pending.push_back(peer); } diff --git a/modules/websocket/wsl_server.h b/modules/websocket/wsl_server.h index 2ceb9410733..de6d6d77f63 100644 --- a/modules/websocket/wsl_server.h +++ b/modules/websocket/wsl_server.h @@ -52,6 +52,7 @@ private: bool _parse_request(const PoolStringArray p_protocols); public: + Ref tcp; Ref connection; int time; From 33644d711865e518a792403304b09f0828478fe9 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Mon, 7 Oct 2019 15:38:03 +0200 Subject: [PATCH 2/5] WebSocketClient can now use custom SSL certificate Via the `trusted_ssl_certificate` property. --- modules/websocket/emws_client.cpp | 6 +++++- modules/websocket/websocket_client.cpp | 16 ++++++++++++++++ modules/websocket/websocket_client.h | 4 ++++ modules/websocket/wsl_client.cpp | 2 +- 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/modules/websocket/emws_client.cpp b/modules/websocket/emws_client.cpp index a59dd163607..dddda0682dc 100644 --- a/modules/websocket/emws_client.cpp +++ b/modules/websocket/emws_client.cpp @@ -69,8 +69,12 @@ Error EMWSClient::connect_to_host(String p_host, String p_path, uint16_t p_port, String proto_string = p_protocols.join(","); String str = "ws://"; - if (p_ssl) + if (p_ssl) { str = "wss://"; + if (ssl_cert.is_valid()) { + WARN_PRINT_ONCE("Custom SSL certificate is not supported in HTML5 platform."); + } + } str += p_host + ":" + itos(p_port) + p_path; _is_connecting = true; diff --git a/modules/websocket/websocket_client.cpp b/modules/websocket/websocket_client.cpp index 8f03efdd831..df6578e8bbc 100644 --- a/modules/websocket/websocket_client.cpp +++ b/modules/websocket/websocket_client.cpp @@ -85,6 +85,17 @@ bool WebSocketClient::is_verify_ssl_enabled() const { return verify_ssl; } +Ref WebSocketClient::get_trusted_ssl_certificate() const { + + return ssl_cert; +} + +void WebSocketClient::set_trusted_ssl_certificate(Ref p_cert) { + + ERR_FAIL_COND(get_connection_status() != CONNECTION_DISCONNECTED); + ssl_cert = p_cert; +} + bool WebSocketClient::is_server() const { return false; @@ -141,6 +152,11 @@ void WebSocketClient::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "verify_ssl", PROPERTY_HINT_NONE, "", 0), "set_verify_ssl_enabled", "is_verify_ssl_enabled"); + ClassDB::bind_method(D_METHOD("get_trusted_ssl_certificate"), &WebSocketClient::get_trusted_ssl_certificate); + ClassDB::bind_method(D_METHOD("set_trusted_ssl_certificate"), &WebSocketClient::set_trusted_ssl_certificate); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "trusted_ssl_certificate", PROPERTY_HINT_RESOURCE_TYPE, "X509Certificate", 0), "set_trusted_ssl_certificate", "get_trusted_ssl_certificate"); + ADD_SIGNAL(MethodInfo("data_received")); ADD_SIGNAL(MethodInfo("connection_established", PropertyInfo(Variant::STRING, "protocol"))); ADD_SIGNAL(MethodInfo("server_close_request", PropertyInfo(Variant::INT, "code"), PropertyInfo(Variant::STRING, "reason"))); diff --git a/modules/websocket/websocket_client.h b/modules/websocket/websocket_client.h index 7ddb9468a5c..8241914bd69 100644 --- a/modules/websocket/websocket_client.h +++ b/modules/websocket/websocket_client.h @@ -31,6 +31,7 @@ #ifndef WEBSOCKET_CLIENT_H #define WEBSOCKET_CLIENT_H +#include "core/crypto/crypto.h" #include "core/error_list.h" #include "websocket_multiplayer_peer.h" #include "websocket_peer.h" @@ -43,6 +44,7 @@ class WebSocketClient : public WebSocketMultiplayerPeer { protected: Ref _peer; bool verify_ssl; + Ref ssl_cert; static void _bind_methods(); @@ -51,6 +53,8 @@ public: void set_verify_ssl_enabled(bool p_verify_ssl); bool is_verify_ssl_enabled() const; + Ref get_trusted_ssl_certificate() const; + void set_trusted_ssl_certificate(Ref p_cert); virtual void poll() = 0; virtual Error connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, PoolVector p_protocol = PoolVector()) = 0; diff --git a/modules/websocket/wsl_client.cpp b/modules/websocket/wsl_client.cpp index 5f254eb9e66..2e9daeb875c 100644 --- a/modules/websocket/wsl_client.cpp +++ b/modules/websocket/wsl_client.cpp @@ -237,7 +237,7 @@ void WSLClient::poll() { ssl = Ref(StreamPeerSSL::create()); ERR_FAIL_COND_MSG(ssl.is_null(), "SSL is not available in this build."); ssl->set_blocking_handshake_enabled(false); - if (ssl->connect_to_stream(_tcp, verify_ssl, _host) != OK) { + if (ssl->connect_to_stream(_tcp, verify_ssl, _host, ssl_cert) != OK) { disconnect_from_host(); _on_error(); return; From c723a8b6aa2e32f0c8b213303610a35d08b01e34 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Mon, 7 Oct 2019 16:35:56 +0200 Subject: [PATCH 3/5] Implement WebSocketServer SSL support. --- modules/websocket/websocket_server.cpp | 39 ++++++++++++++++++++++++++ modules/websocket/websocket_server.h | 14 +++++++++ modules/websocket/wsl_server.cpp | 21 +++++++++++++- modules/websocket/wsl_server.h | 2 ++ 4 files changed, 75 insertions(+), 1 deletion(-) diff --git a/modules/websocket/websocket_server.cpp b/modules/websocket/websocket_server.cpp index ef5f6f5c20b..9e077317c09 100644 --- a/modules/websocket/websocket_server.cpp +++ b/modules/websocket/websocket_server.cpp @@ -49,12 +49,51 @@ void WebSocketServer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_peer_port", "id"), &WebSocketServer::get_peer_port); ClassDB::bind_method(D_METHOD("disconnect_peer", "id", "code", "reason"), &WebSocketServer::disconnect_peer, DEFVAL(1000), DEFVAL("")); + ClassDB::bind_method(D_METHOD("get_private_key"), &WebSocketServer::get_private_key); + ClassDB::bind_method(D_METHOD("set_private_key"), &WebSocketServer::set_private_key); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "private_key", PROPERTY_HINT_RESOURCE_TYPE, "CryptoKey", 0), "set_private_key", "get_private_key"); + + ClassDB::bind_method(D_METHOD("get_ssl_certificate"), &WebSocketServer::get_ssl_certificate); + ClassDB::bind_method(D_METHOD("set_ssl_certificate"), &WebSocketServer::set_ssl_certificate); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "ssl_certificate", PROPERTY_HINT_RESOURCE_TYPE, "X509Certificate", 0), "set_ssl_certificate", "get_ssl_certificate"); + + ClassDB::bind_method(D_METHOD("get_ca_chain"), &WebSocketServer::get_ca_chain); + ClassDB::bind_method(D_METHOD("set_ca_chain"), &WebSocketServer::set_ca_chain); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "ca_chain", PROPERTY_HINT_RESOURCE_TYPE, "X509Certificate", 0), "set_ca_chain", "get_ca_chain"); + ADD_SIGNAL(MethodInfo("client_close_request", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::INT, "code"), PropertyInfo(Variant::STRING, "reason"))); ADD_SIGNAL(MethodInfo("client_disconnected", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::BOOL, "was_clean_close"))); ADD_SIGNAL(MethodInfo("client_connected", PropertyInfo(Variant::INT, "id"), PropertyInfo(Variant::STRING, "protocol"))); ADD_SIGNAL(MethodInfo("data_received", PropertyInfo(Variant::INT, "id"))); } +Ref WebSocketServer::get_private_key() const { + return private_key; +} + +void WebSocketServer::set_private_key(Ref p_key) { + ERR_FAIL_COND(is_listening()); + private_key = p_key; +} + +Ref WebSocketServer::get_ssl_certificate() const { + return ssl_cert; +} + +void WebSocketServer::set_ssl_certificate(Ref p_cert) { + ERR_FAIL_COND(is_listening()); + ssl_cert = p_cert; +} + +Ref WebSocketServer::get_ca_chain() const { + return ca_chain; +} + +void WebSocketServer::set_ca_chain(Ref p_ca_chain) { + ERR_FAIL_COND(is_listening()); + ca_chain = p_ca_chain; +} + NetworkedMultiplayerPeer::ConnectionStatus WebSocketServer::get_connection_status() const { if (is_listening()) return CONNECTION_CONNECTED; diff --git a/modules/websocket/websocket_server.h b/modules/websocket/websocket_server.h index 83c0c104195..2e5c706f330 100644 --- a/modules/websocket/websocket_server.h +++ b/modules/websocket/websocket_server.h @@ -31,6 +31,7 @@ #ifndef WEBSOCKET_H #define WEBSOCKET_H +#include "core/crypto/crypto.h" #include "core/reference.h" #include "websocket_multiplayer_peer.h" #include "websocket_peer.h" @@ -43,6 +44,10 @@ class WebSocketServer : public WebSocketMultiplayerPeer { protected: static void _bind_methods(); + Ref private_key; + Ref ssl_cert; + Ref ca_chain; + public: virtual void poll() = 0; virtual Error listen(int p_port, PoolVector p_protocols = PoolVector(), bool gd_mp_api = false) = 0; @@ -62,6 +67,15 @@ public: void _on_disconnect(int32_t p_peer_id, bool p_was_clean); void _on_close_request(int32_t p_peer_id, int p_code, String p_reason); + Ref get_private_key() const; + void set_private_key(Ref p_key); + + Ref get_ssl_certificate() const; + void set_ssl_certificate(Ref p_cert); + + Ref get_ca_chain() const; + void set_ca_chain(Ref p_ca_chain); + virtual Error set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffer, int p_out_packets) = 0; WebSocketServer(); diff --git a/modules/websocket/wsl_server.cpp b/modules/websocket/wsl_server.cpp index dbf153bd4a6..e3101d99d71 100644 --- a/modules/websocket/wsl_server.cpp +++ b/modules/websocket/wsl_server.cpp @@ -35,6 +35,7 @@ #include "core/project_settings.h" WSLServer::PendingPeer::PendingPeer() { + use_ssl = false; time = 0; has_request = false; response_sent = 0; @@ -100,6 +101,16 @@ bool WSLServer::PendingPeer::_parse_request(const PoolStringArray p_protocols) { Error WSLServer::PendingPeer::do_handshake(PoolStringArray p_protocols) { if (OS::get_singleton()->get_ticks_msec() - time > WSL_SERVER_TIMEOUT) return ERR_TIMEOUT; + if (use_ssl) { + Ref ssl = static_cast >(connection); + if (ssl.is_null()) + return FAILED; + ssl->poll(); + if (ssl->get_status() == StreamPeerSSL::STATUS_HANDSHAKING) + return ERR_BUSY; + else if (ssl->get_status() != StreamPeerSSL::STATUS_CONNECTED) + return FAILED; + } if (!has_request) { int read = 0; while (true) { @@ -210,7 +221,15 @@ void WSLServer::poll() { continue; // Conn will go out-of-scope and be closed. Ref peer = memnew(PendingPeer); - peer->connection = conn; + if (private_key.is_valid() && ssl_cert.is_valid()) { + Ref ssl = Ref(StreamPeerSSL::create()); + ssl->set_blocking_handshake_enabled(false); + ssl->accept_stream(conn, private_key, ssl_cert, ca_chain); + peer->connection = ssl; + peer->use_ssl = true; + } else { + peer->connection = conn; + } peer->tcp = conn; peer->time = OS::get_singleton()->get_ticks_msec(); _pending.push_back(peer); diff --git a/modules/websocket/wsl_server.h b/modules/websocket/wsl_server.h index de6d6d77f63..2ac873cba5c 100644 --- a/modules/websocket/wsl_server.h +++ b/modules/websocket/wsl_server.h @@ -36,6 +36,7 @@ #include "websocket_server.h" #include "wsl_peer.h" +#include "core/io/stream_peer_ssl.h" #include "core/io/stream_peer_tcp.h" #include "core/io/tcp_server.h" @@ -54,6 +55,7 @@ private: public: Ref tcp; Ref connection; + bool use_ssl; int time; uint8_t req_buf[WSL_MAX_HEADER_SIZE]; From 67a4c3033bd4c5e6f61b5ff77709f60512392ab0 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Tue, 8 Oct 2019 20:13:24 +0200 Subject: [PATCH 4/5] Custom headers support in WebSocketClient. This commit also converts all PoolVector parameters to `const Vector` in both WebSocketServer and WebSocketClient. --- modules/websocket/emws_client.cpp | 5 ++++- modules/websocket/emws_client.h | 2 +- modules/websocket/websocket_client.cpp | 6 +++--- modules/websocket/websocket_client.h | 4 ++-- modules/websocket/websocket_server.cpp | 2 +- modules/websocket/websocket_server.h | 2 +- modules/websocket/wsl_client.cpp | 10 +++++++--- modules/websocket/wsl_client.h | 4 ++-- modules/websocket/wsl_server.cpp | 9 +++++---- modules/websocket/wsl_server.h | 8 ++++---- 10 files changed, 30 insertions(+), 22 deletions(-) diff --git a/modules/websocket/emws_client.cpp b/modules/websocket/emws_client.cpp index dddda0682dc..fad766ea5d8 100644 --- a/modules/websocket/emws_client.cpp +++ b/modules/websocket/emws_client.cpp @@ -64,11 +64,14 @@ EMSCRIPTEN_KEEPALIVE void _esws_on_close(void *obj, int code, char *reason, int } } -Error EMWSClient::connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, PoolVector p_protocols) { +Error EMWSClient::connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, const PoolVector p_protocols, const Vector p_custom_headers) { String proto_string = p_protocols.join(","); String str = "ws://"; + if (p_custom_headers.size()) { + WARN_PRINT_ONCE("Custom headers are not supported in in HTML5 platform."); + } if (p_ssl) { str = "wss://"; if (ssl_cert.is_valid()) { diff --git a/modules/websocket/emws_client.h b/modules/websocket/emws_client.h index 1811d05eea0..2d35f7f0f67 100644 --- a/modules/websocket/emws_client.h +++ b/modules/websocket/emws_client.h @@ -50,7 +50,7 @@ public: bool _is_connecting; Error set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffer, int p_out_packets); - Error connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, PoolVector p_protocol = PoolVector()); + Error connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, const PoolVector p_protocol = PoolVector(), const Dictionary p_custom_headers = Dictionary()); Ref get_peer(int p_peer_id) const; void disconnect_from_host(int p_code = 1000, String p_reason = ""); IP_Address get_connected_host() const; diff --git a/modules/websocket/websocket_client.cpp b/modules/websocket/websocket_client.cpp index df6578e8bbc..8bbd5aa37f5 100644 --- a/modules/websocket/websocket_client.cpp +++ b/modules/websocket/websocket_client.cpp @@ -40,7 +40,7 @@ WebSocketClient::WebSocketClient() { WebSocketClient::~WebSocketClient() { } -Error WebSocketClient::connect_to_url(String p_url, PoolVector p_protocols, bool gd_mp_api) { +Error WebSocketClient::connect_to_url(String p_url, const Vector p_protocols, bool gd_mp_api, const Vector p_custom_headers) { _is_multiplayer = gd_mp_api; String host = p_url; @@ -72,7 +72,7 @@ Error WebSocketClient::connect_to_url(String p_url, PoolVector p_protoco host = host.substr(0, p_len); } - return connect_to_host(host, path, port, ssl, p_protocols); + return connect_to_host(host, path, port, ssl, p_protocols, p_custom_headers); } void WebSocketClient::set_verify_ssl_enabled(bool p_verify_ssl) { @@ -143,7 +143,7 @@ void WebSocketClient::_on_error() { } void WebSocketClient::_bind_methods() { - ClassDB::bind_method(D_METHOD("connect_to_url", "url", "protocols", "gd_mp_api"), &WebSocketClient::connect_to_url, DEFVAL(PoolVector()), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("connect_to_url", "url", "protocols", "gd_mp_api", "custom_headers"), &WebSocketClient::connect_to_url, DEFVAL(Vector()), DEFVAL(false), DEFVAL(Vector())); ClassDB::bind_method(D_METHOD("disconnect_from_host", "code", "reason"), &WebSocketClient::disconnect_from_host, DEFVAL(1000), DEFVAL("")); ClassDB::bind_method(D_METHOD("get_connected_host"), &WebSocketClient::get_connected_host); ClassDB::bind_method(D_METHOD("get_connected_port"), &WebSocketClient::get_connected_port); diff --git a/modules/websocket/websocket_client.h b/modules/websocket/websocket_client.h index 8241914bd69..08fd6798fe0 100644 --- a/modules/websocket/websocket_client.h +++ b/modules/websocket/websocket_client.h @@ -49,7 +49,7 @@ protected: static void _bind_methods(); public: - Error connect_to_url(String p_url, PoolVector p_protocols = PoolVector(), bool gd_mp_api = false); + Error connect_to_url(String p_url, const Vector p_protocols = Vector(), bool gd_mp_api = false, const Vector p_custom_headers = Vector()); void set_verify_ssl_enabled(bool p_verify_ssl); bool is_verify_ssl_enabled() const; @@ -57,7 +57,7 @@ public: void set_trusted_ssl_certificate(Ref p_cert); virtual void poll() = 0; - virtual Error connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, PoolVector p_protocol = PoolVector()) = 0; + virtual Error connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, const Vector p_protocol = Vector(), const Vector p_custom_headers = Vector()) = 0; virtual void disconnect_from_host(int p_code = 1000, String p_reason = "") = 0; virtual IP_Address get_connected_host() const = 0; virtual uint16_t get_connected_port() const = 0; diff --git a/modules/websocket/websocket_server.cpp b/modules/websocket/websocket_server.cpp index 9e077317c09..c7414075edc 100644 --- a/modules/websocket/websocket_server.cpp +++ b/modules/websocket/websocket_server.cpp @@ -42,7 +42,7 @@ WebSocketServer::~WebSocketServer() { void WebSocketServer::_bind_methods() { ClassDB::bind_method(D_METHOD("is_listening"), &WebSocketServer::is_listening); - ClassDB::bind_method(D_METHOD("listen", "port", "protocols", "gd_mp_api"), &WebSocketServer::listen, DEFVAL(PoolVector()), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("listen", "port", "protocols", "gd_mp_api"), &WebSocketServer::listen, DEFVAL(Vector()), DEFVAL(false)); ClassDB::bind_method(D_METHOD("stop"), &WebSocketServer::stop); ClassDB::bind_method(D_METHOD("has_peer", "id"), &WebSocketServer::has_peer); ClassDB::bind_method(D_METHOD("get_peer_address", "id"), &WebSocketServer::get_peer_address); diff --git a/modules/websocket/websocket_server.h b/modules/websocket/websocket_server.h index 2e5c706f330..0b39f944735 100644 --- a/modules/websocket/websocket_server.h +++ b/modules/websocket/websocket_server.h @@ -50,7 +50,7 @@ protected: public: virtual void poll() = 0; - virtual Error listen(int p_port, PoolVector p_protocols = PoolVector(), bool gd_mp_api = false) = 0; + virtual Error listen(int p_port, const Vector p_protocols = Vector(), bool gd_mp_api = false) = 0; virtual void stop() = 0; virtual bool is_listening() const = 0; virtual bool has_peer(int p_id) const = 0; diff --git a/modules/websocket/wsl_client.cpp b/modules/websocket/wsl_client.cpp index 2e9daeb875c..a422f65cfc7 100644 --- a/modules/websocket/wsl_client.cpp +++ b/modules/websocket/wsl_client.cpp @@ -152,7 +152,7 @@ bool WSLClient::_verify_headers(String &r_protocol) { return true; } -Error WSLClient::connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, PoolVector p_protocols) { +Error WSLClient::connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, const Vector p_protocols, const Vector p_custom_headers) { ERR_FAIL_COND_V(_connection.is_valid(), ERR_ALREADY_IN_USE); @@ -181,7 +181,8 @@ Error WSLClient::connect_to_host(String p_host, String p_path, uint16_t p_port, _connection = _tcp; _use_ssl = p_ssl; _host = p_host; - _protocols = p_protocols; + _protocols.clear(); + _protocols.append_array(p_protocols); _key = WSLPeer::generate_key(); // TODO custom extra headers (allow overriding this too?) @@ -200,6 +201,9 @@ Error WSLClient::connect_to_host(String p_host, String p_path, uint16_t p_port, } request += "\r\n"; } + for (int i = 0; i < p_custom_headers.size(); i++) { + request += p_custom_headers[i] + "\r\n"; + } request += "\r\n"; _request = request.utf8(); @@ -294,7 +298,7 @@ void WSLClient::disconnect_from_host(int p_code, String p_reason) { _key = ""; _host = ""; - _protocols.resize(0); + _protocols.clear(); _use_ssl = false; _request = ""; diff --git a/modules/websocket/wsl_client.h b/modules/websocket/wsl_client.h index 57dfd635b7f..870be94a87f 100644 --- a/modules/websocket/wsl_client.h +++ b/modules/websocket/wsl_client.h @@ -64,7 +64,7 @@ private: String _key; String _host; - PoolVector _protocols; + Vector _protocols; bool _use_ssl; void _do_handshake(); @@ -72,7 +72,7 @@ private: public: Error set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffer, int p_out_packets); - Error connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, PoolVector p_protocol = PoolVector()); + Error connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, const Vector p_protocol = Vector(), const Vector p_custom_headers = Vector()); int get_max_packet_size() const; Ref get_peer(int p_peer_id) const; void disconnect_from_host(int p_code = 1000, String p_reason = ""); diff --git a/modules/websocket/wsl_server.cpp b/modules/websocket/wsl_server.cpp index e3101d99d71..993dceafb9c 100644 --- a/modules/websocket/wsl_server.cpp +++ b/modules/websocket/wsl_server.cpp @@ -43,7 +43,7 @@ WSLServer::PendingPeer::PendingPeer() { memset(req_buf, 0, sizeof(req_buf)); } -bool WSLServer::PendingPeer::_parse_request(const PoolStringArray p_protocols) { +bool WSLServer::PendingPeer::_parse_request(const Vector p_protocols) { Vector psa = String((char *)req_buf).split("\r\n"); int len = psa.size(); ERR_FAIL_COND_V_MSG(len < 4, false, "Not enough response headers, got: " + itos(len) + ", expected >= 4."); @@ -98,7 +98,7 @@ bool WSLServer::PendingPeer::_parse_request(const PoolStringArray p_protocols) { return true; } -Error WSLServer::PendingPeer::do_handshake(PoolStringArray p_protocols) { +Error WSLServer::PendingPeer::do_handshake(const Vector p_protocols) { if (OS::get_singleton()->get_ticks_msec() - time > WSL_SERVER_TIMEOUT) return ERR_TIMEOUT; if (use_ssl) { @@ -154,11 +154,11 @@ Error WSLServer::PendingPeer::do_handshake(PoolStringArray p_protocols) { return OK; } -Error WSLServer::listen(int p_port, PoolVector p_protocols, bool gd_mp_api) { +Error WSLServer::listen(int p_port, const Vector p_protocols, bool gd_mp_api) { ERR_FAIL_COND_V(is_listening(), ERR_ALREADY_IN_USE); _is_multiplayer = gd_mp_api; - _protocols = p_protocols; + _protocols.append_array(p_protocols); _server->listen(p_port); return OK; @@ -252,6 +252,7 @@ void WSLServer::stop() { } _pending.clear(); _peer_map.clear(); + _protocols.clear(); } bool WSLServer::has_peer(int p_id) const { diff --git a/modules/websocket/wsl_server.h b/modules/websocket/wsl_server.h index 2ac873cba5c..aae563355e0 100644 --- a/modules/websocket/wsl_server.h +++ b/modules/websocket/wsl_server.h @@ -50,7 +50,7 @@ private: class PendingPeer : public Reference { private: - bool _parse_request(const PoolStringArray p_protocols); + bool _parse_request(const Vector p_protocols); public: Ref tcp; @@ -68,7 +68,7 @@ private: PendingPeer(); - Error do_handshake(const PoolStringArray p_protocols); + Error do_handshake(const Vector p_protocols); }; int _in_buf_size; @@ -78,11 +78,11 @@ private: List > _pending; Ref _server; - PoolStringArray _protocols; + Vector _protocols; public: Error set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffer, int p_out_packets); - Error listen(int p_port, PoolVector p_protocols = PoolVector(), bool gd_mp_api = false); + Error listen(int p_port, const Vector p_protocols = Vector(), bool gd_mp_api = false); void stop(); bool is_listening() const; int get_max_packet_size() const; From 2c557787c119ac629085cba2455132f5b82553dc Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Tue, 8 Oct 2019 20:56:10 +0200 Subject: [PATCH 5/5] Document all this new improvements. --- .../websocket/doc_classes/WebSocketClient.xml | 20 +++++++++++++++++++ .../websocket/doc_classes/WebSocketServer.xml | 11 ++++++++++ 2 files changed, 31 insertions(+) diff --git a/modules/websocket/doc_classes/WebSocketClient.xml b/modules/websocket/doc_classes/WebSocketClient.xml index c3baf9de83c..705e3485f58 100644 --- a/modules/websocket/doc_classes/WebSocketClient.xml +++ b/modules/websocket/doc_classes/WebSocketClient.xml @@ -21,10 +21,13 @@ + + Connects to the given URL requesting one of the given [code]protocols[/code] as sub-protocol. If the list empty (default), no sub-protocol will be requested. If [code]true[/code] is passed as [code]gd_mp_api[/code], the client will behave like a network peer for the [MultiplayerAPI], connections to non-Godot servers will not work, and [signal data_received] will not be emitted. If [code]false[/code] is passed instead (default), you must call [PacketPeer] functions ([code]put_packet[/code], [code]get_packet[/code], etc.) on the [WebSocketPeer] returned via [code]get_peer(1)[/code] and not on this object directly (e.g. [code]get_peer(1).put_packet(data)[/code]). + You can optionally pass a list of [code]custom_headers[/code] to be added to the handshake HTTP request (not supported in HTML5 platform). @@ -38,8 +41,25 @@ Disconnects this client from the connected host. See [method WebSocketPeer.close] for more information. + + + + + Return the IP address of the currently connected host. + + + + + + + Return the IP port of the currently connected host. + + + + If specified, this [X509Certificate] will be the only one accepted when connecting to an SSL host. Any other certificate provided by the server will be regarded as invalid. + If [code]true[/code], SSL certificate verification is enabled. [b]Note:[/b] You must specify the certificates to be used in the Project Settings for it to work when exported. diff --git a/modules/websocket/doc_classes/WebSocketServer.xml b/modules/websocket/doc_classes/WebSocketServer.xml index 63318e58743..651048316c9 100644 --- a/modules/websocket/doc_classes/WebSocketServer.xml +++ b/modules/websocket/doc_classes/WebSocketServer.xml @@ -82,6 +82,17 @@ + + + When using SSL (see [member private_key] and [member ssl_certificate]), you can set this to a valid [X509Certificate] to be provided as additional CA chain information during the SSL handshake. + + + When set to a valid [CryptoKey] (along with [member ssl_certificate]) will cause the server to require SSL instead of regular TCP (i.e. the `wss://` protocol). + + + When set to a valid [X509Certificate] (along with [member private_key]) will cause the server to require SSL instead of regular TCP (i.e. the `wss://` protocol). + +