summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/gridmap/doc_classes/GridMap.xml14
-rw-r--r--modules/gridmap/editor/grid_map_editor_plugin.cpp10
-rw-r--r--modules/gridmap/grid_map.cpp40
-rw-r--r--modules/gridmap/grid_map.h4
-rw-r--r--modules/mbedtls/crypto_mbedtls.h6
-rw-r--r--modules/mbedtls/dtls_server_mbedtls.h2
-rw-r--r--modules/mbedtls/packet_peer_mbed_dtls.cpp42
-rw-r--r--modules/mbedtls/packet_peer_mbed_dtls.h4
-rw-r--r--modules/mbedtls/register_types.cpp4
-rw-r--r--modules/mbedtls/stream_peer_mbedtls.cpp38
-rw-r--r--modules/mbedtls/stream_peer_mbedtls.h8
-rw-r--r--modules/mbedtls/tls_context_mbedtls.cpp (renamed from modules/mbedtls/ssl_context_mbedtls.cpp)32
-rw-r--r--modules/mbedtls/tls_context_mbedtls.h (renamed from modules/mbedtls/ssl_context_mbedtls.h)20
-rw-r--r--modules/mono/build_scripts/mono_configure.py290
-rw-r--r--modules/mono/config.py20
-rw-r--r--modules/mono/editor/hostfxr_resolver.cpp335
-rw-r--r--modules/mono/editor/hostfxr_resolver.h45
-rw-r--r--modules/mono/editor/semver.cpp149
-rw-r--r--modules/mono/editor/semver.h106
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp101
-rw-r--r--modules/mono/thirdparty/coreclr_delegates.h47
-rw-r--r--modules/mono/thirdparty/hostfxr.h323
-rw-r--r--modules/websocket/doc_classes/WebSocketClient.xml14
-rw-r--r--modules/websocket/doc_classes/WebSocketServer.xml8
-rw-r--r--modules/websocket/emws_client.cpp6
-rw-r--r--modules/websocket/emws_client.h2
-rw-r--r--modules/websocket/websocket_client.cpp36
-rw-r--r--modules/websocket/websocket_client.h14
-rw-r--r--modules/websocket/websocket_server.cpp14
-rw-r--r--modules/websocket/websocket_server.h6
-rw-r--r--modules/websocket/wsl_client.cpp32
-rw-r--r--modules/websocket/wsl_client.h4
-rw-r--r--modules/websocket/wsl_server.cpp26
-rw-r--r--modules/websocket/wsl_server.h2
34 files changed, 1259 insertions, 545 deletions
diff --git a/modules/gridmap/doc_classes/GridMap.xml b/modules/gridmap/doc_classes/GridMap.xml
index 5548006834..ed6cb8656a 100644
--- a/modules/gridmap/doc_classes/GridMap.xml
+++ b/modules/gridmap/doc_classes/GridMap.xml
@@ -94,6 +94,13 @@
Returns whether or not the specified layer of the [member navigation_layers] bitmask is enabled, given a [code]layer_number[/code] between 1 and 32.
</description>
</method>
+ <method name="get_navigation_map" qualifiers="const">
+ <return type="RID" />
+ <description>
+ Returns the [RID] of the navigation map this GridMap node uses for its cell baked navigation meshes.
+ This function returns always the map set on the GridMap node and not the map on the NavigationServer. If the map is changed directly with the NavigationServer API the GridMap node will not be aware of the map change.
+ </description>
+ </method>
<method name="get_orthogonal_index_from_basis" qualifiers="const">
<return type="int" />
<param index="0" name="basis" type="Basis" />
@@ -176,6 +183,13 @@
Based on [code]value[/code], enables or disables the specified layer in the [member navigation_layers] bitmask, given a [code]layer_number[/code] between 1 and 32.
</description>
</method>
+ <method name="set_navigation_map">
+ <return type="void" />
+ <param index="0" name="navigation_map" type="RID" />
+ <description>
+ Sets the [RID] of the navigation map this GridMap node should use for its cell baked navigation meshes.
+ </description>
+ </method>
</methods>
<members>
<member name="bake_navigation" type="bool" setter="set_bake_navigation" getter="is_baking_navigation" default="false">
diff --git a/modules/gridmap/editor/grid_map_editor_plugin.cpp b/modules/gridmap/editor/grid_map_editor_plugin.cpp
index 17f9832096..b5afd8507d 100644
--- a/modules/gridmap/editor/grid_map_editor_plugin.cpp
+++ b/modules/gridmap/editor/grid_map_editor_plugin.cpp
@@ -603,13 +603,13 @@ EditorPlugin::AfterGUIInput GridMapEditor::forward_spatial_input_event(Camera3D
Ref<InputEventMouseButton> mb = p_event;
if (mb.is_valid()) {
- if (mb->get_button_index() == MouseButton::WHEEL_UP && (mb->is_command_pressed() || mb->is_shift_pressed())) {
+ if (mb->get_button_index() == MouseButton::WHEEL_UP && (mb->is_command_or_control_pressed() || mb->is_shift_pressed())) {
if (mb->is_pressed()) {
floor->set_value(floor->get_value() + mb->get_factor());
}
return EditorPlugin::AFTER_GUI_INPUT_STOP; // Eaten.
- } else if (mb->get_button_index() == MouseButton::WHEEL_DOWN && (mb->is_command_pressed() || mb->is_shift_pressed())) {
+ } else if (mb->get_button_index() == MouseButton::WHEEL_DOWN && (mb->is_command_or_control_pressed() || mb->is_shift_pressed())) {
if (mb->is_pressed()) {
floor->set_value(floor->get_value() - mb->get_factor());
}
@@ -629,7 +629,7 @@ EditorPlugin::AfterGUIInput GridMapEditor::forward_spatial_input_event(Camera3D
} else if (mb->is_shift_pressed() && can_edit) {
input_action = INPUT_SELECT;
last_selection = selection;
- } else if (mb->is_command_pressed() && can_edit) {
+ } else if (mb->is_command_or_control_pressed() && can_edit) {
input_action = INPUT_PICK;
} else {
input_action = INPUT_PAINT;
@@ -746,7 +746,7 @@ EditorPlugin::AfterGUIInput GridMapEditor::forward_spatial_input_event(Camera3D
Ref<InputEventPanGesture> pan_gesture = p_event;
if (pan_gesture.is_valid()) {
- if (pan_gesture->is_alt_pressed() && (pan_gesture->is_command_pressed() || pan_gesture->is_shift_pressed())) {
+ if (pan_gesture->is_alt_pressed() && (pan_gesture->is_command_or_control_pressed() || pan_gesture->is_shift_pressed())) {
const real_t delta = pan_gesture->get_delta().y * 0.5;
accumulated_floor_delta += delta;
int step = 0;
@@ -807,7 +807,7 @@ void GridMapEditor::_mesh_library_palette_input(const Ref<InputEvent> &p_ie) {
const Ref<InputEventMouseButton> mb = p_ie;
// Zoom in/out using Ctrl + mouse wheel
- if (mb.is_valid() && mb->is_pressed() && mb->is_command_pressed()) {
+ if (mb.is_valid() && mb->is_pressed() && mb->is_command_or_control_pressed()) {
if (mb->is_pressed() && mb->get_button_index() == MouseButton::WHEEL_UP) {
size_slider->set_value(size_slider->get_value() + 0.2);
}
diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp
index ac0755cf68..466a2efd21 100644
--- a/modules/gridmap/grid_map.cpp
+++ b/modules/gridmap/grid_map.cpp
@@ -226,6 +226,27 @@ bool GridMap::is_baking_navigation() {
return bake_navigation;
}
+void GridMap::set_navigation_map(RID p_navigation_map) {
+ map_override = p_navigation_map;
+ for (const KeyValue<OctantKey, Octant *> &E : octant_map) {
+ Octant &g = *octant_map[E.key];
+ for (KeyValue<IndexKey, Octant::NavMesh> &F : g.navmesh_ids) {
+ if (F.value.region.is_valid()) {
+ NavigationServer3D::get_singleton()->region_set_map(F.value.region, map_override);
+ }
+ }
+ }
+}
+
+RID GridMap::get_navigation_map() const {
+ if (map_override.is_valid()) {
+ return map_override;
+ } else if (is_inside_tree()) {
+ return get_world_3d()->get_navigation_map();
+ }
+ return RID();
+}
+
void GridMap::set_navigation_layers(uint32_t p_navigation_layers) {
navigation_layers = p_navigation_layers;
_recreate_octant_data();
@@ -639,10 +660,15 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
NavigationServer3D::get_singleton()->region_set_navmesh(region, navmesh);
NavigationServer3D::get_singleton()->region_set_transform(region, get_global_transform() * nm.xform);
if (is_inside_tree()) {
- NavigationServer3D::get_singleton()->region_set_map(region, get_world_3d()->get_navigation_map());
+ if (map_override.is_valid()) {
+ NavigationServer3D::get_singleton()->region_set_map(region, map_override);
+ } else {
+ NavigationServer3D::get_singleton()->region_set_map(region, get_world_3d()->get_navigation_map());
+ }
}
nm.region = region;
+#ifdef DEBUG_ENABLED
// add navigation debugmesh visual instances if debug is enabled
SceneTree *st = SceneTree::get_singleton();
if (st && st->is_debugging_navigation_hint()) {
@@ -650,15 +676,14 @@ bool GridMap::_octant_update(const OctantKey &p_key) {
RID navmesh_debug_rid = navmesh->get_debug_mesh()->get_rid();
nm.navmesh_debug_instance = RS::get_singleton()->instance_create();
RS::get_singleton()->instance_set_base(nm.navmesh_debug_instance, navmesh_debug_rid);
- RS::get_singleton()->mesh_surface_set_material(navmesh_debug_rid, 0, st->get_debug_navigation_material()->get_rid());
}
if (is_inside_tree()) {
RS::get_singleton()->instance_set_scenario(nm.navmesh_debug_instance, get_world_3d()->get_scenario());
RS::get_singleton()->instance_set_transform(nm.navmesh_debug_instance, get_global_transform() * nm.xform);
}
}
+#endif // DEBUG_ENABLED
}
-
g.navmesh_ids[E] = nm;
}
}
@@ -757,7 +782,11 @@ void GridMap::_octant_enter_world(const OctantKey &p_key) {
NavigationServer3D::get_singleton()->region_set_navigation_layers(region, navigation_layers);
NavigationServer3D::get_singleton()->region_set_navmesh(region, nm);
NavigationServer3D::get_singleton()->region_set_transform(region, get_global_transform() * F.value.xform);
- NavigationServer3D::get_singleton()->region_set_map(region, get_world_3d()->get_navigation_map());
+ if (map_override.is_valid()) {
+ NavigationServer3D::get_singleton()->region_set_map(region, map_override);
+ } else {
+ NavigationServer3D::get_singleton()->region_set_map(region, get_world_3d()->get_navigation_map());
+ }
F.value.region = region;
}
@@ -1022,6 +1051,9 @@ void GridMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_bake_navigation", "bake_navigation"), &GridMap::set_bake_navigation);
ClassDB::bind_method(D_METHOD("is_baking_navigation"), &GridMap::is_baking_navigation);
+ ClassDB::bind_method(D_METHOD("set_navigation_map", "navigation_map"), &GridMap::set_navigation_map);
+ ClassDB::bind_method(D_METHOD("get_navigation_map"), &GridMap::get_navigation_map);
+
ClassDB::bind_method(D_METHOD("set_navigation_layers", "layers"), &GridMap::set_navigation_layers);
ClassDB::bind_method(D_METHOD("get_navigation_layers"), &GridMap::get_navigation_layers);
diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h
index 4a4e970fd3..6a53457d25 100644
--- a/modules/gridmap/grid_map.h
+++ b/modules/gridmap/grid_map.h
@@ -152,6 +152,7 @@ class GridMap : public Node3D {
uint32_t collision_mask = 1;
Ref<PhysicsMaterial> physics_material;
bool bake_navigation = false;
+ RID map_override;
uint32_t navigation_layers = 1;
Transform3D last_transform;
@@ -247,6 +248,9 @@ public:
void set_bake_navigation(bool p_bake_navigation);
bool is_baking_navigation();
+ void set_navigation_map(RID p_navigation_map);
+ RID get_navigation_map() const;
+
void set_navigation_layers(uint32_t p_navigation_layers);
uint32_t get_navigation_layers() const;
diff --git a/modules/mbedtls/crypto_mbedtls.h b/modules/mbedtls/crypto_mbedtls.h
index 5ba7e9cbf6..f129ef6f11 100644
--- a/modules/mbedtls/crypto_mbedtls.h
+++ b/modules/mbedtls/crypto_mbedtls.h
@@ -39,7 +39,7 @@
#include <mbedtls/ssl.h>
class CryptoMbedTLS;
-class SSLContextMbedTLS;
+class TLSContextMbedTLS;
class CryptoKeyMbedTLS : public CryptoKey {
private:
mbedtls_pk_context pkey;
@@ -69,7 +69,7 @@ public:
_FORCE_INLINE_ void unlock() { locks--; }
friend class CryptoMbedTLS;
- friend class SSLContextMbedTLS;
+ friend class TLSContextMbedTLS;
};
class X509CertificateMbedTLS : public X509Certificate {
@@ -98,7 +98,7 @@ public:
_FORCE_INLINE_ void unlock() { locks--; }
friend class CryptoMbedTLS;
- friend class SSLContextMbedTLS;
+ friend class TLSContextMbedTLS;
};
class HMACContextMbedTLS : public HMACContext {
diff --git a/modules/mbedtls/dtls_server_mbedtls.h b/modules/mbedtls/dtls_server_mbedtls.h
index a6626c9f65..0c9f10b5ed 100644
--- a/modules/mbedtls/dtls_server_mbedtls.h
+++ b/modules/mbedtls/dtls_server_mbedtls.h
@@ -32,7 +32,7 @@
#define DTLS_SERVER_MBEDTLS_H
#include "core/io/dtls_server.h"
-#include "ssl_context_mbedtls.h"
+#include "tls_context_mbedtls.h"
class DTLSServerMbedTLS : public DTLSServer {
private:
diff --git a/modules/mbedtls/packet_peer_mbed_dtls.cpp b/modules/mbedtls/packet_peer_mbed_dtls.cpp
index 78a06ff4a1..e84d95773d 100644
--- a/modules/mbedtls/packet_peer_mbed_dtls.cpp
+++ b/modules/mbedtls/packet_peer_mbed_dtls.cpp
@@ -79,7 +79,7 @@ int PacketPeerMbedDTLS::bio_recv(void *ctx, unsigned char *buf, size_t len) {
}
void PacketPeerMbedDTLS::_cleanup() {
- ssl_ctx->clear();
+ tls_ctx->clear();
base = Ref<PacketPeer>();
status = STATUS_DISCONNECTED;
}
@@ -91,16 +91,16 @@ int PacketPeerMbedDTLS::_set_cookie() {
uint16_t port = base->get_packet_port();
memcpy(client_id, addr.get_ipv6(), 16);
memcpy(&client_id[16], (uint8_t *)&port, 2);
- return mbedtls_ssl_set_client_transport_id(ssl_ctx->get_context(), client_id, 18);
+ return mbedtls_ssl_set_client_transport_id(tls_ctx->get_context(), client_id, 18);
}
Error PacketPeerMbedDTLS::_do_handshake() {
int ret = 0;
- while ((ret = mbedtls_ssl_handshake(ssl_ctx->get_context())) != 0) {
+ while ((ret = mbedtls_ssl_handshake(tls_ctx->get_context())) != 0) {
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
if (ret != MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED) {
ERR_PRINT("TLS handshake error: " + itos(ret));
- SSLContextMbedTLS::print_mbedtls_error(ret);
+ TLSContextMbedTLS::print_mbedtls_error(ret);
}
_cleanup();
status = STATUS_ERROR;
@@ -121,12 +121,12 @@ Error PacketPeerMbedDTLS::connect_to_peer(Ref<PacketPeerUDP> p_base, bool p_vali
int ret = 0;
int authmode = p_validate_certs ? MBEDTLS_SSL_VERIFY_REQUIRED : MBEDTLS_SSL_VERIFY_NONE;
- Error err = ssl_ctx->init_client(MBEDTLS_SSL_TRANSPORT_DATAGRAM, authmode, p_ca_certs);
+ Error err = tls_ctx->init_client(MBEDTLS_SSL_TRANSPORT_DATAGRAM, authmode, p_ca_certs);
ERR_FAIL_COND_V(err != OK, err);
- mbedtls_ssl_set_hostname(ssl_ctx->get_context(), p_for_hostname.utf8().get_data());
- mbedtls_ssl_set_bio(ssl_ctx->get_context(), this, bio_send, bio_recv, nullptr);
- mbedtls_ssl_set_timer_cb(ssl_ctx->get_context(), &timer, mbedtls_timing_set_delay, mbedtls_timing_get_delay);
+ mbedtls_ssl_set_hostname(tls_ctx->get_context(), p_for_hostname.utf8().get_data());
+ mbedtls_ssl_set_bio(tls_ctx->get_context(), this, bio_send, bio_recv, nullptr);
+ mbedtls_ssl_set_timer_cb(tls_ctx->get_context(), &timer, mbedtls_timing_set_delay, mbedtls_timing_get_delay);
status = STATUS_HANDSHAKING;
@@ -139,13 +139,13 @@ Error PacketPeerMbedDTLS::connect_to_peer(Ref<PacketPeerUDP> p_base, bool p_vali
}
Error PacketPeerMbedDTLS::accept_peer(Ref<PacketPeerUDP> p_base, Ref<CryptoKey> p_key, Ref<X509Certificate> p_cert, Ref<X509Certificate> p_ca_chain, Ref<CookieContextMbedTLS> p_cookies) {
- Error err = ssl_ctx->init_server(MBEDTLS_SSL_TRANSPORT_DATAGRAM, MBEDTLS_SSL_VERIFY_NONE, p_key, p_cert, p_cookies);
+ Error err = tls_ctx->init_server(MBEDTLS_SSL_TRANSPORT_DATAGRAM, MBEDTLS_SSL_VERIFY_NONE, p_key, p_cert, p_cookies);
ERR_FAIL_COND_V(err != OK, err);
base = p_base;
base->set_blocking_mode(false);
- mbedtls_ssl_session_reset(ssl_ctx->get_context());
+ mbedtls_ssl_session_reset(tls_ctx->get_context());
int ret = _set_cookie();
if (ret != 0) {
@@ -153,8 +153,8 @@ Error PacketPeerMbedDTLS::accept_peer(Ref<PacketPeerUDP> p_base, Ref<CryptoKey>
ERR_FAIL_V_MSG(FAILED, "Error setting DTLS client cookie");
}
- mbedtls_ssl_set_bio(ssl_ctx->get_context(), this, bio_send, bio_recv, nullptr);
- mbedtls_ssl_set_timer_cb(ssl_ctx->get_context(), &timer, mbedtls_timing_set_delay, mbedtls_timing_get_delay);
+ mbedtls_ssl_set_bio(tls_ctx->get_context(), this, bio_send, bio_recv, nullptr);
+ mbedtls_ssl_set_timer_cb(tls_ctx->get_context(), &timer, mbedtls_timing_set_delay, mbedtls_timing_get_delay);
status = STATUS_HANDSHAKING;
@@ -173,11 +173,11 @@ Error PacketPeerMbedDTLS::put_packet(const uint8_t *p_buffer, int p_bytes) {
return OK;
}
- int ret = mbedtls_ssl_write(ssl_ctx->get_context(), p_buffer, p_bytes);
+ int ret = mbedtls_ssl_write(tls_ctx->get_context(), p_buffer, p_bytes);
if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
ret = 0; // non blocking io
} else if (ret <= 0) {
- SSLContextMbedTLS::print_mbedtls_error(ret);
+ TLSContextMbedTLS::print_mbedtls_error(ret);
_cleanup();
return ERR_CONNECTION_ERROR;
}
@@ -190,7 +190,7 @@ Error PacketPeerMbedDTLS::get_packet(const uint8_t **r_buffer, int &r_bytes) {
r_bytes = 0;
- int ret = mbedtls_ssl_read(ssl_ctx->get_context(), packet_buffer, PACKET_BUFFER_SIZE);
+ int ret = mbedtls_ssl_read(tls_ctx->get_context(), packet_buffer, PACKET_BUFFER_SIZE);
if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
ret = 0; // non blocking io
} else if (ret <= 0) {
@@ -200,7 +200,7 @@ Error PacketPeerMbedDTLS::get_packet(const uint8_t **r_buffer, int &r_bytes) {
} else {
_cleanup();
status = STATUS_ERROR;
- SSLContextMbedTLS::print_mbedtls_error(ret);
+ TLSContextMbedTLS::print_mbedtls_error(ret);
}
return ERR_CONNECTION_ERROR;
}
@@ -220,7 +220,7 @@ void PacketPeerMbedDTLS::poll() {
ERR_FAIL_COND(!base.is_valid());
- int ret = mbedtls_ssl_read(ssl_ctx->get_context(), nullptr, 0);
+ int ret = mbedtls_ssl_read(tls_ctx->get_context(), nullptr, 0);
if (ret < 0 && ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
@@ -229,7 +229,7 @@ void PacketPeerMbedDTLS::poll() {
} else {
_cleanup();
status = STATUS_ERROR;
- SSLContextMbedTLS::print_mbedtls_error(ret);
+ TLSContextMbedTLS::print_mbedtls_error(ret);
}
}
}
@@ -237,7 +237,7 @@ void PacketPeerMbedDTLS::poll() {
int PacketPeerMbedDTLS::get_available_packet_count() const {
ERR_FAIL_COND_V(status != STATUS_CONNECTED, 0);
- return mbedtls_ssl_get_bytes_avail(&(ssl_ctx->ssl)) > 0 ? 1 : 0;
+ return mbedtls_ssl_get_bytes_avail(&(tls_ctx->tls)) > 0 ? 1 : 0;
}
int PacketPeerMbedDTLS::get_max_packet_size() const {
@@ -245,7 +245,7 @@ int PacketPeerMbedDTLS::get_max_packet_size() const {
}
PacketPeerMbedDTLS::PacketPeerMbedDTLS() {
- ssl_ctx.instantiate();
+ tls_ctx.instantiate();
}
PacketPeerMbedDTLS::~PacketPeerMbedDTLS() {
@@ -261,7 +261,7 @@ void PacketPeerMbedDTLS::disconnect_from_peer() {
int ret = 0;
// Send SSL close notification, blocking, but ignore other errors.
do {
- ret = mbedtls_ssl_close_notify(ssl_ctx->get_context());
+ ret = mbedtls_ssl_close_notify(tls_ctx->get_context());
} while (ret == MBEDTLS_ERR_SSL_WANT_WRITE);
}
diff --git a/modules/mbedtls/packet_peer_mbed_dtls.h b/modules/mbedtls/packet_peer_mbed_dtls.h
index 5f2f42cd30..cc79057d67 100644
--- a/modules/mbedtls/packet_peer_mbed_dtls.h
+++ b/modules/mbedtls/packet_peer_mbed_dtls.h
@@ -32,7 +32,7 @@
#define PACKET_PEER_MBED_DTLS_H
#include "core/io/packet_peer_dtls.h"
-#include "ssl_context_mbedtls.h"
+#include "tls_context_mbedtls.h"
#include <mbedtls/timing.h>
@@ -56,7 +56,7 @@ private:
void _cleanup();
protected:
- Ref<SSLContextMbedTLS> ssl_ctx;
+ Ref<TLSContextMbedTLS> tls_ctx;
mbedtls_timing_delay_context timer;
Error _do_handshake();
diff --git a/modules/mbedtls/register_types.cpp b/modules/mbedtls/register_types.cpp
index 2d4a18b3fc..675091b617 100644
--- a/modules/mbedtls/register_types.cpp
+++ b/modules/mbedtls/register_types.cpp
@@ -45,7 +45,7 @@ void initialize_mbedtls_module(ModuleInitializationLevel p_level) {
}
CryptoMbedTLS::initialize_crypto();
- StreamPeerMbedTLS::initialize_ssl();
+ StreamPeerMbedTLS::initialize_tls();
PacketPeerMbedDTLS::initialize_dtls();
DTLSServerMbedTLS::initialize();
}
@@ -57,6 +57,6 @@ void uninitialize_mbedtls_module(ModuleInitializationLevel p_level) {
DTLSServerMbedTLS::finalize();
PacketPeerMbedDTLS::finalize_dtls();
- StreamPeerMbedTLS::finalize_ssl();
+ StreamPeerMbedTLS::finalize_tls();
CryptoMbedTLS::finalize_crypto();
}
diff --git a/modules/mbedtls/stream_peer_mbedtls.cpp b/modules/mbedtls/stream_peer_mbedtls.cpp
index 0bf4ca7032..a97c6bd916 100644
--- a/modules/mbedtls/stream_peer_mbedtls.cpp
+++ b/modules/mbedtls/stream_peer_mbedtls.cpp
@@ -74,18 +74,18 @@ int StreamPeerMbedTLS::bio_recv(void *ctx, unsigned char *buf, size_t len) {
}
void StreamPeerMbedTLS::_cleanup() {
- ssl_ctx->clear();
+ tls_ctx->clear();
base = Ref<StreamPeer>();
status = STATUS_DISCONNECTED;
}
Error StreamPeerMbedTLS::_do_handshake() {
int ret = 0;
- while ((ret = mbedtls_ssl_handshake(ssl_ctx->get_context())) != 0) {
+ while ((ret = mbedtls_ssl_handshake(tls_ctx->get_context())) != 0) {
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
// An error occurred.
ERR_PRINT("TLS handshake error: " + itos(ret));
- SSLContextMbedTLS::print_mbedtls_error(ret);
+ TLSContextMbedTLS::print_mbedtls_error(ret);
disconnect_from_stream();
status = STATUS_ERROR;
return FAILED;
@@ -108,11 +108,11 @@ Error StreamPeerMbedTLS::connect_to_stream(Ref<StreamPeer> p_base, bool p_valida
base = p_base;
int authmode = p_validate_certs ? MBEDTLS_SSL_VERIFY_REQUIRED : MBEDTLS_SSL_VERIFY_NONE;
- Error err = ssl_ctx->init_client(MBEDTLS_SSL_TRANSPORT_STREAM, authmode, p_ca_certs);
+ Error err = tls_ctx->init_client(MBEDTLS_SSL_TRANSPORT_STREAM, authmode, p_ca_certs);
ERR_FAIL_COND_V(err != OK, err);
- mbedtls_ssl_set_hostname(ssl_ctx->get_context(), p_for_hostname.utf8().get_data());
- mbedtls_ssl_set_bio(ssl_ctx->get_context(), this, bio_send, bio_recv, nullptr);
+ mbedtls_ssl_set_hostname(tls_ctx->get_context(), p_for_hostname.utf8().get_data());
+ mbedtls_ssl_set_bio(tls_ctx->get_context(), this, bio_send, bio_recv, nullptr);
status = STATUS_HANDSHAKING;
@@ -127,12 +127,12 @@ Error StreamPeerMbedTLS::connect_to_stream(Ref<StreamPeer> p_base, bool p_valida
Error StreamPeerMbedTLS::accept_stream(Ref<StreamPeer> p_base, Ref<CryptoKey> p_key, Ref<X509Certificate> p_cert, Ref<X509Certificate> p_ca_chain) {
ERR_FAIL_COND_V(p_base.is_null(), ERR_INVALID_PARAMETER);
- Error err = ssl_ctx->init_server(MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_VERIFY_NONE, p_key, p_cert);
+ Error err = tls_ctx->init_server(MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_VERIFY_NONE, p_key, p_cert);
ERR_FAIL_COND_V(err != OK, err);
base = p_base;
- mbedtls_ssl_set_bio(ssl_ctx->get_context(), this, bio_send, bio_recv, nullptr);
+ mbedtls_ssl_set_bio(tls_ctx->get_context(), this, bio_send, bio_recv, nullptr);
status = STATUS_HANDSHAKING;
@@ -173,7 +173,7 @@ Error StreamPeerMbedTLS::put_partial_data(const uint8_t *p_data, int p_bytes, in
return OK;
}
- int ret = mbedtls_ssl_write(ssl_ctx->get_context(), p_data, p_bytes);
+ int ret = mbedtls_ssl_write(tls_ctx->get_context(), p_data, p_bytes);
if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
// Non blocking IO
ret = 0;
@@ -182,7 +182,7 @@ Error StreamPeerMbedTLS::put_partial_data(const uint8_t *p_data, int p_bytes, in
disconnect_from_stream();
return ERR_FILE_EOF;
} else if (ret <= 0) {
- SSLContextMbedTLS::print_mbedtls_error(ret);
+ TLSContextMbedTLS::print_mbedtls_error(ret);
disconnect_from_stream();
return ERR_CONNECTION_ERROR;
}
@@ -216,7 +216,7 @@ Error StreamPeerMbedTLS::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r
r_received = 0;
- int ret = mbedtls_ssl_read(ssl_ctx->get_context(), p_buffer, p_bytes);
+ int ret = mbedtls_ssl_read(tls_ctx->get_context(), p_buffer, p_bytes);
if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
ret = 0; // non blocking io
} else if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
@@ -224,7 +224,7 @@ Error StreamPeerMbedTLS::get_partial_data(uint8_t *p_buffer, int p_bytes, int &r
disconnect_from_stream();
return ERR_FILE_EOF;
} else if (ret <= 0) {
- SSLContextMbedTLS::print_mbedtls_error(ret);
+ TLSContextMbedTLS::print_mbedtls_error(ret);
disconnect_from_stream();
return ERR_CONNECTION_ERROR;
}
@@ -245,7 +245,7 @@ void StreamPeerMbedTLS::poll() {
// We could pass nullptr as second parameter, but some behaviour sanitizers don't seem to like that.
// Passing a 1 byte buffer to workaround it.
uint8_t byte;
- int ret = mbedtls_ssl_read(ssl_ctx->get_context(), &byte, 0);
+ int ret = mbedtls_ssl_read(tls_ctx->get_context(), &byte, 0);
if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
// Nothing to read/write (non blocking IO)
@@ -254,7 +254,7 @@ void StreamPeerMbedTLS::poll() {
disconnect_from_stream();
return;
} else if (ret < 0) {
- SSLContextMbedTLS::print_mbedtls_error(ret);
+ TLSContextMbedTLS::print_mbedtls_error(ret);
disconnect_from_stream();
return;
}
@@ -269,11 +269,11 @@ void StreamPeerMbedTLS::poll() {
int StreamPeerMbedTLS::get_available_bytes() const {
ERR_FAIL_COND_V(status != STATUS_CONNECTED, 0);
- return mbedtls_ssl_get_bytes_avail(&(ssl_ctx->ssl));
+ return mbedtls_ssl_get_bytes_avail(&(tls_ctx->tls));
}
StreamPeerMbedTLS::StreamPeerMbedTLS() {
- ssl_ctx.instantiate();
+ tls_ctx.instantiate();
}
StreamPeerMbedTLS::~StreamPeerMbedTLS() {
@@ -288,7 +288,7 @@ void StreamPeerMbedTLS::disconnect_from_stream() {
Ref<StreamPeerTCP> tcp = base;
if (tcp.is_valid() && tcp->get_status() == StreamPeerTCP::STATUS_CONNECTED) {
// We are still connected on the socket, try to send close notify.
- mbedtls_ssl_close_notify(ssl_ctx->get_context());
+ mbedtls_ssl_close_notify(tls_ctx->get_context());
}
_cleanup();
@@ -306,12 +306,12 @@ StreamPeerTLS *StreamPeerMbedTLS::_create_func() {
return memnew(StreamPeerMbedTLS);
}
-void StreamPeerMbedTLS::initialize_ssl() {
+void StreamPeerMbedTLS::initialize_tls() {
_create = _create_func;
available = true;
}
-void StreamPeerMbedTLS::finalize_ssl() {
+void StreamPeerMbedTLS::finalize_tls() {
available = false;
_create = nullptr;
}
diff --git a/modules/mbedtls/stream_peer_mbedtls.h b/modules/mbedtls/stream_peer_mbedtls.h
index 12d06d05ed..9219269539 100644
--- a/modules/mbedtls/stream_peer_mbedtls.h
+++ b/modules/mbedtls/stream_peer_mbedtls.h
@@ -32,7 +32,7 @@
#define STREAM_PEER_MBEDTLS_H
#include "core/io/stream_peer_tls.h"
-#include "ssl_context_mbedtls.h"
+#include "tls_context_mbedtls.h"
class StreamPeerMbedTLS : public StreamPeerTLS {
private:
@@ -48,7 +48,7 @@ private:
void _cleanup();
protected:
- Ref<SSLContextMbedTLS> ssl_ctx;
+ Ref<TLSContextMbedTLS> tls_ctx;
Error _do_handshake();
@@ -69,8 +69,8 @@ public:
virtual int get_available_bytes() const;
- static void initialize_ssl();
- static void finalize_ssl();
+ static void initialize_tls();
+ static void finalize_tls();
StreamPeerMbedTLS();
~StreamPeerMbedTLS();
diff --git a/modules/mbedtls/ssl_context_mbedtls.cpp b/modules/mbedtls/tls_context_mbedtls.cpp
index e2dad074cc..1ae7bc0436 100644
--- a/modules/mbedtls/ssl_context_mbedtls.cpp
+++ b/modules/mbedtls/tls_context_mbedtls.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* ssl_context_mbedtls.cpp */
+/* tls_context_mbedtls.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "ssl_context_mbedtls.h"
+#include "tls_context_mbedtls.h"
static void my_debug(void *ctx, int level,
const char *file, int line,
@@ -37,7 +37,7 @@ static void my_debug(void *ctx, int level,
fflush(stdout);
}
-void SSLContextMbedTLS::print_mbedtls_error(int p_ret) {
+void TLSContextMbedTLS::print_mbedtls_error(int p_ret) {
printf("mbedtls error: returned -0x%x\n\n", -p_ret);
fflush(stdout);
}
@@ -82,12 +82,12 @@ CookieContextMbedTLS::~CookieContextMbedTLS() {
clear();
}
-/// SSLContextMbedTLS
+/// TLSContextMbedTLS
-Error SSLContextMbedTLS::_setup(int p_endpoint, int p_transport, int p_authmode) {
+Error TLSContextMbedTLS::_setup(int p_endpoint, int p_transport, int p_authmode) {
ERR_FAIL_COND_V_MSG(inited, ERR_ALREADY_IN_USE, "This SSL context is already active");
- mbedtls_ssl_init(&ssl);
+ mbedtls_ssl_init(&tls);
mbedtls_ssl_config_init(&conf);
mbedtls_ctr_drbg_init(&ctr_drbg);
mbedtls_entropy_init(&entropy);
@@ -110,7 +110,7 @@ Error SSLContextMbedTLS::_setup(int p_endpoint, int p_transport, int p_authmode)
return OK;
}
-Error SSLContextMbedTLS::init_server(int p_transport, int p_authmode, Ref<CryptoKeyMbedTLS> p_pkey, Ref<X509CertificateMbedTLS> p_cert, Ref<CookieContextMbedTLS> p_cookies) {
+Error TLSContextMbedTLS::init_server(int p_transport, int p_authmode, Ref<CryptoKeyMbedTLS> p_pkey, Ref<X509CertificateMbedTLS> p_cert, Ref<CookieContextMbedTLS> p_cookies) {
ERR_FAIL_COND_V(!p_pkey.is_valid(), ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(!p_cert.is_valid(), ERR_INVALID_PARAMETER);
@@ -146,11 +146,11 @@ Error SSLContextMbedTLS::init_server(int p_transport, int p_authmode, Ref<Crypto
cookies = p_cookies;
mbedtls_ssl_conf_dtls_cookies(&conf, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check, &(cookies->cookie_ctx));
}
- mbedtls_ssl_setup(&ssl, &conf);
+ mbedtls_ssl_setup(&tls, &conf);
return OK;
}
-Error SSLContextMbedTLS::init_client(int p_transport, int p_authmode, Ref<X509CertificateMbedTLS> p_valid_cas) {
+Error TLSContextMbedTLS::init_client(int p_transport, int p_authmode, Ref<X509CertificateMbedTLS> p_valid_cas) {
Error err = _setup(MBEDTLS_SSL_IS_CLIENT, p_transport, p_authmode);
ERR_FAIL_COND_V(err != OK, err);
@@ -172,15 +172,15 @@ Error SSLContextMbedTLS::init_client(int p_transport, int p_authmode, Ref<X509Ce
// Set valid CAs
mbedtls_ssl_conf_ca_chain(&conf, &(cas->cert), nullptr);
- mbedtls_ssl_setup(&ssl, &conf);
+ mbedtls_ssl_setup(&tls, &conf);
return OK;
}
-void SSLContextMbedTLS::clear() {
+void TLSContextMbedTLS::clear() {
if (!inited) {
return;
}
- mbedtls_ssl_free(&ssl);
+ mbedtls_ssl_free(&tls);
mbedtls_ssl_config_free(&conf);
mbedtls_ctr_drbg_free(&ctr_drbg);
mbedtls_entropy_free(&entropy);
@@ -198,14 +198,14 @@ void SSLContextMbedTLS::clear() {
inited = false;
}
-mbedtls_ssl_context *SSLContextMbedTLS::get_context() {
+mbedtls_ssl_context *TLSContextMbedTLS::get_context() {
ERR_FAIL_COND_V(!inited, nullptr);
- return &ssl;
+ return &tls;
}
-SSLContextMbedTLS::SSLContextMbedTLS() {
+TLSContextMbedTLS::TLSContextMbedTLS() {
}
-SSLContextMbedTLS::~SSLContextMbedTLS() {
+TLSContextMbedTLS::~TLSContextMbedTLS() {
clear();
}
diff --git a/modules/mbedtls/ssl_context_mbedtls.h b/modules/mbedtls/tls_context_mbedtls.h
index 5883388311..5e7b3dc46e 100644
--- a/modules/mbedtls/ssl_context_mbedtls.h
+++ b/modules/mbedtls/tls_context_mbedtls.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* ssl_context_mbedtls.h */
+/* tls_context_mbedtls.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SSL_CONTEXT_MBEDTLS_H
-#define SSL_CONTEXT_MBEDTLS_H
+#ifndef TLS_CONTEXT_MBEDTLS_H
+#define TLS_CONTEXT_MBEDTLS_H
#include "crypto_mbedtls.h"
@@ -44,10 +44,10 @@
#include <mbedtls/ssl.h>
#include <mbedtls/ssl_cookie.h>
-class SSLContextMbedTLS;
+class TLSContextMbedTLS;
class CookieContextMbedTLS : public RefCounted {
- friend class SSLContextMbedTLS;
+ friend class TLSContextMbedTLS;
protected:
bool inited = false;
@@ -63,7 +63,7 @@ public:
~CookieContextMbedTLS();
};
-class SSLContextMbedTLS : public RefCounted {
+class TLSContextMbedTLS : public RefCounted {
protected:
bool inited = false;
@@ -73,7 +73,7 @@ public:
Ref<X509CertificateMbedTLS> certs;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
- mbedtls_ssl_context ssl;
+ mbedtls_ssl_context tls;
mbedtls_ssl_config conf;
Ref<CookieContextMbedTLS> cookies;
@@ -86,8 +86,8 @@ public:
mbedtls_ssl_context *get_context();
- SSLContextMbedTLS();
- ~SSLContextMbedTLS();
+ TLSContextMbedTLS();
+ ~TLSContextMbedTLS();
};
-#endif // SSL_CONTEXT_MBEDTLS_H
+#endif // TLS_CONTEXT_MBEDTLS_H
diff --git a/modules/mono/build_scripts/mono_configure.py b/modules/mono/build_scripts/mono_configure.py
index c2d5452837..5d63773096 100644
--- a/modules/mono/build_scripts/mono_configure.py
+++ b/modules/mono/build_scripts/mono_configure.py
@@ -27,293 +27,3 @@ def configure(env, env_mono):
if env["tools"]:
env_mono.Append(CPPDEFINES=["GD_MONO_HOT_RELOAD"])
-
- app_host_dir = find_dotnet_app_host_dir(env)
-
- def check_app_host_file_exists(file):
- file_path = os.path.join(app_host_dir, file)
- if not os.path.isfile(file_path):
- raise RuntimeError("File not found: " + file_path)
-
- # TODO:
- # All libnethost does for us is provide a function to find hostfxr.
- # If we could handle that logic ourselves we could void linking it.
-
- # nethost file names:
- # static: libnethost.a/lib
- # shared: libnethost.a/dylib and nethost.dll
- check_app_host_file_exists("libnethost.lib" if os.name == "nt" else "libnethost.a")
- check_app_host_file_exists("nethost.h")
- check_app_host_file_exists("hostfxr.h")
- check_app_host_file_exists("coreclr_delegates.h")
-
- env_mono.Prepend(CPPPATH=app_host_dir)
-
- env.Append(LIBPATH=[app_host_dir])
-
- # Only the editor build links nethost, which is needed to find hostfxr.
- # Exported games don't need this logic as hostfxr is bundled with them.
- if tools_enabled:
- libnethost_path = os.path.join(app_host_dir, "libnethost.lib" if os.name == "nt" else "libnethost.a")
-
- if env["platform"] == "windows":
- env_mono.Append(CPPDEFINES=["NETHOST_USE_AS_STATIC"])
-
- if env.msvc:
- env.Append(LINKFLAGS="libnethost.lib")
- else:
- env.Append(LINKFLAGS=["-Wl,-whole-archive", libnethost_path, "-Wl,-no-whole-archive"])
- else:
- is_apple = env["platform"] in ["macos", "ios"]
- # is_macos = is_apple and not is_ios
-
- # if is_ios and not is_ios_sim:
- # env_mono.Append(CPPDEFINES=["IOS_DEVICE"])
-
- if is_apple:
- env.Append(LINKFLAGS=["-Wl,-force_load," + libnethost_path])
- else:
- env.Append(LINKFLAGS=["-Wl,-whole-archive", libnethost_path, "-Wl,-no-whole-archive"])
-
-
-def find_dotnet_app_host_dir(env):
- dotnet_version = "6.0"
-
- dotnet_root = env["dotnet_root"]
-
- if not dotnet_root:
- dotnet_cmd = find_dotnet_executable(env["arch"])
- if dotnet_cmd:
- sdk_path = find_dotnet_sdk(dotnet_cmd, dotnet_version)
- if sdk_path:
- dotnet_root = os.path.abspath(os.path.join(sdk_path, os.pardir))
-
- if not dotnet_root:
- raise RuntimeError("Cannot find .NET Core Sdk")
-
- print("Found .NET Core Sdk root directory: " + dotnet_root)
-
- dotnet_cmd = os.path.join(dotnet_root, "dotnet.exe" if os.name == "nt" else "dotnet")
-
- runtime_identifier = determine_runtime_identifier(env)
-
- # TODO: In the future, if it can't be found this way, we want to obtain it
- # from the runtime.{runtime_identifier}.Microsoft.NETCore.DotNetAppHost NuGet package.
- app_host_version = find_app_host_version(dotnet_cmd, dotnet_version)
- if not app_host_version:
- raise RuntimeError("Cannot find .NET app host for version: " + dotnet_version)
-
- def get_runtime_path():
- return os.path.join(
- dotnet_root,
- "packs",
- "Microsoft.NETCore.App.Host." + runtime_identifier,
- app_host_version,
- "runtimes",
- runtime_identifier,
- "native",
- )
-
- app_host_dir = get_runtime_path()
-
- # Some Linux distros use their distro name as the RID in these paths.
- # If the initial generic path doesn't exist, try to get the RID from `dotnet --info`.
- # The generic RID should still be the first choice. Some platforms like Windows 10
- # define the RID as `win10-x64` but still use the generic `win-x64` for directory names.
- if not app_host_dir or not os.path.isdir(app_host_dir):
- runtime_identifier = find_dotnet_cli_rid(dotnet_cmd)
- app_host_dir = get_runtime_path()
-
- return app_host_dir
-
-
-def determine_runtime_identifier(env):
- # The keys are Godot's names, the values are the Microsoft's names.
- # List: https://docs.microsoft.com/en-us/dotnet/core/rid-catalog
- names_map = {
- "windows": "win",
- "macos": "osx",
- "linuxbsd": "linux",
- }
- arch_map = {
- "x86_64": "x64",
- "x86_32": "x86",
- "arm64": "arm64",
- "arm32": "arm",
- }
- platform = env["platform"]
- if is_desktop(platform):
- return "%s-%s" % (names_map[platform], arch_map[env["arch"]])
- else:
- raise NotImplementedError()
-
-
-def find_app_host_version(dotnet_cmd, search_version_str):
- import subprocess
- from distutils.version import LooseVersion
-
- search_version = LooseVersion(search_version_str)
- found_match = False
-
- try:
- env = dict(os.environ, DOTNET_CLI_UI_LANGUAGE="en-US")
- lines = subprocess.check_output([dotnet_cmd, "--list-runtimes"], env=env).splitlines()
-
- for line_bytes in lines:
- line = line_bytes.decode("utf-8")
- if not line.startswith("Microsoft.NETCore.App "):
- continue
-
- parts = line.split(" ", 2)
- if len(parts) < 3:
- continue
-
- version_str = parts[1]
-
- version = LooseVersion(version_str)
-
- if version >= search_version:
- search_version = version
- found_match = True
- if found_match:
- return str(search_version)
- except (subprocess.CalledProcessError, OSError) as e:
- import sys
-
- print(e, file=sys.stderr)
-
- return ""
-
-
-def find_dotnet_arch(dotnet_cmd):
- import subprocess
-
- try:
- env = dict(os.environ, DOTNET_CLI_UI_LANGUAGE="en-US")
- lines = subprocess.check_output([dotnet_cmd, "--info"], env=env).splitlines()
-
- for line_bytes in lines:
- line = line_bytes.decode("utf-8")
-
- parts = line.split(":", 1)
- if len(parts) < 2:
- continue
-
- arch_str = parts[0].strip()
- if arch_str != "Architecture":
- continue
-
- arch_value = parts[1].strip()
- arch_map = {"x64": "x86_64", "x86": "x86_32", "arm64": "arm64", "arm32": "arm32"}
- return arch_map[arch_value]
- except (subprocess.CalledProcessError, OSError) as e:
- import sys
-
- print(e, file=sys.stderr)
-
- return ""
-
-
-def find_dotnet_sdk(dotnet_cmd, search_version_str):
- import subprocess
- from distutils.version import LooseVersion
-
- search_version = LooseVersion(search_version_str)
-
- try:
- env = dict(os.environ, DOTNET_CLI_UI_LANGUAGE="en-US")
- lines = subprocess.check_output([dotnet_cmd, "--list-sdks"], env=env).splitlines()
-
- for line_bytes in lines:
- line = line_bytes.decode("utf-8")
-
- parts = line.split(" ", 1)
- if len(parts) < 2:
- continue
-
- version_str = parts[0]
-
- version = LooseVersion(version_str)
-
- if version < search_version:
- continue
-
- path_part = parts[1]
- return path_part[1 : path_part.find("]")]
- except (subprocess.CalledProcessError, OSError) as e:
- import sys
-
- print(e, file=sys.stderr)
-
- return ""
-
-
-def find_dotnet_cli_rid(dotnet_cmd):
- import subprocess
-
- try:
- env = dict(os.environ, DOTNET_CLI_UI_LANGUAGE="en-US")
- lines = subprocess.check_output([dotnet_cmd, "--info"], env=env).splitlines()
-
- for line_bytes in lines:
- line = line_bytes.decode("utf-8")
- if not line.startswith(" RID:"):
- continue
-
- parts = line.split()
- if len(parts) < 2:
- continue
-
- return parts[1]
- except (subprocess.CalledProcessError, OSError) as e:
- import sys
-
- print(e, file=sys.stderr)
-
- return ""
-
-
-ENV_PATH_SEP = ";" if os.name == "nt" else ":"
-
-
-def find_dotnet_executable(arch):
- is_windows = os.name == "nt"
- windows_exts = os.environ["PATHEXT"].split(ENV_PATH_SEP) if is_windows else None
- path_dirs = os.environ["PATH"].split(ENV_PATH_SEP)
-
- search_dirs = path_dirs + [os.getcwd()] # cwd is last in the list
-
- for dir in path_dirs:
- search_dirs += [
- os.path.join(dir, "x64"),
- os.path.join(dir, "x86"),
- os.path.join(dir, "arm64"),
- os.path.join(dir, "arm32"),
- ] # search subfolders for cross compiling
-
- # `dotnet --info` may not specify architecture. In such cases,
- # we fallback to the first one we find without architecture.
- sdk_path_unknown_arch = ""
-
- for dir in search_dirs:
- path = os.path.join(dir, "dotnet")
-
- if is_windows:
- for extension in windows_exts:
- path_with_ext = path + extension
-
- if os.path.isfile(path_with_ext) and os.access(path_with_ext, os.X_OK):
- sdk_arch = find_dotnet_arch(path_with_ext)
- if sdk_arch == arch or arch == "":
- return path_with_ext
- elif sdk_arch == "":
- sdk_path_unknown_arch = path_with_ext
- else:
- if os.path.isfile(path) and os.access(path, os.X_OK):
- sdk_arch = find_dotnet_arch(path)
- if sdk_arch == arch or arch == "":
- return path
- elif sdk_arch == "":
- sdk_path_unknown_arch = path
-
- return sdk_path_unknown_arch
diff --git a/modules/mono/config.py b/modules/mono/config.py
index ad78c8c898..15fe79ef8c 100644
--- a/modules/mono/config.py
+++ b/modules/mono/config.py
@@ -4,23 +4,13 @@ supported_platforms = ["windows", "macos", "linuxbsd"]
def can_build(env, platform):
- return not env["arch"].startswith("rv")
+ if env["arch"].startswith("rv"):
+ return False
+ if env["tools"]:
+ env.module_add_dependencies("mono", ["regex"])
-def get_opts(platform):
- from SCons.Variables import BoolVariable, PathVariable
-
- default_mono_static = platform in ["ios", "web"]
- default_mono_bundles_zlib = platform in ["web"]
-
- return [
- PathVariable(
- "dotnet_root",
- "Path to the .NET Sdk installation directory for the target platform and architecture",
- "",
- PathVariable.PathAccept,
- ),
- ]
+ return True
def configure(env):
diff --git a/modules/mono/editor/hostfxr_resolver.cpp b/modules/mono/editor/hostfxr_resolver.cpp
new file mode 100644
index 0000000000..bdc8fac8b5
--- /dev/null
+++ b/modules/mono/editor/hostfxr_resolver.cpp
@@ -0,0 +1,335 @@
+/*************************************************************************/
+/* hostfxr_resolver.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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. */
+/*************************************************************************/
+
+/*
+Adapted to Godot from the nethost library: https://github.com/dotnet/runtime/tree/main/src/native/corehost
+*/
+
+/*
+The MIT License (MIT)
+
+Copyright (c) .NET Foundation and Contributors
+
+All rights reserved.
+
+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 "hostfxr_resolver.h"
+
+#include "core/config/engine.h"
+#include "core/io/dir_access.h"
+#include "core/io/file_access.h"
+#include "core/os/os.h"
+
+#ifdef WINDOWS_ENABLED
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
+#include "../utils/path_utils.h"
+#include "semver.h"
+
+// We don't use libnethost as it gives us issues with some compilers.
+// This file tries to mimic libnethost's hostfxr_resolver search logic. We try to use the
+// same function names for easier comparing in case we need to update this in the future.
+
+namespace {
+
+String get_hostfxr_file_name() {
+#if defined(WINDOWS_ENABLED) || defined(UWP_ENABLED)
+ return "hostfxr.dll";
+#elif defined(OSX_ENABLED) || defined(IOS_ENABLED)
+ return "libhostfxr.dylib";
+#else
+ return "libhostfxr.so";
+#endif
+}
+
+bool get_latest_fxr(const String &fxr_root, String &r_fxr_path) {
+ godotsharp::SemVerParser sem_ver_parser;
+
+ bool found_ver = false;
+ godotsharp::SemVer latest_ver;
+ String latest_ver_str;
+
+ Ref<DirAccess> da = DirAccess::open(fxr_root);
+ da->list_dir_begin();
+ for (String dir = da->get_next(); !dir.is_empty(); dir = da->get_next()) {
+ if (!da->current_is_dir() || dir == "." || dir == "..") {
+ continue;
+ }
+
+ String ver = dir.get_file();
+
+ godotsharp::SemVer fx_ver;
+ if (sem_ver_parser.parse(ver, fx_ver)) {
+ if (!found_ver || fx_ver > latest_ver) {
+ latest_ver = fx_ver;
+ latest_ver_str = ver;
+ found_ver = true;
+ }
+ }
+ }
+
+ if (!found_ver) {
+ return false;
+ }
+
+ String fxr_with_ver = path::join(fxr_root, latest_ver_str);
+ String hostfxr_file_path = path::join(fxr_with_ver, get_hostfxr_file_name());
+
+ ERR_FAIL_COND_V_MSG(!FileAccess::exists(hostfxr_file_path), false, "Missing hostfxr library in directory: " + fxr_with_ver);
+
+ r_fxr_path = hostfxr_file_path;
+
+ return true;
+}
+
+#ifdef WINDOWS_ENABLED
+typedef BOOL(WINAPI *LPFN_ISWOW64PROCESS)(HANDLE, PBOOL);
+
+BOOL is_wow64() {
+ BOOL wow64 = FALSE;
+
+ LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process");
+
+ if (fnIsWow64Process) {
+ if (!fnIsWow64Process(GetCurrentProcess(), &wow64)) {
+ wow64 = FALSE;
+ }
+ }
+
+ return wow64;
+}
+#endif
+
+static const char *arch_name_map[][2] = {
+ { "arm32", "arm" },
+ { "arm64", "arm64" },
+ { "rv64", "riscv64" },
+ { "x86_64", "x64" },
+ { "x86_32", "x86" },
+ { nullptr, nullptr }
+};
+
+String get_dotnet_arch() {
+ String arch = Engine::get_singleton()->get_architecture_name();
+
+ int idx = 0;
+ while (arch_name_map[idx][0] != nullptr) {
+ if (arch_name_map[idx][0] == arch) {
+ return arch_name_map[idx][1];
+ }
+ idx++;
+ }
+
+ return "";
+}
+
+bool get_default_installation_dir(String &r_dotnet_root) {
+#if defined(WINDOWS_ENABLED)
+ String program_files_env;
+ if (is_wow64()) {
+ // Running x86 on x64, looking for x86 install
+ program_files_env = "ProgramFiles(x86)";
+ } else {
+ program_files_env = "ProgramFiles";
+ }
+
+ String program_files_dir = OS::get_singleton()->get_environment(program_files_env);
+
+ if (program_files_dir.is_empty()) {
+ return false;
+ }
+
+#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(_M_X64)
+ // When emulating x64 on arm
+ String dotnet_root_emulated = path::join(program_files_dir, "dotnet", "x64");
+ if (FileAccess::exists(path::join(dotnet_root_emulated, "dotnet.exe"))) {
+ r_dotnet_root = dotnet_root_emulated;
+ return true;
+ }
+#endif
+
+ r_dotnet_root = path::join(program_files_dir, "dotnet");
+ return true;
+#elif defined(TARGET_OSX)
+ r_dotnet_root = "/usr/local/share/dotnet";
+
+#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__) || defined(_M_X64)
+ // When emulating x64 on arm
+ String dotnet_root_emulated = path::join(r_dotnet_root, "x64");
+ if (FileAccess::exists(path::join(dotnet_root_emulated, "dotnet"))) {
+ r_dotnet_root = dotnet_root_emulated;
+ return true;
+ }
+#endif
+
+ return true;
+#else
+ r_dotnet_root = "/usr/share/dotnet";
+ return true;
+#endif
+}
+
+bool get_install_location_from_file(const String &p_file_path, String &r_dotnet_root) {
+ Error err = OK;
+ Ref<FileAccess> f = FileAccess::open(p_file_path, FileAccess::READ, &err);
+
+ if (f.is_null() || err != OK) {
+ return false;
+ }
+
+ String line = f->get_line();
+
+ if (line.is_empty()) {
+ return false;
+ }
+
+ r_dotnet_root = line;
+ return true;
+}
+
+bool get_dotnet_self_registered_dir(String &r_dotnet_root) {
+#if defined(WINDOWS_ENABLED)
+ String sub_key = "SOFTWARE\\dotnet\\Setup\\InstalledVersions\\" + get_dotnet_arch();
+ Char16String value = String("InstallLocation").utf16();
+
+ HKEY hkey = NULL;
+ LSTATUS result = RegOpenKeyExW(HKEY_LOCAL_MACHINE, (LPCWSTR)(sub_key.utf16().get_data()), 0, KEY_READ | KEY_WOW64_32KEY, &hkey);
+ if (result != ERROR_SUCCESS) {
+ return false;
+ }
+
+ DWORD size = 0;
+ result = RegGetValueW(hkey, nullptr, (LPCWSTR)(value.get_data()), RRF_RT_REG_SZ, nullptr, nullptr, &size);
+ if (result != ERROR_SUCCESS || size == 0) {
+ RegCloseKey(hkey);
+ return false;
+ }
+
+ Vector<WCHAR> buffer;
+ buffer.resize(size / sizeof(WCHAR));
+ result = RegGetValueW(hkey, nullptr, (LPCWSTR)(value.get_data()), RRF_RT_REG_SZ, nullptr, (LPBYTE)buffer.ptrw(), &size);
+ if (result != ERROR_SUCCESS) {
+ RegCloseKey(hkey);
+ return false;
+ }
+
+ r_dotnet_root = String::utf16((const char16_t *)buffer.ptr());
+ RegCloseKey(hkey);
+ return true;
+#else
+ String install_location_file = path::join("/etc/dotnet", "install_location_" + get_dotnet_arch().to_lower());
+ if (get_install_location_from_file(install_location_file, r_dotnet_root)) {
+ return true;
+ }
+
+ if (FileAccess::exists(install_location_file)) {
+ // Don't try with the legacy location, this will fall back to the hard-coded default install location
+ return false;
+ }
+
+ String legacy_install_location_file = path::join("/etc/dotnet", "install_location");
+ return get_install_location_from_file(legacy_install_location_file, r_dotnet_root);
+#endif
+}
+
+bool get_file_path_from_env(const String &p_env_key, String &r_dotnet_root) {
+ String env_value = OS::get_singleton()->get_environment(p_env_key);
+
+ if (!env_value.is_empty()) {
+ env_value = path::realpath(env_value);
+
+ if (DirAccess::exists(env_value)) {
+ r_dotnet_root = env_value;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool get_dotnet_root_from_env(String &r_dotnet_root) {
+ String dotnet_root_env = "DOTNET_ROOT";
+ String arch_for_env = get_dotnet_arch();
+
+ if (!arch_for_env.is_empty()) {
+ // DOTNET_ROOT_<arch>
+ if (get_file_path_from_env(dotnet_root_env + "_" + arch_for_env.to_upper(), r_dotnet_root)) {
+ return true;
+ }
+ }
+
+#ifdef WINDOWS_ENABLED
+ // WoW64-only: DOTNET_ROOT(x86)
+ if (is_wow64() && get_file_path_from_env("DOTNET_ROOT(x86)", r_dotnet_root)) {
+ return true;
+ }
+#endif
+
+ // DOTNET_ROOT
+ return get_file_path_from_env(dotnet_root_env, r_dotnet_root);
+}
+
+} //namespace
+
+bool godotsharp::hostfxr_resolver::try_get_path_from_dotnet_root(const String &p_dotnet_root, String &r_fxr_path) {
+ String fxr_dir = path::join(p_dotnet_root, "host", "fxr");
+ ERR_FAIL_COND_V_MSG(!DirAccess::exists(fxr_dir), false, "The host fxr folder does not exist: " + fxr_dir);
+ return get_latest_fxr(fxr_dir, r_fxr_path);
+}
+
+bool godotsharp::hostfxr_resolver::try_get_path(String &r_dotnet_root, String &r_fxr_path) {
+ if (!get_dotnet_root_from_env(r_dotnet_root) &&
+ !get_dotnet_self_registered_dir(r_dotnet_root) &&
+ !get_default_installation_dir(r_dotnet_root)) {
+ return false;
+ }
+
+ return try_get_path_from_dotnet_root(r_dotnet_root, r_fxr_path);
+}
diff --git a/modules/mono/editor/hostfxr_resolver.h b/modules/mono/editor/hostfxr_resolver.h
new file mode 100644
index 0000000000..0f029ab7ae
--- /dev/null
+++ b/modules/mono/editor/hostfxr_resolver.h
@@ -0,0 +1,45 @@
+/*************************************************************************/
+/* hostfxr_resolver.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 HOSTFXR_RESOLVER_H
+#define HOSTFXR_RESOLVER_H
+
+#include "core/string/ustring.h"
+
+namespace godotsharp {
+namespace hostfxr_resolver {
+
+bool try_get_path_from_dotnet_root(const String &p_dotnet_root, String &r_out_fxr_path);
+bool try_get_path(String &r_out_dotnet_root, String &r_out_fxr_path);
+
+} //namespace hostfxr_resolver
+} //namespace godotsharp
+
+#endif // HOSTFXR_RESOLVER_H
diff --git a/modules/mono/editor/semver.cpp b/modules/mono/editor/semver.cpp
new file mode 100644
index 0000000000..1656d0932f
--- /dev/null
+++ b/modules/mono/editor/semver.cpp
@@ -0,0 +1,149 @@
+/*************************************************************************/
+/* semver.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 "semver.h"
+
+bool godotsharp::SemVer::parse_digit_only_field(const String &p_field, uint64_t &r_result) {
+ if (p_field.is_empty()) {
+ return false;
+ }
+
+ int64_t integer = 0;
+
+ for (int i = 0; i < p_field.length(); i++) {
+ char32_t c = p_field[i];
+ if (is_digit(c)) {
+ bool overflow = ((uint64_t)integer > UINT64_MAX / 10) || ((uint64_t)integer == UINT64_MAX / 10 && c > '5');
+ ERR_FAIL_COND_V_MSG(overflow, false, "Cannot represent '" + p_field + "' as a 64-bit unsigned integer, since the value is too large.");
+ integer *= 10;
+ integer += c - '0';
+ } else {
+ return false;
+ }
+ }
+
+ r_result = (uint64_t)integer;
+ return true;
+}
+
+int godotsharp::SemVer::cmp(const godotsharp::SemVer &p_a, const godotsharp::SemVer &p_b) {
+ if (p_a.major != p_b.major) {
+ return p_a.major > p_b.major ? 1 : -1;
+ }
+
+ if (p_a.minor != p_b.minor) {
+ return p_a.minor > p_b.minor ? 1 : -1;
+ }
+
+ if (p_a.patch != p_b.patch) {
+ return p_a.patch > p_b.patch ? 1 : -1;
+ }
+
+ if (p_a.prerelease.is_empty() && p_b.prerelease.is_empty()) {
+ return 0;
+ }
+
+ if (p_a.prerelease.is_empty() || p_b.prerelease.is_empty()) {
+ return p_a.prerelease.is_empty() ? 1 : -1;
+ }
+
+ if (p_a.prerelease != p_b.prerelease) {
+ // This could be optimized, but I'm too lazy
+
+ Vector<String> a_field_set = p_a.prerelease.split(".");
+ Vector<String> b_field_set = p_b.prerelease.split(".");
+
+ int a_field_count = a_field_set.size();
+ int b_field_count = b_field_set.size();
+
+ int min_field_count = MIN(a_field_count, b_field_count);
+
+ for (int i = 0; i < min_field_count; i++) {
+ const String &a_field = a_field_set[i];
+ const String &b_field = b_field_set[i];
+
+ if (a_field == b_field) {
+ continue;
+ }
+
+ uint64_t a_num;
+ bool a_is_digit_only = parse_digit_only_field(a_field, a_num);
+
+ uint64_t b_num;
+ bool b_is_digit_only = parse_digit_only_field(b_field, b_num);
+
+ if (a_is_digit_only && b_is_digit_only) {
+ // Identifiers consisting of only digits are compared numerically.
+
+ if (a_num == b_num) {
+ continue;
+ }
+
+ return a_num > b_num ? 1 : -1;
+ }
+
+ if (a_is_digit_only || b_is_digit_only) {
+ // Numeric identifiers always have lower precedence than non-numeric identifiers.
+ return b_is_digit_only ? 1 : -1;
+ }
+
+ // Identifiers with letters or hyphens are compared lexically in ASCII sort order.
+ return a_field > b_field ? 1 : -1;
+ }
+
+ if (a_field_count != b_field_count) {
+ // A larger set of pre-release fields has a higher precedence than a smaller set, if all of the preceding identifiers are equal.
+ return a_field_count > b_field_count ? 1 : -1;
+ }
+ }
+
+ return 0;
+}
+
+bool godotsharp::SemVerParser::parse(const String &p_ver_text, godotsharp::SemVer &r_semver) {
+ if (!regex.is_valid() && regex.get_pattern().is_empty()) {
+ regex.compile("^(?P<major>0|[1-9]\\d*)\\.(?P<minor>0|[1-9]\\d*)\\.(?P<patch>0|[1-9]\\d*)(?:-(?P<prerelease>(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+(?P<buildmetadata>[0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$");
+ ERR_FAIL_COND_V(!regex.is_valid(), false);
+ }
+
+ Ref<RegExMatch> match = regex.search(p_ver_text);
+
+ if (match.is_valid()) {
+ r_semver = SemVer(
+ match->get_string("major").to_int(),
+ match->get_string("minor").to_int(),
+ match->get_string("patch").to_int(),
+ match->get_string("prerelease"),
+ match->get_string("buildmetadata"));
+ return true;
+ }
+
+ return false;
+}
diff --git a/modules/mono/editor/semver.h b/modules/mono/editor/semver.h
new file mode 100644
index 0000000000..48ea8b043e
--- /dev/null
+++ b/modules/mono/editor/semver.h
@@ -0,0 +1,106 @@
+/*************************************************************************/
+/* semver.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 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 SEMVER_H
+#define SEMVER_H
+
+#include "core/string/ustring.h"
+#include "modules/regex/regex.h"
+
+// <sys/sysmacros.h> is included somewhere, which defines major(dev) to gnu_dev_major(dev)
+#if defined(major)
+#undef major
+#endif
+#if defined(minor)
+#undef minor
+#endif
+
+namespace godotsharp {
+
+struct SemVer {
+private:
+ static bool parse_digit_only_field(const String &p_field, uint64_t &r_result);
+
+ static int cmp(const SemVer &p_a, const SemVer &p_b);
+
+public:
+ int major = 0;
+ int minor = 0;
+ int patch = 0;
+ String prerelease;
+ String build_metadata;
+
+ bool operator==(const SemVer &b) const {
+ return cmp(*this, b) == 0;
+ }
+
+ bool operator!=(const SemVer &b) const {
+ return !operator==(b);
+ }
+
+ bool operator<(const SemVer &b) const {
+ return cmp(*this, b) < 0;
+ }
+
+ bool operator>(const SemVer &b) const {
+ return cmp(*this, b) > 0;
+ }
+
+ bool operator<=(const SemVer &b) const {
+ return cmp(*this, b) <= 0;
+ }
+
+ bool operator>=(const SemVer &b) const {
+ return cmp(*this, b) >= 0;
+ }
+
+ SemVer() {}
+
+ SemVer(int p_major, int p_minor, int p_patch,
+ const String &p_prerelease, const String &p_build_metadata) :
+ major(p_major),
+ minor(p_minor),
+ patch(p_patch),
+ prerelease(p_prerelease),
+ build_metadata(p_build_metadata) {
+ }
+};
+
+struct SemVerParser {
+private:
+ RegEx regex;
+
+public:
+ bool parse(const String &p_ver_text, SemVer &r_semver);
+};
+
+} //namespace godotsharp
+
+#endif // SEMVER_H
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index e698e92d7a..3b87d9248a 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -43,12 +43,13 @@
#include "../utils/path_utils.h"
#include "gd_mono_cache.h"
+#include "../thirdparty/coreclr_delegates.h"
+#include "../thirdparty/hostfxr.h"
+
#ifdef TOOLS_ENABLED
-#include <nethost.h>
+#include "../editor/hostfxr_resolver.h"
#endif
-#include <coreclr_delegates.h>
-#include <hostfxr.h>
#ifdef UNIX_ENABLED
#include <dlfcn.h>
#endif
@@ -88,85 +89,43 @@ HostFxrCharString str_to_hostfxr(const String &p_str) {
#endif
}
-#ifdef TOOLS_ENABLED
-String str_from_hostfxr(const char_t *p_buffer) {
-#ifdef _WIN32
- return String::utf16((const char16_t *)p_buffer);
-#else
- return String::utf8((const char *)p_buffer);
-#endif
-}
-#endif
-
const char_t *get_data(const HostFxrCharString &p_char_str) {
return (const char_t *)p_char_str.get_data();
}
-#ifdef TOOLS_ENABLED
-String find_hostfxr(size_t p_known_buffer_size, get_hostfxr_parameters *p_get_hostfxr_params) {
- // Pre-allocate a large buffer for the path to hostfxr
- Vector<char_t> buffer;
- buffer.resize(p_known_buffer_size);
-
- int rc = get_hostfxr_path(buffer.ptrw(), &p_known_buffer_size, p_get_hostfxr_params);
-
- ERR_FAIL_COND_V_MSG(rc != 0, String(), "get_hostfxr_path failed with code: " + itos(rc));
-
- return str_from_hostfxr(buffer.ptr());
-}
-#endif
-
String find_hostfxr() {
#ifdef TOOLS_ENABLED
- const int CoreHostLibMissingFailure = 0x80008083;
- const int HostApiBufferTooSmall = 0x80008098;
-
- size_t buffer_size = 0;
- int rc = get_hostfxr_path(nullptr, &buffer_size, nullptr);
-
- if (rc == HostApiBufferTooSmall) {
- return find_hostfxr(buffer_size, nullptr);
+ String dotnet_root;
+ String fxr_path;
+ if (godotsharp::hostfxr_resolver::try_get_path(dotnet_root, fxr_path)) {
+ return fxr_path;
}
- if (rc == CoreHostLibMissingFailure) {
- // Apparently `get_hostfxr_path` doesn't look for dotnet in `PATH`? (I suppose it needs the
- // `DOTNET_ROOT` environment variable). If it fails, we try to find the dotnet executable
- // in `PATH` ourselves and pass its location as `dotnet_root` to `get_hostfxr_path`.
- String dotnet_exe = path::find_executable("dotnet");
-
- if (!dotnet_exe.is_empty()) {
- // The file found in PATH may be a symlink
- dotnet_exe = path::abspath(path::realpath(dotnet_exe));
-
- // TODO:
- // Sometimes, the symlink may not point to the dotnet executable in the dotnet root.
- // That's the case with snaps. The snap install should have been found with the
- // previous `get_hostfxr_path`, but it would still be better to do this properly
- // and use something like `dotnet --list-sdks/runtimes` to find the actual location.
- // This way we could also check if the proper sdk or runtime is installed. This would
- // allow us to fail gracefully and show some helpful information in the editor.
-
- HostFxrCharString dotnet_root = str_to_hostfxr(dotnet_exe.get_base_dir());
-
- get_hostfxr_parameters get_hostfxr_parameters = {
- sizeof(get_hostfxr_parameters),
- nullptr,
- get_data(dotnet_root)
- };
-
- buffer_size = 0;
- rc = get_hostfxr_path(nullptr, &buffer_size, &get_hostfxr_parameters);
- if (rc == HostApiBufferTooSmall) {
- return find_hostfxr(buffer_size, &get_hostfxr_parameters);
- }
+ // hostfxr_resolver doesn't look for dotnet in `PATH`. If it fails, we try to find the dotnet
+ // executable in `PATH` here and pass its location as `dotnet_root` to `get_hostfxr_path`.
+ String dotnet_exe = path::find_executable("dotnet");
+
+ if (!dotnet_exe.is_empty()) {
+ // The file found in PATH may be a symlink
+ dotnet_exe = path::abspath(path::realpath(dotnet_exe));
+
+ // TODO:
+ // Sometimes, the symlink may not point to the dotnet executable in the dotnet root.
+ // That's the case with snaps. The snap install should have been found with the
+ // previous `get_hostfxr_path`, but it would still be better to do this properly
+ // and use something like `dotnet --list-sdks/runtimes` to find the actual location.
+ // This way we could also check if the proper sdk or runtime is installed. This would
+ // allow us to fail gracefully and show some helpful information in the editor.
+
+ dotnet_root = dotnet_exe.get_base_dir();
+ if (godotsharp::hostfxr_resolver::try_get_path_from_dotnet_root(dotnet_root, fxr_path)) {
+ return fxr_path;
}
}
- if (rc == CoreHostLibMissingFailure) {
- ERR_PRINT(String() + ".NET: One of the dependent libraries is missing. " +
- "Typically when the `hostfxr`, `hostpolicy` or `coreclr` dynamic " +
- "libraries are not present in the expected locations.");
- }
+ ERR_PRINT(String() + ".NET: One of the dependent libraries is missing. " +
+ "Typically when the `hostfxr`, `hostpolicy` or `coreclr` dynamic " +
+ "libraries are not present in the expected locations.");
return String();
#else
diff --git a/modules/mono/thirdparty/coreclr_delegates.h b/modules/mono/thirdparty/coreclr_delegates.h
new file mode 100644
index 0000000000..914ab592df
--- /dev/null
+++ b/modules/mono/thirdparty/coreclr_delegates.h
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#ifndef __CORECLR_DELEGATES_H__
+#define __CORECLR_DELEGATES_H__
+
+#include <stdint.h>
+
+#if defined(_WIN32)
+ #define CORECLR_DELEGATE_CALLTYPE __stdcall
+ #ifdef _WCHAR_T_DEFINED
+ typedef wchar_t char_t;
+ #else
+ typedef unsigned short char_t;
+ #endif
+#else
+ #define CORECLR_DELEGATE_CALLTYPE
+ typedef char char_t;
+#endif
+
+#define UNMANAGEDCALLERSONLY_METHOD ((const char_t*)-1)
+
+// Signature of delegate returned by coreclr_delegate_type::load_assembly_and_get_function_pointer
+typedef int (CORECLR_DELEGATE_CALLTYPE *load_assembly_and_get_function_pointer_fn)(
+ const char_t *assembly_path /* Fully qualified path to assembly */,
+ const char_t *type_name /* Assembly qualified type name */,
+ const char_t *method_name /* Public static method name compatible with delegateType */,
+ const char_t *delegate_type_name /* Assembly qualified delegate type name or null
+ or UNMANAGEDCALLERSONLY_METHOD if the method is marked with
+ the UnmanagedCallersOnlyAttribute. */,
+ void *reserved /* Extensibility parameter (currently unused and must be 0) */,
+ /*out*/ void **delegate /* Pointer where to store the function pointer result */);
+
+// Signature of delegate returned by load_assembly_and_get_function_pointer_fn when delegate_type_name == null (default)
+typedef int (CORECLR_DELEGATE_CALLTYPE *component_entry_point_fn)(void *arg, int32_t arg_size_in_bytes);
+
+typedef int (CORECLR_DELEGATE_CALLTYPE *get_function_pointer_fn)(
+ const char_t *type_name /* Assembly qualified type name */,
+ const char_t *method_name /* Public static method name compatible with delegateType */,
+ const char_t *delegate_type_name /* Assembly qualified delegate type name or null,
+ or UNMANAGEDCALLERSONLY_METHOD if the method is marked with
+ the UnmanagedCallersOnlyAttribute. */,
+ void *load_context /* Extensibility parameter (currently unused and must be 0) */,
+ void *reserved /* Extensibility parameter (currently unused and must be 0) */,
+ /*out*/ void **delegate /* Pointer where to store the function pointer result */);
+
+#endif // __CORECLR_DELEGATES_H__
diff --git a/modules/mono/thirdparty/hostfxr.h b/modules/mono/thirdparty/hostfxr.h
new file mode 100644
index 0000000000..591a8ebbea
--- /dev/null
+++ b/modules/mono/thirdparty/hostfxr.h
@@ -0,0 +1,323 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#ifndef __HOSTFXR_H__
+#define __HOSTFXR_H__
+
+#include <stddef.h>
+#include <stdint.h>
+
+#if defined(_WIN32)
+ #define HOSTFXR_CALLTYPE __cdecl
+ #ifdef _WCHAR_T_DEFINED
+ typedef wchar_t char_t;
+ #else
+ typedef unsigned short char_t;
+ #endif
+#else
+ #define HOSTFXR_CALLTYPE
+ typedef char char_t;
+#endif
+
+enum hostfxr_delegate_type
+{
+ hdt_com_activation,
+ hdt_load_in_memory_assembly,
+ hdt_winrt_activation,
+ hdt_com_register,
+ hdt_com_unregister,
+ hdt_load_assembly_and_get_function_pointer,
+ hdt_get_function_pointer,
+};
+
+typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_main_fn)(const int argc, const char_t **argv);
+typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_main_startupinfo_fn)(
+ const int argc,
+ const char_t **argv,
+ const char_t *host_path,
+ const char_t *dotnet_root,
+ const char_t *app_path);
+typedef int32_t(HOSTFXR_CALLTYPE* hostfxr_main_bundle_startupinfo_fn)(
+ const int argc,
+ const char_t** argv,
+ const char_t* host_path,
+ const char_t* dotnet_root,
+ const char_t* app_path,
+ int64_t bundle_header_offset);
+
+typedef void(HOSTFXR_CALLTYPE *hostfxr_error_writer_fn)(const char_t *message);
+
+//
+// Sets a callback which is to be used to write errors to.
+//
+// Parameters:
+// error_writer
+// A callback function which will be invoked every time an error is to be reported.
+// Or nullptr to unregister previously registered callback and return to the default behavior.
+// Return value:
+// The previously registered callback (which is now unregistered), or nullptr if no previous callback
+// was registered
+//
+// The error writer is registered per-thread, so the registration is thread-local. On each thread
+// only one callback can be registered. Subsequent registrations overwrite the previous ones.
+//
+// By default no callback is registered in which case the errors are written to stderr.
+//
+// Each call to the error writer is sort of like writing a single line (the EOL character is omitted).
+// Multiple calls to the error writer may occur for one failure.
+//
+// If the hostfxr invokes functions in hostpolicy as part of its operation, the error writer
+// will be propagated to hostpolicy for the duration of the call. This means that errors from
+// both hostfxr and hostpolicy will be reporter through the same error writer.
+//
+typedef hostfxr_error_writer_fn(HOSTFXR_CALLTYPE *hostfxr_set_error_writer_fn)(hostfxr_error_writer_fn error_writer);
+
+typedef void* hostfxr_handle;
+struct hostfxr_initialize_parameters
+{
+ size_t size;
+ const char_t *host_path;
+ const char_t *dotnet_root;
+};
+
+//
+// Initializes the hosting components for a dotnet command line running an application
+//
+// Parameters:
+// argc
+// Number of argv arguments
+// argv
+// Command-line arguments for running an application (as if through the dotnet executable).
+// Only command-line arguments which are accepted by runtime installation are supported, SDK/CLI commands are not supported.
+// For example 'app.dll app_argument_1 app_argument_2`.
+// parameters
+// Optional. Additional parameters for initialization
+// host_context_handle
+// On success, this will be populated with an opaque value representing the initialized host context
+//
+// Return value:
+// Success - Hosting components were successfully initialized
+// HostInvalidState - Hosting components are already initialized
+//
+// This function parses the specified command-line arguments to determine the application to run. It will
+// then find the corresponding .runtimeconfig.json and .deps.json with which to resolve frameworks and
+// dependencies and prepare everything needed to load the runtime.
+//
+// This function only supports arguments for running an application. It does not support SDK commands.
+//
+// This function does not load the runtime.
+//
+typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_initialize_for_dotnet_command_line_fn)(
+ int argc,
+ const char_t **argv,
+ const struct hostfxr_initialize_parameters *parameters,
+ /*out*/ hostfxr_handle *host_context_handle);
+
+//
+// Initializes the hosting components using a .runtimeconfig.json file
+//
+// Parameters:
+// runtime_config_path
+// Path to the .runtimeconfig.json file
+// parameters
+// Optional. Additional parameters for initialization
+// host_context_handle
+// On success, this will be populated with an opaque value representing the initialized host context
+//
+// Return value:
+// Success - Hosting components were successfully initialized
+// Success_HostAlreadyInitialized - Config is compatible with already initialized hosting components
+// Success_DifferentRuntimeProperties - Config has runtime properties that differ from already initialized hosting components
+// CoreHostIncompatibleConfig - Config is incompatible with already initialized hosting components
+//
+// This function will process the .runtimeconfig.json to resolve frameworks and prepare everything needed
+// to load the runtime. It will only process the .deps.json from frameworks (not any app/component that
+// may be next to the .runtimeconfig.json).
+//
+// This function does not load the runtime.
+//
+// If called when the runtime has already been loaded, this function will check if the specified runtime
+// config is compatible with the existing runtime.
+//
+// Both Success_HostAlreadyInitialized and Success_DifferentRuntimeProperties codes are considered successful
+// initializations. In the case of Success_DifferentRuntimeProperties, it is left to the consumer to verify that
+// the difference in properties is acceptable.
+//
+typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_initialize_for_runtime_config_fn)(
+ const char_t *runtime_config_path,
+ const struct hostfxr_initialize_parameters *parameters,
+ /*out*/ hostfxr_handle *host_context_handle);
+
+//
+// Gets the runtime property value for an initialized host context
+//
+// Parameters:
+// host_context_handle
+// Handle to the initialized host context
+// name
+// Runtime property name
+// value
+// Out parameter. Pointer to a buffer with the property value.
+//
+// Return value:
+// The error code result.
+//
+// The buffer pointed to by value is owned by the host context. The lifetime of the buffer is only
+// guaranteed until any of the below occur:
+// - a 'run' method is called for the host context
+// - properties are changed via hostfxr_set_runtime_property_value
+// - the host context is closed via 'hostfxr_close'
+//
+// If host_context_handle is nullptr and an active host context exists, this function will get the
+// property value for the active host context.
+//
+typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_get_runtime_property_value_fn)(
+ const hostfxr_handle host_context_handle,
+ const char_t *name,
+ /*out*/ const char_t **value);
+
+//
+// Sets the value of a runtime property for an initialized host context
+//
+// Parameters:
+// host_context_handle
+// Handle to the initialized host context
+// name
+// Runtime property name
+// value
+// Value to set
+//
+// Return value:
+// The error code result.
+//
+// Setting properties is only supported for the first host context, before the runtime has been loaded.
+//
+// If the property already exists in the host context, it will be overwritten. If value is nullptr, the
+// property will be removed.
+//
+typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_set_runtime_property_value_fn)(
+ const hostfxr_handle host_context_handle,
+ const char_t *name,
+ const char_t *value);
+
+//
+// Gets all the runtime properties for an initialized host context
+//
+// Parameters:
+// host_context_handle
+// Handle to the initialized host context
+// count
+// [in] Size of the keys and values buffers
+// [out] Number of properties returned (size of keys/values buffers used). If the input value is too
+// small or keys/values is nullptr, this is populated with the number of available properties
+// keys
+// Array of pointers to buffers with runtime property keys
+// values
+// Array of pointers to buffers with runtime property values
+//
+// Return value:
+// The error code result.
+//
+// The buffers pointed to by keys and values are owned by the host context. The lifetime of the buffers is only
+// guaranteed until any of the below occur:
+// - a 'run' method is called for the host context
+// - properties are changed via hostfxr_set_runtime_property_value
+// - the host context is closed via 'hostfxr_close'
+//
+// If host_context_handle is nullptr and an active host context exists, this function will get the
+// properties for the active host context.
+//
+typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_get_runtime_properties_fn)(
+ const hostfxr_handle host_context_handle,
+ /*inout*/ size_t * count,
+ /*out*/ const char_t **keys,
+ /*out*/ const char_t **values);
+
+//
+// Load CoreCLR and run the application for an initialized host context
+//
+// Parameters:
+// host_context_handle
+// Handle to the initialized host context
+//
+// Return value:
+// If the app was successfully run, the exit code of the application. Otherwise, the error code result.
+//
+// The host_context_handle must have been initialized using hostfxr_initialize_for_dotnet_command_line.
+//
+// This function will not return until the managed application exits.
+//
+typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_run_app_fn)(const hostfxr_handle host_context_handle);
+
+//
+// Gets a typed delegate from the currently loaded CoreCLR or from a newly created one.
+//
+// Parameters:
+// host_context_handle
+// Handle to the initialized host context
+// type
+// Type of runtime delegate requested
+// delegate
+// An out parameter that will be assigned the delegate.
+//
+// Return value:
+// The error code result.
+//
+// If the host_context_handle was initialized using hostfxr_initialize_for_runtime_config,
+// then all delegate types are supported.
+// If the host_context_handle was initialized using hostfxr_initialize_for_dotnet_command_line,
+// then only the following delegate types are currently supported:
+// hdt_load_assembly_and_get_function_pointer
+// hdt_get_function_pointer
+//
+typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_get_runtime_delegate_fn)(
+ const hostfxr_handle host_context_handle,
+ enum hostfxr_delegate_type type,
+ /*out*/ void **delegate);
+
+//
+// Closes an initialized host context
+//
+// Parameters:
+// host_context_handle
+// Handle to the initialized host context
+//
+// Return value:
+// The error code result.
+//
+typedef int32_t(HOSTFXR_CALLTYPE *hostfxr_close_fn)(const hostfxr_handle host_context_handle);
+
+struct hostfxr_dotnet_environment_sdk_info
+{
+ size_t size;
+ const char_t* version;
+ const char_t* path;
+};
+
+typedef void(HOSTFXR_CALLTYPE* hostfxr_get_dotnet_environment_info_result_fn)(
+ const struct hostfxr_dotnet_environment_info* info,
+ void* result_context);
+
+struct hostfxr_dotnet_environment_framework_info
+{
+ size_t size;
+ const char_t* name;
+ const char_t* version;
+ const char_t* path;
+};
+
+struct hostfxr_dotnet_environment_info
+{
+ size_t size;
+
+ const char_t* hostfxr_version;
+ const char_t* hostfxr_commit_hash;
+
+ size_t sdk_count;
+ const struct hostfxr_dotnet_environment_sdk_info* sdks;
+
+ size_t framework_count;
+ const struct hostfxr_dotnet_environment_framework_info* frameworks;
+};
+
+#endif //__HOSTFXR_H__
diff --git a/modules/websocket/doc_classes/WebSocketClient.xml b/modules/websocket/doc_classes/WebSocketClient.xml
index 7d73194ea9..1978d2e7c6 100644
--- a/modules/websocket/doc_classes/WebSocketClient.xml
+++ b/modules/websocket/doc_classes/WebSocketClient.xml
@@ -24,8 +24,8 @@
If [code]true[/code] is passed as [code]gd_mp_api[/code], the client will behave like a multiplayer 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.
- [b]Note:[/b] To avoid mixed content warnings or errors in Web, you may have to use a [code]url[/code] that starts with [code]wss://[/code] (secure) instead of [code]ws://[/code]. When doing so, make sure to use the fully qualified domain name that matches the one defined in the server's SSL certificate. Do not connect directly via the IP address for [code]wss://[/code] connections, as it won't match with the SSL certificate.
- [b]Note:[/b] Specifying [code]custom_headers[/code] is not supported in Web exports due to browsers restrictions.
+ [b]Note:[/b] To avoid mixed content warnings or errors in Web, you may have to use a [code]url[/code] that starts with [code]wss://[/code] (secure) instead of [code]ws://[/code]. When doing so, make sure to use the fully qualified domain name that matches the one defined in the server's TLS certificate. Do not connect directly via the IP address for [code]wss://[/code] connections, as it won't match with the TLS certificate.
+ [b]Note:[/b] Specifying [code]custom_headers[/code] is not supported in Web exports due to browsers' restrictions.
</description>
</method>
<method name="disconnect_from_host">
@@ -50,12 +50,12 @@
</method>
</methods>
<members>
- <member name="trusted_ssl_certificate" type="X509Certificate" setter="set_trusted_ssl_certificate" getter="get_trusted_ssl_certificate">
- 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.
- [b]Note:[/b] Specifying a custom [code]trusted_ssl_certificate[/code] is not supported in Web exports due to browsers restrictions.
+ <member name="trusted_tls_certificate" type="X509Certificate" setter="set_trusted_tls_certificate" getter="get_trusted_tls_certificate">
+ If specified, this [X509Certificate] will be the only one accepted when connecting to an TLS host. Any other certificate provided by the server will be regarded as invalid.
+ [b]Note:[/b] Specifying a custom [code]trusted_tls_certificate[/code] is not supported in Web exports due to browsers' restrictions.
</member>
- <member name="verify_ssl" type="bool" setter="set_verify_ssl_enabled" getter="is_verify_ssl_enabled">
- If [code]true[/code], SSL certificate verification is enabled.
+ <member name="verify_tls" type="bool" setter="set_verify_tls_enabled" getter="is_verify_tls_enabled">
+ If [code]true[/code], TLS 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.
</member>
</members>
diff --git a/modules/websocket/doc_classes/WebSocketServer.xml b/modules/websocket/doc_classes/WebSocketServer.xml
index 19c36700e6..07a55b73f1 100644
--- a/modules/websocket/doc_classes/WebSocketServer.xml
+++ b/modules/websocket/doc_classes/WebSocketServer.xml
@@ -79,16 +79,16 @@
When not set to [code]*[/code] will restrict incoming connections to the specified IP address. Setting [code]bind_ip[/code] to [code]127.0.0.1[/code] will cause the server to listen only to the local host.
</member>
<member name="ca_chain" type="X509Certificate" setter="set_ca_chain" getter="get_ca_chain">
- 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 using TLS (see [member private_key] and [member tls_certificate]), you can set this to a valid [X509Certificate] to be provided as additional CA chain information during the TLS handshake.
</member>
<member name="handshake_timeout" type="float" setter="set_handshake_timeout" getter="get_handshake_timeout" default="3.0">
The time in seconds before a pending client (i.e. a client that has not yet finished the HTTP handshake) is considered stale and forcefully disconnected.
</member>
<member name="private_key" type="CryptoKey" setter="set_private_key" getter="get_private_key">
- 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 [code]wss://[/code] protocol).
+ When set to a valid [CryptoKey] (along with [member tls_certificate]) will cause the server to require TLS instead of regular TCP (i.e. the [code]wss://[/code] protocol).
</member>
- <member name="ssl_certificate" type="X509Certificate" setter="set_ssl_certificate" getter="get_ssl_certificate">
- 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 [code]wss://[/code] protocol).
+ <member name="tls_certificate" type="X509Certificate" setter="set_tls_certificate" getter="get_tls_certificate">
+ When set to a valid [X509Certificate] (along with [member private_key]) will cause the server to require TLS instead of regular TCP (i.e. the [code]wss://[/code] protocol).
</member>
</members>
<signals>
diff --git a/modules/websocket/emws_client.cpp b/modules/websocket/emws_client.cpp
index 65e0703c00..933a1f43e9 100644
--- a/modules/websocket/emws_client.cpp
+++ b/modules/websocket/emws_client.cpp
@@ -65,7 +65,7 @@ void EMWSClient::_esws_on_close(void *obj, int code, const char *reason, int was
client->_on_disconnect(was_clean != 0);
}
-Error EMWSClient::connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, const Vector<String> p_protocols, const Vector<String> p_custom_headers) {
+Error EMWSClient::connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_tls, const Vector<String> p_protocols, const Vector<String> p_custom_headers) {
if (_js_id) {
godot_js_websocket_destroy(_js_id);
_js_id = 0;
@@ -84,9 +84,9 @@ Error EMWSClient::connect_to_host(String p_host, String p_path, uint16_t p_port,
if (p_custom_headers.size()) {
WARN_PRINT_ONCE("Custom headers are not supported in Web platform.");
}
- if (p_ssl) {
+ if (p_tls) {
str = "wss://";
- if (ssl_cert.is_valid()) {
+ if (tls_cert.is_valid()) {
WARN_PRINT_ONCE("Custom SSL certificate is not supported in Web platform.");
}
}
diff --git a/modules/websocket/emws_client.h b/modules/websocket/emws_client.h
index ff63a76753..cdcec31e19 100644
--- a/modules/websocket/emws_client.h
+++ b/modules/websocket/emws_client.h
@@ -54,7 +54,7 @@ private:
public:
Error set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffer, int p_out_packets) override;
- Error connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, const Vector<String> p_protocol = Vector<String>(), const Vector<String> p_custom_headers = Vector<String>()) override;
+ Error connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_tls, const Vector<String> p_protocol = Vector<String>(), const Vector<String> p_custom_headers = Vector<String>()) override;
Ref<WebSocketPeer> get_peer(int p_peer_id) const override;
void disconnect_from_host(int p_code = 1000, String p_reason = "") override;
IPAddress get_connected_host() const override;
diff --git a/modules/websocket/websocket_client.cpp b/modules/websocket/websocket_client.cpp
index 2734b4b88f..0b2d5d1918 100644
--- a/modules/websocket/websocket_client.cpp
+++ b/modules/websocket/websocket_client.cpp
@@ -48,34 +48,34 @@ Error WebSocketClient::connect_to_url(String p_url, const Vector<String> p_proto
Error err = p_url.parse_url(scheme, host, port, path);
ERR_FAIL_COND_V_MSG(err != OK, err, "Invalid URL: " + p_url);
- bool ssl = false;
+ bool tls = false;
if (scheme == "wss://") {
- ssl = true;
+ tls = true;
}
if (port == 0) {
- port = ssl ? 443 : 80;
+ port = tls ? 443 : 80;
}
if (path.is_empty()) {
path = "/";
}
- return connect_to_host(host, path, port, ssl, p_protocols, p_custom_headers);
+ return connect_to_host(host, path, port, tls, p_protocols, p_custom_headers);
}
-void WebSocketClient::set_verify_ssl_enabled(bool p_verify_ssl) {
- verify_ssl = p_verify_ssl;
+void WebSocketClient::set_verify_tls_enabled(bool p_verify_tls) {
+ verify_tls = p_verify_tls;
}
-bool WebSocketClient::is_verify_ssl_enabled() const {
- return verify_ssl;
+bool WebSocketClient::is_verify_tls_enabled() const {
+ return verify_tls;
}
-Ref<X509Certificate> WebSocketClient::get_trusted_ssl_certificate() const {
- return ssl_cert;
+Ref<X509Certificate> WebSocketClient::get_trusted_tls_certificate() const {
+ return tls_cert;
}
-void WebSocketClient::set_trusted_ssl_certificate(Ref<X509Certificate> p_cert) {
+void WebSocketClient::set_trusted_tls_certificate(Ref<X509Certificate> p_cert) {
ERR_FAIL_COND(get_connection_status() != CONNECTION_DISCONNECTED);
- ssl_cert = p_cert;
+ tls_cert = p_cert;
}
bool WebSocketClient::is_server() const {
@@ -123,15 +123,15 @@ void WebSocketClient::_bind_methods() {
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);
+ ClassDB::bind_method(D_METHOD("set_verify_tls_enabled", "enabled"), &WebSocketClient::set_verify_tls_enabled);
+ ClassDB::bind_method(D_METHOD("is_verify_tls_enabled"), &WebSocketClient::is_verify_tls_enabled);
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "verify_ssl", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_verify_ssl_enabled", "is_verify_ssl_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "verify_tls", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_verify_tls_enabled", "is_verify_tls_enabled");
- ClassDB::bind_method(D_METHOD("get_trusted_ssl_certificate"), &WebSocketClient::get_trusted_ssl_certificate);
- ClassDB::bind_method(D_METHOD("set_trusted_ssl_certificate", "cert"), &WebSocketClient::set_trusted_ssl_certificate);
+ ClassDB::bind_method(D_METHOD("get_trusted_tls_certificate"), &WebSocketClient::get_trusted_tls_certificate);
+ ClassDB::bind_method(D_METHOD("set_trusted_tls_certificate", "cert"), &WebSocketClient::set_trusted_tls_certificate);
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "trusted_ssl_certificate", PROPERTY_HINT_RESOURCE_TYPE, "X509Certificate", PROPERTY_USAGE_NONE), "set_trusted_ssl_certificate", "get_trusted_ssl_certificate");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "trusted_tls_certificate", PROPERTY_HINT_RESOURCE_TYPE, "X509Certificate", PROPERTY_USAGE_NONE), "set_trusted_tls_certificate", "get_trusted_tls_certificate");
ADD_SIGNAL(MethodInfo("data_received"));
ADD_SIGNAL(MethodInfo("connection_established", PropertyInfo(Variant::STRING, "protocol")));
diff --git a/modules/websocket/websocket_client.h b/modules/websocket/websocket_client.h
index d6c072ae16..e747aee4e4 100644
--- a/modules/websocket/websocket_client.h
+++ b/modules/websocket/websocket_client.h
@@ -42,20 +42,20 @@ class WebSocketClient : public WebSocketMultiplayerPeer {
protected:
Ref<WebSocketPeer> _peer;
- bool verify_ssl = true;
- Ref<X509Certificate> ssl_cert;
+ bool verify_tls = true;
+ Ref<X509Certificate> tls_cert;
static void _bind_methods();
public:
Error connect_to_url(String p_url, const Vector<String> p_protocols = Vector<String>(), bool gd_mp_api = false, const Vector<String> p_custom_headers = Vector<String>());
- void set_verify_ssl_enabled(bool p_verify_ssl);
- bool is_verify_ssl_enabled() const;
- Ref<X509Certificate> get_trusted_ssl_certificate() const;
- void set_trusted_ssl_certificate(Ref<X509Certificate> p_cert);
+ void set_verify_tls_enabled(bool p_verify_tls);
+ bool is_verify_tls_enabled() const;
+ Ref<X509Certificate> get_trusted_tls_certificate() const;
+ void set_trusted_tls_certificate(Ref<X509Certificate> p_cert);
- virtual Error connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, const Vector<String> p_protocol = Vector<String>(), const Vector<String> p_custom_headers = Vector<String>()) = 0;
+ virtual Error connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_tls, const Vector<String> p_protocol = Vector<String>(), const Vector<String> p_custom_headers = Vector<String>()) = 0;
virtual void disconnect_from_host(int p_code = 1000, String p_reason = "") = 0;
virtual IPAddress 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 b7851b02c4..25a6e420fc 100644
--- a/modules/websocket/websocket_server.cpp
+++ b/modules/websocket/websocket_server.cpp
@@ -58,9 +58,9 @@ void WebSocketServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_private_key", "key"), &WebSocketServer::set_private_key);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "private_key", PROPERTY_HINT_RESOURCE_TYPE, "CryptoKey", PROPERTY_USAGE_NONE), "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", "cert"), &WebSocketServer::set_ssl_certificate);
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "ssl_certificate", PROPERTY_HINT_RESOURCE_TYPE, "X509Certificate", PROPERTY_USAGE_NONE), "set_ssl_certificate", "get_ssl_certificate");
+ ClassDB::bind_method(D_METHOD("get_tls_certificate"), &WebSocketServer::get_tls_certificate);
+ ClassDB::bind_method(D_METHOD("set_tls_certificate", "cert"), &WebSocketServer::set_tls_certificate);
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "tls_certificate", PROPERTY_HINT_RESOURCE_TYPE, "X509Certificate", PROPERTY_USAGE_NONE), "set_tls_certificate", "get_tls_certificate");
ClassDB::bind_method(D_METHOD("get_ca_chain"), &WebSocketServer::get_ca_chain);
ClassDB::bind_method(D_METHOD("set_ca_chain", "ca_chain"), &WebSocketServer::set_ca_chain);
@@ -95,13 +95,13 @@ void WebSocketServer::set_private_key(Ref<CryptoKey> p_key) {
private_key = p_key;
}
-Ref<X509Certificate> WebSocketServer::get_ssl_certificate() const {
- return ssl_cert;
+Ref<X509Certificate> WebSocketServer::get_tls_certificate() const {
+ return tls_cert;
}
-void WebSocketServer::set_ssl_certificate(Ref<X509Certificate> p_cert) {
+void WebSocketServer::set_tls_certificate(Ref<X509Certificate> p_cert) {
ERR_FAIL_COND(is_listening());
- ssl_cert = p_cert;
+ tls_cert = p_cert;
}
Ref<X509Certificate> WebSocketServer::get_ca_chain() const {
diff --git a/modules/websocket/websocket_server.h b/modules/websocket/websocket_server.h
index ac04c4e57e..de23ee884d 100644
--- a/modules/websocket/websocket_server.h
+++ b/modules/websocket/websocket_server.h
@@ -46,7 +46,7 @@ protected:
static void _bind_methods();
Ref<CryptoKey> private_key;
- Ref<X509Certificate> ssl_cert;
+ Ref<X509Certificate> tls_cert;
Ref<X509Certificate> ca_chain;
uint32_t handshake_timeout = 3000;
@@ -74,8 +74,8 @@ public:
Ref<CryptoKey> get_private_key() const;
void set_private_key(Ref<CryptoKey> p_key);
- Ref<X509Certificate> get_ssl_certificate() const;
- void set_ssl_certificate(Ref<X509Certificate> p_cert);
+ Ref<X509Certificate> get_tls_certificate() const;
+ void set_tls_certificate(Ref<X509Certificate> p_cert);
Ref<X509Certificate> get_ca_chain() const;
void set_ca_chain(Ref<X509Certificate> p_ca_chain);
diff --git a/modules/websocket/wsl_client.cpp b/modules/websocket/wsl_client.cpp
index 290108706b..50ef53e267 100644
--- a/modules/websocket/wsl_client.cpp
+++ b/modules/websocket/wsl_client.cpp
@@ -161,7 +161,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, const Vector<String> p_protocols, const Vector<String> p_custom_headers) {
+Error WSLClient::connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_tls, const Vector<String> p_protocols, const Vector<String> p_custom_headers) {
ERR_FAIL_COND_V(_connection.is_valid(), ERR_ALREADY_IN_USE);
ERR_FAIL_COND_V(p_path.is_empty(), ERR_INVALID_PARAMETER);
@@ -196,7 +196,7 @@ Error WSLClient::connect_to_host(String p_host, String p_path, uint16_t p_port,
return err;
}
_connection = _tcp;
- _use_ssl = p_ssl;
+ _use_tls = p_tls;
_host = p_host;
_port = p_port;
// Strip edges from protocols.
@@ -209,7 +209,7 @@ Error WSLClient::connect_to_host(String p_host, String p_path, uint16_t p_port,
_key = WSLPeer::generate_key();
String request = "GET " + p_path + " HTTP/1.1\r\n";
String port = "";
- if ((p_port != 80 && !p_ssl) || (p_port != 443 && p_ssl)) {
+ if ((p_port != 80 && !p_tls) || (p_port != 443 && p_tls)) {
port = ":" + itos(p_port);
}
request += "Host: " + p_host + port + "\r\n";
@@ -288,27 +288,27 @@ void WSLClient::poll() {
break;
case StreamPeerTCP::STATUS_CONNECTED: {
_ip_candidates.clear();
- Ref<StreamPeerTLS> ssl;
- if (_use_ssl) {
+ Ref<StreamPeerTLS> tls;
+ if (_use_tls) {
if (_connection == _tcp) {
// Start SSL handshake
- ssl = Ref<StreamPeerTLS>(StreamPeerTLS::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, ssl_cert) != OK) {
+ tls = Ref<StreamPeerTLS>(StreamPeerTLS::create());
+ ERR_FAIL_COND_MSG(tls.is_null(), "SSL is not available in this build.");
+ tls->set_blocking_handshake_enabled(false);
+ if (tls->connect_to_stream(_tcp, verify_tls, _host, tls_cert) != OK) {
disconnect_from_host();
_on_error();
return;
}
- _connection = ssl;
+ _connection = tls;
} else {
- ssl = static_cast<Ref<StreamPeerTLS>>(_connection);
- ERR_FAIL_COND(ssl.is_null()); // Bug?
- ssl->poll();
+ tls = static_cast<Ref<StreamPeerTLS>>(_connection);
+ ERR_FAIL_COND(tls.is_null()); // Bug?
+ tls->poll();
}
- if (ssl->get_status() == StreamPeerTLS::STATUS_HANDSHAKING) {
+ if (tls->get_status() == StreamPeerTLS::STATUS_HANDSHAKING) {
return; // Need more polling.
- } else if (ssl->get_status() != StreamPeerTLS::STATUS_CONNECTED) {
+ } else if (tls->get_status() != StreamPeerTLS::STATUS_CONNECTED) {
disconnect_from_host();
_on_error();
return; // Error.
@@ -356,7 +356,7 @@ void WSLClient::disconnect_from_host(int p_code, String p_reason) {
_key = "";
_host = "";
_protocols.clear();
- _use_ssl = false;
+ _use_tls = false;
_request = "";
_requested = 0;
diff --git a/modules/websocket/wsl_client.h b/modules/websocket/wsl_client.h
index dc4397f04a..dfb989fdd3 100644
--- a/modules/websocket/wsl_client.h
+++ b/modules/websocket/wsl_client.h
@@ -65,7 +65,7 @@ private:
uint16_t _port = 0;
Array _ip_candidates;
Vector<String> _protocols;
- bool _use_ssl = false;
+ bool _use_tls = false;
IP::ResolverID _resolver_id = IP::RESOLVER_INVALID_ID;
void _do_handshake();
@@ -73,7 +73,7 @@ private:
public:
Error set_buffers(int p_in_buffer, int p_in_packets, int p_out_buffer, int p_out_packets) override;
- Error connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_ssl, const Vector<String> p_protocol = Vector<String>(), const Vector<String> p_custom_headers = Vector<String>()) override;
+ Error connect_to_host(String p_host, String p_path, uint16_t p_port, bool p_tls, const Vector<String> p_protocol = Vector<String>(), const Vector<String> p_custom_headers = Vector<String>()) override;
int get_max_packet_size() const override;
Ref<WebSocketPeer> get_peer(int p_peer_id) const override;
void disconnect_from_host(int p_code = 1000, String p_reason = "") override;
diff --git a/modules/websocket/wsl_server.cpp b/modules/websocket/wsl_server.cpp
index ddef360cf5..01dcd53839 100644
--- a/modules/websocket/wsl_server.cpp
+++ b/modules/websocket/wsl_server.cpp
@@ -102,16 +102,16 @@ Error WSLServer::PendingPeer::do_handshake(const Vector<String> p_protocols, uin
return ERR_TIMEOUT;
}
- if (use_ssl) {
- Ref<StreamPeerTLS> ssl = static_cast<Ref<StreamPeerTLS>>(connection);
- if (ssl.is_null()) {
+ if (use_tls) {
+ Ref<StreamPeerTLS> tls = static_cast<Ref<StreamPeerTLS>>(connection);
+ if (tls.is_null()) {
ERR_FAIL_V_MSG(ERR_BUG, "Couldn't get StreamPeerTLS for WebSocket handshake.");
}
- ssl->poll();
- if (ssl->get_status() == StreamPeerTLS::STATUS_HANDSHAKING) {
+ tls->poll();
+ if (tls->get_status() == StreamPeerTLS::STATUS_HANDSHAKING) {
return ERR_BUSY;
- } else if (ssl->get_status() != StreamPeerTLS::STATUS_CONNECTED) {
- print_verbose(vformat("WebSocket SSL connection error during handshake (StreamPeerTLS status code %d).", ssl->get_status()));
+ } else if (tls->get_status() != StreamPeerTLS::STATUS_CONNECTED) {
+ print_verbose(vformat("WebSocket SSL connection error during handshake (StreamPeerTLS status code %d).", tls->get_status()));
return FAILED;
}
}
@@ -247,12 +247,12 @@ void WSLServer::poll() {
}
Ref<PendingPeer> peer = memnew(PendingPeer);
- if (private_key.is_valid() && ssl_cert.is_valid()) {
- Ref<StreamPeerTLS> ssl = Ref<StreamPeerTLS>(StreamPeerTLS::create());
- ssl->set_blocking_handshake_enabled(false);
- ssl->accept_stream(conn, private_key, ssl_cert, ca_chain);
- peer->connection = ssl;
- peer->use_ssl = true;
+ if (private_key.is_valid() && tls_cert.is_valid()) {
+ Ref<StreamPeerTLS> tls = Ref<StreamPeerTLS>(StreamPeerTLS::create());
+ tls->set_blocking_handshake_enabled(false);
+ tls->accept_stream(conn, private_key, tls_cert, ca_chain);
+ peer->connection = tls;
+ peer->use_tls = true;
} else {
peer->connection = conn;
}
diff --git a/modules/websocket/wsl_server.h b/modules/websocket/wsl_server.h
index ce91cfe888..df0c1dc68a 100644
--- a/modules/websocket/wsl_server.h
+++ b/modules/websocket/wsl_server.h
@@ -51,7 +51,7 @@ private:
public:
Ref<StreamPeerTCP> tcp;
Ref<StreamPeer> connection;
- bool use_ssl = false;
+ bool use_tls = false;
uint64_t time = 0;
uint8_t req_buf[WSL_MAX_HEADER_SIZE] = {};