Add support for multiple RemoteDebuggerPeer(s).
It is now possible to register protocol handlers (default tcp://) to support additional debugging communication layers (e.g. websocket).
This commit is contained in:
parent
beb87504e0
commit
ed225faf31
6 changed files with 49 additions and 30 deletions
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include "core/debugger/local_debugger.h"
|
||||
#include "core/debugger/remote_debugger.h"
|
||||
#include "core/debugger/remote_debugger_peer.h"
|
||||
#include "core/debugger/script_debugger.h"
|
||||
#include "core/os/os.h"
|
||||
|
||||
|
@ -40,6 +41,7 @@ ScriptDebugger *EngineDebugger::script_debugger = nullptr;
|
|||
|
||||
Map<StringName, EngineDebugger::Profiler> EngineDebugger::profilers;
|
||||
Map<StringName, EngineDebugger::Capture> EngineDebugger::captures;
|
||||
Map<String, EngineDebugger::CreatePeerFunc> EngineDebugger::protocols;
|
||||
|
||||
void EngineDebugger::register_profiler(const StringName &p_name, const Profiler &p_func) {
|
||||
ERR_FAIL_COND_MSG(profilers.has(p_name), "Profiler already registered: " + p_name);
|
||||
|
@ -66,6 +68,11 @@ void EngineDebugger::unregister_message_capture(const StringName &p_name) {
|
|||
captures.erase(p_name);
|
||||
}
|
||||
|
||||
void EngineDebugger::register_uri_handler(const String &p_protocol, CreatePeerFunc p_func) {
|
||||
ERR_FAIL_COND_MSG(protocols.has(p_protocol), "Protocol handler already registered: " + p_protocol);
|
||||
protocols.insert(p_protocol, p_func);
|
||||
}
|
||||
|
||||
void EngineDebugger::profiler_enable(const StringName &p_name, bool p_enabled, const Array &p_opts) {
|
||||
ERR_FAIL_COND_MSG(!profilers.has(p_name), "Can't change profiler state, no profiler: " + p_name);
|
||||
Profiler &p = profilers[p_name];
|
||||
|
@ -125,6 +132,7 @@ void EngineDebugger::iteration(uint64_t p_frame_ticks, uint64_t p_idle_ticks, ui
|
|||
}
|
||||
|
||||
void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, Vector<String> p_breakpoints) {
|
||||
register_uri_handler("tcp://", RemoteDebuggerPeerTCP::create); // TCP is the default protocol. Platforms/modules can add more.
|
||||
if (p_uri.empty())
|
||||
return;
|
||||
if (p_uri == "local://") {
|
||||
|
@ -132,10 +140,14 @@ void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, Ve
|
|||
script_debugger = memnew(ScriptDebugger);
|
||||
// Tell the OS that we want to handle termination signals.
|
||||
OS::get_singleton()->initialize_debugging();
|
||||
} else {
|
||||
singleton = RemoteDebugger::create_for_uri(p_uri);
|
||||
if (!singleton)
|
||||
} else if (p_uri.find("://") >= 0) {
|
||||
const String proto = p_uri.substr(0, p_uri.find("://") + 3);
|
||||
if (!protocols.has(proto))
|
||||
return;
|
||||
RemoteDebuggerPeer *peer = protocols[proto](p_uri);
|
||||
if (!peer)
|
||||
return;
|
||||
singleton = memnew(RemoteDebugger(Ref<RemoteDebuggerPeer>(peer)));
|
||||
script_debugger = memnew(ScriptDebugger);
|
||||
// Notify editor of our pid (to allow focus stealing).
|
||||
Array msg;
|
||||
|
@ -160,22 +172,24 @@ void EngineDebugger::initialize(const String &p_uri, bool p_skip_breakpoints, Ve
|
|||
}
|
||||
|
||||
void EngineDebugger::deinitialize() {
|
||||
if (!singleton)
|
||||
return;
|
||||
if (singleton) {
|
||||
// Stop all profilers
|
||||
for (Map<StringName, Profiler>::Element *E = profilers.front(); E; E = E->next()) {
|
||||
if (E->get().active)
|
||||
singleton->profiler_enable(E->key(), false);
|
||||
}
|
||||
|
||||
// Stop all profilers
|
||||
for (Map<StringName, Profiler>::Element *E = profilers.front(); E; E = E->next()) {
|
||||
if (E->get().active)
|
||||
singleton->profiler_enable(E->key(), false);
|
||||
// Flush any remaining message
|
||||
singleton->poll_events(false);
|
||||
|
||||
memdelete(singleton);
|
||||
singleton = nullptr;
|
||||
}
|
||||
|
||||
// Flush any remaining message
|
||||
singleton->poll_events(false);
|
||||
|
||||
memdelete(singleton);
|
||||
singleton = nullptr;
|
||||
// Clear profilers/captuers/protocol handlers.
|
||||
profilers.clear();
|
||||
captures.clear();
|
||||
protocols.clear();
|
||||
}
|
||||
|
||||
EngineDebugger::~EngineDebugger() {
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "core/variant.h"
|
||||
#include "core/vector.h"
|
||||
|
||||
class RemoteDebuggerPeer;
|
||||
class ScriptDebugger;
|
||||
|
||||
class EngineDebugger {
|
||||
|
@ -45,8 +46,11 @@ public:
|
|||
typedef void (*ProfilingToggle)(void *p_user, bool p_enable, const Array &p_opts);
|
||||
typedef void (*ProfilingTick)(void *p_user, float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time);
|
||||
typedef void (*ProfilingAdd)(void *p_user, const Array &p_arr);
|
||||
|
||||
typedef Error (*CaptureFunc)(void *p_user, const String &p_msg, const Array &p_args, bool &r_captured);
|
||||
|
||||
typedef RemoteDebuggerPeer *(*CreatePeerFunc)(const String &p_uri);
|
||||
|
||||
class Profiler {
|
||||
friend class EngineDebugger;
|
||||
|
||||
|
@ -94,6 +98,7 @@ protected:
|
|||
|
||||
static Map<StringName, Profiler> profilers;
|
||||
static Map<StringName, Capture> captures;
|
||||
static Map<String, CreatePeerFunc> protocols;
|
||||
|
||||
public:
|
||||
_FORCE_INLINE_ static EngineDebugger *get_singleton() { return singleton; }
|
||||
|
@ -113,6 +118,8 @@ public:
|
|||
static void unregister_message_capture(const StringName &p_name);
|
||||
static bool has_capture(const StringName &p_name);
|
||||
|
||||
static void register_uri_handler(const String &p_protocol, CreatePeerFunc p_func);
|
||||
|
||||
void iteration(uint64_t p_frame_ticks, uint64_t p_idle_ticks, uint64_t p_physics_ticks, float p_physics_frame_time);
|
||||
void profiler_enable(const StringName &p_name, bool p_enabled, const Array &p_opts = Array());
|
||||
Error capture_parse(const StringName &p_name, const String &p_msg, const Array &p_args, bool &r_captured);
|
||||
|
|
|
@ -673,6 +673,9 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) {
|
|||
|
||||
ERR_FAIL_COND_MSG(!is_peer_connected(), "Script Debugger failed to connect, but being used anyway.");
|
||||
|
||||
if (!peer->can_block())
|
||||
return; // Peer does not support blocking IO. We could at least send the error though.
|
||||
|
||||
ScriptLanguage *script_lang = script_debugger->get_break_language();
|
||||
const String error_str = script_lang ? script_lang->debug_get_error() : "";
|
||||
Array msg;
|
||||
|
@ -886,13 +889,6 @@ Error RemoteDebugger::_profiler_capture(const String &p_cmd, const Array &p_data
|
|||
return OK;
|
||||
}
|
||||
|
||||
RemoteDebugger *RemoteDebugger::create_for_uri(const String &p_uri) {
|
||||
Ref<RemoteDebuggerPeer> peer = RemoteDebuggerPeer::create_from_uri(p_uri);
|
||||
if (peer.is_valid())
|
||||
return memnew(RemoteDebugger(peer));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RemoteDebugger::RemoteDebugger(Ref<RemoteDebuggerPeer> p_peer) {
|
||||
peer = p_peer;
|
||||
max_chars_per_second = GLOBAL_GET("network/limits/debugger/max_chars_per_second");
|
||||
|
|
|
@ -108,8 +108,6 @@ private:
|
|||
Error _try_capture(const String &p_name, const Array &p_data, bool &r_captured);
|
||||
|
||||
public:
|
||||
static RemoteDebugger *create_for_uri(const String &p_uri);
|
||||
|
||||
// Overrides
|
||||
void poll_events(bool p_is_idle);
|
||||
void send_message(const String &p_message, const Array &p_args);
|
||||
|
|
|
@ -218,9 +218,8 @@ void RemoteDebuggerPeerTCP::_poll() {
|
|||
}
|
||||
}
|
||||
|
||||
Ref<RemoteDebuggerPeer> RemoteDebuggerPeer::create_from_uri(const String p_uri) {
|
||||
if (!p_uri.begins_with("tcp://"))
|
||||
return Ref<RemoteDebuggerPeer>(); // Only TCP supported for now, more to come.
|
||||
RemoteDebuggerPeer *RemoteDebuggerPeerTCP::create(const String &p_uri) {
|
||||
ERR_FAIL_COND_V(!p_uri.begins_with("tcp://"), nullptr);
|
||||
|
||||
String debug_host = p_uri.replace("tcp://", "");
|
||||
uint16_t debug_port = 6007;
|
||||
|
@ -230,10 +229,13 @@ Ref<RemoteDebuggerPeer> RemoteDebuggerPeer::create_from_uri(const String p_uri)
|
|||
debug_port = debug_host.substr(sep_pos + 1).to_int();
|
||||
debug_host = debug_host.substr(0, sep_pos);
|
||||
}
|
||||
Ref<RemoteDebuggerPeerTCP> peer = Ref<RemoteDebuggerPeer>(memnew(RemoteDebuggerPeerTCP));
|
||||
|
||||
RemoteDebuggerPeerTCP *peer = memnew(RemoteDebuggerPeerTCP);
|
||||
Error err = peer->connect_to_host(debug_host, debug_port);
|
||||
if (err != OK)
|
||||
return Ref<RemoteDebuggerPeer>();
|
||||
if (err != OK) {
|
||||
memdelete(peer);
|
||||
return nullptr;
|
||||
}
|
||||
return peer;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,6 @@ protected:
|
|||
int max_queued_messages = 4096;
|
||||
|
||||
public:
|
||||
static Ref<RemoteDebuggerPeer> create_from_uri(const String p_uri);
|
||||
virtual bool is_peer_connected() = 0;
|
||||
virtual bool has_message() = 0;
|
||||
virtual Error put_message(const Array &p_arr) = 0;
|
||||
|
@ -50,6 +49,7 @@ public:
|
|||
virtual void close() = 0;
|
||||
virtual void poll() = 0;
|
||||
virtual int get_max_message_size() const = 0;
|
||||
virtual bool can_block() const { return true; } // If blocking io is allowed on main thread (debug).
|
||||
|
||||
RemoteDebuggerPeer();
|
||||
};
|
||||
|
@ -77,6 +77,8 @@ private:
|
|||
void _read_in();
|
||||
|
||||
public:
|
||||
static RemoteDebuggerPeer *create(const String &p_uri);
|
||||
|
||||
Error connect_to_host(const String &p_host, uint16_t p_port);
|
||||
|
||||
void poll();
|
||||
|
|
Loading…
Reference in a new issue