From 8a7bd7b69a13fdcbcacee58f5fafea247e8e0077 Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Fri, 20 Dec 2013 23:44:22 -0800 Subject: [PATCH] GET /sessions returns the title info. --- src/xenia/debug/debug_client.cc | 5 +- src/xenia/debug/debug_client.h | 3 + src/xenia/debug/debug_server.cc | 4 ++ src/xenia/debug/debug_server.h | 3 + src/xenia/debug/protocols/gdb/gdb_client.cc | 3 + src/xenia/debug/protocols/ws/ws_client.cc | 68 +++++++++++++++++++- src/xenia/debug/protocols/ws/ws_client.h | 1 + src/xenia/emulator.h | 3 + src/xenia/kernel/xboxkrnl/objects/xmodule.cc | 4 -- src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc | 12 ++++ src/xenia/kernel/xboxkrnl/xboxkrnl_module.h | 2 + 11 files changed, 101 insertions(+), 7 deletions(-) diff --git a/src/xenia/debug/debug_client.cc b/src/xenia/debug/debug_client.cc index 1b5330c53..c5343bbb9 100644 --- a/src/xenia/debug/debug_client.cc +++ b/src/xenia/debug/debug_client.cc @@ -18,9 +18,12 @@ using namespace xe::debug; DebugClient::DebugClient(DebugServer* debug_server) : debug_server_(debug_server) { - debug_server_->AddClient(this); } DebugClient::~DebugClient() { debug_server_->RemoveClient(this); } + +void DebugClient::MakeReady() { + debug_server_->AddClient(this); +} diff --git a/src/xenia/debug/debug_client.h b/src/xenia/debug/debug_client.h index 36827184d..0db1d3b15 100644 --- a/src/xenia/debug/debug_client.h +++ b/src/xenia/debug/debug_client.h @@ -29,6 +29,9 @@ public: virtual int Setup() = 0; virtual void Close() = 0; +protected: + void MakeReady(); + protected: DebugServer* debug_server_; }; diff --git a/src/xenia/debug/debug_server.cc b/src/xenia/debug/debug_server.cc index 49b21a04f..138787c71 100644 --- a/src/xenia/debug/debug_server.cc +++ b/src/xenia/debug/debug_server.cc @@ -44,6 +44,10 @@ DebugServer::~DebugServer() { } int DebugServer::Startup() { + return 0; +} + +int DebugServer::BeforeEntry() { // HACK(benvanik): say we are ok even if we have no listener. if (!protocols_.size()) { return 0; diff --git a/src/xenia/debug/debug_server.h b/src/xenia/debug/debug_server.h index 2a96ed81a..995c4406f 100644 --- a/src/xenia/debug/debug_server.h +++ b/src/xenia/debug/debug_server.h @@ -30,7 +30,10 @@ public: DebugServer(Emulator* emulator); virtual ~DebugServer(); + Emulator* emulator() const { return emulator_; } + int Startup(); + int BeforeEntry(); void Shutdown(); private: diff --git a/src/xenia/debug/protocols/gdb/gdb_client.cc b/src/xenia/debug/protocols/gdb/gdb_client.cc index 0d90b4d6f..52cb1524a 100644 --- a/src/xenia/debug/protocols/gdb/gdb_client.cc +++ b/src/xenia/debug/protocols/gdb/gdb_client.cc @@ -89,9 +89,12 @@ void GDBClient::EventThread() { // First run the HTTP handshake. // This will fail if the connection is not for websockets. if (PerformHandshake()) { + delete this; return; } + MakeReady(); + // Loop forever. while (true) { // Wait on the event. diff --git a/src/xenia/debug/protocols/ws/ws_client.cc b/src/xenia/debug/protocols/ws/ws_client.cc index 0b3c89381..0fdcfbe5f 100644 --- a/src/xenia/debug/protocols/ws/ws_client.cc +++ b/src/xenia/debug/protocols/ws/ws_client.cc @@ -9,20 +9,28 @@ #include +#include +#include + +#include #include #include +#include +#include +#include #if XE_PLATFORM(WIN32) // Required for wslay. typedef SSIZE_T ssize_t; #endif // WIN32 - #include +using namespace std; using namespace xe; using namespace xe::debug; using namespace xe::debug::protocols::ws; +using namespace xe::kernel::xboxkrnl; WSClient::WSClient(DebugServer* debug_server, socket_t socket_id) : @@ -204,6 +212,54 @@ int WSClient::PerformHandshake() { 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. std::string::size_type keyhdstart; if (headers.find("Upgrade: websocket\r\n") == std::string::npos || @@ -228,6 +284,12 @@ int WSClient::PerformHandshake() { "Connection: Upgrade\r\n" "Sec-WebSocket-Accept: " + accept_key + "\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_length = response.size(); while (true) { @@ -250,7 +312,6 @@ int WSClient::PerformHandshake() { } } } - return 0; } @@ -261,9 +322,12 @@ void WSClient::EventThread() { // First run the HTTP handshake. // This will fail if the connection is not for websockets. if (PerformHandshake()) { + delete this; return; } + MakeReady(); + // Prep callbacks. struct wslay_event_callbacks callbacks = { (wslay_event_recv_callback)WSClientRecvCallback, diff --git a/src/xenia/debug/protocols/ws/ws_client.h b/src/xenia/debug/protocols/ws/ws_client.h index bcffbb06a..09deae39a 100644 --- a/src/xenia/debug/protocols/ws/ws_client.h +++ b/src/xenia/debug/protocols/ws/ws_client.h @@ -43,6 +43,7 @@ private: static void StartCallback(void* param); int PerformHandshake(); + int WriteResponse(std::string& response); void EventThread(); xe_thread_ref thread_; diff --git a/src/xenia/emulator.h b/src/xenia/emulator.h index 5072317b6..104e95715 100644 --- a/src/xenia/emulator.h +++ b/src/xenia/emulator.h @@ -47,6 +47,9 @@ public: ExportResolver* export_resolver() const { return export_resolver_; } 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(); // TODO(benvanik): raw binary. diff --git a/src/xenia/kernel/xboxkrnl/objects/xmodule.cc b/src/xenia/kernel/xboxkrnl/objects/xmodule.cc index c1f3652cb..20b3b0265 100644 --- a/src/xenia/kernel/xboxkrnl/objects/xmodule.cc +++ b/src/xenia/kernel/xboxkrnl/objects/xmodule.cc @@ -132,9 +132,6 @@ X_STATUS XModule::Launch(uint32_t flags) { XELOGI("Launching module..."); - // Set as the main module, while running. - kernel_state()->SetExecutableModule(this); - Dump(); // Create a thread to run in. @@ -154,7 +151,6 @@ X_STATUS XModule::Launch(uint32_t flags) { // Wait until thread completes. thread->Wait(0, 0, 0, NULL); - kernel_state()->SetExecutableModule(NULL); thread->Release(); return X_STATUS_SUCCESS; diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc index fa57580d4..50732b8f7 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc @@ -11,7 +11,9 @@ #include +#include #include +#include #include #include #include @@ -166,15 +168,25 @@ int XboxkrnlModule::LaunchModule(const char* path) { return 1; } + // Set as the main module, while running. + kernel_state_->SetExecutableModule(module); + if (FLAGS_abort_before_entry) { XELOGI("--abort_before_entry causing an early exit"); module->Release(); 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. // NOTE: this won't return until the module exits. result_code = module->Launch(0); + kernel_state_->SetExecutableModule(NULL); if (XFAILED(result_code)) { XELOGE("Failed to launch module %s: %.8X", path, result_code); module->Release(); diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_module.h b/src/xenia/kernel/xboxkrnl/xboxkrnl_module.h index d93c6a125..223e3ad04 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_module.h +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_module.h @@ -39,6 +39,8 @@ public: XboxkrnlModule(Emulator* emulator); virtual ~XboxkrnlModule(); + KernelState* kernel_state() const { return kernel_state_; } + int LaunchModule(const char* path); private: