diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/io/http_client.cpp | 36 | ||||
-rw-r--r-- | core/io/http_client.h | 1 | ||||
-rw-r--r-- | core/io/stream_peer_ssl.cpp | 17 | ||||
-rw-r--r-- | core/io/stream_peer_ssl.h | 8 | ||||
-rw-r--r-- | core/project_settings.cpp | 6 | ||||
-rw-r--r-- | core/script_language.cpp | 77 | ||||
-rw-r--r-- | core/script_language.h | 23 |
7 files changed, 158 insertions, 10 deletions
diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index fcbb22b5de..f1620f1493 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -279,6 +279,7 @@ void HTTPClient::close() { chunk_left = 0; read_until_eof = false; response_num = 0; + handshaking = false; } Error HTTPClient::poll() { @@ -327,16 +328,40 @@ Error HTTPClient::poll() { } break; case StreamPeerTCP::STATUS_CONNECTED: { if (ssl) { - Ref<StreamPeerSSL> ssl = StreamPeerSSL::create(); - Error err = ssl->connect_to_stream(tcp_connection, ssl_verify_host, conn_host); - if (err != OK) { + Ref<StreamPeerSSL> ssl; + if (!handshaking) { + // Connect the StreamPeerSSL and start handshaking + ssl = Ref<StreamPeerSSL>(StreamPeerSSL::create()); + ssl->set_blocking_handshake_enabled(false); + Error err = ssl->connect_to_stream(tcp_connection, ssl_verify_host, conn_host); + if (err != OK) { + close(); + status = STATUS_SSL_HANDSHAKE_ERROR; + return ERR_CANT_CONNECT; + } + connection = ssl; + handshaking = true; + } else { + // We are already handshaking, which means we can use your already active SSL connection + ssl = static_cast<Ref<StreamPeerSSL> >(connection); + ssl->poll(); // Try to finish the handshake + } + + if (ssl->get_status() == StreamPeerSSL::STATUS_CONNECTED) { + // Handshake has been successfull + handshaking = false; + status = STATUS_CONNECTED; + return OK; + } else if (ssl->get_status() != StreamPeerSSL::STATUS_HANDSHAKING) { + // Handshake has failed close(); status = STATUS_SSL_HANDSHAKE_ERROR; return ERR_CANT_CONNECT; } - connection = ssl; + // ... we will need to poll more for handshake to finish + } else { + status = STATUS_CONNECTED; } - status = STATUS_CONNECTED; return OK; } break; case StreamPeerTCP::STATUS_ERROR: @@ -669,6 +694,7 @@ HTTPClient::HTTPClient() { response_num = 0; ssl = false; blocking = false; + handshaking = false; read_chunk_size = 4096; } diff --git a/core/io/http_client.h b/core/io/http_client.h index 38ec82ce8c..82b56b01db 100644 --- a/core/io/http_client.h +++ b/core/io/http_client.h @@ -165,6 +165,7 @@ private: bool ssl; bool ssl_verify_host; bool blocking; + bool handshaking; Vector<uint8_t> response_str; diff --git a/core/io/stream_peer_ssl.cpp b/core/io/stream_peer_ssl.cpp index 012ba78c6d..c71af6b641 100644 --- a/core/io/stream_peer_ssl.cpp +++ b/core/io/stream_peer_ssl.cpp @@ -52,6 +52,14 @@ bool StreamPeerSSL::is_available() { return available; } +void StreamPeerSSL::set_blocking_handshake_enabled(bool p_enabled) { + blocking_handshake = p_enabled; +} + +bool StreamPeerSSL::is_blocking_handshake_enabled() const { + return blocking_handshake; +} + PoolByteArray StreamPeerSSL::get_project_cert_array() { PoolByteArray out; @@ -84,16 +92,21 @@ PoolByteArray StreamPeerSSL::get_project_cert_array() { void StreamPeerSSL::_bind_methods() { ClassDB::bind_method(D_METHOD("poll"), &StreamPeerSSL::poll); - ClassDB::bind_method(D_METHOD("accept_stream", "stream"), &StreamPeerSSL::accept_stream); + ClassDB::bind_method(D_METHOD("accept_stream"), &StreamPeerSSL::accept_stream); ClassDB::bind_method(D_METHOD("connect_to_stream", "stream", "validate_certs", "for_hostname"), &StreamPeerSSL::connect_to_stream, DEFVAL(false), DEFVAL(String())); ClassDB::bind_method(D_METHOD("get_status"), &StreamPeerSSL::get_status); ClassDB::bind_method(D_METHOD("disconnect_from_stream"), &StreamPeerSSL::disconnect_from_stream); + ClassDB::bind_method(D_METHOD("set_blocking_handshake_enabled", "enabled"), &StreamPeerSSL::set_blocking_handshake_enabled); + ClassDB::bind_method(D_METHOD("is_blocking_handshake_enabled"), &StreamPeerSSL::is_blocking_handshake_enabled); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "blocking_handshake"), "set_blocking_handshake_enabled", "is_blocking_handshake_enabled"); BIND_ENUM_CONSTANT(STATUS_DISCONNECTED); BIND_ENUM_CONSTANT(STATUS_CONNECTED); - BIND_ENUM_CONSTANT(STATUS_ERROR_NO_CERTIFICATE); + BIND_ENUM_CONSTANT(STATUS_ERROR); BIND_ENUM_CONSTANT(STATUS_ERROR_HOSTNAME_MISMATCH); } StreamPeerSSL::StreamPeerSSL() { + blocking_handshake = true; } diff --git a/core/io/stream_peer_ssl.h b/core/io/stream_peer_ssl.h index 77301a7c87..870704e875 100644 --- a/core/io/stream_peer_ssl.h +++ b/core/io/stream_peer_ssl.h @@ -49,14 +49,20 @@ protected: friend class Main; static bool initialize_certs; + bool blocking_handshake; + public: enum Status { STATUS_DISCONNECTED, + STATUS_HANDSHAKING, STATUS_CONNECTED, - STATUS_ERROR_NO_CERTIFICATE, + STATUS_ERROR, STATUS_ERROR_HOSTNAME_MISMATCH }; + void set_blocking_handshake_enabled(bool p_enabled); + bool is_blocking_handshake_enabled() const; + virtual void poll() = 0; virtual Error accept_stream(Ref<StreamPeer> p_base) = 0; virtual Error connect_to_stream(Ref<StreamPeer> p_base, bool p_validate_certs = false, const String &p_for_hostname = String()) = 0; diff --git a/core/project_settings.cpp b/core/project_settings.cpp index 7f9f4b638a..b1fd66e566 100644 --- a/core/project_settings.cpp +++ b/core/project_settings.cpp @@ -515,7 +515,11 @@ Error ProjectSettings::_load_settings_text(const String p_path) { } } else { // config_version is checked and dropped - set(section + "/" + assign, value); + if (section == String()) { + set(assign, value); + } else { + set(section + "/" + assign, value); + } } } else if (next_tag.name != String()) { section = next_tag.name; diff --git a/core/script_language.cpp b/core/script_language.cpp index acbe3b34db..37ba3cfc62 100644 --- a/core/script_language.cpp +++ b/core/script_language.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "script_language.h" +#include "project_settings.h" ScriptLanguage *ScriptServer::_languages[MAX_LANGUAGES]; int ScriptServer::_language_count = 0; @@ -103,6 +104,20 @@ void ScriptServer::unregister_language(ScriptLanguage *p_language) { void ScriptServer::init_languages() { + { //load global classes + global_classes_clear(); + if (ProjectSettings::get_singleton()->has_setting("_global_script_classes")) { + Array script_classes = ProjectSettings::get_singleton()->get("_global_script_classes"); + + for (int i = 0; i < script_classes.size(); i++) { + Dictionary c = script_classes[i]; + if (!c.has("class") || !c.has("language") || !c.has("path") || !c.has("base")) + continue; + add_global_class(c["class"], c["base"], c["language"], c["path"]); + } + } + } + for (int i = 0; i < _language_count; i++) { _languages[i]->init(); } @@ -113,6 +128,7 @@ void ScriptServer::finish_languages() { for (int i = 0; i < _language_count; i++) { _languages[i]->finish(); } + global_classes_clear(); } void ScriptServer::set_reload_scripts_on_save(bool p_enable) { @@ -139,6 +155,67 @@ void ScriptServer::thread_exit() { } } +HashMap<StringName, ScriptServer::GlobalScriptClass> ScriptServer::global_classes; + +void ScriptServer::global_classes_clear() { + global_classes.clear(); +} + +void ScriptServer::add_global_class(const StringName &p_class, const StringName &p_base, const StringName &p_language, const String &p_path) { + GlobalScriptClass g; + g.language = p_language; + g.path = p_path; + g.base = p_base; + global_classes[p_class] = g; +} +void ScriptServer::remove_global_class(const StringName &p_class) { + global_classes.erase(p_class); +} +bool ScriptServer::is_global_class(const StringName &p_class) { + return global_classes.has(p_class); +} +StringName ScriptServer::get_global_class_language(const StringName &p_class) { + ERR_FAIL_COND_V(!global_classes.has(p_class), StringName()); + return global_classes[p_class].language; +} +String ScriptServer::get_global_class_path(const String &p_class) { + ERR_FAIL_COND_V(!global_classes.has(p_class), String()); + return global_classes[p_class].path; +} + +StringName ScriptServer::get_global_class_base(const String &p_class) { + ERR_FAIL_COND_V(!global_classes.has(p_class), String()); + return global_classes[p_class].base; +} +void ScriptServer::get_global_class_list(List<StringName> *r_global_classes) { + const StringName *K = NULL; + List<StringName> classes; + while ((K = global_classes.next(K))) { + classes.push_back(*K); + } + classes.sort_custom<StringName::AlphCompare>(); + for (List<StringName>::Element *E = classes.front(); E; E = E->next()) { + r_global_classes->push_back(E->get()); + } +} +void ScriptServer::save_global_classes() { + List<StringName> gc; + get_global_class_list(&gc); + Array gcarr; + for (List<StringName>::Element *E = gc.front(); E; E = E->next()) { + Dictionary d; + d["class"] = E->get(); + d["language"] = global_classes[E->get()].language; + d["path"] = global_classes[E->get()].path; + d["base"] = global_classes[E->get()].base; + gcarr.push_back(d); + } + + ProjectSettings::get_singleton()->set("_global_script_classes", gcarr); + ProjectSettings::get_singleton()->save(); +} + +//////////////////// void ScriptInstance::get_property_state(List<Pair<StringName, Variant> > &state) { List<PropertyInfo> pinfo; diff --git a/core/script_language.h b/core/script_language.h index e7748f93e2..2950b35109 100644 --- a/core/script_language.h +++ b/core/script_language.h @@ -54,6 +54,14 @@ class ScriptServer { static bool scripting_enabled; static bool reload_scripts_on_save; + struct GlobalScriptClass { + StringName language; + String path; + String base; + }; + + static HashMap<StringName, GlobalScriptClass> global_classes; + public: static ScriptEditRequestFunction edit_request_func; @@ -70,6 +78,16 @@ public: static void thread_enter(); static void thread_exit(); + static void global_classes_clear(); + static void add_global_class(const StringName &p_class, const StringName &p_base, const StringName &p_language, const String &p_path); + static void remove_global_class(const StringName &p_class); + static bool is_global_class(const StringName &p_class); + static StringName get_global_class_language(const StringName &p_class); + static String get_global_class_path(const String &p_class); + static StringName get_global_class_base(const String &p_class); + static void get_global_class_list(List<StringName> *r_global_classes); + static void save_global_classes(); + static void init_languages(); static void finish_languages(); }; @@ -285,7 +303,10 @@ public: virtual void frame(); - virtual ~ScriptLanguage(){}; + virtual bool handles_global_class_type(const String &p_type) const { return false; } + virtual String get_global_class_name(const String &p_path, String *r_base_type = NULL) const { return String(); } + + virtual ~ScriptLanguage() {} }; extern uint8_t script_encryption_key[32]; |