<commit_before>/*************************************************************************/
/*  script_debugger_remote.cpp                                           */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2018 <NAME>, <NAME>.                 */
/* Copyright (c) 2014-2018 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 "script_debugger_remote.h"

#include "engine.h"
#include "io/ip.h"
#include "io/marshalls.h"
#include "os/input.h"
#include "os/os.h"
#include "project_settings.h"
#include "scene/main/node.h"

void ScriptDebuggerRemote::_send_video_memory() {

	List<ResourceUsage> usage;
	if (resource_usage_func)
		resource_usage_func(&usage);

	usage.sort();

	packet_peer_stream->put_var("message:video_mem");
	packet_peer_stream->put_var(usage.size() * 4);

	for (List<ResourceUsage>::Element *E = usage.front(); E; E = E->next()) {

		packet_peer_stream->put_var(E->get().path);
		packet_peer_stream->put_var(E->get().type);
		packet_peer_stream->put_var(E->get().format);
		packet_peer_stream->put_var(E->get().vram);
	}
}

Error ScriptDebuggerRemote::connect_to_host(const String &p_host, uint16_t p_port) {

	IP_Address ip;
	if (p_host.is_valid_ip_address())
		ip = p_host;
	else
		ip = IP::get_singleton()->resolve_hostname(p_host);

	int port = p_port;

	const int tries = 6;
	int waits[tries] = { 1, 10, 100, 1000, 1000, 1000 };

	tcp_client->connect_to_host(ip, port);

	for (int i = 0; i < tries; i++) {

		if (tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTED) {
			break;
		} else {

			const int ms = waits[i];
			OS::get_singleton()->delay_usec(ms * 1000);
			print_line("Remote Debugger: Connection failed with status: '" + String::num(tcp_client->get_status()) + "', retrying in " + String::num(ms) + " msec.");
		};
	};

	if (tcp_client->get_status() != StreamPeerTCP::STATUS_CONNECTED) {

		print_line("Remote Debugger: Unable to connect");
		return FAILED;
	};

	//    print_line("Remote Debugger: Connection OK!");
	packet_peer_stream->set_stream_peer(tcp_client);

	return OK;
}

static int _ScriptDebuggerRemote_found_id = 0;
static Object *_ScriptDebuggerRemote_find = NULL;
static void _ScriptDebuggerRemote_debug_func(Object *p_obj) {

	if (_ScriptDebuggerRemote_find == p_obj) {
		_ScriptDebuggerRemote_found_id = p_obj->get_instance_id();
	}
}

static ObjectID safe_get_instance_id(const Variant &p_v) {

	Object *o = p_v;
	if (o == NULL)
		return 0;
	else {

		REF r = p_v;
		if (r.is_valid()) {

			return r->get_instance_id();
		} else {

			_ScriptDebuggerRemote_found_id = 0;
			_ScriptDebuggerRemote_find = NULL;
			ObjectDB::debug_objects(_ScriptDebuggerRemote_debug_func);
			return _ScriptDebuggerRemote_found_id;
		}
	}
}

void ScriptDebuggerRemote::_put_variable(const String &p_name, const Variant &p_variable) {

	packet_peer_stream->put_var(p_name);
	int len = 0;
	Error err = encode_variant(p_variable, NULL, len);
	if (err != OK)
		ERR_PRINT("Failed to encode variant");

	if (len > packet_peer_stream->get_output_buffer_max_size()) { //limit to max size
		packet_peer_stream->put_var(Variant());
	} else {
		packet_peer_stream->put_var(p_variable);<commit_msg>Fix crash while the debugger encode a freed object.<commit_after>/*************************************************************************/
/*  script_debugger_remote.cpp                                           */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2018 <NAME>, <NAME>.                 */
/* Copyright (c) 2014-2018 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 "script_debugger_remote.h"

#include "engine.h"
#include "io/ip.h"
#include "io/marshalls.h"
#include "os/input.h"
#include "os/os.h"
#include "project_settings.h"
#include "scene/main/node.h"

void ScriptDebuggerRemote::_send_video_memory() {

	List<ResourceUsage> usage;
	if (resource_usage_func)
		resource_usage_func(&usage);

	usage.sort();

	packet_peer_stream->put_var("message:video_mem");
	packet_peer_stream->put_var(usage.size() * 4);

	for (List<ResourceUsage>::Element *E = usage.front(); E; E = E->next()) {

		packet_peer_stream->put_var(E->get().path);
		packet_peer_stream->put_var(E->get().type);
		packet_peer_stream->put_var(E->get().format);
		packet_peer_stream->put_var(E->get().vram);
	}
}

Error ScriptDebuggerRemote::connect_to_host(const String &p_host, uint16_t p_port) {

	IP_Address ip;
	if (p_host.is_valid_ip_address())
		ip = p_host;
	else
		ip = IP::get_singleton()->resolve_hostname(p_host);

	int port = p_port;

	const int tries = 6;
	int waits[tries] = { 1, 10, 100, 1000, 1000, 1000 };

	tcp_client->connect_to_host(ip, port);

	for (int i = 0; i < tries; i++) {

		if (tcp_client->get_status() == StreamPeerTCP::STATUS_CONNECTED) {
			break;
		} else {

			const int ms = waits[i];
			OS::get_singleton()->delay_usec(ms * 1000);
			print_line("Remote Debugger: Connection failed with status: '" + String::num(tcp_client->get_status()) + "', retrying in " + String::num(ms) + " msec.");
		};
	};

	if (tcp_client->get_status() != StreamPeerTCP::STATUS_CONNECTED) {

		print_line("Remote Debugger: Unable to connect");
		return FAILED;
	};

	//    print_line("Remote Debugger: Connection OK!");
	packet_peer_stream->set_stream_peer(tcp_client);

	return OK;
}

static int _ScriptDebuggerRemote_found_id = 0;
static Object *_ScriptDebuggerRemote_find = NULL;
static void _ScriptDebuggerRemote_debug_func(Object *p_obj) {

	if (_ScriptDebuggerRemote_find == p_obj) {
		_ScriptDebuggerRemote_found_id = p_obj->get_instance_id();
	}
}

static ObjectID safe_get_instance_id(const Variant &p_v) {

	Object *o = p_v;
	if (o == NULL)
		return 0;
	else {

		REF r = p_v;
		if (r.is_valid()) {

			return r->get_instance_id();
		} else {

			_ScriptDebuggerRemote_found_id = 0;
			_ScriptDebuggerRemote_find = NULL;
			ObjectDB::debug_objects(_ScriptDebuggerRemote_debug_func);
			return _ScriptDebuggerRemote_found_id;
		}
	}
}

void ScriptDebuggerRemote::_put_variable(const String &p_name, const Variant &p_variable) {

	packet_peer_stream->put_var(p_name);

	Variant var = p_variable;
	if (p_variable.get_type() == Variant::OBJECT && !ObjectDB::instance_validate(p_variable)) {
		var = Variant();
	}

	int len = 0;
	Error err = encode_variant(var, NULL, len);
	if (err != OK)
		ERR_PRINT("Failed to encode variant");

	if (len > packet_peer_stream->get_output_buffer_max_size()) { //limit to max size
		packet_peer_stream->put_var(Variant());
	} else {
		packet_peer_stream->put_var(var);
{'fraction_non_alphanumeric': 0.17166666666666666, 'fraction_numerical': 0.009215686274509804, 'mean_word_length': 2.93708992666924, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 61, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 26, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2623085', 'n_tokens_mistral': 3137, 'n_tokens_neox': 2873, 'n_words': 776}