Skip to content

Commit f6ad4a2

Browse files
committed
Stub of gadp server.
1 parent 4e82aa9 commit f6ad4a2

File tree

7 files changed

+371
-3
lines changed

7 files changed

+371
-3
lines changed

src/core/gadp-server.cc

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
/***************************************************************************
2+
* Copyright (C) 2020 PCSX-Redux authors *
3+
* *
4+
* This program is free software; you can redistribute it and/or modify *
5+
* it under the terms of the GNU General Public License as published by *
6+
* the Free Software Foundation; either version 2 of the License, or *
7+
* (at your option) any later version. *
8+
* *
9+
* This program is distributed in the hope that it will be useful, *
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12+
* GNU General Public License for more details. *
13+
* *
14+
* You should have received a copy of the GNU General Public License *
15+
* along with this program; if not, write to the *
16+
* Free Software Foundation, Inc., *
17+
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
18+
***************************************************************************/
19+
20+
#include "core/gadp-server.h"
21+
22+
#include <assert.h>
23+
24+
#include "core/debug.h"
25+
#include "core/misc.h"
26+
#include "core/psxemulator.h"
27+
#include "core/psxmem.h"
28+
#include "core/r3000a.h"
29+
#include "core/system.h"
30+
#include "support/protobuf.h"
31+
#include "uvw.hpp"
32+
33+
#undef VOID
34+
35+
enum class ErrorCode {
36+
UNKNOWN = 0,
37+
BAD_REQUEST = 1,
38+
NO_VERSION = 2,
39+
NO_OBJECT = 3,
40+
NO_INTERFACE = 4,
41+
BAD_ARGUMENT = 5,
42+
BAD_ADDRESS = 6,
43+
NOT_SUPPORTED = 7,
44+
MEMORY_ACCESS = 8,
45+
REGISTER_ACCESS = 9,
46+
USER_ERROR = 10,
47+
MODEL_ACCESS = 11,
48+
};
49+
50+
enum class StepKind {
51+
INTO = 0,
52+
ADVANCE = 1,
53+
FINISH = 2,
54+
LINE = 3,
55+
OVER = 4,
56+
OVER_LINE = 5,
57+
SKIP = 6,
58+
RETURN = 7,
59+
UNTIL = 8,
60+
};
61+
62+
enum class AttachKind {
63+
BY_OBJECT_REF = 0,
64+
BY_ID = 1,
65+
};
66+
67+
enum class ExecutionState {
68+
INACTIVE = 0,
69+
ACTIVE = 1,
70+
STOPPED = 2,
71+
RUNNING = 3,
72+
TERMINATED = 4,
73+
};
74+
75+
enum class PrimitiveKind {
76+
UNDEFINED = 0,
77+
VOID = 1,
78+
UINT = 2,
79+
SINT = 3,
80+
FLOAT = 4,
81+
COMPLEX = 5,
82+
};
83+
84+
enum class UpdateMode {
85+
UNSOLICITED = 0,
86+
SOLICITED = 1,
87+
FIXED = 2,
88+
};
89+
90+
enum class ValueType {
91+
VT_VOID = 0,
92+
VT_BOOL = 1,
93+
VT_INT = 2,
94+
VT_LONG = 3,
95+
VT_FLOAT = 4,
96+
VT_DOUBLE = 5,
97+
VT_BYTES = 6,
98+
VT_STRING = 7,
99+
VT_STRING_LIST = 8,
100+
VT_ADDRESS = 9,
101+
VT_RANGE = 10,
102+
VT_BREAK_KIND_SET = 11,
103+
VT_EXECUTION_STATE = 12,
104+
VT_STEP_KIND_SET = 13,
105+
VT_PRIMITIVE_KIND = 14,
106+
VT_DATA_TYPE = 15,
107+
VT_UPDATE_MODE = 16,
108+
VT_PATH = 17,
109+
VT_PATH_LIST = 18,
110+
VT_TYPE = 19,
111+
VT_ATTACH_KIND_SET = 20,
112+
};
113+
114+
enum class TargetEventType {
115+
EV_STOPPED = 0,
116+
EV_RUNNING = 1,
117+
PROCESS_CREATED = 2,
118+
PROCESS_EXITED = 3,
119+
THREAD_CREATED = 4,
120+
THREAD_EXITED = 5,
121+
MODULE_LOADED = 6,
122+
MODULE_UNLOADED = 7,
123+
BREAKPOINT_HIT = 8,
124+
STEP_COMPLETED = 9,
125+
EXCEPTION = 10,
126+
SIGNAL = 11,
127+
};
128+
129+
PCSX::GadpServer::GadpServer() : m_listener(g_system->m_eventBus) {
130+
m_listener.listen<Events::SettingsLoaded>([this](const auto& event) {
131+
if (g_emulator->settings.get<Emulator::SettingGadpServer>()) {
132+
startServer(g_emulator->settings.get<Emulator::SettingGadpServerPort>());
133+
}
134+
});
135+
m_listener.listen<Events::Quitting>([this](const auto& event) {
136+
if (m_serverStatus == SERVER_STARTED) stopServer();
137+
});
138+
}
139+
140+
void PCSX::GadpServer::stopServer() {
141+
assert(m_serverStatus == SERVER_STARTED);
142+
for (auto& client : m_clients) client.close();
143+
m_server->close();
144+
}
145+
146+
void PCSX::GadpServer::startServer(int port) {
147+
assert(m_serverStatus == SERVER_STOPPED);
148+
m_server = g_emulator->m_loop->resource<uvw::TCPHandle>();
149+
m_server->on<uvw::ListenEvent>([this](const uvw::ListenEvent&, uvw::TCPHandle& srv) { onNewConnection(); });
150+
m_server->on<uvw::CloseEvent>(
151+
[this](const uvw::CloseEvent&, uvw::TCPHandle& srv) { m_serverStatus = SERVER_STOPPED; });
152+
m_server->on<uvw::ErrorEvent>(
153+
[this](const uvw::ErrorEvent& event, uvw::TCPHandle& srv) { m_gotError = event.what(); });
154+
m_gotError = "";
155+
m_server->bind("0.0.0.0", port);
156+
if (!m_gotError.empty()) {
157+
g_system->printf("Error while trying to bind to port %i: %s\n", port, m_gotError.c_str());
158+
m_server->close();
159+
return;
160+
}
161+
m_server->listen();
162+
if (!m_gotError.empty()) {
163+
g_system->printf("Error while trying to listen to port %i: %s\n", port, m_gotError.c_str());
164+
m_server->close();
165+
return;
166+
}
167+
168+
m_serverStatus = SERVER_STARTED;
169+
}
170+
171+
void PCSX::GadpServer::onNewConnection() {
172+
GadpClient* client = new GadpClient(m_server);
173+
m_clients.push_back(client);
174+
client->accept(m_server);
175+
}
176+
177+
PCSX::GadpClient::GadpClient(std::shared_ptr<uvw::TCPHandle> srv)
178+
: m_tcp(srv->loop().resource<uvw::TCPHandle>()), m_listener(g_system->m_eventBus) {
179+
m_listener.listen<Events::ExecutionFlow::Pause>([this](const auto& event) {});
180+
m_listener.listen<Events::ExecutionFlow::ShellReached>([this](const auto& event) {});
181+
}
182+
183+
void PCSX::GadpClient::processData(const Slice& slice) {
184+
const uint8_t* ptr = reinterpret_cast<const uint8_t*>(slice.data());
185+
auto size = slice.size();
186+
int v = 0;
187+
188+
while (size) {
189+
switch (m_state) {
190+
case WAIT_FOR_LEN:
191+
m_lenBuffer[m_length++] = *ptr++;
192+
size--;
193+
if (m_length == 4) {
194+
m_length = m_lenBuffer[0] | (m_lenBuffer[1] << 8) | (m_lenBuffer[2] << 16) | (m_lenBuffer[3] << 24);
195+
m_protoBuffer.clear();
196+
if (m_length != 0) {
197+
m_state = READING_DATA;
198+
} else {
199+
// process empty proto
200+
}
201+
}
202+
break;
203+
case READING_DATA: {
204+
auto copySize = std::min(size, m_length);
205+
m_protoBuffer += std::string((const char*)ptr, copySize);
206+
ptr += copySize;
207+
size -= copySize;
208+
m_length -= copySize;
209+
210+
if (m_length == 0) {
211+
m_state = WAIT_FOR_LEN;
212+
// process proto
213+
}
214+
}
215+
}
216+
}
217+
}

