Debugger now listens for connections and will only allow one at a time.

This commit is contained in:
Ben Vanik 2013-12-19 10:08:25 -08:00
parent 597e196940
commit 1461792289
10 changed files with 103 additions and 26 deletions

View File

@ -231,6 +231,7 @@ void xe_socket_loop_destroy(xe_socket_loop_t* loop) {
int xe_socket_loop_poll(xe_socket_loop_t* loop, int xe_socket_loop_poll(xe_socket_loop_t* loop,
bool check_read, bool check_write) { bool check_read, bool check_write) {
// Prep events object. // Prep events object.
loop->events[0].events = 0;
if (check_read) { if (check_read) {
loop->events[0].events |= POLLIN; loop->events[0].events |= POLLIN;
} }

View File

@ -27,6 +27,7 @@ public:
virtual ~DebugClient(); virtual ~DebugClient();
virtual int Setup() = 0; virtual int Setup() = 0;
virtual void Close() = 0;
protected: protected:
DebugServer* debug_server_; DebugServer* debug_server_;

View File

@ -27,15 +27,20 @@ DEFINE_bool(wait_for_debugger, false,
DebugServer::DebugServer(Emulator* emulator) : DebugServer::DebugServer(Emulator* emulator) :
emulator_(emulator) { emulator_(emulator), lock_(0) {
protocols_.push_back( lock_ = xe_mutex_alloc(10000);
new protocols::gdb::GDBProtocol(this));
//protocols_.push_back( //protocols_.push_back(
// new protocols::ws::WSProtocol(this)); // new protocols::gdb::GDBProtocol(this));
protocols_.push_back(
new protocols::ws::WSProtocol(this));
} }
DebugServer::~DebugServer() { DebugServer::~DebugServer() {
Shutdown(); Shutdown();
xe_free(lock_);
lock_ = 0;
} }
int DebugServer::Startup() { int DebugServer::Startup() {
@ -67,6 +72,8 @@ int DebugServer::Startup() {
} }
void DebugServer::Shutdown() { void DebugServer::Shutdown() {
xe_mutex_lock(lock_);
std::vector<DebugClient*> clients(clients_.begin(), clients_.end()); std::vector<DebugClient*> clients(clients_.begin(), clients_.end());
clients_.clear(); clients_.clear();
for (std::vector<DebugClient*>::iterator it = clients.begin(); for (std::vector<DebugClient*>::iterator it = clients.begin();
@ -80,18 +87,35 @@ void DebugServer::Shutdown() {
it != protocols.end(); ++it) { it != protocols.end(); ++it) {
delete *it; delete *it;
} }
xe_mutex_unlock(lock_);
} }
void DebugServer::AddClient(DebugClient* debug_client) { 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); clients_.push_back(debug_client);
xe_mutex_unlock(lock_);
} }
void DebugServer::RemoveClient(DebugClient* debug_client) { void DebugServer::RemoveClient(DebugClient* debug_client) {
xe_mutex_lock(lock_);
for (std::vector<DebugClient*>::iterator it = clients_.begin(); for (std::vector<DebugClient*>::iterator it = clients_.begin();
it != clients_.end(); ++it) { it != clients_.end(); ++it) {
if (*it == debug_client) { if (*it == debug_client) {
clients_.erase(it); clients_.erase(it);
return; break;
} }
} }
xe_mutex_unlock(lock_);
} }

View File

@ -42,6 +42,8 @@ private:
private: private:
Emulator* emulator_; Emulator* emulator_;
std::vector<Protocol*> protocols_; std::vector<Protocol*> protocols_;
xe_mutex_t* lock_;
std::vector<DebugClient*> clients_; std::vector<DebugClient*> clients_;
}; };

View File

@ -68,6 +68,11 @@ int GDBClient::Setup() {
return xe_thread_start(thread_); return xe_thread_start(thread_);
} }
void GDBClient::Close() {
xe_socket_close(socket_id_);
socket_id_ = 0;
}
void GDBClient::StartCallback(void* param) { void GDBClient::StartCallback(void* param) {
GDBClient* client = reinterpret_cast<GDBClient*>(param); GDBClient* client = reinterpret_cast<GDBClient*>(param);
client->EventThread(); client->EventThread();

View File

@ -35,6 +35,7 @@ public:
socket_t socket_id() const { return socket_id_; } socket_t socket_id() const { return socket_id_; }
virtual int Setup(); virtual int Setup();
virtual void Close();
private: private:
static void StartCallback(void* param); static void StartCallback(void* param);

View File

@ -61,6 +61,11 @@ int WSClient::Setup() {
return xe_thread_start(thread_); return xe_thread_start(thread_);
} }
void WSClient::Close() {
xe_socket_close(socket_id_);
socket_id_ = 0;
}
void WSClient::StartCallback(void* param) { void WSClient::StartCallback(void* param) {
WSClient* client = reinterpret_cast<WSClient*>(param); WSClient* client = reinterpret_cast<WSClient*>(param);
client->EventThread(); client->EventThread();
@ -305,6 +310,7 @@ void WSClient::EventThread() {
} }
wslay_event_context_free(ctx); wslay_event_context_free(ctx);
delete this;
} }
void WSClient::Write(uint8_t** buffers, size_t* lengths, size_t count) { void WSClient::Write(uint8_t** buffers, size_t* lengths, size_t count) {

View File

@ -35,6 +35,7 @@ public:
socket_t socket_id() const { return socket_id_; } socket_t socket_id() const { return socket_id_; }
virtual int Setup(); virtual int Setup();
virtual void Close();
void Write(uint8_t** buffers, size_t* lengths, size_t count); void Write(uint8_t** buffers, size_t* lengths, size_t count);

View File

@ -24,11 +24,22 @@ DEFINE_int32(ws_debug_port, 6200,
WSProtocol::WSProtocol(DebugServer* debug_server) : WSProtocol::WSProtocol(DebugServer* debug_server) :
port_(0), socket_id_(0), thread_(0), running_(false),
accepted_event_(INVALID_HANDLE_VALUE),
Protocol(debug_server) { Protocol(debug_server) {
port_ = FLAGS_ws_debug_port; port_ = FLAGS_ws_debug_port;
} }
WSProtocol::~WSProtocol() { 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_) { if (socket_id_) {
xe_socket_close(socket_id_); xe_socket_close(socket_id_);
} }
@ -60,18 +71,29 @@ int WSProtocol::Setup() {
return 1; 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_);
} }
int WSProtocol::WaitForClient() { void WSProtocol::StartCallback(void* param) {
WSProtocol* protocol = reinterpret_cast<WSProtocol*>(param);
protocol->AcceptThread();
}
void WSProtocol::AcceptThread() {
while (running_) {
if (!socket_id_) { if (!socket_id_) {
return 1; break;
} }
// Accept the first connection we get. // Accept the first connection we get.
xe_socket_connection_t client_info; xe_socket_connection_t client_info;
if (xe_socket_accept(socket_id_, &client_info)) { if (xe_socket_accept(socket_id_, &client_info)) {
return 1; XELOGE("WS debugger failed to accept connection");
break;
} }
XELOGI("WS debugger connected from %s", client_info.addr); XELOGI("WS debugger connected from %s", client_info.addr);
@ -81,8 +103,14 @@ int WSProtocol::WaitForClient() {
WSClient* client = new WSClient(debug_server_, client_info.socket); WSClient* client = new WSClient(debug_server_, client_info.socket);
if (client->Setup()) { if (client->Setup()) {
// Client failed to setup - abort. // Client failed to setup - abort.
return 1; continue;
} }
SetEvent(accepted_event_);
}
}
int WSProtocol::WaitForClient() {
WaitForSingleObject(accepted_event_, INFINITE);
return 0; return 0;
} }

View File

@ -33,10 +33,18 @@ public:
virtual int Setup(); virtual int Setup();
virtual int WaitForClient(); virtual int WaitForClient();
private:
static void StartCallback(void* param);
void AcceptThread();
protected: protected:
uint32_t port_; uint32_t port_;
socket_t socket_id_; socket_t socket_id_;
xe_thread_ref thread_;
bool running_;
HANDLE accepted_event_;
}; };