137 lines
5.0 KiB
C++
137 lines
5.0 KiB
C++
/* -----------------------------------------------------------------------------
|
|
GSFramework
|
|
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
|
----------------------------------------------------------------------------- */
|
|
|
|
|
|
#include "network_debugger.h"
|
|
#include "network_debugger_thread.h"
|
|
#include "metafile/nml.h"
|
|
|
|
using namespace GS;
|
|
using namespace GS::Script;
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
void NetworkDebugger::OnControllerPacketReceived(const Array <char> &data)
|
|
{
|
|
using namespace NML;
|
|
|
|
Tag tag;
|
|
Parser::ParseTag(tag, data.Start(), data.End());
|
|
|
|
//----------------------------------------------------------------------
|
|
if (tag.name == "Start")
|
|
start_signal = true;
|
|
else if (tag.name == "StepInto")
|
|
debugger->StepInto();
|
|
else if (tag.name == "StepOver")
|
|
debugger->Step();
|
|
else if (tag.name == "StepOut")
|
|
debugger->StepOut();
|
|
else if (tag.name == "Resume")
|
|
debugger->Resume();
|
|
//----------------------------------------------------------------------
|
|
|
|
//----------------------------------------------------------------------
|
|
else if (tag.name == "SetDebugStackFrame")
|
|
debugger->SetDebugStackFrame(tag.GetInteger());
|
|
else if (tag.name == "SetTopDebugStackFrame")
|
|
debugger->SetDebugStackFrame(-1);
|
|
|
|
else if (tag.name == "RequestDebugStackFrameSource")
|
|
{
|
|
const char *source; int line;
|
|
debugger->GetStackFrameSource(source, line);
|
|
|
|
if (source)
|
|
BroadcastNetworkCommand(String::Format("<SetDebugSource=<Source=\"%s\"><Line=%d>>", source, line));
|
|
}
|
|
else if (tag.name == "RequestDebugCallStack")
|
|
BroadcastNetworkCommand(GetCallstack());
|
|
else if (tag.name == "RequestDebugStackFrameLocals")
|
|
BroadcastNetworkCommand(GetDebugStackFrameLocals());
|
|
else if (tag.name == "SetBreakpoints")
|
|
debugger->SetBreakpoints(tag);
|
|
//----------------------------------------------------------------------
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
String NetworkDebugger::GetPeerAddress()
|
|
{
|
|
ASync::Future <String> address;
|
|
thread->async.QueueMemberCall(address, thread, &NetworkDebuggerThread::GetControllerAddress);
|
|
return address.Get();
|
|
}
|
|
bool NetworkDebugger::IsConnected() const
|
|
{ return thread->IsConnected(); }
|
|
void NetworkDebugger::Stop()
|
|
{ thread->Stop(); }
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
void NetworkDebugger::BroadcastNetworkCommand(const String &cmd)
|
|
{
|
|
// Queue an asynchronous call to the controller thread.
|
|
thread->async.QueueMemberCall(thread, &NetworkDebuggerThread::SendToController, cmd);
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
void NetworkDebugger::OnSuspendExecution(const char *source, int line)
|
|
{
|
|
// Set callstack, stack frame locals and source.
|
|
BroadcastNetworkCommand(GetCallstack());
|
|
BroadcastNetworkCommand(debugger->GetStackFrameLocals());
|
|
BroadcastNetworkCommand(String::Format("<SetDebugSource=<Source=\"%s\"><Line=%d>>", source, line));
|
|
}
|
|
bool NetworkDebugger::OnUpdateSuspendedExecution()
|
|
{
|
|
async.Execute(); // [EJ] execute calls pushed by the debug thread to us so that we may receive new packets
|
|
return thread->IsConnected();
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
void NetworkDebugger::OnFatalError(const char *reason)
|
|
{
|
|
BroadcastNetworkCommand(String::Format("<VMKill=<Description=\"%s\">>", reason));
|
|
}
|
|
void NetworkDebugger::OnCompilerError(const char *error, const char *source, int line)
|
|
{
|
|
// Make sure the error location is displayed prior to the VM kill event being received.
|
|
BroadcastNetworkCommand(String::Format("<SetDebugSource=<Source=\"%s\"><Line=%d>>", source, line));
|
|
BroadcastNetworkCommand(String::Format("<VMKill=<Description=\"%s\">>", error));
|
|
}
|
|
void NetworkDebugger::OnRuntimeException(const char *error)
|
|
{
|
|
BroadcastNetworkCommand(String::Format("<VMException=<Description=\"%s\">>", error));
|
|
|
|
/*
|
|
...then suspend all execution beside the server inspection communication
|
|
channels. The VM along with the executing program will die when this
|
|
function returns.
|
|
*/
|
|
while ((vm->GetState() == IVM::StateExceptionThrown) && thread->IsConnected())
|
|
{
|
|
async.Execute();
|
|
Threading::Thread::Switch();
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
NetworkDebugger::NetworkDebugger(IVM *vm, IDebugger *debugger, const char *address, int port) : IDebuggerProfiler(vm, debugger)
|
|
{
|
|
start_signal = false;
|
|
|
|
thread = new NetworkDebuggerThread(*this, address, port);
|
|
thread->Start();
|
|
}
|
|
NetworkDebugger::~NetworkDebugger()
|
|
{
|
|
_safe_delete(thread);
|
|
}
|
|
//------------------------------------------------------------------------------
|