From 1461792289a086bb40d2f39c9151bd5387c0a69e Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Thu, 19 Dec 2013 10:08:25 -0800 Subject: [PATCH] Debugger now listens for connections and will only allow one at a time. --- src/xenia/core/socket_win.cc | 1 + src/xenia/debug/debug_client.h | 1 + src/xenia/debug/debug_server.cc | 34 ++++++++-- src/xenia/debug/debug_server.h | 2 + src/xenia/debug/protocols/gdb/gdb_client.cc | 5 ++ src/xenia/debug/protocols/gdb/gdb_client.h | 1 + src/xenia/debug/protocols/ws/ws_client.cc | 6 ++ src/xenia/debug/protocols/ws/ws_client.h | 1 + src/xenia/debug/protocols/ws/ws_protocol.cc | 70 ++++++++++++++------- src/xenia/debug/protocols/ws/ws_protocol.h | 8 +++ 10 files changed, 103 insertions(+), 26 deletions(-) diff --git a/src/xenia/core/socket_win.cc b/src/xenia/core/socket_win.cc index 67d4b679a..10e3fc903 100644 --- a/src/xenia/core/socket_win.cc +++ b/src/xenia/core/socket_win.cc @@ -231,6 +231,7 @@ void xe_socket_loop_destroy(xe_socket_loop_t* loop) { int xe_socket_loop_poll(xe_socket_loop_t* loop, bool check_read, bool check_write) { // Prep events object. + loop->events[0].events = 0; if (check_read) { loop->events[0].events |= POLLIN; } diff --git a/src/xenia/debug/debug_client.h b/src/xenia/debug/debug_client.h index f13db9a04..36827184d 100644 --- a/src/xenia/debug/debug_client.h +++ b/src/xenia/debug/debug_client.h @@ -27,6 +27,7 @@ public: virtual ~DebugClient(); virtual int Setup() = 0; + virtual void Close() = 0; protected: DebugServer* debug_server_; diff --git a/src/xenia/debug/debug_server.cc b/src/xenia/debug/debug_server.cc index 2ae9d9bc0..49b21a04f 100644 --- a/src/xenia/debug/debug_server.cc +++ b/src/xenia/debug/debug_server.cc @@ -27,15 +27,20 @@ DEFINE_bool(wait_for_debugger, false, DebugServer::DebugServer(Emulator* emulator) : - emulator_(emulator) { - protocols_.push_back( - new protocols::gdb::GDBProtocol(this)); + emulator_(emulator), lock_(0) { + lock_ = xe_mutex_alloc(10000); + //protocols_.push_back( - // new protocols::ws::WSProtocol(this)); + // new protocols::gdb::GDBProtocol(this)); + protocols_.push_back( + new protocols::ws::WSProtocol(this)); } DebugServer::~DebugServer() { Shutdown(); + + xe_free(lock_); + lock_ = 0; } int DebugServer::Startup() { @@ -67,6 +72,8 @@ int DebugServer::Startup() { } void DebugServer::Shutdown() { + xe_mutex_lock(lock_); + std::vector clients(clients_.begin(), clients_.end()); clients_.clear(); for (std::vector::iterator it = clients.begin(); @@ -80,18 +87,35 @@ void DebugServer::Shutdown() { it != protocols.end(); ++it) { delete *it; } + + xe_mutex_unlock(lock_); } void DebugServer::AddClient(DebugClient* debug_client) { + xe_mutex_lock(lock_); + + // Only one debugger at a time right now. Kill any old one. + while (clients_.size()) { + DebugClient* old_client = clients_.back(); + clients_.pop_back(); + old_client->Close(); + } + clients_.push_back(debug_client); + + xe_mutex_unlock(lock_); } void DebugServer::RemoveClient(DebugClient* debug_client) { + xe_mutex_lock(lock_); + for (std::vector::iterator it = clients_.begin(); it != clients_.end(); ++it) { if (*it == debug_client) { clients_.erase(it); - return; + break; } } + + xe_mutex_unlock(lock_); } diff --git a/src/xenia/debug/debug_server.h b/src/xenia/debug/debug_server.h index 0bf988e9b..2a96ed81a 100644 --- a/src/xenia/debug/debug_server.h +++ b/src/xenia/debug/debug_server.h @@ -42,6 +42,8 @@ private: private: Emulator* emulator_; std::vector protocols_; + + xe_mutex_t* lock_; std::vector clients_; }; diff --git a/src/xenia/debug/protocols/gdb/gdb_client.cc b/src/xenia/debug/protocols/gdb/gdb_client.cc index a64b3d1b8..0d90b4d6f 100644 --- a/src/xenia/debug/protocols/gdb/gdb_client.cc +++ b/src/xenia/debug/protocols/gdb/gdb_client.cc @@ -68,6 +68,11 @@ int GDBClient::Setup() { return xe_thread_start(thread_); } +void GDBClient::Close() { + xe_socket_close(socket_id_); + socket_id_ = 0; +} + void GDBClient::StartCallback(void* param) { GDBClient* client = reinterpret_cast(param); client->EventThread(); diff --git a/src/xenia/debug/protocols/gdb/gdb_client.h b/src/xenia/debug/protocols/gdb/gdb_client.h index 3494b4914..9070dfc23 100644 --- a/src/xenia/debug/protocols/gdb/gdb_client.h +++ b/src/xenia/debug/protocols/gdb/gdb_client.h @@ -35,6 +35,7 @@ public: socket_t socket_id() const { return socket_id_; } virtual int Setup(); + virtual void Close(); private: static void StartCallback(void* param); diff --git a/src/xenia/debug/protocols/ws/ws_client.cc b/src/xenia/debug/protocols/ws/ws_client.cc index f50be5ef4..0b3c89381 100644 --- a/src/xenia/debug/protocols/ws/ws_client.cc +++ b/src/xenia/debug/protocols/ws/ws_client.cc @@ -61,6 +61,11 @@ int WSClient::Setup() { return xe_thread_start(thread_); } +void WSClient::Close() { + xe_socket_close(socket_id_); + socket_id_ = 0; +} + void WSClient::StartCallback(void* param) { WSClient* client = reinterpret_cast(param); client->EventThread(); @@ -305,6 +310,7 @@ void WSClient::EventThread() { } wslay_event_context_free(ctx); + delete this; } void WSClient::Write(uint8_t** buffers, size_t* lengths, size_t count) { diff --git a/src/xenia/debug/protocols/ws/ws_client.h b/src/xenia/debug/protocols/ws/ws_client.h index 0e316d912..bcffbb06a 100644 --- a/src/xenia/debug/protocols/ws/ws_client.h +++ b/src/xenia/debug/protocols/ws/ws_client.h @@ -35,6 +35,7 @@ public: socket_t socket_id() const { return socket_id_; } virtual int Setup(); + virtual void Close(); void Write(uint8_t** buffers, size_t* lengths, size_t count); diff --git a/src/xenia/debug/protocols/ws/ws_protocol.cc b/src/xenia/debug/protocols/ws/ws_protocol.cc index 24ae269e2..3e45b2c46 100644 --- a/src/xenia/debug/protocols/ws/ws_protocol.cc +++ b/src/xenia/debug/protocols/ws/ws_protocol.cc @@ -24,11 +24,22 @@ DEFINE_int32(ws_debug_port, 6200, WSProtocol::WSProtocol(DebugServer* debug_server) : + port_(0), socket_id_(0), thread_(0), running_(false), + accepted_event_(INVALID_HANDLE_VALUE), Protocol(debug_server) { port_ = FLAGS_ws_debug_port; } WSProtocol::~WSProtocol() { + if (thread_) { + // Join thread. + running_ = false; + xe_thread_release(thread_); + thread_ = 0; + } + if (accepted_event_ != INVALID_HANDLE_VALUE) { + CloseHandle(accepted_event_); + } if (socket_id_) { xe_socket_close(socket_id_); } @@ -60,29 +71,46 @@ int WSProtocol::Setup() { return 1; } - return 0; + accepted_event_ = CreateEvent(NULL, FALSE, FALSE, NULL); + + thread_ = xe_thread_create("WS Debugger Listener", StartCallback, this); + running_ = true; + return xe_thread_start(thread_); +} + +void WSProtocol::StartCallback(void* param) { + WSProtocol* protocol = reinterpret_cast(param); + protocol->AcceptThread(); +} + +void WSProtocol::AcceptThread() { + while (running_) { + if (!socket_id_) { + break; + } + + // Accept the first connection we get. + xe_socket_connection_t client_info; + if (xe_socket_accept(socket_id_, &client_info)) { + XELOGE("WS debugger failed to accept connection"); + break; + } + + XELOGI("WS debugger connected from %s", client_info.addr); + + // Create the client object. + // Note that the client will delete itself when done. + WSClient* client = new WSClient(debug_server_, client_info.socket); + if (client->Setup()) { + // Client failed to setup - abort. + continue; + } + + SetEvent(accepted_event_); + } } int WSProtocol::WaitForClient() { - if (!socket_id_) { - return 1; - } - - // Accept the first connection we get. - xe_socket_connection_t client_info; - if (xe_socket_accept(socket_id_, &client_info)) { - return 1; - } - - XELOGI("WS debugger connected from %s", client_info.addr); - - // Create the client object. - // Note that the client will delete itself when done. - WSClient* client = new WSClient(debug_server_, client_info.socket); - if (client->Setup()) { - // Client failed to setup - abort. - return 1; - } - + WaitForSingleObject(accepted_event_, INFINITE); return 0; } diff --git a/src/xenia/debug/protocols/ws/ws_protocol.h b/src/xenia/debug/protocols/ws/ws_protocol.h index d21d33338..f1d6510df 100644 --- a/src/xenia/debug/protocols/ws/ws_protocol.h +++ b/src/xenia/debug/protocols/ws/ws_protocol.h @@ -33,10 +33,18 @@ public: virtual int Setup(); virtual int WaitForClient(); +private: + static void StartCallback(void* param); + void AcceptThread(); + protected: uint32_t port_; socket_t socket_id_; + + xe_thread_ref thread_; + bool running_; + HANDLE accepted_event_; };