GET /sessions returns the title info.
This commit is contained in:
parent
1461792289
commit
8a7bd7b69a
|
@ -18,9 +18,12 @@ using namespace xe::debug;
|
||||||
|
|
||||||
DebugClient::DebugClient(DebugServer* debug_server) :
|
DebugClient::DebugClient(DebugServer* debug_server) :
|
||||||
debug_server_(debug_server) {
|
debug_server_(debug_server) {
|
||||||
debug_server_->AddClient(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DebugClient::~DebugClient() {
|
DebugClient::~DebugClient() {
|
||||||
debug_server_->RemoveClient(this);
|
debug_server_->RemoveClient(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DebugClient::MakeReady() {
|
||||||
|
debug_server_->AddClient(this);
|
||||||
|
}
|
||||||
|
|
|
@ -29,6 +29,9 @@ public:
|
||||||
virtual int Setup() = 0;
|
virtual int Setup() = 0;
|
||||||
virtual void Close() = 0;
|
virtual void Close() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void MakeReady();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
DebugServer* debug_server_;
|
DebugServer* debug_server_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -44,6 +44,10 @@ DebugServer::~DebugServer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int DebugServer::Startup() {
|
int DebugServer::Startup() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DebugServer::BeforeEntry() {
|
||||||
// HACK(benvanik): say we are ok even if we have no listener.
|
// HACK(benvanik): say we are ok even if we have no listener.
|
||||||
if (!protocols_.size()) {
|
if (!protocols_.size()) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -30,7 +30,10 @@ public:
|
||||||
DebugServer(Emulator* emulator);
|
DebugServer(Emulator* emulator);
|
||||||
virtual ~DebugServer();
|
virtual ~DebugServer();
|
||||||
|
|
||||||
|
Emulator* emulator() const { return emulator_; }
|
||||||
|
|
||||||
int Startup();
|
int Startup();
|
||||||
|
int BeforeEntry();
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -89,9 +89,12 @@ void GDBClient::EventThread() {
|
||||||
// First run the HTTP handshake.
|
// First run the HTTP handshake.
|
||||||
// This will fail if the connection is not for websockets.
|
// This will fail if the connection is not for websockets.
|
||||||
if (PerformHandshake()) {
|
if (PerformHandshake()) {
|
||||||
|
delete this;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MakeReady();
|
||||||
|
|
||||||
// Loop forever.
|
// Loop forever.
|
||||||
while (true) {
|
while (true) {
|
||||||
// Wait on the event.
|
// Wait on the event.
|
||||||
|
|
|
@ -9,20 +9,28 @@
|
||||||
|
|
||||||
#include <xenia/debug/protocols/ws/ws_client.h>
|
#include <xenia/debug/protocols/ws/ws_client.h>
|
||||||
|
|
||||||
|
#include <iomanip>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include <xenia/emulator.h>
|
||||||
#include <xenia/debug/debug_server.h>
|
#include <xenia/debug/debug_server.h>
|
||||||
#include <xenia/debug/protocols/ws/simple_sha1.h>
|
#include <xenia/debug/protocols/ws/simple_sha1.h>
|
||||||
|
#include <xenia/kernel/xboxkrnl/kernel_state.h>
|
||||||
|
#include <xenia/kernel/xboxkrnl/xboxkrnl_module.h>
|
||||||
|
#include <xenia/kernel/xboxkrnl/objects/xmodule.h>
|
||||||
|
|
||||||
#if XE_PLATFORM(WIN32)
|
#if XE_PLATFORM(WIN32)
|
||||||
// Required for wslay.
|
// Required for wslay.
|
||||||
typedef SSIZE_T ssize_t;
|
typedef SSIZE_T ssize_t;
|
||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
|
|
||||||
#include <wslay/wslay.h>
|
#include <wslay/wslay.h>
|
||||||
|
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
using namespace xe;
|
using namespace xe;
|
||||||
using namespace xe::debug;
|
using namespace xe::debug;
|
||||||
using namespace xe::debug::protocols::ws;
|
using namespace xe::debug::protocols::ws;
|
||||||
|
using namespace xe::kernel::xboxkrnl;
|
||||||
|
|
||||||
|
|
||||||
WSClient::WSClient(DebugServer* debug_server, socket_t socket_id) :
|
WSClient::WSClient(DebugServer* debug_server, socket_t socket_id) :
|
||||||
|
@ -204,6 +212,54 @@ int WSClient::PerformHandshake() {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this is a get for the session list, just produce that and return.
|
||||||
|
// We could stub out better handling here, if we wanted.
|
||||||
|
if (headers.find("GET /sessions") != std::string::npos) {
|
||||||
|
Emulator* emulator = debug_server_->emulator();
|
||||||
|
KernelState* kernel_state = emulator->xboxkrnl()->kernel_state();
|
||||||
|
XModule* module = kernel_state->GetExecutableModule();
|
||||||
|
const xe_xex2_header_t* header = module->xex_header();
|
||||||
|
char title_id[9];
|
||||||
|
xesnprintfa(title_id, XECOUNT(title_id), "%.8X",
|
||||||
|
header->execution_info.title_id);
|
||||||
|
|
||||||
|
ostringstream response;
|
||||||
|
if (module) {
|
||||||
|
response <<
|
||||||
|
"HTTP/1.0 200 OK\r\n"
|
||||||
|
"Content-Type: application/json\r\n"
|
||||||
|
"Connection: close\r\n"
|
||||||
|
"\r\n";
|
||||||
|
response << "[{";
|
||||||
|
response <<
|
||||||
|
"\"name\": \"" << module->name() << "\",";
|
||||||
|
response <<
|
||||||
|
"\"path\": \"" << module->path() << "\",";
|
||||||
|
response <<
|
||||||
|
"\"titleId\": \"" << title_id << "\"";
|
||||||
|
response << "}]";
|
||||||
|
response <<
|
||||||
|
"\r\n"
|
||||||
|
"\r\n";
|
||||||
|
} else {
|
||||||
|
response <<
|
||||||
|
"HTTP/1.0 200 OK\r\n"
|
||||||
|
"Content-Type: application/json\r\n"
|
||||||
|
"Connection: close\r\n"
|
||||||
|
"\r\n"
|
||||||
|
"[]"
|
||||||
|
"\r\n"
|
||||||
|
"\r\n";
|
||||||
|
}
|
||||||
|
error_code = WriteResponse(response.str());
|
||||||
|
if (error_code) {
|
||||||
|
return error_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Eh, we just kill the connection here.
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Parse the headers to verify its a websocket request.
|
// Parse the headers to verify its a websocket request.
|
||||||
std::string::size_type keyhdstart;
|
std::string::size_type keyhdstart;
|
||||||
if (headers.find("Upgrade: websocket\r\n") == std::string::npos ||
|
if (headers.find("Upgrade: websocket\r\n") == std::string::npos ||
|
||||||
|
@ -228,6 +284,12 @@ int WSClient::PerformHandshake() {
|
||||||
"Connection: Upgrade\r\n"
|
"Connection: Upgrade\r\n"
|
||||||
"Sec-WebSocket-Accept: " + accept_key + "\r\n"
|
"Sec-WebSocket-Accept: " + accept_key + "\r\n"
|
||||||
"\r\n";
|
"\r\n";
|
||||||
|
return WriteResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
int WSClient::WriteResponse(std::string& response) {
|
||||||
|
int error_code = 0;
|
||||||
|
int64_t r;
|
||||||
size_t write_offset = 0;
|
size_t write_offset = 0;
|
||||||
size_t write_length = response.size();
|
size_t write_length = response.size();
|
||||||
while (true) {
|
while (true) {
|
||||||
|
@ -250,7 +312,6 @@ int WSClient::PerformHandshake() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,9 +322,12 @@ void WSClient::EventThread() {
|
||||||
// First run the HTTP handshake.
|
// First run the HTTP handshake.
|
||||||
// This will fail if the connection is not for websockets.
|
// This will fail if the connection is not for websockets.
|
||||||
if (PerformHandshake()) {
|
if (PerformHandshake()) {
|
||||||
|
delete this;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MakeReady();
|
||||||
|
|
||||||
// Prep callbacks.
|
// Prep callbacks.
|
||||||
struct wslay_event_callbacks callbacks = {
|
struct wslay_event_callbacks callbacks = {
|
||||||
(wslay_event_recv_callback)WSClientRecvCallback,
|
(wslay_event_recv_callback)WSClientRecvCallback,
|
||||||
|
|
|
@ -43,6 +43,7 @@ private:
|
||||||
static void StartCallback(void* param);
|
static void StartCallback(void* param);
|
||||||
|
|
||||||
int PerformHandshake();
|
int PerformHandshake();
|
||||||
|
int WriteResponse(std::string& response);
|
||||||
void EventThread();
|
void EventThread();
|
||||||
|
|
||||||
xe_thread_ref thread_;
|
xe_thread_ref thread_;
|
||||||
|
|
|
@ -47,6 +47,9 @@ public:
|
||||||
ExportResolver* export_resolver() const { return export_resolver_; }
|
ExportResolver* export_resolver() const { return export_resolver_; }
|
||||||
kernel::xboxkrnl::fs::FileSystem* file_system() const { return file_system_; }
|
kernel::xboxkrnl::fs::FileSystem* file_system() const { return file_system_; }
|
||||||
|
|
||||||
|
kernel::xboxkrnl::XboxkrnlModule* xboxkrnl() const { return xboxkrnl_; }
|
||||||
|
kernel::xam::XamModule* xam() const { return xam_; }
|
||||||
|
|
||||||
X_STATUS Setup();
|
X_STATUS Setup();
|
||||||
|
|
||||||
// TODO(benvanik): raw binary.
|
// TODO(benvanik): raw binary.
|
||||||
|
|
|
@ -132,9 +132,6 @@ X_STATUS XModule::Launch(uint32_t flags) {
|
||||||
|
|
||||||
XELOGI("Launching module...");
|
XELOGI("Launching module...");
|
||||||
|
|
||||||
// Set as the main module, while running.
|
|
||||||
kernel_state()->SetExecutableModule(this);
|
|
||||||
|
|
||||||
Dump();
|
Dump();
|
||||||
|
|
||||||
// Create a thread to run in.
|
// Create a thread to run in.
|
||||||
|
@ -154,7 +151,6 @@ X_STATUS XModule::Launch(uint32_t flags) {
|
||||||
// Wait until thread completes.
|
// Wait until thread completes.
|
||||||
thread->Wait(0, 0, 0, NULL);
|
thread->Wait(0, 0, 0, NULL);
|
||||||
|
|
||||||
kernel_state()->SetExecutableModule(NULL);
|
|
||||||
thread->Release();
|
thread->Release();
|
||||||
|
|
||||||
return X_STATUS_SUCCESS;
|
return X_STATUS_SUCCESS;
|
||||||
|
|
|
@ -11,7 +11,9 @@
|
||||||
|
|
||||||
#include <gflags/gflags.h>
|
#include <gflags/gflags.h>
|
||||||
|
|
||||||
|
#include <xenia/emulator.h>
|
||||||
#include <xenia/export_resolver.h>
|
#include <xenia/export_resolver.h>
|
||||||
|
#include <xenia/debug/debug_server.h>
|
||||||
#include <xenia/kernel/xboxkrnl/kernel_state.h>
|
#include <xenia/kernel/xboxkrnl/kernel_state.h>
|
||||||
#include <xenia/kernel/xboxkrnl/xboxkrnl_private.h>
|
#include <xenia/kernel/xboxkrnl/xboxkrnl_private.h>
|
||||||
#include <xenia/kernel/xboxkrnl/objects/xmodule.h>
|
#include <xenia/kernel/xboxkrnl/objects/xmodule.h>
|
||||||
|
@ -166,15 +168,25 @@ int XboxkrnlModule::LaunchModule(const char* path) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set as the main module, while running.
|
||||||
|
kernel_state_->SetExecutableModule(module);
|
||||||
|
|
||||||
if (FLAGS_abort_before_entry) {
|
if (FLAGS_abort_before_entry) {
|
||||||
XELOGI("--abort_before_entry causing an early exit");
|
XELOGI("--abort_before_entry causing an early exit");
|
||||||
module->Release();
|
module->Release();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Spin up the debugger and let it know we are starting.
|
||||||
|
if (emulator_->debug_server()->BeforeEntry()) {
|
||||||
|
XELOGE("Debugger failed to startup.");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
// Launch the module.
|
// Launch the module.
|
||||||
// NOTE: this won't return until the module exits.
|
// NOTE: this won't return until the module exits.
|
||||||
result_code = module->Launch(0);
|
result_code = module->Launch(0);
|
||||||
|
kernel_state_->SetExecutableModule(NULL);
|
||||||
if (XFAILED(result_code)) {
|
if (XFAILED(result_code)) {
|
||||||
XELOGE("Failed to launch module %s: %.8X", path, result_code);
|
XELOGE("Failed to launch module %s: %.8X", path, result_code);
|
||||||
module->Release();
|
module->Release();
|
||||||
|
|
|
@ -39,6 +39,8 @@ public:
|
||||||
XboxkrnlModule(Emulator* emulator);
|
XboxkrnlModule(Emulator* emulator);
|
||||||
virtual ~XboxkrnlModule();
|
virtual ~XboxkrnlModule();
|
||||||
|
|
||||||
|
KernelState* kernel_state() const { return kernel_state_; }
|
||||||
|
|
||||||
int LaunchModule(const char* path);
|
int LaunchModule(const char* path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
Loading…
Reference in New Issue