diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/SCsub | 1 | ||||
-rw-r--r-- | core/bind/core_bind.cpp | 2 | ||||
-rw-r--r-- | core/crypto/SCsub | 38 | ||||
-rw-r--r-- | core/crypto/crypto.cpp | 170 | ||||
-rw-r--r-- | core/crypto/crypto.h | 105 | ||||
-rw-r--r-- | core/crypto/crypto_core.cpp (renamed from core/math/crypto_core.cpp) | 32 | ||||
-rw-r--r-- | core/crypto/crypto_core.h (renamed from core/math/crypto_core.h) | 20 | ||||
-rw-r--r-- | core/crypto/hashing_context.cpp | 137 | ||||
-rw-r--r-- | core/crypto/hashing_context.h | 66 | ||||
-rw-r--r-- | core/io/config_file.cpp | 2 | ||||
-rw-r--r-- | core/io/file_access_encrypted.cpp | 2 | ||||
-rw-r--r-- | core/io/file_access_pack.cpp | 6 | ||||
-rw-r--r-- | core/io/stream_peer_ssl.cpp | 68 | ||||
-rw-r--r-- | core/io/stream_peer_ssl.h | 13 | ||||
-rw-r--r-- | core/math/SCsub | 33 | ||||
-rw-r--r-- | core/math/a_star.cpp | 239 | ||||
-rw-r--r-- | core/math/a_star.h | 26 | ||||
-rw-r--r-- | core/math/delaunay.h | 4 | ||||
-rw-r--r-- | core/oa_hash_map.h | 34 | ||||
-rw-r--r-- | core/object.cpp | 11 | ||||
-rw-r--r-- | core/object.h | 2 | ||||
-rw-r--r-- | core/os/file_access.cpp | 2 | ||||
-rw-r--r-- | core/register_core_types.cpp | 24 | ||||
-rw-r--r-- | core/ustring.cpp | 2 | ||||
-rw-r--r-- | core/variant_call.cpp | 10 |
25 files changed, 807 insertions, 242 deletions
diff --git a/core/SCsub b/core/SCsub index 85e5f1b089..ed9a0a231d 100644 --- a/core/SCsub +++ b/core/SCsub @@ -159,6 +159,7 @@ env.CommandNoCache('#core/license.gen.h', ["../COPYRIGHT.txt", "../LICENSE.txt"] # Chain load SCsubs SConscript('os/SCsub') SConscript('math/SCsub') +SConscript('crypto/SCsub') SConscript('io/SCsub') SConscript('bind/SCsub') diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index 56369a3cc6..8e0d156438 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -30,11 +30,11 @@ #include "core_bind.h" +#include "core/crypto/crypto_core.h" #include "core/io/file_access_compressed.h" #include "core/io/file_access_encrypted.h" #include "core/io/json.h" #include "core/io/marshalls.h" -#include "core/math/crypto_core.h" #include "core/math/geometry.h" #include "core/os/keyboard.h" #include "core/os/os.h" diff --git a/core/crypto/SCsub b/core/crypto/SCsub new file mode 100644 index 0000000000..0a3f05d87a --- /dev/null +++ b/core/crypto/SCsub @@ -0,0 +1,38 @@ +#!/usr/bin/env python + +Import('env') + +env_crypto = env.Clone() + +is_builtin = env["builtin_mbedtls"] +has_module = env["module_mbedtls_enabled"] + +if is_builtin or not has_module: + # Use our headers for builtin or if the module is not going to be compiled. + # We decided not to depend on system mbedtls just for these few files that can + # be easily extracted. + env_crypto.Prepend(CPPPATH=["#thirdparty/mbedtls/include"]) + +# MbedTLS core functions (for CryptoCore). +# If the mbedtls module is compiled we don't need to add the .c files with our +# custom config since they will be built by the module itself. +# Only if the module is not enabled, we must compile here the required sources +# to make a "light" build with only the necessary mbedtls files. +if not has_module: + env_thirdparty = env_crypto.Clone() + env_thirdparty.disable_warnings() + # Custom config file + env_thirdparty.Append(CPPDEFINES=[('MBEDTLS_CONFIG_FILE', '\\"thirdparty/mbedtls/include/godot_core_mbedtls_config.h\\"')]) + thirdparty_mbedtls_dir = "#thirdparty/mbedtls/library/" + thirdparty_mbedtls_sources = [ + "aes.c", + "base64.c", + "md5.c", + "sha1.c", + "sha256.c", + "godot_core_mbedtls_platform.c" + ] + thirdparty_mbedtls_sources = [thirdparty_mbedtls_dir + file for file in thirdparty_mbedtls_sources] + env_thirdparty.add_source_files(env.core_sources, thirdparty_mbedtls_sources) + +env_crypto.add_source_files(env.core_sources, "*.cpp") diff --git a/core/crypto/crypto.cpp b/core/crypto/crypto.cpp new file mode 100644 index 0000000000..925a01b36a --- /dev/null +++ b/core/crypto/crypto.cpp @@ -0,0 +1,170 @@ +/*************************************************************************/ +/* crypto.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "crypto.h" + +#include "core/engine.h" +#include "core/io/certs_compressed.gen.h" +#include "core/io/compression.h" + +/// Resources + +CryptoKey *(*CryptoKey::_create)() = NULL; +CryptoKey *CryptoKey::create() { + if (_create) + return _create(); + return NULL; +} + +void CryptoKey::_bind_methods() { + ClassDB::bind_method(D_METHOD("save", "path"), &CryptoKey::save); + ClassDB::bind_method(D_METHOD("load", "path"), &CryptoKey::load); +} + +X509Certificate *(*X509Certificate::_create)() = NULL; +X509Certificate *X509Certificate::create() { + if (_create) + return _create(); + return NULL; +} + +void X509Certificate::_bind_methods() { + ClassDB::bind_method(D_METHOD("save", "path"), &X509Certificate::save); + ClassDB::bind_method(D_METHOD("load", "path"), &X509Certificate::load); +} + +/// Crypto + +void (*Crypto::_load_default_certificates)(String p_path) = NULL; +Crypto *(*Crypto::_create)() = NULL; +Crypto *Crypto::create() { + if (_create) + return _create(); + return memnew(Crypto); +} + +void Crypto::load_default_certificates(String p_path) { + + if (_load_default_certificates) + _load_default_certificates(p_path); +} + +void Crypto::_bind_methods() { + ClassDB::bind_method(D_METHOD("generate_random_bytes", "size"), &Crypto::generate_random_bytes); + ClassDB::bind_method(D_METHOD("generate_rsa", "size"), &Crypto::generate_rsa); + ClassDB::bind_method(D_METHOD("generate_self_signed_certificate", "key", "issuer_name", "not_before", "not_after"), &Crypto::generate_self_signed_certificate, DEFVAL("CN=myserver,O=myorganisation,C=IT"), DEFVAL("20140101000000"), DEFVAL("20340101000000")); +} + +PoolByteArray Crypto::generate_random_bytes(int p_bytes) { + ERR_FAIL_V_MSG(PoolByteArray(), "generate_random_bytes is not available when mbedtls module is disabled."); +} + +Ref<CryptoKey> Crypto::generate_rsa(int p_bytes) { + ERR_FAIL_V_MSG(NULL, "generate_rsa is not available when mbedtls module is disabled."); +} + +Ref<X509Certificate> Crypto::generate_self_signed_certificate(Ref<CryptoKey> p_key, String p_issuer_name, String p_not_before, String p_not_after) { + ERR_FAIL_V_MSG(NULL, "generate_self_signed_certificate is not available when mbedtls module is disabled."); +} + +Crypto::Crypto() { +} + +/// Resource loader/saver + +RES ResourceFormatLoaderCrypto::load(const String &p_path, const String &p_original_path, Error *r_error) { + + String el = p_path.get_extension().to_lower(); + if (el == "crt") { + X509Certificate *cert = X509Certificate::create(); + if (cert) + cert->load(p_path); + return cert; + } else if (el == "key") { + CryptoKey *key = CryptoKey::create(); + if (key) + key->load(p_path); + return key; + } + return NULL; +} + +void ResourceFormatLoaderCrypto::get_recognized_extensions(List<String> *p_extensions) const { + + p_extensions->push_back("crt"); + p_extensions->push_back("key"); +} + +bool ResourceFormatLoaderCrypto::handles_type(const String &p_type) const { + + return p_type == "X509Certificate" || p_type == "CryptoKey"; +} + +String ResourceFormatLoaderCrypto::get_resource_type(const String &p_path) const { + + String el = p_path.get_extension().to_lower(); + if (el == "crt") + return "X509Certificate"; + else if (el == "key") + return "CryptoKey"; + return ""; +} + +Error ResourceFormatSaverCrypto::save(const String &p_path, const RES &p_resource, uint32_t p_flags) { + + Error err; + Ref<X509Certificate> cert = p_resource; + Ref<CryptoKey> key = p_resource; + if (cert.is_valid()) { + err = cert->save(p_path); + } else if (key.is_valid()) { + err = key->save(p_path); + } else { + ERR_FAIL_V(ERR_INVALID_PARAMETER); + } + ERR_FAIL_COND_V(err != OK, err); + return OK; +} + +void ResourceFormatSaverCrypto::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const { + + const X509Certificate *cert = Object::cast_to<X509Certificate>(*p_resource); + const CryptoKey *key = Object::cast_to<CryptoKey>(*p_resource); + if (cert) { + p_extensions->push_back("crt"); + } + if (key) { + p_extensions->push_back("key"); + } +} +bool ResourceFormatSaverCrypto::recognize(const RES &p_resource) const { + + return Object::cast_to<X509Certificate>(*p_resource) || Object::cast_to<CryptoKey>(*p_resource); +} diff --git a/core/crypto/crypto.h b/core/crypto/crypto.h new file mode 100644 index 0000000000..2de81f5b57 --- /dev/null +++ b/core/crypto/crypto.h @@ -0,0 +1,105 @@ +/*************************************************************************/ +/* crypto.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef CRYPTO_H +#define CRYPTO_H + +#include "core/reference.h" +#include "core/resource.h" + +#include "core/io/resource_loader.h" +#include "core/io/resource_saver.h" + +class CryptoKey : public Resource { + GDCLASS(CryptoKey, Resource); + +protected: + static void _bind_methods(); + static CryptoKey *(*_create)(); + +public: + static CryptoKey *create(); + virtual Error load(String p_path) = 0; + virtual Error save(String p_path) = 0; +}; + +class X509Certificate : public Resource { + GDCLASS(X509Certificate, Resource); + +protected: + static void _bind_methods(); + static X509Certificate *(*_create)(); + +public: + static X509Certificate *create(); + virtual Error load(String p_path) = 0; + virtual Error load_from_memory(const uint8_t *p_buffer, int p_len) = 0; + virtual Error save(String p_path) = 0; +}; + +class Crypto : public Reference { + GDCLASS(Crypto, Reference); + +protected: + static void _bind_methods(); + static Crypto *(*_create)(); + static void (*_load_default_certificates)(String p_path); + +public: + static Crypto *create(); + static void load_default_certificates(String p_path); + + virtual PoolByteArray generate_random_bytes(int p_bytes); + virtual Ref<CryptoKey> generate_rsa(int p_bytes); + virtual Ref<X509Certificate> generate_self_signed_certificate(Ref<CryptoKey> p_key, String p_issuer_name, String p_not_before, String p_not_after); + + Crypto(); +}; + +class ResourceFormatLoaderCrypto : public ResourceFormatLoader { + GDCLASS(ResourceFormatLoaderCrypto, ResourceFormatLoader); + +public: + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL); + virtual void get_recognized_extensions(List<String> *p_extensions) const; + virtual bool handles_type(const String &p_type) const; + virtual String get_resource_type(const String &p_path) const; +}; + +class ResourceFormatSaverCrypto : public ResourceFormatSaver { + GDCLASS(ResourceFormatSaverCrypto, ResourceFormatSaver); + +public: + virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0); + virtual void get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const; + virtual bool recognize(const RES &p_resource) const; +}; + +#endif // CRYPTO_H diff --git a/core/math/crypto_core.cpp b/core/crypto/crypto_core.cpp index d7ba54e469..51c2e3c9e5 100644 --- a/core/math/crypto_core.cpp +++ b/core/crypto/crypto_core.cpp @@ -52,7 +52,7 @@ Error CryptoCore::MD5Context::start() { return ret ? FAILED : OK; } -Error CryptoCore::MD5Context::update(uint8_t *p_src, size_t p_len) { +Error CryptoCore::MD5Context::update(const uint8_t *p_src, size_t p_len) { int ret = mbedtls_md5_update_ret((mbedtls_md5_context *)ctx, p_src, p_len); return ret ? FAILED : OK; } @@ -62,6 +62,32 @@ Error CryptoCore::MD5Context::finish(unsigned char r_hash[16]) { return ret ? FAILED : OK; } +// SHA1 +CryptoCore::SHA1Context::SHA1Context() { + ctx = memalloc(sizeof(mbedtls_sha1_context)); + mbedtls_sha1_init((mbedtls_sha1_context *)ctx); +} + +CryptoCore::SHA1Context::~SHA1Context() { + mbedtls_sha1_free((mbedtls_sha1_context *)ctx); + memfree((mbedtls_sha1_context *)ctx); +} + +Error CryptoCore::SHA1Context::start() { + int ret = mbedtls_sha1_starts_ret((mbedtls_sha1_context *)ctx); + return ret ? FAILED : OK; +} + +Error CryptoCore::SHA1Context::update(const uint8_t *p_src, size_t p_len) { + int ret = mbedtls_sha1_update_ret((mbedtls_sha1_context *)ctx, p_src, p_len); + return ret ? FAILED : OK; +} + +Error CryptoCore::SHA1Context::finish(unsigned char r_hash[20]) { + int ret = mbedtls_sha1_finish_ret((mbedtls_sha1_context *)ctx, r_hash); + return ret ? FAILED : OK; +} + // SHA256 CryptoCore::SHA256Context::SHA256Context() { ctx = memalloc(sizeof(mbedtls_sha256_context)); @@ -78,12 +104,12 @@ Error CryptoCore::SHA256Context::start() { return ret ? FAILED : OK; } -Error CryptoCore::SHA256Context::update(uint8_t *p_src, size_t p_len) { +Error CryptoCore::SHA256Context::update(const uint8_t *p_src, size_t p_len) { int ret = mbedtls_sha256_update_ret((mbedtls_sha256_context *)ctx, p_src, p_len); return ret ? FAILED : OK; } -Error CryptoCore::SHA256Context::finish(unsigned char r_hash[16]) { +Error CryptoCore::SHA256Context::finish(unsigned char r_hash[32]) { int ret = mbedtls_sha256_finish_ret((mbedtls_sha256_context *)ctx, r_hash); return ret ? FAILED : OK; } diff --git a/core/math/crypto_core.h b/core/crypto/crypto_core.h index e28cb5a792..c859d612d4 100644 --- a/core/math/crypto_core.h +++ b/core/crypto/crypto_core.h @@ -46,10 +46,24 @@ public: ~MD5Context(); Error start(); - Error update(uint8_t *p_src, size_t p_len); + Error update(const uint8_t *p_src, size_t p_len); Error finish(unsigned char r_hash[16]); }; + class SHA1Context { + + private: + void *ctx; // To include, or not to include... + + public: + SHA1Context(); + ~SHA1Context(); + + Error start(); + Error update(const uint8_t *p_src, size_t p_len); + Error finish(unsigned char r_hash[20]); + }; + class SHA256Context { private: @@ -60,8 +74,8 @@ public: ~SHA256Context(); Error start(); - Error update(uint8_t *p_src, size_t p_len); - Error finish(unsigned char r_hash[16]); + Error update(const uint8_t *p_src, size_t p_len); + Error finish(unsigned char r_hash[32]); }; class AESContext { diff --git a/core/crypto/hashing_context.cpp b/core/crypto/hashing_context.cpp new file mode 100644 index 0000000000..bdccb258dd --- /dev/null +++ b/core/crypto/hashing_context.cpp @@ -0,0 +1,137 @@ +/*************************************************************************/ +/* hashing_context.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "hashing_context.h" + +#include "core/crypto/crypto_core.h" + +Error HashingContext::start(HashType p_type) { + ERR_FAIL_COND_V(ctx != NULL, ERR_ALREADY_IN_USE); + _create_ctx(p_type); + ERR_FAIL_COND_V(ctx == NULL, ERR_UNAVAILABLE); + switch (type) { + case HASH_MD5: + return ((CryptoCore::MD5Context *)ctx)->start(); + case HASH_SHA1: + return ((CryptoCore::SHA1Context *)ctx)->start(); + case HASH_SHA256: + return ((CryptoCore::SHA256Context *)ctx)->start(); + } + return ERR_UNAVAILABLE; +} + +Error HashingContext::update(PoolByteArray p_chunk) { + ERR_FAIL_COND_V(ctx == NULL, ERR_UNCONFIGURED); + size_t len = p_chunk.size(); + PoolByteArray::Read r = p_chunk.read(); + switch (type) { + case HASH_MD5: + return ((CryptoCore::MD5Context *)ctx)->update(&r[0], len); + case HASH_SHA1: + return ((CryptoCore::SHA1Context *)ctx)->update(&r[0], len); + case HASH_SHA256: + return ((CryptoCore::SHA256Context *)ctx)->update(&r[0], len); + } + return ERR_UNAVAILABLE; +} + +PoolByteArray HashingContext::finish() { + ERR_FAIL_COND_V(ctx == NULL, PoolByteArray()); + PoolByteArray out; + Error err = FAILED; + switch (type) { + case HASH_MD5: + out.resize(16); + err = ((CryptoCore::MD5Context *)ctx)->finish(out.write().ptr()); + break; + case HASH_SHA1: + out.resize(20); + err = ((CryptoCore::SHA1Context *)ctx)->finish(out.write().ptr()); + break; + case HASH_SHA256: + out.resize(32); + err = ((CryptoCore::SHA256Context *)ctx)->finish(out.write().ptr()); + break; + } + _delete_ctx(); + ERR_FAIL_COND_V(err != OK, PoolByteArray()); + return out; +} + +void HashingContext::_create_ctx(HashType p_type) { + type = p_type; + switch (type) { + case HASH_MD5: + ctx = memnew(CryptoCore::MD5Context); + break; + case HASH_SHA1: + ctx = memnew(CryptoCore::SHA1Context); + break; + case HASH_SHA256: + ctx = memnew(CryptoCore::SHA256Context); + break; + default: + ctx = NULL; + } +} + +void HashingContext::_delete_ctx() { + return; + switch (type) { + case HASH_MD5: + memdelete((CryptoCore::MD5Context *)ctx); + break; + case HASH_SHA1: + memdelete((CryptoCore::SHA1Context *)ctx); + break; + case HASH_SHA256: + memdelete((CryptoCore::SHA256Context *)ctx); + break; + } + ctx = NULL; +} + +void HashingContext::_bind_methods() { + ClassDB::bind_method(D_METHOD("start", "type"), &HashingContext::start); + ClassDB::bind_method(D_METHOD("update", "chunk"), &HashingContext::update); + ClassDB::bind_method(D_METHOD("finish"), &HashingContext::finish); + BIND_ENUM_CONSTANT(HASH_MD5); + BIND_ENUM_CONSTANT(HASH_SHA1); + BIND_ENUM_CONSTANT(HASH_SHA256); +} + +HashingContext::HashingContext() { + ctx = NULL; +} + +HashingContext::~HashingContext() { + if (ctx != NULL) + _delete_ctx(); +} diff --git a/core/crypto/hashing_context.h b/core/crypto/hashing_context.h new file mode 100644 index 0000000000..aa69636f2c --- /dev/null +++ b/core/crypto/hashing_context.h @@ -0,0 +1,66 @@ +/*************************************************************************/ +/* hashing_context.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef HASHING_CONTEXT_H +#define HASHING_CONTEXT_H + +#include "core/reference.h" + +class HashingContext : public Reference { + GDCLASS(HashingContext, Reference); + +public: + enum HashType { + HASH_MD5, + HASH_SHA1, + HASH_SHA256 + }; + +private: + void *ctx; + HashType type; + +protected: + static void _bind_methods(); + void _create_ctx(HashType p_type); + void _delete_ctx(); + +public: + Error start(HashType p_type); + Error update(PoolByteArray p_chunk); + PoolByteArray finish(); + + HashingContext(); + ~HashingContext(); +}; + +VARIANT_ENUM_CAST(HashingContext::HashType); + +#endif // HASHING_CONTEXT_H diff --git a/core/io/config_file.cpp b/core/io/config_file.cpp index 70bb816acd..9063e028be 100644 --- a/core/io/config_file.cpp +++ b/core/io/config_file.cpp @@ -201,7 +201,7 @@ Error ConfigFile::load(const String &p_path) { FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err); if (!f) - return ERR_CANT_OPEN; + return err; return _internal_load(p_path, f); } diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp index 1452c61d1a..77decc107d 100644 --- a/core/io/file_access_encrypted.cpp +++ b/core/io/file_access_encrypted.cpp @@ -30,7 +30,7 @@ #include "file_access_encrypted.h" -#include "core/math/crypto_core.h" +#include "core/crypto/crypto_core.h" #include "core/os/copymem.h" #include "core/print_string.h" #include "core/variant.h" diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp index 6b683759f8..d49d36c2b9 100644 --- a/core/io/file_access_pack.cpp +++ b/core/io/file_access_pack.cpp @@ -90,7 +90,7 @@ void PackedData::add_path(const String &pkg_path, const String &path, uint64_t o } } String filename = path.get_file(); - // Don't add as a file if the path points to a directoryy + // Don't add as a file if the path points to a directory if (!filename.empty()) { cd->files.insert(filename); } @@ -460,11 +460,15 @@ String DirAccessPack::get_current_dir() { bool DirAccessPack::file_exists(String p_file) { + p_file = fix_path(p_file); + return current->files.has(p_file); } bool DirAccessPack::dir_exists(String p_dir) { + p_dir = fix_path(p_dir); + return current->subdirs.has(p_dir); } diff --git a/core/io/stream_peer_ssl.cpp b/core/io/stream_peer_ssl.cpp index ccce48ccd7..f2eaf57acc 100644 --- a/core/io/stream_peer_ssl.cpp +++ b/core/io/stream_peer_ssl.cpp @@ -30,10 +30,7 @@ #include "stream_peer_ssl.h" -#include "core/io/certs_compressed.gen.h" -#include "core/io/compression.h" -#include "core/os/file_access.h" -#include "core/project_settings.h" +#include "core/engine.h" StreamPeerSSL *(*StreamPeerSSL::_create)() = NULL; @@ -44,22 +41,8 @@ StreamPeerSSL *StreamPeerSSL::create() { return NULL; } -StreamPeerSSL::LoadCertsFromMemory StreamPeerSSL::load_certs_func = NULL; bool StreamPeerSSL::available = false; -void StreamPeerSSL::load_certs_from_memory(const PoolByteArray &p_memory) { - if (load_certs_func) - load_certs_func(p_memory); -} - -void StreamPeerSSL::load_certs_from_file(String p_path) { - if (p_path != "") { - PoolByteArray certs = get_cert_file_as_array(p_path); - if (certs.size() > 0) - load_certs_func(certs); - } -} - bool StreamPeerSSL::is_available() { return available; } @@ -72,56 +55,11 @@ bool StreamPeerSSL::is_blocking_handshake_enabled() const { return blocking_handshake; } -PoolByteArray StreamPeerSSL::get_cert_file_as_array(String p_path) { - - PoolByteArray out; - FileAccess *f = FileAccess::open(p_path, FileAccess::READ); - if (f) { - int flen = f->get_len(); - out.resize(flen + 1); - PoolByteArray::Write w = out.write(); - f->get_buffer(w.ptr(), flen); - w[flen] = 0; // Make sure it ends with string terminator - memdelete(f); -#ifdef DEBUG_ENABLED - print_verbose(vformat("Loaded certs from '%s'.", p_path)); -#endif - } - - return out; -} - -PoolByteArray StreamPeerSSL::get_project_cert_array() { - - PoolByteArray out; - String certs_path = GLOBAL_DEF("network/ssl/certificates", ""); - ProjectSettings::get_singleton()->set_custom_property_info("network/ssl/certificates", PropertyInfo(Variant::STRING, "network/ssl/certificates", PROPERTY_HINT_FILE, "*.crt")); - - if (certs_path != "") { - // Use certs defined in project settings. - return get_cert_file_as_array(certs_path); - } -#ifdef BUILTIN_CERTS_ENABLED - else { - // Use builtin certs only if user did not override it in project settings. - out.resize(_certs_uncompressed_size + 1); - PoolByteArray::Write w = out.write(); - Compression::decompress(w.ptr(), _certs_uncompressed_size, _certs_compressed, _certs_compressed_size, Compression::MODE_DEFLATE); - w[_certs_uncompressed_size] = 0; // Make sure it ends with string terminator -#ifdef DEBUG_ENABLED - print_verbose("Loaded builtin certs"); -#endif - } -#endif - - return out; -} - void StreamPeerSSL::_bind_methods() { ClassDB::bind_method(D_METHOD("poll"), &StreamPeerSSL::poll); - ClassDB::bind_method(D_METHOD("accept_stream", "base"), &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("accept_stream", "stream", "private_key", "certificate", "chain"), &StreamPeerSSL::accept_stream, DEFVAL(Ref<X509Certificate>())); + ClassDB::bind_method(D_METHOD("connect_to_stream", "stream", "validate_certs", "for_hostname", "valid_certificate"), &StreamPeerSSL::connect_to_stream, DEFVAL(false), DEFVAL(String()), DEFVAL(Ref<X509Certificate>())); 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); diff --git a/core/io/stream_peer_ssl.h b/core/io/stream_peer_ssl.h index 482576c4c6..dedc35b9ac 100644 --- a/core/io/stream_peer_ssl.h +++ b/core/io/stream_peer_ssl.h @@ -31,19 +31,16 @@ #ifndef STREAM_PEER_SSL_H #define STREAM_PEER_SSL_H +#include "core/crypto/crypto.h" #include "core/io/stream_peer.h" class StreamPeerSSL : public StreamPeer { GDCLASS(StreamPeerSSL, StreamPeer); -public: - typedef void (*LoadCertsFromMemory)(const PoolByteArray &p_certs); - protected: static StreamPeerSSL *(*_create)(); static void _bind_methods(); - static LoadCertsFromMemory load_certs_func; static bool available; bool blocking_handshake; @@ -61,18 +58,14 @@ public: 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; + virtual Error accept_stream(Ref<StreamPeer> p_base, Ref<CryptoKey> p_key, Ref<X509Certificate> p_cert, Ref<X509Certificate> p_ca_chain = Ref<X509Certificate>()) = 0; + virtual Error connect_to_stream(Ref<StreamPeer> p_base, bool p_validate_certs = false, const String &p_for_hostname = String(), Ref<X509Certificate> p_valid_cert = Ref<X509Certificate>()) = 0; virtual Status get_status() const = 0; virtual void disconnect_from_stream() = 0; static StreamPeerSSL *create(); - static PoolByteArray get_cert_file_as_array(String p_path); - static PoolByteArray get_project_cert_array(); - static void load_certs_from_file(String p_path); - static void load_certs_from_memory(const PoolByteArray &p_memory); static bool is_available(); StreamPeerSSL(); diff --git a/core/math/SCsub b/core/math/SCsub index 0995298a4b..be438fcfbe 100644 --- a/core/math/SCsub +++ b/core/math/SCsub @@ -2,37 +2,6 @@ Import('env') -env_math = env.Clone() # Maybe make one specific for crypto? - -is_builtin = env["builtin_mbedtls"] -has_module = env["module_mbedtls_enabled"] - -if is_builtin or not has_module: - # Use our headers for builtin or if the module is not going to be compiled. - # We decided not to depend on system mbedtls just for these few files that can - # be easily extracted. - env_math.Prepend(CPPPATH=["#thirdparty/mbedtls/include"]) - -# MbedTLS core functions (for CryptoCore). -# If the mbedtls module is compiled we don't need to add the .c files with our -# custom config since they will be built by the module itself. -# Only if the module is not enabled, we must compile here the required sources -# to make a "light" build with only the necessary mbedtls files. -if not has_module: - env_thirdparty = env_math.Clone() - env_thirdparty.disable_warnings() - # Custom config file - env_thirdparty.Append(CPPDEFINES=[('MBEDTLS_CONFIG_FILE', '\\"thirdparty/mbedtls/include/godot_core_mbedtls_config.h\\"')]) - thirdparty_mbedtls_dir = "#thirdparty/mbedtls/library/" - thirdparty_mbedtls_sources = [ - "aes.c", - "base64.c", - "md5.c", - "sha1.c", - "sha256.c", - "godot_core_mbedtls_platform.c" - ] - thirdparty_mbedtls_sources = [thirdparty_mbedtls_dir + file for file in thirdparty_mbedtls_sources] - env_thirdparty.add_source_files(env.core_sources, thirdparty_mbedtls_sources) +env_math = env.Clone() env_math.add_source_files(env.core_sources, "*.cpp") diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp index b61119d8df..aea42a1edf 100644 --- a/core/math/a_star.cpp +++ b/core/math/a_star.cpp @@ -40,7 +40,17 @@ int AStar::get_available_point_id() const { return 1; } - return points.back()->key() + 1; + // calculate our new next available point id if bigger than before or next id already contained in set of points. + if (points.has(last_free_id)) { + int cur_new_id = last_free_id; + while (points.has(cur_new_id)) { + cur_new_id++; + } + int &non_const = const_cast<int &>(last_free_id); + non_const = cur_new_id; + } + + return last_free_id; } void AStar::add_point(int p_id, const Vector3 &p_pos, real_t p_weight_scale) { @@ -48,7 +58,10 @@ void AStar::add_point(int p_id, const Vector3 &p_pos, real_t p_weight_scale) { ERR_FAIL_COND(p_id < 0); ERR_FAIL_COND(p_weight_scale < 1); - if (!points.has(p_id)) { + Point *found_pt; + bool p_exists = points.lookup(p_id, found_pt); + + if (!p_exists) { Point *pt = memnew(Point); pt->id = p_id; pt->pos = p_pos; @@ -57,84 +70,98 @@ void AStar::add_point(int p_id, const Vector3 &p_pos, real_t p_weight_scale) { pt->open_pass = 0; pt->closed_pass = 0; pt->enabled = true; - points[p_id] = pt; + points.set(p_id, pt); } else { - points[p_id]->pos = p_pos; - points[p_id]->weight_scale = p_weight_scale; + found_pt->pos = p_pos; + found_pt->weight_scale = p_weight_scale; } } Vector3 AStar::get_point_position(int p_id) const { - ERR_FAIL_COND_V(!points.has(p_id), Vector3()); + Point *p; + bool p_exists = points.lookup(p_id, p); + ERR_FAIL_COND_V(!p_exists, Vector3()); - return points[p_id]->pos; + return p->pos; } void AStar::set_point_position(int p_id, const Vector3 &p_pos) { - ERR_FAIL_COND(!points.has(p_id)); + Point *p; + bool p_exists = points.lookup(p_id, p); + ERR_FAIL_COND(!p_exists); - points[p_id]->pos = p_pos; + p->pos = p_pos; } real_t AStar::get_point_weight_scale(int p_id) const { - ERR_FAIL_COND_V(!points.has(p_id), 0); + Point *p; + bool p_exists = points.lookup(p_id, p); + ERR_FAIL_COND_V(!p_exists, 0); - return points[p_id]->weight_scale; + return p->weight_scale; } void AStar::set_point_weight_scale(int p_id, real_t p_weight_scale) { - ERR_FAIL_COND(!points.has(p_id)); + Point *p; + bool p_exists = points.lookup(p_id, p); + ERR_FAIL_COND(!p_exists); ERR_FAIL_COND(p_weight_scale < 1); - points[p_id]->weight_scale = p_weight_scale; + p->weight_scale = p_weight_scale; } void AStar::remove_point(int p_id) { - ERR_FAIL_COND(!points.has(p_id)); - - Point *p = points[p_id]; + Point *p; + bool p_exists = points.lookup(p_id, p); + ERR_FAIL_COND(!p_exists); - for (Set<Point *>::Element *E = p->neighbours.front(); E; E = E->next()) { + for (OAHashMap<int, Point *>::Iterator it = p->neighbours.iter(); it.valid; it = p->neighbours.next_iter(it)) { - Segment s(p_id, E->get()->id); + Segment s(p_id, (*it.key)); segments.erase(s); - E->get()->neighbours.erase(p); - E->get()->unlinked_neighbours.erase(p); + (*it.value)->neighbours.remove(p->id); + (*it.value)->unlinked_neighbours.remove(p->id); } - for (Set<Point *>::Element *E = p->unlinked_neighbours.front(); E; E = E->next()) { + for (OAHashMap<int, Point *>::Iterator it = p->unlinked_neighbours.iter(); it.valid; it = p->unlinked_neighbours.next_iter(it)) { - Segment s(p_id, E->get()->id); + Segment s(p_id, (*it.key)); segments.erase(s); - E->get()->neighbours.erase(p); - E->get()->unlinked_neighbours.erase(p); + (*it.value)->neighbours.remove(p->id); + (*it.value)->unlinked_neighbours.remove(p->id); } memdelete(p); - points.erase(p_id); + points.remove(p_id); + last_free_id = p_id; } void AStar::connect_points(int p_id, int p_with_id, bool bidirectional) { - ERR_FAIL_COND(!points.has(p_id)); - ERR_FAIL_COND(!points.has(p_with_id)); ERR_FAIL_COND(p_id == p_with_id); - Point *a = points[p_id]; - Point *b = points[p_with_id]; - a->neighbours.insert(b); + Point *a; + bool from_exists = points.lookup(p_id, a); + ERR_FAIL_COND(!from_exists); - if (bidirectional) - b->neighbours.insert(a); - else - b->unlinked_neighbours.insert(a); + Point *b; + bool to_exists = points.lookup(p_with_id, b); + ERR_FAIL_COND(!to_exists); + + a->neighbours.set(b->id, b); + + if (bidirectional) { + b->neighbours.set(a->id, a); + } else { + b->unlinked_neighbours.set(a->id, a); + } Segment s(p_id, p_with_id); if (s.from == p_id) { @@ -147,6 +174,7 @@ void AStar::connect_points(int p_id, int p_with_id, bool bidirectional) { segments.insert(s); } + void AStar::disconnect_points(int p_id, int p_with_id) { Segment s(p_id, p_with_id); @@ -154,12 +182,18 @@ void AStar::disconnect_points(int p_id, int p_with_id) { segments.erase(s); - Point *a = points[p_id]; - Point *b = points[p_with_id]; - a->neighbours.erase(b); - a->unlinked_neighbours.erase(b); - b->neighbours.erase(a); - b->unlinked_neighbours.erase(a); + Point *a; + bool a_exists = points.lookup(p_id, a); + CRASH_COND(!a_exists); + + Point *b; + bool b_exists = points.lookup(p_with_id, b); + CRASH_COND(!b_exists); + + a->neighbours.remove(b->id); + a->unlinked_neighbours.remove(b->id); + b->neighbours.remove(a->id); + b->unlinked_neighbours.remove(a->id); } bool AStar::has_point(int p_id) const { @@ -171,8 +205,8 @@ Array AStar::get_points() { Array point_list; - for (const Map<int, Point *>::Element *E = points.front(); E; E = E->next()) { - point_list.push_back(E->key()); + for (OAHashMap<int, Point *>::Iterator it = points.iter(); it.valid; it = points.next_iter(it)) { + point_list.push_back(*(it.key)); } return point_list; @@ -180,14 +214,14 @@ Array AStar::get_points() { PoolVector<int> AStar::get_point_connections(int p_id) { - ERR_FAIL_COND_V(!points.has(p_id), PoolVector<int>()); + Point *p; + bool p_exists = points.lookup(p_id, p); + ERR_FAIL_COND_V(!p_exists, PoolVector<int>()); PoolVector<int> point_list; - Point *p = points[p_id]; - - for (Set<Point *>::Element *E = p->neighbours.front(); E; E = E->next()) { - point_list.push_back(E->get()->id); + for (OAHashMap<int, Point *>::Iterator it = p->neighbours.iter(); it.valid; it = p->neighbours.next_iter(it)) { + point_list.push_back((*it.key)); } return point_list; @@ -201,9 +235,9 @@ bool AStar::are_points_connected(int p_id, int p_with_id) const { void AStar::clear() { - for (const Map<int, Point *>::Element *E = points.front(); E; E = E->next()) { - - memdelete(E->get()); + last_free_id = 0; + for (OAHashMap<int, Point *>::Iterator it = points.iter(); it.valid; it = points.next_iter(it)) { + memdelete(*(it.value)); } segments.clear(); points.clear(); @@ -214,14 +248,14 @@ int AStar::get_closest_point(const Vector3 &p_point) const { int closest_id = -1; real_t closest_dist = 1e20; - for (const Map<int, Point *>::Element *E = points.front(); E; E = E->next()) { + for (OAHashMap<int, Point *>::Iterator it = points.iter(); it.valid; it = points.next_iter(it)) { + + if (!(*it.value)->enabled) continue; // Disabled points should not be considered. - if (!E->get()->enabled) - continue; //Disabled points should not be considered - real_t d = p_point.distance_squared_to(E->get()->pos); + real_t d = p_point.distance_squared_to((*it.value)->pos); if (closest_id < 0 || d < closest_dist) { closest_dist = d; - closest_id = E->key(); + closest_id = *(it.key); } } @@ -230,8 +264,8 @@ int AStar::get_closest_point(const Vector3 &p_point) const { Vector3 AStar::get_closest_position_in_segment(const Vector3 &p_point) const { - real_t closest_dist = 1e20; bool found = false; + real_t closest_dist = 1e20; Vector3 closest_point; for (const Set<Segment>::Element *E = segments.front(); E; E = E->next()) { @@ -262,8 +296,7 @@ bool AStar::_solve(Point *begin_point, Point *end_point) { pass++; - if (!end_point->enabled) - return false; + if (!end_point->enabled) return false; bool found_route = false; @@ -272,13 +305,9 @@ bool AStar::_solve(Point *begin_point, Point *end_point) { begin_point->g_score = 0; begin_point->f_score = _estimate_cost(begin_point->id, end_point->id); - open_list.push_back(begin_point); - while (true) { - - if (open_list.size() == 0) // No path found - break; + while (!open_list.empty()) { Point *p = open_list[0]; // The currently processed point @@ -291,24 +320,23 @@ bool AStar::_solve(Point *begin_point, Point *end_point) { open_list.remove(open_list.size() - 1); p->closed_pass = pass; // Mark the point as closed - for (Set<Point *>::Element *E = p->neighbours.front(); E; E = E->next()) { + for (OAHashMap<int, Point *>::Iterator it = p->neighbours.iter(); it.valid; it = p->neighbours.next_iter(it)) { - Point *e = E->get(); // The neighbour point + Point *e = *(it.value); // The neighbour point - if (!e->enabled || e->closed_pass == pass) + if (!e->enabled || e->closed_pass == pass) { continue; + } real_t tentative_g_score = p->g_score + _compute_cost(p->id, e->id) * e->weight_scale; bool new_point = false; - if (e->open_pass != pass) { // The point wasn't inside the open list - + if (e->open_pass != pass) { // The point wasn't inside the open list. e->open_pass = pass; open_list.push_back(e); new_point = true; - } else if (tentative_g_score >= e->g_score) { // The new path is worse than the previous - + } else if (tentative_g_score >= e->g_score) { // The new path is worse than the previous. continue; } @@ -316,10 +344,11 @@ bool AStar::_solve(Point *begin_point, Point *end_point) { e->g_score = tentative_g_score; e->f_score = e->g_score + _estimate_cost(e->id, end_point->id); - if (new_point) // The position of the new points is already known + if (new_point) { // The position of the new points is already known. sorter.push_heap(0, open_list.size() - 1, 0, e, open_list.ptrw()); - else + } else { sorter.push_heap(0, open_list.find(e), 0, e, open_list.ptrw()); + } } } @@ -331,7 +360,15 @@ float AStar::_estimate_cost(int p_from_id, int p_to_id) { if (get_script_instance() && get_script_instance()->has_method(SceneStringNames::get_singleton()->_estimate_cost)) return get_script_instance()->call(SceneStringNames::get_singleton()->_estimate_cost, p_from_id, p_to_id); - return points[p_from_id]->pos.distance_to(points[p_to_id]->pos); + Point *from_point; + bool from_exists = points.lookup(p_from_id, from_point); + CRASH_COND(!from_exists); + + Point *to_point; + bool to_exists = points.lookup(p_to_id, to_point); + CRASH_COND(!to_exists); + + return from_point->pos.distance_to(to_point->pos); } float AStar::_compute_cost(int p_from_id, int p_to_id) { @@ -339,16 +376,26 @@ float AStar::_compute_cost(int p_from_id, int p_to_id) { if (get_script_instance() && get_script_instance()->has_method(SceneStringNames::get_singleton()->_compute_cost)) return get_script_instance()->call(SceneStringNames::get_singleton()->_compute_cost, p_from_id, p_to_id); - return points[p_from_id]->pos.distance_to(points[p_to_id]->pos); + Point *from_point; + bool from_exists = points.lookup(p_from_id, from_point); + CRASH_COND(!from_exists); + + Point *to_point; + bool to_exists = points.lookup(p_to_id, to_point); + CRASH_COND(!to_exists); + + return from_point->pos.distance_to(to_point->pos); } PoolVector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) { - ERR_FAIL_COND_V(!points.has(p_from_id), PoolVector<Vector3>()); - ERR_FAIL_COND_V(!points.has(p_to_id), PoolVector<Vector3>()); + Point *a; + bool from_exists = points.lookup(p_from_id, a); + ERR_FAIL_COND_V(!from_exists, PoolVector<Vector3>()); - Point *a = points[p_from_id]; - Point *b = points[p_to_id]; + Point *b; + bool to_exists = points.lookup(p_to_id, b); + ERR_FAIL_COND_V(!to_exists, PoolVector<Vector3>()); if (a == b) { PoolVector<Vector3> ret; @@ -360,11 +407,8 @@ PoolVector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) { Point *end_point = b; bool found_route = _solve(begin_point, end_point); + if (!found_route) return PoolVector<Vector3>(); - if (!found_route) - return PoolVector<Vector3>(); - - // Midpoints Point *p = end_point; int pc = 1; // Begin point while (p != begin_point) { @@ -393,11 +437,13 @@ PoolVector<Vector3> AStar::get_point_path(int p_from_id, int p_to_id) { PoolVector<int> AStar::get_id_path(int p_from_id, int p_to_id) { - ERR_FAIL_COND_V(!points.has(p_from_id), PoolVector<int>()); - ERR_FAIL_COND_V(!points.has(p_to_id), PoolVector<int>()); + Point *a; + bool from_exists = points.lookup(p_from_id, a); + ERR_FAIL_COND_V(!from_exists, PoolVector<int>()); - Point *a = points[p_from_id]; - Point *b = points[p_to_id]; + Point *b; + bool to_exists = points.lookup(p_to_id, b); + ERR_FAIL_COND_V(!to_exists, PoolVector<int>()); if (a == b) { PoolVector<int> ret; @@ -409,11 +455,8 @@ PoolVector<int> AStar::get_id_path(int p_from_id, int p_to_id) { Point *end_point = b; bool found_route = _solve(begin_point, end_point); + if (!found_route) return PoolVector<int>(); - if (!found_route) - return PoolVector<int>(); - - // Midpoints Point *p = end_point; int pc = 1; // Begin point while (p != begin_point) { @@ -442,16 +485,20 @@ PoolVector<int> AStar::get_id_path(int p_from_id, int p_to_id) { void AStar::set_point_disabled(int p_id, bool p_disabled) { - ERR_FAIL_COND(!points.has(p_id)); + Point *p; + bool p_exists = points.lookup(p_id, p); + ERR_FAIL_COND(!p_exists); - points[p_id]->enabled = !p_disabled; + p->enabled = !p_disabled; } bool AStar::is_point_disabled(int p_id) const { - ERR_FAIL_COND_V(!points.has(p_id), false); + Point *p; + bool p_exists = points.lookup(p_id, p); + ERR_FAIL_COND_V(!p_exists, false); - return !points[p_id]->enabled; + return !p->enabled; } void AStar::_bind_methods() { @@ -487,13 +534,11 @@ void AStar::_bind_methods() { } AStar::AStar() { - + last_free_id = 0; pass = 1; } AStar::~AStar() { - - pass = 1; clear(); } diff --git a/core/math/a_star.h b/core/math/a_star.h index cbabcce974..53aaaa1f6c 100644 --- a/core/math/a_star.h +++ b/core/math/a_star.h @@ -31,6 +31,7 @@ #ifndef ASTAR_H #define ASTAR_H +#include "core/oa_hash_map.h" #include "core/reference.h" /** @@ -43,8 +44,6 @@ class AStar : public Reference { GDCLASS(AStar, Reference); - uint64_t pass; - struct Point { int id; @@ -52,10 +51,10 @@ class AStar : public Reference { real_t weight_scale; bool enabled; - Set<Point *> neighbours; - Set<Point *> unlinked_neighbours; + OAHashMap<int, Point *> neighbours; + OAHashMap<int, Point *> unlinked_neighbours; - // Used for pathfinding + // Used for pathfinding. Point *prev_point; real_t g_score; real_t f_score; @@ -63,16 +62,15 @@ class AStar : public Reference { uint64_t closed_pass; }; - Map<int, Point *> points; - struct SortPoints { - _FORCE_INLINE_ bool operator()(const Point *A, const Point *B) const { // Returns true when the Point A is worse than Point B - if (A->f_score > B->f_score) + _FORCE_INLINE_ bool operator()(const Point *A, const Point *B) const { // Returns true when the Point A is worse than Point B. + if (A->f_score > B->f_score) { return true; - else if (A->f_score < B->f_score) + } else if (A->f_score < B->f_score) { return false; - else - return A->g_score < B->g_score; // If the f_costs are the same then prioritize the points that are further away from the start + } else { + return A->g_score < B->g_score; // If the f_costs are the same then prioritize the points that are further away from the start. + } } }; @@ -100,6 +98,10 @@ class AStar : public Reference { } }; + int last_free_id; + uint64_t pass; + + OAHashMap<int, Point *> points; Set<Segment> segments; bool _solve(Point *begin_point, Point *end_point); diff --git a/core/math/delaunay.h b/core/math/delaunay.h index ed52c506db..3f8013a3e6 100644 --- a/core/math/delaunay.h +++ b/core/math/delaunay.h @@ -80,11 +80,11 @@ public: } static bool edge_compare(const Vector<Vector2> &p_vertices, const Edge &p_a, const Edge &p_b) { - if (Math::is_zero_approx(p_vertices[p_a.edge[0]].distance_to(p_vertices[p_b.edge[0]])) && Math::is_zero_approx(p_vertices[p_a.edge[1]].distance_to(p_vertices[p_b.edge[1]]))) { + if (p_vertices[p_a.edge[0]] == p_vertices[p_b.edge[0]] && p_vertices[p_a.edge[1]] == p_vertices[p_b.edge[1]]) { return true; } - if (Math::is_zero_approx(p_vertices[p_a.edge[0]].distance_to(p_vertices[p_b.edge[1]])) && Math::is_zero_approx(p_vertices[p_a.edge[1]].distance_to(p_vertices[p_b.edge[0]]))) { + if (p_vertices[p_a.edge[0]] == p_vertices[p_b.edge[1]] && p_vertices[p_a.edge[1]] == p_vertices[p_b.edge[0]]) { return true; } diff --git a/core/oa_hash_map.h b/core/oa_hash_map.h index e52d36a859..83621bec14 100644 --- a/core/oa_hash_map.h +++ b/core/oa_hash_map.h @@ -62,7 +62,7 @@ private: static const uint32_t EMPTY_HASH = 0; static const uint32_t DELETED_HASH_BIT = 1 << 31; - _FORCE_INLINE_ uint32_t _hash(const TKey &p_key) { + _FORCE_INLINE_ uint32_t _hash(const TKey &p_key) const { uint32_t hash = Hasher::hash(p_key); if (hash == EMPTY_HASH) { @@ -74,7 +74,7 @@ private: return hash; } - _FORCE_INLINE_ uint32_t _get_probe_length(uint32_t p_pos, uint32_t p_hash) { + _FORCE_INLINE_ uint32_t _get_probe_length(uint32_t p_pos, uint32_t p_hash) const { p_hash = p_hash & ~DELETED_HASH_BIT; // we don't care if it was deleted or not uint32_t original_pos = p_hash % capacity; @@ -90,7 +90,7 @@ private: num_elements++; } - bool _lookup_pos(const TKey &p_key, uint32_t &r_pos) { + bool _lookup_pos(const TKey &p_key, uint32_t &r_pos) const { uint32_t hash = _hash(p_key); uint32_t pos = hash % capacity; uint32_t distance = 0; @@ -151,6 +151,7 @@ private: distance++; } } + void _resize_and_rehash() { TKey *old_keys = keys; @@ -190,6 +191,26 @@ public: _FORCE_INLINE_ uint32_t get_capacity() const { return capacity; } _FORCE_INLINE_ uint32_t get_num_elements() const { return num_elements; } + bool empty() const { + return num_elements == 0; + } + + void clear() { + + for (uint32_t i = 0; i < capacity; i++) { + + if (hashes[i] & DELETED_HASH_BIT) { + continue; + } + + hashes[i] |= DELETED_HASH_BIT; + values[i].~TValue(); + keys[i].~TKey(); + } + + num_elements = 0; + } + void insert(const TKey &p_key, const TValue &p_value) { if ((float)num_elements / (float)capacity > 0.9) { @@ -219,7 +240,7 @@ public: * if r_data is not NULL then the value will be written to the object * it points to. */ - bool lookup(const TKey &p_key, TValue &r_data) { + bool lookup(const TKey &p_key, TValue &r_data) const { uint32_t pos = 0; bool exists = _lookup_pos(p_key, pos); @@ -232,7 +253,7 @@ public: return false; } - _FORCE_INLINE_ bool has(const TKey &p_key) { + _FORCE_INLINE_ bool has(const TKey &p_key) const { uint32_t _pos = 0; return _lookup_pos(p_key, _pos); } @@ -302,6 +323,9 @@ public: return it; } + OAHashMap(const OAHashMap &) = delete; // Delete the copy constructor so we don't get unexpected copies and dangling pointers. + OAHashMap &operator=(const OAHashMap &) = delete; // Same for assignment operator. + OAHashMap(uint32_t p_initial_capacity = 64) { capacity = p_initial_capacity; diff --git a/core/object.cpp b/core/object.cpp index 5875a46ea2..62bfa31480 100644 --- a/core/object.cpp +++ b/core/object.cpp @@ -1400,8 +1400,9 @@ void Object::get_signal_connection_list(const StringName &p_signal, List<Connect p_connections->push_back(s->slot_map.getv(i).conn); } -bool Object::has_persistent_signal_connections() const { +int Object::get_persistent_signal_connection_count() const { + int count = 0; const StringName *S = NULL; while ((S = signal_map.next(S))) { @@ -1409,13 +1410,13 @@ bool Object::has_persistent_signal_connections() const { const Signal *s = &signal_map[*S]; for (int i = 0; i < s->slot_map.size(); i++) { - - if (s->slot_map.getv(i).conn.flags & CONNECT_PERSIST) - return true; + if (s->slot_map.getv(i).conn.flags & CONNECT_PERSIST) { + count += 1; + } } } - return false; + return count; } void Object::get_signals_connected_to_this(List<Connection> *p_connections) const { diff --git a/core/object.h b/core/object.h index 15c3ab94c5..ac8620757c 100644 --- a/core/object.h +++ b/core/object.h @@ -707,7 +707,7 @@ public: void get_signal_list(List<MethodInfo> *p_signals) const; void get_signal_connection_list(const StringName &p_signal, List<Connection> *p_connections) const; void get_all_signal_connections(List<Connection> *p_connections) const; - bool has_persistent_signal_connections() const; + int get_persistent_signal_connection_count() const; void get_signals_connected_to_this(List<Connection> *p_connections) const; Error connect(const StringName &p_signal, Object *p_to_object, const StringName &p_to_method, const Vector<Variant> &p_binds = Vector<Variant>(), uint32_t p_flags = 0); diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp index ba94e87da6..9a8315a3bb 100644 --- a/core/os/file_access.cpp +++ b/core/os/file_access.cpp @@ -30,9 +30,9 @@ #include "file_access.h" +#include "core/crypto/crypto_core.h" #include "core/io/file_access_pack.h" #include "core/io/marshalls.h" -#include "core/math/crypto_core.h" #include "core/os/os.h" #include "core/project_settings.h" diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index e442546124..efc77bde48 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -34,6 +34,8 @@ #include "core/class_db.h" #include "core/compressed_translation.h" #include "core/core_string_names.h" +#include "core/crypto/crypto.h" +#include "core/crypto/hashing_context.h" #include "core/engine.h" #include "core/func_ref.h" #include "core/input_map.h" @@ -70,6 +72,8 @@ static Ref<ResourceFormatLoaderBinary> resource_loader_binary; static Ref<ResourceFormatImporter> resource_format_importer; static Ref<ResourceFormatLoaderImage> resource_format_image; static Ref<TranslationLoaderPO> resource_format_po; +static Ref<ResourceFormatSaverCrypto> resource_format_saver_crypto; +static Ref<ResourceFormatLoaderCrypto> resource_format_loader_crypto; static _ResourceLoader *_resource_loader = NULL; static _ResourceSaver *_resource_saver = NULL; @@ -151,7 +155,19 @@ void register_core_types() { ClassDB::register_class<StreamPeerTCP>(); ClassDB::register_class<TCP_Server>(); ClassDB::register_class<PacketPeerUDP>(); + + // Crypto + ClassDB::register_class<HashingContext>(); + ClassDB::register_custom_instance_class<X509Certificate>(); + ClassDB::register_custom_instance_class<CryptoKey>(); + ClassDB::register_custom_instance_class<Crypto>(); ClassDB::register_custom_instance_class<StreamPeerSSL>(); + + resource_format_saver_crypto.instance(); + ResourceSaver::add_resource_format_saver(resource_format_saver_crypto); + resource_format_loader_crypto.instance(); + ResourceLoader::add_resource_format_loader(resource_format_loader_crypto); + ClassDB::register_virtual_class<IP>(); ClassDB::register_virtual_class<PacketPeer>(); ClassDB::register_class<PacketPeerStream>(); @@ -211,6 +227,9 @@ void register_core_settings() { ProjectSettings::get_singleton()->set_custom_property_info("network/limits/tcp/connect_timeout_seconds", PropertyInfo(Variant::INT, "network/limits/tcp/connect_timeout_seconds", PROPERTY_HINT_RANGE, "1,1800,1")); GLOBAL_DEF_RST("network/limits/packet_peer_stream/max_buffer_po2", (16)); ProjectSettings::get_singleton()->set_custom_property_info("network/limits/packet_peer_stream/max_buffer_po2", PropertyInfo(Variant::INT, "network/limits/packet_peer_stream/max_buffer_po2", PROPERTY_HINT_RANGE, "0,64,1,or_greater")); + + GLOBAL_DEF("network/ssl/certificates", ""); + ProjectSettings::get_singleton()->set_custom_property_info("network/ssl/certificates", PropertyInfo(Variant::STRING, "network/ssl/certificates", PROPERTY_HINT_FILE, "*.crt")); } void register_core_singletons() { @@ -272,6 +291,11 @@ void unregister_core_types() { ResourceLoader::remove_resource_format_loader(resource_format_po); resource_format_po.unref(); + ResourceSaver::remove_resource_format_saver(resource_format_saver_crypto); + resource_format_saver_crypto.unref(); + ResourceLoader::remove_resource_format_loader(resource_format_loader_crypto); + resource_format_loader_crypto.unref(); + if (ip) memdelete(ip); diff --git a/core/ustring.cpp b/core/ustring.cpp index ed401c3763..4e9ab7be6b 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -31,7 +31,7 @@ #include "ustring.h" #include "core/color.h" -#include "core/math/crypto_core.h" +#include "core/crypto/crypto_core.h" #include "core/math/math_funcs.h" #include "core/os/memory.h" #include "core/print_string.h" diff --git a/core/variant_call.cpp b/core/variant_call.cpp index 9ea2fed5ae..02c6cd73d8 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -32,8 +32,8 @@ #include "core/color_names.inc" #include "core/core_string_names.h" +#include "core/crypto/crypto_core.h" #include "core/io/compression.h" -#include "core/math/crypto_core.h" #include "core/object.h" #include "core/os/os.h" #include "core/script_language.h" @@ -606,6 +606,13 @@ struct _VariantCall { r_ret = s; } + static void _call_PoolByteArray_hex_encode(Variant &r_ret, Variant &p_self, const Variant **p_args) { + PoolByteArray *ba = reinterpret_cast<PoolByteArray *>(p_self._data._mem); + PoolByteArray::Read r = ba->read(); + String s = String::hex_encode_buffer(&r[0], ba->size()); + r_ret = s; + } + VCALL_LOCALMEM0R(PoolByteArray, size); VCALL_LOCALMEM2(PoolByteArray, set); VCALL_LOCALMEM1R(PoolByteArray, get); @@ -1763,6 +1770,7 @@ void register_variant_methods() { ADDFUNC0R(POOL_BYTE_ARRAY, STRING, PoolByteArray, get_string_from_ascii, varray()); ADDFUNC0R(POOL_BYTE_ARRAY, STRING, PoolByteArray, get_string_from_utf8, varray()); ADDFUNC0R(POOL_BYTE_ARRAY, STRING, PoolByteArray, sha256_string, varray()); + ADDFUNC0R(POOL_BYTE_ARRAY, STRING, PoolByteArray, hex_encode, varray()); ADDFUNC1R(POOL_BYTE_ARRAY, POOL_BYTE_ARRAY, PoolByteArray, compress, INT, "compression_mode", varray(0)); ADDFUNC2R(POOL_BYTE_ARRAY, POOL_BYTE_ARRAY, PoolByteArray, decompress, INT, "buffer_size", INT, "compression_mode", varray(0)); |