src/core/gadp-server.h

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/***************************************************************************
2+
* Copyright (C) 2020 PCSX-Redux authors *
3+
* *
4+
* This program is free software; you can redistribute it and/or modify *
5+
* it under the terms of the GNU General Public License as published by *
6+
* the Free Software Foundation; either version 2 of the License, or *
7+
* (at your option) any later version. *
8+
* *
9+
* This program is distributed in the hope that it will be useful, *
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12+
* GNU General Public License for more details. *
13+
* *
14+
* You should have received a copy of the GNU General Public License *
15+
* along with this program; if not, write to the *
16+
* Free Software Foundation, Inc., *
17+
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
18+
***************************************************************************/
19+
20+
#pragma once
21+
22+
#include <assert.h>
23+
24+
#include "support/eventbus.h"
25+
#include "support/list.h"
26+
#include "support/slice.h"
27+
#include "uvw.hpp"
28+
29+
namespace PCSX {
30+
31+
class GadpClient : public Intrusive::List<GadpClient>::Node {
32+
public:
33+
GadpClient(std::shared_ptr<uvw::TCPHandle> srv);
34+
~GadpClient() { assert(m_requests.size() == 0); }
35+
typedef Intrusive::List<GadpClient> ListType;
36+
37+
void accept(std::shared_ptr<uvw::TCPHandle> srv) {
38+
assert(m_status == CLOSED);
39+
m_tcp->on<uvw::CloseEvent>([this](const uvw::CloseEvent&, uvw::TCPHandle&) { delete this; });
40+
m_tcp->on<uvw::EndEvent>([this](const uvw::EndEvent&, uvw::TCPHandle&) { close(); });
41+
m_tcp->on<uvw::ErrorEvent>([this](const uvw::ErrorEvent&, uvw::TCPHandle&) { close(); });
42+
m_tcp->on<uvw::DataEvent>([this](const uvw::DataEvent& event, uvw::TCPHandle&) { read(event); });
43+
m_tcp->on<uvw::WriteEvent>([this](const uvw::WriteEvent&, uvw::TCPHandle&) {
44+
auto top = m_requests.begin();
45+
if (top == m_requests.end()) return;
46+
top->gotWriteEvent();
47+
});
48+
srv->accept(*m_tcp);
49+
m_tcp->read();
50+
m_status = OPEN;
51+
}
52+
void close() {
53+
if (m_status != OPEN) return;
54+
m_status = CLOSING;
55+
m_tcp->close();
56+
m_requests.destroyAll();
57+
}
58+
59+
private:
60+
void write(const Slice& slice) {
61+
auto* req = new WriteRequest();
62+
req->m_slice = slice;
63+
req->enqueue(this);
64+
}
65+
66+
struct WriteRequest : public Intrusive::List<WriteRequest>::Node {
67+
void enqueue(GadpClient* client) {
68+
m_outstanding = 1;
69+
client->m_requests.push_back(this);
70+
client->m_tcp->write(static_cast<char*>(const_cast<void*>(m_slice.data())), m_slice.size());
71+
}
72+
void gotWriteEvent() {
73+
if (--m_outstanding == 0) delete this;
74+
}
75+
uv_write_t m_req;
76+
Slice m_slice;
77+
unsigned m_outstanding;
78+
};
79+
friend struct WriteRequest;
80+
Intrusive::List<WriteRequest> m_requests;
81+
void read(const uvw::DataEvent& event) {
82+
Slice slice;
83+
slice.borrow(event.data.get(), event.length);
84+
85+
processData(slice);
86+
}
87+
void processData(const Slice& slice);
88+
89+
std::shared_ptr<uvw::TCPHandle> m_tcp;
90+
enum { CLOSED, OPEN, CLOSING } m_status = CLOSED;
91+
92+
EventBus::Listener m_listener;
93+
94+
std::string m_protoBuffer;
95+
enum {
96+
WAIT_FOR_LEN,
97+
READING_DATA,
98+
} m_state = WAIT_FOR_LEN;
99+
uint8_t m_lenBuffer[4];
100+
uint32_t m_length = 0;
101+
};
102+
103+
class GadpServer {
104+
public:
105+
GadpServer();
106+
enum GadpServerStatus {
107+
SERVER_STOPPED,
108+
SERVER_STARTED,
109+
};
110+
GadpServerStatus getServerStatus() { return m_serverStatus; }
111+
112+
void startServer(int port = 15432);
113+
void stopServer();
114+
115+
private:
116+
void onNewConnection();
117+
GadpServerStatus m_serverStatus = SERVER_STOPPED;
118+
std::shared_ptr<uvw::TCPHandle> m_server;
119+
GadpClient::ListType m_clients;
120+
EventBus::Listener m_listener;
121+
std::string m_gotError;
122+
};
123+
124+
} // namespace PCSX

