@@ -22,6 +22,8 @@ using namespace llvm;
22
22
23
23
LLDB_PLUGIN_DEFINE (ProtocolServerMCP)
24
24
25
+ static constexpr size_t kChunkSize = 1024;
26
+
25
27
ProtocolServerMCP::ProtocolServerMCP (Debugger &debugger)
26
28
: ProtocolServer(), m_debugger(debugger) {
27
29
AddRequestHandler (" initialize" ,
@@ -91,21 +93,52 @@ void ProtocolServerMCP::AcceptCallback(std::unique_ptr<Socket> socket) {
91
93
m_clients.size () + 1 );
92
94
93
95
lldb::IOObjectSP io_sp = std::move (socket);
94
- auto transport_sp = std::make_shared<JSONRPCTransport>(io_sp, io_sp);
96
+ auto client_up = std::make_unique<Client>();
97
+ client_up->io_sp = io_sp;
98
+ Client *client = client_up.get ();
95
99
96
100
Status status;
97
101
auto read_handle_up = m_loop.RegisterReadObject (
98
102
io_sp,
99
- [=](MainLoopBase &) {
100
- if (llvm::Error err = HandleData (*transport_sp)) {
101
- LLDB_LOG_ERROR (GetLog (LLDBLog::Host), std::move (err), " {0}" );
103
+ [this , client](MainLoopBase &loop) {
104
+ if (Error error = ReadCallback (*client)) {
105
+ LLDB_LOG_ERROR (GetLog (LLDBLog::Host), std::move (error), " {0}" );
106
+ client->read_handle_up .reset ();
102
107
}
103
108
},
104
109
status);
105
110
if (status.Fail ())
106
111
return ;
107
112
108
- m_clients.emplace_back (io_sp, std::move (read_handle_up));
113
+ client_up->read_handle_up = std::move (read_handle_up);
114
+ m_clients.emplace_back (std::move (client_up));
115
+ }
116
+
117
+ llvm::Error ProtocolServerMCP::ReadCallback (Client &client) {
118
+ char chunk[kChunkSize ];
119
+ size_t bytes_read = sizeof (chunk);
120
+ if (Status status = client.io_sp ->Read (chunk, bytes_read); status.Fail ())
121
+ return status.takeError ();
122
+ client.buffer .append (chunk, bytes_read);
123
+
124
+ for (std::string::size_type pos;
125
+ (pos = client.buffer .find (' \n ' )) != std::string::npos;) {
126
+ llvm::Expected<std::optional<protocol::Message>> message =
127
+ HandleData (StringRef (client.buffer .data (), pos));
128
+ client.buffer = client.buffer .erase (0 , pos + 1 );
129
+ if (!message)
130
+ return message.takeError ();
131
+
132
+ if (*message) {
133
+ std::string Output;
134
+ llvm::raw_string_ostream OS (Output);
135
+ OS << llvm::formatv (" {0}" , toJSON (**message)) << ' \n ' ;
136
+ size_t num_bytes = Output.size ();
137
+ return client.io_sp ->Write (Output.data (), num_bytes).takeError ();
138
+ }
139
+ }
140
+
141
+ return llvm::Error::success ();
109
142
}
110
143
111
144
llvm::Error ProtocolServerMCP::Start (ProtocolServer::Connection connection) {
@@ -165,58 +198,43 @@ llvm::Error ProtocolServerMCP::Stop() {
165
198
return llvm::Error::success ();
166
199
}
167
200
168
- llvm::Error ProtocolServerMCP::HandleData (JSONTransport &transport) {
169
- llvm::Expected<protocol::Message> maybe_message =
170
- transport.Read <protocol::Message>(std::chrono::seconds (1 ));
171
- if (maybe_message.errorIsA <TransportEOFError>() ||
172
- maybe_message.errorIsA <TransportInvalidError>() ||
173
- maybe_message.errorIsA <TransportTimeoutError>()) {
174
- consumeError (maybe_message.takeError ());
175
- return llvm::Error::success ();
176
- }
177
-
178
- if (llvm::Error err = maybe_message.takeError ())
179
- return err;
201
+ llvm::Expected<std::optional<protocol::Message>>
202
+ ProtocolServerMCP::HandleData (llvm::StringRef data) {
203
+ auto message = llvm::json::parse<protocol::Message>(/* JSON=*/ data);
204
+ if (!message)
205
+ return message.takeError ();
180
206
181
- protocol::Message &message = *maybe_message;
182
207
if (const protocol::Request *request =
183
- std::get_if<protocol::Request>(&message)) {
184
- llvm::Expected<protocol::Response> maybe_response = Handle (*request);
208
+ std::get_if<protocol::Request>(&(* message) )) {
209
+ llvm::Expected<protocol::Response> response = Handle (*request);
185
210
186
- // Handle failures.
187
- if (!maybe_response ) {
211
+ // Handle failures by converting them into an Error message .
212
+ if (!response ) {
188
213
protocol::Error protocol_error;
189
214
llvm::handleAllErrors (
190
- maybe_response .takeError (),
215
+ response .takeError (),
191
216
[&](const MCPError &err) { protocol_error = err.toProtcolError (); },
192
217
[&](const llvm::ErrorInfoBase &err) {
193
218
protocol_error.error .code = -1 ;
194
219
protocol_error.error .message = err.message ();
195
220
});
196
221
protocol_error.id = request->id ;
197
- if (llvm::Error err = transport.Write (protocol_error))
198
- return err;
199
-
200
- return llvm::Error::success ();
222
+ return protocol_error;
201
223
}
202
224
203
- // Handle success.
204
- if (llvm::Error err = transport.Write (*maybe_response))
205
- return err;
206
-
207
- return llvm::Error::success ();
225
+ return *response;
208
226
}
209
227
210
228
if (const protocol::Notification *notification =
211
- std::get_if<protocol::Notification>(&message)) {
229
+ std::get_if<protocol::Notification>(&(* message) )) {
212
230
Handle (*notification);
213
- return llvm::Error::success () ;
231
+ return std::nullopt ;
214
232
}
215
233
216
- if (std::get_if<protocol::Error>(&message))
234
+ if (std::get_if<protocol::Error>(&(* message) ))
217
235
return llvm::createStringError (" unexpected MCP message: error" );
218
236
219
- if (std::get_if<protocol::Response>(&message))
237
+ if (std::get_if<protocol::Response>(&(* message) ))
220
238
return llvm::createStringError (" unexpected MCP message: response" );
221
239
222
240
llvm_unreachable (" all message types handled" );
0 commit comments