summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/io/http_client.cpp36
-rw-r--r--core/io/http_client.h1
-rw-r--r--core/io/stream_peer_ssl.cpp17
-rw-r--r--core/io/stream_peer_ssl.h8
-rw-r--r--core/project_settings.cpp6
-rw-r--r--core/script_language.cpp77
-rw-r--r--core/script_language.h23
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];