src/core/psxemulator.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "core/cdrom.h"
2323
#include "core/cheat.h"
2424
#include "core/debug.h"
25+
#include "core/gadp-server.h"
2526
#include "core/gdb-server.h"
2627
#include "core/gpu.h"
2728
#include "core/gte.h"

src/core/psxemulator.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ class CDRom;
8585
class Cheats;
8686
class Counters;
8787
class Debug;
88+
class GadpServer;
8889
class GdbServer;
8990
class WebServer;
9091
class GPU;
@@ -141,6 +142,8 @@ class Emulator {
141142
typedef SettingString<TYPESTRING("Locale")> SettingLocale;
142143
typedef Setting<bool, TYPESTRING("Mcd1Inserted"), true> SettingMcd1Inserted;
143144
typedef Setting<bool, TYPESTRING("Mcd2Inserted"), true> SettingMcd2Inserted;
145+
typedef Setting<bool, TYPESTRING("GadpServer"), false> SettingGadpServer;
146+
typedef Setting<int, TYPESTRING("GadpServerPort"), 15432> SettingGadpServerPort;
144147
typedef Setting<bool, TYPESTRING("GdbServer"), false> SettingGdbServer;
145148
typedef Setting<bool, TYPESTRING("GdbManifest"), true> SettingGdbManifest;
146149
typedef Setting<int, TYPESTRING("GdbServerPort"), 3333> SettingGdbServerPort;
@@ -152,9 +155,9 @@ class Emulator {
152155
Settings<SettingStdout, SettingLogfile, SettingMcd1, SettingMcd2, SettingBios, SettingPpfDir, SettingPsxExe,
153156
SettingXa, SettingSioIrq, SettingSpuIrq, SettingBnWMdec, SettingAutoVideo, SettingVideo, SettingCDDA,
154157
SettingFastBoot, SettingDebug, SettingVerbose, SettingRCntFix, SettingIsoPath, SettingLocale,
155-
SettingMcd1Inserted, SettingMcd2Inserted, SettingBiosOverlay, SettingGdbServer, SettingGdbManifest,
156-
SettingGdbServerPort, SettingGdbServerTrace, SettingWebServer, SettingWebServerPort, SettingDynarec,
157-
Setting8MB>
158+
SettingMcd1Inserted, SettingMcd2Inserted, SettingBiosOverlay, SettingGadpServer, SettingGadpServerPort,
159+
SettingGdbServer, SettingGdbManifest, SettingGdbServerPort, SettingGdbServerTrace, SettingWebServer,
160+
SettingWebServerPort, SettingDynarec, Setting8MB>
158161
settings;
159162
class PcsxConfig {
160163
public:
@@ -207,6 +210,7 @@ class Emulator {
207210
std::unique_ptr<Cheats> m_cheats;
208211
std::unique_ptr<MDEC> m_mdec;
209212
std::unique_ptr<GPU> m_gpu;
213+
std::unique_ptr<GadpServer> m_gadpServer;
210214
std::unique_ptr<GdbServer> m_gdbServer;
211215
std::unique_ptr<WebServer> m_webServer;
212216
std::unique_ptr<Debug> m_debug;

0 commit comments

Comments
 (0)