GET /sessions returns the title info.

This commit is contained in:
Ben Vanik 2013-12-20 23:44:22 -08:00
parent 1461792289
commit 8a7bd7b69a
11 changed files with 101 additions and 7 deletions

View File

@ -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);
}

View File

@ -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_;
}; };

View File

@ -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;

View File

@ -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:

View File

@ -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.

View File

@ -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,

View File

@ -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_;

View File

@ -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.

View File

@ -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;

View File

@ -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();

View File

@ -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: